Author: aandrejevic
Date: Sun Oct 27 00:37:01 2013
New Revision: 60761
URL: 
http://svn.reactos.org/svn/reactos?rev=60761&view=rev
Log:
[FAST486]
Separate external interrupts from interrupt signals (which are
interrupts whose number is not known until they can be serviced,
just like hardware interrupts on a real CPU).
[NTVDM]
Improve the PIC emulation code (IRQ priorities, etc...).
Instead of checking for interrupts in the main loop, move the
PS/2 input parsing to a different thread.
Improve BIOS keyboard IRQ handling.
Modified:
    branches/ntvdm/include/reactos/libs/fast486/fast486.h
    branches/ntvdm/lib/fast486/fast486.c
    branches/ntvdm/lib/fast486/opcodes.c
    branches/ntvdm/subsystems/ntvdm/bios.c
    branches/ntvdm/subsystems/ntvdm/emulator.c
    branches/ntvdm/subsystems/ntvdm/emulator.h
    branches/ntvdm/subsystems/ntvdm/ntvdm.c
    branches/ntvdm/subsystems/ntvdm/pic.c
    branches/ntvdm/subsystems/ntvdm/pic.h
    branches/ntvdm/subsystems/ntvdm/ps2.c
    branches/ntvdm/subsystems/ntvdm/ps2.h
Modified: branches/ntvdm/include/reactos/libs/fast486/fast486.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/include/reactos/libs/fast…
==============================================================================
--- branches/ntvdm/include/reactos/libs/fast486/fast486.h       [iso-8859-1] (original)
+++ branches/ntvdm/include/reactos/libs/fast486/fast486.h       [iso-8859-1] Sun Oct 27
00:37:01 2013
@@ -145,6 +145,13 @@
     FAST486_EXCEPTION_MC = 0x12
 } FAST486_EXCEPTIONS, *PFAST486_EXCEPTIONS;
+typedef enum _FAST486_INT_STATUS
+{
+    FAST486_INT_NONE = 0,
+    FAST486_INT_EXECUTE = 1,
+    FAST486_INT_SIGNAL = 2
+} FAST486_INT_STATUS, *PFAST486_INT_STATUS;
+
 typedef
 BOOLEAN
 (NTAPI *FAST486_MEM_READ_PROC)
@@ -198,6 +205,13 @@
 (
     PFAST486_STATE State,
     USHORT BopCode
+);
+
+typedef
+UCHAR
+(NTAPI *FAST486_INT_ACK_PROC)
+(
+    PFAST486_STATE State
 );
 typedef union _FAST486_REG
@@ -352,6 +366,7 @@
     FAST486_IO_WRITE_PROC IoWriteCallback;
     FAST486_IDLE_PROC IdleCallback;
     FAST486_BOP_PROC BopCallback;
+    FAST486_INT_ACK_PROC IntAckCallback;
     FAST486_REG GeneralRegs[FAST486_NUM_GEN_REGS];
     FAST486_SEG_REG SegmentRegs[FAST486_NUM_SEG_REGS];
     FAST486_REG InstPtr, SavedInstPtr;
@@ -362,7 +377,7 @@
     ULONG ExceptionCount;
     ULONG PrefixFlags;
     FAST486_SEG_REGS SegmentOverride;
-    BOOLEAN HardwareInt;
+    FAST486_INT_STATUS IntStatus;
     UCHAR PendingIntNum;
 };
@@ -398,6 +413,10 @@
 VOID
 NTAPI
+Fast486InterruptSignal(PFAST486_STATE State);
+
+VOID
+NTAPI
 Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset);
 VOID
