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
ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
{
// char tmpstr[100];
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
int state_dx, state_dy, state_buttons;
unsigned scancode;
unsigned status = controller_read_status();
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)
{
// mouse_handle_event(scancode); proceed to handle it
}
if ((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
{
// mouse_handle_event(scancode); proceed to handle it
}
else
{
return FALSE; // keyboard_handle_event(scancode);
}
{
return FALSE; // keyboard_handle_event(scancode);
}
if (mouse_replies_expected > 0)
{
if (scancode == MOUSE_ACK)
{
mouse_replies_expected--;
return;
if (scancode == MOUSE_ACK)
{
mouse_replies_expected--;
return;
}
mouse_replies_expected = 0;
}
mouse_replies_expected = 0;
}
/* Add this scancode to the mouse event queue. */
mouse_buffer[mouse_buffer_position] = scancode;
mouse_buffer_position++;
// If the buffer is full, parse this event
/* If the buffer is full, parse this event */
if (mouse_buffer_position == 3)
{
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]);
}
{
mouse_buffer_position = 0;
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)))
{
// FIXME: Implement button state, see /include/ntddmous.h
{
ULONG Queue;
PMOUSE_INPUT_DATA Input;
DeviceObject = (PDEVICE_OBJECT)ServiceContext;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* FIXME: Implement button state, see /include/ntddmous.h */
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)
{
return TRUE;
}
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].RawButtons = state_buttons;
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].ButtonData = state_buttons;
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastX = state_dx;
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastY = state_dy;
DeviceExtension->InputDataCount++;
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
return TRUE;
Input = &DeviceExtension->MouseInputData[Queue]
[DeviceExtension->InputDataCount[Queue]];
Input->RawButtons = state_buttons;
Input->ButtonData = state_buttons;
Input->LastX = state_dx;
Input->LastY = state_dy;
DeviceExtension->InputDataCount[Queue]++;
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp,
NULL);
return TRUE;
}
}
}
@ -200,8 +211,9 @@ BOOLEAN mouse_init (PDEVICE_OBJECT DeviceObject)
has_mouse = TRUE;
DeviceExtension->InputDataCount = 0;
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE);
DeviceExtension->InputDataCount[0] = 0;
DeviceExtension->InputDataCount[1] = 0;
DeviceExtension->ActiveQueue = 0;
// Enable the PS/2 mouse port
controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE);

View file

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

View file

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