Annotation of ntddk/src/input/inport/i386/inpdep.c, revision 1.1.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.