Fixed race condition between psaux ISR and DPC.

svn path=/trunk/; revision=3686
This commit is contained in:
David Welch 2002-10-31 23:48:06 +00:00
parent 58aee3a2d8
commit 6072415050
3 changed files with 101 additions and 92 deletions

View file

@ -19,101 +19,112 @@ int mouse_replies_expected = 0;
BOOLEAN STDCALL BOOLEAN STDCALL
ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext) ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
{ {
// char tmpstr[100];
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext; PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
int state_dx, state_dy, state_buttons; int state_dx, state_dy, state_buttons;
unsigned scancode; unsigned scancode;
unsigned status = controller_read_status(); unsigned status = controller_read_status();
scancode = controller_read_input(); scancode = controller_read_input();
// Don't handle the mouse event if we aren't connected to the mouse class driver /*
if(DeviceExtension->ClassInformation.CallBack == NULL) return FALSE; * Don't handle the mouse event if we aren't connected to the mouse class
* driver
*/
if (DeviceExtension->ClassInformation.CallBack == NULL)
{
return FALSE;
}
if((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0) if ((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
{ {
// mouse_handle_event(scancode); proceed to handle it // mouse_handle_event(scancode); proceed to handle it
} }
else else
{ {
return FALSE; // keyboard_handle_event(scancode); return FALSE; // keyboard_handle_event(scancode);
} }
if (mouse_replies_expected > 0) if (mouse_replies_expected > 0)
{
if (scancode == MOUSE_ACK)
{ {
mouse_replies_expected--; if (scancode == MOUSE_ACK)
return; {
mouse_replies_expected--;
return;
}
mouse_replies_expected = 0;
} }
mouse_replies_expected = 0;
}
/* Add this scancode to the mouse event queue. */ /* Add this scancode to the mouse event queue. */
mouse_buffer[mouse_buffer_position] = scancode; mouse_buffer[mouse_buffer_position] = scancode;
mouse_buffer_position++; mouse_buffer_position++;
// If the buffer is full, parse this event /* If the buffer is full, parse this event */
if (mouse_buffer_position == 3) if (mouse_buffer_position == 3)
{ {
mouse_buffer_position = 0; mouse_buffer_position = 0;
// system_call_debug_print_simple ("We got a mouse event");
state_buttons = (mouse_buffer[0] & 1) * GPM_B_LEFT +
(mouse_buffer[0] & 2) * GPM_B_RIGHT +
(mouse_buffer[0] & 4) * GPM_B_MIDDLE;
/* Some PS/2 mice send reports with negative bit set in data[0] and zero for movement. I think this is a
bug in the mouse, but working around it only causes artifacts when the actual report is -256; they'll
be treated as zero. This should be rare if the mouse sampling rate is set to a reasonable value; the
default of 100 Hz is plenty. (Stephen Tell) */
if (mouse_buffer[1] == 0)
{
state_dx = 0;
}
else
{
state_dx = (mouse_buffer[0] & 0x10) ?
mouse_buffer[1] - 256 :
mouse_buffer[1];
}
if (mouse_buffer[2] == 0)
{
state_dy = 0;
}
else
{
state_dy = -((mouse_buffer[0] & 0x20) ?
mouse_buffer[2] - 256 :
mouse_buffer[2]);
}
state_buttons = (mouse_buffer[0] & 1) * GPM_B_LEFT +
(mouse_buffer[0] & 2) * GPM_B_RIGHT +
(mouse_buffer[0] & 4) * GPM_B_MIDDLE;
/*
* Some PS/2 mice send reports with negative bit set in data[0] and zero
* for movement. I think this is a bug in the mouse, but working around
* it only causes artifacts when the actual report is -256; they'll
* be treated as zero. This should be rare if the mouse sampling rate is
* set to a reasonable value; the default of 100 Hz is plenty.
* (Stephen Tell)
*/
if (mouse_buffer[1] == 0)
{
state_dx = 0;
}
else
{
state_dx = (mouse_buffer[0] & 0x10) ?
mouse_buffer[1] - 256 :
mouse_buffer[1];
}
if (mouse_buffer[2] == 0)
{
state_dy = 0;
}
else
{
state_dy = -((mouse_buffer[0] & 0x20) ?
mouse_buffer[2] - 256 :
mouse_buffer[2]);
}
if (((state_dx!=0) || (state_dy!=0) || (state_buttons!=0))) if (((state_dx!=0) || (state_dy!=0) || (state_buttons!=0)))
{ {
// FIXME: Implement button state, see /include/ntddmous.h ULONG Queue;
PMOUSE_INPUT_DATA Input;
DeviceObject = (PDEVICE_OBJECT)ServiceContext; /* FIXME: Implement button state, see /include/ntddmous.h */
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
DeviceObject = (PDEVICE_OBJECT)ServiceContext;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
Queue = DeviceExtension->ActiveQueue % 2;
if (DeviceExtension->InputDataCount[Queue] == MOUSE_BUFFER_SIZE)
{
return TRUE;
}
if (DeviceExtension->InputDataCount == MOUSE_BUFFER_SIZE) Input = &DeviceExtension->MouseInputData[Queue]
{ [DeviceExtension->InputDataCount[Queue]];
return TRUE; Input->RawButtons = state_buttons;
} Input->ButtonData = state_buttons;
Input->LastX = state_dx;
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].RawButtons = state_buttons; Input->LastY = state_dy;
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].ButtonData = state_buttons; DeviceExtension->InputDataCount[Queue]++;
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastX = state_dx;
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastY = state_dy; KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp,
DeviceExtension->InputDataCount++; NULL);
return TRUE;
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
return TRUE;
} }
} }
} }
@ -200,8 +211,9 @@ BOOLEAN mouse_init (PDEVICE_OBJECT DeviceObject)
has_mouse = TRUE; has_mouse = TRUE;
DeviceExtension->InputDataCount = 0; DeviceExtension->InputDataCount[0] = 0;
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); DeviceExtension->InputDataCount[1] = 0;
DeviceExtension->ActiveQueue = 0;
// Enable the PS/2 mouse port // Enable the PS/2 mouse port
controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE); controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE);

