diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c b/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c index 87ba6caa3f0..283e341acdc 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c +++ b/reactos/subsystems/mvdm/ntvdm/hardware/cmos.c @@ -46,6 +46,7 @@ static VOID RtcUpdatePeriodicTimer(VOID) 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 FASTCALL RtcTimeUpdate(ULONGLONG ElapsedTime) } } -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; + Data &= ~CMOS_DISABLE_NMI; - if (Value < CMOS_REG_MAX) + if (Data < CMOS_REG_MAX) { /* Select the new register */ - SelectedRegister = Value; + SelectedRegister = Data; } else { @@ -121,11 +124,13 @@ static VOID CmosWriteAddress(BYTE Value) } } -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 @@ static BYTE CmosReadData(VOID) 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 @@ static VOID CmosWriteData(BYTE Value) 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 @@ static VOID CmosWriteData(BYTE Value) 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 @@ static VOID CmosWriteData(BYTE Value) { 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 @@ static VOID CmosWriteData(BYTE Value) * 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 @@ static VOID CmosWriteData(BYTE Value) /* 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 @@ static VOID CmosWriteData(BYTE Value) 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 @@ static VOID CmosWriteData(BYTE Value) { /* 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 @@ static VOID CmosWriteData(BYTE Value) { /* 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; } } @@ -425,20 +432,6 @@ static VOID CmosWriteData(BYTE Value) 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); -} - /* PUBLIC FUNCTIONS ***********************************************************/ @@ -511,8 +504,8 @@ VOID CmosInitialize(VOID) 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), diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/dma.c b/reactos/subsystems/mvdm/ntvdm/hardware/dma.c index ae63da78f3f..c0c414771e1 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/dma.c +++ b/reactos/subsystems/mvdm/ntvdm/hardware/dma.c @@ -559,12 +559,12 @@ VOID DmaInitialize(VOID) 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 @@ VOID DmaInitialize(VOID) 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 */ diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c b/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c index ac17986894f..ed52f617d0b 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c +++ b/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.c @@ -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 ***********************************************************/ @@ -38,6 +167,9 @@ VOID KeyboardEventHandler(PKEY_EVENT_RECORD KeyEvent) 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 @@ BOOLEAN KeyboardInit(BYTE PS2Connector) /* Finish to plug the keyboard to the specified PS/2 port */ PS2Port = PS2Connector; PS2SetDeviceCmdProc(PS2Port, NULL, KeyboardCommand); - return TRUE; } diff --git a/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h b/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h index 0b7cd4a55b8..b784c7999f4 100644 --- a/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h +++ b/reactos/subsystems/mvdm/ntvdm/hardware/keyboard.h @@ -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 ******************************************************************/