ReactOS 0.4.15-dev-7906-g1b85a5f
pit.c File Reference
#include "ntvdm.h"
#include <debug.h>
#include "emulator.h"
#include "pit.h"
#include "io.h"
#include "pic.h"
#include "clock.h"
Include dependency graph for pit.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static VOID PitLatchChannelStatus (BYTE Channel)
 
static VOID PitLatchChannelCount (BYTE Channel)
 
static VOID PitSetOut (PPIT_CHANNEL Channel, BOOLEAN State)
 
static VOID PitInitCounter (PPIT_CHANNEL Channel)
 
static VOID PitWriteCommand (BYTE Value)
 
static BYTE PitReadData (BYTE Channel)
 
static VOID PitWriteData (BYTE Channel, BYTE Value)
 
static BYTE WINAPI PitReadPort (USHORT Port)
 
static VOID WINAPI PitWritePort (USHORT Port, BYTE Data)
 
static VOID PitDecrementCount (PPIT_CHANNEL Channel, DWORD Count)
 
static VOID FASTCALL PitClock (ULONGLONG Count)
 
VOID PitSetOutFunction (BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction)
 
VOID PitSetGate (BYTE Channel, BOOLEAN State)
 
WORD PitGetReloadValue (BYTE Channel)
 
VOID PitInitialize (VOID)
 

Variables

static PIT_CHANNEL PitChannels [PIT_CHANNELS]
 
static PHARDWARE_TIMER MasterClock
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 15 of file pit.c.

Function Documentation

◆ PitClock()

static VOID FASTCALL PitClock ( ULONGLONG  Count)
static

Definition at line 463 of file pit.c.

464{
465 UCHAR i;
466
467 for (i = 0; i < PIT_CHANNELS; i++)
468 {
469 // if (!PitChannels[i].Counting) continue;
471 }
472}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int Count
Definition: noreturn.cpp:7
static VOID PitDecrementCount(PPIT_CHANNEL Channel, DWORD Count)
Definition: pit.c:321
static PIT_CHANNEL PitChannels[PIT_CHANNELS]
Definition: pit.c:27
#define PIT_CHANNELS
Definition: pit.h:16
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by PitInitialize().

◆ PitDecrementCount()

static VOID PitDecrementCount ( PPIT_CHANNEL  Channel,
DWORD  Count 
)
static

Definition at line 321 of file pit.c.

