ReactOS 0.4.15-dev-7842-g558ab78
pnp.c File Reference
#include "i8042prt.h"
#include <debug.h>
Include dependency graph for pnp.c:

Go to the source code of this file.

Functions

BOOLEAN i8042ChangeMode (IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR FlagsToDisable, IN UCHAR FlagsToEnable)
 
static NTSTATUS i8042BasicDetect (IN PPORT_DEVICE_EXTENSION DeviceExtension)
 
static VOID i8042DetectKeyboard (IN PPORT_DEVICE_EXTENSION DeviceExtension)
 
static VOID i8042DetectMouse (IN PPORT_DEVICE_EXTENSION DeviceExtension)
 
static NTSTATUS i8042ConnectKeyboardInterrupt (IN PI8042_KEYBOARD_EXTENSION DeviceExtension)
 
static NTSTATUS i8042ConnectMouseInterrupt (IN PI8042_MOUSE_EXTENSION DeviceExtension)
 
static NTSTATUS EnableInterrupts (IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR FlagsToDisable, IN UCHAR FlagsToEnable)
 
static NTSTATUS StartProcedure (IN PPORT_DEVICE_EXTENSION DeviceExtension)
 
static NTSTATUS i8042PnpStartDevice (IN PDEVICE_OBJECT DeviceObject, IN PCM_RESOURCE_LIST AllocatedResources, IN PCM_RESOURCE_LIST AllocatedResourcesTranslated)
 
static VOID i8042RemoveDevice (IN PDEVICE_OBJECT DeviceObject)
 
NTSTATUS NTAPI i8042Pnp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 

Function Documentation

◆ EnableInterrupts()

static NTSTATUS EnableInterrupts ( IN PPORT_DEVICE_EXTENSION  DeviceExtension,
IN UCHAR  FlagsToDisable,
IN UCHAR  FlagsToEnable 
)
static

Definition at line 380 of file pnp.c.

384{
385 i8042Flush(DeviceExtension);
386
387 if (!i8042ChangeMode(DeviceExtension, FlagsToDisable, FlagsToEnable))
388 return STATUS_UNSUCCESSFUL;
389
390 return STATUS_SUCCESS;
391}
BOOLEAN i8042ChangeMode(IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR FlagsToDisable, IN UCHAR FlagsToEnable)
Definition: pnp.c:37
VOID i8042Flush(IN PPORT_DEVICE_EXTENSION DeviceExtension)
Definition: readwrite.c:21
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by EHCI_InterruptDpc(), HalpInitializePICs(), and StartProcedure().

◆ i8042BasicDetect()

static NTSTATUS i8042BasicDetect ( IN PPORT_DEVICE_EXTENSION  DeviceExtension)
static

Definition at line 77 of file pnp.c.

79{
81 ULONG ResendIterations;
82 UCHAR Value = 0;
83
84 /* Don't enable keyboard and mouse interrupts, disable keyboard/mouse */
85 i8042Flush(DeviceExtension);
88
89 i8042Flush(DeviceExtension);
90
91 /* Issue a CTRL_SELF_TEST command to check if this is really an i8042 controller */
92 ResendIterations = DeviceExtension->Settings.ResendIterations + 1;
93 while (ResendIterations--)
94 {
95 if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST))
96 {
97 WARN_(I8042PRT, "Writing CTRL_SELF_TEST command failed\n");
98 return STATUS_IO_TIMEOUT;
99 }
100
101 Status = i8042ReadDataWait(DeviceExtension, &Value);
102 if (!NT_SUCCESS(Status))
103 {
104 WARN_(I8042PRT, "Failed to read CTRL_SELF_TEST response, status 0x%08lx\n", Status);
105 return Status;
106 }
107
108 if (Value == KBD_SELF_TEST_OK)
109 {
110 INFO_(I8042PRT, "CTRL_SELF_TEST completed successfully!\n");
111 break;
112 }
113 else if (Value == KBD_RESEND)
114 {
115 TRACE_(I8042PRT, "Resending...\n");
117 }
118 else
119 {
120 WARN_(I8042PRT, "Got 0x%02x instead of 0x55\n", Value);
122 }
123 }
124
125 return STATUS_SUCCESS;
126}
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:81
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define TRACE_(x)
Definition: compat.h:76
Status
Definition: gdiplustypes.h:25
#define CCB_KBD_DISAB
Definition: i8042prt.h:262
NTSTATUS i8042ReadDataWait(IN PPORT_DEVICE_EXTENSION DeviceExtension, OUT PUCHAR Data)
Definition: readwrite.c:95
#define KBD_SELF_TEST_OK
Definition: i8042prt.h:241
#define CCB_KBD_INT_ENAB
Definition: i8042prt.h:259
#define CCB_MOUSE_DISAB
Definition: i8042prt.h:263
#define KBD_RESEND
Definition: i8042prt.h:244
BOOLEAN i8042Write(IN PPORT_DEVICE_EXTENSION DeviceExtension, IN PUCHAR addr, IN UCHAR data)
Definition: readwrite.c:199
#define CCB_MOUSE_INT_ENAB
Definition: i8042prt.h:260
#define CTRL_SELF_TEST
Definition: i8042prt.h:225
#define INFO_(ch,...)
Definition: debug.h:159
#define WARN_(ch,...)
Definition: debug.h:157
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by StartProcedure().

