Annotation of ntddk/src/input/i8042prt/i8042cmn.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.