|
|
1.1 ! root 1: ! 2: /*++ ! 3: ! 4: Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation ! 5: ! 6: Module Name: ! 7: ! 8: kbddep.c ! 9: ! 10: Abstract: ! 11: ! 12: The initialization and hardware-dependent portions of ! 13: the Intel i8042 port driver which are specific to the ! 14: keyboard. ! 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: Revision History: ! 29: ! 30: --*/ ! 31: ! 32: #include "stdarg.h" ! 33: #include "stdio.h" ! 34: #include "string.h" ! 35: #include "ntddk.h" ! 36: #include "i8042prt.h" ! 37: #include "i8042log.h" ! 38: ! 39: // ! 40: // Use the alloc_text pragma to specify the driver initialization routines ! 41: // (they can be paged out). ! 42: // ! 43: ! 44: #ifdef ALLOC_PRAGMA ! 45: #pragma alloc_text(init,I8xKeyboardConfiguration) ! 46: #pragma alloc_text(init,I8xKeyboardPeripheralCallout) ! 47: #pragma alloc_text(init,I8xInitializeKeyboard) ! 48: #endif ! 49: ! 50: ! 51: BOOLEAN ! 52: I8042KeyboardInterruptService( ! 53: IN PKINTERRUPT Interrupt, ! 54: IN PVOID Context ! 55: ) ! 56: ! 57: /*++ ! 58: ! 59: Routine Description: ! 60: ! 61: This is the interrupt service routine for the keyboard device when ! 62: scan code set 1 is in use. ! 63: ! 64: Arguments: ! 65: ! 66: Interrupt - A pointer to the interrupt object for this interrupt. ! 67: ! 68: Context - A pointer to the device object. ! 69: ! 70: Return Value: ! 71: ! 72: Returns TRUE if the interrupt was expected (and therefore processed); ! 73: otherwise, FALSE is returned. ! 74: ! 75: --*/ ! 76: ! 77: { ! 78: UCHAR scanCode; ! 79: PDEVICE_EXTENSION deviceExtension; ! 80: PDEVICE_OBJECT deviceObject; ! 81: KEYBOARD_SCAN_STATE *scanState; ! 82: PKEYBOARD_INPUT_DATA input; ! 83: ULONG i; ! 84: ! 85: UNREFERENCED_PARAMETER(Interrupt); ! 86: ! 87: I8xPrint((2, "I8042PRT-I8042KeyboardInterruptService: enter\n")); ! 88: ! 89: // ! 90: // Get the device extension. ! 91: // ! 92: ! 93: deviceObject = (PDEVICE_OBJECT) Context; ! 94: deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; ! 95: ! 96: // ! 97: // Verify that this device really interrupted. Check the status ! 98: // register. The Output Buffer Full bit should be set, and the ! 99: // Auxiliary Device Output Buffer Full bit should be clear. ! 100: // ! 101: ! 102: if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort]) ! 103: & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) ! 104: != OUTPUT_BUFFER_FULL) { ! 105: ! 106: // ! 107: // Stall and then try again. The Olivetti MIPS machine ! 108: // sometimes gets an interrupt before the status ! 109: // register is set. They do this for DOS compatibility (some ! 110: // DOS apps do things in polled mode, until they see a character ! 111: // in the keyboard buffer at which point they expect to get ! 112: // an interrupt???). ! 113: // ! 114: ! 115: for (i = 0; i < (ULONG)deviceExtension->Configuration.PollStatusIterations; i++) { ! 116: KeStallExecutionProcessor(1); ! 117: if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort]) ! 118: & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) ! 119: == (OUTPUT_BUFFER_FULL)) ! 120: break; ! 121: } ! 122: ! 123: if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort]) ! 124: & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) ! 125: != (OUTPUT_BUFFER_FULL)) { ! 126: ! 127: // ! 128: // Not our interrupt. ! 129: // ! 130: // NOTE: If the keyboard has not yet been "enabled", go ahead ! 131: // and read a byte from the data port anyway. ! 132: // This fixes weirdness on some Gateway machines, where ! 133: // we get an interrupt sometime during driver initialization ! 134: // after the interrupt is connected, but the output buffer ! 135: // full bit never gets set. ! 136: // ! 137: ! 138: I8xPrint(( ! 139: 1, ! 140: "I8042PRT-I8042KeyboardInterruptService: not our interrupt!\n" ! 141: )); ! 142: ! 143: if (deviceExtension->KeyboardEnableCount == 0) { ! 144: scanCode = ! 145: I8X_GET_DATA_BYTE(deviceExtension->DeviceRegisters[DataPort]); ! 146: } ! 147: ! 148: return(FALSE); ! 149: } ! 150: } ! 151: ! 152: // ! 153: // The interrupt is valid. Read the byte from the i8042 data port. ! 154: // ! 155: ! 156: I8xGetByteAsynchronous( ! 157: (CCHAR) KeyboardDeviceType, ! 158: deviceExtension, ! 159: &scanCode ! 160: ); ! 161: ! 162: I8xPrint(( ! 163: 2, ! 164: "I8042PRT-I8042KeyboardInterruptService: scanCode 0x%x\n", ! 165: scanCode ! 166: )); ! 167: ! 168: // ! 169: // Take the appropriate action, depending on whether the byte read ! 170: // is a keyboard command response or a real scan code. ! 171: // ! 172: ! 173: switch(scanCode) { ! 174: ! 175: // ! 176: // The keyboard controller requests a resend. If the resend count ! 177: // has not been exceeded, re-initiate the I/O operation. ! 178: // ! 179: ! 180: case RESEND: ! 181: ! 182: I8xPrint(( ! 183: 3, ! 184: "I8042PRT-I8042KeyboardInterruptService: RESEND, retries = %d\n", ! 185: deviceExtension->KeyboardExtension.ResendCount + 1 ! 186: )); ! 187: ! 188: // ! 189: // If the timer count is zero, don't process the interrupt ! 190: // further. The timeout routine will complete this request. ! 191: // ! 192: ! 193: if (deviceExtension->TimerCount == 0) { ! 194: break; ! 195: } ! 196: ! 197: // ! 198: // Reset the timeout value to indicate no timeout. ! 199: // ! 200: ! 201: deviceExtension->TimerCount = I8042_ASYNC_NO_TIMEOUT; ! 202: ! 203: // ! 204: // If the maximum number of retries has not been exceeded, ! 205: // re-initiate the operation; otherwise, queue the DPC to ! 206: // complete this request. ! 207: // ! 208: ! 209: if ((deviceExtension->KeyboardExtension.CurrentOutput.State==Idle) ! 210: || (deviceObject->CurrentIrp == NULL)) { ! 211: ! 212: // ! 213: // We weren't sending a command or parameter to the hardware. ! 214: // Why would the hardware give us a resend??? Log an error. ! 215: // ! 216: ! 217: KeInsertQueueDpc( ! 218: &deviceExtension->ErrorLogDpc, ! 219: (PIRP) NULL, ! 220: (PVOID) (ULONG) I8042_UNEXPECTED_RESEND); ! 221: ! 222: } else if (deviceExtension->KeyboardExtension.ResendCount ! 223: < deviceExtension->Configuration.ResendIterations) { ! 224: ! 225: deviceExtension->KeyboardExtension.ResendCount += 1; ! 226: I8xKeyboardInitiateIo((PVOID) deviceObject); ! 227: ! 228: } else { ! 229: ! 230: KeInsertQueueDpc( ! 231: &deviceExtension->RetriesExceededDpc, ! 232: deviceObject->CurrentIrp, ! 233: NULL ! 234: ); ! 235: } ! 236: ! 237: break; ! 238: ! 239: // ! 240: // The keyboard controller has acknowledged a previous send. ! 241: // If there are more bytes to send for the current packet, initiate ! 242: // the next send operation. Otherwise, queue the completion DPC. ! 243: // ! 244: ! 245: case ACKNOWLEDGE: ! 246: ! 247: I8xPrint(( ! 248: 3, ! 249: "I8042PRT-I8042KeyboardInterruptService: ACK, " ! 250: )); ! 251: ! 252: // ! 253: // If the timer count is zero, don't process the interrupt ! 254: // further. The timeout routine will complete this request. ! 255: // ! 256: ! 257: if (deviceExtension->TimerCount == 0) { ! 258: break; ! 259: } ! 260: ! 261: // ! 262: // Reset the timeout value to indicate no timeout. ! 263: // ! 264: ! 265: deviceExtension->TimerCount = I8042_ASYNC_NO_TIMEOUT; ! 266: ! 267: // ! 268: // Reset resend count. ! 269: // ! 270: ! 271: deviceExtension->KeyboardExtension.ResendCount = 0; ! 272: ! 273: if (deviceExtension->KeyboardExtension.CurrentOutput.State ! 274: == SendFirstByte) { ! 275: ! 276: // ! 277: // We've successfully sent the first byte of a 2-byte ! 278: // command sequence. Initiate a send of the second byte. ! 279: // ! 280: ! 281: I8xPrint(( ! 282: 3, ! 283: "now initiate send of last byte\n" ! 284: )); ! 285: ! 286: deviceExtension->KeyboardExtension.CurrentOutput.State = ! 287: SendLastByte; ! 288: ! 289: I8xKeyboardInitiateIo((PVOID) deviceObject); ! 290: ! 291: } else if (deviceExtension->KeyboardExtension.CurrentOutput.State ! 292: == SendLastByte) { ! 293: ! 294: // ! 295: // We've successfully sent all bytes in the command sequence. ! 296: // Reset the current state and queue the completion DPC. ! 297: // ! 298: ! 299: I8xPrint(( ! 300: 3, ! 301: "all bytes have been sent\n" ! 302: )); ! 303: ! 304: deviceExtension->KeyboardExtension.CurrentOutput.State = Idle; ! 305: ! 306: IoRequestDpc( ! 307: deviceObject, ! 308: deviceObject->CurrentIrp, ! 309: NULL ! 310: ); ! 311: ! 312: } else { ! 313: I8xPrint(( ! 314: 1, ! 315: "unexpected, State is 0x%x\n", ! 316: deviceExtension->KeyboardExtension.CurrentOutput.State ! 317: )); ! 318: // ! 319: // Queue a DPC to log an internal driver error. ! 320: // ! 321: ! 322: KeInsertQueueDpc( ! 323: &deviceExtension->ErrorLogDpc, ! 324: (PIRP) NULL, ! 325: (PVOID) (ULONG) I8042_INVALID_ISR_STATE); ! 326: ! 327: // ! 328: // Note: We don't ASSERT here, because there are some ! 329: // machines (e.g., Compaq 386/25) that send back an ! 330: // extra ACK in response to the SETLED sequence. We've ! 331: // noticed this when, for example, CAPSLOCK is pressed ! 332: // at the same time as a normal key. Just ignore ! 333: // random ACKs. ! 334: // ! 335: } ! 336: ! 337: break; ! 338: ! 339: // ! 340: // Assume we've got a real, live scan code (or perhaps a keyboard ! 341: // overrun code, which we treat like a scan code). I.e., a key ! 342: // has been pressed or released. Queue the ISR DPC to process ! 343: // a complete scan code sequence. ! 344: // ! 345: ! 346: default: ! 347: ! 348: I8xPrint(( ! 349: 3, ! 350: "I8042PRT-I8042KeyboardInterruptService: real scan code\n" ! 351: )); ! 352: ! 353: // ! 354: // Differentiate between an extended key sequence (first ! 355: // byte is E0, followed by a normal make or break byte), or ! 356: // a normal make code (one byte, the high bit is NOT set), ! 357: // or a normal break code (one byte, same as the make code ! 358: // but the high bit is set), or the key #126 byte sequence ! 359: // (requires special handling -- sequence is E11D459DC5). ! 360: // ! 361: // If there is a key detection error/overrun, the keyboard ! 362: // sends an overrun indicator (0xFF in scan code set 1). ! 363: // Map it to the overrun indicator expected by the Windows ! 364: // USER Raw Input Thread. ! 365: // ! 366: ! 367: input = &deviceExtension->KeyboardExtension.CurrentInput; ! 368: scanState = &deviceExtension->KeyboardExtension.CurrentScanState; ! 369: ! 370: if (scanCode == (UCHAR) 0xFF) { ! 371: I8xPrint(( ! 372: 1, ! 373: "I8042PRT-I8042KeyboardInterruptService: OVERRUN\n" ! 374: )); ! 375: input->MakeCode = KEYBOARD_OVERRUN_MAKE_CODE; ! 376: input->Flags = 0; ! 377: *scanState = Normal; ! 378: } else { ! 379: ! 380: switch (*scanState) { ! 381: case Normal: ! 382: if (scanCode == (UCHAR) 0xE0) { ! 383: input->Flags |= KEY_E0; ! 384: *scanState = GotE0; ! 385: I8xPrint(( ! 386: 3, ! 387: "I8042PRT-I8042KeyboardInterruptService: change state to GotE0\n" ! 388: )); ! 389: break; ! 390: } else if (scanCode == (UCHAR) 0xE1) { ! 391: input->Flags |= KEY_E1; ! 392: *scanState = GotE1; ! 393: I8xPrint(( ! 394: 3, ! 395: "I8042PRT-I8042KeyboardInterruptService: change state to GotE1\n" ! 396: )); ! 397: break; ! 398: } ! 399: ! 400: // ! 401: // Fall through to the GotE0/GotE1 case for the rest of the ! 402: // Normal case. ! 403: // ! 404: ! 405: case GotE0: ! 406: case GotE1: ! 407: ! 408: if (scanCode > 0x7F) { ! 409: ! 410: // ! 411: // Got a break code. Strip the high bit off ! 412: // to get the associated make code and set flags ! 413: // to indicate a break code. ! 414: // ! 415: ! 416: I8xPrint(( ! 417: 3, ! 418: "I8042PRT-I8042KeyboardInterruptService: BREAK code\n" ! 419: )); ! 420: ! 421: input->MakeCode = scanCode & 0x7F; ! 422: input->Flags |= KEY_BREAK; ! 423: ! 424: } else { ! 425: ! 426: // ! 427: // Got a make code. ! 428: // ! 429: ! 430: I8xPrint(( ! 431: 3, ! 432: "I8042PRT-I8042KeyboardInterruptService: MAKE code\n" ! 433: )); ! 434: ! 435: input->MakeCode = scanCode; ! 436: ! 437: // ! 438: // If the input scan code is debug stop, then drop ! 439: // into the kernel debugger if it is active. ! 440: // ! 441: ! 442: if (*((PBOOLEAN)(*(PLONG)&KdDebuggerNotPresent)) ! 443: == FALSE && !(input->Flags & KEY_BREAK)) { ! 444: if (ENHANCED_KEYBOARD( ! 445: deviceExtension->Configuration.KeyboardAttributes.KeyboardIdentifier ! 446: )) { ! 447: // ! 448: // Enhanced 101 keyboard, SysReq key is 0xE0 0x37. ! 449: // ! 450: ! 451: if ((input->MakeCode == KEYBOARD_DEBUG_HOTKEY_ENH) && ! 452: (input->Flags & KEY_E0)) { ! 453: try { ! 454: DbgBreakPoint(); ! 455: ! 456: } except(EXCEPTION_EXECUTE_HANDLER) { ! 457: } ! 458: } ! 459: // ! 460: // 84-key AT keyboard, SysReq key is 0xE0 0x54. ! 461: // ! 462: ! 463: } else if ((input->MakeCode == KEYBOARD_DEBUG_HOTKEY_AT)) { ! 464: try { ! 465: DbgBreakPoint(); ! 466: ! 467: } except(EXCEPTION_EXECUTE_HANDLER) { ! 468: } ! 469: } ! 470: } ! 471: } ! 472: ! 473: // ! 474: // Reset the state to Normal. ! 475: // ! 476: ! 477: *scanState = Normal; ! 478: break; ! 479: ! 480: default: ! 481: ! 482: // ! 483: // Queue a DPC to log an internal driver error. ! 484: // ! 485: ! 486: KeInsertQueueDpc( ! 487: &deviceExtension->ErrorLogDpc, ! 488: (PIRP) NULL, ! 489: (PVOID) (ULONG) I8042_INVALID_ISR_STATE); ! 490: ! 491: ASSERT(FALSE); ! 492: break; ! 493: } ! 494: } ! 495: ! 496: // ! 497: // In the Normal state, if the keyboard device is enabled, ! 498: // add the data to the InputData queue and queue the ISR DPC. ! 499: // ! 500: ! 501: if (*scanState == Normal) { ! 502: ! 503: if (deviceExtension->KeyboardEnableCount) { ! 504: deviceExtension->KeyboardExtension.CurrentInput.UnitId = ! 505: deviceExtension->KeyboardExtension.UnitId; ! 506: if (!I8xWriteDataToKeyboardQueue( ! 507: &deviceExtension->KeyboardExtension, ! 508: input ! 509: )) { ! 510: ! 511: // ! 512: // The InputData queue overflowed. There is ! 513: // not much that can be done about it, so just ! 514: // continue (but don't queue the ISR DPC, since ! 515: // no new packets were added to the queue). ! 516: // ! 517: // Queue a DPC to log an overrun error. ! 518: // ! 519: ! 520: I8xPrint(( ! 521: 1, ! 522: "I8042PRT-I8042KeyboardInterruptService: queue overflow\n" ! 523: )); ! 524: ! 525: if (deviceExtension->KeyboardExtension.OkayToLogOverflow) { ! 526: KeInsertQueueDpc( ! 527: &deviceExtension->ErrorLogDpc, ! 528: (PIRP) NULL, ! 529: (PVOID) (ULONG) I8042_KBD_BUFFER_OVERFLOW ! 530: ); ! 531: deviceExtension->KeyboardExtension.OkayToLogOverflow = FALSE; ! 532: } ! 533: ! 534: } else if (deviceExtension->DpcInterlockKeyboard >= 0) { ! 535: ! 536: // ! 537: // The ISR DPC is already executing. Tell the ISR DPC ! 538: // it has more work to do by incrementing ! 539: // DpcInterlockKeyboard. ! 540: // ! 541: ! 542: deviceExtension->DpcInterlockKeyboard += 1; ! 543: ! 544: } else { ! 545: ! 546: // ! 547: // Queue the ISR DPC. ! 548: // ! 549: ! 550: KeInsertQueueDpc( ! 551: &deviceExtension->KeyboardIsrDpc, ! 552: deviceObject->CurrentIrp, ! 553: NULL ! 554: ); ! 555: } ! 556: } ! 557: ! 558: // ! 559: // Reset the input state. ! 560: // ! 561: ! 562: input->Flags = 0; ! 563: } ! 564: ! 565: break; ! 566: ! 567: } ! 568: ! 569: I8xPrint((2, "I8042PRT-I8042KeyboardInterruptService: exit\n")); ! 570: ! 571: return(TRUE); ! 572: } ! 573: ! 574: // ! 575: // The following table is used to convert typematic rate (keys per ! 576: // second) into the value expected by the keyboard. The index into the ! 577: // array is the number of keys per second. The resulting value is ! 578: // the bit equate to send to the keyboard. ! 579: // ! 580: ! 581: UCHAR TypematicPeriod[] = { ! 582: 31, // 0 keys per second ! 583: 31, // 1 keys per second ! 584: 31, // 2 keys per second ! 585: 26, // 3 keys per second ! 586: 23, // 4 keys per second ! 587: 20, // 5 keys per second ! 588: 18, // 6 keys per second ! 589: 17, // 7 keys per second ! 590: 15, // 8 keys per second ! 591: 13, // 9 keys per second ! 592: 12, // 10 keys per second ! 593: 11, // 11 keys per second ! 594: 10, // 12 keys per second ! 595: 9, // 13 keys per second ! 596: 9, // 14 keys per second ! 597: 8, // 15 keys per second ! 598: 7, // 16 keys per second ! 599: 6, // 17 keys per second ! 600: 5, // 18 keys per second ! 601: 4, // 19 keys per second ! 602: 4, // 20 keys per second ! 603: 3, // 21 keys per second ! 604: 3, // 22 keys per second ! 605: 2, // 23 keys per second ! 606: 2, // 24 keys per second ! 607: 1, // 25 keys per second ! 608: 1, // 26 keys per second ! 609: 1 // 27 keys per second ! 610: // > 27 keys per second, use 0 ! 611: }; ! 612: ! 613: UCHAR ! 614: I8xConvertTypematicParameters( ! 615: IN USHORT Rate, ! 616: IN USHORT Delay ! 617: ) ! 618: ! 619: /*++ ! 620: ! 621: Routine Description: ! 622: ! 623: This routine converts the typematic rate and delay to the form the ! 624: keyboard expects. ! 625: ! 626: The byte passed to the keyboard looks like this: ! 627: ! 628: - bit 7 is zero ! 629: - bits 5 and 6 indicate the delay ! 630: - bits 0-4 indicate the rate ! 631: ! 632: The delay is equal to 1 plus the binary value of bits 6 and 5, ! 633: multiplied by 250 milliseconds. ! 634: ! 635: The period (interval from one typematic output to the next) is ! 636: determined by the following equation: ! 637: ! 638: Period = (8 + A) x (2^B) x 0.00417 seconds ! 639: where ! 640: A = binary value of bits 0-2 ! 641: B = binary value of bits 3 and 4 ! 642: ! 643: ! 644: Arguments: ! 645: ! 646: Rate - Number of keys per second. ! 647: ! 648: Delay - Number of milliseconds to delay before the key repeat starts. ! 649: ! 650: Return Value: ! 651: ! 652: The byte to pass to the keyboard. ! 653: ! 654: --*/ ! 655: ! 656: { ! 657: UCHAR value; ! 658: ! 659: I8xPrint((2, "I8042PRT-I8xConvertTypematicParameters: enter\n")); ! 660: ! 661: // ! 662: // Calculate the delay bits. ! 663: // ! 664: ! 665: value = (UCHAR) ((Delay / 250) - 1); ! 666: ! 667: // ! 668: // Put delay bits in the right place. ! 669: // ! 670: ! 671: value <<= 5; ! 672: ! 673: // ! 674: // Get the typematic period from the table. If keys per second ! 675: // is > 27, the typematic period value is zero. ! 676: // ! 677: ! 678: if (Rate <= 27) { ! 679: value |= TypematicPeriod[Rate]; ! 680: } ! 681: ! 682: I8xPrint((2, "I8042PRT-I8xConvertTypematicParameters: exit\n")); ! 683: ! 684: return(value); ! 685: } ! 686: ! 687: NTSTATUS ! 688: I8xInitializeKeyboard( ! 689: IN PDEVICE_OBJECT DeviceObject ! 690: ) ! 691: ! 692: /*++ ! 693: ! 694: Routine Description: ! 695: ! 696: This routine initializes the i8042 keyboard hardware. It is called ! 697: only at initialization, and does not synchronize access to the hardware. ! 698: ! 699: Arguments: ! 700: ! 701: DeviceObject - Pointer to the device object. ! 702: ! 703: Return Value: ! 704: ! 705: Returns status. ! 706: ! 707: --*/ ! 708: ! 709: { ! 710: NTSTATUS status; ! 711: PKEYBOARD_ID id; ! 712: PDEVICE_EXTENSION deviceExtension; ! 713: UCHAR byte; ! 714: I8042_TRANSMIT_CCB_CONTEXT transmitCCBContext; ! 715: ULONG i; ! 716: PIO_ERROR_LOG_PACKET errorLogEntry; ! 717: ULONG uniqueErrorValue; ! 718: NTSTATUS errorCode = STATUS_SUCCESS; ! 719: ULONG dumpCount; ! 720: ! 721: #define DUMP_COUNT 4 ! 722: ULONG dumpData[DUMP_COUNT]; ! 723: ! 724: I8xPrint((2, "I8042PRT-I8xInitializeKeyboard: enter\n")); ! 725: ! 726: for (i = 0; i < DUMP_COUNT; i++) ! 727: dumpData[i] = 0; ! 728: ! 729: // ! 730: // Get the device extension. ! 731: // ! 732: ! 733: deviceExtension = DeviceObject->DeviceExtension; ! 734: ! 735: // ! 736: // Reset the keyboard. ! 737: // ! 738: ! 739: status = I8xPutBytePolled( ! 740: (CCHAR) DataPort, ! 741: WAIT_FOR_ACKNOWLEDGE, ! 742: (CCHAR) KeyboardDeviceType, ! 743: deviceExtension, ! 744: (UCHAR) KEYBOARD_RESET ! 745: ); ! 746: if (!NT_SUCCESS(status)) { ! 747: I8xPrint(( ! 748: 1, ! 749: "I8042PRT-I8xInitializeKeyboard: failed keyboard reset, status 0x%x\n", ! 750: status ! 751: )); ! 752: ! 753: // ! 754: // Set up error log info. ! 755: // ! 756: ! 757: errorCode = I8042_KBD_RESET_COMMAND_FAILED; ! 758: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 510; ! 759: dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND; ! 760: dumpData[1] = DataPort; ! 761: dumpData[2] = KEYBOARD_RESET; ! 762: dumpCount = 3; ! 763: ! 764: // ! 765: // NOTE: The following line was commented out to work around a ! 766: // problem with the Gateway 4DX2/66V when an old Compaq 286 ! 767: // keyboard is attached. In this case, the keyboard reset ! 768: // is not acknowledged (at least, the system never ! 769: // receives the ack). Instead, the KEYBOARD_COMPLETE_SUCCESS ! 770: // byte is sitting in the i8042 output buffer. The workaround ! 771: // is to ignore the keyboard reset failure and continue. ! 772: // ! 773: // goto I8xInitializeKeyboardExit; ! 774: } ! 775: ! 776: // ! 777: // Get the keyboard reset self-test response. A response byte of ! 778: // KEYBOARD_COMPLETE_SUCCESS indicates success; KEYBOARD_COMPLETE_FAILURE ! 779: // indicates failure. ! 780: // ! 781: // Note that it is usually necessary to stall a long time to get the ! 782: // keyboard reset/self-test to work. The stall value was determined by ! 783: // experimentation. ! 784: // ! 785: ! 786: for (i = 0; i < 11200; i++) { ! 787: ! 788: status = I8xGetBytePolled( ! 789: (CCHAR) KeyboardDeviceType, ! 790: deviceExtension, ! 791: &byte ! 792: ); ! 793: ! 794: if (NT_SUCCESS(status)) { ! 795: if (byte == (UCHAR) KEYBOARD_COMPLETE_SUCCESS) { ! 796: ! 797: // ! 798: // The reset completed successfully. ! 799: // ! 800: ! 801: break; ! 802: ! 803: } else { ! 804: ! 805: // ! 806: // There was some sort of failure during the reset ! 807: // self-test. Continue anyway. ! 808: // ! 809: ! 810: // ! 811: // Log a warning. ! 812: // ! 813: ! 814: ! 815: dumpData[0] = KBDMOU_INCORRECT_RESPONSE; ! 816: dumpData[1] = KeyboardDeviceType; ! 817: dumpData[2] = KEYBOARD_COMPLETE_SUCCESS; ! 818: dumpData[3] = byte; ! 819: ! 820: I8xLogError( ! 821: DeviceObject, ! 822: I8042_KBD_RESET_RESPONSE_FAILED, ! 823: I8042_ERROR_VALUE_BASE + 515, ! 824: status, ! 825: dumpData, ! 826: 4 ! 827: ); ! 828: ! 829: break; ! 830: } ! 831: ! 832: ! 833: } else { ! 834: ! 835: if (status == STATUS_IO_TIMEOUT) { ! 836: ! 837: // ! 838: // Stall, and then try again to get a response from ! 839: // the reset. ! 840: // ! 841: ! 842: KeStallExecutionProcessor(50); ! 843: ! 844: } else { ! 845: ! 846: break; ! 847: ! 848: } ! 849: ! 850: } ! 851: } ! 852: ! 853: if (!NT_SUCCESS(status)) { ! 854: I8xPrint(( ! 855: 1, ! 856: "I8042PRT-I8xInitializeKeyboard: failed reset response, status 0x%x, byte 0x%x\n", ! 857: status, ! 858: byte ! 859: )); ! 860: ! 861: // ! 862: // Set up error log info. ! 863: // ! 864: ! 865: errorCode = I8042_KBD_RESET_RESPONSE_FAILED; ! 866: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 520; ! 867: dumpData[0] = KBDMOU_INCORRECT_RESPONSE; ! 868: dumpData[1] = KeyboardDeviceType; ! 869: dumpData[2] = KEYBOARD_COMPLETE_SUCCESS; ! 870: dumpData[3] = byte; ! 871: dumpCount = 4; ! 872: ! 873: goto I8xInitializeKeyboardExit; ! 874: } ! 875: ! 876: // ! 877: // Turn off Keyboard Translate Mode. Call I8xTransmitControllerCommand ! 878: // to read the Controller Command Byte, modify the appropriate bits, and ! 879: // rewrite the Controller Command Byte. ! 880: // ! 881: ! 882: transmitCCBContext.HardwareDisableEnableMask = 0; ! 883: transmitCCBContext.AndOperation = AND_OPERATION; ! 884: transmitCCBContext.ByteMask = (UCHAR) ~((UCHAR)CCB_KEYBOARD_TRANSLATE_MODE); ! 885: ! 886: I8xTransmitControllerCommand( ! 887: deviceExtension, ! 888: (PVOID) &transmitCCBContext ! 889: ); ! 890: ! 891: if (!NT_SUCCESS(transmitCCBContext.Status)) { ! 892: I8xPrint(( ! 893: 1, ! 894: "I8042PRT-I8xInitializeKeyboard: could not turn off translate\n" ! 895: )); ! 896: status = transmitCCBContext.Status; ! 897: goto I8xInitializeKeyboardExit; ! 898: } ! 899: ! 900: // ! 901: // Get a pointer to the keyboard identifier field. ! 902: // ! 903: ! 904: id = &deviceExtension->Configuration.KeyboardAttributes.KeyboardIdentifier; ! 905: ! 906: // ! 907: // Set the typematic rate and delay. Send the Set Typematic Rate command ! 908: // to the keyboard, followed by the typematic rate/delay parameter byte. ! 909: // Note that it is often necessary to stall a long time to get this ! 910: // to work. The stall value was determined by experimentation. Some ! 911: // broken hardware does not accept this command, so ignore errors in the ! 912: // hope that the keyboard will work okay anyway. ! 913: // ! 914: // ! 915: ! 916: if ((status = I8xPutBytePolled( ! 917: (CCHAR) DataPort, ! 918: WAIT_FOR_ACKNOWLEDGE, ! 919: (CCHAR) KeyboardDeviceType, ! 920: deviceExtension, ! 921: (UCHAR) SET_KEYBOARD_TYPEMATIC ! 922: )) != STATUS_SUCCESS) { ! 923: I8xPrint(( ! 924: 1, ! 925: "I8042PRT-I8xInitializeKeyboard: could not send SET TYPEMATIC cmd\n" ! 926: )); ! 927: ! 928: // ! 929: // Log an error. ! 930: // ! 931: ! 932: dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND; ! 933: dumpData[1] = DataPort; ! 934: dumpData[2] = SET_KEYBOARD_TYPEMATIC; ! 935: ! 936: I8xLogError( ! 937: DeviceObject, ! 938: I8042_SET_TYPEMATIC_FAILED, ! 939: I8042_ERROR_VALUE_BASE + 535, ! 940: status, ! 941: dumpData, ! 942: 3 ! 943: ); ! 944: ! 945: } else if ((status = I8xPutBytePolled( ! 946: (CCHAR) DataPort, ! 947: WAIT_FOR_ACKNOWLEDGE, ! 948: (CCHAR) KeyboardDeviceType, ! 949: deviceExtension, ! 950: I8xConvertTypematicParameters( ! 951: deviceExtension->Configuration.KeyRepeatCurrent.Rate, ! 952: deviceExtension->Configuration.KeyRepeatCurrent.Delay ! 953: ))) != STATUS_SUCCESS) { ! 954: I8xPrint(( ! 955: 1, ! 956: "I8042PRT-I8xInitializeKeyboard: could not send typematic param\n" ! 957: )); ! 958: ! 959: // ! 960: // Log an error. ! 961: // ! 962: ! 963: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 964: dumpData[1] = DataPort; ! 965: dumpData[2] = SET_KEYBOARD_TYPEMATIC; ! 966: dumpData[3] = ! 967: I8xConvertTypematicParameters( ! 968: deviceExtension->Configuration.KeyRepeatCurrent.Rate, ! 969: deviceExtension->Configuration.KeyRepeatCurrent.Delay ! 970: ); ! 971: ! 972: I8xLogError( ! 973: DeviceObject, ! 974: I8042_SET_TYPEMATIC_FAILED, ! 975: I8042_ERROR_VALUE_BASE + 540, ! 976: status, ! 977: dumpData, ! 978: 4 ! 979: ); ! 980: ! 981: } ! 982: ! 983: status = STATUS_SUCCESS; ! 984: ! 985: // ! 986: // Set the keyboard indicator lights. Ignore errors. ! 987: // ! 988: ! 989: if ((status = I8xPutBytePolled( ! 990: (CCHAR) DataPort, ! 991: WAIT_FOR_ACKNOWLEDGE, ! 992: (CCHAR) KeyboardDeviceType, ! 993: deviceExtension, ! 994: (UCHAR) SET_KEYBOARD_INDICATORS ! 995: )) != STATUS_SUCCESS) { ! 996: I8xPrint(( ! 997: 1, ! 998: "I8042PRT-I8xInitializeKeyboard: could not send SET LEDS cmd\n" ! 999: )); ! 1000: ! 1001: // ! 1002: // Log an error. ! 1003: // ! 1004: ! 1005: dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND; ! 1006: dumpData[1] = DataPort; ! 1007: dumpData[2] = SET_KEYBOARD_INDICATORS; ! 1008: ! 1009: I8xLogError( ! 1010: DeviceObject, ! 1011: I8042_SET_LED_FAILED, ! 1012: I8042_ERROR_VALUE_BASE + 545, ! 1013: status, ! 1014: dumpData, ! 1015: 3 ! 1016: ); ! 1017: ! 1018: } else if ((status = I8xPutBytePolled( ! 1019: (CCHAR) DataPort, ! 1020: WAIT_FOR_ACKNOWLEDGE, ! 1021: (CCHAR) KeyboardDeviceType, ! 1022: deviceExtension, ! 1023: (UCHAR) deviceExtension->Configuration.KeyboardIndicators.LedFlags ! 1024: )) != STATUS_SUCCESS) { ! 1025: I8xPrint(( ! 1026: 1, ! 1027: "I8042PRT-I8xInitializeKeyboard: could not send SET LEDS param\n" ! 1028: )); ! 1029: ! 1030: // ! 1031: // Log an error. ! 1032: // ! 1033: ! 1034: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 1035: dumpData[1] = DataPort; ! 1036: dumpData[2] = SET_KEYBOARD_INDICATORS; ! 1037: dumpData[3] = ! 1038: deviceExtension->Configuration.KeyboardIndicators.LedFlags; ! 1039: ! 1040: I8xLogError( ! 1041: DeviceObject, ! 1042: I8042_SET_LED_FAILED, ! 1043: I8042_ERROR_VALUE_BASE + 550, ! 1044: status, ! 1045: dumpData, ! 1046: 4 ! 1047: ); ! 1048: ! 1049: } ! 1050: ! 1051: status = STATUS_SUCCESS; ! 1052: ! 1053: #ifndef i386 ! 1054: ! 1055: // ! 1056: // BUGBUG: This code is necessary until the MIPS firmware stops ! 1057: // selecting scan code set 3. Select scan code set 2 here. ! 1058: // Since the translate bit is set, the net effect is that ! 1059: // we will receive scan code set 1 bytes. ! 1060: // ! 1061: ! 1062: if (ENHANCED_KEYBOARD(*id)) { ! 1063: status = I8xPutBytePolled( ! 1064: (CCHAR) DataPort, ! 1065: WAIT_FOR_ACKNOWLEDGE, ! 1066: (CCHAR) KeyboardDeviceType, ! 1067: deviceExtension, ! 1068: (UCHAR) SELECT_SCAN_CODE_SET ! 1069: ); ! 1070: if (!NT_SUCCESS(status)) { ! 1071: I8xPrint(( ! 1072: 1, ! 1073: "I8042PRT-I8xInitializeKeyboard: could not send Select Scan command\n" ! 1074: )); ! 1075: I8xPrint(( ! 1076: 0, ! 1077: "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 3\n" ! 1078: )); ! 1079: deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 3; ! 1080: } else { ! 1081: ! 1082: // ! 1083: // Send the associated parameter byte. ! 1084: // ! 1085: ! 1086: status = I8xPutBytePolled( ! 1087: (CCHAR) DataPort, ! 1088: WAIT_FOR_ACKNOWLEDGE, ! 1089: (CCHAR) KeyboardDeviceType, ! 1090: deviceExtension, ! 1091: (UCHAR) 2 ! 1092: ); ! 1093: if (!NT_SUCCESS(status)) { ! 1094: I8xPrint(( ! 1095: 1, ! 1096: "I8042PRT-I8xInitializeKeyboard: could not send Select Scan param\n" ! 1097: )); ! 1098: I8xPrint(( ! 1099: 0, ! 1100: "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 3\n" ! 1101: )); ! 1102: deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 3; ! 1103: } ! 1104: } ! 1105: } ! 1106: #endif ! 1107: ! 1108: if (deviceExtension->Configuration.KeyboardAttributes.KeyboardMode == 1) { ! 1109: ! 1110: // ! 1111: // Turn translate back on. The keyboard should, by default, send ! 1112: // scan code set 2. When the translate bit in the 8042 command byte ! 1113: // is on, the 8042 translates the scan code set 2 bytes to scan code ! 1114: // set 1 before sending them to the CPU. Scan code set 1 is ! 1115: // the industry standard scan code set. ! 1116: // ! 1117: // N.B. It does not appear to be possible to change the translate ! 1118: // bit on some models of PS/2. ! 1119: // ! 1120: ! 1121: transmitCCBContext.HardwareDisableEnableMask = 0; ! 1122: transmitCCBContext.AndOperation = OR_OPERATION; ! 1123: transmitCCBContext.ByteMask = (UCHAR) CCB_KEYBOARD_TRANSLATE_MODE; ! 1124: ! 1125: I8xTransmitControllerCommand( ! 1126: deviceExtension, ! 1127: (PVOID) &transmitCCBContext ! 1128: ); ! 1129: ! 1130: if (!NT_SUCCESS(transmitCCBContext.Status)) { ! 1131: I8xPrint(( ! 1132: 1, ! 1133: "I8042PRT-I8xInitializeKeyboard: couldn't turn on translate\n" ! 1134: )); ! 1135: if (transmitCCBContext.Status == STATUS_DEVICE_DATA_ERROR) { ! 1136: ! 1137: // ! 1138: // Could not turn translate back on. This happens on some ! 1139: // PS/2 machines. In this case, select scan code set 1 ! 1140: // for the keyboard, since the 8042 will not do the ! 1141: // translation from the scan code set 2, which is what the ! 1142: // KEYBOARD_RESET caused the keyboard to default to. ! 1143: // ! 1144: ! 1145: if (ENHANCED_KEYBOARD(*id)) { ! 1146: status = I8xPutBytePolled( ! 1147: (CCHAR) DataPort, ! 1148: WAIT_FOR_ACKNOWLEDGE, ! 1149: (CCHAR) KeyboardDeviceType, ! 1150: deviceExtension, ! 1151: (UCHAR) SELECT_SCAN_CODE_SET ! 1152: ); ! 1153: if (!NT_SUCCESS(status)) { ! 1154: I8xPrint(( ! 1155: 1, ! 1156: "I8042PRT-I8xInitializeKeyboard: could not send Select Scan command\n" ! 1157: )); ! 1158: I8xPrint(( ! 1159: 0, ! 1160: "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 2\n" ! 1161: )); ! 1162: deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 2; ! 1163: // ! 1164: // Log an error. ! 1165: // ! 1166: ! 1167: dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND; ! 1168: dumpData[1] = DataPort; ! 1169: dumpData[2] = SELECT_SCAN_CODE_SET; ! 1170: ! 1171: I8xLogError( ! 1172: DeviceObject, ! 1173: I8042_SELECT_SCANSET_FAILED, ! 1174: I8042_ERROR_VALUE_BASE + 555, ! 1175: status, ! 1176: dumpData, ! 1177: 3 ! 1178: ); ! 1179: ! 1180: } else { ! 1181: ! 1182: // ! 1183: // Send the associated parameter byte. ! 1184: // ! 1185: ! 1186: status = I8xPutBytePolled( ! 1187: (CCHAR) DataPort, ! 1188: WAIT_FOR_ACKNOWLEDGE, ! 1189: (CCHAR) KeyboardDeviceType, ! 1190: deviceExtension, ! 1191: (UCHAR) 1 ! 1192: ); ! 1193: if (!NT_SUCCESS(status)) { ! 1194: I8xPrint(( ! 1195: 1, ! 1196: "I8042PRT-I8xInitializeKeyboard: could not send Select Scan param\n" ! 1197: )); ! 1198: I8xPrint(( ! 1199: 0, ! 1200: "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 2\n" ! 1201: )); ! 1202: deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 2; ! 1203: // ! 1204: // Log an error. ! 1205: // ! 1206: ! 1207: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 1208: dumpData[1] = DataPort; ! 1209: dumpData[2] = SELECT_SCAN_CODE_SET; ! 1210: dumpData[3] = 1; ! 1211: ! 1212: I8xLogError( ! 1213: DeviceObject, ! 1214: I8042_SELECT_SCANSET_FAILED, ! 1215: I8042_ERROR_VALUE_BASE + 560, ! 1216: status, ! 1217: dumpData, ! 1218: 4 ! 1219: ); ! 1220: ! 1221: } ! 1222: } ! 1223: } ! 1224: ! 1225: } else { ! 1226: status = transmitCCBContext.Status; ! 1227: goto I8xInitializeKeyboardExit; ! 1228: } ! 1229: } ! 1230: } ! 1231: ! 1232: I8xInitializeKeyboardExit: ! 1233: ! 1234: // ! 1235: // If the keyboard initialization failed, log an error. ! 1236: // ! 1237: ! 1238: if (errorCode != STATUS_SUCCESS) { ! 1239: ! 1240: errorLogEntry = (PIO_ERROR_LOG_PACKET) ! 1241: IoAllocateErrorLogEntry( ! 1242: DeviceObject, ! 1243: (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) ! 1244: + (dumpCount * sizeof(ULONG))) ! 1245: ); ! 1246: ! 1247: if (errorLogEntry != NULL) { ! 1248: ! 1249: errorLogEntry->ErrorCode = errorCode; ! 1250: errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG); ! 1251: errorLogEntry->SequenceNumber = 0; ! 1252: errorLogEntry->MajorFunctionCode = 0; ! 1253: errorLogEntry->IoControlCode = 0; ! 1254: errorLogEntry->RetryCount = 0; ! 1255: errorLogEntry->UniqueErrorValue = uniqueErrorValue; ! 1256: errorLogEntry->FinalStatus = status; ! 1257: for (i = 0; i < dumpCount; i++) ! 1258: errorLogEntry->DumpData[i] = dumpData[i]; ! 1259: ! 1260: IoWriteErrorLogEntry(errorLogEntry); ! 1261: } ! 1262: } ! 1263: ! 1264: // ! 1265: // Initialize current keyboard set packet state. ! 1266: // ! 1267: ! 1268: deviceExtension->KeyboardExtension.CurrentOutput.State = Idle; ! 1269: deviceExtension->KeyboardExtension.CurrentOutput.FirstByte = 0; ! 1270: deviceExtension->KeyboardExtension.CurrentOutput.LastByte = 0; ! 1271: ! 1272: I8xPrint((2, "I8042PRT-I8xInitializeKeyboard: exit\n")); ! 1273: ! 1274: return(status); ! 1275: } ! 1276: ! 1277: VOID ! 1278: I8xKeyboardConfiguration( ! 1279: IN PDEVICE_EXTENSION DeviceExtension, ! 1280: IN PUNICODE_STRING RegistryPath, ! 1281: IN PUNICODE_STRING KeyboardDeviceName, ! 1282: IN PUNICODE_STRING PointerDeviceName ! 1283: ) ! 1284: ! 1285: /*++ ! 1286: ! 1287: Routine Description: ! 1288: ! 1289: This routine retrieves the configuration information for the keyboard. ! 1290: ! 1291: Arguments: ! 1292: ! 1293: DeviceExtension - Pointer to the device extension. ! 1294: ! 1295: RegistryPath - Pointer to the null-terminated Unicode name of the ! 1296: registry path for this driver. ! 1297: ! 1298: KeyboardDeviceName - Pointer to the Unicode string that will receive ! 1299: the keyboard port device name. ! 1300: ! 1301: PointerDeviceName - Pointer to the Unicode string that will receive ! 1302: the pointer port device name. ! 1303: ! 1304: Return Value: ! 1305: ! 1306: None. As a side-effect, may set DeviceExtension->HardwarePresent. ! 1307: ! 1308: --*/ ! 1309: { ! 1310: NTSTATUS status = STATUS_SUCCESS; ! 1311: PI8042_CONFIGURATION_INFORMATION configuration; ! 1312: INTERFACE_TYPE interfaceType; ! 1313: CONFIGURATION_TYPE controllerType = KeyboardController; ! 1314: CONFIGURATION_TYPE peripheralType = KeyboardPeripheral; ! 1315: PKEYBOARD_ID keyboardId; ! 1316: ULONG i; ! 1317: ! 1318: for (i = 0; i < MaximumInterfaceType; i++) { ! 1319: ! 1320: // ! 1321: // Get the registry information for this device. ! 1322: // ! 1323: ! 1324: interfaceType = i; ! 1325: status = IoQueryDeviceDescription(&interfaceType, ! 1326: NULL, ! 1327: &controllerType, ! 1328: NULL, ! 1329: &peripheralType, ! 1330: NULL, ! 1331: I8xKeyboardPeripheralCallout, ! 1332: (PVOID) DeviceExtension); ! 1333: ! 1334: if (DeviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) { ! 1335: ! 1336: // ! 1337: // Get the service parameters (e.g., user-configurable number ! 1338: // of resends, polling iterations, etc.). ! 1339: // ! 1340: ! 1341: I8xServiceParameters( ! 1342: DeviceExtension, ! 1343: RegistryPath, ! 1344: KeyboardDeviceName, ! 1345: PointerDeviceName ! 1346: ); ! 1347: configuration = &DeviceExtension->Configuration; ! 1348: ! 1349: keyboardId = &configuration->KeyboardAttributes.KeyboardIdentifier; ! 1350: if (!ENHANCED_KEYBOARD(*keyboardId)) { ! 1351: I8xPrint(( ! 1352: 1, ! 1353: "I8042PRT-I8xKeyboardConfiguration: Old AT-style keyboard\n" ! 1354: )); ! 1355: configuration->PollingIterations = ! 1356: configuration->PollingIterationsMaximum; ! 1357: } ! 1358: ! 1359: // ! 1360: // Initialize keyboard-specific configuration parameters. ! 1361: // ! 1362: ! 1363: configuration->KeyboardAttributes.NumberOfFunctionKeys = ! 1364: KeyboardTypeInformation[keyboardId->Type - 1].NumberOfFunctionKeys; ! 1365: configuration->KeyboardAttributes.NumberOfIndicators = ! 1366: KeyboardTypeInformation[keyboardId->Type - 1].NumberOfIndicators; ! 1367: configuration->KeyboardAttributes.NumberOfKeysTotal = ! 1368: KeyboardTypeInformation[keyboardId->Type - 1].NumberOfKeysTotal; ! 1369: ! 1370: configuration->KeyboardAttributes.KeyboardMode = ! 1371: KEYBOARD_SCAN_CODE_SET; ! 1372: ! 1373: configuration->KeyboardAttributes.KeyRepeatMinimum.Rate = ! 1374: KEYBOARD_TYPEMATIC_RATE_MINIMUM; ! 1375: configuration->KeyboardAttributes.KeyRepeatMinimum.Delay = ! 1376: KEYBOARD_TYPEMATIC_DELAY_MINIMUM; ! 1377: configuration->KeyboardAttributes.KeyRepeatMaximum.Rate = ! 1378: KEYBOARD_TYPEMATIC_RATE_MAXIMUM; ! 1379: configuration->KeyboardAttributes.KeyRepeatMaximum.Delay = ! 1380: KEYBOARD_TYPEMATIC_DELAY_MAXIMUM; ! 1381: configuration->KeyRepeatCurrent.Rate = ! 1382: KEYBOARD_TYPEMATIC_RATE_DEFAULT; ! 1383: configuration->KeyRepeatCurrent.Delay = ! 1384: KEYBOARD_TYPEMATIC_DELAY_DEFAULT; ! 1385: ! 1386: break; ! 1387: ! 1388: } else { ! 1389: I8xPrint(( ! 1390: 1, ! 1391: "I8042PRT-I8xKeyboardConfiguration: IoQueryDeviceDescription for bus type %d failed\n", ! 1392: interfaceType ! 1393: )); ! 1394: } ! 1395: } ! 1396: } ! 1397: ! 1398: VOID ! 1399: I8xKeyboardInitiateIo( ! 1400: IN PVOID Context ! 1401: ) ! 1402: ! 1403: /*++ ! 1404: ! 1405: Routine Description: ! 1406: ! 1407: This routine is called synchronously from I8xKeyboardInitiateWrapper and ! 1408: the ISR to initiate an I/O operation for the keyboard device. ! 1409: ! 1410: Arguments: ! 1411: ! 1412: Context - Pointer to the device object. ! 1413: ! 1414: Return Value: ! 1415: ! 1416: None. ! 1417: ! 1418: --*/ ! 1419: ! 1420: { ! 1421: PDEVICE_EXTENSION deviceExtension; ! 1422: PDEVICE_OBJECT deviceObject; ! 1423: KEYBOARD_SET_PACKET keyboardPacket; ! 1424: ! 1425: I8xPrint((2, "I8042PRT-I8xKeyboardInitiateIo: enter\n")); ! 1426: ! 1427: // ! 1428: // Get the device extension. ! 1429: // ! 1430: ! 1431: deviceObject = (PDEVICE_OBJECT) Context; ! 1432: deviceExtension = deviceObject->DeviceExtension; ! 1433: ! 1434: // ! 1435: // Set the timeout value. ! 1436: // ! 1437: ! 1438: deviceExtension->TimerCount = I8042_ASYNC_TIMEOUT; ! 1439: ! 1440: // ! 1441: // Get the current set request packet to work on. ! 1442: // ! 1443: ! 1444: keyboardPacket = deviceExtension->KeyboardExtension.CurrentOutput; ! 1445: ! 1446: if (deviceExtension->KeyboardExtension.CurrentOutput.State ! 1447: == SendFirstByte){ ! 1448: ! 1449: I8xPrint(( ! 1450: 2, ! 1451: "I8042PRT-I8xKeyboardInitiateIo: send first byte 0x%x\n", ! 1452: keyboardPacket.FirstByte ! 1453: )); ! 1454: ! 1455: // ! 1456: // Send the first byte of a 2-byte command sequence to the ! 1457: // keyboard controller, asynchronously. ! 1458: // ! 1459: ! 1460: I8xPutByteAsynchronous( ! 1461: (CCHAR) DataPort, ! 1462: deviceExtension, ! 1463: keyboardPacket.FirstByte ! 1464: ); ! 1465: ! 1466: } else if (deviceExtension->KeyboardExtension.CurrentOutput.State ! 1467: == SendLastByte) { ! 1468: ! 1469: I8xPrint(( ! 1470: 2, ! 1471: "I8042PRT-I8xKeyboardInitiateIo: send last byte 0x%x\n", ! 1472: keyboardPacket.LastByte ! 1473: )); ! 1474: ! 1475: // ! 1476: // Send the last byte of a command sequence to the keyboard ! 1477: // controller, asynchronously. ! 1478: // ! 1479: ! 1480: I8xPutByteAsynchronous( ! 1481: (CCHAR) DataPort, ! 1482: deviceExtension, ! 1483: keyboardPacket.LastByte ! 1484: ); ! 1485: ! 1486: } else { ! 1487: ! 1488: I8xPrint((2, "I8042PRT-I8xKeyboardInitiateIo: INVALID REQUEST\n")); ! 1489: ! 1490: // ! 1491: // Queue a DPC to log an internal driver error. ! 1492: // ! 1493: ! 1494: KeInsertQueueDpc( ! 1495: &deviceExtension->ErrorLogDpc, ! 1496: (PIRP) NULL, ! 1497: (PVOID) (ULONG) I8042_INVALID_INITIATE_STATE); ! 1498: ! 1499: ASSERT(FALSE); ! 1500: } ! 1501: ! 1502: I8xPrint((2, "I8042PRT-I8xKeyboardInitiateIo: exit\n")); ! 1503: ! 1504: return; ! 1505: } ! 1506: ! 1507: VOID ! 1508: I8xKeyboardInitiateWrapper( ! 1509: IN PVOID Context ! 1510: ) ! 1511: ! 1512: /*++ ! 1513: ! 1514: Routine Description: ! 1515: ! 1516: This routine is called from StartIo synchronously. It sets up the ! 1517: CurrentOutput and ResendCount fields in the device extension, and ! 1518: then calls I8xKeyboardInitiateIo to do the real work. ! 1519: ! 1520: Arguments: ! 1521: ! 1522: Context - Pointer to the context structure containing the first and ! 1523: last bytes of the send sequence. ! 1524: ! 1525: Return Value: ! 1526: ! 1527: None. ! 1528: ! 1529: --*/ ! 1530: ! 1531: { ! 1532: PDEVICE_OBJECT deviceObject; ! 1533: PDEVICE_EXTENSION deviceExtension; ! 1534: ! 1535: // ! 1536: // Get a pointer to the device object from the context argument. ! 1537: // ! 1538: ! 1539: deviceObject = ((PKEYBOARD_INITIATE_CONTEXT) Context)->DeviceObject; ! 1540: ! 1541: // ! 1542: // Set up CurrentOutput state for this operation. ! 1543: // ! 1544: ! 1545: deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; ! 1546: ! 1547: deviceExtension->KeyboardExtension.CurrentOutput.State = SendFirstByte; ! 1548: deviceExtension->KeyboardExtension.CurrentOutput.FirstByte = ! 1549: ((PKEYBOARD_INITIATE_CONTEXT) Context)->FirstByte; ! 1550: deviceExtension->KeyboardExtension.CurrentOutput.LastByte = ! 1551: ((PKEYBOARD_INITIATE_CONTEXT) Context)->LastByte; ! 1552: ! 1553: // ! 1554: // We're starting a new operation, so reset the resend count. ! 1555: // ! 1556: ! 1557: deviceExtension->KeyboardExtension.ResendCount = 0; ! 1558: ! 1559: // ! 1560: // Initiate the keyboard I/O operation. Note that we were called ! 1561: // using KeSynchronizeExecution, so I8xKeyboardInitiateIo is also ! 1562: // synchronized with the keyboard ISR. ! 1563: // ! 1564: ! 1565: I8xKeyboardInitiateIo((PVOID) deviceObject); ! 1566: ! 1567: } ! 1568: ! 1569: NTSTATUS ! 1570: I8xKeyboardPeripheralCallout( ! 1571: IN PVOID Context, ! 1572: IN PUNICODE_STRING PathName, ! 1573: IN INTERFACE_TYPE BusType, ! 1574: IN ULONG BusNumber, ! 1575: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 1576: IN CONFIGURATION_TYPE ControllerType, ! 1577: IN ULONG ControllerNumber, ! 1578: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 1579: IN CONFIGURATION_TYPE PeripheralType, ! 1580: IN ULONG PeripheralNumber, ! 1581: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 1582: ) ! 1583: ! 1584: /*++ ! 1585: ! 1586: Routine Description: ! 1587: ! 1588: This is the callout routine sent as a parameter to ! 1589: IoQueryDeviceDescription. It grabs the keyboard controller and ! 1590: peripheral configuration information. ! 1591: ! 1592: Arguments: ! 1593: ! 1594: Context - Context parameter that was passed in by the routine ! 1595: that called IoQueryDeviceDescription. ! 1596: ! 1597: PathName - The full pathname for the registry key. ! 1598: ! 1599: BusType - Bus interface type (Isa, Eisa, Mca, etc.). ! 1600: ! 1601: BusNumber - The bus sub-key (0, 1, etc.). ! 1602: ! 1603: BusInformation - Pointer to the array of pointers to the full value ! 1604: information for the bus. ! 1605: ! 1606: ControllerType - The controller type (should be KeyboardController). ! 1607: ! 1608: ControllerNumber - The controller sub-key (0, 1, etc.). ! 1609: ! 1610: ControllerInformation - Pointer to the array of pointers to the full ! 1611: value information for the controller key. ! 1612: ! 1613: PeripheralType - The peripheral type (should be KeyboardPeripheral). ! 1614: ! 1615: PeripheralNumber - The peripheral sub-key. ! 1616: ! 1617: PeripheralInformation - Pointer to the array of pointers to the full ! 1618: value information for the peripheral key. ! 1619: ! 1620: ! 1621: Return Value: ! 1622: ! 1623: None. If successful, will have the following side-effects: ! 1624: ! 1625: - Sets DeviceObject->DeviceExtension->HardwarePresent. ! 1626: - Sets configuration fields in ! 1627: DeviceObject->DeviceExtension->Configuration. ! 1628: ! 1629: --*/ ! 1630: { ! 1631: PDEVICE_EXTENSION deviceExtension; ! 1632: PI8042_CONFIGURATION_INFORMATION configuration; ! 1633: UNICODE_STRING unicodeIdentifier; ! 1634: PUCHAR controllerData; ! 1635: PUCHAR peripheralData; ! 1636: NTSTATUS status = STATUS_SUCCESS; ! 1637: ULONG i; ! 1638: ULONG listCount; ! 1639: PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor; ! 1640: CM_PARTIAL_RESOURCE_DESCRIPTOR tmpResourceDescriptor; ! 1641: PCM_KEYBOARD_DEVICE_DATA keyboardSpecificData; ! 1642: BOOLEAN defaultInterruptShare; ! 1643: KINTERRUPT_MODE defaultInterruptMode; ! 1644: ! 1645: I8xPrint(( ! 1646: 1, ! 1647: "I8042PRT-I8xKeyboardPeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n", ! 1648: PathName, BusType, BusNumber ! 1649: )); ! 1650: I8xPrint(( ! 1651: 1, ! 1652: " Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n", ! 1653: ControllerType, ControllerNumber, ControllerInformation ! 1654: )); ! 1655: I8xPrint(( ! 1656: 1, ! 1657: " Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n", ! 1658: PeripheralType, PeripheralNumber, PeripheralInformation ! 1659: )); ! 1660: ! 1661: ! 1662: // ! 1663: // Get the length of the peripheral identifier information. ! 1664: // ! 1665: ! 1666: unicodeIdentifier.Length = ! 1667: (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength; ! 1668: ! 1669: // ! 1670: // If we already have the configuration information for the ! 1671: // keyboard peripheral, or if the peripheral identifier is missing, ! 1672: // just return. ! 1673: // ! 1674: ! 1675: deviceExtension = (PDEVICE_EXTENSION) Context; ! 1676: if ((deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) ! 1677: || (unicodeIdentifier.Length == 0)) { ! 1678: return (status); ! 1679: } ! 1680: ! 1681: configuration = &deviceExtension->Configuration; ! 1682: ! 1683: // ! 1684: // Get the identifier information for the peripheral. ! 1685: // ! 1686: ! 1687: unicodeIdentifier.MaximumLength = unicodeIdentifier.Length; ! 1688: unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation + ! 1689: IoQueryDeviceIdentifier))) + ! 1690: (*(PeripheralInformation + ! 1691: IoQueryDeviceIdentifier))->DataOffset); ! 1692: I8xPrint(( ! 1693: 1, ! 1694: "I8042PRT-I8xKeyboardPeripheralCallout: Keyboard type %ws\n", ! 1695: unicodeIdentifier.Buffer ! 1696: )); ! 1697: ! 1698: deviceExtension->HardwarePresent |= KEYBOARD_HARDWARE_PRESENT; ! 1699: ! 1700: // ! 1701: // Initialize the Keyboard Type to unknown. ! 1702: // ! 1703: ! 1704: configuration->KeyboardAttributes.KeyboardIdentifier.Type = 0; ! 1705: configuration->KeyboardAttributes.KeyboardIdentifier.Subtype = 0; ! 1706: ! 1707: // ! 1708: // Look through the peripheral's resource list for device-specific ! 1709: // information. The keyboard-specific information is defined ! 1710: // in sdk\inc\ntconfig.h. ! 1711: // ! 1712: ! 1713: if ((*(PeripheralInformation + IoQueryDeviceConfigurationData))->DataLength != 0){ ! 1714: peripheralData = ((PUCHAR) (*(PeripheralInformation + ! 1715: IoQueryDeviceConfigurationData))) + ! 1716: (*(PeripheralInformation + ! 1717: IoQueryDeviceConfigurationData))->DataOffset; ! 1718: ! 1719: peripheralData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, ! 1720: PartialResourceList); ! 1721: ! 1722: listCount = ((PCM_PARTIAL_RESOURCE_LIST) peripheralData)->Count; ! 1723: ! 1724: resourceDescriptor = ! 1725: ((PCM_PARTIAL_RESOURCE_LIST) peripheralData)->PartialDescriptors; ! 1726: ! 1727: for (i = 0; i < listCount; i++, resourceDescriptor++) { ! 1728: switch(resourceDescriptor->Type) { ! 1729: ! 1730: case CmResourceTypeDeviceSpecific: ! 1731: ! 1732: // ! 1733: // Get the keyboard type, subtype, and the initial ! 1734: // settings for the LEDs. ! 1735: // ! 1736: ! 1737: keyboardSpecificData = ! 1738: (PCM_KEYBOARD_DEVICE_DATA)(((PUCHAR)resourceDescriptor) ! 1739: + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); ! 1740: if (keyboardSpecificData->Type<= NUM_KNOWN_KEYBOARD_TYPES){ ! 1741: configuration->KeyboardAttributes.KeyboardIdentifier.Type = ! 1742: keyboardSpecificData->Type; ! 1743: } ! 1744: configuration->KeyboardAttributes.KeyboardIdentifier.Subtype = ! 1745: keyboardSpecificData->Subtype; ! 1746: configuration->KeyboardIndicators.LedFlags = ! 1747: (keyboardSpecificData->KeyboardFlags >> 4) & 7; ! 1748: ! 1749: break; ! 1750: ! 1751: default: ! 1752: break; ! 1753: } ! 1754: } ! 1755: } ! 1756: ! 1757: // ! 1758: // If no keyboard-specific information (i.e., keyboard type, subtype, ! 1759: // and initial LED settings) was found, use the keyboard driver ! 1760: // defaults. ! 1761: // ! 1762: ! 1763: if (configuration->KeyboardAttributes.KeyboardIdentifier.Type == 0) { ! 1764: ! 1765: I8xPrint(( ! 1766: 1, ! 1767: "I8042PRT-I8xKeyboardPeripheralCallout: Using default keyboard type\n" ! 1768: )); ! 1769: ! 1770: configuration->KeyboardAttributes.KeyboardIdentifier.Type = ! 1771: KEYBOARD_TYPE_DEFAULT; ! 1772: configuration->KeyboardIndicators.LedFlags = ! 1773: KEYBOARD_INDICATORS_DEFAULT; ! 1774: ! 1775: } ! 1776: ! 1777: I8xPrint(( ! 1778: 1, ! 1779: "I8042PRT-I8xKeyboardPeripheralCallout: Keyboard device specific data --\n" ! 1780: )); ! 1781: I8xPrint(( ! 1782: 1, ! 1783: " Type = %d, Subtype = %d, Initial LEDs = 0x%x\n", ! 1784: configuration->KeyboardAttributes.KeyboardIdentifier.Type, ! 1785: configuration->KeyboardAttributes.KeyboardIdentifier.Subtype, ! 1786: configuration->KeyboardIndicators.LedFlags ! 1787: )); ! 1788: ! 1789: // ! 1790: // Get the bus information. ! 1791: // ! 1792: ! 1793: configuration->InterfaceType = BusType; ! 1794: configuration->BusNumber = BusNumber; ! 1795: configuration->FloatingSave = I8042_FLOATING_SAVE; ! 1796: ! 1797: if (BusType == MicroChannel) { ! 1798: defaultInterruptShare = TRUE; ! 1799: defaultInterruptMode = LevelSensitive; ! 1800: } else { ! 1801: defaultInterruptShare = I8042_INTERRUPT_SHARE; ! 1802: defaultInterruptMode = I8042_INTERRUPT_MODE; ! 1803: } ! 1804: ! 1805: // ! 1806: // Look through the controller's resource list for interrupt and port ! 1807: // configuration information. ! 1808: // ! 1809: ! 1810: if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){ ! 1811: controllerData = ((PUCHAR) (*(ControllerInformation + ! 1812: IoQueryDeviceConfigurationData))) + ! 1813: (*(ControllerInformation + ! 1814: IoQueryDeviceConfigurationData))->DataOffset; ! 1815: ! 1816: controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, ! 1817: PartialResourceList); ! 1818: ! 1819: listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count; ! 1820: ! 1821: resourceDescriptor = ! 1822: ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors; ! 1823: ! 1824: for (i = 0; i < listCount; i++, resourceDescriptor++) { ! 1825: switch(resourceDescriptor->Type) { ! 1826: case CmResourceTypePort: ! 1827: ! 1828: // ! 1829: // Copy the port information. We will sort the port list ! 1830: // into ascending order based on the starting port address ! 1831: // later (note that we *know* there are a max of two port ! 1832: // ranges for the i8042). ! 1833: // ! 1834: ! 1835: ASSERT(configuration->PortListCount < MaximumPortCount); ! 1836: configuration->PortList[configuration->PortListCount] = ! 1837: *resourceDescriptor; ! 1838: configuration->PortList[configuration->PortListCount].ShareDisposition = ! 1839: I8042_REGISTER_SHARE? CmResourceShareShared: ! 1840: CmResourceShareDriverExclusive; ! 1841: configuration->PortListCount += 1; ! 1842: ! 1843: break; ! 1844: ! 1845: case CmResourceTypeInterrupt: ! 1846: ! 1847: // ! 1848: // Copy the interrupt information. ! 1849: // ! 1850: ! 1851: configuration->KeyboardInterrupt = *resourceDescriptor; ! 1852: configuration->KeyboardInterrupt.ShareDisposition = ! 1853: defaultInterruptShare? CmResourceShareShared : ! 1854: CmResourceShareDeviceExclusive; ! 1855: ! 1856: break; ! 1857: ! 1858: case CmResourceTypeDeviceSpecific: ! 1859: break; ! 1860: ! 1861: default: ! 1862: break; ! 1863: } ! 1864: } ! 1865: } ! 1866: ! 1867: // ! 1868: // If no interrupt configuration information was found, use the ! 1869: // keyboard driver defaults. ! 1870: // ! 1871: ! 1872: if (!(configuration->KeyboardInterrupt.Type & CmResourceTypeInterrupt)) { ! 1873: ! 1874: I8xPrint(( ! 1875: 1, ! 1876: "I8042PRT-I8xKeyboardPeripheralCallout: Using default keyboard interrupt config\n" ! 1877: )); ! 1878: ! 1879: configuration->KeyboardInterrupt.Type = CmResourceTypeInterrupt; ! 1880: configuration->KeyboardInterrupt.ShareDisposition = ! 1881: defaultInterruptShare? CmResourceShareShared : ! 1882: CmResourceShareDeviceExclusive; ! 1883: configuration->KeyboardInterrupt.Flags = ! 1884: (defaultInterruptMode == Latched)? CM_RESOURCE_INTERRUPT_LATCHED : ! 1885: CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 1886: configuration->KeyboardInterrupt.u.Interrupt.Level = KEYBOARD_IRQL; ! 1887: configuration->KeyboardInterrupt.u.Interrupt.Vector = KEYBOARD_VECTOR; ! 1888: } ! 1889: ! 1890: I8xPrint(( ! 1891: 1, ! 1892: "I8042PRT-I8xKeyboardPeripheralCallout: Keyboard interrupt config --\n" ! 1893: )); ! 1894: I8xPrint(( ! 1895: 1, ! 1896: " %s, %s, Irq = %d\n", ! 1897: configuration->KeyboardInterrupt.ShareDisposition == CmResourceShareShared? ! 1898: "Sharable" : "NonSharable", ! 1899: configuration->KeyboardInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED? ! 1900: "Latched" : "Level Sensitive", ! 1901: configuration->KeyboardInterrupt.u.Interrupt.Vector ! 1902: )); ! 1903: ! 1904: // ! 1905: // If no port configuration information was found, use the ! 1906: // keyboard driver defaults. ! 1907: // ! 1908: ! 1909: if (configuration->PortListCount == 0) { ! 1910: ! 1911: // ! 1912: // No port configuration information was found, so use ! 1913: // the driver defaults. ! 1914: // ! 1915: ! 1916: I8xPrint(( ! 1917: 1, ! 1918: "I8042PRT-I8xKeyboardPeripheralCallout: Using default port config\n" ! 1919: )); ! 1920: ! 1921: configuration->PortList[DataPort].Type = CmResourceTypePort; ! 1922: configuration->PortList[DataPort].Flags = I8042_PORT_TYPE; ! 1923: configuration->PortList[DataPort].ShareDisposition = ! 1924: I8042_REGISTER_SHARE? CmResourceShareShared: ! 1925: CmResourceShareDriverExclusive; ! 1926: configuration->PortList[DataPort].u.Port.Start.LowPart = ! 1927: I8042_PHYSICAL_BASE + I8042_DATA_REGISTER_OFFSET; ! 1928: configuration->PortList[DataPort].u.Port.Start.HighPart = 0; ! 1929: configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH; ! 1930: ! 1931: configuration->PortList[CommandPort].Type = CmResourceTypePort; ! 1932: configuration->PortList[CommandPort].Flags = I8042_PORT_TYPE; ! 1933: configuration->PortList[CommandPort].ShareDisposition = ! 1934: I8042_REGISTER_SHARE? CmResourceShareShared: ! 1935: CmResourceShareDriverExclusive; ! 1936: configuration->PortList[CommandPort].u.Port.Start.LowPart = ! 1937: I8042_PHYSICAL_BASE + I8042_COMMAND_REGISTER_OFFSET; ! 1938: configuration->PortList[CommandPort].u.Port.Start.HighPart = 0; ! 1939: configuration->PortList[CommandPort].u.Port.Length = I8042_REGISTER_LENGTH; ! 1940: ! 1941: configuration->PortListCount = 2; ! 1942: } else if (configuration->PortListCount == 1) { ! 1943: ! 1944: // ! 1945: // Kludge for Jazz machines. Their ARC firmware neglects to ! 1946: // separate out the port addresses, so fix that up here. ! 1947: // ! 1948: ! 1949: configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH; ! 1950: configuration->PortList[CommandPort] = configuration->PortList[DataPort]; ! 1951: configuration->PortList[CommandPort].u.Port.Start.LowPart += ! 1952: I8042_COMMAND_REGISTER_OFFSET; ! 1953: configuration->PortListCount += 1; ! 1954: } else { ! 1955: ! 1956: // ! 1957: // Put the lowest port address range in the DataPort element of ! 1958: // the port list. ! 1959: // ! 1960: ! 1961: if (configuration->PortList[CommandPort].u.Port.Start.LowPart ! 1962: < configuration->PortList[DataPort].u.Port.Start.LowPart) { ! 1963: tmpResourceDescriptor = configuration->PortList[DataPort]; ! 1964: configuration->PortList[DataPort] = ! 1965: configuration->PortList[CommandPort]; ! 1966: configuration->PortList[CommandPort] = tmpResourceDescriptor; ! 1967: } ! 1968: } ! 1969: ! 1970: for (i = 0; i < configuration->PortListCount; i++) { ! 1971: ! 1972: I8xPrint(( ! 1973: 1, ! 1974: " %s, Ports 0x%x - 0x%x\n", ! 1975: configuration->PortList[i].ShareDisposition ! 1976: == CmResourceShareShared? "Sharable" : "NonSharable", ! 1977: configuration->PortList[i].u.Port.Start.LowPart, ! 1978: configuration->PortList[i].u.Port.Start.LowPart + ! 1979: configuration->PortList[i].u.Port.Length - 1 ! 1980: )); ! 1981: } ! 1982: ! 1983: return(status); ! 1984: } ! 1985:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.