Annotation of ntddk/src/input/sermouse/sermdep.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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