|
|
1.1 root 1:
2: /*++
3:
4: Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
5:
6: Module Name:
7:
8: i8042dep.c
9:
10: Abstract:
11:
12: The initialization and hardware-dependent portions of
13: the Intel i8042 port driver which are common to both
14: the keyboard and the auxiliary (PS/2 mouse) device.
15:
16: Environment:
17:
18: Kernel mode only.
19:
20: Notes:
21:
22: NOTES: (Future/outstanding issues)
23:
24: - Powerfail not implemented.
25:
26: - Consolidate duplicate code, where possible and appropriate.
27:
28: - There is code ifdef'ed out (#if 0). This code was intended to
29: disable the device by setting the correct disable bit in the CCB.
30: It is supposedly correct to disable the device prior to sending a
31: command that will cause output to end up in the 8042 output buffer
32: (thereby possibly trashing something that was already in the output
33: buffer). Unfortunately, on rev K8 of the AMI 8042, disabling the
34: device where we do caused some commands to timeout, because
35: the keyboard was unable to return the expected bytes. Interestingly,
36: AMI claim that the device is only really disabled until the next ACK
37: comes back.
38:
39: Revision History:
40:
41: --*/
42:
43: #include "stdarg.h"
44: #include "stdio.h"
45: #include "string.h"
46: #include "ntddk.h"
47: #include "i8042prt.h"
48: #include "i8042log.h"
49:
50: //
51: // Use the alloc_text pragma to specify the driver initialization routines
52: // (they can be paged out).
53: //
54:
55: #ifdef ALLOC_PRAGMA
56: #pragma alloc_text(init,DriverEntry)
57: #pragma alloc_text(init,I8xServiceParameters)
58: #pragma alloc_text(init,I8xBuildResourceList)
59: #pragma alloc_text(init,I8xInitializeHardware)
60: #endif
61:
62:
63: NTSTATUS
64: DriverEntry(
65: IN PDRIVER_OBJECT DriverObject,
66: IN PUNICODE_STRING RegistryPath
67: )
68:
69: /*++
70:
71: Routine Description:
72:
73: This routine initializes the i8042 keyboard/mouse port driver.
74:
75: Arguments:
76:
77: DriverObject - Pointer to driver object created by system.
78:
79: RegistryPath - Pointer to the Unicode name of the registry path
80: for this driver.
81:
82: Return Value:
83:
84: The function value is the final status from the initialization operation.
85:
86: --*/
87:
88: {
89: PDEVICE_OBJECT portDeviceObject = NULL;
90: PDEVICE_EXTENSION deviceExtension = NULL;
91: DEVICE_EXTENSION tmpDeviceExtension;
92: NTSTATUS status = STATUS_SUCCESS;
93: KIRQL coordinatorIrql = 0;
94: I8042_INITIALIZE_DATA_CONTEXT initializeDataContext;
95: ULONG keyboardInterruptVector;
96: ULONG mouseInterruptVector;
97: KIRQL keyboardInterruptLevel;
98: KIRQL mouseInterruptLevel;
99: KAFFINITY keyboardAffinity;
100: KAFFINITY mouseAffinity;
101: ULONG addressSpace;
102: PHYSICAL_ADDRESS cardAddress;
103: PIO_ERROR_LOG_PACKET errorLogEntry;
104: ULONG uniqueErrorValue;
105: NTSTATUS errorCode = STATUS_SUCCESS;
106: ULONG dumpCount = 0;
107: PCM_RESOURCE_LIST resources = NULL;
108: ULONG resourceListSize = 0;
109: BOOLEAN conflictDetected;
110: ULONG i;
111: UNICODE_STRING fullKeyboardName;
112: UNICODE_STRING fullPointerName;
113: UNICODE_STRING baseKeyboardName;
114: UNICODE_STRING basePointerName;
115: UNICODE_STRING deviceNameSuffix;
116: UNICODE_STRING resourceDeviceClass;
117: UNICODE_STRING registryPath;
118:
119: #define NAME_MAX 256
120: WCHAR keyboardBuffer[NAME_MAX];
121: WCHAR pointerBuffer[NAME_MAX];
122:
123: #define DUMP_COUNT 4
124: ULONG dumpData[DUMP_COUNT];
125:
126: I8xPrint((1,"\n\nI8042PRT-I8042Initialize: enter\n"));
127:
128: //
129: // Zero-initialize various structures.
130: //
131:
132: RtlZeroMemory(&tmpDeviceExtension, sizeof(DEVICE_EXTENSION));
133: for (i = 0; i < DUMP_COUNT; i++)
134: dumpData[i] = 0;
135:
136: fullKeyboardName.MaximumLength = 0;
137: fullKeyboardName.Length = 0;
138: fullPointerName.MaximumLength = 0;
139: fullPointerName.Length = 0;
140: deviceNameSuffix.MaximumLength = 0;
141: deviceNameSuffix.Length = 0;
142: resourceDeviceClass.MaximumLength = 0;
143: resourceDeviceClass.Length = 0;
144: registryPath.MaximumLength = 0;
145:
146: RtlZeroMemory(keyboardBuffer, NAME_MAX * sizeof(WCHAR));
147: baseKeyboardName.Buffer = keyboardBuffer;
148: baseKeyboardName.Length = 0;
149: baseKeyboardName.MaximumLength = NAME_MAX * sizeof(WCHAR);
150:
151: RtlZeroMemory(pointerBuffer, NAME_MAX * sizeof(WCHAR));
152: basePointerName.Buffer = pointerBuffer;
153: basePointerName.Length = 0;
154: basePointerName.MaximumLength = NAME_MAX * sizeof(WCHAR);
155:
156: //
157: // Need to ensure that the registry path is null-terminated.
158: // Allocate pool to hold a null-terminated copy of the path.
159: //
160:
161: registryPath.Buffer = ExAllocatePool(
162: PagedPool,
163: RegistryPath->Length + sizeof(UNICODE_NULL)
164: );
165:
166: if (!registryPath.Buffer) {
167: I8xPrint((
168: 1,
169: "I8042PRT-I8042Initialize: Couldn't allocate pool for registry path\n"
170: ));
171:
172: status = STATUS_UNSUCCESSFUL;
173: errorCode = I8042_INSUFFICIENT_RESOURCES;
174: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 2;
175: dumpData[0] = (ULONG) RegistryPath->Length + sizeof(UNICODE_NULL);
176: dumpCount = 1;
177: goto I8042InitializeExit;
178:
179: } else {
180:
181: registryPath.Length = RegistryPath->Length + sizeof(UNICODE_NULL);
182: registryPath.MaximumLength = registryPath.Length;
183:
184: RtlZeroMemory(
185: registryPath.Buffer,
186: registryPath.Length
187: );
188:
189: RtlMoveMemory(
190: registryPath.Buffer,
191: RegistryPath->Buffer,
192: RegistryPath->Length
193: );
194:
195: }
196:
197: //
198: // Get the configuration information for this driver.
199: //
200:
201: I8xKeyboardConfiguration(
202: &tmpDeviceExtension,
203: ®istryPath,
204: &baseKeyboardName,
205: &basePointerName
206: );
207:
208: I8xMouseConfiguration(
209: &tmpDeviceExtension,
210: ®istryPath,
211: &baseKeyboardName,
212: &basePointerName
213: );
214:
215: if (tmpDeviceExtension.HardwarePresent == 0) {
216:
217: //
218: // There is neither a keyboard nor a mouse attached. Free
219: // resources and return with unsuccessful status.
220: //
221:
222: I8xPrint((1,"I8042PRT-I8042Initialize: No keyboard/mouse attached.\n"));
223: status = STATUS_NO_SUCH_DEVICE;
224: errorCode = I8042_NO_SUCH_DEVICE;
225: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 4;
226: goto I8042InitializeExit;
227:
228: } else if (!(tmpDeviceExtension.HardwarePresent & KEYBOARD_HARDWARE_PRESENT)) {
229: //
230: // Log a warning about the missing keyboard later on, but
231: // continue processing.
232: //
233:
234: I8xPrint((1,"I8042PRT-I8042Initialize: No keyboard attached.\n"));
235: status = STATUS_NO_SUCH_DEVICE;
236: errorCode = I8042_NO_KBD_DEVICE;
237: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 5;
238: dumpCount = 0;
239:
240: }
241: #if 0
242: //
243: // This code was removed so that we don't log an error when the mouse
244: // is not present. It was annoying to those who did not have
245: // PS/2 compatible mice to get the informational message on every boot.
246: //
247:
248: else if (!(tmpDeviceExtension.HardwarePresent & MOUSE_HARDWARE_PRESENT)) {
249:
250: //
251: // Log a warning about the missing mouse later on, but
252: // continue processing.
253: //
254:
255: I8xPrint((1,"I8042PRT-I8042Initialize: No mouse attached.\n"));
256: status = STATUS_NO_SUCH_DEVICE;
257: errorCode = I8042_NO_MOU_DEVICE;
258: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 6;
259: dumpCount = 0;
260: }
261: #endif
262:
263: //
264: // Set up space for the port's device object suffix. Note that
265: // we overallocate space for the suffix string because it is much
266: // easier than figuring out exactly how much space is required.
267: // The storage gets freed at the end of driver initialization, so
268: // who cares...
269: //
270:
271: RtlInitUnicodeString(
272: &deviceNameSuffix,
273: NULL
274: );
275:
276: deviceNameSuffix.MaximumLength =
277: (KEYBOARD_PORTS_MAXIMUM > POINTER_PORTS_MAXIMUM)?
278: KEYBOARD_PORTS_MAXIMUM * sizeof(WCHAR):
279: POINTER_PORTS_MAXIMUM * sizeof(WCHAR);
280: deviceNameSuffix.MaximumLength += sizeof(UNICODE_NULL);
281:
282: deviceNameSuffix.Buffer = ExAllocatePool(
283: PagedPool,
284: deviceNameSuffix.MaximumLength
285: );
286:
287: if (!deviceNameSuffix.Buffer) {
288:
289: I8xPrint((
290: 1,
291: "I8042PRT-I8042Initialize: Couldn't allocate string for device object suffix\n"
292: ));
293:
294: status = STATUS_UNSUCCESSFUL;
295: errorCode = I8042_INSUFFICIENT_RESOURCES;
296: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 8;
297: dumpData[0] = (ULONG) deviceNameSuffix.MaximumLength;
298: dumpCount = 1;
299: goto I8042InitializeExit;
300:
301: }
302:
303: RtlZeroMemory(
304: deviceNameSuffix.Buffer,
305: deviceNameSuffix.MaximumLength
306: );
307:
308: //
309: // Set up space for the port's full keyboard device object name.
310: //
311:
312: RtlInitUnicodeString(
313: &fullKeyboardName,
314: NULL
315: );
316:
317: fullKeyboardName.MaximumLength = sizeof(L"\\Device\\") +
318: baseKeyboardName.Length +
319: deviceNameSuffix.MaximumLength;
320:
321:
322: fullKeyboardName.Buffer = ExAllocatePool(
323: PagedPool,
324: fullKeyboardName.MaximumLength
325: );
326:
327: if (!fullKeyboardName.Buffer) {
328:
329: I8xPrint((
330: 1,
331: "I8042PRT-I8042Initialize: Couldn't allocate string for keyboard device object name\n"
332: ));
333:
334: status = STATUS_UNSUCCESSFUL;
335: errorCode = I8042_INSUFFICIENT_RESOURCES;
336: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 10;
337: dumpData[0] = (ULONG) fullKeyboardName.MaximumLength;
338: dumpCount = 1;
339: goto I8042InitializeExit;
340:
341: }
342:
343: RtlZeroMemory(
344: fullKeyboardName.Buffer,
345: fullKeyboardName.MaximumLength
346: );
347: RtlAppendUnicodeToString(
348: &fullKeyboardName,
349: L"\\Device\\"
350: );
351: RtlAppendUnicodeToString(
352: &fullKeyboardName,
353: baseKeyboardName.Buffer
354: );
355:
356: for (i = 0; i < KEYBOARD_PORTS_MAXIMUM; i++) {
357:
358: //
359: // Append the suffix to the device object name string. E.g., turn
360: // \Device\KeyboardPort into \Device\KeyboardPort0. Then we attempt
361: // to create the device object. If the device object already
362: // exists (because it was already created by another port driver),
363: // increment the suffix and try again.
364: //
365:
366: status = RtlIntegerToUnicodeString(
367: i,
368: 10,
369: &deviceNameSuffix
370: );
371:
372: if (!NT_SUCCESS(status)) {
373: break;
374: }
375:
376: RtlAppendUnicodeStringToString(
377: &fullKeyboardName,
378: &deviceNameSuffix
379: );
380:
381: I8xPrint((
382: 1,
383: "I8042PRT-I8042Initialize: Creating device object named %ws\n",
384: fullKeyboardName.Buffer
385: ));
386:
387: //
388: // Create device object for the i8042 keyboard port device.
389: // Note that we specify that this is a non-exclusive device.
390: // User code will be able to open this device, but they cannot
391: // do any real harm because all the device controls are internal
392: // device controls (and thus not accessible from user code).
393: //
394:
395: status = IoCreateDevice(
396: DriverObject,
397: sizeof(DEVICE_EXTENSION),
398: &fullKeyboardName,
399: FILE_DEVICE_8042_PORT,
400: 0,
401: FALSE,
402: &portDeviceObject
403: );
404:
405: if (NT_SUCCESS(status)) {
406:
407: //
408: // We've successfully created a device object.
409: //
410:
411: break;
412: } else {
413:
414: //
415: // We'll increment the suffix and try again. Note that we reset
416: // the length of the string here to get back to the beginning
417: // of the suffix portion of the name. Do not bother to
418: // zero the suffix, though, because the string for the
419: // incremented suffix will be at least as long as the previous
420: // one.
421: //
422:
423: fullKeyboardName.Length -= deviceNameSuffix.Length;
424: }
425: }
426:
427: if (!NT_SUCCESS(status)) {
428: I8xPrint((
429: 1,
430: "I8042PRT-I8042Initialize: Could not create port device object = %ws\n",
431: fullKeyboardName.Buffer
432: ));
433: errorCode = I8042_INSUFFICIENT_RESOURCES;
434: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 12;
435: dumpData[0] = (ULONG) i;
436: dumpCount = 1;
437: goto I8042InitializeExit;
438: }
439:
440: //
441: // Set up the device extension.
442: //
443:
444: deviceExtension =
445: (PDEVICE_EXTENSION)portDeviceObject->DeviceExtension;
446: *deviceExtension = tmpDeviceExtension;
447: deviceExtension->DeviceObject = portDeviceObject;
448:
449: //
450: // Set up the resource list prior to reporting resource usage.
451: //
452:
453: I8xBuildResourceList(deviceExtension, &resources, &resourceListSize);
454:
455: //
456: // Set up space for the resource device class name.
457: //
458:
459: RtlInitUnicodeString(
460: &resourceDeviceClass,
461: NULL
462: );
463:
464: resourceDeviceClass.MaximumLength = baseKeyboardName.Length +
465: sizeof(L"/") +
466: basePointerName.Length;
467:
468: resourceDeviceClass.Buffer = ExAllocatePool(
469: PagedPool,
470: resourceDeviceClass.MaximumLength
471: );
472:
473: if (!resourceDeviceClass.Buffer) {
474:
475: I8xPrint((
476: 1,
477: "I8042PRT-I8042Initialize: Couldn't allocate string for resource device class name\n"
478: ));
479:
480: status = STATUS_UNSUCCESSFUL;
481: errorCode = I8042_INSUFFICIENT_RESOURCES;
482: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 15;
483: dumpData[0] = (ULONG) resourceDeviceClass.MaximumLength;
484: dumpCount = 1;
485: goto I8042InitializeExit;
486:
487: }
488:
489: //
490: // Form the resource device class name from both the keyboard and
491: // the pointer base device names.
492: //
493:
494: RtlZeroMemory(
495: resourceDeviceClass.Buffer,
496: resourceDeviceClass.MaximumLength
497: );
498: RtlAppendUnicodeStringToString(
499: &resourceDeviceClass,
500: &baseKeyboardName
501: );
502: RtlAppendUnicodeToString(
503: &resourceDeviceClass,
504: L"/"
505: );
506: RtlAppendUnicodeStringToString(
507: &resourceDeviceClass,
508: &basePointerName
509: );
510:
511: //
512: // Report resource usage for the registry.
513: //
514:
515:
516: IoReportResourceUsage(
517: &resourceDeviceClass,
518: DriverObject,
519: NULL,
520: 0,
521: portDeviceObject,
522: resources,
523: resourceListSize,
524: FALSE,
525: &conflictDetected
526: );
527:
528: if (conflictDetected) {
529:
530: //
531: // Some other device already owns the i8042 ports or interrupts.
532: // Fatal error.
533: //
534:
535: I8xPrint((
536: 1,
537: "I8042PRT-I8042Initialize: Resource usage conflict\n"
538: ));
539:
540: //
541: // Set up error log info.
542: //
543:
544: errorCode = I8042_RESOURCE_CONFLICT;
545: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 20;
546: dumpData[0] = (ULONG)
547: resources->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Level;
548: dumpData[1] = (ULONG)
549: resources->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Level;
550: dumpData[2] = (ULONG)
551: resources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level;
552: dumpData[3] = (ULONG)
553: resources->List[0].PartialResourceList.PartialDescriptors[3].u.Interrupt.Level;
554: dumpCount = 4;
555:
556: goto I8042InitializeExit;
557:
558: }
559:
560: //
561: // Map the i8042 controller registers.
562: //
563:
564: for (i = 0; i < deviceExtension->Configuration.PortListCount; i++) {
565:
566: addressSpace = (deviceExtension->Configuration.PortList[i].Flags
567: & CM_RESOURCE_PORT_IO) == CM_RESOURCE_PORT_IO? 1:0;
568:
569: HalTranslateBusAddress(
570: deviceExtension->Configuration.InterfaceType,
571: deviceExtension->Configuration.BusNumber,
572: deviceExtension->Configuration.PortList[i].u.Port.Start,
573: &addressSpace,
574: &cardAddress
575: );
576:
577: if (!addressSpace) {
578:
579: deviceExtension->UnmapRegistersRequired = TRUE;
580: deviceExtension->DeviceRegisters[i] =
581: MmMapIoSpace(
582: cardAddress,
583: deviceExtension->Configuration.PortList[i].u.Port.Length,
584: FALSE
585: );
586:
587: } else {
588:
589: deviceExtension->UnmapRegistersRequired = FALSE;
590: deviceExtension->DeviceRegisters[i] = (PVOID)cardAddress.LowPart;
591:
592: }
593:
594: if (!deviceExtension->DeviceRegisters[i]) {
595:
596: I8xPrint((
597: 1,
598: "I8042PRT-I8042Initialize: Couldn't map the device registers.\n"
599: ));
600: status = STATUS_NONE_MAPPED;
601:
602: //
603: // Set up error log info.
604: //
605:
606: errorCode = I8042_REGISTERS_NOT_MAPPED;
607: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 30;
608: dumpData[0] = cardAddress.LowPart;
609: dumpCount = 1;
610:
611: goto I8042InitializeExit;
612:
613: }
614: }
615:
616: //
617: // Do buffered I/O.
618: //
619:
620: portDeviceObject->Flags |= DO_BUFFERED_IO;
621:
622: //
623: // Initialize the 8042 hardware to default values for the keyboard and
624: // mouse.
625: //
626:
627: I8xInitializeHardware(portDeviceObject);
628:
629: //
630: // Initialize shared spinlock used to synchronize access to the
631: // i8042 controller, keyboard, and mouse.
632: //
633:
634: KeInitializeSpinLock(&(deviceExtension->SharedInterruptSpinLock));
635:
636: //
637: // Allocate ring buffers for the keyboard and/or mouse input data.
638: //
639:
640: if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
641:
642: //
643: // Allocate memory for the keyboard data queue.
644: //
645:
646: deviceExtension->KeyboardExtension.InputData =
647: ExAllocatePool(
648: NonPagedPool,
649: deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength
650: );
651:
652: if (!deviceExtension->KeyboardExtension.InputData) {
653:
654: //
655: // Could not allocate memory for the keyboard data queue.
656: //
657:
658:
659: I8xPrint((
660: 1,
661: "I8042PRT-I8042Initialize: Could not allocate keyboard input data queue\n"
662: ));
663:
664: status = STATUS_INSUFFICIENT_RESOURCES;
665:
666: //
667: // Set up error log info.
668: //
669:
670: errorCode = I8042_NO_BUFFER_ALLOCATED;
671: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 50;
672: dumpData[0] =
673: deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength;
674: dumpCount = 1;
675:
676: goto I8042InitializeExit;
677: }
678:
679: deviceExtension->KeyboardExtension.DataEnd =
680: (PKEYBOARD_INPUT_DATA)
681: ((PCHAR) (deviceExtension->KeyboardExtension.InputData)
682: + deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength);
683:
684: //
685: // Zero the keyboard input data ring buffer.
686: //
687:
688: RtlZeroMemory(
689: deviceExtension->KeyboardExtension.InputData,
690: deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength
691: );
692:
693: }
694:
695: if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
696:
697: //
698: // Set up space for the port's full pointer device object name.
699: //
700:
701: RtlInitUnicodeString(
702: &fullPointerName,
703: NULL
704: );
705:
706: fullPointerName.MaximumLength = sizeof(L"\\Device\\") +
707: basePointerName.Length +
708: deviceNameSuffix.MaximumLength;
709:
710:
711: fullPointerName.Buffer = ExAllocatePool(
712: PagedPool,
713: fullPointerName.MaximumLength
714: );
715:
716: if (!fullPointerName.Buffer) {
717:
718: I8xPrint((
719: 1,
720: "I8042PRT-I8042Initialize: Couldn't allocate string for pointer device object name\n"
721: ));
722:
723: status = STATUS_UNSUCCESSFUL;
724: goto I8042InitializeExit;
725:
726: }
727:
728: RtlZeroMemory(
729: fullPointerName.Buffer,
730: fullPointerName.MaximumLength
731: );
732: RtlAppendUnicodeToString(
733: &fullPointerName,
734: L"\\Device\\"
735: );
736: RtlAppendUnicodeToString(
737: &fullPointerName,
738: basePointerName.Buffer
739: );
740:
741: RtlZeroMemory(
742: deviceNameSuffix.Buffer,
743: deviceNameSuffix.MaximumLength
744: );
745: deviceNameSuffix.Length = 0;
746:
747: for (i = 0; i < POINTER_PORTS_MAXIMUM; i++) {
748:
749: //
750: // Append the suffix to the device object name string. E.g., turn
751: // \Device\PointerPort into \Device\PointerPort0. Then we attempt
752: // to create a symbolic link to the keyboard device object. If
753: // a device object with the symbolic link name already
754: // exists (because it was created by another port driver),
755: // increment the suffix and try again.
756: //
757:
758: status = RtlIntegerToUnicodeString(
759: i,
760: 10,
761: &deviceNameSuffix
762: );
763:
764: if (!NT_SUCCESS(status)) {
765: break;
766: }
767:
768: RtlAppendUnicodeStringToString(
769: &fullPointerName,
770: &deviceNameSuffix
771: );
772:
773: I8xPrint((
774: 1,
775: "I8042PRT-I8042Initialize: pointer port name (symbolic link) = %ws\n",
776: fullPointerName.Buffer
777: ));
778:
779: //
780: // Set up a symbolic link so that the keyboard and mouse class
781: // drivers can access the port device object by different names.
782: //
783:
784: status = IoCreateSymbolicLink(
785: &fullPointerName,
786: &fullKeyboardName
787: );
788:
789: if (NT_SUCCESS(status)) {
790:
791: //
792: // We've successfully created a symbolic link.
793: //
794:
795: break;
796:
797: } else {
798:
799: //
800: // We'll increment the suffix and try again. Note that we reset
801: // the length of the string here to get back to the beginning
802: // of the suffix portion of the name. Do not bother to
803: // zero the suffix, though, because the string for the
804: // incremented suffix will be at least as long as the previous
805: // one.
806: //
807:
808: fullPointerName.Length -= deviceNameSuffix.Length;
809: }
810: }
811:
812: if (!NT_SUCCESS(status)) {
813: I8xPrint((
814: 1,
815: "I8042PRT-I8042Initialize: Could not create symbolic link = %ws\n",
816: fullPointerName.Buffer
817: ));
818: goto I8042InitializeExit;
819: }
820:
821: //
822: // Allocate memory for the mouse data queue.
823: //
824:
825: deviceExtension->MouseExtension.InputData =
826: ExAllocatePool(
827: NonPagedPool,
828: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength
829: );
830:
831: if (!deviceExtension->MouseExtension.InputData) {
832:
833: //
834: // Could not allocate memory for the mouse data queue.
835: //
836:
837: I8xPrint((
838: 1,
839: "I8042PRT-I8042Initialize: Could not allocate mouse input data queue\n"
840: ));
841:
842: status = STATUS_INSUFFICIENT_RESOURCES;
843:
844: //
845: // Set up error log info.
846: //
847:
848: errorCode = I8042_NO_BUFFER_ALLOCATED;
849: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 60;
850: dumpData[0] =
851: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength;
852: dumpCount = 1;
853:
854: goto I8042InitializeExit;
855: }
856:
857: deviceExtension->MouseExtension.DataEnd =
858: (PMOUSE_INPUT_DATA)
859: ((PCHAR) (deviceExtension->MouseExtension.InputData)
860: + deviceExtension->Configuration.MouseAttributes.InputDataQueueLength);
861:
862: //
863: // Zero the mouse input data ring buffer.
864: //
865:
866: RtlZeroMemory(
867: deviceExtension->MouseExtension.InputData,
868: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength
869: );
870:
871: }
872:
873: //
874: // Initialize the connection data.
875: //
876:
877: deviceExtension->KeyboardExtension.ConnectData.ClassDeviceObject = NULL;
878: deviceExtension->KeyboardExtension.ConnectData.ClassService = NULL;
879: deviceExtension->MouseExtension.ConnectData.ClassDeviceObject = NULL;
880: deviceExtension->MouseExtension.ConnectData.ClassService = NULL;
881:
882: //
883: // Initialize the input data queues.
884: //
885:
886: initializeDataContext.DeviceExtension = deviceExtension;
887: initializeDataContext.DeviceType = KeyboardDeviceType;
888: I8xInitializeDataQueue((PVOID) &initializeDataContext);
889:
890: initializeDataContext.DeviceType = MouseDeviceType;
891: I8xInitializeDataQueue((PVOID) &initializeDataContext);
892:
893: //
894: // Initialize the port completion DPC object in the device extension.
895: // This DPC routine handles the completion of successful set requests.
896: //
897:
898: deviceExtension->DpcInterlockKeyboard = -1;
899: deviceExtension->DpcInterlockMouse = -1;
900: IoInitializeDpcRequest(portDeviceObject, I8042CompletionDpc);
901:
902: //
903: // Initialize the port completion DPC for requests that exceed the
904: // maximum number of retries.
905: //
906:
907: KeInitializeDpc(
908: &deviceExtension->RetriesExceededDpc,
909: (PKDEFERRED_ROUTINE) I8042RetriesExceededDpc,
910: portDeviceObject
911: );
912:
913: //
914: // Initialize the port DPC queue to log overrun and internal
915: // driver errors.
916: //
917:
918: KeInitializeDpc(
919: &deviceExtension->ErrorLogDpc,
920: (PKDEFERRED_ROUTINE) I8042ErrorLogDpc,
921: portDeviceObject
922: );
923:
924: //
925: // Initialize the port keyboard ISR DPC and mouse ISR DPC. The ISR DPC
926: // is responsible for calling the connected class driver's callback
927: // routine to process the input data queue.
928: //
929:
930: KeInitializeDpc(
931: &deviceExtension->KeyboardIsrDpc,
932: (PKDEFERRED_ROUTINE) I8042KeyboardIsrDpc,
933: portDeviceObject
934: );
935:
936: KeInitializeDpc(
937: &deviceExtension->KeyboardIsrDpcRetry,
938: (PKDEFERRED_ROUTINE) I8042KeyboardIsrDpc,
939: portDeviceObject
940: );
941:
942: KeInitializeDpc(
943: &deviceExtension->MouseIsrDpc,
944: (PKDEFERRED_ROUTINE) I8042MouseIsrDpc,
945: portDeviceObject
946: );
947:
948: KeInitializeDpc(
949: &deviceExtension->MouseIsrDpcRetry,
950: (PKDEFERRED_ROUTINE) I8042MouseIsrDpc,
951: portDeviceObject
952: );
953:
954: //
955: // Initialize the port DPC queue for timeouts.
956: //
957:
958: KeInitializeDpc(
959: &deviceExtension->TimeOutDpc,
960: (PKDEFERRED_ROUTINE) I8042TimeOutDpc,
961: portDeviceObject
962: );
963:
964: //
965: // Initialize the i8042 command timer.
966: //
967:
968: KeInitializeTimer(&deviceExtension->CommandTimer);
969: deviceExtension->TimerCount = I8042_ASYNC_NO_TIMEOUT;
970:
971: //
972: // Initialize the keyboard and mouse data consumption timers.
973: //
974:
975: KeInitializeTimer(&deviceExtension->KeyboardExtension.DataConsumptionTimer);
976: KeInitializeTimer(&deviceExtension->MouseExtension.DataConsumptionTimer);
977:
978: //
979: // From the Hal, get the keyboard and mouse interrupt vectors and levels.
980: //
981:
982: keyboardInterruptVector = HalGetInterruptVector(
983: deviceExtension->Configuration.InterfaceType,
984: deviceExtension->Configuration.BusNumber,
985: deviceExtension->Configuration.KeyboardInterrupt.u.Interrupt.Level,
986: deviceExtension->Configuration.KeyboardInterrupt.u.Interrupt.Vector,
987: &keyboardInterruptLevel,
988: &keyboardAffinity
989: );
990:
991: mouseInterruptVector = HalGetInterruptVector(
992: deviceExtension->Configuration.InterfaceType,
993: deviceExtension->Configuration.BusNumber,
994: deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Level,
995: deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Vector,
996: &mouseInterruptLevel,
997: &mouseAffinity
998: );
999:
1000: //
1001: // Determine the coordinator interrupt object
1002: // based on which device has the highest IRQL.
1003: //
1004:
1005: if ((deviceExtension->HardwarePresent &
1006: (KEYBOARD_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT)) ==
1007: (KEYBOARD_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT)) {
1008:
1009: coordinatorIrql = (keyboardInterruptLevel > mouseInterruptLevel) ?
1010: keyboardInterruptLevel: mouseInterruptLevel;
1011: }
1012:
1013: //
1014: // Initialize and connect the interrupt object for the mouse.
1015: // Determine the coordinator interrupt object based on which device
1016: // has the highest IRQL.
1017: //
1018:
1019: if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
1020:
1021: status = IoConnectInterrupt(
1022: &(deviceExtension->MouseInterruptObject),
1023: (PKSERVICE_ROUTINE) I8042MouseInterruptService,
1024: (PVOID) portDeviceObject,
1025: &(deviceExtension->SharedInterruptSpinLock),
1026: mouseInterruptVector,
1027: mouseInterruptLevel,
1028: (KIRQL) ((coordinatorIrql == (KIRQL)0) ?
1029: mouseInterruptLevel : coordinatorIrql),
1030: deviceExtension->Configuration.MouseInterrupt.Flags
1031: == CM_RESOURCE_INTERRUPT_LATCHED ?
1032: Latched : LevelSensitive,
1033: deviceExtension->Configuration.MouseInterrupt.ShareDisposition,
1034: mouseAffinity,
1035: deviceExtension->Configuration.FloatingSave
1036: );
1037:
1038: if (!NT_SUCCESS(status)) {
1039:
1040: //
1041: // Failed to install. Free up resources before exiting.
1042: //
1043:
1044: I8xPrint((
1045: 1,
1046: "I8042PRT-I8042Initialize: Could not connect mouse interrupt\n"
1047: ));
1048:
1049: //
1050: // Set up error log info.
1051: //
1052:
1053: errorCode = I8042_NO_INTERRUPT_CONNECTED;
1054: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 70;
1055: dumpData[0] = mouseInterruptLevel;
1056: dumpCount = 1;
1057:
1058: goto I8042InitializeExit;
1059:
1060: }
1061:
1062: //
1063: // Enable mouse transmissions, now that the interrupts are enabled.
1064: // We've held off transmissions until now, in an attempt to
1065: // keep the driver's notion of mouse input data state in sync
1066: // with the mouse hardware.
1067: //
1068:
1069: status = I8xMouseEnableTransmission(portDeviceObject);
1070:
1071: if (!NT_SUCCESS(status)) {
1072:
1073: //
1074: // Couldn't enable mouse transmissions. Continue on, anyway.
1075: //
1076:
1077: I8xPrint((
1078: 1,
1079: "I8042PRT-I8042Initialize: Could not enable mouse transmission\n"
1080: ));
1081:
1082: status = STATUS_SUCCESS;
1083: }
1084:
1085: }
1086:
1087: //
1088: // Initialize and connect the interrupt object for the keyboard.
1089: // Determine the coordinator interrupt object based on which device
1090: // has the highest IRQL.
1091: //
1092:
1093: if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
1094:
1095: status = IoConnectInterrupt(
1096: &(deviceExtension->KeyboardInterruptObject),
1097: (PKSERVICE_ROUTINE) I8042KeyboardInterruptService,
1098: (PVOID) portDeviceObject,
1099: &(deviceExtension->SharedInterruptSpinLock),
1100: keyboardInterruptVector,
1101: keyboardInterruptLevel,
1102: (KIRQL) ((coordinatorIrql == (KIRQL)0) ?
1103: keyboardInterruptLevel : coordinatorIrql),
1104: deviceExtension->Configuration.KeyboardInterrupt.Flags
1105: == CM_RESOURCE_INTERRUPT_LATCHED ?
1106: Latched : LevelSensitive,
1107: deviceExtension->Configuration.KeyboardInterrupt.ShareDisposition,
1108: keyboardAffinity,
1109: deviceExtension->Configuration.FloatingSave
1110: );
1111:
1112: if (!NT_SUCCESS(status)) {
1113:
1114: //
1115: // Failed to install. Free up resources before exiting.
1116: //
1117:
1118: I8xPrint((
1119: 1,
1120: "I8042PRT-I8042Initialize: Could not connect keyboard interrupt\n"
1121: ));
1122:
1123: //
1124: // Set up error log info.
1125: //
1126:
1127: errorCode = I8042_NO_INTERRUPT_CONNECTED;
1128: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 80;
1129: dumpData[0] = keyboardInterruptLevel;
1130: dumpCount = 1;
1131:
1132: goto I8042InitializeExit;
1133:
1134: }
1135:
1136: }
1137:
1138: //
1139: // Once initialization is finished, load the device map information
1140: // into the registry so that setup can determine which pointer port
1141: // and keyboard port are active.
1142: //
1143:
1144: if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
1145:
1146: status = RtlWriteRegistryValue(
1147: RTL_REGISTRY_DEVICEMAP,
1148: baseKeyboardName.Buffer,
1149: fullKeyboardName.Buffer,
1150: REG_SZ,
1151: registryPath.Buffer,
1152: registryPath.Length
1153: );
1154:
1155: if (!NT_SUCCESS(status)) {
1156:
1157: I8xPrint((
1158: 1,
1159: "I8042PRT-I8042Initialize: Could not store keyboard name in DeviceMap\n"
1160: ));
1161:
1162: errorCode = I8042_NO_DEVICEMAP_CREATED;
1163: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 90;
1164: dumpCount = 0;
1165:
1166: goto I8042InitializeExit;
1167:
1168: } else {
1169:
1170: I8xPrint((
1171: 1,
1172: "I8042PRT-I8042Initialize: Stored keyboard name in DeviceMap\n"
1173: ));
1174: }
1175: }
1176:
1177: if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
1178:
1179: status = RtlWriteRegistryValue(
1180: RTL_REGISTRY_DEVICEMAP,
1181: basePointerName.Buffer,
1182: fullPointerName.Buffer,
1183: REG_SZ,
1184: registryPath.Buffer,
1185: registryPath.Length
1186: );
1187:
1188: if (!NT_SUCCESS(status)) {
1189:
1190: I8xPrint((
1191: 1,
1192: "I8042PRT-I8042Initialize: Could not store pointer name in DeviceMap\n"
1193: ));
1194:
1195: errorCode = I8042_NO_DEVICEMAP_CREATED;
1196: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 95;
1197: dumpCount = 0;
1198:
1199: goto I8042InitializeExit;
1200:
1201: } else {
1202:
1203: I8xPrint((
1204: 1,
1205: "I8042PRT-I8042Initialize: Stored pointer name in DeviceMap\n"
1206: ));
1207: }
1208: }
1209:
1210: ASSERT(status == STATUS_SUCCESS);
1211:
1212: //
1213: // Set up the device driver entry points.
1214: //
1215:
1216: DriverObject->DriverStartIo = I8042StartIo;
1217: DriverObject->MajorFunction[IRP_MJ_CREATE] = I8042OpenCloseDispatch;
1218: DriverObject->MajorFunction[IRP_MJ_CLOSE] = I8042OpenCloseDispatch;
1219: DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] =
1220: I8042Flush;
1221: DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
1222: I8042InternalDeviceControl;
1223: //
1224: // NOTE: Don't allow this driver to unload. Otherwise, we would set
1225: // DriverObject->DriverUnload = I8042Unload.
1226: //
1227:
1228: I8042InitializeExit:
1229:
1230: if (errorCode != STATUS_SUCCESS) {
1231:
1232: //
1233: // Log an error/warning message.
1234: //
1235:
1236: errorLogEntry = (PIO_ERROR_LOG_PACKET)
1237: IoAllocateErrorLogEntry(
1238: (portDeviceObject == NULL) ?
1239: (PVOID) DriverObject : (PVOID) portDeviceObject,
1240: (UCHAR) (sizeof(IO_ERROR_LOG_PACKET)
1241: + (dumpCount * sizeof(ULONG)))
1242: );
1243:
1244: if (errorLogEntry != NULL) {
1245:
1246: errorLogEntry->ErrorCode = errorCode;
1247: errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG);
1248: errorLogEntry->SequenceNumber = 0;
1249: errorLogEntry->MajorFunctionCode = 0;
1250: errorLogEntry->IoControlCode = 0;
1251: errorLogEntry->RetryCount = 0;
1252: errorLogEntry->UniqueErrorValue = uniqueErrorValue;
1253: errorLogEntry->FinalStatus = status;
1254: for (i = 0; i < dumpCount; i++)
1255: errorLogEntry->DumpData[i] = dumpData[i];
1256:
1257: IoWriteErrorLogEntry(errorLogEntry);
1258: }
1259: }
1260:
1261: if (!NT_SUCCESS(status)) {
1262:
1263: //
1264: // The initialization failed. Cleanup resources before exiting.
1265: //
1266: // N.B. It is okay to disconnect the interrupt even if it never
1267: // got connected.
1268: //
1269:
1270: //
1271: // Note: No need/way to undo the KeInitializeDpc or
1272: // KeInitializeTimer calls.
1273: //
1274:
1275: //
1276: // The initialization failed. Cleanup resources before exiting.
1277: //
1278:
1279: if (resources) {
1280:
1281: //
1282: // Call IoReportResourceUsage to remove the resources from
1283: // the map.
1284: //
1285:
1286: resources->Count = 0;
1287:
1288: IoReportResourceUsage(
1289: &resourceDeviceClass,
1290: DriverObject,
1291: NULL,
1292: 0,
1293: portDeviceObject,
1294: resources,
1295: resourceListSize,
1296: FALSE,
1297: &conflictDetected
1298: );
1299:
1300: }
1301:
1302: if (deviceExtension) {
1303: if (deviceExtension->KeyboardInterruptObject != NULL)
1304: IoDisconnectInterrupt(deviceExtension->KeyboardInterruptObject);
1305: if (deviceExtension->MouseInterruptObject != NULL)
1306: IoDisconnectInterrupt(deviceExtension->MouseInterruptObject);
1307: if (deviceExtension->KeyboardExtension.InputData)
1308: ExFreePool(deviceExtension->KeyboardExtension.InputData);
1309: if (deviceExtension->MouseExtension.InputData)
1310: ExFreePool(deviceExtension->MouseExtension.InputData);
1311:
1312: if (deviceExtension->UnmapRegistersRequired) {
1313: for (i = 0;
1314: i < deviceExtension->Configuration.PortListCount; i++){
1315: if (deviceExtension->DeviceRegisters[i]) {
1316: MmUnmapIoSpace(
1317: deviceExtension->DeviceRegisters[i],
1318: deviceExtension->Configuration.PortList[i].u.Port.Length);
1319: }
1320: }
1321: }
1322: }
1323:
1324:
1325: if (portDeviceObject) {
1326: if (fullPointerName.Length > 0) {
1327: IoDeleteSymbolicLink(&fullPointerName);
1328: }
1329: IoDeleteDevice(portDeviceObject);
1330: }
1331: }
1332:
1333: //
1334: // Free the resource list.
1335: //
1336: // N.B. If we ever decide to hang on to the resource list instead,
1337: // we need to allocate it from non-paged pool (it is now paged pool).
1338: //
1339:
1340: if (resources) {
1341: ExFreePool(resources);
1342: }
1343:
1344: //
1345: // Free the unicode strings for device names.
1346: //
1347:
1348: if (deviceNameSuffix.MaximumLength != 0)
1349: ExFreePool(deviceNameSuffix.Buffer);
1350: if (fullKeyboardName.MaximumLength != 0)
1351: ExFreePool(fullKeyboardName.Buffer);
1352: if (fullPointerName.MaximumLength != 0)
1353: ExFreePool(fullPointerName.Buffer);
1354: if (resourceDeviceClass.MaximumLength != 0)
1355: ExFreePool(resourceDeviceClass.Buffer);
1356: if (registryPath.MaximumLength != 0)
1357: ExFreePool(registryPath.Buffer);
1358:
1359: I8xPrint((1,"I8042PRT-I8042Initialize: exit\n"));
1360:
1361: return(status);
1362:
1363: }
1364:
1365: VOID
1366: I8042Unload(
1367: IN PDRIVER_OBJECT DriverObject
1368: )
1369: {
1370: UNREFERENCED_PARAMETER(DriverObject);
1371:
1372: I8xPrint((2, "I8042PRT-I8042Unload: enter\n"));
1373: I8xPrint((2, "I8042PRT-I8042Unload: exit\n"));
1374: }
1375:
1376: VOID
1377: I8xBuildResourceList(
1378: IN PDEVICE_EXTENSION DeviceExtension,
1379: OUT PCM_RESOURCE_LIST *ResourceList,
1380: OUT PULONG ResourceListSize
1381: )
1382:
1383: /*++
1384:
1385: Routine Description:
1386:
1387: Creates a resource list that is used to query or report resource usage.
1388:
1389: Arguments:
1390:
1391: DeviceExtension - Pointer to the port's device extension.
1392:
1393: ResourceList - Pointer to a pointer to the resource list to be allocated
1394: and filled.
1395:
1396: ResourceListSize - Pointer to the returned size of the resource
1397: list (in bytes).
1398:
1399: Return Value:
1400:
1401: None. If the call succeeded, *ResourceList points to the built
1402: resource list and *ResourceListSize is set to the size (in bytes)
1403: of the resource list; otherwise, *ResourceList is NULL.
1404:
1405: Note:
1406:
1407: Memory may be allocated here for *ResourceList. It must be
1408: freed up by the caller, by calling ExFreePool();
1409:
1410: --*/
1411:
1412: {
1413: ULONG count = 0;
1414: ULONG i = 0;
1415: ULONG j = 0;
1416: #define DUMP_COUNT 4
1417: ULONG dumpData[DUMP_COUNT];
1418:
1419: count += DeviceExtension->Configuration.PortListCount;
1420: if (DeviceExtension->Configuration.KeyboardInterrupt.Type
1421: == CmResourceTypeInterrupt)
1422: count += 1;
1423: if (DeviceExtension->Configuration.MouseInterrupt.Type
1424: == CmResourceTypeInterrupt)
1425: count += 1;
1426:
1427: *ResourceListSize = sizeof(CM_RESOURCE_LIST) +
1428: ((count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
1429:
1430: *ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool(
1431: PagedPool,
1432: *ResourceListSize
1433: );
1434:
1435: //
1436: // Return NULL if the structure could not be allocated.
1437: // Otherwise, fill in the resource list.
1438: //
1439:
1440: if (!*ResourceList) {
1441:
1442: //
1443: // Could not allocate memory for the resource list.
1444: //
1445:
1446: I8xPrint((
1447: 1,
1448: "I8042PRT-I8xBuildResourceList: Could not allocate resource list\n"
1449: ));
1450:
1451: //
1452: // Log an error.
1453: //
1454:
1455: dumpData[0] = *ResourceListSize;
1456: *ResourceListSize = 0;
1457:
1458: I8xLogError(
1459: DeviceExtension->DeviceObject,
1460: I8042_INSUFFICIENT_RESOURCES,
1461: I8042_ERROR_VALUE_BASE + 110,
1462: STATUS_INSUFFICIENT_RESOURCES,
1463: dumpData,
1464: 1
1465: );
1466:
1467: return;
1468: }
1469:
1470: RtlZeroMemory(
1471: *ResourceList,
1472: *ResourceListSize
1473: );
1474:
1475: //
1476: // Concoct one full resource descriptor.
1477: //
1478:
1479: (*ResourceList)->Count = 1;
1480:
1481: (*ResourceList)->List[0].InterfaceType =
1482: DeviceExtension->Configuration.InterfaceType;
1483: (*ResourceList)->List[0].BusNumber =
1484: DeviceExtension->Configuration.BusNumber;
1485:
1486: //
1487: // Build the partial resource descriptors for interrupt and port
1488: // resources from the saved values.
1489: //
1490:
1491: (*ResourceList)->List[0].PartialResourceList.Count = count;
1492: if (DeviceExtension->Configuration.KeyboardInterrupt.Type
1493: == CmResourceTypeInterrupt)
1494: (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] =
1495: DeviceExtension->Configuration.KeyboardInterrupt;
1496: if (DeviceExtension->Configuration.MouseInterrupt.Type
1497: == CmResourceTypeInterrupt)
1498: (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] =
1499: DeviceExtension->Configuration.MouseInterrupt;
1500:
1501: for (j = 0; j < DeviceExtension->Configuration.PortListCount; j++) {
1502: (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] =
1503: DeviceExtension->Configuration.PortList[j];
1504: }
1505:
1506: }
1507:
1508: VOID
1509: I8xDrainOutputBuffer(
1510: IN PUCHAR DataAddress,
1511: IN PUCHAR CommandAddress
1512: )
1513:
1514: /*++
1515:
1516: Routine Description:
1517:
1518: This routine drains the i8042 controller's output buffer. This gets
1519: rid of stale data that may have resulted from the user hitting a key
1520: or moving the mouse, prior to the execution of I8042Initialize.
1521:
1522: Arguments:
1523:
1524: DataAddress - Pointer to the data address to read/write from/to.
1525:
1526: CommandAddress - Pointer to the command/status address to
1527: read/write from/to.
1528:
1529:
1530: Return Value:
1531:
1532: None.
1533:
1534: --*/
1535:
1536: {
1537: UCHAR byte;
1538:
1539: I8xPrint((3, "I8042PRT-I8xDrainOutputBuffer: enter\n"));
1540:
1541: while (I8X_GET_STATUS_BYTE(CommandAddress) & OUTPUT_BUFFER_FULL) {
1542:
1543: //
1544: // Eat the output buffer byte.
1545: //
1546:
1547: byte = I8X_GET_DATA_BYTE(DataAddress);
1548: }
1549:
1550: I8xPrint((3, "I8042PRT-I8xDrainOutputBuffer: exit\n"));
1551: }
1552:
1553: VOID
1554: I8xGetByteAsynchronous(
1555: IN CCHAR DeviceType,
1556: IN PDEVICE_EXTENSION DeviceExtension,
1557: OUT PUCHAR Byte
1558: )
1559:
1560: /*++
1561:
1562: Routine Description:
1563:
1564: This routine reads a data byte from the controller or keyboard
1565: or mouse, asynchronously.
1566:
1567: Arguments:
1568:
1569: DeviceType - Specifies which device (i8042 controller, keyboard, or
1570: mouse) to read the byte from.
1571:
1572: DeviceExtension - Pointer to the device extension.
1573:
1574: Byte - Pointer to the location to store the byte read from the hardware.
1575:
1576: Return Value:
1577:
1578: None.
1579:
1580: As a side-effect, the byte value read is stored. If the hardware was not
1581: ready for output or did not respond, the byte value is not stored.
1582:
1583: --*/
1584:
1585: {
1586: ULONG i;
1587: UCHAR response;
1588: UCHAR desiredMask;
1589:
1590: I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: enter\n"));
1591:
1592: if (DeviceType == KeyboardDeviceType) {
1593: I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: keyboard\n"));
1594: } else if (DeviceType == MouseDeviceType) {
1595: I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: mouse\n"));
1596: } else {
1597: I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: 8042 controller\n"));
1598: }
1599:
1600: i = 0;
1601: desiredMask = (DeviceType == MouseDeviceType)?
1602: (UCHAR) (OUTPUT_BUFFER_FULL | MOUSE_OUTPUT_BUFFER_FULL):
1603: (UCHAR) OUTPUT_BUFFER_FULL;
1604:
1605: //
1606: // Poll until we get back a controller status value that indicates
1607: // the output buffer is full. If we want to read a byte from the mouse,
1608: // further ensure that the auxiliary device output buffer full bit is
1609: // set.
1610: //
1611:
1612: while ((i < (ULONG)DeviceExtension->Configuration.PollingIterations) &&
1613: ((UCHAR)((response =
1614: I8X_GET_STATUS_BYTE(DeviceExtension->DeviceRegisters[CommandPort]))
1615: & desiredMask) != desiredMask)) {
1616:
1617: if (response & OUTPUT_BUFFER_FULL) {
1618:
1619: //
1620: // There is something in the i8042 output buffer, but it
1621: // isn't from the device we want to get a byte from. Eat
1622: // the byte and try again.
1623: //
1624:
1625: *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
1626: I8xPrint((2, "I8042PRT-I8xGetByteAsynchronous: ate 0x%x\n", *Byte));
1627: } else {
1628:
1629: //
1630: // Try again.
1631: //
1632:
1633: i += 1;
1634:
1635: I8xPrint((
1636: 2,
1637: "I8042PRT-I8xGetByteAsynchronous: wait for correct status\n"
1638: ));
1639: }
1640:
1641: }
1642: if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
1643: I8xPrint((2, "I8042PRT-I8xGetByteAsynchronous: timing out\n"));
1644: return;
1645: }
1646:
1647: //
1648: // Grab the byte from the hardware.
1649: //
1650:
1651: *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
1652:
1653: I8xPrint((
1654: 3,
1655: "I8042PRT-I8xGetByteAsynchronous: exit with Byte 0x%x\n", *Byte
1656: ));
1657:
1658: }
1659:
1660: NTSTATUS
1661: I8xGetBytePolled(
1662: IN CCHAR DeviceType,
1663: IN PDEVICE_EXTENSION DeviceExtension,
1664: OUT PUCHAR Byte
1665: )
1666:
1667: /*++
1668:
1669: Routine Description:
1670:
1671: This routine reads a data byte from the controller or keyboard
1672: or mouse, in polling mode.
1673:
1674: Arguments:
1675:
1676: DeviceType - Specifies which device (i8042 controller, keyboard, or
1677: mouse) to read the byte from.
1678:
1679: DeviceExtension - Pointer to the device extension.
1680:
1681: Byte - Pointer to the location to store the byte read from the hardware.
1682:
1683: Return Value:
1684:
1685: STATUS_IO_TIMEOUT - The hardware was not ready for output or did not
1686: respond.
1687:
1688: STATUS_SUCCESS - The byte was successfully read from the hardware.
1689:
1690: As a side-effect, the byte value read is stored.
1691:
1692: --*/
1693:
1694: {
1695: ULONG i;
1696: UCHAR response;
1697: UCHAR desiredMask;
1698:
1699: I8xPrint((3, "I8042PRT-I8xGetBytePolled: enter\n"));
1700:
1701: if (DeviceType == KeyboardDeviceType) {
1702: I8xPrint((3, "I8042PRT-I8xGetBytePolled: keyboard\n"));
1703: } else if (DeviceType == MouseDeviceType) {
1704: I8xPrint((3, "I8042PRT-I8xGetBytePolled: mouse\n"));
1705: } else {
1706: I8xPrint((3, "I8042PRT-I8xGetBytePolled: 8042 controller\n"));
1707: }
1708:
1709: i = 0;
1710: desiredMask = (DeviceType == MouseDeviceType)?
1711: (UCHAR) (OUTPUT_BUFFER_FULL | MOUSE_OUTPUT_BUFFER_FULL):
1712: (UCHAR) OUTPUT_BUFFER_FULL;
1713:
1714:
1715: //
1716: // Poll until we get back a controller status value that indicates
1717: // the output buffer is full. If we want to read a byte from the mouse,
1718: // further ensure that the auxiliary device output buffer full bit is
1719: // set.
1720: //
1721:
1722: while ((i < (ULONG)DeviceExtension->Configuration.PollingIterations) &&
1723: ((UCHAR)((response =
1724: I8X_GET_STATUS_BYTE(DeviceExtension->DeviceRegisters[CommandPort]))
1725: & desiredMask) != desiredMask)) {
1726: if (response & OUTPUT_BUFFER_FULL) {
1727:
1728: //
1729: // There is something in the i8042 output buffer, but it
1730: // isn't from the device we want to get a byte from. Eat
1731: // the byte and try again.
1732: //
1733:
1734: *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
1735: I8xPrint((2, "I8042PRT-I8xGetBytePolled: ate 0x%x\n", *Byte));
1736: } else {
1737: I8xPrint((2, "I8042PRT-I8xGetBytePolled: stalling\n"));
1738: KeStallExecutionProcessor(
1739: DeviceExtension->Configuration.StallMicroseconds
1740: );
1741: i += 1;
1742: }
1743: }
1744: if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
1745: I8xPrint((2, "I8042PRT-I8xGetBytePolled: timing out\n"));
1746: return(STATUS_IO_TIMEOUT);
1747: }
1748:
1749: //
1750: // Grab the byte from the hardware, and return success.
1751: //
1752:
1753: *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
1754:
1755: I8xPrint((3, "I8042PRT-I8xGetBytePolled: exit with Byte 0x%x\n", *Byte));
1756:
1757: return(STATUS_SUCCESS);
1758:
1759: }
1760:
1761: NTSTATUS
1762: I8xGetControllerCommand(
1763: IN ULONG HardwareDisableEnableMask,
1764: IN PDEVICE_EXTENSION DeviceExtension,
1765: OUT PUCHAR Byte
1766: )
1767:
1768: /*++
1769:
1770: Routine Description:
1771:
1772: This routine reads the 8042 Controller Command Byte.
1773:
1774: Arguments:
1775:
1776: HardwareDisableEnableMask - Specifies which hardware devices, if any,
1777: need to be disabled/enable around the operation.
1778:
1779: DeviceExtension - Pointer to the device extension.
1780:
1781: Byte - Pointer to the location into which the Controller Command Byte is
1782: read.
1783:
1784: Return Value:
1785:
1786: Status is returned.
1787:
1788: --*/
1789:
1790: {
1791: NTSTATUS status;
1792: NTSTATUS secondStatus;
1793:
1794: I8xPrint((3, "I8042PRT-I8xGetControllerCommand: enter\n"));
1795:
1796: //
1797: // Disable the specified devices before sending the command to
1798: // read the Controller Command Byte (otherwise data in the output
1799: // buffer might get trashed).
1800: //
1801:
1802: if (HardwareDisableEnableMask & KEYBOARD_HARDWARE_PRESENT) {
1803: status = I8xPutBytePolled(
1804: (CCHAR) CommandPort,
1805: NO_WAIT_FOR_ACKNOWLEDGE,
1806: (CCHAR) UndefinedDeviceType,
1807: DeviceExtension,
1808: (UCHAR) I8042_DISABLE_KEYBOARD_DEVICE
1809: );
1810: if (!NT_SUCCESS(status)) {
1811: return(status);
1812: }
1813: }
1814:
1815: if (HardwareDisableEnableMask & MOUSE_HARDWARE_PRESENT) {
1816: status = I8xPutBytePolled(
1817: (CCHAR) CommandPort,
1818: NO_WAIT_FOR_ACKNOWLEDGE,
1819: (CCHAR) UndefinedDeviceType,
1820: DeviceExtension,
1821: (UCHAR) I8042_DISABLE_MOUSE_DEVICE
1822: );
1823: if (!NT_SUCCESS(status)) {
1824:
1825: //
1826: // Re-enable the keyboard device, if necessary, before returning.
1827: //
1828:
1829: if (HardwareDisableEnableMask & KEYBOARD_HARDWARE_PRESENT) {
1830: secondStatus = I8xPutBytePolled(
1831: (CCHAR) CommandPort,
1832: NO_WAIT_FOR_ACKNOWLEDGE,
1833: (CCHAR) UndefinedDeviceType,
1834: DeviceExtension,
1835: (UCHAR) I8042_ENABLE_KEYBOARD_DEVICE
1836: );
1837: }
1838: return(status);
1839: }
1840: }
1841:
1842: //
1843: // Send a command to the i8042 controller to read the Controller
1844: // Command Byte.
1845: //
1846:
1847: status = I8xPutBytePolled(
1848: (CCHAR) CommandPort,
1849: NO_WAIT_FOR_ACKNOWLEDGE,
1850: (CCHAR) UndefinedDeviceType,
1851: DeviceExtension,
1852: (UCHAR) I8042_READ_CONTROLLER_COMMAND_BYTE
1853: );
1854:
1855: //
1856: // Read the byte from the i8042 data port.
1857: //
1858:
1859: if (NT_SUCCESS(status)) {
1860: status = I8xGetBytePolled(
1861: (CCHAR) ControllerDeviceType,
1862: DeviceExtension,
1863: Byte
1864: );
1865: }
1866:
1867: //
1868: // Re-enable the specified devices. Clear the device disable
1869: // bits in the Controller Command Byte by hand (they got set when
1870: // we disabled the devices, so the CCB we read lacked the real
1871: // device disable bit information).
1872: //
1873:
1874: if (HardwareDisableEnableMask & KEYBOARD_HARDWARE_PRESENT) {
1875: secondStatus = I8xPutBytePolled(
1876: (CCHAR) CommandPort,
1877: NO_WAIT_FOR_ACKNOWLEDGE,
1878: (CCHAR) UndefinedDeviceType,
1879: DeviceExtension,
1880: (UCHAR) I8042_ENABLE_KEYBOARD_DEVICE
1881: );
1882: if (!NT_SUCCESS(secondStatus)) {
1883: if (NT_SUCCESS(status))
1884: status = secondStatus;
1885: } else if (status == STATUS_SUCCESS) {
1886: *Byte &= (UCHAR) ~CCB_DISABLE_KEYBOARD_DEVICE;
1887: }
1888:
1889: }
1890:
1891: if (HardwareDisableEnableMask & MOUSE_HARDWARE_PRESENT) {
1892: secondStatus = I8xPutBytePolled(
1893: (CCHAR) CommandPort,
1894: NO_WAIT_FOR_ACKNOWLEDGE,
1895: (CCHAR) UndefinedDeviceType,
1896: DeviceExtension,
1897: (UCHAR) I8042_ENABLE_MOUSE_DEVICE
1898: );
1899: if (!NT_SUCCESS(secondStatus)) {
1900: if (NT_SUCCESS(status))
1901: status = secondStatus;
1902: } else if (NT_SUCCESS(status)) {
1903: *Byte &= (UCHAR) ~CCB_DISABLE_MOUSE_DEVICE;
1904: }
1905: }
1906:
1907: I8xPrint((3, "I8042PRT-I8xGetControllerCommand: exit\n"));
1908:
1909: return(status);
1910:
1911: }
1912:
1913: VOID
1914: I8xInitializeHardware(
1915: IN PDEVICE_OBJECT DeviceObject
1916: )
1917:
1918: /*++
1919:
1920: Routine Description:
1921:
1922: This routine initializes the i8042 controller, keyboard, and mouse.
1923: Note that it is only called at initialization time. This routine
1924: does not need to synchronize access to the hardware, or synchronize
1925: with the ISRs (they aren't connected yet).
1926:
1927: Arguments:
1928:
1929: DeviceObject - Pointer to the device object.
1930:
1931: Return Value:
1932:
1933: None. As a side-effect, however, DeviceExtension->HardwarePresent is set.
1934:
1935: --*/
1936:
1937: {
1938: PDEVICE_EXTENSION deviceExtension;
1939: NTSTATUS status;
1940: I8042_TRANSMIT_CCB_CONTEXT transmitCCBContext;
1941: PUCHAR dataAddress, commandAddress;
1942:
1943: I8xPrint((2, "I8042PRT-I8xInitializeHardware: enter\n"));
1944:
1945: //
1946: // Grab useful configuration parameters from the device extension.
1947: //
1948:
1949: deviceExtension = DeviceObject->DeviceExtension;
1950: dataAddress = deviceExtension->DeviceRegisters[DataPort];
1951: commandAddress = deviceExtension->DeviceRegisters[CommandPort];
1952:
1953: //
1954: // Drain the i8042 output buffer to get rid of stale data.
1955: //
1956:
1957: I8xDrainOutputBuffer(dataAddress, commandAddress);
1958:
1959: //
1960: // Disable interrupts from the keyboard and mouse. Read the Controller
1961: // Command Byte, turn off the keyboard and auxiliary interrupt enable
1962: // bits, and rewrite the Controller Command Byte.
1963: //
1964:
1965: transmitCCBContext.HardwareDisableEnableMask = 0;
1966: transmitCCBContext.AndOperation = AND_OPERATION;
1967: transmitCCBContext.ByteMask = (UCHAR)
1968: ~((UCHAR) CCB_ENABLE_KEYBOARD_INTERRUPT |
1969: (UCHAR) CCB_ENABLE_MOUSE_INTERRUPT);
1970:
1971: I8xTransmitControllerCommand(deviceExtension, (PVOID) &transmitCCBContext);
1972:
1973: if (!NT_SUCCESS(transmitCCBContext.Status)) {
1974: I8xPrint((
1975: 1,
1976: "I8042PRT-I8xInitializeHardware: failed to disable interrupts, status 0x%x\n",
1977: transmitCCBContext.Status
1978: ));
1979:
1980: return;
1981: }
1982:
1983: if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) == 0) {
1984: I8xPrint((
1985: 1,
1986: "I8042PRT-I8xInitializeHardware: no mouse present\n"
1987: ));
1988: }
1989:
1990: if ((deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) == 0) {
1991: I8xPrint((
1992: 1,
1993: "I8042PRT-I8xInitializeHardware: no keyboard present\n"
1994: ));
1995: }
1996:
1997:
1998: //
1999: // Disable the keyboard and mouse devices.
2000: //
2001:
2002: #if 0
2003: //
2004: // NOTE: This is supposedly the "correct" thing to do. However,
2005: // disabling the keyboard device here causes the AMI rev K8 machines
2006: // (e.g., some Northgates) to fail some commands (e.g., the READID
2007: // command).
2008: //
2009:
2010: status = I8xPutBytePolled(
2011: (CCHAR) CommandPort,
2012: NO_WAIT_FOR_ACKNOWLEDGE,
2013: (CCHAR) UndefinedDeviceType,
2014: deviceExtension,
2015: (UCHAR) I8042_DISABLE_KEYBOARD_DEVICE
2016: );
2017: if (!NT_SUCCESS(status)) {
2018: I8xPrint((
2019: 1,
2020: "I8042PRT-I8xInitializeHardware: failed kbd disable, status 0x%x\n",
2021: status
2022: ));
2023: deviceExtension->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
2024: }
2025: #endif
2026:
2027: status = I8xPutBytePolled(
2028: (CCHAR) CommandPort,
2029: NO_WAIT_FOR_ACKNOWLEDGE,
2030: (CCHAR) UndefinedDeviceType,
2031: deviceExtension,
2032: (UCHAR) I8042_DISABLE_MOUSE_DEVICE
2033: );
2034: if (!NT_SUCCESS(status)) {
2035: I8xPrint((
2036: 1,
2037: "I8042PRT-I8xInitializeHardware: failed mou disable, status 0x%x\n",
2038: status
2039: ));
2040:
2041: deviceExtension->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
2042: }
2043:
2044: //
2045: // Drain the i8042 output buffer to get rid of stale data that could
2046: // come in sometime between the previous drain and the time the devices
2047: // are disabled.
2048: //
2049:
2050: I8xDrainOutputBuffer(dataAddress, commandAddress);
2051:
2052: //
2053: // Setup the mouse hardware. This consists of resetting the mouse and
2054: // then setting the mouse sample rate.
2055: //
2056:
2057: if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
2058: status = I8xInitializeMouse(DeviceObject);
2059: if (!NT_SUCCESS(status)) {
2060: I8xPrint((
2061: 1,
2062: "I8042PRT-I8xInitializeHardware: failed mou init, status 0x%x\n",
2063: status
2064: ));
2065: deviceExtension->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
2066: }
2067: }
2068:
2069: //
2070: // Setup the keyboard hardware.
2071: //
2072:
2073: if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
2074: status = I8xInitializeKeyboard(DeviceObject);
2075: if (!NT_SUCCESS(status)) {
2076: I8xPrint((
2077: 0,
2078: "I8042PRT-I8xInitializeHardware: failed kbd init, status 0x%x\n",
2079: status
2080: ));
2081:
2082: deviceExtension->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
2083: }
2084: }
2085:
2086: //
2087: // Enable the keyboard and mouse devices and their interrupts. Note
2088: // that it is required that this operation happen during intialization
2089: // time, because the i8042 Output Buffer Full bit gets set in the
2090: // Controller Command Byte when the keyboard/mouse is used, even if
2091: // the device is disabled. Hence, we cannot successfully perform
2092: // the enable operation later (e.g., when processing
2093: // IOCTL_INTERNAL_*_ENABLE), because we can't guarantee that
2094: // I8xPutBytePolled() won't time out waiting for the Output Buffer Full
2095: // bit to clear, even if we drain the output buffer (because the user
2096: // could be playing with the mouse/keyboard, and continuing to set the
2097: // OBF bit). KeyboardEnableCount and MouseEnableCount remain zero until
2098: // their respective IOCTL_INTERNAL_*_ENABLE call succeeds, so the ISR
2099: // ignores the unexpected interrupts.
2100: //
2101:
2102: //
2103: // Re-enable the keyboard device in the Controller Command Byte.
2104: // Note that some of the keyboards will send an ACK back, while
2105: // others don't. Don't wait for an ACK, but do drain the output
2106: // buffer afterwards so that an unexpected ACK doesn't screw up
2107: // successive PutByte operations.
2108:
2109: if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
2110: status = I8xPutBytePolled(
2111: (CCHAR) CommandPort,
2112: NO_WAIT_FOR_ACKNOWLEDGE,
2113: (CCHAR) UndefinedDeviceType,
2114: deviceExtension,
2115: (UCHAR) I8042_ENABLE_KEYBOARD_DEVICE
2116: );
2117: if (!NT_SUCCESS(status)) {
2118: I8xPrint((
2119: 1,
2120: "I8042PRT-I8xInitializeHardware: failed kbd re-enable, status 0x%x\n",
2121: status
2122: ));
2123: deviceExtension->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
2124: }
2125:
2126: I8xDrainOutputBuffer(dataAddress, commandAddress);
2127: }
2128:
2129:
2130: //
2131: // Re-enable the mouse device in the Controller Command Byte.
2132: //
2133:
2134: if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
2135: status = I8xPutBytePolled(
2136: (CCHAR) CommandPort,
2137: NO_WAIT_FOR_ACKNOWLEDGE,
2138: (CCHAR) UndefinedDeviceType,
2139: deviceExtension,
2140: (UCHAR) I8042_ENABLE_MOUSE_DEVICE
2141: );
2142: if (!NT_SUCCESS(status)) {
2143: I8xPrint((
2144: 1,
2145: "I8042PRT-I8xInitializeHardware: failed mou re-enable, status 0x%x\n",
2146: status
2147: ));
2148: deviceExtension->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
2149: }
2150: I8xDrainOutputBuffer(dataAddress, commandAddress);
2151: }
2152:
2153: //
2154: // Re-enable interrupts in the Controller Command Byte.
2155: //
2156:
2157: if (deviceExtension->HardwarePresent) {
2158: transmitCCBContext.HardwareDisableEnableMask =
2159: deviceExtension->HardwarePresent;
2160: transmitCCBContext.AndOperation = OR_OPERATION;
2161: transmitCCBContext.ByteMask =
2162: (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) ?
2163: CCB_ENABLE_KEYBOARD_INTERRUPT : 0;
2164: transmitCCBContext.ByteMask |= (UCHAR)
2165: (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) ?
2166: CCB_ENABLE_MOUSE_INTERRUPT : 0;
2167:
2168: I8xTransmitControllerCommand(
2169: deviceExtension,
2170: (PVOID) &transmitCCBContext
2171: );
2172:
2173: if (!NT_SUCCESS(transmitCCBContext.Status)) {
2174: I8xPrint((
2175: 1,
2176: "I8042PRT-I8xInitializeHardware: failed to re-enable interrupts, status 0x%x\n",
2177: transmitCCBContext.Status
2178: ));
2179:
2180: //
2181: // We have the option here of resetting HardwarePresent to zero,
2182: // which will cause the driver to fail its initialization and
2183: // unload. Instead, we allow initialization to continue in
2184: // the hope that the command to re-enable interrupts was
2185: // successful at the hardware level (i.e., things will work),
2186: // even though the hardware response indicates otherwise.
2187: //
2188: }
2189: }
2190:
2191: I8xPrint((2, "I8042PRT-I8xInitializeHardware: exit\n"));
2192:
2193: return;
2194:
2195: }
2196:
2197: VOID
2198: I8xPutByteAsynchronous(
2199: IN CCHAR PortType,
2200: IN PDEVICE_EXTENSION DeviceExtension,
2201: IN UCHAR Byte
2202: )
2203:
2204: /*++
2205:
2206: Routine Description:
2207:
2208: This routine sends a command or data byte to the controller or keyboard
2209: or mouse, asynchronously. It does not wait for acknowledgment.
2210: If the hardware was not ready for input, the byte is not sent.
2211:
2212: Arguments:
2213:
2214: PortType - If CommandPort, send the byte to the command register,
2215: otherwise send it to the data register.
2216:
2217: DeviceExtension - Pointer to the device extension.
2218:
2219: Byte - The byte to send to the hardware.
2220:
2221: Return Value:
2222:
2223: None.
2224:
2225: --*/
2226:
2227: {
2228: ULONG i;
2229:
2230: I8xPrint((3, "I8042PRT-I8xPutByteAsynchronous: enter\n"));
2231:
2232: //
2233: // Make sure the Input Buffer Full controller status bit is clear.
2234: // Time out if necessary.
2235: //
2236:
2237: i = 0;
2238: while ((i++ < (ULONG)DeviceExtension->Configuration.PollingIterations) &&
2239: (I8X_GET_STATUS_BYTE(DeviceExtension->DeviceRegisters[CommandPort])
2240: & INPUT_BUFFER_FULL)) {
2241:
2242: //
2243: // Do nothing.
2244: //
2245:
2246: I8xPrint((
2247: 3,
2248: "I8042PRT-I8xPutByteAsynchronous: wait for IBF and OBF to clear\n"
2249: ));
2250:
2251: }
2252: if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
2253: I8xPrint((
2254: 3,
2255: "I8042PRT-I8xPutByteAsynchronous: exceeded number of retries\n"
2256: ));
2257: return;
2258: }
2259:
2260: //
2261: // Send the byte to the appropriate (command/data) hardware register.
2262: //
2263:
2264: if (PortType == CommandPort) {
2265: I8xPrint((
2266: 3,
2267: "I8042PRT-I8xPutByteAsynchronous: sending 0x%x to command port\n",
2268: Byte
2269: ));
2270: I8X_PUT_COMMAND_BYTE(DeviceExtension->DeviceRegisters[CommandPort], Byte);
2271: } else {
2272: I8xPrint((
2273: 3,
2274: "I8042PRT-I8xPutByteAsynchronous: sending 0x%x to data port\n",
2275: Byte
2276: ));
2277: I8X_PUT_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort], Byte);
2278: }
2279:
2280: I8xPrint((3, "I8042PRT-I8xPutByteAsynchronous: exit\n"));
2281:
2282: }
2283:
2284: NTSTATUS
2285: I8xPutBytePolled(
2286: IN CCHAR PortType,
2287: IN BOOLEAN WaitForAcknowledge,
2288: IN CCHAR AckDeviceType,
2289: IN PDEVICE_EXTENSION DeviceExtension,
2290: IN UCHAR Byte
2291: )
2292:
2293: /*++
2294:
2295: Routine Description:
2296:
2297: This routine sends a command or data byte to the controller or keyboard
2298: or mouse, in polling mode. It waits for acknowledgment and resends
2299: the command/data if necessary.
2300:
2301: Arguments:
2302:
2303: PortType - If CommandPort, send the byte to the command register,
2304: otherwise send it to the data register.
2305:
2306: WaitForAcknowledge - If true, wait for an ACK back from the hardware.
2307:
2308: AckDeviceType - Indicates which device we expect to get the ACK back
2309: from.
2310:
2311: DeviceExtension - Pointer to the device extension.
2312:
2313: Byte - The byte to send to the hardware.
2314:
2315: Return Value:
2316:
2317: STATUS_IO_TIMEOUT - The hardware was not ready for input or did not
2318: respond.
2319:
2320: STATUS_SUCCESS - The byte was successfully sent to the hardware.
2321:
2322: --*/
2323:
2324: {
2325: ULONG i,j;
2326: UCHAR response;
2327: NTSTATUS status;
2328: BOOLEAN keepTrying;
2329: PUCHAR dataAddress, commandAddress;
2330:
2331: I8xPrint((3, "I8042PRT-I8xPutBytePolled: enter\n"));
2332:
2333: if (AckDeviceType == MouseDeviceType) {
2334:
2335: //
2336: // We need to precede a PutByte for the mouse device with
2337: // a PutByte that tells the controller that the next byte
2338: // sent to the controller should go to the auxiliary device
2339: // (by default it would go to the keyboard device). We
2340: // do this by calling I8xPutBytePolled recursively to send
2341: // the "send next byte to auxiliary device" command
2342: // before sending the intended byte to the mouse. Note that
2343: // there is only one level of recursion, since the AckDeviceType
2344: // for the recursive call is guaranteed to be UndefinedDeviceType,
2345: // and hence this IF statement will evaluate to FALSE.
2346: //
2347:
2348: I8xPutBytePolled(
2349: (CCHAR) CommandPort,
2350: NO_WAIT_FOR_ACKNOWLEDGE,
2351: (CCHAR) UndefinedDeviceType,
2352: DeviceExtension,
2353: (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
2354: );
2355: }
2356:
2357: dataAddress = DeviceExtension->DeviceRegisters[DataPort];
2358: commandAddress = DeviceExtension->DeviceRegisters[CommandPort];
2359:
2360: for (j=0;j < (ULONG)DeviceExtension->Configuration.ResendIterations;j++) {
2361:
2362: //
2363: // Make sure the Input Buffer Full controller status bit is clear.
2364: // Time out if necessary.
2365: //
2366:
2367: i = 0;
2368: while ((i++ < (ULONG)DeviceExtension->Configuration.PollingIterations)
2369: && (I8X_GET_STATUS_BYTE(commandAddress) & INPUT_BUFFER_FULL)) {
2370: I8xPrint((2, "I8042PRT-I8xPutBytePolled: stalling\n"));
2371: KeStallExecutionProcessor(
2372: DeviceExtension->Configuration.StallMicroseconds
2373: );
2374: }
2375: if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
2376: I8xPrint((2, "I8042PRT-I8xPutBytePolled: timing out\n"));
2377: status = STATUS_IO_TIMEOUT;
2378: break;
2379: }
2380:
2381: //
2382: // Drain the i8042 output buffer to get rid of stale data.
2383: //
2384:
2385: I8xDrainOutputBuffer(dataAddress, commandAddress);
2386:
2387: //
2388: // Send the byte to the appropriate (command/data) hardware register.
2389: //
2390:
2391: if (PortType == CommandPort) {
2392: I8xPrint((
2393: 3,
2394: "I8042PRT-I8xPutBytePolled: sending 0x%x to command port\n",
2395: Byte
2396: ));
2397: I8X_PUT_COMMAND_BYTE(commandAddress, Byte);
2398: } else {
2399: I8xPrint((
2400: 3,
2401: "I8042PRT-I8xPutBytePolled: sending 0x%x to data port\n",
2402: Byte
2403: ));
2404: I8X_PUT_DATA_BYTE(dataAddress, Byte);
2405: }
2406:
2407: //
2408: // If we don't need to wait for an ACK back from the controller,
2409: // set the status and break out of the for loop.
2410: //
2411: //
2412:
2413: if (WaitForAcknowledge == NO_WAIT_FOR_ACKNOWLEDGE) {
2414: status = STATUS_SUCCESS;
2415: break;
2416: }
2417:
2418: //
2419: // Wait for an ACK back from the controller. If we get an ACK,
2420: // the operation was successful. If we get a RESEND, break out to
2421: // the for loop and try the operation again. Ignore anything other
2422: // than ACK or RESEND.
2423: //
2424:
2425: I8xPrint((3, "I8042PRT-I8xPutBytePolled: waiting for ACK\n"));
2426: keepTrying = FALSE;
2427: while ((status = I8xGetBytePolled(
2428: AckDeviceType,
2429: DeviceExtension,
2430: &response
2431: )
2432: ) == STATUS_SUCCESS) {
2433:
2434: if (response == ACKNOWLEDGE) {
2435: I8xPrint((3, "I8042PRT-I8xPutBytePolled: got ACK\n"));
2436: break;
2437: } else if (response == RESEND) {
2438: I8xPrint((3, "I8042PRT-I8xPutBytePolled: got RESEND\n"));
2439:
2440: if (AckDeviceType == MouseDeviceType) {
2441:
2442: //
2443: // We need to precede the "resent" PutByte for the
2444: // mouse device with a PutByte that tells the controller
2445: // that the next byte sent to the controller should go
2446: // to the auxiliary device (by default it would go to
2447: // the keyboard device). We do this by calling
2448: // I8xPutBytePolled recursively to send the "send next
2449: // byte to auxiliary device" command before resending
2450: // the byte to the mouse. Note that there is only one
2451: // level of recursion, since the AckDeviceType for the
2452: // recursive call is guaranteed to be UndefinedDeviceType.
2453: //
2454:
2455: I8xPutBytePolled(
2456: (CCHAR) CommandPort,
2457: NO_WAIT_FOR_ACKNOWLEDGE,
2458: (CCHAR) UndefinedDeviceType,
2459: DeviceExtension,
2460: (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
2461: );
2462: }
2463:
2464: keepTrying = TRUE;
2465: break;
2466: }
2467:
2468: //
2469: // Ignore any other response, and keep trying.
2470: //
2471:
2472: }
2473:
2474: if (!keepTrying)
2475: break;
2476: }
2477:
2478: //
2479: // Check to see if the number of allowable retries was exceeded.
2480: //
2481:
2482: if (j >= (ULONG)DeviceExtension->Configuration.ResendIterations) {
2483: I8xPrint((
2484: 2,
2485: "I8042PRT-I8xPutBytePolled: exceeded number of retries\n"
2486: ));
2487: status = STATUS_IO_TIMEOUT;
2488: }
2489:
2490: I8xPrint((3, "I8042PRT-I8xPutBytePolled: exit\n"));
2491:
2492: return(status);
2493: }
2494:
2495: NTSTATUS
2496: I8xPutControllerCommand(
2497: IN PDEVICE_EXTENSION DeviceExtension,
2498: IN UCHAR Byte
2499: )
2500:
2501: /*++
2502:
2503: Routine Description:
2504:
2505: This routine writes the 8042 Controller Command Byte.
2506:
2507: Arguments:
2508:
2509: DeviceExtension - Pointer to the device extension.
2510:
2511: Byte - The byte to store in the Controller Command Byte.
2512:
2513: Return Value:
2514:
2515: Status is returned.
2516:
2517: --*/
2518:
2519: {
2520: NTSTATUS status;
2521:
2522: I8xPrint((3, "I8042PRT-I8xPutControllerCommand: enter\n"));
2523:
2524: //
2525: // Send a command to the i8042 controller to write the Controller
2526: // Command Byte.
2527: //
2528:
2529: status = I8xPutBytePolled(
2530: (CCHAR) CommandPort,
2531: NO_WAIT_FOR_ACKNOWLEDGE,
2532: (CCHAR) UndefinedDeviceType,
2533: DeviceExtension,
2534: (UCHAR) I8042_WRITE_CONTROLLER_COMMAND_BYTE
2535: );
2536:
2537: if (!NT_SUCCESS(status)) {
2538: return(status);
2539: }
2540:
2541: //
2542: // Write the byte through the i8042 data port.
2543: //
2544:
2545: I8xPrint((3, "I8042PRT-I8xPutControllerCommand: exit\n"));
2546:
2547: return(I8xPutBytePolled(
2548: (CCHAR) DataPort,
2549: NO_WAIT_FOR_ACKNOWLEDGE,
2550: (CCHAR) UndefinedDeviceType,
2551: DeviceExtension,
2552: (UCHAR) Byte
2553: )
2554: );
2555: }
2556:
2557: VOID
2558: I8xServiceParameters(
2559: IN PDEVICE_EXTENSION DeviceExtension,
2560: IN PUNICODE_STRING RegistryPath,
2561: IN PUNICODE_STRING KeyboardDeviceName,
2562: IN PUNICODE_STRING PointerDeviceName
2563: )
2564:
2565: /*++
2566:
2567: Routine Description:
2568:
2569: This routine retrieves this driver's service parameters information
2570: from the registry.
2571:
2572: Arguments:
2573:
2574: DeviceExtension - Pointer to the device extension.
2575:
2576: RegistryPath - Pointer to the null-terminated Unicode name of the
2577: registry path for this driver.
2578:
2579: KeyboardDeviceName - Pointer to the Unicode string that will receive
2580: the keyboard port device name.
2581:
2582: PointerDeviceName - Pointer to the Unicode string that will receive
2583: the pointer port device name.
2584:
2585: Return Value:
2586:
2587: None. As a side-effect, sets fields in DeviceExtension->Configuration.
2588:
2589: --*/
2590:
2591: {
2592: PI8042_CONFIGURATION_INFORMATION configuration;
2593: PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
2594: UNICODE_STRING parametersPath;
2595: USHORT defaultResendIterations = I8042_RESEND_DEFAULT;
2596: ULONG resendIterations = 0;
2597: USHORT defaultPollingIterations = I8042_POLLING_DEFAULT;
2598: ULONG pollingIterations = 0;
2599: USHORT defaultPollingIterationsMaximum = I8042_POLLING_MAXIMUM;
2600: ULONG pollingIterationsMaximum = 0;
2601: USHORT defaultPollStatusIterations = I8042_POLLING_DEFAULT;
2602: ULONG pollStatusIterations = 0;
2603: ULONG defaultDataQueueSize = DATA_QUEUE_SIZE;
2604: ULONG numberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
2605: USHORT defaultNumberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
2606: ULONG sampleRate = MOUSE_SAMPLE_RATE;
2607: USHORT defaultSampleRate = MOUSE_SAMPLE_RATE;
2608: ULONG mouseResolution = MOUSE_RESOLUTION;
2609: USHORT defaultMouseResolution = MOUSE_RESOLUTION;
2610: ULONG overrideKeyboardType = 0;
2611: ULONG invalidKeyboardType = 0;
2612: ULONG overrideKeyboardSubtype = (ULONG) -1;
2613: ULONG invalidKeyboardSubtype = (ULONG) -1;
2614: ULONG defaultSynchPacket100ns = MOUSE_SYNCH_PACKET_100NS;
2615: UNICODE_STRING defaultPointerName;
2616: UNICODE_STRING defaultKeyboardName;
2617: NTSTATUS status = STATUS_SUCCESS;
2618: PWSTR path = NULL;
2619: USHORT queriesPlusOne = 15;
2620:
2621: configuration = &DeviceExtension->Configuration;
2622: configuration->StallMicroseconds = I8042_STALL_DEFAULT;
2623: parametersPath.Buffer = NULL;
2624:
2625: //
2626: // Registry path is already null-terminated, so just use it.
2627: //
2628:
2629: path = RegistryPath->Buffer;
2630:
2631: if (NT_SUCCESS(status)) {
2632:
2633: //
2634: // Allocate the Rtl query table.
2635: //
2636:
2637: parameters = ExAllocatePool(
2638: PagedPool,
2639: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2640: );
2641:
2642: if (!parameters) {
2643:
2644: I8xPrint((
2645: 1,
2646: "I8042PRT-I8xServiceParameters: Couldn't allocate table for Rtl query to parameters for %ws\n",
2647: path
2648: ));
2649:
2650: status = STATUS_UNSUCCESSFUL;
2651:
2652: } else {
2653:
2654: RtlZeroMemory(
2655: parameters,
2656: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2657: );
2658:
2659: //
2660: // Form a path to this driver's Parameters subkey.
2661: //
2662:
2663: RtlInitUnicodeString(
2664: ¶metersPath,
2665: NULL
2666: );
2667:
2668: parametersPath.MaximumLength = RegistryPath->Length +
2669: sizeof(L"\\Parameters");
2670:
2671: parametersPath.Buffer = ExAllocatePool(
2672: PagedPool,
2673: parametersPath.MaximumLength
2674: );
2675:
2676: if (!parametersPath.Buffer) {
2677:
2678: I8xPrint((
2679: 1,
2680: "I8042PRT-I8xServiceParameters: Couldn't allocate string for path to parameters for %ws\n",
2681: path
2682: ));
2683:
2684: status = STATUS_UNSUCCESSFUL;
2685:
2686: }
2687: }
2688: }
2689:
2690: if (NT_SUCCESS(status)) {
2691:
2692: //
2693: // Form the parameters path.
2694: //
2695:
2696: RtlZeroMemory(
2697: parametersPath.Buffer,
2698: parametersPath.MaximumLength
2699: );
2700: RtlAppendUnicodeToString(
2701: ¶metersPath,
2702: path
2703: );
2704: RtlAppendUnicodeToString(
2705: ¶metersPath,
2706: L"\\Parameters"
2707: );
2708:
2709: I8xPrint((
2710: 1,
2711: "I8042PRT-I8xServiceParameters: parameters path is %ws\n",
2712: parametersPath.Buffer
2713: ));
2714:
2715: //
2716: // Form the default port device names, in case they are not
2717: // specified in the registry.
2718: //
2719:
2720: RtlInitUnicodeString(
2721: &defaultKeyboardName,
2722: DD_KEYBOARD_PORT_BASE_NAME_U
2723: );
2724: RtlInitUnicodeString(
2725: &defaultPointerName,
2726: DD_POINTER_PORT_BASE_NAME_U
2727: );
2728:
2729: //
2730: // Gather all of the "user specified" information from
2731: // the registry.
2732: //
2733:
2734: parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
2735: parameters[0].Name = L"ResendIterations";
2736: parameters[0].EntryContext = &resendIterations;
2737: parameters[0].DefaultType = REG_DWORD;
2738: parameters[0].DefaultData = &defaultResendIterations;
2739: parameters[0].DefaultLength = sizeof(USHORT);
2740:
2741: parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
2742: parameters[1].Name = L"PollingIterations";
2743: parameters[1].EntryContext = &pollingIterations;
2744: parameters[1].DefaultType = REG_DWORD;
2745: parameters[1].DefaultData = &defaultPollingIterations;
2746: parameters[1].DefaultLength = sizeof(USHORT);
2747:
2748: parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
2749: parameters[2].Name = L"PollingIterationsMaximum";
2750: parameters[2].EntryContext = &pollingIterationsMaximum;
2751: parameters[2].DefaultType = REG_DWORD;
2752: parameters[2].DefaultData = &defaultPollingIterationsMaximum;
2753: parameters[2].DefaultLength = sizeof(USHORT);
2754:
2755: parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
2756: parameters[3].Name = L"KeyboardDataQueueSize";
2757: parameters[3].EntryContext =
2758: &configuration->KeyboardAttributes.InputDataQueueLength;
2759: parameters[3].DefaultType = REG_DWORD;
2760: parameters[3].DefaultData = &defaultDataQueueSize;
2761: parameters[3].DefaultLength = sizeof(ULONG);
2762:
2763: parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
2764: parameters[4].Name = L"MouseDataQueueSize";
2765: parameters[4].EntryContext =
2766: &configuration->MouseAttributes.InputDataQueueLength;
2767: parameters[4].DefaultType = REG_DWORD;
2768: parameters[4].DefaultData = &defaultDataQueueSize;
2769: parameters[4].DefaultLength = sizeof(ULONG);
2770:
2771: parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
2772: parameters[5].Name = L"NumberOfButtons";
2773: parameters[5].EntryContext = &numberOfButtons;
2774: parameters[5].DefaultType = REG_DWORD;
2775: parameters[5].DefaultData = &defaultNumberOfButtons;
2776: parameters[5].DefaultLength = sizeof(USHORT);
2777:
2778: parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
2779: parameters[6].Name = L"SampleRate";
2780: parameters[6].EntryContext = &sampleRate;
2781: parameters[6].DefaultType = REG_DWORD;
2782: parameters[6].DefaultData = &defaultSampleRate;
2783: parameters[6].DefaultLength = sizeof(USHORT);
2784:
2785: parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
2786: parameters[7].Name = L"MouseResolution";
2787: parameters[7].EntryContext = &mouseResolution;
2788: parameters[7].DefaultType = REG_DWORD;
2789: parameters[7].DefaultData = &defaultMouseResolution;
2790: parameters[7].DefaultLength = sizeof(USHORT);
2791:
2792: parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
2793: parameters[8].Name = L"OverrideKeyboardType";
2794: parameters[8].EntryContext = &overrideKeyboardType;
2795: parameters[8].DefaultType = REG_DWORD;
2796: parameters[8].DefaultData = &invalidKeyboardType;
2797: parameters[8].DefaultLength = sizeof(ULONG);
2798:
2799: parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
2800: parameters[9].Name = L"OverrideKeyboardSubtype";
2801: parameters[9].EntryContext = &overrideKeyboardSubtype;
2802: parameters[9].DefaultType = REG_DWORD;
2803: parameters[9].DefaultData = &invalidKeyboardSubtype;
2804: parameters[9].DefaultLength = sizeof(ULONG);
2805:
2806: parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
2807: parameters[10].Name = L"KeyboardDeviceBaseName";
2808: parameters[10].EntryContext = KeyboardDeviceName;
2809: parameters[10].DefaultType = REG_SZ;
2810: parameters[10].DefaultData = defaultKeyboardName.Buffer;
2811: parameters[10].DefaultLength = 0;
2812:
2813: parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
2814: parameters[11].Name = L"PointerDeviceBaseName";
2815: parameters[11].EntryContext = PointerDeviceName;
2816: parameters[11].DefaultType = REG_SZ;
2817: parameters[11].DefaultData = defaultPointerName.Buffer;
2818: parameters[11].DefaultLength = 0;
2819:
2820: parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
2821: parameters[12].Name = L"MouseSynchIn100ns";
2822: parameters[12].EntryContext =
2823: &DeviceExtension->MouseExtension.SynchTickCount;
2824: parameters[12].DefaultType = REG_DWORD;
2825: parameters[12].DefaultData = &defaultSynchPacket100ns;
2826: parameters[12].DefaultLength = sizeof(ULONG);
2827:
2828: parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT;
2829: parameters[13].Name = L"PollStatusIterations";
2830: parameters[13].EntryContext = &pollStatusIterations;
2831: parameters[13].DefaultType = REG_DWORD;
2832: parameters[13].DefaultData = &defaultPollStatusIterations;
2833: parameters[13].DefaultLength = sizeof(USHORT);
2834:
2835: status = RtlQueryRegistryValues(
2836: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
2837: parametersPath.Buffer,
2838: parameters,
2839: NULL,
2840: NULL
2841: );
2842:
2843: if (!NT_SUCCESS(status)) {
2844: I8xPrint((
2845: 1,
2846: "I8042PRT-I8xServiceParameters: RtlQueryRegistryValues failed with 0x%x\n",
2847: status
2848: ));
2849: }
2850: }
2851:
2852: if (!NT_SUCCESS(status)) {
2853:
2854: //
2855: // Go ahead and assign driver defaults.
2856: //
2857:
2858: configuration->ResendIterations = defaultResendIterations;
2859: configuration->PollingIterations = defaultPollingIterations;
2860: configuration->PollingIterationsMaximum =
2861: defaultPollingIterationsMaximum;
2862: configuration->PollStatusIterations = defaultPollStatusIterations;
2863: configuration->KeyboardAttributes.InputDataQueueLength =
2864: defaultDataQueueSize;
2865: configuration->MouseAttributes.InputDataQueueLength =
2866: defaultDataQueueSize;
2867: DeviceExtension->MouseExtension.SynchTickCount =
2868: defaultSynchPacket100ns;
2869: RtlCopyUnicodeString(KeyboardDeviceName, &defaultKeyboardName);
2870: RtlCopyUnicodeString(PointerDeviceName, &defaultPointerName);
2871: } else {
2872: configuration->ResendIterations = (USHORT) resendIterations;
2873: configuration->PollingIterations = (USHORT) pollingIterations;
2874: configuration->PollingIterationsMaximum =
2875: (USHORT) pollingIterationsMaximum;
2876: configuration->PollStatusIterations = (USHORT) pollStatusIterations;
2877: }
2878:
2879: I8xPrint((
2880: 1,
2881: "I8042PRT-I8xServiceParameters: Keyboard port base name = %ws\n",
2882: KeyboardDeviceName->Buffer
2883: ));
2884:
2885: I8xPrint((
2886: 1,
2887: "I8042PRT-I8xServiceParameters: Pointer port base name = %ws\n",
2888: PointerDeviceName->Buffer
2889: ));
2890:
2891: I8xPrint((
2892: 1,
2893: "I8042PRT-I8xServiceParameters: StallMicroseconds = %d\n",
2894: configuration->StallMicroseconds
2895: ));
2896: I8xPrint((
2897: 1,
2898: "I8042PRT-I8xServiceParameters: ResendIterations = %d\n",
2899: configuration->ResendIterations
2900: ));
2901: I8xPrint((
2902: 1,
2903: "I8042PRT-I8xServiceParameters: PollingIterations = %d\n",
2904: configuration->PollingIterations
2905: ));
2906: I8xPrint((
2907: 1,
2908: "I8042PRT-I8xServiceParameters: PollingIterationsMaximum = %d\n",
2909: configuration->PollingIterationsMaximum
2910: ));
2911: I8xPrint((
2912: 1,
2913: "I8042PRT-I8xServiceParameters: PollStatusIterations = %d\n",
2914: configuration->PollStatusIterations
2915: ));
2916:
2917: if (configuration->KeyboardAttributes.InputDataQueueLength == 0) {
2918:
2919: I8xPrint((
2920: 1,
2921: "I8042PRT-I8xServiceParameters: overriding KeyboardInputDataQueueLength = 0x%x\n",
2922: configuration->KeyboardAttributes.InputDataQueueLength
2923: ));
2924:
2925: configuration->KeyboardAttributes.InputDataQueueLength =
2926: defaultDataQueueSize;
2927: }
2928:
2929: configuration->KeyboardAttributes.InputDataQueueLength *=
2930: sizeof(KEYBOARD_INPUT_DATA);
2931:
2932: I8xPrint((
2933: 1,
2934: "I8042PRT-I8xServiceParameters: KeyboardInputDataQueueLength = 0x%x\n",
2935: configuration->KeyboardAttributes.InputDataQueueLength
2936: ));
2937:
2938: if (configuration->MouseAttributes.InputDataQueueLength == 0) {
2939:
2940: I8xPrint((
2941: 1,
2942: "I8042PRT-I8xServiceParameters: overriding MouseInputDataQueueLength = 0x%x\n",
2943: configuration->MouseAttributes.InputDataQueueLength
2944: ));
2945:
2946: configuration->MouseAttributes.InputDataQueueLength =
2947: defaultDataQueueSize;
2948: }
2949:
2950: configuration->MouseAttributes.InputDataQueueLength *=
2951: sizeof(MOUSE_INPUT_DATA);
2952:
2953: I8xPrint((
2954: 1,
2955: "I8042PRT-I8xServiceParameters: MouseInputDataQueueLength = 0x%x\n",
2956: configuration->MouseAttributes.InputDataQueueLength
2957: ));
2958:
2959: configuration->MouseAttributes.NumberOfButtons = numberOfButtons;
2960: I8xPrint((
2961: 1,
2962: "I8042PRT-I8xServiceParameters: NumberOfButtons = %d\n",
2963: configuration->MouseAttributes.NumberOfButtons
2964: ));
2965:
2966: configuration->MouseAttributes.SampleRate = sampleRate;
2967: I8xPrint((
2968: 1,
2969: "I8042PRT-I8xServiceParameters: SampleRate = %d\n",
2970: configuration->MouseAttributes.SampleRate
2971: ));
2972:
2973: configuration->MouseResolution = mouseResolution;
2974: I8xPrint((
2975: 1,
2976: "I8042PRT-I8xServiceParameters: MouseResolution = %d\n",
2977: configuration->MouseResolution
2978: ));
2979:
2980: if (overrideKeyboardType != invalidKeyboardType) {
2981: if (overrideKeyboardType <= NUM_KNOWN_KEYBOARD_TYPES) {
2982: I8xPrint((
2983: 1,
2984: "I8042PRT-I8xServiceParameters: Override KeyboardType = %d\n",
2985: overrideKeyboardType
2986: ));
2987: configuration->KeyboardAttributes.KeyboardIdentifier.Type =
2988: (UCHAR) overrideKeyboardType;
2989: } else {
2990: I8xPrint((
2991: 1,
2992: "I8042PRT-I8xServiceParameters: Invalid OverrideKeyboardType = %d\n",
2993: overrideKeyboardType
2994: ));
2995: }
2996: }
2997:
2998: if (overrideKeyboardSubtype != invalidKeyboardSubtype) {
2999: I8xPrint((
3000: 1,
3001: "I8042PRT-I8xServiceParameters: Override KeyboardSubtype = %d\n",
3002: overrideKeyboardSubtype
3003: ));
3004: configuration->KeyboardAttributes.KeyboardIdentifier.Subtype =
3005: (UCHAR) overrideKeyboardSubtype;
3006: }
3007:
3008: if (DeviceExtension->MouseExtension.SynchTickCount == 0) {
3009:
3010: I8xPrint((
3011: 1,
3012: "I8042PRT-I8xServiceParameters: overriding MouseSynchIn100ns\n"
3013: ));
3014:
3015: DeviceExtension->MouseExtension.SynchTickCount =
3016: defaultSynchPacket100ns;
3017: }
3018:
3019: //
3020: // Convert SynchTickCount to be the number of interval timer
3021: // interrupts that occur during the time specified by MouseSynchIn100ns.
3022: // Note that KeQueryTimeIncrement returns the number of 100ns units that
3023: // are added to the system time each time the interval clock interrupts.
3024: //
3025:
3026: DeviceExtension->MouseExtension.SynchTickCount /= KeQueryTimeIncrement();
3027:
3028: I8xPrint((
3029: 1,
3030: "I8042PRT-I8xServiceParameters: SynchTickCount = 0x%x\n",
3031: DeviceExtension->MouseExtension.SynchTickCount
3032: ));
3033:
3034: //
3035: // Free the allocated memory before returning.
3036: //
3037:
3038: if (parametersPath.Buffer)
3039: ExFreePool(parametersPath.Buffer);
3040: if (parameters)
3041: ExFreePool(parameters);
3042:
3043: }
3044:
3045: VOID
3046: I8xTransmitControllerCommand(
3047: IN PDEVICE_EXTENSION DeviceExtension,
3048: IN PVOID Context
3049: )
3050:
3051: /*++
3052:
3053: Routine Description:
3054:
3055: This routine reads the 8042 Controller Command Byte, performs an AND
3056: or OR operation using the specified ByteMask, and writes the resulting
3057: ControllerCommandByte.
3058:
3059: Arguments:
3060:
3061: DeviceExtension - Pointer to the device extension.
3062:
3063: Context - Pointer to a structure containing the HardwareDisableEnableMask,
3064: the AndOperation boolean, and the ByteMask to apply to the Controller
3065: Command Byte before it is rewritten.
3066:
3067: Return Value:
3068:
3069: None. Status is returned in the Context structure.
3070:
3071: --*/
3072:
3073: {
3074: UCHAR controllerCommandByte;
3075: UCHAR verifyCommandByte;
3076: PI8042_TRANSMIT_CCB_CONTEXT transmitCCBContext;
3077: PIO_ERROR_LOG_PACKET errorLogEntry;
3078:
3079: I8xPrint((3, "I8042PRT-I8xTransmitControllerCommand: enter\n"));
3080:
3081: //
3082: // Grab the parameters from the Context structure.
3083: //
3084:
3085: transmitCCBContext = (PI8042_TRANSMIT_CCB_CONTEXT) Context;
3086:
3087: //
3088: // Get the current Controller Command Byte.
3089: //
3090:
3091: transmitCCBContext->Status =
3092: I8xGetControllerCommand(
3093: transmitCCBContext->HardwareDisableEnableMask,
3094: DeviceExtension,
3095: &controllerCommandByte
3096: );
3097:
3098: if (!NT_SUCCESS(transmitCCBContext->Status)) {
3099: return;
3100: }
3101:
3102: I8xPrint((
3103: 3,
3104: "I8042PRT-I8xTransmitControllerCommand: current CCB 0x%x\n",
3105: controllerCommandByte
3106: ));
3107:
3108: //
3109: // Diddle the desired bits in the Controller Command Byte.
3110: //
3111:
3112: if (transmitCCBContext->AndOperation)
3113: controllerCommandByte &= transmitCCBContext->ByteMask;
3114: else
3115: controllerCommandByte |= transmitCCBContext->ByteMask;
3116:
3117: //
3118: // Write the new Controller Command Byte.
3119: //
3120:
3121: transmitCCBContext->Status =
3122: I8xPutControllerCommand(DeviceExtension, controllerCommandByte);
3123:
3124: I8xPrint((
3125: 3,
3126: "I8042PRT-I8xTransmitControllerCommand: new CCB 0x%x\n",
3127: controllerCommandByte
3128: ));
3129:
3130: //
3131: // Verify that the new Controller Command Byte really got written.
3132: //
3133:
3134: transmitCCBContext->Status =
3135: I8xGetControllerCommand(
3136: transmitCCBContext->HardwareDisableEnableMask,
3137: DeviceExtension,
3138: &verifyCommandByte
3139: );
3140:
3141: if (NT_SUCCESS(transmitCCBContext->Status)
3142: && (verifyCommandByte != controllerCommandByte)) {
3143: transmitCCBContext->Status = STATUS_DEVICE_DATA_ERROR;
3144:
3145: //
3146: // Log an error.
3147: //
3148:
3149: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
3150: DeviceExtension->DeviceObject,
3151: sizeof(IO_ERROR_LOG_PACKET)
3152: + (4 * sizeof(ULONG))
3153: );
3154: if (errorLogEntry != NULL) {
3155:
3156: errorLogEntry->ErrorCode = I8042_CCB_WRITE_FAILED;
3157: errorLogEntry->DumpDataSize = 4 * sizeof(ULONG);
3158: errorLogEntry->SequenceNumber = 0;
3159: errorLogEntry->MajorFunctionCode = 0;
3160: errorLogEntry->IoControlCode = 0;
3161: errorLogEntry->RetryCount = 0;
3162: errorLogEntry->UniqueErrorValue = 80;
3163: errorLogEntry->FinalStatus = transmitCCBContext->Status;
3164: errorLogEntry->DumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
3165: errorLogEntry->DumpData[1] = DataPort;
3166: errorLogEntry->DumpData[2] = I8042_WRITE_CONTROLLER_COMMAND_BYTE;
3167: errorLogEntry->DumpData[3] = controllerCommandByte;
3168:
3169: IoWriteErrorLogEntry(errorLogEntry);
3170: }
3171:
3172: }
3173:
3174: I8xPrint((3, "I8042PRT-I8xTransmitControllerCommand: exit\n"));
3175:
3176: return;
3177:
3178: }
3179:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.