Annotation of ntddk/src/input/inport/i386/inpdep.c, revision 1.1

1.1     ! root        1: #if defined(i386)
        !             2: 
        !             3: /*++
        !             4: 
        !             5: Copyright (c) 1989, 1990, 1991, 1992, 1993  Microsoft Corporation
        !             6: 
        !             7: Module Name:
        !             8: 
        !             9:     inpdep.c
        !            10: 
        !            11: Abstract:
        !            12: 
        !            13:     The initialization and hardware-dependent portions of
        !            14:     the Microsoft InPort mouse port driver.  Modifications to
        !            15:     support new mice similar to the InPort mouse should be
        !            16:     localized to this file.
        !            17: 
        !            18: Environment:
        !            19: 
        !            20:     Kernel mode only.
        !            21: 
        !            22: Notes:
        !            23: 
        !            24:     NOTES:  (Future/outstanding issues)
        !            25: 
        !            26:     - Powerfail not implemented.
        !            27: 
        !            28:     - Consolidate duplicate code, where possible and appropriate.
        !            29: 
        !            30: Revision History:
        !            31: 
        !            32: --*/
        !            33: 
        !            34: #include "stdarg.h"
        !            35: #include "stdio.h"
        !            36: #include "string.h"
        !            37: #include "ntddk.h"
        !            38: #include "inport.h"
        !            39: #include "inplog.h"
        !            40: 
        !            41: //
        !            42: // Use the alloc_text pragma to specify the driver initialization routines
        !            43: // (they can be paged out).
        !            44: //
        !            45: 
        !            46: #ifdef ALLOC_PRAGMA
        !            47: #pragma alloc_text(init,DriverEntry)
        !            48: #pragma alloc_text(init,InpConfiguration)
        !            49: #pragma alloc_text(init,InpPeripheralCallout)
        !            50: #pragma alloc_text(init,InpServiceParameters)
        !            51: #pragma alloc_text(init,InpInitializeHardware)
        !            52: #pragma alloc_text(init,InpBuildResourceList)
        !            53: #endif
        !            54: 
        !            55: 
        !            56: NTSTATUS
        !            57: DriverEntry(
        !            58:     IN PDRIVER_OBJECT DriverObject,
        !            59:     IN PUNICODE_STRING RegistryPath
        !            60:     )
        !            61: 
        !            62: /*++
        !            63: 
        !            64: Routine Description:
        !            65: 
        !            66:     This routine initializes the Inport mouse port driver.
        !            67: 
        !            68: Arguments:
        !            69: 
        !            70:     DriverObject - Pointer to driver object created by system.
        !            71: 
        !            72:     RegistryPath - Pointer to the Unicode name of the registry path
        !            73:         for this driver.
        !            74: 
        !            75: Return Value:
        !            76: 
        !            77:     The function value is the final status from the initialization operation.
        !            78: 
        !            79: --*/
        !            80: 
        !            81: {
        !            82:     PDEVICE_OBJECT portDeviceObject =  NULL;
        !            83:     PDEVICE_EXTENSION deviceExtension = NULL;
        !            84:     DEVICE_EXTENSION tmpDeviceExtension;
        !            85:     NTSTATUS status = STATUS_SUCCESS;
        !            86:     KIRQL coordinatorIrql = 0;
        !            87:     ULONG interruptVector;
        !            88:     KIRQL interruptLevel;
        !            89:     PIO_ERROR_LOG_PACKET errorLogEntry;
        !            90:     ULONG uniqueErrorValue;
        !            91:     ULONG dumpCount;
        !            92:     NTSTATUS errorCode = STATUS_SUCCESS;
        !            93:     PCM_RESOURCE_LIST resources = NULL;
        !            94:     ULONG resourceListSize = 0;
        !            95:     BOOLEAN conflictDetected;
        !            96:     KAFFINITY affinity;
        !            97:     ULONG addressSpace;
        !            98:     PHYSICAL_ADDRESS cardAddress;
        !            99:     ULONG i;
        !           100:     UNICODE_STRING fullDeviceName;
        !           101:     UNICODE_STRING baseDeviceName;
        !           102:     UNICODE_STRING deviceNameSuffix;
        !           103:     UNICODE_STRING registryPath;
        !           104: 
        !           105: #define NAME_MAX 256
        !           106:     WCHAR nameBuffer[NAME_MAX];
        !           107: 
        !           108: #define DUMP_COUNT 4
        !           109:     ULONG dumpData[DUMP_COUNT];
        !           110: 
        !           111: 
        !           112:     InpPrint((1,"\n\nINPORT-InportInitialize: enter\n"));
        !           113: 
        !           114:     //
        !           115:     // Zero-initialize various structures.
        !           116:     //
        !           117: 
        !           118:     RtlZeroMemory(&tmpDeviceExtension, sizeof(tmpDeviceExtension));
        !           119:     for (i = 0; i < DUMP_COUNT; i++)
        !           120:         dumpData[i] = 0;
        !           121: 
        !           122:     fullDeviceName.MaximumLength = 0;
        !           123:     deviceNameSuffix.MaximumLength = 0;
        !           124:     registryPath.MaximumLength = 0;
        !           125: 
        !           126:     RtlZeroMemory(nameBuffer, NAME_MAX * sizeof(WCHAR));
        !           127:     baseDeviceName.Buffer = nameBuffer;
        !           128:     baseDeviceName.Length = 0;
        !           129:     baseDeviceName.MaximumLength = NAME_MAX * sizeof(WCHAR);
        !           130: 
        !           131:     //
        !           132:     // Need to ensure that the registry path is null-terminated.
        !           133:     // Allocate pool to hold a null-terminated copy of the path.
        !           134:     //
        !           135: 
        !           136:     registryPath.Buffer = ExAllocatePool(
        !           137:                               PagedPool,
        !           138:                               RegistryPath->Length + sizeof(UNICODE_NULL)
        !           139:                               );
        !           140: 
        !           141:     if (!registryPath.Buffer) {
        !           142:         InpPrint((
        !           143:             1,
        !           144:             "INPORT-InportInitialize: Couldn't allocate pool for registry path\n"
        !           145:             ));
        !           146: 
        !           147:         status = STATUS_UNSUCCESSFUL;
        !           148:         errorCode = INPORT_INSUFFICIENT_RESOURCES;
        !           149:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 2;
        !           150:         dumpData[0] = (ULONG) RegistryPath->Length + sizeof(UNICODE_NULL);
        !           151:         dumpCount = 1;
        !           152:         goto InportInitializeExit;
        !           153: 
        !           154:     } else {
        !           155: 
        !           156:         registryPath.Length = RegistryPath->Length + sizeof(UNICODE_NULL);
        !           157:         registryPath.MaximumLength = registryPath.Length;
        !           158: 
        !           159:         RtlZeroMemory(
        !           160:             registryPath.Buffer,
        !           161:             registryPath.Length
        !           162:                 );
        !           163: 
        !           164:         RtlMoveMemory(
        !           165:             registryPath.Buffer,
        !           166:             RegistryPath->Buffer,
        !           167:             RegistryPath->Length
        !           168:             );
        !           169: 
        !           170:     }
        !           171: 
        !           172:     //
        !           173:     // Get the configuration information for this driver.
        !           174:     //
        !           175: 
        !           176:     InpConfiguration(&tmpDeviceExtension, &registryPath, &baseDeviceName);
        !           177: 
        !           178:     if (tmpDeviceExtension.HardwarePresent == FALSE) {
        !           179: 
        !           180:         //
        !           181:         // There is no Inport mouse attached.  Return unsuccessful status.
        !           182:         //
        !           183: 
        !           184:         InpPrint((1,"INPORT-InportInitialize: No mouse attached.\n"));
        !           185:         status = STATUS_NO_SUCH_DEVICE;
        !           186:         errorCode = INPORT_NO_SUCH_DEVICE;
        !           187:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 4;
        !           188:         dumpCount = 0;
        !           189:         goto InportInitializeExit;
        !           190: 
        !           191:     }
        !           192: 
        !           193:     //
        !           194:     // Set up space for the port's device object suffix.  Note that
        !           195:     // we overallocate space for the suffix string because it is much
        !           196:     // easier than figuring out exactly how much space is required.
        !           197:     // The storage gets freed at the end of driver initialization, so
        !           198:     // who cares...
        !           199:     //
        !           200: 
        !           201:     RtlInitUnicodeString(
        !           202:         &deviceNameSuffix,
        !           203:         NULL
        !           204:         );
        !           205:     
        !           206:     deviceNameSuffix.MaximumLength = POINTER_PORTS_MAXIMUM * sizeof(WCHAR);
        !           207:     deviceNameSuffix.MaximumLength += sizeof(UNICODE_NULL);
        !           208:     
        !           209:     deviceNameSuffix.Buffer = ExAllocatePool(
        !           210:                                   PagedPool,
        !           211:                                   deviceNameSuffix.MaximumLength
        !           212:                                   );
        !           213:     
        !           214:     if (!deviceNameSuffix.Buffer) {
        !           215:     
        !           216:         InpPrint((
        !           217:             1,
        !           218:             "INPORT-InportInitialize: Couldn't allocate string for device object suffix\n"
        !           219:             ));
        !           220:     
        !           221:         status = STATUS_UNSUCCESSFUL;
        !           222:         errorCode = INPORT_INSUFFICIENT_RESOURCES;
        !           223:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 6;
        !           224:         dumpData[0] = (ULONG) deviceNameSuffix.MaximumLength;
        !           225:         dumpCount = 1;
        !           226:         goto InportInitializeExit;
        !           227:     
        !           228:     }
        !           229: 
        !           230:     RtlZeroMemory(
        !           231:         deviceNameSuffix.Buffer,
        !           232:         deviceNameSuffix.MaximumLength
        !           233:         );
        !           234: 
        !           235:     //
        !           236:     // Set up space for the port's full device object name.  
        !           237:     //
        !           238: 
        !           239:     RtlInitUnicodeString(
        !           240:         &fullDeviceName,
        !           241:         NULL
        !           242:         );
        !           243:     
        !           244:     fullDeviceName.MaximumLength = sizeof(L"\\Device\\") +
        !           245:                                       baseDeviceName.Length +
        !           246:                                       deviceNameSuffix.MaximumLength;
        !           247:                                       
        !           248:     
        !           249:     fullDeviceName.Buffer = ExAllocatePool(
        !           250:                                    PagedPool,
        !           251:                                    fullDeviceName.MaximumLength
        !           252:                                    );
        !           253:     
        !           254:     if (!fullDeviceName.Buffer) {
        !           255:     
        !           256:         InpPrint((
        !           257:             1,
        !           258:             "INPORT-InportInitialize: Couldn't allocate string for device object name\n"
        !           259:             ));
        !           260:     
        !           261:         status = STATUS_UNSUCCESSFUL;
        !           262:         errorCode = INPORT_INSUFFICIENT_RESOURCES;
        !           263:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 8;
        !           264:         dumpData[0] = (ULONG) fullDeviceName.MaximumLength;
        !           265:         dumpCount = 1;
        !           266:         goto InportInitializeExit;
        !           267:     
        !           268:     }
        !           269: 
        !           270:     RtlZeroMemory(
        !           271:         fullDeviceName.Buffer,
        !           272:         fullDeviceName.MaximumLength
        !           273:         );
        !           274:     RtlAppendUnicodeToString(
        !           275:         &fullDeviceName,
        !           276:         L"\\Device\\"
        !           277:         );
        !           278:     RtlAppendUnicodeToString(
        !           279:         &fullDeviceName,
        !           280:         baseDeviceName.Buffer
        !           281:         );
        !           282: 
        !           283:     for (i = 0; i < POINTER_PORTS_MAXIMUM; i++) {
        !           284:     
        !           285:         //
        !           286:         // Append the suffix to the device object name string.  E.g., turn
        !           287:         // \Device\PointerPort into \Device\PointerPort0.  Then we attempt
        !           288:         // to create the device object.  If the device object already
        !           289:         // exists (because it was already created by another port driver),
        !           290:         // increment the suffix and try again.
        !           291:         //
        !           292: 
        !           293:         status = RtlIntegerToUnicodeString(
        !           294:                      i,
        !           295:                      10,
        !           296:                      &deviceNameSuffix
        !           297:                      );
        !           298: 
        !           299:         if (!NT_SUCCESS(status)) {
        !           300:             break; 
        !           301:         }
        !           302: 
        !           303:         RtlAppendUnicodeStringToString(
        !           304:             &fullDeviceName,
        !           305:             &deviceNameSuffix
        !           306:         );
        !           307: 
        !           308:         InpPrint((
        !           309:             1,
        !           310:             "INPORT-InportInitialize: Creating device object named %ws\n",
        !           311:             fullDeviceName.Buffer
        !           312:             ));
        !           313: 
        !           314:         //
        !           315:         // Create a non-exclusive device object for the Inport mouse 
        !           316:         // port device.
        !           317:         //
        !           318: 
        !           319:         status = IoCreateDevice(
        !           320:                     DriverObject,
        !           321:                     sizeof(DEVICE_EXTENSION),
        !           322:                     &fullDeviceName,
        !           323:                     FILE_DEVICE_INPORT_PORT,
        !           324:                     0,
        !           325:                     FALSE,
        !           326:                     &portDeviceObject
        !           327:                     );
        !           328: 
        !           329:         if (NT_SUCCESS(status)) {
        !           330: 
        !           331:             //
        !           332:             // We've successfully created a device object.
        !           333:             //
        !           334: 
        !           335:             break; 
        !           336:         } else {
        !           337: 
        !           338:            //
        !           339:            // We'll increment the suffix and try again.  Note that we reset
        !           340:            // the length of the string here to get back to the beginning
        !           341:            // of the suffix portion of the name.  Do not bother to
        !           342:            // zero the suffix, though, because the string for the 
        !           343:            // incremented suffix will be at least as long as the previous
        !           344:            // one.
        !           345:            //
        !           346: 
        !           347:            fullDeviceName.Length -= deviceNameSuffix.Length;
        !           348:         }
        !           349:     }
        !           350: 
        !           351:     if (!NT_SUCCESS(status)) {
        !           352:         InpPrint((
        !           353:             1,
        !           354:             "INPORT-InportInitialize: Could not create port device object = %ws\n",
        !           355:             fullDeviceName.Buffer
        !           356:             ));
        !           357:         errorCode = INPORT_INSUFFICIENT_RESOURCES;
        !           358:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 10;
        !           359:         dumpData[0] = (ULONG) i;
        !           360:         dumpCount = 1;
        !           361:         goto InportInitializeExit;
        !           362:     } 
        !           363: 
        !           364:     //
        !           365:     // Do buffered I/O.  I.e., the I/O system will copy to/from user data
        !           366:     // from/to a system buffer.
        !           367:     //
        !           368: 
        !           369:     portDeviceObject->Flags |= DO_BUFFERED_IO;
        !           370: 
        !           371:     //
        !           372:     // Set up the device extension.
        !           373:     //
        !           374: 
        !           375:     deviceExtension =
        !           376:         (PDEVICE_EXTENSION) portDeviceObject->DeviceExtension;
        !           377:     *deviceExtension = tmpDeviceExtension;
        !           378:     deviceExtension->DeviceObject = portDeviceObject;
        !           379: 
        !           380:     //
        !           381:     // Set up the device resource list prior to reporting resource usage.
        !           382:     //
        !           383: 
        !           384:     InpBuildResourceList(deviceExtension, &resources, &resourceListSize);
        !           385: 
        !           386:     //
        !           387:     // Report resource usage for the registry.
        !           388:     //
        !           389: 
        !           390:     IoReportResourceUsage(
        !           391:         &baseDeviceName, 
        !           392:         DriverObject,
        !           393:         NULL,
        !           394:         0,
        !           395:         portDeviceObject,
        !           396:         resources, 
        !           397:         resourceListSize,
        !           398:         FALSE,
        !           399:         &conflictDetected
        !           400:         );
        !           401: 
        !           402:     if (conflictDetected) {
        !           403: 
        !           404:         //
        !           405:         // Some other device already owns the ports or interrupts.
        !           406:         // Fatal error.
        !           407:         //
        !           408: 
        !           409:         InpPrint((
        !           410:             1,
        !           411:             "INPORT-InportInitialize: Resource usage conflict\n"
        !           412:             ));
        !           413: 
        !           414:         //
        !           415:         // Log an error.
        !           416:         //
        !           417: 
        !           418:         errorCode = INPORT_RESOURCE_CONFLICT;
        !           419:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 15;
        !           420:         dumpData[0] =  (ULONG) 
        !           421:             resources->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Level;
        !           422:         dumpData[1] = (ULONG)
        !           423:             resources->List[0].PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector;
        !           424:         dumpData[2] = (ULONG)
        !           425:             resources->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Level;
        !           426:         dumpData[3] = (ULONG)
        !           427:             resources->List[0].PartialResourceList.PartialDescriptors[1].u.Interrupt.Vector;
        !           428:         dumpCount = 4;
        !           429: 
        !           430:         goto InportInitializeExit;
        !           431: 
        !           432:     }
        !           433: 
        !           434:     //
        !           435:     // Map the Inport controller registers.
        !           436:     //
        !           437: 
        !           438:     addressSpace = (deviceExtension->Configuration.PortList[0].Flags 
        !           439:                        & CM_RESOURCE_PORT_IO) == CM_RESOURCE_PORT_IO? 1:0;
        !           440:     HalTranslateBusAddress(
        !           441:         deviceExtension->Configuration.InterfaceType,
        !           442:         deviceExtension->Configuration.BusNumber,
        !           443:         deviceExtension->Configuration.PortList[0].u.Port.Start,
        !           444:         &addressSpace,
        !           445:         &cardAddress
        !           446:         );
        !           447: 
        !           448:     if (!addressSpace) {
        !           449: 
        !           450:         deviceExtension->Configuration.UnmapRegistersRequired = TRUE;
        !           451:         deviceExtension->Configuration.DeviceRegisters[0] = 
        !           452:             MmMapIoSpace(
        !           453:                 cardAddress,
        !           454:                 deviceExtension->Configuration.PortList[0].u.Port.Length,
        !           455:                 FALSE
        !           456:                 );
        !           457: 
        !           458:     } else {
        !           459: 
        !           460:         deviceExtension->Configuration.UnmapRegistersRequired = FALSE;
        !           461:         deviceExtension->Configuration.DeviceRegisters[0] = 
        !           462:             (PVOID)cardAddress.LowPart;
        !           463: 
        !           464:     }
        !           465: 
        !           466:     if (!deviceExtension->Configuration.DeviceRegisters[0]) {
        !           467: 
        !           468:         InpPrint((
        !           469:             1, 
        !           470:             "INPORT-InportInitialize: Couldn't map the device registers.\n"
        !           471:             ));
        !           472:         deviceExtension->Configuration.UnmapRegistersRequired = FALSE;
        !           473:         status = STATUS_NONE_MAPPED;
        !           474: 
        !           475:         //
        !           476:         // Log an error.
        !           477:         //
        !           478: 
        !           479:         errorCode = INPORT_REGISTERS_NOT_MAPPED;
        !           480:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 20;
        !           481:         dumpData[0] = cardAddress.LowPart;
        !           482:         dumpCount = 1;
        !           483: 
        !           484:         goto InportInitializeExit;
        !           485: 
        !           486:     }
        !           487: 
        !           488:     //
        !           489:     // Initialize the Inport hardware to default values for the mouse.  Note
        !           490:     // that interrupts remain disabled until the class driver
        !           491:     // requests a MOUSE_CONNECT internal device control.
        !           492:     //
        !           493: 
        !           494:     status = InpInitializeHardware(portDeviceObject);
        !           495: 
        !           496:     if (!NT_SUCCESS(status)) {
        !           497:         InpPrint((
        !           498:             1,
        !           499:             "INPORT-InportInitialize: Could not initialize hardware\n"
        !           500:             ));
        !           501:         goto InportInitializeExit;
        !           502:     } 
        !           503: 
        !           504: 
        !           505:     //
        !           506:     // Allocate the ring buffer for the mouse input data.
        !           507:     //
        !           508: 
        !           509:     deviceExtension->InputData = 
        !           510:         ExAllocatePool(
        !           511:             NonPagedPool,
        !           512:             deviceExtension->Configuration.MouseAttributes.InputDataQueueLength
        !           513:             );
        !           514: 
        !           515:     if (!deviceExtension->InputData) {
        !           516:    
        !           517:         //
        !           518:         // Could not allocate memory for the mouse data queue.
        !           519:         //
        !           520: 
        !           521:         InpPrint((
        !           522:             1,
        !           523:             "INPORT-InportInitialize: Could not allocate mouse input data queue\n"
        !           524:             ));
        !           525: 
        !           526:         status = STATUS_INSUFFICIENT_RESOURCES;
        !           527: 
        !           528:         //
        !           529:         // Log an error.
        !           530:         //
        !           531: 
        !           532:         errorCode = INPORT_NO_BUFFER_ALLOCATED;
        !           533:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 30;
        !           534:         dumpData[0] = 
        !           535:             deviceExtension->Configuration.MouseAttributes.InputDataQueueLength;
        !           536:         dumpCount = 1;
        !           537: 
        !           538:         goto InportInitializeExit;
        !           539:     }
        !           540: 
        !           541:     deviceExtension->DataEnd =
        !           542:         (PMOUSE_INPUT_DATA)  ((PCHAR) (deviceExtension->InputData) 
        !           543:         + deviceExtension->Configuration.MouseAttributes.InputDataQueueLength);
        !           544: 
        !           545:     //
        !           546:     // Zero the mouse input data ring buffer.
        !           547:     //
        !           548: 
        !           549:     RtlZeroMemory(
        !           550:         deviceExtension->InputData, 
        !           551:         deviceExtension->Configuration.MouseAttributes.InputDataQueueLength
        !           552:         );
        !           553: 
        !           554:     //
        !           555:     // Initialize the connection data.
        !           556:     //
        !           557: 
        !           558:     deviceExtension->ConnectData.ClassDeviceObject = NULL;
        !           559:     deviceExtension->ConnectData.ClassService = NULL;
        !           560: 
        !           561:     //
        !           562:     // Initialize the input data queue.
        !           563:     //
        !           564: 
        !           565:     InpInitializeDataQueue((PVOID) deviceExtension);
        !           566: 
        !           567:     //
        !           568:     // Initialize the port ISR DPC.  The ISR DPC is responsible for
        !           569:     // calling the connected class driver's callback routine to process
        !           570:     // the input data queue.
        !           571:     //
        !           572: 
        !           573:     deviceExtension->DpcInterlockVariable = -1;
        !           574: 
        !           575:     KeInitializeSpinLock(&deviceExtension->SpinLock);
        !           576: 
        !           577:     KeInitializeDpc(
        !           578:         &deviceExtension->IsrDpc,
        !           579:         (PKDEFERRED_ROUTINE) InportIsrDpc,
        !           580:         portDeviceObject
        !           581:         );
        !           582: 
        !           583:     KeInitializeDpc(
        !           584:         &deviceExtension->IsrDpcRetry,
        !           585:         (PKDEFERRED_ROUTINE) InportIsrDpc,
        !           586:         portDeviceObject
        !           587:         );
        !           588: 
        !           589:     //
        !           590:     // Initialize the mouse data consumption timer.
        !           591:     //
        !           592: 
        !           593:     KeInitializeTimer(&deviceExtension->DataConsumptionTimer);
        !           594: 
        !           595:     //
        !           596:     // Initialize the port DPC queue to log overrun and internal
        !           597:     // driver errors.
        !           598:     //
        !           599: 
        !           600:     KeInitializeDpc(
        !           601:         &deviceExtension->ErrorLogDpc,
        !           602:         (PKDEFERRED_ROUTINE) InportErrorLogDpc,
        !           603:         portDeviceObject
        !           604:         );
        !           605: 
        !           606:     //
        !           607:     // From the Hal, get the interrupt vector and level.
        !           608:     //
        !           609: 
        !           610:     interruptVector = HalGetInterruptVector(
        !           611:                           deviceExtension->Configuration.InterfaceType,
        !           612:                           deviceExtension->Configuration.BusNumber,
        !           613:                           deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Level,
        !           614:                           deviceExtension->Configuration.MouseInterrupt.u.Interrupt.Vector,
        !           615:                           &interruptLevel,
        !           616:                           &affinity
        !           617:                           );
        !           618: 
        !           619:     //
        !           620:     // Initialize and connect the interrupt object for the mouse.
        !           621:     //
        !           622: 
        !           623:     status = IoConnectInterrupt(
        !           624:                  &(deviceExtension->InterruptObject),
        !           625:                  (PKSERVICE_ROUTINE) InportInterruptService,
        !           626:                  (PVOID) portDeviceObject,
        !           627:                  (PKSPIN_LOCK)NULL,
        !           628:                  interruptVector,
        !           629:                  interruptLevel,
        !           630:                  interruptLevel,
        !           631:                  deviceExtension->Configuration.MouseInterrupt.Flags 
        !           632:                      == CM_RESOURCE_INTERRUPT_LATCHED ? Latched:LevelSensitive, 
        !           633:                  deviceExtension->Configuration.MouseInterrupt.ShareDisposition,
        !           634:                  affinity,
        !           635:                  deviceExtension->Configuration.FloatingSave
        !           636:                  );
        !           637: 
        !           638:     if (!NT_SUCCESS(status)) {
        !           639: 
        !           640:         //
        !           641:         // Failed to install.  Free up resources before exiting.
        !           642:         //
        !           643: 
        !           644:         InpPrint((
        !           645:             1,
        !           646:             "INPORT-InportInitialize: Could not connect mouse interrupt\n"
        !           647:             ));
        !           648: 
        !           649:         //
        !           650:         // Log an error.
        !           651:         //
        !           652: 
        !           653:         errorCode = INPORT_NO_INTERRUPT_CONNECTED;
        !           654:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 40;
        !           655:         dumpData[0] = interruptLevel; 
        !           656:         dumpCount = 1;
        !           657: 
        !           658:         goto InportInitializeExit;
        !           659: 
        !           660:     }
        !           661: 
        !           662:     //
        !           663:     // Once initialization is finished, load the device map information 
        !           664:     // into the registry so that setup can determine which pointer port
        !           665:     // is active.  
        !           666:     //
        !           667: 
        !           668:     status = RtlWriteRegistryValue(
        !           669:                  RTL_REGISTRY_DEVICEMAP,
        !           670:                  baseDeviceName.Buffer,
        !           671:                  fullDeviceName.Buffer,
        !           672:                  REG_SZ,
        !           673:                  registryPath.Buffer,
        !           674:                  registryPath.Length
        !           675:                  );
        !           676: 
        !           677:     if (!NT_SUCCESS(status)) {
        !           678: 
        !           679:         InpPrint((
        !           680:             1, 
        !           681:             "INPORT-InportInitialize: Could not store name in DeviceMap\n"
        !           682:             ));
        !           683: 
        !           684:         errorCode = INPORT_NO_DEVICEMAP_CREATED;
        !           685:         uniqueErrorValue = INPORT_ERROR_VALUE_BASE + 50;
        !           686:         dumpCount = 0;
        !           687: 
        !           688:         goto InportInitializeExit;
        !           689: 
        !           690:     } else {
        !           691: 
        !           692:         InpPrint((
        !           693:             1, 
        !           694:             "INPORT-InportInitialize: Stored name in DeviceMap\n"
        !           695:             ));
        !           696:     }
        !           697: 
        !           698:     ASSERT(status == STATUS_SUCCESS);
        !           699: 
        !           700:     //
        !           701:     // Set up the device driver entry points.
        !           702:     //
        !           703: 
        !           704:     DriverObject->DriverStartIo = InportStartIo;
        !           705:     DriverObject->MajorFunction[IRP_MJ_CREATE] = InportOpenClose;
        !           706:     DriverObject->MajorFunction[IRP_MJ_CLOSE]  = InportOpenClose;
        !           707:     DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]  =
        !           708:                                              InportFlush;
        !           709:     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
        !           710:                                          InportInternalDeviceControl;
        !           711: 
        !           712:     //
        !           713:     // NOTE: Don't allow this driver to unload.  Otherwise, we would set
        !           714:     // DriverObject->DriverUnload = InportUnload.
        !           715:     //
        !           716: 
        !           717: InportInitializeExit:
        !           718: 
        !           719:     //
        !           720:     // Log an error, if necessary.
        !           721:     //
        !           722: 
        !           723:     if (errorCode != STATUS_SUCCESS) {
        !           724:         errorLogEntry = (PIO_ERROR_LOG_PACKET)
        !           725:             IoAllocateErrorLogEntry(
        !           726:                 (portDeviceObject == NULL) ? 
        !           727:                     (PVOID) DriverObject : (PVOID) portDeviceObject,
        !           728:                 (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + (dumpCount * sizeof(ULONG)))
        !           729:                 );
        !           730: 
        !           731:         if (errorLogEntry != NULL) {
        !           732: 
        !           733:             errorLogEntry->ErrorCode = errorCode;
        !           734:             errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG);
        !           735:             errorLogEntry->SequenceNumber = 0;
        !           736:             errorLogEntry->MajorFunctionCode = 0;
        !           737:             errorLogEntry->IoControlCode = 0;
        !           738:             errorLogEntry->RetryCount = 0;
        !           739:             errorLogEntry->UniqueErrorValue = uniqueErrorValue;
        !           740:             errorLogEntry->FinalStatus = status;
        !           741:             for (i = 0; i < dumpCount; i++)
        !           742:                 errorLogEntry->DumpData[i] = dumpData[i];
        !           743: 
        !           744:             IoWriteErrorLogEntry(errorLogEntry);
        !           745:         }
        !           746:     }
        !           747: 
        !           748:     if (!NT_SUCCESS(status)) {
        !           749: 
        !           750:         //
        !           751:         // The initialization failed.  Cleanup resources before exiting.
        !           752:         //
        !           753:         // Note:  No need/way to undo the KeInitializeDpc or 
        !           754:         //        KeInitializeTimer calls.
        !           755:         //
        !           756: 
        !           757:         if (resources) {
        !           758: 
        !           759:             //
        !           760:             // Call IoReportResourceUsage to remove the resources from 
        !           761:             // the map.
        !           762:             //
        !           763: 
        !           764:             resources->Count = 0;
        !           765: 
        !           766:             IoReportResourceUsage(
        !           767:                 &baseDeviceName,
        !           768:                 DriverObject,
        !           769:                 NULL,
        !           770:                 0,
        !           771:                 portDeviceObject,
        !           772:                 resources, 
        !           773:                 resourceListSize,
        !           774:                 FALSE,
        !           775:                 &conflictDetected
        !           776:                 );
        !           777: 
        !           778:         }
        !           779: 
        !           780:         if (deviceExtension) {
        !           781:             if (deviceExtension->InterruptObject != NULL)
        !           782:                 IoDisconnectInterrupt(deviceExtension->InterruptObject);
        !           783:             if (deviceExtension->Configuration.UnmapRegistersRequired) {
        !           784:     
        !           785:                 MmUnmapIoSpace(
        !           786:                     deviceExtension->Configuration.DeviceRegisters[0],
        !           787:                     deviceExtension->Configuration.PortList[0].u.Port.Length
        !           788:                     );
        !           789:             }
        !           790:             if (deviceExtension->InputData)
        !           791:                 ExFreePool(deviceExtension->InputData);
        !           792:         }
        !           793:         if (portDeviceObject)
        !           794:             IoDeleteDevice(portDeviceObject);
        !           795:     }
        !           796: 
        !           797:     //
        !           798:     // Free the resource list.
        !           799:     //
        !           800:     // N.B.  If we ever decide to hang on to the resource list instead,
        !           801:     //       we need to allocate it from non-paged pool (it is now paged pool).
        !           802:     //
        !           803: 
        !           804:     if (resources)
        !           805:         ExFreePool(resources);
        !           806: 
        !           807:     //
        !           808:     // Free the unicode strings.
        !           809:     //
        !           810: 
        !           811:     if (deviceNameSuffix.MaximumLength != 0)
        !           812:         ExFreePool(deviceNameSuffix.Buffer);
        !           813:     if (fullDeviceName.MaximumLength != 0)
        !           814:         ExFreePool(fullDeviceName.Buffer);
        !           815:     if (registryPath.MaximumLength != 0)
        !           816:         ExFreePool(registryPath.Buffer);
        !           817: 
        !           818:     InpPrint((1,"INPORT-InportInitialize: exit\n"));
        !           819: 
        !           820:     return(status);
        !           821: 
        !           822: }
        !           823: 
        !           824: BOOLEAN
        !           825: InportInterruptService(
        !           826:     IN PKINTERRUPT Interrupt,
        !           827:     IN PVOID Context
        !           828:     )
        !           829: 
        !           830: /*++
        !           831: 
        !           832: Routine Description:
        !           833: 
        !           834:     This is the interrupt service routine for the mouse device.
        !           835: 
        !           836: Arguments:
        !           837: 
        !           838:     Interrupt - A pointer to the interrupt object for this interrupt.
        !           839: 
        !           840:     Context - A pointer to the device object.
        !           841: 
        !           842: Return Value:
        !           843: 
        !           844:     Returns TRUE if the interrupt was expected (and therefore processed);
        !           845:     otherwise, FALSE is returned.
        !           846: 
        !           847: --*/
        !           848: 
        !           849: {
        !           850:     PDEVICE_EXTENSION deviceExtension;
        !           851:     PDEVICE_OBJECT deviceObject;
        !           852:     PUCHAR port;
        !           853:     UCHAR previousButtons;
        !           854:     UCHAR mode;
        !           855:     UCHAR status;
        !           856: 
        !           857:     UNREFERENCED_PARAMETER(Interrupt);
        !           858: 
        !           859:     InpPrint((2, "INPORT-InportInterruptService: enter\n"));
        !           860: 
        !           861:     //
        !           862:     // Get the device extension.
        !           863:     //
        !           864: 
        !           865:     deviceObject = (PDEVICE_OBJECT) Context;
        !           866:     deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
        !           867: 
        !           868:     //
        !           869:     // Get the Inport mouse port address.
        !           870:     //
        !           871: 
        !           872:     port = deviceExtension->Configuration.DeviceRegisters[0];
        !           873: 
        !           874:     //
        !           875:     // Note:  It would be nice to verify that the interrupt really
        !           876:     // belongs to this driver, but it is currently not known how to
        !           877:     // make that determination.
        !           878:     //
        !           879: 
        !           880:     //
        !           881:     // Set the Inport hold bit.  Note that there is a bug in the 1.1 version
        !           882:     // of the Inport chip in DATA mode.  The interrupt signal doesn't get
        !           883:     // cleared in some cases, thus effectively disabling the device.  The
        !           884:     // workaround is to set the HOLD bit twice.
        !           885:     //
        !           886: 
        !           887:     WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
        !           888:     mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !           889:     WRITE_PORT_UCHAR(
        !           890:         (PUCHAR) (port + INPORT_DATA_REGISTER_1),
        !           891:         (UCHAR) (mode | INPORT_MODE_HOLD)
        !           892:         );
        !           893:     WRITE_PORT_UCHAR(
        !           894:         (PUCHAR) (port + INPORT_DATA_REGISTER_1),
        !           895:         (UCHAR) (mode | INPORT_MODE_HOLD)
        !           896:         );
        !           897: 
        !           898:     //
        !           899:     // Read the Inport status register.  It contains the following information:
        !           900:     //
        !           901:     //          XXXXXXXX
        !           902:     //           |   | |------  1 if button 3 is down (right button)
        !           903:     //           |   |--------  1 if button 1 is down (left button)
        !           904:     //           |------------  1 if the mouse has moved
        !           905:     //
        !           906: 
        !           907:     WRITE_PORT_UCHAR((PUCHAR) port, INPORT_STATUS_REGISTER);
        !           908:     status = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !           909: 
        !           910:     InpPrint((2, "INPORT-InportInterruptService: status byte 0x%x\n", status));
        !           911: 
        !           912:     //
        !           913:     // Update CurrentInput with button transition data.
        !           914:     // I.e., set a button up/down bit in the Buttons field if
        !           915:     // the state of a given button has changed since we
        !           916:     // received the last packet.
        !           917:     //
        !           918: 
        !           919:     previousButtons = 
        !           920:         deviceExtension->PreviousButtons;
        !           921: 
        !           922:     deviceExtension->CurrentInput.Buttons = 0;
        !           923: 
        !           924:     if ((!(previousButtons & INPORT_STATUS_BUTTON1)) 
        !           925:            &&  (status & INPORT_STATUS_BUTTON1)) {
        !           926:         deviceExtension->CurrentInput.Buttons |=
        !           927:             MOUSE_LEFT_BUTTON_DOWN;
        !           928:     } else
        !           929:     if ((previousButtons & INPORT_STATUS_BUTTON1) 
        !           930:            &&  !(status & INPORT_STATUS_BUTTON1)) {
        !           931:         deviceExtension->CurrentInput.Buttons |=
        !           932:             MOUSE_LEFT_BUTTON_UP;
        !           933:     }
        !           934:     if ((!(previousButtons & INPORT_STATUS_BUTTON3)) 
        !           935:            &&  (status & INPORT_STATUS_BUTTON3)) {
        !           936:         deviceExtension->CurrentInput.Buttons |=
        !           937:             MOUSE_RIGHT_BUTTON_DOWN;
        !           938:     } else
        !           939:     if ((previousButtons & INPORT_STATUS_BUTTON3) 
        !           940:            &&  !(status & INPORT_STATUS_BUTTON3)) {
        !           941:         deviceExtension->CurrentInput.Buttons |=
        !           942:             MOUSE_RIGHT_BUTTON_UP;
        !           943:     }
        !           944:             
        !           945:     //
        !           946:     // If the button position changed or the mouse moved, continue to process
        !           947:     // the interrupt.  Otherwise, just clear the hold bit and ignore this
        !           948:     // interrupt's data.
        !           949:     //
        !           950: 
        !           951:     if (deviceExtension->CurrentInput.Buttons
        !           952:            || (status & INPORT_STATUS_MOVEMENT)) {
        !           953: 
        !           954:         deviceExtension->CurrentInput.UnitId = deviceExtension->UnitId;
        !           955: 
        !           956:         //
        !           957:         // Keep track of the state of the mouse buttons for the next
        !           958:         // interrupt.
        !           959:         //
        !           960: 
        !           961:         deviceExtension->PreviousButtons =
        !           962:             status & (INPORT_STATUS_BUTTON1 | INPORT_STATUS_BUTTON3);
        !           963: 
        !           964:         //
        !           965:         // If mouse movement was recorded, get the X and Y motion data.
        !           966:         //
        !           967: 
        !           968:         if (status & INPORT_STATUS_MOVEMENT) {
        !           969: 
        !           970:             //
        !           971:             // Select the Data1 register as the current data register, and
        !           972:             // get the X motion byte.
        !           973:             //
        !           974: 
        !           975:             WRITE_PORT_UCHAR((PUCHAR) port, INPORT_DATA_REGISTER_1);
        !           976:             deviceExtension->CurrentInput.LastX =
        !           977:                 (LONG)(SCHAR) READ_PORT_UCHAR(
        !           978:                                    (PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !           979: 
        !           980:             //
        !           981:             // Select the Data2 register as the current data register, and
        !           982:             // get the Y motion byte.
        !           983:             //
        !           984: 
        !           985:             WRITE_PORT_UCHAR((PUCHAR) port, INPORT_DATA_REGISTER_2);
        !           986:             deviceExtension->CurrentInput.LastY =
        !           987:                 (LONG)(SCHAR) READ_PORT_UCHAR(
        !           988:                                    (PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !           989:         } else {
        !           990:             deviceExtension->CurrentInput.LastX = 0;
        !           991:             deviceExtension->CurrentInput.LastY = 0;
        !           992:         }
        !           993: 
        !           994:         //
        !           995:         // Clear the Inport hold bit.
        !           996:         //
        !           997: 
        !           998:         WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
        !           999:         mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !          1000:         WRITE_PORT_UCHAR(
        !          1001:             (PUCHAR) (port + INPORT_DATA_REGISTER_1),
        !          1002:             (UCHAR) (mode & ~INPORT_MODE_HOLD)
        !          1003:             );
        !          1004: 
        !          1005:         //
        !          1006:         // Write the input data to the queue and request the ISR DPC to
        !          1007:         // finish processing the interrupt at DISPATCH_LEVEL.
        !          1008:         //
        !          1009: 
        !          1010:         if (!InpWriteDataToQueue(
        !          1011:                 deviceExtension,
        !          1012:                 &deviceExtension->CurrentInput
        !          1013:                 )) {
        !          1014: 
        !          1015:             //
        !          1016:             // The mouse input data queue is full.  Just drop the
        !          1017:             // latest input on the floor.
        !          1018:             //
        !          1019:             // Queue a DPC to log an overrun error.
        !          1020:             //
        !          1021: 
        !          1022:             InpPrint((
        !          1023:                 1,
        !          1024:                 "INPORT-InportInterruptService: queue overflow\n"
        !          1025:                 ));
        !          1026: 
        !          1027:             if (deviceExtension->OkayToLogOverflow) {
        !          1028:                 KeInsertQueueDpc(
        !          1029:                     &deviceExtension->ErrorLogDpc,
        !          1030:                     (PIRP) NULL,
        !          1031:                     (PVOID) (ULONG) INPORT_MOU_BUFFER_OVERFLOW
        !          1032:                     );
        !          1033:                 deviceExtension->OkayToLogOverflow = FALSE;
        !          1034:             }
        !          1035: 
        !          1036:         } else if (deviceExtension->DpcInterlockVariable >= 0) {
        !          1037:     
        !          1038:             //
        !          1039:             // The ISR DPC is already executing.  Tell the ISR DPC it has
        !          1040:             // more work to do by incrementing the DpcInterlockVariable.
        !          1041:             //
        !          1042:     
        !          1043:             deviceExtension->DpcInterlockVariable += 1;
        !          1044:     
        !          1045:         } else {
        !          1046:     
        !          1047:             //
        !          1048:             // Queue the ISR DPC.
        !          1049:             //
        !          1050:     
        !          1051:             KeInsertQueueDpc(
        !          1052:                 &deviceExtension->IsrDpc,
        !          1053:                 deviceObject->CurrentIrp,
        !          1054:                 NULL
        !          1055:                 );
        !          1056:     
        !          1057:         }
        !          1058: 
        !          1059:     } else {
        !          1060: 
        !          1061:         InpPrint((
        !          1062:             3,
        !          1063:             "INPORT-InportInterruptService: interrupt without button/motion change\n"
        !          1064:             ));
        !          1065: 
        !          1066: 
        !          1067:         //
        !          1068:         // Clear the Inport hold bit.
        !          1069:         //
        !          1070: 
        !          1071:         WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
        !          1072:         mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !          1073:         WRITE_PORT_UCHAR(
        !          1074:             (PUCHAR) (port + INPORT_DATA_REGISTER_1),
        !          1075:             (UCHAR) (mode & ~INPORT_MODE_HOLD)
        !          1076:             );
        !          1077: 
        !          1078:     }
        !          1079: 
        !          1080:     InpPrint((2, "INPORT-InportInterruptService: exit\n"));
        !          1081: 
        !          1082:     return(TRUE);
        !          1083: }
        !          1084: 
        !          1085: VOID
        !          1086: InportUnload(
        !          1087:     IN PDRIVER_OBJECT DriverObject
        !          1088:     )
        !          1089: {
        !          1090:     UNREFERENCED_PARAMETER(DriverObject);
        !          1091: 
        !          1092:     InpPrint((2, "INPORT-InportUnload: enter\n"));
        !          1093:     InpPrint((2, "INPORT-InportUnload: exit\n"));
        !          1094: }
        !          1095: 
        !          1096: VOID
        !          1097: InpBuildResourceList(
        !          1098:     IN PDEVICE_EXTENSION DeviceExtension,
        !          1099:     OUT PCM_RESOURCE_LIST *ResourceList,
        !          1100:     OUT PULONG ResourceListSize
        !          1101:     )
        !          1102: 
        !          1103: /*++
        !          1104: 
        !          1105: Routine Description:
        !          1106: 
        !          1107:     Creates a resource list that is used to query or report resource usage.
        !          1108: 
        !          1109: Arguments:
        !          1110: 
        !          1111:     DeviceExtension - Pointer to the port's device extension.
        !          1112: 
        !          1113:     ResourceList - Pointer to a pointer to the resource list to be allocated
        !          1114:         and filled.
        !          1115:     
        !          1116:     ResourceListSize - Pointer to the returned size of the resource 
        !          1117:         list (in bytes).
        !          1118: 
        !          1119: Return Value:
        !          1120: 
        !          1121:     None.  If the call succeeded, *ResourceList points to the built
        !          1122:     resource list and *ResourceListSize is set to the size (in bytes)
        !          1123:     of the resource list; otherwise, *ResourceList is NULL.
        !          1124: 
        !          1125: Note:
        !          1126: 
        !          1127:     Memory is allocated here for *ResourceList. It must be
        !          1128:     freed up by the caller, by calling ExFreePool();
        !          1129: 
        !          1130: --*/
        !          1131: 
        !          1132: {
        !          1133:     ULONG count = 0; 
        !          1134:     PIO_ERROR_LOG_PACKET errorLogEntry;
        !          1135:     ULONG i = 0;
        !          1136:     ULONG j = 0;
        !          1137: 
        !          1138:     count += DeviceExtension->Configuration.PortListCount;
        !          1139:     if (DeviceExtension->Configuration.MouseInterrupt.Type 
        !          1140:         == CmResourceTypeInterrupt)
        !          1141:         count += 1;
        !          1142: 
        !          1143:     *ResourceListSize = sizeof(CM_RESOURCE_LIST) + 
        !          1144:                        ((count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
        !          1145: 
        !          1146:     *ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool(
        !          1147:                                             PagedPool,
        !          1148:                                             *ResourceListSize
        !          1149:                                             );
        !          1150: 
        !          1151:     //
        !          1152:     // Return NULL if the structure could not be allocated.
        !          1153:     // Otherwise, fill in the resource list.
        !          1154:     //
        !          1155: 
        !          1156:     if (!*ResourceList) {
        !          1157: 
        !          1158:         //
        !          1159:         // Could not allocate memory for the resource list.
        !          1160:         //
        !          1161: 
        !          1162:         InpPrint((
        !          1163:             1,
        !          1164:             "INPORT-InpBuildResourceList: Could not allocate resource list\n"
        !          1165:             ));
        !          1166: 
        !          1167:         //
        !          1168:         // Log an error.
        !          1169:         //
        !          1170: 
        !          1171:         errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
        !          1172:                                               DeviceExtension->DeviceObject,
        !          1173:                                               sizeof(IO_ERROR_LOG_PACKET)
        !          1174:                                               + sizeof(ULONG)
        !          1175:                                               );
        !          1176: 
        !          1177:         if (errorLogEntry != NULL) {
        !          1178: 
        !          1179:             errorLogEntry->ErrorCode = INPORT_INSUFFICIENT_RESOURCES;
        !          1180:             errorLogEntry->DumpDataSize = sizeof(ULONG);
        !          1181:             errorLogEntry->SequenceNumber = 0;
        !          1182:             errorLogEntry->MajorFunctionCode = 0;
        !          1183:             errorLogEntry->IoControlCode = 0;
        !          1184:             errorLogEntry->RetryCount = 0;
        !          1185:             errorLogEntry->UniqueErrorValue = INPORT_ERROR_VALUE_BASE + 110;
        !          1186:             errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
        !          1187:             errorLogEntry->DumpData[0] = *ResourceListSize;
        !          1188:             *ResourceListSize = 0;
        !          1189: 
        !          1190:             IoWriteErrorLogEntry(errorLogEntry);
        !          1191:         }
        !          1192: 
        !          1193:         return;
        !          1194: 
        !          1195:     }
        !          1196: 
        !          1197:     RtlZeroMemory(
        !          1198:         *ResourceList,
        !          1199:         *ResourceListSize
        !          1200:         );
        !          1201: 
        !          1202:     //
        !          1203:     // Concoct one full resource descriptor.
        !          1204:     //
        !          1205: 
        !          1206:     (*ResourceList)->Count = 1;
        !          1207: 
        !          1208:     (*ResourceList)->List[0].InterfaceType = 
        !          1209:         DeviceExtension->Configuration.InterfaceType; 
        !          1210:     (*ResourceList)->List[0].BusNumber = 
        !          1211:         DeviceExtension->Configuration.BusNumber; 
        !          1212: 
        !          1213:     //
        !          1214:     // Build the partial resource descriptors for interrupt and port
        !          1215:     // resources from the saved values.
        !          1216:     //
        !          1217: 
        !          1218:     (*ResourceList)->List[0].PartialResourceList.Count = count;
        !          1219:     if (DeviceExtension->Configuration.MouseInterrupt.Type 
        !          1220:         == CmResourceTypeInterrupt)
        !          1221:         (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] =
        !          1222:             DeviceExtension->Configuration.MouseInterrupt;
        !          1223: 
        !          1224:     for (j = 0; j < DeviceExtension->Configuration.PortListCount; j++) {
        !          1225:         (*ResourceList)->List[0].PartialResourceList.PartialDescriptors[i++] = 
        !          1226:             DeviceExtension->Configuration.PortList[j];
        !          1227:     }
        !          1228: 
        !          1229: } 
        !          1230: 
        !          1231: VOID
        !          1232: InpConfiguration(
        !          1233:     IN PDEVICE_EXTENSION DeviceExtension,
        !          1234:     IN PUNICODE_STRING RegistryPath,
        !          1235:     IN PUNICODE_STRING DeviceName
        !          1236:     )
        !          1237: 
        !          1238: /*++
        !          1239: 
        !          1240: Routine Description:
        !          1241: 
        !          1242:     This routine retrieves the configuration information for the mouse.
        !          1243: 
        !          1244: Arguments:
        !          1245: 
        !          1246:     DeviceExtension - Pointer to the device extension.
        !          1247: 
        !          1248:     RegistryPath - Pointer to the null-terminated Unicode name of the 
        !          1249:         registry path for this driver.
        !          1250: 
        !          1251:     DeviceName - Pointer to the Unicode string that will receive
        !          1252:         the port device name.
        !          1253: 
        !          1254: Return Value:
        !          1255: 
        !          1256:     None.  As a side-effect, may set DeviceExtension->HardwarePresent.
        !          1257: 
        !          1258: --*/
        !          1259: {
        !          1260:     NTSTATUS status = STATUS_SUCCESS;
        !          1261:     PINPORT_CONFIGURATION_INFORMATION configuration;
        !          1262:     INTERFACE_TYPE interfaceType;
        !          1263:     CONFIGURATION_TYPE controllerType = PointerController;
        !          1264:     CONFIGURATION_TYPE peripheralType = PointerPeripheral;
        !          1265:     ULONG i;
        !          1266: 
        !          1267:     for (i = 0; i < MaximumInterfaceType; i++) {
        !          1268: 
        !          1269:         //
        !          1270:         // Get the registry information for this device.
        !          1271:         //
        !          1272: 
        !          1273:         interfaceType = i;
        !          1274:         status = IoQueryDeviceDescription(&interfaceType,
        !          1275:                                           NULL,
        !          1276:                                           &controllerType,
        !          1277:                                           NULL,
        !          1278:                                           &peripheralType,
        !          1279:                                           NULL,
        !          1280:                                           InpPeripheralCallout,
        !          1281:                                           (PVOID) DeviceExtension);
        !          1282:     
        !          1283:         if (DeviceExtension->HardwarePresent) {
        !          1284:     
        !          1285:     
        !          1286:             //
        !          1287:             // Get the service parameters (e.g., user-configurable 
        !          1288:             // data input queue size, etc.).
        !          1289:             //
        !          1290: 
        !          1291:             InpServiceParameters(DeviceExtension, RegistryPath, DeviceName);
        !          1292:             configuration = &DeviceExtension->Configuration;
        !          1293:     
        !          1294:             //
        !          1295:             // Initialize mouse-specific configuration parameters.
        !          1296:             //
        !          1297:         
        !          1298:             configuration->MouseAttributes.MouseIdentifier =
        !          1299:                 MOUSE_INPORT_HARDWARE;
        !          1300:     
        !          1301:             break;
        !          1302:     
        !          1303:         } else {
        !          1304:     
        !          1305:             InpPrint((
        !          1306:                 1, 
        !          1307:                 "INPORT-InpConfiguration: IoQueryDeviceDescription for bus type %d failed\n",
        !          1308:                 interfaceType
        !          1309:                 ));
        !          1310:         }
        !          1311:     }
        !          1312: }
        !          1313: 
        !          1314: VOID
        !          1315: InpDisableInterrupts(
        !          1316:     IN PVOID Context
        !          1317:     )
        !          1318: 
        !          1319: /*++
        !          1320: 
        !          1321: Routine Description:
        !          1322: 
        !          1323:     This routine is called from StartIo synchronously.  It touches the
        !          1324:     hardware to  disable interrupts.
        !          1325: 
        !          1326: Arguments:
        !          1327: 
        !          1328:     Context - Pointer to the device extension.
        !          1329: 
        !          1330: Return Value:
        !          1331: 
        !          1332:     None.
        !          1333: 
        !          1334: --*/
        !          1335: 
        !          1336: {
        !          1337:     PUCHAR port;
        !          1338:     PLONG  enableCount;
        !          1339:     UCHAR  mode;
        !          1340: 
        !          1341:     //
        !          1342:     // Decrement the reference count for device enables.
        !          1343:     //
        !          1344: 
        !          1345:     enableCount = &((PDEVICE_EXTENSION) Context)->MouseEnableCount;
        !          1346:     *enableCount = *enableCount - 1;
        !          1347: 
        !          1348:     if (*enableCount == 0) {
        !          1349: 
        !          1350:         //
        !          1351:         // Get the port register address.
        !          1352:         //
        !          1353:     
        !          1354:         port = ((PDEVICE_EXTENSION) Context)->Configuration.DeviceRegisters[0];
        !          1355:     
        !          1356:         //
        !          1357:         // Select the mode register as the current data register.
        !          1358:         //
        !          1359:     
        !          1360:         WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
        !          1361:     
        !          1362:         //
        !          1363:         // Read the current mode.
        !          1364:         //
        !          1365:     
        !          1366:         mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !          1367:     
        !          1368:         //
        !          1369:         // Rewrite the mode byte with the interrupt disabled.
        !          1370:         //
        !          1371:     
        !          1372:         WRITE_PORT_UCHAR(
        !          1373:             (PUCHAR) (port + INPORT_DATA_REGISTER_1),
        !          1374:             (UCHAR) (mode & ~INPORT_DATA_INTERRUPT_ENABLE)
        !          1375:             );
        !          1376:     }
        !          1377: 
        !          1378: }
        !          1379: 
        !          1380: VOID
        !          1381: InpEnableInterrupts(
        !          1382:     IN PVOID Context
        !          1383:     )
        !          1384: 
        !          1385: /*++
        !          1386: 
        !          1387: Routine Description:
        !          1388: 
        !          1389:     This routine is called from StartIo synchronously.  It touches the
        !          1390:     hardware to enable interrupts.
        !          1391: 
        !          1392: Arguments:
        !          1393: 
        !          1394:     Context - Pointer to the device extension.
        !          1395: 
        !          1396: Return Value:
        !          1397: 
        !          1398:     None.
        !          1399: 
        !          1400: --*/
        !          1401: 
        !          1402: {
        !          1403:     PUCHAR port;
        !          1404:     PLONG  enableCount;
        !          1405:     UCHAR  mode;
        !          1406: 
        !          1407:     enableCount = &((PDEVICE_EXTENSION) Context)->MouseEnableCount;
        !          1408: 
        !          1409:     if (*enableCount == 0) {
        !          1410: 
        !          1411:         //
        !          1412:         // Get the port register address.
        !          1413:         //
        !          1414:     
        !          1415:         port = ((PDEVICE_EXTENSION) Context)->Configuration.DeviceRegisters[0];
        !          1416:     
        !          1417:         //
        !          1418:         // Select the mode register as the current data register.
        !          1419:         //
        !          1420:     
        !          1421:         WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
        !          1422:     
        !          1423:         //
        !          1424:         // Read the current mode.
        !          1425:         //
        !          1426:     
        !          1427:         mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
        !          1428:     
        !          1429:         //
        !          1430:         // Rewrite the mode byte with the interrupt enabled.
        !          1431:         //
        !          1432:     
        !          1433:         WRITE_PORT_UCHAR(
        !          1434:             (PUCHAR) (port + INPORT_DATA_REGISTER_1),
        !          1435:             (UCHAR) (mode | INPORT_DATA_INTERRUPT_ENABLE)
        !          1436:             );
        !          1437:     }
        !          1438: 
        !          1439:     //
        !          1440:     // Increment the reference count for device enables.
        !          1441:     //
        !          1442: 
        !          1443:     *enableCount = *enableCount + 1;
        !          1444: }
        !          1445: 
        !          1446: NTSTATUS
        !          1447: InpInitializeHardware(
        !          1448:     IN PDEVICE_OBJECT DeviceObject
        !          1449:     )
        !          1450: 
        !          1451: /*++
        !          1452: 
        !          1453: Routine Description:
        !          1454: 
        !          1455:     This routine initializes the Inport mouse.  Note that this routine is
        !          1456:     only called at initialization time, so synchronization is not required.
        !          1457: 
        !          1458: Arguments:
        !          1459: 
        !          1460:     DeviceObject - Pointer to the device object.
        !          1461: 
        !          1462: Return Value:
        !          1463: 
        !          1464:     None.
        !          1465: 
        !          1466: --*/
        !          1467: 
        !          1468: {
        !          1469:     PDEVICE_EXTENSION deviceExtension;
        !          1470:     PUCHAR mousePort;
        !          1471:     NTSTATUS status = STATUS_SUCCESS;
        !          1472: 
        !          1473:     InpPrint((2, "INPORT-InpInitializeHardware: enter\n"));
        !          1474: 
        !          1475:     //
        !          1476:     // Grab useful configuration parameters from the device extension.
        !          1477:     //
        !          1478: 
        !          1479:     deviceExtension = DeviceObject->DeviceExtension;
        !          1480:     mousePort = deviceExtension->Configuration.DeviceRegisters[0];
        !          1481: 
        !          1482:     //
        !          1483:     // Reset the Inport chip, leaving interrupts off.
        !          1484:     //
        !          1485: 
        !          1486:     WRITE_PORT_UCHAR((PUCHAR) mousePort, INPORT_RESET);
        !          1487: 
        !          1488:     //
        !          1489:     // Select the mode register as the current data register.  Set the
        !          1490:     // Inport mouse up for quadrature mode, and set the sample
        !          1491:     // rate (i.e., the interrupt Hz rate).  Leave interrupts disabled.
        !          1492:     //
        !          1493: 
        !          1494:     WRITE_PORT_UCHAR((PUCHAR) mousePort, INPORT_MODE_REGISTER);
        !          1495:     WRITE_PORT_UCHAR(
        !          1496:         (PUCHAR) ((ULONG)mousePort + INPORT_DATA_REGISTER_1),
        !          1497:         (UCHAR) (deviceExtension->Configuration.HzMode
        !          1498:                  | INPORT_MODE_QUADRATURE)
        !          1499:         );
        !          1500: 
        !          1501:     InpPrint((2, "INPORT-InpInitializeHardware: exit\n"));
        !          1502: 
        !          1503:     return(status);
        !          1504: 
        !          1505: }
        !          1506: 
        !          1507: NTSTATUS 
        !          1508: InpPeripheralCallout(
        !          1509:     IN PVOID Context,
        !          1510:     IN PUNICODE_STRING PathName,
        !          1511:     IN INTERFACE_TYPE BusType,
        !          1512:     IN ULONG BusNumber,
        !          1513:     IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
        !          1514:     IN CONFIGURATION_TYPE ControllerType,
        !          1515:     IN ULONG ControllerNumber,
        !          1516:     IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
        !          1517:     IN CONFIGURATION_TYPE PeripheralType,
        !          1518:     IN ULONG PeripheralNumber,
        !          1519:     IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
        !          1520:     )
        !          1521: 
        !          1522: /*++
        !          1523: 
        !          1524: Routine Description:
        !          1525: 
        !          1526:     This is the callout routine sent as a parameter to 
        !          1527:     IoQueryDeviceDescription.  It grabs the pointer controller and
        !          1528:     peripheral configuration information.
        !          1529: 
        !          1530: Arguments:
        !          1531: 
        !          1532:     Context - Context parameter that was passed in by the routine
        !          1533:         that called IoQueryDeviceDescription.
        !          1534: 
        !          1535:     PathName - The full pathname for the registry key.
        !          1536: 
        !          1537:     BusType - Bus interface type (Isa, Eisa, Mca, etc.).
        !          1538: 
        !          1539:     BusNumber - The bus sub-key (0, 1, etc.).
        !          1540: 
        !          1541:     BusInformation - Pointer to the array of pointers to the full value 
        !          1542:         information for the bus.
        !          1543: 
        !          1544:     ControllerType - The controller type (should be PointerController).
        !          1545: 
        !          1546:     ControllerNumber - The controller sub-key (0, 1, etc.).
        !          1547: 
        !          1548:     ControllerInformation - Pointer to the array of pointers to the full 
        !          1549:         value information for the controller key.
        !          1550: 
        !          1551:     PeripheralType - The peripheral type (should be PointerPeripheral).
        !          1552: 
        !          1553:     PeripheralNumber - The peripheral sub-key.
        !          1554: 
        !          1555:     PeripheralInformation - Pointer to the array of pointers to the full 
        !          1556:         value information for the peripheral key.
        !          1557:     
        !          1558: 
        !          1559: Return Value:
        !          1560: 
        !          1561:     None.  If successful, will have the following side-effects:
        !          1562: 
        !          1563:         - Sets DeviceObject->DeviceExtension->HardwarePresent.
        !          1564:         - Sets configuration fields in 
        !          1565:           DeviceObject->DeviceExtension->Configuration.
        !          1566: 
        !          1567: --*/
        !          1568: {
        !          1569:     PDEVICE_EXTENSION deviceExtension;
        !          1570:     PINPORT_CONFIGURATION_INFORMATION configuration;
        !          1571:     UNICODE_STRING unicodeIdentifier;
        !          1572:     PUCHAR controllerData;
        !          1573:     NTSTATUS status = STATUS_SUCCESS;
        !          1574:     ULONG i;
        !          1575:     ULONG listCount;
        !          1576:     PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor;
        !          1577:     ANSI_STRING ansiString;
        !          1578:     BOOLEAN defaultInterruptShare;
        !          1579:     KINTERRUPT_MODE defaultInterruptMode; 
        !          1580: 
        !          1581:     InpPrint((
        !          1582:         1, 
        !          1583:         "INPORT-InpPeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n",
        !          1584:         PathName, BusType, BusNumber 
        !          1585:         ));
        !          1586:     InpPrint((
        !          1587:         1, 
        !          1588:         "    Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n",
        !          1589:         ControllerType, ControllerNumber, ControllerInformation
        !          1590:         ));
        !          1591:     InpPrint((
        !          1592:         1, 
        !          1593:         "    Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n",
        !          1594:         PeripheralType, PeripheralNumber, PeripheralInformation
        !          1595:         ));
        !          1596: 
        !          1597:     //
        !          1598:     // Get the length of the peripheral identifier information.
        !          1599:     //
        !          1600: 
        !          1601:     unicodeIdentifier.Length =
        !          1602:         (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength;
        !          1603: 
        !          1604:     //
        !          1605:     // If we already have the configuration information for the
        !          1606:     // mouse peripheral, or if the peripheral identifier is missing, 
        !          1607:     // just return.
        !          1608:     //
        !          1609: 
        !          1610:     deviceExtension = (PDEVICE_EXTENSION) Context;
        !          1611:     if ((deviceExtension->HardwarePresent) || (unicodeIdentifier.Length == 0)){
        !          1612:         return (status);
        !          1613:     }
        !          1614: 
        !          1615:     configuration = &deviceExtension->Configuration;
        !          1616: 
        !          1617:     //
        !          1618:     // Get the identifier information for the peripheral.
        !          1619:     //
        !          1620: 
        !          1621:     unicodeIdentifier.MaximumLength = unicodeIdentifier.Length;
        !          1622:     unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation +
        !          1623:                                IoQueryDeviceIdentifier))) +
        !          1624:                                (*(PeripheralInformation + 
        !          1625:                                IoQueryDeviceIdentifier))->DataOffset);
        !          1626:     InpPrint((
        !          1627:         1,
        !          1628:         "INPORT-InpPeripheralCallout: Mouse type %ws\n",
        !          1629:         unicodeIdentifier.Buffer
        !          1630:         ));
        !          1631: 
        !          1632:     //
        !          1633:     // Verify that this is an Inport mouse.
        !          1634:     //
        !          1635: 
        !          1636:     status = RtlUnicodeStringToAnsiString(
        !          1637:                  &ansiString,
        !          1638:                  &unicodeIdentifier,
        !          1639:                  TRUE
        !          1640:                  );
        !          1641: 
        !          1642:     if (!NT_SUCCESS(status)) {
        !          1643:         InpPrint((
        !          1644:             1,
        !          1645:             "INPORT-InpPeripheralCallout: Could not convert identifier to Ansi\n"
        !          1646:             ));
        !          1647:         return(status);
        !          1648:     }
        !          1649:  
        !          1650:     if (strstr(ansiString.Buffer, "INPORT")) {
        !          1651: 
        !          1652:          //
        !          1653:          // There is an Inport mouse present.
        !          1654:          //
        !          1655: 
        !          1656:          deviceExtension->HardwarePresent = TRUE;
        !          1657:     }
        !          1658:    
        !          1659:     RtlFreeAnsiString(&ansiString);
        !          1660: 
        !          1661:     if (!deviceExtension->HardwarePresent) {
        !          1662:         return(status);
        !          1663:     }
        !          1664: 
        !          1665:     //
        !          1666:     // Get the bus information.
        !          1667:     //
        !          1668: 
        !          1669:     configuration->InterfaceType = BusType;
        !          1670:     configuration->BusNumber = BusNumber;
        !          1671:     configuration->FloatingSave = INPORT_FLOATING_SAVE;
        !          1672: 
        !          1673:     if (BusType == MicroChannel) {
        !          1674:         defaultInterruptShare = TRUE;
        !          1675:         defaultInterruptMode = LevelSensitive;
        !          1676:     } else {
        !          1677:         defaultInterruptShare = INPORT_INTERRUPT_SHARE;
        !          1678:         defaultInterruptMode = INPORT_INTERRUPT_MODE;
        !          1679:     }
        !          1680: 
        !          1681:     //
        !          1682:     // Look through the resource list for interrupt and port
        !          1683:     // configuration information.
        !          1684:     //
        !          1685:     
        !          1686:     if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){
        !          1687:         controllerData = ((PUCHAR) (*(ControllerInformation +
        !          1688:                                    IoQueryDeviceConfigurationData))) +
        !          1689:                                    (*(ControllerInformation +
        !          1690:                                    IoQueryDeviceConfigurationData))->DataOffset;
        !          1691:     
        !          1692:         controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, 
        !          1693:                                        PartialResourceList);
        !          1694:     
        !          1695:         listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count;
        !          1696:     
        !          1697:         resourceDescriptor = 
        !          1698:             ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors;
        !          1699:      
        !          1700:         for (i = 0; i < listCount; i++, resourceDescriptor++) {
        !          1701:             switch(resourceDescriptor->Type) {
        !          1702:                 case CmResourceTypePort:
        !          1703:     
        !          1704:                     //
        !          1705:                     // Copy the port information.  Note that we only expect to 
        !          1706:                     // find one port range for the Inport mouse.
        !          1707:                     //
        !          1708:     
        !          1709:                     ASSERT(configuration->PortListCount == 0);
        !          1710:                     configuration->PortList[configuration->PortListCount] =
        !          1711:                         *resourceDescriptor;
        !          1712:                     configuration->PortList[configuration->PortListCount].ShareDisposition =
        !          1713:                         INPORT_REGISTER_SHARE? CmResourceShareShared:
        !          1714:                                                CmResourceShareDeviceExclusive;
        !          1715:                     configuration->PortListCount += 1;
        !          1716:              
        !          1717:                     break;
        !          1718:         
        !          1719:                 case CmResourceTypeInterrupt:
        !          1720:     
        !          1721:                     //
        !          1722:                     // Copy the interrupt information.
        !          1723:                     //
        !          1724:     
        !          1725:                     configuration->MouseInterrupt = *resourceDescriptor;
        !          1726:                     configuration->MouseInterrupt.ShareDisposition = 
        !          1727:                         defaultInterruptShare?  CmResourceShareShared : 
        !          1728:                                                 CmResourceShareDeviceExclusive;
        !          1729:     
        !          1730:                     break;
        !          1731:         
        !          1732:                 default:
        !          1733:                     break;
        !          1734:             }
        !          1735:         }
        !          1736:     }
        !          1737:     
        !          1738:     //
        !          1739:     // If no interrupt configuration information was found, use the
        !          1740:     // driver defaults.
        !          1741:     //
        !          1742:     
        !          1743:     if (!(configuration->MouseInterrupt.Type & CmResourceTypeInterrupt)) {
        !          1744:     
        !          1745:         InpPrint((
        !          1746:             1,
        !          1747:             "INPORT-InpPeripheralCallout: Using default mouse interrupt config\n"
        !          1748:             ));
        !          1749: 
        !          1750:         configuration->MouseInterrupt.Type = CmResourceTypeInterrupt;
        !          1751:         configuration->MouseInterrupt.ShareDisposition = 
        !          1752:             defaultInterruptShare?  CmResourceShareShared : 
        !          1753:                                     CmResourceShareDeviceExclusive;
        !          1754:         configuration->MouseInterrupt.Flags = 
        !          1755:             (defaultInterruptMode == Latched)? CM_RESOURCE_INTERRUPT_LATCHED :
        !          1756:                 CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
        !          1757:         configuration->MouseInterrupt.u.Interrupt.Level = MOUSE_IRQL;
        !          1758:         configuration->MouseInterrupt.u.Interrupt.Vector = MOUSE_VECTOR;
        !          1759:     }
        !          1760:     
        !          1761:     InpPrint((
        !          1762:         1,
        !          1763:         "INPORT-InpPeripheralCallout: Mouse interrupt config --\n"
        !          1764:         ));
        !          1765:     InpPrint((
        !          1766:         1,
        !          1767:         "%s, %s, Irq = %d\n",
        !          1768:         configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared? 
        !          1769:             "Sharable" : "NonSharable",
        !          1770:         configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED?
        !          1771:             "Latched" : "Level Sensitive",
        !          1772:         configuration->MouseInterrupt.u.Interrupt.Vector
        !          1773:         ));
        !          1774:     
        !          1775:     //
        !          1776:     // If no port configuration information was found, use the
        !          1777:     // driver defaults.
        !          1778:     //
        !          1779:     
        !          1780:     if (configuration->PortListCount == 0) {
        !          1781:     
        !          1782:         //
        !          1783:         // No port configuration information was found, so use 
        !          1784:         // the driver defaults.
        !          1785:         //
        !          1786:     
        !          1787:         InpPrint((
        !          1788:             1,
        !          1789:             "INPORT-InpPeripheralCallout: Using default port config\n"
        !          1790:             ));
        !          1791: 
        !          1792:         configuration->PortList[0].Type = CmResourceTypePort;
        !          1793:         configuration->PortList[0].Flags = INPORT_PORT_TYPE;
        !          1794:         configuration->PortList[0].Flags = CM_RESOURCE_PORT_IO;
        !          1795:         configuration->PortList[0].ShareDisposition = 
        !          1796:             INPORT_REGISTER_SHARE? CmResourceShareShared:
        !          1797:                                    CmResourceShareDeviceExclusive;
        !          1798:         configuration->PortList[0].u.Port.Start.LowPart = 
        !          1799:             INPORT_PHYSICAL_BASE;
        !          1800:         configuration->PortList[0].u.Port.Start.HighPart = 0;
        !          1801:         configuration->PortList[0].u.Port.Length = INPORT_REGISTER_LENGTH;
        !          1802:     
        !          1803:         configuration->PortListCount = 1;
        !          1804:     }
        !          1805: 
        !          1806:     for (i = 0; i < configuration->PortListCount; i++) {
        !          1807: 
        !          1808:         InpPrint((
        !          1809:             1,
        !          1810:             "%s, Ports 0x%x - 0x%x\n",
        !          1811:             configuration->PortList[i].ShareDisposition 
        !          1812:                 == CmResourceShareShared?  "Sharable" : "NonSharable",
        !          1813:             configuration->PortList[i].u.Port.Start.LowPart,
        !          1814:             configuration->PortList[i].u.Port.Start.LowPart +
        !          1815:                 configuration->PortList[i].u.Port.Length - 1
        !          1816:             ));
        !          1817:     }
        !          1818: 
        !          1819:     return(status);
        !          1820: }
        !          1821: 
        !          1822: VOID
        !          1823: InpServiceParameters(
        !          1824:     IN PDEVICE_EXTENSION DeviceExtension,
        !          1825:     IN PUNICODE_STRING RegistryPath,
        !          1826:     IN PUNICODE_STRING DeviceName
        !          1827:     )
        !          1828: 
        !          1829: /*++
        !          1830: 
        !          1831: Routine Description:
        !          1832: 
        !          1833:     This routine retrieves this driver's service parameters information 
        !          1834:     from the registry.
        !          1835: 
        !          1836: Arguments:
        !          1837: 
        !          1838:     DeviceExtension - Pointer to the device extension.
        !          1839: 
        !          1840:     RegistryPath - Pointer to the null-terminated Unicode name of the 
        !          1841:         registry path for this driver.
        !          1842: 
        !          1843:     DeviceName - Pointer to the Unicode string that will receive
        !          1844:         the port device name.
        !          1845: 
        !          1846: Return Value:
        !          1847: 
        !          1848:     None.  As a side-effect, sets fields in DeviceExtension->Configuration.
        !          1849: 
        !          1850: --*/
        !          1851: 
        !          1852: {
        !          1853:     PINPORT_CONFIGURATION_INFORMATION configuration;
        !          1854:     PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
        !          1855:     UNICODE_STRING parametersPath;
        !          1856:     ULONG defaultDataQueueSize = DATA_QUEUE_SIZE;
        !          1857:     ULONG numberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
        !          1858:     USHORT defaultNumberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
        !          1859:     ULONG sampleRate = MOUSE_SAMPLE_RATE_50HZ;
        !          1860:     USHORT defaultSampleRate = MOUSE_SAMPLE_RATE_50HZ;
        !          1861:     ULONG hzMode = INPORT_MODE_50HZ;
        !          1862:     USHORT defaultHzMode = INPORT_MODE_50HZ;
        !          1863:     UNICODE_STRING defaultUnicodeName;
        !          1864:     NTSTATUS status = STATUS_SUCCESS;
        !          1865:     PWSTR path = NULL;
        !          1866:     USHORT queriesPlusOne = 6;
        !          1867:     
        !          1868:     configuration = &DeviceExtension->Configuration;
        !          1869:     parametersPath.Buffer = NULL;
        !          1870: 
        !          1871:     //
        !          1872:     // Registry path is already null-terminated, so just use it.
        !          1873:     //
        !          1874: 
        !          1875:     path = RegistryPath->Buffer;
        !          1876: 
        !          1877:     if (NT_SUCCESS(status)) {
        !          1878: 
        !          1879:         //
        !          1880:         // Allocate the Rtl query table.
        !          1881:         //
        !          1882:     
        !          1883:         parameters = ExAllocatePool(
        !          1884:                          PagedPool,
        !          1885:                          sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
        !          1886:                          );
        !          1887:     
        !          1888:         if (!parameters) {
        !          1889:     
        !          1890:             InpPrint((
        !          1891:                 1,
        !          1892:                 "INPORT-InpServiceParameters: Couldn't allocate table for Rtl query to parameters for %ws\n",
        !          1893:                  path
        !          1894:                  ));
        !          1895:     
        !          1896:             status = STATUS_UNSUCCESSFUL;
        !          1897:     
        !          1898:         } else {
        !          1899:     
        !          1900:             RtlZeroMemory(
        !          1901:                 parameters,
        !          1902:                 sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
        !          1903:                 );
        !          1904:     
        !          1905:             //
        !          1906:             // Form a path to this driver's Parameters subkey.
        !          1907:             //
        !          1908:     
        !          1909:             RtlInitUnicodeString(
        !          1910:                 &parametersPath,
        !          1911:                 NULL
        !          1912:                 );
        !          1913:     
        !          1914:             parametersPath.MaximumLength = RegistryPath->Length +
        !          1915:                                            sizeof(L"\\Parameters");
        !          1916:     
        !          1917:             parametersPath.Buffer = ExAllocatePool(
        !          1918:                                         PagedPool,
        !          1919:                                         parametersPath.MaximumLength
        !          1920:                                         );
        !          1921:     
        !          1922:             if (!parametersPath.Buffer) {
        !          1923:     
        !          1924:                 InpPrint((
        !          1925:                     1,
        !          1926:                     "INPORT-InpServiceParameters: Couldn't allocate string for path to parameters for %ws\n",
        !          1927:                      path
        !          1928:                     ));
        !          1929:     
        !          1930:                 status = STATUS_UNSUCCESSFUL;
        !          1931:     
        !          1932:             }
        !          1933:         }
        !          1934:     }
        !          1935: 
        !          1936:     if (NT_SUCCESS(status)) {
        !          1937: 
        !          1938:         //
        !          1939:         // Form the parameters path.
        !          1940:         //
        !          1941:     
        !          1942:         RtlZeroMemory(
        !          1943:             parametersPath.Buffer,
        !          1944:             parametersPath.MaximumLength
        !          1945:             );
        !          1946:         RtlAppendUnicodeToString(
        !          1947:             &parametersPath,
        !          1948:             path
        !          1949:             );
        !          1950:         RtlAppendUnicodeToString(
        !          1951:             &parametersPath,
        !          1952:             L"\\Parameters"
        !          1953:             );
        !          1954:     
        !          1955:         InpPrint((
        !          1956:             1,
        !          1957:             "INPORT-InpServiceParameters: parameters path is %ws\n",
        !          1958:              parametersPath.Buffer
        !          1959:             ));
        !          1960: 
        !          1961:         //
        !          1962:         // Form the default pointer port device name, in case it is not
        !          1963:         // specified in the registry.
        !          1964:         //
        !          1965: 
        !          1966:         RtlInitUnicodeString(
        !          1967:             &defaultUnicodeName,
        !          1968:             DD_POINTER_PORT_BASE_NAME_U
        !          1969:             );
        !          1970: 
        !          1971:         //
        !          1972:         // Gather all of the "user specified" information from
        !          1973:         // the registry.
        !          1974:         //
        !          1975: 
        !          1976:         parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
        !          1977:         parameters[0].Name = L"MouseDataQueueSize";
        !          1978:         parameters[0].EntryContext = 
        !          1979:             &configuration->MouseAttributes.InputDataQueueLength;
        !          1980:         parameters[0].DefaultType = REG_DWORD;
        !          1981:         parameters[0].DefaultData = &defaultDataQueueSize;
        !          1982:         parameters[0].DefaultLength = sizeof(ULONG);
        !          1983:     
        !          1984:         parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
        !          1985:         parameters[1].Name = L"NumberOfButtons";
        !          1986:         parameters[1].EntryContext = &numberOfButtons;
        !          1987:         parameters[1].DefaultType = REG_DWORD;
        !          1988:         parameters[1].DefaultData = &defaultNumberOfButtons;
        !          1989:         parameters[1].DefaultLength = sizeof(USHORT);
        !          1990:     
        !          1991:         parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
        !          1992:         parameters[2].Name = L"SampleRate";
        !          1993:         parameters[2].EntryContext = &sampleRate;
        !          1994:         parameters[2].DefaultType = REG_DWORD;
        !          1995:         parameters[2].DefaultData = &defaultSampleRate;
        !          1996:         parameters[2].DefaultLength = sizeof(USHORT);
        !          1997:     
        !          1998:         parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
        !          1999:         parameters[3].Name = L"HzMode";
        !          2000:         parameters[3].EntryContext = &hzMode;
        !          2001:         parameters[3].DefaultType = REG_DWORD;
        !          2002:         parameters[3].DefaultData = &defaultHzMode;
        !          2003:         parameters[3].DefaultLength = sizeof(USHORT);
        !          2004: 
        !          2005:         parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
        !          2006:         parameters[4].Name = L"PointerDeviceBaseName";
        !          2007:         parameters[4].EntryContext = DeviceName;
        !          2008:         parameters[4].DefaultType = REG_SZ;
        !          2009:         parameters[4].DefaultData = defaultUnicodeName.Buffer;
        !          2010:         parameters[4].DefaultLength = 0;
        !          2011:     
        !          2012:         status = RtlQueryRegistryValues(
        !          2013:                      RTL_REGISTRY_ABSOLUTE,
        !          2014:                      parametersPath.Buffer,
        !          2015:                      parameters,
        !          2016:                      NULL,
        !          2017:                      NULL
        !          2018:                      );
        !          2019: 
        !          2020:         if (!NT_SUCCESS(status)) {
        !          2021:             InpPrint((
        !          2022:                 1,
        !          2023:                 "INPORT-InpServiceParameters: RtlQueryRegistryValues failed with 0x%x\n",
        !          2024:                 status
        !          2025:                 ));
        !          2026:         }
        !          2027:     }
        !          2028: 
        !          2029:     if (!NT_SUCCESS(status)) {
        !          2030: 
        !          2031:         //
        !          2032:         // Go ahead and assign driver defaults.
        !          2033:         //
        !          2034: 
        !          2035:         configuration->MouseAttributes.InputDataQueueLength = 
        !          2036:             defaultDataQueueSize;
        !          2037:         RtlCopyUnicodeString(DeviceName, &defaultUnicodeName);
        !          2038:     }
        !          2039: 
        !          2040:     InpPrint((
        !          2041:         1,
        !          2042:         "INPORT-InpServiceParameters: Pointer port base name = %ws\n",
        !          2043:         DeviceName->Buffer
        !          2044:         ));
        !          2045: 
        !          2046:     if (configuration->MouseAttributes.InputDataQueueLength == 0) {
        !          2047: 
        !          2048:         InpPrint((
        !          2049:             1,
        !          2050:             "INPORT-InpServiceParameters: overriding MouseInputDataQueueLength = 0x%x\n",
        !          2051:             configuration->MouseAttributes.InputDataQueueLength
        !          2052:             ));
        !          2053: 
        !          2054:         configuration->MouseAttributes.InputDataQueueLength = 
        !          2055:             defaultDataQueueSize;
        !          2056:     }
        !          2057: 
        !          2058:     configuration->MouseAttributes.InputDataQueueLength *= 
        !          2059:         sizeof(MOUSE_INPUT_DATA);
        !          2060: 
        !          2061:     InpPrint((
        !          2062:         1,
        !          2063:         "INPORT-InpServiceParameters: MouseInputDataQueueLength = 0x%x\n",
        !          2064:         configuration->MouseAttributes.InputDataQueueLength
        !          2065:         ));
        !          2066: 
        !          2067:     configuration->MouseAttributes.NumberOfButtons = numberOfButtons;
        !          2068:     InpPrint((
        !          2069:         1,
        !          2070:         "INPORT-InpServiceParameters: NumberOfButtons = %d\n",
        !          2071:         configuration->MouseAttributes.NumberOfButtons
        !          2072:         ));
        !          2073: 
        !          2074:     configuration->MouseAttributes.SampleRate = sampleRate;
        !          2075:     InpPrint((
        !          2076:         1,
        !          2077:         "INPORT-InpServiceParameters: SampleRate = %d\n",
        !          2078:         configuration->MouseAttributes.SampleRate
        !          2079:         ));
        !          2080: 
        !          2081:     configuration->HzMode = hzMode;
        !          2082:     InpPrint((
        !          2083:         1,
        !          2084:         "INPORT-InpServiceParameters: HzMode = %d\n",
        !          2085:         configuration->HzMode
        !          2086:         ));
        !          2087: 
        !          2088:     //
        !          2089:     // Free the allocated memory before returning.
        !          2090:     //
        !          2091: 
        !          2092:     if (parametersPath.Buffer)
        !          2093:         ExFreePool(parametersPath.Buffer);
        !          2094:     if (parameters)
        !          2095:         ExFreePool(parameters);
        !          2096: 
        !          2097: }
        !          2098: 
        !          2099: #endif

unix.superglobalmegacorp.com

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