|
|
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.