Annotation of Examples/DriverKit/SoundBlaster8/SoundBlaster8_reloc.tproj/SoundBlaster8Inline.h, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved. 
        !             3:  *
        !             4:  * HISTORY
        !             5:  * 4-Mar-94    Rakesh Dubey at NeXT
        !             6:  *      Created. 
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  * Base address. 
        !            11:  */
        !            12: static unsigned int sbBaseRegisterAddress = 0;
        !            13: 
        !            14: /*
        !            15:  * Register addresses. The base register addressess are determined at
        !            16:  * run-time. 
        !            17:  */
        !            18: 
        !            19: static unsigned int sbResetReg = 0;
        !            20: static unsigned int sbReadDataReg = 0;
        !            21: static unsigned int sbWriteDataOrCommandReg = 0;
        !            22: 
        !            23: static unsigned int sbWriteBufferStatusReg = 0;
        !            24: static unsigned int sbDataAvailableStatusReg = 0;
        !            25: 
        !            26: static __inline__
        !            27: void
        !            28: assignDSPRegAddresses(void)
        !            29: {
        !            30:     sbResetReg = 
        !            31:         (sbBaseRegisterAddress + SB_DSP_RESET_OFFSET);
        !            32:     sbReadDataReg = 
        !            33:         (sbBaseRegisterAddress + SB_DSP_READ_DATA_OFFSET);
        !            34:     sbWriteDataOrCommandReg = 
        !            35:         (sbBaseRegisterAddress + SB_DSP_WRITE_DATA_OR_COMMAND_OFFSET);
        !            36:         
        !            37:     sbWriteBufferStatusReg = 
        !            38:         (sbBaseRegisterAddress + SB_DSP_WRITE_BUFFER_STATUS_OFFSET);
        !            39:     sbDataAvailableStatusReg = 
        !            40:         (sbBaseRegisterAddress + SB_DSP_DATA_AVAILABLE_STATUS_OFFSET);
        !            41: }
        !            42: 
        !            43: 
        !            44: /*
        !            45:  * Print what is being written. 
        !            46:  */
        !            47: static __inline__
        !            48: void
        !            49: outbV(unsigned int address, unsigned int data)
        !            50: {
        !            51: #ifdef DEBUG
        !            52:     IOLog("SoundBlaster8: Writing %x at address %x\n", data, address);
        !            53: #endif DEBUG
        !            54:     outb(address, data);
        !            55: }
        !            56: 
        !            57: static unsigned int sbMixerAddressReg = 0;
        !            58: static unsigned int sbMixerDataReg = 0;
        !            59: 
        !            60: static __inline__
        !            61: void
        !            62: assignMixerRegAddresses(void)
        !            63: {
        !            64:     sbMixerAddressReg = 
        !            65:         (sbBaseRegisterAddress + SB_MIXER_ADDRESS_OFFSET);
        !            66:     sbMixerDataReg = 
        !            67:         (sbBaseRegisterAddress + SB_MIXER_DATA_OFFSET);
        !            68: }
        !            69: 
        !            70: /*
        !            71:  * Shadow registers for volume. Add more to this list when necessary. 
        !            72:  */
        !            73: 
        !            74: static sbStereoMixerRegister_t volMaster =     {0};
        !            75: static sbStereoMixerRegister_t volFM =                 {0};
        !            76: static sbStereoMixerRegister_t volLine =       {0};
        !            77: static sbStereoMixerRegister_t volVoc =        {0};
        !            78: 
        !            79: static sbMonoMixerRegister_t volMic =          {0};
        !            80: static sbMonoMixerRegister_t volCD =           {0};
        !            81: 
        !            82: static sbRecordingMode_t sbRecord =            {0};
        !            83: static sbPlaybackMode_t sbPlayback =           {0};
        !            84: 
        !            85: 
        !            86: #define MAX_WAIT_FOR_DATA_AVAILABLE            2000
        !            87: #define SB_WAIT_DELAY                          10
        !            88: #define SB_RESET_DELAY                         100
        !            89: 
        !            90: static  __inline__
        !            91: BOOL
        !            92: dspReadWait()
        !            93: {
        !            94:     int     i;
        !            95:     unsigned int val;
        !            96: 
        !            97:     for (i = 0; i < MAX_WAIT_FOR_DATA_AVAILABLE; i++) {
        !            98:        IODelay(SB_WAIT_DELAY);
        !            99:        val = inb(sbDataAvailableStatusReg);
        !           100:        if (val & 0x080)   /* MSB == 1 before reading */
        !           101:            return YES;
        !           102:     }
        !           103: 
        !           104:     /* Reset DSP, hopefully we will recover. */
        !           105:     outbV(sbResetReg, 0x01);
        !           106:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           107:     outbV(sbResetReg, 0x00);
        !           108:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           109:     IODelay(SB_RESET_DELAY);
        !           110: 
        !           111: #ifdef DEBUG
        !           112:     IOLog("SoundBlaster8: DSP not ready for reading!\n");
        !           113: #endif DEBUG
        !           114: 
        !           115:     return NO;
        !           116: }
        !           117: 
        !           118: static __inline__
        !           119: BOOL 
        !           120: dspWriteWait()
        !           121: {
        !           122:     int     i;
        !           123:     unsigned int val;
        !           124: 
        !           125:     for (i = 0; i < MAX_WAIT_FOR_DATA_AVAILABLE; i++) {
        !           126:        IODelay(SB_WAIT_DELAY);
        !           127:        val = inb(sbWriteBufferStatusReg);
        !           128:        if (!(val & 0x080))     /* MSB == 0 before writing */
        !           129:            return YES;
        !           130:     }
        !           131: 
        !           132:     /* Reset DSP */
        !           133:     outbV(sbResetReg, 0x01);
        !           134:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           135:     outbV(sbResetReg, 0x00);
        !           136:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           137:     IODelay(SB_RESET_DELAY);
        !           138: 
        !           139: #ifdef DEBUG
        !           140:     IOLog("SoundBlaster8: DSP not ready for writing!\n");
        !           141: #endif DEBUG
        !           142: 
        !           143:     return NO;
        !           144: }
        !           145: 
        !           146: /*
        !           147:  * Send some data or command to SoundBlaster8 DSP. 
        !           148:  */
        !           149: static
        !           150: BOOL
        !           151: writeToDSP(unsigned int dataOrCommand)
        !           152: {
        !           153:     outbV(sbWriteDataOrCommandReg, dataOrCommand);
        !           154:     IODelay(SB_DATA_WRITE_DELAY);
        !           155: 
        !           156: #ifdef DEBUG
        !           157:     //IOLog("SoundBlaster8: Wrote DSP command %x\n", dataOrCommand);
        !           158: #endif DEBUG
        !           159: 
        !           160:     return YES;
        !           161: }
        !           162: 
        !           163: /*
        !           164:  * Read from the SoundBlaster DSP. 
        !           165:  */
        !           166: static
        !           167: unsigned int
        !           168: readFromDSP(void)
        !           169: {
        !           170:     unsigned int val;
        !           171:     
        !           172:     val = inb(sbReadDataReg);
        !           173:     IODelay(SB_DATA_READ_DELAY);
        !           174: 
        !           175: #ifdef DEBUG
        !           176:     IOLog("SoundBlaster8: read from DSP %x\n", val);
        !           177: #endif DEBUG
        !           178: 
        !           179:     return val;
        !           180: }
        !           181:     
        !           182: /*
        !           183:  * Function to read from the Mixer registers. 
        !           184:  */
        !           185: static __inline__
        !           186: unsigned int
        !           187: inbIXMixer(unsigned int address)
        !           188: {
        !           189:     unsigned int val = 0xff;
        !           190:         
        !           191:     outbV(sbMixerAddressReg, address);
        !           192:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           193:     val = inb(sbMixerDataReg);
        !           194:     
        !           195: #ifdef DEBUG
        !           196:     IOLog("SoundBlaster8: Mixer address %x. Read %x\n", address, val);
        !           197: #endif DEBUG
        !           198:     return val;
        !           199: }
        !           200: 
        !           201: /*
        !           202:  * Function to write to the Mixer registers. 
        !           203:  */
        !           204: static  __inline__
        !           205: void
        !           206: outbIXMixer(unsigned int address, unsigned int val)
        !           207: {
        !           208:     outbV(sbMixerAddressReg, address);
        !           209:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           210:     outbV(sbMixerDataReg, val);
        !           211:     IODelay(SB_DATA_WRITE_DELAY);
        !           212: 
        !           213: #ifdef DEBUG
        !           214:     IOLog("SoundBlaster8: Mixer address %x. Wrote %x\n", address, val);
        !           215: #endif DEBUG
        !           216: }
        !           217: 
        !           218: /*
        !           219:  * Initialize DSP registers. There aren't any.
        !           220:  */
        !           221: 
        !           222: static __inline__
        !           223: void
        !           224: initDSPRegisters(void)
        !           225: {
        !           226: }
        !           227: 
        !           228: /*
        !           229:  * Initialize the registers on the Mixer. 
        !           230:  */
        !           231: 
        !           232: static __inline__
        !           233: void
        !           234: initMixerRegisters(void)
        !           235: {
        !           236:     if (sbCardType.mixerPresent == NO)
        !           237:         return;
        !           238: 
        !           239: #ifdef DEBUG
        !           240:     IOLog("SoundBlaster8: Initializing mixer registers.\n");
        !           241: #endif DEBUG
        !           242: 
        !           243:     /*
        !           244:      * First set the volume controlling registers to their default values. 
        !           245:      */
        !           246:     volMaster.reg.left = 10;
        !           247:     volMaster.reg.right = 10;
        !           248:     outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
        !           249:     
        !           250:     volFM.reg.left = 0;
        !           251:     volFM.reg.right = 0;
        !           252:     outbIXMixer(MC_FM_VOLUME, volFM.data);
        !           253:     
        !           254:     volCD = 0;
        !           255:     outbIXMixer(MC_CD_VOLUME, volCD);
        !           256:     
        !           257:     volLine.reg.left = 0;
        !           258:     volLine.reg.right = 0;
        !           259:     outbIXMixer(MC_LINE_VOLUME, volLine.data);
        !           260:     
        !           261:     volVoc.reg.left = 10;
        !           262:     volVoc.reg.right = 10;
        !           263:     outbIXMixer(MC_VOC_VOLUME, volVoc.data);
        !           264:     
        !           265:     /* Microphone can go only upto 7. */
        !           266:     volMic = 6;
        !           267:     outbIXMixer(MC_MICROPHONE_VOLUME, volMic);
        !           268:     
        !           269:     /* 
        !           270:      * Now set the record and playback mode registers.
        !           271:      */
        !           272:     sbRecord.data = 0;
        !           273:     sbRecord.reg.source = SB_RECORD_SOURCE_MIC;
        !           274:     sbRecord.reg.inputFilter = SB_RECORD_ANFI_OFF;
        !           275:     sbRecord.reg.highFreq = SB_RECORD_FREQ_HIGH;
        !           276:     outbIXMixer(MC_RECORD_CONTROL, sbRecord.data);
        !           277:     
        !           278:     sbPlayback.data = 0;
        !           279:     sbPlayback.reg.outputFilter = SB_PLAYBACK_DNFI_OFF;
        !           280:     sbPlayback.reg.stereo = SB_PLAYBACK_STEREO;
        !           281:     outbIXMixer(MC_PLAYBACK_CONTROL, sbPlayback.data);
        !           282: }
        !           283: 
        !           284: /*
        !           285:  * Input can be either microphone level or line level. We don't support other
        !           286:  * inputs. 
        !           287:  */
        !           288: 
        !           289: static __inline__
        !           290: void
        !           291: setInputLevel(unsigned int level)
        !           292: {
        !           293:     if (sbCardType.mixerPresent == NO)
        !           294:         return;
        !           295:         
        !           296:     if (level == LINE_LEVEL_INPUT)      {
        !           297:         sbRecord.reg.source = SB_RECORD_SOURCE_LINE;
        !           298:     } else {
        !           299:         sbRecord.reg.source = SB_RECORD_SOURCE_MIC;
        !           300:     }
        !           301:     
        !           302:     outbIXMixer(MC_RECORD_CONTROL, sbRecord.data);
        !           303: }
        !           304: 
        !           305: /*
        !           306:  * Output level cannot be changed. 
        !           307:  */
        !           308: 
        !           309: static __inline__
        !           310: void
        !           311: setOutputLevel(unsigned int channel, unsigned int level)
        !           312: {
        !           313: #ifdef DEBUG
        !           314:     IOLog("SoundBlaster8: Audio output level is fixed.\n");
        !           315: #endif DEBUG
        !           316: }
        !           317: 
        !           318: /*
        !           319:  * Initialize the hardware registers. 
        !           320:  */
        !           321: static __inline__
        !           322: void 
        !           323: initRegisters(void)
        !           324: {
        !           325:     initDSPRegisters();
        !           326:     initMixerRegisters();
        !           327: }
        !           328: 
        !           329: 
        !           330: /*
        !           331:  * These two routines are used to avoid clicks. 
        !           332:  */
        !           333: 
        !           334: static __inline__
        !           335: void 
        !           336: muteOutput(void)
        !           337: {
        !           338:     sbStereoMixerRegister_t volMaster = {0};
        !           339:     
        !           340:     if (sbCardType.mixerPresent == NO)
        !           341:         return;
        !           342:                 
        !           343:     volMaster.reg.left = 0;
        !           344:     volMaster.reg.right = 0;
        !           345:     
        !           346:     outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
        !           347: }
        !           348: 
        !           349: /*
        !           350:  * This takes it back to the old values. So it is not exactly unmute.
        !           351:  */
        !           352: static __inline__
        !           353: void 
        !           354: unMuteOutput(void)
        !           355: {
        !           356:     if (sbCardType.mixerPresent == NO)
        !           357:         return;
        !           358:         
        !           359:     outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
        !           360: }
        !           361: 
        !           362: /*
        !           363:  * This routine does a quick reset of the card. This is needed because
        !           364:  * apparently the SoundBlaster8 cards need to be reset if you go from the
        !           365:  * high speed to the low speed mode (wonderful world of hardware). 
        !           366:  */
        !           367: 
        !           368: static __inline__
        !           369: void
        !           370: resetDSPQuick(void)
        !           371: {
        !           372:     outbV(sbResetReg, 0x01);
        !           373:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           374:     outbV(sbResetReg, 0x00);
        !           375:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           376:     
        !           377:     /* It takes about 100us to reset */
        !           378:     dspReadWait();
        !           379:     if (readFromDSP() != 0xaa)    {
        !           380:         IOLog("SoundBlaster8: Can not reset DSP.\n");
        !           381:     }
        !           382: }
        !           383: 
        !           384: 
        !           385: #define SB_DELAY                                       100
        !           386: #define MAX_RESET_WAIT                         1000
        !           387: 
        !           388: /*
        !           389:  * Reset the SoundBlaster card. This routine also detects if the card is
        !           390:  * present and the type of card. 
        !           391:  */
        !           392: static __inline__
        !           393: void
        !           394: resetDSP(void)
        !           395: {
        !           396:     unsigned int val;
        !           397: 
        !           398:     /*
        !           399:      * Assume no sound card in the system. 
        !           400:      */
        !           401:     sbCardType.version = SB_NONE;
        !           402:     sbCardType.name = "";
        !           403:     sbCardType.majorVersion = 0;
        !           404:     sbCardType.minorVersion = 0;
        !           405:     sbCardType.mixerPresent = NO;
        !           406:     
        !           407:     outbV(sbResetReg, 0x01);
        !           408:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           409:     outbV(sbResetReg, 0x00);
        !           410:     IODelay(SB_ADDRESS_WRITE_DELAY);
        !           411:     
        !           412:     /* Now we can read the data. */
        !           413:     dspReadWait();
        !           414:     val = readFromDSP();
        !           415:     if (val == 0xaa)    {
        !           416: #ifdef DEBUG
        !           417:         IOLog("SoundBlaster8: DSP detected.\n");
        !           418: #endif DEBUG
        !           419:         IOSleep(1);
        !           420:     } else {
        !           421: #ifdef DEBUG
        !           422:         IOLog("SoundBlaster8: Read ID %x is wrong.\n", val);
        !           423:         IOLog("SoundBlaster8: SoundBlaster not detected at address 0x%0x.\n", 
        !           424:                 sbBaseRegisterAddress);
        !           425: #endif DEBUG
        !           426:         return;
        !           427:     }
        !           428: 
        !           429:     /*
        !           430:      * We have a SoundBlaster card. We will upgrade it to a pro if we detect
        !           431:      * a mixer as well. 
        !           432:      */
        !           433:     sbCardType.version = SB_CLASSIC;
        !           434: 
        !           435:     /*
        !           436:      * Another confirmatory test here. This is not documented in the SB SDK
        !           437:      * so it might fail on some compatible cards. Maybe we should just print
        !           438:      * a warning message if this test fails. 
        !           439:      */
        !           440:     dspWriteWait();
        !           441:     writeToDSP(DC_INVERT_BYTE);
        !           442:     
        !           443:     dspWriteWait();
        !           444:     writeToDSP(0x43);   /* Send some test pattern. */
        !           445:     
        !           446:     dspReadWait();
        !           447:     val = readFromDSP();
        !           448:     
        !           449:     if (val == 0xbc)    {
        !           450: #ifdef DEBUG
        !           451:         IOLog("SoundBlaster8: Invert test passed.\n");
        !           452: #endif DEBUG
        !           453:     } else      {
        !           454: #ifdef DEBUG
        !           455:         IOLog("SoundBlaster8: Invert test failed!!\n");
        !           456:         IOLog("SoundBlaster8: SoundBlaster not detected at address 0x%0x.\n", 
        !           457:                 sbBaseRegisterAddress);
        !           458: #endif DEBUG
        !           459:     }
        !           460: 
        !           461:     /*
        !           462:      * Reset the DSP here because sometimes you may get crazy values as
        !           463:      * version. So just to be on the safe side.. 
        !           464:      */
        !           465:     resetDSPQuick();
        !           466:     
        !           467:     /*
        !           468:      * Now we know that a SoundBlaster or compatible card exists. We need to
        !           469:      * find the version number to decide the type of card.
        !           470:      */
        !           471:     dspWriteWait();
        !           472:     writeToDSP(DC_GET_VERSION);
        !           473: 
        !           474:     dspReadWait();
        !           475:     sbCardType.majorVersion = readFromDSP() & 0x0f;
        !           476:     sbCardType.minorVersion = readFromDSP() & 0x0f;
        !           477:     
        !           478: #ifdef DEBUG
        !           479:     //IOLog("SoundBlaster8: Major 0x%x Minor 0x%x\n", sbCardType.majorVersion, sbCardType.minorVersion);
        !           480: #endif DEBUG
        !           481: 
        !           482:     /*
        !           483:      * Upgrade the card to SB_20 or SB_16 depending upon what the version
        !           484:      * number reads. 
        !           485:      */
        !           486:     if (sbCardType.majorVersion >= 2)
        !           487:         sbCardType.version = SB_20;
        !           488:  
        !           489:     if (sbCardType.majorVersion >= 4)
        !           490:         sbCardType.version = SB_16;
        !           491: }
        !           492: 
        !           493: 
        !           494: 
        !           495: static __inline__
        !           496: void
        !           497: resetMixer(void)
        !           498: {
        !           499:     unsigned int val1, val2;
        !           500:     
        !           501:     /*
        !           502:      * Reset the mixer by sending zero to both address and data ports.
        !           503:      */
        !           504:      outbIXMixer(0x0, 0x0);
        !           505: 
        !           506:     /*
        !           507:      * Now try to write and then read from one of the mixer registers. 
        !           508:      */
        !           509:      outbIXMixer(MC_MASTER_VOLUME, 0x15);
        !           510:      outbIXMixer(MC_MICROPHONE_VOLUME, 0x13);
        !           511:      
        !           512:      val1 = inbIXMixer(MC_MASTER_VOLUME);
        !           513:      val2 = inbIXMixer(MC_MICROPHONE_VOLUME);
        !           514: 
        !           515:     if ((val1 == 0x15) && (val2 == 0x13)) {
        !           516:        sbCardType.mixerPresent = YES;
        !           517:     } else {
        !           518:        sbCardType.mixerPresent = NO;
        !           519:     }
        !           520:                 
        !           521:     /*
        !           522:      * Try once more, so that we are really sure. 
        !           523:      */
        !           524:      outbIXMixer(MC_LINE_VOLUME, 0x17);
        !           525:      outbIXMixer(MC_FM_VOLUME, 0x19);
        !           526: 
        !           527:      val1 = inbIXMixer(MC_LINE_VOLUME);
        !           528:      val2 = inbIXMixer(MC_FM_VOLUME);
        !           529: 
        !           530:     if ((val1 == 0x17) && (val2 == 0x19)) {
        !           531:        sbCardType.mixerPresent = YES;
        !           532:     } else {
        !           533:        sbCardType.mixerPresent = NO;
        !           534:     }
        !           535: 
        !           536:     /*
        !           537:      * We have a pro card if we found the mixer. 
        !           538:      */
        !           539:     if (sbCardType.mixerPresent == YES) {
        !           540:         sbCardType.version = SB_PRO;
        !           541:         outbIXMixer(0x0, 0x0);          /* reset the mixer to a good state */
        !           542:     }
        !           543:      
        !           544: #ifdef DEBUG
        !           545:      if (sbCardType.mixerPresent == YES)
        !           546:         IOLog("SoundBlaster8: Mixer detected.\n");
        !           547:      else
        !           548:         IOLog("SoundBlaster8: Mixer not detected.\n");
        !           549: #endif DEBUG
        !           550: }
        !           551: 
        !           552: 
        !           553: /*
        !           554:  * Reset all hardware and bring us back to the default state. 
        !           555:  */
        !           556: static __inline__
        !           557: void 
        !           558: resetHardware(void)
        !           559: {
        !           560:     resetDSP();
        !           561:     resetMixer();
        !           562:     initRegisters();
        !           563: }
        !           564: 
        !           565: /*
        !           566:  * There seems to be no way to change input gain. 
        !           567:  */
        !           568: static  __inline__
        !           569: void 
        !           570: setInputGain(unsigned int channel, unsigned int gain)
        !           571: {
        !           572:     if (sbCardType.mixerPresent == NO)
        !           573:         return;
        !           574:         
        !           575:     volMic = gain;
        !           576:     outbIXMixer(MC_MICROPHONE_VOLUME, volMic);
        !           577:     
        !           578: #ifdef DEBUG
        !           579:     IOLog("SoundBlaster8: set input gain %d\n", gain);
        !           580: #endif DEBUG
        !           581: }
        !           582: 
        !           583: static  __inline__
        !           584: void
        !           585: setOutputAttenuation(unsigned int channel, unsigned int attenuation)
        !           586: {
        !           587:     if (sbCardType.mixerPresent == NO)
        !           588:         return;
        !           589:         
        !           590:     if (channel == LEFT_CHANNEL) {
        !           591:         volMaster.reg.left = attenuation;
        !           592:         outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
        !           593: 
        !           594:     } else {
        !           595:         volMaster.reg.right = attenuation;
        !           596:         outbIXMixer(MC_MASTER_VOLUME, volMaster.data);
        !           597:     }
        !           598: #ifdef DEBUG
        !           599:     IOLog("SoundBlaster8: set output attenuation %d\n", attenuation);
        !           600: #endif DEBUG
        !           601: }
        !           602: 
        !           603: /*
        !           604:  * This will not work for SB16 running in SBPro compatibility mode. The mixer
        !           605:  * registers need to be written to mute output. 
        !           606:  */
        !           607: 
        !           608: static __inline__
        !           609: void
        !           610: enableAudioOutput(BOOL enable)
        !           611: {
        !           612:     dspWriteWait();
        !           613:     if (enable) {
        !           614:         writeToDSP(DC_TURN_ON_SPEAKER);
        !           615:     } else {
        !           616:         writeToDSP(DC_TURN_OFF_SPEAKER);
        !           617:     }
        !           618: }
        !           619: 
        !           620: static  __inline__
        !           621: void    setSampleBufferCounter(unsigned int count)
        !           622: {
        !           623:     if (!lowSpeedDMA)  {
        !           624:        dspWriteWait();
        !           625:         writeToDSP(DC_SET_BLOCK_SIZE);
        !           626:     } 
        !           627:     
        !           628:     count -= 1;
        !           629:     dspWriteWait();
        !           630:     writeToDSP(count & 0x0ff);
        !           631:     dspWriteWait();
        !           632:     writeToDSP((count >> 8) & 0x0ff);
        !           633: #ifdef DEBUG
        !           634:     //IOLog("SoundBlaster8: buffer counter set to %x\n", count);
        !           635: #endif DEBUG
        !           636: }
        !           637: 
        !           638: /*
        !           639:  * Start DMA. Command patterns are different depending upon whether we are
        !           640:  * doing low speed or high speed transfers. 
        !           641:  */
        !           642:      
        !           643: static __inline__
        !           644: void startDMA(unsigned int direction)
        !           645: {       
        !           646:     dspWriteWait();
        !           647:     if (lowSpeedDMA)    {
        !           648:         if (direction == DMA_DIRECTION_IN) 
        !           649:             writeToDSP(DC_START_LS_DMA_ADC_8);
        !           650:         else
        !           651:             writeToDSP(DC_START_LS_DMA_DAC_8);
        !           652:     } else {
        !           653:         if (direction == DMA_DIRECTION_IN) 
        !           654:             writeToDSP(DC_START_HS_DMA_ADC_8);
        !           655:         else
        !           656:             writeToDSP(DC_START_HS_DMA_DAC_8);
        !           657:     }
        !           658: }
        !           659: 
        !           660: /* No can do */
        !           661: static __inline__
        !           662: void enableCodecInterrupts(void)
        !           663: {
        !           664: }
        !           665: 
        !           666: static __inline__
        !           667: void disableCodecInterrupts(void)
        !           668: {
        !           669: }
        !           670: 
        !           671: static __inline__
        !           672: void stopDMA(void)
        !           673: {
        !           674:     writeToDSP(DC_HALT_DMA);
        !           675: }
        !           676: 
        !           677: /*
        !           678:  * This routine will stop input dma. 
        !           679:  */
        !           680: static __inline__
        !           681: void stopDMAInput(void)
        !           682: {
        !           683:     stopDMA();
        !           684: }
        !           685: 
        !           686: /*
        !           687:  * Likewise, but for output dma. 
        !           688:  */
        !           689: static __inline__
        !           690: void stopDMAOutput(void)
        !           691: {
        !           692:     stopDMA();
        !           693: }
        !           694: 
        !           695: /*
        !           696:  * Select between DSP_MONO_MODE and DSP_STEREO_MODE mode. Note that stereo
        !           697:  * recording is undocumented so it could potentially break on some clone
        !           698:  * cards. 
        !           699:  */
        !           700: static __inline__
        !           701: void setCodecDataMode(unsigned int mode, unsigned int dir)
        !           702: {
        !           703:     if (sbCardType.mixerPresent == NO)
        !           704:         return;
        !           705:         
        !           706:     if (dir == DMA_DIRECTION_OUT) {
        !           707:        if (mode == DSP_STEREO_MODE) {
        !           708:            sbPlayback.reg.stereo = SB_PLAYBACK_STEREO;
        !           709:        } else {
        !           710:            sbPlayback.reg.stereo = SB_PLAYBACK_MONO;
        !           711:        }
        !           712:        outbIXMixer(MC_PLAYBACK_CONTROL, sbPlayback.data);
        !           713:     } else if (dir == DMA_DIRECTION_IN)        {
        !           714:        dspWriteWait();
        !           715:        if (mode == DSP_STEREO_MODE) {
        !           716:            writeToDSP(DC_RECORD_IN_STEREO);
        !           717:        } else {
        !           718:            writeToDSP(DC_RECORD_IN_MONO);
        !           719:        }
        !           720:     }
        !           721: }
        !           722: 
        !           723: 
        !           724: static __inline__
        !           725: void setCodecSamplingRate(unsigned int rate)
        !           726: {
        !           727:     unsigned int timeConstant;
        !           728:     
        !           729:     /* Sanity check. */
        !           730:     if (rate < SB_MIN_SAMPLE_RATE)
        !           731:         rate = SB_MIN_SAMPLE_RATE;
        !           732:     else if (rate > SB_MAX_SAMPLE_RATE)
        !           733:         rate = SB_MAX_SAMPLE_RATE;
        !           734:         
        !           735:     dspWriteWait();
        !           736:     if (lowSpeedDMA)    {
        !           737:         timeConstant = 256 - (1000*1000)/rate;
        !           738:         writeToDSP(DC_SET_TIME_CONSTANT);
        !           739:        dspWriteWait();
        !           740:         writeToDSP(timeConstant);
        !           741: #ifdef DEBUG
        !           742:     IOLog("SoundBlaster8: Sample rate = %u, timeConstant = %x\n", rate, timeConstant);
        !           743: #endif DEBUG
        !           744:     } else {
        !           745:         timeConstant = 65536 - (256*1000*1000)/rate;
        !           746:         writeToDSP(DC_SET_TIME_CONSTANT);
        !           747:        dspWriteWait();
        !           748:         writeToDSP(timeConstant >> 8);
        !           749: #ifdef DEBUG
        !           750:     IOLog("SoundBlaster8: Sample rate = %u, timeConstant = %x\n", rate, timeConstant >> 8);
        !           751: #endif DEBUG
        !           752:     }
        !           753: }
        !           754: 
        !           755: /*
        !           756:  * We test here if the user supplied dma/irq selections are correct. Actually
        !           757:  * it is more complicated than this because not all kinds of cards can use
        !           758:  * all dma/irq combinations. We simply allow the superset and avoid
        !           759:  * complicated version dependent verification. (Available interrupts are 3,
        !           760:  * 5, 7 for SBPro and 5, 7, 10 for other kinds, clone cards may have slight
        !           761:  * differences.) 
        !           762:  */
        !           763: 
        !           764: static  __inline__
        !           765: BOOL
        !           766: checkSelectedDMAAndIRQ(unsigned int channel, unsigned int irq)
        !           767: {
        !           768:     BOOL status = YES;
        !           769: 
        !           770:     if ((channel != 0) && (channel != 1) && (channel != 3)) {
        !           771:         IOLog("SoundBlaster8: Audio DMA channel is %d.\n", channel);
        !           772:         IOLog("SoundBlaster8: Audio DMA channel must be one of 0, 1, 3.\n");
        !           773:         status = NO;
        !           774:     }
        !           775:     if ((irq != 3) && (irq != 5) &&
        !           776:         (irq != 7) && (irq != 10)) {
        !           777:         IOLog("SoundBlaster8: Audio irq is %d.\n", irq);
        !           778:         IOLog("SoundBlaster8: Audio IRQ must be one of 3, 5, 7, 10.\n");
        !           779:         status = NO;
        !           780:     }
        !           781:     
        !           782:     return status;
        !           783: }
        !           784: 

unix.superglobalmegacorp.com

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