322{
323 if (Count == 0) return;
324
325 switch (Channel->Mode)
326 {
328 {
329 /* Decrement the value */
330 if (Count > Channel->CurrentValue)
331 {
332 /* The value does not reload in this case */
333 Channel->CurrentValue = 0;
334 }
335 else Channel->CurrentValue -= Count;
336
337 /* Did it fall to the terminal count? */
338 if (Channel->CurrentValue == 0 && !Channel->Out)
339 {
340 /* Yes, raise the output line */
341 PitSetOut(Channel, TRUE);
342 }
343 break;
344 }
345
347 {
348 BOOLEAN Reloaded = FALSE;
349
350 while (Count)
351 {
352 if ((Count > Channel->CurrentValue)
353 && (Channel->CurrentValue != 0))
354 {
355 /* Decrement the count */
356 Count -= Channel->CurrentValue;
357
358 /* Reload the value */
359 Channel->CurrentValue = Channel->ReloadValue;
360
361 /* Set the flag */
362 Reloaded = TRUE;
363 }
364 else
365 {
366 /* Decrement the value */
367 Channel->CurrentValue -= Count;
368
369 /* Clear the count */
370 Count = 0;
371
372 /* Did it fall to zero? */
373 if (Channel->CurrentValue == 0)
374 {
375 Channel->CurrentValue = Channel->ReloadValue;
376 Reloaded = TRUE;
377 }
378 }
379 }
380
381 /* If there was a reload, raise the output line */
382 if (Reloaded) PitSetOut(Channel, TRUE);
383
384 break;
385 }
386
388 {
389 INT ReloadCount = 0;
390 WORD ReloadValue = Channel->ReloadValue;
391
392 /* The reload value must be even */
393 ReloadValue &= ~1;
394
395 while (Count)
396 {
397 if (((Count * 2) > Channel->CurrentValue)
398 && (Channel->CurrentValue != 0))
399 {
400 /* Decrement the count */
401 Count -= Channel->CurrentValue / 2;
402
403 /* Reload the value */
404 Channel->CurrentValue = ReloadValue;
405
406 /* Increment the reload count */
407 ReloadCount++;
408 }
409 else
410 {
411 /* Decrement the value */
412 Channel->CurrentValue -= Count * 2;
413
414 /* Clear the count */
415 Count = 0;
416
417 /* Did it fall to zero? */
418 if (Channel->CurrentValue == 0)
419 {
420 /* Reload the value */
421 Channel->CurrentValue = ReloadValue;
422
423 /* Increment the reload count */
424 ReloadCount++;
425 }
426 }
427 }
428
429 if (ReloadCount == 0) break;
430
431 /* Toggle the flip-flop if the number of reloads was odd */
432 if (ReloadCount & 1)
433 {
434 Channel->FlipFlop = !Channel->FlipFlop;
435 PitSetOut(Channel, !Channel->Out);
436 }
437
438 /* Was there any rising edge? */
439 if ((Channel->FlipFlop && (ReloadCount == 1)) || (ReloadCount > 1))
440 {
441 /* Yes, raise the output line */
442 PitSetOut(Channel, TRUE);
443 }
444
445 break;
446 }
447
449 {
450 // TODO: NOT IMPLEMENTED
451 break;
452 }
453
456 {
457 /* These modes do not work on x86 PCs */
458 break;
459 }
460 }
461}
unsigned char BOOLEAN
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned short WORD
Definition: ntddk_ex.h:93
static VOID PitSetOut(PPIT_CHANNEL Channel, BOOLEAN State)
Definition: pit.c:79
WORD ReloadValue
Definition: pit.h:61
PIT_MODE Mode
Definition: pit.h:42
WORD CurrentValue
Definition: pit.h:62
BOOLEAN FlipFlop
Definition: pit.h:66
BOOLEAN Out
Definition: pit.h:65
@ PIT_MODE_HARDWARE_ONE_SHOT
Definition: pit.h:30
@ PIT_MODE_HARDWARE_STROBE
Definition: pit.h:34
@ PIT_MODE_RATE_GENERATOR
Definition: pit.h:31
@ PIT_MODE_SOFTWARE_STROBE
Definition: pit.h:33
@ PIT_MODE_SQUARE_WAVE
Definition: pit.h:32
@ PIT_MODE_INT_ON_TERMINAL_COUNT
Definition: pit.h:29
int32_t INT
Definition: typedefs.h:58

Referenced by PitClock().

◆ PitGetReloadValue()

WORD PitGetReloadValue ( BYTE  Channel)

Definition at line 493 of file pit.c.

494{
495 if (Channel >= PIT_CHANNELS) return 0xFFFF;
496
497 if (PitChannels[Channel].ReloadValue == 0)
498 return 0xFFFF;
499 else
500 return PitChannels[Channel].ReloadValue;
501}

Referenced by SpeakerChange().

◆ PitInitCounter()

static VOID PitInitCounter ( PPIT_CHANNEL  Channel)
static

Definition at line 91 of file pit.c.

92{
93 switch (Channel->Mode)
94 {
96 PitSetOut(Channel, FALSE);
97 break;
98
104 PitSetOut(Channel, TRUE);
105 break;
106 }
107}

Referenced by PitWriteCommand().

◆ PitInitialize()

VOID PitInitialize ( VOID  )

Definition at line 503 of file pit.c.

504{
505 /* Set up the timers to their default value */
507 PitSetGate(0, TRUE);
509 PitSetGate(1, TRUE);
511 PitSetGate(2, FALSE);
512
513 /* Register the I/O Ports */
518
519 /* Register the hardware timer */
522 PitClock);
523}
#define HARDWARE_TIMER_ENABLED
Definition: clock.h:15
#define HARDWARE_TIMER_PRECISE
Definition: clock.h:17
#define HZ_TO_NS(Freq)
Definition: clock.h:20
#define NULL
Definition: types.h:112
static VOID FASTCALL PitClock(ULONGLONG Count)
Definition: pit.c:463
static VOID WINAPI PitWritePort(USHORT Port, BYTE Data)
Definition: pit.c:301
VOID PitSetOutFunction(BYTE Channel, LPVOID Param, PIT_OUT_FUNCTION OutFunction)
Definition: pit.c:476
VOID PitSetGate(BYTE Channel, BOOLEAN State)
Definition: pit.c:484
static BYTE WINAPI PitReadPort(USHORT Port)
Definition: pit.c:286
static PHARDWARE_TIMER MasterClock
Definition: pit.c:28
PHARDWARE_TIMER CreateHardwareTimer(ULONG Flags, ULONGLONG Delay, PHARDWARE_TIMER_PROC Callback)
Definition: clock.c:144
#define PIT_DATA_PORT(x)
Definition: pit.h:18
#define PIT_COMMAND_PORT
Definition: pit.h:19
#define PIT_BASE_FREQUENCY
Definition: pit.h:17
VOID RegisterIoPort(USHORT Port, EMULATOR_INB_PROC InHandler, EMULATOR_OUTB_PROC OutHandler)
Definition: io.c:320