◆ i8042ChangeMode()

BOOLEAN i8042ChangeMode ( IN PPORT_DEVICE_EXTENSION  DeviceExtension,
IN UCHAR  FlagsToDisable,
IN UCHAR  FlagsToEnable 
)

Definition at line 37 of file pnp.c.

41{
44
45 if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, KBD_READ_MODE))
46 {
47 WARN_(I8042PRT, "Can't read i8042 mode\n");
48 return FALSE;
49 }
50
51 Status = i8042ReadDataWait(DeviceExtension, &Value);
52 if (!NT_SUCCESS(Status))
53 {
54 WARN_(I8042PRT, "No response after read i8042 mode\n");
55 return FALSE;
56 }
57
58 Value &= ~FlagsToDisable;
59 Value |= FlagsToEnable;
60
61 if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, KBD_WRITE_MODE))
62 {
63 WARN_(I8042PRT, "Can't set i8042 mode\n");
64 return FALSE;
65 }
66
67 if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Value))
68 {
69 WARN_(I8042PRT, "Can't send i8042 mode\n");
70 return FALSE;
71 }
72
73 return TRUE;
74}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define KBD_WRITE_MODE
Definition: i8042prt.h:222
#define KBD_READ_MODE
Definition: i8042prt.h:221

Referenced by EnableInterrupts(), i8042BasicDetect(), and i8042DetectKeyboard().

◆ i8042ConnectKeyboardInterrupt()

static NTSTATUS i8042ConnectKeyboardInterrupt ( IN PI8042_KEYBOARD_EXTENSION  DeviceExtension)
static

Definition at line 267 of file pnp.c.

269{
270 PPORT_DEVICE_EXTENSION PortDeviceExtension;
271 KIRQL DirqlMax;
273
274 TRACE_(I8042PRT, "i8042ConnectKeyboardInterrupt()\n");
275
276 PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;
277
278 // Enable keyboard clock line
279 i8042Write(PortDeviceExtension, PortDeviceExtension->ControlPort, KBD_CLK_ENABLE);
280
281 DirqlMax = MAX(
282 PortDeviceExtension->KeyboardInterrupt.Dirql,
283 PortDeviceExtension->MouseInterrupt.Dirql);
284
285 INFO_(I8042PRT, "KeyboardInterrupt.Vector %lu\n",
286 PortDeviceExtension->KeyboardInterrupt.Vector);
287 INFO_(I8042PRT, "KeyboardInterrupt.Dirql %lu\n",
288 PortDeviceExtension->KeyboardInterrupt.Dirql);
289 INFO_(I8042PRT, "KeyboardInterrupt.DirqlMax %lu\n",
290 DirqlMax);
291 INFO_(I8042PRT, "KeyboardInterrupt.InterruptMode %s\n",
292 PortDeviceExtension->KeyboardInterrupt.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched");
293 INFO_(I8042PRT, "KeyboardInterrupt.ShareInterrupt %s\n",
294 PortDeviceExtension->KeyboardInterrupt.ShareInterrupt ? "yes" : "no");
295 INFO_(I8042PRT, "KeyboardInterrupt.Affinity 0x%lx\n",
296 PortDeviceExtension->KeyboardInterrupt.Affinity);
298 &PortDeviceExtension->KeyboardInterrupt.Object,
300 DeviceExtension, &PortDeviceExtension->SpinLock,
301 PortDeviceExtension->KeyboardInterrupt.Vector, PortDeviceExtension->KeyboardInterrupt.Dirql, DirqlMax,
302 PortDeviceExtension->KeyboardInterrupt.InterruptMode, PortDeviceExtension->KeyboardInterrupt.ShareInterrupt,
303 PortDeviceExtension->KeyboardInterrupt.Affinity, FALSE);
304 if (!NT_SUCCESS(Status))
305 {
306 WARN_(I8042PRT, "IoConnectInterrupt() failed with status 0x%08x\n", Status);
307 return Status;
308 }
309
310 if (DirqlMax == PortDeviceExtension->KeyboardInterrupt.Dirql)
311 PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object;
312 PortDeviceExtension->Flags |= KEYBOARD_INITIALIZED;
313 return STATUS_SUCCESS;
314}
#define MAX(x, y)
Definition: rdesktop.h:175
UCHAR KIRQL
Definition: env_spec_w32.h:591
KSERVICE_ROUTINE i8042KbdInterruptService
Definition: i8042prt.h:320
#define KEYBOARD_INITIALIZED
Definition: i8042prt.h:71
#define KBD_CLK_ENABLE
Definition: i8042prt.h:227
NTSTATUS NTAPI IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave)
Definition: irq.c:22
@ LevelSensitive
Definition: miniport.h:80
KINTERRUPT_MODE InterruptMode
Definition: i8042prt.h:55
BOOLEAN ShareInterrupt
Definition: i8042prt.h:56
PKINTERRUPT Object
Definition: i8042prt.h:52
ULONG Vector
Definition: i8042prt.h:53
KAFFINITY Affinity
Definition: i8042prt.h:57
INTERRUPT_DATA KeyboardInterrupt
Definition: i8042prt.h:85
PKINTERRUPT HighestDIRQLInterrupt
Definition: i8042prt.h:88
KSPIN_LOCK SpinLock
Definition: i8042prt.h:89
INTERRUPT_DATA MouseInterrupt
Definition: i8042prt.h:87
COMMON_DEVICE_EXTENSION Common
Definition: kbdclass.h:42

