Author: hbelusca Date: Thu Aug 13 17:11:17 2015 New Revision: 68708
URL: http://svn.reactos.org/svn/reactos?rev=68708&view=rev Log: [NTVDM] - When we have few R/W IO port handlers, just register them directly instead of using a wrap-up function. - Start implementing the PS/2 keyboard command handler. - Report scancodes only if the keyboard is enabled. See r68415. CORE-9920
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/dma.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c [iso-8859-1] Thu Aug 13 17:11:17 2015 @@ -46,6 +46,7 @@ if (RateSelect <= 2) RateSelect += 7;
SetHardwareTimerDelay(PeriodicTimer, HZ_TO_NS(1 << (16 - RateSelect))); + // FIXME: This call keeps EnableCount increasing without compensating it! EnableHardwareTimer(PeriodicTimer); }
@@ -101,18 +102,20 @@ } }
-static VOID CmosWriteAddress(BYTE Value) -{ +static VOID WINAPI CmosWriteAddress(USHORT Port, BYTE Data) +{ + UNREFERENCED_PARAMETER(Port); + /* Update the NMI enabled flag */ - NmiEnabled = !(Value & CMOS_DISABLE_NMI); + NmiEnabled = !(Data & CMOS_DISABLE_NMI);
/* Get the register number */ - Value &= ~CMOS_DISABLE_NMI; - - if (Value < CMOS_REG_MAX) + Data &= ~CMOS_DISABLE_NMI; + + if (Data < CMOS_REG_MAX) { /* Select the new register */ - SelectedRegister = Value; + SelectedRegister = Data; } else { @@ -121,10 +124,12 @@ } }
-static BYTE CmosReadData(VOID) +static BYTE WINAPI CmosReadData(USHORT Port) { BYTE Value; SYSTEMTIME CurrentTime; + + UNREFERENCED_PARAMETER(Port);
/* Get the current time */ GetLocalTime(&CurrentTime); @@ -257,11 +262,13 @@ return Value; }
-static VOID CmosWriteData(BYTE Value) +static VOID WINAPI CmosWriteData(USHORT Port, BYTE Data) { BOOLEAN ChangeTime = FALSE; SYSTEMTIME CurrentTime;
+ UNREFERENCED_PARAMETER(Port); + /* Get the current time */ GetLocalTime(&CurrentTime);
@@ -270,26 +277,26 @@ case CMOS_REG_SECONDS: { ChangeTime = TRUE; - CurrentTime.wSecond = WRITE_CMOS_DATA(CmosMemory, Value); + CurrentTime.wSecond = WRITE_CMOS_DATA(CmosMemory, Data); break; }
case CMOS_REG_ALARM_SEC: { - CmosMemory.AlarmSecond = WRITE_CMOS_DATA(CmosMemory, Value); + CmosMemory.AlarmSecond = WRITE_CMOS_DATA(CmosMemory, Data); break; }
case CMOS_REG_MINUTES: { ChangeTime = TRUE; - CurrentTime.wMinute = WRITE_CMOS_DATA(CmosMemory, Value); + CurrentTime.wMinute = WRITE_CMOS_DATA(CmosMemory, Data); break; }
case CMOS_REG_ALARM_MIN: { - CmosMemory.AlarmMinute = WRITE_CMOS_DATA(CmosMemory, Value); + CmosMemory.AlarmMinute = WRITE_CMOS_DATA(CmosMemory, Data); break; }
@@ -299,13 +306,13 @@
ChangeTime = TRUE;
- if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80)) + if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Data & 0x80)) { - Value &= ~0x80; + Data &= ~0x80; Afternoon = TRUE; }
- CurrentTime.wHour = WRITE_CMOS_DATA(CmosMemory, Value); + CurrentTime.wHour = WRITE_CMOS_DATA(CmosMemory, Data);
/* Convert to 24-hour format */ if (Afternoon) CurrentTime.wHour += 12; @@ -317,13 +324,13 @@ { BOOLEAN Afternoon = FALSE;
- if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Value & 0x80)) + if (!(CmosMemory.StatusRegB & CMOS_STB_24HOUR) && (Data & 0x80)) { - Value &= ~0x80; + Data &= ~0x80; Afternoon = TRUE; }
- CmosMemory.AlarmHour = WRITE_CMOS_DATA(CmosMemory, Value); + CmosMemory.AlarmHour = WRITE_CMOS_DATA(CmosMemory, Data);
/* Convert to 24-hour format */ if (Afternoon) CmosMemory.AlarmHour += 12; @@ -339,22 +346,22 @@ * SetLocalTime API value is 0-based. * Correct it. */ - Value -= 1; - CurrentTime.wDayOfWeek = WRITE_CMOS_DATA(CmosMemory, Value); + Data -= 1; + CurrentTime.wDayOfWeek = WRITE_CMOS_DATA(CmosMemory, Data); break; }
case CMOS_REG_DAY: { ChangeTime = TRUE; - CurrentTime.wDay = WRITE_CMOS_DATA(CmosMemory, Value); + CurrentTime.wDay = WRITE_CMOS_DATA(CmosMemory, Data); break; }
case CMOS_REG_MONTH: { ChangeTime = TRUE; - CurrentTime.wMonth = WRITE_CMOS_DATA(CmosMemory, Value); + CurrentTime.wMonth = WRITE_CMOS_DATA(CmosMemory, Data); break; }
@@ -365,7 +372,7 @@ /* Clear everything except the century */ CurrentTime.wYear = (CurrentTime.wYear / 100) * 100;
- CurrentTime.wYear += WRITE_CMOS_DATA(CmosMemory, Value); + CurrentTime.wYear += WRITE_CMOS_DATA(CmosMemory, Data); break; }
@@ -377,14 +384,14 @@
case CMOS_REG_STATUS_A: { - CmosMemory.StatusRegA = Value & 0x7F; // Bit 7 is read-only + CmosMemory.StatusRegA = Data & 0x7F; // Bit 7 is read-only RtcUpdatePeriodicTimer(); break; }
case CMOS_REG_STATUS_B: { - CmosMemory.StatusRegB = Value; + CmosMemory.StatusRegB = Data; break; }
@@ -399,7 +406,7 @@ { /* Sync EMS and UMS */ CmosMemory.Regs[CMOS_REG_EXT_MEMORY_LOW] = - CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW] = Value; + CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_LOW] = Data; break; }
@@ -409,13 +416,13 @@ { /* Sync EMS and UMS */ CmosMemory.Regs[CMOS_REG_EXT_MEMORY_HIGH] = - CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = Value; + CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = Data; break; }
default: { - CmosMemory.Regs[SelectedRegister] = Value; + CmosMemory.Regs[SelectedRegister] = Data; } }
@@ -423,20 +430,6 @@
/* Return to Status Register D */ SelectedRegister = CMOS_REG_STATUS_D; -} - -static BYTE WINAPI CmosReadPort(USHORT Port) -{ - ASSERT(Port == CMOS_DATA_PORT); - return CmosReadData(); -} - -static VOID WINAPI CmosWritePort(USHORT Port, BYTE Data) -{ - if (Port == CMOS_ADDRESS_PORT) - CmosWriteAddress(Data); - else if (Port == CMOS_DATA_PORT) - CmosWriteData(Data); }
@@ -511,8 +504,8 @@ CmosMemory.Regs[CMOS_REG_ACTUAL_EXT_MEMORY_HIGH] = HIBYTE((MAX_ADDRESS - 0x100000) / 1024);
/* Register the I/O Ports */ - RegisterIoPort(CMOS_ADDRESS_PORT, NULL , CmosWritePort); - RegisterIoPort(CMOS_DATA_PORT , CmosReadPort, CmosWritePort); + RegisterIoPort(CMOS_ADDRESS_PORT, NULL, CmosWriteAddress); + RegisterIoPort(CMOS_DATA_PORT , CmosReadData, CmosWriteData );
ClockTimer = CreateHardwareTimer(HARDWARE_TIMER_ENABLED, HZ_TO_NS(1),
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/dma.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/dma.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/dma.c [iso-8859-1] Thu Aug 13 17:11:17 2015 @@ -559,12 +559,12 @@ RegisterIoPort(0x07, DmaReadPort, DmaWritePort); /* Current(R) / Base (W) Count Register 3 */
RegisterIoPort(0x08, DmaReadPort, DmaWritePort); /* Status (Read) / Command (Write) Registers */ - RegisterIoPort(0x09, NULL, DmaWritePort); /* Request Register */ - RegisterIoPort(0x0A, NULL, DmaWritePort); /* Single Channel Mask Register */ - RegisterIoPort(0x0B, NULL, DmaWritePort); /* Mode Register */ - RegisterIoPort(0x0C, NULL, DmaWritePort); /* Flip-Flop Reset Register */ + RegisterIoPort(0x09, NULL, DmaWritePort); /* Request Register */ + RegisterIoPort(0x0A, NULL, DmaWritePort); /* Single Channel Mask Register */ + RegisterIoPort(0x0B, NULL, DmaWritePort); /* Mode Register */ + RegisterIoPort(0x0C, NULL, DmaWritePort); /* Flip-Flop Reset Register */ RegisterIoPort(0x0D, DmaReadPort, DmaWritePort); /* Intermediate (Read) / Master Reset (Write) Registers */ - RegisterIoPort(0x0E, NULL, DmaWritePort); /* Mask Reset Register */ + RegisterIoPort(0x0E, NULL, DmaWritePort); /* Mask Reset Register */ RegisterIoPort(0x0F, DmaReadPort, DmaWritePort); /* Multi-Channel Mask Register */
@@ -579,12 +579,12 @@ RegisterIoPort(0xCE, DmaReadPort, DmaWritePort); /* Current(R) / Base (W) Count Register 7 */
RegisterIoPort(0xD0, DmaReadPort, DmaWritePort); /* Status (Read) / Command (Write) Registers */ - RegisterIoPort(0xD2, NULL, DmaWritePort); /* Request Register */ - RegisterIoPort(0xD4, NULL, DmaWritePort); /* Single Channel Mask Register */ - RegisterIoPort(0xD6, NULL, DmaWritePort); /* Mode Register */ - RegisterIoPort(0xD8, NULL, DmaWritePort); /* Flip-Flop Reset Register */ + RegisterIoPort(0xD2, NULL, DmaWritePort); /* Request Register */ + RegisterIoPort(0xD4, NULL, DmaWritePort); /* Single Channel Mask Register */ + RegisterIoPort(0xD6, NULL, DmaWritePort); /* Mode Register */ + RegisterIoPort(0xD8, NULL, DmaWritePort); /* Flip-Flop Reset Register */ RegisterIoPort(0xDA, DmaReadPort, DmaWritePort); /* Intermediate (Read) / Master Reset (Write) Registers */ - RegisterIoPort(0xDC, NULL, DmaWritePort); /* Mask Reset Register */ + RegisterIoPort(0xDC, NULL, DmaWritePort); /* Mask Reset Register */ RegisterIoPort(0xDE, DmaReadPort, DmaWritePort); /* Multi-Channel Mask Register */
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c [iso-8859-1] Thu Aug 13 17:11:17 2015 @@ -16,19 +16,148 @@
/* PRIVATE VARIABLES **********************************************************/
+static BOOLEAN Reporting = FALSE; +static BYTE KeyboardId = 0; // We only support basic old-type keyboard +static BYTE DataByteWait = 0; + static BYTE PS2Port = 0;
/* PRIVATE FUNCTIONS **********************************************************/
static VOID WINAPI KeyboardCommand(LPVOID Param, BYTE Command) { - // FIXME: UNIMPLEMENTED; just return ACKnowledge. - // This unblocks some programs that want to initialize - // the keyboard by sending keyboard commands and then - // performing polling on the port until "valid" data - // comes out. - DPRINT1("KeyboardCommand(0x%02X) NOT IMPLEMENTED\n", Command); - PS2QueuePush(PS2Port, 0xFA); + /* Check if we were waiting for a data byte */ + if (DataByteWait) + { + PS2QueuePush(PS2Port, KEYBOARD_ACK); + + switch (DataByteWait) + { + /* Set/Reset Mode Indicators */ + case 0xED: + { + // Ignore setting the keyboard LEDs + break; + } + + /* PS/2 Select/Read Alternate Scan Code Sets */ + case 0xF0: + /* Set Typematic Rate/Delay */ + case 0xF3: + { + // FIXME: UNIMPLEMENTED; just return ACKnowledge. + // This unblocks some programs that want to initialize + // the keyboard by sending keyboard commands and then + // performing polling on the port until "valid" data + // comes out. + DPRINT1("KeyboardCommand(0x%02X) NOT IMPLEMENTED\n", DataByteWait); + break; + } + + default: + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + } + + DataByteWait = 0; + return; + } + + switch (Command) + { + /* Set/Reset Mode Indicators */ + case 0xED: + /* PS/2 Select/Read Alternate Scan Code Sets */ + case 0xF0: + /* Set Typematic Rate/Delay */ + case 0xF3: + { + DataByteWait = Command; + PS2QueuePush(PS2Port, KEYBOARD_ACK); + break; + } + + /* Echo test command */ + case 0xEE: + { + PS2QueuePush(PS2Port, 0xEE); + break; + } + + /* Get Keyboard ID */ + case 0xF2: + { + PS2QueuePush(PS2Port, KEYBOARD_ACK); + PS2QueuePush(PS2Port, KeyboardId); + break; + } + + /* Enable Reporting */ + case 0xF4: + { + Reporting = TRUE; + PS2QueuePush(PS2Port, KEYBOARD_ACK); + break; + } + + /* Disable Reporting */ + case 0xF5: + { + Reporting = FALSE; + PS2QueuePush(PS2Port, KEYBOARD_ACK); + break; + } + + /* Set Defaults */ + case 0xF6: + { + // So far, nothing to reset + PS2QueuePush(PS2Port, KEYBOARD_ACK); + break; + } + + /* PS/2 Typematic & Make/Break key modes */ + case 0xF7: case 0xF8: case 0xF9: + case 0xFA: case 0xFB: case 0xFC: case 0xFD: + { + /* + * Unsupported on PC-AT, they are just ignored + * and acknowledged as discussed in: + * http://stanislavs.org/helppc/keyboard_commands.html + */ + PS2QueuePush(PS2Port, KEYBOARD_ACK); + } + + /* Resend */ + case 0xFE: + { + PS2QueuePush(PS2Port, KEYBOARD_ACK); + UNIMPLEMENTED; + break; + } + + /* Reset */ + case 0xFF: + { + /* Send ACKnowledge */ + PS2QueuePush(PS2Port, KEYBOARD_ACK); + + // So far, nothing to reset + + /* Send the Basic Assurance Test success code and the device ID */ + PS2QueuePush(PS2Port, KEYBOARD_BAT_SUCCESS); + PS2QueuePush(PS2Port, KeyboardId); + break; + } + + /* Unknown command */ + default: + { + PS2QueuePush(PS2Port, KEYBOARD_ERROR); + } + } }
/* PUBLIC FUNCTIONS ***********************************************************/ @@ -37,6 +166,9 @@ { WORD i; BYTE ScanCode = (BYTE)KeyEvent->wVirtualScanCode; + + /* Check if we're not reporting */ + if (!Reporting) return;
/* If this is a key release, set the highest bit in the scan code */ if (!KeyEvent->bKeyDown) ScanCode |= 0x80; @@ -56,6 +188,5 @@ /* Finish to plug the keyboard to the specified PS/2 port */ PS2Port = PS2Connector; PS2SetDeviceCmdProc(PS2Port, NULL, KeyboardCommand); - return TRUE; }
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hardw... ============================================================================== --- trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h [iso-8859-1] Thu Aug 13 17:11:17 2015 @@ -12,8 +12,10 @@ /* DEFINES ********************************************************************/
/* Command responses */ -#define KEYBOARD_ACK 0xFA -#define KEYBOARD_RESEND 0xFE +#define KEYBOARD_BAT_SUCCESS 0xAA +#define KEYBOARD_ACK 0xFA +#define KEYBOARD_ERROR 0xFC +#define KEYBOARD_RESEND 0xFE
/* FUNCTIONS ******************************************************************/