Annotation of ntddk/src/mmedia/sndblst/driver/config.c, revision 1.1.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.