|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1991 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: Sound Blaster device driver.
13:
14: Author:
15:
16: Robin Speed (RobinSp) 17-Oct-1992
17:
18: Environment:
19:
20: Kernel mode
21:
22: Revision History:
23:
24: --*/
25:
26: #include "sound.h"
27: #include "stdlib.h"
28:
29: //
30: // Local definitions
31: //
32: NTSTATUS
33: DriverEntry(
34: IN PDRIVER_OBJECT pDriverObject,
35: IN PUNICODE_STRING RegistryPathName
36: );
37: VOID
38: SoundCleanup(
39: IN PGLOBAL_DEVICE_INFO pGDI
40: );
41: VOID SoundUnload(
42: IN PDRIVER_OBJECT pDriverObject
43: );
44: BOOLEAN
45: SoundExcludeRoutine(
46: IN OUT PLOCAL_DEVICE_INFO pLDI,
47: IN SOUND_EXCLUDE_CODE Code
48: );
49:
50: //
51: // Remove initialization stuff from resident memory
52: //
53:
54: #ifdef ALLOC_PRAGMA
55: #pragma alloc_text(init,DriverEntry)
56: #endif
57:
58: //
59: // Device initialization data
60: //
61:
62: SOUND_DEVICE_INIT DeviceInit[NumberOfDevices] =
63: {
64: {
65: REG_VALUENAME_LEFTADC, REG_VALUENAME_RIGHTADC,
66: 0,
67: FILE_DEVICE_WAVE_IN,
68: WAVE_IN,
69: "LDWi",
70: DD_WAVE_IN_DEVICE_NAME_U,
71: SoundWaveDeferred,
72: SoundExcludeRoutine,
73: SoundWaveDispatch,
74: SoundWaveInGetCaps,
75: SoundNoVolume,
76: DO_DIRECT_IO
77: },
78: {
79: REG_VALUENAME_LEFTDAC, REG_VALUENAME_RIGHTDAC,
80: 0x90000000,
81: FILE_DEVICE_WAVE_OUT,
82: WAVE_OUT,
83: "LDWo",
84: DD_WAVE_OUT_DEVICE_NAME_U,
85: SoundWaveDeferred,
86: SoundExcludeRoutine,
87: SoundWaveDispatch,
88: SoundWaveOutGetCaps,
89: HwSetVolume,
90: DO_DIRECT_IO
91: },
92: {
93: NULL, NULL,
94: 0,
95: FILE_DEVICE_MIDI_OUT,
96: MIDI_OUT,
97: "LDMo",
98: DD_MIDI_OUT_DEVICE_NAME_U,
99: NULL,
100: SoundExcludeRoutine,
101: SoundMidiDispatch,
102: SoundMidiOutGetCaps,
103: SoundNoVolume,
104: DO_DIRECT_IO
105: },
106: {
107: NULL, NULL,
108: 0,
109: FILE_DEVICE_MIDI_IN,
110: MIDI_IN,
111: "LDMi",
112: DD_MIDI_IN_DEVICE_NAME_U,
113: SoundMidiInDeferred,
114: SoundExcludeRoutine,
115: SoundMidiDispatch,
116: SoundMidiInGetCaps,
117: SoundNoVolume,
118: DO_DIRECT_IO
119: },
120: {
121: REG_VALUENAME_LEFTLINEIN, REG_VALUENAME_RIGHTLINEIN,
122: 0,
123: FILE_DEVICE_SOUND,
124: AUX_DEVICE,
125: "LDLi",
126: DD_AUX_DEVICE_NAME_U,
127: NULL,
128: SoundExcludeRoutine,
129: SoundAuxDispatch,
130: SoundAuxGetCaps,
131: HwSetVolume,
132: DO_BUFFERED_IO
133: }
134: #ifdef MICMIX
135: ,
136: {
137: REG_VALUENAME_LEFTMICMIX, REG_VALUENAME_RIGHTMICMIX,
138: 0,
139: FILE_DEVICE_SOUND,
140: AUX_DEVICE,
141: "LDMc",
142: DD_AUX_DEVICE_NAME_U,
143: NULL,
144: SoundExcludeRoutine,
145: SoundAuxDispatch,
146: SoundAuxGetCaps,
147: HwSetVolume,
148: DO_BUFFERED_IO
149: }
150: #endif // MICMIX
151: #ifdef MASTERVOLUME
152: ,
153: {
154: REG_VALUENAME_LEFTMASTER, REG_VALUENAME_RIGHTMASTER,
155: DEF_AUX_VOLUME,
156: FILE_DEVICE_SOUND,
157: AUX_DEVICE,
158: "LDMa",
159: DD_AUX_DEVICE_NAME_U,
160: NULL, // No Dpc routine
161: SoundExcludeRoutine,
162: SoundAuxDispatch,
163: SoundAuxGetCaps,
164: SoundNoVolume, // Simulated volume setting
165: DO_BUFFERED_IO
166: }
167: #endif // MASTERVOLUME
168: };
169:
170:
171: NTSTATUS
172: SoundShutdown(
173: IN PDEVICE_OBJECT pDO,
174: IN PIRP pIrp
175: )
176: /*++
177:
178: Routine Description:
179:
180: Save away volume settings when the system is shut down
181:
182: Arguments:
183:
184: pDO - the device object we registered for shutdown with
185: pIrp - No used
186:
187: Return Value:
188:
189: The function value is the final status from the initialization operation.
190: Here STATUS_SUCCESS
191:
192: --*/
193: {
194: //
195: // Save volume for all devices
196: //
197:
198: PLOCAL_DEVICE_INFO pLDI;
199: PGLOBAL_DEVICE_INFO pGDI;
200:
201: pLDI = pDO->DeviceExtension;
202:
203: SoundSaveVolume(pLDI->pGlobalInfo);
204:
205: return STATUS_SUCCESS;
206: }
207:
208: BOOLEAN
209: SoundExcludeRoutine(
210: IN OUT PLOCAL_DEVICE_INFO pLDI,
211: IN SOUND_EXCLUDE_CODE Code
212: )
213:
214: /*++
215:
216: Routine Description:
217:
218: Perform mutual exclusion for our devices
219:
220: Arguments:
221:
222: pLDI - device info for the device being open, closed, entered or left
223: Code - Function to perform (see devices.h)
224:
225: Return Value:
226:
227: The function value is the final status from the initialization operation.
228:
229: --*/
230: {
231: PGLOBAL_DEVICE_INFO pGDI;
232: BOOLEAN ReturnCode;
233:
234: pGDI = pLDI->pGlobalInfo;
235:
236: ReturnCode = FALSE;
237:
238: switch (Code) {
239: case SoundExcludeOpen:
240:
241: //
242: // Special case - for sound blaster 1 midi out and
243: // midi in cannot run simultaneously
244: //
245:
246: if (SB1(&pGDI->Hw) &&
247: (pLDI->DeviceIndex == MidiOutDevice &&
248: pGDI->Usage == WaveInDevice ||
249: pLDI->DeviceIndex == MidiInDevice &&
250: pGDI->MidiInUse)) {
251: } else {
252:
253: switch (pLDI->DeviceIndex) {
254: case WaveInDevice:
255: case WaveOutDevice:
256: case MidiInDevice:
257:
258: if (pGDI->Usage == 0xFF) {
259: pGDI->Usage = pLDI->DeviceIndex;
260: ReturnCode = TRUE;
261: }
262: break;
263:
264: case MidiOutDevice:
265: if (!pGDI->MidiInUse) {
266: pGDI->MidiInUse = TRUE;
267: ReturnCode = TRUE;
268: }
269: break;
270:
271: default:
272: //
273: // aux devices should not receive this call
274: //
275:
276: ASSERT(FALSE);
277: break;
278: }
279: }
280: break;
281:
282: case SoundExcludeClose:
283:
284: ReturnCode = TRUE;
285: switch (pLDI->DeviceIndex) {
286: case WaveInDevice:
287: case WaveOutDevice:
288: case MidiInDevice:
289:
290: ASSERT(pGDI->Usage != 0xFF);
291: pGDI->Usage = 0xFF;
292: break;
293:
294: case MidiOutDevice:
295: ASSERT(pGDI->MidiInUse);
296: pGDI->MidiInUse = FALSE;
297: break;
298:
299: default:
300: //
301: // aux devices should not receive this call
302: //
303:
304: ASSERT(FALSE);
305: break;
306: }
307: break;
308:
309: case SoundExcludeEnter:
310:
311: ReturnCode = TRUE;
312:
313: switch (pLDI->DeviceIndex) {
314: case MidiOutDevice:
315:
316: KeWaitForSingleObject(&pGDI->MidiMutex,
317: Executive,
318: KernelMode,
319: FALSE, // Not alertable
320: NULL);
321:
322: break;
323:
324: default:
325:
326: KeWaitForSingleObject(&pGDI->DeviceMutex,
327: Executive,
328: KernelMode,
329: FALSE, // Not alertable
330: NULL);
331:
332: break;
333: }
334: break;
335:
336: case SoundExcludeLeave:
337:
338: ReturnCode = TRUE;
339:
340: switch (pLDI->DeviceIndex) {
341: case MidiOutDevice:
342: KeReleaseMutex(&pGDI->MidiMutex, FALSE);
343: break;
344:
345: default:
346: KeReleaseMutex(&pGDI->DeviceMutex, FALSE);
347: break;
348: }
349: break;
350:
351: case SoundExcludeQueryOpen:
352:
353: switch (pLDI->DeviceIndex) {
354: case WaveInDevice:
355: case WaveOutDevice:
356: case MidiInDevice:
357:
358: //
359: // Guess!
360: //
361: ReturnCode = pGDI->Usage == pLDI->DeviceIndex;
362:
363: break;
364:
365: case MidiOutDevice:
366:
367: ReturnCode = pGDI->MidiInUse;
368: break;
369:
370: default:
371:
372: ASSERT(FALSE);
373: break;
374: }
375: break;
376: }
377:
378: return ReturnCode;
379: }
380:
381:
382: NTSTATUS
383: DriverEntry(
384: IN PDRIVER_OBJECT pDriverObject,
385: IN PUNICODE_STRING RegistryPathName
386: )
387:
388: /*++
389:
390: Routine Description:
391:
392: This routine performs initialization for the sound system
393: device driver when it is first loaded
394:
395: The design is as follows :
396:
397: 0. Cleanup is always by calling SoundCleanup. This routine
398: is also called by the unload entry point.
399:
400: 1. Find which bus our device is on (this is needed for
401: mapping things via the Hal).
402:
403: 1. Allocate space to store our global info
404:
405: 1. Open the driver's registry information and read it
406:
407: 2. Fill in the driver object with our routines
408:
409: 3. Create devices
410:
411: 1. Wave input
412: 2. Wave output
413: 3. Midi output
414: 4. Line in
415: 5. Master volume control
416:
417: Customize each device type and initialize data
418:
419: Also store the registry string in our global info so we can
420: open it again to store volume settings etc on shutdown
421:
422: 4. Check hardware conflicts by calling IoReportResourceUsage
423: for each device (as required)
424:
425: 5. Find our IO port and check the device is really there
426:
427: 6. Allocate DMA channel
428:
429: 7. Connect interrupt
430:
431: 8. Test interrupt and DMA channel and write config data
432: back to the registry
433:
434: During this phase the interrupt and channel may get changed
435: if conflicts arise
436:
437: In any even close our registry handle
438:
439: Arguments:
440:
441: pDriverObject - Pointer to a driver object.
442: RegistryPathName - the path to our driver services node
443:
444: Return Value:
445:
446: The function value is the final status from the initialization operation.
447:
448: --*/
449:
450: {
451: /********************************************************************
452: *
453: * Local variables
454: *
455: ********************************************************************/
456:
457: //
458: // Return code from last function called
459: //
460:
461: NTSTATUS Status;
462:
463: //
464: // Configuration data :
465: //
466:
467: SB_CONFIG_DATA ConfigData;
468:
469: //
470: // Where we keep all general driver information
471: // We avoid using static data because :
472: // 1. Accesses are slower with 32-bit offsets
473: // 2. If we supported more than one card with the same driver
474: // we could not use static data
475: //
476:
477: PGLOBAL_DEVICE_INFO pGDI;
478:
479: //
480: // The number of devices we actually create
481: //
482:
483: int NumberOfDevicesCreated;
484:
485: /********************************************************************
486: *
487: * Initialize debugging
488: *
489: ********************************************************************/
490: #if DBG
491: DriverName = "SNDBLST";
492: #endif
493:
494:
495: #if DBG
496: if (SoundDebugLevel >= 4) {
497: DbgBreakPoint();
498: }
499: #endif
500:
501: /********************************************************************
502: *
503: * Allocate our global info
504: *
505: ********************************************************************/
506:
507: pGDI =
508: (PGLOBAL_DEVICE_INFO)ExAllocatePool(
509: NonPagedPool,
510: sizeof(GLOBAL_DEVICE_INFO));
511:
512: if (pGDI == NULL) {
513: return STATUS_INSUFFICIENT_RESOURCES;
514: }
515:
516: dprintf4((" GlobalInfo : %08lXH", pGDI));
517: RtlZeroMemory(pGDI, sizeof(GLOBAL_DEVICE_INFO));
518: pGDI->Key = GDI_KEY;
519:
520: pGDI->Usage = 0xFF; // Free
521: pGDI->DriverObject = pDriverObject;
522:
523: //
524: // Initialize some of the device global info. Note that ALL
525: // devices share the same exclusion. More than one device can
526: // be open in the case of Midi Output and other devices. In
527: // this case the midi output is synchronized with wave output
528: // either by the mutual exclusion or the wave spin lock which
529: // it grabs.
530: //
531:
532: KeInitializeMutex(&pGDI->DeviceMutex,
533: 2 // High level
534: );
535:
536: KeInitializeMutex(&pGDI->MidiMutex,
537: 1 // Low level
538: );
539:
540: //
541: // Initialize generic device environments - first get the
542: // hardware routines in place
543: //
544:
545: HwInitialize(pGDI);
546:
547: SoundInitMidiIn(&pGDI->MidiInfo,
548: &pGDI->Hw);
549:
550:
551: /********************************************************************
552: *
553: * See if we can find our bus. We run on both ISA and EISA
554: * We ASSUME that if there's an ISA bus we're on that
555: *
556: ********************************************************************/
557:
558: Status = SoundGetBusNumber(Isa, &pGDI->BusNumber);
559:
560: if (!NT_SUCCESS(Status)) {
561: //
562: // Cound not find an ISA bus so try EISA
563: //
564: Status = SoundGetBusNumber(Eisa, &pGDI->BusNumber);
565:
566: if (!NT_SUCCESS(Status)) {
567: dprintf1(("driver does not work on non-Isa/Eisa"));
568: SoundCleanup(pGDI);
569: return Status;
570: }
571:
572: pGDI->BusType = Eisa;
573: } else {
574: pGDI->BusType = Isa;
575: }
576:
577:
578: /********************************************************************
579: *
580: * Save our registry path. This is needed to save volume settings
581: * into the registry on shutdown. We append the parameters subkey
582: * at this stage to make things easier (since we discard this code).
583: *
584: ********************************************************************/
585:
586: Status = SoundSaveRegistryPath(RegistryPathName, &pGDI->RegistryPathName);
587: if (!NT_SUCCESS(Status)) {
588: SoundCleanup(pGDI);
589: return STATUS_INSUFFICIENT_RESOURCES;
590: }
591:
592:
593: //
594: // Set configuration to default in case we don't get all the
595: // values back from the registry.
596: //
597: // Also set default volume for all devices
598: //
599:
600: ConfigData.Port = SOUND_DEF_PORT;
601: ConfigData.InterruptNumber = SOUND_DEF_INT;
602: ConfigData.DmaChannel = SOUND_DEF_DMACHANNEL;
603: ConfigData.InputSource = INPUT_MIC; // Default to microphone
604: ConfigData.DmaBufferSize = DEFAULT_DMA_BUFFERSIZE;
605:
606: {
607: int i;
608: for (i = 0; i < NumberOfDevices ; i++) {
609: ConfigData.Volume[i].Left =
610: DeviceInit[i].DefaultVolume;
611: ConfigData.Volume[i].Right =
612: DeviceInit[i].DefaultVolume;
613: }
614: }
615:
616: //
617: // Get the system configuration information for this driver.
618: //
619: //
620: // Port, Interrupt, DMA channel, DMA buffer size
621: // Volume settings
622: //
623:
624: {
625: RTL_QUERY_REGISTRY_TABLE Table[2];
626:
627: RtlZeroMemory(Table, sizeof(Table));
628:
629: Table[0].QueryRoutine = SoundReadConfiguration;
630:
631: Status = RtlQueryRegistryValues(
632: RTL_REGISTRY_ABSOLUTE,
633: pGDI->RegistryPathName,
634: Table,
635: &ConfigData,
636: NULL);
637:
638: if (!NT_SUCCESS(Status)) {
639: SoundCleanup(pGDI);
640: return Status;
641: }
642: }
643:
644:
645: //
646: // print out some info about the configuration
647: //
648:
649: dprintf2(("port %3X", ConfigData.Port));
650: dprintf2(("int %u", ConfigData.InterruptNumber));
651: dprintf2(("DMA channel %u", ConfigData.DmaChannel));
652:
653: //
654: // Create a couple of devices to ease reporting problems and
655: // bypass kernel IO ss bugs
656: //
657: {
658: int i;
659:
660: for (i = 0; i < 2 ; i++) {
661: Status = SoundCreateDevice(
662: &DeviceInit[i],
663: (BOOLEAN)FALSE, // No range for midi out
664: pDriverObject,
665: pGDI,
666: (PVOID)&pGDI->WaveInfo,
667: &pGDI->Hw,
668: i,
669: &pGDI->DeviceObject[i]);
670:
671: if (!NT_SUCCESS(Status)) {
672: dprintf1(("Failed to create device %ls - status %8X",
673: DeviceInit[i].PrototypeName, Status));
674: SoundCleanup(pGDI);
675: return Status;
676: }
677: }
678: }
679:
680:
681: //
682: // Report all resources used.
683: //
684:
685: Status = SoundReportResourceUsage(
686: (PDEVICE_OBJECT)pGDI->DriverObject,
687: pGDI->BusType,
688: pGDI->BusNumber,
689: &ConfigData.InterruptNumber,
690: INTERRUPT_MODE,
691: IRQ_SHARABLE,
692: &ConfigData.DmaChannel,
693: &ConfigData.Port,
694: NUMBER_OF_SOUND_PORTS);
695:
696: if (!NT_SUCCESS(Status)) {
697: SoundCleanup(pGDI);
698: return Status;
699: }
700:
701: //
702: // Check the configuration and acquire the resources
703: // If this doesn't work try again after trying to init the
704: // Pro spectrum
705: //
706:
707: Status = SoundInitHardwareConfig(pGDI, &ConfigData);
708:
709: if (!NT_SUCCESS(Status)) {
710: SoundCleanup(pGDI);
711: return Status;
712: }
713:
714: SoundInitializeWaveInfo(&pGDI->WaveInfo,
715: (UCHAR)(SB1(&pGDI->Hw) ?
716: SoundReprogramOnInterruptDMA :
717: SoundAutoInitDMA),
718: SoundQueryFormat,
719: &pGDI->Hw);
720:
721:
722: //
723: // Create our devices
724: //
725: {
726: int i;
727: PLOCAL_DEVICE_INFO pLDI;
728:
729: if (pGDI->ProAudioSpectrum || SBPRO(&pGDI->Hw)) {
730: NumberOfDevicesCreated = NumberOfDevices;
731: } else {
732: //
733: // Early cards do not support wave volume setting
734: //
735: ((PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveInDevice]->DeviceExtension)
736: ->CreationFlags |= SOUND_CREATION_NO_VOLUME;
737: ((PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveOutDevice]->DeviceExtension)
738: ->CreationFlags |= SOUND_CREATION_NO_VOLUME;
739:
740: NumberOfDevicesCreated = 4;
741: }
742:
743: for (i = 2; i < NumberOfDevicesCreated ; i++) {
744:
745: //
746: // No Midi for Pro spectrum or ThunderBoard
747: //
748:
749: if (!((i == MidiInDevice ||
750: i == MidiOutDevice) &&
751: pGDI->Hw.ThunderBoard)) {
752:
753: //
754: // Create device
755: //
756:
757: Status = SoundCreateDevice(
758: &DeviceInit[i],
759: (UCHAR)(i == MidiInDevice || i == MidiOutDevice ?
760: SOUND_CREATION_NO_VOLUME : 0),
761: pDriverObject,
762: pGDI,
763: i == MidiInDevice || i == MidiOutDevice ?
764: (PVOID)&pGDI->MidiInfo :
765: NULL,
766: &pGDI->Hw,
767: i,
768: &pGDI->DeviceObject[i]);
769:
770: if (!NT_SUCCESS(Status)) {
771: dprintf1(("Failed to create device %ls - status %8X",
772: DeviceInit[i].PrototypeName, Status));
773: SoundCleanup(pGDI);
774: return Status;
775: }
776:
777:
778: #ifdef MASTERVOLUME
779: pLDI =
780: (PLOCAL_DEVICE_INFO)pGDI->DeviceObject[i]->DeviceExtension;
781: if (i == MasterVolumeDevice) {
782: pLDI->MasterVolume = TRUE;
783: }
784: #endif // MASTERVOLUME
785: }
786: }
787:
788: IoRegisterShutdownNotification(pGDI->DeviceObject[WaveInDevice]);
789: }
790:
791: //
792: // Initialize volume settings in hardware
793: //
794:
795: {
796: int i;
797: for (i = 0; i < NumberOfDevicesCreated; i++) {
798: PLOCAL_DEVICE_INFO pLDI;
799:
800: if (pGDI->DeviceObject[i]) {
801: pLDI = pGDI->DeviceObject[i]->DeviceExtension;
802:
803: pLDI->Volume = ConfigData.Volume[i];
804:
805: (*pLDI->DeviceInit->HwSetVolume)(pLDI);
806: }
807: }
808: }
809:
810: //
811: // initialise mixer level for midi synth to max volume
812: // (the synth driver does not access the mixer, and controls the
813: // volume via changes to the synth instrument parameters)
814: //
815: HwInitVolume(pGDI);
816:
817:
818: //
819: // Initialize the driver object dispatch table.
820: //
821:
822: pDriverObject->DriverUnload = SoundUnload;
823: pDriverObject->MajorFunction[IRP_MJ_CREATE] = SoundDispatch;
824: pDriverObject->MajorFunction[IRP_MJ_CLOSE] = SoundDispatch;
825: pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SoundDispatch;
826: pDriverObject->MajorFunction[IRP_MJ_READ] = SoundDispatch;
827: pDriverObject->MajorFunction[IRP_MJ_WRITE] = SoundDispatch;
828: pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = SoundDispatch;
829: pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SoundShutdown;
830:
831: //
832: // We'd like to get called on shutdown to save away our volume
833: // settings but only file systems get called.
834: //
835: // pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SoundDispatch;
836:
837:
838: return STATUS_SUCCESS;
839:
840: }
841:
842:
843:
844: VOID
845: SoundCleanup(
846: IN PGLOBAL_DEVICE_INFO pGDI
847: )
848:
849: /*++
850:
851: Routine Description:
852:
853: Clean up all resources allocated by our initialization
854:
855: Arguments:
856:
857: pGDI - Pointer to global data
858:
859: Return Value:
860:
861: NONE
862:
863: --*/
864:
865: {
866: //
867: // Free our interrupt
868: //
869:
870: if (pGDI->WaveInfo.Interrupt) {
871: IoDisconnectInterrupt(pGDI->WaveInfo.Interrupt);
872: }
873:
874: SoundFreeCommonBuffer(&pGDI->WaveInfo.DMABuf);
875:
876: if (pGDI->DeviceObject[WaveInDevice]) {
877:
878: //
879: // There are some devices to delete
880: //
881:
882: PDRIVER_OBJECT DriverObject;
883:
884: IoUnregisterShutdownNotification(pGDI->DeviceObject[WaveInDevice]);
885:
886: DriverObject = pGDI->DeviceObject[WaveInDevice]->DriverObject;
887:
888: while (DriverObject->DeviceObject != NULL) {
889: //
890: // Undeclare resources used by device and
891: // delete the device object and associated data
892: //
893:
894: SoundFreeDevice(DriverObject->DeviceObject);
895: }
896: }
897:
898: if (pGDI->MemType == 0) {
899: if (pGDI->Hw.PortBase != NULL) {
900: MmUnmapIoSpace(pGDI->Hw.PortBase, NUMBER_OF_SOUND_PORTS);
901: }
902: if (pGDI->PASInfo.PROBase != NULL) {
903: MmUnmapIoSpace(pGDI->PASInfo.PROBase, 0x10000);
904: }
905: }
906:
907:
908: //
909: // Free device name
910: //
911:
912: if (pGDI->RegistryPathName) {
913: ExFreePool(pGDI->RegistryPathName);
914: }
915:
916: ExFreePool(pGDI);
917: }
918:
919:
920: VOID
921: SoundUnload(
922: IN OUT PDRIVER_OBJECT pDriverObject
923: )
924: {
925: PGLOBAL_DEVICE_INFO pGDI;
926:
927: dprintf3(("Unload request"));
928:
929: //
930: // Find our global data
931: //
932:
933: pGDI = ((PLOCAL_DEVICE_INFO)pDriverObject->DeviceObject->DeviceExtension)
934: ->pGlobalInfo;
935:
936: //
937: // Write out volume settings
938: //
939:
940: SoundSaveVolume(pGDI);
941:
942: //
943: // Assume all handles (and therefore interrupts etc) are closed down
944: //
945:
946: //
947: // Delete the things we allocated - devices, Interrupt objects,
948: // adapter objects. The driver object has a chain of devices
949: // across it.
950: //
951:
952: SoundCleanup(pGDI);
953:
954: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.