2 * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/input/i8042prt/pnp.c
5 * PURPOSE: IRP_MJ_PNP operations
6 * PROGRAMMERS: Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
7 * Copyright 2008 Colin Finck (mail@colinfinck.de)
10 /* INCLUDES ******************************************************************/
14 /* FUNCTIONS *****************************************************************/
16 /* This is all pretty confusing. There's more than one way to
17 * disable/enable the keyboard. You can send KBD_ENABLE to the
18 * keyboard, and it will start scanning keys. Sending KBD_DISABLE
19 * will disable the key scanning but also reset the parameters to
22 * You can also send 0xAE to the controller for enabling the
23 * keyboard clock line and 0xAD for disabling it. Then it'll
24 * automatically get turned on at the next command. The last
25 * way is by modifying the bit that drives the clock line in the
26 * 'command byte' of the controller. This is almost, but not quite,
27 * the same as the AE/AD thing. The difference can be used to detect
28 * some really old broken keyboard controllers which I hope won't be
31 * We change the command byte, sending KBD_ENABLE/DISABLE seems to confuse
36 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
37 IN UCHAR FlagsToDisable
,
38 IN UCHAR FlagsToEnable
)
43 if (!i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, KBD_READ_MODE
))
45 WARN_(I8042PRT
, "Can't read i8042 mode\n");
49 Status
= i8042ReadDataWait(DeviceExtension
, &Value
);
50 if (!NT_SUCCESS(Status
))
52 WARN_(I8042PRT
, "No response after read i8042 mode\n");
56 Value
&= ~FlagsToDisable
;
57 Value
|= FlagsToEnable
;
59 if (!i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, KBD_WRITE_MODE
))
61 WARN_(I8042PRT
, "Can't set i8042 mode\n");
65 if (!i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, Value
))
67 WARN_(I8042PRT
, "Can't send i8042 mode\n");
76 IN PPORT_DEVICE_EXTENSION DeviceExtension
)
79 ULONG ResendIterations
;
82 /* Don't enable keyboard and mouse interrupts, disable keyboard/mouse */
83 if (!i8042ChangeMode(DeviceExtension
, CCB_KBD_INT_ENAB
| CCB_MOUSE_INT_ENAB
, CCB_KBD_DISAB
| CCB_MOUSE_DISAB
))
84 return STATUS_IO_DEVICE_ERROR
;
86 i8042Flush(DeviceExtension
);
88 ResendIterations
= DeviceExtension
->Settings
.ResendIterations
+ 1;
89 while (ResendIterations
--)
91 if (!i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, CTRL_SELF_TEST
))
93 WARN_(I8042PRT
, "Writing CTRL_SELF_TEST command failed\n");
94 return STATUS_IO_TIMEOUT
;
97 Status
= i8042ReadDataWait(DeviceExtension
, &Value
);
98 if (!NT_SUCCESS(Status
))
100 WARN_(I8042PRT
, "Failed to read CTRL_SELF_TEST response, status 0x%08lx\n", Status
);
104 if (Value
== KBD_SELF_TEST_OK
)
106 INFO_(I8042PRT
, "CTRL_SELF_TEST completed successfully!\n");
109 else if (Value
== KBD_RESEND
)
111 TRACE_(I8042PRT
, "Resending...\n", Value
);
112 KeStallExecutionProcessor(50);
116 WARN_(I8042PRT
, "Got 0x%02x instead of 0x55\n", Value
);
117 return STATUS_IO_DEVICE_ERROR
;
122 * We used to send a KBD_LINE_TEST (0xAB) command here, but on at least HP
123 * Pavilion notebooks the response to that command was incorrect.
124 * So now we just assume that a keyboard is attached.
126 DeviceExtension
->Flags
|= KEYBOARD_PRESENT
;
128 if (i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, MOUSE_LINE_TEST
))
130 Status
= i8042ReadDataWait(DeviceExtension
, &Value
);
131 if (NT_SUCCESS(Status
) && Value
== 0)
132 DeviceExtension
->Flags
|= MOUSE_PRESENT
;
135 if (IsFirstStageSetup())
136 /* Ignore the mouse */
137 DeviceExtension
->Flags
&= ~MOUSE_PRESENT
;
139 return STATUS_SUCCESS
;
144 IN PPORT_DEVICE_EXTENSION DeviceExtension
)
148 /* Set LEDs (that is not fatal if some error occurs) */
149 Status
= i8042SynchWritePort(DeviceExtension
, 0, KBD_CMD_SET_LEDS
, TRUE
);
150 if (NT_SUCCESS(Status
))
152 Status
= i8042SynchWritePort(DeviceExtension
, 0, 0, TRUE
);
153 if (!NT_SUCCESS(Status
))
155 WARN_(I8042PRT
, "Can't finish SET_LEDS (0x%08lx)\n", Status
);
161 WARN_(I8042PRT
, "Warning: can't write SET_LEDS (0x%08lx)\n", Status
);
164 /* Turn on translation and SF (Some machines don't reboot if SF is not set, see ReactOS bug #1842) */
165 if (!i8042ChangeMode(DeviceExtension
, 0, CCB_TRANSLATE
| CCB_SYSTEM_FLAG
))
168 INFO_(I8042PRT
, "Keyboard detected\n");
173 IN PPORT_DEVICE_EXTENSION DeviceExtension
)
177 UCHAR ExpectedReply
[] = { MOUSE_ACK
, 0xAA };
180 i8042Flush(DeviceExtension
);
182 if(!i8042IsrWritePort(DeviceExtension
, MOU_CMD_RESET
, CTRL_WRITE_MOUSE
))
184 WARN_(I8042PRT
, "Failed to write reset command to mouse\n");
188 /* The implementation of the "Mouse Reset" command differs much from chip to chip.
190 By default, the first byte is an ACK, when the mouse is plugged in and working and NACK when it's not.
191 On success, the next bytes are 0xAA and 0x00.
193 But on some systems (like ECS K7S5A Pro, SiS 735 chipset), we always get an ACK and 0xAA.
194 Only the last byte indicates, whether a mouse is plugged in.
195 It is either sent or not, so there is no byte, which indicates a failure here.
197 After the Mouse Reset command was issued, it usually takes some time until we get a response.
198 So get the first two bytes in a loop. */
200 ReplyByte
< sizeof(ExpectedReply
) / sizeof(ExpectedReply
[0]);
207 Status
= i8042ReadDataWait(DeviceExtension
, &Value
);
209 if(!NT_SUCCESS(Status
))
211 /* Wait some time before trying again */
212 KeStallExecutionProcessor(50);
214 } while (Status
== STATUS_IO_TIMEOUT
&& Counter
--);
216 if (!NT_SUCCESS(Status
))
218 WARN_(I8042PRT
, "No ACK after mouse reset, status 0x%08lx\n", Status
);
221 else if (Value
!= ExpectedReply
[ReplyByte
])
223 WARN_(I8042PRT
, "Unexpected reply: 0x%02x (expected 0x%02x)\n", Value
, ExpectedReply
[ReplyByte
]);
228 /* Finally get the third byte, but only try it one time (see above).
229 Otherwise this takes around 45 seconds on a K7S5A Pro, when no mouse is plugged in. */
230 Status
= i8042ReadDataWait(DeviceExtension
, &Value
);
232 if(!NT_SUCCESS(Status
))
234 WARN_(I8042PRT
, "Last byte was not transmitted after mouse reset, status 0x%08lx\n", Status
);
237 else if(Value
!= 0x00)
239 WARN_(I8042PRT
, "Last byte after mouse reset was not 0x00, but 0x%02x\n", Value
);
243 INFO_(I8042PRT
, "Mouse detected\n");
247 /* There is probably no mouse present. On some systems,
248 the probe locks the entire keyboard controller. Let's
249 try to get access to the keyboard again by sending a
251 i8042Flush(DeviceExtension
);
252 i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, CTRL_SELF_TEST
);
253 i8042ReadDataWait(DeviceExtension
, &Value
);
254 i8042Flush(DeviceExtension
);
256 INFO_(I8042PRT
, "Mouse not detected\n");
260 i8042ConnectKeyboardInterrupt(
261 IN PI8042_KEYBOARD_EXTENSION DeviceExtension
)
263 PPORT_DEVICE_EXTENSION PortDeviceExtension
;
267 TRACE_(I8042PRT
, "i8042ConnectKeyboardInterrupt()\n");
269 PortDeviceExtension
= DeviceExtension
->Common
.PortDeviceExtension
;
271 PortDeviceExtension
->KeyboardInterrupt
.Dirql
,
272 PortDeviceExtension
->MouseInterrupt
.Dirql
);
274 INFO_(I8042PRT
, "KeyboardInterrupt.Vector %lu\n",
275 PortDeviceExtension
->KeyboardInterrupt
.Vector
);
276 INFO_(I8042PRT
, "KeyboardInterrupt.Dirql %lu\n",
277 PortDeviceExtension
->KeyboardInterrupt
.Dirql
);
278 INFO_(I8042PRT
, "KeyboardInterrupt.DirqlMax %lu\n",
280 INFO_(I8042PRT
, "KeyboardInterrupt.InterruptMode %s\n",
281 PortDeviceExtension
->KeyboardInterrupt
.InterruptMode
== LevelSensitive
? "LevelSensitive" : "Latched");
282 INFO_(I8042PRT
, "KeyboardInterrupt.ShareInterrupt %s\n",
283 PortDeviceExtension
->KeyboardInterrupt
.ShareInterrupt
? "yes" : "no");
284 INFO_(I8042PRT
, "KeyboardInterrupt.Affinity 0x%lx\n",
285 PortDeviceExtension
->KeyboardInterrupt
.Affinity
);
286 Status
= IoConnectInterrupt(
287 &PortDeviceExtension
->KeyboardInterrupt
.Object
,
288 i8042KbdInterruptService
,
289 DeviceExtension
, &PortDeviceExtension
->SpinLock
,
290 PortDeviceExtension
->KeyboardInterrupt
.Vector
, PortDeviceExtension
->KeyboardInterrupt
.Dirql
, DirqlMax
,
291 PortDeviceExtension
->KeyboardInterrupt
.InterruptMode
, PortDeviceExtension
->KeyboardInterrupt
.ShareInterrupt
,
292 PortDeviceExtension
->KeyboardInterrupt
.Affinity
, FALSE
);
293 if (!NT_SUCCESS(Status
))
295 WARN_(I8042PRT
, "IoConnectInterrupt() failed with status 0x%08x\n", Status
);
299 if (DirqlMax
== PortDeviceExtension
->KeyboardInterrupt
.Dirql
)
300 PortDeviceExtension
->HighestDIRQLInterrupt
= PortDeviceExtension
->KeyboardInterrupt
.Object
;
301 PortDeviceExtension
->Flags
|= KEYBOARD_INITIALIZED
;
302 return STATUS_SUCCESS
;
306 i8042ConnectMouseInterrupt(
307 IN PI8042_MOUSE_EXTENSION DeviceExtension
)
309 PPORT_DEVICE_EXTENSION PortDeviceExtension
;
313 TRACE_(I8042PRT
, "i8042ConnectMouseInterrupt()\n");
315 Status
= i8042MouInitialize(DeviceExtension
);
316 if (!NT_SUCCESS(Status
))
319 PortDeviceExtension
= DeviceExtension
->Common
.PortDeviceExtension
;
321 PortDeviceExtension
->KeyboardInterrupt
.Dirql
,
322 PortDeviceExtension
->MouseInterrupt
.Dirql
);
324 INFO_(I8042PRT
, "MouseInterrupt.Vector %lu\n",
325 PortDeviceExtension
->MouseInterrupt
.Vector
);
326 INFO_(I8042PRT
, "MouseInterrupt.Dirql %lu\n",
327 PortDeviceExtension
->MouseInterrupt
.Dirql
);
328 INFO_(I8042PRT
, "MouseInterrupt.DirqlMax %lu\n",
330 INFO_(I8042PRT
, "MouseInterrupt.InterruptMode %s\n",
331 PortDeviceExtension
->MouseInterrupt
.InterruptMode
== LevelSensitive
? "LevelSensitive" : "Latched");
332 INFO_(I8042PRT
, "MouseInterrupt.ShareInterrupt %s\n",
333 PortDeviceExtension
->MouseInterrupt
.ShareInterrupt
? "yes" : "no");
334 INFO_(I8042PRT
, "MouseInterrupt.Affinity 0x%lx\n",
335 PortDeviceExtension
->MouseInterrupt
.Affinity
);
336 Status
= IoConnectInterrupt(
337 &PortDeviceExtension
->MouseInterrupt
.Object
,
338 i8042MouInterruptService
,
339 DeviceExtension
, &PortDeviceExtension
->SpinLock
,
340 PortDeviceExtension
->MouseInterrupt
.Vector
, PortDeviceExtension
->MouseInterrupt
.Dirql
, DirqlMax
,
341 PortDeviceExtension
->MouseInterrupt
.InterruptMode
, PortDeviceExtension
->MouseInterrupt
.ShareInterrupt
,
342 PortDeviceExtension
->MouseInterrupt
.Affinity
, FALSE
);
343 if (!NT_SUCCESS(Status
))
345 WARN_(I8042PRT
, "IoConnectInterrupt() failed with status 0x%08x\n", Status
);
349 if (DirqlMax
== PortDeviceExtension
->MouseInterrupt
.Dirql
)
350 PortDeviceExtension
->HighestDIRQLInterrupt
= PortDeviceExtension
->MouseInterrupt
.Object
;
352 PortDeviceExtension
->Flags
|= MOUSE_INITIALIZED
;
353 Status
= STATUS_SUCCESS
;
356 if (!NT_SUCCESS(Status
))
358 PortDeviceExtension
->Flags
&= ~MOUSE_INITIALIZED
;
359 if (PortDeviceExtension
->MouseInterrupt
.Object
)
361 IoDisconnectInterrupt(PortDeviceExtension
->MouseInterrupt
.Object
);
362 PortDeviceExtension
->HighestDIRQLInterrupt
= PortDeviceExtension
->KeyboardInterrupt
.Object
;
370 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
371 IN UCHAR FlagsToDisable
,
372 IN UCHAR FlagsToEnable
)
374 i8042Flush(DeviceExtension
);
376 if (!i8042ChangeMode(DeviceExtension
, FlagsToDisable
, FlagsToEnable
))
377 return STATUS_UNSUCCESSFUL
;
379 /* Reset the mouse (if any) to start the detection */
380 if (DeviceExtension
->Flags
& MOUSE_PRESENT
)
384 Irql
= KeAcquireInterruptSpinLock(DeviceExtension
->HighestDIRQLInterrupt
);
385 i8042IsrWritePort(DeviceExtension
, MOU_CMD_RESET
, CTRL_WRITE_MOUSE
);
386 KeReleaseInterruptSpinLock(DeviceExtension
->HighestDIRQLInterrupt
, Irql
);
389 return STATUS_SUCCESS
;
394 IN PPORT_DEVICE_EXTENSION DeviceExtension
)
397 UCHAR FlagsToDisable
= 0;
398 UCHAR FlagsToEnable
= 0;
400 if (DeviceExtension
->DataPort
== 0)
402 /* Unable to do something at the moment */
403 return STATUS_SUCCESS
;
406 if (!(DeviceExtension
->Flags
& (KEYBOARD_PRESENT
| MOUSE_PRESENT
)))
408 /* Try to detect them */
409 TRACE_(I8042PRT
, "Check if the controller is really a i8042\n");
410 Status
= i8042BasicDetect(DeviceExtension
);
411 if (!NT_SUCCESS(Status
))
413 WARN_(I8042PRT
, "i8042BasicDetect() failed with status 0x%08lx\n", Status
);
414 return STATUS_UNSUCCESSFUL
;
417 /* First detect the mouse and then the keyboard!
418 If we do it the other way round, some systems throw away settings like the keyboard translation, when detecting the mouse. */
419 TRACE_(I8042PRT
, "Detecting mouse\n");
420 i8042DetectMouse(DeviceExtension
);
422 TRACE_(I8042PRT
, "Detecting keyboard\n");
423 i8042DetectKeyboard(DeviceExtension
);
425 INFO_(I8042PRT
, "Keyboard present: %s\n", DeviceExtension
->Flags
& KEYBOARD_PRESENT
? "YES" : "NO");
426 INFO_(I8042PRT
, "Mouse present : %s\n", DeviceExtension
->Flags
& MOUSE_PRESENT
? "YES" : "NO");
429 /* Connect interrupts */
430 if (DeviceExtension
->Flags
& KEYBOARD_PRESENT
&&
431 DeviceExtension
->Flags
& KEYBOARD_CONNECTED
&&
432 DeviceExtension
->Flags
& KEYBOARD_STARTED
&&
433 !(DeviceExtension
->Flags
& KEYBOARD_INITIALIZED
))
435 /* Keyboard is ready to be initialized */
436 Status
= i8042ConnectKeyboardInterrupt(DeviceExtension
->KeyboardExtension
);
437 if (NT_SUCCESS(Status
))
439 DeviceExtension
->Flags
|= KEYBOARD_INITIALIZED
;
440 FlagsToDisable
|= CCB_KBD_DISAB
;
441 FlagsToEnable
|= CCB_KBD_INT_ENAB
;
445 if (DeviceExtension
->Flags
& MOUSE_PRESENT
&&
446 DeviceExtension
->Flags
& MOUSE_CONNECTED
&&
447 DeviceExtension
->Flags
& MOUSE_STARTED
&&
448 !(DeviceExtension
->Flags
& MOUSE_INITIALIZED
))
450 /* Mouse is ready to be initialized */
451 Status
= i8042ConnectMouseInterrupt(DeviceExtension
->MouseExtension
);
452 if (NT_SUCCESS(Status
))
454 DeviceExtension
->Flags
|= MOUSE_INITIALIZED
;
455 FlagsToDisable
|= CCB_MOUSE_DISAB
;
456 FlagsToEnable
|= CCB_MOUSE_INT_ENAB
;
461 Status
= EnableInterrupts(DeviceExtension
, FlagsToDisable
, FlagsToEnable
);
463 Status
= STATUS_SUCCESS
;
470 IN PDEVICE_OBJECT DeviceObject
,
471 IN PCM_RESOURCE_LIST AllocatedResources
,
472 IN PCM_RESOURCE_LIST AllocatedResourcesTranslated
)
474 PFDO_DEVICE_EXTENSION DeviceExtension
;
475 PPORT_DEVICE_EXTENSION PortDeviceExtension
;
476 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
, ResourceDescriptorTranslated
;
477 INTERRUPT_DATA InterruptData
;
478 BOOLEAN FoundDataPort
= FALSE
;
479 BOOLEAN FoundControlPort
= FALSE
;
480 BOOLEAN FoundIrq
= FALSE
;
484 TRACE_(I8042PRT
, "i8042PnpStartDevice(%p)\n", DeviceObject
);
485 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
486 PortDeviceExtension
= DeviceExtension
->PortDeviceExtension
;
488 ASSERT(DeviceExtension
->PnpState
== dsStopped
);
490 if (!AllocatedResources
)
492 WARN_(I8042PRT
, "No allocated resources sent to driver\n");
493 return STATUS_INSUFFICIENT_RESOURCES
;
495 if (AllocatedResources
->Count
!= 1)
497 WARN_(I8042PRT
, "Wrong number of allocated resources sent to driver\n");
498 return STATUS_INSUFFICIENT_RESOURCES
;
500 if (AllocatedResources
->List
[0].PartialResourceList
.Version
!= 1
501 || AllocatedResources
->List
[0].PartialResourceList
.Revision
!= 1
502 || AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Version
!= 1
503 || AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Revision
!= 1)
505 WARN_(I8042PRT
, "Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
506 AllocatedResources
->List
[0].PartialResourceList
.Version
,
507 AllocatedResources
->List
[0].PartialResourceList
.Revision
,
508 AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Version
,
509 AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Revision
);
510 return STATUS_REVISION_MISMATCH
;
513 /* Get Irq and optionally control port and data port */
514 for (i
= 0; i
< AllocatedResources
->List
[0].PartialResourceList
.Count
; i
++)
516 ResourceDescriptor
= &AllocatedResources
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
517 ResourceDescriptorTranslated
= &AllocatedResourcesTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
518 switch (ResourceDescriptor
->Type
)
520 case CmResourceTypePort
:
522 if (ResourceDescriptor
->u
.Port
.Length
== 1)
524 /* We assume that the first ressource will
525 * be the control port and the second one
526 * will be the data port...
530 PortDeviceExtension
->DataPort
= ULongToPtr(ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
);
531 INFO_(I8042PRT
, "Found data port: %p\n", PortDeviceExtension
->DataPort
);
532 FoundDataPort
= TRUE
;
534 else if (!FoundControlPort
)
536 PortDeviceExtension
->ControlPort
= ULongToPtr(ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
);
537 INFO_(I8042PRT
, "Found control port: %p\n", PortDeviceExtension
->ControlPort
);
538 FoundControlPort
= TRUE
;
542 WARN_(I8042PRT
, "Too much I/O ranges provided: 0x%lx\n", ResourceDescriptor
->u
.Port
.Length
);
543 return STATUS_INVALID_PARAMETER
;
547 WARN_(I8042PRT
, "Invalid I/O range length: 0x%lx\n", ResourceDescriptor
->u
.Port
.Length
);
550 case CmResourceTypeInterrupt
:
553 return STATUS_INVALID_PARAMETER
;
554 InterruptData
.Dirql
= (KIRQL
)ResourceDescriptorTranslated
->u
.Interrupt
.Level
;
555 InterruptData
.Vector
= ResourceDescriptorTranslated
->u
.Interrupt
.Vector
;
556 InterruptData
.Affinity
= ResourceDescriptorTranslated
->u
.Interrupt
.Affinity
;
557 if (ResourceDescriptorTranslated
->Flags
& CM_RESOURCE_INTERRUPT_LATCHED
)
558 InterruptData
.InterruptMode
= Latched
;
560 InterruptData
.InterruptMode
= LevelSensitive
;
561 InterruptData
.ShareInterrupt
= (ResourceDescriptorTranslated
->ShareDisposition
== CmResourceShareShared
);
562 INFO_(I8042PRT
, "Found irq resource: %lu\n", ResourceDescriptor
->u
.Interrupt
.Level
);
567 WARN_(I8042PRT
, "Unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
573 WARN_(I8042PRT
, "Interrupt resource was not found in allocated resources list\n");
574 return STATUS_INSUFFICIENT_RESOURCES
;
576 else if (DeviceExtension
->Type
== Keyboard
&& (!FoundDataPort
|| !FoundControlPort
))
578 WARN_(I8042PRT
, "Some required resources were not found in allocated resources list\n");
579 return STATUS_INSUFFICIENT_RESOURCES
;
581 else if (DeviceExtension
->Type
== Mouse
&& (FoundDataPort
|| FoundControlPort
))
583 WARN_(I8042PRT
, "Too much resources were provided in allocated resources list\n");
584 return STATUS_INVALID_PARAMETER
;
587 switch (DeviceExtension
->Type
)
592 &PortDeviceExtension
->KeyboardInterrupt
,
594 sizeof(INTERRUPT_DATA
));
595 PortDeviceExtension
->Flags
|= KEYBOARD_STARTED
;
596 Status
= StartProcedure(PortDeviceExtension
);
602 &PortDeviceExtension
->MouseInterrupt
,
604 sizeof(INTERRUPT_DATA
));
605 PortDeviceExtension
->Flags
|= MOUSE_STARTED
;
606 Status
= StartProcedure(PortDeviceExtension
);
611 ERR_(I8042PRT
, "Unknown FDO type %u\n", DeviceExtension
->Type
);
613 Status
= STATUS_INVALID_DEVICE_REQUEST
;
617 if (NT_SUCCESS(Status
))
618 DeviceExtension
->PnpState
= dsStarted
;
625 IN PDEVICE_OBJECT DeviceObject
,
628 PIO_STACK_LOCATION Stack
;
630 I8042_DEVICE_TYPE DeviceType
;
631 ULONG_PTR Information
= 0;
634 Stack
= IoGetCurrentIrpStackLocation(Irp
);
635 MinorFunction
= Stack
->MinorFunction
;
636 DeviceType
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->Type
;
638 switch (MinorFunction
)
640 case IRP_MN_START_DEVICE
: /* 0x00 */
642 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
644 /* Call lower driver (if any) */
645 if (DeviceType
!= PhysicalDeviceObject
)
647 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
648 if (NT_SUCCESS(Status
))
649 Status
= i8042PnpStartDevice(
651 Stack
->Parameters
.StartDevice
.AllocatedResources
,
652 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
);
655 Status
= STATUS_SUCCESS
;
658 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* (optional) 0x07 */
660 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
664 PDEVICE_RELATIONS DeviceRelations
;
666 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
667 DeviceRelations
= ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), I8042PRT_TAG
);
670 DeviceRelations
->Count
= 0;
671 Information
= (ULONG_PTR
)DeviceRelations
;
672 Status
= STATUS_SUCCESS
;
675 Status
= STATUS_INSUFFICIENT_RESOURCES
;
678 case RemovalRelations
:
680 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
681 return ForwardIrpAndForget(DeviceObject
, Irp
);
684 ERR_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
685 Stack
->Parameters
.QueryDeviceRelations
.Type
);
687 return ForwardIrpAndForget(DeviceObject
, Irp
);
691 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* (optional) 0x0d */
693 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
695 Status
= Irp
->IoStatus
.Status
;
700 ERR_(I8042PRT
, "IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction
);
702 return ForwardIrpAndForget(DeviceObject
, Irp
);
706 Irp
->IoStatus
.Information
= Information
;
707 Irp
->IoStatus
.Status
= Status
;
708 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);