Referenced by EmulatorInitialize().

◆ PitLatchChannelCount()

static VOID PitLatchChannelCount ( BYTE  Channel)
static

Definition at line 58 of file pit.c.

59{
60 if (Channel >= PIT_CHANNELS) return;
61
62 /*
63 * A given counter can be latched only one time until it gets unlatched.
64 * If the counter is latched and then is latched again later before the
65 * value is read, then this last latch command is ignored and the value
66 * will be the value at the time the first command was issued.
67 */
68 if (PitChannels[Channel].ReadStatus == 0x00)
69 {
70 /* Latch the counter's value */
72
73 /* Convert the current value to BCD if needed */
74 PitChannels[Channel].OutputLatch =
75 READ_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CurrentValue);
76 }
77}
static UCHAR ReadStatus(_In_ PUCHAR ReadDataPort)
Definition: hardware.c:167
BYTE ReadWriteMode
Definition: pit.h:44
BYTE ReadStatus
Definition: pit.h:47
WORD OutputLatch
Definition: pit.h:58
#define READ_PIT_VALUE(PitChannel, Value)
Definition: pit.h:24

Referenced by PitReadData(), and PitWriteCommand().

◆ PitLatchChannelStatus()

static VOID PitLatchChannelStatus ( BYTE  Channel)
static

HACK!!

HACK!!

Definition at line 32 of file pit.c.

33{
34 if (Channel >= PIT_CHANNELS) return;
35
36 /*
37 * A given counter can be latched only one time until it gets unlatched.
38 * If the counter is latched and then is latched again later before the
39 * value is read, then this last latch command is ignored and the value
40 * will be the value at the time the first command was issued.
41 */
42 if (PitChannels[Channel].LatchStatusSet == FALSE)
43 {
44 BYTE StatusLatch = 0;BYTE NullCount = 0;
47 StatusLatch = PitChannels[Channel].Out << 7 | NullCount << 6;
48 StatusLatch |= (PitChannels[Channel].ReadWriteMode & 0x03) << 4;
49 StatusLatch |= (PitChannels[Channel].Mode & 0x07) << 1;
50 StatusLatch |= (PitChannels[Channel].Bcd & 0x01);
51
52 /* Latch the counter's status */
54 PitChannels[Channel].StatusLatch = StatusLatch;
55 }
56}
BOOLEAN Bcd
Definition: pit.h:43
BOOLEAN LatchStatusSet
Definition: pit.h:51
BYTE StatusLatch
Definition: pit.h:52
unsigned char BYTE
Definition: xxhash.c:193

Referenced by PitWriteCommand().

◆ PitReadData()

static BYTE PitReadData ( BYTE  Channel)
static

Definition at line 193 of file pit.c.

194{
196 LPWORD CurrentValue = NULL;
197
198 /*
199 * If the status was latched, the first read operation will return the
200 * latched status, whichever value (count or status) was latched first.
201 */
202 if (PitChannels[Channel].LatchStatusSet)
203 {
205 return PitChannels[Channel].StatusLatch;
206 }
207
208 /* To be able to read the count asynchronously, latch it first if needed */
209 if (PitChannels[Channel].ReadStatus == 0) PitLatchChannelCount(Channel);
210
211 /* The count is now latched */
212 ASSERT(PitChannels[Channel].ReadStatus != 0);
213
215 CurrentValue = &PitChannels[Channel].OutputLatch;
216
217 if (*ReadWriteMode & 1)
218 {
219 /* Read LSB */
220 *ReadWriteMode &= ~1;
221 return LOBYTE(*CurrentValue);
222 }
223
224 if (*ReadWriteMode & 2)
225 {
226 /* Read MSB */
227 *ReadWriteMode &= ~2;
228 return HIBYTE(*CurrentValue);
229 }
230
231 /* Shouldn't get here */
232 ASSERT(FALSE);
233 return 0;
234}
static VOID ReadWriteMode(_In_ UCHAR Mode)
Definition: vga.c:74
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
#define ASSERT(a)
Definition: mode.c:44
static VOID PitLatchChannelCount(BYTE Channel)
Definition: pit.c:58
unsigned char * LPBYTE
Definition: typedefs.h:53
uint16_t * LPWORD
Definition: typedefs.h:56

