Annotation of Examples/DriverKit/ProAudioSpectrum16/ProAudioSpectrum16_reloc.tproj/ProAudioSpectrum16.m, revision 1.1

1.1     ! root        1: /*     Copyright (c) 1993 NeXT Computer, Inc.  All rights reserved. 
        !             2:  *
        !             3:  */
        !             4: #import "ProAudioSpectrum16.h"
        !             5: #import "ProAudioSpectrum16Registers.h"
        !             6: #import "ProAudioSpectrum16Inline.h"
        !             7: 
        !             8: #import <driverkit/generalFuncs.h>
        !             9: 
        !            10: static char pasDeviceName[] = "ProAudioSpectrum16";
        !            11: static char pasDeviceKind[] = "Audio";
        !            12: 
        !            13: @implementation ProAudioSpectrum16
        !            14: 
        !            15: /*
        !            16:  *  Probe and initialize new instance
        !            17:  */
        !            18: + (BOOL) probe:description
        !            19: {
        !            20:     ProAudioSpectrum16 *dev;
        !            21:     
        !            22:     dev = [self alloc];
        !            23:     if (dev == nil)
        !            24:         return NO;
        !            25:     
        !            26:     /*
        !            27:      * Sets the base IO address (needs to be performed before any other
        !            28:      * hardware access)
        !            29:      */
        !            30:     setBaseAddress(DEFAULT_BASE_ADDRESS);
        !            31: 
        !            32:     return [dev initFromDeviceDescription:description] != nil;
        !            33: }
        !            34: 
        !            35: - (BOOL) reset
        !            36: {
        !            37:     IOReturn   ioReturn;
        !            38:     unsigned int dmaChannel    = [[self deviceDescription] channel];
        !            39:     unsigned int interrupt     = [[self deviceDescription] interrupt];
        !            40:     IOEISADMATransferWidth     transferWidth = IO_16BitByteCount;
        !            41:     
        !            42:     [self setName: pasDeviceName];
        !            43:     [self setDeviceKind: pasDeviceKind];
        !            44:     
        !            45:     if (! (resetHardware())) {
        !            46:         IOLog("%s: hardware failed verification\n", [self name]);
        !            47:         return NO;
        !            48:     }
        !            49:     
        !            50:     /*
        !            51:      * The irq and dma channel are software selectable on the 
        !            52:      * ProAudioSpectrum16.
        !            53:      */
        !            54:     if (! (setDMAChannel(dmaChannel))) {
        !            55:         IOLog("%s: %d is an invalid dma setting\n",
        !            56:            [self name], dmaChannel);
        !            57:        return NO;
        !            58:     }
        !            59: 
        !            60:     if (! (setInterrupt(interrupt))) {
        !            61:         IOLog("%s: %d is an invalid irq setting\n",
        !            62:            [self name], interrupt);
        !            63:        return NO;
        !            64:     }
        !            65: 
        !            66:     /*
        !            67:      * The DMA controller is initialized.
        !            68:      */
        !            69:     [self disableChannel: 0];
        !            70: 
        !            71:     /*
        !            72:      * On both ISA and EISA machines, the ProAudioSpectrum16 hardware
        !            73:      * requires that DMA channels 0-4 are set to an 8-bit transfer width. 
        !            74:      */
        !            75:     if ([self isEISAPresent]) {
        !            76:         if (dmaChannel < 5)
        !            77:            transferWidth = IO_8Bit;
        !            78:            
        !            79:         ioReturn = [self setDMATransferWidth: transferWidth forChannel: 0];
        !            80:        if (ioReturn != IO_R_SUCCESS) {
        !            81:            IOLog("%s: dma transfer width error %d\n", [self name], ioReturn);
        !            82:            return NO;
        !            83:        }
        !            84:     }
        !            85: 
        !            86:     ioReturn = [self setTransferMode: IO_Single forChannel: 0];
        !            87: 
        !            88:     if (ioReturn != IO_R_SUCCESS)  {
        !            89:        IOLog("%s: dma transfer mode error %d\n", [self name], ioReturn);
        !            90:        return NO;
        !            91:     }
        !            92: 
        !            93:     ioReturn = [self setAutoinitialize: YES forChannel: 0];
        !            94:     if (ioReturn != IO_R_SUCCESS) {
        !            95:        IOLog("%s: dma auto initialize error %d", [self name], ioReturn);
        !            96:        return NO;
        !            97:     }
        !            98: 
        !            99:     return YES;
        !           100: }
        !           101: 
        !           102: /*
        !           103:  * converts gain (0 - 32768) into attenuation (0 - 31)
        !           104:  */
        !           105: 
        !           106: - (void) updateInputGainLeft
        !           107: {
        !           108:     unsigned int gain = [self inputGainLeft] / 1057;
        !           109:     
        !           110:     setInputAttenuation(MICROPHONE, LEFT_CHANNEL, (unsigned char) gain);
        !           111:     setInputAttenuation(EXTERNAL_LINE_IN, LEFT_CHANNEL, (unsigned char) gain);
        !           112: }
        !           113: 
        !           114: - (void)updateInputGainRight
        !           115: {
        !           116:     unsigned int gain = [self inputGainRight] / 1057;
        !           117:     
        !           118:     setInputAttenuation(MICROPHONE, RIGHT_CHANNEL, (unsigned char) gain);
        !           119:     setInputAttenuation(EXTERNAL_LINE_IN, RIGHT_CHANNEL, (unsigned char) gain);
        !           120: }
        !           121: 
        !           122: - (void)updateOutputMute
        !           123: {
        !           124:     enableAudioOutput(! [self isOutputMuted]);
        !           125: }
        !           126: 
        !           127: - (void)updateLoudnessEnhanced
        !           128: {
        !           129:     setLoudnessFilter([self isLoudnessEnhanced]);
        !           130: }
        !           131: 
        !           132: /*
        !           133:  * (0) - (-84) needs to be converted to (0) - (31)
        !           134:  */
        !           135: - (void) updateOutputAttenuationLeft
        !           136: {
        !           137:    unsigned int attenuation = [self outputAttenuationLeft] + 84;
        !           138:    attenuation = ((attenuation * 10)/27);
        !           139:     
        !           140:     setOutputAttenuation(PCM, LEFT_CHANNEL, (unsigned char) attenuation);
        !           141: }
        !           142: 
        !           143: /*
        !           144:  * (0) - (-84) needs to be converted to (0) - (32)
        !           145:  */
        !           146: - (void) updateOutputAttenuationRight
        !           147: {
        !           148:    unsigned int attenuation = [self outputAttenuationRight] + 84;
        !           149:    attenuation = ((attenuation * 10)/27);
        !           150: 
        !           151:     setOutputAttenuation(PCM, RIGHT_CHANNEL, (unsigned char) attenuation);
        !           152: }
        !           153: 
        !           154: - (IOReturn) enableAllInterrupts
        !           155: {
        !           156:     interruptStatus_t  interruptStatus = {0};
        !           157:     interruptControl_t interruptControl = {0};
        !           158:     
        !           159:     /*
        !           160:      * clear all interrupts
        !           161:      */
        !           162:     setInterruptStatus(interruptStatus);
        !           163: 
        !           164:     interruptControl.enableSampleBufferInterrupt = YES;
        !           165:     setInterruptControl(interruptControl);
        !           166:     
        !           167:     return [super enableAllInterrupts];
        !           168: }
        !           169: 
        !           170: - (void) disableAllInterrupts
        !           171: {
        !           172:     interruptControl_t interruptControl = {0};
        !           173: 
        !           174:     setInterruptControl(interruptControl);
        !           175:     
        !           176:     [super disableAllInterrupts];
        !           177: }
        !           178: 
        !           179: 
        !           180: - (BOOL) startDMAForChannel: (unsigned int) localChannel
        !           181:                        read: (BOOL) isRead
        !           182:                      buffer: (IOEISADMABuffer) buffer
        !           183:     bufferSizeForInterrupts: (unsigned int) bufferSize
        !           184: {
        !           185: 
        !           186:     IOReturn ioReturn;
        !           187:     unsigned int rate = [self sampleRate];
        !           188:     
        !           189:     IOEISADMATransferWidth     transferWidth;
        !           190:     
        !           191:     filterControl_t            filterControl           = {0};
        !           192:     crossChannelControl_t      crossChannelControl     = {0};
        !           193:     systemConfiguration2_t     systemConfiguration2    = {0};
        !           194: 
        !           195: 
        !           196:     /*
        !           197:      * Before enabling the DMA channel, "secure" the channel via the DRQ
        !           198:      * bit in the Cross Channel register (0xf8a). This causes the
        !           199:      * ProAudioSpectrum16 to drive the DMA channel from a floating state to
        !           200:      * a known good state. If you enable the DMA channel with an unsecured
        !           201:      * DRQ line, the DMA will perform a rapid-fire data tranfer due to the
        !           202:      * floating DRQ line.
        !           203:      */
        !           204:     crossChannelControl = getCrossChannelControl();
        !           205:     crossChannelControl.enableDMA = YES;
        !           206:     setCrossChannelControl(crossChannelControl);
        !           207:     
        !           208:     ioReturn = [self startDMAForBuffer: buffer channel: localChannel];
        !           209: 
        !           210:     if (ioReturn != IO_R_SUCCESS) {
        !           211:         IOLog("%s: could not start DMA channel error %d\n",
        !           212:                [self name], ioReturn);
        !           213:        return NO;
        !           214:     }
        !           215:         
        !           216:     ioReturn = [self enableChannel: localChannel];
        !           217:     
        !           218:     if (ioReturn != IO_R_SUCCESS) {
        !           219:         IOLog("%s: could not enable DMA channel error %d\n",
        !           220:                [self name], ioReturn);
        !           221:        return NO;
        !           222:     }
        !           223: 
        !           224:     (void) [self enableAllInterrupts];
        !           225: 
        !           226:     setSampleRateTimer(rate);
        !           227:    
        !           228:     /*
        !           229:      * Use the Sample Buffer Count register to set the number of bytes in the
        !           230:      * DMA buffer division. This register holds a 16-bit value. When using a
        !           231:      * 16-bit DMA channel, the Sample Buffer Count must be divided by two.
        !           232:      */
        !           233:     (void) [self getDMATransferWidth: &transferWidth forChannel: localChannel];
        !           234:     if (transferWidth == IO_16BitByteCount ||
        !           235:        transferWidth == IO_16BitWordCount)
        !           236:        setSampleBufferCounter(bufferSize / 2);
        !           237:     else
        !           238:        setSampleBufferCounter(bufferSize);
        !           239:         
        !           240: 
        !           241:     if ([self dataEncoding] == NX_SoundStreamDataEncoding_Linear16)
        !           242:        systemConfiguration2.dataEncoding = LINEAR_16;
        !           243:     else
        !           244:        systemConfiguration2.dataEncoding = LINEAR_8;
        !           245:        
        !           246:     setSystemConfiguration2(systemConfiguration2);
        !           247:     
        !           248:     crossChannelControl.rightToRight = YES;
        !           249:     crossChannelControl.leftToLeft = YES;
        !           250: 
        !           251:     crossChannelControl.direction = !isRead;
        !           252:        
        !           253:     /*
        !           254:      * The mixer has feedback problems. MediaVision advised us to mute
        !           255:      * the PCM output channel when recording.
        !           256:      */
        !           257:     if (isRead)
        !           258:         setOutputAttenuation(PCM, BOTH_CHANNELS, 0);
        !           259:        
        !           260:     if ([self channelCount] == 1) 
        !           261:         crossChannelControl.isMono = YES;
        !           262:     else
        !           263:         crossChannelControl.isMono = NO;
        !           264:        
        !           265:     setCrossChannelControl(crossChannelControl);
        !           266:     crossChannelControl.enablePCM = YES;
        !           267:     crossChannelControl.enableDMA = YES;
        !           268:     setCrossChannelControl(crossChannelControl);
        !           269:     
        !           270:     filterControl = getFilterControl();
        !           271:     filterControl.enableSampleRateTimer = YES;
        !           272:     filterControl.enableSampleBufferCounter = YES;
        !           273:     setFilterControl(filterControl);
        !           274: 
        !           275:     return YES;
        !           276: }
        !           277: 
        !           278: - (void) stopDMAForChannel: (unsigned int) localChannel read: (BOOL) isRead
        !           279: {
        !           280:     filterControl_t            filterControl           = {0};
        !           281:     crossChannelControl_t      crossChannelControl     = {0};
        !           282: 
        !           283:     [self disableChannel: localChannel];
        !           284:     
        !           285:     filterControl = getFilterControl();
        !           286:     filterControl.enableSampleRateTimer = NO;
        !           287:     filterControl.enableSampleBufferCounter = NO;
        !           288:     setFilterControl(filterControl);
        !           289:  
        !           290:     (void)[self disableAllInterrupts];   
        !           291:  
        !           292:     crossChannelControl = getCrossChannelControl();
        !           293:     crossChannelControl.enablePCM = NO;
        !           294:     setCrossChannelControl(crossChannelControl);
        !           295:     crossChannelControl.enableDMA = NO;
        !           296:     setCrossChannelControl(crossChannelControl);
        !           297:     
        !           298:     /*
        !           299:      * Due to mixer feedback problems, the PCM channels are muted during
        !           300:      * recording. Their current values are restored here.
        !           301:      */
        !           302:     if (isRead) {
        !           303:         [self updateOutputAttenuationLeft];
        !           304:        [self updateOutputAttenuationRight];
        !           305:     }
        !           306: }
        !           307: 
        !           308: static void clearInterrupts(void)
        !           309: {
        !           310:     interruptStatus_t  interruptStatus = {0};
        !           311: 
        !           312:     /*
        !           313:      * clear the hardware interrupt register
        !           314:      */
        !           315:     interruptStatus = getInterruptStatus();
        !           316:     if (! interruptStatus.sampleBufferInterruptPending)
        !           317:        return;
        !           318:     
        !           319:     /*
        !           320:      * The chip specification states that a write to this register
        !           321:      * will clear the clip status and sample interrupts.
        !           322:      */
        !           323:     interruptStatus.sampleBufferInterruptPending = NO;
        !           324:     setInterruptStatus(interruptStatus);
        !           325: }
        !           326: 
        !           327: - (IOAudioInterruptClearFunc) interruptClearFunc
        !           328: {
        !           329:     return clearInterrupts;
        !           330: }
        !           331: 
        !           332: - (void) interruptOccurredForInput: (BOOL*)serviceInput
        !           333:                          forOutput:(BOOL*)serviceOutput
        !           334: {
        !           335:     interruptStatus_t  interruptStatus = {0};
        !           336: 
        !           337:     /*
        !           338:      * clear the hardware interrupt register
        !           339:      */
        !           340:     interruptStatus = getInterruptStatus();
        !           341:     if (! interruptStatus.sampleBufferInterruptPending) {
        !           342:        IOLog("ProAudioSpectrum16: spurious dma interrupt\n");
        !           343:        return;
        !           344:     }
        !           345:     
        !           346:     /*
        !           347:      * The chip specification states that a write to this register
        !           348:      * will clear the clip status and sample interrupts.
        !           349:      */
        !           350:     interruptStatus.sampleBufferInterruptPending = NO;
        !           351:     setInterruptStatus(interruptStatus);
        !           352: 
        !           353:     if ([self isInputActive])
        !           354:         *serviceInput = YES;
        !           355:     else
        !           356:         *serviceOutput = YES;
        !           357: }
        !           358: 
        !           359: - (void) timeoutOccurred
        !           360: {
        !           361:     crossChannelControl_t      crossChannelControl     = {0};
        !           362: 
        !           363:     crossChannelControl = getCrossChannelControl();
        !           364:     crossChannelControl.enablePCM = NO;
        !           365:     setCrossChannelControl(crossChannelControl);
        !           366:     crossChannelControl.enablePCM = YES;
        !           367:     setCrossChannelControl(crossChannelControl);
        !           368: }
        !           369: 
        !           370: /*
        !           371:  * Parameter access.
        !           372:  */
        !           373: 
        !           374: - (BOOL)acceptsContinuousSamplingRates
        !           375: {
        !           376:     return YES;
        !           377: }
        !           378: 
        !           379: - (void)getSamplingRatesLow: (int *)lowRate
        !           380:                        high: (int *)highRate
        !           381: {
        !           382:     *lowRate = 2000;
        !           383:     *highRate = 44100;
        !           384: }
        !           385: 
        !           386: - (void)getSamplingRates: (int *)rates
        !           387:                    count: (unsigned int *)numRates
        !           388: {
        !           389:     /* Return a few common rates */
        !           390:     rates[0] = 2000;
        !           391:     rates[1] = 8000;
        !           392:     rates[2] = 11025;
        !           393:     rates[3] = 16000;
        !           394:     rates[4] = 22050;
        !           395:     rates[5] = 32000;
        !           396:     rates[6] = 44100;
        !           397:     *numRates = 7;
        !           398: }
        !           399: 
        !           400: - (void)getDataEncodings: (NXSoundParameterTag *)encodings
        !           401:                    count: (unsigned int *)numEncodings
        !           402: {
        !           403:     IOEISADMATransferWidth transferWidth;
        !           404: 
        !           405:     encodings[0] = NX_SoundStreamDataEncoding_Linear8;
        !           406:     encodings[1] = NX_SoundStreamDataEncoding_Linear16;
        !           407:     *numEncodings = 2;
        !           408: 
        !           409:     /*
        !           410:      * For EISA machines, the driver is unable to handle 16-bit linear data
        !           411:      * when the DMA transfer width is 8 bits.
        !           412:      */
        !           413:     if ([self isEISAPresent]) {
        !           414:         (void)[self getDMATransferWidth: &transferWidth forChannel: 0];
        !           415:        if (transferWidth == IO_8Bit) {
        !           416:            encodings[1] = 0;
        !           417:            *numEncodings = 1;
        !           418:        }
        !           419:     }
        !           420: }
        !           421: 
        !           422: - (unsigned int) channelCountLimit
        !           423: {
        !           424:     return 2;  /* stereo and mono */
        !           425: }
        !           426: 
        !           427: @end

unix.superglobalmegacorp.com

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