|
|
1.1 ! root 1: ! 2: /*++ ! 3: ! 4: Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation ! 5: ! 6: Module Name: ! 7: ! 8: i8042cmn.c ! 9: ! 10: Abstract: ! 11: ! 12: The common portions of the Intel i8042 port driver which ! 13: apply to both the keyboard and the auxiliary (PS/2 mouse) device. ! 14: ! 15: Environment: ! 16: ! 17: Kernel mode only. ! 18: ! 19: Notes: ! 20: ! 21: NOTES: (Future/outstanding issues) ! 22: ! 23: - Powerfail not implemented. ! 24: ! 25: - IOCTL_INTERNAL_KEYBOARD_DISCONNECT and IOCTL_INTERNAL_MOUSE_DISCONNECT ! 26: have not been implemented. They're not needed until the class ! 27: unload routine is implemented. Right now, we don't want to allow ! 28: either the keyboard or the mouse class driver to unload. ! 29: ! 30: - Consolidate duplicate code, where possible and appropriate. ! 31: ! 32: Revision History: ! 33: ! 34: --*/ ! 35: ! 36: #include "stdarg.h" ! 37: #include "stdio.h" ! 38: #include "string.h" ! 39: #include "ntddk.h" ! 40: #include "i8042prt.h" ! 41: #include "i8042log.h" ! 42: ! 43: // ! 44: // Declare the global debug flag for this driver. ! 45: // ! 46: ! 47: #if DBG ! 48: ULONG i8042Debug = 0; ! 49: #endif ! 50: ! 51: ! 52: VOID ! 53: I8042CompletionDpc( ! 54: IN PKDPC Dpc, ! 55: IN PDEVICE_OBJECT DeviceObject, ! 56: IN PIRP Irp, ! 57: IN PVOID Context ! 58: ! 59: /*++ ! 60: ! 61: Routine Description: ! 62: ! 63: This routine runs at DISPATCH_LEVEL IRQL to complete requests. ! 64: It is queued by the ISR routine. ! 65: ! 66: Note: Currently, only the keyboard ISR queues this routine. ! 67: Only the keyboard ISR handles both input and output to ! 68: the device. The mouse is input-only once it is initialized. ! 69: ! 70: Arguments: ! 71: ! 72: Dpc - Pointer to the DPC object. ! 73: ! 74: DeviceObject - Pointer to the device object. ! 75: ! 76: Irp - Not used. ! 77: ! 78: Context - Indicates type of error to log. ! 79: ! 80: Return Value: ! 81: ! 82: None. ! 83: ! 84: --*/ ! 85: ! 86: ) ! 87: { ! 88: PDEVICE_EXTENSION deviceExtension; ! 89: PIO_STACK_LOCATION irpSp; ! 90: ! 91: UNREFERENCED_PARAMETER(Dpc); ! 92: UNREFERENCED_PARAMETER(Context); ! 93: ! 94: I8xPrint((2, "I8042PRT-I8042CompletionDpc: enter\n")); ! 95: ! 96: // ! 97: // Get the device extension and current IRP. ! 98: // ! 99: ! 100: deviceExtension = DeviceObject->DeviceExtension; ! 101: ! 102: // ! 103: // Stop the command timer. ! 104: // ! 105: ! 106: KeCancelTimer(&deviceExtension->CommandTimer); ! 107: ! 108: // ! 109: // Get the current IRP. ! 110: // ! 111: ! 112: Irp = DeviceObject->CurrentIrp; ! 113: ASSERT(Irp != NULL); ! 114: ! 115: // ! 116: // Get a pointer to the current parameters for this request. The ! 117: // information is contained in the current stack location. ! 118: // ! 119: ! 120: irpSp = IoGetCurrentIrpStackLocation(Irp); ! 121: ! 122: // ! 123: // We know we're completing an internal device control request. Switch ! 124: // on IoControlCode. ! 125: // ! 126: ! 127: switch(irpSp->Parameters.DeviceIoControl.IoControlCode) { ! 128: ! 129: // ! 130: // Complete the keyboard set indicators request. ! 131: // ! 132: ! 133: case IOCTL_KEYBOARD_SET_INDICATORS: ! 134: ! 135: I8xPrint(( ! 136: 2, ! 137: "I8042PRT-I8042CompletionDpc: keyboard set indicators updated\n" ! 138: )); ! 139: ! 140: // ! 141: // Update the current indicators flag in the device extension. ! 142: // ! 143: ! 144: deviceExtension->Configuration.KeyboardIndicators = ! 145: *(PKEYBOARD_INDICATOR_PARAMETERS) ! 146: Irp->AssociatedIrp.SystemBuffer; ! 147: ! 148: I8xPrint(( ! 149: 2, ! 150: "I8042PRT-I8042CompletionDpc: new LED flags 0x%x\n", ! 151: deviceExtension->Configuration.KeyboardIndicators.LedFlags ! 152: )); ! 153: ! 154: break; ! 155: ! 156: // ! 157: // Complete the keyboard set typematic request. ! 158: // ! 159: ! 160: case IOCTL_KEYBOARD_SET_TYPEMATIC: ! 161: ! 162: I8xPrint(( ! 163: 2, ! 164: "I8042PRT-I8042CompletionDpc: keyboard set typematic updated\n" ! 165: )); ! 166: ! 167: // ! 168: // Update the current typematic rate/delay in the device extension. ! 169: // ! 170: ! 171: deviceExtension->Configuration.KeyRepeatCurrent = ! 172: *(PKEYBOARD_TYPEMATIC_PARAMETERS) ! 173: Irp->AssociatedIrp.SystemBuffer; ! 174: ! 175: I8xPrint(( ! 176: 2, ! 177: "I8042PRT-I8042CompletionDpc: new rate/delay 0x%x/%x\n", ! 178: deviceExtension->Configuration.KeyRepeatCurrent.Rate, ! 179: deviceExtension->Configuration.KeyRepeatCurrent.Delay ! 180: )); ! 181: ! 182: break; ! 183: ! 184: default: ! 185: ! 186: I8xPrint((2, "I8042PRT-I8042CompletionDpc: miscellaneous\n")); ! 187: ! 188: break; ! 189: ! 190: } ! 191: ! 192: // ! 193: // Set the completion status, start the next packet, and complete the ! 194: // request. ! 195: // ! 196: ! 197: Irp->IoStatus.Status = STATUS_SUCCESS; ! 198: IoStartNextPacket(DeviceObject, FALSE); ! 199: IoCompleteRequest (Irp, IO_KEYBOARD_INCREMENT); ! 200: ! 201: I8xPrint((2, "I8042PRT-I8042CompletionDpc: exit\n")); ! 202: } ! 203: ! 204: VOID ! 205: I8042ErrorLogDpc( ! 206: IN PKDPC Dpc, ! 207: IN PDEVICE_OBJECT DeviceObject, ! 208: IN PIRP Irp, ! 209: IN PVOID Context ! 210: ) ! 211: ! 212: /*++ ! 213: ! 214: Routine Description: ! 215: ! 216: This routine runs at DISPATCH_LEVEL IRQL to log errors that are ! 217: discovered at IRQL > DISPATCH_LEVEL (e.g., in the ISR routine or ! 218: in a routine that is executed via KeSynchronizeExecution). There ! 219: is not necessarily a current request associated with this condition. ! 220: ! 221: Arguments: ! 222: ! 223: Dpc - Pointer to the DPC object. ! 224: ! 225: DeviceObject - Pointer to the device object. ! 226: ! 227: Irp - Not used. ! 228: ! 229: Context - Indicates type of error to log. ! 230: ! 231: Return Value: ! 232: ! 233: None. ! 234: ! 235: --*/ ! 236: ! 237: { ! 238: PDEVICE_EXTENSION deviceExtension; ! 239: PIO_ERROR_LOG_PACKET errorLogEntry; ! 240: ! 241: UNREFERENCED_PARAMETER(Dpc); ! 242: UNREFERENCED_PARAMETER(Irp); ! 243: ! 244: I8xPrint((2, "I8042PRT-I8042ErrorLogDpc: enter\n")); ! 245: ! 246: deviceExtension = DeviceObject->DeviceExtension; ! 247: ! 248: // ! 249: // Log an error packet. ! 250: // ! 251: ! 252: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( ! 253: DeviceObject, ! 254: sizeof(IO_ERROR_LOG_PACKET) ! 255: + (2 * sizeof(ULONG)) ! 256: ); ! 257: if (errorLogEntry != NULL) { ! 258: ! 259: errorLogEntry->DumpDataSize = 2 * sizeof(ULONG); ! 260: if ((ULONG) Context == I8042_KBD_BUFFER_OVERFLOW) { ! 261: errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 310; ! 262: errorLogEntry->DumpData[0] = sizeof(KEYBOARD_INPUT_DATA); ! 263: errorLogEntry->DumpData[1] = ! 264: deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength; ! 265: } else if ((ULONG) Context == I8042_MOU_BUFFER_OVERFLOW) { ! 266: errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 320; ! 267: errorLogEntry->DumpData[0] = sizeof(MOUSE_INPUT_DATA); ! 268: errorLogEntry->DumpData[1] = ! 269: deviceExtension->Configuration.MouseAttributes.InputDataQueueLength; ! 270: } else { ! 271: errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 330; ! 272: errorLogEntry->DumpData[0] = 0; ! 273: errorLogEntry->DumpData[1] = 0; ! 274: } ! 275: ! 276: errorLogEntry->ErrorCode = (ULONG) Context; ! 277: errorLogEntry->SequenceNumber = 0; ! 278: errorLogEntry->MajorFunctionCode = 0; ! 279: errorLogEntry->IoControlCode = 0; ! 280: errorLogEntry->RetryCount = 0; ! 281: errorLogEntry->FinalStatus = 0; ! 282: ! 283: IoWriteErrorLogEntry(errorLogEntry); ! 284: } ! 285: ! 286: I8xPrint((2, "I8042PRT-I8042ErrorLogDpc: exit\n")); ! 287: ! 288: } ! 289: ! 290: NTSTATUS ! 291: I8042Flush( ! 292: IN PDEVICE_OBJECT DeviceObject, ! 293: IN PIRP Irp ! 294: ) ! 295: { ! 296: UNREFERENCED_PARAMETER(DeviceObject); ! 297: UNREFERENCED_PARAMETER(Irp); ! 298: ! 299: I8xPrint((2,"I8042PRT-I8042Flush: enter\n")); ! 300: I8xPrint((2,"I8042PRT-I8042Flush: exit\n")); ! 301: ! 302: return(STATUS_NOT_IMPLEMENTED); ! 303: } ! 304: ! 305: NTSTATUS ! 306: I8042InternalDeviceControl( ! 307: IN PDEVICE_OBJECT DeviceObject, ! 308: IN PIRP Irp ! 309: ) ! 310: ! 311: /*++ ! 312: ! 313: Routine Description: ! 314: ! 315: This routine is the dispatch routine for internal device control requests. ! 316: ! 317: Arguments: ! 318: ! 319: DeviceObject - Pointer to the device object. ! 320: ! 321: Irp - Pointer to the request packet. ! 322: ! 323: Return Value: ! 324: ! 325: Status is returned. ! 326: ! 327: --*/ ! 328: ! 329: { ! 330: ! 331: PIO_STACK_LOCATION irpSp; ! 332: PDEVICE_EXTENSION deviceExtension; ! 333: NTSTATUS status; ! 334: I8042_INITIALIZE_DATA_CONTEXT initializeDataContext; ! 335: PVOID parameters; ! 336: PKEYBOARD_ATTRIBUTES keyboardAttributes; ! 337: ULONG sizeOfTranslation; ! 338: ! 339: I8xPrint((2,"I8042PRT-I8042InternalDeviceControl: enter\n")); ! 340: ! 341: // ! 342: // Get a pointer to the device extension. ! 343: // ! 344: ! 345: deviceExtension = DeviceObject->DeviceExtension; ! 346: ! 347: // ! 348: // Initialize the returned Information field. ! 349: // ! 350: ! 351: Irp->IoStatus.Information = 0; ! 352: ! 353: // ! 354: // Get a pointer to the current parameters for this request. The ! 355: // information is contained in the current stack location. ! 356: // ! 357: ! 358: irpSp = IoGetCurrentIrpStackLocation(Irp); ! 359: ! 360: // ! 361: // Case on the device control subfunction that is being performed by the ! 362: // requestor. ! 363: // ! 364: ! 365: switch (irpSp->Parameters.DeviceIoControl.IoControlCode) { ! 366: ! 367: // ! 368: // Connect a keyboard class device driver to the port driver. ! 369: // ! 370: ! 371: case IOCTL_INTERNAL_KEYBOARD_CONNECT: ! 372: ! 373: I8xPrint(( ! 374: 2, ! 375: "I8042PRT-I8042InternalDeviceControl: keyboard connect\n" ! 376: )); ! 377: ! 378: // ! 379: // Only allow a connection if the keyboard hardware is present. ! 380: // Also, only allow one connection. ! 381: // ! 382: // FUTURE: Consider allowing multiple connections, just for ! 383: // the sake of generality? It really makes no sense for the ! 384: // i8042, though. ! 385: // ! 386: ! 387: if ((deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) ! 388: != KEYBOARD_HARDWARE_PRESENT) { ! 389: ! 390: I8xPrint(( ! 391: 2, ! 392: "I8042PRT-I8042InternalDeviceControl: error - hardware not present\n" ! 393: )); ! 394: ! 395: status = STATUS_NO_SUCH_DEVICE; ! 396: break; ! 397: } else ! 398: if (deviceExtension->KeyboardExtension.ConnectData.ClassService ! 399: != NULL) { ! 400: ! 401: I8xPrint(( ! 402: 2, ! 403: "I8042PRT-I8042InternalDeviceControl: error - already connected\n" ! 404: )); ! 405: ! 406: status = STATUS_SHARING_VIOLATION; ! 407: break; ! 408: ! 409: } else ! 410: if (irpSp->Parameters.DeviceIoControl.InputBufferLength < ! 411: sizeof(CONNECT_DATA)) { ! 412: ! 413: I8xPrint(( ! 414: 2, ! 415: "I8042PRT-I8042InternalDeviceControl: error - invalid buffer length\n" ! 416: )); ! 417: ! 418: status = STATUS_INVALID_PARAMETER; ! 419: break; ! 420: } ! 421: ! 422: // ! 423: // Copy the connection parameters to the device extension. ! 424: // ! 425: ! 426: deviceExtension->KeyboardExtension.ConnectData = ! 427: *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer)); ! 428: ! 429: // ! 430: // Reinitialize the port input data queue. ! 431: // ! 432: ! 433: initializeDataContext.DeviceExtension = deviceExtension; ! 434: initializeDataContext.DeviceType = KeyboardDeviceType; ! 435: ! 436: KeSynchronizeExecution( ! 437: deviceExtension->KeyboardInterruptObject, ! 438: (PKSYNCHRONIZE_ROUTINE) I8xInitializeDataQueue, ! 439: (PVOID) &initializeDataContext ! 440: ); ! 441: ! 442: // ! 443: // Set the completion status. ! 444: // ! 445: ! 446: status = STATUS_SUCCESS; ! 447: break; ! 448: ! 449: // ! 450: // Disconnect a keyboard class device driver from the port driver. ! 451: // ! 452: // NOTE: Not implemented. ! 453: // ! 454: ! 455: case IOCTL_INTERNAL_KEYBOARD_DISCONNECT: ! 456: ! 457: I8xPrint(( ! 458: 2, ! 459: "I8042PRT-I8042InternalDeviceControl: keyboard disconnect\n" ! 460: )); ! 461: ! 462: // ! 463: // Perform a keyboard interrupt disable call. ! 464: // ! 465: ! 466: // ! 467: // Clear the connection parameters in the device extension. ! 468: // NOTE: Must synchronize this with the keyboard ISR. ! 469: // ! 470: // ! 471: //deviceExtension->KeyboardExtension.ConnectData.ClassDeviceObject = ! 472: // Null; ! 473: //deviceExtension->KeyboardExtension.ConnectData.ClassService = ! 474: // Null; ! 475: ! 476: // ! 477: // Set the completion status. ! 478: // ! 479: ! 480: status = STATUS_NOT_IMPLEMENTED; ! 481: break; ! 482: ! 483: // ! 484: // Connect a mouse class device driver to the port driver. ! 485: // ! 486: ! 487: case IOCTL_INTERNAL_MOUSE_CONNECT: ! 488: ! 489: I8xPrint(( ! 490: 2, ! 491: "I8042PRT-I8042InternalDeviceControl: mouse connect\n" ! 492: )); ! 493: ! 494: ! 495: // ! 496: // Only allow a connection if the mouse hardware is present. ! 497: // Also, only allow one connection. ! 498: // ! 499: // FUTURE: Consider allowing multiple connections, just for ! 500: // the sake of generality? It really makes no sense for the ! 501: // i8042, though. ! 502: // ! 503: ! 504: if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) ! 505: != MOUSE_HARDWARE_PRESENT) { ! 506: ! 507: I8xPrint(( ! 508: 2, ! 509: "I8042PRT-I8042InternalDeviceControl: error - hardware not present\n" ! 510: )); ! 511: ! 512: status = STATUS_NO_SUCH_DEVICE; ! 513: break; ! 514: } else ! 515: if (deviceExtension->MouseExtension.ConnectData.ClassService ! 516: != NULL) { ! 517: ! 518: I8xPrint(( ! 519: 2, ! 520: "I8042PRT-I8042InternalDeviceControl: error - already connected\n" ! 521: )); ! 522: ! 523: status = STATUS_SHARING_VIOLATION; ! 524: break; ! 525: ! 526: } else ! 527: if (irpSp->Parameters.DeviceIoControl.InputBufferLength < ! 528: sizeof(CONNECT_DATA)) { ! 529: ! 530: I8xPrint(( ! 531: 2, ! 532: "I8042PRT-I8042InternalDeviceControl: error - invalid buffer length\n" ! 533: )); ! 534: ! 535: status = STATUS_INVALID_PARAMETER; ! 536: break; ! 537: } ! 538: ! 539: // ! 540: // Copy the connection parameters to the device extension. ! 541: // ! 542: ! 543: deviceExtension->MouseExtension.ConnectData = ! 544: *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer)); ! 545: ! 546: // ! 547: // Reinitialize the port input data queue. ! 548: // ! 549: ! 550: initializeDataContext.DeviceExtension = deviceExtension; ! 551: initializeDataContext.DeviceType = MouseDeviceType; ! 552: ! 553: KeSynchronizeExecution( ! 554: deviceExtension->MouseInterruptObject, ! 555: (PKSYNCHRONIZE_ROUTINE) I8xInitializeDataQueue, ! 556: (PVOID) &initializeDataContext ! 557: ); ! 558: ! 559: // ! 560: // Set the completion status. ! 561: // ! 562: ! 563: status = STATUS_SUCCESS; ! 564: break; ! 565: ! 566: // ! 567: // Disconnect a mouse class device driver from the port driver. ! 568: // ! 569: // NOTE: Not implemented. ! 570: // ! 571: ! 572: case IOCTL_INTERNAL_MOUSE_DISCONNECT: ! 573: ! 574: I8xPrint(( ! 575: 2, ! 576: "I8042PRT-I8042InternalDeviceControl: mouse disconnect\n" ! 577: )); ! 578: ! 579: // ! 580: // Perform a mouse interrupt disable call. ! 581: // ! 582: ! 583: // ! 584: // Clear the connection parameters in the device extension. ! 585: // NOTE: Must synchronize this with the mouse ISR. ! 586: // ! 587: // ! 588: //deviceExtension->MouseExtension.ConnectData.ClassDeviceObject = ! 589: // Null; ! 590: //deviceExtension->MouseExtension.ConnectData.ClassService = ! 591: // Null; ! 592: ! 593: // ! 594: // Set the completion status. ! 595: // ! 596: ! 597: status = STATUS_NOT_IMPLEMENTED; ! 598: break; ! 599: ! 600: // ! 601: // Enable keyboard interrupts (mark the request pending and handle ! 602: // it in StartIo). ! 603: // ! 604: ! 605: case IOCTL_INTERNAL_KEYBOARD_ENABLE: ! 606: ! 607: I8xPrint(( ! 608: 2, ! 609: "I8042PRT-I8042InternalDeviceControl: keyboard enable\n" ! 610: )); ! 611: ! 612: status = STATUS_PENDING; ! 613: break; ! 614: ! 615: // ! 616: // Disable keyboard interrupts (mark the request pending and handle ! 617: // it in StartIo). ! 618: // ! 619: ! 620: case IOCTL_INTERNAL_KEYBOARD_DISABLE: ! 621: ! 622: I8xPrint(( ! 623: 2, ! 624: "I8042PRT-I8042InternalDeviceControl: keyboard disable\n" ! 625: )); ! 626: ! 627: status = STATUS_PENDING; ! 628: break; ! 629: ! 630: // ! 631: // Enable mouse interrupts (mark the request pending and handle ! 632: // it in StartIo). ! 633: // ! 634: ! 635: case IOCTL_INTERNAL_MOUSE_ENABLE: ! 636: ! 637: I8xPrint(( ! 638: 2, ! 639: "I8042PRT-I8042InternalDeviceControl: mouse enable\n" ! 640: )); ! 641: ! 642: status = STATUS_PENDING; ! 643: break; ! 644: ! 645: // ! 646: // Disable mouse interrupts (mark the request pending and handle ! 647: // it in StartIo). ! 648: // ! 649: ! 650: case IOCTL_INTERNAL_MOUSE_DISABLE: ! 651: ! 652: I8xPrint(( ! 653: 2, ! 654: "I8042PRT-I8042InternalDeviceControl: mouse disable\n" ! 655: )); ! 656: ! 657: status = STATUS_PENDING; ! 658: break; ! 659: ! 660: // ! 661: // Query the keyboard attributes. First check for adequate buffer ! 662: // length. Then, copy the keyboard attributes from the device ! 663: // extension to the output buffer. ! 664: // ! 665: ! 666: case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: ! 667: ! 668: I8xPrint(( ! 669: 2, ! 670: "I8042PRT-I8042InternalDeviceControl: keyboard query attributes\n" ! 671: )); ! 672: ! 673: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < ! 674: sizeof(KEYBOARD_ATTRIBUTES)) { ! 675: status = STATUS_BUFFER_TOO_SMALL; ! 676: } else { ! 677: ! 678: // ! 679: // Copy the attributes from the DeviceExtension to the ! 680: // buffer. ! 681: // ! 682: ! 683: *(PKEYBOARD_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer = ! 684: deviceExtension->Configuration.KeyboardAttributes; ! 685: ! 686: Irp->IoStatus.Information = sizeof(KEYBOARD_ATTRIBUTES); ! 687: status = STATUS_SUCCESS; ! 688: } ! 689: ! 690: break; ! 691: ! 692: // ! 693: // Query the scan code to indicator-light mapping. Validate the ! 694: // parameters, and copy the indicator mapping information from ! 695: // the port device extension to the SystemBuffer. ! 696: // ! 697: ! 698: case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: ! 699: ! 700: I8xPrint(( ! 701: 2, ! 702: "I8042PRT-I8042InternalDeviceControl: keyboard query indicator translation\n" ! 703: )); ! 704: ! 705: sizeOfTranslation = sizeof(KEYBOARD_INDICATOR_TRANSLATION) ! 706: + (sizeof(INDICATOR_LIST) ! 707: * (deviceExtension->Configuration.KeyboardAttributes.NumberOfIndicators - 1)); ! 708: ! 709: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < ! 710: sizeOfTranslation) { ! 711: status = STATUS_BUFFER_TOO_SMALL; ! 712: } else { ! 713: ! 714: // ! 715: // Copy the indicator mapping information to the system ! 716: // buffer. ! 717: // ! 718: ! 719: ((PKEYBOARD_INDICATOR_TRANSLATION) ! 720: Irp->AssociatedIrp.SystemBuffer)->NumberOfIndicatorKeys = ! 721: deviceExtension->Configuration.KeyboardAttributes.NumberOfIndicators; ! 722: RtlMoveMemory( ! 723: ((PKEYBOARD_INDICATOR_TRANSLATION) ! 724: Irp->AssociatedIrp.SystemBuffer)->IndicatorList, ! 725: (PCHAR) IndicatorList, ! 726: sizeOfTranslation ! 727: ); ! 728: ! 729: Irp->IoStatus.Information = sizeOfTranslation; ! 730: status = STATUS_SUCCESS; ! 731: } ! 732: ! 733: break; ! 734: ! 735: // ! 736: // Query the keyboard indicators. Validate the parameters, and ! 737: // copy the indicator information from the port device extension to ! 738: // the SystemBuffer. ! 739: // ! 740: ! 741: case IOCTL_KEYBOARD_QUERY_INDICATORS: ! 742: ! 743: ! 744: I8xPrint(( ! 745: 2, ! 746: "I8042PRT-I8042InternalDeviceControl: keyboard query indicators\n" ! 747: )); ! 748: ! 749: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < ! 750: sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { ! 751: status = STATUS_BUFFER_TOO_SMALL; ! 752: } else { ! 753: ! 754: // ! 755: // Don't bother to synchronize access to the DeviceExtension ! 756: // KeyboardIndicators field while copying it. We don't ! 757: // really care if another process is setting the LEDs via ! 758: // StartIo running on another processor. ! 759: // ! 760: ! 761: *(PKEYBOARD_INDICATOR_PARAMETERS) ! 762: Irp->AssociatedIrp.SystemBuffer = ! 763: deviceExtension->Configuration.KeyboardIndicators; ! 764: Irp->IoStatus.Information = ! 765: sizeof(KEYBOARD_INDICATOR_PARAMETERS); ! 766: status = STATUS_SUCCESS; ! 767: } ! 768: ! 769: break; ! 770: ! 771: // ! 772: // Set the keyboard indicators (validate the parameters, mark the ! 773: // request pending, and handle it in StartIo). ! 774: // ! 775: ! 776: case IOCTL_KEYBOARD_SET_INDICATORS: ! 777: ! 778: I8xPrint(( ! 779: 2, ! 780: "I8042PRT-I8042InternalDeviceControl: keyboard set indicators\n" ! 781: )); ! 782: ! 783: if ((irpSp->Parameters.DeviceIoControl.InputBufferLength < ! 784: sizeof(KEYBOARD_INDICATOR_PARAMETERS)) || ! 785: ((((PKEYBOARD_INDICATOR_PARAMETERS) ! 786: Irp->AssociatedIrp.SystemBuffer)->LedFlags ! 787: & ~(KEYBOARD_SCROLL_LOCK_ON ! 788: | KEYBOARD_NUM_LOCK_ON | KEYBOARD_CAPS_LOCK_ON)) != 0)) { ! 789: status = STATUS_INVALID_PARAMETER; ! 790: } else { ! 791: status = STATUS_PENDING; ! 792: } ! 793: ! 794: break; ! 795: ! 796: // ! 797: // Query the current keyboard typematic rate and delay. Validate ! 798: // the parameters, and copy the typematic information from the port ! 799: // device extension to the SystemBuffer. ! 800: // ! 801: ! 802: case IOCTL_KEYBOARD_QUERY_TYPEMATIC: ! 803: ! 804: I8xPrint(( ! 805: 2, ! 806: "I8042PRT-I8042InternalDeviceControl: keyboard query typematic\n" ! 807: )); ! 808: ! 809: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < ! 810: sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) { ! 811: status = STATUS_BUFFER_TOO_SMALL; ! 812: } else { ! 813: ! 814: // ! 815: // Don't bother to synchronize access to the DeviceExtension ! 816: // KeyRepeatCurrent field while copying it. We don't ! 817: // really care if another process is setting the typematic ! 818: // rate/delay via StartIo running on another processor. ! 819: // ! 820: ! 821: *(PKEYBOARD_TYPEMATIC_PARAMETERS) ! 822: Irp->AssociatedIrp.SystemBuffer = ! 823: deviceExtension->Configuration.KeyRepeatCurrent; ! 824: Irp->IoStatus.Information = ! 825: sizeof(KEYBOARD_TYPEMATIC_PARAMETERS); ! 826: status = STATUS_SUCCESS; ! 827: } ! 828: ! 829: break; ! 830: ! 831: // ! 832: // Set the keyboard typematic rate and delay (validate the parameters, ! 833: // mark the request pending, and handle it in StartIo). ! 834: // ! 835: ! 836: case IOCTL_KEYBOARD_SET_TYPEMATIC: ! 837: ! 838: I8xPrint(( ! 839: 2, ! 840: "I8042PRT-I8042InternalDeviceControl: keyboard set typematic\n" ! 841: )); ! 842: ! 843: parameters = Irp->AssociatedIrp.SystemBuffer; ! 844: keyboardAttributes = ! 845: &deviceExtension->Configuration.KeyboardAttributes; ! 846: ! 847: if ((irpSp->Parameters.DeviceIoControl.InputBufferLength < ! 848: sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) || ! 849: (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Rate < ! 850: keyboardAttributes->KeyRepeatMinimum.Rate) || ! 851: (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Rate > ! 852: keyboardAttributes->KeyRepeatMaximum.Rate) || ! 853: (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Delay < ! 854: keyboardAttributes->KeyRepeatMinimum.Delay) || ! 855: (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Delay > ! 856: keyboardAttributes->KeyRepeatMaximum.Delay)) { ! 857: status = STATUS_INVALID_PARAMETER; ! 858: } else { ! 859: status = STATUS_PENDING; ! 860: } ! 861: ! 862: break; ! 863: ! 864: // ! 865: // Query the mouse attributes. First check for adequate buffer ! 866: // length. Then, copy the mouse attributes from the device ! 867: // extension to the output buffer. ! 868: // ! 869: ! 870: case IOCTL_MOUSE_QUERY_ATTRIBUTES: ! 871: ! 872: I8xPrint(( ! 873: 2, ! 874: "I8042PRT-I8042InternalDeviceControl: mouse query attributes\n" ! 875: )); ! 876: ! 877: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < ! 878: sizeof(MOUSE_ATTRIBUTES)) { ! 879: status = STATUS_BUFFER_TOO_SMALL; ! 880: } else { ! 881: ! 882: // ! 883: // Copy the attributes from the DeviceExtension to the ! 884: // buffer. ! 885: // ! 886: ! 887: *(PMOUSE_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer = ! 888: deviceExtension->Configuration.MouseAttributes; ! 889: ! 890: Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES); ! 891: status = STATUS_SUCCESS; ! 892: } ! 893: ! 894: break; ! 895: ! 896: default: ! 897: ! 898: I8xPrint(( ! 899: 2, ! 900: "I8042PRT-I8042InternalDeviceControl: INVALID REQUEST\n" ! 901: )); ! 902: ! 903: status = STATUS_INVALID_DEVICE_REQUEST; ! 904: break; ! 905: } ! 906: ! 907: Irp->IoStatus.Status = status; ! 908: if (status == STATUS_PENDING) { ! 909: IoMarkIrpPending(Irp); ! 910: IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL); ! 911: } else { ! 912: IoCompleteRequest(Irp, IO_NO_INCREMENT); ! 913: } ! 914: ! 915: I8xPrint((2,"I8042PRT-I8042InternalDeviceControl: exit\n")); ! 916: ! 917: return(status); ! 918: ! 919: } ! 920: ! 921: NTSTATUS ! 922: I8042OpenCloseDispatch( ! 923: IN PDEVICE_OBJECT DeviceObject, ! 924: IN PIRP Irp ! 925: ) ! 926: ! 927: /*++ ! 928: ! 929: Routine Description: ! 930: ! 931: This is the dispatch routine for create/open and close requests. ! 932: These requests complete successfully. ! 933: ! 934: Arguments: ! 935: ! 936: DeviceObject - Pointer to the device object. ! 937: ! 938: Irp - Pointer to the request packet. ! 939: ! 940: Return Value: ! 941: ! 942: Status is returned. ! 943: ! 944: --*/ ! 945: ! 946: { ! 947: ! 948: UNREFERENCED_PARAMETER(DeviceObject); ! 949: ! 950: I8xPrint((3,"I8042PRT-I8042OpenCloseDispatch: enter\n")); ! 951: ! 952: // ! 953: // Complete the request with successful status. ! 954: // ! 955: ! 956: Irp->IoStatus.Status = STATUS_SUCCESS; ! 957: Irp->IoStatus.Information = 0; ! 958: IoCompleteRequest(Irp, IO_NO_INCREMENT); ! 959: ! 960: I8xPrint((3,"I8042PRT-I8042OpenCloseDispatch: exit\n")); ! 961: ! 962: return(STATUS_SUCCESS); ! 963: ! 964: } ! 965: ! 966: VOID ! 967: I8042RetriesExceededDpc( ! 968: IN PKDPC Dpc, ! 969: IN PDEVICE_OBJECT DeviceObject, ! 970: IN PIRP Irp, ! 971: IN PVOID Context ! 972: ) ! 973: ! 974: /*++ ! 975: ! 976: Routine Description: ! 977: ! 978: This routine runs at DISPATCH_LEVEL IRQL to complete requests that ! 979: have exceeded the maximum number of retries. It is queued in the ! 980: keyboard ISR. ! 981: ! 982: Arguments: ! 983: ! 984: Dpc - Pointer to the DPC object. ! 985: ! 986: DeviceObject - Pointer to the device object. ! 987: ! 988: Irp - Pointer to the Irp. ! 989: ! 990: Context - Not used. ! 991: ! 992: Return Value: ! 993: ! 994: None. ! 995: ! 996: --*/ ! 997: ! 998: { ! 999: PDEVICE_EXTENSION deviceExtension; ! 1000: PIO_ERROR_LOG_PACKET errorLogEntry; ! 1001: PIO_STACK_LOCATION irpSp; ! 1002: ! 1003: UNREFERENCED_PARAMETER(Dpc); ! 1004: UNREFERENCED_PARAMETER(Context); ! 1005: ! 1006: I8xPrint((2, "I8042PRT-I8042RetriesExceededDpc: enter\n")); ! 1007: ! 1008: deviceExtension = DeviceObject->DeviceExtension; ! 1009: ! 1010: // ! 1011: // Set the completion status. ! 1012: // ! 1013: ! 1014: Irp->IoStatus.Status = STATUS_IO_TIMEOUT; ! 1015: ! 1016: // ! 1017: // Log an error. ! 1018: // ! 1019: ! 1020: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( ! 1021: DeviceObject, ! 1022: sizeof(IO_ERROR_LOG_PACKET) ! 1023: + (3 * sizeof(ULONG)) ! 1024: ); ! 1025: if (errorLogEntry != NULL) { ! 1026: ! 1027: errorLogEntry->ErrorCode = I8042_RETRIES_EXCEEDED; ! 1028: errorLogEntry->DumpDataSize = 3 * sizeof(ULONG); ! 1029: errorLogEntry->SequenceNumber = ! 1030: deviceExtension->KeyboardExtension.SequenceNumber; ! 1031: irpSp = IoGetCurrentIrpStackLocation(Irp); ! 1032: errorLogEntry->MajorFunctionCode = irpSp->MajorFunction; ! 1033: errorLogEntry->IoControlCode = ! 1034: irpSp->Parameters.DeviceIoControl.IoControlCode; ! 1035: errorLogEntry->RetryCount = ! 1036: deviceExtension->KeyboardExtension.ResendCount; ! 1037: errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 210; ! 1038: errorLogEntry->FinalStatus = Irp->IoStatus.Status; ! 1039: errorLogEntry->DumpData[0] = ! 1040: deviceExtension->KeyboardExtension.CurrentOutput.State; ! 1041: errorLogEntry->DumpData[1] = ! 1042: deviceExtension->KeyboardExtension.CurrentOutput.FirstByte; ! 1043: errorLogEntry->DumpData[2] = ! 1044: deviceExtension->KeyboardExtension.CurrentOutput.LastByte; ! 1045: ! 1046: IoWriteErrorLogEntry(errorLogEntry); ! 1047: } ! 1048: ! 1049: // ! 1050: // Start the next packet and complete the request. ! 1051: // ! 1052: ! 1053: IoStartNextPacket(DeviceObject, FALSE); ! 1054: IoCompleteRequest (Irp, IO_KEYBOARD_INCREMENT); ! 1055: ! 1056: I8xPrint((2, "I8042PRT-I8042RetriesExceededDpc: exit\n")); ! 1057: ! 1058: } ! 1059: ! 1060: VOID ! 1061: I8042StartIo( ! 1062: IN PDEVICE_OBJECT DeviceObject, ! 1063: IN PIRP Irp ! 1064: ) ! 1065: ! 1066: /*++ ! 1067: ! 1068: Routine Description: ! 1069: ! 1070: This routine starts an I/O operation for the device. ! 1071: ! 1072: Arguments: ! 1073: ! 1074: DeviceObject - Pointer to the device object. ! 1075: ! 1076: Irp - Pointer to the request packet. ! 1077: ! 1078: Return Value: ! 1079: ! 1080: None. ! 1081: ! 1082: --*/ ! 1083: ! 1084: { ! 1085: PDEVICE_EXTENSION deviceExtension; ! 1086: PIO_STACK_LOCATION irpSp; ! 1087: KEYBOARD_INITIATE_CONTEXT keyboardInitiateContext; ! 1088: LARGE_INTEGER deltaTime; ! 1089: INTERLOCKED_RESULT interlockedResult; ! 1090: ! 1091: I8xPrint((2, "I8042PRT-I8042StartIo: enter\n")); ! 1092: ! 1093: deviceExtension = DeviceObject->DeviceExtension; ! 1094: ! 1095: // ! 1096: // Bump the error log sequence number. ! 1097: // ! 1098: ! 1099: deviceExtension->KeyboardExtension.SequenceNumber += 1; ! 1100: ! 1101: // ! 1102: // Get a pointer to the current parameters for this request. The ! 1103: // information is contained in the current stack location. ! 1104: // ! 1105: ! 1106: irpSp = IoGetCurrentIrpStackLocation(Irp); ! 1107: ! 1108: // ! 1109: // We know we got here with an internal device control request. Switch ! 1110: // on IoControlCode. ! 1111: // ! 1112: ! 1113: switch(irpSp->Parameters.DeviceIoControl.IoControlCode) { ! 1114: ! 1115: // ! 1116: // Enable the keyboard device. ! 1117: // ! 1118: ! 1119: case IOCTL_INTERNAL_KEYBOARD_ENABLE: ! 1120: ! 1121: // ! 1122: // Enable keyboard by incrementing the KeyboardEnableCount ! 1123: // field. The keyboard ISR will start processing keyboard ! 1124: // interrupts when KeyboardEnableCount is non-zero. Note that ! 1125: // the keyboard device and its interrupts are *always* enabled ! 1126: // in the i8042 Controller Command Byte, following initialization. ! 1127: // Interrupts are ignored in the ISR, however, until the ! 1128: // KeyboardEnableCount is greater than zero (indicating that the ! 1129: // user has "enabled" the device). ! 1130: // ! 1131: ! 1132: interlockedResult = ExInterlockedIncrementLong( ! 1133: &deviceExtension->KeyboardEnableCount, ! 1134: &deviceExtension->SharedInterruptSpinLock ! 1135: ); ! 1136: ! 1137: I8xPrint(( ! 1138: 2, ! 1139: "I8042PRT-I8042StartIo: keyboard enable (count %d)\n", ! 1140: deviceExtension->KeyboardEnableCount ! 1141: )); ! 1142: ! 1143: Irp->IoStatus.Status = STATUS_SUCCESS; ! 1144: ! 1145: // ! 1146: // Complete the request. ! 1147: // ! 1148: ! 1149: IoStartNextPacket(DeviceObject, FALSE); ! 1150: IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT); ! 1151: ! 1152: break; ! 1153: ! 1154: // ! 1155: // Disable the keyboard device. ! 1156: // ! 1157: ! 1158: case IOCTL_INTERNAL_KEYBOARD_DISABLE: ! 1159: ! 1160: I8xPrint((2, "I8042PRT-I8042StartIo: keyboard disable")); ! 1161: ! 1162: if (deviceExtension->KeyboardEnableCount == 0) { ! 1163: ! 1164: // ! 1165: // Keyboard already disabled. ! 1166: // ! 1167: ! 1168: I8xPrint((2, " - error\n")); ! 1169: ! 1170: Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR; ! 1171: ! 1172: } else { ! 1173: ! 1174: // ! 1175: // Disable keyboard by decrementing the KeyboardEnableCount ! 1176: // field. The keyboard ISR will ignore keyboard ! 1177: // interrupts when KeyboardEnableCount is zero. ! 1178: // ! 1179: ! 1180: interlockedResult = ! 1181: ExInterlockedDecrementLong( ! 1182: &deviceExtension->KeyboardEnableCount, ! 1183: &deviceExtension->SharedInterruptSpinLock ! 1184: ); ! 1185: ! 1186: I8xPrint(( ! 1187: 2, ! 1188: " (count %d)\n", ! 1189: deviceExtension->KeyboardEnableCount ! 1190: )); ! 1191: ! 1192: Irp->IoStatus.Status = STATUS_SUCCESS; ! 1193: } ! 1194: ! 1195: // ! 1196: // Complete the request. ! 1197: // ! 1198: ! 1199: IoStartNextPacket(DeviceObject, FALSE); ! 1200: IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT); ! 1201: ! 1202: break; ! 1203: ! 1204: // ! 1205: // Enable the mouse device. ! 1206: // ! 1207: ! 1208: case IOCTL_INTERNAL_MOUSE_ENABLE: ! 1209: ! 1210: // ! 1211: // Enable mouse by incrementing the MouseEnableCount ! 1212: // field. The mouse ISR will start processing mouse ! 1213: // interrupts when MouseEnableCount is non-zero. Note that ! 1214: // the mouse device and its interrupts are *always* enabled ! 1215: // in the i8042 Controller Command Byte, following initialization. ! 1216: // Interrupts are ignored in the ISR, however, until the ! 1217: // MouseEnableCount is greater than zero (indicating that the ! 1218: // user has "enabled" the device). ! 1219: // ! 1220: ! 1221: ! 1222: interlockedResult = ExInterlockedIncrementLong( ! 1223: &deviceExtension->MouseEnableCount, ! 1224: &deviceExtension->SharedInterruptSpinLock ! 1225: ); ! 1226: ! 1227: ! 1228: I8xPrint(( ! 1229: 2, ! 1230: "I8042PRT-I8042StartIo: mouse enable (count %d)\n", ! 1231: deviceExtension->MouseEnableCount ! 1232: )); ! 1233: ! 1234: Irp->IoStatus.Status = STATUS_SUCCESS; ! 1235: ! 1236: // ! 1237: // Complete the request. ! 1238: // ! 1239: ! 1240: IoStartNextPacket(DeviceObject, FALSE); ! 1241: IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); ! 1242: ! 1243: break; ! 1244: ! 1245: // ! 1246: // Disable the mouse device. ! 1247: // ! 1248: ! 1249: case IOCTL_INTERNAL_MOUSE_DISABLE: ! 1250: ! 1251: I8xPrint((2, "I8042PRT-I8042StartIo: mouse disable")); ! 1252: ! 1253: if (deviceExtension->MouseEnableCount == 0) { ! 1254: ! 1255: // ! 1256: // Mouse already disabled. ! 1257: // ! 1258: ! 1259: I8xPrint((2, " - error\n")); ! 1260: ! 1261: Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR; ! 1262: ! 1263: } else { ! 1264: ! 1265: // ! 1266: // Disable mouse by decrementing the MouseEnableCount ! 1267: // field. The mouse ISR will ignore keyboard ! 1268: // interrupts when MouseEnableCount is zero. ! 1269: // ! 1270: ! 1271: interlockedResult = ! 1272: ExInterlockedDecrementLong( ! 1273: &deviceExtension->MouseEnableCount, ! 1274: &deviceExtension->SharedInterruptSpinLock ! 1275: ); ! 1276: ! 1277: I8xPrint(( ! 1278: 2, ! 1279: " (count %d)\n", ! 1280: deviceExtension->MouseEnableCount ! 1281: )); ! 1282: ! 1283: Irp->IoStatus.Status = STATUS_SUCCESS; ! 1284: } ! 1285: ! 1286: // ! 1287: // Complete the request. ! 1288: // ! 1289: ! 1290: IoStartNextPacket(DeviceObject, FALSE); ! 1291: IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); ! 1292: ! 1293: break; ! 1294: ! 1295: // ! 1296: // Set the keyboard indicators to the desired state. ! 1297: // ! 1298: ! 1299: case IOCTL_KEYBOARD_SET_INDICATORS: ! 1300: ! 1301: I8xPrint((2, "I8042PRT-I8042StartIo: keyboard set indicators\n")); ! 1302: ! 1303: // ! 1304: // Set up the context structure for the InitiateIo wrapper. ! 1305: // ! 1306: ! 1307: keyboardInitiateContext.DeviceObject = DeviceObject; ! 1308: keyboardInitiateContext.FirstByte = SET_KEYBOARD_INDICATORS; ! 1309: keyboardInitiateContext.LastByte = ! 1310: (UCHAR) ((PKEYBOARD_INDICATOR_PARAMETERS) ! 1311: Irp->AssociatedIrp.SystemBuffer)->LedFlags; ! 1312: ! 1313: // ! 1314: // Call the InitiateIo wrapper synchronously. The wrapper ! 1315: // stores the context parameters in the device extension, ! 1316: // and then initiates the I/O operation, all synchronized ! 1317: // with the keyboard ISR. ! 1318: // ! 1319: ! 1320: KeSynchronizeExecution( ! 1321: deviceExtension->KeyboardInterruptObject, ! 1322: (PKSYNCHRONIZE_ROUTINE) I8xKeyboardInitiateWrapper, ! 1323: (PVOID) &keyboardInitiateContext ! 1324: ); ! 1325: ! 1326: // ! 1327: // Start the 1-second command timer. InitiateIo changed ! 1328: // the TimerCount already. ! 1329: // ! 1330: ! 1331: deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000); ! 1332: deltaTime.HighPart = -1; ! 1333: ! 1334: (VOID) KeSetTimer( ! 1335: &deviceExtension->CommandTimer, ! 1336: deltaTime, ! 1337: &deviceExtension->TimeOutDpc ! 1338: ); ! 1339: ! 1340: break; ! 1341: ! 1342: // ! 1343: // Set the keyboard typematic rate and delay. ! 1344: // ! 1345: ! 1346: case IOCTL_KEYBOARD_SET_TYPEMATIC: ! 1347: ! 1348: I8xPrint((2, "I8042PRT-I8042StartIo: keyboard set typematic\n")); ! 1349: ! 1350: // ! 1351: // Set up the context structure for the InitiateIo wrapper. ! 1352: // ! 1353: ! 1354: keyboardInitiateContext.DeviceObject = DeviceObject; ! 1355: keyboardInitiateContext.FirstByte = SET_KEYBOARD_TYPEMATIC; ! 1356: keyboardInitiateContext.LastByte = ! 1357: I8xConvertTypematicParameters( ! 1358: ((PKEYBOARD_TYPEMATIC_PARAMETERS) ! 1359: Irp->AssociatedIrp.SystemBuffer)->Rate, ! 1360: ((PKEYBOARD_TYPEMATIC_PARAMETERS) ! 1361: Irp->AssociatedIrp.SystemBuffer)->Delay ! 1362: ); ! 1363: ! 1364: // ! 1365: // Call the InitiateIo wrapper synchronously. The wrapper ! 1366: // stores the context parameters in the device extension, ! 1367: // and then initiates the I/O operation, all synchronized ! 1368: // with the keyboard ISR. ! 1369: // ! 1370: ! 1371: KeSynchronizeExecution( ! 1372: deviceExtension->KeyboardInterruptObject, ! 1373: (PKSYNCHRONIZE_ROUTINE) I8xKeyboardInitiateWrapper, ! 1374: (PVOID) &keyboardInitiateContext ! 1375: ); ! 1376: ! 1377: // ! 1378: // Start the 1-second command timer. InitiateIo changed ! 1379: // the TimerCount already. ! 1380: // ! 1381: ! 1382: deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000); ! 1383: deltaTime.HighPart = -1; ! 1384: ! 1385: (VOID) KeSetTimer( ! 1386: &deviceExtension->CommandTimer, ! 1387: deltaTime, ! 1388: &deviceExtension->TimeOutDpc ! 1389: ); ! 1390: ! 1391: break; ! 1392: ! 1393: default: ! 1394: ! 1395: I8xPrint((2, "I8042PRT-I8042StartIo: INVALID REQUEST\n")); ! 1396: ! 1397: // ! 1398: // Log an internal error. Note that we're calling the ! 1399: // error log DPC routine directly, rather than duplicating ! 1400: // code. ! 1401: // ! 1402: ! 1403: I8042ErrorLogDpc( ! 1404: (PKDPC) NULL, ! 1405: DeviceObject, ! 1406: Irp, ! 1407: (PVOID) (ULONG) I8042_INVALID_STARTIO_REQUEST ! 1408: ); ! 1409: ! 1410: ASSERT(FALSE); ! 1411: break; ! 1412: } ! 1413: ! 1414: I8xPrint((2, "I8042PRT-I8042StartIo: exit\n")); ! 1415: ! 1416: return; ! 1417: } ! 1418: ! 1419: VOID ! 1420: I8042TimeOutDpc( ! 1421: IN PKDPC Dpc, ! 1422: IN PDEVICE_OBJECT DeviceObject, ! 1423: IN PVOID SystemContext1, ! 1424: IN PVOID SystemContext2 ! 1425: ) ! 1426: ! 1427: /*++ ! 1428: ! 1429: Routine Description: ! 1430: ! 1431: This is the driver's command timeout routine. It is called when the ! 1432: command timer fires. ! 1433: ! 1434: Arguments: ! 1435: ! 1436: Dpc - Not Used. ! 1437: ! 1438: DeviceObject - Pointer to the device object. ! 1439: ! 1440: SystemContext1 - Not Used. ! 1441: ! 1442: SystemContext2 - Not Used. ! 1443: ! 1444: Return Value: ! 1445: ! 1446: None. As a side-effect, the timeout counter is updated and an error ! 1447: is logged. ! 1448: ! 1449: --*/ ! 1450: ! 1451: { ! 1452: PDEVICE_EXTENSION deviceExtension; ! 1453: KIRQL cancelIrql; ! 1454: TIMER_CONTEXT timerContext; ! 1455: PIRP irp; ! 1456: PIO_ERROR_LOG_PACKET errorLogEntry; ! 1457: PIO_STACK_LOCATION irpSp; ! 1458: LARGE_INTEGER deltaTime; ! 1459: ! 1460: I8xPrint((3, "I8042PRT-I8042TimeOutDpc: enter\n")); ! 1461: ! 1462: // ! 1463: // Get the device extension. ! 1464: // ! 1465: ! 1466: deviceExtension = DeviceObject->DeviceExtension; ! 1467: ! 1468: // ! 1469: // Acquire the cancel spinlock, verify that the CurrentIrp has not been ! 1470: // cancelled (i.e., CurrentIrp != NULL), set the cancel routine to NULL, ! 1471: // and release the cancel spinlock. ! 1472: // ! 1473: ! 1474: IoAcquireCancelSpinLock(&cancelIrql); ! 1475: irp = DeviceObject->CurrentIrp; ! 1476: if (irp == NULL) { ! 1477: IoReleaseCancelSpinLock(cancelIrql); ! 1478: return; ! 1479: } ! 1480: IoSetCancelRoutine(irp, NULL); ! 1481: IoReleaseCancelSpinLock(cancelIrql); ! 1482: ! 1483: // ! 1484: // If the TimerCounter == 0 on entry to this routine, the last packet ! 1485: // timed out and was completed. We just decrement TimerCounter ! 1486: // (synchronously) to indicate that we're no longer timing. ! 1487: // ! 1488: // If the TimerCounter indicates no timeout (I8042_ASYNC_NO_TIMEOUT) ! 1489: // on entry to this routine, there is no command being timed. ! 1490: // ! 1491: ! 1492: timerContext.DeviceObject = DeviceObject; ! 1493: timerContext.TimerCounter = &deviceExtension->TimerCount; ! 1494: ! 1495: KeSynchronizeExecution( ! 1496: deviceExtension->KeyboardInterruptObject, ! 1497: (PKSYNCHRONIZE_ROUTINE) I8xDecrementTimer, ! 1498: &timerContext ! 1499: ); ! 1500: ! 1501: if (timerContext.NewTimerCount == 0) { ! 1502: ! 1503: // ! 1504: // Set up the IO Status Block prior to completing the request. ! 1505: // ! 1506: ! 1507: DeviceObject->CurrentIrp->IoStatus.Information = 0; ! 1508: DeviceObject->CurrentIrp->IoStatus.Status = STATUS_IO_TIMEOUT; ! 1509: ! 1510: // ! 1511: // Log a timeout error. ! 1512: // ! 1513: ! 1514: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( ! 1515: DeviceObject, ! 1516: sizeof(IO_ERROR_LOG_PACKET) ! 1517: + (3 * sizeof(ULONG)) ! 1518: ); ! 1519: ! 1520: if (errorLogEntry != NULL) { ! 1521: ! 1522: errorLogEntry->ErrorCode = I8042_TIMEOUT; ! 1523: errorLogEntry->DumpDataSize = 3 * sizeof(ULONG); ! 1524: errorLogEntry->SequenceNumber = ! 1525: deviceExtension->KeyboardExtension.SequenceNumber; ! 1526: irpSp = IoGetCurrentIrpStackLocation(irp); ! 1527: errorLogEntry->MajorFunctionCode = irpSp->MajorFunction; ! 1528: errorLogEntry->IoControlCode = ! 1529: irpSp->Parameters.DeviceIoControl.IoControlCode; ! 1530: errorLogEntry->RetryCount = ! 1531: deviceExtension->KeyboardExtension.ResendCount; ! 1532: errorLogEntry->UniqueErrorValue = 90; ! 1533: errorLogEntry->FinalStatus = STATUS_IO_TIMEOUT; ! 1534: errorLogEntry->DumpData[0] = ! 1535: deviceExtension->KeyboardExtension.CurrentOutput.State; ! 1536: errorLogEntry->DumpData[1] = ! 1537: deviceExtension->KeyboardExtension.CurrentOutput.FirstByte; ! 1538: errorLogEntry->DumpData[2] = ! 1539: deviceExtension->KeyboardExtension.CurrentOutput.LastByte; ! 1540: ! 1541: IoWriteErrorLogEntry(errorLogEntry); ! 1542: } ! 1543: ! 1544: // ! 1545: // Start the next packet and complete the request. ! 1546: // ! 1547: ! 1548: IoStartNextPacket(DeviceObject, FALSE); ! 1549: IoCompleteRequest(irp, IO_KEYBOARD_INCREMENT); ! 1550: ! 1551: } else { ! 1552: ! 1553: // ! 1554: // Restart the command timer. Once started, the timer stops only ! 1555: // when the TimerCount goes to zero (indicating that the command ! 1556: // has timed out) or when explicitly cancelled in the completion ! 1557: // DPC (indicating that the command has successfully completed). ! 1558: // ! 1559: ! 1560: deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000); ! 1561: deltaTime.HighPart = -1; ! 1562: ! 1563: (VOID) KeSetTimer( ! 1564: &deviceExtension->CommandTimer, ! 1565: deltaTime, ! 1566: &deviceExtension->TimeOutDpc ! 1567: ); ! 1568: } ! 1569: ! 1570: I8xPrint((3, "I8042PRT-I8042TimeOutDpc: exit\n")); ! 1571: } ! 1572: ! 1573: #if DBG ! 1574: VOID ! 1575: I8xDebugPrint( ! 1576: ULONG DebugPrintLevel, ! 1577: PCCHAR DebugMessage, ! 1578: ... ! 1579: ) ! 1580: ! 1581: /*++ ! 1582: ! 1583: Routine Description: ! 1584: ! 1585: Debug print routine. ! 1586: ! 1587: Arguments: ! 1588: ! 1589: Debug print level between 0 and 3, with 3 being the most verbose. ! 1590: ! 1591: Return Value: ! 1592: ! 1593: None. ! 1594: ! 1595: --*/ ! 1596: ! 1597: { ! 1598: va_list ap; ! 1599: ! 1600: va_start(ap, DebugMessage); ! 1601: ! 1602: if (DebugPrintLevel <= i8042Debug) { ! 1603: ! 1604: char buffer[128]; ! 1605: ! 1606: (VOID) vsprintf(buffer, DebugMessage, ap); ! 1607: ! 1608: DbgPrint(buffer); ! 1609: } ! 1610: ! 1611: va_end(ap); ! 1612: ! 1613: } ! 1614: #endif ! 1615: ! 1616: ! 1617: VOID ! 1618: I8xDecrementTimer( ! 1619: IN PTIMER_CONTEXT Context ! 1620: ) ! 1621: ! 1622: /*++ ! 1623: ! 1624: Routine Description: ! 1625: ! 1626: This routine decrements the timeout counter. It is called from ! 1627: I8042TimeOutDpc. ! 1628: ! 1629: Arguments: ! 1630: ! 1631: Context - Points to the context structure containing a pointer ! 1632: to the device object and a pointer to the timeout counter. ! 1633: ! 1634: Return Value: ! 1635: ! 1636: None. As a side-effect, the timeout counter is updated. ! 1637: ! 1638: --*/ ! 1639: ! 1640: { ! 1641: PDEVICE_OBJECT deviceObject; ! 1642: PDEVICE_EXTENSION deviceExtension; ! 1643: ! 1644: deviceObject = Context->DeviceObject; ! 1645: deviceExtension = deviceObject->DeviceExtension; ! 1646: ! 1647: // ! 1648: // Decrement the timeout counter. ! 1649: // ! 1650: ! 1651: if (*(Context->TimerCounter) != I8042_ASYNC_NO_TIMEOUT) ! 1652: (*(Context->TimerCounter))--; ! 1653: ! 1654: // ! 1655: // Return the decremented timer count in NewTimerCount. The ! 1656: // TimerCounter itself could change between the time this KeSynch'ed ! 1657: // routine returns to the TimeOutDpc, and the time the TimeOutDpc ! 1658: // looks at the value. The TimeOutDpc will use NewTimerCount. ! 1659: // ! 1660: ! 1661: Context->NewTimerCount = *(Context->TimerCounter); ! 1662: ! 1663: // ! 1664: // Reset the state and the resend count, if the timeout counter goes to 0. ! 1665: // ! 1666: ! 1667: if (*(Context->TimerCounter) == 0) { ! 1668: deviceExtension->KeyboardExtension.CurrentOutput.State ! 1669: = Idle; ! 1670: deviceExtension->KeyboardExtension.ResendCount = 0; ! 1671: } ! 1672: ! 1673: } ! 1674: ! 1675: VOID ! 1676: I8xDpcVariableOperation( ! 1677: IN PVOID Context ! 1678: ) ! 1679: ! 1680: /*++ ! 1681: ! 1682: Routine Description: ! 1683: ! 1684: This routine is called synchronously by the ISR DPC to perform an ! 1685: operation on the InterlockedDpcVariable. The operations that can be ! 1686: performed include increment, decrement, write, and read. The ISR ! 1687: itself reads and writes the InterlockedDpcVariable without calling this ! 1688: routine. ! 1689: ! 1690: Arguments: ! 1691: ! 1692: Context - Pointer to a structure containing the address of the variable ! 1693: to be operated on, the operation to perform, and the address at ! 1694: which to copy the resulting value of the variable (the latter is also ! 1695: used to pass in the value to write to the variable, on a write ! 1696: operation). ! 1697: ! 1698: Return Value: ! 1699: ! 1700: None. ! 1701: ! 1702: --*/ ! 1703: ! 1704: { ! 1705: PVARIABLE_OPERATION_CONTEXT operationContext = Context; ! 1706: ! 1707: I8xPrint((3,"I8042PRT-I8xDpcVariableOperation: enter\n")); ! 1708: I8xPrint(( ! 1709: 3, ! 1710: "\tPerforming %s at 0x%x (current value 0x%x)\n", ! 1711: (operationContext->Operation == IncrementOperation)? "increment": ! 1712: (operationContext->Operation == DecrementOperation)? "decrement": ! 1713: (operationContext->Operation == WriteOperation)? "write": ! 1714: (operationContext->Operation == ReadOperation)? "read":"", ! 1715: operationContext->VariableAddress, ! 1716: *(operationContext->VariableAddress) ! 1717: )); ! 1718: ! 1719: // ! 1720: // Perform the specified operation at the specified address. ! 1721: // ! 1722: ! 1723: switch(operationContext->Operation) { ! 1724: case IncrementOperation: ! 1725: *(operationContext->VariableAddress) += 1; ! 1726: break; ! 1727: case DecrementOperation: ! 1728: *(operationContext->VariableAddress) -= 1; ! 1729: break; ! 1730: case ReadOperation: ! 1731: break; ! 1732: case WriteOperation: ! 1733: I8xPrint(( ! 1734: 3, ! 1735: "\tWriting 0x%x\n", ! 1736: *(operationContext->NewValue) ! 1737: )); ! 1738: *(operationContext->VariableAddress) = ! 1739: *(operationContext->NewValue); ! 1740: break; ! 1741: default: ! 1742: ASSERT(FALSE); ! 1743: break; ! 1744: } ! 1745: ! 1746: *(operationContext->NewValue) = *(operationContext->VariableAddress); ! 1747: ! 1748: I8xPrint(( ! 1749: 3, ! 1750: "I8042PRT-I8xDpcVariableOperation: exit with value 0x%x\n", ! 1751: *(operationContext->NewValue) ! 1752: )); ! 1753: } ! 1754: ! 1755: VOID ! 1756: I8xGetDataQueuePointer( ! 1757: IN PVOID Context ! 1758: ) ! 1759: ! 1760: /*++ ! 1761: ! 1762: Routine Description: ! 1763: ! 1764: This routine is called synchronously to get the current DataIn and DataOut ! 1765: pointers for the port InputData queue. ! 1766: ! 1767: Arguments: ! 1768: ! 1769: Context - Pointer to a structure containing the device extension, ! 1770: device type, address at which to store the current DataIn pointer, ! 1771: and the address at which to store the current DataOut pointer. ! 1772: ! 1773: Return Value: ! 1774: ! 1775: None. ! 1776: ! 1777: --*/ ! 1778: ! 1779: { ! 1780: PDEVICE_EXTENSION deviceExtension; ! 1781: CCHAR deviceType; ! 1782: ! 1783: I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: enter\n")); ! 1784: ! 1785: // ! 1786: // Get address of device extension. ! 1787: // ! 1788: ! 1789: deviceExtension = (PDEVICE_EXTENSION) ! 1790: ((PGET_DATA_POINTER_CONTEXT) Context)->DeviceExtension; ! 1791: deviceType = (CCHAR) ((PGET_DATA_POINTER_CONTEXT) Context)->DeviceType; ! 1792: ! 1793: // ! 1794: // Get the DataIn and DataOut pointers for the indicated device. ! 1795: // ! 1796: ! 1797: if (deviceType == KeyboardDeviceType) { ! 1798: I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: keyboard\n")); ! 1799: I8xPrint(( ! 1800: 3, ! 1801: "I8042PRT-I8xGetDataQueuePointer: DataIn 0x%x, DataOut 0x%x\n", ! 1802: deviceExtension->KeyboardExtension.DataIn, ! 1803: deviceExtension->KeyboardExtension.DataOut ! 1804: )); ! 1805: ((PGET_DATA_POINTER_CONTEXT) Context)->DataIn = ! 1806: deviceExtension->KeyboardExtension.DataIn; ! 1807: ((PGET_DATA_POINTER_CONTEXT) Context)->DataOut = ! 1808: deviceExtension->KeyboardExtension.DataOut; ! 1809: ((PGET_DATA_POINTER_CONTEXT) Context)->InputCount = ! 1810: deviceExtension->KeyboardExtension.InputCount; ! 1811: } else if (deviceType == MouseDeviceType) { ! 1812: I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: mouse\n")); ! 1813: I8xPrint(( ! 1814: 3, ! 1815: "I8042PRT-I8xGetDataQueuePointer: DataIn 0x%x, DataOut 0x%x\n", ! 1816: deviceExtension->MouseExtension.DataIn, ! 1817: deviceExtension->MouseExtension.DataOut ! 1818: )); ! 1819: ((PGET_DATA_POINTER_CONTEXT) Context)->DataIn = ! 1820: deviceExtension->MouseExtension.DataIn; ! 1821: ((PGET_DATA_POINTER_CONTEXT) Context)->DataOut = ! 1822: deviceExtension->MouseExtension.DataOut; ! 1823: ((PGET_DATA_POINTER_CONTEXT) Context)->InputCount = ! 1824: deviceExtension->MouseExtension.InputCount; ! 1825: } else { ! 1826: ASSERT(FALSE); ! 1827: } ! 1828: ! 1829: I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: exit\n")); ! 1830: } ! 1831: ! 1832: VOID ! 1833: I8xInitializeDataQueue ( ! 1834: IN PVOID Context ! 1835: ) ! 1836: ! 1837: /*++ ! 1838: ! 1839: Routine Description: ! 1840: ! 1841: This routine initializes the input data queue for the indicated device. ! 1842: This routine is called via KeSynchronization, except when called from ! 1843: the initialization routine. ! 1844: ! 1845: Arguments: ! 1846: ! 1847: Context - Pointer to a structure containing the device extension and ! 1848: the device type. ! 1849: ! 1850: Return Value: ! 1851: ! 1852: None. ! 1853: ! 1854: --*/ ! 1855: ! 1856: { ! 1857: ! 1858: PDEVICE_EXTENSION deviceExtension; ! 1859: CCHAR deviceType; ! 1860: ! 1861: I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: enter\n")); ! 1862: ! 1863: // ! 1864: // Get address of device extension. ! 1865: // ! 1866: ! 1867: deviceExtension = (PDEVICE_EXTENSION) ! 1868: ((PI8042_INITIALIZE_DATA_CONTEXT) Context)->DeviceExtension; ! 1869: deviceType = (CCHAR) ((PI8042_INITIALIZE_DATA_CONTEXT) Context)->DeviceType; ! 1870: ! 1871: // ! 1872: // Initialize the input data queue for the indicated device. ! 1873: // ! 1874: ! 1875: if (deviceType == KeyboardDeviceType) { ! 1876: deviceExtension->KeyboardExtension.InputCount = 0; ! 1877: deviceExtension->KeyboardExtension.DataIn = ! 1878: deviceExtension->KeyboardExtension.InputData; ! 1879: deviceExtension->KeyboardExtension.DataOut = ! 1880: deviceExtension->KeyboardExtension.InputData; ! 1881: deviceExtension->KeyboardExtension.OkayToLogOverflow = TRUE; ! 1882: I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: keyboard\n")); ! 1883: } else if (deviceType == MouseDeviceType) { ! 1884: deviceExtension->MouseExtension.InputCount = 0; ! 1885: deviceExtension->MouseExtension.DataIn = ! 1886: deviceExtension->MouseExtension.InputData; ! 1887: deviceExtension->MouseExtension.DataOut = ! 1888: deviceExtension->MouseExtension.InputData; ! 1889: deviceExtension->MouseExtension.OkayToLogOverflow = TRUE; ! 1890: I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: mouse\n")); ! 1891: } else { ! 1892: ASSERT(FALSE); ! 1893: } ! 1894: ! 1895: I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: exit\n")); ! 1896: ! 1897: } ! 1898: ! 1899: VOID ! 1900: I8xLogError( ! 1901: IN PDEVICE_OBJECT DeviceObject, ! 1902: IN NTSTATUS ErrorCode, ! 1903: IN ULONG UniqueErrorValue, ! 1904: IN NTSTATUS FinalStatus, ! 1905: IN PULONG DumpData, ! 1906: IN ULONG DumpCount ! 1907: ) ! 1908: ! 1909: /*++ ! 1910: ! 1911: Routine Description: ! 1912: ! 1913: This routine contains common code to write an error log entry. It is ! 1914: called from other routines, especially I8xInitializeKeyboard, to avoid ! 1915: duplication of code. Note that some routines continue to have their ! 1916: own error logging code (especially in the case where the error logging ! 1917: can be localized and/or the routine has more data because there is ! 1918: and IRP). ! 1919: ! 1920: Arguments: ! 1921: ! 1922: DeviceObject - Pointer to the device object. ! 1923: ! 1924: ErrorCode - The error code for the error log packet. ! 1925: ! 1926: UniqueErrorValue - The unique error value for the error log packet. ! 1927: ! 1928: FinalStatus - The final status of the operation for the error log packet. ! 1929: ! 1930: DumpData - Pointer to an array of dump data for the error log packet. ! 1931: ! 1932: DumpCount - The number of entries in the dump data array. ! 1933: ! 1934: ! 1935: Return Value: ! 1936: ! 1937: None. ! 1938: ! 1939: --*/ ! 1940: ! 1941: { ! 1942: PIO_ERROR_LOG_PACKET errorLogEntry; ! 1943: ULONG i; ! 1944: ! 1945: errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( ! 1946: DeviceObject, ! 1947: (UCHAR) ! 1948: (sizeof(IO_ERROR_LOG_PACKET) ! 1949: + (DumpCount * sizeof(ULONG))) ! 1950: ); ! 1951: ! 1952: if (errorLogEntry != NULL) { ! 1953: ! 1954: errorLogEntry->ErrorCode = ErrorCode; ! 1955: errorLogEntry->DumpDataSize = (USHORT) (DumpCount * sizeof(ULONG)); ! 1956: errorLogEntry->SequenceNumber = 0; ! 1957: errorLogEntry->MajorFunctionCode = 0; ! 1958: errorLogEntry->IoControlCode = 0; ! 1959: errorLogEntry->RetryCount = 0; ! 1960: errorLogEntry->UniqueErrorValue = UniqueErrorValue; ! 1961: errorLogEntry->FinalStatus = FinalStatus; ! 1962: for (i = 0; i < DumpCount; i++) ! 1963: errorLogEntry->DumpData[i] = DumpData[i]; ! 1964: ! 1965: IoWriteErrorLogEntry(errorLogEntry); ! 1966: } ! 1967: } ! 1968: ! 1969: VOID ! 1970: I8xSetDataQueuePointer( ! 1971: IN PVOID Context ! 1972: ) ! 1973: ! 1974: /*++ ! 1975: ! 1976: Routine Description: ! 1977: ! 1978: This routine is called synchronously to set the DataOut pointer ! 1979: and InputCount for the port InputData queue. ! 1980: ! 1981: Arguments: ! 1982: ! 1983: Context - Pointer to a structure containing the device extension, ! 1984: device type, and the new DataOut value for the port InputData queue. ! 1985: ! 1986: Return Value: ! 1987: ! 1988: None. ! 1989: ! 1990: --*/ ! 1991: ! 1992: { ! 1993: PDEVICE_EXTENSION deviceExtension; ! 1994: CCHAR deviceType; ! 1995: ! 1996: I8xPrint((3,"I8042PRT-I8xSetDataQueuePointer: enter\n")); ! 1997: ! 1998: // ! 1999: // Get address of device extension. ! 2000: // ! 2001: ! 2002: deviceExtension = (PDEVICE_EXTENSION) ! 2003: ((PSET_DATA_POINTER_CONTEXT) Context)->DeviceExtension; ! 2004: deviceType = (CCHAR) ((PSET_DATA_POINTER_CONTEXT) Context)->DeviceType; ! 2005: ! 2006: // ! 2007: // Set the DataOut pointer for the indicated device. ! 2008: // ! 2009: ! 2010: if (deviceType == KeyboardDeviceType) { ! 2011: I8xPrint(( ! 2012: 3, ! 2013: "I8042PRT-I8xSetDataQueuePointer: old keyboard DataOut 0x%x, InputCount %d\n", ! 2014: deviceExtension->KeyboardExtension.DataOut, ! 2015: deviceExtension->KeyboardExtension.InputCount ! 2016: )); ! 2017: deviceExtension->KeyboardExtension.DataOut = ! 2018: ((PSET_DATA_POINTER_CONTEXT) Context)->DataOut; ! 2019: deviceExtension->KeyboardExtension.InputCount -= ! 2020: ((PSET_DATA_POINTER_CONTEXT) Context)->InputCount; ! 2021: if (deviceExtension->KeyboardExtension.InputCount == 0) { ! 2022: ! 2023: // ! 2024: // Reset the flag that determines whether it is time to log ! 2025: // queue overflow errors. We don't want to log errors too often. ! 2026: // Instead, log an error on the first overflow that occurs after ! 2027: // the ring buffer has been emptied, and then stop logging errors ! 2028: // until it gets cleared out and overflows again. ! 2029: // ! 2030: ! 2031: I8xPrint(( ! 2032: 1, ! 2033: "I8042PRT-I8xSetDataQueuePointer: Okay to log keyboard overflow\n" ! 2034: )); ! 2035: deviceExtension->KeyboardExtension.OkayToLogOverflow = TRUE; ! 2036: } ! 2037: I8xPrint(( ! 2038: 3, ! 2039: "I8042PRT-I8xSetDataQueuePointer: new keyboard DataOut 0x%x, InputCount %d\n", ! 2040: deviceExtension->KeyboardExtension.DataOut, ! 2041: deviceExtension->KeyboardExtension.InputCount ! 2042: )); ! 2043: } else if (deviceType == MouseDeviceType) { ! 2044: I8xPrint(( ! 2045: 3, ! 2046: "I8042PRT-I8xSetDataQueuePointer: old mouse DataOut 0x%x, InputCount %d\n", ! 2047: deviceExtension->MouseExtension.DataOut, ! 2048: deviceExtension->MouseExtension.InputCount ! 2049: )); ! 2050: deviceExtension->MouseExtension.DataOut = ! 2051: ((PSET_DATA_POINTER_CONTEXT) Context)->DataOut; ! 2052: deviceExtension->MouseExtension.InputCount -= ! 2053: ((PSET_DATA_POINTER_CONTEXT) Context)->InputCount; ! 2054: if (deviceExtension->MouseExtension.InputCount == 0) { ! 2055: ! 2056: // ! 2057: // Reset the flag that determines whether it is time to log ! 2058: // queue overflow errors. We don't want to log errors too often. ! 2059: // Instead, log an error on the first overflow that occurs after ! 2060: // the ring buffer has been emptied, and then stop logging errors ! 2061: // until it gets cleared out and overflows again. ! 2062: // ! 2063: ! 2064: I8xPrint(( ! 2065: 1, ! 2066: "I8042PRT-I8xSetDataQueuePointer: Okay to log mouse overflow\n" ! 2067: )); ! 2068: deviceExtension->MouseExtension.OkayToLogOverflow = TRUE; ! 2069: } ! 2070: I8xPrint(( ! 2071: 3, ! 2072: "I8042PRT-I8xSetDataQueuePointer: new mouse DataOut 0x%x, InputCount %d\n", ! 2073: deviceExtension->MouseExtension.DataOut, ! 2074: deviceExtension->MouseExtension.InputCount ! 2075: )); ! 2076: } else { ! 2077: ASSERT(FALSE); ! 2078: } ! 2079: ! 2080: I8xPrint((3,"I8042PRT-I8xSetDataQueuePointer: exit\n")); ! 2081: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.