Annotation of ntddk/src/input/sermouse/sermdep.c, revision 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.