Modified: branches/ntvdm/lib/fast486/fast486.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/fast486.c?rev…
==============================================================================
--- branches/ntvdm/lib/fast486/fast486.c        [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/fast486.c        [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -61,10 +61,22 @@
         {
             State->SavedInstPtr = State->InstPtr;
-            /* Check if interrupts are enabled and there is an interrupt pending */
-            if (State->Flags.If && State->HardwareInt)
+            /*
+             * Check if there is an interrupt to execute, or a hardware interrupt signal
+             * while interrupts are enabled.
+             */
+            if ((State->IntStatus == FAST486_INT_EXECUTE)
+                || (State->Flags.If
+                && (State->IntAckCallback != NULL)
+                && (State->IntStatus == FAST486_INT_SIGNAL)))
             {
                 FAST486_IDT_ENTRY IdtEntry;
+
+                if (State->IntStatus == FAST486_INT_SIGNAL)
+                {
+                    /* Acknowledge the interrupt to get the number */
+                    State->PendingIntNum = State->IntAckCallback(State);
+                }
                 /* Get the interrupt vector */
                 if (Fast486GetIntVector(State, State->PendingIntNum, &IdtEntry))
@@ -76,8 +88,8 @@
                                              IdtEntry.Type);
                 }
-                /* Clear the interrupt pending flag */
-                State->HardwareInt = FALSE;
+                /* Clear the interrupt status */
+                State->IntStatus = FAST486_INT_NONE;
             }
         }
@@ -243,6 +255,7 @@
     FAST486_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback;
     FAST486_IDLE_PROC IdleCallback = State->IdleCallback;
     FAST486_BOP_PROC BopCallback = State->BopCallback;
+    FAST486_INT_ACK_PROC IntAckCallback = State->IntAckCallback;
     /* Clear the entire structure */
     RtlZeroMemory(State, sizeof(*State));
@@ -278,15 +291,24 @@
     State->IoWriteCallback = IoWriteCallback;
     State->IdleCallback = IdleCallback;
     State->BopCallback = BopCallback;
+    State->IntAckCallback = IntAckCallback;
 }
 VOID
 NTAPI
 Fast486Interrupt(PFAST486_STATE State, UCHAR Number)
 {
-    /* Set the hardware interrupt flag */
-    State->HardwareInt = TRUE;
+    /* Set the interrupt status and the number */
+    State->IntStatus = FAST486_INT_EXECUTE;
     State->PendingIntNum = Number;
+}
+
+VOID
+NTAPI
+Fast486InterruptSignal(PFAST486_STATE State)
+{
+    /* Set the interrupt status */
+    State->IntStatus = FAST486_INT_SIGNAL;
 }
 VOID
Modified: branches/ntvdm/lib/fast486/opcodes.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/fast486/opcodes.c?rev…
==============================================================================
--- branches/ntvdm/lib/fast486/opcodes.c        [iso-8859-1] (original)
+++ branches/ntvdm/lib/fast486/opcodes.c        [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -876,7 +876,7 @@
     }
     /* Halt */
-    while (!State->HardwareInt) State->IdleCallback(State);
+    while (State->IntStatus != FAST486_INT_SIGNAL) State->IdleCallback(State);
     /* Return success */
     return TRUE;
Modified: branches/ntvdm/subsystems/ntvdm/bios.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.c?r…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/bios.c      [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/bios.c      [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -1092,39 +1092,40 @@
             BYTE ScanCode, VirtualKey;
             WORD Character;
-            /* Check if there is a scancode available */
-            if (!(KeyboardReadStatus() & 1)) break;
-
-            /* 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)))
+            /* Loop while there is a scancode available */
+            while (KeyboardReadStatus() & 1)
             {
-                /* Key press */
-                if (VirtualKey == VK_NUMLOCK
-                    || VirtualKey == VK_CAPITAL
-                    || VirtualKey == VK_SCROLL)
+                /* 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)))
                 {
-                    /* For toggle keys, toggle the lowest bit in the keyboard map */
-                    BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
+                    /* Key press */
+                    if (VirtualKey == VK_NUMLOCK
+                        || VirtualKey == VK_CAPITAL
+                        || VirtualKey == VK_SCROLL)
+                    {
+                        /* 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 */
+                    if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0)
> 0)
+                    {
+                        /* Push it onto the BIOS keyboard queue */
+                        BiosKbdBufferPush((ScanCode << 8) | (Character &
0xFF));
+                    }
                 }
-
-                /* Set the highest bit */
-                BiosKeyboardMap[VirtualKey] |= (1 << 7);
-
-                /* Find out which character this is */
-                if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0)
> 0)
+                else
                 {
-                    /* Push it onto the BIOS keyboard queue */
-                    BiosKbdBufferPush((ScanCode << 8) | (Character & 0xFF));
+                    /* Key release, unset the highest bit */
+                    BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
                 }