Referenced by StartProcedure().

◆ i8042ConnectMouseInterrupt()

static NTSTATUS i8042ConnectMouseInterrupt ( IN PI8042_MOUSE_EXTENSION  DeviceExtension)
static

Definition at line 317 of file pnp.c.

319{
320 PPORT_DEVICE_EXTENSION PortDeviceExtension;
321 KIRQL DirqlMax;
323
324 TRACE_(I8042PRT, "i8042ConnectMouseInterrupt()\n");
325
326 Status = i8042MouInitialize(DeviceExtension);
327 if (!NT_SUCCESS(Status))
328 return Status;
329
330 PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;
331 DirqlMax = MAX(
332 PortDeviceExtension->KeyboardInterrupt.Dirql,
333 PortDeviceExtension->MouseInterrupt.Dirql);
334
335 INFO_(I8042PRT, "MouseInterrupt.Vector %lu\n",
336 PortDeviceExtension->MouseInterrupt.Vector);
337 INFO_(I8042PRT, "MouseInterrupt.Dirql %lu\n",
338 PortDeviceExtension->MouseInterrupt.Dirql);
339 INFO_(I8042PRT, "MouseInterrupt.DirqlMax %lu\n",
340 DirqlMax);
341 INFO_(I8042PRT, "MouseInterrupt.InterruptMode %s\n",
342 PortDeviceExtension->MouseInterrupt.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched");
343 INFO_(I8042PRT, "MouseInterrupt.ShareInterrupt %s\n",
344 PortDeviceExtension->MouseInterrupt.ShareInterrupt ? "yes" : "no");
345 INFO_(I8042PRT, "MouseInterrupt.Affinity 0x%lx\n",
346 PortDeviceExtension->MouseInterrupt.Affinity);
348 &PortDeviceExtension->MouseInterrupt.Object,
350 DeviceExtension, &PortDeviceExtension->SpinLock,
351 PortDeviceExtension->MouseInterrupt.Vector, PortDeviceExtension->MouseInterrupt.Dirql, DirqlMax,
352 PortDeviceExtension->MouseInterrupt.InterruptMode, PortDeviceExtension->MouseInterrupt.ShareInterrupt,
353 PortDeviceExtension->MouseInterrupt.Affinity, FALSE);
354 if (!NT_SUCCESS(Status))
355 {
356 WARN_(I8042PRT, "IoConnectInterrupt() failed with status 0x%08x\n", Status);
357 goto cleanup;
358 }
359
360 if (DirqlMax == PortDeviceExtension->MouseInterrupt.Dirql)
361 PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->MouseInterrupt.Object;
362
363 PortDeviceExtension->Flags |= MOUSE_INITIALIZED;
365
366cleanup:
367 if (!NT_SUCCESS(Status))
368 {
369 PortDeviceExtension->Flags &= ~MOUSE_INITIALIZED;
370 if (PortDeviceExtension->MouseInterrupt.Object)
371 {
372 IoDisconnectInterrupt(PortDeviceExtension->MouseInterrupt.Object);
373 PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object;
374 }
375 }
376 return Status;
377}
static void cleanup(void)
Definition: main.c:1335
KSERVICE_ROUTINE i8042MouInterruptService
Definition: i8042prt.h:367
NTSTATUS i8042MouInitialize(IN PI8042_MOUSE_EXTENSION DeviceExtension)
Definition: mouse.c:224
#define MOUSE_INITIALIZED
Definition: i8042prt.h:75
VOID NTAPI IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
Definition: irq.c:141

Referenced by StartProcedure().

◆ i8042DetectKeyboard()

static VOID i8042DetectKeyboard ( IN PPORT_DEVICE_EXTENSION  DeviceExtension)
static

Definition at line 129 of file pnp.c.

