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