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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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/hard…
==============================================================================
--- 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 ******************************************************************/