Annotation of ntddk/src/mmedia/sndblst/driver/config.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1991  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     config.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains code configuration code for the initialization phase
        !            12:     of the Microsoft Sound System 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: 
        !            27: #include "sound.h"
        !            28: 
        !            29: //
        !            30: // Internal routines
        !            31: //
        !            32: NTSTATUS
        !            33: SoundInitIoPort(
        !            34:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !            35:     IN OUT PSB_CONFIG_DATA ConfigData
        !            36: );
        !            37: NTSTATUS
        !            38: SoundPortValid(
        !            39:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !            40:     IN OUT PULONG Port
        !            41: );
        !            42: NTSTATUS
        !            43: SoundInitDmaChannel(
        !            44:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !            45:     IN OUT PULONG DmaChannel,
        !            46:     IN     ULONG DmaBufferSize
        !            47: );
        !            48: NTSTATUS
        !            49: SoundDmaChannelValid(
        !            50:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !            51:     IN OUT PULONG DmaChannel
        !            52: );
        !            53: NTSTATUS
        !            54: SoundInitInterrupt(
        !            55:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !            56:     IN OUT PULONG Interrupt
        !            57: );
        !            58: NTSTATUS
        !            59: SoundInterruptValid(
        !            60:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !            61:     IN OUT PULONG Interrupt
        !            62: );
        !            63: VOID
        !            64: SoundSetVersion(
        !            65:     IN PGLOBAL_DEVICE_INFO pGlobalInfo,
        !            66:     IN ULONG DSPVersion
        !            67: );
        !            68: 
        !            69: #ifdef ALLOC_PRAGMA
        !            70: #pragma alloc_text(init,SoundSetVersion)
        !            71: #pragma alloc_text(init,SoundInitHardwareConfig)
        !            72: #pragma alloc_text(init,SoundInitIoPort)
        !            73: #pragma alloc_text(init,SoundInitDmaChannel)
        !            74: #pragma alloc_text(init,SoundInitInterrupt)
        !            75: #pragma alloc_text(init,SoundSaveConfig)
        !            76: #pragma alloc_text(init,SoundReadConfiguration)
        !            77: #endif
        !            78: 
        !            79: 
        !            80: VOID
        !            81: SoundSetVersion(
        !            82:     IN PGLOBAL_DEVICE_INFO pGlobalInfo,
        !            83:     IN ULONG DSPVersion
        !            84: )
        !            85: /*++
        !            86: 
        !            87: Routine Description :
        !            88: 
        !            89:     Sets a version DWORD into the registry as a pseudo return code
        !            90:     to sndblst.drv
        !            91: 
        !            92:     As a side effect the key to the registry entry is closed.
        !            93: 
        !            94: Arguments :
        !            95: 
        !            96:     pGlobalInfo - Our driver global info
        !            97: 
        !            98:     DSPVersion - the version number we want to set
        !            99: 
        !           100: Return Value :
        !           101: 
        !           102:     None
        !           103: 
        !           104: --*/
        !           105: {
        !           106:     UNICODE_STRING VersionString;
        !           107: 
        !           108:     RtlInitUnicodeString(&VersionString, L"DSP Version");
        !           109:     if (pGlobalInfo->RegistryPathName) {
        !           110:         NTSTATUS SetStatus;
        !           111: 
        !           112:         SetStatus =
        !           113: 
        !           114:         SoundWriteRegistryDWORD(pGlobalInfo->RegistryPathName,
        !           115:                                 L"DSP Version",
        !           116:                                 DSPVersion);
        !           117: 
        !           118:         if (!NT_SUCCESS(SetStatus)) {
        !           119:             dprintf1(("Failed to write version - status %x", SetStatus));
        !           120:         }
        !           121:     }
        !           122: }
        !           123: 
        !           124: 
        !           125: NTSTATUS
        !           126: SoundInitHardwareConfig(
        !           127:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !           128:     IN     PSB_CONFIG_DATA ConfigData
        !           129: )
        !           130: {
        !           131: 
        !           132:     NTSTATUS Status;
        !           133: 
        !           134:     //
        !           135:     // Check the input source
        !           136:     //
        !           137: 
        !           138:     if (ConfigData->InputSource > INPUT_OUTPUT) {
        !           139:         return STATUS_DEVICE_CONFIGURATION_ERROR;
        !           140:     }
        !           141: 
        !           142:     pGDI->Hw.InputSource = ConfigData->InputSource;
        !           143: 
        !           144:     //
        !           145:     // Find port
        !           146:     //
        !           147: 
        !           148:     Status = SoundInitIoPort(pGDI, ConfigData);
        !           149: 
        !           150:     if (!NT_SUCCESS(Status)) {
        !           151:         return Status;
        !           152:     }
        !           153: 
        !           154:     //
        !           155:     // Find interrupt
        !           156:     //
        !           157: 
        !           158:     Status = SoundInitInterrupt(pGDI, &ConfigData->InterruptNumber);
        !           159: 
        !           160:     if (!NT_SUCCESS(Status)) {
        !           161:         return Status;
        !           162:     }
        !           163: 
        !           164:     //
        !           165:     // Find DMA channel
        !           166:     //
        !           167: 
        !           168:     Status = SoundInitDmaChannel(pGDI, &ConfigData->DmaChannel,
        !           169:                                  ConfigData->DmaBufferSize);
        !           170: 
        !           171:     if (!NT_SUCCESS(Status)) {
        !           172:         return Status;
        !           173:     }
        !           174: 
        !           175:     //
        !           176:     // Report the sound-blaster version number (and a flag
        !           177:     // to say if it's a Thunderboard.
        !           178:     // We do this via an entry in our registry node - under
        !           179:     // our device-specific section.  If this fails then configuration
        !           180:     // won't work so well but the driver will work fine.
        !           181:     //
        !           182:     // We use the registry handle generated by SoundReadConfiguration
        !           183: 
        !           184:     {
        !           185:         ULONG DSPVersion;
        !           186: 
        !           187:         DSPVersion = pGDI->Hw.DSPVersion;
        !           188: 
        !           189:         //
        !           190:         // If it's a pro audio spectrum set a bit to say it is
        !           191:         //
        !           192: 
        !           193:         if (pGDI->ProAudioSpectrum) {
        !           194:             DSPVersion |= 0x800;
        !           195:         } else {
        !           196:             //
        !           197:             // If it's a Thunderboard following comparison will fail.
        !           198:             // There's not much point having a constant for a flag
        !           199:             // because there's no logical way to share info between
        !           200:             // sndblst.sys and sndblst.drv
        !           201:             //
        !           202: 
        !           203:             if (pGDI->Hw.ThunderBoard) {
        !           204:                 DSPVersion |= 0x8000;
        !           205: 
        !           206:                 //
        !           207:                 // Note - it MAY be a pro spectrum !
        !           208:                 //
        !           209:             }
        !           210:         }
        !           211: 
        !           212:         //
        !           213:         // Put the version number in the registry (if we can)
        !           214:         //
        !           215: 
        !           216:         SoundSetVersion(pGDI, DSPVersion);
        !           217:     }
        !           218: 
        !           219: 
        !           220:     //
        !           221:     // turn on the speaker
        !           222:     //
        !           223: 
        !           224:     dspSpeakerOn(&pGDI->Hw);
        !           225: 
        !           226:     return STATUS_SUCCESS;
        !           227: 
        !           228: }
        !           229: 
        !           230: 
        !           231: 
        !           232: 
        !           233: NTSTATUS
        !           234: SoundInitIoPort(
        !           235:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !           236:     IN OUT PSB_CONFIG_DATA ConfigData
        !           237: )
        !           238: {
        !           239:     NTSTATUS Status;
        !           240: 
        !           241:     //
        !           242:     // Find where our device is mapped
        !           243:     //
        !           244: 
        !           245:     pGDI->Hw.PortBase = SoundMapPortAddress(
        !           246:                                pGDI->BusType,
        !           247:                                pGDI->BusNumber,
        !           248:                                ConfigData->Port,
        !           249:                                NUMBER_OF_SOUND_PORTS,
        !           250:                                &pGDI->MemType);
        !           251: 
        !           252:     //
        !           253:     // Check and see if the hardware is happy
        !           254:     //
        !           255: 
        !           256:     //
        !           257:     // Check the SoundBlaster is where we think it is and get
        !           258:     // the dsp version code.
        !           259:     //
        !           260: 
        !           261:     if (!dspReset(&pGDI->Hw)) {
        !           262:         NTSTATUS PasStatus = STATUS_DEVICE_CONFIGURATION_ERROR;
        !           263: 
        !           264: #ifdef PAS16 // There's a proper driver now
        !           265: 
        !           266:         //
        !           267:         // Try to wake up any lurking Pro audio spectrums
        !           268:         // that are asleep
        !           269:         //
        !           270: 
        !           271:         PasStatus = FindPasHardware(pGDI, ConfigData);
        !           272: 
        !           273: #endif // PAS16
        !           274: 
        !           275:         if (!NT_SUCCESS(PasStatus) || !dspReset(&pGDI->Hw)) {
        !           276:             pGDI->Hw.DSPVersion = 0;
        !           277:             SoundSetVersion(pGDI, 0x4000); // Means port was wrong
        !           278:             return STATUS_DEVICE_CONFIGURATION_ERROR;
        !           279:         }
        !           280: 
        !           281:         pGDI->ProAudioSpectrum = TRUE;
        !           282:     }
        !           283: 
        !           284:     pGDI->Hw.DSPVersion = dspGetVersion(&pGDI->Hw);
        !           285: 
        !           286:     //
        !           287:     // Check for Thunderboards and Pro Spectrums
        !           288:     //
        !           289: 
        !           290:     if (dspGetVersion(&pGDI->Hw) != pGDI->Hw.DSPVersion) {
        !           291:         pGDI->Hw.ThunderBoard = TRUE;
        !           292: 
        !           293: #ifdef PAS16 // We now have a proper driver for this
        !           294:         //
        !           295:         // See if this guy is a Pro audio spectrum.  By this
        !           296:         // stage it will be woken up but we still need to tell if
        !           297:         // it is one and set its features and mixer.
        !           298:         //
        !           299: 
        !           300:         if (pGDI->ProAudioSpectrum ||
        !           301:             NT_SUCCESS(FindPasHardware(pGDI, ConfigData))) {
        !           302: 
        !           303:             pGDI->ProAudioSpectrum = TRUE;
        !           304:             InitPasAndMixer(&pGDI->PASInfo, ConfigData);
        !           305:         }
        !           306: #endif // PAS16
        !           307:     }
        !           308: 
        !           309: 
        !           310:     //
        !           311:     // Set up version - dependent stuff
        !           312:     //
        !           313:     if (pGDI->Hw.DSPVersion >= MIN_DSP_VERSION) {
        !           314: 
        !           315:         pGDI->MinHz = 4000;
        !           316: 
        !           317:         if (SB1(&pGDI->Hw)) {
        !           318:             pGDI->MaxInHz = 12000;
        !           319:             pGDI->MaxOutHz = 23000;
        !           320:         } else {
        !           321:             if (!SBPRO(&pGDI->Hw)) {
        !           322:                 pGDI->MaxInHz = 13000;
        !           323:                 pGDI->MaxOutHz = 23000;
        !           324:             } else {
        !           325:                 pGDI->MaxInHz = 23000;
        !           326:                 pGDI->MaxOutHz = 23000;
        !           327:             }
        !           328:         }
        !           329:         return STATUS_SUCCESS;
        !           330:     } else {
        !           331:         return STATUS_DEVICE_CONFIGURATION_ERROR;
        !           332:     }
        !           333: }
        !           334: 
        !           335: 
        !           336: 
        !           337: NTSTATUS
        !           338: SoundInitDmaChannel(
        !           339:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !           340:     IN OUT PULONG DmaChannel,
        !           341:     IN     ULONG DmaBufferSize
        !           342: )
        !           343: {
        !           344:     NTSTATUS Status;
        !           345: 
        !           346:     DEVICE_DESCRIPTION DeviceDescription;      // DMA adapter object
        !           347: 
        !           348:     //
        !           349:     // See if we can get this channel
        !           350:     //
        !           351: 
        !           352:     //
        !           353:     // Zero the device description structure.
        !           354:     //
        !           355: 
        !           356:     RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
        !           357: 
        !           358:     //
        !           359:     // Get the adapter object for this card.
        !           360:     //
        !           361: 
        !           362:     DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
        !           363:     DeviceDescription.AutoInitialize = !SB1(&pGDI->Hw);
        !           364:     DeviceDescription.ScatterGather = FALSE;
        !           365:     DeviceDescription.DmaChannel = *DmaChannel;
        !           366:     DeviceDescription.InterfaceType = Isa;    // Must use Isa DMA
        !           367:     DeviceDescription.DmaWidth = Width8Bits;
        !           368:     DeviceDescription.DmaSpeed = Compatible;
        !           369:     DeviceDescription.MaximumLength = DmaBufferSize;
        !           370:     DeviceDescription.BusNumber = pGDI->BusNumber;
        !           371: 
        !           372:     return SoundGetCommonBuffer(&DeviceDescription, &pGDI->WaveInfo.DMABuf);
        !           373: }
        !           374: 
        !           375: 
        !           376: 
        !           377: NTSTATUS
        !           378: SoundInitInterrupt(
        !           379:     IN OUT PGLOBAL_DEVICE_INFO pGDI,
        !           380:     IN OUT PULONG Interrupt
        !           381: )
        !           382: {
        !           383:     NTSTATUS Status;
        !           384: 
        !           385:     //
        !           386:     // See if we can get this interrupt
        !           387:     //
        !           388: 
        !           389: 
        !           390:     Status = SoundConnectInterrupt(
        !           391:                *Interrupt,
        !           392:                pGDI->BusType,
        !           393:                pGDI->BusNumber,
        !           394:                SoundISR,
        !           395:                (PVOID)pGDI,
        !           396:                INTERRUPT_MODE,
        !           397:                IRQ_SHARABLE,
        !           398:                &pGDI->WaveInfo.Interrupt);
        !           399: 
        !           400:     if (!NT_SUCCESS(Status)) {
        !           401:         return Status;
        !           402:     }
        !           403: 
        !           404:     //
        !           405:     // Check if our interrupts are working.
        !           406:     // To do this we write a special code to make the card generate
        !           407:     // an interrupt.  We wait a reasonable amount of time for
        !           408:     // this to happen.  This is tried 10 times.
        !           409:     //
        !           410:     {
        !           411:         int i;
        !           412:         int j;
        !           413:         ULONG CurrentCount;
        !           414:         CurrentCount = pGDI->InterruptsReceived + 1;
        !           415: 
        !           416:         for (i = 0; i < 10; i++, CurrentCount++) {
        !           417: 
        !           418:             // Tell the card to generate an interrupt
        !           419: 
        !           420:             dspWrite(&pGDI->Hw, DSP_GENERATE_INT);
        !           421: 
        !           422:             //
        !           423:             // The interrupt routine will increment the InterruptsReceived
        !           424:             // field if we get an interrupt.
        !           425:             //
        !           426: 
        !           427:             for (j = 0; j < 1000; j++) {
        !           428:                 if (CurrentCount == pGDI->InterruptsReceived) {
        !           429:                     break;
        !           430:                 }
        !           431:                 KeStallExecutionProcessor(10);
        !           432:             }
        !           433: 
        !           434:             //
        !           435:             // This test catches both too many and too few interrupts
        !           436:             //
        !           437: 
        !           438:             if (CurrentCount != pGDI->InterruptsReceived) {
        !           439: 
        !           440:                 dprintf1(("Sound blaster configured at wrong interrupt"));
        !           441: 
        !           442:                 SoundSetVersion(pGDI, 0x2000); // Means wrong interrupt
        !           443:                 return STATUS_DEVICE_CONFIGURATION_ERROR;
        !           444:             }
        !           445:         }
        !           446:     }
        !           447: 
        !           448:     return STATUS_SUCCESS;
        !           449: }
        !           450: 
        !           451: 
        !           452: 
        !           453: NTSTATUS
        !           454: SoundSaveConfig(
        !           455:     IN  PWSTR DeviceKey,
        !           456:     IN  ULONG Port,
        !           457:     IN  ULONG DmaChannel,
        !           458:     IN  ULONG Interrupt,
        !           459:     IN  ULONG InputSource
        !           460: )
        !           461: {
        !           462:     NTSTATUS Status;
        !           463: 
        !           464:     Status = SoundWriteRegistryDWORD(DeviceKey, SOUND_REG_PORT, Port);
        !           465: 
        !           466:     if (!NT_SUCCESS(Status)) {
        !           467:         return Status;
        !           468:     }
        !           469: 
        !           470:     Status = SoundWriteRegistryDWORD(DeviceKey, SOUND_REG_DMACHANNEL, DmaChannel);
        !           471: 
        !           472:     if (!NT_SUCCESS(Status)) {
        !           473:         return Status;
        !           474:     }
        !           475: 
        !           476:     Status = SoundWriteRegistryDWORD(DeviceKey, SOUND_REG_INTERRUPT, Interrupt);
        !           477: 
        !           478:     if (!NT_SUCCESS(Status)) {
        !           479:         return Status;
        !           480:     }
        !           481: 
        !           482:     Status = SoundWriteRegistryDWORD(DeviceKey, SOUND_REG_INPUTSOURCE, InputSource);
        !           483: 
        !           484:     if (!NT_SUCCESS(Status)) {
        !           485:         return Status;
        !           486:     }
        !           487: 
        !           488:     //
        !           489:     // Make sure the config routine sees the data
        !           490:     //
        !           491: }
        !           492: 
        !           493: 
        !           494: VOID
        !           495: SoundSaveVolume(
        !           496:     PGLOBAL_DEVICE_INFO pGDI
        !           497: )
        !           498: {
        !           499:     NTSTATUS Status;
        !           500: 
        !           501:     //
        !           502:     // Write out left and right volume settings for each device
        !           503:     //
        !           504: 
        !           505:     int i;
        !           506:     for (i = 0; i < NumberOfDevices; i++) {
        !           507:         PLOCAL_DEVICE_INFO pLDI;
        !           508: 
        !           509:         if (pGDI->DeviceObject[i]){
        !           510:             pLDI = (PLOCAL_DEVICE_INFO)pGDI->DeviceObject[i]->DeviceExtension;
        !           511:             SoundSaveDeviceVolume(pLDI, pGDI->RegistryPathName);
        !           512:         }
        !           513: 
        !           514:     }
        !           515: 
        !           516:     //
        !           517:     // Make sure the volume settings make it do disk
        !           518:     //
        !           519: 
        !           520:     SoundFlushRegistryKey(pGDI->RegistryPathName);
        !           521: }
        !           522: 
        !           523: 
        !           524: 
        !           525: NTSTATUS
        !           526: SoundReadConfiguration(
        !           527:     IN  PWSTR ValueName,
        !           528:     IN  ULONG ValueType,
        !           529:     IN  PVOID ValueData,
        !           530:     IN  ULONG ValueLength,
        !           531:     IN  PVOID Context,
        !           532:     IN  PVOID EntryContext
        !           533: )
        !           534: /*++
        !           535: 
        !           536: Routine Description :
        !           537: 
        !           538:     Return configuration information for our device
        !           539: 
        !           540: Arguments :
        !           541: 
        !           542:     ConfigData - where to store the result
        !           543: 
        !           544: Return Value :
        !           545: 
        !           546:     NT status code - STATUS_SUCCESS if no problems
        !           547: 
        !           548: --*/
        !           549: {
        !           550:     PSB_CONFIG_DATA ConfigData;
        !           551: 
        !           552:     ConfigData = Context;
        !           553: 
        !           554:     if (ValueType == REG_DWORD) {
        !           555: 
        !           556:         if (wcsicmp(ValueName, SOUND_REG_PORT)  == 0) {
        !           557:             ConfigData->Port = *(PULONG)ValueData;
        !           558:             dprintf3(("Read Port Base : %x", ConfigData->Port));
        !           559:         }
        !           560: 
        !           561:         else if (wcsicmp(ValueName, SOUND_REG_INTERRUPT)  == 0) {
        !           562:             ConfigData->InterruptNumber = *(PULONG)ValueData;
        !           563:             dprintf3(("Read Interrupt : %x", ConfigData->InterruptNumber));
        !           564:         }
        !           565: 
        !           566:         else if (wcsicmp(ValueName, SOUND_REG_DMACHANNEL)  == 0) {
        !           567:             ConfigData->DmaChannel = *(PULONG)ValueData;
        !           568:             dprintf3(("Read DMA Channel : %x", ConfigData->DmaChannel));
        !           569:         }
        !           570: 
        !           571:         else if (wcsicmp(ValueName, SOUND_REG_DMABUFFERSIZE)  == 0) {
        !           572:             ConfigData->DmaBufferSize = *(PULONG)ValueData;
        !           573:             dprintf3(("Read DMA Channel : %x", ConfigData->DmaBufferSize));
        !           574:         }
        !           575: 
        !           576:         else if (wcsicmp(ValueName, SOUND_REG_INPUTSOURCE)  == 0) {
        !           577:             ConfigData->InputSource = *(PULONG)ValueData;
        !           578:             dprintf3(("Read Input Source : %s",
        !           579:                      ConfigData->InputSource == INPUT_LINEIN ? "Line in" :
        !           580:                      ConfigData->InputSource == INPUT_AUX ? "Aux" :
        !           581:                      ConfigData->InputSource == INPUT_MIC ? "Microphone" :
        !           582:                      ConfigData->InputSource == INPUT_OUTPUT ? "Output" :
        !           583:                      "Invalid input source"
        !           584:                      ));
        !           585:         }
        !           586: 
        !           587:         else {
        !           588:             int i;
        !           589:             for (i = 0; i < NumberOfDevices; i++) {
        !           590:                 if (DeviceInit[i].LeftVolumeName != NULL &&
        !           591:                     wcsicmp(ValueName, DeviceInit[i].LeftVolumeName) == 0) {
        !           592:                     ConfigData->Volume[i].Left = *(PULONG)ValueData;
        !           593: 
        !           594:                     dprintf3(("%ls = %8X", DeviceInit[i].LeftVolumeName,
        !           595:                               ConfigData->Volume[i].Left));
        !           596:                     break;
        !           597:                 }
        !           598:                 if (DeviceInit[i].RightVolumeName != NULL &&
        !           599:                     wcsicmp(ValueName, DeviceInit[i].RightVolumeName) == 0) {
        !           600:                     ConfigData->Volume[i].Right = *(PULONG)ValueData;
        !           601: 
        !           602:                     dprintf3(("%ls = %8X", DeviceInit[i].RightVolumeName,
        !           603:                               ConfigData->Volume[i].Right));
        !           604:                     break;
        !           605:                 }
        !           606:             }
        !           607:         }
        !           608: 
        !           609:     }
        !           610: 
        !           611:     return STATUS_SUCCESS;
        !           612: }

unix.superglobalmegacorp.com

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