Improve the keyboard event handling.
Clean up the PS/2 code a bit.


svn path=/branches/ntvdm/; revision=61229
This commit is contained in:
Aleksandar Andrejevic 2013-12-06 04:35:58 +00:00
parent 6dde554aa8
commit 1b784a5b7b
5 changed files with 233 additions and 261 deletions

View file

@ -1429,11 +1429,8 @@ VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
BYTE ScanCode, VirtualKey;
WORD Character;
/* Loop while there is a scancode available */
do
{
/* Get the scan code and virtual key code */
ScanCode = KeyboardReadData();
ScanCode = PS2ReadPort(PS2_DATA_PORT);
VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
/* Check if this is a key press or release */
@ -1468,8 +1465,6 @@ VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
/* Key release, unset the highest bit */
BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
}
}
while (KeyboardReadStatus() & 1);
/* Clear the keyboard flags */
Bda->KeybdShiftFlags = 0;

View file

@ -78,6 +78,7 @@ INT wmain(INT argc, WCHAR *argv[])
DWORD LastVerticalRefresh;
DWORD LastCyclePrintout;
DWORD Cycles = 0;
INT KeyboardIntCounter = 0;
/* Set the handler routine */
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
@ -227,6 +228,13 @@ INT wmain(INT argc, WCHAR *argv[])
LastVerticalRefresh = CurrentTickCount;
}
KeyboardIntCounter++;
if (KeyboardIntCounter == KBD_INT_CYCLES)
{
GenerateKeyboardInterrupts();
KeyboardIntCounter = 0;
}
/* Horizontal retrace occurs as fast as possible */
VgaHorizontalRetrace();

View file

@ -45,6 +45,7 @@
/* Processor speed */
#define STEPS_PER_CYCLE 256
#define KBD_INT_CYCLES 16
/* FUNCTIONS ******************************************************************/

View file

@ -25,24 +25,17 @@ 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;
/* Check if the keyboard queue is full */
if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd)) return FALSE;
WaitForSingleObject(QueueMutex, INFINITE);
/* Check if the keyboard queue is full */
if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd))
{
Result = FALSE;
goto Done;
}
/* Insert the value in the queue */
KeyboardQueue[KeyboardQueueEnd] = ScanCode;
KeyboardQueueEnd++;
@ -51,24 +44,17 @@ static BOOLEAN KeyboardQueuePush(BYTE ScanCode)
/* Since we inserted a value, it's not empty anymore */
KeyboardQueueEmpty = FALSE;
Done:
ReleaseMutex(QueueMutex);
return Result;
return TRUE;
}
static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
{
BOOLEAN Result = TRUE;
/* Make sure the keyboard queue is not empty */
if (KeyboardQueueEmpty) return FALSE;
WaitForSingleObject(QueueMutex, INFINITE);
/* Make sure the keyboard queue is not empty */
if (KeyboardQueueEmpty)
{
Result = FALSE;
goto Done;
}
/* Get the scan code */
*ScanCode = KeyboardQueue[KeyboardQueueStart];
@ -82,24 +68,21 @@ static BOOLEAN KeyboardQueuePop(BYTE *ScanCode)
KeyboardQueueEmpty = TRUE;
}
Done:
ReleaseMutex(QueueMutex);
return Result;
return TRUE;
}
/* PUBLIC FUNCTIONS ***********************************************************/
BYTE KeyboardReadStatus()
BYTE WINAPI PS2ReadPort(ULONG Port)
{
if (Port == PS2_CONTROL_PORT)
{
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;
@ -107,11 +90,26 @@ BYTE KeyboardReadStatus()
if (KeyboardWriteResponse) Status |= 1 << 3;
return Status;
}
else if (Port == PS2_DATA_PORT)
{
/* If there was a response byte from the controller, return it */
if (KeyboardReadResponse)
{
KeyboardReadResponse = FALSE;
KeyboardData = KeyboardResponse;
}
return KeyboardData;
}
else return 0;
}
VOID KeyboardWriteCommand(BYTE Command)
VOID WINAPI PS2WritePort(ULONG Port, BYTE Data)
{
switch (Command)
if (Port == PS2_CONTROL_PORT)
{
switch (Data)
{
/* Read configuration byte */
case 0x20:
@ -133,7 +131,7 @@ VOID KeyboardWriteCommand(BYTE Command)
case 0xD4:
{
/* These commands require a response */
KeyboardResponse = Command;
KeyboardResponse = Data;
KeyboardWriteResponse = TRUE;
break;
}
@ -204,27 +202,9 @@ VOID KeyboardWriteCommand(BYTE Command)
break;
}
}
}
BYTE KeyboardReadData()
{
/* If there was a response byte from the controller, return it */
if (KeyboardReadResponse)
{
KeyboardReadResponse = FALSE;
KeyboardData = KeyboardResponse;
}
else
else if (Port == PS2_DATA_PORT)
{
/* Otherwise, read the data from the queue */
KeyboardQueuePop(&KeyboardData);
}
return KeyboardData;
}
VOID KeyboardWriteData(BYTE Data)
{
/* Check if the controller is waiting for a response */
if (KeyboardWriteResponse)
{
@ -280,24 +260,16 @@ VOID KeyboardWriteData(BYTE Data)
}
// TODO: Implement PS/2 device commands
}
}
BYTE WINAPI PS2ReadPort(ULONG Port)
VOID GenerateKeyboardInterrupts(VOID)
{
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);
if (KeyboardQueuePop(&KeyboardData))
{
/* IRQ 1 */
PicInterruptRequest(1);
}
}
DWORD WINAPI InputThreadProc(LPVOID Parameter)
@ -335,8 +307,6 @@ DWORD WINAPI InputThreadProc(LPVOID Parameter)
KeyboardQueuePush(ScanCode);
}
/* Keyboard IRQ */
PicInterruptRequest(1);
break;
}

View file

@ -24,13 +24,11 @@
/* FUNCTIONS ******************************************************************/
BYTE KeyboardReadStatus();
//VOID KeyboardWriteCommand(BYTE Command);
BYTE KeyboardReadData();
//VOID KeyboardWriteData(BYTE Data);
BOOLEAN PS2Initialize(HANDLE ConsoleInput);
VOID PS2Cleanup(VOID);
BYTE WINAPI PS2ReadPort(ULONG Port);
VOID WINAPI PS2WritePort(ULONG Port, BYTE Data);
VOID GenerateKeyboardInterrupts(VOID);
#endif // _PS2_H_