131{
133
134 /* Set LEDs (that is not fatal if some error occurs) */
135 Status = i8042SynchWritePort(DeviceExtension, 0, KBD_CMD_SET_LEDS, TRUE);
136 if (NT_SUCCESS(Status))
137 {
138 Status = i8042SynchWritePort(DeviceExtension, 0, 0, TRUE);
139 if (!NT_SUCCESS(Status))
140 {
141 WARN_(I8042PRT, "Can't finish SET_LEDS (0x%08lx)\n", Status);
142 return;
143 }
144 }
145 else
146 {
147 WARN_(I8042PRT, "Warning: can't write SET_LEDS (0x%08lx)\n", Status);
148 }
149
150 /* Turn on translation and SF (Some machines don't reboot if SF is not set, see ReactOS bug CORE-1713) */
151 if (!i8042ChangeMode(DeviceExtension, 0, CCB_TRANSLATE | CCB_SYSTEM_FLAG))
152 return;
153
154 /*
155 * We used to send a KBD_LINE_TEST (0xAB) command, but on at least HP
156 * Pavilion notebooks the response to that command was incorrect.
157 * So now we just assume that a keyboard is attached.
158 */
159 DeviceExtension->Flags |= KEYBOARD_PRESENT;
160
161 INFO_(I8042PRT, "Keyboard detected\n");
162}
#define KBD_CMD_SET_LEDS
Definition: i8042prt.h:234
#define CCB_TRANSLATE
Definition: i8042prt.h:264
#define CCB_SYSTEM_FLAG
Definition: i8042prt.h:261
NTSTATUS NTAPI i8042SynchWritePort(IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR Port, IN UCHAR Value, IN BOOLEAN WaitForAck)
Definition: readwrite.c:144
#define KEYBOARD_PRESENT
Definition: i8042prt.h:68

Referenced by StartProcedure().

◆ i8042DetectMouse()

static VOID i8042DetectMouse ( IN PPORT_DEVICE_EXTENSION  DeviceExtension)
static

Definition at line 165 of file pnp.c.

167{
169 UCHAR Value;
170 UCHAR ExpectedReply[] = { MOUSE_ACK, 0xAA };
171 UCHAR ReplyByte;
172
173 /* First do a mouse line test */
174 if (i8042Write(DeviceExtension, DeviceExtension->ControlPort, MOUSE_LINE_TEST))
175 {
176 Status = i8042ReadDataWait(DeviceExtension, &Value);
177
178 if (!NT_SUCCESS(Status) || Value != 0)
179 {
180 WARN_(I8042PRT, "Mouse line test failed\n");
181 goto failure;
182 }
183 }
184
185 /* Now reset the mouse */
186 i8042Flush(DeviceExtension);
187
188 if(!i8042IsrWritePort(DeviceExtension, MOU_CMD_RESET, CTRL_WRITE_MOUSE))
189 {
190 WARN_(I8042PRT, "Failed to write reset command to mouse\n");
191 goto failure;
192 }
193
194 /* The implementation of the "Mouse Reset" command differs much from chip to chip.
195
196 By default, the first byte is an ACK, when the mouse is plugged in and working and NACK when it's not.
197 On success, the next bytes are 0xAA and 0x00.
198
199 But on some systems (like ECS K7S5A Pro, SiS 735 chipset), we always get an ACK and 0xAA.
200 Only the last byte indicates, whether a mouse is plugged in.
201 It is either sent or not, so there is no byte, which indicates a failure here.
202
203 After the Mouse Reset command was issued, it usually takes some time until we get a response.
204 So get the first two bytes in a loop. */
205 for (ReplyByte = 0;
206 ReplyByte < sizeof(ExpectedReply) / sizeof(ExpectedReply[0]);
207 ReplyByte++)
208 {
209 ULONG Counter = 500;
210
211 do
212 {
213 Status = i8042ReadDataWait(DeviceExtension, &Value);
214
215 if(!NT_SUCCESS(Status))
216 {
217 /* Wait some time before trying again */
219 }
220 } while (Status == STATUS_IO_TIMEOUT && Counter--);
221
222 if (!NT_SUCCESS(Status))
223 {
224 WARN_(I8042PRT, "No ACK after mouse reset, status 0x%08lx\n", Status);
225 goto failure;
226 }
227 else if (Value != ExpectedReply[ReplyByte])
228 {
229 WARN_(I8042PRT, "Unexpected reply: 0x%02x (expected 0x%02x)\n", Value, ExpectedReply[ReplyByte]);
230 goto failure;
231 }
232 }
233
234 /* Finally get the third byte, but only try it one time (see above).
235 Otherwise this takes around 45 seconds on a K7S5A Pro, when no mouse is plugged in. */
236 Status = i8042ReadDataWait(DeviceExtension, &Value);
237
238 if(!NT_SUCCESS(Status))
239 {
240 WARN_(I8042PRT, "Last byte was not transmitted after mouse reset, status 0x%08lx\n", Status);
241 goto failure;
242 }
243 else if(Value != 0x00)
244 {
245 WARN_(I8042PRT, "Last byte after mouse reset was not 0x00, but 0x%02x\n", Value);
246 goto failure;
247 }
248
249 DeviceExtension->Flags |= MOUSE_PRESENT;
250 INFO_(I8042PRT, "Mouse detected\n");
251 return;
252
253failure:
254 /* There is probably no mouse present. On some systems,
255 the probe locks the entire keyboard controller. Let's
256 try to get access to the keyboard again by sending a
257 reset */
258 i8042Flush(DeviceExtension);
259 i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST);
260 i8042ReadDataWait(DeviceExtension, &Value);
261 i8042Flush(DeviceExtension);
262
263 INFO_(I8042PRT, "Mouse not detected\n");
264}
#define MOUSE_ACK
Definition: i8042prt.h:285
#define CTRL_WRITE_MOUSE
Definition: i8042prt.h:228
#define MOUSE_PRESENT
Definition: i8042prt.h:72
BOOLEAN i8042IsrWritePort(IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR Value, IN UCHAR SelectCmd OPTIONAL)
Definition: readwrite.c:40
#define MOU_CMD_RESET
Definition: i8042prt.h:279
#define MOUSE_LINE_TEST
Definition: i8042prt.h:224
static LARGE_INTEGER Counter
Definition: clock.c:43

