mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
- Enable/disable keyboard by writing the controller command byte instead of
issuing keyboard commands, the keyboard commands seem to confuse some kvm switches. - Use STATUS_IO_TIMEOUT consistently, STATUS_TIMEOUT is not an error condition - Introduce symbolic constants for controller command byte bits - Try to detect mouse early and if its not present, reset the keyboard controller. Some controllers seem to get locked up when writing to a non-present mouse. - Don't check the timeout status bit when reading from the controller. It is often wrong. - Don't treat failure to read keyboard id as a fatal error, we only read it to set KeyboardIsAT which we then don't use. Still try to detect the keyboard type, but don't fail if it doesn't work. Fixes bug 688. Thanks to Hartmut, Filip and WaxDragon for testing. svn path=/trunk/; revision=18664
This commit is contained in:
parent
a861531b6c
commit
6940e61dd6
4 changed files with 194 additions and 47 deletions
|
@ -10,9 +10,7 @@
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ****************************************************************/
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#endif
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include "i8042prt.h"
|
#include "i8042prt.h"
|
||||||
|
@ -78,7 +76,7 @@ NTSTATUS I8042ReadData(UCHAR *Data)
|
||||||
DPRINT("Read: %x (status: %x)\n", Data[0], Status);
|
DPRINT("Read: %x (status: %x)\n", Data[0], Status);
|
||||||
|
|
||||||
// If the data is valid (not timeout, not parity error)
|
// If the data is valid (not timeout, not parity error)
|
||||||
if (0 == (Status & (KBD_GTO | KBD_PERR)))
|
if (0 == (Status & KBD_PERR))
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
@ -115,7 +113,7 @@ VOID I8042Flush()
|
||||||
UCHAR Ignore;
|
UCHAR Ignore;
|
||||||
|
|
||||||
while (STATUS_SUCCESS == I8042ReadData(&Ignore)) {
|
while (STATUS_SUCCESS == I8042ReadData(&Ignore)) {
|
||||||
; /* drop */
|
DPRINT("Data flushed\n"); /* drop */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,25 +144,38 @@ NTSTATUS STDCALL I8042SynchWritePort(PDEVICE_EXTENSION DevExt,
|
||||||
do {
|
do {
|
||||||
if (Port)
|
if (Port)
|
||||||
if (!I8042Write(DevExt, I8042_DATA_PORT, Port))
|
if (!I8042Write(DevExt, I8042_DATA_PORT, Port))
|
||||||
return STATUS_TIMEOUT;
|
{
|
||||||
|
DPRINT1("Failed to write Port\n");
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!I8042Write(DevExt, I8042_DATA_PORT, Value))
|
if (!I8042Write(DevExt, I8042_DATA_PORT, Value))
|
||||||
return STATUS_TIMEOUT;
|
{
|
||||||
|
DPRINT1("Failed to write Value\n");
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (WaitForAck) {
|
if (WaitForAck) {
|
||||||
Status = I8042ReadDataWait(DevExt, &Ack);
|
Status = I8042ReadDataWait(DevExt, &Ack);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to read Ack\n");
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
if (Ack == KBD_ACK)
|
if (Ack == KBD_ACK)
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
if (Ack != KBD_RESEND)
|
if (Ack != KBD_RESEND)
|
||||||
|
{
|
||||||
|
DPRINT1("Unexpected Ack 0x%x\n", Ack);
|
||||||
return STATUS_UNEXPECTED_IO_ERROR;
|
return STATUS_UNEXPECTED_IO_ERROR;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
DPRINT("Reiterating\n");
|
||||||
ResendIterations--;
|
ResendIterations--;
|
||||||
} while (ResendIterations);
|
} while (ResendIterations);
|
||||||
return STATUS_TIMEOUT;
|
return STATUS_IO_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -241,7 +252,7 @@ NTSTATUS STDCALL I8042StartPacket(PDEVICE_EXTENSION DevExt,
|
||||||
DevExt->PacketPort = 0;
|
DevExt->PacketPort = 0;
|
||||||
|
|
||||||
if (!I8042PacketWrite(DevExt)) {
|
if (!I8042PacketWrite(DevExt)) {
|
||||||
Status = STATUS_TIMEOUT;
|
Status = STATUS_IO_TIMEOUT;
|
||||||
DevExt->Packet.State = Idle;
|
DevExt->Packet.State = Idle;
|
||||||
DevExt->PacketResult = STATUS_ABANDONED;
|
DevExt->PacketResult = STATUS_ABANDONED;
|
||||||
goto startpacketdone;
|
goto startpacketdone;
|
||||||
|
@ -273,7 +284,7 @@ BOOLEAN STDCALL I8042PacketIsr(PDEVICE_EXTENSION DevExt,
|
||||||
if (DevExt->PacketResends > DevExt->Settings.ResendIterations) {
|
if (DevExt->PacketResends > DevExt->Settings.ResendIterations) {
|
||||||
DevExt->Packet.State = Idle;
|
DevExt->Packet.State = Idle;
|
||||||
DevExt->PacketComplete = TRUE;
|
DevExt->PacketComplete = TRUE;
|
||||||
DevExt->PacketResult = STATUS_TIMEOUT;
|
DevExt->PacketResult = STATUS_IO_TIMEOUT;
|
||||||
DevExt->PacketResends = 0;
|
DevExt->PacketResends = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +312,7 @@ BOOLEAN STDCALL I8042PacketIsr(PDEVICE_EXTENSION DevExt,
|
||||||
if (!I8042PacketWrite(DevExt)) {
|
if (!I8042PacketWrite(DevExt)) {
|
||||||
DevExt->Packet.State = Idle;
|
DevExt->Packet.State = Idle;
|
||||||
DevExt->PacketComplete = TRUE;
|
DevExt->PacketComplete = TRUE;
|
||||||
DevExt->PacketResult = STATUS_TIMEOUT;
|
DevExt->PacketResult = STATUS_IO_TIMEOUT;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
DevExt->Packet.CurrentByte++;
|
DevExt->Packet.CurrentByte++;
|
||||||
|
@ -519,23 +530,53 @@ static NTSTATUS STDCALL I8042BasicDetect(PDEVICE_EXTENSION DevExt)
|
||||||
|
|
||||||
I8042Flush();
|
I8042Flush();
|
||||||
|
|
||||||
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_SELF_TEST))
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_SELF_TEST)) {
|
||||||
return STATUS_TIMEOUT;
|
DPRINT1("Writing KBD_SELF_TEST command failed\n");
|
||||||
|
return STATUS_IO_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait longer?
|
// Wait longer?
|
||||||
Counter = 3;
|
Counter = 3;
|
||||||
do {
|
do {
|
||||||
Status = I8042ReadDataWait(DevExt, &Value);
|
Status = I8042ReadDataWait(DevExt, &Value);
|
||||||
} while ((Counter--) && (STATUS_TIMEOUT == Status));
|
} while ((Counter--) && (STATUS_IO_TIMEOUT == Status));
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
DPRINT1("Failed to read KBD_SELF_TEST response, status 0x%x\n",
|
||||||
|
Status);
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
if (Value != 0x55) {
|
if (Value != 0x55) {
|
||||||
DPRINT1("Got %x instead of 55\n", Value);
|
DPRINT1("Got %x instead of 55\n", Value);
|
||||||
return STATUS_IO_DEVICE_ERROR;
|
return STATUS_IO_DEVICE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) {
|
||||||
|
DPRINT1("Can't read i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = I8042ReadDataWait(DevExt, &Value);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
DPRINT1("No response after read i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value |= CCB_KBD_DISAB | CCB_MOUSE_DISAB; /* disable keyboard/mouse */
|
||||||
|
Value &= ~(CCB_KBD_INT_ENAB | CCB_MOUSE_INT_ENAB);
|
||||||
|
/* don't enable keyboard and mouse interrupts */
|
||||||
|
|
||||||
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) {
|
||||||
|
DPRINT1("Can't set i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) {
|
||||||
|
DPRINT1("Can't send i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (I8042Write(DevExt, I8042_CTRL_PORT, KBD_LINE_TEST))
|
if (I8042Write(DevExt, I8042_CTRL_PORT, KBD_LINE_TEST))
|
||||||
{
|
{
|
||||||
Status = I8042ReadDataWait(DevExt, &Value);
|
Status = I8042ReadDataWait(DevExt, &Value);
|
||||||
|
@ -563,6 +604,11 @@ static NTSTATUS STDCALL I8042Initialize(PDEVICE_EXTENSION DevExt)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DevExt->MouseExists) {
|
||||||
|
DPRINT("Aux port detected\n");
|
||||||
|
DevExt->MouseExists = I8042DetectMouse(DevExt);
|
||||||
|
}
|
||||||
|
|
||||||
if (!DevExt->KeyboardExists) {
|
if (!DevExt->KeyboardExists) {
|
||||||
DPRINT("Keyboard port not detected\n");
|
DPRINT("Keyboard port not detected\n");
|
||||||
if (DevExt->Settings.Headless)
|
if (DevExt->Settings.Headless)
|
||||||
|
@ -820,4 +866,3 @@ NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,17 @@ typedef struct _I8042_HOOK_WORKITEM
|
||||||
#define KBD_GTO 0x40
|
#define KBD_GTO 0x40
|
||||||
#define KBD_PERR 0x80
|
#define KBD_PERR 0x80
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controller command byte bits
|
||||||
|
*/
|
||||||
|
#define CCB_KBD_INT_ENAB 0x01
|
||||||
|
#define CCB_MOUSE_INT_ENAB 0x02
|
||||||
|
#define CCB_SYSTEM_FLAG 0x04
|
||||||
|
#define CCB_IGN_KEY_LOCK 0x08
|
||||||
|
#define CCB_KBD_DISAB 0x10
|
||||||
|
#define CCB_MOUSE_DISAB 0x20
|
||||||
|
#define CCB_TRANSLATE 0x40
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LED bits
|
* LED bits
|
||||||
|
@ -359,6 +370,7 @@ VOID STDCALL I8042MouseHandle(PDEVICE_EXTENSION DevExt,
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042MouseEnable(PDEVICE_EXTENSION DevExt);
|
BOOLEAN STDCALL I8042MouseEnable(PDEVICE_EXTENSION DevExt);
|
||||||
BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt);
|
BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt);
|
||||||
|
BOOLEAN STDCALL I8042DetectMouse(PDEVICE_EXTENSION DevExt);
|
||||||
|
|
||||||
/* ps2pp.c */
|
/* ps2pp.c */
|
||||||
VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input);
|
VOID I8042MouseHandlePs2pp(PDEVICE_EXTENSION DevExt, UCHAR Input);
|
||||||
|
|
|
@ -11,13 +11,11 @@
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ****************************************************************/
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define NDEBUG
|
|
||||||
#endif
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "i8042prt.h"
|
#include "i8042prt.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
static UCHAR TypematicTable[] = {
|
static UCHAR TypematicTable[] = {
|
||||||
|
@ -559,34 +557,73 @@ intcontfailure:
|
||||||
* some really old broken keyboard controllers which I hope won't be
|
* some really old broken keyboard controllers which I hope won't be
|
||||||
* necessary.
|
* necessary.
|
||||||
*
|
*
|
||||||
* Anyway, disabling the keyboard helps the detection and it also
|
* We change the command byte, sending KBD_ENABLE/DISABLE seems to confuse
|
||||||
* clears the keyboard buffer and sets defaults which is what we
|
* some kvm switches.
|
||||||
* want.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOLEAN STDCALL I8042KeyboardEnable(PDEVICE_EXTENSION DevExt)
|
BOOLEAN STDCALL I8042KeyboardEnable(PDEVICE_EXTENSION DevExt)
|
||||||
{
|
{
|
||||||
DPRINT("Enabling keyboard\n");
|
UCHAR Value;
|
||||||
if (STATUS_SUCCESS != I8042SynchWritePort(DevExt,
|
NTSTATUS Status;
|
||||||
0,
|
|
||||||
KBD_ENABLE,
|
DPRINT("Enable keyboard\n");
|
||||||
TRUE)) {
|
|
||||||
DPRINT("Can't enable keyboard\n");
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) {
|
||||||
|
DPRINT1("Can't read i8042 mode\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = I8042ReadDataWait(DevExt, &Value);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
DPRINT1("No response after read i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value &= ~CCB_KBD_DISAB; // don't disable keyboard
|
||||||
|
|
||||||
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) {
|
||||||
|
DPRINT1("Can't set i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) {
|
||||||
|
DPRINT1("Can't send i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN STDCALL I8042KeyboardDefaultsAndDisable(PDEVICE_EXTENSION DevExt)
|
static BOOLEAN STDCALL I8042KeyboardDefaultsAndDisable(PDEVICE_EXTENSION DevExt)
|
||||||
{
|
{
|
||||||
|
UCHAR Value;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT("Disabling keyboard\n");
|
DPRINT("Disabling keyboard\n");
|
||||||
if (STATUS_SUCCESS != I8042SynchWritePort(DevExt,
|
|
||||||
0,
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) {
|
||||||
KBD_DISABLE,
|
DPRINT1("Can't read i8042 mode\n");
|
||||||
TRUE)) {
|
|
||||||
DPRINT("Can't disable keyboard\n");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status = I8042ReadDataWait(DevExt, &Value);
|
||||||
|
if (!NT_SUCCESS(Status)) {
|
||||||
|
DPRINT1("No response after read i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value |= CCB_KBD_DISAB; // disable keyboard
|
||||||
|
|
||||||
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) {
|
||||||
|
DPRINT1("Can't set i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) {
|
||||||
|
DPRINT1("Can't send i8042 mode\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,8 +645,8 @@ BOOLEAN STDCALL I8042KeyboardEnableInterrupt(PDEVICE_EXTENSION DevExt)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value &= ~(0x10); // don't disable keyboard
|
Value &= ~CCB_KBD_DISAB; // don't disable keyboard
|
||||||
Value |= 0x01; // enable keyboard interrupts
|
Value |= CCB_KBD_INT_ENAB; // enable keyboard interrupts
|
||||||
|
|
||||||
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) {
|
if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) {
|
||||||
DPRINT1("Can't set i8042 mode\n");
|
DPRINT1("Can't set i8042 mode\n");
|
||||||
|
@ -628,6 +665,7 @@ BOOLEAN STDCALL I8042DetectKeyboard(PDEVICE_EXTENSION DevExt)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
UCHAR Value;
|
UCHAR Value;
|
||||||
|
UCHAR Value2;
|
||||||
ULONG RetryCount = 10;
|
ULONG RetryCount = 10;
|
||||||
|
|
||||||
DPRINT("Detecting keyboard\n");
|
DPRINT("Detecting keyboard\n");
|
||||||
|
@ -635,12 +673,15 @@ BOOLEAN STDCALL I8042DetectKeyboard(PDEVICE_EXTENSION DevExt)
|
||||||
I8042KeyboardDefaultsAndDisable(DevExt);
|
I8042KeyboardDefaultsAndDisable(DevExt);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
I8042Flush();
|
||||||
Status = I8042SynchWritePort(DevExt, 0, KBD_GET_ID, TRUE);
|
Status = I8042SynchWritePort(DevExt, 0, KBD_GET_ID, TRUE);
|
||||||
} while (STATUS_TIMEOUT == Status && RetryCount--);
|
} while (STATUS_IO_TIMEOUT == Status && RetryCount--);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
DPRINT1("Can't write GET_ID (%x)\n", Status);
|
DPRINT1("Can't write GET_ID (%x)\n", Status);
|
||||||
return FALSE;
|
/* Could be an AT keyboard */
|
||||||
|
DevExt->KeyboardIsAT = TRUE;
|
||||||
|
goto detectsetleds;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = I8042ReadDataWait(DevExt, &Value);
|
Status = I8042ReadDataWait(DevExt, &Value);
|
||||||
|
@ -658,17 +699,17 @@ BOOLEAN STDCALL I8042DetectKeyboard(PDEVICE_EXTENSION DevExt)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT("Keyboard ID: %x", Value);
|
Status = I8042ReadDataWait(DevExt, &Value2);
|
||||||
|
|
||||||
Status = I8042ReadDataWait(DevExt, &Value);
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
DPRINT("Partial ID\n");
|
DPRINT("Partial ID\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT ("%x\n", Value);
|
DPRINT("Keyboard ID: 0x%x 0x%x\n", Value, Value2);
|
||||||
|
|
||||||
detectsetleds:
|
detectsetleds:
|
||||||
|
I8042Flush(); /* Flush any bytes left over from GET_ID */
|
||||||
|
|
||||||
Status = I8042SynchWritePort(DevExt, 0, KBD_SET_LEDS, TRUE);
|
Status = I8042SynchWritePort(DevExt, 0, KBD_SET_LEDS, TRUE);
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status)) {
|
||||||
DPRINT("Can't write SET_LEDS (%x)\n", Status);
|
DPRINT("Can't write SET_LEDS (%x)\n", Status);
|
||||||
|
|
|
@ -11,13 +11,11 @@
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ****************************************************************/
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
#define NDEBUG
|
|
||||||
#endif
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "i8042prt.h"
|
#include "i8042prt.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions are callbacks for filter driver custom interrupt
|
* These functions are callbacks for filter driver custom interrupt
|
||||||
* service routines.
|
* service routines.
|
||||||
|
@ -897,3 +895,54 @@ BOOLEAN STDCALL I8042MouseDisable(PDEVICE_EXTENSION DevExt)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN STDCALL I8042DetectMouse(PDEVICE_EXTENSION DevExt)
|
||||||
|
{
|
||||||
|
BOOLEAN Ok = TRUE;
|
||||||
|
NTSTATUS Status;
|
||||||
|
UCHAR Value;
|
||||||
|
UCHAR ExpectedReply[] = { 0xFA, 0xAA, 0x00 };
|
||||||
|
unsigned ReplyByte;
|
||||||
|
|
||||||
|
if (! I8042Write(DevExt, I8042_CTRL_PORT, 0xD4) ||
|
||||||
|
! I8042Write(DevExt, I8042_DATA_PORT, 0xFF))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to write reset command to mouse\n");
|
||||||
|
Ok = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ReplyByte = 0;
|
||||||
|
ReplyByte < sizeof(ExpectedReply) / sizeof(ExpectedReply[0]) && Ok;
|
||||||
|
ReplyByte++)
|
||||||
|
{
|
||||||
|
Status = I8042ReadDataWait(DevExt, &Value);
|
||||||
|
if (! NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("No ACK after mouse reset, status 0x%08x\n",
|
||||||
|
Status);
|
||||||
|
Ok = FALSE;
|
||||||
|
}
|
||||||
|
else if (Value != ExpectedReply[ReplyByte])
|
||||||
|
{
|
||||||
|
DPRINT1("Unexpected reply: 0x%02x (expected 0x%02x)\n",
|
||||||
|
Value, ExpectedReply[ReplyByte]);
|
||||||
|
Ok = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! Ok)
|
||||||
|
{
|
||||||
|
/* There is probably no mouse present. On some systems,
|
||||||
|
the probe locks the entire keyboard controller. Let's
|
||||||
|
try to get access to the keyboard again by sending a
|
||||||
|
reset */
|
||||||
|
I8042Flush();
|
||||||
|
I8042Write(DevExt, I8042_CTRL_PORT, KBD_SELF_TEST);
|
||||||
|
I8042ReadDataWait(DevExt, &Value);
|
||||||
|
I8042Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Mouse %sdetected\n", Ok ? "" : "not ");
|
||||||
|
|
||||||
|
return Ok;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue