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