Referenced by StartProcedure().

◆ i8042Pnp()

NTSTATUS NTAPI i8042Pnp ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 675 of file pnp.c.

678{
685
687 MinorFunction = Stack->MinorFunction;
688 FdoExtension = DeviceObject->DeviceExtension;
689 DeviceType = FdoExtension->Type;
690
691 switch (MinorFunction)
692 {
693 case IRP_MN_START_DEVICE: /* 0x00 */
694 {
695 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
696
697 /* Call lower driver (if any) */
699 {
701
702 if (IoForwardIrpSynchronously(FdoExtension->LowerDevice, Irp))
703 {
704 Status = Irp->IoStatus.Status;
705 if (NT_SUCCESS(Status))
706 {
709 Stack->Parameters.StartDevice.AllocatedResources,
710 Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
711 }
712 }
713 }
714 else
716 break;
717 }
718 case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x07 */
719 {
720 switch (Stack->Parameters.QueryDeviceRelations.Type)
721 {
722 case BusRelations:
723 {
724 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
726 }
727 case RemovalRelations:
728 {
729 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
731 }
732 default:
733 ERR_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
734 Stack->Parameters.QueryDeviceRelations.Type);
736 }
737 break;
738 }
739 case IRP_MN_QUERY_CAPABILITIES: /* (optional) 0x09 */
740 {
741 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
743 }
744 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* (optional) 0x0d */
745 {
746 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
748 }
749 case IRP_MN_QUERY_PNP_DEVICE_STATE: /* (optional) 0x14 */
750 {
751 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
753 }
755 {
756 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
758 }
760 {
761 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_CANCEL_REMOVE_DEVICE\n");
763 }
765 {
766 TRACE_(I8042PRT, "IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
769 return Status;
770 }
771 default:
772 {
773 ERR_(I8042PRT, "IRP_MJ_PNP / unknown minor function 0x%x\n", MinorFunction);
775 }
776 }
777
778 Irp->IoStatus.Information = Information;
779 Irp->IoStatus.Status = Status;
781 return Status;
782}
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
_In_ PIRP Irp
Definition: csq.h:116
static VOID i8042RemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: pnp.c:655
static NTSTATUS i8042PnpStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PCM_RESOURCE_LIST AllocatedResources, IN PCM_RESOURCE_LIST AllocatedResourcesTranslated)
Definition: pnp.c:500
@ FdoExtension
Definition: precomp.h:48
DRIVER_DISPATCH ForwardIrpAndForget
Definition: i8042prt.h:341
enum _I8042_DEVICE_TYPE I8042_DEVICE_TYPE
DeviceType
Definition: mmdrv.h:42
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1625
#define ERR_(ch,...)
Definition: debug.h:156
uint32_t ULONG_PTR
Definition: typedefs.h:65
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ UCHAR _In_ UCHAR MinorFunction
Definition: wdfdevice.h:1699
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
@ RemovalRelations
Definition: iotypes.h:2155
@ BusRelations
Definition: iotypes.h:2152
#define IRP_MN_QUERY_PNP_DEVICE_STATE
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MN_START_DEVICE
#define IRP_MN_REMOVE_DEVICE
#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS
#define IRP_MN_QUERY_DEVICE_RELATIONS
#define IRP_MN_QUERY_CAPABILITIES
#define IRP_MN_CANCEL_REMOVE_DEVICE
#define IRP_MN_QUERY_REMOVE_DEVICE

Referenced by DriverEntry().

◆ i8042PnpStartDevice()

static NTSTATUS i8042PnpStartDevice ( IN PDEVICE_OBJECT  DeviceObject,
IN PCM_RESOURCE_LIST  AllocatedResources,
IN PCM_RESOURCE_LIST  AllocatedResourcesTranslated 
)
static

