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 *******************************************************************/
15 /* PRIVATE VARIABLES **********************************************************/
17 static BYTE KeyboardQueue
[KEYBOARD_BUFFER_SIZE
];
18 static BOOLEAN KeyboardQueueEmpty
= TRUE
;
19 static UINT KeyboardQueueStart
= 0;
20 static UINT KeyboardQueueEnd
= 0;
21 static BYTE KeyboardResponse
= 0;
22 static BOOLEAN KeyboardReadResponse
= FALSE
, KeyboardWriteResponse
= FALSE
;
23 static BYTE KeyboardConfig
= PS2_DEFAULT_CONFIG
;
25 /* PRIVATE FUNCTIONS **********************************************************/
27 static BOOLEAN
KeyboardQueuePush(BYTE ScanCode
)
29 /* Check if the keyboard queue is full */
30 if (!KeyboardQueueEmpty
&& (KeyboardQueueStart
== KeyboardQueueEnd
))
35 /* Insert the value in the queue */
36 KeyboardQueue
[KeyboardQueueEnd
] = ScanCode
;
38 KeyboardQueueEnd
%= KEYBOARD_BUFFER_SIZE
;
40 /* Since we inserted a value, it's not empty anymore */
41 KeyboardQueueEmpty
= FALSE
;
46 static BOOLEAN
KeyboardQueuePop(BYTE
*ScanCode
)
48 /* Make sure the keyboard queue is not empty */
49 if (KeyboardQueueEmpty
) return FALSE
;
51 /* Get the scan code */
52 *ScanCode
= KeyboardQueue
[KeyboardQueueStart
];
54 /* Remove the value from the queue */
56 KeyboardQueueStart
%= KEYBOARD_BUFFER_SIZE
;
58 /* Check if the queue is now empty */
59 if (KeyboardQueueStart
== KeyboardQueueEnd
)
61 KeyboardQueueEmpty
= TRUE
;
67 /* PUBLIC FUNCTIONS ***********************************************************/
69 BYTE
KeyboardReadStatus()
73 /* Set the first bit if the data can be read */
74 if (KeyboardReadResponse
|| !KeyboardQueueEmpty
) Status
|= 1 << 0;
76 /* Always set bit 2 */
79 /* Set bit 3 if the next byte goes to the controller */
80 if (KeyboardWriteResponse
) Status
|= 1 << 3;
85 VOID
KeyboardWriteCommand(BYTE Command
)
89 /* Read configuration byte */
92 KeyboardResponse
= KeyboardConfig
;
93 KeyboardReadResponse
= TRUE
;
98 /* Write configuration byte */
100 /* Write controller output port */
102 /* Write keyboard output buffer */
104 /* Write mouse output buffer */
106 /* Write mouse input buffer */
109 /* These commands require a response */
110 KeyboardResponse
= Command
;
111 KeyboardWriteResponse
= TRUE
;
119 // TODO: Mouse support
127 // TODO: Mouse support
132 /* Test mouse port */
135 KeyboardResponse
= 0;
136 KeyboardReadResponse
= TRUE
;
141 /* Test PS/2 controller */
144 KeyboardResponse
= 0x55;
145 KeyboardReadResponse
= TRUE
;
150 /* Disable keyboard */
153 // TODO: Not implemented
157 /* Enable keyboard */
160 // TODO: Not implemented
164 /* Read controller output port */
167 // TODO: Not implemented
181 /* Stop the simulation */
189 BYTE
KeyboardReadData()
193 /* If there was a response byte from the controller, return it */
194 if (KeyboardReadResponse
)
196 KeyboardReadResponse
= FALSE
;
197 return KeyboardResponse
;
200 /* Otherwise, read the data from the queue */
201 KeyboardQueuePop(&Value
);
206 VOID
KeyboardWriteData(BYTE Data
)
208 /* Check if the controller is waiting for a response */
209 if (KeyboardWriteResponse
)
211 KeyboardWriteResponse
= FALSE
;
213 /* Check which command it was */
214 switch (KeyboardResponse
)
216 /* Write configuration byte */
219 KeyboardConfig
= Data
;
223 /* Write controller output */
226 /* Check if bit 0 is unset */
227 if (!(Data
& (1 << 0)))
229 /* CPU disabled - end simulation */
233 /* Update the A20 line setting */
234 EmulatorSetA20(Data
& (1 << 1));
241 /* Push the data byte to the keyboard queue */
242 KeyboardQueuePush(Data
);
249 // TODO: Mouse support
255 // TODO: Mouse support
263 // TODO: Implement PS/2 device commands
266 VOID
CheckForInputEvents()
268 PINPUT_RECORD Buffer
;
269 HANDLE ConsoleInput
= GetStdHandle(STD_INPUT_HANDLE
);
270 DWORD i
, j
, Count
, TotalEvents
;
273 /* Get the number of input events */
274 if (!GetNumberOfConsoleInputEvents(ConsoleInput
, &Count
)) return;
275 if (Count
== 0) return;
277 /* Allocate the buffer */
278 Buffer
= (PINPUT_RECORD
)HeapAlloc(GetProcessHeap(), 0, Count
* sizeof(INPUT_RECORD
));
279 if (Buffer
== NULL
) return;
281 /* Peek the input events */
282 if (!ReadConsoleInput(ConsoleInput
, Buffer
, Count
, &TotalEvents
)) goto Cleanup
;
284 for (i
= 0; i
< TotalEvents
; i
++)
286 /* Check if this is a key event */
287 if (Buffer
[i
].EventType
!= KEY_EVENT
) continue;
289 /* Get the scan code */
290 ScanCode
= Buffer
[i
].Event
.KeyEvent
.wVirtualScanCode
;
292 /* If this is a key release, set the highest bit in the scan code */
293 if (!Buffer
[i
].Event
.KeyEvent
.bKeyDown
) ScanCode
|= 0x80;
295 /* Push the scan code onto the keyboard queue */
296 for (j
= 0; j
< Buffer
[i
].Event
.KeyEvent
.wRepeatCount
; j
++)
298 KeyboardQueuePush(ScanCode
);
302 PicInterruptRequest(1);
309 HeapFree(GetProcessHeap(), 0, Buffer
);