-            }
-            else
-            {
-                /* Key release, unset the highest bit */
-                BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
             }
             break;
Modified: branches/ntvdm/subsystems/ntvdm/emulator.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.c  [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/emulator.c  [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -329,6 +329,14 @@
     }
 }
+static BYTE WINAPI EmulatorIntAcknowledge(PFAST486_STATE State)
+{
+    UNREFERENCED_PARAMETER(State);
+
+    /* Get the interrupt number from the PIC */
+    return PicGetInterrupt();
+}
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 BOOLEAN EmulatorInitialize()
@@ -342,7 +350,8 @@
     EmulatorContext.MemWriteCallback = (FAST486_MEM_WRITE_PROC)EmulatorWriteMemory;
     EmulatorContext.IoReadCallback = (FAST486_IO_READ_PROC)EmulatorReadIo;
     EmulatorContext.IoWriteCallback = (FAST486_IO_WRITE_PROC)EmulatorWriteIo;
-    EmulatorContext.BopCallback = (FAST486_BOP_PROC)EmulatorBiosOperation;
+    EmulatorContext.BopCallback = EmulatorBiosOperation;
+    EmulatorContext.IntAckCallback = EmulatorIntAcknowledge;
     /* Reset the CPU */
     Fast486Reset(&EmulatorContext);
@@ -371,10 +380,10 @@
     Fast486Interrupt(&EmulatorContext, Number);
 }
-VOID EmulatorExternalInterrupt(BYTE Number)
+VOID EmulatorInterruptSignal(VOID)
 {
     /* Call the Fast486 API */
-    Fast486Interrupt(&EmulatorContext, Number);
+    Fast486InterruptSignal(&EmulatorContext);
 }
 ULONG EmulatorGetRegister(ULONG Register)