View file

@ -96,11 +96,6 @@ PS2MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
VOID PS2MouseInitializeDataQueue(PVOID Context) VOID PS2MouseInitializeDataQueue(PVOID Context)
{ {
;
/* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtension;
DeviceExtension->InputDataCount = 0;
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); */
} }
NTSTATUS STDCALL NTSTATUS STDCALL
@ -143,14 +138,16 @@ PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{ {
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
ULONG Queue;
Queue = DeviceExtension->ActiveQueue % 2;
InterlockedIncrement(&DeviceExtension->ActiveQueue);
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)( (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
DeviceExtension->ClassInformation.DeviceObject, DeviceExtension->ClassInformation.DeviceObject,
DeviceExtension->MouseInputData, DeviceExtension->MouseInputData[Queue],
NULL, NULL,
&DeviceExtension->InputDataCount); &DeviceExtension->InputDataCount[Queue]);
DeviceExtension->InputDataCount[Queue] = 0;
DeviceExtension->InputDataCount = 0;
} }
NTSTATUS STDCALL NTSTATUS STDCALL
@ -188,7 +185,6 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
DeviceExtension = DeviceObject->DeviceExtension; DeviceExtension = DeviceObject->DeviceExtension;
KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject); KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
KeInitializeDpc(&DeviceExtension->IsrDpcRetry, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
mouse_init(DeviceObject); mouse_init(DeviceObject);

View file

@ -1,12 +1,13 @@
typedef struct _DEVICE_EXTENSION { typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
ULONG InputDataCount;
PMOUSE_INPUT_DATA MouseInputData;
CLASS_INFORMATION ClassInformation;
PKINTERRUPT MouseInterrupt; ULONG ActiveQueue;
ULONG InputDataCount[2];
MOUSE_INPUT_DATA MouseInputData[2][MOUSE_BUFFER_SIZE];
CLASS_INFORMATION ClassInformation;
PKINTERRUPT MouseInterrupt;
KDPC IsrDpc; KDPC IsrDpc;
KDPC IsrDpcRetry;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION; } DEVICE_EXTENSION, *PDEVICE_EXTENSION;