Author: aandrejevic Date: Fri Dec 6 04:35:58 2013 New Revision: 61229
URL: http://svn.reactos.org/svn/reactos?rev=61229&view=rev Log: [NTVDM] Improve the keyboard event handling. Clean up the PS/2 code a bit.
Modified: branches/ntvdm/subsystems/ntvdm/bios.c branches/ntvdm/subsystems/ntvdm/ntvdm.c branches/ntvdm/subsystems/ntvdm/ntvdm.h branches/ntvdm/subsystems/ntvdm/ps2.c branches/ntvdm/subsystems/ntvdm/ps2.h
Modified: branches/ntvdm/subsystems/ntvdm/bios.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.c?re... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] Fri Dec 6 04:35:58 2013 @@ -1429,47 +1429,42 @@ BYTE ScanCode, VirtualKey; WORD Character;
- /* Loop while there is a scancode available */ - do + /* Get the scan code and virtual key code */ + ScanCode = PS2ReadPort(PS2_DATA_PORT); + VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK); + + /* Check if this is a key press or release */ + if (!(ScanCode & (1 << 7))) { - /* Get the scan code and virtual key code */ - ScanCode = KeyboardReadData(); - VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK); - - /* Check if this is a key press or release */ - if (!(ScanCode & (1 << 7))) + /* Key press */ + if (VirtualKey == VK_NUMLOCK || + VirtualKey == VK_CAPITAL || + VirtualKey == VK_SCROLL || + VirtualKey == VK_INSERT) { - /* Key press */ - if (VirtualKey == VK_NUMLOCK || - VirtualKey == VK_CAPITAL || - VirtualKey == VK_SCROLL || - VirtualKey == VK_INSERT) - { - /* For toggle keys, toggle the lowest bit in the keyboard map */ - BiosKeyboardMap[VirtualKey] ^= ~(1 << 0); - } - - /* Set the highest bit */ - BiosKeyboardMap[VirtualKey] |= (1 << 7); - - /* Find out which character this is */ + /* For toggle keys, toggle the lowest bit in the keyboard map */ + BiosKeyboardMap[VirtualKey] ^= ~(1 << 0); + } + + /* Set the highest bit */ + BiosKeyboardMap[VirtualKey] |= (1 << 7); + + /* Find out which character this is */ + Character = 0; + if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0) + { + /* Not ASCII */ Character = 0; - if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0) - { - /* Not ASCII */ - Character = 0; - } - - /* Push it onto the BIOS keyboard queue */ - BiosKbdBufferPush(MAKEWORD(Character, ScanCode)); } - else - { - /* Key release, unset the highest bit */ - BiosKeyboardMap[VirtualKey] &= ~(1 << 7); - } + + /* Push it onto the BIOS keyboard queue */ + BiosKbdBufferPush(MAKEWORD(Character, ScanCode)); } - while (KeyboardReadStatus() & 1); + else + { + /* Key release, unset the highest bit */ + BiosKeyboardMap[VirtualKey] &= ~(1 << 7); + }
/* Clear the keyboard flags */ Bda->KeybdShiftFlags = 0;
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.c?r... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/ntvdm.c [iso-8859-1] Fri Dec 6 04:35:58 2013 @@ -78,6 +78,7 @@ DWORD LastVerticalRefresh; DWORD LastCyclePrintout; DWORD Cycles = 0; + INT KeyboardIntCounter = 0;
/* Set the handler routine */ SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); @@ -225,6 +226,13 @@ { VgaRefreshDisplay(); LastVerticalRefresh = CurrentTickCount; + } + + KeyboardIntCounter++; + if (KeyboardIntCounter == KBD_INT_CYCLES) + { + GenerateKeyboardInterrupts(); + KeyboardIntCounter = 0; }
/* Horizontal retrace occurs as fast as possible */
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.h?r... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/ntvdm.h [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/ntvdm.h [iso-8859-1] Fri Dec 6 04:35:58 2013 @@ -45,6 +45,7 @@
/* Processor speed */ #define STEPS_PER_CYCLE 256 +#define KBD_INT_CYCLES 16
/* FUNCTIONS ******************************************************************/
Modified: branches/ntvdm/subsystems/ntvdm/ps2.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ps2.c?rev... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/ps2.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/ps2.c [iso-8859-1] Fri Dec 6 04:35:58 2013 @@ -25,23 +25,16 @@ static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE; static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG; static HANDLE QueueMutex = NULL; - static HANDLE InputThread = NULL;
/* PRIVATE FUNCTIONS **********************************************************/
static BOOLEAN KeyboardQueuePush(BYTE ScanCode) { - BOOLEAN Result = TRUE; + /* Check if the keyboard queue is full */ + if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd)) return FALSE;
WaitForSingleObject(QueueMutex, INFINITE); - - /* Check if the keyboard queue is full */ - if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd)) - { - Result = FALSE; - goto Done; - }
/* Insert the value in the queue */ KeyboardQueue[KeyboardQueueEnd] = ScanCode; @@ -51,23 +44,16 @@ /* Since we inserted a value, it's not empty anymore */ KeyboardQueueEmpty = FALSE;
-Done: ReleaseMutex(QueueMutex); - return Result; + return TRUE; }
static BOOLEAN KeyboardQueuePop(BYTE *ScanCode) { - BOOLEAN Result = TRUE; + /* Make sure the keyboard queue is not empty */ + if (KeyboardQueueEmpty) return FALSE;
WaitForSingleObject(QueueMutex, INFINITE); - - /* Make sure the keyboard queue is not empty */ - if (KeyboardQueueEmpty) - { - Result = FALSE; - goto Done; - }
/* Get the scan code */ *ScanCode = KeyboardQueue[KeyboardQueueStart]; @@ -82,222 +68,208 @@ KeyboardQueueEmpty = TRUE; }
-Done: ReleaseMutex(QueueMutex); - return Result; + return TRUE; }
/* PUBLIC FUNCTIONS ***********************************************************/
-BYTE KeyboardReadStatus() -{ - BYTE Status = 0; - - WaitForSingleObject(QueueMutex, INFINITE); - - /* Set the first bit if the data can be read */ - if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0; - - ReleaseMutex(QueueMutex); - - /* Always set bit 2 */ - Status |= 1 << 2; - - /* Set bit 3 if the next byte goes to the controller */ - if (KeyboardWriteResponse) Status |= 1 << 3; - - return Status; -} - -VOID KeyboardWriteCommand(BYTE Command) -{ - switch (Command) - { - /* Read configuration byte */ - case 0x20: - { - KeyboardResponse = KeyboardConfig; - KeyboardReadResponse = TRUE; - break; - } - - /* Write configuration byte */ - case 0x60: - /* Write controller output port */ - case 0xD1: - /* Write keyboard output buffer */ - case 0xD2: - /* Write mouse output buffer */ - case 0xD3: - /* Write mouse input buffer */ - case 0xD4: - { - /* These commands require a response */ - KeyboardResponse = Command; - KeyboardWriteResponse = TRUE; - break; - } - - /* Disable mouse */ - case 0xA7: - { - // TODO: Mouse support - break; - } - - /* Enable mouse */ - case 0xA8: - { - // TODO: Mouse support - break; - } - - /* Test mouse port */ - case 0xA9: - { - KeyboardResponse = 0; - KeyboardReadResponse = TRUE; - break; - } - - /* Test PS/2 controller */ - case 0xAA: - { - KeyboardResponse = 0x55; - KeyboardReadResponse = TRUE; - break; - } - - /* Disable keyboard */ - case 0xAD: - { - // TODO: Not implemented - break; - } - - /* Enable keyboard */ - case 0xAE: - { - // TODO: Not implemented - break; - } - - /* Read controller output port */ - case 0xD0: - { - // TODO: Not implemented - break; - } - - /* CPU Reset */ - case 0xF0: - case 0xF2: - case 0xF4: - case 0xF6: - case 0xF8: - case 0xFA: - case 0xFC: - case 0xFE: - { - /* Stop the simulation */ - VdmRunning = FALSE; - break; - } - } -} - -BYTE KeyboardReadData() -{ - /* If there was a response byte from the controller, return it */ - if (KeyboardReadResponse) - { - KeyboardReadResponse = FALSE; - KeyboardData = KeyboardResponse; - } - else - { - /* Otherwise, read the data from the queue */ - KeyboardQueuePop(&KeyboardData); - } - - return KeyboardData; -} - -VOID KeyboardWriteData(BYTE Data) -{ - /* Check if the controller is waiting for a response */ - if (KeyboardWriteResponse) - { - KeyboardWriteResponse = FALSE; - - /* Check which command it was */ - switch (KeyboardResponse) - { +BYTE WINAPI PS2ReadPort(ULONG Port) +{ + if (Port == PS2_CONTROL_PORT) + { + BYTE Status = 0; + + /* Set the first bit if the data can be read */ + if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0; + + /* Always set bit 2 */ + Status |= 1 << 2; + + /* Set bit 3 if the next byte goes to the controller */ + if (KeyboardWriteResponse) Status |= 1 << 3; + + return Status; + } + else if (Port == PS2_DATA_PORT) + { + /* If there was a response byte from the controller, return it */ + if (KeyboardReadResponse) + { + KeyboardReadResponse = FALSE; + KeyboardData = KeyboardResponse; + } + + return KeyboardData; + } + else return 0; +} + +VOID WINAPI PS2WritePort(ULONG Port, BYTE Data) +{ + if (Port == PS2_CONTROL_PORT) + { + switch (Data) + { + /* Read configuration byte */ + case 0x20: + { + KeyboardResponse = KeyboardConfig; + KeyboardReadResponse = TRUE; + break; + } + /* Write configuration byte */ case 0x60: - { - KeyboardConfig = Data; - break; - } - - /* Write controller output */ + /* Write controller output port */ case 0xD1: - { - /* Check if bit 0 is unset */ - if (!(Data & (1 << 0))) - { - /* CPU disabled - end simulation */ - VdmRunning = FALSE; - } - - /* Update the A20 line setting */ - EmulatorSetA20(Data & (1 << 1)); - - break; - } + /* Write keyboard output buffer */ + case 0xD2: + /* Write mouse output buffer */ + case 0xD3: + /* Write mouse input buffer */ + case 0xD4: + { + /* These commands require a response */ + KeyboardResponse = Data; + KeyboardWriteResponse = TRUE; + break; + } + + /* Disable mouse */ + case 0xA7: + { + // TODO: Mouse support + break; + } + + /* Enable mouse */ + case 0xA8: + { + // TODO: Mouse support + break; + } + + /* Test mouse port */ + case 0xA9: + { + KeyboardResponse = 0; + KeyboardReadResponse = TRUE; + break; + } + + /* Test PS/2 controller */ + case 0xAA: + { + KeyboardResponse = 0x55; + KeyboardReadResponse = TRUE; + break; + } + + /* Disable keyboard */ + case 0xAD: + { + // TODO: Not implemented + break; + } + + /* Enable keyboard */ + case 0xAE: + { + // TODO: Not implemented + break; + } + + /* Read controller output port */ + case 0xD0: + { + // TODO: Not implemented + break; + } + + /* CPU Reset */ + case 0xF0: + case 0xF2: + case 0xF4: + case 0xF6: + case 0xF8: + case 0xFA: + case 0xFC: + case 0xFE: + { + /* Stop the simulation */ + VdmRunning = FALSE; + break; + } + } + } + else if (Port == PS2_DATA_PORT) + { + /* Check if the controller is waiting for a response */ + if (KeyboardWriteResponse) + { + KeyboardWriteResponse = FALSE; + + /* Check which command it was */ + switch (KeyboardResponse) + { + /* Write configuration byte */ + case 0x60: + { + KeyboardConfig = Data; + break; + } + + /* Write controller output */ + case 0xD1: + { + /* Check if bit 0 is unset */ + if (!(Data & (1 << 0))) + { + /* CPU disabled - end simulation */ + VdmRunning = FALSE; + } + + /* Update the A20 line setting */ + EmulatorSetA20(Data & (1 << 1)); + + break; + }
- case 0xD2: - { - /* Push the data byte to the keyboard queue */ - KeyboardQueuePush(Data); - break; - } - - case 0xD3: - { - // TODO: Mouse support - break; - } - - case 0xD4: - { - // TODO: Mouse support - break; - } - } - - return; - } - - // TODO: Implement PS/2 device commands -} - -BYTE WINAPI PS2ReadPort(ULONG Port) -{ - if (Port == PS2_CONTROL_PORT) - return KeyboardReadStatus(); - else if (Port == PS2_DATA_PORT) - return KeyboardReadData(); - else - return 0; -} - -VOID WINAPI PS2WritePort(ULONG Port, BYTE Data) -{ - if (Port == PS2_CONTROL_PORT) - KeyboardWriteCommand(Data); - else if (Port == PS2_DATA_PORT) - KeyboardWriteData(Data); + case 0xD2: + { + /* Push the data byte to the keyboard queue */ + KeyboardQueuePush(Data); + break; + } + + case 0xD3: + { + // TODO: Mouse support + break; + } + + case 0xD4: + { + // TODO: Mouse support + break; + } + } + + return; + } + + // TODO: Implement PS/2 device commands + } +} + +VOID GenerateKeyboardInterrupts(VOID) +{ + if (KeyboardQueuePop(&KeyboardData)) + { + /* IRQ 1 */ + PicInterruptRequest(1); + } }
DWORD WINAPI InputThreadProc(LPVOID Parameter) @@ -335,8 +307,6 @@ KeyboardQueuePush(ScanCode); }
- /* Keyboard IRQ */ - PicInterruptRequest(1); break; }
Modified: branches/ntvdm/subsystems/ntvdm/ps2.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ps2.h?rev... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/ps2.h [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/ps2.h [iso-8859-1] Fri Dec 6 04:35:58 2013 @@ -24,13 +24,11 @@
/* FUNCTIONS ******************************************************************/
-BYTE KeyboardReadStatus(); -//VOID KeyboardWriteCommand(BYTE Command); -BYTE KeyboardReadData(); -//VOID KeyboardWriteData(BYTE Data); - BOOLEAN PS2Initialize(HANDLE ConsoleInput); VOID PS2Cleanup(VOID); +BYTE WINAPI PS2ReadPort(ULONG Port); +VOID WINAPI PS2WritePort(ULONG Port, BYTE Data); +VOID GenerateKeyboardInterrupts(VOID);
#endif // _PS2_H_