Definition at line 500 of file pnp.c.

504{
505 PFDO_DEVICE_EXTENSION DeviceExtension;
506 PPORT_DEVICE_EXTENSION PortDeviceExtension;
507 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor, ResourceDescriptorTranslated;
508 INTERRUPT_DATA InterruptData = { NULL };
509 BOOLEAN FoundDataPort = FALSE;
510 BOOLEAN FoundControlPort = FALSE;
511 BOOLEAN FoundIrq = FALSE;
512 ULONG i;
514
515 TRACE_(I8042PRT, "i8042PnpStartDevice(%p)\n", DeviceObject);
516 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
517 PortDeviceExtension = DeviceExtension->PortDeviceExtension;
518
519 ASSERT(DeviceExtension->PnpState == dsStopped);
520
522 {
523 WARN_(I8042PRT, "No allocated resources sent to driver\n");
525 }
526 if (AllocatedResources->Count != 1)
527 {
528 WARN_(I8042PRT, "Wrong number of allocated resources sent to driver\n");
530 }
531 if (AllocatedResources->List[0].PartialResourceList.Version != 1
532 || AllocatedResources->List[0].PartialResourceList.Revision != 1
533 || AllocatedResourcesTranslated->List[0].PartialResourceList.Version != 1
534 || AllocatedResourcesTranslated->List[0].PartialResourceList.Revision != 1)
535 {
536 WARN_(I8042PRT, "Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
537 AllocatedResources->List[0].PartialResourceList.Version,
538 AllocatedResources->List[0].PartialResourceList.Revision,
539 AllocatedResourcesTranslated->List[0].PartialResourceList.Version,
540 AllocatedResourcesTranslated->List[0].PartialResourceList.Revision);
542 }
543
544 /* Get Irq and optionally control port and data port */
545 for (i = 0; i < AllocatedResources->List[0].PartialResourceList.Count; i++)
546 {
547 ResourceDescriptor = &AllocatedResources->List[0].PartialResourceList.PartialDescriptors[i];
548 ResourceDescriptorTranslated = &AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
549 switch (ResourceDescriptor->Type)
550 {
552 {
553 if (ResourceDescriptor->u.Port.Length == 1)
554 {
555 /* We assume that the first resource will
556 * be the control port and the second one
557 * will be the data port...
558 */
559 if (!FoundDataPort)
560 {
561 PortDeviceExtension->DataPort = ULongToPtr(ResourceDescriptor->u.Port.Start.u.LowPart);
562 INFO_(I8042PRT, "Found data port: %p\n", PortDeviceExtension->DataPort);
563 FoundDataPort = TRUE;
564 }
565 else if (!FoundControlPort)
566 {
567 PortDeviceExtension->ControlPort = ULongToPtr(ResourceDescriptor->u.Port.Start.u.LowPart);
568 INFO_(I8042PRT, "Found control port: %p\n", PortDeviceExtension->ControlPort);
569 FoundControlPort = TRUE;
570 }
571 else
572 {
573 /* FIXME: implement PS/2 Active Multiplexing */
574 ERR_(I8042PRT, "Unhandled I/O ranges provided: 0x%lx\n", ResourceDescriptor->u.Port.Length);
575 }
576 }
577 else
578 WARN_(I8042PRT, "Invalid I/O range length: 0x%lx\n", ResourceDescriptor->u.Port.Length);
579 break;
580 }
582 {
583 if (FoundIrq)
585 InterruptData.Dirql = (KIRQL)ResourceDescriptorTranslated->u.Interrupt.Level;
586 InterruptData.Vector = ResourceDescriptorTranslated->u.Interrupt.Vector;
587 InterruptData.Affinity = ResourceDescriptorTranslated->u.Interrupt.Affinity;
588 if (ResourceDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
589 InterruptData.InterruptMode = Latched;
590 else
591 InterruptData.InterruptMode = LevelSensitive;
592 InterruptData.ShareInterrupt = (ResourceDescriptorTranslated->ShareDisposition == CmResourceShareShared);
593 INFO_(I8042PRT, "Found irq resource: %lu\n", ResourceDescriptor->u.Interrupt.Level);
594 FoundIrq = TRUE;
595 break;
596 }
597 default:
598 WARN_(I8042PRT, "Unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type);
599 }
600 }
601
602 if (!FoundIrq)
603 {
604 WARN_(I8042PRT, "Interrupt resource was not found in allocated resources list\n");
606 }
607 else if (DeviceExtension->Type == Keyboard && (!FoundDataPort || !FoundControlPort))
608 {
609 WARN_(I8042PRT, "Some required resources were not found in allocated resources list\n");
611 }
612 else if (DeviceExtension->Type == Mouse && (FoundDataPort || FoundControlPort))
613 {
614 WARN_(I8042PRT, "Too much resources were provided in allocated resources list\n");
616 }
617
618 switch (DeviceExtension->Type)
619 {
620 case Keyboard:
621 {
623 &PortDeviceExtension->KeyboardInterrupt,
624 &InterruptData,
625 sizeof(INTERRUPT_DATA));
626 PortDeviceExtension->Flags |= KEYBOARD_STARTED;
627 Status = StartProcedure(PortDeviceExtension);
628 break;
629 }
630 case Mouse:
631 {
633 &PortDeviceExtension->MouseInterrupt,
634 &InterruptData,
635 sizeof(INTERRUPT_DATA));
636 PortDeviceExtension->Flags |= MOUSE_STARTED;
637 Status = StartProcedure(PortDeviceExtension);
638 break;
639 }
640 default:
641 {
642 WARN_(I8042PRT, "Unknown FDO type %u\n", DeviceExtension->Type);
643 ASSERT(!(PortDeviceExtension->Flags & KEYBOARD_CONNECTED) || !(PortDeviceExtension->Flags & MOUSE_CONNECTED));
645 }
646 }
647
648 if (NT_SUCCESS(Status))
649 DeviceExtension->PnpState = dsStarted;
650
651 return Status;
652}
unsigned char BOOLEAN
#define ULongToPtr(ul)
Definition: basetsd.h:92
#define NULL
Definition: types.h:112
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
static NTSTATUS StartProcedure(IN PPORT_DEVICE_EXTENSION DeviceExtension)
Definition: pnp.c:394
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define CmResourceTypePort
Definition: hwresource.cpp:123
#define CmResourceTypeInterrupt
Definition: hwresource.cpp:124
#define MOUSE_STARTED
Definition: i8042prt.h:74
#define KEYBOARD_CONNECTED
Definition: i8042prt.h:69
#define MOUSE_CONNECTED
Definition: i8042prt.h:73
#define KEYBOARD_STARTED
Definition: i8042prt.h:70
@ Keyboard
Definition: i8042prt.h:115
@ Mouse
Definition: i8042prt.h:116
@ dsStopped
Definition: isapnp.h:34
@ dsStarted
Definition: isapnp.h:35
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
_Inout_opt_ PDEVICE_OBJECT _Inout_opt_ PDEVICE_OBJECT _Inout_opt_ PDEVICE_OBJECT _Inout_opt_ PCM_RESOURCE_LIST * AllocatedResources
Definition: ndis.h:4643
_Inout_opt_ PDEVICE_OBJECT _Inout_opt_ PDEVICE_OBJECT _Inout_opt_ PDEVICE_OBJECT _Inout_opt_ PCM_RESOURCE_LIST _Inout_opt_ PCM_RESOURCE_LIST * AllocatedResourcesTranslated
Definition: ndis.h:4644
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: cmtypes.h:144
#define STATUS_REVISION_MISMATCH
Definition: ntstatus.h:325
@ Latched
Definition: miniport.h:81
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393::@396 Interrupt
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393::@395 Port
I8042_DEVICE_TYPE Type
Definition: i8042prt.h:122
DEVICE_STATE PnpState
Definition: i8042prt.h:132
PPORT_DEVICE_EXTENSION PortDeviceExtension
Definition: i8042prt.h:134
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
@ CmResourceShareShared
Definition: cmtypes.h:243

