2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/input/i8042prt/i8042prt.c
5 * PURPOSE: i8042 (ps/2 keyboard-mouse controller) driver
6 * PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
7 * Jason Filby (jasonfilby@yahoo.com)
11 /* INCLUDES ****************************************************************/
18 /* GLOBALS *******************************************************************/
23 #define I8042_TIMEOUT 500000
25 #define I8042_MAX_COMMAND_LENGTH 16
26 #define I8042_MAX_UPWARDS_STACK 5
28 UNICODE_STRING I8042RegistryPath
;
30 /* FUNCTIONS *****************************************************************/
33 * FUNCTION: Write data to a port, waiting first for it to become ready
35 BOOLEAN
I8042Write(PDEVICE_EXTENSION DevExt
, PUCHAR addr
, UCHAR data
)
37 ULONG ResendIterations
= DevExt
->Settings
.PollingIterations
;
39 while ((KBD_IBF
& READ_PORT_UCHAR(I8042_CTRL_PORT
)) &&
42 KeStallExecutionProcessor(50);
45 if (ResendIterations
) {
46 WRITE_PORT_UCHAR(addr
,data
);
47 DPRINT("Sent %x to %x\n", data
, addr
);
53 #if 0 /* function is not needed */
55 * FUNCTION: Write data to a port, without waiting first
57 static BOOLEAN
I8042WriteNoWait(PDEVICE_EXTENSION DevExt
, int addr
, UCHAR data
)
59 WRITE_PORT_UCHAR((PUCHAR
)addr
,data
);
60 DPRINT("Sent %x to %x\n", data
, addr
);
66 * FUNCTION: Read data from port 0x60
68 NTSTATUS
I8042ReadData(UCHAR
*Data
)
71 Status
=READ_PORT_UCHAR(I8042_CTRL_PORT
);
73 // If data is available
74 if ((Status
& KBD_OBF
)) {
75 Data
[0]=READ_PORT_UCHAR((PUCHAR
)I8042_DATA_PORT
);
76 DPRINT("Read: %x (status: %x)\n", Data
[0], Status
);
78 // If the data is valid (not timeout, not parity error)
79 if (0 == (Status
& KBD_PERR
))
80 return STATUS_SUCCESS
;
82 return STATUS_UNSUCCESSFUL
;
85 NTSTATUS
I8042ReadStatus(UCHAR
*Status
)
87 Status
[0]=READ_PORT_UCHAR(I8042_CTRL_PORT
);
88 return STATUS_SUCCESS
;
92 * FUNCTION: Read data from port 0x60
94 NTSTATUS
I8042ReadDataWait(PDEVICE_EXTENSION DevExt
, UCHAR
*Data
)
96 ULONG Counter
= DevExt
->Settings
.PollingIterations
;
100 Status
= I8042ReadData(Data
);
102 if (STATUS_SUCCESS
== Status
)
105 KeStallExecutionProcessor(50);
108 return STATUS_IO_TIMEOUT
;
115 while (STATUS_SUCCESS
== I8042ReadData(&Ignore
)) {
116 DPRINT("Data flushed\n"); /* drop */
120 VOID STDCALL
I8042IsrWritePort(PDEVICE_EXTENSION DevExt
,
125 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, SelectCmd
))
128 I8042Write(DevExt
, I8042_DATA_PORT
, Value
);
132 * These functions are callbacks for filter driver custom
133 * initialization routines.
135 NTSTATUS STDCALL
I8042SynchWritePort(PDEVICE_EXTENSION DevExt
,
142 ULONG ResendIterations
= DevExt
->Settings
.ResendIterations
+ 1;
146 if (!I8042Write(DevExt
, I8042_DATA_PORT
, Port
))
148 DPRINT1("Failed to write Port\n");
149 return STATUS_IO_TIMEOUT
;
152 if (!I8042Write(DevExt
, I8042_DATA_PORT
, Value
))
154 DPRINT1("Failed to write Value\n");
155 return STATUS_IO_TIMEOUT
;
159 Status
= I8042ReadDataWait(DevExt
, &Ack
);
160 if (!NT_SUCCESS(Status
))
162 DPRINT1("Failed to read Ack\n");
166 return STATUS_SUCCESS
;
167 if (Ack
!= KBD_RESEND
)
169 DPRINT1("Unexpected Ack 0x%x\n", Ack
);
170 return STATUS_UNEXPECTED_IO_ERROR
;
173 return STATUS_SUCCESS
;
175 DPRINT("Reiterating\n");
177 } while (ResendIterations
);
178 return STATUS_IO_TIMEOUT
;
182 * This one reads a value from the port; You don't have to specify
183 * which one, it'll always be from the one you talked to, so one function
184 * is enough this time. Note how MSDN specifies the
185 * WaitForAck parameter to be ignored.
187 static NTSTATUS STDCALL
I8042SynchReadPort(PVOID Context
,
191 PDEVICE_EXTENSION DevExt
= (PDEVICE_EXTENSION
)Context
;
193 return I8042ReadDataWait(DevExt
, Value
);
196 /* Write the current byte of the packet. Returns FALSE in case
199 static BOOLEAN STDCALL
I8042PacketWrite(PDEVICE_EXTENSION DevExt
)
201 UCHAR Port
= DevExt
->PacketPort
;
204 if (!I8042Write(DevExt
,
207 /* something is really wrong! */
208 DPRINT1("Failed to send packet byte!\n");
213 return I8042Write(DevExt
,
215 DevExt
->Packet
.Bytes
[DevExt
->Packet
.CurrentByte
]);
220 * This function starts a packet. It must be called with the
223 NTSTATUS STDCALL
I8042StartPacket(PDEVICE_EXTENSION DevExt
,
224 PDEVICE_OBJECT Device
,
231 PFDO_DEVICE_EXTENSION FdoDevExt
= Device
->DeviceExtension
;
233 Irql
= KeAcquireInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
);
235 DevExt
->CurrentIrp
= Irp
;
236 DevExt
->CurrentIrpDevice
= Device
;
238 if (Idle
!= DevExt
->Packet
.State
) {
239 Status
= STATUS_DEVICE_BUSY
;
240 goto startpacketdone
;
243 DevExt
->Packet
.Bytes
= Bytes
;
244 DevExt
->Packet
.CurrentByte
= 0;
245 DevExt
->Packet
.ByteCount
= ByteCount
;
246 DevExt
->Packet
.State
= SendingBytes
;
247 DevExt
->PacketResult
= Status
= STATUS_PENDING
;
249 if (Mouse
== FdoDevExt
->Type
)
250 DevExt
->PacketPort
= 0xD4;
252 DevExt
->PacketPort
= 0;
254 if (!I8042PacketWrite(DevExt
)) {
255 Status
= STATUS_IO_TIMEOUT
;
256 DevExt
->Packet
.State
= Idle
;
257 DevExt
->PacketResult
= STATUS_ABANDONED
;
258 goto startpacketdone
;
261 DevExt
->Packet
.CurrentByte
++;
264 KeReleaseInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
, Irql
);
266 if (STATUS_PENDING
!= Status
) {
267 DevExt
->CurrentIrp
= NULL
;
268 DevExt
->CurrentIrpDevice
= NULL
;
269 Irp
->IoStatus
.Status
= Status
;
270 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
275 BOOLEAN STDCALL
I8042PacketIsr(PDEVICE_EXTENSION DevExt
,
278 if (Idle
== DevExt
->Packet
.State
)
283 DevExt
->PacketResends
++;
284 if (DevExt
->PacketResends
> DevExt
->Settings
.ResendIterations
) {
285 DevExt
->Packet
.State
= Idle
;
286 DevExt
->PacketComplete
= TRUE
;
287 DevExt
->PacketResult
= STATUS_IO_TIMEOUT
;
288 DevExt
->PacketResends
= 0;
291 DevExt
->Packet
.CurrentByte
--;
295 DevExt
->Packet
.State
= Idle
;
296 DevExt
->PacketComplete
= TRUE
;
297 DevExt
->PacketResult
= STATUS_UNEXPECTED_IO_ERROR
;
298 DevExt
->PacketResends
= 0;
302 DevExt
->PacketResends
= 0;
305 if (DevExt
->Packet
.CurrentByte
>= DevExt
->Packet
.ByteCount
) {
306 DevExt
->Packet
.State
= Idle
;
307 DevExt
->PacketComplete
= TRUE
;
308 DevExt
->PacketResult
= STATUS_SUCCESS
;
312 if (!I8042PacketWrite(DevExt
)) {
313 DevExt
->Packet
.State
= Idle
;
314 DevExt
->PacketComplete
= TRUE
;
315 DevExt
->PacketResult
= STATUS_IO_TIMEOUT
;
318 DevExt
->Packet
.CurrentByte
++;
323 VOID
I8042PacketDpc(PDEVICE_EXTENSION DevExt
)
325 BOOLEAN FinishIrp
= FALSE
;
326 NTSTATUS Result
= STATUS_INTERNAL_ERROR
; /* Shouldn't happen */
329 /* If the interrupt happens before this is setup, the key
330 * was already in the buffer. Too bad! */
331 if (!DevExt
->HighestDIRQLInterrupt
)
334 Irql
= KeAcquireInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
);
336 if (Idle
== DevExt
->Packet
.State
&&
337 DevExt
->PacketComplete
) {
339 Result
= DevExt
->PacketResult
;
340 DevExt
->PacketComplete
= FALSE
;
343 KeReleaseInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
,
349 if (DevExt
->CurrentIrp
) {
350 DevExt
->CurrentIrp
->IoStatus
.Status
= Result
;
351 IoCompleteRequest(DevExt
->CurrentIrp
, IO_NO_INCREMENT
);
352 IoStartNextPacket(DevExt
->CurrentIrpDevice
, FALSE
);
353 DevExt
->CurrentIrp
= NULL
;
354 DevExt
->CurrentIrpDevice
= NULL
;
358 VOID STDCALL
I8042SendHookWorkItem(PDEVICE_OBJECT DeviceObject
,
362 IO_STATUS_BLOCK IoStatus
;
364 PDEVICE_EXTENSION DevExt
;
365 PFDO_DEVICE_EXTENSION FdoDevExt
;
367 PI8042_HOOK_WORKITEM WorkItemData
= (PI8042_HOOK_WORKITEM
)Context
;
371 ULONG InputBufferLength
;
374 DPRINT("HookWorkItem\n");
376 FdoDevExt
= (PFDO_DEVICE_EXTENSION
)
377 DeviceObject
->DeviceExtension
;
379 DevExt
= FdoDevExt
->PortDevExt
;
381 if (WorkItemData
->Target
== DevExt
->KeyboardData
.ClassDeviceObject
) {
382 IoControlCode
= IOCTL_INTERNAL_I8042_HOOK_KEYBOARD
;
383 InputBuffer
= &DevExt
->KeyboardHook
;
384 InputBufferLength
= sizeof(INTERNAL_I8042_HOOK_KEYBOARD
);
386 DPRINT ("is for keyboard.\n");
387 } else if (WorkItemData
->Target
== DevExt
->MouseData
.ClassDeviceObject
){
388 IoControlCode
= IOCTL_INTERNAL_I8042_HOOK_MOUSE
;
389 InputBuffer
= &DevExt
->MouseHook
;
390 InputBufferLength
= sizeof(INTERNAL_I8042_HOOK_MOUSE
);
392 DPRINT ("is for mouse.\n");
394 DPRINT1("I8042SendHookWorkItem: Can't find DeviceObject\n");
395 WorkItemData
->Irp
->IoStatus
.Status
= STATUS_INTERNAL_ERROR
;
396 goto hookworkitemdone
;
399 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
401 NewIrp
= IoBuildDeviceIoControlRequest(
403 WorkItemData
->Target
,
413 DPRINT("IOCTL_INTERNAL_(device)_CONNECT: "
414 "Can't allocate IRP\n");
415 WorkItemData
->Irp
->IoStatus
.Status
=
416 STATUS_INSUFFICIENT_RESOURCES
;
417 goto hookworkitemdone
;
421 Status
= IoCallDriver(
422 WorkItemData
->Target
,
425 if (STATUS_PENDING
== Status
)
426 KeWaitForSingleObject(&Event
,
434 /* Call the hooked initialization if it exists */
435 if (DevExt
->KeyboardHook
.InitializationRoutine
) {
436 Status
= DevExt
->KeyboardHook
.InitializationRoutine(
437 DevExt
->KeyboardHook
.Context
,
440 I8042SynchWritePortKbd
,
442 if (!NT_SUCCESS(Status
)) {
443 WorkItemData
->Irp
->IoStatus
.Status
= Status
;
444 goto hookworkitemdone
;
447 /* TODO: Now would be the right time to enable the interrupt */
449 DevExt
->KeyboardClaimed
= TRUE
;
451 /* Mouse doesn't have this, but we need to send a
452 * reset to start the detection.
456 Irql
= KeAcquireInterruptSpinLock(
457 DevExt
->HighestDIRQLInterrupt
);
459 I8042Write(DevExt
, I8042_CTRL_PORT
, 0xD4);
460 I8042Write(DevExt
, I8042_DATA_PORT
, 0xFF);
462 KeReleaseInterruptSpinLock(DevExt
->HighestDIRQLInterrupt
, Irql
);
465 WorkItemData
->Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
468 WorkItemData
->Irp
->IoStatus
.Information
= 0;
469 IoCompleteRequest(WorkItemData
->Irp
, IO_NO_INCREMENT
);
471 IoFreeWorkItem(WorkItemData
->WorkItem
);
472 ExFreePool(WorkItemData
);
473 DPRINT("HookWorkItem done\n");
476 static VOID STDCALL
I8042StartIo(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
478 if (!I8042StartIoKbd(DeviceObject
, Irp
)) {
479 DPRINT1("Unhandled StartIo!\n");
483 static NTSTATUS STDCALL
I8042InternalDeviceControl(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
485 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
486 PFDO_DEVICE_EXTENSION FdoDevExt
= DeviceObject
->DeviceExtension
;
488 DPRINT("InternalDeviceControl\n");
490 switch (FdoDevExt
->Type
) {
492 Status
= I8042InternalDeviceControlKbd(DeviceObject
, Irp
);
495 Status
= I8042InternalDeviceControlMouse(DeviceObject
, Irp
);
499 if (Status
== STATUS_INVALID_DEVICE_REQUEST
) {
500 DPRINT1("Invalid internal device request!\n");
503 if (Status
!= STATUS_PENDING
)
504 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
509 static NTSTATUS STDCALL
I8042CreateDispatch(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
513 DPRINT ("I8042CreateDispatch\n");
515 Status
= STATUS_SUCCESS
;
517 Irp
->IoStatus
.Status
= Status
;
518 Irp
->IoStatus
.Information
= 0;
519 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
524 static NTSTATUS STDCALL
I8042BasicDetect(PDEVICE_EXTENSION DevExt
)
530 DevExt
->MouseExists
= FALSE
;
531 DevExt
->KeyboardExists
= FALSE
;
535 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, KBD_SELF_TEST
)) {
536 DPRINT1("Writing KBD_SELF_TEST command failed\n");
537 return STATUS_IO_TIMEOUT
;
543 Status
= I8042ReadDataWait(DevExt
, &Value
);
544 } while ((Counter
--) && (STATUS_IO_TIMEOUT
== Status
));
546 if (!NT_SUCCESS(Status
)) {
547 DPRINT1("Failed to read KBD_SELF_TEST response, status 0x%x\n",
553 DPRINT1("Got %x instead of 55\n", Value
);
554 return STATUS_IO_DEVICE_ERROR
;
557 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, KBD_READ_MODE
)) {
558 DPRINT1("Can't read i8042 mode\n");
562 Status
= I8042ReadDataWait(DevExt
, &Value
);
563 if (!NT_SUCCESS(Status
)) {
564 DPRINT1("No response after read i8042 mode\n");
568 Value
|= CCB_KBD_DISAB
| CCB_MOUSE_DISAB
; /* disable keyboard/mouse */
569 Value
&= ~(CCB_KBD_INT_ENAB
| CCB_MOUSE_INT_ENAB
);
570 /* don't enable keyboard and mouse interrupts */
572 if (!I8042Write(DevExt
, I8042_CTRL_PORT
, KBD_WRITE_MODE
)) {
573 DPRINT1("Can't set i8042 mode\n");
577 if (!I8042Write(DevExt
, I8042_DATA_PORT
, Value
)) {
578 DPRINT1("Can't send i8042 mode\n");
583 * We used to send a KBD_LINE_TEST command here, but on at least HP
584 * Pavilion notebooks the response to that command was incorrect.
585 * So now we just assume that a keyboard is attached.
587 DevExt
->KeyboardExists
= TRUE
;
589 if (I8042Write(DevExt
, I8042_CTRL_PORT
, MOUSE_LINE_TEST
))
591 Status
= I8042ReadDataWait(DevExt
, &Value
);
592 if (NT_SUCCESS(Status
) && Value
== 0)
593 DevExt
->MouseExists
= TRUE
;
596 return STATUS_SUCCESS
;
599 static NTSTATUS STDCALL
I8042Initialize(PDEVICE_EXTENSION DevExt
)
603 Status
= I8042BasicDetect(DevExt
);
604 if (!NT_SUCCESS(Status
)) {
605 DPRINT1("Basic keyboard detection failed: %x\n", Status
);
609 if (DevExt
->MouseExists
) {
610 DPRINT("Aux port detected\n");
611 DevExt
->MouseExists
= I8042DetectMouse(DevExt
);
614 if (!DevExt
->KeyboardExists
) {
615 DPRINT("Keyboard port not detected\n");
616 if (DevExt
->Settings
.Headless
)
617 /* Act as if it exists regardless */
618 DevExt
->KeyboardExists
= TRUE
;
620 DPRINT("Keyboard port detected\n");
621 DevExt
->KeyboardExists
= I8042DetectKeyboard(DevExt
);
624 if (DevExt
->KeyboardExists
) {
625 DPRINT("Keyboard detected\n");
626 I8042KeyboardEnable(DevExt
);
627 I8042KeyboardEnableInterrupt(DevExt
);
630 if (DevExt
->MouseExists
) {
631 DPRINT("Mouse detected\n");
632 I8042MouseEnable(DevExt
);
635 return STATUS_SUCCESS
;
640 IN PCWSTR PortTypeName
,
641 IN PUNICODE_STRING DeviceName
,
642 IN PCWSTR RegistryPath
)
644 UNICODE_STRING PathU
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
645 OBJECT_ATTRIBUTES ObjectAttributes
;
646 HANDLE hDeviceMapKey
= (HANDLE
)-1;
647 HANDLE hPortKey
= (HANDLE
)-1;
648 UNICODE_STRING PortTypeNameU
;
651 InitializeObjectAttributes(&ObjectAttributes
, &PathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
652 Status
= ZwOpenKey(&hDeviceMapKey
, 0, &ObjectAttributes
);
653 if (!NT_SUCCESS(Status
))
655 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
659 RtlInitUnicodeString(&PortTypeNameU
, PortTypeName
);
660 InitializeObjectAttributes(&ObjectAttributes
, &PortTypeNameU
, OBJ_KERNEL_HANDLE
, hDeviceMapKey
, NULL
);
661 Status
= ZwCreateKey(&hPortKey
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
662 if (!NT_SUCCESS(Status
))
664 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
668 Status
= ZwSetValueKey(hPortKey
, DeviceName
, 0, REG_SZ
, (PVOID
)RegistryPath
, wcslen(RegistryPath
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
669 if (!NT_SUCCESS(Status
))
671 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
675 Status
= STATUS_SUCCESS
;
678 if (hDeviceMapKey
!= (HANDLE
)-1)
679 ZwClose(hDeviceMapKey
);
680 if (hPortKey
!= (HANDLE
)-1)
685 static NTSTATUS STDCALL
I8042AddDevice(PDRIVER_OBJECT DriverObject
,
688 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\KeyboardPort8042");
689 UNICODE_STRING MouseName
= RTL_CONSTANT_STRING(L
"\\Device\\PointerPort8042");
690 ULONG MappedIrqKeyboard
= 0, MappedIrqMouse
= 0;
691 KIRQL DirqlKeyboard
= 0;
692 KIRQL DirqlMouse
= 0;
696 PDEVICE_EXTENSION DevExt
;
697 PFDO_DEVICE_EXTENSION FdoDevExt
;
700 DPRINT("I8042AddDevice\n");
704 /* Device detected by pnpmgr. Ignore it, as we already have
705 * detected the keyboard and mouse at first call */
706 return STATUS_UNSUCCESSFUL
;
709 Status
= IoCreateDevice(DriverObject
,
710 sizeof(DEVICE_EXTENSION
),
712 FILE_DEVICE_8042_PORT
,
713 FILE_DEVICE_SECURE_OPEN
,
717 if (!NT_SUCCESS(Status
))
720 DevExt
= Fdo
->DeviceExtension
;
722 RtlZeroMemory(DevExt
, sizeof(DEVICE_EXTENSION
));
724 I8042ReadRegistry(DriverObject
, DevExt
);
726 KeInitializeSpinLock(&DevExt
->SpinLock
);
727 InitializeListHead(&DevExt
->BusDevices
);
729 KeInitializeDpc(&DevExt
->DpcKbd
,
733 KeInitializeDpc(&DevExt
->DpcMouse
,
734 I8042DpcRoutineMouse
,
737 KeInitializeDpc(&DevExt
->DpcMouseTimeout
,
738 I8042DpcRoutineMouseTimeout
,
741 KeInitializeTimer(&DevExt
->TimerMouseTimeout
);
743 Status
= I8042Initialize(DevExt
);
744 if (!NT_SUCCESS(STATUS_SUCCESS
)) {
745 DPRINT1("Initialization failure: %x\n", Status
);
749 if (DevExt
->KeyboardExists
) {
750 MappedIrqKeyboard
= HalGetInterruptVector(Internal
,
757 Status
= IoCreateDevice(DriverObject
,
758 sizeof(FDO_DEVICE_EXTENSION
),
760 FILE_DEVICE_8042_PORT
,
761 FILE_DEVICE_SECURE_OPEN
,
765 if (NT_SUCCESS(Status
))
767 AddRegistryEntry(L
"KeyboardPort", &DeviceName
, L
"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\i8042prt");
768 FdoDevExt
= Fdo
->DeviceExtension
;
770 RtlZeroMemory(FdoDevExt
, sizeof(FDO_DEVICE_EXTENSION
));
772 FdoDevExt
->PortDevExt
= DevExt
;
773 FdoDevExt
->Type
= Keyboard
;
774 FdoDevExt
->DeviceObject
= Fdo
;
776 Fdo
->Flags
|= DO_BUFFERED_IO
;
778 DevExt
->DebugWorkItem
= IoAllocateWorkItem(Fdo
);
779 DevExt
->KeyboardObject
= Fdo
;
781 DevExt
->KeyboardBuffer
= ExAllocatePoolWithTag(
783 DevExt
->KeyboardAttributes
.InputDataQueueLength
*
784 sizeof(KEYBOARD_INPUT_DATA
),
787 if (!DevExt
->KeyboardBuffer
) {
788 DPRINT1("No memory for keyboardbuffer\n");
789 return STATUS_INSUFFICIENT_RESOURCES
;
792 InsertTailList(&DevExt
->BusDevices
, &FdoDevExt
->BusDevices
);
795 DevExt
->KeyboardExists
= FALSE
;
798 if (DevExt
->MouseExists
) {
799 MappedIrqMouse
= HalGetInterruptVector(Internal
,
806 Status
= IoCreateDevice(DriverObject
,
807 sizeof(FDO_DEVICE_EXTENSION
),
809 FILE_DEVICE_8042_PORT
,
810 FILE_DEVICE_SECURE_OPEN
,
814 if (NT_SUCCESS(Status
))
816 AddRegistryEntry(L
"PointerPort", &MouseName
, L
"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\i8042prt");
817 FdoDevExt
= Fdo
->DeviceExtension
;
819 RtlZeroMemory(FdoDevExt
, sizeof(FDO_DEVICE_EXTENSION
));
821 FdoDevExt
->PortDevExt
= DevExt
;
822 FdoDevExt
->Type
= Mouse
;
823 FdoDevExt
->DeviceObject
= Fdo
;
825 Fdo
->Flags
|= DO_BUFFERED_IO
;
826 DevExt
->MouseObject
= Fdo
;
828 DevExt
->MouseBuffer
= ExAllocatePoolWithTag(
830 DevExt
->MouseAttributes
.InputDataQueueLength
*
831 sizeof(MOUSE_INPUT_DATA
),
834 if (!DevExt
->MouseBuffer
) {
835 ExFreePoolWithTag(DevExt
->KeyboardBuffer
, TAG_I8042
);
836 DPRINT1("No memory for mouse buffer\n");
837 return STATUS_INSUFFICIENT_RESOURCES
;
840 InsertTailList(&DevExt
->BusDevices
, &FdoDevExt
->BusDevices
);
843 DevExt
->MouseExists
= FALSE
;
846 if (DirqlKeyboard
> DirqlMouse
)
847 DirqlMax
= DirqlKeyboard
;
849 DirqlMax
= DirqlMouse
;
851 if (DevExt
->KeyboardExists
) {
852 Status
= IoConnectInterrupt(&DevExt
->KeyboardInterruptObject
,
853 I8042InterruptServiceKbd
,
864 DPRINT("Keyboard Irq Status: %x\n", Status
);
867 if (DevExt
->MouseExists
) {
868 Status
= IoConnectInterrupt(&DevExt
->MouseInterruptObject
,
869 I8042InterruptServiceMouse
,
880 DPRINT("Mouse Irq Status: %x\n", Status
);
883 if (DirqlKeyboard
> DirqlMouse
)
884 DevExt
->HighestDIRQLInterrupt
= DevExt
->KeyboardInterruptObject
;
886 DevExt
->HighestDIRQLInterrupt
= DevExt
->MouseInterruptObject
;
888 DPRINT("I8042AddDevice done\n");
890 return(STATUS_SUCCESS
);
893 NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject
,
894 PUNICODE_STRING RegistryPath
)
896 * FUNCTION: Module entry point
899 DPRINT("I8042 Driver 0.0.1\n");
901 I8042RegistryPath
.MaximumLength
= RegistryPath
->Length
+ sizeof(L
"\\Parameters");
902 I8042RegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
903 I8042RegistryPath
.MaximumLength
,
905 if (I8042RegistryPath
.Buffer
== NULL
) {
907 return STATUS_INSUFFICIENT_RESOURCES
;
910 RtlCopyUnicodeString(&I8042RegistryPath
, RegistryPath
);
911 RtlAppendUnicodeToString(&I8042RegistryPath
, L
"\\Parameters");
912 I8042RegistryPath
.Buffer
[I8042RegistryPath
.Length
/ sizeof(WCHAR
)] = 0;
916 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = I8042CreateDispatch
;
917 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] =
918 I8042InternalDeviceControl
;
920 DriverObject
->DriverStartIo
= I8042StartIo
;
921 DriverObject
->DriverExtension
->AddDevice
= I8042AddDevice
;
923 return(STATUS_SUCCESS
);