Referenced by PitReadPort().

◆ PitReadPort()

static BYTE WINAPI PitReadPort ( USHORT  Port)
static

Definition at line 286 of file pit.c.

287{
288 switch (Port)
289 {
290 case PIT_DATA_PORT(0):
291 case PIT_DATA_PORT(1):
292 case PIT_DATA_PORT(2):
293 {
294 return PitReadData(Port - PIT_DATA_PORT(0));
295 }
296 }
297
298 return 0;
299}
CPPORT Port[4]
Definition: headless.c:35
static BYTE PitReadData(BYTE Channel)
Definition: pit.c:193

Referenced by PitInitialize().

◆ PitSetGate()

VOID PitSetGate ( BYTE  Channel,
BOOLEAN  State 
)

Definition at line 484 of file pit.c.

485{
486 if (Channel >= PIT_CHANNELS) return;
487 if (State == PitChannels[Channel].Gate) return;
488
489 /* UNIMPLEMENTED */
490 PitChannels[Channel].Gate = State;
491}
BOOLEAN Gate
Definition: pit.h:55

Referenced by PitInitialize(), and Port61hWrite().

◆ PitSetOut()

static VOID PitSetOut ( PPIT_CHANNEL  Channel,
BOOLEAN  State 
)
static

HACK!! **\ if (State == Channel->Out) return; ** HACK!!

Definition at line 79 of file pit.c.

80{
83 /* Set the new state of the OUT pin */
84 Channel->Out = State;
85
86 /* Call the callback */
87 if (!Channel->Gate) return; // HACK: This is a HACK until gates are properly used (needed for the speaker to work properly).
88 if (Channel->OutFunction) Channel->OutFunction(Channel->OutParam, State);
89}
PIT_OUT_FUNCTION OutFunction
Definition: pit.h:68
LPVOID OutParam
Definition: pit.h:67

Referenced by PitDecrementCount(), and PitInitCounter().

◆ PitSetOutFunction()

VOID PitSetOutFunction ( BYTE  Channel,
LPVOID  Param,
PIT_OUT_FUNCTION  OutFunction 
)

Definition at line 476 of file pit.c.

477{
478 if (Channel >= PIT_CHANNELS) return;
479
480 PitChannels[Channel].OutParam = Param;
481 PitChannels[Channel].OutFunction = OutFunction;
482}

Referenced by EmulatorInitialize(), and PitInitialize().

◆ PitWriteCommand()

static VOID PitWriteCommand ( BYTE  Value)
static

HACK!!

HACK!!

Definition at line 109 of file pit.c.

