|
|
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.