|
|
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, ®istryPath, &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: ¶metersPath,
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: ¶metersPath,
1911: path
1912: );
1913: RtlAppendUnicodeToString(
1914: ¶metersPath,
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.