Annotation of ntddk/src/mmedia/synth/driver/init.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.