Annotation of ntddk/src/input/i8042prt/i8042dep.c, revision 1.1.1.1

1.1       root        1: 
                      2: /*++
                      3: 
                      4: Copyright (c) 1990, 1991, 1992, 1993  Microsoft Corporation
                      5: 
                      6: Module Name:
                      7: 
                      8:     i8042dep.c
                      9: 
                     10: Abstract:
                     11: 
                     12:     The initialization and hardware-dependent portions of
                     13:     the Intel i8042 port driver which are common to both
                     14:     the keyboard and the auxiliary (PS/2 mouse) device.  
                     15: 
                     16: Environment:
                     17: 
                     18:     Kernel mode only.
                     19: 
                     20: Notes:
                     21: 
                     22:     NOTES:  (Future/outstanding issues)
                     23: 
                     24:     - Powerfail not implemented.
                     25: 
                     26:     - Consolidate duplicate code, where possible and appropriate.
                     27: 
                     28:     - There is code ifdef'ed out (#if 0).  This code was intended to
                     29:       disable the device by setting the correct disable bit in the CCB.
                     30:       It is supposedly correct to disable the device prior to sending a
                     31:       command that will cause output to end up in the 8042 output buffer
                     32:       (thereby possibly trashing something that was already in the output
                     33:       buffer).  Unfortunately, on rev K8 of the AMI 8042, disabling the
                     34:       device where we do caused some commands to timeout, because
                     35:       the keyboard was unable to return the expected bytes.  Interestingly, 
                     36:       AMI claim that the device is only really disabled until the next ACK 
                     37:       comes back.  
                     38: 
                     39: Revision History:
                     40: 
                     41: --*/
                     42: 
                     43: #include "stdarg.h"
                     44: #include "stdio.h"
                     45: #include "string.h"
                     46: #include "ntddk.h"
                     47: #include "i8042prt.h"
                     48: #include "i8042log.h"
                     49: 
                     50: //
                     51: // Use the alloc_text pragma to specify the driver initialization routines
                     52: // (they can be paged out).
                     53: //
                     54: 
                     55: #ifdef ALLOC_PRAGMA
                     56: #pragma alloc_text(init,DriverEntry)
                     57: #pragma alloc_text(init,I8xServiceParameters)
                     58: #pragma alloc_text(init,I8xBuildResourceList)
                     59: #pragma alloc_text(init,I8xInitializeHardware)
                     60: #endif
                     61: 
                     62: 
                     63: NTSTATUS
                     64: DriverEntry(
                     65:     IN PDRIVER_OBJECT DriverObject,
                     66:     IN PUNICODE_STRING RegistryPath
                     67:     )
                     68: 
                     69: /*++
                     70: 
                     71: Routine Description:
                     72: 
                     73:     This routine initializes the i8042 keyboard/mouse port driver.
                     74: 
                     75: Arguments:
                     76: 
                     77:     DriverObject - Pointer to driver object created by system.
                     78: 
                     79:     RegistryPath - Pointer to the Unicode name of the registry path
                     80:         for this driver.
                     81: 
                     82: Return Value:
                     83: 
                     84:     The function value is the final status from the initialization operation.
                     85: 
                     86: --*/
                     87: 
                     88: {
                     89:     PDEVICE_OBJECT portDeviceObject = NULL;
                     90:     PDEVICE_EXTENSION deviceExtension = NULL;
                     91:     DEVICE_EXTENSION tmpDeviceExtension;
                     92:     NTSTATUS status = STATUS_SUCCESS;
                     93:     KIRQL coordinatorIrql = 0;
                     94:     I8042_INITIALIZE_DATA_CONTEXT initializeDataContext;
                     95:     ULONG keyboardInterruptVector;
                     96:     ULONG mouseInterruptVector;
                     97:     KIRQL keyboardInterruptLevel;
                     98:     KIRQL mouseInterruptLevel;
                     99:     KAFFINITY keyboardAffinity;
                    100:     KAFFINITY mouseAffinity;
                    101:     ULONG addressSpace;
                    102:     PHYSICAL_ADDRESS cardAddress;
                    103:     PIO_ERROR_LOG_PACKET errorLogEntry;
                    104:     ULONG uniqueErrorValue;
                    105:     NTSTATUS errorCode = STATUS_SUCCESS;
                    106:     ULONG dumpCount = 0;
                    107:     PCM_RESOURCE_LIST resources = NULL;
                    108:     ULONG resourceListSize = 0;
                    109:     BOOLEAN conflictDetected;
                    110:     ULONG i;
                    111:     UNICODE_STRING fullKeyboardName;
                    112:     UNICODE_STRING fullPointerName;
                    113:     UNICODE_STRING baseKeyboardName;
                    114:     UNICODE_STRING basePointerName;
                    115:     UNICODE_STRING deviceNameSuffix;
                    116:     UNICODE_STRING resourceDeviceClass;
                    117:     UNICODE_STRING registryPath;
                    118: 
                    119: #define NAME_MAX 256
                    120:     WCHAR keyboardBuffer[NAME_MAX];
                    121:     WCHAR pointerBuffer[NAME_MAX];
                    122: 
                    123: #define DUMP_COUNT 4
                    124:     ULONG dumpData[DUMP_COUNT];
                    125: 
                    126:     I8xPrint((1,"\n\nI8042PRT-I8042Initialize: enter\n"));
                    127: 
                    128:     //
                    129:     // Zero-initialize various structures.
                    130:     //
                    131: 
                    132:     RtlZeroMemory(&tmpDeviceExtension, sizeof(DEVICE_EXTENSION));
                    133:     for (i = 0; i < DUMP_COUNT; i++)
                    134:         dumpData[i] = 0;
                    135: 
                    136:     fullKeyboardName.MaximumLength = 0;
                    137:     fullKeyboardName.Length = 0;
                    138:     fullPointerName.MaximumLength = 0;
                    139:     fullPointerName.Length = 0;
                    140:     deviceNameSuffix.MaximumLength = 0;
                    141:     deviceNameSuffix.Length = 0;
                    142:     resourceDeviceClass.MaximumLength = 0;
                    143:     resourceDeviceClass.Length = 0;
                    144:     registryPath.MaximumLength = 0;
                    145: 
                    146:     RtlZeroMemory(keyboardBuffer, NAME_MAX * sizeof(WCHAR));
                    147:     baseKeyboardName.Buffer = keyboardBuffer;
                    148:     baseKeyboardName.Length = 0;
                    149:     baseKeyboardName.MaximumLength = NAME_MAX * sizeof(WCHAR);
                    150: 
                    151:     RtlZeroMemory(pointerBuffer, NAME_MAX * sizeof(WCHAR));
                    152:     basePointerName.Buffer = pointerBuffer;
                    153:     basePointerName.Length = 0;
                    154:     basePointerName.MaximumLength = NAME_MAX * sizeof(WCHAR);
                    155: 
                    156:     //
                    157:     // Need to ensure that the registry path is null-terminated.
                    158:     // Allocate pool to hold a null-terminated copy of the path.
                    159:     //
                    160: 
                    161:     registryPath.Buffer = ExAllocatePool(
                    162:                               PagedPool,
                    163:                               RegistryPath->Length + sizeof(UNICODE_NULL)
                    164:                               );
                    165: 
                    166:     if (!registryPath.Buffer) {
                    167:         I8xPrint((
                    168:             1,
                    169:             "I8042PRT-I8042Initialize: Couldn't allocate pool for registry path\n"
                    170:             ));
                    171: 
                    172:         status = STATUS_UNSUCCESSFUL;
                    173:         errorCode = I8042_INSUFFICIENT_RESOURCES;
                    174:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 2;
                    175:         dumpData[0] = (ULONG) RegistryPath->Length + sizeof(UNICODE_NULL);
                    176:         dumpCount = 1;
                    177:         goto I8042InitializeExit;
                    178: 
                    179:     } else {
                    180: 
                    181:         registryPath.Length = RegistryPath->Length + sizeof(UNICODE_NULL);
                    182:         registryPath.MaximumLength = registryPath.Length;
                    183: 
                    184:         RtlZeroMemory(
                    185:             registryPath.Buffer,
                    186:             registryPath.Length
                    187:                 );
                    188: 
                    189:         RtlMoveMemory(
                    190:             registryPath.Buffer,
                    191:             RegistryPath->Buffer,
                    192:             RegistryPath->Length
                    193:             );
                    194: 
                    195:     }
                    196: 
                    197:     //
                    198:     // Get the configuration information for this driver.
                    199:     //
                    200: 
                    201:     I8xKeyboardConfiguration(
                    202:         &tmpDeviceExtension, 
                    203:         &registryPath, 
                    204:         &baseKeyboardName,
                    205:         &basePointerName
                    206:         );
                    207: 
                    208:     I8xMouseConfiguration(
                    209:         &tmpDeviceExtension, 
                    210:         &registryPath, 
                    211:         &baseKeyboardName,
                    212:         &basePointerName
                    213:         );
                    214: 
                    215:     if (tmpDeviceExtension.HardwarePresent == 0) {
                    216: 
                    217:         //
                    218:         // There is neither a keyboard nor a mouse attached.  Free
                    219:         // resources and return with unsuccessful status.
                    220:         //
                    221: 
                    222:         I8xPrint((1,"I8042PRT-I8042Initialize: No keyboard/mouse attached.\n"));
                    223:         status = STATUS_NO_SUCH_DEVICE;
                    224:         errorCode = I8042_NO_SUCH_DEVICE;
                    225:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 4;
                    226:         goto I8042InitializeExit;
                    227: 
                    228:     } else if (!(tmpDeviceExtension.HardwarePresent & KEYBOARD_HARDWARE_PRESENT)) {
                    229:         //
                    230:         // Log a warning about the missing keyboard later on, but 
                    231:         // continue processing.
                    232:         //
                    233: 
                    234:         I8xPrint((1,"I8042PRT-I8042Initialize: No keyboard attached.\n"));
                    235:         status = STATUS_NO_SUCH_DEVICE;
                    236:         errorCode = I8042_NO_KBD_DEVICE;
                    237:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 5;
                    238:         dumpCount = 0;
                    239: 
                    240:     } 
                    241: #if 0
                    242:     //
                    243:     // This code was removed so that we don't log an error when the mouse
                    244:     // is not present.  It was annoying to those who did not have 
                    245:     // PS/2 compatible mice to get the informational message on every boot.
                    246:     //
                    247: 
                    248:     else if (!(tmpDeviceExtension.HardwarePresent & MOUSE_HARDWARE_PRESENT)) {
                    249: 
                    250:         //
                    251:         // Log a warning about the missing mouse later on, but 
                    252:         // continue processing.
                    253:         //
                    254: 
                    255:         I8xPrint((1,"I8042PRT-I8042Initialize: No mouse attached.\n"));
                    256:         status = STATUS_NO_SUCH_DEVICE;
                    257:         errorCode = I8042_NO_MOU_DEVICE;
                    258:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 6;
                    259:         dumpCount = 0;
                    260:     }
                    261: #endif
                    262: 
                    263:     //
                    264:     // Set up space for the port's device object suffix.  Note that
                    265:     // we overallocate space for the suffix string because it is much
                    266:     // easier than figuring out exactly how much space is required.
                    267:     // The storage gets freed at the end of driver initialization, so
                    268:     // who cares...
                    269:     //
                    270: 
                    271:     RtlInitUnicodeString(
                    272:         &deviceNameSuffix,
                    273:         NULL
                    274:         );
                    275:     
                    276:     deviceNameSuffix.MaximumLength = 
                    277:         (KEYBOARD_PORTS_MAXIMUM > POINTER_PORTS_MAXIMUM)?
                    278:             KEYBOARD_PORTS_MAXIMUM * sizeof(WCHAR): 
                    279:             POINTER_PORTS_MAXIMUM * sizeof(WCHAR);
                    280:     deviceNameSuffix.MaximumLength += sizeof(UNICODE_NULL);
                    281:     
                    282:     deviceNameSuffix.Buffer = ExAllocatePool(
                    283:                                   PagedPool,
                    284:                                   deviceNameSuffix.MaximumLength
                    285:                                   );
                    286:     
                    287:     if (!deviceNameSuffix.Buffer) {
                    288:     
                    289:         I8xPrint((
                    290:             1,
                    291:             "I8042PRT-I8042Initialize: Couldn't allocate string for device object suffix\n"
                    292:             ));
                    293:     
                    294:         status = STATUS_UNSUCCESSFUL;
                    295:         errorCode = I8042_INSUFFICIENT_RESOURCES;
                    296:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 8;
                    297:         dumpData[0] = (ULONG) deviceNameSuffix.MaximumLength;
                    298:         dumpCount = 1;
                    299:         goto I8042InitializeExit;
                    300:     
                    301:     }
                    302: 
                    303:     RtlZeroMemory(
                    304:         deviceNameSuffix.Buffer,
                    305:         deviceNameSuffix.MaximumLength
                    306:         );
                    307: 
                    308:     //
                    309:     // Set up space for the port's full keyboard device object name.  
                    310:     //
                    311: 
                    312:     RtlInitUnicodeString(
                    313:         &fullKeyboardName,
                    314:         NULL
                    315:         );
                    316:     
                    317:     fullKeyboardName.MaximumLength = sizeof(L"\\Device\\") +
                    318:                                       baseKeyboardName.Length +
                    319:                                       deviceNameSuffix.MaximumLength;
                    320:                                       
                    321:     
                    322:     fullKeyboardName.Buffer = ExAllocatePool(
                    323:                                   PagedPool,
                    324:                                   fullKeyboardName.MaximumLength
                    325:                                   );
                    326:     
                    327:     if (!fullKeyboardName.Buffer) {
                    328:     
                    329:         I8xPrint((
                    330:             1,
                    331:             "I8042PRT-I8042Initialize: Couldn't allocate string for keyboard device object name\n"
                    332:             ));
                    333:     
                    334:         status = STATUS_UNSUCCESSFUL;
                    335:         errorCode = I8042_INSUFFICIENT_RESOURCES;
                    336:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 10;
                    337:         dumpData[0] = (ULONG) fullKeyboardName.MaximumLength;
                    338:         dumpCount = 1;
                    339:         goto I8042InitializeExit;
                    340:     
                    341:     }
                    342: 
                    343:     RtlZeroMemory(
                    344:         fullKeyboardName.Buffer,
                    345:         fullKeyboardName.MaximumLength
                    346:         );
                    347:     RtlAppendUnicodeToString(
                    348:         &fullKeyboardName,
                    349:         L"\\Device\\"
                    350:         );
                    351:     RtlAppendUnicodeToString(
                    352:         &fullKeyboardName,
                    353:         baseKeyboardName.Buffer
                    354:         );
                    355: 
                    356:     for (i = 0; i < KEYBOARD_PORTS_MAXIMUM; i++) {
                    357:     
                    358:         //
                    359:         // Append the suffix to the device object name string.  E.g., turn
                    360:         // \Device\KeyboardPort into \Device\KeyboardPort0.  Then we attempt
                    361:         // to create the device object.  If the device object already
                    362:         // exists (because it was already created by another port driver),
                    363:         // increment the suffix and try again.
                    364:         //
                    365: 
                    366:         status = RtlIntegerToUnicodeString(
                    367:                      i,
                    368:                      10,
                    369:                      &deviceNameSuffix
                    370:                      );
                    371: 
                    372:         if (!NT_SUCCESS(status)) {
                    373:             break; 
                    374:         }
                    375: 
                    376:         RtlAppendUnicodeStringToString(
                    377:             &fullKeyboardName,
                    378:             &deviceNameSuffix
                    379:         );
                    380: 
                    381:         I8xPrint((
                    382:             1,
                    383:             "I8042PRT-I8042Initialize: Creating device object named %ws\n",
                    384:             fullKeyboardName.Buffer
                    385:             ));
                    386: 
                    387:         //
                    388:         // Create device object for the i8042 keyboard port device.
                    389:         // Note that we specify that this is a non-exclusive device.
                    390:         // User code will be able to open this device, but they cannot
                    391:         // do any real harm because all the device controls are internal
                    392:         // device controls (and thus not accessible from user code).
                    393:         //
                    394: 
                    395:         status = IoCreateDevice(
                    396:                     DriverObject,
                    397:                     sizeof(DEVICE_EXTENSION),
                    398:                     &fullKeyboardName,
                    399:                     FILE_DEVICE_8042_PORT,
                    400:                     0,
                    401:                     FALSE,
                    402:                     &portDeviceObject
                    403:                     );
                    404: 
                    405:         if (NT_SUCCESS(status)) {
                    406: 
                    407:             //
                    408:             // We've successfully created a device object.
                    409:             //
                    410: 
                    411:             break; 
                    412:         } else {
                    413: 
                    414:            //
                    415:            // We'll increment the suffix and try again.  Note that we reset
                    416:            // the length of the string here to get back to the beginning
                    417:            // of the suffix portion of the name.  Do not bother to
                    418:            // zero the suffix, though, because the string for the 
                    419:            // incremented suffix will be at least as long as the previous
                    420:            // one.
                    421:            //
                    422: 
                    423:            fullKeyboardName.Length -= deviceNameSuffix.Length;
                    424:         }
                    425:     }
                    426: 
                    427:     if (!NT_SUCCESS(status)) {
                    428:         I8xPrint((
                    429:             1,
                    430:             "I8042PRT-I8042Initialize: Could not create port device object = %ws\n",
                    431:             fullKeyboardName.Buffer
                    432:             ));
                    433:         errorCode = I8042_INSUFFICIENT_RESOURCES;
                    434:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 12;
                    435:         dumpData[0] = (ULONG) i;
                    436:         dumpCount = 1;
                    437:         goto I8042InitializeExit;
                    438:     } 
                    439: 
                    440:     //
                    441:     // Set up the device extension.
                    442:     //
                    443: 
                    444:     deviceExtension =
                    445:         (PDEVICE_EXTENSION)portDeviceObject->DeviceExtension;
                    446:     *deviceExtension = tmpDeviceExtension;
                    447:     deviceExtension->DeviceObject = portDeviceObject;
                    448: 
                    449:     //
                    450:     // Set up the resource list prior to reporting resource usage.
                    451:     //
                    452: 
                    453:     I8xBuildResourceList(deviceExtension, &resources, &resourceListSize);
                    454: 
                    455:     //
                    456:     // Set up space for the resource device class name.  
                    457:     //
                    458: 
                    459:     RtlInitUnicodeString(
                    460:         &resourceDeviceClass,
                    461:         NULL
                    462:         );
                    463:     
                    464:     resourceDeviceClass.MaximumLength = baseKeyboardName.Length +
                    465:                                         sizeof(L"/") +
                    466:                                         basePointerName.Length;
                    467:     
                    468:     resourceDeviceClass.Buffer = ExAllocatePool(
                    469:                                      PagedPool,
                    470:                                      resourceDeviceClass.MaximumLength
                    471:                                   );
                    472:     
                    473:     if (!resourceDeviceClass.Buffer) {
                    474:     
                    475:         I8xPrint((
                    476:             1,
                    477:             "I8042PRT-I8042Initialize: Couldn't allocate string for resource device class name\n"
                    478:             ));
                    479:     
                    480:         status = STATUS_UNSUCCESSFUL;
                    481:         errorCode = I8042_INSUFFICIENT_RESOURCES;
                    482:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 15;
                    483:         dumpData[0] = (ULONG) resourceDeviceClass.MaximumLength;
                    484:         dumpCount = 1;
                    485:         goto I8042InitializeExit;
                    486:     
                    487:     }
                    488: 
                    489:     //
                    490:     // Form the resource device class name from both the keyboard and
                    491:     // the pointer base device names.
                    492:     //
                    493: 
                    494:     RtlZeroMemory(
                    495:         resourceDeviceClass.Buffer,
                    496:         resourceDeviceClass.MaximumLength
                    497:         );
                    498:     RtlAppendUnicodeStringToString(
                    499:         &resourceDeviceClass,
                    500:         &baseKeyboardName
                    501:         );
                    502:     RtlAppendUnicodeToString(
                    503:         &resourceDeviceClass,
                    504:         L"/"
                    505:         );
                    506:     RtlAppendUnicodeStringToString(
                    507:         &resourceDeviceClass,
                    508:         &basePointerName
                    509:         );
                    510: 
                    511:     //
                    512:     // Report resource usage for the registry.
                    513:     //
                    514: 
                    515: 
                    516:     IoReportResourceUsage(
                    517:         &resourceDeviceClass, 
                    518:         DriverObject,
                    519:         NULL,
                    520:         0,
                    521:         portDeviceObject,
                    522:         resources, 
                    523:         resourceListSize,
                    524:         FALSE,
                    525:         &conflictDetected
                    526:         );
                    527: 
                    528:     if (conflictDetected) {
                    529: 
                    530:         //
                    531:         // Some other device already owns the i8042 ports or interrupts.
                    532:         // Fatal error.
                    533:         //
                    534: 
                    535:         I8xPrint((
                    536:             1,
                    537:             "I8042PRT-I8042Initialize: Resource usage conflict\n"
                    538:             ));
                    539: 
                    540:         //
                    541:         // Set up error log info.
                    542:         //
                    543: 
                    544:         errorCode = I8042_RESOURCE_CONFLICT;
                    545:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 20;
                    546:         dumpData[0] =  (ULONG) 
                    547:             resources->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Level;
                    548:         dumpData[1] = (ULONG)
                    549:             resources->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Level;
                    550:         dumpData[2] = (ULONG)
                    551:             resources->List[0].PartialResourceList.PartialDescriptors[2].u.Interrupt.Level;
                    552:         dumpData[3] = (ULONG)
                    553:             resources->List[0].PartialResourceList.PartialDescriptors[3].u.Interrupt.Level;
                    554:         dumpCount = 4;
                    555: 
                    556:         goto I8042InitializeExit;
                    557: 
                    558:     }
                    559: 
                    560:     //
                    561:     // Map the i8042 controller registers.
                    562:     //
                    563: 
                    564:     for (i = 0; i < deviceExtension->Configuration.PortListCount; i++) {
                    565: 
                    566:         addressSpace = (deviceExtension->Configuration.PortList[i].Flags 
                    567:                            & CM_RESOURCE_PORT_IO) == CM_RESOURCE_PORT_IO? 1:0;
                    568: 
                    569:         HalTranslateBusAddress(
                    570:             deviceExtension->Configuration.InterfaceType,
                    571:             deviceExtension->Configuration.BusNumber,
                    572:             deviceExtension->Configuration.PortList[i].u.Port.Start,
                    573:             &addressSpace,
                    574:             &cardAddress
                    575:         );
                    576: 
                    577:         if (!addressSpace) {
                    578: 
                    579:             deviceExtension->UnmapRegistersRequired = TRUE;
                    580:             deviceExtension->DeviceRegisters[i] = 
                    581:                 MmMapIoSpace(
                    582:                     cardAddress,
                    583:                     deviceExtension->Configuration.PortList[i].u.Port.Length,
                    584:                     FALSE
                    585:                     );
                    586: 
                    587:         } else {
                    588: 
                    589:             deviceExtension->UnmapRegistersRequired = FALSE;
                    590:             deviceExtension->DeviceRegisters[i] = (PVOID)cardAddress.LowPart;
                    591: 
                    592:         }
                    593:    
                    594:         if (!deviceExtension->DeviceRegisters[i]) {
                    595: 
                    596:             I8xPrint((
                    597:                 1, 
                    598:                 "I8042PRT-I8042Initialize: Couldn't map the device registers.\n"
                    599:                 ));
                    600:             status = STATUS_NONE_MAPPED;
                    601: 
                    602:             //
                    603:             // Set up error log info.
                    604:             //
                    605: 
                    606:             errorCode = I8042_REGISTERS_NOT_MAPPED;
                    607:             uniqueErrorValue = I8042_ERROR_VALUE_BASE + 30;
                    608:             dumpData[0] = cardAddress.LowPart;
                    609:             dumpCount = 1;
                    610: 
                    611:             goto I8042InitializeExit;
                    612: 
                    613:         }
                    614:     }
                    615: 
                    616:     //
                    617:     // Do buffered I/O.
                    618:     //
                    619: 
                    620:     portDeviceObject->Flags |= DO_BUFFERED_IO;
                    621: 
                    622:     //
                    623:     // Initialize the 8042 hardware to default values for the keyboard and
                    624:     // mouse.
                    625:     //
                    626: 
                    627:     I8xInitializeHardware(portDeviceObject);
                    628: 
                    629:     //
                    630:     // Initialize shared spinlock used to synchronize access to the
                    631:     // i8042 controller, keyboard, and mouse.
                    632:     //
                    633: 
                    634:     KeInitializeSpinLock(&(deviceExtension->SharedInterruptSpinLock));
                    635: 
                    636:     //
                    637:     // Allocate ring buffers for the keyboard and/or mouse input data.
                    638:     //
                    639: 
                    640:     if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
                    641: 
                    642:         //
                    643:         // Allocate memory for the keyboard data queue.
                    644:         //
                    645: 
                    646:         deviceExtension->KeyboardExtension.InputData = 
                    647:             ExAllocatePool(
                    648:                 NonPagedPool,
                    649:                 deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength
                    650:                 );
                    651: 
                    652:         if (!deviceExtension->KeyboardExtension.InputData) {
                    653:    
                    654:             //
                    655:             // Could not allocate memory for the keyboard data queue.
                    656:             //
                    657: 
                    658:             
                    659:             I8xPrint((
                    660:                 1,
                    661:                 "I8042PRT-I8042Initialize: Could not allocate keyboard input data queue\n"
                    662:                 ));
                    663: 
                    664:             status = STATUS_INSUFFICIENT_RESOURCES;
                    665: 
                    666:             //
                    667:             // Set up error log info.
                    668:             //
                    669:     
                    670:             errorCode = I8042_NO_BUFFER_ALLOCATED;
                    671:             uniqueErrorValue = I8042_ERROR_VALUE_BASE + 50;
                    672:             dumpData[0] = 
                    673:                 deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength;
                    674:             dumpCount = 1;
                    675: 
                    676:             goto I8042InitializeExit;
                    677:         }
                    678: 
                    679:         deviceExtension->KeyboardExtension.DataEnd =
                    680:             (PKEYBOARD_INPUT_DATA) 
                    681:             ((PCHAR) (deviceExtension->KeyboardExtension.InputData) 
                    682:                  + deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength);
                    683: 
                    684:         //
                    685:         // Zero the keyboard input data ring buffer.
                    686:         //
                    687: 
                    688:         RtlZeroMemory(
                    689:             deviceExtension->KeyboardExtension.InputData, 
                    690:             deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength
                    691:             );
                    692: 
                    693:     }
                    694:     
                    695:     if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
                    696: 
                    697:         //
                    698:         // Set up space for the port's full pointer device object name.  
                    699:         //
                    700:     
                    701:         RtlInitUnicodeString(
                    702:             &fullPointerName,
                    703:             NULL
                    704:             );
                    705:         
                    706:         fullPointerName.MaximumLength = sizeof(L"\\Device\\") +
                    707:                                         basePointerName.Length +
                    708:                                         deviceNameSuffix.MaximumLength;
                    709:                                           
                    710:         
                    711:         fullPointerName.Buffer = ExAllocatePool(
                    712:                                      PagedPool,
                    713:                                      fullPointerName.MaximumLength
                    714:                                       );
                    715:         
                    716:         if (!fullPointerName.Buffer) {
                    717:         
                    718:             I8xPrint((
                    719:                 1,
                    720:                 "I8042PRT-I8042Initialize: Couldn't allocate string for pointer device object name\n"
                    721:                 ));
                    722:         
                    723:             status = STATUS_UNSUCCESSFUL;
                    724:             goto I8042InitializeExit;
                    725:         
                    726:         }
                    727:     
                    728:         RtlZeroMemory(
                    729:             fullPointerName.Buffer,
                    730:             fullPointerName.MaximumLength
                    731:             );
                    732:         RtlAppendUnicodeToString(
                    733:             &fullPointerName,
                    734:             L"\\Device\\"
                    735:             );
                    736:         RtlAppendUnicodeToString(
                    737:             &fullPointerName,
                    738:             basePointerName.Buffer
                    739:             );
                    740: 
                    741:         RtlZeroMemory(
                    742:             deviceNameSuffix.Buffer,
                    743:             deviceNameSuffix.MaximumLength
                    744:             );
                    745:         deviceNameSuffix.Length = 0;
                    746:     
                    747:         for (i = 0; i < POINTER_PORTS_MAXIMUM; i++) {
                    748:         
                    749:             //
                    750:             // Append the suffix to the device object name string.  E.g., turn
                    751:             // \Device\PointerPort into \Device\PointerPort0.  Then we attempt
                    752:             // to create a symbolic link to the keyboard device object.  If 
                    753:             // a device object with the symbolic link name already
                    754:             // exists (because it was created by another port driver),
                    755:             // increment the suffix and try again.
                    756:             //
                    757:     
                    758:             status = RtlIntegerToUnicodeString(
                    759:                          i,
                    760:                          10,
                    761:                          &deviceNameSuffix
                    762:                          );
                    763:     
                    764:             if (!NT_SUCCESS(status)) {
                    765:                 break; 
                    766:             }
                    767:     
                    768:             RtlAppendUnicodeStringToString(
                    769:                 &fullPointerName,
                    770:                 &deviceNameSuffix
                    771:             );
                    772:     
                    773:             I8xPrint((
                    774:                 1,
                    775:                 "I8042PRT-I8042Initialize: pointer port name (symbolic link) = %ws\n", 
                    776:                 fullPointerName.Buffer
                    777:                 ));
                    778:     
                    779:             //
                    780:             // Set up a symbolic link so that the keyboard and mouse class 
                    781:             // drivers can access the port device object by different names.
                    782:             //
                    783: 
                    784:             status = IoCreateSymbolicLink( 
                    785:                          &fullPointerName,
                    786:                          &fullKeyboardName 
                    787:                          );
                    788: 
                    789:             if (NT_SUCCESS(status)) {
                    790: 
                    791:                 //
                    792:                 // We've successfully created a symbolic link.
                    793:                 //
                    794: 
                    795:                 break;
                    796: 
                    797:             } else {
                    798:     
                    799:                //
                    800:                // We'll increment the suffix and try again.  Note that we reset
                    801:                // the length of the string here to get back to the beginning
                    802:                // of the suffix portion of the name.  Do not bother to
                    803:                // zero the suffix, though, because the string for the 
                    804:                // incremented suffix will be at least as long as the previous
                    805:                // one.
                    806:                //
                    807:     
                    808:                fullPointerName.Length -= deviceNameSuffix.Length;
                    809:             }
                    810:         }
                    811:     
                    812:         if (!NT_SUCCESS(status)) {
                    813:             I8xPrint((
                    814:                 1,
                    815:                 "I8042PRT-I8042Initialize: Could not create symbolic link = %ws\n",
                    816:                 fullPointerName.Buffer
                    817:                 ));
                    818:             goto I8042InitializeExit;
                    819:         } 
                    820:     
                    821:         //
                    822:         // Allocate memory for the mouse data queue.
                    823:         //
                    824: 
                    825:         deviceExtension->MouseExtension.InputData = 
                    826:             ExAllocatePool(
                    827:                 NonPagedPool,
                    828:                 deviceExtension->Configuration.MouseAttributes.InputDataQueueLength
                    829:                 );
                    830: 
                    831:         if (!deviceExtension->MouseExtension.InputData) {
                    832:    
                    833:             //
                    834:             // Could not allocate memory for the mouse data queue.
                    835:             //
                    836: 
                    837:             I8xPrint((
                    838:                 1,
                    839:                 "I8042PRT-I8042Initialize: Could not allocate mouse input data queue\n"
                    840:                 ));
                    841: 
                    842:             status = STATUS_INSUFFICIENT_RESOURCES;
                    843: 
                    844:             //
                    845:             // Set up error log info.
                    846:             //
                    847:     
                    848:             errorCode = I8042_NO_BUFFER_ALLOCATED;
                    849:             uniqueErrorValue = I8042_ERROR_VALUE_BASE + 60;
                    850:             dumpData[0] = 
                    851:                 deviceExtension->Configuration.MouseAttributes.InputDataQueueLength;
                    852:             dumpCount = 1;
                    853: 
                    854:             goto I8042InitializeExit;
                    855:         }
                    856: 
                    857:         deviceExtension->MouseExtension.DataEnd =
                    858:             (PMOUSE_INPUT_DATA) 
                    859:             ((PCHAR) (deviceExtension->MouseExtension.InputData) 
                    860:                  + deviceExtension->Configuration.MouseAttributes.InputDataQueueLength);
                    861: 
                    862:         //
                    863:         // Zero the mouse input data ring buffer.
                    864:         //
                    865: 
                    866:         RtlZeroMemory(
                    867:             deviceExtension->MouseExtension.InputData, 
                    868:             deviceExtension->Configuration.MouseAttributes.InputDataQueueLength
                    869:             );
                    870: 
                    871:     }
                    872: 
                    873:     //
                    874:     // Initialize the connection data.
                    875:     //
                    876: 
                    877:     deviceExtension->KeyboardExtension.ConnectData.ClassDeviceObject = NULL;
                    878:     deviceExtension->KeyboardExtension.ConnectData.ClassService = NULL;
                    879:     deviceExtension->MouseExtension.ConnectData.ClassDeviceObject = NULL;
                    880:     deviceExtension->MouseExtension.ConnectData.ClassService = NULL;
                    881: 
                    882:     //
                    883:     // Initialize the input data queues.
                    884:     //
                    885: 
                    886:     initializeDataContext.DeviceExtension = deviceExtension;
                    887:     initializeDataContext.DeviceType = KeyboardDeviceType;
                    888:     I8xInitializeDataQueue((PVOID) &initializeDataContext);
                    889: 
                    890:     initializeDataContext.DeviceType = MouseDeviceType;
                    891:     I8xInitializeDataQueue((PVOID) &initializeDataContext);
                    892: 
                    893:     //
                    894:     // Initialize the port completion DPC object in the device extension.
                    895:     // This DPC routine handles the completion of successful set requests.
                    896:     //
                    897: 
                    898:     deviceExtension->DpcInterlockKeyboard = -1;
                    899:     deviceExtension->DpcInterlockMouse = -1;
                    900:     IoInitializeDpcRequest(portDeviceObject, I8042CompletionDpc);
                    901: 
                    902:     //
                    903:     // Initialize the port completion DPC for requests that exceed the
                    904:     // maximum number of retries.
                    905:     //
                    906: 
                    907:     KeInitializeDpc(
                    908:         &deviceExtension->RetriesExceededDpc,
                    909:         (PKDEFERRED_ROUTINE) I8042RetriesExceededDpc,
                    910:         portDeviceObject
                    911:         );
                    912: 
                    913:     //
                    914:     // Initialize the port DPC queue to log overrun and internal
                    915:     // driver errors.
                    916:     //
                    917: 
                    918:     KeInitializeDpc(
                    919:         &deviceExtension->ErrorLogDpc,
                    920:         (PKDEFERRED_ROUTINE) I8042ErrorLogDpc,
                    921:         portDeviceObject
                    922:         );
                    923: 
                    924:     //
                    925:     // Initialize the port keyboard ISR DPC and mouse ISR DPC.  The ISR DPC
                    926:     // is responsible for calling the connected class driver's callback
                    927:     // routine to process the input data queue.
                    928:     //
                    929: 
                    930:     KeInitializeDpc(
                    931:         &deviceExtension->KeyboardIsrDpc,
                    932:         (PKDEFERRED_ROUTINE) I8042KeyboardIsrDpc,
                    933:         portDeviceObject
                    934:         );
                    935: 
                    936:     KeInitializeDpc(
                    937:         &deviceExtension->KeyboardIsrDpcRetry,
                    938:         (PKDEFERRED_ROUTINE) I8042KeyboardIsrDpc,
                    939:         portDeviceObject
                    940:         );
                    941: 
                    942:     KeInitializeDpc(
                    943:         &deviceExtension->MouseIsrDpc,
                    944:         (PKDEFERRED_ROUTINE) I8042MouseIsrDpc,
                    945:         portDeviceObject
                    946:         );
                    947: 
                    948:     KeInitializeDpc(
                    949:         &deviceExtension->MouseIsrDpcRetry,
                    950:         (PKDEFERRED_ROUTINE) I8042MouseIsrDpc,
                    951:         portDeviceObject
                    952:         );
                    953: 
                    954:     //
                    955:     // Initialize the port DPC queue for timeouts. 
                    956:     //
                    957: 
                    958:     KeInitializeDpc(
                    959:         &deviceExtension->TimeOutDpc,
                    960:         (PKDEFERRED_ROUTINE) I8042TimeOutDpc,
                    961:         portDeviceObject
                    962:         );
                    963: 
                    964:     //
                    965:     // Initialize the i8042 command timer.
                    966:     //
                    967: 
                    968:     KeInitializeTimer(&deviceExtension->CommandTimer);
                    969:     deviceExtension->TimerCount = I8042_ASYNC_NO_TIMEOUT;
                    970: 
                    971:     //
                    972:     // Initialize the keyboard and mouse data consumption timers.
                    973:     //
                    974: 
                    975:     KeInitializeTimer(&deviceExtension->KeyboardExtension.DataConsumptionTimer);
                    976:     KeInitializeTimer(&deviceExtension->MouseExtension.DataConsumptionTimer);
                    977: 
                    978:     //
                    979:     // From the Hal, get the keyboard and mouse interrupt vectors and levels.
                    980:     //
                    981: 
                    982:     keyboardInterruptVector = HalGetInterruptVector(
                    983:                                  deviceExtension->Configuration.InterfaceType,
                    984:                                  deviceExtension->Configuration.BusNumber,
                    985:                                  deviceExtension->Configuration.KeyboardInterrupt.u.Interrupt.Level,
                    986:                                  deviceExtension->Configuration.KeyboardInterrupt.u.Interrupt.Vector,
                    987:                                  &keyboardInterruptLevel,
                    988:                                  &keyboardAffinity
                    989:                                  );
                    990: 
                    991:     mouseInterruptVector = HalGetInterruptVector(
                    992:                                deviceExtension->Configuration.InterfaceType,
                    993:                                deviceExtension->Configuration.BusNumber,
                    994:                                deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Level,
                    995:                                deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Vector,
                    996:                                &mouseInterruptLevel,
                    997:                                &mouseAffinity
                    998:                                );
                    999: 
                   1000:     //
                   1001:     // Determine the coordinator interrupt object 
                   1002:     // based on which device has the highest IRQL.
                   1003:     //
                   1004: 
                   1005:     if ((deviceExtension->HardwarePresent &
                   1006:         (KEYBOARD_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT)) ==
                   1007:         (KEYBOARD_HARDWARE_PRESENT | MOUSE_HARDWARE_PRESENT)) {
                   1008: 
                   1009:         coordinatorIrql = (keyboardInterruptLevel > mouseInterruptLevel) ?
                   1010:             keyboardInterruptLevel: mouseInterruptLevel;
                   1011:     }
                   1012: 
                   1013:     //
                   1014:     // Initialize and connect the interrupt object for the mouse.
                   1015:     // Determine the coordinator interrupt object based on which device
                   1016:     // has the highest IRQL.
                   1017:     //
                   1018: 
                   1019:     if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
                   1020: 
                   1021:         status = IoConnectInterrupt(
                   1022:                      &(deviceExtension->MouseInterruptObject),
                   1023:                      (PKSERVICE_ROUTINE) I8042MouseInterruptService,
                   1024:                      (PVOID) portDeviceObject,
                   1025:                      &(deviceExtension->SharedInterruptSpinLock),
                   1026:                      mouseInterruptVector,
                   1027:                      mouseInterruptLevel,
                   1028:                      (KIRQL) ((coordinatorIrql == (KIRQL)0) ?
                   1029:                           mouseInterruptLevel : coordinatorIrql),
                   1030:                      deviceExtension->Configuration.MouseInterrupt.Flags 
                   1031:                          == CM_RESOURCE_INTERRUPT_LATCHED ?
                   1032:                          Latched : LevelSensitive, 
                   1033:                      deviceExtension->Configuration.MouseInterrupt.ShareDisposition,
                   1034:                      mouseAffinity,
                   1035:                      deviceExtension->Configuration.FloatingSave
                   1036:                      );
                   1037: 
                   1038:         if (!NT_SUCCESS(status)) {
                   1039: 
                   1040:             //
                   1041:             // Failed to install.  Free up resources before exiting.
                   1042:             //
                   1043: 
                   1044:             I8xPrint((
                   1045:                 1,
                   1046:                 "I8042PRT-I8042Initialize: Could not connect mouse interrupt\n"
                   1047:                 ));
                   1048: 
                   1049:             //
                   1050:             // Set up error log info.
                   1051:             //
                   1052:     
                   1053:             errorCode = I8042_NO_INTERRUPT_CONNECTED;
                   1054:             uniqueErrorValue = I8042_ERROR_VALUE_BASE + 70;
                   1055:             dumpData[0] = mouseInterruptLevel;
                   1056:             dumpCount = 1;
                   1057: 
                   1058:             goto I8042InitializeExit;
                   1059: 
                   1060:         }
                   1061: 
                   1062:         //
                   1063:         // Enable mouse transmissions, now that the interrupts are enabled.
                   1064:         // We've held off transmissions until now, in an attempt to
                   1065:         // keep the driver's notion of mouse input data state in sync
                   1066:         // with the mouse hardware.
                   1067:         //
                   1068: 
                   1069:         status = I8xMouseEnableTransmission(portDeviceObject);
                   1070: 
                   1071:         if (!NT_SUCCESS(status)) {
                   1072: 
                   1073:             //
                   1074:             // Couldn't enable mouse transmissions.  Continue on, anyway.
                   1075:             //
                   1076: 
                   1077:             I8xPrint((
                   1078:                 1,
                   1079:                 "I8042PRT-I8042Initialize: Could not enable mouse transmission\n"
                   1080:                 ));
                   1081: 
                   1082:             status = STATUS_SUCCESS;
                   1083:         }
                   1084: 
                   1085:     }
                   1086: 
                   1087:     //
                   1088:     // Initialize and connect the interrupt object for the keyboard.
                   1089:     // Determine the coordinator interrupt object based on which device
                   1090:     // has the highest IRQL.
                   1091:     //
                   1092: 
                   1093:     if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
                   1094: 
                   1095:         status = IoConnectInterrupt(
                   1096:                      &(deviceExtension->KeyboardInterruptObject),
                   1097:                      (PKSERVICE_ROUTINE) I8042KeyboardInterruptService,
                   1098:                      (PVOID) portDeviceObject,
                   1099:                      &(deviceExtension->SharedInterruptSpinLock),
                   1100:                      keyboardInterruptVector,
                   1101:                      keyboardInterruptLevel,
                   1102:                      (KIRQL) ((coordinatorIrql == (KIRQL)0) ?
                   1103:                           keyboardInterruptLevel : coordinatorIrql),
                   1104:                      deviceExtension->Configuration.KeyboardInterrupt.Flags 
                   1105:                          == CM_RESOURCE_INTERRUPT_LATCHED ?
                   1106:                          Latched : LevelSensitive, 
                   1107:                      deviceExtension->Configuration.KeyboardInterrupt.ShareDisposition, 
                   1108:                      keyboardAffinity,
                   1109:                      deviceExtension->Configuration.FloatingSave
                   1110:                      );
                   1111: 
                   1112:         if (!NT_SUCCESS(status)) {
                   1113: 
                   1114:             //
                   1115:             // Failed to install.  Free up resources before exiting.
                   1116:             //
                   1117: 
                   1118:             I8xPrint((
                   1119:                 1,
                   1120:                 "I8042PRT-I8042Initialize: Could not connect keyboard interrupt\n"
                   1121:                 ));
                   1122: 
                   1123:             //
                   1124:             // Set up error log info.
                   1125:             //
                   1126:     
                   1127:             errorCode = I8042_NO_INTERRUPT_CONNECTED;
                   1128:             uniqueErrorValue = I8042_ERROR_VALUE_BASE + 80;
                   1129:             dumpData[0] = keyboardInterruptLevel; 
                   1130:             dumpCount = 1;
                   1131: 
                   1132:             goto I8042InitializeExit;
                   1133: 
                   1134:         }
                   1135: 
                   1136:     }
                   1137: 
                   1138:     //
                   1139:     // Once initialization is finished, load the device map information 
                   1140:     // into the registry so that setup can determine which pointer port
                   1141:     // and keyboard port are active.  
                   1142:     //
                   1143: 
                   1144:     if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
                   1145: 
                   1146:         status = RtlWriteRegistryValue(
                   1147:                      RTL_REGISTRY_DEVICEMAP,
                   1148:                      baseKeyboardName.Buffer,
                   1149:                      fullKeyboardName.Buffer,
                   1150:                      REG_SZ,
                   1151:                      registryPath.Buffer,
                   1152:                      registryPath.Length
                   1153:                      );
                   1154:     
                   1155:         if (!NT_SUCCESS(status)) {
                   1156:     
                   1157:             I8xPrint((
                   1158:                 1, 
                   1159:                 "I8042PRT-I8042Initialize: Could not store keyboard name in DeviceMap\n"
                   1160:                 ));
                   1161:     
                   1162:             errorCode = I8042_NO_DEVICEMAP_CREATED;
                   1163:             uniqueErrorValue = I8042_ERROR_VALUE_BASE + 90;
                   1164:             dumpCount = 0;
                   1165: 
                   1166:             goto I8042InitializeExit;
                   1167:     
                   1168:         } else {
                   1169:     
                   1170:             I8xPrint((
                   1171:                 1, 
                   1172:                 "I8042PRT-I8042Initialize: Stored keyboard name in DeviceMap\n"
                   1173:                 ));
                   1174:         }
                   1175:     }
                   1176: 
                   1177:     if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
                   1178: 
                   1179:         status = RtlWriteRegistryValue(
                   1180:                      RTL_REGISTRY_DEVICEMAP,
                   1181:                      basePointerName.Buffer,
                   1182:                      fullPointerName.Buffer,
                   1183:                      REG_SZ,
                   1184:                      registryPath.Buffer,
                   1185:                      registryPath.Length
                   1186:                      );
                   1187:     
                   1188:         if (!NT_SUCCESS(status)) {
                   1189:     
                   1190:             I8xPrint((
                   1191:                 1, 
                   1192:                 "I8042PRT-I8042Initialize: Could not store pointer name in DeviceMap\n"
                   1193:                 ));
                   1194: 
                   1195:             errorCode = I8042_NO_DEVICEMAP_CREATED;
                   1196:             uniqueErrorValue = I8042_ERROR_VALUE_BASE + 95;
                   1197:             dumpCount = 0;
                   1198: 
                   1199:             goto I8042InitializeExit;
                   1200:     
                   1201:         } else {
                   1202:     
                   1203:             I8xPrint((
                   1204:                 1, 
                   1205:                 "I8042PRT-I8042Initialize: Stored pointer name in DeviceMap\n"
                   1206:                 ));
                   1207:         }
                   1208:     }
                   1209: 
                   1210:     ASSERT(status == STATUS_SUCCESS);
                   1211: 
                   1212:     //
                   1213:     // Set up the device driver entry points.
                   1214:     //
                   1215: 
                   1216:     DriverObject->DriverStartIo = I8042StartIo;
                   1217:     DriverObject->MajorFunction[IRP_MJ_CREATE] = I8042OpenCloseDispatch;
                   1218:     DriverObject->MajorFunction[IRP_MJ_CLOSE]  = I8042OpenCloseDispatch;
                   1219:     DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]  =
                   1220:                                              I8042Flush;
                   1221:     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
                   1222:                                          I8042InternalDeviceControl;
                   1223:     //
                   1224:     // NOTE: Don't allow this driver to unload.  Otherwise, we would set
                   1225:     // DriverObject->DriverUnload = I8042Unload.
                   1226:     //
                   1227: 
                   1228: I8042InitializeExit:
                   1229: 
                   1230:     if (errorCode != STATUS_SUCCESS) {
                   1231: 
                   1232:         //
                   1233:         // Log an error/warning message.
                   1234:         //
                   1235: 
                   1236:         errorLogEntry = (PIO_ERROR_LOG_PACKET)
                   1237:             IoAllocateErrorLogEntry(
                   1238:                 (portDeviceObject == NULL) ? 
                   1239:                     (PVOID) DriverObject : (PVOID) portDeviceObject,
                   1240:                 (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) 
                   1241:                          + (dumpCount * sizeof(ULONG)))
                   1242:                 );
                   1243: 
                   1244:         if (errorLogEntry != NULL) {
                   1245: 
                   1246:             errorLogEntry->ErrorCode = errorCode;
                   1247:             errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG);
                   1248:             errorLogEntry->SequenceNumber = 0;
                   1249:             errorLogEntry->MajorFunctionCode = 0;
                   1250:             errorLogEntry->IoControlCode = 0;
                   1251:             errorLogEntry->RetryCount = 0;
                   1252:             errorLogEntry->UniqueErrorValue = uniqueErrorValue;
                   1253:             errorLogEntry->FinalStatus = status;
                   1254:             for (i = 0; i < dumpCount; i++)
                   1255:                 errorLogEntry->DumpData[i] = dumpData[i];
                   1256: 
                   1257:             IoWriteErrorLogEntry(errorLogEntry);
                   1258:         }
                   1259:     }
                   1260: 
                   1261:     if (!NT_SUCCESS(status)) {
                   1262: 
                   1263:         //
                   1264:         // The initialization failed.  Cleanup resources before exiting.
                   1265:         //
                   1266:         // N.B.  It is okay to disconnect the interrupt even if it never
                   1267:         // got connected.
                   1268:         //
                   1269: 
                   1270:         //
                   1271:         // Note:  No need/way to undo the KeInitializeDpc or 
                   1272:         //        KeInitializeTimer calls.
                   1273:         //
                   1274: 
                   1275:         //
                   1276:         // The initialization failed.  Cleanup resources before exiting.
                   1277:         //
                   1278: 
                   1279:         if (resources) {
                   1280: 
                   1281:             //
                   1282:             // Call IoReportResourceUsage to remove the resources from 
                   1283:             // the map.
                   1284:             //
                   1285: 
                   1286:             resources->Count = 0; 
                   1287: 
                   1288:             IoReportResourceUsage(
                   1289:                 &resourceDeviceClass, 
                   1290:                 DriverObject,
                   1291:                 NULL,
                   1292:                 0,
                   1293:                 portDeviceObject,
                   1294:                 resources, 
                   1295:                 resourceListSize,
                   1296:                 FALSE,
                   1297:                 &conflictDetected
                   1298:                 );
                   1299: 
                   1300:         }
                   1301: 
                   1302:         if (deviceExtension) {
                   1303:             if (deviceExtension->KeyboardInterruptObject != NULL)
                   1304:                 IoDisconnectInterrupt(deviceExtension->KeyboardInterruptObject);
                   1305:             if (deviceExtension->MouseInterruptObject != NULL)
                   1306:                 IoDisconnectInterrupt(deviceExtension->MouseInterruptObject);
                   1307:             if (deviceExtension->KeyboardExtension.InputData)
                   1308:                 ExFreePool(deviceExtension->KeyboardExtension.InputData);
                   1309:             if (deviceExtension->MouseExtension.InputData)
                   1310:                 ExFreePool(deviceExtension->MouseExtension.InputData);
                   1311: 
                   1312:             if (deviceExtension->UnmapRegistersRequired) {
                   1313:                 for (i = 0; 
                   1314:                      i < deviceExtension->Configuration.PortListCount; i++){
                   1315:                     if (deviceExtension->DeviceRegisters[i]) {
                   1316:                         MmUnmapIoSpace(
                   1317:                             deviceExtension->DeviceRegisters[i],
                   1318:                             deviceExtension->Configuration.PortList[i].u.Port.Length);
                   1319:                     }
                   1320:                 }
                   1321:             }
                   1322:         }
                   1323: 
                   1324: 
                   1325:         if (portDeviceObject) {
                   1326:             if (fullPointerName.Length > 0) {
                   1327:                 IoDeleteSymbolicLink(&fullPointerName);
                   1328:             }
                   1329:             IoDeleteDevice(portDeviceObject);
                   1330:         }
                   1331:     }
                   1332: 
                   1333:     //
                   1334:     // Free the resource list.
                   1335:     //
                   1336:     // N.B.  If we ever decide to hang on to the resource list instead,
                   1337:     //       we need to allocate it from non-paged pool (it is now paged pool).
                   1338:     //
                   1339: 
                   1340:     if (resources) {
                   1341:         ExFreePool(resources);
                   1342:     }
                   1343: 
                   1344:     //
                   1345:     // Free the unicode strings for device names.
                   1346:     //
                   1347: 
                   1348:     if (deviceNameSuffix.MaximumLength != 0)
                   1349:         ExFreePool(deviceNameSuffix.Buffer);
                   1350:     if (fullKeyboardName.MaximumLength != 0)
                   1351:         ExFreePool(fullKeyboardName.Buffer);
                   1352:     if (fullPointerName.MaximumLength != 0)
                   1353:         ExFreePool(fullPointerName.Buffer);
                   1354:     if (resourceDeviceClass.MaximumLength != 0)
                   1355:         ExFreePool(resourceDeviceClass.Buffer);
                   1356:     if (registryPath.MaximumLength != 0)
                   1357:         ExFreePool(registryPath.Buffer);
                   1358: 
                   1359:     I8xPrint((1,"I8042PRT-I8042Initialize: exit\n"));
                   1360: 
                   1361:     return(status);
                   1362: 
                   1363: }
                   1364: 
                   1365: VOID
                   1366: I8042Unload(
                   1367:     IN PDRIVER_OBJECT DriverObject
                   1368:     )
                   1369: {
                   1370:     UNREFERENCED_PARAMETER(DriverObject);
                   1371: 
                   1372:     I8xPrint((2, "I8042PRT-I8042Unload: enter\n"));
                   1373:     I8xPrint((2, "I8042PRT-I8042Unload: exit\n"));
                   1374: }
                   1375: 
                   1376: VOID
                   1377: I8xBuildResourceList(
                   1378:     IN PDEVICE_EXTENSION DeviceExtension,
                   1379:     OUT PCM_RESOURCE_LIST *ResourceList,
                   1380:     OUT PULONG ResourceListSize
                   1381:     )
                   1382: 
                   1383: /*++
                   1384: 
                   1385: Routine Description:
                   1386: 
                   1387:     Creates a resource list that is used to query or report resource usage.
                   1388: 
                   1389: Arguments:
                   1390: 
                   1391:     DeviceExtension - Pointer to the port's device extension.
                   1392: 
                   1393:     ResourceList - Pointer to a pointer to the resource list to be allocated
                   1394:         and filled.
                   1395:     
                   1396:     ResourceListSize - Pointer to the returned size of the resource 
                   1397:         list (in bytes).
                   1398: 
                   1399: Return Value:
                   1400: 
                   1401:     None.  If the call succeeded, *ResourceList points to the built
                   1402:     resource list and *ResourceListSize is set to the size (in bytes)
                   1403:     of the resource list; otherwise, *ResourceList is NULL.
                   1404: 
                   1405: Note:
                   1406: 
                   1407:     Memory may be allocated here for *ResourceList. It must be
                   1408:     freed up by the caller, by calling ExFreePool();
                   1409: 
                   1410: --*/
                   1411: 
                   1412: {
                   1413:     ULONG count = 0; 
                   1414:     ULONG i = 0;
                   1415:     ULONG j = 0;
                   1416: #define DUMP_COUNT 4
                   1417:     ULONG dumpData[DUMP_COUNT];
                   1418: 
                   1419:     count += DeviceExtension->Configuration.PortListCount;
                   1420:     if (DeviceExtension->Configuration.KeyboardInterrupt.Type 
                   1421:         == CmResourceTypeInterrupt)
                   1422:         count += 1;
                   1423:     if (DeviceExtension->Configuration.MouseInterrupt.Type 
                   1424:         == CmResourceTypeInterrupt)
                   1425:         count += 1;
                   1426: 
                   1427:     *ResourceListSize = sizeof(CM_RESOURCE_LIST) + 
                   1428:                        ((count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
                   1429: 
                   1430:     *ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool(
                   1431:                                             PagedPool,
                   1432:                                             *ResourceListSize
                   1433:                                             );
                   1434: 
                   1435:     //
                   1436:     // Return NULL if the structure could not be allocated.
                   1437:     // Otherwise, fill in the resource list.
                   1438:     //
                   1439: 
                   1440:     if (!*ResourceList) {
                   1441: 
                   1442:         //
                   1443:         // Could not allocate memory for the resource list.
                   1444:         //
                   1445: 
                   1446:         I8xPrint((
                   1447:             1,
                   1448:             "I8042PRT-I8xBuildResourceList: Could not allocate resource list\n"
                   1449:             ));
                   1450: 
                   1451:         //
                   1452:         // Log an error.
                   1453:         //
                   1454: 
                   1455:         dumpData[0] = *ResourceListSize;
                   1456:         *ResourceListSize = 0;
                   1457: 
                   1458:         I8xLogError(
                   1459:             DeviceExtension->DeviceObject,
                   1460:             I8042_INSUFFICIENT_RESOURCES,
                   1461:             I8042_ERROR_VALUE_BASE + 110,
                   1462:             STATUS_INSUFFICIENT_RESOURCES,
                   1463:             dumpData,
                   1464:             1
                   1465:             );
                   1466:              
                   1467:         return;
                   1468:     }
                   1469: 
                   1470:     RtlZeroMemory(
                   1471:         *ResourceList,
                   1472:         *ResourceListSize
                   1473:         );
                   1474: 
                   1475:     //
                   1476:     // Concoct one full resource descriptor.
                   1477:     //
                   1478: 
                   1479:     (*ResourceList)->Count = 1;
                   1480: 
                   1481:     (*ResourceList)->List[0].InterfaceType = 
                   1482:         DeviceExtension->Configuration.InterfaceType; 
                   1483:     (*ResourceList)->List[0].BusNumber = 
                   1484:         DeviceExtension->Configuration.BusNumber; 
                   1485: 
                   1486:     //
                   1487:     // Build the partial resource descriptors for interrupt and port
                   1488:     // resources from the saved values.
                   1489:     //
                   1490: 
                   1491:     (*ResourceList)->List[0].PartialResourceList.Count = count;
                   1492:     if (DeviceExtension->Configuration.KeyboardInterrupt.Type 
                   1493:         == CmResourceTypeInterrupt)
                   1494:         (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] =
                   1495:             DeviceExtension->Configuration.KeyboardInterrupt;
                   1496:     if (DeviceExtension->Configuration.MouseInterrupt.Type 
                   1497:         == CmResourceTypeInterrupt)
                   1498:         (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] = 
                   1499:             DeviceExtension->Configuration.MouseInterrupt;
                   1500: 
                   1501:     for (j = 0; j < DeviceExtension->Configuration.PortListCount; j++) {
                   1502:         (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] = 
                   1503:             DeviceExtension->Configuration.PortList[j];
                   1504:     }
                   1505: 
                   1506: } 
                   1507: 
                   1508: VOID
                   1509: I8xDrainOutputBuffer(
                   1510:     IN PUCHAR DataAddress,
                   1511:     IN PUCHAR CommandAddress
                   1512:     )
                   1513: 
                   1514: /*++
                   1515: 
                   1516: Routine Description:
                   1517: 
                   1518:     This routine drains the i8042 controller's output buffer.  This gets
                   1519:     rid of stale data that may have resulted from the user hitting a key
                   1520:     or moving the mouse, prior to the execution of I8042Initialize.
                   1521: 
                   1522: Arguments:
                   1523: 
                   1524:     DataAddress - Pointer to the data address to read/write from/to.
                   1525: 
                   1526:     CommandAddress - Pointer to the command/status address to 
                   1527:         read/write from/to.
                   1528: 
                   1529: 
                   1530: Return Value:
                   1531: 
                   1532:     None.
                   1533: 
                   1534: --*/
                   1535: 
                   1536: {
                   1537:     UCHAR byte;
                   1538: 
                   1539:     I8xPrint((3, "I8042PRT-I8xDrainOutputBuffer: enter\n"));
                   1540: 
                   1541:     while (I8X_GET_STATUS_BYTE(CommandAddress) & OUTPUT_BUFFER_FULL) {
                   1542: 
                   1543:         //
                   1544:         // Eat the output buffer byte.
                   1545:         //
                   1546: 
                   1547:         byte = I8X_GET_DATA_BYTE(DataAddress);
                   1548:     }
                   1549: 
                   1550:     I8xPrint((3, "I8042PRT-I8xDrainOutputBuffer: exit\n"));
                   1551: }
                   1552: 
                   1553: VOID
                   1554: I8xGetByteAsynchronous(
                   1555:     IN CCHAR DeviceType,
                   1556:     IN PDEVICE_EXTENSION DeviceExtension,
                   1557:     OUT PUCHAR Byte
                   1558:     )
                   1559: 
                   1560: /*++
                   1561: 
                   1562: Routine Description:
                   1563: 
                   1564:     This routine reads a data byte from the controller or keyboard
                   1565:     or mouse, asynchronously.
                   1566: 
                   1567: Arguments:
                   1568: 
                   1569:     DeviceType - Specifies which device (i8042 controller, keyboard, or
                   1570:         mouse) to read the byte from.
                   1571: 
                   1572:     DeviceExtension - Pointer to the device extension.
                   1573: 
                   1574:     Byte - Pointer to the location to store the byte read from the hardware.
                   1575: 
                   1576: Return Value:
                   1577: 
                   1578:     None.
                   1579: 
                   1580:     As a side-effect, the byte value read is stored.  If the hardware was not
                   1581:     ready for output or did not respond, the byte value is not stored.
                   1582: 
                   1583: --*/
                   1584: 
                   1585: {
                   1586:     ULONG i;
                   1587:     UCHAR response;
                   1588:     UCHAR desiredMask;
                   1589: 
                   1590:     I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: enter\n"));
                   1591: 
                   1592:     if (DeviceType == KeyboardDeviceType) {
                   1593:         I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: keyboard\n"));
                   1594:     } else if (DeviceType == MouseDeviceType) {
                   1595:         I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: mouse\n"));
                   1596:     } else {
                   1597:         I8xPrint((3, "I8042PRT-I8xGetByteAsynchronous: 8042 controller\n"));
                   1598:     }
                   1599: 
                   1600:     i = 0;
                   1601:     desiredMask = (DeviceType == MouseDeviceType)?
                   1602:                   (UCHAR) (OUTPUT_BUFFER_FULL | MOUSE_OUTPUT_BUFFER_FULL):
                   1603:                   (UCHAR) OUTPUT_BUFFER_FULL;
                   1604: 
                   1605:     //
                   1606:     // Poll until we get back a controller status value that indicates
                   1607:     // the output buffer is full.  If we want to read a byte from the mouse,
                   1608:     // further ensure that the auxiliary device output buffer full bit is
                   1609:     // set.
                   1610:     //
                   1611: 
                   1612:     while ((i < (ULONG)DeviceExtension->Configuration.PollingIterations) &&
                   1613:            ((UCHAR)((response = 
                   1614:                I8X_GET_STATUS_BYTE(DeviceExtension->DeviceRegisters[CommandPort])) 
                   1615:                & desiredMask) != desiredMask)) {
                   1616: 
                   1617:         if (response & OUTPUT_BUFFER_FULL) {
                   1618: 
                   1619:             //
                   1620:             // There is something in the i8042 output buffer, but it
                   1621:             // isn't from the device we want to get a byte from.  Eat
                   1622:             // the byte and try again.
                   1623:             //
                   1624: 
                   1625:             *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
                   1626:             I8xPrint((2, "I8042PRT-I8xGetByteAsynchronous: ate 0x%x\n", *Byte));
                   1627:         } else {
                   1628: 
                   1629:             //
                   1630:             // Try again.
                   1631:             //
                   1632: 
                   1633:             i += 1;
                   1634: 
                   1635:             I8xPrint((
                   1636:                 2, 
                   1637:                 "I8042PRT-I8xGetByteAsynchronous: wait for correct status\n"
                   1638:                 ));
                   1639:         }
                   1640: 
                   1641:     }
                   1642:     if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
                   1643:         I8xPrint((2, "I8042PRT-I8xGetByteAsynchronous: timing out\n"));
                   1644:         return;
                   1645:     }
                   1646: 
                   1647:     //
                   1648:     // Grab the byte from the hardware.
                   1649:     //
                   1650: 
                   1651:     *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
                   1652: 
                   1653:     I8xPrint((
                   1654:         3, 
                   1655:         "I8042PRT-I8xGetByteAsynchronous: exit with Byte 0x%x\n", *Byte
                   1656:         ));
                   1657: 
                   1658: }
                   1659: 
                   1660: NTSTATUS
                   1661: I8xGetBytePolled(
                   1662:     IN CCHAR DeviceType,
                   1663:     IN PDEVICE_EXTENSION DeviceExtension,
                   1664:     OUT PUCHAR Byte
                   1665:     )
                   1666: 
                   1667: /*++
                   1668: 
                   1669: Routine Description:
                   1670: 
                   1671:     This routine reads a data byte from the controller or keyboard
                   1672:     or mouse, in polling mode.
                   1673: 
                   1674: Arguments:
                   1675: 
                   1676:     DeviceType - Specifies which device (i8042 controller, keyboard, or
                   1677:         mouse) to read the byte from.
                   1678: 
                   1679:     DeviceExtension - Pointer to the device extension.
                   1680: 
                   1681:     Byte - Pointer to the location to store the byte read from the hardware.
                   1682: 
                   1683: Return Value:
                   1684: 
                   1685:     STATUS_IO_TIMEOUT - The hardware was not ready for output or did not
                   1686:     respond.
                   1687: 
                   1688:     STATUS_SUCCESS - The byte was successfully read from the hardware.
                   1689: 
                   1690:     As a side-effect, the byte value read is stored.
                   1691: 
                   1692: --*/
                   1693: 
                   1694: {
                   1695:     ULONG i;
                   1696:     UCHAR response;
                   1697:     UCHAR desiredMask;
                   1698: 
                   1699:     I8xPrint((3, "I8042PRT-I8xGetBytePolled: enter\n"));
                   1700: 
                   1701:     if (DeviceType == KeyboardDeviceType) {
                   1702:         I8xPrint((3, "I8042PRT-I8xGetBytePolled: keyboard\n"));
                   1703:     } else if (DeviceType == MouseDeviceType) {
                   1704:         I8xPrint((3, "I8042PRT-I8xGetBytePolled: mouse\n"));
                   1705:     } else {
                   1706:         I8xPrint((3, "I8042PRT-I8xGetBytePolled: 8042 controller\n"));
                   1707:     }
                   1708: 
                   1709:     i = 0;
                   1710:     desiredMask = (DeviceType == MouseDeviceType)?
                   1711:                   (UCHAR) (OUTPUT_BUFFER_FULL | MOUSE_OUTPUT_BUFFER_FULL):
                   1712:                   (UCHAR) OUTPUT_BUFFER_FULL;
                   1713: 
                   1714: 
                   1715:     //
                   1716:     // Poll until we get back a controller status value that indicates
                   1717:     // the output buffer is full.  If we want to read a byte from the mouse,
                   1718:     // further ensure that the auxiliary device output buffer full bit is
                   1719:     // set.
                   1720:     //
                   1721: 
                   1722:     while ((i < (ULONG)DeviceExtension->Configuration.PollingIterations) &&
                   1723:            ((UCHAR)((response = 
                   1724:                I8X_GET_STATUS_BYTE(DeviceExtension->DeviceRegisters[CommandPort])) 
                   1725:                & desiredMask) != desiredMask)) {
                   1726:         if (response & OUTPUT_BUFFER_FULL) {
                   1727: 
                   1728:             //
                   1729:             // There is something in the i8042 output buffer, but it
                   1730:             // isn't from the device we want to get a byte from.  Eat
                   1731:             // the byte and try again.
                   1732:             //
                   1733: 
                   1734:             *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
                   1735:             I8xPrint((2, "I8042PRT-I8xGetBytePolled: ate 0x%x\n", *Byte));
                   1736:         } else {
                   1737:             I8xPrint((2, "I8042PRT-I8xGetBytePolled: stalling\n"));
                   1738:             KeStallExecutionProcessor(
                   1739:                  DeviceExtension->Configuration.StallMicroseconds
                   1740:                  );
                   1741:             i += 1;
                   1742:         }
                   1743:     }
                   1744:     if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
                   1745:         I8xPrint((2, "I8042PRT-I8xGetBytePolled: timing out\n"));
                   1746:         return(STATUS_IO_TIMEOUT);
                   1747:     }
                   1748: 
                   1749:     //
                   1750:     // Grab the byte from the hardware, and return success.
                   1751:     //
                   1752: 
                   1753:     *Byte = I8X_GET_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort]);
                   1754: 
                   1755:     I8xPrint((3, "I8042PRT-I8xGetBytePolled: exit with Byte 0x%x\n", *Byte));
                   1756: 
                   1757:     return(STATUS_SUCCESS);
                   1758: 
                   1759: }
                   1760: 
                   1761: NTSTATUS
                   1762: I8xGetControllerCommand(
                   1763:     IN ULONG HardwareDisableEnableMask,
                   1764:     IN PDEVICE_EXTENSION DeviceExtension,
                   1765:     OUT PUCHAR Byte
                   1766:     )
                   1767: 
                   1768: /*++
                   1769: 
                   1770: Routine Description:
                   1771: 
                   1772:     This routine reads the 8042 Controller Command Byte.
                   1773: 
                   1774: Arguments:
                   1775: 
                   1776:     HardwareDisableEnableMask - Specifies which hardware devices, if any,
                   1777:         need to be disabled/enable around the operation.
                   1778: 
                   1779:     DeviceExtension - Pointer to the device extension.
                   1780: 
                   1781:     Byte - Pointer to the location into which the Controller Command Byte is
                   1782:         read.
                   1783: 
                   1784: Return Value:
                   1785: 
                   1786:     Status is returned.
                   1787: 
                   1788: --*/
                   1789: 
                   1790: {
                   1791:     NTSTATUS status;
                   1792:     NTSTATUS secondStatus;
                   1793: 
                   1794:     I8xPrint((3, "I8042PRT-I8xGetControllerCommand: enter\n"));
                   1795: 
                   1796:     //
                   1797:     // Disable the specified devices before sending the command to
                   1798:     // read the Controller Command Byte (otherwise data in the output
                   1799:     // buffer might get trashed).
                   1800:     //
                   1801: 
                   1802:     if (HardwareDisableEnableMask & KEYBOARD_HARDWARE_PRESENT) {
                   1803:         status = I8xPutBytePolled(
                   1804:                      (CCHAR) CommandPort,
                   1805:                      NO_WAIT_FOR_ACKNOWLEDGE,
                   1806:                      (CCHAR) UndefinedDeviceType, 
                   1807:                      DeviceExtension,
                   1808:                      (UCHAR) I8042_DISABLE_KEYBOARD_DEVICE
                   1809:                      );
                   1810:         if (!NT_SUCCESS(status)) {
                   1811:             return(status);
                   1812:         }
                   1813:     }
                   1814: 
                   1815:     if (HardwareDisableEnableMask & MOUSE_HARDWARE_PRESENT) {
                   1816:         status = I8xPutBytePolled(
                   1817:                      (CCHAR) CommandPort,
                   1818:                      NO_WAIT_FOR_ACKNOWLEDGE,
                   1819:                      (CCHAR) UndefinedDeviceType, 
                   1820:                      DeviceExtension,
                   1821:                      (UCHAR) I8042_DISABLE_MOUSE_DEVICE
                   1822:                      );
                   1823:         if (!NT_SUCCESS(status)) {
                   1824: 
                   1825:             //
                   1826:             // Re-enable the keyboard device, if necessary, before returning.
                   1827:             //
                   1828: 
                   1829:             if (HardwareDisableEnableMask & KEYBOARD_HARDWARE_PRESENT) {
                   1830:                 secondStatus = I8xPutBytePolled(
                   1831:                                    (CCHAR) CommandPort,
                   1832:                                    NO_WAIT_FOR_ACKNOWLEDGE,
                   1833:                                    (CCHAR) UndefinedDeviceType, 
                   1834:                                    DeviceExtension,
                   1835:                                    (UCHAR) I8042_ENABLE_KEYBOARD_DEVICE
                   1836:                                    );
                   1837:             }
                   1838:             return(status);
                   1839:         }
                   1840:     }
                   1841: 
                   1842:     //
                   1843:     // Send a command to the i8042 controller to read the Controller
                   1844:     // Command Byte.
                   1845:     //
                   1846: 
                   1847:     status = I8xPutBytePolled(
                   1848:                  (CCHAR) CommandPort,
                   1849:                  NO_WAIT_FOR_ACKNOWLEDGE,
                   1850:                  (CCHAR) UndefinedDeviceType, 
                   1851:                  DeviceExtension,
                   1852:                  (UCHAR) I8042_READ_CONTROLLER_COMMAND_BYTE
                   1853:                  );
                   1854: 
                   1855:     //
                   1856:     // Read the byte from the i8042 data port.
                   1857:     //
                   1858: 
                   1859:     if (NT_SUCCESS(status)) {
                   1860:         status = I8xGetBytePolled(
                   1861:                      (CCHAR) ControllerDeviceType, 
                   1862:                      DeviceExtension, 
                   1863:                      Byte
                   1864:                      );
                   1865:     }
                   1866: 
                   1867:     //
                   1868:     // Re-enable the specified devices.  Clear the device disable
                   1869:     // bits in the Controller Command Byte by hand (they got set when
                   1870:     // we disabled the devices, so the CCB we read lacked the real
                   1871:     // device disable bit information).
                   1872:     //
                   1873: 
                   1874:     if (HardwareDisableEnableMask & KEYBOARD_HARDWARE_PRESENT) {
                   1875:         secondStatus = I8xPutBytePolled(
                   1876:                            (CCHAR) CommandPort,
                   1877:                            NO_WAIT_FOR_ACKNOWLEDGE,
                   1878:                            (CCHAR) UndefinedDeviceType, 
                   1879:                            DeviceExtension,
                   1880:                            (UCHAR) I8042_ENABLE_KEYBOARD_DEVICE
                   1881:                            );
                   1882:         if (!NT_SUCCESS(secondStatus)) {
                   1883:             if (NT_SUCCESS(status))
                   1884:                 status = secondStatus;
                   1885:         } else if (status == STATUS_SUCCESS) {
                   1886:             *Byte &= (UCHAR) ~CCB_DISABLE_KEYBOARD_DEVICE;
                   1887:         }
                   1888: 
                   1889:     }
                   1890: 
                   1891:     if (HardwareDisableEnableMask & MOUSE_HARDWARE_PRESENT) {
                   1892:         secondStatus = I8xPutBytePolled(
                   1893:                            (CCHAR) CommandPort,
                   1894:                            NO_WAIT_FOR_ACKNOWLEDGE,
                   1895:                            (CCHAR) UndefinedDeviceType, 
                   1896:                            DeviceExtension,
                   1897:                            (UCHAR) I8042_ENABLE_MOUSE_DEVICE
                   1898:                            );
                   1899:         if (!NT_SUCCESS(secondStatus)) {
                   1900:             if (NT_SUCCESS(status))
                   1901:                 status = secondStatus;
                   1902:         } else if (NT_SUCCESS(status)) {
                   1903:             *Byte &= (UCHAR) ~CCB_DISABLE_MOUSE_DEVICE;
                   1904:         }
                   1905:     }
                   1906: 
                   1907:     I8xPrint((3, "I8042PRT-I8xGetControllerCommand: exit\n"));
                   1908: 
                   1909:     return(status);
                   1910: 
                   1911: }
                   1912: 
                   1913: VOID
                   1914: I8xInitializeHardware(
                   1915:     IN PDEVICE_OBJECT DeviceObject
                   1916:     )
                   1917: 
                   1918: /*++
                   1919: 
                   1920: Routine Description:
                   1921: 
                   1922:     This routine initializes the i8042 controller, keyboard, and mouse.
                   1923:     Note that it is only called at initialization time.  This routine
                   1924:     does not need to synchronize access to the hardware, or synchronize
                   1925:     with the ISRs (they aren't connected yet).
                   1926: 
                   1927: Arguments:
                   1928: 
                   1929:     DeviceObject - Pointer to the device object.
                   1930: 
                   1931: Return Value:
                   1932: 
                   1933:     None.  As a side-effect, however, DeviceExtension->HardwarePresent is set.
                   1934: 
                   1935: --*/
                   1936: 
                   1937: {
                   1938:     PDEVICE_EXTENSION deviceExtension;
                   1939:     NTSTATUS status;
                   1940:     I8042_TRANSMIT_CCB_CONTEXT transmitCCBContext;
                   1941:     PUCHAR dataAddress, commandAddress;
                   1942: 
                   1943:     I8xPrint((2, "I8042PRT-I8xInitializeHardware: enter\n"));
                   1944: 
                   1945:     //
                   1946:     // Grab useful configuration parameters from the device extension.
                   1947:     //
                   1948: 
                   1949:     deviceExtension = DeviceObject->DeviceExtension;
                   1950:     dataAddress = deviceExtension->DeviceRegisters[DataPort];
                   1951:     commandAddress = deviceExtension->DeviceRegisters[CommandPort];
                   1952: 
                   1953:     //
                   1954:     // Drain the i8042 output buffer to get rid of stale data.
                   1955:     //
                   1956: 
                   1957:     I8xDrainOutputBuffer(dataAddress, commandAddress);
                   1958: 
                   1959:     //
                   1960:     // Disable interrupts from the keyboard and mouse.  Read the Controller
                   1961:     // Command Byte, turn off the keyboard and auxiliary interrupt enable
                   1962:     // bits, and rewrite the Controller Command Byte.
                   1963:     //
                   1964: 
                   1965:     transmitCCBContext.HardwareDisableEnableMask = 0;
                   1966:     transmitCCBContext.AndOperation = AND_OPERATION;
                   1967:     transmitCCBContext.ByteMask = (UCHAR)
                   1968:                            ~((UCHAR) CCB_ENABLE_KEYBOARD_INTERRUPT |
                   1969:                             (UCHAR) CCB_ENABLE_MOUSE_INTERRUPT);
                   1970: 
                   1971:     I8xTransmitControllerCommand(deviceExtension, (PVOID) &transmitCCBContext);
                   1972: 
                   1973:     if (!NT_SUCCESS(transmitCCBContext.Status)) {
                   1974:         I8xPrint((
                   1975:             1,
                   1976:             "I8042PRT-I8xInitializeHardware: failed to disable interrupts, status 0x%x\n",
                   1977:             transmitCCBContext.Status
                   1978:             ));
                   1979: 
                   1980:         return;
                   1981:     }
                   1982: 
                   1983:     if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) == 0) {
                   1984:         I8xPrint((
                   1985:             1,
                   1986:             "I8042PRT-I8xInitializeHardware: no mouse present\n"
                   1987:             ));
                   1988:     }
                   1989: 
                   1990:     if ((deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) == 0) {
                   1991:         I8xPrint((
                   1992:             1,
                   1993:             "I8042PRT-I8xInitializeHardware: no keyboard present\n"
                   1994:             ));
                   1995:     }
                   1996: 
                   1997: 
                   1998:     //
                   1999:     // Disable the keyboard and mouse devices.
                   2000:     //
                   2001: 
                   2002: #if 0
                   2003:     //
                   2004:     // NOTE:  This is supposedly the "correct" thing to do.  However,
                   2005:     // disabling the keyboard device here causes the AMI rev K8 machines
                   2006:     // (e.g., some Northgates) to fail some commands (e.g., the READID 
                   2007:     // command).
                   2008:     //
                   2009: 
                   2010:     status = I8xPutBytePolled(
                   2011:                  (CCHAR) CommandPort,
                   2012:                  NO_WAIT_FOR_ACKNOWLEDGE,
                   2013:                  (CCHAR) UndefinedDeviceType, 
                   2014:                  deviceExtension,
                   2015:                  (UCHAR) I8042_DISABLE_KEYBOARD_DEVICE
                   2016:                  );
                   2017:     if (!NT_SUCCESS(status)) {
                   2018:         I8xPrint((
                   2019:             1,
                   2020:             "I8042PRT-I8xInitializeHardware: failed kbd disable, status 0x%x\n",
                   2021:             status
                   2022:             ));
                   2023:         deviceExtension->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
                   2024:     }
                   2025: #endif
                   2026: 
                   2027:     status = I8xPutBytePolled(
                   2028:                  (CCHAR) CommandPort,
                   2029:                  NO_WAIT_FOR_ACKNOWLEDGE,
                   2030:                  (CCHAR) UndefinedDeviceType, 
                   2031:                  deviceExtension,
                   2032:                  (UCHAR) I8042_DISABLE_MOUSE_DEVICE
                   2033:                  );
                   2034:     if (!NT_SUCCESS(status)) {
                   2035:         I8xPrint((
                   2036:             1,
                   2037:             "I8042PRT-I8xInitializeHardware: failed mou disable, status 0x%x\n",
                   2038:             status
                   2039:             ));
                   2040: 
                   2041:         deviceExtension->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
                   2042:     }
                   2043: 
                   2044:     //
                   2045:     // Drain the i8042 output buffer to get rid of stale data that could
                   2046:     // come in sometime between the previous drain and the time the devices
                   2047:     // are disabled.
                   2048:     //
                   2049: 
                   2050:     I8xDrainOutputBuffer(dataAddress, commandAddress);
                   2051: 
                   2052:     //
                   2053:     // Setup the mouse hardware.  This consists of resetting the mouse and
                   2054:     // then setting the mouse sample rate.
                   2055:     //
                   2056: 
                   2057:     if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
                   2058:         status = I8xInitializeMouse(DeviceObject);
                   2059:         if (!NT_SUCCESS(status)) {
                   2060:             I8xPrint((
                   2061:                 1,
                   2062:                 "I8042PRT-I8xInitializeHardware: failed mou init, status 0x%x\n",
                   2063:                 status
                   2064:                 ));
                   2065:             deviceExtension->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
                   2066:         }
                   2067:     }
                   2068: 
                   2069:     //
                   2070:     // Setup the keyboard hardware.  
                   2071:     //
                   2072: 
                   2073:     if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
                   2074:         status = I8xInitializeKeyboard(DeviceObject);
                   2075:         if (!NT_SUCCESS(status)) {
                   2076:             I8xPrint((
                   2077:                 0,
                   2078:                 "I8042PRT-I8xInitializeHardware: failed kbd init, status 0x%x\n",
                   2079:                 status
                   2080:                 ));
                   2081: 
                   2082:             deviceExtension->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
                   2083:         }
                   2084:     }
                   2085: 
                   2086:     //
                   2087:     // Enable the keyboard and mouse devices and their interrupts.  Note
                   2088:     // that it is required that this operation happen during intialization
                   2089:     // time, because the i8042 Output Buffer Full bit gets set in the
                   2090:     // Controller Command Byte when the keyboard/mouse is used, even if
                   2091:     // the device is disabled.  Hence, we cannot successfully perform
                   2092:     // the enable operation later (e.g., when processing
                   2093:     // IOCTL_INTERNAL_*_ENABLE), because we can't guarantee that
                   2094:     // I8xPutBytePolled() won't time out waiting for the Output Buffer Full
                   2095:     // bit to clear, even if we drain the output buffer (because the user
                   2096:     // could be playing with the mouse/keyboard, and continuing to set the
                   2097:     // OBF bit).  KeyboardEnableCount and MouseEnableCount remain zero until 
                   2098:     // their respective IOCTL_INTERNAL_*_ENABLE call succeeds, so the ISR 
                   2099:     // ignores the unexpected interrupts.
                   2100:     //
                   2101: 
                   2102:     //
                   2103:     // Re-enable the keyboard device in the Controller Command Byte.
                   2104:     // Note that some of the keyboards will send an ACK back, while
                   2105:     // others don't.  Don't wait for an ACK, but do drain the output
                   2106:     // buffer afterwards so that an unexpected ACK doesn't screw up
                   2107:     // successive PutByte operations.
                   2108: 
                   2109:     if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
                   2110:         status = I8xPutBytePolled(
                   2111:                      (CCHAR) CommandPort,
                   2112:                      NO_WAIT_FOR_ACKNOWLEDGE,
                   2113:                      (CCHAR) UndefinedDeviceType, 
                   2114:                      deviceExtension,
                   2115:                      (UCHAR) I8042_ENABLE_KEYBOARD_DEVICE
                   2116:                      );
                   2117:         if (!NT_SUCCESS(status)) {
                   2118:             I8xPrint((
                   2119:                 1,
                   2120:                 "I8042PRT-I8xInitializeHardware: failed kbd re-enable, status 0x%x\n",
                   2121:                 status
                   2122:                 ));
                   2123:             deviceExtension->HardwarePresent &= ~KEYBOARD_HARDWARE_PRESENT;
                   2124:         }
                   2125: 
                   2126:         I8xDrainOutputBuffer(dataAddress, commandAddress);
                   2127:     }
                   2128: 
                   2129: 
                   2130:     //
                   2131:     // Re-enable the mouse device in the Controller Command Byte.
                   2132:     //
                   2133: 
                   2134:     if (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
                   2135:         status = I8xPutBytePolled(
                   2136:                      (CCHAR) CommandPort,
                   2137:                      NO_WAIT_FOR_ACKNOWLEDGE,
                   2138:                      (CCHAR) UndefinedDeviceType, 
                   2139:                      deviceExtension,
                   2140:                      (UCHAR) I8042_ENABLE_MOUSE_DEVICE
                   2141:                      );
                   2142:         if (!NT_SUCCESS(status)) {
                   2143:             I8xPrint((
                   2144:                 1,
                   2145:                 "I8042PRT-I8xInitializeHardware: failed mou re-enable, status 0x%x\n",
                   2146:                 status
                   2147:                 ));
                   2148:             deviceExtension->HardwarePresent &= ~MOUSE_HARDWARE_PRESENT;
                   2149:         }
                   2150:         I8xDrainOutputBuffer(dataAddress, commandAddress);
                   2151:     }
                   2152: 
                   2153:     //
                   2154:     // Re-enable interrupts in the Controller Command Byte.
                   2155:     //
                   2156: 
                   2157:     if (deviceExtension->HardwarePresent) {
                   2158:         transmitCCBContext.HardwareDisableEnableMask =
                   2159:             deviceExtension->HardwarePresent;
                   2160:         transmitCCBContext.AndOperation = OR_OPERATION;
                   2161:         transmitCCBContext.ByteMask =
                   2162:             (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) ?
                   2163:             CCB_ENABLE_KEYBOARD_INTERRUPT : 0;
                   2164:         transmitCCBContext.ByteMask |= (UCHAR)
                   2165:             (deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) ?
                   2166:             CCB_ENABLE_MOUSE_INTERRUPT : 0;
                   2167: 
                   2168:         I8xTransmitControllerCommand(
                   2169:             deviceExtension, 
                   2170:             (PVOID) &transmitCCBContext
                   2171:             );
                   2172: 
                   2173:         if (!NT_SUCCESS(transmitCCBContext.Status)) {
                   2174:             I8xPrint((
                   2175:                 1,
                   2176:                 "I8042PRT-I8xInitializeHardware: failed to re-enable interrupts, status 0x%x\n",
                   2177:                 transmitCCBContext.Status
                   2178:                 ));
                   2179: 
                   2180:             //
                   2181:             // We have the option here of resetting HardwarePresent to zero,
                   2182:             // which will cause the driver to fail its initialization and
                   2183:             // unload.  Instead, we allow initialization to continue in
                   2184:             // the hope that the command to re-enable interrupts was
                   2185:             // successful at the hardware level (i.e., things will work),
                   2186:             // even though the hardware response indicates otherwise.
                   2187:             //
                   2188:         }
                   2189:     }
                   2190: 
                   2191:     I8xPrint((2, "I8042PRT-I8xInitializeHardware: exit\n"));
                   2192: 
                   2193:     return;
                   2194: 
                   2195: }
                   2196: 
                   2197: VOID
                   2198: I8xPutByteAsynchronous(
                   2199:     IN CCHAR PortType,
                   2200:     IN PDEVICE_EXTENSION DeviceExtension,
                   2201:     IN UCHAR Byte
                   2202:     )
                   2203: 
                   2204: /*++
                   2205: 
                   2206: Routine Description:
                   2207: 
                   2208:     This routine sends a command or data byte to the controller or keyboard
                   2209:     or mouse, asynchronously.  It does not wait for acknowledgment.
                   2210:     If the hardware was not ready for input, the byte is not sent.
                   2211: 
                   2212: Arguments:
                   2213: 
                   2214:     PortType - If CommandPort, send the byte to the command register,
                   2215:         otherwise send it to the data register.
                   2216: 
                   2217:     DeviceExtension - Pointer to the device extension.
                   2218: 
                   2219:     Byte - The byte to send to the hardware.
                   2220: 
                   2221: Return Value:
                   2222: 
                   2223:     None.
                   2224: 
                   2225: --*/
                   2226: 
                   2227: {
                   2228:     ULONG i;
                   2229: 
                   2230:     I8xPrint((3, "I8042PRT-I8xPutByteAsynchronous: enter\n"));
                   2231: 
                   2232:     //
                   2233:     // Make sure the Input Buffer Full controller status bit is clear.  
                   2234:     // Time out if necessary.
                   2235:     //
                   2236: 
                   2237:     i = 0;
                   2238:     while ((i++ < (ULONG)DeviceExtension->Configuration.PollingIterations) &&
                   2239:            (I8X_GET_STATUS_BYTE(DeviceExtension->DeviceRegisters[CommandPort]) 
                   2240:                 & INPUT_BUFFER_FULL)) {
                   2241: 
                   2242:         //
                   2243:         // Do nothing.
                   2244:         //
                   2245: 
                   2246:         I8xPrint((
                   2247:             3,
                   2248:             "I8042PRT-I8xPutByteAsynchronous: wait for IBF and OBF to clear\n"
                   2249:             ));
                   2250: 
                   2251:     }
                   2252:     if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
                   2253:         I8xPrint((
                   2254:             3, 
                   2255:             "I8042PRT-I8xPutByteAsynchronous: exceeded number of retries\n"
                   2256:             ));
                   2257:         return;
                   2258:     }
                   2259: 
                   2260:     //
                   2261:     // Send the byte to the appropriate (command/data) hardware register.
                   2262:     //
                   2263: 
                   2264:     if (PortType == CommandPort) {
                   2265:         I8xPrint((
                   2266:             3,
                   2267:             "I8042PRT-I8xPutByteAsynchronous: sending 0x%x to command port\n",
                   2268:             Byte
                   2269:             ));
                   2270:         I8X_PUT_COMMAND_BYTE(DeviceExtension->DeviceRegisters[CommandPort], Byte);
                   2271:     } else {
                   2272:         I8xPrint((
                   2273:             3,
                   2274:             "I8042PRT-I8xPutByteAsynchronous: sending 0x%x to data port\n",
                   2275:             Byte
                   2276:             ));
                   2277:         I8X_PUT_DATA_BYTE(DeviceExtension->DeviceRegisters[DataPort], Byte);
                   2278:     }
                   2279: 
                   2280:     I8xPrint((3, "I8042PRT-I8xPutByteAsynchronous: exit\n"));
                   2281: 
                   2282: }
                   2283: 
                   2284: NTSTATUS
                   2285: I8xPutBytePolled(
                   2286:     IN CCHAR PortType,
                   2287:     IN BOOLEAN WaitForAcknowledge,
                   2288:     IN CCHAR AckDeviceType,
                   2289:     IN PDEVICE_EXTENSION DeviceExtension,
                   2290:     IN UCHAR Byte
                   2291:     )
                   2292: 
                   2293: /*++
                   2294: 
                   2295: Routine Description:
                   2296: 
                   2297:     This routine sends a command or data byte to the controller or keyboard
                   2298:     or mouse, in polling mode.  It waits for acknowledgment and resends
                   2299:     the command/data if necessary.
                   2300: 
                   2301: Arguments:
                   2302: 
                   2303:     PortType - If CommandPort, send the byte to the command register,
                   2304:         otherwise send it to the data register.
                   2305: 
                   2306:     WaitForAcknowledge - If true, wait for an ACK back from the hardware.
                   2307: 
                   2308:     AckDeviceType - Indicates which device we expect to get the ACK back
                   2309:         from.
                   2310: 
                   2311:     DeviceExtension - Pointer to the device extension.
                   2312: 
                   2313:     Byte - The byte to send to the hardware.
                   2314: 
                   2315: Return Value:
                   2316: 
                   2317:     STATUS_IO_TIMEOUT - The hardware was not ready for input or did not
                   2318:     respond.
                   2319: 
                   2320:     STATUS_SUCCESS - The byte was successfully sent to the hardware.
                   2321: 
                   2322: --*/
                   2323: 
                   2324: {
                   2325:     ULONG i,j;
                   2326:     UCHAR response;
                   2327:     NTSTATUS status;
                   2328:     BOOLEAN keepTrying;
                   2329:     PUCHAR dataAddress, commandAddress;
                   2330: 
                   2331:     I8xPrint((3, "I8042PRT-I8xPutBytePolled: enter\n"));
                   2332: 
                   2333:     if (AckDeviceType == MouseDeviceType) {
                   2334: 
                   2335:         //
                   2336:         // We need to precede a PutByte for the mouse device with
                   2337:         // a PutByte that tells the controller that the next byte
                   2338:         // sent to the controller should go to the auxiliary device
                   2339:         // (by default it would go to the keyboard device).  We
                   2340:         // do this by calling I8xPutBytePolled recursively to send
                   2341:         // the "send next byte to auxiliary device" command 
                   2342:         // before sending the intended byte to the mouse.  Note that
                   2343:         // there is only one level of recursion, since the AckDeviceType
                   2344:         // for the recursive call is guaranteed to be UndefinedDeviceType,
                   2345:         // and hence this IF statement will evaluate to FALSE.
                   2346:         //
                   2347: 
                   2348:         I8xPutBytePolled(
                   2349:             (CCHAR) CommandPort,
                   2350:             NO_WAIT_FOR_ACKNOWLEDGE,
                   2351:             (CCHAR) UndefinedDeviceType,
                   2352:             DeviceExtension,
                   2353:             (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
                   2354:             );
                   2355:     }
                   2356: 
                   2357:     dataAddress = DeviceExtension->DeviceRegisters[DataPort];
                   2358:     commandAddress = DeviceExtension->DeviceRegisters[CommandPort];
                   2359: 
                   2360:     for (j=0;j < (ULONG)DeviceExtension->Configuration.ResendIterations;j++) {
                   2361: 
                   2362:         //
                   2363:         // Make sure the Input Buffer Full controller status bit is clear.
                   2364:         // Time out if necessary.
                   2365:         //
                   2366: 
                   2367:         i = 0;
                   2368:         while ((i++ < (ULONG)DeviceExtension->Configuration.PollingIterations)
                   2369:                && (I8X_GET_STATUS_BYTE(commandAddress) & INPUT_BUFFER_FULL)) {
                   2370:             I8xPrint((2, "I8042PRT-I8xPutBytePolled: stalling\n"));
                   2371:             KeStallExecutionProcessor(
                   2372:                 DeviceExtension->Configuration.StallMicroseconds
                   2373:                 );
                   2374:         }
                   2375:         if (i >= (ULONG)DeviceExtension->Configuration.PollingIterations) {
                   2376:             I8xPrint((2, "I8042PRT-I8xPutBytePolled: timing out\n"));
                   2377:             status = STATUS_IO_TIMEOUT;
                   2378:             break;
                   2379:         }
                   2380: 
                   2381:         //
                   2382:         // Drain the i8042 output buffer to get rid of stale data.
                   2383:         //
                   2384: 
                   2385:         I8xDrainOutputBuffer(dataAddress, commandAddress);
                   2386: 
                   2387:         //
                   2388:         // Send the byte to the appropriate (command/data) hardware register.
                   2389:         //
                   2390: 
                   2391:         if (PortType == CommandPort) {
                   2392:             I8xPrint((
                   2393:                 3,
                   2394:                 "I8042PRT-I8xPutBytePolled: sending 0x%x to command port\n",
                   2395:                 Byte
                   2396:                 ));
                   2397:             I8X_PUT_COMMAND_BYTE(commandAddress, Byte);
                   2398:         } else {
                   2399:             I8xPrint((
                   2400:                 3,
                   2401:                 "I8042PRT-I8xPutBytePolled: sending 0x%x to data port\n",
                   2402:                 Byte
                   2403:                 ));
                   2404:             I8X_PUT_DATA_BYTE(dataAddress, Byte);
                   2405:         }
                   2406: 
                   2407:         //
                   2408:         // If we don't need to wait for an ACK back from the controller,
                   2409:         // set the status and break out of the for loop.
                   2410:         //
                   2411:         //
                   2412: 
                   2413:         if (WaitForAcknowledge == NO_WAIT_FOR_ACKNOWLEDGE) {
                   2414:             status = STATUS_SUCCESS;
                   2415:             break;
                   2416:         }
                   2417: 
                   2418:         //
                   2419:         // Wait for an ACK back from the controller.  If we get an ACK,
                   2420:         // the operation was successful.  If we get a RESEND, break out to
                   2421:         // the for loop and try the operation again.  Ignore anything other
                   2422:         // than ACK or RESEND.
                   2423:         //
                   2424: 
                   2425:         I8xPrint((3, "I8042PRT-I8xPutBytePolled: waiting for ACK\n"));
                   2426:         keepTrying = FALSE;
                   2427:         while ((status = I8xGetBytePolled(
                   2428:                              AckDeviceType,
                   2429:                              DeviceExtension, 
                   2430:                              &response
                   2431:                              )
                   2432:                ) == STATUS_SUCCESS) {
                   2433: 
                   2434:             if (response == ACKNOWLEDGE) {
                   2435:                 I8xPrint((3, "I8042PRT-I8xPutBytePolled: got ACK\n"));
                   2436:                 break;
                   2437:             } else if (response == RESEND) {
                   2438:                 I8xPrint((3, "I8042PRT-I8xPutBytePolled: got RESEND\n"));
                   2439: 
                   2440:                 if (AckDeviceType == MouseDeviceType) {
                   2441: 
                   2442:                     //
                   2443:                     // We need to precede the "resent" PutByte for the 
                   2444:                     // mouse device with a PutByte that tells the controller 
                   2445:                     // that the next byte sent to the controller should go 
                   2446:                     // to the auxiliary device (by default it would go to 
                   2447:                     // the keyboard device).  We do this by calling 
                   2448:                     // I8xPutBytePolled recursively to send the "send next 
                   2449:                     // byte to auxiliary device" command before resending 
                   2450:                     // the byte to the mouse.  Note that there is only one 
                   2451:                     // level of recursion, since the AckDeviceType for the 
                   2452:                     // recursive call is guaranteed to be UndefinedDeviceType.
                   2453:                     //
                   2454: 
                   2455:                     I8xPutBytePolled(
                   2456:                         (CCHAR) CommandPort,
                   2457:                         NO_WAIT_FOR_ACKNOWLEDGE,
                   2458:                         (CCHAR) UndefinedDeviceType,
                   2459:                         DeviceExtension,
                   2460:                         (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
                   2461:                         );
                   2462:                 }
                   2463: 
                   2464:                 keepTrying = TRUE;
                   2465:                 break;
                   2466:             }
                   2467: 
                   2468:            //
                   2469:            // Ignore any other response, and keep trying.
                   2470:            //
                   2471: 
                   2472:         }
                   2473: 
                   2474:         if (!keepTrying)
                   2475:             break;
                   2476:     }
                   2477: 
                   2478:     //
                   2479:     // Check to see if the number of allowable retries was exceeded.
                   2480:     //
                   2481: 
                   2482:     if (j >= (ULONG)DeviceExtension->Configuration.ResendIterations) {
                   2483:         I8xPrint((
                   2484:             2, 
                   2485:             "I8042PRT-I8xPutBytePolled: exceeded number of retries\n"
                   2486:             ));
                   2487:         status = STATUS_IO_TIMEOUT;
                   2488:     }
                   2489: 
                   2490:     I8xPrint((3, "I8042PRT-I8xPutBytePolled: exit\n"));
                   2491: 
                   2492:     return(status);
                   2493: }
                   2494: 
                   2495: NTSTATUS
                   2496: I8xPutControllerCommand(
                   2497:     IN PDEVICE_EXTENSION DeviceExtension,
                   2498:     IN UCHAR Byte
                   2499:     )
                   2500: 
                   2501: /*++
                   2502: 
                   2503: Routine Description:
                   2504: 
                   2505:     This routine writes the 8042 Controller Command Byte.
                   2506: 
                   2507: Arguments:
                   2508: 
                   2509:     DeviceExtension - Pointer to the device extension.
                   2510: 
                   2511:     Byte - The byte to store in the Controller Command Byte.
                   2512: 
                   2513: Return Value:
                   2514: 
                   2515:     Status is returned.
                   2516: 
                   2517: --*/
                   2518: 
                   2519: {
                   2520:     NTSTATUS status;
                   2521: 
                   2522:     I8xPrint((3, "I8042PRT-I8xPutControllerCommand: enter\n"));
                   2523: 
                   2524:     //
                   2525:     // Send a command to the i8042 controller to write the Controller
                   2526:     // Command Byte.
                   2527:     //
                   2528: 
                   2529:     status = I8xPutBytePolled(
                   2530:                  (CCHAR) CommandPort,
                   2531:                  NO_WAIT_FOR_ACKNOWLEDGE,
                   2532:                  (CCHAR) UndefinedDeviceType, 
                   2533:                  DeviceExtension,
                   2534:                  (UCHAR) I8042_WRITE_CONTROLLER_COMMAND_BYTE
                   2535:                  );
                   2536: 
                   2537:     if (!NT_SUCCESS(status)) {
                   2538:         return(status);
                   2539:     }
                   2540: 
                   2541:     //
                   2542:     // Write the byte through the i8042 data port.
                   2543:     //
                   2544: 
                   2545:     I8xPrint((3, "I8042PRT-I8xPutControllerCommand: exit\n"));
                   2546: 
                   2547:     return(I8xPutBytePolled(
                   2548:                (CCHAR) DataPort,
                   2549:                NO_WAIT_FOR_ACKNOWLEDGE,
                   2550:                (CCHAR) UndefinedDeviceType,
                   2551:                DeviceExtension,
                   2552:                (UCHAR) Byte
                   2553:                )
                   2554:     );
                   2555: }
                   2556: 
                   2557: VOID
                   2558: I8xServiceParameters(
                   2559:     IN PDEVICE_EXTENSION DeviceExtension,
                   2560:     IN PUNICODE_STRING RegistryPath,
                   2561:     IN PUNICODE_STRING KeyboardDeviceName,
                   2562:     IN PUNICODE_STRING PointerDeviceName
                   2563:     )
                   2564: 
                   2565: /*++
                   2566: 
                   2567: Routine Description:
                   2568: 
                   2569:     This routine retrieves this driver's service parameters information 
                   2570:     from the registry.
                   2571: 
                   2572: Arguments:
                   2573: 
                   2574:     DeviceExtension - Pointer to the device extension.
                   2575: 
                   2576:     RegistryPath - Pointer to the null-terminated Unicode name of the 
                   2577:         registry path for this driver.
                   2578: 
                   2579:     KeyboardDeviceName - Pointer to the Unicode string that will receive
                   2580:         the keyboard port device name.
                   2581: 
                   2582:     PointerDeviceName - Pointer to the Unicode string that will receive
                   2583:         the pointer port device name.
                   2584: 
                   2585: Return Value:
                   2586: 
                   2587:     None.  As a side-effect, sets fields in DeviceExtension->Configuration.
                   2588: 
                   2589: --*/
                   2590: 
                   2591: {
                   2592:     PI8042_CONFIGURATION_INFORMATION configuration;
                   2593:     PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
                   2594:     UNICODE_STRING parametersPath;
                   2595:     USHORT defaultResendIterations = I8042_RESEND_DEFAULT;
                   2596:     ULONG resendIterations = 0;
                   2597:     USHORT defaultPollingIterations = I8042_POLLING_DEFAULT;
                   2598:     ULONG pollingIterations = 0;
                   2599:     USHORT defaultPollingIterationsMaximum = I8042_POLLING_MAXIMUM;
                   2600:     ULONG pollingIterationsMaximum = 0;
                   2601:     USHORT defaultPollStatusIterations = I8042_POLLING_DEFAULT;
                   2602:     ULONG pollStatusIterations = 0;
                   2603:     ULONG defaultDataQueueSize = DATA_QUEUE_SIZE;
                   2604:     ULONG numberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
                   2605:     USHORT defaultNumberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
                   2606:     ULONG sampleRate = MOUSE_SAMPLE_RATE;
                   2607:     USHORT defaultSampleRate = MOUSE_SAMPLE_RATE;
                   2608:     ULONG mouseResolution = MOUSE_RESOLUTION;
                   2609:     USHORT defaultMouseResolution = MOUSE_RESOLUTION;
                   2610:     ULONG overrideKeyboardType = 0;
                   2611:     ULONG invalidKeyboardType = 0;
                   2612:     ULONG overrideKeyboardSubtype = (ULONG) -1;
                   2613:     ULONG invalidKeyboardSubtype = (ULONG) -1;
                   2614:     ULONG defaultSynchPacket100ns = MOUSE_SYNCH_PACKET_100NS;
                   2615:     UNICODE_STRING defaultPointerName;
                   2616:     UNICODE_STRING defaultKeyboardName;
                   2617:     NTSTATUS status = STATUS_SUCCESS;
                   2618:     PWSTR path = NULL;
                   2619:     USHORT queriesPlusOne = 15;
                   2620: 
                   2621:     configuration = &DeviceExtension->Configuration;
                   2622:     configuration->StallMicroseconds = I8042_STALL_DEFAULT;
                   2623:     parametersPath.Buffer = NULL;
                   2624: 
                   2625:     //
                   2626:     // Registry path is already null-terminated, so just use it.
                   2627:     //
                   2628: 
                   2629:     path = RegistryPath->Buffer;
                   2630: 
                   2631:     if (NT_SUCCESS(status)) {
                   2632: 
                   2633:         //
                   2634:         // Allocate the Rtl query table.
                   2635:         //
                   2636:     
                   2637:         parameters = ExAllocatePool(
                   2638:                          PagedPool,
                   2639:                          sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
                   2640:                          );
                   2641:     
                   2642:         if (!parameters) {
                   2643:     
                   2644:             I8xPrint((
                   2645:                 1,
                   2646:                 "I8042PRT-I8xServiceParameters: Couldn't allocate table for Rtl query to parameters for %ws\n",
                   2647:                  path
                   2648:                  ));
                   2649:     
                   2650:             status = STATUS_UNSUCCESSFUL;
                   2651:     
                   2652:         } else {
                   2653:     
                   2654:             RtlZeroMemory(
                   2655:                 parameters,
                   2656:                 sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
                   2657:                 );
                   2658:     
                   2659:             //
                   2660:             // Form a path to this driver's Parameters subkey.
                   2661:             //
                   2662:     
                   2663:             RtlInitUnicodeString(
                   2664:                 &parametersPath,
                   2665:                 NULL
                   2666:                 );
                   2667:     
                   2668:             parametersPath.MaximumLength = RegistryPath->Length +
                   2669:                                            sizeof(L"\\Parameters");
                   2670:     
                   2671:             parametersPath.Buffer = ExAllocatePool(
                   2672:                                         PagedPool,
                   2673:                                         parametersPath.MaximumLength
                   2674:                                         );
                   2675:     
                   2676:             if (!parametersPath.Buffer) {
                   2677:     
                   2678:                 I8xPrint((
                   2679:                     1,
                   2680:                     "I8042PRT-I8xServiceParameters: Couldn't allocate string for path to parameters for %ws\n",
                   2681:                      path
                   2682:                     ));
                   2683:     
                   2684:                 status = STATUS_UNSUCCESSFUL;
                   2685:     
                   2686:             }
                   2687:         }
                   2688:     }
                   2689: 
                   2690:     if (NT_SUCCESS(status)) {
                   2691: 
                   2692:         //
                   2693:         // Form the parameters path.
                   2694:         //
                   2695:     
                   2696:         RtlZeroMemory(
                   2697:             parametersPath.Buffer,
                   2698:             parametersPath.MaximumLength
                   2699:             );
                   2700:         RtlAppendUnicodeToString(
                   2701:             &parametersPath,
                   2702:             path
                   2703:             );
                   2704:         RtlAppendUnicodeToString(
                   2705:             &parametersPath,
                   2706:             L"\\Parameters"
                   2707:             );
                   2708:     
                   2709:         I8xPrint((
                   2710:             1,
                   2711:             "I8042PRT-I8xServiceParameters: parameters path is %ws\n",
                   2712:              parametersPath.Buffer
                   2713:             ));
                   2714:     
                   2715:         //
                   2716:         // Form the default port device names, in case they are not
                   2717:         // specified in the registry.
                   2718:         //
                   2719: 
                   2720:         RtlInitUnicodeString(
                   2721:             &defaultKeyboardName,
                   2722:             DD_KEYBOARD_PORT_BASE_NAME_U
                   2723:             );
                   2724:         RtlInitUnicodeString(
                   2725:             &defaultPointerName,
                   2726:             DD_POINTER_PORT_BASE_NAME_U
                   2727:             );
                   2728: 
                   2729:         //
                   2730:         // Gather all of the "user specified" information from
                   2731:         // the registry.
                   2732:         //
                   2733: 
                   2734:         parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2735:         parameters[0].Name = L"ResendIterations";
                   2736:         parameters[0].EntryContext = &resendIterations;
                   2737:         parameters[0].DefaultType = REG_DWORD;
                   2738:         parameters[0].DefaultData = &defaultResendIterations;
                   2739:         parameters[0].DefaultLength = sizeof(USHORT);
                   2740:     
                   2741:         parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2742:         parameters[1].Name = L"PollingIterations";
                   2743:         parameters[1].EntryContext = &pollingIterations;
                   2744:         parameters[1].DefaultType = REG_DWORD;
                   2745:         parameters[1].DefaultData = &defaultPollingIterations;
                   2746:         parameters[1].DefaultLength = sizeof(USHORT);
                   2747:     
                   2748:         parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2749:         parameters[2].Name = L"PollingIterationsMaximum";
                   2750:         parameters[2].EntryContext = &pollingIterationsMaximum;
                   2751:         parameters[2].DefaultType = REG_DWORD;
                   2752:         parameters[2].DefaultData = &defaultPollingIterationsMaximum;
                   2753:         parameters[2].DefaultLength = sizeof(USHORT);
                   2754:     
                   2755:         parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2756:         parameters[3].Name = L"KeyboardDataQueueSize";
                   2757:         parameters[3].EntryContext = 
                   2758:             &configuration->KeyboardAttributes.InputDataQueueLength;
                   2759:         parameters[3].DefaultType = REG_DWORD;
                   2760:         parameters[3].DefaultData = &defaultDataQueueSize;
                   2761:         parameters[3].DefaultLength = sizeof(ULONG);
                   2762:     
                   2763:         parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2764:         parameters[4].Name = L"MouseDataQueueSize";
                   2765:         parameters[4].EntryContext = 
                   2766:             &configuration->MouseAttributes.InputDataQueueLength;
                   2767:         parameters[4].DefaultType = REG_DWORD;
                   2768:         parameters[4].DefaultData = &defaultDataQueueSize;
                   2769:         parameters[4].DefaultLength = sizeof(ULONG);
                   2770:     
                   2771:         parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2772:         parameters[5].Name = L"NumberOfButtons";
                   2773:         parameters[5].EntryContext = &numberOfButtons;
                   2774:         parameters[5].DefaultType = REG_DWORD;
                   2775:         parameters[5].DefaultData = &defaultNumberOfButtons;
                   2776:         parameters[5].DefaultLength = sizeof(USHORT);
                   2777:     
                   2778:         parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2779:         parameters[6].Name = L"SampleRate";
                   2780:         parameters[6].EntryContext = &sampleRate;
                   2781:         parameters[6].DefaultType = REG_DWORD;
                   2782:         parameters[6].DefaultData = &defaultSampleRate;
                   2783:         parameters[6].DefaultLength = sizeof(USHORT);
                   2784:     
                   2785:         parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2786:         parameters[7].Name = L"MouseResolution";
                   2787:         parameters[7].EntryContext = &mouseResolution;
                   2788:         parameters[7].DefaultType = REG_DWORD;
                   2789:         parameters[7].DefaultData = &defaultMouseResolution;
                   2790:         parameters[7].DefaultLength = sizeof(USHORT);
                   2791:     
                   2792:         parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2793:         parameters[8].Name = L"OverrideKeyboardType";
                   2794:         parameters[8].EntryContext = &overrideKeyboardType;
                   2795:         parameters[8].DefaultType = REG_DWORD;
                   2796:         parameters[8].DefaultData = &invalidKeyboardType;
                   2797:         parameters[8].DefaultLength = sizeof(ULONG);
                   2798:     
                   2799:         parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2800:         parameters[9].Name = L"OverrideKeyboardSubtype";
                   2801:         parameters[9].EntryContext = &overrideKeyboardSubtype;
                   2802:         parameters[9].DefaultType = REG_DWORD;
                   2803:         parameters[9].DefaultData = &invalidKeyboardSubtype;
                   2804:         parameters[9].DefaultLength = sizeof(ULONG);
                   2805:     
                   2806:         parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2807:         parameters[10].Name = L"KeyboardDeviceBaseName";
                   2808:         parameters[10].EntryContext = KeyboardDeviceName;
                   2809:         parameters[10].DefaultType = REG_SZ;
                   2810:         parameters[10].DefaultData = defaultKeyboardName.Buffer;
                   2811:         parameters[10].DefaultLength = 0;
                   2812: 
                   2813:         parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2814:         parameters[11].Name = L"PointerDeviceBaseName";
                   2815:         parameters[11].EntryContext = PointerDeviceName;
                   2816:         parameters[11].DefaultType = REG_SZ;
                   2817:         parameters[11].DefaultData = defaultPointerName.Buffer;
                   2818:         parameters[11].DefaultLength = 0;
                   2819: 
                   2820:         parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2821:         parameters[12].Name = L"MouseSynchIn100ns";
                   2822:         parameters[12].EntryContext = 
                   2823:             &DeviceExtension->MouseExtension.SynchTickCount;
                   2824:         parameters[12].DefaultType = REG_DWORD;
                   2825:         parameters[12].DefaultData = &defaultSynchPacket100ns;
                   2826:         parameters[12].DefaultLength = sizeof(ULONG);
                   2827:     
                   2828:         parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT;
                   2829:         parameters[13].Name = L"PollStatusIterations";
                   2830:         parameters[13].EntryContext = &pollStatusIterations;
                   2831:         parameters[13].DefaultType = REG_DWORD;
                   2832:         parameters[13].DefaultData = &defaultPollStatusIterations;
                   2833:         parameters[13].DefaultLength = sizeof(USHORT);
                   2834: 
                   2835:         status = RtlQueryRegistryValues(
                   2836:                      RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
                   2837:                      parametersPath.Buffer,
                   2838:                      parameters,
                   2839:                      NULL,
                   2840:                      NULL
                   2841:                      );
                   2842: 
                   2843:         if (!NT_SUCCESS(status)) {
                   2844:             I8xPrint((
                   2845:                 1,
                   2846:                 "I8042PRT-I8xServiceParameters: RtlQueryRegistryValues failed with 0x%x\n",
                   2847:                 status
                   2848:                 ));
                   2849:         }
                   2850:     }
                   2851: 
                   2852:     if (!NT_SUCCESS(status)) {
                   2853: 
                   2854:         //
                   2855:         // Go ahead and assign driver defaults.
                   2856:         //
                   2857: 
                   2858:         configuration->ResendIterations = defaultResendIterations;
                   2859:         configuration->PollingIterations = defaultPollingIterations;
                   2860:         configuration->PollingIterationsMaximum = 
                   2861:             defaultPollingIterationsMaximum;
                   2862:         configuration->PollStatusIterations = defaultPollStatusIterations;
                   2863:         configuration->KeyboardAttributes.InputDataQueueLength = 
                   2864:             defaultDataQueueSize;
                   2865:         configuration->MouseAttributes.InputDataQueueLength = 
                   2866:             defaultDataQueueSize;
                   2867:         DeviceExtension->MouseExtension.SynchTickCount =
                   2868:             defaultSynchPacket100ns;
                   2869:         RtlCopyUnicodeString(KeyboardDeviceName, &defaultKeyboardName);
                   2870:         RtlCopyUnicodeString(PointerDeviceName, &defaultPointerName);
                   2871:     } else {
                   2872:         configuration->ResendIterations = (USHORT) resendIterations;
                   2873:         configuration->PollingIterations = (USHORT) pollingIterations;
                   2874:         configuration->PollingIterationsMaximum = 
                   2875:             (USHORT) pollingIterationsMaximum;
                   2876:         configuration->PollStatusIterations = (USHORT) pollStatusIterations;
                   2877:     }
                   2878: 
                   2879:     I8xPrint((
                   2880:         1,
                   2881:         "I8042PRT-I8xServiceParameters: Keyboard port base name = %ws\n",
                   2882:         KeyboardDeviceName->Buffer
                   2883:         ));
                   2884: 
                   2885:     I8xPrint((
                   2886:         1,
                   2887:         "I8042PRT-I8xServiceParameters: Pointer port base name = %ws\n",
                   2888:         PointerDeviceName->Buffer
                   2889:         ));
                   2890: 
                   2891:     I8xPrint((
                   2892:         1,
                   2893:         "I8042PRT-I8xServiceParameters: StallMicroseconds = %d\n",
                   2894:         configuration->StallMicroseconds 
                   2895:         ));
                   2896:     I8xPrint((
                   2897:         1,
                   2898:         "I8042PRT-I8xServiceParameters: ResendIterations = %d\n",
                   2899:         configuration->ResendIterations
                   2900:         ));
                   2901:     I8xPrint((
                   2902:         1,
                   2903:         "I8042PRT-I8xServiceParameters: PollingIterations = %d\n",
                   2904:         configuration->PollingIterations
                   2905:         ));
                   2906:     I8xPrint((
                   2907:         1,
                   2908:         "I8042PRT-I8xServiceParameters: PollingIterationsMaximum = %d\n",
                   2909:         configuration->PollingIterationsMaximum
                   2910:         ));
                   2911:     I8xPrint((
                   2912:         1,
                   2913:         "I8042PRT-I8xServiceParameters: PollStatusIterations = %d\n",
                   2914:         configuration->PollStatusIterations
                   2915:         ));
                   2916: 
                   2917:     if (configuration->KeyboardAttributes.InputDataQueueLength == 0) {
                   2918: 
                   2919:         I8xPrint((
                   2920:             1,
                   2921:             "I8042PRT-I8xServiceParameters: overriding KeyboardInputDataQueueLength = 0x%x\n",
                   2922:             configuration->KeyboardAttributes.InputDataQueueLength
                   2923:             ));
                   2924: 
                   2925:         configuration->KeyboardAttributes.InputDataQueueLength = 
                   2926:             defaultDataQueueSize;
                   2927:     }
                   2928: 
                   2929:     configuration->KeyboardAttributes.InputDataQueueLength *= 
                   2930:         sizeof(KEYBOARD_INPUT_DATA);
                   2931: 
                   2932:     I8xPrint((
                   2933:         1,
                   2934:         "I8042PRT-I8xServiceParameters: KeyboardInputDataQueueLength = 0x%x\n",
                   2935:         configuration->KeyboardAttributes.InputDataQueueLength
                   2936:         ));
                   2937: 
                   2938:     if (configuration->MouseAttributes.InputDataQueueLength == 0) {
                   2939: 
                   2940:         I8xPrint((
                   2941:             1,
                   2942:             "I8042PRT-I8xServiceParameters: overriding MouseInputDataQueueLength = 0x%x\n",
                   2943:             configuration->MouseAttributes.InputDataQueueLength
                   2944:             ));
                   2945: 
                   2946:         configuration->MouseAttributes.InputDataQueueLength = 
                   2947:             defaultDataQueueSize;
                   2948:     }
                   2949: 
                   2950:     configuration->MouseAttributes.InputDataQueueLength *= 
                   2951:         sizeof(MOUSE_INPUT_DATA);
                   2952: 
                   2953:     I8xPrint((
                   2954:         1,
                   2955:         "I8042PRT-I8xServiceParameters: MouseInputDataQueueLength = 0x%x\n",
                   2956:         configuration->MouseAttributes.InputDataQueueLength
                   2957:         ));
                   2958: 
                   2959:     configuration->MouseAttributes.NumberOfButtons = numberOfButtons;
                   2960:     I8xPrint((
                   2961:         1,
                   2962:         "I8042PRT-I8xServiceParameters: NumberOfButtons = %d\n",
                   2963:         configuration->MouseAttributes.NumberOfButtons
                   2964:         ));
                   2965: 
                   2966:     configuration->MouseAttributes.SampleRate = sampleRate;
                   2967:     I8xPrint((
                   2968:         1,
                   2969:         "I8042PRT-I8xServiceParameters: SampleRate = %d\n",
                   2970:         configuration->MouseAttributes.SampleRate
                   2971:         ));
                   2972: 
                   2973:     configuration->MouseResolution = mouseResolution;
                   2974:     I8xPrint((
                   2975:         1,
                   2976:         "I8042PRT-I8xServiceParameters: MouseResolution = %d\n",
                   2977:         configuration->MouseResolution
                   2978:         ));
                   2979: 
                   2980:     if (overrideKeyboardType != invalidKeyboardType) {
                   2981:         if (overrideKeyboardType <= NUM_KNOWN_KEYBOARD_TYPES) {
                   2982:             I8xPrint((
                   2983:                 1,
                   2984:                 "I8042PRT-I8xServiceParameters: Override KeyboardType = %d\n",
                   2985:                 overrideKeyboardType
                   2986:                 ));
                   2987:             configuration->KeyboardAttributes.KeyboardIdentifier.Type =
                   2988:                 (UCHAR) overrideKeyboardType;
                   2989:         } else {
                   2990:             I8xPrint((
                   2991:                 1,
                   2992:                 "I8042PRT-I8xServiceParameters: Invalid OverrideKeyboardType = %d\n",
                   2993:                 overrideKeyboardType
                   2994:                 ));
                   2995:         }
                   2996:     }
                   2997: 
                   2998:     if (overrideKeyboardSubtype != invalidKeyboardSubtype) {
                   2999:         I8xPrint((
                   3000:             1,
                   3001:             "I8042PRT-I8xServiceParameters: Override KeyboardSubtype = %d\n",
                   3002:             overrideKeyboardSubtype
                   3003:             ));
                   3004:         configuration->KeyboardAttributes.KeyboardIdentifier.Subtype =
                   3005:             (UCHAR) overrideKeyboardSubtype;
                   3006:     }
                   3007: 
                   3008:     if (DeviceExtension->MouseExtension.SynchTickCount == 0) {
                   3009: 
                   3010:         I8xPrint((
                   3011:             1,
                   3012:             "I8042PRT-I8xServiceParameters: overriding MouseSynchIn100ns\n"
                   3013:             ));
                   3014: 
                   3015:         DeviceExtension->MouseExtension.SynchTickCount =
                   3016:             defaultSynchPacket100ns;
                   3017:     }
                   3018: 
                   3019:     //
                   3020:     // Convert SynchTickCount to be the number of interval timer
                   3021:     // interrupts that occur during the time specified by MouseSynchIn100ns.
                   3022:     // Note that KeQueryTimeIncrement returns the number of 100ns units that 
                   3023:     // are added to the system time each time the interval clock interrupts.
                   3024:     //
                   3025: 
                   3026:     DeviceExtension->MouseExtension.SynchTickCount /= KeQueryTimeIncrement();
                   3027: 
                   3028:     I8xPrint((
                   3029:         1,
                   3030:         "I8042PRT-I8xServiceParameters: SynchTickCount = 0x%x\n",
                   3031:         DeviceExtension->MouseExtension.SynchTickCount
                   3032:         ));
                   3033: 
                   3034:     //
                   3035:     // Free the allocated memory before returning.
                   3036:     //
                   3037: 
                   3038:     if (parametersPath.Buffer)
                   3039:         ExFreePool(parametersPath.Buffer);
                   3040:     if (parameters)
                   3041:         ExFreePool(parameters);
                   3042: 
                   3043: }
                   3044: 
                   3045: VOID
                   3046: I8xTransmitControllerCommand(
                   3047:     IN PDEVICE_EXTENSION DeviceExtension,
                   3048:     IN PVOID Context
                   3049:     )
                   3050: 
                   3051: /*++
                   3052: 
                   3053: Routine Description:
                   3054: 
                   3055:     This routine reads the 8042 Controller Command Byte, performs an AND
                   3056:     or OR operation using the specified ByteMask, and writes the resulting
                   3057:     ControllerCommandByte.
                   3058: 
                   3059: Arguments:
                   3060: 
                   3061:     DeviceExtension - Pointer to the device extension.
                   3062: 
                   3063:     Context - Pointer to a structure containing the HardwareDisableEnableMask,
                   3064:         the AndOperation boolean, and the ByteMask to apply to the Controller
                   3065:         Command Byte before it is rewritten.
                   3066: 
                   3067: Return Value:
                   3068: 
                   3069:     None.  Status is returned in the Context structure.
                   3070: 
                   3071: --*/
                   3072: 
                   3073: {
                   3074:     UCHAR  controllerCommandByte;
                   3075:     UCHAR  verifyCommandByte;
                   3076:     PI8042_TRANSMIT_CCB_CONTEXT transmitCCBContext;
                   3077:     PIO_ERROR_LOG_PACKET errorLogEntry;
                   3078: 
                   3079:     I8xPrint((3, "I8042PRT-I8xTransmitControllerCommand: enter\n"));
                   3080: 
                   3081:     //
                   3082:     // Grab the parameters from the Context structure.
                   3083:     //
                   3084: 
                   3085:     transmitCCBContext = (PI8042_TRANSMIT_CCB_CONTEXT) Context;
                   3086: 
                   3087:     //
                   3088:     // Get the current Controller Command Byte.
                   3089:     //
                   3090: 
                   3091:     transmitCCBContext->Status =
                   3092:         I8xGetControllerCommand(
                   3093:             transmitCCBContext->HardwareDisableEnableMask,
                   3094:             DeviceExtension,
                   3095:             &controllerCommandByte
                   3096:             );
                   3097: 
                   3098:     if (!NT_SUCCESS(transmitCCBContext->Status)) {
                   3099:         return;
                   3100:     }
                   3101: 
                   3102:     I8xPrint((
                   3103:         3,
                   3104:         "I8042PRT-I8xTransmitControllerCommand: current CCB 0x%x\n",
                   3105:         controllerCommandByte
                   3106:         ));
                   3107: 
                   3108:     //
                   3109:     // Diddle the desired bits in the Controller Command Byte.
                   3110:     //
                   3111: 
                   3112:     if (transmitCCBContext->AndOperation)
                   3113:         controllerCommandByte &= transmitCCBContext->ByteMask;
                   3114:     else
                   3115:         controllerCommandByte |= transmitCCBContext->ByteMask;
                   3116: 
                   3117:     //
                   3118:     // Write the new Controller Command Byte.
                   3119:     //
                   3120: 
                   3121:     transmitCCBContext->Status =
                   3122:         I8xPutControllerCommand(DeviceExtension, controllerCommandByte);
                   3123: 
                   3124:     I8xPrint((
                   3125:         3,
                   3126:         "I8042PRT-I8xTransmitControllerCommand: new CCB 0x%x\n",
                   3127:         controllerCommandByte
                   3128:         ));
                   3129: 
                   3130:     //
                   3131:     // Verify that the new Controller Command Byte really got written.
                   3132:     //
                   3133: 
                   3134:     transmitCCBContext->Status =
                   3135:         I8xGetControllerCommand(
                   3136:             transmitCCBContext->HardwareDisableEnableMask,
                   3137:             DeviceExtension,
                   3138:             &verifyCommandByte
                   3139:             );
                   3140: 
                   3141:     if (NT_SUCCESS(transmitCCBContext->Status) 
                   3142:         && (verifyCommandByte != controllerCommandByte)) {
                   3143:             transmitCCBContext->Status = STATUS_DEVICE_DATA_ERROR;
                   3144: 
                   3145:         //
                   3146:         // Log an error.
                   3147:         //
                   3148:     
                   3149:         errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
                   3150:                                                   DeviceExtension->DeviceObject,
                   3151:                                                   sizeof(IO_ERROR_LOG_PACKET)
                   3152:                                                   + (4 * sizeof(ULONG))
                   3153:                                                   );
                   3154:         if (errorLogEntry != NULL) {
                   3155:     
                   3156:             errorLogEntry->ErrorCode = I8042_CCB_WRITE_FAILED;
                   3157:             errorLogEntry->DumpDataSize = 4 * sizeof(ULONG); 
                   3158:             errorLogEntry->SequenceNumber = 0; 
                   3159:             errorLogEntry->MajorFunctionCode = 0;
                   3160:             errorLogEntry->IoControlCode = 0;
                   3161:             errorLogEntry->RetryCount = 0;
                   3162:             errorLogEntry->UniqueErrorValue = 80;
                   3163:             errorLogEntry->FinalStatus = transmitCCBContext->Status;
                   3164:             errorLogEntry->DumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
                   3165:             errorLogEntry->DumpData[1] = DataPort;
                   3166:             errorLogEntry->DumpData[2] = I8042_WRITE_CONTROLLER_COMMAND_BYTE;
                   3167:             errorLogEntry->DumpData[3] = controllerCommandByte;
                   3168:     
                   3169:             IoWriteErrorLogEntry(errorLogEntry);
                   3170:         }
                   3171: 
                   3172:     }
                   3173: 
                   3174:     I8xPrint((3, "I8042PRT-I8xTransmitControllerCommand: exit\n"));
                   3175: 
                   3176:     return;
                   3177: 
                   3178: }
                   3179: 

unix.superglobalmegacorp.com

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