This is ProAudioSpectrumInline.h in view mode; [Download] [Up]
/* * Copyright (c) 1993 NeXT Computer, Inc. All rights reserved. */ #import "ProAudioSpectrumRegisters.h" #import <driverkit/i386/ioPorts.h> #import <driverkit/generalFuncs.h> static inline void setBaseAddress(unsigned int baseAddress) { /* * To relocate the I/O addresses, two 8-bit values are written to the * Master Address Pointer (0x9a01): * (1) board ID value (valid settings are 0xbc-0xbf) * (2) base address shifted right by two positions */ outb(MASTER_ADDRESS_POINTER, FIRST_BOARD_ID); outb(MASTER_ADDRESS_POINTER, (baseAddress) >> 2); } static inline filterControl_t getFilterControl() { union { filterControl_t reg; unsigned char data; } filterControl; filterControl.data = inb(FILTER_CONTROL); return (filterControl.reg); } static inline void setFilterControl(filterControl_t reg) { union { filterControl_t reg; unsigned char data; } filterControl; filterControl.reg = reg; outb(FILTER_CONTROL, filterControl.data); } static inline void enableAudioOutput(boolean_t enable) { filterControl_t filterControl = {0}; filterControl = getFilterControl(); filterControl.enableAudioOutput = enable; setFilterControl(filterControl); } static inline interruptControl_t getInterruptControl() { union { interruptControl_t reg; unsigned char data; } interruptControl; interruptControl.data = inb(INTERRUPT_CONTROL); return (interruptControl.reg); } static inline void setInterruptControl(interruptControl_t reg) { union { interruptControl_t reg; unsigned char data; } interruptControl; interruptControl.reg = reg; outb(INTERRUPT_CONTROL, interruptControl.data); } static inline interruptStatus_t getInterruptStatus() { union { interruptStatus_t reg; unsigned char data; } interruptStatus; interruptStatus.data = inb(INTERRUPT_STATUS); return (interruptStatus.reg); } static inline void setInterruptStatus(interruptStatus_t reg) { union { interruptStatus_t reg; unsigned char data; } interruptStatus; interruptStatus.reg = reg; outb(INTERRUPT_STATUS, interruptStatus.data); } static inline crossChannelControl_t getCrossChannelControl() { union { crossChannelControl_t reg; unsigned char data; } crossChannelControl; crossChannelControl.data = inb(CROSS_CHANNEL_CONTROL); return (crossChannelControl.reg); } static inline void setCrossChannelControl(crossChannelControl_t reg) { union { crossChannelControl_t reg; unsigned char data; } crossChannelControl; crossChannelControl.reg = reg; outb(CROSS_CHANNEL_CONTROL, crossChannelControl.data); } static inline sampleCounterControl_t getSampleCounterControl() { union { sampleCounterControl_t reg; unsigned char data; } sampleCounterControl; sampleCounterControl.data = inb(SAMPLE_COUNTER_CONTROL); return (sampleCounterControl.reg); } static inline void setSampleCounterControl(sampleCounterControl_t reg) { union { sampleCounterControl_t reg; unsigned char data; } sampleCounterControl; sampleCounterControl.reg = reg; outb(SAMPLE_COUNTER_CONTROL, sampleCounterControl.data); } static inline systemConfiguration1_t getSystemConfiguration1() { union { systemConfiguration1_t reg; unsigned char data; } systemConfiguration1; systemConfiguration1.data = inb(SYSTEM_CONFIGURATION_1); return (systemConfiguration1.reg); } static inline void setSystemConfiguration1(systemConfiguration1_t reg) { union { systemConfiguration1_t reg; unsigned char data; } systemConfiguration1; systemConfiguration1.reg = reg; outb(SYSTEM_CONFIGURATION_1, systemConfiguration1.data); } static inline systemConfiguration2_t getSystemConfiguration2() { union { systemConfiguration2_t reg; unsigned char data; } systemConfiguration2; systemConfiguration2.data = inb(SYSTEM_CONFIGURATION_2); return (systemConfiguration2.reg); } static inline void setSystemConfiguration2(systemConfiguration2_t reg) { union { systemConfiguration2_t reg; unsigned char data; } systemConfiguration2; systemConfiguration2.reg = reg; outb(SYSTEM_CONFIGURATION_2, systemConfiguration2.data); } static inline DMAChannelConfiguration_t getDMAChannelConfiguration() { union { DMAChannelConfiguration_t reg; unsigned char data; } DMAChannelConfiguration; DMAChannelConfiguration.data = inb(DMA_CHANNEL_CONFIGURATION); return (DMAChannelConfiguration.reg); } static inline void setDMAChannelConfiguration(DMAChannelConfiguration_t reg) { union { DMAChannelConfiguration_t reg; unsigned char data; } DMAChannelConfiguration; DMAChannelConfiguration.reg = reg; outb(DMA_CHANNEL_CONFIGURATION, DMAChannelConfiguration.data); } static inline boolean_t setDMAChannel(int channel) { static DMAChannelConfiguration_t DMAChannelConfiguration = {0}; static const unsigned char DMAMap[] = { DMA_CHANNEL_0, DMA_CHANNEL_1, DMA_CHANNEL_2, DMA_CHANNEL_3, DMA_CHANNEL_NONE, DMA_CHANNEL_5, DMA_CHANNEL_6, DMA_CHANNEL_7, }; if (DMAMap[channel] == DMA_CHANNEL_NONE) return FALSE; DMAChannelConfiguration.channel = DMAMap[channel]; setDMAChannelConfiguration(DMAChannelConfiguration); return TRUE; } static inline IRQConfiguration_t getIRQConfiguration() { union { IRQConfiguration_t reg; unsigned char data; } IRQConfiguration; IRQConfiguration.data = inb(IRQ_CONFIGURATION); return (IRQConfiguration.reg); } static inline void setIRQConfiguration(IRQConfiguration_t reg) { union { IRQConfiguration_t reg; unsigned char data; } IRQConfiguration; IRQConfiguration.reg = reg; outb(IRQ_CONFIGURATION, IRQConfiguration.data); } static inline boolean_t setInterrupt(int interrupt) { static IRQConfiguration_t IRQConfiguration = {0}; static const unsigned char IRQMap[] = { INTERRUPT_NONE, INTERRUPT_NONE, INTERRUPT_2, INTERRUPT_3, INTERRUPT_4, INTERRUPT_5, INTERRUPT_6, INTERRUPT_7, INTERRUPT_NONE, INTERRUPT_NONE, INTERRUPT_10, INTERRUPT_11, INTERRUPT_12, INTERRUPT_NONE, INTERRUPT_14, INTERRUPT_15 }; if (IRQMap[interrupt] == INTERRUPT_NONE) return FALSE; IRQConfiguration.interrupt = IRQMap[interrupt]; setIRQConfiguration(IRQConfiguration); return TRUE; } static inline void setMasterOutputAttenuation(u_int channel, masterAttenuation_t attenuation) { union { channelSelection_t reg; unsigned char data; } channelSelection; // avoid a warning channelSelection.data = 0; // select the master A mixer channelSelection.reg.selectAddress = MIXER_A_MASTER; channelSelection.reg.selectChannel = channel; channelSelection.reg.isTransfer = TRUE; outb(MIXER_CONTROL, channelSelection.data); // set the attenuation outb(MIXER_CONTROL, (char)attenuation); } static inline void setOutputAttenuation(u_int address, u_int channel, u_int attenuation) { union { channelSelection_t reg; unsigned char data; } channelSelection; union { channelAttenuation_t reg; unsigned char data; } channelAttenuation; // avoid a warning channelSelection.data = 0; channelAttenuation.data = 0; channelSelection.reg.selectAddress = address; channelSelection.reg.selectChannel = channel; channelSelection.reg.isTransfer = TRUE; outb(MIXER_CONTROL, channelSelection.data); channelAttenuation.reg.attenuation = attenuation; channelAttenuation.reg.routeChannel = MIXER_A_ROUTE; channelAttenuation.reg.swapChannels = NORMAL_STEREO; outb(MIXER_CONTROL, channelAttenuation.data); } static inline void setMasterInputAttenuation(u_int channel, masterAttenuation_t attenuation) { union { channelSelection_t reg; unsigned char data; } channelSelection; // avoid a warning channelSelection.data = 0; // select the master B mixer channelSelection.reg.selectAddress = MIXER_B_MASTER; channelSelection.reg.selectChannel = channel; channelSelection.reg.isTransfer = TRUE; outb(MIXER_CONTROL, channelSelection.data); // set the attenuation outb(MIXER_CONTROL, (char)attenuation); } static inline void setInputAttenuation(u_int address, u_int channel, u_int attenuation) { union { channelSelection_t reg; unsigned char data; } channelSelection; union { channelAttenuation_t reg; unsigned char data; } channelAttenuation; // avoid a warning channelSelection.data = 0; channelAttenuation.data = 0; channelSelection.reg.selectAddress = address; channelSelection.reg.selectChannel = channel; channelSelection.reg.isTransfer = TRUE; outb(MIXER_CONTROL, channelSelection.data); channelAttenuation.reg.attenuation = attenuation; channelAttenuation.reg.routeChannel = MIXER_B_ROUTE; channelAttenuation.reg.swapChannels = NORMAL_STEREO; outb(MIXER_CONTROL, channelAttenuation.data); } /* * In the 3.1 release, the driver set the sample rate using the technique * described in the Developer Reference. Unfortunately, this was imprecise * due to rounding errors. The values were calculated as follows: * * 1193180 / (sample rate * channel count) * 1193180 / (44100 * 1) = 27 // 44.1 kHz mono * 1193180 / (44100 * 2) = 13 // 44.1 kHz stereo * * MediaVision has provided us with the calculateRate function which calculates * the sample rate with more precision. This technique (which also sets the * prescale register) is undocumented in their reference manual. * */ static inline void calculateRate(u_int sampleRate, u_int *timer, u_int *prescale) { long targetRatio; long bestRatio; long testRatio; long bestDifference; long lastDifference; long testDifference; long p; long t; targetRatio = (441000L << 10) / sampleRate; bestRatio = 300L << 10; bestDifference = 7000L << 10; *prescale = 0; *timer = 0; for (p = 2; p < 256; p++) { lastDifference = 300L << 10; for (t = p+1; t < 256; t++) { testRatio = (t << 10) / p; if (testRatio == targetRatio) { bestRatio = testRatio; *prescale = p; *timer = t; return; } testDifference = testRatio - targetRatio; if (testDifference < 0) testDifference = -testDifference; if (testDifference > lastDifference) break; if (testDifference < bestDifference) { bestRatio = testRatio; bestDifference = testDifference; *prescale = p; *timer = t; } lastDifference = testDifference; } } } static inline void setSampleRateTimer(u_int rate) { u_int prescale; u_int timer; union { sampleRateTimer_t rate; unsigned char data[2]; } sampleRateTimer; filterControl_t filterControl = {0}; sampleCounterControl_t sampleCounterControl = {0}; /* * Before setting the sample rate interval, be sure to select the * Sample Rate Timer using Local Timer Control Register (0x138b). Also * remember to set the Sample Rate Timer Gate of the Audio Filter Control * Register (0xb8a) to 0 before programming the timer. */ filterControl = getFilterControl(); filterControl.enableSampleRateTimer = FALSE; setFilterControl(filterControl); sampleCounterControl.countFormat = BINARY_COUNT_FORMAT; sampleCounterControl.selectMode = SAMPLE_RATE_MODE; sampleCounterControl.latchCounter = 3; sampleCounterControl.selectCounter = SAMPLE_RATE_COUNT; setSampleCounterControl(sampleCounterControl); switch (rate) { case 44100: timer = 20; prescale = 2; break; case 22050: timer = 40; prescale = 2; break; case 8012: timer = 110; prescale = 2; break; default: calculateRate(rate, &timer, &prescale); break; } sampleRateTimer.rate = timer; outb(SAMPLE_RATE_TIMER, sampleRateTimer.data[0]); outb(SAMPLE_RATE_TIMER, sampleRateTimer.data[1]); outb(PRESCALE_DIVIDER, prescale & 0x0F); } static inline void setSampleBufferCounter(sampleBufferCounter_t count) { union { sampleBufferCounter_t count; unsigned char data[2]; } sampleBufferCounter; filterControl_t filterControl = {0}; sampleCounterControl_t sampleCounterControl = {0}; filterControl = getFilterControl(); filterControl.enableSampleBufferCounter = FALSE; setFilterControl(filterControl); sampleCounterControl.countFormat = BINARY_COUNT_FORMAT; sampleCounterControl.latchCounter = 3; sampleCounterControl.selectMode = SAMPLE_BUFFER_MODE; sampleCounterControl.selectCounter = SAMPLE_BUFFER_COUNT; setSampleCounterControl(sampleCounterControl); sampleBufferCounter.count = count; outb(SAMPLE_BUFFER_COUNTER, sampleBufferCounter.data[0]); outb(SAMPLE_BUFFER_COUNTER, sampleBufferCounter.data[1]); } static inline void setMasterModeControl(masterModeControl_t mode) { union { masterModeControl_t reg; unsigned char data; } masterModeControl; union { channelSelection_t reg; unsigned char data; } channelSelection; // avoid a warning channelSelection.data = 0; channelSelection.reg.selectAddress = MASTER_MODE_CONTROL; channelSelection.reg.selectChannel = BOTH_CHANNELS; channelSelection.reg.isTransfer = TRUE; outb(MIXER_CONTROL, channelSelection.data); masterModeControl.reg = mode; outb(MIXER_CONTROL, masterModeControl.data); } static inline void setLoudnessFilter(boolean_t flag) { masterModeControl_t masterModeControl = {0}; masterModeControl.loudnessFilter = flag; setMasterModeControl(masterModeControl); } static inline void setBassControl(unsigned char boost) { union { channelSelection_t reg; unsigned char data; } channelSelection; // avoid a warning channelSelection.data = 0; channelSelection.reg.selectAddress = BASS_CONTROL; channelSelection.reg.selectChannel = BOTH_CHANNELS; channelSelection.reg.isTransfer = TRUE; outb(MIXER_CONTROL, channelSelection.data); outb(MIXER_CONTROL, boost); } static inline void setTrebleControl(unsigned char boost) { union { channelSelection_t reg; unsigned char data; } channelSelection; // avoid a warning channelSelection.data = 0; channelSelection.reg.selectAddress = TREBLE_CONTROL; channelSelection.reg.selectChannel = BOTH_CHANNELS; channelSelection.reg.isTransfer = TRUE; outb(MIXER_CONTROL, channelSelection.data); outb(MIXER_CONTROL, boost); } static inline void resetMixer() { setMasterOutputAttenuation(BOTH_CHANNELS, DEFAULT_MASTER_OUTPUT_ATTENUATION); setOutputAttenuation(PCM, BOTH_CHANNELS, DEFAULT_OUTPUT_ATTENUATION); /* * mute all other output channels */ /* Don't mute this so that CD-Audio can get through, I have no idea why. * Modified 12/8/94 Jason LaPierre */ /** muting loopback makes so inputs are not looped back through the main output. I changed the attenuation level to the maximum. Modified by Scott Bender 01/29/94 **/ setOutputAttenuation(INPUT_MIXER_LOOPBACK, BOTH_CHANNELS, DEFAULT_MICROPHONE_ATTENUATION); setMasterInputAttenuation(BOTH_CHANNELS, DEFAULT_MASTER_INPUT_ATTENUATION); setInputAttenuation(MICROPHONE, BOTH_CHANNELS, DEFAULT_MICROPHONE_ATTENUATION); /** Set external line in attenuation to max value Changed by Scott Bender 1/29/94 **/ setInputAttenuation(EXTERNAL_LINE_IN, BOTH_CHANNELS, DEFAULT_MICROPHONE_ATTENUATION); /* * mute all other input channels */ setInputAttenuation(FM_SYNTHESIS, BOTH_CHANNELS, MUTE); /* Don't mute internal jack so that CD-Audio can get through * Modified 12/8/94 Jason LaPierre */ /** I went ahead and set this to the max Modified bt Scott Bender 1/29/94 (this has not been tested) **/ setInputAttenuation(INTERNAL_LINE_IN, BOTH_CHANNELS, DEFAULT_MICROPHONE_ATTENUATION); setInputAttenuation(SPEAKER, BOTH_CHANNELS, MUTE); setInputAttenuation(SOUNDBLASTER, BOTH_CHANNELS, MUTE); /* * set treble and bass boost to 0db */ setBassControl(DEFAULT_BASS_BOOST); setTrebleControl(DEFAULT_TREBLE_BOOST); } /* * resetHardware uses "magic" values recommended by MediaVision. These * settings are not always documented in the reference guide. In addition, * some of the values are specific to a particular version of the hardware. */ static inline boolean_t resetHardware() { systemConfiguration1_t systemConfiguration1; union { interruptControl_t reg; unsigned char data; } interruptControl; unsigned char version; /* * The presence of the hardware is verified. The version bits in the * interrupt control register are read only. */ interruptControl.data = inb(INTERRUPT_CONTROL); if (interruptControl.data == 0xff) return FALSE; version = interruptControl.reg.version; interruptControl.reg.version = 0; outb(INTERRUPT_CONTROL, interruptControl.data); interruptControl.data = inb(INTERRUPT_CONTROL); if (interruptControl.reg.version != version) return FALSE; /* * Turn off MPU and SoundBlaster emulation * outb(COMPATIBILITY_ENABLE, 0); /* * Turn off MPU and SoundBlaster interrupts */ outb(EMULATION_CONFIGURATION, 0); /* * Sets wait state to 140ns period */ outb(WAIT_STATE, WAIT_STATE_RESET); /* * D0 - resets FM * D1 - resets Codec * D2 - resets SoundBlaster * D4 - resets MVA508 Mixer */ outb(AUDIO_MIXER, 0); outb(AUDIO_MIXER, AUDIO_MIXER_RESET); /* * This is required when using the prescale register for more precise * sample rate timing. */ systemConfiguration1 = getSystemConfiguration1(); systemConfiguration1.selectCompatibleClock = TRUE; setSystemConfiguration1(systemConfiguration1); outb(SYSTEM_CONFIGURATION_2, SYSTEM_CONFIGURATION_2_RESET); /* * D3 (invert bclk output) * D4 (use codec sync output) */ outb(SYSTEM_CONFIGURATION_3, SYSTEM_CONFIGURATION_3_RESET); outb(SYSTEM_CONFIGURATION_4, SYSTEM_CONFIGURATION_4_RESET); /* * When a 16 bit Codec is attached, the Prescale counter is used to * set the ratio between the incoming Codec bit clock and the outgoing * master clock. */ outb(PRESCALE_DIVIDER, PRESCALE_DIVIDER_RESET); resetMixer(); return TRUE; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.