Modified: branches/ntvdm/subsystems/ntvdm/emulator.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/emulator.h  [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/emulator.h  [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -88,7 +88,7 @@
 VOID EmulatorSetStack(WORD Segment, DWORD Offset);
 VOID EmulatorExecute(WORD Segment, WORD Offset);
 VOID EmulatorInterrupt(BYTE Number);
-VOID EmulatorExternalInterrupt(BYTE Number);
+VOID EmulatorInterruptSignal(VOID);
 ULONG EmulatorGetRegister(ULONG Register);
 ULONG EmulatorGetProgramCounter(VOID);
 VOID EmulatorSetRegister(ULONG Register, ULONG Value);
Modified: branches/ntvdm/subsystems/ntvdm/ntvdm.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ntvdm.c?…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ntvdm.c     [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ntvdm.c     [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -79,12 +79,12 @@
     INT i;
     CHAR CommandLine[DOS_CMDLINE_LENGTH];
     DWORD CurrentTickCount;
-    DWORD LastTickCount = GetTickCount();
     DWORD Cycles = 0;
     DWORD LastCyclePrintout = GetTickCount();
     DWORD LastVerticalRefresh = GetTickCount();
     LARGE_INTEGER Frequency, LastTimerTick, Counter;
     LONGLONG TimerTicks;
+    HANDLE InputThread = NULL;
     /* Set the handler routine */
     SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
@@ -141,6 +141,9 @@
         DisplayMessage(L"Could not start program: %S", CommandLine);
         return -1;
     }
+
+    /* Start the input thread */
+    InputThread = CreateThread(NULL, 0, &InputThreadProc, NULL, 0, NULL);
     /* Set the last timer tick to the current time */
     QueryPerformanceCounter(&LastTimerTick);
@@ -162,13 +165,6 @@
         for (i = 0; i < TimerTicks; i++) PitDecrementCount();
         LastTimerTick = Counter;
-        /* Check for console input events every millisecond */
-        if (CurrentTickCount != LastTickCount)
-        {
-            CheckForInputEvents();
-            LastTickCount = CurrentTickCount;
-        }
-
         /* Check for vertical retrace */
         if ((CurrentTickCount - LastVerticalRefresh) >= 16)
         {
@@ -198,6 +194,7 @@
     VgaRefreshDisplay();
 Cleanup:
+    if (InputThread != NULL) CloseHandle(InputThread);
     BiosCleanup();
     EmulatorCleanup();
Modified: branches/ntvdm/subsystems/ntvdm/pic.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/pic.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/pic.c       [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/pic.c       [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -35,8 +35,8 @@
     }
     else
     {
-        /* The IRR is always 0, as the emulated CPU receives the interrupt instantly */
-        return 0;
+        /* Read the interrupt request register */
+        return Pic->IntRequestRegister;
     }
 }
@@ -167,9 +167,9 @@
         /* Check if the interrupt is masked */
         if (MasterPic.MaskRegister & (1 << Number)) return;
-        /* Set the appropriate bit in the ISR and interrupt the CPU */
-        if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << Number;
-        EmulatorExternalInterrupt(MasterPic.IntOffset + Number);
+        /* Set the appropriate bit in the IRR and interrupt the CPU */
+        MasterPic.IntRequestRegister |= 1 << Number;
+        EmulatorInterruptSignal();
     }
     else if (Number >= 8 && Number < 16)
     {
@@ -187,7 +187,7 @@
         /* Check if any of the higher-priorirty interrupts are busy */
         if (MasterPic.InServiceRegister != 0) return;
-        for (i = 0; i <= Number ; i++)
+        for (i = 0; i <= Number; i++)
         {
             if (SlavePic.InServiceRegister & (1 << Number)) return;
         }
@@ -196,12 +196,57 @@
         if (SlavePic.MaskRegister & (1 << Number)) return;
         /* Set the IRQ 2 bit in the master ISR */
-        if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << 2;
-
-        /* Set the appropriate bit in the ISR and interrupt the CPU */
-        if (!SlavePic.AutoEoi) SlavePic.InServiceRegister |= 1 << Number;
-        EmulatorExternalInterrupt(SlavePic.IntOffset + Number);
-    }
+        if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= (1 << 2);
+
+        /* Set the appropriate bit in the IRR and interrupt the CPU */
+        SlavePic.IntRequestRegister |= 1 << Number;
+        EmulatorInterruptSignal();
+    }
+}
+
+BYTE PicGetInterrupt(VOID)
+{
+    INT i, j;
+
+    /* Search interrupts by priority */
+    for (i = 0; i < 8; i++)
+    {
+        /* Check if this line is cascaded to the slave PIC */
+        if ((i == 2)
+            && MasterPic.CascadeRegister & (1 << 2)
+            && SlavePic.Slave
+            && (SlavePic.CascadeRegister == 2))
+        {
+            /* Search the slave PIC interrupts by priority */
+            for (j = 0; j < 8; j++) if ((j != 1) &&
SlavePic.IntRequestRegister & (1 << j))
+            {
+                /* Clear the IRR flag */
+                SlavePic.IntRequestRegister &= ~(1 << j);
+
+                /* Set the ISR flag, unless AEOI is enabled */
+                if (!SlavePic.AutoEoi) SlavePic.InServiceRegister |= (1 << j);
+
+                /* Return the interrupt number */
+                return SlavePic.IntOffset + j;
+            }
+        }
+
+        if (MasterPic.IntRequestRegister & (1 << i))
+        {
+            /* Clear the IRR flag */
+            MasterPic.IntRequestRegister &= ~(1 << i);
+
+            /* Set the ISR flag, unless AEOI is enabled */
+            if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= (1 << i);
+
+            /* Return the interrupt number */
+            return MasterPic.IntOffset + i;
+        }
+    }
+
+    /* Spurious interrupt */
+    if (MasterPic.InServiceRegister & (1 << 2)) return SlavePic.IntOffset + 7;
+    else return MasterPic.IntOffset + 7;
 }
 /* EOF */
Modified: branches/ntvdm/subsystems/ntvdm/pic.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/pic.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/pic.h       [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/pic.h       [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -34,6 +34,7 @@
 {
     BOOLEAN Initialization;
     BYTE MaskRegister;
+    BYTE IntRequestRegister;
     BYTE InServiceRegister;
     BYTE IntOffset;
     BYTE ConfigRegister;
@@ -51,6 +52,7 @@
 BYTE PicReadData(BYTE Port);
 VOID PicWriteData(BYTE Port, BYTE Value);
 VOID PicInterruptRequest(BYTE Number);
+BYTE PicGetInterrupt(VOID);
 #endif // _PIC_H_
Modified: branches/ntvdm/subsystems/ntvdm/ps2.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ps2.c?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ps2.c       [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ps2.c       [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -265,49 +265,64 @@
     // TODO: Implement PS/2 device commands
 }
-VOID CheckForInputEvents()
-{
-    PINPUT_RECORD Buffer;
+DWORD WINAPI InputThreadProc(LPVOID Parameter)
+{
+    INT i;
     HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
-    DWORD i, j, Count, TotalEvents;
-    BYTE ScanCode;
-    BOOLEAN Interrupt = FALSE;
-
-    /* Get the number of input events */
-    if (!GetNumberOfConsoleInputEvents(ConsoleInput, &Count)) return;
-    if (Count == 0) return;
-
-    /* Allocate the buffer */
-    Buffer = (PINPUT_RECORD)HeapAlloc(GetProcessHeap(), 0, Count * sizeof(INPUT_RECORD));
-    if (Buffer == NULL) return;
-
-    /* Peek the input events */
-    if (!ReadConsoleInput(ConsoleInput, Buffer, Count, &TotalEvents)) goto Cleanup;
-
-    for (i = 0; i < TotalEvents; i++)
-    {
-        /* Check if this is a key event */
-        if (Buffer[i].EventType != KEY_EVENT) continue;
-
-        /* Get the scan code */
-        ScanCode = (BYTE)Buffer[i].Event.KeyEvent.wVirtualScanCode;
-
-        /* If this is a key release, set the highest bit in the scan code */
-        if (!Buffer[i].Event.KeyEvent.bKeyDown) ScanCode |= 0x80;
-
-        /* Push the scan code onto the keyboard queue */
-        for (j = 0; j < Buffer[i].Event.KeyEvent.wRepeatCount; j++)
-        {
-            KeyboardQueuePush(ScanCode);
-        }
-
-        Interrupt = TRUE;
-    }
-
-    if (Interrupt) PicInterruptRequest(1);
-
-Cleanup:
-    HeapFree(GetProcessHeap(), 0, Buffer);
+    INPUT_RECORD InputRecord;
+    DWORD Count;
+
+    while (VdmRunning)
+    {
+        /* Wait for an input record */
+        if (!ReadConsoleInput(ConsoleInput, &InputRecord, 1, &Count))
+        {
+            DPRINT1("Error reading console input\n");
+            return GetLastError();
+
+        }
+
+        ASSERT(Count != 0);
+
+        /* Check the event type */
+        switch (InputRecord.EventType)
+        {
+            case KEY_EVENT:
+            {
+                BYTE ScanCode = (BYTE)InputRecord.Event.KeyEvent.wVirtualScanCode;
+
+                /* If this is a key release, set the highest bit in the scan code */
+                if (!InputRecord.Event.KeyEvent.bKeyDown) ScanCode |= 0x80;
+
+                /* Push the scan code onto the keyboard queue */
+                for (i = 0; i < InputRecord.Event.KeyEvent.wRepeatCount; i++)
+                {
+                    KeyboardQueuePush(ScanCode);
+                }
+
+                /* Keyboard IRQ */
+                PicInterruptRequest(1);
+
+                break;
+            }
+
+            case MOUSE_EVENT:
+            {
+                // TODO: NOT IMPLEMENTED
+                UNIMPLEMENTED;
+
+                break;
+            }
+
+            default:
+            {
+                /* Ignored */
+                break;
+            }
+        }
+    }
+
+    return 0;
 }
 /* EOF */
Modified: branches/ntvdm/subsystems/ntvdm/ps2.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/ps2.h?re…
==============================================================================
--- branches/ntvdm/subsystems/ntvdm/ps2.h       [iso-8859-1] (original)
+++ branches/ntvdm/subsystems/ntvdm/ps2.h       [iso-8859-1] Sun Oct 27 00:37:01 2013
@@ -28,7 +28,7 @@
 VOID KeyboardWriteCommand(BYTE Command);
 BYTE KeyboardReadData();
 VOID KeyboardWriteData(BYTE Data);
-VOID CheckForInputEvents();
+DWORD WINAPI InputThreadProc(LPVOID Parameter);
 #endif // _PS2_H_