|
|
1.1 ! root 1: ! 2: /*++ ! 3: ! 4: Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation ! 5: ! 6: Module Name: ! 7: ! 8: moudep.c ! 9: ! 10: Abstract: ! 11: ! 12: The initialization and hardware-dependent portions of ! 13: the Intel i8042 port driver which are specific to ! 14: 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: 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,I8xMouseConfiguration) ! 46: #pragma alloc_text(init,I8xMousePeripheralCallout) ! 47: #pragma alloc_text(init,I8xInitializeMouse) ! 48: #endif ! 49: ! 50: ! 51: BOOLEAN ! 52: I8042MouseInterruptService( ! 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 mouse device. ! 62: ! 63: Arguments: ! 64: ! 65: Interrupt - A pointer to the interrupt object for this interrupt. ! 66: ! 67: Context - A pointer to the device object. ! 68: ! 69: Return Value: ! 70: ! 71: Returns TRUE if the interrupt was expected (and therefore processed); ! 72: otherwise, FALSE is returned. ! 73: ! 74: --*/ ! 75: ! 76: { ! 77: PDEVICE_EXTENSION deviceExtension; ! 78: PDEVICE_OBJECT deviceObject; ! 79: LARGE_INTEGER tickDelta, newTick; ! 80: UCHAR previousButtons; ! 81: UCHAR previousSignAndOverflow; ! 82: UCHAR byte; ! 83: ! 84: UNREFERENCED_PARAMETER(Interrupt); ! 85: ! 86: I8xPrint((2, "I8042PRT-I8042MouseInterruptService: enter\n")); ! 87: ! 88: deviceObject = (PDEVICE_OBJECT) Context; ! 89: deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension; ! 90: ! 91: // ! 92: // Verify that this device really interrupted. Check the status ! 93: // register. The Output Buffer Full bit should be set, and the ! 94: // Auxiliary Device Output Buffer Full bit should be set. ! 95: // ! 96: ! 97: if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort]) ! 98: & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) ! 99: != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) { ! 100: ! 101: // ! 102: // Stall and then try again. The Olivetti MIPS machine ! 103: // sometimes gets a mouse interrupt before the status ! 104: // register is set. ! 105: // ! 106: ! 107: KeStallExecutionProcessor(10); ! 108: if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort]) ! 109: & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) ! 110: != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) { ! 111: ! 112: // ! 113: // Not our interrupt. ! 114: // ! 115: ! 116: I8xPrint(( ! 117: 1, ! 118: "I8042PRT-I8042MouseInterruptService: not our interrupt!\n" ! 119: )); ! 120: return(FALSE); ! 121: } ! 122: } ! 123: ! 124: // ! 125: // Read the byte from the i8042 data port. ! 126: // ! 127: ! 128: I8xGetByteAsynchronous( ! 129: (CCHAR) MouseDeviceType, ! 130: deviceExtension, ! 131: &byte ! 132: ); ! 133: ! 134: I8xPrint(( ! 135: 3, ! 136: "I8042PRT-I8042MouseInterruptService: byte 0x%x\n", ! 137: byte ! 138: )); ! 139: ! 140: // ! 141: // Take the appropriate action, depending on the current state. ! 142: // When the state is Idle, we expect to receive mouse button ! 143: // data. When the state is XMovement, we expect to receive mouse ! 144: // motion in the X direction data. When the state is YMovement, ! 145: // we expect to receive mouse motion in the Y direction data. Once ! 146: // the Y motion data has been received, the data is queued to the ! 147: // mouse InputData queue, the mouse ISR DPC is requested, and the ! 148: // state returns to Idle. ! 149: // ! 150: ! 151: KeQueryTickCount(&newTick); ! 152: tickDelta = RtlLargeIntegerSubtract( ! 153: newTick, ! 154: deviceExtension->MouseExtension.PreviousTick ! 155: ); ! 156: ! 157: if ((deviceExtension->MouseExtension.InputState != MouseIdle) ! 158: && (deviceExtension->MouseExtension.InputState != MouseExpectingACK) ! 159: && ((tickDelta.LowPart >= deviceExtension->MouseExtension.SynchTickCount) ! 160: || (tickDelta.HighPart != 0))) { ! 161: ! 162: // ! 163: // It has been a long time since we got a byte of ! 164: // the data packet. Assume that we are now receiving ! 165: // the first byte of a new packet, and discard any ! 166: // partially received packet. ! 167: // ! 168: // N.B. We assume that SynchTickCount is ULONG, and avoid ! 169: // a LARGE_INTEGER compare with tickDelta... ! 170: // ! 171: ! 172: I8xPrint(( ! 173: 1, ! 174: "I8042PRT-I8042MouseInterruptService: State was %d, synching\n", ! 175: deviceExtension->MouseExtension.InputState ! 176: )); ! 177: ! 178: deviceExtension->MouseExtension.InputState = MouseIdle; ! 179: } ! 180: ! 181: deviceExtension->MouseExtension.PreviousTick = newTick; ! 182: ! 183: switch(deviceExtension->MouseExtension.InputState) { ! 184: ! 185: // ! 186: // The mouse interrupted with a status byte. The status byte ! 187: // contains information on the mouse button state along with ! 188: // the sign and overflow bits for the (yet-to-be-received) ! 189: // X and Y motion bytes. ! 190: // ! 191: ! 192: case MouseIdle: ! 193: ! 194: I8xPrint(( ! 195: 3, ! 196: "I8042PRT-I8042MouseInterruptService: mouse status byte\n" ! 197: )); ! 198: ! 199: // ! 200: // Update CurrentInput with button transition data. ! 201: // I.e., set a button up/down bit in the Buttons field if ! 202: // the state of a given button has changed since we ! 203: // received the last packet. ! 204: // ! 205: ! 206: previousButtons = ! 207: deviceExtension->MouseExtension.PreviousButtons; ! 208: ! 209: deviceExtension->MouseExtension.CurrentInput.Buttons = 0; ! 210: ! 211: if ((!(previousButtons & LEFT_BUTTON_DOWN)) ! 212: && (byte & LEFT_BUTTON_DOWN)) { ! 213: deviceExtension->MouseExtension.CurrentInput.Buttons |= ! 214: MOUSE_LEFT_BUTTON_DOWN; ! 215: } else ! 216: if ((previousButtons & LEFT_BUTTON_DOWN) ! 217: && !(byte & LEFT_BUTTON_DOWN)) { ! 218: deviceExtension->MouseExtension.CurrentInput.Buttons |= ! 219: MOUSE_LEFT_BUTTON_UP; ! 220: } ! 221: if ((!(previousButtons & RIGHT_BUTTON_DOWN)) ! 222: && (byte & RIGHT_BUTTON_DOWN)) { ! 223: deviceExtension->MouseExtension.CurrentInput.Buttons |= ! 224: MOUSE_RIGHT_BUTTON_DOWN; ! 225: } else ! 226: if ((previousButtons & RIGHT_BUTTON_DOWN) ! 227: && !(byte & RIGHT_BUTTON_DOWN)) { ! 228: deviceExtension->MouseExtension.CurrentInput.Buttons |= ! 229: MOUSE_RIGHT_BUTTON_UP; ! 230: } ! 231: if ((!(previousButtons & MIDDLE_BUTTON_DOWN)) ! 232: && (byte & MIDDLE_BUTTON_DOWN)) { ! 233: deviceExtension->MouseExtension.CurrentInput.Buttons |= ! 234: MOUSE_MIDDLE_BUTTON_DOWN; ! 235: } else ! 236: if ((previousButtons & MIDDLE_BUTTON_DOWN) ! 237: && !(byte & MIDDLE_BUTTON_DOWN)) { ! 238: deviceExtension->MouseExtension.CurrentInput.Buttons |= ! 239: MOUSE_MIDDLE_BUTTON_UP; ! 240: } ! 241: ! 242: // ! 243: // Save the button state for comparison the next time around. ! 244: // ! 245: ! 246: deviceExtension->MouseExtension.PreviousButtons = ! 247: byte & (RIGHT_BUTTON_DOWN|MIDDLE_BUTTON_DOWN|LEFT_BUTTON_DOWN); ! 248: ! 249: // ! 250: // Save the sign and overflow information from the current byte. ! 251: // ! 252: ! 253: deviceExtension->MouseExtension.CurrentSignAndOverflow = ! 254: (UCHAR) (byte & MOUSE_SIGN_OVERFLOW_MASK); ! 255: ! 256: // ! 257: // Update to the next state. ! 258: // ! 259: ! 260: deviceExtension->MouseExtension.InputState = XMovement; ! 261: ! 262: break; ! 263: ! 264: // ! 265: // The mouse interrupted with the X motion byte. Apply ! 266: // the sign and overflow bits from the mouse status byte received ! 267: // previously. Attempt to correct for bogus changes in sign ! 268: // that occur with large, rapid mouse movements. ! 269: // ! 270: ! 271: case XMovement: ! 272: ! 273: I8xPrint(( ! 274: 3, ! 275: "I8042PRT-I8042MouseInterruptService: mouse LastX byte\n" ! 276: )); ! 277: ! 278: // ! 279: // Update CurrentInput with the X motion data. ! 280: // ! 281: ! 282: if (deviceExtension->MouseExtension.CurrentSignAndOverflow ! 283: & X_OVERFLOW) { ! 284: ! 285: // ! 286: // Handle overflow in the X direction. If the previous ! 287: // mouse movement overflowed too, ensure that the current ! 288: // overflow is in the same direction (i.e., that the sign ! 289: // is the same as it was for the previous event). We do this ! 290: // to correct for hardware problems -- it should not be possible ! 291: // to overflow in one direction and then immediately overflow ! 292: // in the opposite direction. ! 293: // ! 294: ! 295: previousSignAndOverflow = ! 296: deviceExtension->MouseExtension.PreviousSignAndOverflow; ! 297: if (previousSignAndOverflow & X_OVERFLOW) { ! 298: if ((previousSignAndOverflow & X_DATA_SIGN) != ! 299: (deviceExtension->MouseExtension.CurrentSignAndOverflow ! 300: & X_DATA_SIGN)) { ! 301: deviceExtension->MouseExtension.CurrentSignAndOverflow ! 302: ^= X_DATA_SIGN; ! 303: } ! 304: } ! 305: ! 306: if (deviceExtension->MouseExtension.CurrentSignAndOverflow & ! 307: X_DATA_SIGN) ! 308: deviceExtension->MouseExtension.CurrentInput.LastX = ! 309: (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA; ! 310: else ! 311: deviceExtension->MouseExtension.CurrentInput.LastX = ! 312: (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA; ! 313: ! 314: } else { ! 315: ! 316: // ! 317: // No overflow. Just store the data, correcting for the ! 318: // sign if necessary. ! 319: // ! 320: ! 321: deviceExtension->MouseExtension.CurrentInput.LastX = ! 322: (ULONG) byte; ! 323: if (deviceExtension->MouseExtension.CurrentSignAndOverflow & ! 324: X_DATA_SIGN) ! 325: deviceExtension->MouseExtension.CurrentInput.LastX |= ! 326: MOUSE_MAXIMUM_NEGATIVE_DELTA; ! 327: } ! 328: ! 329: // ! 330: // Update to the next state. ! 331: // ! 332: ! 333: deviceExtension->MouseExtension.InputState = YMovement; ! 334: ! 335: break; ! 336: ! 337: // ! 338: // The mouse interrupted with the Y motion byte. Apply ! 339: // the sign and overflow bits from the mouse status byte received ! 340: // previously. [Attempt to correct for bogus changes in sign ! 341: // that occur with large, rapid mouse movements.] Write the ! 342: // data to the mouse InputData queue, and queue the mouse ISR DPC ! 343: // to complete the interrupt processing. ! 344: // ! 345: ! 346: case YMovement: ! 347: ! 348: I8xPrint(( ! 349: 3, ! 350: "I8042PRT-I8042MouseInterruptService: mouse LastY byte\n" ! 351: )); ! 352: ! 353: // ! 354: // Update CurrentInput with the Y motion data. ! 355: // ! 356: ! 357: if (deviceExtension->MouseExtension.CurrentSignAndOverflow ! 358: & Y_OVERFLOW) { ! 359: ! 360: // ! 361: // Handle overflow in the Y direction. If the previous ! 362: // mouse movement overflowed too, ensure that the current ! 363: // overflow is in the same direction (i.e., that the sign ! 364: // is the same as it was for the previous event). We do this ! 365: // to correct for hardware problems -- it should not be possible ! 366: // to overflow in one direction and then immediately overflow ! 367: // in the opposite direction. ! 368: // ! 369: ! 370: previousSignAndOverflow = ! 371: deviceExtension->MouseExtension.PreviousSignAndOverflow; ! 372: if (previousSignAndOverflow & Y_OVERFLOW) { ! 373: if ((previousSignAndOverflow & Y_DATA_SIGN) != ! 374: (deviceExtension->MouseExtension.CurrentSignAndOverflow ! 375: & Y_DATA_SIGN)) { ! 376: deviceExtension->MouseExtension.CurrentSignAndOverflow ! 377: ^= Y_DATA_SIGN; ! 378: } ! 379: } ! 380: ! 381: if (deviceExtension->MouseExtension.CurrentSignAndOverflow & ! 382: Y_DATA_SIGN) ! 383: deviceExtension->MouseExtension.CurrentInput.LastY = ! 384: (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA; ! 385: else ! 386: deviceExtension->MouseExtension.CurrentInput.LastY = ! 387: (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA; ! 388: ! 389: } else { ! 390: ! 391: // ! 392: // No overflow. Just store the data, correcting for the ! 393: // sign if necessary. ! 394: // ! 395: ! 396: deviceExtension->MouseExtension.CurrentInput.LastY = ! 397: (ULONG) byte; ! 398: if (deviceExtension->MouseExtension.CurrentSignAndOverflow & ! 399: Y_DATA_SIGN) ! 400: deviceExtension->MouseExtension.CurrentInput.LastY |= ! 401: MOUSE_MAXIMUM_NEGATIVE_DELTA; ! 402: ! 403: // ! 404: // Negate the LastY value (the hardware reports positive ! 405: // motion in the direction that we consider negative). ! 406: // ! 407: ! 408: deviceExtension->MouseExtension.CurrentInput.LastY = ! 409: -deviceExtension->MouseExtension.CurrentInput.LastY; ! 410: ! 411: } ! 412: ! 413: // ! 414: // Update our notion of the previous sign and overflow bits for ! 415: // the start of the next mouse input sequence. ! 416: // ! 417: ! 418: deviceExtension->MouseExtension.PreviousSignAndOverflow = ! 419: deviceExtension->MouseExtension.CurrentSignAndOverflow; ! 420: ! 421: // ! 422: // If the mouse is enabled, add the data to the InputData queue ! 423: // and queue the ISR DPC. One might wonder why we bother to ! 424: // do all this processing of the mouse packet, only to toss it ! 425: // away (i.e., not queue it) at this point. The answer is that ! 426: // this mouse provides no data to allow the driver to determine ! 427: // when the first byte of a packet is received -- if the driver ! 428: // doesn't process all interrupts from the start, there is no ! 429: // way to keep MouseExtension.InputState in synch with hardware ! 430: // reality. ! 431: // ! 432: ! 433: if (deviceExtension->MouseEnableCount) { ! 434: deviceExtension->MouseExtension.CurrentInput.UnitId = ! 435: deviceExtension->MouseExtension.UnitId; ! 436: if (!I8xWriteDataToMouseQueue( ! 437: &deviceExtension->MouseExtension, ! 438: &deviceExtension->MouseExtension.CurrentInput ! 439: )) { ! 440: ! 441: // ! 442: // InputData queue overflowed. ! 443: // ! 444: // Queue a DPC to log an overrun error. ! 445: // ! 446: ! 447: I8xPrint(( ! 448: 1, ! 449: "I8042PRT-I8042MouseInterruptService: queue overflow\n" ! 450: )); ! 451: ! 452: if (deviceExtension->MouseExtension.OkayToLogOverflow) { ! 453: KeInsertQueueDpc( ! 454: &deviceExtension->ErrorLogDpc, ! 455: (PIRP) NULL, ! 456: (PVOID) (ULONG) I8042_MOU_BUFFER_OVERFLOW ! 457: ); ! 458: deviceExtension->MouseExtension.OkayToLogOverflow = ! 459: FALSE; ! 460: } ! 461: ! 462: } else if (deviceExtension->DpcInterlockMouse >= 0) { ! 463: ! 464: // ! 465: // The ISR DPC is already executing. Tell the ISR DPC it has ! 466: // more work to do by incrementing DpcInterlockMouse. ! 467: // ! 468: ! 469: deviceExtension->DpcInterlockMouse += 1; ! 470: ! 471: } else { ! 472: ! 473: // ! 474: // Queue the ISR DPC. ! 475: // ! 476: ! 477: KeInsertQueueDpc( ! 478: &deviceExtension->MouseIsrDpc, ! 479: deviceObject->CurrentIrp, ! 480: NULL ! 481: ); ! 482: } ! 483: ! 484: } ! 485: ! 486: // ! 487: // Reset the state. ! 488: // ! 489: ! 490: deviceExtension->MouseExtension.InputState = MouseIdle; ! 491: ! 492: break; ! 493: ! 494: case MouseExpectingACK: ! 495: ! 496: // ! 497: // This is a special case. We hit this on one of the very ! 498: // first mouse interrupts following the IoConnectInterrupt. ! 499: // The interrupt is caused when we enable mouse transmissions ! 500: // via I8xMouseEnableTransmission() -- the hardware returns ! 501: // an ACK. Just toss this byte away, and set the input state ! 502: // to coincide with the start of a new mouse data packet. ! 503: // ! 504: ! 505: I8xPrint(( ! 506: 1, ! 507: "I8042PRT-I8042MouseInterruptService: expecting ACK (0x%x), got 0x%x\n", ! 508: (ULONG) ACKNOWLEDGE, ! 509: (ULONG) byte ! 510: )); ! 511: ! 512: if (byte == (UCHAR) ACKNOWLEDGE) { ! 513: deviceExtension->MouseExtension.InputState = MouseIdle; ! 514: } else if (byte == (UCHAR) RESEND) { ! 515: ! 516: // ! 517: // Resend the "Enable Mouse Transmission" sequence. ! 518: // ! 519: // NOTE: This is a hack for the Olivetti MIPS machine, ! 520: // which sends a resend response if a key is held down ! 521: // while we're attempting the I8xMouseEnableTransmission. ! 522: // ! 523: ! 524: I8xPutByteAsynchronous( ! 525: (CCHAR) CommandPort, ! 526: deviceExtension, ! 527: (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE ! 528: ); ! 529: ! 530: I8xPutByteAsynchronous( ! 531: (CCHAR) DataPort, ! 532: deviceExtension, ! 533: (UCHAR) ENABLE_MOUSE_TRANSMISSION ! 534: ); ! 535: } ! 536: ! 537: break; ! 538: ! 539: default: ! 540: ! 541: I8xPrint(( ! 542: 3, ! 543: "I8042PRT-I8042MouseInterruptService: INVALID STATE\n" ! 544: )); ! 545: ! 546: // ! 547: // Queue a DPC to log an internal driver error. ! 548: // ! 549: ! 550: KeInsertQueueDpc( ! 551: &deviceExtension->ErrorLogDpc, ! 552: (PIRP) NULL, ! 553: (PVOID) (ULONG) I8042_INVALID_ISR_STATE ! 554: ); ! 555: ! 556: ASSERT(FALSE); ! 557: break; ! 558: ! 559: } ! 560: ! 561: I8xPrint((2, "I8042PRT-I8042MouseInterruptService: exit\n")); ! 562: ! 563: return(TRUE); ! 564: } ! 565: ! 566: NTSTATUS ! 567: I8xInitializeMouse( ! 568: IN PDEVICE_OBJECT DeviceObject ! 569: ) ! 570: ! 571: /*++ ! 572: ! 573: Routine Description: ! 574: ! 575: This routine initializes the i8042 mouse hardware. It is called ! 576: only at initialization, and does not synchronize access to the hardware. ! 577: ! 578: Arguments: ! 579: ! 580: DeviceObject - Pointer to the device object. ! 581: ! 582: Return Value: ! 583: ! 584: Returns status. ! 585: ! 586: --*/ ! 587: ! 588: { ! 589: NTSTATUS status; ! 590: PDEVICE_EXTENSION deviceExtension; ! 591: UCHAR byte; ! 592: ULONG i; ! 593: PIO_ERROR_LOG_PACKET errorLogEntry; ! 594: ULONG uniqueErrorValue; ! 595: NTSTATUS errorCode = STATUS_SUCCESS; ! 596: ULONG dumpCount = 0; ! 597: ! 598: #define DUMP_COUNT 4 ! 599: ULONG dumpData[DUMP_COUNT]; ! 600: ! 601: I8xPrint((2, "I8042PRT-I8xInitializeMouse: enter\n")); ! 602: ! 603: for (i = 0; i < DUMP_COUNT; i++) ! 604: dumpData[i] = 0; ! 605: ! 606: // ! 607: // Get the device extension. ! 608: // ! 609: ! 610: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; ! 611: ! 612: // ! 613: // Reset the mouse. Send a Write To Auxiliary Device command to the ! 614: // 8042 controller. Then send the Reset Mouse command to the mouse ! 615: // through the 8042 data register. Expect to get back an ACK, followed ! 616: // by a completion code and the ID code (0x00). ! 617: // ! 618: ! 619: status = I8xPutBytePolled( ! 620: (CCHAR) DataPort, ! 621: WAIT_FOR_ACKNOWLEDGE, ! 622: (CCHAR) MouseDeviceType, ! 623: deviceExtension, ! 624: (UCHAR) MOUSE_RESET ! 625: ); ! 626: if (!NT_SUCCESS(status)) { ! 627: I8xPrint(( ! 628: 1, ! 629: "I8042PRT-I8xInitializeMouse: failed mouse reset, status 0x%x\n", ! 630: status ! 631: )); ! 632: ! 633: // ! 634: // Set up error log info. ! 635: // ! 636: ! 637: errorCode = I8042_MOU_RESET_COMMAND_FAILED; ! 638: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 415; ! 639: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 640: dumpData[1] = DataPort; ! 641: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE; ! 642: dumpData[3] = MOUSE_RESET; ! 643: dumpCount = 4; ! 644: ! 645: goto I8xInitializeMouseExit; ! 646: } ! 647: ! 648: // ! 649: // Get the mouse reset responses. The first response should be a ! 650: // MOUSE_COMPLETE. The second response should be the mouse ID. ! 651: // Note that it is usually necessary to stall a long time to get the ! 652: // mouse reset/self-test to work. The stall value was determined by ! 653: // experimentation. ! 654: // ! 655: // ! 656: ! 657: for (i = 0; i < 11200; i++) { ! 658: ! 659: status = I8xGetBytePolled( ! 660: (CCHAR) ControllerDeviceType, ! 661: deviceExtension, ! 662: &byte ! 663: ); ! 664: ! 665: if (NT_SUCCESS(status) && (byte == (UCHAR) MOUSE_COMPLETE)) { ! 666: ! 667: // ! 668: // The reset completed successfully. ! 669: // ! 670: ! 671: break; ! 672: ! 673: ! 674: } else { ! 675: ! 676: // ! 677: // Stall, and then try again to get a response from ! 678: // the reset. ! 679: // ! 680: ! 681: if (status == STATUS_IO_TIMEOUT) { ! 682: ! 683: // ! 684: // Stall, and then try again to get a response from ! 685: // the reset. ! 686: // ! 687: ! 688: KeStallExecutionProcessor(50); ! 689: ! 690: } else { ! 691: ! 692: break; ! 693: ! 694: } ! 695: } ! 696: } ! 697: ! 698: if (!NT_SUCCESS(status)) { ! 699: I8xPrint(( ! 700: 1, ! 701: "I8042PRT-I8xInitializeMouse: failed reset response 1, status 0x%x, byte 0x%x\n", ! 702: status, ! 703: byte ! 704: )); ! 705: ! 706: // ! 707: // Set up error log info. ! 708: // ! 709: ! 710: errorCode = I8042_MOU_RESET_RESPONSE_FAILED; ! 711: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 420; ! 712: dumpData[0] = KBDMOU_INCORRECT_RESPONSE; ! 713: dumpData[1] = ControllerDeviceType; ! 714: dumpData[2] = MOUSE_COMPLETE; ! 715: dumpData[3] = byte; ! 716: dumpCount = 4; ! 717: ! 718: goto I8xInitializeMouseExit; ! 719: } ! 720: ! 721: status = I8xGetBytePolled( ! 722: (CCHAR) ControllerDeviceType, ! 723: deviceExtension, ! 724: &byte ! 725: ); ! 726: ! 727: if ((!NT_SUCCESS(status)) || (byte != MOUSE_ID_BYTE)) { ! 728: I8xPrint(( ! 729: 1, ! 730: "I8042PRT-I8xInitializeMouse: failed reset response 2, status 0x%x, byte 0x%x\n", ! 731: status, ! 732: byte ! 733: )); ! 734: ! 735: // ! 736: // Set up error log info. ! 737: // ! 738: ! 739: errorCode = I8042_MOU_RESET_RESPONSE_FAILED; ! 740: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 425; ! 741: dumpData[0] = KBDMOU_INCORRECT_RESPONSE; ! 742: dumpData[1] = ControllerDeviceType; ! 743: dumpData[2] = MOUSE_ID_BYTE; ! 744: dumpData[3] = byte; ! 745: dumpCount = 4; ! 746: ! 747: goto I8xInitializeMouseExit; ! 748: } ! 749: ! 750: // ! 751: // Set mouse sampling rate. Send a Write To Auxiliary Device command ! 752: // to the 8042 controller. Then send the Set Mouse Sampling Rate ! 753: // command to the mouse through the 8042 data register, ! 754: // followed by its parameter. ! 755: // ! 756: ! 757: status = I8xPutBytePolled( ! 758: (CCHAR) DataPort, ! 759: WAIT_FOR_ACKNOWLEDGE, ! 760: (CCHAR) MouseDeviceType, ! 761: deviceExtension, ! 762: (UCHAR) SET_MOUSE_SAMPLING_RATE ! 763: ); ! 764: if (!NT_SUCCESS(status)) { ! 765: I8xPrint(( ! 766: 1, ! 767: "I8042PRT-I8xInitializeMouse: failed write set sample rate, status 0x%x\n", ! 768: status ! 769: )); ! 770: ! 771: // ! 772: // Set up error log info. ! 773: // ! 774: ! 775: errorCode = I8042_SET_SAMPLE_RATE_FAILED; ! 776: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 435; ! 777: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 778: dumpData[1] = DataPort; ! 779: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE; ! 780: dumpData[3] = SET_MOUSE_SAMPLING_RATE; ! 781: dumpCount = 4; ! 782: ! 783: goto I8xInitializeMouseExit; ! 784: } ! 785: ! 786: status = I8xPutBytePolled( ! 787: (CCHAR) DataPort, ! 788: WAIT_FOR_ACKNOWLEDGE, ! 789: (CCHAR) MouseDeviceType, ! 790: deviceExtension, ! 791: (UCHAR) MOUSE_SAMPLE_RATE ! 792: ); ! 793: if (!NT_SUCCESS(status)) { ! 794: I8xPrint(( ! 795: 1, ! 796: "I8042PRT-I8xInitializeMouse: failed write sample rate, status 0x%x\n", ! 797: status ! 798: )); ! 799: ! 800: // ! 801: // Set up error log info. ! 802: // ! 803: ! 804: errorCode = I8042_SET_SAMPLE_RATE_FAILED; ! 805: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 445; ! 806: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 807: dumpData[1] = DataPort; ! 808: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE; ! 809: dumpData[3] = MOUSE_SAMPLE_RATE; ! 810: dumpCount = 4; ! 811: ! 812: goto I8xInitializeMouseExit; ! 813: } ! 814: ! 815: // ! 816: // Set the mouse resolution. Send a Write To Auxiliary Device command ! 817: // to the 8042 controller. Then send the Set Mouse Resolution ! 818: // command to the mouse through the 8042 data register, ! 819: // followed by its parameter. ! 820: // ! 821: ! 822: status = I8xPutBytePolled( ! 823: (CCHAR) DataPort, ! 824: WAIT_FOR_ACKNOWLEDGE, ! 825: (CCHAR) MouseDeviceType, ! 826: deviceExtension, ! 827: (UCHAR) SET_MOUSE_RESOLUTION ! 828: ); ! 829: if (!NT_SUCCESS(status)) { ! 830: I8xPrint(( ! 831: 1, ! 832: "I8042PRT-I8xInitializeMouse: failed write set resolution, status 0x%x\n", ! 833: status ! 834: )); ! 835: ! 836: // ! 837: // Set up error log info. ! 838: // ! 839: ! 840: errorCode = I8042_SET_RESOLUTION_FAILED; ! 841: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 455; ! 842: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 843: dumpData[1] = DataPort; ! 844: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE; ! 845: dumpData[3] = SET_MOUSE_RESOLUTION; ! 846: dumpCount = 4; ! 847: ! 848: goto I8xInitializeMouseExit; ! 849: } ! 850: ! 851: status = I8xPutBytePolled( ! 852: (CCHAR) DataPort, ! 853: WAIT_FOR_ACKNOWLEDGE, ! 854: (CCHAR) MouseDeviceType, ! 855: deviceExtension, ! 856: (UCHAR) deviceExtension->Configuration.MouseResolution ! 857: ); ! 858: if (!NT_SUCCESS(status)) { ! 859: I8xPrint(( ! 860: 1, ! 861: "I8042PRT-I8xInitializeMouse: failed set mouse resolution, status 0x%x\n", ! 862: status ! 863: )); ! 864: ! 865: // ! 866: // Set up error log info. ! 867: // ! 868: ! 869: errorCode = I8042_SET_RESOLUTION_FAILED; ! 870: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 465; ! 871: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 872: dumpData[1] = DataPort; ! 873: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE; ! 874: dumpData[3] = deviceExtension->Configuration.MouseResolution; ! 875: dumpCount = 4; ! 876: ! 877: goto I8xInitializeMouseExit; ! 878: } ! 879: ! 880: I8xInitializeMouseExit: ! 881: ! 882: if (!NT_SUCCESS(status)) { ! 883: ! 884: // ! 885: // The mouse initialization failed. Log an error. ! 886: // ! 887: ! 888: if (errorCode != STATUS_SUCCESS) { ! 889: errorLogEntry = (PIO_ERROR_LOG_PACKET) ! 890: IoAllocateErrorLogEntry( ! 891: DeviceObject, ! 892: (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) ! 893: + (dumpCount * sizeof(ULONG))) ! 894: ); ! 895: ! 896: if (errorLogEntry != NULL) { ! 897: ! 898: errorLogEntry->ErrorCode = errorCode; ! 899: errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG); ! 900: errorLogEntry->SequenceNumber = 0; ! 901: errorLogEntry->MajorFunctionCode = 0; ! 902: errorLogEntry->IoControlCode = 0; ! 903: errorLogEntry->RetryCount = 0; ! 904: errorLogEntry->UniqueErrorValue = uniqueErrorValue; ! 905: errorLogEntry->FinalStatus = status; ! 906: for (i = 0; i < dumpCount; i++) ! 907: errorLogEntry->DumpData[i] = dumpData[i]; ! 908: ! 909: IoWriteErrorLogEntry(errorLogEntry); ! 910: } ! 911: } ! 912: } ! 913: ! 914: // ! 915: // Initialize current mouse input packet state. ! 916: // ! 917: ! 918: deviceExtension->MouseExtension.PreviousSignAndOverflow = 0; ! 919: deviceExtension->MouseExtension.InputState = MouseExpectingACK; ! 920: ! 921: I8xPrint((2, "I8042PRT-I8xInitializeMouse: exit\n")); ! 922: ! 923: return(status); ! 924: } ! 925: ! 926: VOID ! 927: I8xMouseConfiguration( ! 928: IN PDEVICE_EXTENSION DeviceExtension, ! 929: IN PUNICODE_STRING RegistryPath, ! 930: IN PUNICODE_STRING KeyboardDeviceName, ! 931: IN PUNICODE_STRING PointerDeviceName ! 932: ) ! 933: ! 934: /*++ ! 935: ! 936: Routine Description: ! 937: ! 938: This routine retrieves the configuration information for the mouse. ! 939: ! 940: Arguments: ! 941: ! 942: DeviceExtension - Pointer to the device extension. ! 943: ! 944: RegistryPath - Pointer to the null-terminated Unicode name of the ! 945: registry path for this driver. ! 946: ! 947: KeyboardDeviceName - Pointer to the Unicode string that will receive ! 948: the keyboard port device name. ! 949: ! 950: PointerDeviceName - Pointer to the Unicode string that will receive ! 951: the pointer port device name. ! 952: ! 953: ! 954: Return Value: ! 955: ! 956: None. As a side-effect, may set DeviceExtension->HardwarePresent. ! 957: ! 958: --*/ ! 959: { ! 960: NTSTATUS status = STATUS_SUCCESS; ! 961: INTERFACE_TYPE interfaceType; ! 962: CONFIGURATION_TYPE controllerType = PointerController; ! 963: CONFIGURATION_TYPE peripheralType = PointerPeripheral; ! 964: ULONG i; ! 965: ! 966: for (i = 0; i < MaximumInterfaceType; i++) { ! 967: ! 968: // ! 969: // Get the registry information for this device. ! 970: // ! 971: ! 972: interfaceType = i; ! 973: status = IoQueryDeviceDescription(&interfaceType, ! 974: NULL, ! 975: &controllerType, ! 976: NULL, ! 977: &peripheralType, ! 978: NULL, ! 979: I8xMousePeripheralCallout, ! 980: (PVOID) DeviceExtension); ! 981: ! 982: if (DeviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) { ! 983: ! 984: // ! 985: // If we didn't already get these when determining the keyboard ! 986: // configuration, get the service parameters now (e.g., ! 987: // user-configurable number of resends, polling iterations, etc.). ! 988: // ! 989: ! 990: if (!(DeviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)) ! 991: I8xServiceParameters( ! 992: DeviceExtension, ! 993: RegistryPath, ! 994: KeyboardDeviceName, ! 995: PointerDeviceName ! 996: ); ! 997: ! 998: // ! 999: // Initialize mouse-specific configuration parameters. ! 1000: // ! 1001: ! 1002: DeviceExtension->Configuration.MouseAttributes.MouseIdentifier = ! 1003: MOUSE_I8042_HARDWARE; ! 1004: ! 1005: break; ! 1006: ! 1007: } else { ! 1008: I8xPrint(( ! 1009: 1, ! 1010: "I8042PRT-I8xMouseConfiguration: IoQueryDeviceDescription for bus type %d failed\n", ! 1011: interfaceType ! 1012: )); ! 1013: } ! 1014: } ! 1015: } ! 1016: ! 1017: NTSTATUS ! 1018: I8xMouseEnableTransmission( ! 1019: IN PDEVICE_OBJECT DeviceObject ! 1020: ) ! 1021: ! 1022: /*++ ! 1023: ! 1024: Routine Description: ! 1025: ! 1026: This routine sends an Enable command to the mouse hardware, causing ! 1027: the mouse to begin transmissions. It is called at initialization ! 1028: time, but only after the interrupt has been connected. This is ! 1029: necessary so the driver can keep its notion of the mouse input data ! 1030: state in sync with the hardware (i.e., for this type of mouse there is no ! 1031: way to differentiate the first byte of a packet; if the user is randomly ! 1032: moving the mouse during boot/initialization, the first mouse interrupt we ! 1033: receive following IoConnectInterrupt could be for a byte that is not the ! 1034: start of a packet, and we have no way to know that). ! 1035: ! 1036: Arguments: ! 1037: ! 1038: DeviceObject - Pointer to the device object. ! 1039: ! 1040: Return Value: ! 1041: ! 1042: Returns status. ! 1043: ! 1044: --*/ ! 1045: ! 1046: { ! 1047: NTSTATUS status; ! 1048: PDEVICE_EXTENSION deviceExtension; ! 1049: PIO_ERROR_LOG_PACKET errorLogEntry; ! 1050: ULONG uniqueErrorValue; ! 1051: NTSTATUS errorCode = STATUS_SUCCESS; ! 1052: ULONG i; ! 1053: ULONG dumpCount = 0; ! 1054: ! 1055: #define DUMP_COUNT 4 ! 1056: ULONG dumpData[DUMP_COUNT]; ! 1057: ! 1058: I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: enter\n")); ! 1059: ! 1060: for (i = 0; i < DUMP_COUNT; i++) ! 1061: dumpData[i] = 0; ! 1062: ! 1063: // ! 1064: // Get the device extension. ! 1065: // ! 1066: ! 1067: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; ! 1068: ! 1069: // ! 1070: // Re-enable the mouse at the mouse hardware, so that it can transmit ! 1071: // data packets in continuous mode. Note that this is not the same ! 1072: // as enabling the mouse device at the 8042 controller. The mouse ! 1073: // hardware is sent an Enable command here, because it was ! 1074: // Disabled as a result of the mouse reset command performed ! 1075: // in I8xInitializeMouse(). ! 1076: // ! 1077: // Note that we don't wait for an ACKNOWLEDGE back. The ! 1078: // ACKNOWLEDGE back will actually cause a mouse interrupt, which ! 1079: // then gets handled in the mouse ISR. ! 1080: // ! 1081: ! 1082: status = I8xPutBytePolled( ! 1083: (CCHAR) DataPort, ! 1084: NO_WAIT_FOR_ACKNOWLEDGE, ! 1085: (CCHAR) MouseDeviceType, ! 1086: deviceExtension, ! 1087: (UCHAR) ENABLE_MOUSE_TRANSMISSION ! 1088: ); ! 1089: if (!NT_SUCCESS(status)) { ! 1090: I8xPrint(( ! 1091: 1, ! 1092: "I8042PRT-I8xMouseEnableTransmission: failed write enable transmission, status 0x%x\n", ! 1093: status ! 1094: )); ! 1095: ! 1096: // ! 1097: // Set up error log info. ! 1098: // ! 1099: ! 1100: errorCode = I8042_MOU_ENABLE_XMIT; ! 1101: uniqueErrorValue = I8042_ERROR_VALUE_BASE + 475; ! 1102: dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM; ! 1103: dumpData[1] = DataPort; ! 1104: dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE; ! 1105: dumpData[3] = ENABLE_MOUSE_TRANSMISSION; ! 1106: dumpCount = 4; ! 1107: ! 1108: } ! 1109: ! 1110: I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: exit\n")); ! 1111: ! 1112: return(status); ! 1113: } ! 1114: ! 1115: NTSTATUS ! 1116: I8xMousePeripheralCallout( ! 1117: IN PVOID Context, ! 1118: IN PUNICODE_STRING PathName, ! 1119: IN INTERFACE_TYPE BusType, ! 1120: IN ULONG BusNumber, ! 1121: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 1122: IN CONFIGURATION_TYPE ControllerType, ! 1123: IN ULONG ControllerNumber, ! 1124: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 1125: IN CONFIGURATION_TYPE PeripheralType, ! 1126: IN ULONG PeripheralNumber, ! 1127: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 1128: ) ! 1129: ! 1130: /*++ ! 1131: ! 1132: Routine Description: ! 1133: ! 1134: This is the callout routine sent as a parameter to ! 1135: IoQueryDeviceDescription. It grabs the pointer controller and ! 1136: peripheral configuration information. ! 1137: ! 1138: Arguments: ! 1139: ! 1140: Context - Context parameter that was passed in by the routine ! 1141: that called IoQueryDeviceDescription. ! 1142: ! 1143: PathName - The full pathname for the registry key. ! 1144: ! 1145: BusType - Bus interface type (Isa, Eisa, Mca, etc.). ! 1146: ! 1147: BusNumber - The bus sub-key (0, 1, etc.). ! 1148: ! 1149: BusInformation - Pointer to the array of pointers to the full value ! 1150: information for the bus. ! 1151: ! 1152: ControllerType - The controller type (should be PointerController). ! 1153: ! 1154: ControllerNumber - The controller sub-key (0, 1, etc.). ! 1155: ! 1156: ControllerInformation - Pointer to the array of pointers to the full ! 1157: value information for the controller key. ! 1158: ! 1159: PeripheralType - The peripheral type (should be PointerPeripheral). ! 1160: ! 1161: PeripheralNumber - The peripheral sub-key. ! 1162: ! 1163: PeripheralInformation - Pointer to the array of pointers to the full ! 1164: value information for the peripheral key. ! 1165: ! 1166: ! 1167: Return Value: ! 1168: ! 1169: None. If successful, will have the following side-effects: ! 1170: ! 1171: - Sets DeviceObject->DeviceExtension->HardwarePresent. ! 1172: - Sets configuration fields in ! 1173: DeviceObject->DeviceExtension->Configuration. ! 1174: ! 1175: --*/ ! 1176: { ! 1177: PDEVICE_EXTENSION deviceExtension; ! 1178: PI8042_CONFIGURATION_INFORMATION configuration; ! 1179: UNICODE_STRING unicodeIdentifier; ! 1180: ANSI_STRING ansiString; ! 1181: PUCHAR controllerData; ! 1182: NTSTATUS status = STATUS_SUCCESS; ! 1183: ULONG i; ! 1184: ULONG listCount; ! 1185: PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor; ! 1186: CM_PARTIAL_RESOURCE_DESCRIPTOR tmpResourceDescriptor; ! 1187: BOOLEAN portInfoNeeded; ! 1188: BOOLEAN defaultInterruptShare; ! 1189: KINTERRUPT_MODE defaultInterruptMode; ! 1190: ! 1191: I8xPrint(( ! 1192: 1, ! 1193: "I8042PRT-I8xMousePeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n", ! 1194: PathName, BusType, BusNumber ! 1195: )); ! 1196: I8xPrint(( ! 1197: 1, ! 1198: " Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n", ! 1199: ControllerType, ControllerNumber, ControllerInformation ! 1200: )); ! 1201: I8xPrint(( ! 1202: 1, ! 1203: " Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n", ! 1204: PeripheralType, PeripheralNumber, PeripheralInformation ! 1205: )); ! 1206: ! 1207: // ! 1208: // Get the length of the peripheral identifier information. ! 1209: // ! 1210: ! 1211: unicodeIdentifier.Length = ! 1212: (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength; ! 1213: ! 1214: // ! 1215: // If we already have the configuration information for the ! 1216: // pointer peripheral, or if the peripheral identifier is missing, ! 1217: // just return. ! 1218: // ! 1219: ! 1220: deviceExtension = (PDEVICE_EXTENSION) Context; ! 1221: if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) ! 1222: || (unicodeIdentifier.Length == 0)) { ! 1223: return (status); ! 1224: } ! 1225: ! 1226: configuration = &deviceExtension->Configuration; ! 1227: ! 1228: // ! 1229: // Get the identifier information for the peripheral. ! 1230: // ! 1231: ! 1232: unicodeIdentifier.MaximumLength = unicodeIdentifier.Length; ! 1233: unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation + ! 1234: IoQueryDeviceIdentifier))) + ! 1235: (*(PeripheralInformation + ! 1236: IoQueryDeviceIdentifier))->DataOffset); ! 1237: I8xPrint(( ! 1238: 1, ! 1239: "I8042PRT-I8xMousePeripheralCallout: Mouse type %ws\n", ! 1240: unicodeIdentifier.Buffer)); ! 1241: ! 1242: // ! 1243: // Verify that this is an i8042 mouse. ! 1244: // ! 1245: ! 1246: status = RtlUnicodeStringToAnsiString( ! 1247: &ansiString, ! 1248: &unicodeIdentifier, ! 1249: TRUE ! 1250: ); ! 1251: ! 1252: if (!NT_SUCCESS(status)) { ! 1253: I8xPrint(( ! 1254: 1, ! 1255: "I8042PRT-I8xMousePeripheralCallout: Could not convert identifier to Ansi\n" ! 1256: )); ! 1257: return(status); ! 1258: } ! 1259: ! 1260: if (strstr(ansiString.Buffer, "PS2")) { ! 1261: ! 1262: // ! 1263: // There is a mouse on the i8042 controller. ! 1264: // ! 1265: ! 1266: deviceExtension->HardwarePresent |= MOUSE_HARDWARE_PRESENT; ! 1267: } ! 1268: ! 1269: RtlFreeAnsiString(&ansiString); ! 1270: ! 1271: if (!(deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT)) { ! 1272: return(status); ! 1273: } ! 1274: ! 1275: if (!(deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)) { ! 1276: ! 1277: // ! 1278: // If we don't already have the bus information as the result ! 1279: // of the keyboard configuration, grab it now. ! 1280: // ! 1281: ! 1282: configuration->InterfaceType = BusType; ! 1283: configuration->BusNumber = BusNumber; ! 1284: configuration->FloatingSave = I8042_FLOATING_SAVE; ! 1285: } ! 1286: ! 1287: if (configuration->InterfaceType == MicroChannel) { ! 1288: defaultInterruptShare = TRUE; ! 1289: defaultInterruptMode = LevelSensitive; ! 1290: } else { ! 1291: defaultInterruptShare = I8042_INTERRUPT_SHARE; ! 1292: defaultInterruptMode = I8042_INTERRUPT_MODE; ! 1293: } ! 1294: ! 1295: // ! 1296: // Look through the controller's resource list for interrupt ! 1297: // and (possibly) port configuration information. ! 1298: // ! 1299: ! 1300: if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){ ! 1301: controllerData = ((PUCHAR) (*(ControllerInformation + ! 1302: IoQueryDeviceConfigurationData))) + ! 1303: (*(ControllerInformation + ! 1304: IoQueryDeviceConfigurationData))->DataOffset; ! 1305: ! 1306: controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, ! 1307: PartialResourceList); ! 1308: ! 1309: listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count; ! 1310: ! 1311: resourceDescriptor = ! 1312: ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors; ! 1313: ! 1314: portInfoNeeded = configuration->PortListCount? FALSE:TRUE; ! 1315: ! 1316: for (i = 0; i < listCount; i++, resourceDescriptor++) { ! 1317: switch(resourceDescriptor->Type) { ! 1318: case CmResourceTypePort: ! 1319: ! 1320: if (portInfoNeeded) { ! 1321: ! 1322: // ! 1323: // If we don't already have the port information as ! 1324: // a result of the keyboard configuration, copy it ! 1325: // to the port list. ! 1326: // ! 1327: ! 1328: configuration->PortList[configuration->PortListCount] = ! 1329: *resourceDescriptor; ! 1330: configuration->PortList[configuration->PortListCount].ShareDisposition = ! 1331: I8042_REGISTER_SHARE? CmResourceShareShared: ! 1332: CmResourceShareDriverExclusive; ! 1333: configuration->PortListCount += 1; ! 1334: ! 1335: } ! 1336: ! 1337: break; ! 1338: ! 1339: case CmResourceTypeInterrupt: ! 1340: ! 1341: // ! 1342: // Copy the interrupt information. ! 1343: // ! 1344: ! 1345: configuration->MouseInterrupt = *resourceDescriptor; ! 1346: configuration->MouseInterrupt.ShareDisposition = ! 1347: defaultInterruptShare? CmResourceShareShared : ! 1348: CmResourceShareDeviceExclusive; ! 1349: ! 1350: break; ! 1351: ! 1352: default: ! 1353: break; ! 1354: } ! 1355: } ! 1356: } ! 1357: ! 1358: // ! 1359: // If no interrupt configuration information was found, use the ! 1360: // mouse driver defaults. ! 1361: // ! 1362: ! 1363: if (!(configuration->MouseInterrupt.Type & CmResourceTypeInterrupt)) { ! 1364: ! 1365: I8xPrint(( ! 1366: 1, ! 1367: "I8042PRT-I8xMousePeripheralCallout: Using default mouse interrupt config\n" ! 1368: )); ! 1369: ! 1370: configuration->MouseInterrupt.Type = CmResourceTypeInterrupt; ! 1371: configuration->MouseInterrupt.ShareDisposition = ! 1372: defaultInterruptShare? CmResourceShareShared : ! 1373: CmResourceShareDeviceExclusive; ! 1374: configuration->MouseInterrupt.Flags = ! 1375: (defaultInterruptMode == Latched)? CM_RESOURCE_INTERRUPT_LATCHED : ! 1376: CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 1377: configuration->MouseInterrupt.u.Interrupt.Level = MOUSE_IRQL; ! 1378: configuration->MouseInterrupt.u.Interrupt.Vector = MOUSE_VECTOR; ! 1379: } ! 1380: ! 1381: I8xPrint(( ! 1382: 1, ! 1383: "I8042PRT-I8xMousePeripheralCallout: Mouse interrupt config --\n" ! 1384: )); ! 1385: I8xPrint(( ! 1386: 1, ! 1387: "%s, %s, Irq = %d\n", ! 1388: configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared? ! 1389: "Sharable" : "NonSharable", ! 1390: configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED? ! 1391: "Latched" : "Level Sensitive", ! 1392: configuration->MouseInterrupt.u.Interrupt.Vector ! 1393: )); ! 1394: ! 1395: // ! 1396: // If no port configuration information was found, use the ! 1397: // mouse driver defaults. ! 1398: // ! 1399: ! 1400: if (configuration->PortListCount == 0) { ! 1401: ! 1402: // ! 1403: // No port configuration information was found, so use ! 1404: // the driver defaults. ! 1405: // ! 1406: ! 1407: I8xPrint(( ! 1408: 1, ! 1409: "I8042PRT-I8xMousePeripheralCallout: Using default port config\n" ! 1410: )); ! 1411: ! 1412: configuration->PortList[DataPort].Type = CmResourceTypePort; ! 1413: configuration->PortList[DataPort].Flags = I8042_PORT_TYPE; ! 1414: configuration->PortList[DataPort].ShareDisposition = ! 1415: I8042_REGISTER_SHARE? CmResourceShareShared: ! 1416: CmResourceShareDriverExclusive; ! 1417: configuration->PortList[DataPort].u.Port.Start.LowPart = ! 1418: I8042_PHYSICAL_BASE + I8042_DATA_REGISTER_OFFSET; ! 1419: configuration->PortList[DataPort].u.Port.Start.HighPart = 0; ! 1420: configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH; ! 1421: ! 1422: configuration->PortList[CommandPort].Type = CmResourceTypePort; ! 1423: configuration->PortList[CommandPort].Flags = I8042_PORT_TYPE; ! 1424: configuration->PortList[CommandPort].ShareDisposition = ! 1425: I8042_REGISTER_SHARE? CmResourceShareShared: ! 1426: CmResourceShareDriverExclusive; ! 1427: configuration->PortList[CommandPort].u.Port.Start.LowPart = ! 1428: I8042_PHYSICAL_BASE + I8042_COMMAND_REGISTER_OFFSET; ! 1429: configuration->PortList[CommandPort].u.Port.Start.HighPart = 0; ! 1430: configuration->PortList[CommandPort].u.Port.Length = I8042_REGISTER_LENGTH; ! 1431: ! 1432: configuration->PortListCount = 2; ! 1433: } else if (configuration->PortListCount == 1) { ! 1434: ! 1435: // ! 1436: // Kludge for Jazz machines. Their ARC firmware neglects to ! 1437: // separate out the port addresses, so fix that up here. ! 1438: // ! 1439: ! 1440: configuration->PortList[CommandPort] = configuration->PortList[DataPort]; ! 1441: configuration->PortList[CommandPort].u.Port.Start.LowPart += ! 1442: I8042_COMMAND_REGISTER_OFFSET; ! 1443: configuration->PortListCount += 1; ! 1444: } else { ! 1445: ! 1446: // ! 1447: // Put the lowest port address range in the DataPort element of ! 1448: // the port list. ! 1449: // ! 1450: ! 1451: if (configuration->PortList[CommandPort].u.Port.Start.LowPart ! 1452: < configuration->PortList[DataPort].u.Port.Start.LowPart) { ! 1453: tmpResourceDescriptor = configuration->PortList[DataPort]; ! 1454: configuration->PortList[DataPort] = ! 1455: configuration->PortList[CommandPort]; ! 1456: configuration->PortList[CommandPort] = tmpResourceDescriptor; ! 1457: } ! 1458: } ! 1459: ! 1460: for (i = 0; i < configuration->PortListCount; i++) { ! 1461: ! 1462: I8xPrint(( ! 1463: 1, ! 1464: " %s, Ports 0x%x - 0x%x\n", ! 1465: configuration->PortList[i].ShareDisposition ! 1466: == CmResourceShareShared? "Sharable" : "NonSharable", ! 1467: configuration->PortList[i].u.Port.Start.LowPart, ! 1468: configuration->PortList[i].u.Port.Start.LowPart + ! 1469: configuration->PortList[i].u.Port.Length - 1 ! 1470: )); ! 1471: } ! 1472: ! 1473: return(status); ! 1474: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.