[NTVDM]
[reactos.git] / reactos / subsystems / ntvdm / bios / bios32 / kbdbios32.c
index 716af1f..7ef9a8b 100644 (file)
@@ -35,18 +35,15 @@ static BOOLEAN BiosKbdBufferPush(WORD Data)
     if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart;
 
     /* If it's full, fail */
-    if (NextElement == Bda->KeybdBufferHead) return FALSE;
+    if (NextElement == Bda->KeybdBufferHead)
+    {
+        DPRINT1("BIOS keyboard buffer full.\n");
+        return FALSE;
+    }
 
     /* Put the value in the queue */
     *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data;
-    Bda->KeybdBufferTail += sizeof(WORD);
-
-    /* Check if we are at, or have passed, the end of the buffer */
-    if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd)
-    {
-        /* Return it to the beginning */
-        Bda->KeybdBufferTail = Bda->KeybdBufferStart;
-    }
+    Bda->KeybdBufferTail = NextElement;
 
     /* Return success */
     return TRUE;
@@ -197,11 +194,38 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
 // Keyboard IRQ 1
 static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
 {
+    BOOLEAN SkipScanCode;
     BYTE ScanCode, VirtualKey;
     WORD Character;
 
-    /* Get the scan code and virtual key code */
-    ScanCode = IOReadB(PS2_DATA_PORT);
+    /*
+     * Get the scan code from the PS/2 port, then call the
+     * INT 15h, AH=4Fh Keyboard Intercept function to try to
+     * translate the scan code. CF must be set before the call.
+     * In return, if CF is set we continue processing the scan code
+     * stored in AL, and if not, we skip it.
+     */
+    BYTE CF;
+    WORD AX;
+    CF = getCF();
+    AX = getAX();
+
+    setCF(1);
+    setAL(IOReadB(PS2_DATA_PORT));
+    setAH(0x4F);
+    Int32Call(&BiosContext, BIOS_MISC_INTERRUPT);
+
+    /* Retrieve the modified scan code in AL */
+    SkipScanCode = (getCF() == 0);
+    ScanCode = getAL();
+
+    setAX(AX);
+    setCF(CF);
+
+    /* Check whether CF is clear. If so, skip the scan code. */
+    if (SkipScanCode) goto Quit;
+
+    /* Get the corresponding virtual key code */
     VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
 
     /* Check if this is a key press or release */
@@ -258,6 +282,10 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
     if (BiosKeyboardMap[VK_CAPITAL]  & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK;
     if (BiosKeyboardMap[VK_INSERT]   & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT;
 
+    DPRINT("BiosKeyboardIrq - Character = 0x%X, ScanCode = 0x%X, KeybdShiftFlags = 0x%X\n",
+           Character, ScanCode, Bda->KeybdShiftFlags);
+
+Quit:
     PicIRQComplete(Stack);
 }
 
@@ -271,7 +299,10 @@ BOOLEAN KbdBios32Initialize(VOID)
     /* Initialize the BDA */
     Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
     Bda->KeybdBufferEnd   = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
-    Bda->KeybdBufferHead  = Bda->KeybdBufferTail = 0;
+    Bda->KeybdBufferHead  = Bda->KeybdBufferTail = Bda->KeybdBufferStart;
+
+    // FIXME: Fill the keyboard buffer with invalid values, for diagnostic purposes...
+    RtlFillMemory(((LPVOID)((ULONG_PTR)Bda + Bda->KeybdBufferStart)), BIOS_KBD_BUFFER_SIZE * sizeof(WORD), 'A');
 
     /* Register the BIOS 32-bit Interrupts */
 
@@ -280,7 +311,6 @@ BOOLEAN KbdBios32Initialize(VOID)
 
     /* Set up the HW vector interrupts */
     EnableHwIRQ(1, BiosKeyboardIrq);
-    // EnableHwIRQ(12, BiosMouseIrq);
 
     return TRUE;
 }