2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: PS/2 controller emulation
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
9 /* INCLUDES *******************************************************************/
17 /* PRIVATE VARIABLES **********************************************************/
19 static BYTE KeyboardQueue
[KEYBOARD_BUFFER_SIZE
];
20 static BOOLEAN KeyboardQueueEmpty
= TRUE
;
21 static UINT KeyboardQueueStart
= 0;
22 static UINT KeyboardQueueEnd
= 0;
23 static BYTE KeyboardResponse
= 0;
24 static BOOLEAN KeyboardReadResponse
= FALSE
, KeyboardWriteResponse
= FALSE
;
25 static BYTE KeyboardConfig
= PS2_DEFAULT_CONFIG
;
27 /* PRIVATE FUNCTIONS **********************************************************/
29 static BOOLEAN
KeyboardQueuePush(BYTE ScanCode
)
31 /* Check if the keyboard queue is full */
32 if (!KeyboardQueueEmpty
&& (KeyboardQueueStart
== KeyboardQueueEnd
))
37 /* Insert the value in the queue */
38 KeyboardQueue
[KeyboardQueueEnd
] = ScanCode
;
40 KeyboardQueueEnd
%= KEYBOARD_BUFFER_SIZE
;
42 /* Since we inserted a value, it's not empty anymore */
43 KeyboardQueueEmpty
= FALSE
;
48 static BOOLEAN
KeyboardQueuePop(BYTE
*ScanCode
)
50 /* Make sure the keyboard queue is not empty */
51 if (KeyboardQueueEmpty
) return FALSE
;
53 /* Get the scan code */
54 *ScanCode
= KeyboardQueue
[KeyboardQueueStart
];
56 /* Remove the value from the queue */
58 KeyboardQueueStart
%= KEYBOARD_BUFFER_SIZE
;
60 /* Check if the queue is now empty */
61 if (KeyboardQueueStart
== KeyboardQueueEnd
)
63 KeyboardQueueEmpty
= TRUE
;
69 /* PUBLIC FUNCTIONS ***********************************************************/
71 BYTE
KeyboardReadStatus()
75 /* Set the first bit if the data can be read */
76 if (KeyboardReadResponse
|| !KeyboardQueueEmpty
) Status
|= 1 << 0;
78 /* Always set bit 2 */
81 /* Set bit 3 if the next byte goes to the controller */
82 if (KeyboardWriteResponse
) Status
|= 1 << 3;
87 VOID
KeyboardWriteCommand(BYTE Command
)
91 /* Read configuration byte */
94 KeyboardResponse
= KeyboardConfig
;
95 KeyboardReadResponse
= TRUE
;
100 /* Write configuration byte */
102 /* Write controller output port */
104 /* Write keyboard output buffer */
106 /* Write mouse output buffer */
108 /* Write mouse input buffer */
111 /* These commands require a response */
112 KeyboardResponse
= Command
;
113 KeyboardWriteResponse
= TRUE
;
121 // TODO: Mouse support
129 // TODO: Mouse support
134 /* Test mouse port */
137 KeyboardResponse
= 0;
138 KeyboardReadResponse
= TRUE
;
143 /* Test PS/2 controller */
146 KeyboardResponse
= 0x55;
147 KeyboardReadResponse
= TRUE
;
152 /* Disable keyboard */
155 // TODO: Not implemented
159 /* Enable keyboard */
162 // TODO: Not implemented
166 /* Read controller output port */
169 // TODO: Not implemented
183 /* Stop the simulation */
191 BYTE
KeyboardReadData()
195 /* If there was a response byte from the controller, return it */
196 if (KeyboardReadResponse
)
198 KeyboardReadResponse
= FALSE
;
199 return KeyboardResponse
;
202 /* Otherwise, read the data from the queue */
203 KeyboardQueuePop(&Value
);
208 VOID
KeyboardWriteData(BYTE Data
)
210 /* Check if the controller is waiting for a response */
211 if (KeyboardWriteResponse
)
213 KeyboardWriteResponse
= FALSE
;
215 /* Check which command it was */
216 switch (KeyboardResponse
)
218 /* Write configuration byte */
221 KeyboardConfig
= Data
;
225 /* Write controller output */
228 /* Check if bit 0 is unset */
229 if (!(Data
& (1 << 0)))
231 /* CPU disabled - end simulation */
235 /* Update the A20 line setting */
236 EmulatorSetA20(Data
& (1 << 1));
243 /* Push the data byte to the keyboard queue */
244 KeyboardQueuePush(Data
);
251 // TODO: Mouse support
257 // TODO: Mouse support
265 // TODO: Implement PS/2 device commands
268 VOID
CheckForInputEvents()
270 PINPUT_RECORD Buffer
;
271 HANDLE ConsoleInput
= GetStdHandle(STD_INPUT_HANDLE
);
272 DWORD i
, j
, Count
, TotalEvents
;
275 /* Get the number of input events */
276 if (!GetNumberOfConsoleInputEvents(ConsoleInput
, &Count
)) return;
277 if (Count
== 0) return;
279 /* Allocate the buffer */
280 Buffer
= (PINPUT_RECORD
)HeapAlloc(GetProcessHeap(), 0, Count
* sizeof(INPUT_RECORD
));
281 if (Buffer
== NULL
) return;
283 /* Peek the input events */
284 if (!ReadConsoleInput(ConsoleInput
, Buffer
, Count
, &TotalEvents
)) goto Cleanup
;
286 for (i
= 0; i
< TotalEvents
; i
++)
288 /* Check if this is a key event */
289 if (Buffer
[i
].EventType
!= KEY_EVENT
) continue;
291 /* Get the scan code */
292 ScanCode
= Buffer
[i
].Event
.KeyEvent
.wVirtualScanCode
;
294 /* If this is a key release, set the highest bit in the scan code */
295 if (!Buffer
[i
].Event
.KeyEvent
.bKeyDown
) ScanCode
|= 0x80;
297 /* Push the scan code onto the keyboard queue */
298 for (j
= 0; j
< Buffer
[i
].Event
.KeyEvent
.wRepeatCount
; j
++)
300 KeyboardQueuePush(ScanCode
);
304 PicInterruptRequest(1);
311 HeapFree(GetProcessHeap(), 0, Buffer
);