[NTVDM]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 6 Dec 2013 04:35:58 +0000 (04:35 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Fri, 6 Dec 2013 04:35:58 +0000 (04:35 +0000)
Improve the keyboard event handling.
Clean up the PS/2 code a bit.

svn path=/branches/ntvdm/; revision=61229

subsystems/ntvdm/bios.c
subsystems/ntvdm/ntvdm.c
subsystems/ntvdm/ntvdm.h
subsystems/ntvdm/ps2.c
subsystems/ntvdm/ps2.h

index 25294bc..9670caf 100644 (file)
@@ -1429,47 +1429,42 @@ VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
             BYTE ScanCode, VirtualKey;
             WORD Character;
 
-            /* Loop while there is a scancode available */
-            do
-            {
-                /* Get the scan code and virtual key code */
-                ScanCode = KeyboardReadData();
-                VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
+            /* 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)))
+            /* 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);
-                    }
+                    /* For toggle keys, toggle the lowest bit in the keyboard map */
+                    BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
+                }
 
-                    /* Set the highest bit */
-                    BiosKeyboardMap[VirtualKey] |= (1 << 7);
+                /* 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;
-                    }
-
-                    /* Push it onto the BIOS keyboard queue */
-                    BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
-                }
-                else
+                /* Find out which character this is */
+                Character = 0;
+                if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
                 {
-                    /* Key release, unset the highest bit */
-                    BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
+                    /* 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);
             }
-            while (KeyboardReadStatus() & 1);
 
             /* Clear the keyboard flags */
             Bda->KeybdShiftFlags = 0;
index fb8e738..4c0df14 100644 (file)
@@ -78,6 +78,7 @@ INT wmain(INT argc, WCHAR *argv[])
     DWORD LastVerticalRefresh;
     DWORD LastCyclePrintout;
     DWORD Cycles = 0;
+    INT KeyboardIntCounter = 0;
 
     /* Set the handler routine */
     SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
@@ -227,6 +228,13 @@ INT wmain(INT argc, WCHAR *argv[])
             LastVerticalRefresh = CurrentTickCount;
         }
 
+        KeyboardIntCounter++;
+        if (KeyboardIntCounter == KBD_INT_CYCLES)
+        {
+            GenerateKeyboardInterrupts();
+            KeyboardIntCounter = 0;
+        }
+
         /* Horizontal retrace occurs as fast as possible */
         VgaHorizontalRetrace();
 
index c057413..96fe0f8 100644 (file)
@@ -45,6 +45,7 @@
 
 /* Processor speed */
 #define STEPS_PER_CYCLE 256
+#define KBD_INT_CYCLES 16
 
 /* FUNCTIONS ******************************************************************/
 
index 5138d0b..d2f9997 100644 (file)
@@ -25,24 +25,17 @@ static BYTE KeyboardData = 0, KeyboardResponse = 0;
 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;
     KeyboardQueueEnd++;
@@ -51,24 +44,17 @@ static BOOLEAN KeyboardQueuePush(BYTE ScanCode)
     /* 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 @@ static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
         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)
+BYTE WINAPI PS2ReadPort(ULONG Port)
 {
-    switch (Command)
+    if (Port == PS2_CONTROL_PORT)
     {
-        /* 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;
-        }
+        BYTE Status = 0;
 
-        /* Enable mouse */
-        case 0xA8:
-        {
-            // TODO: Mouse support
-            break;
-        }
+        /* Set the first bit if the data can be read */
+        if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0;
 
-        /* Test mouse port */
-        case 0xA9:
-        {
-            KeyboardResponse = 0;
-            KeyboardReadResponse = TRUE;
-            break;
-        }
+        /* Always set bit 2 */
+        Status |= 1 << 2;
 
-        /* Test PS/2 controller */
-        case 0xAA:
-        {
-            KeyboardResponse = 0x55;
-            KeyboardReadResponse = TRUE;
-            break;
-        }
+        /* Set bit 3 if the next byte goes to the controller */
+        if (KeyboardWriteResponse) Status |= 1 << 3;
 
