2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: Programmable Interval Timer emulation
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
14 /* PRIVATE VARIABLES **********************************************************/
16 static PIT_CHANNEL PitChannels
[PIT_CHANNELS
];
18 /* PUBLIC FUNCTIONS ***********************************************************/
20 VOID
PitWriteCommand(BYTE Value
)
22 BYTE Channel
= Value
>> 6;
23 BYTE Mode
= (Value
>> 1) & 0x07;
25 /* Check if this is a counter latch command */
26 if (((Value
>> 4) & 3) == 0)
28 PitChannels
[Channel
].LatchSet
= TRUE
;
29 PitChannels
[Channel
].LatchedValue
= PitChannels
[Channel
].CurrentValue
;
33 /* Set the access mode and reset flip-flops */
34 PitChannels
[Channel
].AccessMode
= (Value
>> 4) & 3;
35 PitChannels
[Channel
].Pulsed
= FALSE
;
36 PitChannels
[Channel
].LatchSet
= FALSE
;
37 PitChannels
[Channel
].InputFlipFlop
= FALSE
;
38 PitChannels
[Channel
].OutputFlipFlop
= FALSE
;
49 PitChannels
[Channel
].Mode
= Mode
;
55 PitChannels
[Channel
].Mode
= PIT_MODE_RATE_GENERATOR
;
61 PitChannels
[Channel
].Mode
= PIT_MODE_SQUARE_WAVE
;
67 BYTE
PitReadData(BYTE Channel
)
69 WORD CurrentValue
= PitChannels
[Channel
].CurrentValue
;
70 BYTE AccessMode
= PitChannels
[Channel
].AccessMode
;
72 /* Check if the value was latched */
73 if (PitChannels
[Channel
].LatchSet
)
75 CurrentValue
= PitChannels
[Channel
].LatchedValue
;
77 if (AccessMode
== 1 || AccessMode
== 2)
79 /* The latched value was read as one byte */
80 PitChannels
[Channel
].LatchSet
= FALSE
;
84 /* Use the flip-flop for access mode 3 */
87 AccessMode
= PitChannels
[Channel
].InputFlipFlop
? 1 : 2;
88 PitChannels
[Channel
].InputFlipFlop
= !PitChannels
[Channel
].InputFlipFlop
;
90 /* Check if this was the last read for the latched value */
91 if (!PitChannels
[Channel
].InputFlipFlop
)
93 /* Yes, the latch value was read as two bytes */
94 PitChannels
[Channel
].LatchSet
= FALSE
;
103 return CurrentValue
& 0x00FF;
109 return CurrentValue
>> 8;
113 /* Shouldn't get here */
117 VOID
PitWriteData(BYTE Channel
, BYTE Value
)
119 BYTE AccessMode
= PitChannels
[Channel
].AccessMode
;
121 /* Use the flip-flop for access mode 3 */
122 if (PitChannels
[Channel
].AccessMode
== 3)
124 AccessMode
= PitChannels
[Channel
].InputFlipFlop
? 1 : 2;
125 PitChannels
[Channel
].InputFlipFlop
= !PitChannels
[Channel
].InputFlipFlop
;
133 PitChannels
[Channel
].ReloadValue
&= 0xFF00;
134 PitChannels
[Channel
].ReloadValue
|= Value
;
141 PitChannels
[Channel
].ReloadValue
&= 0x00FF;
142 PitChannels
[Channel
].ReloadValue
|= Value
<< 8;
147 VOID
PitDecrementCount()
151 for (i
= 0; i
< PIT_CHANNELS
; i
++)
153 switch (PitChannels
[i
].Mode
)
155 case PIT_MODE_INT_ON_TERMINAL_COUNT
:
157 /* Decrement the value */
158 PitChannels
[i
].CurrentValue
--;
160 /* Did it fall to the terminal count? */
161 if (PitChannels
[i
].CurrentValue
== 0 && !PitChannels
[i
].Pulsed
)
163 /* Yes, raise the output line */
164 if (i
== 0) PicInterruptRequest(0);
165 PitChannels
[i
].Pulsed
= TRUE
;
170 case PIT_MODE_RATE_GENERATOR
:
172 /* Decrement the value */
173 PitChannels
[i
].CurrentValue
--;
175 /* Did it fall to zero? */
176 if (PitChannels
[i
].CurrentValue
!= 0) break;
178 /* Yes, raise the output line and reload */
179 if (i
== 0) PicInterruptRequest(0);
180 PitChannels
[i
].CurrentValue
= PitChannels
[i
].ReloadValue
;
185 case PIT_MODE_SQUARE_WAVE
:
187 /* Decrement the value by 2 */
188 PitChannels
[i
].CurrentValue
-= 2;
190 /* Did it fall to zero? */
191 if (PitChannels
[i
].CurrentValue
!= 0) break;
193 /* Yes, toggle the flip-flop */
194 PitChannels
[i
].OutputFlipFlop
= !PitChannels
[i
].OutputFlipFlop
;
196 /* Did this create a rising edge in the signal? */
197 if (PitChannels
[i
].OutputFlipFlop
)
199 /* Yes, IRQ 0 if this is channel 0 */
200 if (i
== 0) PicInterruptRequest(0);
203 /* Reload the value, but make sure it's even */
204 if (PitChannels
[i
].ReloadValue
% 2)
206 /* It's odd, reduce it by 1 */
207 PitChannels
[i
].CurrentValue
= PitChannels
[i
].ReloadValue
- 1;
212 PitChannels
[i
].CurrentValue
= PitChannels
[i
].ReloadValue
;
218 case PIT_MODE_SOFTWARE_STROBE
:
220 // TODO: NOT IMPLEMENTED
224 case PIT_MODE_HARDWARE_ONE_SHOT
:
225 case PIT_MODE_HARDWARE_STROBE
:
227 /* These modes do not work on x86 PCs */