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
;
416 TRACE_(I8042PRT
, "Detecting keyboard\n");
417 i8042DetectKeyboard(DeviceExtension
);
419 TRACE_(I8042PRT
, "Detecting mouse\n");
420 i8042DetectMouse(DeviceExtension
);
422 INFO_(I8042PRT
, "Keyboard present: %s\n", DeviceExtension
->Flags
& KEYBOARD_PRESENT
? "YES" : "NO");
423 INFO_(I8042PRT
, "Mouse present : %s\n", DeviceExtension
->Flags
& MOUSE_PRESENT
? "YES" : "NO");
426 /* Connect interrupts */
427 if (DeviceExtension
->Flags
& KEYBOARD_PRESENT
&&
428 DeviceExtension
->Flags
& KEYBOARD_CONNECTED
&&
429 DeviceExtension
->Flags
& KEYBOARD_STARTED
&&
430 !(DeviceExtension
->Flags
& KEYBOARD_INITIALIZED
))
432 /* Keyboard is ready to be initialized */
433 Status
= i8042ConnectKeyboardInterrupt(DeviceExtension
->KeyboardExtension
);
434 if (NT_SUCCESS(Status
))
436 DeviceExtension
->Flags
|= KEYBOARD_INITIALIZED
;
437 FlagsToDisable
|= CCB_KBD_DISAB
;
438 FlagsToEnable
|= CCB_KBD_INT_ENAB
;
442 if (DeviceExtension
->Flags
& MOUSE_PRESENT
&&
443 DeviceExtension
->Flags
& MOUSE_CONNECTED
&&
444 DeviceExtension
->Flags
& MOUSE_STARTED
&&
445 !(DeviceExtension
->Flags
& MOUSE_INITIALIZED
))
447 /* Mouse is ready to be initialized */
448 Status
= i8042ConnectMouseInterrupt(DeviceExtension
->MouseExtension
);
449 if (NT_SUCCESS(Status
))
451 DeviceExtension
->Flags
|= MOUSE_INITIALIZED
;
452 FlagsToDisable
|= CCB_MOUSE_DISAB
;
453 FlagsToEnable
|= CCB_MOUSE_INT_ENAB
;
458 Status
= EnableInterrupts(DeviceExtension
, FlagsToDisable
, FlagsToEnable
);
460 Status
= STATUS_SUCCESS
;
467 IN PDEVICE_OBJECT DeviceObject
,
468 IN PCM_RESOURCE_LIST AllocatedResources
,
469 IN PCM_RESOURCE_LIST AllocatedResourcesTranslated
)
471 PFDO_DEVICE_EXTENSION DeviceExtension
;
472 PPORT_DEVICE_EXTENSION PortDeviceExtension
;
473 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
, ResourceDescriptorTranslated
;
474 INTERRUPT_DATA InterruptData
;
475 BOOLEAN FoundDataPort
= FALSE
;
476 BOOLEAN FoundControlPort
= FALSE
;
477 BOOLEAN FoundIrq
= FALSE
;
481 TRACE_(I8042PRT
, "i8042PnpStartDevice(%p)\n", DeviceObject
);
482 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
483 PortDeviceExtension
= DeviceExtension
->PortDeviceExtension
;
485 ASSERT(DeviceExtension
->PnpState
== dsStopped
);
487 if (!AllocatedResources
)
489 WARN_(I8042PRT
, "No allocated resources sent to driver\n");
490 return STATUS_INSUFFICIENT_RESOURCES
;
492 if (AllocatedResources
->Count
!= 1)
494 WARN_(I8042PRT
, "Wrong number of allocated resources sent to driver\n");
495 return STATUS_INSUFFICIENT_RESOURCES
;
497 if (AllocatedResources
->List
[0].PartialResourceList
.Version
!= 1
498 || AllocatedResources
->List
[0].PartialResourceList
.Revision
!= 1
499 || AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Version
!= 1
500 || AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Revision
!= 1)
502 WARN_(I8042PRT
, "Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
503 AllocatedResources
->List
[0].PartialResourceList
.Version
,
504 AllocatedResources
->List
[0].PartialResourceList
.Revision
,
505 AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Version
,
506 AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Revision
);
507 return STATUS_REVISION_MISMATCH
;
510 /* Get Irq and optionally control port and data port */
511 for (i
= 0; i
< AllocatedResources
->List
[0].PartialResourceList
.Count
; i
++)
513 ResourceDescriptor
= &AllocatedResources
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
514 ResourceDescriptorTranslated
= &AllocatedResourcesTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
515 switch (ResourceDescriptor
->Type
)
517 case CmResourceTypePort
:
519 if (ResourceDescriptor
->u
.Port
.Length
== 1)
521 /* We assume that the first ressource will
522 * be the control port and the second one
523 * will be the data port...
527 PortDeviceExtension
->DataPort
= ULongToPtr(ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
);
528 INFO_(I8042PRT
, "Found data port: %p\n", PortDeviceExtension
->DataPort
);
529 FoundDataPort
= TRUE
;
531 else if (!FoundControlPort
)
533 PortDeviceExtension
->ControlPort
= ULongToPtr(ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
);
534 INFO_(I8042PRT
, "Found control port: %p\n", PortDeviceExtension
->ControlPort
);
535 FoundControlPort
= TRUE
;
539 WARN_(I8042PRT
, "Too much I/O ranges provided: 0x%lx\n", ResourceDescriptor
->u
.Port
.Length
);
540 return STATUS_INVALID_PARAMETER
;
544 WARN_(I8042PRT
, "Invalid I/O range length: 0x%lx\n", ResourceDescriptor
->u
.Port
.Length
);
547 case CmResourceTypeInterrupt
:
550 return STATUS_INVALID_PARAMETER
;
551 InterruptData
.Dirql
= (KIRQL
)ResourceDescriptorTranslated
->u
.Interrupt
.Level
;
552 InterruptData
.Vector
= ResourceDescriptorTranslated
->u
.Interrupt
.Vector
;
553 InterruptData
.Affinity
= ResourceDescriptorTranslated
->u
.Interrupt
.Affinity
;
554 if (ResourceDescriptorTranslated
->Flags
& CM_RESOURCE_INTERRUPT_LATCHED
)
555 InterruptData
.InterruptMode
= Latched
;
557 InterruptData
.InterruptMode
= LevelSensitive
;
558 InterruptData
.ShareInterrupt
= (ResourceDescriptorTranslated
->ShareDisposition
== CmResourceShareShared
);
559 INFO_(I8042PRT
, "Found irq resource: %lu\n", ResourceDescriptor
->u
.Interrupt
.Level
);
564 WARN_(I8042PRT
, "Unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
570 WARN_(I8042PRT
, "Interrupt resource was not found in allocated resources list\n");
571 return STATUS_INSUFFICIENT_RESOURCES
;
573 else if (DeviceExtension
->Type
== Keyboard
&& (!FoundDataPort
|| !FoundControlPort
))
575 WARN_(I8042PRT
, "Some required resources were not found in allocated resources list\n");
576 return STATUS_INSUFFICIENT_RESOURCES
;
578 else if (DeviceExtension
->Type
== Mouse
&& (FoundDataPort
|| FoundControlPort
))
580 WARN_(I8042PRT
, "Too much resources were provided in allocated resources list\n");
581 return STATUS_INVALID_PARAMETER
;
584 switch (DeviceExtension
->Type
)
589 &PortDeviceExtension
->KeyboardInterrupt
,
591 sizeof(INTERRUPT_DATA
));
592 PortDeviceExtension
->Flags
|= KEYBOARD_STARTED
;
593 Status
= StartProcedure(PortDeviceExtension
);
599 &PortDeviceExtension
->MouseInterrupt
,
601 sizeof(INTERRUPT_DATA
));
602 PortDeviceExtension
->Flags
|= MOUSE_STARTED
;
603 Status
= StartProcedure(PortDeviceExtension
);
608 ERR_(I8042PRT
, "Unknown FDO type %u\n", DeviceExtension
->Type
);
610 Status
= STATUS_INVALID_DEVICE_REQUEST
;
614 if (NT_SUCCESS(Status
))
615 DeviceExtension
->PnpState
= dsStarted
;
622 IN PDEVICE_OBJECT DeviceObject
,
625 PIO_STACK_LOCATION Stack
;
627 I8042_DEVICE_TYPE DeviceType
;
628 ULONG_PTR Information
= 0;
631 Stack
= IoGetCurrentIrpStackLocation(Irp
);
632 MinorFunction
= Stack
->MinorFunction
;
633 DeviceType
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->Type
;
635 switch (MinorFunction
)
637 case IRP_MN_START_DEVICE
: /* 0x00 */
639 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
641 /* Call lower driver (if any) */
642 if (DeviceType
!= PhysicalDeviceObject
)
644 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
645 if (NT_SUCCESS(Status
))
646 Status
= i8042PnpStartDevice(
648 Stack
->Parameters
.StartDevice
.AllocatedResources
,
649 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
);
652 Status
= STATUS_SUCCESS
;
655 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* (optional) 0x07 */
657 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
661 PDEVICE_RELATIONS DeviceRelations
;
663 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
664 DeviceRelations
= ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), I8042PRT_TAG
);
667 DeviceRelations
->Count
= 0;
668 Information
= (ULONG_PTR
)DeviceRelations
;
669 Status
= STATUS_SUCCESS
;
672 Status
= STATUS_INSUFFICIENT_RESOURCES
;
675 case RemovalRelations
:
677 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
678 return ForwardIrpAndForget(DeviceObject
, Irp
);
681 ERR_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
682 Stack
->Parameters
.QueryDeviceRelations
.Type
);
684 return ForwardIrpAndForget(DeviceObject
, Irp
);
688 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* (optional) 0x0d */
690 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
692 Status
= Irp
->IoStatus
.Status
;
697 ERR_(I8042PRT
, "IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction
);
699 return ForwardIrpAndForget(DeviceObject
, Irp
);
703 Irp
->IoStatus
.Information
= Information
;
704 Irp
->IoStatus
.Status
= Status
;
705 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);