|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 Microsoft Corporation
4:
5: Module Name:
6:
7: init.c
8:
9: Abstract:
10:
11: This module contains code for the initialization phase of the
12: Midi Synthesiser device
13:
14: Author:
15:
16: Geraint Davies
17:
18: Environment:
19:
20: Kernel mode
21:
22: Revision History:
23:
24: --*/
25:
26: #include "sound.h"
27: #include "string.h"
28: #include "stdlib.h"
29:
30: //
31: // Local definitions
32: //
33: BOOLEAN
34: SoundExcludeRoutine(
35: IN OUT PLOCAL_DEVICE_INFO pLDI,
36: IN SOUND_EXCLUDE_CODE Code
37: );
38: NTSTATUS
39: DriverEntry(
40: IN PDRIVER_OBJECT pDriverObject,
41: IN PUNICODE_STRING RegistryPathName
42: );
43: VOID
44: SoundCleanup(
45: IN PGLOBAL_DEVICE_INFO pGDI
46: );
47: VOID SoundUnload(
48: IN PDRIVER_OBJECT pDriverObject
49: );
50:
51: //
52: // Remove initialization stuff from resident memory
53: //
54:
55: #ifdef ALLOC_PRAGMA
56: #pragma alloc_text(init,DriverEntry)
57: #endif
58:
59: //
60: // Device initialization data
61: //
62:
63: SOUND_DEVICE_INIT DeviceInit[NumberOfDevices] =
64: {
65: {
66: REG_VALUENAME_LEFTSYNTH, REG_VALUENAME_RIGHTSYNTH,
67: DEF_SYNTH_VOLUME,
68: FILE_DEVICE_MIDI_OUT,
69: MIDI_OUT,
70: "LDMo",
71: STR_ADLIB_DEVICENAME,
72: NULL,
73: SoundExcludeRoutine,
74: SoundMidiDispatch, // Handles CREATE, CLOSE and WRITE
75: NULL, // Low level driver takes care of caps
76: SoundNoVolume,
77: 0
78: },
79: {
80: REG_VALUENAME_LEFTSYNTH, REG_VALUENAME_RIGHTSYNTH,
81: DEF_SYNTH_VOLUME,
82: FILE_DEVICE_MIDI_OUT,
83: MIDI_OUT,
84: "LDMo",
85: STR_OPL3_DEVICENAME,
86: NULL,
87: SoundExcludeRoutine,
88: SoundMidiDispatch, // Handles CREATE, CLOSE and WRITE
89: NULL, // Low level driver takes care of caps
90: SoundNoVolume,
91: 0
92: }
93: };
94:
95:
96: NTSTATUS
97: SoundShutdown(
98: IN PDEVICE_OBJECT pDO,
99: IN PIRP pIrp
100: )
101: /*++
102:
103: Routine Description:
104:
105: Save away volume settings when the system is shut down
106:
107: Arguments:
108:
109: pDO - the device object we registered for shutdown with
110: pIrp - No used
111:
112: Return Value:
113:
114: The function value is the final status from the initialization operation.
115: Here STATUS_SUCCESS
116:
117: --*/
118: {
119: //
120: // Save volume for all devices
121: //
122:
123: PLOCAL_DEVICE_INFO pLDI;
124:
125: pLDI = pDO->DeviceExtension;
126:
127: SoundSaveVolume(pLDI->pGlobalInfo);
128:
129: return STATUS_SUCCESS;
130: }
131:
132:
133: BOOLEAN
134: SoundExcludeRoutine(
135: IN OUT PLOCAL_DEVICE_INFO pLDI,
136: IN SOUND_EXCLUDE_CODE Code
137: )
138:
139: /*++
140:
141: Routine Description:
142:
143: Perform mutual exclusion for our devices
144:
145: Arguments:
146:
147: pLDI - device info for the device being open, closed, entered or left
148: Code - Function to perform (see devices.h)
149:
150: Return Value:
151:
152: The function value is the final status from the initialization operation.
153:
154: --*/
155: {
156: PGLOBAL_DEVICE_INFO pGDI;
157: BOOLEAN ReturnCode;
158:
159: pGDI = pLDI->pGlobalInfo;
160:
161: ReturnCode = FALSE;
162:
163: switch (Code) {
164: case SoundExcludeOpen:
165: if (pGDI->DeviceInUse == 0xFF) {
166: pGDI->DeviceInUse = pLDI->DeviceIndex;
167: ReturnCode = TRUE;
168: }
169: break;
170:
171: case SoundExcludeClose:
172:
173: ReturnCode = TRUE;
174: ASSERT(pGDI->DeviceInUse == pLDI->DeviceIndex);
175: pGDI->DeviceInUse = 0xFF;
176: break;
177:
178:
179: case SoundExcludeEnter:
180:
181: ReturnCode = TRUE;
182:
183: KeWaitForSingleObject(&pGDI->MidiMutex,
184: Executive,
185: KernelMode,
186: FALSE, // Not alertable
187: NULL);
188:
189: break;
190:
191: case SoundExcludeLeave:
192:
193: ReturnCode = TRUE;
194:
195: KeReleaseMutex(&pGDI->MidiMutex, FALSE);
196: break;
197:
198: case SoundExcludeQueryOpen:
199: ReturnCode = pGDI->DeviceInUse == pLDI->DeviceIndex;
200: break;
201:
202: }
203:
204: return ReturnCode;
205: }
206:
207:
208: NTSTATUS
209: DriverEntry(
210: IN PDRIVER_OBJECT pDriverObject,
211: IN PUNICODE_STRING RegistryPathName
212: )
213:
214: /*++
215:
216: Routine Description:
217:
218: This routine performs initialization for the sound system
219: device driver when it is first loaded.
220:
221: It is called DriverEntry by convention as this is the entry
222: point the IO subsystem looks for by default.
223:
224: The design is as follows :
225:
226: 0. Cleanup is always by calling SoundCleanup. This routine
227: is also called by the unload entry point.
228:
229: 1. Find which bus our device is on (this is needed for
230: mapping things via the Hal).
231:
232: 1. Allocate space to store our global info
233:
234: 1. Open the driver's registry information and read it
235:
236: 2. Fill in the driver object with our routines
237:
238: 3. Create device
239:
240: Currently, one device only is created -
241: 1. Midi output
242:
243: Customize each device type and initialize data
244:
245: Also store the registry string in our global info so we can
246: open it again to store volume settings etc on shutdown
247:
248: 4. Check hardware conflicts by calling IoReportResourceUsage
249: for each device (as required)
250: (this may need to be called again later if
251:
252: 5. Find our IO port and check the device is really there
253:
254:
255: Arguments:
256:
257: pDriverObject - Pointer to a driver object.
258: RegistryPathName - the path to our driver services node
259:
260: Return Value:
261:
262: The function value is the final status from the initialization operation.
263:
264: --*/
265:
266: {
267: /********************************************************************
268: *
269: * Local variables
270: *
271: ********************************************************************/
272:
273: //
274: // Return code from last function called
275: //
276:
277: NTSTATUS Status;
278:
279: //
280: // Configuration data :
281: //
282:
283: SOUND_CONFIG_DATA ConfigData;
284:
285: //
286: // Where we keep all general driver information
287: // We avoid using static data because :
288: // 1. Accesses are slower with 32-bit offsets
289: // 2. If we supported more than one card with the same driver
290: // we could not use static data
291: //
292:
293: PGLOBAL_DEVICE_INFO pGDI;
294:
295: /********************************************************************
296: *
297: * Initialize debugging
298: *
299: ********************************************************************/
300: #if DBG
301: DriverName = "SYNTH";
302: #endif
303:
304:
305: #if DBG
306: if (SoundDebugLevel >= 4) {
307: DbgBreakPoint();
308: }
309: #endif
310:
311: /********************************************************************
312: *
313: * Allocate our global info
314: *
315: ********************************************************************/
316:
317: pGDI =
318: (PGLOBAL_DEVICE_INFO)ExAllocatePool(
319: NonPagedPool,
320: sizeof(GLOBAL_DEVICE_INFO));
321:
322:
323: if (pGDI == NULL) {
324: return STATUS_INSUFFICIENT_RESOURCES;
325: }
326:
327: dprintf4((" GlobalInfo : %08lXH", pGDI));
328: RtlZeroMemory(pGDI, sizeof(GLOBAL_DEVICE_INFO));
329: pGDI->Key = GDI_KEY;
330:
331: pGDI->DriverObject = pDriverObject;
332:
333: //
334: // Initialize some of the device global info.
335: //
336:
337: pGDI->DeviceInUse = 0xFF; // Free
338:
339: KeInitializeMutex(&pGDI->MidiMutex,
340: 1 // Level
341: );
342:
343:
344: /********************************************************************
345: *
346: * See if we can find our bus. We run on both ISA and EISA
347: * We ASSUME that if there's an ISA bus we're on that
348: *
349: ********************************************************************/
350:
351: Status = SoundGetBusNumber(Isa, &pGDI->BusNumber);
352:
353: if (!NT_SUCCESS(Status)) {
354: //
355: // Cound not find an ISA bus so try EISA
356: //
357: Status = SoundGetBusNumber(Eisa, &pGDI->BusNumber);
358:
359: if (!NT_SUCCESS(Status)) {
360:
361: Status = SoundGetBusNumber(MicroChannel, &pGDI->BusNumber);
362:
363: if (!NT_SUCCESS(Status)) {
364: dprintf1(("driver does not work on non-Isa/Eisa/Mca"));
365: SoundCleanup(pGDI);
366: return Status;
367: }
368: pGDI->BusType = MicroChannel;
369:
370: } else {
371: pGDI->BusType = Eisa;
372: }
373: } else {
374: pGDI->BusType = Isa;
375: }
376:
377:
378: /********************************************************************
379: *
380: * Save our registry path. This is needed to save volume settings
381: * into the registry on shutdown. We append the parameters subkey
382: * at this stage to make things easier (since we discard this code).
383: *
384: ********************************************************************/
385:
386: Status = SoundSaveRegistryPath(RegistryPathName, &pGDI->RegistryPathName);
387: if (!NT_SUCCESS(Status)) {
388: SoundCleanup(pGDI);
389: return STATUS_INSUFFICIENT_RESOURCES;
390: }
391:
392:
393: //
394: // Set configuration to default in case we don't get all the
395: // values back from the registry.
396: //
397: // Also set default volume for all devices
398: //
399:
400: {
401: int i;
402: for (i = 0; i < NumberOfDevices ; i++) {
403: ConfigData.Volume[i].Left =
404: DeviceInit[i].DefaultVolume;
405: ConfigData.Volume[i].Right =
406: DeviceInit[i].DefaultVolume;
407: }
408: }
409:
410: //
411: // Get the system configuration information for this driver:
412: //
413: //
414: // Volume settings
415: //
416:
417: {
418: RTL_QUERY_REGISTRY_TABLE Table[2];
419:
420: RtlZeroMemory(Table, sizeof(Table));
421:
422: Table[0].QueryRoutine = SoundReadConfiguration;
423:
424: Status = RtlQueryRegistryValues(
425: RTL_REGISTRY_ABSOLUTE,
426: pGDI->RegistryPathName,
427: Table,
428: &ConfigData,
429: NULL);
430:
431: // all we read is volume - not important if fails.
432: // if (!NT_SUCCESS(Status)) {
433: // SoundCleanup(pGDI);
434: // return Status;
435: // }
436:
437: }
438:
439: //
440: // Check the synthesizer config
441: // safe to do this before creating devices as the resource usage
442: // is reported by the driver object, not the device object.
443: //
444: //
445: Status = SoundSynthPortValid(pGDI);
446:
447: if (!NT_SUCCESS(Status)) {
448: dprintf1(("Problem finding synthesizer hardware!"));
449: SoundCleanup(pGDI);
450: return Status;
451: }
452:
453:
454: //
455: // Create our devices
456: //
457: {
458: int i;
459:
460: for (i = 0; i < NumberOfDevices ; i++) {
461:
462: if (i == Opl3Device) {
463: //
464: // only create the Opl3 device if there is
465: // a new (opl3-compatible) synthesizer chip
466: if (!SoundMidiIsOpl3(&pGDI->Hw)) {
467: continue;
468: }
469: }
470:
471: Status = SoundCreateDevice(
472: &DeviceInit[i],
473: SOUND_CREATION_NO_NAME_RANGE, // No range for midi out
474: pDriverObject,
475: pGDI,
476: NULL,
477: &pGDI->Hw,
478: i,
479: &pGDI->DeviceObject[i]);
480:
481: if (!NT_SUCCESS(Status)) {
482: dprintf1(("Failed to create device %ls - status %8X",
483: DeviceInit[i].PrototypeName, Status));
484: SoundCleanup(pGDI);
485: return Status;
486: }
487: }
488: }
489:
490:
491: //
492: // Say we want to be called at shutdown time
493: //
494:
495: IoRegisterShutdownNotification(pGDI->DeviceObject[AdlibDevice]);
496:
497:
498: SoundMidiQuiet(AdlibDevice, &pGDI->Hw);
499:
500:
501:
502: //
503: // Initialize volume settings in hardware
504: //
505:
506: {
507: int i;
508: for (i = 0; i < NumberOfDevices; i++) {
509: PLOCAL_DEVICE_INFO pLDI;
510:
511: if (pGDI->DeviceObject[i]) {
512: pLDI = pGDI->DeviceObject[i]->DeviceExtension;
513:
514: pLDI->Volume = ConfigData.Volume[i];
515:
516: (*pLDI->DeviceInit->HwSetVolume)(pLDI);
517: }
518: }
519: }
520:
521:
522: //
523: // Initialize the driver object dispatch table.
524: //
525:
526: pDriverObject->DriverUnload = SoundUnload;
527: pDriverObject->MajorFunction[IRP_MJ_CREATE] = SoundDispatch;
528: pDriverObject->MajorFunction[IRP_MJ_CLOSE] = SoundDispatch;
529: pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SoundDispatch;
530: pDriverObject->MajorFunction[IRP_MJ_READ] = SoundDispatch;
531: pDriverObject->MajorFunction[IRP_MJ_WRITE] = SoundDispatch;
532: pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = SoundDispatch;
533: pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SoundShutdown;
534:
535:
536: return STATUS_SUCCESS;
537:
538: }
539:
540:
541:
542: VOID
543: SoundCleanup(
544: IN PGLOBAL_DEVICE_INFO pGDI
545: )
546:
547: /*++
548:
549: Routine Description:
550:
551: Clean up all resources allocated by our initialization
552:
553: Arguments:
554:
555: pGDI - Pointer to global data
556:
557: Return Value:
558:
559: NONE
560:
561: --*/
562:
563: {
564: //
565: // Unreport the driver's resources - we have to do this because
566: // we may not have any devices at this point
567: //
568:
569: {
570: BOOLEAN ResourceConflict;
571: CM_RESOURCE_LIST NullResourceList;
572: NullResourceList.Count = 0;
573:
574: IoReportResourceUsage(NULL,
575: pGDI->DriverObject,
576: &NullResourceList,
577: sizeof(ULONG),
578: NULL,
579: NULL,
580: 0,
581: FALSE,
582: &ResourceConflict);
583: }
584:
585: if (pGDI->DeviceObject[AdlibDevice]) {
586: PDRIVER_OBJECT DriverObject;
587:
588: IoUnregisterShutdownNotification(pGDI->DeviceObject[AdlibDevice]);
589:
590:
591: DriverObject = pGDI->DeviceObject[AdlibDevice]->DriverObject;
592:
593: // delete the devices we created
594: while (DriverObject->DeviceObject != NULL) {
595: //
596: // Undeclare resources used by device and
597: // delete the device object and associated data
598: //
599:
600: // one side-effect of freeing a device is that the
601: // DriverObject->DeviceObject pointer will be updated
602: // to point to the next remaining device object.
603:
604: SoundFreeDevice(DriverObject->DeviceObject);
605: }
606: }
607:
608: if (pGDI->Hw.SynthBase && pGDI->MemType == 0) {
609: MmUnmapIoSpace(pGDI->Hw.SynthBase, NUMBER_OF_SYNTH_PORTS);
610: }
611:
612: //
613: // Free device name
614: //
615:
616: if (pGDI->RegistryPathName) {
617: ExFreePool(pGDI->RegistryPathName);
618: }
619:
620: ExFreePool(pGDI);
621: }
622:
623:
624: VOID
625: SoundUnload(
626: IN OUT PDRIVER_OBJECT pDriverObject
627: )
628: {
629: PGLOBAL_DEVICE_INFO pGDI;
630:
631: dprintf3(("Unload request"));
632:
633: //
634: // Find our global data
635: //
636:
637: pGDI = ((PLOCAL_DEVICE_INFO)pDriverObject->DeviceObject->DeviceExtension)
638: ->pGlobalInfo;
639:
640: //
641: // Write out volume settings
642: //
643:
644: SoundSaveVolume(pGDI);
645:
646: //
647: // Assume all handles (and therefore interrupts etc) are closed down
648: //
649:
650: //
651: // Delete the things we allocated - devices, Interrupt objects,
652: // adapter objects. The driver object has a chain of devices
653: // across it.
654: //
655:
656: SoundCleanup(pGDI);
657:
658: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.