-        /* 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:
+        return Status;
+    }
+    else if (Port == PS2_DATA_PORT)
+    {
+        /* If there was a response byte from the controller, return it */
+        if (KeyboardReadResponse)
         {
-            /* Stop the simulation */
-            VdmRunning = FALSE;
-            break;
+            KeyboardReadResponse = FALSE;
+            KeyboardData = KeyboardResponse;
         }
-    }
-}
 
-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;
     }
-
-    return KeyboardData;
+    else return 0;
 }
 
-VOID KeyboardWriteData(BYTE Data)
+VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
 {
-    /* Check if the controller is waiting for a response */
-    if (KeyboardWriteResponse)
+    if (Port == PS2_CONTROL_PORT)
     {
-        KeyboardWriteResponse = FALSE;
-
-        /* Check which command it was */
-        switch (KeyboardResponse)
+        switch (Data)
         {
+            /* 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:
             {
-                KeyboardConfig = Data;
+                /* These commands require a response */
+                KeyboardResponse = Data;
+                KeyboardWriteResponse = TRUE;
                 break;
             }
 
-            /* Write controller output */
-            case 0xD1:
+            /* Disable mouse */
+            case 0xA7:
             {
-                /* Check if bit 0 is unset */
-                if (!(Data & (1 << 0)))
-                {
-                    /* CPU disabled - end simulation */
-                    VdmRunning = FALSE;
-                }
+                // TODO: Mouse support
+                break;
+            }
 
-                /* Update the A20 line setting */
-                EmulatorSetA20(Data & (1 << 1));
+            /* Enable mouse */
+            case 0xA8:
+            {
+                // TODO: Mouse support
+                break;
+            }
 
+            /* Test mouse port */
+            case 0xA9:
+            {
+                KeyboardResponse = 0;
+                KeyboardReadResponse = TRUE;
                 break;
             }
-            
-            case 0xD2:
+
+            /* Test PS/2 controller */
+            case 0xAA:
             {
-                /* Push the data byte to the keyboard queue */
-                KeyboardQueuePush(Data);
+                KeyboardResponse = 0x55;
+                KeyboardReadResponse = TRUE;
                 break;
             }
 
-            case 0xD3:
+            /* Disable keyboard */
+            case 0xAD:
             {
-                // TODO: Mouse support
+                // TODO: Not implemented
                 break;
             }
 
-            case 0xD4:
+            /* Enable keyboard */
+            case 0xAE:
             {
-                // TODO: Mouse support
+                // TODO: Not implemented
+                break;
+            }
+
+            /* Read controller output port */
+            case 0xD0:
+            {
+                // TODO: Not implemented
                 break;
             }
-        }
 
-        return;
+            /* 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;
 
-    // TODO: Implement PS/2 device commands
-}
+            /* Check which command it was */
+            switch (KeyboardResponse)
+            {
+                /* Write configuration byte */
+                case 0x60:
+                {
+                    KeyboardConfig = Data;
+                    break;
+                }
 
-BYTE WINAPI PS2ReadPort(ULONG Port)
-{
-    if (Port == PS2_CONTROL_PORT)
-        return KeyboardReadStatus();
-    else if (Port == PS2_DATA_PORT)
-        return KeyboardReadData();
-    else
-        return 0;
+                /* 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
+    }
 }
 
-VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
+VOID GenerateKeyboardInterrupts(VOID)
 {
-    if (Port == PS2_CONTROL_PORT)
-        KeyboardWriteCommand(Data);
-    else if (Port == PS2_DATA_PORT)
-        KeyboardWriteData(Data);
+    if (KeyboardQueuePop(&KeyboardData))
+    {
+        /* IRQ 1 */
+        PicInterruptRequest(1);
+    }
 }
 
 DWORD WINAPI InputThreadProc(LPVOID Parameter)
@@ -335,8 +307,6 @@ DWORD WINAPI InputThreadProc(LPVOID Parameter)
                     KeyboardQueuePush(ScanCode);
                 }
 
-                /* Keyboard IRQ */
-                PicInterruptRequest(1);
                 break;
             }
 
index e152e2b..5d887d5 100644 (file)
 
 /* 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_