Annotation of ntddk/src/mmedia/synth/driver/init.c, revision 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.