[NTVDM]
[reactos.git] / reactos / subsystems / mvdm / ntvdm / hardware / ps2.c
index b7e6c13..829b6b7 100644 (file)
 
 #define NDEBUG
 
+#include "ntvdm.h"
 #include "emulator.h"
-#include "io.h"
 #include "ps2.h"
+
+#include "io.h"
 #include "pic.h"
+#include "clock.h"
 
 /* PRIVATE VARIABLES **********************************************************/
 
@@ -41,7 +44,7 @@ typedef struct _PS2_PORT
 #define PS2_PORTS  2
 static PS2_PORT Ports[PS2_PORTS];
 
-#define PS2_DEFAULT_CONFIG  0x47
+#define PS2_DEFAULT_CONFIG  0x45
 static BYTE ControllerConfig = PS2_DEFAULT_CONFIG;
 static BYTE ControllerCommand = 0x00;
 
@@ -49,6 +52,8 @@ static BYTE StatusRegister = 0x00;
 // static BYTE InputBuffer  = 0x00; // PS/2 Input  Buffer
 static BYTE OutputBuffer = 0x00; // PS/2 Output Buffer
 
+static PHARDWARE_TIMER IrqTimer = NULL;
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 static VOID PS2SendCommand(PPS2_PORT Port, BYTE Command)
@@ -176,7 +181,11 @@ static VOID WINAPI PS2WritePort(USHORT Port, BYTE Data)
             /* Read controller output port */
             case 0xD0:
             {
-                // TODO: Not implemented
+                /* Bit 0 always set, and bit 1 is the A20 gate state */
+                OutputBuffer = (!!EmulatorGetA20() << 1) | 0x01;
+                // FIXME: Set the status of IRQ1 and IRQ12
+
+                StatusRegister |= (1 << 0); // There is something to read
                 break;
             }
 
@@ -226,6 +235,8 @@ static VOID WINAPI PS2WritePort(USHORT Port, BYTE Data)
                     /* Update the A20 line setting */
                     EmulatorSetA20(Data & (1 << 1));
 
+                    // FIXME: Add the status of IRQ1 and IRQ12
+
                     break;
                 }
 
@@ -262,7 +273,30 @@ static VOID WINAPI PS2WritePort(USHORT Port, BYTE Data)
     }
 }
 
-static BOOLEAN PS2PortQueueRead(BYTE PS2Port)
+static VOID FASTCALL GeneratePS2Irq(ULONGLONG ElapsedTime)
+{
+    UNREFERENCED_PARAMETER(ElapsedTime);
+
+    /* Generate an IRQ 1 if there is data ready in the output queue */
+    if (PS2PortQueueRead(0))
+    {
+        /* Generate an interrupt if interrupts for the first PS/2 port are enabled */
+        if (ControllerConfig & 0x01) PicInterruptRequest(1);
+        return;
+    }
+
+    /* Generate an IRQ 12 if there is data ready in the output queue */
+    if (PS2PortQueueRead(1))
+    {
+        /* Generate an interrupt if interrupts for the second PS/2 port are enabled */
+        if (ControllerConfig & 0x02) PicInterruptRequest(12);
+        return;
+    }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BOOLEAN PS2PortQueueRead(BYTE PS2Port)
 {
     BOOLEAN Result = TRUE;
     PPS2_PORT Port;
@@ -316,8 +350,6 @@ Done:
     return Result;
 }
 
-/* PUBLIC FUNCTIONS ***********************************************************/
-
 VOID PS2SetDeviceCmdProc(BYTE PS2Port, LPVOID Param, PS2_DEVICE_CMDPROC DeviceCommand)
 {
     if (PS2Port >= PS2_PORTS) return;
@@ -354,43 +386,14 @@ BOOLEAN PS2QueuePush(BYTE PS2Port, BYTE Data)
     /* The queue is not empty anymore */
     Port->QueueEmpty = FALSE;
 
-/*
-    // Get the data
-    OutputBuffer = Port->Queue[Port->QueueStart];
-    StatusRegister |= (1 << 0); // There is something to read
-    // FIXME: Sometimes StatusRegister |= (1 << 5); for the second PS/2 port
-
-    if (PS2Port == 0)
-        PicInterruptRequest(1);
-    else if (PS2Port == 1)
-        PicInterruptRequest(12);
-*/
+    /* Schedule the IRQ */
+    EnableHardwareTimer(IrqTimer);
 
 Done:
     ReleaseMutex(Port->QueueMutex);
     return Result;
 }
 
-VOID GenerateIrq1(VOID)
-{
-    /* Generate an interrupt if interrupts for the first PS/2 port are enabled */
-    if (ControllerConfig & 0x01)
-    {
-        /* Generate an IRQ 1 if there is data ready in the output queue */
-        if (PS2PortQueueRead(0)) PicInterruptRequest(1);
-    }
-}
-
-VOID GenerateIrq12(VOID)
-{
-    /* Generate an interrupt if interrupts for the second PS/2 port are enabled */
-    if (ControllerConfig & 0x02)
-    {
-        /* Generate an IRQ 12 if there is data ready in the output queue */
-        if (PS2PortQueueRead(1)) PicInterruptRequest(12);
-    }
-}
-
 BOOLEAN PS2Initialize(VOID)
 {
     /* Initialize the PS/2 ports */
@@ -410,11 +413,17 @@ BOOLEAN PS2Initialize(VOID)
     RegisterIoPort(PS2_CONTROL_PORT, PS2ReadPort, PS2WritePort);
     RegisterIoPort(PS2_DATA_PORT   , PS2ReadPort, PS2WritePort);
 
+    IrqTimer = CreateHardwareTimer(HARDWARE_TIMER_ONESHOT,
+                                   HZ_TO_NS(100),
+                                   GeneratePS2Irq);
+
     return TRUE;
 }
 
 VOID PS2Cleanup(VOID)
 {
+    DestroyHardwareTimer(IrqTimer);
+
     CloseHandle(Ports[1].QueueMutex);
     CloseHandle(Ports[0].QueueMutex);
 }