[NTVDM]
[reactos.git] / subsystems / ntvdm / ps2.c
index 03ff018..5138d0b 100644 (file)
@@ -10,8 +10,9 @@
 
 #define NDEBUG
 
-#include "ps2.h"
 #include "emulator.h"
+#include "io.h"
+#include "ps2.h"
 #include "pic.h"
 
 /* PRIVATE VARIABLES **********************************************************/
@@ -23,15 +24,23 @@ static UINT KeyboardQueueEnd = 0;
 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;
+
+    WaitForSingleObject(QueueMutex, INFINITE);
+
     /* Check if the keyboard queue is full */
     if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd))
     {
-        return FALSE;
+        Result = FALSE;
+        goto Done;
     }
 
     /* Insert the value in the queue */
@@ -42,13 +51,23 @@ static BOOLEAN KeyboardQueuePush(BYTE ScanCode)
     /* Since we inserted a value, it's not empty anymore */
     KeyboardQueueEmpty = FALSE;
 
-    return TRUE;
+Done:
+    ReleaseMutex(QueueMutex);
+    return Result;
 }
 
 static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
 {
+    BOOLEAN Result = TRUE;
+
+    WaitForSingleObject(QueueMutex, INFINITE);
+
     /* Make sure the keyboard queue is not empty */
-    if (KeyboardQueueEmpty) return FALSE;
+    if (KeyboardQueueEmpty)
+    {
+        Result = FALSE;
+        goto Done;
+    }
 
     /* Get the scan code */
     *ScanCode = KeyboardQueue[KeyboardQueueStart];
@@ -63,7 +82,9 @@ static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
         KeyboardQueueEmpty = TRUE;
     }
 
-    return TRUE;
+Done:
+    ReleaseMutex(QueueMutex);
+    return Result;
 }
 
 /* PUBLIC FUNCTIONS ***********************************************************/
@@ -72,9 +93,13 @@ 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;
 
@@ -93,7 +118,6 @@ VOID KeyboardWriteCommand(BYTE Command)
         {
             KeyboardResponse = KeyboardConfig;
             KeyboardReadResponse = TRUE;
-
             break;
         }
 
@@ -111,7 +135,6 @@ VOID KeyboardWriteCommand(BYTE Command)
             /* These commands require a response */
             KeyboardResponse = Command;
             KeyboardWriteResponse = TRUE;
-
             break;
         }
 
@@ -119,7 +142,6 @@ VOID KeyboardWriteCommand(BYTE Command)
         case 0xA7:
         {
             // TODO: Mouse support
-
             break;
         }
 
@@ -127,7 +149,6 @@ VOID KeyboardWriteCommand(BYTE Command)
         case 0xA8:
         {
             // TODO: Mouse support
-
             break;
         }
 
@@ -136,7 +157,6 @@ VOID KeyboardWriteCommand(BYTE Command)
         {
             KeyboardResponse = 0;
             KeyboardReadResponse = TRUE;
-
             break;
         }
 
@@ -145,7 +165,6 @@ VOID KeyboardWriteCommand(BYTE Command)
         {
             KeyboardResponse = 0x55;
             KeyboardReadResponse = TRUE;
-
             break;
         }
 
@@ -182,7 +201,6 @@ VOID KeyboardWriteCommand(BYTE Command)
         {
             /* Stop the simulation */
             VdmRunning = FALSE;
-
             break;
         }
     }
@@ -242,7 +260,6 @@ VOID KeyboardWriteData(BYTE Data)
             {
                 /* Push the data byte to the keyboard queue */
                 KeyboardQueuePush(Data);
-
                 break;
             }
 
@@ -265,6 +282,24 @@ VOID KeyboardWriteData(BYTE Data)
     // 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);
+}
+
 DWORD WINAPI InputThreadProc(LPVOID Parameter)
 {
     INT i;
@@ -302,7 +337,6 @@ DWORD WINAPI InputThreadProc(LPVOID Parameter)
 
                 /* Keyboard IRQ */
                 PicInterruptRequest(1);
-
                 break;
             }
 
@@ -310,7 +344,6 @@ DWORD WINAPI InputThreadProc(LPVOID Parameter)
             {
                 // TODO: NOT IMPLEMENTED
                 UNIMPLEMENTED;
-
                 break;
             }
 
@@ -325,4 +358,30 @@ DWORD WINAPI InputThreadProc(LPVOID Parameter)
     return 0;
 }
 
+BOOLEAN PS2Initialize(HANDLE ConsoleInput)
+{
+    /* Create the mutex */
+    QueueMutex = CreateMutex(NULL, FALSE, NULL);
+
+    /* Start the input thread */
+    InputThread = CreateThread(NULL, 0, &InputThreadProc, ConsoleInput, 0, NULL);
+
+    // if (InputThread == NULL) return FALSE;
+
+    /* Register the I/O Ports */
+    RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort);
+    RegisterIoPort(PS2_DATA_PORT   , PS2ReadPort, PS2WritePort);
+
+    return TRUE;
+}
+
+VOID PS2Cleanup(VOID)
+{
+    /* Close the input thread handle */
+    if (InputThread != NULL) CloseHandle(InputThread);
+    InputThread = NULL;
+
+    CloseHandle(QueueMutex);
+}
+
 /* EOF */