110{
111 BYTE Channel = (Value >> 6) & 0x03;
112 BYTE ReadWriteMode = (Value >> 4) & 0x03;
113 BYTE Mode = (Value >> 1) & 0x07;
114 BOOLEAN IsBcd = Value & 0x01;
115
116 /*
117 * Check for valid PIT channel - Possible values: 0, 1, 2.
118 * A value of 3 is for Read-Back Command.
119 */
120 if (Channel > PIT_CHANNELS) return;
121
122 /* Read-Back Command */
123 if (Channel == PIT_CHANNELS)
124 {
125 if ((Value & 0x20) == 0) // Bit 5 (Count) == 0: We latch multiple counters' counts
126 {
127 if (Value & 0x02) PitLatchChannelCount(0);
128 if (Value & 0x04) PitLatchChannelCount(1);
129 if (Value & 0x08) PitLatchChannelCount(2);
130 }
131 if ((Value & 0x10) == 0) // Bit 4 (Status) == 0: We latch multiple counters' statuses
132 {
133 if (Value & 0x02) PitLatchChannelStatus(0);
134 if (Value & 0x04) PitLatchChannelStatus(1);
135 if (Value & 0x08) PitLatchChannelStatus(2);
136 }
137 return;
138 }
139
140 /* Check if this is a counter latch command... */
141 if (ReadWriteMode == 0)
142 {
143 PitLatchChannelCount(Channel);
144 return;
145 }
146
147 /* ... otherwise, set the modes and reset flip-flops */
149 PitChannels[Channel].ReadStatus = 0x00;
150 PitChannels[Channel].WriteStatus = 0x00;
151
153 PitChannels[Channel].StatusLatch = 0x00;
154
155 PitChannels[Channel].CountRegister = 0x00;
156 PitChannels[Channel].OutputLatch = 0x00;
157PitChannels[Channel].FlipFlop = FALSE;
160 /* Fix the current value if we switch to BCD counting */
161 PitChannels[Channel].Bcd = IsBcd;
162 if (IsBcd && PitChannels[Channel].CurrentValue > 9999)
163 PitChannels[Channel].CurrentValue = 9999;
164
165 switch (Mode)
166 {
167 case 0:
168 case 1:
169 case 2:
170 case 3:
171 case 4:
172 case 5:
173 {
174 PitChannels[Channel].Mode = Mode;
175 break;
176 }
177
178 case 6:
179 case 7:
180 {
181 /*
182 * Modes 6 and 7 become PIT_MODE_RATE_GENERATOR
183 * and PIT_MODE_SQUARE_WAVE respectively.
184 */
185 PitChannels[Channel].Mode = Mode - 4;
186 break;
187 }
188 }
189
190 PitInitCounter(&PitChannels[Channel]);
191}
_In_ ULONG Mode
Definition: hubbusif.h:303
static VOID PitInitCounter(PPIT_CHANNEL Channel)
Definition: pit.c:91
static VOID PitLatchChannelStatus(BYTE Channel)
Definition: pit.c:32
BYTE WriteStatus
Definition: pit.h:48
WORD CountRegister
Definition: pit.h:57
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413

Referenced by PitWritePort().

◆ PitWriteData()

static VOID PitWriteData ( BYTE  Channel,
BYTE  Value 
)
static

Definition at line 236 of file pit.c.

237{
239
240 if (PitChannels[Channel].WriteStatus == 0x00)
241 {
243 }
244
245 ASSERT(PitChannels[Channel].WriteStatus != 0);
246
248
249 if (*ReadWriteMode & 1)
250 {
251 /* Write LSB */
252 *ReadWriteMode &= ~1;
253 PitChannels[Channel].CountRegister &= 0xFF00;
254 PitChannels[Channel].CountRegister |= Value;
255 }
256 else if (*ReadWriteMode & 2)
257 {
258 /* Write MSB */
259 *ReadWriteMode &= ~2;
260 PitChannels[Channel].CountRegister &= 0x00FF;
261 PitChannels[Channel].CountRegister |= Value << 8;
262 }
263
264 /* ReadWriteMode went to zero: we are going to load the new count */
265 if (*ReadWriteMode == 0x00)
266 {
267 if (PitChannels[Channel].CountRegister == 0x0000)
268 {
269 /* Wrap around to the highest count */
270 if (PitChannels[Channel].Bcd)
271 PitChannels[Channel].CountRegister = 9999;
272 else
273 PitChannels[Channel].CountRegister = 0xFFFF; // 0x10000; // 65536
274 }
275
276 /* Convert the current value from BCD if needed */
277 PitChannels[Channel].CountRegister =
278 WRITE_PIT_VALUE(PitChannels[Channel], PitChannels[Channel].CountRegister);
280
281 /* Reload now the new count */
283 }
284}
#define WRITE_PIT_VALUE(PitChannel, Value)
Definition: pit.h:21

Referenced by PitWritePort().

◆ PitWritePort()

static VOID WINAPI PitWritePort ( USHORT  Port,
BYTE  Data 
)
static

Definition at line 301 of file pit.c.

302{
303 switch (Port)
304 {
305 case PIT_COMMAND_PORT:
306 {
308 break;
309 }
310
311 case PIT_DATA_PORT(0):
312 case PIT_DATA_PORT(1):
313 case PIT_DATA_PORT(2):
314 {
316 break;
317 }
318 }
319}
static VOID PitWriteData(BYTE Channel, BYTE Value)
Definition: pit.c:236
static VOID PitWriteCommand(BYTE Value)
Definition: pit.c:109

Referenced by PitInitialize().

Variable Documentation

◆ MasterClock

PHARDWARE_TIMER MasterClock
static

Definition at line 28 of file pit.c.

Referenced by DECLARE_INTERFACE_(), and PitInitialize().

◆ PitChannels