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 (!i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, CTRL_WRITE_MOUSE
)
183 ||!i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, MOU_CMD_RESET
))
185 WARN_(I8042PRT
, "Failed to write reset command to mouse\n");
189 /* The implementation of the "Mouse Reset" command differs much from chip to chip.
191 By default, the first byte is an ACK, when the mouse is plugged in and working and NACK when it's not.
192 On success, the next bytes are 0xAA and 0x00.
194 But on some systems (like ECS K7S5A Pro, SiS 735 chipset), we always get an ACK and 0xAA.
195 Only the last byte indicates, whether a mouse is plugged in.
196 It is either sent or not, so there is no byte, which indicates a failure here.
198 After the Mouse Reset command was issued, it usually takes some time until we get a response.
199 So get the first two bytes in a loop. */
201 ReplyByte
< sizeof(ExpectedReply
) / sizeof(ExpectedReply
[0]);
208 Status
= i8042ReadDataWait(DeviceExtension
, &Value
);
210 if(!NT_SUCCESS(Status
))
212 /* Wait some time before trying again */
213 KeStallExecutionProcessor(50);
215 } while (Status
== STATUS_IO_TIMEOUT
&& Counter
--);
217 if (!NT_SUCCESS(Status
))
219 WARN_(I8042PRT
, "No ACK after mouse reset, status 0x%08lx\n", Status
);
222 else if (Value
!= ExpectedReply
[ReplyByte
])
224 WARN_(I8042PRT
, "Unexpected reply: 0x%02x (expected 0x%02x)\n", Value
, ExpectedReply
[ReplyByte
]);
229 /* Finally get the third byte, but only try it one time (see above).
230 Otherwise this takes around 45 seconds on a K7S5A Pro, when no mouse is plugged in. */
231 Status
= i8042ReadDataWait(DeviceExtension
, &Value
);
233 if(!NT_SUCCESS(Status
))
235 WARN_(I8042PRT
, "Last byte was not transmitted after mouse reset, status 0x%08lx\n", Status
);
238 else if(Value
!= 0x00)
240 WARN_(I8042PRT
, "Last byte after mouse reset was not 0x00, but 0x%02x\n", Value
);
244 INFO_(I8042PRT
, "Mouse detected\n");
248 /* There is probably no mouse present. On some systems,
249 the probe locks the entire keyboard controller. Let's
250 try to get access to the keyboard again by sending a
252 i8042Flush(DeviceExtension
);
253 i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, CTRL_SELF_TEST
);
254 i8042ReadDataWait(DeviceExtension
, &Value
);
255 i8042Flush(DeviceExtension
);
257 INFO_(I8042PRT
, "Mouse not detected\n");
261 i8042ConnectKeyboardInterrupt(
262 IN PI8042_KEYBOARD_EXTENSION DeviceExtension
)
264 PPORT_DEVICE_EXTENSION PortDeviceExtension
;
268 TRACE_(I8042PRT
, "i8042ConnectKeyboardInterrupt()\n");
270 PortDeviceExtension
= DeviceExtension
->Common
.PortDeviceExtension
;
272 PortDeviceExtension
->KeyboardInterrupt
.Dirql
,
273 PortDeviceExtension
->MouseInterrupt
.Dirql
);
275 INFO_(I8042PRT
, "KeyboardInterrupt.Vector %lu\n",
276 PortDeviceExtension
->KeyboardInterrupt
.Vector
);
277 INFO_(I8042PRT
, "KeyboardInterrupt.Dirql %lu\n",
278 PortDeviceExtension
->KeyboardInterrupt
.Dirql
);
279 INFO_(I8042PRT
, "KeyboardInterrupt.DirqlMax %lu\n",
281 INFO_(I8042PRT
, "KeyboardInterrupt.InterruptMode %s\n",
282 PortDeviceExtension
->KeyboardInterrupt
.InterruptMode
== LevelSensitive
? "LevelSensitive" : "Latched");
283 INFO_(I8042PRT
, "KeyboardInterrupt.ShareInterrupt %s\n",
284 PortDeviceExtension
->KeyboardInterrupt
.ShareInterrupt
? "yes" : "no");
285 INFO_(I8042PRT
, "KeyboardInterrupt.Affinity 0x%lx\n",
286 PortDeviceExtension
->KeyboardInterrupt
.Affinity
);
287 Status
= IoConnectInterrupt(
288 &PortDeviceExtension
->KeyboardInterrupt
.Object
,
289 i8042KbdInterruptService
,
290 DeviceExtension
, &PortDeviceExtension
->SpinLock
,
291 PortDeviceExtension
->KeyboardInterrupt
.Vector
, PortDeviceExtension
->KeyboardInterrupt
.Dirql
, DirqlMax
,
292 PortDeviceExtension
->KeyboardInterrupt
.InterruptMode
, PortDeviceExtension
->KeyboardInterrupt
.ShareInterrupt
,
293 PortDeviceExtension
->KeyboardInterrupt
.Affinity
, FALSE
);
294 if (!NT_SUCCESS(Status
))
296 WARN_(I8042PRT
, "IoConnectInterrupt() failed with status 0x%08x\n", Status
);
300 if (DirqlMax
== PortDeviceExtension
->KeyboardInterrupt
.Dirql
)
301 PortDeviceExtension
->HighestDIRQLInterrupt
= PortDeviceExtension
->KeyboardInterrupt
.Object
;
302 PortDeviceExtension
->Flags
|= KEYBOARD_INITIALIZED
;
303 return STATUS_SUCCESS
;
307 i8042ConnectMouseInterrupt(
308 IN PI8042_MOUSE_EXTENSION DeviceExtension
)
310 PPORT_DEVICE_EXTENSION PortDeviceExtension
;
314 TRACE_(I8042PRT
, "i8042ConnectMouseInterrupt()\n");
316 Status
= i8042MouInitialize(DeviceExtension
);
317 if (!NT_SUCCESS(Status
))
320 PortDeviceExtension
= DeviceExtension
->Common
.PortDeviceExtension
;
322 PortDeviceExtension
->KeyboardInterrupt
.Dirql
,
323 PortDeviceExtension
->MouseInterrupt
.Dirql
);
325 INFO_(I8042PRT
, "MouseInterrupt.Vector %lu\n",
326 PortDeviceExtension
->MouseInterrupt
.Vector
);
327 INFO_(I8042PRT
, "MouseInterrupt.Dirql %lu\n",
328 PortDeviceExtension
->MouseInterrupt
.Dirql
);
329 INFO_(I8042PRT
, "MouseInterrupt.DirqlMax %lu\n",
331 INFO_(I8042PRT
, "MouseInterrupt.InterruptMode %s\n",
332 PortDeviceExtension
->MouseInterrupt
.InterruptMode
== LevelSensitive
? "LevelSensitive" : "Latched");
333 INFO_(I8042PRT
, "MouseInterrupt.ShareInterrupt %s\n",
334 PortDeviceExtension
->MouseInterrupt
.ShareInterrupt
? "yes" : "no");
335 INFO_(I8042PRT
, "MouseInterrupt.Affinity 0x%lx\n",
336 PortDeviceExtension
->MouseInterrupt
.Affinity
);
337 Status
= IoConnectInterrupt(
338 &PortDeviceExtension
->MouseInterrupt
.Object
,
339 i8042MouInterruptService
,
340 DeviceExtension
, &PortDeviceExtension
->SpinLock
,
341 PortDeviceExtension
->MouseInterrupt
.Vector
, PortDeviceExtension
->MouseInterrupt
.Dirql
, DirqlMax
,
342 PortDeviceExtension
->MouseInterrupt
.InterruptMode
, PortDeviceExtension
->MouseInterrupt
.ShareInterrupt
,
343 PortDeviceExtension
->MouseInterrupt
.Affinity
, FALSE
);
344 if (!NT_SUCCESS(Status
))
346 WARN_(I8042PRT
, "IoConnectInterrupt() failed with status 0x%08x\n", Status
);
350 if (DirqlMax
== PortDeviceExtension
->MouseInterrupt
.Dirql
)
351 PortDeviceExtension
->HighestDIRQLInterrupt
= PortDeviceExtension
->MouseInterrupt
.Object
;
353 PortDeviceExtension
->Flags
|= MOUSE_INITIALIZED
;
354 Status
= STATUS_SUCCESS
;
357 if (!NT_SUCCESS(Status
))
359 PortDeviceExtension
->Flags
&= ~MOUSE_INITIALIZED
;
360 if (PortDeviceExtension
->MouseInterrupt
.Object
)
362 IoDisconnectInterrupt(PortDeviceExtension
->MouseInterrupt
.Object
);
363 PortDeviceExtension
->HighestDIRQLInterrupt
= PortDeviceExtension
->KeyboardInterrupt
.Object
;
371 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
372 IN UCHAR FlagsToDisable
,
373 IN UCHAR FlagsToEnable
)
375 i8042Flush(DeviceExtension
);
377 if (!i8042ChangeMode(DeviceExtension
, FlagsToDisable
, FlagsToEnable
))
378 return STATUS_UNSUCCESSFUL
;
380 /* Reset the mouse (if any) to start the detection */
381 if (DeviceExtension
->Flags
& MOUSE_PRESENT
)
385 Irql
= KeAcquireInterruptSpinLock(DeviceExtension
->HighestDIRQLInterrupt
);
387 i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, CTRL_WRITE_MOUSE
);
388 i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, MOU_CMD_RESET
);
390 KeReleaseInterruptSpinLock(DeviceExtension
->HighestDIRQLInterrupt
, Irql
);
393 return STATUS_SUCCESS
;
398 IN PPORT_DEVICE_EXTENSION DeviceExtension
)
401 UCHAR FlagsToDisable
= 0;
402 UCHAR FlagsToEnable
= 0;
404 if (DeviceExtension
->DataPort
== 0)
406 /* Unable to do something at the moment */
407 return STATUS_SUCCESS
;
410 if (!(DeviceExtension
->Flags
& (KEYBOARD_PRESENT
| MOUSE_PRESENT
)))
412 /* Try to detect them */
413 TRACE_(I8042PRT
, "Check if the controller is really a i8042\n");
414 Status
= i8042BasicDetect(DeviceExtension
);
415 if (!NT_SUCCESS(Status
))
417 WARN_(I8042PRT
, "i8042BasicDetect() failed with status 0x%08lx\n", Status
);
418 return STATUS_UNSUCCESSFUL
;
420 TRACE_(I8042PRT
, "Detecting keyboard\n");
421 i8042DetectKeyboard(DeviceExtension
);
423 TRACE_(I8042PRT
, "Detecting mouse\n");
424 i8042DetectMouse(DeviceExtension
);
426 INFO_(I8042PRT
, "Keyboard present: %s\n", DeviceExtension
->Flags
& KEYBOARD_PRESENT
? "YES" : "NO");
427 INFO_(I8042PRT
, "Mouse present : %s\n", DeviceExtension
->Flags
& MOUSE_PRESENT
? "YES" : "NO");
430 /* Connect interrupts */
431 if (DeviceExtension
->Flags
& KEYBOARD_PRESENT
&&
432 DeviceExtension
->Flags
& KEYBOARD_CONNECTED
&&
433 DeviceExtension
->Flags
& KEYBOARD_STARTED
&&
434 !(DeviceExtension
->Flags
& KEYBOARD_INITIALIZED
))
436 /* Keyboard is ready to be initialized */
437 Status
= i8042ConnectKeyboardInterrupt(DeviceExtension
->KeyboardExtension
);
438 if (NT_SUCCESS(Status
))
440 DeviceExtension
->Flags
|= KEYBOARD_INITIALIZED
;
441 FlagsToDisable
|= CCB_KBD_DISAB
;
442 FlagsToEnable
|= CCB_KBD_INT_ENAB
;
446 if (DeviceExtension
->Flags
& MOUSE_PRESENT
&&
447 DeviceExtension
->Flags
& MOUSE_CONNECTED
&&
448 DeviceExtension
->Flags
& MOUSE_STARTED
&&
449 !(DeviceExtension
->Flags
& MOUSE_INITIALIZED
))
451 /* Mouse is ready to be initialized */
452 Status
= i8042ConnectMouseInterrupt(DeviceExtension
->MouseExtension
);
453 if (NT_SUCCESS(Status
))
455 DeviceExtension
->Flags
|= MOUSE_INITIALIZED
;
456 FlagsToDisable
|= CCB_MOUSE_DISAB
;
457 FlagsToEnable
|= CCB_MOUSE_INT_ENAB
;
462 Status
= EnableInterrupts(DeviceExtension
, FlagsToDisable
, FlagsToEnable
);
464 Status
= STATUS_SUCCESS
;
471 IN PDEVICE_OBJECT DeviceObject
,
472 IN PCM_RESOURCE_LIST AllocatedResources
,
473 IN PCM_RESOURCE_LIST AllocatedResourcesTranslated
)
475 PFDO_DEVICE_EXTENSION DeviceExtension
;
476 PPORT_DEVICE_EXTENSION PortDeviceExtension
;
477 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
, ResourceDescriptorTranslated
;
478 INTERRUPT_DATA InterruptData
;
479 BOOLEAN FoundDataPort
= FALSE
;
480 BOOLEAN FoundControlPort
= FALSE
;
481 BOOLEAN FoundIrq
= FALSE
;
485 TRACE_(I8042PRT
, "i8042PnpStartDevice(%p)\n", DeviceObject
);
486 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
487 PortDeviceExtension
= DeviceExtension
->PortDeviceExtension
;
489 ASSERT(DeviceExtension
->PnpState
== dsStopped
);
491 if (!AllocatedResources
)
493 WARN_(I8042PRT
, "No allocated resources sent to driver\n");
494 return STATUS_INSUFFICIENT_RESOURCES
;
496 if (AllocatedResources
->Count
!= 1)
498 WARN_(I8042PRT
, "Wrong number of allocated resources sent to driver\n");
499 return STATUS_INSUFFICIENT_RESOURCES
;
501 if (AllocatedResources
->List
[0].PartialResourceList
.Version
!= 1
502 || AllocatedResources
->List
[0].PartialResourceList
.Revision
!= 1
503 || AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Version
!= 1
504 || AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Revision
!= 1)
506 WARN_(I8042PRT
, "Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
507 AllocatedResources
->List
[0].PartialResourceList
.Version
,
508 AllocatedResources
->List
[0].PartialResourceList
.Revision
,
509 AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Version
,
510 AllocatedResourcesTranslated
->List
[0].PartialResourceList
.Revision
);
511 return STATUS_REVISION_MISMATCH
;
514 /* Get Irq and optionally control port and data port */
515 for (i
= 0; i
< AllocatedResources
->List
[0].PartialResourceList
.Count
; i
++)
517 ResourceDescriptor
= &AllocatedResources
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
518 ResourceDescriptorTranslated
= &AllocatedResourcesTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[i
];
519 switch (ResourceDescriptor
->Type
)
521 case CmResourceTypePort
:
523 if (ResourceDescriptor
->u
.Port
.Length
== 1)
525 /* We assume that the first ressource will
526 * be the control port and the second one
527 * will be the data port...
531 PortDeviceExtension
->DataPort
= ULongToPtr(ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
);
532 INFO_(I8042PRT
, "Found data port: %p\n", PortDeviceExtension
->DataPort
);
533 FoundDataPort
= TRUE
;
535 else if (!FoundControlPort
)
537 PortDeviceExtension
->ControlPort
= ULongToPtr(ResourceDescriptor
->u
.Port
.Start
.u
.LowPart
);
538 INFO_(I8042PRT
, "Found control port: %p\n", PortDeviceExtension
->ControlPort
);
539 FoundControlPort
= TRUE
;
543 WARN_(I8042PRT
, "Too much I/O ranges provided: 0x%lx\n", ResourceDescriptor
->u
.Port
.Length
);
544 return STATUS_INVALID_PARAMETER
;
548 WARN_(I8042PRT
, "Invalid I/O range length: 0x%lx\n", ResourceDescriptor
->u
.Port
.Length
);
551 case CmResourceTypeInterrupt
:
554 return STATUS_INVALID_PARAMETER
;
555 InterruptData
.Dirql
= (KIRQL
)ResourceDescriptorTranslated
->u
.Interrupt
.Level
;
556 InterruptData
.Vector
= ResourceDescriptorTranslated
->u
.Interrupt
.Vector
;
557 InterruptData
.Affinity
= ResourceDescriptorTranslated
->u
.Interrupt
.Affinity
;
558 if (ResourceDescriptorTranslated
->Flags
& CM_RESOURCE_INTERRUPT_LATCHED
)
559 InterruptData
.InterruptMode
= Latched
;
561 InterruptData
.InterruptMode
= LevelSensitive
;
562 InterruptData
.ShareInterrupt
= (ResourceDescriptorTranslated
->ShareDisposition
== CmResourceShareShared
);
563 INFO_(I8042PRT
, "Found irq resource: %lu\n", ResourceDescriptor
->u
.Interrupt
.Level
);
568 WARN_(I8042PRT
, "Unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
574 WARN_(I8042PRT
, "Interrupt resource was not found in allocated resources list\n");
575 return STATUS_INSUFFICIENT_RESOURCES
;
577 else if (DeviceExtension
->Type
== Keyboard
&& (!FoundDataPort
|| !FoundControlPort
))
579 WARN_(I8042PRT
, "Some required resources were not found in allocated resources list\n");
580 return STATUS_INSUFFICIENT_RESOURCES
;
582 else if (DeviceExtension
->Type
== Mouse
&& (FoundDataPort
|| FoundControlPort
))
584 WARN_(I8042PRT
, "Too much resources were provided in allocated resources list\n");
585 return STATUS_INVALID_PARAMETER
;
588 switch (DeviceExtension
->Type
)
593 &PortDeviceExtension
->KeyboardInterrupt
,
595 sizeof(INTERRUPT_DATA
));
596 PortDeviceExtension
->Flags
|= KEYBOARD_STARTED
;
597 Status
= StartProcedure(PortDeviceExtension
);
603 &PortDeviceExtension
->MouseInterrupt
,
605 sizeof(INTERRUPT_DATA
));
606 PortDeviceExtension
->Flags
|= MOUSE_STARTED
;
607 Status
= StartProcedure(PortDeviceExtension
);
612 ERR_(I8042PRT
, "Unknown FDO type %u\n", DeviceExtension
->Type
);
614 Status
= STATUS_INVALID_DEVICE_REQUEST
;
618 if (NT_SUCCESS(Status
))
619 DeviceExtension
->PnpState
= dsStarted
;
626 IN PDEVICE_OBJECT DeviceObject
,
629 PIO_STACK_LOCATION Stack
;
631 I8042_DEVICE_TYPE DeviceType
;
632 ULONG_PTR Information
= 0;
635 Stack
= IoGetCurrentIrpStackLocation(Irp
);
636 MinorFunction
= Stack
->MinorFunction
;
637 DeviceType
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->Type
;
639 switch (MinorFunction
)
641 case IRP_MN_START_DEVICE
: /* 0x00 */
643 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
645 /* Call lower driver (if any) */
646 if (DeviceType
!= PhysicalDeviceObject
)
648 Status
= ForwardIrpAndWait(DeviceObject
, Irp
);
649 if (NT_SUCCESS(Status
))
650 Status
= i8042PnpStartDevice(
652 Stack
->Parameters
.StartDevice
.AllocatedResources
,
653 Stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
);
656 Status
= STATUS_SUCCESS
;
659 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* (optional) 0x07 */
661 switch (Stack
->Parameters
.QueryDeviceRelations
.Type
)
665 PDEVICE_RELATIONS DeviceRelations
;
667 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
668 DeviceRelations
= ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), I8042PRT_TAG
);
671 DeviceRelations
->Count
= 0;
672 Information
= (ULONG_PTR
)DeviceRelations
;
673 Status
= STATUS_SUCCESS
;
676 Status
= STATUS_INSUFFICIENT_RESOURCES
;
679 case RemovalRelations
:
681 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
682 return ForwardIrpAndForget(DeviceObject
, Irp
);
685 ERR_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
686 Stack
->Parameters
.QueryDeviceRelations
.Type
);
688 return ForwardIrpAndForget(DeviceObject
, Irp
);
692 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* (optional) 0x0d */
694 TRACE_(I8042PRT
, "IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
696 Status
= Irp
->IoStatus
.Status
;
701 ERR_(I8042PRT
, "IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction
);
703 return ForwardIrpAndForget(DeviceObject
, Irp
);
707 Irp
->IoStatus
.Information
= Information
;
708 Irp
->IoStatus
.Status
= Status
;
709 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);