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 *******************************************************************/
16 /* PRIVATE VARIABLES **********************************************************/
18 static PIT_CHANNEL PitChannels
[PIT_CHANNELS
];
20 /* PUBLIC FUNCTIONS ***********************************************************/
22 VOID
PitWriteCommand(BYTE Value
)
24 BYTE Channel
= Value
>> 6;
25 BYTE Mode
= (Value
>> 1) & 0x07;
27 /* Check if this is a counter latch command */
28 if (((Value
>> 4) & 3) == 0)
30 PitChannels
[Channel
].LatchSet
= TRUE
;
31 PitChannels
[Channel
].LatchedValue
= PitChannels
[Channel
].CurrentValue
;
35 /* Set the access mode and reset flip-flops */
36 PitChannels
[Channel
].AccessMode
= (Value
>> 4) & 3;
37 PitChannels
[Channel
].Pulsed
= FALSE
;
38 PitChannels
[Channel
].LatchSet
= FALSE
;
39 PitChannels
[Channel
].InputFlipFlop
= FALSE
;
40 PitChannels
[Channel
].OutputFlipFlop
= FALSE
;
51 PitChannels
[Channel
].Mode
= Mode
;
57 PitChannels
[Channel
].Mode
= PIT_MODE_RATE_GENERATOR
;
63 PitChannels
[Channel
].Mode
= PIT_MODE_SQUARE_WAVE
;
69 BYTE
PitReadData(BYTE Channel
)
71 WORD CurrentValue
= PitChannels
[Channel
].CurrentValue
;
72 BYTE AccessMode
= PitChannels
[Channel
].AccessMode
;
74 /* Check if the value was latched */
75 if (PitChannels
[Channel
].LatchSet
)
77 CurrentValue
= PitChannels
[Channel
].LatchedValue
;
79 if (AccessMode
== 1 || AccessMode
== 2)
81 /* The latched value was read as one byte */
82 PitChannels
[Channel
].LatchSet
= FALSE
;
86 /* Use the flip-flop for access mode 3 */
89 AccessMode
= PitChannels
[Channel
].InputFlipFlop
? 1 : 2;
90 PitChannels
[Channel
].InputFlipFlop
= !PitChannels
[Channel
].InputFlipFlop
;
92 /* Check if this was the last read for the latched value */
93 if (!PitChannels
[Channel
].InputFlipFlop
)
95 /* Yes, the latch value was read as two bytes */
96 PitChannels
[Channel
].LatchSet
= FALSE
;
105 return CurrentValue
& 0x00FF;
111 return CurrentValue
>> 8;
115 /* Shouldn't get here */
119 VOID
PitWriteData(BYTE Channel
, BYTE Value
)
121 BYTE AccessMode
= PitChannels
[Channel
].AccessMode
;
123 /* Use the flip-flop for access mode 3 */
124 if (PitChannels
[Channel
].AccessMode
== 3)
126 AccessMode
= PitChannels
[Channel
].InputFlipFlop
? 1 : 2;
127 PitChannels
[Channel
].InputFlipFlop
= !PitChannels
[Channel
].InputFlipFlop
;
135 PitChannels
[Channel
].ReloadValue
&= 0xFF00;
136 PitChannels
[Channel
].ReloadValue
|= Value
;
143 PitChannels
[Channel
].ReloadValue
&= 0x00FF;
144 PitChannels
[Channel
].ReloadValue
|= Value
<< 8;
149 VOID
PitDecrementCount()
153 for (i
= 0; i
< PIT_CHANNELS
; i
++)
155 switch (PitChannels
[i
].Mode
)
157 case PIT_MODE_INT_ON_TERMINAL_COUNT
:
159 /* Decrement the value */
160 PitChannels
[i
].CurrentValue
--;
162 /* Did it fall to the terminal count? */
163 if (PitChannels
[i
].CurrentValue
== 0 && !PitChannels
[i
].Pulsed
)
165 /* Yes, raise the output line */
166 if (i
== 0) PicInterruptRequest(0);
167 PitChannels
[i
].Pulsed
= TRUE
;
172 case PIT_MODE_RATE_GENERATOR
:
174 /* Decrement the value */
175 PitChannels
[i
].CurrentValue
--;
177 /* Did it fall to zero? */
178 if (PitChannels
[i
].CurrentValue
!= 0) break;
180 /* Yes, raise the output line and reload */
181 if (i
== 0) PicInterruptRequest(0);
182 PitChannels
[i
].CurrentValue
= PitChannels
[i
].ReloadValue
;
187 case PIT_MODE_SQUARE_WAVE
:
189 /* Decrement the value by 2 */
190 PitChannels
[i
].CurrentValue
-= 2;
192 /* Did it fall to zero? */
193 if (PitChannels
[i
].CurrentValue
!= 0) break;
195 /* Yes, toggle the flip-flop */
196 PitChannels
[i
].OutputFlipFlop
= !PitChannels
[i
].OutputFlipFlop
;
198 /* Did this create a rising edge in the signal? */
199 if (PitChannels
[i
].OutputFlipFlop
)
201 /* Yes, IRQ 0 if this is channel 0 */
202 if (i
== 0) PicInterruptRequest(0);
205 /* Reload the value, but make sure it's even */
206 if (PitChannels
[i
].ReloadValue
% 2)
208 /* It's odd, reduce it by 1 */
209 PitChannels
[i
].CurrentValue
= PitChannels
[i
].ReloadValue
- 1;
214 PitChannels
[i
].CurrentValue
= PitChannels
[i
].ReloadValue
;
220 case PIT_MODE_SOFTWARE_STROBE
:
222 // TODO: NOT IMPLEMENTED
226 case PIT_MODE_HARDWARE_ONE_SHOT
:
227 case PIT_MODE_HARDWARE_STROBE
:
229 /* These modes do not work on x86 PCs */