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

1.1     ! root        1: 
        !             2: /*++
        !             3: 
        !             4: Copyright (c) 1990, 1991, 1992, 1993  Microsoft Corporation
        !             5: 
        !             6: Module Name:
        !             7: 
        !             8:     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.