Referenced by i8042Pnp().

◆ i8042RemoveDevice()

static VOID i8042RemoveDevice ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 655 of file pnp.c.

657{
660 PFDO_DEVICE_EXTENSION DeviceExtension;
661
663 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
664
665 KeAcquireSpinLock(&DriverExtension->DeviceListLock, &OldIrql);
666 RemoveEntryList(&DeviceExtension->ListEntry);
667 KeReleaseSpinLock(&DriverExtension->DeviceListLock, OldIrql);
668
669 IoDetachDevice(DeviceExtension->LowerDevice);
670
672}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
struct _I8042_DRIVER_EXTENSION * PI8042_DRIVER_EXTENSION
VOID NTAPI IoDetachDevice(IN PDEVICE_OBJECT TargetDevice)
Definition: device.c:1296
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1904
PPCI_DRIVER_EXTENSION DriverExtension
Definition: pci.c:31
PDEVICE_OBJECT LowerDevice
Definition: i8042prt.h:130
LIST_ENTRY ListEntry
Definition: pci.h:86
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by i8042Pnp().

◆ StartProcedure()

static NTSTATUS StartProcedure ( IN PPORT_DEVICE_EXTENSION  DeviceExtension)
static

Definition at line 394 of file pnp.c.

396{
398 UCHAR FlagsToDisable = 0;
399 UCHAR FlagsToEnable = 0;
400 KIRQL Irql;
401
402 if (DeviceExtension->DataPort == 0)
403 {
404 /* Unable to do something at the moment */
405 return STATUS_SUCCESS;
406 }
407
408 if (!(DeviceExtension->Flags & (KEYBOARD_PRESENT | MOUSE_PRESENT)))
409 {
410 /* Try to detect them */
411 TRACE_(I8042PRT, "Check if the controller is really a i8042\n");
412 Status = i8042BasicDetect(DeviceExtension);
413 if (!NT_SUCCESS(Status))
414 {
415 WARN_(I8042PRT, "i8042BasicDetect() failed with status 0x%08lx\n", Status);
416 return STATUS_UNSUCCESSFUL;
417 }
418
419 /* First detect the mouse and then the keyboard!
420 If we do it the other way round, some systems throw away settings like the keyboard translation, when detecting the mouse. */
421 TRACE_(I8042PRT, "Detecting mouse\n");
422 i8042DetectMouse(DeviceExtension);
423 TRACE_(I8042PRT, "Detecting keyboard\n");
424 i8042DetectKeyboard(DeviceExtension);
425
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");
428
429 TRACE_(I8042PRT, "Enabling i8042 interrupts\n");
430 if (DeviceExtension->Flags & KEYBOARD_PRESENT)
431 {
432 FlagsToDisable |= CCB_KBD_DISAB;
433 FlagsToEnable |= CCB_KBD_INT_ENAB;
434 }
435 if (DeviceExtension->Flags & MOUSE_PRESENT)
436 {
437 FlagsToDisable |= CCB_MOUSE_DISAB;
438 FlagsToEnable |= CCB_MOUSE_INT_ENAB;
439 }
440
441 Status = EnableInterrupts(DeviceExtension, FlagsToDisable, FlagsToEnable);
442 if (!NT_SUCCESS(Status))
443 {
444 WARN_(I8042PRT, "EnableInterrupts failed: %lx\n", Status);
445 DeviceExtension->Flags &= ~(KEYBOARD_PRESENT | MOUSE_PRESENT);
446 return Status;
447 }
448 }
449
450 /* Connect interrupts */
451 if (DeviceExtension->Flags & KEYBOARD_PRESENT &&
452 DeviceExtension->Flags & KEYBOARD_CONNECTED &&
453 DeviceExtension->Flags & KEYBOARD_STARTED &&
454 !(DeviceExtension->Flags & KEYBOARD_INITIALIZED))
455 {
456 /* Keyboard is ready to be initialized */
457 Status = i8042ConnectKeyboardInterrupt(DeviceExtension->KeyboardExtension);
458 if (NT_SUCCESS(Status))
459 {
460 DeviceExtension->Flags |= KEYBOARD_INITIALIZED;
461 }
462 else
463 {
464 WARN_(I8042PRT, "i8042ConnectKeyboardInterrupt failed: %lx\n", Status);
465 }
466 }
467
468 if (DeviceExtension->Flags & MOUSE_PRESENT &&
469 DeviceExtension->Flags & MOUSE_CONNECTED &&
470 DeviceExtension->Flags & MOUSE_STARTED &&
471 !(DeviceExtension->Flags & MOUSE_INITIALIZED))
472 {
473 /* Mouse is ready to be initialized */
474 Status = i8042ConnectMouseInterrupt(DeviceExtension->MouseExtension);
475 if (NT_SUCCESS(Status))
476 {
477 DeviceExtension->Flags |= MOUSE_INITIALIZED;
478 }
479 else
480 {
481 WARN_(I8042PRT, "i8042ConnectMouseInterrupt failed: %lx\n", Status);
482 }
483
484 /* Start the mouse */
485 Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt);
486 /* HACK: the mouse has already been reset in i8042DetectMouse. This second
487 reset prevents some touchpads/mice from working (Dell D531, D600).
488 See CORE-6901 */
489 if (!(i8042HwFlags & FL_INITHACK))
490 {
492 }
493 KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql);
494 }
495
496 return Status;
497}
_Out_ PKIRQL Irql
Definition: csq.h:179
static NTSTATUS i8042ConnectKeyboardInterrupt(IN PI8042_KEYBOARD_EXTENSION DeviceExtension)
Definition: pnp.c:267
static NTSTATUS i8042BasicDetect(IN PPORT_DEVICE_EXTENSION DeviceExtension)
Definition: pnp.c:77
static VOID i8042DetectMouse(IN PPORT_DEVICE_EXTENSION DeviceExtension)
Definition: pnp.c:165
static VOID i8042DetectKeyboard(IN PPORT_DEVICE_EXTENSION DeviceExtension)
Definition: pnp.c:129
static NTSTATUS i8042ConnectMouseInterrupt(IN PI8042_MOUSE_EXTENSION DeviceExtension)
Definition: pnp.c:317
static NTSTATUS EnableInterrupts(IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR FlagsToDisable, IN UCHAR FlagsToEnable)
Definition: pnp.c:380
ULONG i8042HwFlags
Definition: hwhacks.c:22
@ FL_INITHACK
Definition: i8042prt.h:454
KIRQL NTAPI KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
Definition: spinlock.c:154
VOID NTAPI KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, IN KIRQL OldIrql)
Definition: spinlock.c:171

Referenced by i8042PnpStartDevice().