diff --git a/sys/arch/i386/isa/ad1848.c b/sys/arch/i386/isa/ad1848.c deleted file mode 100644 index 63be64a2ec79..000000000000 --- a/sys/arch/i386/isa/ad1848.c +++ /dev/null @@ -1,1380 +0,0 @@ -/* $NetBSD: ad1848.c,v 1.3 1995/04/17 12:06:55 cgd Exp $ */ - -/* - * Copyright (c) 1994 John Brezak - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: ad1848.c,v 1.3 1995/04/17 12:06:55 cgd Exp $ - */ - -/* - * Copyright by Hannu Savolainen 1994 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. 2. - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -/* - * Portions of this code are from the VOXware support for the ad1848 - * by Hannu Savolainen - * - * Portions also supplied from the SoundBlaster driver for NetBSD. - */ - -/* - * Todo: - * - Need datasheet for CS4231 (for use with GUS MAX) - * - Use fast audio_dma - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#ifdef DEBUG -extern void Dprintf __P((const char *, ...)); - -#define DPRINTF(x) if (ad1848debug) Dprintf x -int ad1848debug = 0; -#else -#define DPRINTF(x) -#endif - -/* - * Initial values for the indirect registers of CS4248/AD1848. - */ -static int ad1848_init_values[] = { - /* Left Input Control */ - GAIN_12|INPUT_MIC_GAIN_ENABLE, - /* Right Input Control */ - GAIN_12|INPUT_MIC_GAIN_ENABLE, - ATTEN_12, /* Left Aux #1 Input Control */ - ATTEN_12, /* Right Aux #1 Input Control */ - ATTEN_12, /* Left Aux #2 Input Control */ - ATTEN_12, /* Right Aux #2 Input Control */ - 0x19, /* Left DAC Control */ - 0x19, /* Right DAC Control */ - /* Clock and Data Format */ - CLOCK_XTAL1|LINEAR|PCM, - /* Interface Config */ - SINGLE_DMA, - INTERRUPT_ENABLE, /* Pin control */ - 0x00, /* Test and Init */ - 0xca, /* Misc control */ - ATTEN_0<<2, /* Digital Mix Control */ - 0, /* Upper base Count */ - 0 /* Lower base Count */ -}; - -int ad1848_probe(); -void ad1848_attach(); - -void ad1848_reset __P((struct ad1848_softc *)); -int ad1848_set_speed __P((struct ad1848_softc *, int)); - -#ifndef NEWCONFIG -#define at_dma(flags, ptr, cc, chan) isa_dmastart(flags, ptr, cc, chan) -#endif - -#define splaudio splclock - -static int -ad_read(sc, reg) - struct ad1848_softc *sc; - int reg; -{ - int x; - - outb(sc->sc_iobase+AD1848_IADDR, (u_char) (reg & 0xff) | sc->MCE_bit); - x = inb(sc->sc_iobase+AD1848_IDATA); - /* printf("(%02x<-%02x) ", reg|sc->MCE_bit, x); */ - - return x; -} - -static void -ad_write(sc, reg, data) - struct ad1848_softc *sc; - int reg; - int data; -{ - outb(sc->sc_iobase+AD1848_IADDR, (u_char) (reg & 0xff) | sc->MCE_bit); - outb(sc->sc_iobase+AD1848_IDATA, (u_char) (data & 0xff)); - /* printf("(%02x->%02x) ", reg|sc->MCE_bit, data); */ -} - -static void -ad_set_MCE(sc, state) - struct ad1848_softc *sc; - int state; -{ - if (state) - sc->MCE_bit = MODE_CHANGE_ENABLE; - else - sc->MCE_bit = 0; - - outb(sc->sc_iobase+AD1848_IADDR, sc->MCE_bit); -} - -static void -wait_for_calibration(sc) - struct ad1848_softc *sc; -{ - int timeout = 100000; - - /* - * Wait until the auto calibration process has finished. - * - * 1) Wait until the chip becomes ready (reads don't return 0x80). - * 2) Wait until the ACI bit of I11 gets on and then off. - */ - while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT) - timeout--; - - if (inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT) - DPRINTF(("ad1848: Auto calibration timed out(1).\n")); - - if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) { - timeout = 100000; - while (timeout > 0 && !(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) - timeout--; - - if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) - DPRINTF(("ad1848: Auto calibration timed out(2).\n")); - } - - timeout = 100000; - while (timeout > 0 && ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG) - timeout--; - if (ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG) - DPRINTF(("ad1848: Auto calibration timed out(3).\n")); -} - -#ifdef DEBUG -void -ad1848_dump_regs(sc) - struct ad1848_softc *sc; -{ - int i; - u_char r; - - printf("ad1848 status=%x", inb(sc->sc_iobase+AD1848_STATUS)); - printf(" regs: "); - for (i = 0; i < 16; i++) { - r = ad_read(sc, i); - printf("%x ", r); - } - printf("\n"); -} -#endif - -#ifdef NEWCONFIG -void -ad1848_forceintr(sc) - struct ad1848_softc *sc; -{ - static char dmabuf; - - /* - * Set up a DMA read of one byte. - * XXX Note that at this point we haven't called - * at_setup_dmachan(). This is okay because it just - * allocates a buffer in case it needs to make a copy, - * and it won't need to make a copy for a 1 byte buffer. - * (I think that calling at_setup_dmachan() should be optional; - * if you don't call it, it will be called the first time - * it is needed (and you pay the latency). Also, you might - * never need the buffer anyway.) - */ - at_dma(B_READ, &dmabuf, 1, sc->sc_drq); - - ad_write(sc, SP_LOWER_BASE_COUNT, 0); - ad_write(sc, SP_UPPER_BASE_COUNT, 0); - ad_write(sc, SP_INTERFACE_CONFIG, PLAYBACK_ENABLE); -} -#endif - -/* - * Probe for the ad1848 chip - */ -int -ad1848_probe(sc) - struct ad1848_softc *sc; -{ - register u_short iobase = sc->sc_iobase; - u_char tmp, tmp1 = 0xff, tmp2 = 0xff; - int i; - - if (!AD1848_BASE_VALID(iobase)) { - printf("ad1848: configured iobase %d invalid\n", iobase); - return 0; - } - - sc->sc_iobase = iobase; - - /* Is there an ad1848 chip ? */ - sc->MCE_bit = MODE_CHANGE_ENABLE; - sc->chip_name = "ad1848"; - sc->mode = 1; /* MODE 1 = original ad1849 */ - - /* - * Check that the I/O address is in use. - * - * The bit 0x80 of the base I/O port is known to be 0 after the - * chip has performed it's power on initialization. Just assume - * this has happened before the OS is starting. - * - * If the I/O address is unused, it typically returns 0xff. - */ - if ((inb(iobase+AD1848_IADDR) & 0x80) != 0x00) {/* Not a AD1848 */ - DPRINTF(("ad_detect_A\n")); - return 0; - } - - /* - * Test if it's possible to change contents of the indirect registers. - * Registers 0 and 1 are ADC volume registers. The bit 0x10 is read only - * so try to avoid using it. - */ - ad_write(sc, 0, 0xaa); - ad_write(sc, 1, 0x45); /* 0x55 with bit 0x10 clear */ - - if ((tmp1 = ad_read(sc, 0)) != 0xaa || - (tmp2 = ad_read(sc, 1)) != 0x45) { - DPRINTF(("ad_detect_B (%x/%x)\n", tmp1, tmp2)); - return 0; - } - - ad_write(sc, 0, 0x45); - ad_write(sc, 1, 0xaa); - - if ((tmp1 = ad_read(sc, 0)) != 0x45 || - (tmp2 = ad_read(sc, 1)) != 0xaa) { - DPRINTF(("ad_detect_C (%x/%x)\n", tmp1, tmp2)); - return 0; - } - - /* - * The indirect register I12 has some read only bits. Lets - * try to change them. - */ - tmp = ad_read(sc, SP_MISC_INFO); - ad_write(sc, SP_MISC_INFO, (~tmp) & 0x0f); - - if ((tmp & 0x0f) != ((tmp1 = ad_read(sc, SP_MISC_INFO)) & 0x0f)) { - DPRINTF(("ad_detect_D (%x)\n", tmp1)); - return 0; - } - - /* - * NOTE! Last 4 bits of the reg I12 tell the chip revision. - * 0x01=RevB and 0x0A=RevC. - */ - sc->rev = tmp1 & 0x0f; - switch (sc->rev) { - case 11: - sc->chip_name = "ad1846"; - sc->rev = 0; - break; - } - - - /* - * The original AD1848/CS4248 has just 15 indirect registers. This means - * that I0 and I16 should return the same value (etc.). - * Ensure that the Mode2 enable bit of I12 is 0. Otherwise this test fails - * with CS4231. - */ - ad_write(sc, SP_MISC_INFO, 0); /* Mode2 = disabled */ - - for (i = 0; i < 16; i++) - if ((tmp1 = ad_read(sc, i)) != (tmp2 = ad_read(sc, i + 16))) { - DPRINTF(("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2)); - return 0; - } - - /* - * Try to switch the chip to mode2 (CS4231) by setting the MODE2 bit (0x40) - * The bit 0x80 is always 1 in CS4248 and CS4231. - */ - ad_write(sc, SP_MISC_INFO, 0x40); /* Set mode2, clear 0x80 */ - - tmp1 = ad_read(sc, SP_MISC_INFO); - if (tmp1 & 0x80) - sc->chip_name = "cs4248"; - - if ((tmp1 & 0xc0) == (0x80 | 0x40)) { - /* - * CS4231 detected - is it? - * - * Verify that setting I0 doesn't change I16. - */ - ad_write(sc, 16, 0); /* Set I16 to known value */ - - ad_write(sc, 0, 0x45); - if ((tmp1 = ad_read(sc, 16)) != 0x45) { /* No change -> CS4231? */ - ad_write(sc, 0, 0xaa); - if ((tmp1 = ad_read(sc, 16)) == 0xaa) { /* Rotten bits? */ - DPRINTF(("ad_detect_H(%x)\n", tmp1)); - return 0; - } - - /* - * It's a CS4231 - */ - sc->chip_name = "cs4231"; - sc->mode = 2; - } - } - - /* Wait for 1848 to init */ - while(inb(sc->sc_iobase+AD1848_IADDR) & SP_IN_INIT); - - /* Wait for 1848 to autocal */ - outb(sc->sc_iobase+AD1848_IADDR, SP_TEST_AND_INIT); - while(inb(sc->sc_iobase+AD1848_IDATA) & AUTO_CAL_IN_PROG); - - return 1; -} - -/* - * Attach hardware to driver, attach hardware driver to audio - * pseudo-device driver . - */ -void -ad1848_attach(sc) - struct ad1848_softc *sc; -{ - register u_short iobase = sc->sc_iobase; - int i; - struct ad1848_volume vol_mid = {150, 150}; - struct ad1848_volume vol_0 = {0, 0}; - - sc->sc_locked = 0; - - /* Initialize the ad1848 */ - for (i = 0; i < 16; i++) - ad_write(sc, i, ad1848_init_values[i]); - - ad1848_reset(sc); - -#ifdef NEWCONFIG - /* - * We limit DMA transfers to a page, and use the generic DMA handling - * code in isa.c. This code can end up copying a buffer, but since - * the audio driver uses relative small buffers this isn't likely. - * - * This allocation scheme means that the maximum transfer is limited - * by the page size (rather than 64k). This is reasonable. For 4K - * pages, the transfer time at 48KHz is 4096 / 48000 = 85ms. This - * is plenty long enough to amortize any fixed time overhead. - */ - at_setup_dmachan(sc->sc_drq, NBPG); -#endif - - /* Set default encoding (ULAW) */ - sc->sc_irate = sc->sc_orate = 8000; - sc->precision = 8; - sc->channels = 1; - sc->encoding = AUDIO_ENCODING_ULAW; - (void) ad1848_set_in_sr(sc, sc->sc_irate); - (void) ad1848_set_out_sr(sc, sc->sc_orate); - - /* Set default gains */ - (void) ad1848_set_rec_gain(sc, &vol_mid); - (void) ad1848_set_out_gain(sc, &vol_mid); - (void) ad1848_set_mon_gain(sc, &vol_0); - (void) ad1848_set_aux1_gain(sc, &vol_mid); /* CD volume */ - (void) ad1848_set_aux2_gain(sc, &vol_0); - - /* Set default port */ - (void) ad1848_set_rec_port(sc, MIC_IN_PORT); - - printf(": %s%c", sc->chip_name, (sc->rev)?'A'+sc->rev:' '); -} - -/* - * Various routines to interface to higher level audio driver - */ -int -ad1848_set_rec_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - register u_char reg, gain; - - DPRINTF(("ad1848_set_in_gain: %d:%d\n", gp->left, gp->right)); - - sc->rec_gain = *gp; - - gain = (gp->left * GAIN_22_5)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); - reg &= INPUT_GAIN_MASK; - ad_write(sc, SP_LEFT_INPUT_CONTROL, (gain&0x0f)|reg); - - gain = (gp->right * GAIN_22_5)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL); - reg &= INPUT_GAIN_MASK; - ad_write(sc, SP_RIGHT_INPUT_CONTROL, (gain&0x0f)|reg); - - return(0); -} - -int -ad1848_get_rec_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - *gp = sc->rec_gain; - return(0); -} - -int -ad1848_set_out_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - u_char reg; - u_int atten; - - DPRINTF(("ad1848_set_out_gain: %d:%d\n", gp->left, gp->right)); - - sc->out_gain = *gp; - - atten = ((AUDIO_MAX_GAIN - gp->left) * OUTPUT_ATTEN_BITS)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_LEFT_OUTPUT_CONTROL); - reg &= ~(OUTPUT_ATTEN_MASK); - ad_write(sc, SP_LEFT_OUTPUT_CONTROL, (atten&0x3f)|reg); - - atten = ((AUDIO_MAX_GAIN - gp->right) * OUTPUT_ATTEN_BITS)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_RIGHT_OUTPUT_CONTROL); - reg &= ~(OUTPUT_ATTEN_MASK); - ad_write(sc, SP_RIGHT_OUTPUT_CONTROL, (atten&0x3f)|reg); - - return(0); -} - -int -ad1848_get_out_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - *gp = sc->out_gain; - return(0); -} - -int -ad1848_set_mon_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - u_char reg; - u_int atten; - - DPRINTF(("ad1848_set_mon_gain: %d\n", gp->left)); - - sc->mon_gain = *gp; - - atten = ((AUDIO_MAX_GAIN - gp->left) * OUTPUT_ATTEN_BITS)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_DIGITAL_MIX); - reg &= ~(MIX_ATTEN_MASK); - ad_write(sc, SP_DIGITAL_MIX, (atten&OUTPUT_ATTEN_BITS)|reg); - - return(0); -} - -int -ad1848_get_mon_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - *gp = sc->mon_gain; - return(0); -} - -void -ad1848_mute_monitor(addr, mute) - void *addr; - int mute; -{ - struct ad1848_softc *sc = addr; - u_char reg; - - if (mute) { - reg = ad_read(sc, SP_LEFT_AUX1_CONTROL); - ad_write(sc, SP_LEFT_AUX1_CONTROL, AUX_INPUT_MUTE|reg); - - reg = ad_read(sc, SP_RIGHT_AUX1_CONTROL); - ad_write(sc, SP_RIGHT_AUX1_CONTROL, AUX_INPUT_MUTE|reg); - - reg = ad_read(sc, SP_LEFT_AUX2_CONTROL); - ad_write(sc, SP_LEFT_AUX2_CONTROL, AUX_INPUT_MUTE|reg); - - reg = ad_read(sc, SP_RIGHT_AUX2_CONTROL); - ad_write(sc, SP_RIGHT_AUX2_CONTROL, AUX_INPUT_MUTE|reg); - } - else { - reg = ad_read(sc, SP_LEFT_AUX1_CONTROL); - ad_write(sc, SP_LEFT_AUX1_CONTROL, ~(AUX_INPUT_MUTE)®); - - reg = ad_read(sc, SP_RIGHT_AUX1_CONTROL); - ad_write(sc, SP_RIGHT_AUX1_CONTROL, ~(AUX_INPUT_MUTE)®); - - reg = ad_read(sc, SP_LEFT_AUX2_CONTROL); - ad_write(sc, SP_LEFT_AUX2_CONTROL, ~(AUX_INPUT_MUTE)®); - - reg = ad_read(sc, SP_RIGHT_AUX2_CONTROL); - ad_write(sc, SP_RIGHT_AUX2_CONTROL, ~(AUX_INPUT_MUTE)®); - } -} - -int -ad1848_set_aux1_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - u_char reg; - u_int atten; - - DPRINTF(("ad1848_set_aux1_gain: %d:%d\n", gp->left, gp->right)); - - sc->aux1_gain = *gp; - - atten = ((AUDIO_MAX_GAIN - gp->left) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_LEFT_AUX1_CONTROL); - reg &= ~(AUX_INPUT_ATTEN_BITS); - ad_write(sc, SP_LEFT_AUX1_CONTROL, (atten&0x1f)|reg); - - atten = ((AUDIO_MAX_GAIN - gp->right) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_RIGHT_AUX1_CONTROL); - reg &= ~(AUX_INPUT_ATTEN_BITS); - ad_write(sc, SP_RIGHT_AUX1_CONTROL, (atten&0x1f)|reg); - - return(0); -} - -int -ad1848_get_aux1_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - *gp = sc->aux1_gain; - return(0); -} - -int -ad1848_set_aux2_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - u_char reg; - u_int atten; - - DPRINTF(("ad1848_set_aux2_gain: %d:%d\n", gp->left, gp->right)); - - sc->aux2_gain = *gp; - - atten = ((AUDIO_MAX_GAIN - gp->left) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_LEFT_AUX2_CONTROL); - reg &= ~(AUX_INPUT_ATTEN_BITS); - ad_write(sc, SP_LEFT_AUX2_CONTROL, (atten&0x1f)|reg); - - atten = ((AUDIO_MAX_GAIN - gp->right) * AUX_INPUT_ATTEN_BITS)/AUDIO_MAX_GAIN; - reg = ad_read(sc, SP_RIGHT_AUX2_CONTROL); - reg &= ~(AUX_INPUT_ATTEN_BITS); - ad_write(sc, SP_RIGHT_AUX2_CONTROL, (atten&0x1f)|reg); - - return(0); -} - -int -ad1848_get_aux2_gain(sc, gp) - register struct ad1848_softc *sc; - struct ad1848_volume *gp; -{ - *gp = sc->aux2_gain; - return 0; -} - -int -ad1848_set_in_sr(addr, sr) - void *addr; - u_long sr; -{ - register struct ad1848_softc *sc = addr; - - DPRINTF(("ad1848_set_in_sr: %d\n", sr)); - - ad1848_set_speed(sc, sr); - sc->sc_irate = sr; - - return(0); -} - -u_long -ad1848_get_in_sr(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - - return(sc->sc_irate); -} - -int -ad1848_set_out_sr(addr, sr) - void *addr; - u_long sr; -{ - register struct ad1848_softc *sc = addr; - - DPRINTF(("ad1848_set_out_sr: %d\n", sr)); - - ad1848_set_speed(sc, sr); - sc->sc_orate = sr; - - return(0); -} - -u_long -ad1848_get_out_sr(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - - return(sc->sc_orate); -} - -int -ad1848_query_encoding(addr, fp) - void *addr; - struct audio_encoding *fp; -{ - switch (fp->index) { - case 0: - strcpy(fp->name, "MU-Law"); - fp->format_id = AUDIO_ENCODING_ULAW; - break; - case 1: - strcpy(fp->name, "A-Law"); - fp->format_id = AUDIO_ENCODING_ALAW; - break; - case 2: - strcpy(fp->name, "pcm16"); - fp->format_id = AUDIO_ENCODING_PCM16; - break; - case 3: - strcpy(fp->name, "pcm8"); - fp->format_id = AUDIO_ENCODING_PCM8; - break; - default: - return(EINVAL); - /*NOTREACHED*/ - } - return (0); -} - -int -ad1848_set_encoding(addr, enc) - void *addr; - u_int enc; -{ - register struct ad1848_softc *sc = addr; - - DPRINTF(("ad1848_set_encoding: %d\n", enc)); - - if (sc->encoding != AUDIO_ENCODING_PCM8 && - sc->encoding != AUDIO_ENCODING_PCM16 && - sc->encoding != AUDIO_ENCODING_ALAW && - sc->encoding != AUDIO_ENCODING_ULAW) { - - sc->encoding = AUDIO_ENCODING_PCM8; - return (EINVAL); - } - - sc->encoding = ad1848_set_format(sc, enc, sc->precision); - - if (sc->encoding == -1) { - sc->encoding = AUDIO_ENCODING_PCM8; - return (EINVAL); - } - - return (0); -} - -int -ad1848_get_encoding(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - - return(sc->encoding); -} - -int -ad1848_set_precision(addr, prec) - void *addr; - u_int prec; -{ - register struct ad1848_softc *sc = addr; - - DPRINTF(("ad1848_set_precision: %d\n", prec)); - - sc->encoding = ad1848_set_format(sc, sc->encoding, prec); - if (sc->encoding == -1) { - sc->encoding = AUDIO_ENCODING_PCM16; - sc->precision = 16; - return (EINVAL); - } - sc->precision = prec; - - return (0); -} - -int -ad1848_get_precision(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - - return(sc->precision); -} - -int -ad1848_set_channels(addr, chans) - void *addr; - int chans; -{ - register struct ad1848_softc *sc = addr; - int mode; - - DPRINTF(("ad1848_set_channels: %d\n", chans)); - - if (chans < 1 || chans > 2) - return(EINVAL); - - sc->channels = chans; - - return(0); -} - -int -ad1848_get_channels(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - - return(sc->channels); -} - -int -ad1848_set_rec_port(sc, port) - register struct ad1848_softc *sc; - int port; -{ - u_char inp, reg; - - DPRINTF(("ad1848_set_rec_port: 0x%x\n", port)); - - if (port == MIC_IN_PORT) { - inp = MIC_INPUT; - } - else if (port == LINE_IN_PORT) { - inp = LINE_INPUT; - } - else if (port == DAC_IN_PORT) { - inp = MIXED_DAC_INPUT; - } - else - return(EINVAL); - - reg = ad_read(sc, SP_LEFT_INPUT_CONTROL); - reg &= INPUT_SOURCE_MASK; - ad_write(sc, SP_LEFT_INPUT_CONTROL, (inp|reg)); - - reg = ad_read(sc, SP_RIGHT_INPUT_CONTROL); - reg &= INPUT_SOURCE_MASK; - ad_write(sc, SP_RIGHT_INPUT_CONTROL, (inp|reg)); - - sc->rec_port = port; - - return(0); -} - -int -ad1848_get_rec_port(sc) - register struct ad1848_softc *sc; -{ - return(sc->rec_port); -} - -int -ad1848_round_blocksize(addr, blk) - void *addr; - int blk; -{ - register struct ad1848_softc *sc = addr; - - sc->sc_lastcc = -1; - - /* Higher speeds need bigger blocks to avoid popping and silence gaps. */ - if ((sc->sc_orate > 8000 || sc->sc_irate > 8000) && - (blk > NBPG/2 || blk < NBPG/4)) - blk = NBPG/2; - /* don't try to DMA too much at once, though. */ - if (blk > NBPG) - blk = NBPG; - - if (sc->channels == 2) - return (blk & ~1); /* must be even to preserve stereo separation */ - else - return(blk); /* Anything goes :-) */ -} - -u_int -ad1848_get_silence(enc) - int enc; -{ -#define ULAW_SILENCE 0x7f -#define ALAW_SILENCE 0x55 -#define LINEAR_SILENCE 0 - u_int auzero; - - switch (enc) { - case AUDIO_ENCODING_ULAW: - auzero = ULAW_SILENCE; - break; - case AUDIO_ENCODING_ALAW: - auzero = ALAW_SILENCE; - break; - case AUDIO_ENCODING_PCM8: - case AUDIO_ENCODING_PCM16: - default: - auzero = LINEAR_SILENCE; - break; - } - - return(auzero); -} - - -int -ad1848_open(sc, dev, flags) - struct ad1848_softc *sc; - dev_t dev; - int flags; -{ - DPRINTF(("ad1848_open: sc=0x%x\n", sc)); - - sc->sc_intr = 0; - sc->sc_lastcc = -1; - sc->sc_locked = 0; - - /* Enable interrupts */ - DPRINTF(("ad1848_open: enable intrs\n")); - ad_write(sc, SP_PIN_CONTROL, INTERRUPT_ENABLE|ad_read(sc, SP_PIN_CONTROL)); - -#ifdef DEBUG - if (ad1848debug) - ad1848_dump_regs(sc); -#endif - - return 0; -} - -void -ad1848_close(addr) - void *addr; -{ - struct ad1848_softc *sc = addr; - register u_char r; - int s = splaudio(); - - sc->sc_intr = 0; - - DPRINTF(("ad1848_close: stop DMA\n")); - ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)0); - ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)0); - - /* Disable interrupts */ - DPRINTF(("ad1848_close: disable intrs\n")); - ad_write(sc, SP_PIN_CONTROL, ad_read(sc, SP_PIN_CONTROL) & ~(INTERRUPT_ENABLE)); - - DPRINTF(("ad1848_close: disable capture and playback\n")); - r = ad_read(sc, SP_INTERFACE_CONFIG); - r &= ~(CAPTURE_ENABLE|PLAYBACK_ENABLE); - ad_write(sc, SP_INTERFACE_CONFIG, r); - -#ifdef DEBUG - if (ad1848debug) - ad1848_dump_regs(sc); -#endif - splx(s); -} - -/* - * Lower-level routines - */ -int -ad1848_commit_settings(addr) - void *addr; -{ - struct ad1848_softc *sc = addr; - int timeout; - u_char fs; - int s = splaudio(); - - ad1848_mute_monitor(sc, 1); - - ad_set_MCE(sc, 1); /* Enables changes to the format select reg */ - - fs = sc->speed_bits | (sc->format_bits << 5); - - if (sc->channels == 2) - fs |= FMT_STEREO; - - ad_write(sc, SP_CLOCK_DATA_FORMAT, fs); - - /* - * If mode == 2 (CS4231), set I28 also. It's the capture format register. - */ - if (sc->mode == 2) - ad_write(sc, 28, fs); - - /* - * Write to I8 starts resyncronization. Wait until it completes. - */ - timeout = 100000; - while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT) - timeout--; - - if (inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT) - printf("ad1848_commit: Auto calibration timed out\n"); - - /* - * Starts the calibration process and - * enters playback mode after it. - */ - ad_set_MCE(sc, 0); - wait_for_calibration(sc); - - ad1848_mute_monitor(sc, 0); - - sc->sc_lastcc = -1; - - splx(s); - - return 0; -} - -void -ad1848_reset(sc) - register struct ad1848_softc *sc; -{ - u_char r; - - DPRINTF(("ad1848_reset\n")); - - /* Clear the PEN and CEN bits */ -#if 0 - r = ad_read(sc, SP_INTERFACE_CONFIG); - r &= ~(CAPTURE_ENABLE|PLAYBACK_ENABLE); - ad_write(sc, SP_INTERFACE_CONFIG, r); -#else - ad_write(sc, SP_INTERFACE_CONFIG, 0); -#endif - - /* Clear interrupt status */ - outb(sc->sc_iobase+AD1848_STATUS, 0); -} - -int -ad1848_set_speed(sc, arg) - register struct ad1848_softc *sc; - int arg; -{ - /* - * The sampling speed is encoded in the least significant nible of I8. The - * LSB selects the clock source (0=24.576 MHz, 1=16.9344 Mhz) and other - * three bits select the divisor (indirectly): - * - * The available speeds are in the following table. Keep the speeds in - * the increasing order. - */ - typedef struct { - int speed; - u_char bits; - } speed_struct; - - static speed_struct speed_table[] = { - {5510, (0 << 1) | 1}, - {5510, (0 << 1) | 1}, - {6620, (7 << 1) | 1}, - {8000, (0 << 1) | 0}, - {9600, (7 << 1) | 0}, - {11025, (1 << 1) | 1}, - {16000, (1 << 1) | 0}, - {18900, (2 << 1) | 1}, - {22050, (3 << 1) | 1}, - {27420, (2 << 1) | 0}, - {32000, (3 << 1) | 0}, - {33075, (6 << 1) | 1}, - {37800, (4 << 1) | 1}, - {44100, (5 << 1) | 1}, - {48000, (6 << 1) | 0} - }; - - int i, n, selected = -1; - - n = sizeof(speed_table) / sizeof(speed_struct); - - if (arg < speed_table[0].speed) - selected = 0; - if (arg > speed_table[n - 1].speed) - selected = n - 1; - - for (i = 1 /*really*/ ; selected == -1 && i < n; i++) - if (speed_table[i].speed == arg) - selected = i; - else if (speed_table[i].speed > arg) { - int diff1, diff2; - - diff1 = arg - speed_table[i - 1].speed; - diff2 = speed_table[i].speed - arg; - - if (diff1 < diff2) - selected = i - 1; - else - selected = i; - } - - if (selected == -1) { - printf("ad1848: Can't find speed???\n"); - selected = 3; - } - - sc->speed = speed_table[selected].speed; - sc->speed_bits = speed_table[selected].bits; - - return sc->speed; -} - -int -ad1848_set_format(sc, fmt, prec) - register struct ad1848_softc *sc; - int fmt, prec; -{ - static u_char format2bits[] = { - /* AUDIO_ENCODING_ULAW */ 1, - /* AUDIO_ENCODING_ALAW */ 3, - /* AUDIO_ENCODING_PCM16 */ 2, - /* AUDIO_ENCODING_PCM8 */ 0 - }; - - - DPRINTF(("ad1848_set_format: fmt=%d prec=%d\n", fmt, prec)); - - /* If not linear; force prec to 8bits */ - if (fmt != AUDIO_ENCODING_PCM16 && prec == 16) - prec = 8; - - if (fmt < AUDIO_ENCODING_ULAW || fmt > AUDIO_ENCODING_PCM8) - goto nogood; - - if (prec != 8 && prec != 16) - goto nogood; - - sc->format_bits = format2bits[fmt-1]; - - if (fmt == AUDIO_ENCODING_PCM16 && prec == 8) - sc->format_bits = 0; - - DPRINTF(("ad1848_set_format: bits=%x\n", sc->format_bits)); - - return fmt; - - nogood: - sc->format_bits = 0; - return -1; -} - -/* - * Halt a DMA in progress. - */ -int -ad1848_halt_out_dma(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - u_char reg; - - DPRINTF(("ad1848: ad1848_halt_out_dma\n")); - - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~PLAYBACK_ENABLE)); - sc->sc_locked = 0; - - return(0); -} - -int -ad1848_halt_in_dma(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - u_char reg; - - DPRINTF(("ad1848: ad1848_halt_in_dma\n")); - - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (reg & ~CAPTURE_ENABLE)); - sc->sc_locked = 0; - - return(0); -} - -int -ad1848_cont_out_dma(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - u_char reg; - - DPRINTF(("ad1848: ad1848_cont_out_dma %s\n", sc->sc_locked?"(locked)":"")); - - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (reg | PLAYBACK_ENABLE)); - - return(0); -} - -int -ad1848_cont_in_dma(addr) - void *addr; -{ - register struct ad1848_softc *sc = addr; - u_char reg; - - DPRINTF(("ad1848: ad1848_cont_in_dma %s\n", sc->sc_locked?"(locked)":"")); - - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (reg | CAPTURE_ENABLE)); - - return(0); -} - -int -ad1848_dma_input(addr, p, cc, intr, arg) - void *addr; - void *p; - int cc; - void (*intr)(); - void *arg; -{ - register struct ad1848_softc *sc = addr; - register u_short iobase; - register u_char reg; - int s; - - if (sc->sc_locked) { - DPRINTF(("ad1848_dma_input: locked\n")); - return 0; - } - -#ifdef DEBUG - if (ad1848debug > 1) - Dprintf("ad1848_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg); -#endif - sc->sc_locked = 1; - sc->sc_intr = intr; - sc->sc_arg = arg; -#ifndef NEWCONFIG - sc->sc_dma_flags = B_READ; - sc->sc_dma_bp = p; - sc->sc_dma_cnt = cc; -#endif - at_dma(B_READ, p, cc, sc->sc_drq); - - if (sc->precision == 16) - cc >>= 1; - - if (sc->channels == 2) - cc >>= 1; - - cc--; - - if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_RECORD) { - int s = splaudio(); - - ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff)); - ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff)); - if (sc->mode == 2) { - ad_write(sc, 31, (u_char) (cc & 0xff)); - ad_write(sc, 32, (u_char) ((cc >> 8) & 0xff)); - } - - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (CAPTURE_ENABLE|reg)); - - sc->sc_lastcc = cc; - sc->sc_mode = AUMODE_RECORD; - splx(s); - } - - return 0; -} - -int -ad1848_dma_output(addr, p, cc, intr, arg) - void *addr; - void *p; - int cc; - void (*intr)(); - void *arg; -{ - register struct ad1848_softc *sc = addr; - register u_short iobase; - register u_char reg; - - if (sc->sc_locked) { - DPRINTF(("ad1848_dma_output: locked\n")); - return 0; - } - -#ifdef DEBUG - if (ad1848debug > 1) - Dprintf("ad1848_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg); -#endif - sc->sc_locked = 1; - sc->sc_intr = intr; - sc->sc_arg = arg; -#ifndef NEWCONFIG - sc->sc_dma_flags = B_WRITE; - sc->sc_dma_bp = p; - sc->sc_dma_cnt = cc; -#endif - at_dma(B_WRITE, p, cc, sc->sc_drq); - - if (sc->precision == 16) - cc >>= 1; - - if (sc->channels == 2) - cc >>= 1; - cc--; - - if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_PLAY) { - int s = splaudio(); - - ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff)); - ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff)); - reg = ad_read(sc, SP_INTERFACE_CONFIG); - ad_write(sc, SP_INTERFACE_CONFIG, (PLAYBACK_ENABLE|reg)); - sc->sc_lastcc = cc; - sc->sc_mode = AUMODE_PLAY; - - splx(s); - } - - return 0; -} - -int -ad1848_intr(arg) - void *arg; -{ - register struct ad1848_softc *sc = arg; - int retval = 0; - u_char status; - - /* Get WSS intr status */ - status = inb(sc->sc_iobase+AD1848_STATUS); - -#ifdef DEBUG - if (ad1848debug > 1) - Dprintf("ad1848_intr: intr=0x%x status=%x\n", sc->sc_intr, status); -#endif - sc->sc_locked = 0; - sc->sc_interrupts++; - - /* Handle WSS interrupt */ - if (sc->sc_intr && (status & INTERRUPT_STATUS)) { - /* ACK DMA read because it may be in a bounce buffer */ - /* XXX Do write to mask DMA ? */ - if (sc->sc_dma_flags & B_READ) -#ifdef NEWCONFIG - at_dma_terminate(sc->sc_drq); -#else - isa_dmadone(sc->sc_dma_flags, sc->sc_dma_bp, sc->sc_dma_cnt, sc->sc_drq); -#endif - (*sc->sc_intr)(sc->sc_arg); - retval = 1; - } - - /* clear interrupt */ - if (status & INTERRUPT_STATUS) - outb(sc->sc_iobase+AD1848_STATUS, 0); - - return(retval); -} diff --git a/sys/arch/i386/isa/ad1848reg.h b/sys/arch/i386/isa/ad1848reg.h deleted file mode 100644 index a0f33995c587..000000000000 --- a/sys/arch/i386/isa/ad1848reg.h +++ /dev/null @@ -1,201 +0,0 @@ -/* $NetBSD: ad1848reg.h,v 1.1 1995/02/21 02:26:41 brezak Exp $ */ - -/* - * Copyright (c) 1994 John Brezak - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: ad1848reg.h,v 1.1 1995/02/21 02:26:41 brezak Exp $ - */ -/* - * Copyright (c) 1993 Analog Devices Inc. All rights reserved - */ - -#define AD1848_BASE_VALID(base) ((base) == 0x530) - -/* ad1848 direct registers */ -#define AD1848_IADDR 0x04 -#define AD1848_IDATA 0x05 -#define AD1848_STATUS 0x06 -#define AD1848_PIO 0x07 - -/* Gain constants */ -#define GAIN_0 0x00 -#define GAIN_1_5 0x01 -#define GAIN_3 0x02 -#define GAIN_4_5 0x03 -#define GAIN_6 0x04 -#define GAIN_7_5 0x05 -#define GAIN_9 0x06 -#define GAIN_10_5 0x07 -#define GAIN_12 0x08 -#define GAIN_13_5 0x09 -#define GAIN_15 0x0a -#define GAIN_16_5 0x0b -#define GAIN_18 0x0c -#define GAIN_19_5 0x0d -#define GAIN_21 0x0e -#define GAIN_22_5 0x0f -#define MUTE 0XFFFF - -/* Attenuation constants */ - -#define ATTEN_0 0x00 -#define ATTEN_1_5 0x01 -#define ATTEN_3 0x02 -#define ATTEN_4_5 0x03 -#define ATTEN_6 0x04 -#define ATTEN_7_5 0x05 -#define ATTEN_9 0x06 -#define ATTEN_10_5 0x07 -#define ATTEN_12 0x08 -#define ATTEN_13_5 0x09 -#define ATTEN_15 0x0a -#define ATTEN_16_5 0x0b -#define ATTEN_18 0x0c -#define ATTEN_19_5 0x0d -#define ATTEN_21 0x0e -#define ATTEN_22_5 0x0f - -/* 1848 Sound Port bit defines */ -#define SP_IN_INIT 0x80 -#define MODE_CHANGE_ENABLE 0x40 -#define MODE_CHANGE_MASK 0xbf -#define TRANSFER_DISABLE 0x20 -#define TRANSFER_DISABLE_MASK 0xdf -#define ADDRESS_MASK 0xf0 - -/* Status bits */ -#define INTERRUPT_STATUS 0x01 -#define PLAYBACK_READY 0x02 -#define PLAYBACK_LEFT 0x04 -/* pbright is not left */ -#define PLAYBACK_UPPER 0x08 -/* bplower is not upper */ - -#define SAMPLE_OVERRUN 0x10 -#define SAMPLE_UNDERRUN 0x10 -#define CAPTURE_READY 0x20 -#define CAPTURE_LEFT 0x40 -/* cpright is not left */ -#define CAPTURE_UPPER 0x08 -/* cplower is not upper */ - -/* Input & Output regs bits */ -#define LINE_INPUT 0x00 -#define AUX_INPUT 0x40 -#define MIC_INPUT 0x80 -#define MIXED_DAC_INPUT 0xC0 -#define INPUT_GAIN_MASK 0xf0 -#define INPUT_MIC_GAIN_ENABLE 0x20 -#define INPUT_MIC_GAIN_MASK 0xdf -#define INPUT_SOURCE_MASK 0x3f -#define AUX_INPUT_ATTEN_BITS 0x1f -#define AUX_INPUT_ATTEN_MASK 0xe0 -#define AUX_INPUT_MUTE 0x80 -#define AUX_INPUT_MUTE_MASK 0x7f -#define OUTPUT_MUTE 0x80 -#define OUTPUT_MUTE_MASK 0x7f -#define OUTPUT_ATTEN_BITS 0x3f -#define OUTPUT_ATTEN_MASK 0xc0 - -/* Clock and Data format reg bits */ -#define CLOCK_SELECT_MASK 0xfe -#define CLOCK_XTAL2 0x01 -#define CLOCK_XTAL1 0x00 -#define CLOCK_FREQ_MASK 0xf1 -#define STEREO_MONO_MASK 0xef -#define FMT_STEREO 0x10 -#define RMT_MONO 0x00 -#define LINEAR_COMP_MASK 0xdf -#define LINEAR 0x00 -#define COMPANDED 0x20 -#define FORMAT_MASK 0xbf -#define PCM 0x00 -#define ULAW 0x00 -#define TWOS_COMP 0x40 -#define ALAW 0x40 - -/* Interface Configuration reg bits */ -#define PLAYBACK_ENABLE 0x01 -#define PLAYBACK_ENABLE_MASK 0xfe -#define CAPTURE_ENABLE 0x02 -#define CAPTURE_ENABLE_MASK 0xfd -#define SINGLE_DMA 0x04 -#define SINGLE_DMA_MASK 0xfb -#define DUAL_DMA 0x00 -#define AUTO_CAL_ENABLE 0x08 -#define AUTO_CAL_DISABLE_MASK 0xf7 -#define PLAYBACK_PIO_ENABLE 0x40 -#define PLAYBACK_DMA_MASK 0xbf -#define CAPTURE_PIO_ENABLE 0x80 -#define CAPTURE_DMA_MASK 0x7f - -/* Pin control bits */ -#define INTERRUPT_ENABLE 0x02 -#define INTERRUPT_MASK 0xfd -#define XCTL0_ENABLE 0x40 -#define XCTL1_ENABLE 0x80 - -/* Test and init reg bits */ -#define OVERRANGE_LEFT_MASK 0xfc -#define OVERRANGE_RIGHT_MASK 0xf3 -#define DATA_REQUEST_STATUS 0x10 -#define AUTO_CAL_IN_PROG 0x20 -#define PLAYBACK_UNDERRUN 0x40 -#define CAPTURE_UNDERRUN 0x80 - -/* Miscellaneous Control reg bits */ -#define ID_MASK 0xf0 - -/* Digital Mix Control reg bits */ -#define DIGITAL_MIX1_MUTE_MASK 0xfe -#define DIGITAL_MIX1_ENABLE 0x01 -#define MIX_ATTEN_MASK 0xfc - -/* 1848 Sound Port reg defines */ -#define SP_LEFT_INPUT_CONTROL 0x0 -#define SP_RIGHT_INPUT_CONTROL 0x1 -#define SP_LEFT_AUX1_CONTROL 0x2 -#define SP_RIGHT_AUX1_CONTROL 0x3 -#define SP_LEFT_AUX2_CONTROL 0x4 -#define SP_RIGHT_AUX2_CONTROL 0x5 -#define SP_LEFT_OUTPUT_CONTROL 0x6 -#define SP_RIGHT_OUTPUT_CONTROL 0x7 -#define SP_CLOCK_DATA_FORMAT 0x8 -#define SP_INTERFACE_CONFIG 0x9 -#define SP_PIN_CONTROL 0xA -#define SP_TEST_AND_INIT 0xB -#define SP_MISC_INFO 0xC -#define SP_DIGITAL_MIX 0xD -#define SP_UPPER_BASE_COUNT 0xE -#define SP_LOWER_BASE_COUNT 0xF - diff --git a/sys/arch/i386/isa/ad1848var.h b/sys/arch/i386/isa/ad1848var.h deleted file mode 100644 index d72815e3a872..000000000000 --- a/sys/arch/i386/isa/ad1848var.h +++ /dev/null @@ -1,153 +0,0 @@ -/* $NetBSD: ad1848var.h,v 1.4 1995/04/17 12:06:57 cgd Exp $ */ - -/* - * Copyright (c) 1994 John Brezak - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: ad1848var.h,v 1.4 1995/04/17 12:06:57 cgd Exp $ - */ - -#define AD1848_NPORT 8 - -struct ad1848_volume { - u_char left; - u_char right; -}; - -struct ad1848_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - void *parent; - - u_short sc_locked; /* true when doing HS DMA */ - u_int sc_lastcc; /* size of last DMA xfer */ - int sc_mode; /* half-duplex record/play */ - -#ifndef NEWCONFIG - int sc_dma_flags; - void *sc_dma_bp; - u_int sc_dma_cnt; -#endif - - u_short sc_iobase; /* I/O port base address */ - u_short sc_irq; /* interrupt */ - u_short sc_drq; /* DMA */ - - u_long sc_irate; /* Sample rate for input */ - u_long sc_orate; /* ...and output */ - - /* We keep track of these */ - struct ad1848_volume rec_gain, aux1_gain, aux2_gain, out_gain, mon_gain; - - u_int encoding; /* ulaw/linear -- keep track */ - u_int precision; /* 8/16 bits */ - - int rec_port; /* recording port */ - - int channels; - - /* ad1848 */ - u_char MCE_bit; - char *chip_name; - int rev; - int mode; - - int speed; - u_char speed_bits; - u_char format_bits; - - u_long sc_interrupts; /* number of interrupts taken */ - void (*sc_intr)(void *); /* dma completion intr handler */ - void *sc_arg; /* arg for sc_intr() */ -}; - -/* - * Ad1848 ports - */ -#define MIC_IN_PORT 0 -#define LINE_IN_PORT 1 -#define AUX1_IN_PORT 2 -#define DAC_IN_PORT 3 - -#ifdef _KERNEL -int ad1848_probe __P((struct ad1848_softc *)); -void ad1848_attach __P((struct ad1848_softc *)); - -int ad1848_open __P((struct ad1848_softc *, dev_t, int)); -void ad1848_close __P((void *)); - -void ad1848_forceintr __P((struct ad1848_softc *)); - -int ad1848_set_in_sr __P((void *, u_long)); -u_long ad1848_get_in_sr __P((void *)); -int ad1848_set_out_sr __P((void *, u_long)); -u_long ad1848_get_out_sr __P((void *)); -int ad1848_query_encoding __P((void *, struct audio_encoding *)); -int ad1848_set_encoding __P((void *, u_int)); -int ad1848_get_encoding __P((void *)); -int ad1848_set_precision __P((void *, u_int)); -int ad1848_get_precision __P((void *)); -int ad1848_set_channels __P((void *, int)); -int ad1848_get_channels __P((void *)); - -int ad1848_round_blocksize __P((void *, int)); - -int ad1848_dma_output __P((void *, void *, int, void (*)(), void*)); -int ad1848_dma_input __P((void *, void *, int, void (*)(), void*)); - -int ad1848_commit_settings __P((void *)); - -u_int ad1848_get_silence __P((int)); - -int ad1848_halt_in_dma __P((void *)); -int ad1848_halt_out_dma __P((void *)); -int ad1848_cont_in_dma __P((void *)); -int ad1848_cont_out_dma __P((void *)); - -int ad1848_intr __P((void *)); - -int ad1848_set_rec_port __P((struct ad1848_softc *, int)); -int ad1848_get_rec_port __P((struct ad1848_softc *)); - -int ad1848_set_aux1_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_get_aux1_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_set_aux2_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_get_aux2_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_set_out_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_get_out_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_set_rec_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_get_rec_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_set_mon_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -int ad1848_get_mon_gain __P((struct ad1848_softc *, struct ad1848_volume *)); -#endif diff --git a/sys/arch/i386/isa/pas.c b/sys/arch/i386/isa/pas.c deleted file mode 100644 index 683221b73ef0..000000000000 --- a/sys/arch/i386/isa/pas.c +++ /dev/null @@ -1,495 +0,0 @@ -/* $NetBSD: pas.c,v 1.5 1995/04/17 12:07:23 cgd Exp $ */ - -/* - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: pas.c,v 1.5 1995/04/17 12:07:23 cgd Exp $ - */ -/* - * Todo: - * - look at other PAS drivers (for PAS native suport) - * - use common sb.c once emulation is setup - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#define DEFINE_TRANSLATIONS -#include - -#define DEBUG /*XXX*/ -#ifdef DEBUG -#define DPRINTF(x) if (pasdebug) printf x -int pasdebug = 0; -#else -#define DPRINTF(x) -#endif - -/* - * Software state, per SoundBlaster card. - * The soundblaster has multiple functionality, which we must demultiplex. - * One approach is to have one major device number for the soundblaster card, - * and use different minor numbers to indicate which hardware function - * we want. This would make for one large driver. Instead our approach - * is to partition the design into a set of drivers that share an underlying - * piece of hardware. Most things are hard to share, for example, the audio - * and midi ports. For audio, we might want to mix two processes' signals, - * and for midi we might want to merge streams (this is hard due to - * running status). Moreover, we should be able to re-use the high-level - * modules with other kinds of hardware. In this module, we only handle the - * most basic communications with the sb card. - */ -struct pas_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - u_short sc_iobase; /* PAS iobase */ - u_short sc_irq; /* PAS irq */ - u_short sc_drq; /* PAS drq */ - - int model; - int rev; - - struct sbdsp_softc sc_sbdsp; -}; - -int pasopen __P((dev_t, int)); - -int pasprobe(); -void pasattach(); - -int pas_getdev __P((void *, struct audio_device *)); - - -/* - * Define our interface to the higher level audio driver. - */ - -struct audio_hw_if pas_hw_if = { - pasopen, - sbdsp_close, - NULL, - sbdsp_set_in_sr, - sbdsp_get_in_sr, - sbdsp_set_out_sr, - sbdsp_get_out_sr, - sbdsp_query_encoding, - sbdsp_set_encoding, - sbdsp_get_encoding, - sbdsp_set_precision, - sbdsp_get_precision, - sbdsp_set_channels, - sbdsp_get_channels, - sbdsp_round_blocksize, - sbdsp_set_out_port, - sbdsp_get_out_port, - sbdsp_set_in_port, - sbdsp_get_in_port, - sbdsp_commit_settings, - sbdsp_get_silence, - sbdsp_expand, - sbdsp_compress, - sbdsp_dma_output, - sbdsp_dma_input, - sbdsp_haltdma, - sbdsp_haltdma, - sbdsp_contdma, - sbdsp_contdma, - sbdsp_speaker_ctl, - pas_getdev, - sbdsp_setfd, - sbdsp_mixer_set_port, - sbdsp_mixer_get_port, - sbdsp_mixer_query_devinfo, - 0, /* not full-duplex */ - 0 -}; - -/* The Address Translation code is used to convert I/O register addresses to - be relative to the given base -register */ - -static char *pasnames[] = { - "", - "Plus", - "CDPC", - "16", - "16Basic" -}; - -static struct audio_device pas_device = { - "PAS,??", - "", - "pas" -}; - -/*XXX assume default I/O base address */ -#define pasread(p) inb(p) -#define paswrite(d, p) outb(p, d) - -void -pasconf(int model, int sbbase, int sbirq, int sbdrq) -{ - int i; - - paswrite(0x00, INTERRUPT_MASK); - /* Local timer control register */ - paswrite(0x36, SAMPLE_COUNTER_CONTROL); - /* Sample rate timer (16 bit) */ - paswrite(0x36, SAMPLE_RATE_TIMER); - paswrite(0, SAMPLE_RATE_TIMER); - /* Local timer control register */ - paswrite(0x74, SAMPLE_COUNTER_CONTROL); - /* Sample count register (16 bit) */ - paswrite(0x74, SAMPLE_BUFFER_COUNTER); - paswrite(0, SAMPLE_BUFFER_COUNTER); - - paswrite(P_C_PCM_MONO | P_C_PCM_DAC_MODE | - P_C_MIXER_CROSS_L_TO_L | P_C_MIXER_CROSS_R_TO_R, - PCM_CONTROL); - paswrite(S_M_PCM_RESET | S_M_FM_RESET | - S_M_SB_RESET | S_M_MIXER_RESET, SERIAL_MIXER); - -/*XXX*/ - paswrite(I_C_1_BOOT_RESET_ENABLE|1, IO_CONFIGURATION_1); - - paswrite(I_C_2_PCM_DMA_DISABLED, IO_CONFIGURATION_2); - paswrite(I_C_3_PCM_IRQ_DISABLED, IO_CONFIGURATION_3); - -#ifdef BROKEN_BUS_CLOCK - paswrite(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND | - S_C_1_FM_EMULATE_CLOCK, SYSTEM_CONFIGURATION_1); -#else - paswrite(S_C_1_PCS_ENABLE | S_C_1_PCS_STEREO | S_C_1_PCS_REALSOUND, - SYSTEM_CONFIGURATION_1); -#endif - - /*XXX*/ - paswrite(0, SYSTEM_CONFIGURATION_2); - paswrite(0, SYSTEM_CONFIGURATION_3); - - /* Sets mute off and selects filter rate of 17.897 kHz */ - paswrite(F_F_MIXER_UNMUTE | 0x01, FILTER_FREQUENCY); - - if (model == PAS_16 || model == PAS_16BASIC) - paswrite(8, PRESCALE_DIVIDER); - else - paswrite(0, PRESCALE_DIVIDER); - - paswrite(P_M_MV508_ADDRESS | P_M_MV508_PCM, PARALLEL_MIXER); - paswrite(5, PARALLEL_MIXER); - - /* - * Setup SoundBlaster emulation. - */ - paswrite((sbbase >> 4) & 0xf, EMULATION_ADDRESS); - paswrite(E_C_SB_IRQ_translate[sbirq] | E_C_SB_DMA_translate[sbdrq], - EMULATION_CONFIGURATION); - paswrite(C_E_SB_ENABLE, COMPATIBILITY_ENABLE); - - /* - * Set mid-range levels. - */ - paswrite(P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER); - paswrite(P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_NONE, PARALLEL_MIXER); - - paswrite(P_M_MV508_ADDRESS | P_M_MV508_MASTER_A, PARALLEL_MIXER); - paswrite(50, PARALLEL_MIXER); - paswrite(P_M_MV508_ADDRESS | P_M_MV508_MASTER_B, PARALLEL_MIXER); - paswrite(50, PARALLEL_MIXER); - - paswrite(P_M_MV508_ADDRESS | P_M_MV508_MIXER | P_M_MV508_SB, PARALLEL_MIXER); - paswrite(P_M_MV508_OUTPUTMIX | 30, PARALLEL_MIXER); - - paswrite(P_M_MV508_ADDRESS | P_M_MV508_MIXER | P_M_MV508_MIC, PARALLEL_MIXER); - paswrite(P_M_MV508_INPUTMIX | 30, PARALLEL_MIXER); -} - -struct cfdriver pascd = { - NULL, "pas", pasprobe, pasattach, DV_DULL, sizeof(struct pas_softc) -}; - -/* - * Probe / attach routines. - */ - -/* - * Probe for the soundblaster hardware. - */ -int -pasprobe(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct pas_softc *sc = (void *)self; - register struct isa_attach_args *ia = aux; - register u_short iobase; - u_char id, t; - - /* - * WARNING: Setting an option like W:1 or so that disables - * warm boot reset of the card will screw up this detect code - * something fierce. Adding code to handle this means possibly - * interfering with other cards on the bus if you have something - * on base port 0x388. SO be forewarned. - */ - /* Talk to first board */ - outb(MASTER_DECODE, 0xbc); - /* Set base address */ - -#if 0 - /* XXX Need to setup pseudo device */ - /* XXX What are good io addrs ? */ - if (iobase != PAS_DEFAULT_BASE) { - printf("pas: configured iobase %d invalid\n", iobase); - return 0; - } -#else - /* Start out talking to native PAS */ - iobase = PAS_DEFAULT_BASE; -#endif - - outb(MASTER_DECODE, iobase >> 2); - /* One wait-state */ - paswrite(1, WAIT_STATE); - - id = pasread(INTERRUPT_MASK); - if (id == 0xff || id == 0xfe) { - /* sanity */ - DPRINTF(("pas: bogus card id\n")); - return 0; - } - /* - * We probably have a PAS-series board, now check for a - * PAS2-series board by trying to change the board revision - * bits. PAS2-series hardware won't let you do this because - * the bits are read-only. - */ - t = id ^ 0xe0; - paswrite(t, INTERRUPT_MASK); - t = inb(INTERRUPT_MASK); - paswrite(id, INTERRUPT_MASK); - - if (t != id) { - /* Not a PAS2 */ - printf("pas: detected card but PAS2 test failed\n"); - return 0; - } - /*XXX*/ - t = pasread(OPERATION_MODE_1) & 0xf; - sc->model = O_M_1_to_card[t]; - if (sc->model != 0) { - sc->rev = pasread(BOARD_REV_ID); - } - else { - DPRINTF(("pas: bogus model id\n")); - return 0; - } - - if (sc->model >= 0) { - int irq = ia->ia_irq; - if (irq == IRQUNK) { - printf("pas: sb emulation requires known irq\n"); - return (0); - } - irq = ia->ia_irq; - pasconf(sc->model, ia->ia_iobase, irq, 1); - } else { - DPRINTF(("pas: could not probe pas\n")); - return (0); - } - - /* Now a SoundBlaster */ - sc->sc_iobase = ia->ia_iobase; - /* and set the SB iobase into the DSP as well ... */ - sc->sc_sbdsp.sc_iobase = ia->ia_iobase; - if (sbdsp_reset(&sc->sc_sbdsp) < 0) { - DPRINTF(("pas: couldn't reset card\n")); - return 0; - } - - /* - * Cannot auto-discover DMA channel. - */ - if (!SB_DRQ_VALID(ia->ia_drq)) { - printf("pas: configured dma chan %d invalid\n", ia->ia_drq); - return 0; - } -#ifdef NEWCONFIG - /* - * If the IRQ wasn't compiled in, auto-detect it. - */ - if (ia->ia_irq == IRQUNK) { - ia->ia_irq = isa_discoverintr(pasforceintr, aux); - sbdsp_reset(&sc->sc_sbdsp); - if (!SB_IRQ_VALID(ia->ia_irq)) { - printf("pas: couldn't auto-detect interrupt"); - return 0; - } - } else -#endif - if (!SB_IRQ_VALID(ia->ia_irq)) { - int irq = ia->ia_irq; - printf("pas: configured irq %d invalid\n", irq); - return 0; - } - - sc->sc_sbdsp.sc_irq = ia->ia_irq; - sc->sc_sbdsp.sc_drq = ia->ia_drq; - - if (sbdsp_probe(&sc->sc_sbdsp) == 0) { - DPRINTF(("pas: sbdsp probe failed\n")); - return 0; - } - - ia->ia_iosize = SB_NPORT; - return 1; -} - -#ifdef NEWCONFIG -void -pasforceintr(aux) - void *aux; -{ - static char dmabuf; - struct isa_attach_args *ia = aux; - u_short iobase = ia->ia_iobase; - - /* - * Set up a DMA read of one byte. - * XXX Note that at this point we haven't called - * at_setup_dmachan(). This is okay because it just - * allocates a buffer in case it needs to make a copy, - * and it won't need to make a copy for a 1 byte buffer. - * (I think that calling at_setup_dmachan() should be optional; - * if you don't call it, it will be called the first time - * it is needed (and you pay the latency). Also, you might - * never need the buffer anyway.) - */ - at_dma(1, &dmabuf, 1, ia->ia_drq); - if (pas_wdsp(iobase, SB_DSP_RDMA) == 0) { - (void)pas_wdsp(iobase, 0); - (void)pas_wdsp(iobase, 0); - } -} -#endif - -/* - * Attach hardware to driver, attach hardware driver to audio - * pseudo-device driver . - */ -void -pasattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct pas_softc *sc = (struct pas_softc *)self; - struct isa_attach_args *ia = (struct isa_attach_args *)aux; - register u_short iobase = ia->ia_iobase; - - sc->sc_iobase = iobase; - -#ifdef NEWCONFIG - isa_establish(&sc->sc_id, &sc->sc_dev); -#endif - sc->sc_ih = isa_intr_establish(ia->ia_irq, ISA_IST_EDGE, ISA_IPL_BIO, - sbdsp_intr, &sc->sc_sbdsp); - -#ifdef NEWCONFIG - /* - * We limit DMA transfers to a page, and use the generic DMA handling - * code in isa.c. This code can end up copying a buffer, but since - * the audio driver uses relative small buffers this isn't likely. - * - * This allocation scheme means that the maximum transfer is limited - * by the page size (rather than 64k). This is reasonable. For 4K - * pages, the transfer time at 48KHz is 4096 / 48000 = 85ms. This - * is plenty long enough to amortize any fixed time overhead. - */ - at_setup_dmachan(sc->sc_dmachan, NBPG); -#endif - - printf(" ProAudio Spectrum %s [rev %d] ", pasnames[sc->model], sc->rev); - - sbdsp_attach(&sc->sc_sbdsp); - - sprintf(pas_device.name, "pas,%s", pasnames[sc->model]); - sprintf(pas_device.version, "%d", sc->rev); - - if (audio_hardware_attach(&pas_hw_if, &sc->sc_sbdsp) != 0) - printf("pas: could not attach to audio pseudo-device driver\n"); -} - -int -pasopen(dev, flags) - dev_t dev; - int flags; -{ - struct pas_softc *sc; - int unit = AUDIOUNIT(dev); - - if (unit >= pascd.cd_ndevs) - return ENODEV; - - sc = pascd.cd_devs[unit]; - if (!sc) - return ENXIO; - - return sbdsp_open(&sc->sc_sbdsp, dev, flags); -} - -int -pas_getdev(addr, retp) - void *addr; - struct audio_device *retp; -{ - *retp = pas_device; - return 0; -} diff --git a/sys/arch/i386/isa/pasreg.h b/sys/arch/i386/isa/pasreg.h deleted file mode 100644 index e1b5466e7fcb..000000000000 --- a/sys/arch/i386/isa/pasreg.h +++ /dev/null @@ -1,254 +0,0 @@ -/* $NetBSD: pasreg.h,v 1.2 1995/03/15 18:45:58 brezak Exp $ */ - -/* Port addresses and bit fields for the Media Vision Pro AudioSpectrum - * second generation sound cards. - * - * Feel free to use this header file in any application you create that - * has support for the Media Vision Pro AudioSpectrum second generation - * sound cards. Other uses prohibited without prior permission. - * - * - cmetz@thor.tjhsst.edu - * - * Notes: - * - * - All of these ports go into the MVD101 multimedia controller chip, - * which then signals the other chips to do the actual work. Many - * ports like the FM ones functionally attach directly to the - * destination chip though they don't actually have a direct connection. - * - The PAS2 series cards have an MVD101 multimedia controller chip, - * the original PAS cards don't. The original PAS cards are pretty - * defunct now, so no attempt is made here to support them. - * - The PAS2 series cards are all really different at the hardware level, - * though the MVD101 hides some of the incompatibilities, there still - * are differences that need to be accounted for. - * - * Card CD-ROM interface PCM chip Mixer chip FM chip - * PAS Plus Sony proprietary (Crystal?) 8-bit DAC National OPL3 - * PAS 16 Zilog SCSI MVA416 16-bit Codec MVA508 OPL3 - * CDPC Sony proprietary Sony 16-bit Codec National OPL3 - * Fusion CD 16 Sony proprietary MVA416 16-bit Codec MVA508 OPL3 - * Fusion CD Sony proprietary (Crystal?) 8-bit DAC National OPL3 - * - */ - -#define PAS_DEFAULT_BASE 0x388 - -/* Symbolic Name Value R W Subsystem Description */ -#define SPEAKER_CONTROL 0x61 /* W PC speaker Control register */ -#define SPEAKER_CONTROL_GHOST 0x738B /* R W PC speaker Control ghost register */ -#define SPEAKER_TIMER_CONTROL 0x43 /* W PC speaker Timer control register */ -#define SPEAKER_TIMER_CONTROL_GHOST 0x778B /* R W PC speaker Timer control register ghost */ -#define SPEAKER_TIMER_DATA 0x42 /* W PC speaker Timer data register */ -#define SPEAKER_TIMER_DATA_GHOST 0x138A /* R W PC speaker Timer data register ghost */ - -#define WARM_BOOT 0x41 /* W Control Used to detect system warm boot */ -#define WARM_BOOT_GHOST 0x7789 /* ? W Control Use to get the card to fake warm boot */ -#define MASTER_DECODE 0x9A01 /* W Control Address >> 2 of card base address */ -#define PRESCALE_DIVIDER 0xBF8A /* R W PCM Ration between Codec clock and master clock */ -#define WAIT_STATE 0xBF88 /* R W Control Four-bit bus wait-state count (~140ns ea.) */ -#define BOARD_REV_ID 0x2789 /* R Control Extended Board Revision ID */ - -#define SYSTEM_CONFIGURATION_1 0x8388 /* R W Control */ - #define S_C_1_PCS_ENABLE 0x01 /* R W PC speaker 1=enable, 0=disable PC speaker emulation */ - #define S_C_1_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=14.31818Mhz/12, 0=28.224Mhz master clock */ - #define S_C_1_FM_EMULATE_CLOCK 0x04 /* R W FM 1=use 28.224Mhz/2, 0=use 14.31818Mhz clock */ - #define S_C_1_PCS_STEREO 0x10 /* R W PC speaker 1=enable PC speaker stereo effect, 0=disable */ - #define S_C_1_PCS_REALSOUND 0x20 /* R W PC speaker 1=enable RealSound enhancement, 0=disable */ - #define S_C_1_FORCE_EXT_RESET 0x40 /* R W Control Force external reset */ - #define S_C_1_FORCE_INT_RESET 0x80 /* R W Control Force internal reset */ -#define SYSTEM_CONFIGURATION_2 0x8389 /* R W Control */ - #define S_C_2_PCM_OVERSAMPLING 0x03 /* R W PCM 00=0x, 01=2x, 10=4x, 11=reserved */ - #define S_C_2_PCM_16_BIT 0x04 /* R W PCM 1=16-bit, 0=8-bit samples */ -#define SYSTEM_CONFIGURATION_3 0x838A /* R W Control */ - #define S_C_3_PCM_CLOCK_SELECT 0x02 /* R W PCM 1=use 1.008Mhz clock for PCM, 0=don't */ -#define SYSTEM_CONFIGURATION_4 0x838B /* R W Control CD-ROM interface controls */ - -#define IO_CONFIGURATION_1 0xF388 /* R W Control */ - #define I_C_1_BOOT_RESET_ENABLE 0x80 /* R W Control 1=reset board on warm boot, 0=don't */ -#define IO_CONFIGURATION_2 0xF389 /* R W Control */ - #define I_C_2_PCM_DMA_DISABLED 0x00 /* R W PCM PCM DMA disabled */ -#define IO_CONFIGURATION_3 0xF38A /* R W Control */ - #define I_C_3_PCM_IRQ_DISABLED 0x00 /* R W PCM PCM IRQ disabled */ - -#define COMPATIBILITY_ENABLE 0xF788 /* R W Control */ - #define C_E_MPU401_ENABLE 0x01 /* R W MIDI 1=enable, 0=disable MPU401 MIDI emulation */ - #define C_E_SB_ENABLE 0x02 /* R W PCM 1=enable, 0=disable Sound Blaster emulation */ - #define C_E_SB_ACTIVE 0x04 /* R PCM "Sound Blaster Interrupt active" */ - #define C_E_MPU401_ACTIVE 0x08 /* R MIDI "MPU UART mode active" */ - #define C_E_PCM_COMPRESSION 0x10 /* R W PCM 1=enable, 0=disabled compression */ -#define EMULATION_ADDRESS 0xF789 /* R W Control */ - #define E_A_SB_BASE 0x0f /* R W PCM bits A4-A7 for SB base port */ - #define E_A_MPU401_BASE 0xf0 /* R W MIDI bits A4-A7 for MPU401 base port */ -#define EMULATION_CONFIGURATION 0xFB8A /* R W ***** Only valid on newer PAS2 cards (?) ***** */ - #define E_C_MPU401_IRQ 0x07 /* R W MIDI MPU401 emulation IRQ */ - #define E_C_SB_IRQ 0x38 /* R W PCM SB emulation IRQ */ - #define E_C_SB_DMA 0xC0 /* R W PCM SB emulation DMA */ - -#define OPERATION_MODE_1 0xEF8B /* R Control */ - #define O_M_1_CDROM_TYPE 0x03 /* R CD-ROM 3=SCSI, 2=Sony, 0=no CD-ROM interface */ - #define O_M_1_FM_TYPE 0x04 /* R FM 1=sterero, 0=mono FM chip */ - #define O_M_1_PCM_TYPE 0x08 /* R PCM 1=16-bit Codec, 0=8-bit DAC */ -#define OPERATION_MODE_2 0xFF8B /* R Control */ - #define O_M_2_PCS_ENABLED 0x02 /* R PC speaker PC speaker emulation 1=enabled, 0=disabled */ - #define O_M_2_BUS_TIMING 0x10 /* R Control 1=AT bus timing, 0=XT bus timing */ - #define O_M_2_BOARD_REVISION 0xe0 /* R Control Board revision */ - -#define INTERRUPT_MASK 0x0B8B /* R W Control */ - #define I_M_FM_LEFT_IRQ_ENABLE 0x01 /* R W FM Enable FM left interrupt */ - #define I_M_FM_RIGHT_IRQ_ENABLE 0x02 /* R W FM Enable FM right interrupt */ - #define I_M_PCM_RATE_IRQ_ENABLE 0x04 /* R W PCM Enable Sample Rate interrupt */ - #define I_M_PCM_BUFFER_IRQ_ENABLE 0x08 /* R W PCM Enable Sample Buffer interrupt */ - #define I_M_MIDI_IRQ_ENABLE 0x10 /* R W MIDI Enable MIDI interrupt */ - #define I_M_BOARD_REV 0xE0 /* R Control Board revision */ - -#define INTERRUPT_STATUS 0x0B89 /* R W Control */ - #define I_S_FM_LEFT_IRQ 0x01 /* R W FM Left FM Interrupt Pending */ - #define I_S_FM_RIGHT_IRQ 0x02 /* R W FM Right FM Interrupt Pending */ - #define I_S_PCM_SAMPLE_RATE_IRQ 0x04 /* R W PCM Sample Rate Interrupt Pending */ - #define I_S_PCM_SAMPLE_BUFFER_IRQ 0x08 /* R W PCM Sample Buffer Interrupt Pending */ - #define I_S_MIDI_IRQ 0x10 /* R W MIDI MIDI Interrupt Pending */ - #define I_S_PCM_CHANNEL 0x20 /* R W PCM 1=right, 0=left */ - #define I_S_RESET_ACTIVE 0x40 /* R W Control Reset is active (Timed pulse not finished) */ - #define I_S_PCM_CLIPPING 0x80 /* R W PCM Clipping has occurred */ - -#define FILTER_FREQUENCY 0x0B8A /* R W Control */ - #define F_F_FILTER_DISABLED 0x00 /* R W Mixer No filter */ -#if 0 - struct { /* R W Mixer Filter translation */ - unsigned int freq:24; - unsigned int value:8; - } F_F_FILTER_translate[] = - { { 73500, 0x01 }, /* 73500Hz - divide by 16 */ - { 65333, 0x02 }, /* 65333Hz - divide by 18 */ - { 49000, 0x09 }, /* 49000Hz - divide by 24 */ - { 36750, 0x11 }, /* 36750Hz - divide by 32 */ - { 24500, 0x19 }, /* 24500Hz - divide by 48 */ - { 18375, 0x07 }, /* 18375Hz - divide by 64 */ - { 12783, 0x0f }, /* 12783Hz - divide by 92 */ - { 12250, 0x04 }, /* 12250Hz - divide by 96 */ - { 9188, 0x17 }, /* 9188Hz - divide by 128 */ - { 6125, 0x1f }, /* 6125Hz - divide by 192 */ - }; -#endif - #define F_F_MIXER_UNMUTE 0x20 /* R W Mixer 1=disable, 0=enable board mute */ - #define F_F_PCM_RATE_COUNTER 0x40 /* R W PCM 1=enable, 0=disable sample rate counter */ - #define F_F_PCM_BUFFER_COUNTER 0x80 /* R W PCM 1=enable, 0=disable sample buffer counter */ - -#define PAS_NONE 0 -#define PAS_PLUS 1 -#define PAS_CDPC 2 -#define PAS_16 3 -#define PAS_16BASIC 4 /* no CDrom */ - -#ifdef DEFINE_TRANSLATIONS - char I_C_2_PCM_DMA_translate[] = /* R W PCM PCM DMA channel value translations */ - { 4, 1, 2, 3, 0, 5, 6, 7 }; - char I_C_3_PCM_IRQ_translate[] = /* R W PCM PCM IRQ level value translation */ - { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 }; - char E_C_MPU401_IRQ_translate[] = /* R W MIDI MPU401 emulation IRQ value translation */ - { 0x00, 0x00, 0x01, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x05, 0x06, 0x07 }; - char E_C_SB_IRQ_translate[] = /* R W PCM SB emulation IRQ translate */ - { 0x00, 0x00, 0x08, 0x10, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x28, 0x30, 0x38 }; - char E_C_SB_DMA_translate[] = /* R W PCM SB emulation DMA translate */ - { 0x00, 0x40, 0x80, 0xC0 }; - char O_M_1_to_card[] = /* R W Control Translate (OM1 & 0x0f) to card type */ - { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4, 0, 2, 3 }; -#else - extern char I_C_2_PCM_DMA_translate[]; /* R W PCM PCM DMA channel value translations */ - extern char I_C_3_PCM_IRQ_translate[]; /* R W PCM PCM IRQ level value translation */ - extern char E_C_MPU401_IRQ_translate[]; /* R W MIDI MPU401 emulation IRQ value translation */ - extern char E_C_SB_IRQ_translate[]; /* R W PCM SB emulation IRQ translate */ - extern char E_C_SB_DMA_translate[]; /* R W PCM SB emulation DMA translate */ - extern char O_M_1_to_card[]; /* R W Control Translate (OM1 & 0x0f) to card type */ -#endif - -#define PARALLEL_MIXER 0x078B /* W Mixer Documented for MVD101 as FM Mono Right decode?? */ - #define P_M_MV508_ADDRESS 0x80 /* W Mixer MVD508 Address/mixer select */ - #define P_M_MV508_DATA 0x00 - #define P_M_MV508_LEFT 0x20 /* W Mixer MVD508 Left channel select */ - #define P_M_MV508_RIGHT 0x40 /* W Mixer MVD508 Right channel select */ - #define P_M_MV508_BOTH 0x00 /* W Mixer MVD508 Both channel select */ - #define P_M_MV508_MIXER 0x10 /* W Mixer MVD508 Select a mixer (rather than a volume) */ - #define P_M_MV508_VOLUME 0x00 - - #define P_M_MV508_INPUTMIX 0x20 /* W Mixer MVD508 Select mixer A */ - #define P_M_MV508_OUTPUTMIX 0x00 /* W Mixer MVD508 Select mixer B */ - - #define P_M_MV508_MASTER_A 0x01 /* W Mixer MVD508 Master volume control A (output) */ - #define P_M_MV508_MASTER_B 0x02 /* W Mixer MVD508 Master volume control B (DSP input) */ - #define P_M_MV508_BASS 0x03 /* W Mixer MVD508 Bass control */ - #define P_M_MV508_TREBLE 0x04 /* W Mixer MVD508 Treble control */ - #define P_M_MV508_MODE 0x05 /* W Mixer MVD508 Master mode control */ - - #define P_M_MV508_LOUDNESS 0x04 /* W Mixer MVD508 Mode control - Loudness filter */ - #define P_M_MV508_ENHANCE_NONE 0x00 /* W Mixer MVD508 Mode control - No stereo enhancement */ - #define P_M_MV508_ENHANCE_40 0x01 /* W Mixer MVD508 Mode control - 40% stereo enhancement */ - #define P_M_MV508_ENHANCE_60 0x02 /* W Mixer MVD508 Mode control - 60% stereo enhancement */ - #define P_M_MV508_ENHANCE_80 0x03 /* W Mixer MVD508 Mode control - 80% stereo enhancement */ - - #define P_M_MV508_FM 0x00 /* W Mixer MVD508 Channel 0 - FM */ - #define P_M_MV508_IMIXER 0x01 /* W Mixer MVD508 Channel 1 - Input mixer (rec monitor) */ - #define P_M_MV508_LINE 0x02 /* W Mixer MVD508 Channel 2 - Line in */ - #define P_M_MV508_CDROM 0x03 /* W Mixer MVD508 Channel 3 - CD-ROM */ - #define P_M_MV508_MIC 0x04 /* W Mixer MVD508 Channel 4 - Microphone */ - #define P_M_MV508_PCM 0x05 /* W Mixer MVD508 Channel 5 - PCM */ - #define P_M_MV508_SPEAKER 0x06 /* W Mixer MVD508 Channel 6 - PC Speaker */ - #define P_M_MV508_SB 0x07 /* W Mixer MVD508 Channel 7 - SB DSP */ - -#define SERIAL_MIXER 0xB88 /* R W Control Serial mixer control (used other ways) */ - #define S_M_PCM_RESET 0x01 /* R W PCM Codec/DSP reset */ - #define S_M_FM_RESET 0x02 /* R W FM FM chip reset */ - #define S_M_SB_RESET 0x04 /* R W PCM SB emulation chip reset */ - #define S_M_MIXER_RESET 0x10 /* R W Mixer Mixer chip reset */ - #define S_M_INTEGRATOR_ENABLE 0x40 /* R W Speaker Enable PC speaker integrator (FORCE RealSound) */ - -#define PCM_CONTROL 0xF8A /* R W PCM PCM Control Register */ - #define P_C_MIXER_CROSS_FIELD 0x0f - #define P_C_MIXER_CROSS_R_TO_R 0x01 /* R W Mixer Connect Right to Right */ - #define P_C_MIXER_CROSS_L_TO_R 0x02 /* R W Mixer Connect Left to Right */ - #define P_C_MIXER_CROSS_R_TO_L 0x04 /* R W Mixer Connect Right to Left */ - #define P_C_MIXER_CROSS_L_TO_L 0x08 /* R W Mixer Connect Left to Left */ - #define P_C_PCM_DAC_MODE 0x10 /* R W PCM Playback (DAC) mode */ - #define P_C_PCM_ADC_MODE 0x00 /* R W PCM Record (ADC) mode */ - #define P_C_PCM_MONO 0x20 /* R W PCM Mono mode */ - #define P_C_PCM_STEREO 0x00 /* R W PCM Stereo mode */ - #define P_C_PCM_ENABLE 0x40 /* R W PCM Enable PCM engine */ - #define P_C_PCM_DMA_ENABLE 0x80 /* R W PCM Enable DRQ */ - -#define SAMPLE_COUNTER_CONTROL 0x138B /* R W PCM Sample counter control register */ - #define S_C_C_SQUARE_WAVE 0x04 /* R W PCM Square wave generator (use for sample rate) */ - #define S_C_C_RATE 0x06 /* R W PCM Rate generator (use for sample buffer count) */ - #define S_C_C_LSB_THEN_MSB 0x30 /* R W PCM Change all 16 bits, LSB first, then MSB */ - - /* MVD101 and SDK documentations have S_C_C_SAMPLE_RATE and S_C_C_SAMPLE_BUFFER transposed. Only one works :-) */ - #define S_C_C_SAMPLE_RATE 0x00 /* R W PCM Select sample rate timer */ - #define S_C_C_SAMPLE_BUFFER 0x40 /* R W PCM Select sample buffer counter */ - - #define S_C_C_PC_SPEAKER 0x80 /* R W PCM Select PC speaker counter */ - -#define SAMPLE_RATE_TIMER 0x1388 /* W PCM Sample rate timer register (PCM wait interval) */ -#define SAMPLE_BUFFER_COUNTER 0x1389 /* R W PCM Sample buffer counter (DMA buffer size) */ - -#define MIDI_CONTROL 0x178b /* R W MIDI Midi control register */ - #define M_C_ENA_TSTAMP_IRQ 0x01 /* R W MIDI Enable Time Stamp Interrupts */ - #define M_C_ENA_TME_COMP_IRQ 0x02 /* R W MIDI Enable time compare interrupts */ - #define M_C_ENA_INPUT_IRQ 0x04 /* R W MIDI Enable input FIFO interrupts */ - #define M_C_ENA_OUTPUT_IRQ 0x08 /* R W MIDI Enable output FIFO interrupts */ - #define M_C_ENA_OUTPUT_HALF_IRQ 0x10 /* R W MIDI Enable output FIFO half full interrupts */ - #define M_C_RESET_INPUT_FIFO 0x20 /* R W MIDI Reset input FIFO pointer */ - #define M_C_RESET_OUTPUT_FIFO 0x40 /* R W MIDI Reset output FIFO pointer */ - #define M_C_ENA_THRU_MODE 0x80 /* R W MIDI Echo input to output (THRU) */ - -#define MIDI_STATUS 0x1B88 /* R W MIDI Midi (interrupt) status register */ - #define M_S_TIMESTAMP 0x01 /* R W MIDI Midi time stamp interrupt occurred */ - #define M_S_COMPARE 0x02 /* R W MIDI Midi compare time interrupt occurred */ - #define M_S_INPUT_AVAIL 0x04 /* R W MIDI Midi input data available interrupt occurred */ - #define M_S_OUTPUT_EMPTY 0x08 /* R W MIDI Midi output FIFO empty interrupt occurred */ - #define M_S_OUTPUT_HALF_EMPTY 0x10 /* R W MIDI Midi output FIFO half empty interrupt occurred */ - #define M_S_INPUT_OVERRUN 0x20 /* R W MIDI Midi input overrun error occurred */ - #define M_S_OUTPUT_OVERRUN 0x40 /* R W MIDI Midi output overrun error occurred */ - #define M_S_FRAMING_ERROR 0x80 /* R W MIDI Midi input framing error occurred */ - -#define MIDI_FIFO_STATUS 0x1B89 /* R W MIDI Midi fifo status */ -#define MIDI_DATA 0x178A /* R W MIDI Midi data register */ - diff --git a/sys/arch/i386/isa/pss.c b/sys/arch/i386/isa/pss.c deleted file mode 100644 index 6413b38b78e5..000000000000 --- a/sys/arch/i386/isa/pss.c +++ /dev/null @@ -1,1852 +0,0 @@ -/* $NetBSD: pss.c,v 1.4 1995/04/17 12:07:34 cgd Exp $ */ - -/* - * Copyright (c) 1994 John Brezak - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: pss.c,v 1.4 1995/04/17 12:07:34 cgd Exp $ - */ - -/* - * Copyright (c) 1993 Analog Devices Inc. All rights reserved - * - * Portions provided by Marc.Hoffman@analog.com and - * Greg.Yukna@analog.com . - * - */ - -/* - * Todo: - * - Provide PSS driver to access DSP - * - Provide MIDI driver to access MPU - * - Finish support for CD drive (Sony and SCSI) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* - * Mixer devices - */ -#define PSS_MIC_IN_LVL 0 -#define PSS_LINE_IN_LVL 1 -#define PSS_DAC_LVL 2 -#define PSS_REC_LVL 3 -#define PSS_MON_LVL 4 -#define PSS_MASTER_VOL 5 -#define PSS_MASTER_TREBLE 6 -#define PSS_MASTER_BASS 7 -#define PSS_MIC_IN_MUTE 8 -#define PSS_LINE_IN_MUTE 9 -#define PSS_DAC_MUTE 10 - -#define PSS_OUTPUT_MODE 11 -#define PSS_SPKR_MONO 0 -#define PSS_SPKR_STEREO 1 -#define PSS_SPKR_PSEUDO 2 -#define PSS_SPKR_SPATIAL 3 - -#define PSS_RECORD_SOURCE 12 - -/* Classes */ -#define PSS_INPUT_CLASS 13 -#define PSS_RECORD_CLASS 14 -#define PSS_MONITOR_CLASS 15 -#define PSS_OUTPUT_CLASS 16 - - -struct pss_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - u_short sc_iobase; /* I/O port base address */ - u_short sc_drq; /* dma channel */ - - struct ad1848_softc *ad1848_sc; - - int out_port; - - struct ad1848_volume master_volume; - int master_mode; - - int monitor_treble; - int monitor_bass; - - int mic_mute, cd_mute, dac_mute; -}; - -struct mpu_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - u_short sc_iobase; /* MIDI I/O port base address */ - u_short sc_irq; /* MIDI interrupt */ -}; - -struct cd_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - u_short sc_iobase; /* CD I/O port base address */ - u_short sc_irq; /* CD interrupt */ -}; - -#define DEBUG /*XXX*/ -#ifdef DEBUG -#define DPRINTF(x) if (pssdebug) printf x -int pssdebug = 0; -#else -#define DPRINTF(x) -#endif - -int pssprobe(); -void pssattach __P((struct device *, struct device *, void *)); - -int spprobe(); -void spattach __P((struct device *, struct device *, void *)); - -int mpuprobe(); -void mpuattach __P((struct device *, struct device *, void *)); - -int pcdprobe(); -void pcdattach __P((struct device *, struct device *, void *)); - -int spopen __P((dev_t, int)); - -int pssintr __P((void *)); -int mpuintr __P((void *)); - -int pss_speaker_ctl __P((void *, int)); - -int pss_getdev __P((void *, struct audio_device *)); -int pss_setfd __P((void *, int)); - -int pss_set_out_port __P((void *, int)); -int pss_get_out_port __P((void *)); -int pss_set_in_port __P((void *, int)); -int pss_get_in_port __P((void *)); -int pss_mixer_set_port __P((void *, mixer_ctrl_t *)); -int pss_mixer_get_port __P((void *, mixer_ctrl_t *)); -int pss_query_devinfo __P((void *, mixer_devinfo_t *)); - -/* - * Define our interface to the higher level audio driver. - */ - -struct audio_hw_if pss_audio_if = { - spopen, - ad1848_close, - NULL, - ad1848_set_in_sr, - ad1848_get_in_sr, - ad1848_set_out_sr, - ad1848_get_out_sr, - ad1848_query_encoding, - ad1848_set_encoding, - ad1848_get_encoding, - ad1848_set_precision, - ad1848_get_precision, - ad1848_set_channels, - ad1848_get_channels, - ad1848_round_blocksize, - pss_set_out_port, - pss_get_out_port, - pss_set_in_port, - pss_get_in_port, - ad1848_commit_settings, - ad1848_get_silence, - NULL, - NULL, - ad1848_dma_output, - ad1848_dma_input, - ad1848_halt_out_dma, - ad1848_halt_in_dma, - ad1848_cont_out_dma, - ad1848_cont_in_dma, - pss_speaker_ctl, - pss_getdev, - pss_setfd, - pss_mixer_set_port, - pss_mixer_get_port, - pss_query_devinfo, - 0, /* not full-duplex */ - 0 -}; - - -/* Interrupt translation for WSS config */ -static u_char wss_interrupt_bits[12] = { - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x08, - 0xff, 0x10, 0x18, 0x20 -}; -/* ditto for WSS DMA channel */ -static u_char wss_dma_bits[4] = {1, 2, 0, 3}; - -#ifndef NEWCONFIG -#define at_dma(flags, ptr, cc, chan) isa_dmastart(flags, ptr, cc, chan) -#endif - -struct cfdriver psscd = { - NULL, "pss", pssprobe, pssattach, DV_DULL, sizeof(struct pss_softc), 1 -}; - -struct cfdriver spcd = { - NULL, "sp", spprobe, spattach, DV_DULL, sizeof(struct ad1848_softc) -}; - -struct cfdriver mpucd = { - NULL, "mpu", mpuprobe, mpuattach, DV_DULL, sizeof(struct mpu_softc) -}; - -struct cfdriver pcdcd = { - NULL, "pcd", pcdprobe, pcdattach, DV_DULL, sizeof(struct cd_softc) -}; - -struct audio_device pss_device = { - "pss,ad1848", - "", - "PSS" -}; - -void -pss_dspwrite(struct pss_softc *sc, int data) -{ - int i; - u_short pss_base = sc->sc_iobase; - - /* - * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes - * called while interrupts are disabled. This means that the timer is - * disabled also. However the timeout situation is a abnormal condition. - * Normally the DSP should be ready to accept commands after just couple of - * loops. - */ - for (i = 0; i < 5000000; i++) { - if (inw(pss_base+PSS_STATUS) & PSS_WRITE_EMPTY) { - outw(pss_base+PSS_DATA, data); - return; - } - } - printf ("pss: DSP Command (%04x) Timeout.\n", data); -} - -void -pss_setaddr(int addr, int configAddr) -{ - int val; - - val = inw(configAddr); - val &= ADDR_MASK; - val |= (addr << 4); - outw(configAddr,val); -} - -/* pss_setint - * This function sets the correct bits in the - * configuration register to - * enable the chosen interrupt. - */ -int -pss_setint(int intNum, int configAddress) -{ - int val; - switch(intNum) { - case 0: - val = inw(configAddress); - val &= INT_MASK; - outw(configAddress,val); - break; - case 3: - val = inw(configAddress); - val &= INT_MASK; - val |= INT_3_BITS; - outw(configAddress,val); - break; - case 5: - val = inw(configAddress); - val &= INT_MASK; - val |= INT_5_BITS; - outw(configAddress,val); - break; - case 7: - val = inw(configAddress); - val &= INT_MASK; - val |= INT_7_BITS; - outw(configAddress,val); - break; - case 9: - val = inw(configAddress); - val &= INT_MASK; - val |= INT_9_BITS; - outw(configAddress,val); - break; - case 10: - val = inw(configAddress); - val &= INT_MASK; - val |= INT_10_BITS; - outw(configAddress,val); - break; - case 11: - val = inw(configAddress); - val &= INT_MASK; - val |= INT_11_BITS; - outw(configAddress,val); - break; - case 12: - val = inw(configAddress); - val &= INT_MASK; - val |= INT_12_BITS; - outw(configAddress,val); - break; - default: - printf("pss_setint unkown int\n"); - return 1; - } - return 0; -} - -int -pss_setdma(int dmaNum, int configAddress) -{ - int val; - - switch(dmaNum) { - case 0: - val = inw(configAddress); - val &= DMA_MASK; - val |= DMA_0_BITS; - outw(configAddress,val); - break; - case 1: - val = inw(configAddress); - val &= DMA_MASK; - val |= DMA_1_BITS; - outw(configAddress,val); - break; - case 3: - val = inw(configAddress); - val &= DMA_MASK; - val |= DMA_3_BITS; - outw(configAddress,val); - break; - case 5: - val = inw(configAddress); - val &= DMA_MASK; - val |= DMA_5_BITS; - outw(configAddress,val); - break; - case 6: - val = inw(configAddress); - val &= DMA_MASK; - val |= DMA_6_BITS; - outw(configAddress,val); - break; - case 7: - val = inw(configAddress); - val &= DMA_MASK; - val |= DMA_7_BITS; - outw(configAddress,val); - break; - default: - printf("PSS ERROR! pss_setdma: unknown_dma\n"); - return 1; - } - return 0; -} - -/* - * This function tests an interrupt number to see if - * it is availible. It takes the interrupt button - * as it's argument and returns TRUE if the interrupt - * is ok. -*/ -static int -pss_testirq(struct pss_softc *sc, int intNum) -{ - u_short iobase = sc->sc_iobase; - int val; - int ret; - int i; - - /* Set the interrupt bits */ - switch(intNum) { - case 3: - val = inw(iobase+PSS_CONFIG); - val &= INT_MASK; /* Special: 0 */ - outw(iobase+PSS_CONFIG, val); - break; - case 5: - val = inw(iobase+PSS_CONFIG); - val &= INT_MASK; - val |= INT_5_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 7: - val = inw(iobase+PSS_CONFIG); - val &= INT_MASK; - val |= INT_7_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 9: - val = inw(iobase+PSS_CONFIG); - val &= INT_MASK; - val |= INT_9_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 10: - val = inw(iobase+PSS_CONFIG); - val &= INT_MASK; - val |= INT_10_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 11: - val = inw(iobase+PSS_CONFIG); - val &= INT_MASK; - val |= INT_11_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 12: - val = inw(iobase+PSS_CONFIG); - val &= INT_MASK; - val |= INT_12_BITS; - outw(iobase+PSS_CONFIG,val); - break; - default: - DPRINTF(("pss: unknown IRQ (%d)\n", intNum)); - return 0; - } - - /* Set the interrupt test bit */ - val = inw(iobase+PSS_CONFIG); - val |= INT_TEST_BIT; - outw(iobase+PSS_CONFIG,val); - - /* Check if the interrupt is in use */ - /* Do it a few times in case there is a delay */ - ret = 0; - for (i = 0; i < 5; i++) { - val = inw(iobase+PSS_CONFIG); - if (val & INT_TEST_PASS) { - ret = 1; - break; - } - } - - /* Clear the Test bit and the interrupt bits */ - val = inw(iobase+PSS_CONFIG); - val &= INT_TEST_BIT_MASK; - val &= INT_MASK; - outw(iobase+PSS_CONFIG,val); - return(ret); -} - -/* - * This function tests a dma channel to see if - * it is availible. It takes the DMA channel button - * as it's argument and returns TRUE if the channel - * is ok. - */ -int -pss_testdma(struct pss_softc *sc, int dmaNum) -{ - u_short iobase = sc->sc_iobase; - int val; - int i,ret; - - switch (dmaNum) { - case 0: - val = inw(iobase+PSS_CONFIG); - val &= DMA_MASK; - val |= DMA_0_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 1: - val = inw(iobase+PSS_CONFIG); - val &= DMA_MASK; - val |= DMA_1_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 3: - val = inw(iobase+PSS_CONFIG); - val &= DMA_MASK; - val |= DMA_3_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 5: - val = inw(iobase+PSS_CONFIG); - val &= DMA_MASK; - val |= DMA_5_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 6: - val = inw(iobase+PSS_CONFIG); - val &= DMA_MASK; - val |= DMA_6_BITS; - outw(iobase+PSS_CONFIG,val); - break; - case 7: - val = inw(iobase+PSS_CONFIG); - val &= DMA_MASK; - val |= DMA_7_BITS; - outw(iobase+PSS_CONFIG,val); - break; - default: - DPRINTF(("pss: unknown DMA channel (%d)\n", dmaNum)); - return 0; - } - - /* Set the DMA test bit */ - val = inw(iobase+PSS_CONFIG); - val |= DMA_TEST_BIT; - outw(iobase+PSS_CONFIG,val); - - /* Check if the DMA channel is in use */ - /* Do it a few times in case there is a delay */ - ret = 0; - for (i = 0; i < 3; i++) { - val = inw(iobase+PSS_CONFIG); - if (val & DMA_TEST_PASS) { - ret = 1; - break; - } - } - - /* Clear the Test bit and the DMA bits */ - val = inw(iobase+PSS_CONFIG); - val &= DMA_TEST_BIT_MASK; - val &= DMA_MASK; - outw(iobase+PSS_CONFIG,val); - return(ret); -} - -int -pss_reset_dsp(struct pss_softc *sc) -{ - u_long i; - u_short pss_base = sc->sc_iobase; - - outw(pss_base+PSS_CONTROL, PSS_RESET); - - for (i = 0; i < 32768; i++) - inw(pss_base+PSS_CONTROL); - - outw(pss_base+PSS_CONTROL, 0); - - return 1; -} - -/* - * This function loads an image into the PSS - * card. The function loads the file by putting - * reseting the dsp and feeding it the boot bytes. - * First you feed the ASIC the first byte of - * the boot sequence. The ASIC waits until it - * detects a BMS and RD and asserts BR - * and outputs the byte. The host must poll for - * the BG signal. It then feeds the ASIC another - * byte which removes BR. - */ -int -pss_download_dsp(struct pss_softc *sc, u_char *block, int size) -{ - int i, val, count; - u_short pss_base = sc->sc_iobase; - - DPRINTF(("pss: downloading boot code...")); - - /* Warn DSP software that a boot is coming */ - outw(pss_base+PSS_DATA, 0x00fe); - - for (i = 0; i < 32768; i++) - if (inw(pss_base+PSS_DATA) == 0x5500) - break; - outw(pss_base+PSS_DATA, *block++); - - pss_reset_dsp(sc); - - DPRINTF(("start ")); - - count = 1; - while(1) { - int j; - for (j=0; j<327670; j++) { - /* Wait for BG to appear */ - if (inw(pss_base+PSS_STATUS) & PSS_FLAG3) - break; - } - - if (j==327670) { - /* It's ok we timed out when the file was empty */ - if (count >= size) - break; - else { - printf("\npss: DownLoad timeout problems, byte %d=%d\n", - count, size); - return 0; - } - } - /* Send the next byte */ - outw(pss_base+PSS_DATA, *block++); - count++; - } - - outw(pss_base+PSS_DATA, 0); - for (i = 0; i < 32768; i++) - (void) inw(pss_base+PSS_STATUS); - - DPRINTF(("downloaded\n")); - - for (i = 0; i < 32768; i++) { - val = inw(pss_base+PSS_STATUS); - if (val & PSS_READ_FULL) - break; - } - - /* now read the version */ - for (i = 0; i < 32000; i++) { - val = inw(pss_base+PSS_STATUS); - if (val & PSS_READ_FULL) - break; - } - if (i == 32000) - return 0; - - (void) inw(pss_base+PSS_DATA); - - return 1; -} - -void -wss_dump_regs(struct ad1848_softc *sc) -{ - printf("WSS regs: config=%x version=%x\n", - (u_char)inb(sc->sc_iobase+WSS_CONFIG), - (u_char)inb(sc->sc_iobase+WSS_STATUS)); -} - -void -pss_dump_regs(struct pss_softc *sc) -{ - printf("PSS regs: status=%x vers=%x ", - (u_short)inw(sc->sc_iobase+PSS_STATUS), - (u_short)inw(sc->sc_iobase+PSS_ID_VERS)); - - printf("config=%x wss_config=%x\n", - (u_short)inw(sc->sc_iobase+PSS_CONFIG), - (u_short)inw(sc->sc_iobase+PSS_WSS_CONFIG)); -} - -/* - * Probe for the PSS hardware. - */ -int -pssprobe(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct pss_softc *sc = (void *)self; - struct isa_attach_args *ia = aux; - u_short iobase = ia->ia_iobase; - int i; - - if (!PSS_BASE_VALID(iobase)) { - printf("pss: configured iobase %d invalid\n", iobase); - return 0; - } - - /* Need to probe for iobase when IOBASEUNK {0x220 0x240} */ - if (iobase == (u_short)IOBASEUNK) { - - iobase = 0x220; - if ((inw(iobase+PSS_ID_VERS) & 0xff00) == 0x4500) - goto pss_found; - - iobase = 0x240; - if ((inw(iobase+PSS_ID_VERS) & 0xff00) == 0x4500) - goto pss_found; - - DPRINTF(("pss: no PSS found (at 0x220 or 0x240)\n")); - return 0; - } - else if ((inw(iobase+PSS_ID_VERS) & 0xff00) != 0x4500) { - DPRINTF(("pss: not a PSS - %x\n", inw(iobase+PSS_ID_VERS))); - return 0; - } - -pss_found: - sc->sc_iobase = iobase; - - /* Clear WSS config */ - pss_setaddr(WSS_BASE_ADDRESS, sc->sc_iobase+PSS_WSS_CONFIG); - outb(WSS_BASE_ADDRESS+WSS_CONFIG, 0); - - /* Clear config registers (POR reset state) */ - outw(sc->sc_iobase+PSS_CONFIG, 0); - outw(sc->sc_iobase+PSS_WSS_CONFIG, 0); - outw(sc->sc_iobase+SB_CONFIG, 0); - outw(sc->sc_iobase+MIDI_CONFIG, 0); - outw(sc->sc_iobase+CD_CONFIG, 0); - - if (ia->ia_irq == IRQUNK) { - int i; - for (i = 0; i < 16; i++) { - if (pss_testirq(sc, i) != 0) - break; - } - if (i == 16) { - printf("pss: unable to locate free IRQ channel\n"); - return 0; - } - else { - ia->ia_irq = (1<ia_irq) == 0) { - printf("pss: configured IRQ unavailable (%d)\n", ia->ia_irq); - return 0; - } - } - - /* XXX Need to deal with DRQUNK */ - if (pss_testdma(sc, ia->ia_drq) == 0) { - printf("pss: configured DMA channel unavailable (%d)\n", ia->ia_drq); - return 0; - } - - ia->ia_iosize = PSS_NPORT; - - /* Initialize PSS irq and dma */ - pss_setint(ia->ia_irq, sc->sc_iobase+PSS_CONFIG); - pss_setdma(sc->sc_drq, sc->sc_iobase+PSS_CONFIG); - - - /* Setup the Game port */ -#ifdef PSS_GAMEPORT - DPRINTF(("Turning Game Port On.\n")); - outw(sc->sc_iobase+PSS_STATUS, inw(sc->sc_iobase+PSS_STATUS) | GAME_BIT); -#else - outw(sc->sc_iobase+PSS_STATUS, inw(sc->sc_iobase+PSS_STATUS) & GAME_BIT_MASK); -#endif - - /* Reset DSP */ - pss_reset_dsp(sc); - - return 1; -} - -/* - * Probe for the Soundport (ad1848) - */ -int -spprobe(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct ad1848_softc *sc = (void *)match; - struct pss_softc *pc = (void *)parent; - struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata; - u_char bits; - int i; - - sc->sc_iobase = cf->cf_iobase; - - /* Set WSS io address */ - pss_setaddr(sc->sc_iobase, pc->sc_iobase+PSS_WSS_CONFIG); - - /* Is there an ad1848 chip at the WSS iobase ? */ - if (ad1848_probe(sc) == 0) { - DPRINTF(("sp: no ad1848 ? iobase=%x\n", sc->sc_iobase)); - return 0; - } - - /* Setup WSS interrupt and DMA if auto */ - if (cf->cf_irq == IRQUNK) { - - /* Find unused IRQ for WSS */ - for (i = 0; i < 12; i++) { - if (wss_interrupt_bits[i] != 0xff) { - if (pss_testirq(pc, i)) - break; - } - } - if (i == 12) { - printf("sp: unable to locate free IRQ for WSS\n"); - return 0; - } - else { - cf->cf_irq = i; - sc->sc_irq = i; - DPRINTF(("sp: found IRQ %d free\n", i)); - } - } - else { - sc->sc_irq = cf->cf_irq; - if (pss_testirq(pc, sc->sc_irq) == 0) { - printf("sp: configured IRQ unavailable (%d)\n", sc->sc_irq); - return 0; - } - } - - if (cf->cf_drq == DRQUNK) { - /* Find unused DMA channel for WSS */ - for (i = 0; i < 4; i++) { - if (wss_dma_bits[i]) { - if (pss_testdma(pc, i)) - break; - } - } - if (i == 4) { - printf("sp: unable to locate free DMA channel for WSS\n"); - return 0; - } - else { - sc->sc_drq = cf->cf_drq = i; - DPRINTF(("sp: found DMA %d free\n", i)); - } - } - else { - if (pss_testdma(pc, sc->sc_drq) == 0) { - printf("sp: configured DMA channel unavailable (%d)\n", sc->sc_drq); - return 0; - } - sc->sc_drq = cf->cf_drq; - } - - /* Set WSS config registers */ - if ((bits = wss_interrupt_bits[sc->sc_irq]) == 0xff) { - printf("sp: invalid interrupt configuration (irq=%d)\n", sc->sc_irq); - return 0; - } - - outb(sc->sc_iobase+WSS_CONFIG, (bits | 0x40)); - if ((inb(sc->sc_iobase+WSS_STATUS) & 0x40) == 0) /* XXX What do these bits mean ? */ - DPRINTF(("sp: IRQ %x\n", inb(sc->sc_iobase+WSS_STATUS))); - - outb(sc->sc_iobase+WSS_CONFIG, (bits | wss_dma_bits[sc->sc_drq])); - - pc->ad1848_sc = sc; - sc->parent = pc; - - return 1; -} - -int -mpuprobe(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct mpu_softc *sc = (void *)match; - struct pss_softc *pc = (void *)parent; - struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata; - - /* Check if midi is enabled; if it is check the interrupt */ - sc->sc_iobase = cf->cf_iobase; - - if (cf->cf_irq == IRQUNK) { - int i; - for (i = 0; i < 16; i++) { - if (pss_testirq(pc, i) != 0) - break; - } - if (i == 16) { - printf("mpu: unable to locate free IRQ channel for MIDI\n"); - return 0; - } - else { - cf->cf_irq = i; - sc->sc_irq = i; - DPRINTF(("mpu: found IRQ %d free\n", i)); - } - } - else { - sc->sc_irq = cf->cf_irq; - - if (pss_testirq(pc, sc->sc_irq) == 0) { - printf("pss: configured MIDI IRQ unavailable (%d)\n", sc->sc_irq); - return 0; - } - } - - outw(pc->sc_iobase+MIDI_CONFIG,0); - DPRINTF(("pss: mpu port 0x%x irq %d\n", sc->sc_iobase, sc->sc_irq)); - pss_setaddr(sc->sc_iobase, pc->sc_iobase+MIDI_CONFIG); - pss_setint(sc->sc_irq, pc->sc_iobase+MIDI_CONFIG); - - return 1; -} - -int -pcdprobe(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct cd_softc *sc = (void *)match; - struct pss_softc *pc = (void *)parent; - struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata; - u_short val; - - sc->sc_iobase = cf->cf_iobase; - - pss_setaddr(sc->sc_iobase, pc->sc_iobase+CD_CONFIG); - - /* Set the correct irq polarity. */ - val = inw(pc->sc_iobase+CD_CONFIG); - outw(pc->sc_iobase+CD_CONFIG, 0); - val &= CD_POL_MASK; - val | CD_POL_BIT; /* XXX if (pol) */ - outw(pc->sc_iobase+CD_CONFIG, val); - - if (cf->cf_irq == IRQUNK) { - int i; - for (i = 0; i < 16; i++) { - if (pss_testirq(pc, i) != 0) - break; - } - if (i == 16) { - printf("pcd: unable to locate free IRQ channel for CD\n"); - return 0; - } - else { - cf->cf_irq = i; - sc->sc_irq = i; - DPRINTF(("pcd: found IRQ %d free\n", i)); - } - } - else { - sc->sc_irq = cf->cf_irq; - - if (pss_testirq(pc, sc->sc_irq) == 0) { - printf("pcd: configured CD IRQ unavailable (%d)\n", sc->sc_irq); - return 0; - } - return 1; - } - pss_setint(sc->sc_irq, pc->sc_iobase+CD_CONFIG); - - return 1; -} - -/* - * Attach hardware to driver, attach hardware driver to audio - * pseudo-device driver . - */ -void -pssattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct pss_softc *sc = (struct pss_softc *)self; - struct isa_attach_args *ia = (struct isa_attach_args *)aux; - u_short iobase = ia->ia_iobase; - u_char vers; - struct ad1848_volume vol = {150, 150}; - - sc->sc_iobase = iobase; - sc->sc_drq = ia->ia_drq; - -#ifdef NEWCONFIG - isa_establish(&sc->sc_id, &sc->sc_dev); -#endif - - /* Setup interrupt handler for PSS */ - sc->sc_ih = isa_intr_establish(ia->ia_irq, ISA_IST_EDGE, ISA_IPL_CLOCK, - pssintr, sc); - - vers = (inw(sc->sc_iobase+PSS_ID_VERS)&0xff) - 1; - printf(": esc614%c\n", (vers > 0)?'A'+vers:' '); - - (void)config_found(self, NULL, NULL); - - sc->out_port = PSS_MASTER_VOL; - - (void)pss_set_master_mode(sc, PSS_SPKR_STEREO); - (void)pss_set_master_gain(sc, &vol); - (void)pss_set_treble(sc, AUDIO_MAX_GAIN/2); - (void)pss_set_bass(sc, AUDIO_MAX_GAIN/2); - - if (audio_hardware_attach(&pss_audio_if, sc->ad1848_sc) != 0) - printf("pss: could not attach to audio pseudo-device driver\n"); -} - -void -spattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct ad1848_softc *sc = (struct ad1848_softc *)self; - struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata; - u_short iobase = cf->cf_iobase; - - sc->sc_iobase = iobase; - sc->sc_drq = cf->cf_drq; - -#ifdef NEWCONFIG - isa_establish(&sc->sc_id, &sc->sc_dev); -#endif - - sc->sc_ih = isa_intr_establish(cf->cf_irq, ISA_IST_EDGE, ISA_IPL_CLOCK, - ad1848_intr, sc); - - /* XXX might use pssprint func ?? */ - printf(" port 0x%x-0x%x irq %d drq %d", - sc->sc_iobase, sc->sc_iobase+AD1848_NPORT, - cf->cf_irq, cf->cf_drq); - - ad1848_attach(sc); - - printf("\n"); -} - -void -mpuattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct mpu_softc *sc = (struct mpu_softc *)self; - struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata; - u_short iobase = cf->cf_iobase; - - sc->sc_iobase = iobase; - -#ifdef NEWCONFIG - isa_establish(&sc->sc_id, &sc->sc_dev); -#endif - - sc->sc_ih = isa_intr_establish(cf->cf_irq, ISA_IST_EDGE, ISA_IPL_CLOCK, - mpuintr, sc); - - /* XXX might use pssprint func ?? */ - printf(" port 0x%x-0x%x irq %d\n", - sc->sc_iobase, sc->sc_iobase+MIDI_NPORT, - cf->cf_irq); -} - -void -pcdattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct cd_softc *sc = (struct cd_softc *)self; - struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata; - u_short iobase = cf->cf_iobase; - - /* - * The pss driver simply enables the cd interface. The CD - * appropriate driver - scsi (aic6360) or Sony needs to be - * used after this to handle the device. - */ - sc->sc_iobase = iobase; - -#ifdef NEWCONFIG - isa_establish(&sc->sc_id, &sc->sc_dev); -#endif - - /* XXX might use pssprint func ?? */ - printf(" port 0x%x-0x%x irq %d\n", - sc->sc_iobase, sc->sc_iobase+2, - cf->cf_irq); -} - -static int -pss_to_vol(cp, vol) - mixer_ctrl_t *cp; - struct ad1848_volume *vol; -{ - if (cp->un.value.num_channels == 1) { - vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; - return(1); - } - else if (cp->un.value.num_channels == 2) { - vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; - vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; - return(1); - } - return(0); -} - -static int -pss_from_vol(cp, vol) - mixer_ctrl_t *cp; - struct ad1848_volume *vol; -{ - if (cp->un.value.num_channels == 1) { - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left; - return(1); - } - else if (cp->un.value.num_channels == 2) { - cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left; - cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right; - return(1); - } - return(0); -} - -int -spopen(dev, flags) - dev_t dev; - int flags; -{ - struct ad1848_softc *sc; - int unit = AUDIOUNIT(dev); - - if (unit >= spcd.cd_ndevs) - return ENODEV; - - sc = spcd.cd_devs[unit]; - if (!sc) - return ENXIO; - - return ad1848_open(sc, dev, flags); -} - -int -pss_set_master_gain(sc, gp) - register struct pss_softc *sc; - struct ad1848_volume *gp; -{ - DPRINTF(("pss_set_master_gain: %d:%d\n", gp->left, gp->right)); - -#ifdef PSS_DSP - if (gp->left > PHILLIPS_VOL_MAX) - gp->left = PHILLIPS_VOL_MAX; - if (gp->left < PHILLIPS_VOL_MIN) - gp->left = PHILLIPS_VOL_MIN; - if (gp->right > PHILLIPS_VOL_MAX) - gp->right = PHILLIPS_VOL_MAX; - if (gp->right < PHILLIPS_VOL_MIN) - gp->right = PHILLIPS_VOL_MIN; - - pss_dspwrite(sc, SET_MASTER_COMMAND); - pss_dspwrite(sc, MASTER_VOLUME_LEFT|(PHILLIPS_VOL_CONSTANT + gp->left / PHILLIPS_VOL_STEP)); - pss_dspwrite(sc, SET_MASTER_COMMAND); - pss_dspwrite(sc, MASTER_VOLUME_RIGHT|(PHILLIPS_VOL_CONSTANT + gp->right / PHILLIPS_VOL_STEP)); -#endif - - sc->master_volume = *gp; - return(0); -} - -int -pss_set_master_mode(sc, mode) - register struct pss_softc *sc; - int mode; -{ - short phillips_mode; - - DPRINTF(("pss_set_master_mode: %d\n", mode)); - - if (mode == PSS_SPKR_STEREO) - phillips_mode = PSS_STEREO; - else if (mode == PSS_SPKR_PSEUDO) - phillips_mode = PSS_PSEUDO; - else if (mode == PSS_SPKR_SPATIAL) - phillips_mode = PSS_SPATIAL; - else if (mode == PSS_SPKR_MONO) - phillips_mode = PSS_MONO; - else - return (EINVAL); - -#ifdef PSS_DSP - pss_dspwrite(sc, SET_MASTER_COMMAND); - pss_dspwrite(sc, MASTER_SWITCH | mode); -#endif - - sc->master_mode = mode; - - return(0); -} - -int -pss_set_treble(sc, treb) - register struct pss_softc *sc; - u_char treb; -{ - DPRINTF(("pss_set_treble: %d\n", treb)); - -#ifdef PSS_DSP - if (treb > PHILLIPS_TREBLE_MAX) - treb = PHILLIPS_TREBLE_MAX; - if (treb < PHILLIPS_TREBLE_MIN) - treb = PHILLIPS_TREBLE_MIN; - pss_dspwrite(sc, SET_MASTER_COMMAND); - pss_dspwrite(sc, MASTER_TREBLE|(PHILLIPS_TREBLE_CONSTANT + treb / PHILLIPS_TREBLE_STEP)); -#endif - - sc->monitor_treble = treb; - - return(0); -} - -int -pss_set_bass(sc, bass) - register struct pss_softc *sc; - u_int bass; -{ - DPRINTF(("pss_set_bass: %d\n", bass)); - -#ifdef PSS_DSP - if (bass > PHILLIPS_BASS_MAX) - bass = PHILLIPS_BASS_MAX; - if (bass < PHILLIPS_BASS_MIN) - bass = PHILLIPS_BASS_MIN; - pss_dspwrite(sc, SET_MASTER_COMMAND); - pss_dspwrite(sc, MASTER_BASS|(PHILLIPS_BASS_CONSTANT + bass / PHILLIPS_BASS_STEP)); -#endif - - sc->monitor_bass = bass; - - return(0); -} - -int -pss_get_master_gain(sc, gp) - register struct pss_softc *sc; - struct ad1848_volume *gp; -{ - *gp = sc->master_volume; - return(0); -} - -int -pss_get_master_mode(sc, mode) - register struct pss_softc *sc; - u_int *mode; -{ - *mode = sc->master_mode; - return(0); -} - -int -pss_get_treble(sc, tp) - register struct pss_softc *sc; - u_char *tp; -{ - *tp = sc->monitor_treble; - return(0); -} - -int -pss_get_bass(sc, bp) - register struct pss_softc *sc; - u_char *bp; -{ - *bp = sc->monitor_bass; - return(0); -} - -int -pss_speaker_ctl(addr, newstate) - void *addr; - int newstate; -{ - return(0); -} - -int -pssintr(arg) - void *arg; -{ - register struct pss_softc *sc = arg; - u_short sr; - - sr = inw(sc->sc_iobase+PSS_STATUS); - - DPRINTF(("pssintr: sc=%x st=%x\n", sc, sr)); - - /* Acknowledge intr */ - outw(sc->sc_iobase+PSS_IRQ_ACK, 0); - - /* Is it one of ours ? */ - if (sr & (PSS_WRITE_EMPTY|PSS_READ_FULL|PSS_IRQ|PSS_DMQ_TC)) { - /* XXX do something */ - return 1; - } - - return 0; -} - -int -mpuintr(arg) - void *arg; -{ - register struct mpu_softc *sc = arg; - u_char sr; - - sr = inb(sc->sc_iobase+MIDI_STATUS_REG); - - printf("mpuintr: sc=%x sr=%x\n", sc, sr); - - /* XXX Need to clear intr */ - return 1; -} - -int -pss_getdev(addr, retp) - void *addr; - struct audio_device *retp; -{ - DPRINTF(("pss_getdev: retp=0x%x\n", retp)); - - *retp = pss_device; - return 0; -} - -int -pss_setfd(addr, flag) - void *addr; - int flag; -{ - /* Can't do full-duplex */ - return(ENOTTY); -} - -int -pss_set_out_port(addr, port) - void *addr; - int port; -{ - register struct ad1848_softc *ac = addr; - register struct pss_softc *sc = ac->parent; - - DPRINTF(("pss_set_out_port: %d\n", port)); - - if (port != PSS_MASTER_VOL) - return(EINVAL); - - sc->out_port = port; - - return(0); -} - -int -pss_get_out_port(addr) - void *addr; -{ - register struct ad1848_softc *ac = addr; - register struct pss_softc *sc = ac->parent; - - DPRINTF(("pss_get_out_port: %d\n", sc->out_port)); - - return(sc->out_port); -} - -int -pss_set_in_port(addr, port) - void *addr; - int port; -{ - register struct ad1848_softc *ac = addr; - register struct pss_softc *sc = ac->parent; - - DPRINTF(("pss_set_in_port: %d\n", port)); - - switch(port) { - case PSS_MIC_IN_LVL: - port = MIC_IN_PORT; - break; - case PSS_LINE_IN_LVL: - port = LINE_IN_PORT; - break; - case PSS_DAC_LVL: - port = DAC_IN_PORT; - break; - default: - return(EINVAL); - /*NOTREACHED*/ - } - - return(ad1848_set_rec_port(ac, port)); -} - -int -pss_get_in_port(addr) - void *addr; -{ - register struct ad1848_softc *ac = addr; - register struct pss_softc *sc = ac->parent; - int port = PSS_MIC_IN_LVL; - - switch(ad1848_get_rec_port(ac)) { - case MIC_IN_PORT: - port = PSS_MIC_IN_LVL; - break; - case LINE_IN_PORT: - port = PSS_LINE_IN_LVL; - break; - case DAC_IN_PORT: - port = PSS_DAC_LVL; - break; - } - - DPRINTF(("pss_get_in_port: %d\n", port)); - - return(port); -} - -int -pss_mixer_set_port(addr, cp) - void *addr; - mixer_ctrl_t *cp; -{ - register struct ad1848_softc *ac = addr; - register struct pss_softc *sc = ac->parent; - struct ad1848_volume vol; - u_char eq; - int error = EINVAL; - - DPRINTF(("pss_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type)); - - switch (cp->dev) { - case PSS_MIC_IN_LVL: /* Microphone */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (pss_to_vol(cp, &vol)) - error = ad1848_set_aux2_gain(ac, &vol); - } - break; - - case PSS_MIC_IN_MUTE: /* Microphone */ - if (cp->type == AUDIO_MIXER_ENUM) { - sc->mic_mute = cp->un.ord; - DPRINTF(("mic mute %d\n", cp->un.ord)); - error = 0; - } - break; - - case PSS_LINE_IN_LVL: /* linein/CD */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (pss_to_vol(cp, &vol)) - error = ad1848_set_aux1_gain(ac, &vol); - } - break; - - case PSS_LINE_IN_MUTE: /* linein/CD */ - if (cp->type == AUDIO_MIXER_ENUM) { - sc->cd_mute = cp->un.ord; - DPRINTF(("CD mute %d\n", cp->un.ord)); - error = 0; - } - break; - - case PSS_DAC_LVL: /* dac out */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (pss_to_vol(cp, &vol)) - error = ad1848_set_out_gain(ac, &vol); - } - break; - - case PSS_DAC_MUTE: /* dac out */ - if (cp->type == AUDIO_MIXER_ENUM) { - sc->dac_mute = cp->un.ord; - DPRINTF(("DAC mute %d\n", cp->un.ord)); - error = 0; - } - break; - - case PSS_REC_LVL: /* record level */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (pss_to_vol(cp, &vol)) - error = ad1848_set_rec_gain(ac, &vol); - } - break; - - case PSS_RECORD_SOURCE: - if (cp->type == AUDIO_MIXER_ENUM) { - error = ad1848_set_rec_port(ac, cp->un.ord); - } - break; - - case PSS_MON_LVL: - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) { - vol.left = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; - error = ad1848_set_mon_gain(ac, &vol); - } - break; - - case PSS_MASTER_VOL: /* master volume */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (pss_to_vol(cp, &vol)) - error = pss_set_master_gain(sc, &vol); - } - break; - - case PSS_OUTPUT_MODE: - if (cp->type == AUDIO_MIXER_ENUM) - error = pss_set_master_mode(sc, cp->un.ord); - break; - - case PSS_MASTER_TREBLE: /* master treble */ - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) - error = pss_set_treble(sc, (u_char)cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); - break; - - case PSS_MASTER_BASS: /* master bass */ - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) - error = pss_set_bass(sc, (u_char)cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]); - break; - - default: - return ENXIO; - /*NOTREACHED*/ - } - - return 0; -} - -int -pss_mixer_get_port(addr, cp) - void *addr; - mixer_ctrl_t *cp; -{ - register struct ad1848_softc *ac = addr; - register struct pss_softc *sc = ac->parent; - struct ad1848_volume vol; - u_char eq; - int error = EINVAL; - - DPRINTF(("pss_mixer_get_port: port=%d\n", cp->dev)); - - switch (cp->dev) { - case PSS_MIC_IN_LVL: /* Microphone */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_aux2_gain(ac, &vol); - if (!error) - pss_from_vol(cp, &vol); - } - break; - - case PSS_MIC_IN_MUTE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = sc->mic_mute; - error = 0; - } - break; - - case PSS_LINE_IN_LVL: /* linein/CD */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_aux1_gain(ac, &vol); - if (!error) - pss_from_vol(cp, &vol); - } - break; - - case PSS_LINE_IN_MUTE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = sc->cd_mute; - error = 0; - } - break; - - case PSS_DAC_LVL: /* dac out */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_out_gain(ac, &vol); - if (!error) - pss_from_vol(cp, &vol); - } - break; - - case PSS_DAC_MUTE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = sc->dac_mute; - error = 0; - } - break; - - case PSS_REC_LVL: /* record level */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_rec_gain(ac, &vol); - if (!error) - pss_from_vol(cp, &vol); - } - break; - - case PSS_RECORD_SOURCE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = ad1848_get_rec_port(ac); - error = 0; - } - break; - - case PSS_MON_LVL: /* monitor level */ - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) { - error = ad1848_get_mon_gain(ac, &vol); - if (!error) - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol.left; - } - break; - - case PSS_MASTER_VOL: /* master volume */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = pss_get_master_gain(sc, &vol); - if (!error) - pss_from_vol(cp, &vol); - } - break; - - case PSS_MASTER_TREBLE: /* master treble */ - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) { - error = pss_get_treble(sc, &eq); - if (!error) - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = eq; - } - break; - - case PSS_MASTER_BASS: /* master bass */ - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) { - error = pss_get_bass(sc, &eq); - if (!error) - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = eq; - } - break; - - case PSS_OUTPUT_MODE: - if (cp->type == AUDIO_MIXER_ENUM) - error = pss_get_master_mode(sc, &cp->un.ord); - break; - - default: - error = ENXIO; - break; - } - - return(error); -} - -int -pss_query_devinfo(addr, dip) - void *addr; - register mixer_devinfo_t *dip; -{ - register struct ad1848_softc *ac = addr; - register struct pss_softc *sc = ac->parent; - - DPRINTF(("pss_query_devinfo: index=%d\n", dip->index)); - - switch(dip->index) { - case PSS_MIC_IN_LVL: /* Microphone */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = PSS_MIC_IN_MUTE; - strcpy(dip->label.name, AudioNmicrophone); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case PSS_LINE_IN_LVL: /* line/CD */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = PSS_LINE_IN_MUTE; - strcpy(dip->label.name, AudioNcd); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case PSS_DAC_LVL: /* dacout */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = PSS_DAC_MUTE; - strcpy(dip->label.name, AudioNdac); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case PSS_REC_LVL: /* record level */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_RECORD_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = PSS_RECORD_SOURCE; - strcpy(dip->label.name, AudioNrecord); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case PSS_MON_LVL: /* monitor level */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_MONITOR_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNmonitor); - dip->un.v.num_channels = 1; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case PSS_MASTER_VOL: /* master volume */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_OUTPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = PSS_OUTPUT_MODE; - strcpy(dip->label.name, AudioNvolume); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case PSS_MASTER_TREBLE: /* master treble */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_OUTPUT_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNtreble); - dip->un.v.num_channels = 1; - strcpy(dip->un.v.units.name, AudioNtreble); - break; - - case PSS_MASTER_BASS: /* master bass */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = PSS_OUTPUT_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNbass); - dip->un.v.num_channels = 1; - strcpy(dip->un.v.units.name, AudioNbass); - break; - - case PSS_OUTPUT_CLASS: /* output class descriptor */ - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = PSS_OUTPUT_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNspeaker); - break; - - case PSS_INPUT_CLASS: /* input class descriptor */ - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = PSS_INPUT_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioCInputs); - break; - - case PSS_MONITOR_CLASS: /* monitor class descriptor */ - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = PSS_MONITOR_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNmonitor); - break; - - case PSS_RECORD_CLASS: /* record source class */ - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = PSS_RECORD_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNrecord); - break; - - case PSS_MIC_IN_MUTE: - dip->mixer_class = PSS_INPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = PSS_MIC_IN_LVL; - dip->next = AUDIO_MIXER_LAST; - goto mute; - - case PSS_LINE_IN_MUTE: - dip->mixer_class = PSS_INPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = PSS_LINE_IN_LVL; - dip->next = AUDIO_MIXER_LAST; - goto mute; - - case PSS_DAC_MUTE: - dip->mixer_class = PSS_INPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = PSS_DAC_LVL; - dip->next = AUDIO_MIXER_LAST; - mute: - strcpy(dip->label.name, AudioNmute); - dip->un.e.num_mem = 2; - strcpy(dip->un.e.member[0].label.name, AudioNoff); - dip->un.e.member[0].ord = 0; - strcpy(dip->un.e.member[1].label.name, AudioNon); - dip->un.e.member[1].ord = 1; - break; - - case PSS_OUTPUT_MODE: - dip->mixer_class = PSS_OUTPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = PSS_MASTER_VOL; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNmode); - dip->un.e.num_mem = 4; - strcpy(dip->un.e.member[0].label.name, AudioNmono); - dip->un.e.member[0].ord = PSS_SPKR_MONO; - strcpy(dip->un.e.member[1].label.name, AudioNstereo); - dip->un.e.member[1].ord = PSS_SPKR_STEREO; - strcpy(dip->un.e.member[2].label.name, AudioNpseudo); - dip->un.e.member[2].ord = PSS_SPKR_PSEUDO; - strcpy(dip->un.e.member[3].label.name, AudioNspatial); - dip->un.e.member[3].ord = PSS_SPKR_SPATIAL; - break; - - case PSS_RECORD_SOURCE: - dip->mixer_class = PSS_RECORD_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = PSS_REC_LVL; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNsource); - dip->un.e.num_mem = 3; - strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); - dip->un.e.member[0].ord = PSS_MIC_IN_LVL; - strcpy(dip->un.e.member[1].label.name, AudioNcd); - dip->un.e.member[1].ord = PSS_LINE_IN_LVL; - strcpy(dip->un.e.member[2].label.name, AudioNdac); - dip->un.e.member[2].ord = PSS_DAC_LVL; - break; - - default: - return ENXIO; - /*NOTREACHED*/ - } - DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); - - return 0; -} diff --git a/sys/arch/i386/isa/pssreg.h b/sys/arch/i386/isa/pssreg.h deleted file mode 100644 index c792f53812b6..000000000000 --- a/sys/arch/i386/isa/pssreg.h +++ /dev/null @@ -1,165 +0,0 @@ -/* $NetBSD: pssreg.h,v 1.1 1995/02/21 04:15:04 brezak Exp $ */ - -/* - * Copyright (c) 1994 John Brezak - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: pssreg.h,v 1.1 1995/02/21 04:15:04 brezak Exp $ - */ -/* - * Copyright (c) 1993 Analog Devices Inc. All rights reserved - */ - -/* - * Macros to detect valid hardware configuration data. - */ -#define PSS_BASE_VALID(base) ((base) == 0x220 || (base) == 0x240) - -/* - * ESC614 Interface chip - */ -#define ADDR_MASK 0x003f - -#define INT_MASK 0xffc7 -#define INT_3_BITS 0x0008 -#define INT_5_BITS 0x0010 -#define INT_7_BITS 0x0018 -#define INT_9_BITS 0x0020 -#define INT_10_BITS 0x0028 -#define INT_11_BITS 0x0030 -#define INT_12_BITS 0x0038 - -#define INT_TEST_BIT 0x0200 -#define INT_TEST_PASS 0x0100 -#define INT_TEST_BIT_MASK 0xFDFF - -#define DMA_MASK 0xfff8 -#define DMA_0_BITS 0x0001 -#define DMA_1_BITS 0x0002 -#define DMA_3_BITS 0x0003 -#define DMA_5_BITS 0x0004 -#define DMA_6_BITS 0x0005 -#define DMA_7_BITS 0x0006 - -#define DMA_TEST_BIT 0x0080 -#define DMA_TEST_PASS 0x0040 -#define DMA_TEST_BIT_MASK 0xFF7F - -/* Echo DSP Flags */ -#define DSP_FLAG3 0x10 -#define DSP_FLAG2 0x08 -#define DSP_FLAG1 0x80 -#define DSP_FLAG0 0x40 - -/* ESC614 register offsets */ -#define PSS_NPORT 32 - -#define PSS_DATA 0x00 -#define PSS_STATUS 0x02 -#define PSS_CONTROL 0x02 -#define PSS_ID_VERS 0x04 -#define PSS_IRQ_ACK 0x04 - -#define PSS_CONFIG 0x10 -#define PSS_WSS_CONFIG 0x12 -#define SB_CONFIG 0x14 -#define CD_CONFIG 0x16 -#define MIDI_CONFIG 0x18 -#define UART_CONFIG 0x1a - -/* PSS control register */ -#define PSS_WEIE 0x8000 -#define PSS_RFIE 0x4000 -#define PSS_RESET 0x2000 -#define PSS_FLAG1 0x1000 -#define PSS_FLAG0 0x0800 - -/* PSS status register */ -#define PSS_WRITE_EMPTY 0x8000 -#define PSS_READ_FULL 0x4000 -#define PSS_IRQ 0x2000 -#define PSS_DMQ_TC 0x1000 -#define PSS_FLAG3 0x0800 -#define PSS_FLAG2 0x0400 - -/* Game control register */ -#define GAME_BIT 0x0400 -#define GAME_BIT_MASK 0xfbff - -/* MPU registers */ -#define MIDI_NPORT 8 - -#define MIDI_DATA_REG 0x00 -#define MIDI_STATUS_REG 0x01 -#define MIDI_COMMAND_REG 0x01 - -#define MIDI_SR_RF 0x80 -#define MIDI_SR_TE 0x40 - -/* CD Interface registers */ -#define CD_NPORT 16 - -#define CD_POL_MASK 0xFFBF -#define CD_POL_BIT 0x0040 - -/* Phillips amplifier controls: only via DSP */ -/* DSP commands */ -#define SET_MASTER_COMMAND 0x0010 -#define MASTER_VOLUME_LEFT 0x0000 -#define MASTER_VOLUME_RIGHT 0x0100 -#define MASTER_BASS 0x0200 -#define MASTER_TREBLE 0x0300 -#define MASTER_SWITCH 0x0800 - -#define PSS_STEREO 0x00ce -#define PSS_PSEUDO 0x00d6 -#define PSS_SPATIAL 0x00de -#define PSS_MONO 0x00c6 - -#define PHILLIPS_VOL_MIN -64 -#define PHILLIPS_VOL_MAX 6 -#define PHILLIPS_VOL_DELTA 70 -#define PHILLIPS_VOL_INITIAL -20 -#define PHILLIPS_VOL_CONSTANT 252 -#define PHILLIPS_VOL_STEP 2 -#define PHILLIPS_BASS_MIN -12 -#define PHILLIPS_BASS_MAX 15 -#define PHILLIPS_BASS_DELTA 27 -#define PHILLIPS_BASS_INITIAL 0 -#define PHILLIPS_BASS_CONSTANT 246 -#define PHILLIPS_BASS_STEP 2 -#define PHILLIPS_TREBLE_MIN -12 -#define PHILLIPS_TREBLE_MAX 12 -#define PHILLIPS_TREBLE_DELTA 24 -#define PHILLIPS_TREBLE_INITIAL 0 -#define PHILLIPS_TREBLE_CONSTANT 246 -#define PHILLIPS_TREBLE_STEP 2 diff --git a/sys/arch/i386/isa/sb.c b/sys/arch/i386/isa/sb.c deleted file mode 100644 index f0d876d5ad67..000000000000 --- a/sys/arch/i386/isa/sb.c +++ /dev/null @@ -1,322 +0,0 @@ -/* $NetBSD: sb.c,v 1.23 1995/04/17 12:07:37 cgd Exp $ */ - -/* - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sb.c,v 1.23 1995/04/17 12:07:37 cgd Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#define DEBUG /*XXX*/ -#ifdef DEBUG -#define DPRINTF(x) if (sbdebug) printf x -int sbdebug = 0; -#else -#define DPRINTF(x) -#endif - -struct sb_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - struct sbdsp_softc sc_sbdsp; -}; - -int sbprobe(); -void sbattach __P((struct device *, struct device *, void *)); - -struct cfdriver sbcd = { - NULL, "sb", sbprobe, sbattach, DV_DULL, sizeof(struct sb_softc) -}; - -struct audio_device sb_device = { - "SoundBlaster", - "x", - "sb" -}; - -int sbopen __P((dev_t, int)); - -int sbprobe(); -void sbattach(); - -int sb_getdev __P((void *, struct audio_device *)); - -/* - * Define our interface to the higher level audio driver. - */ - -struct audio_hw_if sb_hw_if = { - sbopen, - sbdsp_close, - NULL, - sbdsp_set_in_sr, - sbdsp_get_in_sr, - sbdsp_set_out_sr, - sbdsp_get_out_sr, - sbdsp_query_encoding, - sbdsp_set_encoding, - sbdsp_get_encoding, - sbdsp_set_precision, - sbdsp_get_precision, - sbdsp_set_channels, - sbdsp_get_channels, - sbdsp_round_blocksize, - sbdsp_set_out_port, - sbdsp_get_out_port, - sbdsp_set_in_port, - sbdsp_get_in_port, - sbdsp_commit_settings, - sbdsp_get_silence, - sbdsp_expand, - sbdsp_compress, - sbdsp_dma_output, - sbdsp_dma_input, - sbdsp_haltdma, - sbdsp_haltdma, - sbdsp_contdma, - sbdsp_contdma, - sbdsp_speaker_ctl, - sb_getdev, - sbdsp_setfd, - sbdsp_mixer_set_port, - sbdsp_mixer_get_port, - sbdsp_mixer_query_devinfo, - 0, /* not full-duplex */ - 0 -}; - -/* - * Probe / attach routines. - */ - -/* - * Probe for the soundblaster hardware. - */ -int -sbprobe(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct sb_softc *sc = (void *)self; - register struct isa_attach_args *ia = aux; - register u_short iobase = ia->ia_iobase; - static u_char irq_conf[11] = { - -1, -1, 0x01, -1, -1, 0x02, -1, 0x04, -1, 0x01, 0x08 - }; - - if (!SB_BASE_VALID(ia->ia_iobase)) { - printf("sb: configured iobase %d invalid\n", ia->ia_iobase); - return 0; - } - sc->sc_sbdsp.sc_iobase = iobase; - if (sbdsp_probe(&sc->sc_sbdsp) == 0) { - DPRINTF(("sb: sbdsp probe failed\n")); - return 0; - } - - /* - * Cannot auto-discover DMA channel. - */ - if (ISSBPROCLASS(&sc->sc_sbdsp)) { - if (!SBP_DRQ_VALID(ia->ia_drq)) { - printf("sb: configured dma chan %d invalid\n", ia->ia_drq); - return 0; - } - if (ISSB16CLASS(&sc->sc_sbdsp)) { - sbdsp_mix_write(&sc->sc_sbdsp, SBP_SET_DRQ, - 1 << ia->ia_drq); - } - } - else { - if (!SB_DRQ_VALID(ia->ia_drq)) { - printf("sb: configured dma chan %d invalid\n", ia->ia_drq); - return 0; - } - } - -#ifdef NEWCONFIG - /* - * If the IRQ wasn't compiled in, auto-detect it. - */ - if (ia->ia_irq == IRQUNK) { - ia->ia_irq = isa_discoverintr(sbforceintr, aux); - sbdsp_reset(&sc->sc_sbdsp); - if (ISSBPROCLASS(&sc->sc_sbdsp)) { - if (!SBP_IRQ_VALID(ia->ia_irq)) { - printf("sb: couldn't auto-detect interrupt"); - return 0; - } - } - else { - if (!SB_IRQ_VALID(ia->ia_irq)) { - printf("sb: couldn't auto-detect interrupt"); - return 0; - } - } - } else -#endif - if (ISSBPROCLASS(&sc->sc_sbdsp)) { - if (!SBP_IRQ_VALID(ia->ia_irq)) { - printf("sb: configured irq %d invalid\n", ia->ia_irq); - return 0; - } - if (ISSB16CLASS(&sc->sc_sbdsp)) { - sbdsp_mix_write(&sc->sc_sbdsp, SBP_SET_IRQ, - irq_conf[ia->ia_irq]); - } - } - else { - if (!SB_IRQ_VALID(ia->ia_irq)) { - printf("sb: configured irq %d invalid\n", ia->ia_irq); - return 0; - } - } - - sc->sc_sbdsp.sc_irq = ia->ia_irq; - sc->sc_sbdsp.sc_drq = ia->ia_drq; - - if (ISSBPROCLASS(&sc->sc_sbdsp)) - ia->ia_iosize = SBP_NPORT; - else - ia->ia_iosize = SB_NPORT; - return 1; -} - -#ifdef NEWCONFIG -void -sbforceintr(aux) - void *aux; -{ - static char dmabuf; - struct isa_attach_args *ia = aux; - u_short iobase = ia->ia_iobase; - - /* - * Set up a DMA read of one byte. - * XXX Note that at this point we haven't called - * at_setup_dmachan(). This is okay because it just - * allocates a buffer in case it needs to make a copy, - * and it won't need to make a copy for a 1 byte buffer. - * (I think that calling at_setup_dmachan() should be optional; - * if you don't call it, it will be called the first time - * it is needed (and you pay the latency). Also, you might - * never need the buffer anyway.) - */ - at_dma(B_READ, &dmabuf, 1, ia->ia_drq); - if (sbdsp_wdsp(iobase, SB_DSP_RDMA) == 0) { - (void)sbdsp_wdsp(iobase, 0); - (void)sbdsp_wdsp(iobase, 0); - } -} -#endif - -/* - * Attach hardware to driver, attach hardware driver to audio - * pseudo-device driver . - */ -void -sbattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct sb_softc *sc = (struct sb_softc *)self; - struct isa_attach_args *ia = (struct isa_attach_args *)aux; - register u_short iobase = ia->ia_iobase; - -#ifdef NEWCONFIG - isa_establish(&sc->sc_id, &sc->sc_dev); -#endif - sc->sc_ih = isa_intr_establish(ia->ia_irq, ISA_IST_EDGE, ISA_IPL_BIO, - sbdsp_intr, &sc->sc_sbdsp); - - sbdsp_attach(&sc->sc_sbdsp); - - sprintf(sb_device.version, "%d.%d", - SBVER_MAJOR(sc->sc_sbdsp.sc_model), - SBVER_MINOR(sc->sc_sbdsp.sc_model)); - - if (audio_hardware_attach(&sb_hw_if, &sc->sc_sbdsp) != 0) - printf("sb: could not attach to audio pseudo-device driver\n"); -} - -/* - * Various routines to interface to higher level audio driver - */ - -int -sbopen(dev, flags) - dev_t dev; - int flags; -{ - struct sb_softc *sc; - int unit = AUDIOUNIT(dev); - - if (unit >= sbcd.cd_ndevs) - return ENODEV; - - sc = sbcd.cd_devs[unit]; - if (!sc) - return ENXIO; - - return sbdsp_open(&sc->sc_sbdsp, dev, flags); -} - -int -sb_getdev(addr, retp) - void *addr; - struct audio_device *retp; -{ - *retp = sb_device; - return 0; -} diff --git a/sys/arch/i386/isa/sbdsp.c b/sys/arch/i386/isa/sbdsp.c deleted file mode 100644 index 9e7488a3d858..000000000000 --- a/sys/arch/i386/isa/sbdsp.c +++ /dev/null @@ -1,1649 +0,0 @@ -/* $NetBSD: sbdsp.c,v 1.6 1995/04/17 12:07:41 cgd Exp $ */ - -/* - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sbdsp.c,v 1.6 1995/04/17 12:07:41 cgd Exp $ - */ -/* - * SoundBlaster Pro code provided by John Kohl, based on lots of - * information he gleaned from Steve Haehnichen 's - * SBlast driver for 386BSD and DOS driver code from Daniel Sachs - * . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include - -#ifdef DEBUG -extern void Dprintf __P((const char *, ...)); - -#define DPRINTF(x) if (sbdspdebug) printf x -int sbdspdebug = 0; -#else -#define DPRINTF(x) -#endif - -#ifndef NEWCONFIG -#define at_dma(flags, ptr, cc, chan) isa_dmastart(flags, ptr, cc, chan) -#endif - -#ifndef SBDSP_NPOLL -#define SBDSP_NPOLL 3000 -#endif - -struct { - int wdsp; - int rdsp; - int wmidi; -} sberr; - -#ifdef DEBUG -void -sb_printsc(struct sbdsp_softc *sc) -{ - int i; - - printf("open %d dmachan %d iobase %x locked %d\n", sc->sc_open, sc->sc_drq, - sc->sc_iobase, sc->sc_locked); - printf("hispeed %d irate %d orate %d encoding %x\n", - sc->sc_adacmode, sc->sc_irate, sc->sc_orate, sc->encoding); - printf("outport %d inport %d spkron %d nintr %d\n", - sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts); - printf("tc %x chans %x scintr %x arg %x\n", sc->sc_adactc, sc->sc_chans, - sc->sc_intr, sc->sc_arg); - printf("gain: "); - for (i = 0; i < SB_NDEVS; i++) - printf("%d ", sc->gain[i]); - printf("\n"); -} -#endif - -/* - * Probe / attach routines. - */ - -/* - * Probe for the soundblaster hardware. - */ -int -sbdsp_probe(sc) - struct sbdsp_softc *sc; -{ - register u_short iobase = sc->sc_iobase; - - if (sbdsp_reset(sc) < 0) { - DPRINTF(("sbdsp: couldn't reset card\n")); - return 0; - } - sc->sc_model = sbversion(sc); - - return 1; -} - -/* - * Attach hardware to driver, attach hardware driver to audio - * pseudo-device driver . - */ -void -sbdsp_attach(sc) - struct sbdsp_softc *sc; -{ - register u_short iobase = sc->sc_iobase; - - sc->sc_locked = 0; - -#ifdef NEWCONFIG - /* - * We limit DMA transfers to a page, and use the generic DMA handling - * code in isa.c. This code can end up copying a buffer, but since - * the audio driver uses relative small buffers this isn't likely. - * - * This allocation scheme means that the maximum transfer is limited - * by the page size (rather than 64k). This is reasonable. For 4K - * pages, the transfer time at 48KHz is 4096 / 48000 = 85ms. This - * is plenty long enough to amortize any fixed time overhead. - */ - at_setup_dmachan(sc->sc_drq, NBPG); -#endif - - /* Set defaults */ - if (ISSBPROCLASS(sc)) - sc->sc_irate = sc->sc_orate = 45454; - else - sc->sc_irate = sc->sc_orate = 14925; - sc->sc_chans = 1; - sc->encoding = AUDIO_ENCODING_LINEAR; - - (void) sbdsp_set_in_sr_real(sc, sc->sc_irate); - (void) sbdsp_set_out_sr_real(sc, sc->sc_orate); - - (void) sbdsp_set_in_port(sc, SB_MIC_PORT); - (void) sbdsp_set_out_port(sc, SB_SPEAKER); - - if (ISSBPROCLASS(sc)) { - int i; - - /* set mixer to default levels, by sending a mixer - reset command. */ - sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET); - /* then some adjustments :) */ - sbdsp_mix_write(sc, SBP_CD_VOL, - sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL)); - sbdsp_mix_write(sc, SBP_DAC_VOL, - sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL)); - sbdsp_mix_write(sc, SBP_MASTER_VOL, - sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL)); - sbdsp_mix_write(sc, SBP_LINE_VOL, - sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL)); - for (i = 0; i < SB_NDEVS; i++) - sc->gain[i] = sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL); - } - printf(": dsp v%d.%d\n", - SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model)); -} - -/* - * Various routines to interface to higher level audio driver - */ - -void -sbdsp_mix_write(sc, mixerport, val) - struct sbdsp_softc *sc; - int mixerport; - int val; -{ - int iobase = sc->sc_iobase; - outb(iobase + SBP_MIXER_ADDR, mixerport); - delay(10); - outb(iobase + SBP_MIXER_DATA, val); - delay(30); -} - -int -sbdsp_mix_read(sc, mixerport) - struct sbdsp_softc *sc; - int mixerport; -{ - int iobase = sc->sc_iobase; - outb(iobase + SBP_MIXER_ADDR, mixerport); - delay(10); - return inb(iobase + SBP_MIXER_DATA); -} - -int -sbdsp_set_in_sr(addr, sr) - void *addr; - u_long sr; -{ - register struct sbdsp_softc *sc = addr; - - sc->sc_irate = sr; - - return 0; -} - -int -sbdsp_set_in_sr_real(addr, sr) - void *addr; - u_long sr; -{ - register struct sbdsp_softc *sc = addr; - int rval; - - if (rval = sbdsp_set_sr(sc, &sr, SB_INPUT_RATE)) - return rval; - sc->sc_irate = sr; - sc->sc_dmain_inprogress = 0; /* do it again on next DMA out */ - sc->sc_dmaout_inprogress = 0; - return(0); -} - -u_long -sbdsp_get_in_sr(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - - return(sc->sc_irate); -} - -int -sbdsp_set_out_sr(addr, sr) - void *addr; - u_long sr; -{ - register struct sbdsp_softc *sc = addr; - - sc->sc_orate = sr; - return(0); -} - -int -sbdsp_set_out_sr_real(addr, sr) - void *addr; - u_long sr; -{ - register struct sbdsp_softc *sc = addr; - int rval; - - if (rval = sbdsp_set_sr(sc, &sr, SB_OUTPUT_RATE)) - return rval; - sc->sc_orate = sr; - sc->sc_dmain_inprogress = 0; /* do it again on next DMA out */ - return(0); -} - -u_long -sbdsp_get_out_sr(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - - return(sc->sc_orate); -} - -int -sbdsp_query_encoding(addr, fp) - void *addr; - struct audio_encoding *fp; -{ - register struct sbdsp_softc *sc = addr; - - switch (fp->index) { - case 0: - strcpy(fp->name, "MU-Law"); - fp->format_id = AUDIO_ENCODING_ULAW; - break; - case 2: - strcpy(fp->name, "pcm16"); - fp->format_id = AUDIO_ENCODING_PCM16; - break; - default: - return(EINVAL); - /*NOTREACHED*/ - } - return (0); -} - -int -sbdsp_set_encoding(addr, enc) - void *addr; - u_int enc; -{ - register struct sbdsp_softc *sc = addr; - - switch(enc){ - case AUDIO_ENCODING_ULAW: - sc->encoding = AUDIO_ENCODING_ULAW; - break; - case AUDIO_ENCODING_LINEAR: - sc->encoding = AUDIO_ENCODING_LINEAR; - break; - default: - return (EINVAL); - } - return (0); -} - -int -sbdsp_get_encoding(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - - return(sc->encoding); -} - -int -sbdsp_set_precision(addr, prec) - void *addr; - u_int prec; -{ - - if (prec != 8) - return(EINVAL); - return(0); -} - -int -sbdsp_get_precision(addr) - void *addr; -{ - return(8); -} - -int -sbdsp_set_channels(addr, chans) - void *addr; - int chans; -{ - register struct sbdsp_softc *sc = addr; - int rval; - - if (ISSBPROCLASS(sc)) { - if (chans != 1 && chans != 2) - return(EINVAL); - - sc->sc_chans = chans; - if (rval = sbdsp_set_in_sr_real(addr, sc->sc_irate)) - return rval; - sbdsp_mix_write(sc, SBP_STEREO, - (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) | - (chans == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO)); - /* recording channels needs to be done right when we start - DMA recording. Just record number of channels for now - and set stereo when ready. */ - } - else { - if (chans != 1) - return(EINVAL); - sc->sc_chans = 1; - } - - return(0); -} - -int -sbdsp_get_channels(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - -#if 0 - /* recording stereo may frob the mixer output */ - if (ISSBPROCLASS(sc)) { - if ((sbdsp_mix_read(sc, SBP_STEREO) & SBP_PLAYMODE_MASK) == SBP_PLAYMODE_STEREO) { - sc->sc_chans = 2; - } - else { - sc->sc_chans = 1; - } - } - else { - sc->sc_chans = 1; - } -#endif - - return(sc->sc_chans); -} - -int -sbdsp_set_out_port(addr, port) - void *addr; - int port; -{ - register struct sbdsp_softc *sc = addr; - - sc->out_port = port; /* Just record it */ - - return(0); -} - -int -sbdsp_get_out_port(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - - return(sc->out_port); -} - - -int -sbdsp_set_in_port(addr, port) - void *addr; - int port; -{ - register struct sbdsp_softc *sc = addr; - int mixport, sbport; - - switch (port) { - case SB_MIC_PORT: - sbport = SBP_FROM_MIC; - mixport = SBP_MIC_VOL; - break; - } - - if (ISSBPROCLASS(sc)) { - switch (port) { - case SB_LINE_IN_PORT: - sbport = SBP_FROM_LINE; - mixport = SBP_LINE_VOL; - break; - case SB_CD_PORT: - sbport = SBP_FROM_CD; - mixport = SBP_CD_VOL; - break; - case SB_DAC_PORT: - case SB_FM_PORT: - default: - return(EINVAL); - /*NOTREACHED*/ - } - } - else { - return(EINVAL); - /*NOTREACHED*/ - } - - sc->in_port = port; /* Just record it */ - - if (ISSBPROCLASS(sc)) { - /* record from that port */ - sbdsp_mix_write(sc, SBP_RECORD_SOURCE, - SBP_RECORD_FROM(sbport, SBP_FILTER_OFF, - SBP_FILTER_HIGH)); - /* fetch gain from that port */ - sc->gain[port] = sbdsp_mix_read(sc, mixport); - } - - return(0); -} - -int -sbdsp_get_in_port(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - - return(sc->in_port); -} - - -int -sbdsp_speaker_ctl(addr, newstate) - void *addr; - int newstate; -{ - register struct sbdsp_softc *sc = addr; - - if ((newstate == SPKR_ON) && - (sc->spkr_state == SPKR_OFF)) { - sbdsp_spkron(sc); - sc->spkr_state = SPKR_ON; - } - if ((newstate == SPKR_OFF) && - (sc->spkr_state == SPKR_ON)) { - sbdsp_spkroff(sc); - sc->spkr_state = SPKR_OFF; - } - return(0); -} - -int -sbdsp_round_blocksize(addr, blk) - void *addr; - int blk; -{ - register struct sbdsp_softc *sc = addr; - - sc->sc_last_hsr_size = sc->sc_last_hsw_size = 0; - - /* Higher speeds need bigger blocks to avoid popping and silence gaps. */ - if ((sc->sc_orate > 8000 || sc->sc_irate > 8000) && - (blk > NBPG/2 || blk < NBPG/4)) - blk = NBPG/2; - /* don't try to DMA too much at once, though. */ - if (blk > NBPG) blk = NBPG; - if (sc->sc_chans == 2) - return (blk & ~1); /* must be even to preserve stereo separation */ - else - return(blk); /* Anything goes :-) */ -} - -int -sbdsp_commit_settings(addr) - void *addr; -{ - /* due to potentially unfortunate ordering in the above layers, - re-do a few sets which may be important--input gains - (adjust the proper channels), number of input channels (hit the - record rate and set mode) */ - - register struct sbdsp_softc *sc = addr; - - sbdsp_set_out_sr_real(addr, sc->sc_orate); - sbdsp_set_in_sr_real(addr, sc->sc_irate); - - sc->sc_last_hsw_size = sc->sc_last_hsr_size = 0; - return(0); -} - - -int -sbdsp_open(sc, dev, flags) - register struct sbdsp_softc *sc; - dev_t dev; - int flags; -{ - DPRINTF(("sbdsp_open: sc=0x%x\n", sc)); - - if (sc->sc_open != 0 || sbdsp_reset(sc) != 0) - return ENXIO; - - sc->sc_open = 1; - sc->sc_mintr = 0; - sc->sc_intr = 0; - sc->sc_arg = 0; - sc->sc_locked = 0; - if (ISSBPROCLASS(sc) && - sbdsp_wdsp(sc->sc_iobase, SB_DSP_RECORD_MONO) < 0) { - DPRINTF(("sbdsp_open: can't set mono mode\n")); - /* we'll readjust when it's time for DMA. */ - } - sc->sc_dmain_inprogress = 0; - sc->sc_dmaout_inprogress = 0; - - /* - * Leave most things as they were; users must change things if - * the previous process didn't leave it they way they wanted. - * Looked at another way, it's easy to set up a configuration - * in one program and leave it for another to inherit. - */ - DPRINTF(("sbdsp_open: opened\n")); - - return 0; -} - -void -sbdsp_close(addr) - void *addr; -{ - struct sbdsp_softc *sc = addr; - - DPRINTF(("sbdsp_close: sc=0x%x\n", sc)); - - sc->sc_open = 0; - sbdsp_spkroff(sc); - sc->spkr_state = SPKR_OFF; - sc->sc_intr = 0; - sc->sc_mintr = 0; - /* XXX this will turn off any dma */ - sbdsp_reset(sc); - - DPRINTF(("sbdsp_close: closed\n")); -} - -/* - * Lower-level routines - */ - -/* - * Reset the card. - * Return non-zero if the card isn't detected. - */ -int -sbdsp_reset(sc) - register struct sbdsp_softc *sc; -{ - register u_short iobase = sc->sc_iobase; - - /* - * erase any memory of last transfer size. - */ - sc->sc_last_hsr_size = sc->sc_last_hsw_size = 0; - /* - * See SBK, section 11.3. - * We pulse a reset signal into the card. - * Gee, what a brilliant hardware design. - */ - outb(iobase + SBP_DSP_RESET, 1); - delay(3); - outb(iobase + SBP_DSP_RESET, 0); - if (sbdsp_rdsp(iobase) != SB_MAGIC) - return -1; - return 0; -} - -/* - * Write a byte to the dsp. - * XXX We are at the mercy of the card as we use a - * polling loop and wait until it can take the byte. - */ -int -sbdsp_wdsp(u_short iobase, int v) -{ - register int i; - - for (i = SBDSP_NPOLL; --i >= 0; ) { - if ((inb(iobase + SBP_DSP_WSTAT) & SB_DSP_BUSY) != 0) { - delay(10); continue; - } - outb(iobase + SBP_DSP_WRITE, v); - return 0; - } - ++sberr.wdsp; - return -1; -} - -/* - * Read a byte from the DSP, using polling. - */ -int -sbdsp_rdsp(u_short iobase) -{ - register int i; - - for (i = SBDSP_NPOLL; --i >= 0; ) { - if ((inb(iobase + SBP_DSP_RSTAT) & SB_DSP_READY) == 0) - continue; - return inb(iobase + SBP_DSP_READ); - } - ++sberr.rdsp; - return -1; -} - -/* - * Doing certain things (like toggling the speaker) make - * the SB hardware go away for a while, so pause a little. - */ -void -sbdsp_to(arg) - void *arg; -{ - wakeup(arg); -} - -void -sbdsp_pause(sc) - struct sbdsp_softc *sc; -{ - extern int hz; - - timeout(sbdsp_to, sbdsp_to, hz/8); - (void)tsleep(sbdsp_to, PWAIT, "sbpause", 0); -} - -/* - * Turn on the speaker. The SBK documention says this operation - * can take up to 1/10 of a second. Higher level layers should - * probably let the task sleep for this amount of time after - * calling here. Otherwise, things might not work (because - * sbdsp_wdsp() and sbdsp_rdsp() will probably timeout.) - * - * These engineers had their heads up their ass when - * they designed this card. - */ -void -sbdsp_spkron(sc) - struct sbdsp_softc *sc; -{ - (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_SPKR_ON); - sbdsp_pause(sc); -} - -/* - * Turn off the speaker; see comment above. - */ -void -sbdsp_spkroff(sc) - struct sbdsp_softc *sc; -{ - (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_SPKR_OFF); - sbdsp_pause(sc); -} - -/* - * Read the version number out of the card. Return major code - * in high byte, and minor code in low byte. - */ -short -sbversion(sc) - struct sbdsp_softc *sc; -{ - register u_short iobase = sc->sc_iobase; - short v; - - if (sbdsp_wdsp(iobase, SB_DSP_VERSION) < 0) - return 0; - v = sbdsp_rdsp(iobase) << 8; - v |= sbdsp_rdsp(iobase); - return ((v >= 0) ? v : 0); -} - -/* - * Halt a DMA in progress. A low-speed transfer can be - * resumed with sbdsp_contdma(). - */ -int -sbdsp_haltdma(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - - DPRINTF(("sbdsp_haltdma: sc=0x%x\n", sc)); - - if (sc->sc_locked) - sbdsp_reset(sc); - else - (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_HALT); - - isa_dmaabort(sc->sc_drq); - sc->dmaaddr = 0; - sc->dmacnt = 0; - sc->sc_locked = 0; - sc->dmaflags = 0; - sc->sc_dmain_inprogress = sc->sc_dmaout_inprogress = 0; - return(0); -} - -int -sbdsp_contdma(addr) - void *addr; -{ - register struct sbdsp_softc *sc = addr; - - DPRINTF(("sbdsp_contdma: sc=0x%x\n", sc)); - - /* XXX how do we reinitialize the DMA controller state? do we care? */ - (void)sbdsp_wdsp(sc->sc_iobase, SB_DSP_CONT); - return(0); -} - -/* - * Time constant routines follow. See SBK, section 12. - * Although they don't come out and say it (in the docs), - * the card clearly uses a 1MHz countdown timer, as the - * low-speed formula (p. 12-4) is: - * tc = 256 - 10^6 / sr - * In high-speed mode, the constant is the upper byte of a 16-bit counter, - * and a 256MHz clock is used: - * tc = 65536 - 256 * 10^ 6 / sr - * Since we can only use the upper byte of the HS TC, the two formulae - * are equivalent. (Why didn't they say so?) E.g., - * (65536 - 256 * 10 ^ 6 / x) >> 8 = 256 - 10^6 / x - * - * The crossover point (from low- to high-speed modes) is different - * for the SBPRO and SB20. The table on p. 12-5 gives the following data: - * - * SBPRO SB20 - * ----- -------- - * input ls min 4 KHz 4 KHz - * input ls max 23 KHz 13 KHz - * input hs max 44.1 KHz 15 KHz - * output ls min 4 KHz 4 KHz - * output ls max 23 KHz 23 KHz - * output hs max 44.1 KHz 44.1 KHz - */ -#define SB_LS_MIN 0x06 /* 4000 Hz */ -#define SBPRO_ADC_LS_MAX 0xd4 /* 22727 Hz */ -#define SBPRO_ADC_HS_MAX 0xea /* 45454 Hz */ -#define SBCLA_ADC_LS_MAX 0xb3 /* 12987 Hz */ -#define SBCLA_ADC_HS_MAX 0xbd /* 14925 Hz */ -#define SB_DAC_LS_MAX 0xd4 /* 22727 Hz */ -#define SB_DAC_HS_MAX 0xea /* 45454 Hz */ - -/* - * Convert a linear sampling rate into the DAC time constant. - * Set *mode to indicate the high/low-speed DMA operation. - * Because of limitations of the card, not all rates are possible. - * We return the time constant of the closest possible rate. - * The sampling rate limits are different for the DAC and ADC, - * so isdac indicates output, and !isdac indicates input. - */ -int -sbdsp_srtotc(sc, sr, mode, isdac) - register struct sbdsp_softc *sc; - int sr; - int *mode; - int isdac; -{ - int adc_ls_max, adc_hs_max; - register int tc; - - if (sr == 0) { - *mode = SB_ADAC_LS; - return SB_LS_MIN; - } - tc = 256 - 1000000 / sr; - - /* XXX use better rounding--compare distance to nearest tc on both - sides of requested speed */ - if (ISSBPROCLASS(sc)) { - adc_ls_max = SBPRO_ADC_LS_MAX; - adc_hs_max = SBPRO_ADC_HS_MAX; - } - else { - adc_ls_max = SBCLA_ADC_LS_MAX; - adc_hs_max = SBCLA_ADC_HS_MAX; - } - - if (tc < SB_LS_MIN) { - tc = SB_LS_MIN; - *mode = SB_ADAC_LS; - } else if (isdac) { - if (tc <= SB_DAC_LS_MAX) - *mode = SB_ADAC_LS; - else { - *mode = SB_ADAC_HS; - if (tc > SB_DAC_HS_MAX) - tc = SB_DAC_HS_MAX; - } - } else { - if (tc <= adc_ls_max) - *mode = SB_ADAC_LS; - else { - *mode = SB_ADAC_HS; - if (tc > adc_hs_max) - tc = adc_hs_max; - } - } - return tc; -} - -/* - * Convert a DAC time constant to a sampling rate. - * See SBK, section 12. - */ -int -sbdsp_tctosr(sc, tc) - register struct sbdsp_softc *sc; - int tc; -{ - int adc; - - if (ISSBPROCLASS(sc)) - adc = SBPRO_ADC_HS_MAX; - else - adc = SBCLA_ADC_HS_MAX; - - if (tc > adc) - tc = adc; - - return (1000000 / (256 - tc)); -} - -int -sbdsp_set_sr(sc, srp, isdac) - register struct sbdsp_softc *sc; - u_long *srp; - int isdac; -{ - register int tc; - int mode; - int sr = *srp; - register u_short iobase; - - /* - * A SBPro in stereo mode uses time constants at double the - * actual rate. - */ - if (ISSBPRO(sc) && sc->sc_chans == 2) { - if (sr > 22727) - sr = 22727; /* Can't bounce it...order of - operations may yield bogus - sr here. */ - sr *= 2; - } - else if (!ISSBPROCLASS(sc) && sc->sc_chans != 1) - return EINVAL; - - tc = sbdsp_srtotc(sc, sr, &mode, isdac); - DPRINTF(("sbdsp_set_sr: sc=0x%x sr=%d mode=0x%x\n", sc, sr, mode)); - - iobase = sc->sc_iobase; - if (sbdsp_wdsp(iobase, SB_DSP_TIMECONST) < 0 || - sbdsp_wdsp(iobase, tc) < 0) - return EIO; - - sr = sbdsp_tctosr(sc, tc); - if (ISSBPRO(sc) && sc->sc_chans == 2) - *srp = sr / 2; - else - *srp = sr; - - sc->sc_adacmode = mode; - sc->sc_adactc = tc; - return 0; -} - -int -sbdsp_dma_input(addr, p, cc, intr, arg) - void *addr; - void *p; - int cc; - void (*intr)(); - void *arg; -{ - register struct sbdsp_softc *sc = addr; - register u_short iobase; - u_int phys; - -#ifdef DEBUG - if (sbdspdebug > 1) - Dprintf("sbdsp_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg); -#endif - if (sc->sc_chans == 2 && (cc & 1)) { - DPRINTF(("sbdsp_dma_input: stereo input, odd bytecnt\n")); - return EIO; - } - iobase = sc->sc_iobase; - if (ISSBPROCLASS(sc) && !sc->sc_dmain_inprogress) { - if (sc->sc_chans == 2) { - if (sbdsp_wdsp(iobase, SB_DSP_RECORD_STEREO) < 0) - goto badmode; - sbdsp_mix_write(sc, SBP_STEREO, - sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK); - sbdsp_mix_write(sc, SBP_INFILTER, - sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF); - } - else { - if (sbdsp_wdsp(iobase, SB_DSP_RECORD_MONO) < 0) - goto badmode; - sbdsp_mix_write(sc, SBP_STEREO, - sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK); - sbdsp_mix_write(sc, SBP_INFILTER, - sc->sc_irate <= 8000 ? - sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_FILTER_MASK : - sbdsp_mix_read(sc, SBP_INFILTER) | SBP_FILTER_OFF); - } - sc->sc_dmain_inprogress = 1; - sc->sc_last_hsr_size = 0; /* restarting */ - } - sc->sc_dmaout_inprogress = 0; - - at_dma(B_READ, p, cc, sc->sc_drq); - sc->sc_intr = intr; - sc->sc_arg = arg; - sc->dmaflags = B_READ; - sc->dmaaddr = p; - sc->dmacnt = --cc; /* DMA controller is strange...? */ - if (sc->sc_adacmode == SB_ADAC_LS) { - if (sbdsp_wdsp(iobase, SB_DSP_RDMA) < 0 || - sbdsp_wdsp(iobase, cc) < 0 || - sbdsp_wdsp(iobase, cc >> 8) < 0) { - goto giveup; - } - } - else { - if (cc != sc->sc_last_hsr_size) { - if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0 || - sbdsp_wdsp(iobase, cc) < 0 || - sbdsp_wdsp(iobase, cc >> 8) < 0) - goto giveup; - } - if (sbdsp_wdsp(iobase, SB_DSP_HS_INPUT) < 0) - goto giveup; - sc->sc_last_hsr_size = cc; - sc->sc_locked = 1; - } - return 0; - -giveup: - isa_dmaabort(sc->sc_drq); - sbdsp_reset(sc); - sc->sc_intr = 0; - sc->sc_arg = 0; - return EIO; -badmode: - DPRINTF(("sbdsp_dma_input: can't set %s mode\n", - sc->sc_chans == 2 ? "stereo" : "mono")); - return EIO; -} - -int -sbdsp_dma_output(addr, p, cc, intr, arg) - void *addr; - void *p; - int cc; - void (*intr)(); - void *arg; -{ - register struct sbdsp_softc *sc = addr; - register u_short iobase; - -#ifdef DEBUG - if (sbdspdebug > 1) - Dprintf("sbdsp_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg); -#endif - if (sc->sc_chans == 2 && cc & 1) { - DPRINTF(("stereo playback odd bytes (%d)\n", cc)); - return EIO; - } - - if (ISSBPROCLASS(sc) && !sc->sc_dmaout_inprogress) { - /* make sure we re-set stereo mixer bit when we start - output. */ - sbdsp_mix_write(sc, SBP_STEREO, - (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) | - (sc->sc_chans == 2 ? - SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO)); - sc->sc_dmaout_inprogress = 1; - sc->sc_last_hsw_size = 0; /* restarting */ - } - sc->sc_dmain_inprogress = 0; - at_dma(B_WRITE, p, cc, sc->sc_drq); - sc->sc_intr = intr; - sc->sc_arg = arg; - sc->dmaflags = B_WRITE; - sc->dmaaddr = p; - sc->dmacnt = --cc; /* a vagary of how DMA works, apparently. */ - - iobase = sc->sc_iobase; - if (sc->sc_adacmode == SB_ADAC_LS) { - if (sbdsp_wdsp(iobase, SB_DSP_WDMA) < 0 || - sbdsp_wdsp(iobase, cc) < 0 || - sbdsp_wdsp(iobase, cc >> 8) < 0) { - DPRINTF(("sbdsp_dma_output: LS DMA start failed\n")); - goto giveup; - } - } - else { - if (cc != sc->sc_last_hsw_size) { - if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0) { - /* sometimes fails initial startup?? */ - delay(100); - if (sbdsp_wdsp(iobase, SB_DSP_BLOCKSIZE) < 0) { - DPRINTF(("sbdsp_dma_output: BLOCKSIZE failed\n")); - goto giveup; - } - } - if (sbdsp_wdsp(iobase, cc) < 0 || - sbdsp_wdsp(iobase, cc >> 8) < 0) { - DPRINTF(("sbdsp_dma_output: HS DMA start failed\n")); - goto giveup; - } - sc->sc_last_hsw_size = cc; - } - if (sbdsp_wdsp(iobase, SB_DSP_HS_OUTPUT) < 0) { - delay(100); - if (sbdsp_wdsp(iobase, SB_DSP_HS_OUTPUT) < 0) { - DPRINTF(("sbdsp_dma_output: HS DMA restart failed\n")); - goto giveup; - } - } - sc->sc_locked = 1; - } - - return 0; - - giveup: - isa_dmaabort(sc->sc_drq); - sbdsp_reset(sc); - sc->sc_intr = 0; - sc->sc_arg = 0; - return EIO; -} - -/* - * Only the DSP unit on the sound blaster generates interrupts. - * There are three cases of interrupt: reception of a midi byte - * (when mode is enabled), completion of dma transmission, or - * completion of a dma reception. The three modes are mutually - * exclusive so we know a priori which event has occurred. - */ -int -sbdsp_intr(arg) - void *arg; -{ - register struct sbdsp_softc *sc = arg; - -#ifdef DEBUG - if (sbdspdebug > 1) - Dprintf("sbdsp_intr: intr=0x%x\n", sc->sc_intr); -#endif - sc->sc_interrupts++; - sc->sc_locked = 0; - /* clear interrupt */ - inb(sc->sc_iobase + SBP_DSP_RSTAT); -#if 0 - if (sc->sc_mintr != 0) { - int c = sbdsp_rdsp(sc->sc_iobase); - (*sc->sc_mintr)(sc->sc_arg, c); - } else -#endif - if (sc->sc_intr != 0) { - /* - * The SBPro used to develop and test this driver often - * generated dma underruns--it interrupted to signal - * completion of the DMA input recording block, but the - * ISA DMA controller didn't think the channel was - * finished. Maybe this is just a bus speed issue, I dunno, - * but it seems strange and leads to channel-flipping with stereo - * recording. Sigh. - */ - isa_dmadone(sc->dmaflags, sc->dmaaddr, sc->dmacnt, - sc->sc_drq); - sc->dmaflags = 0; - sc->dmaaddr = 0; - sc->dmacnt = 0; - (*sc->sc_intr)(sc->sc_arg); - } - else - return 0; - return 1; -} - -#if 0 -/* - * Enter midi uart mode and arrange for read interrupts - * to vector to `intr'. This puts the card in a mode - * which allows only midi I/O; the card must be reset - * to leave this mode. Unfortunately, the card does not - * use transmit interrupts, so bytes must be output - * using polling. To keep the polling overhead to a - * minimum, output should be driven off a timer. - * This is a little tricky since only 320us separate - * consecutive midi bytes. - */ -void -sbdsp_set_midi_mode(sc, intr, arg) - struct sbdsp_softc *sc; - void (*intr)(); - void *arg; -{ - - sbdsp_wdsp(sc->sc_iobase, SB_MIDI_UART_INTR); - sc->sc_mintr = intr; - sc->sc_intr = 0; - sc->sc_arg = arg; -} - -/* - * Write a byte to the midi port, when in midi uart mode. - */ -void -sbdsp_midi_output(sc, v) - struct sbdsp_softc *sc; - int v; -{ - - if (sbdsp_wdsp(sc->sc_iobase, v) < 0) - ++sberr.wmidi; -} -#endif - -u_int -sbdsp_get_silence(enc) - int enc; -{ -#define ULAW_SILENCE 0x7f -#define LINEAR_SILENCE 0 - u_int auzero; - - switch (enc) { - case AUDIO_ENCODING_ULAW: - auzero = ULAW_SILENCE; - break; - case AUDIO_ENCODING_PCM16: - default: - auzero = LINEAR_SILENCE; - break; - } - - return(auzero); -} - -static u_char mulawtolin[256] = { - 128, 4, 8, 12, 16, 20, 24, 28, - 32, 36, 40, 44, 48, 52, 56, 60, - 64, 66, 68, 70, 72, 74, 76, 78, - 80, 82, 84, 86, 88, 90, 92, 94, - 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, - 112, 112, 113, 113, 114, 114, 115, 115, - 116, 116, 117, 117, 118, 118, 119, 119, - 120, 120, 120, 121, 121, 121, 121, 122, - 122, 122, 122, 123, 123, 123, 123, 124, - 124, 124, 124, 124, 125, 125, 125, 125, - 125, 125, 125, 125, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, - 255, 251, 247, 243, 239, 235, 231, 227, - 223, 219, 215, 211, 207, 203, 199, 195, - 191, 189, 187, 185, 183, 181, 179, 177, - 175, 173, 171, 169, 167, 165, 163, 161, - 159, 158, 157, 156, 155, 154, 153, 152, - 151, 150, 149, 148, 147, 146, 145, 144, - 143, 143, 142, 142, 141, 141, 140, 140, - 139, 139, 138, 138, 137, 137, 136, 136, - 135, 135, 135, 134, 134, 134, 134, 133, - 133, 133, 133, 132, 132, 132, 132, 131, - 131, 131, 131, 131, 130, 130, 130, 130, - 130, 130, 130, 130, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 129, 129, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 128, 128, 128, 128, 128, -}; - -static u_char lintomulaw[256] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 2, 2, 2, 2, 3, 3, 3, - 3, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, - 7, 8, 8, 8, 8, 9, 9, 9, - 9, 10, 10, 10, 10, 11, 11, 11, - 11, 12, 12, 12, 12, 13, 13, 13, - 13, 14, 14, 14, 14, 15, 15, 15, - 15, 16, 16, 17, 17, 18, 18, 19, - 19, 20, 20, 21, 21, 22, 22, 23, - 23, 24, 24, 25, 25, 26, 26, 27, - 27, 28, 28, 29, 29, 30, 30, 31, - 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 50, 52, 54, 56, 58, 60, - 62, 65, 69, 73, 77, 83, 91, 103, - 255, 231, 219, 211, 205, 201, 197, 193, - 190, 188, 186, 184, 182, 180, 178, 176, - 175, 174, 173, 172, 171, 170, 169, 168, - 167, 166, 165, 164, 163, 162, 161, 160, - 159, 159, 158, 158, 157, 157, 156, 156, - 155, 155, 154, 154, 153, 153, 152, 152, - 151, 151, 150, 150, 149, 149, 148, 148, - 147, 147, 146, 146, 145, 145, 144, 144, - 143, 143, 143, 143, 142, 142, 142, 142, - 141, 141, 141, 141, 140, 140, 140, 140, - 139, 139, 139, 139, 138, 138, 138, 138, - 137, 137, 137, 137, 136, 136, 136, 136, - 135, 135, 135, 135, 134, 134, 134, 134, - 133, 133, 133, 133, 132, 132, 132, 132, - 131, 131, 131, 131, 130, 130, 130, 130, - 129, 129, 129, 129, 128, 128, 128, 128, -}; - -void -sbdsp_compress(e, p, cc) - int e; - u_char *p; - int cc; -{ - u_char *tab; - - switch (e) { - case AUDIO_ENCODING_ULAW: - tab = lintomulaw; - break; - default: - return; - } - - while (--cc >= 0) { - *p = tab[*p]; - ++p; - } -} - -void -sbdsp_expand(e, p, cc) - int e; - u_char *p; - int cc; -{ - u_char *tab; - - switch (e) { - case AUDIO_ENCODING_ULAW: - tab = mulawtolin; - break; - default: - return; - } - - while (--cc >= 0) { - *p = tab[*p]; - ++p; - } -} - -int -sbdsp_setfd(addr, flag) - void *addr; - int flag; -{ - /* Can't do full-duplex */ - return(ENOTTY); -} - -int -sbdsp_mixer_set_port(addr, cp) - void *addr; - mixer_ctrl_t *cp; -{ - register struct sbdsp_softc *sc = addr; - int error = 0; - int src, gain; - int left, right; - - DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev, cp->un.value.num_channels)); - - /* - * Everything is a value except for SBPro special OUTPUT_MODE and - * RECORD_SOURCE - */ - if (cp->type != AUDIO_MIXER_VALUE) { - if (!ISSBPROCLASS(sc) || (cp->dev != SB_OUTPUT_MODE && - cp->dev != SB_RECORD_SOURCE)) - return EINVAL; - } - else { - /* - * All the mixer ports are stereo except for the microphone. - * If we get a single-channel gain value passed in, then we - * duplicate it to both left and right channels. - */ - if (cp->un.value.num_channels == 2) { - left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; - right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; - } - else - left = right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; - } - - if (ISSBPROCLASS(sc)) { - /* The _PORT things are all signal inputs to the mixer. - * Here we are tweaking their mixing level. - * - * We can also tweak the output stage volume (MASTER_VOL) - */ - gain = sbdsp_stereo_vol(SBP_AGAIN_TO_SBGAIN(left), - SBP_AGAIN_TO_SBGAIN(right)); - switch(cp->dev) { - case SB_MIC_PORT: - src = SBP_MIC_VOL; - if (cp->un.value.num_channels != 1) - error = EINVAL; - else - /* handle funny microphone gain */ - gain = SBP_AGAIN_TO_MICGAIN(left); - break; - case SB_LINE_IN_PORT: - src = SBP_LINE_VOL; - break; - case SB_DAC_PORT: - src = SBP_DAC_VOL; - break; - case SB_FM_PORT: - src = SBP_FM_VOL; - break; - case SB_CD_PORT: - src = SBP_CD_VOL; - break; - case SB_SPEAKER: - cp->dev = SB_MASTER_VOL; - case SB_MASTER_VOL: - src = SBP_MASTER_VOL; - break; -#if 0 - case SB_OUTPUT_MODE: - if (cp->type == AUDIO_MIXER_ENUM) - return sbdsp_set_channels(addr, cp->un.ord); - /* fall through...carefully! */ -#endif - case SB_RECORD_SOURCE: - if (cp->type == AUDIO_MIXER_ENUM) - return sbdsp_set_in_port(addr, cp->un.ord); - /* else fall through: bad input */ - case SB_TREBLE: - case SB_BASS: - default: - error = EINVAL; - break; - } - if (!error) - sbdsp_mix_write(sc, src, gain); - } - else if (cp->dev != SB_MIC_PORT && - cp->dev != SB_SPEAKER) - error = EINVAL; - - if (!error) - sc->gain[cp->dev] = gain; - - return(error); -} - -int -sbdsp_mixer_get_port(addr, cp) - void *addr; - mixer_ctrl_t *cp; -{ - register struct sbdsp_softc *sc = addr; - int error = 0; - int done = 0; - - DPRINTF(("sbdsp_mixer_get_port: port=%d", cp->dev)); - - if (ISSBPROCLASS(sc)) - switch(cp->dev) { - case SB_MIC_PORT: - if (cp->un.value.num_channels == 1) { - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = - SBP_MICGAIN_TO_AGAIN(sc->gain[cp->dev]); - return 0; - } - else - return EINVAL; - break; - case SB_LINE_IN_PORT: - case SB_DAC_PORT: - case SB_FM_PORT: - case SB_CD_PORT: - case SB_MASTER_VOL: - break; - case SB_SPEAKER: - cp->dev = SB_MASTER_VOL; - break; - default: - error = EINVAL; - break; - } - else { - if (cp->un.value.num_channels != 1) /* no stereo on SB classic */ - error = EINVAL; - else - switch(cp->dev) { - case SB_MIC_PORT: - break; - case SB_SPEAKER: - break; - default: - error = EINVAL; - break; - } - } - if (error == 0) { - if (cp->un.value.num_channels == 1) { - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = - SBP_SBGAIN_TO_AGAIN(sc->gain[cp->dev]); - } - else if (cp->un.value.num_channels == 2) { - cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = - SBP_LEFTGAIN(sc->gain[cp->dev]); - cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = - SBP_RIGHTGAIN(sc->gain[cp->dev]); - } else - return EINVAL; - } - return(error); -} - -int -sbdsp_mixer_query_devinfo(addr, dip) - void *addr; - register mixer_devinfo_t *dip; -{ - register struct sbdsp_softc *sc = addr; - int done = 0; - - DPRINTF(("sbdsp_mixer_query_devinfo: index=%d\n", dip->index)); - - switch (dip->index) { - case SB_MIC_PORT: - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = SB_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNmicrophone); - dip->un.v.num_channels = 1; - strcpy(dip->un.v.units.name, AudioNvolume); - done = 1; - break; - case SB_SPEAKER: - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = SB_OUTPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNspeaker); - dip->un.v.num_channels = 1; - strcpy(dip->un.v.units.name, AudioNvolume); - done = 1; - break; - case SB_INPUT_CLASS: - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = SB_INPUT_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioCInputs); - done = 1; - break; - case SB_OUTPUT_CLASS: - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = SB_OUTPUT_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioCOutputs); - done = 1; - break; - } - - if (!done) { - if (ISSBPROCLASS(sc)) - switch(dip->index) { - case SB_LINE_IN_PORT: - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = SB_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNline); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - case SB_DAC_PORT: - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = SB_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNdac); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - case SB_CD_PORT: - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = SB_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNcd); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - case SB_FM_PORT: - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = SB_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, "fmsynth"); /* XXX move to audioio.h */ - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - case SB_MASTER_VOL: - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = SB_OUTPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = SB_OUTPUT_MODE; - strcpy(dip->label.name, AudioNvolume); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; -#if 0 - case SB_OUTPUT_MODE: - dip->mixer_class = SB_OUTPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = SB_MASTER_VOL; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNmode); - dip->un.e.num_mem = 2; - strcpy(dip->un.e.member[0].label.name, AudioNmono); - dip->un.e.member[0].ord = 1; /* nchans */ - strcpy(dip->un.e.member[1].label.name, AudioNstereo); - dip->un.e.member[1].ord = 2; /* nchans */ - break; -#endif - case SB_RECORD_SOURCE: - dip->mixer_class = SB_RECORD_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = AUDIO_MIXER_LAST; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNsource); - dip->un.e.num_mem = 3; - strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); - dip->un.e.member[0].ord = SB_MIC_PORT; - strcpy(dip->un.e.member[1].label.name, AudioNcd); - dip->un.e.member[1].ord = SB_CD_PORT; - strcpy(dip->un.e.member[2].label.name, AudioNline); - dip->un.e.member[2].ord = SB_LINE_IN_PORT; - break; - case SB_BASS: - case SB_TREBLE: - default: - return ENXIO; - /*NOTREACHED*/ - } - else - return ENXIO; - } - - DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); - - return 0; -} diff --git a/sys/arch/i386/isa/sbdspvar.h b/sys/arch/i386/isa/sbdspvar.h deleted file mode 100644 index dc16d9e049bb..000000000000 --- a/sys/arch/i386/isa/sbdspvar.h +++ /dev/null @@ -1,200 +0,0 @@ -/* $NetBSD: sbdspvar.h,v 1.5 1995/04/17 12:07:44 cgd Exp $ */ - -/* - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sbdspvar.h,v 1.5 1995/04/17 12:07:44 cgd Exp $ - */ - -#define SB_MIC_PORT 0 -#define SB_SPEAKER 1 -#define SB_LINE_IN_PORT 2 -#define SB_DAC_PORT 3 -#define SB_FM_PORT 4 -#define SB_CD_PORT 5 -#define SB_MASTER_VOL 6 -#define SB_TREBLE 7 -#define SB_BASS 8 -#define SB_NDEVS 9 - -#define SB_OUTPUT_MODE 9 -#define SB_SPKR_MONO 0 -#define SB_SPKR_STEREO 1 - -#define SB_RECORD_SOURCE 10 - -#define SB_INPUT_CLASS 11 -#define SB_OUTPUT_CLASS 12 -#define SB_RECORD_CLASS 13 - - -/* - * Software state, per SoundBlaster card. - * The soundblaster has multiple functionality, which we must demultiplex. - * One approach is to have one major device number for the soundblaster card, - * and use different minor numbers to indicate which hardware function - * we want. This would make for one large driver. Instead our approach - * is to partition the design into a set of drivers that share an underlying - * piece of hardware. Most things are hard to share, for example, the audio - * and midi ports. For audio, we might want to mix two processes' signals, - * and for midi we might want to merge streams (this is hard due to - * running status). Moreover, we should be able to re-use the high-level - * modules with other kinds of hardware. In this module, we only handle the - * most basic communications with the sb card. - */ -struct sbdsp_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - u_short sc_iobase; /* I/O port base address */ - u_short sc_irq; /* interrupt */ - u_short sc_drq; /* DMA */ - - u_short sc_open; /* reference count of open calls */ - u_short sc_locked; /* true when doing HS DMA */ - u_short sc_adacmode; /* low/high speed mode indicator */ - - u_long sc_irate; /* Sample rate for input */ - u_long sc_orate; /* ...and output */ - - u_int gain[SB_NDEVS]; /* kept in SB levels: right/left each - in a nibble */ - - u_int encoding; /* ulaw/linear -- keep track */ - - u_int out_port; /* output port */ - u_int in_port; /* input port */ - - u_int spkr_state; /* non-null is on */ - -#define SB_ADAC_LS 0 -#define SB_ADAC_HS 1 - u_short sc_adactc; /* current adac time constant */ - u_long sc_interrupts; /* number of interrupts taken */ - void (*sc_intr)(void*); /* dma completion intr handler */ - void (*sc_mintr)(void*, int);/* midi input intr handler */ - void *sc_arg; /* arg for sc_intr() */ - - int dmaflags; - caddr_t dmaaddr; - vm_size_t dmacnt; - int sc_last_hsw_size; /* last HS dma size */ - int sc_last_hsr_size; /* last HS dma size */ - int sc_chans; /* # of channels */ - char sc_dmain_inprogress; /* DMA input in progress? */ - char sc_dmaout_inprogress; /* DMA output in progress? */ - - u_int sc_model; /* DSP model */ -#define SBVER_MAJOR(v) ((v)>>8) -#define SBVER_MINOR(v) ((v)&0xff) -}; - -#define ISSBPRO(sc) \ - (SBVER_MAJOR((sc)->sc_model) == 3) - -#define ISSBPROCLASS(sc) \ - (SBVER_MAJOR((sc)->sc_model) > 2) - -#define ISSB16CLASS(sc) \ - (SBVER_MAJOR((sc)->sc_model) > 3) - - -#ifdef _KERNEL -int sbdsp_open __P((struct sbdsp_softc *, dev_t, int)); -void sbdsp_close __P((void *)); - -int sbdsp_probe __P((struct sbdsp_softc *)); -void sbdsp_attach __P((struct sbdsp_softc *)); - -int sbdsp_set_in_gain __P((void *, u_int, u_char)); -int sbdsp_set_in_gain_real __P((void *, u_int, u_char)); -int sbdsp_get_in_gain __P((void *)); -int sbdsp_set_out_gain __P((void *, u_int, u_char)); -int sbdsp_set_out_gain_real __P((void *, u_int, u_char)); -int sbdsp_get_out_gain __P((void *)); -int sbdsp_set_monitor_gain __P((void *, u_int)); -int sbdsp_get_monitor_gain __P((void *)); -int sbdsp_set_in_sr __P((void *, u_long)); -int sbdsp_set_in_sr_real __P((void *, u_long)); -u_long sbdsp_get_in_sr __P((void *)); -int sbdsp_set_out_sr __P((void *, u_long)); -int sbdsp_set_out_sr_real __P((void *, u_long)); -u_long sbdsp_get_out_sr __P((void *)); -int sbdsp_query_encoding __P((void *, struct audio_encoding *)); -int sbdsp_set_encoding __P((void *, u_int)); -int sbdsp_get_encoding __P((void *)); -int sbdsp_set_precision __P((void *, u_int)); -int sbdsp_get_precision __P((void *)); -int sbdsp_set_channels __P((void *, int)); -int sbdsp_get_channels __P((void *)); -int sbdsp_round_blocksize __P((void *, int)); -int sbdsp_set_out_port __P((void *, int)); -int sbdsp_get_out_port __P((void *)); -int sbdsp_set_in_port __P((void *, int)); -int sbdsp_get_in_port __P((void *)); -int sbdsp_get_avail_in_ports __P((void *)); -int sbdsp_get_avail_out_ports __P((void *)); -int sbdsp_speaker_ctl __P((void *, int)); -int sbdsp_commit_settings __P((void *)); - -int sbdsp_dma_output __P((void *, void *, int, void (*)(), void*)); -int sbdsp_dma_input __P((void *, void *, int, void (*)(), void*)); - -int sbdsp_haltdma __P((void *)); -int sbdsp_contdma __P((void *)); - -u_int sbdsp_get_silence __P((int)); -void sbdsp_compress __P((int, u_char *, int)); -void sbdsp_expand __P((int, u_char *, int)); - -int sbdsp_reset __P((struct sbdsp_softc *)); -void sbdsp_spkron __P((struct sbdsp_softc *)); -void sbdsp_spkroff __P((struct sbdsp_softc *)); - -int sbdsp_wdsp(u_short iobase, int v); -int sbdsp_rdsp(u_short iobase); - -int sbdsp_intr __P((void *)); -short sbversion __P((struct sbdsp_softc *)); - -int sbdsp_set_sr __P((struct sbdsp_softc *, u_long *, int)); -int sbdsp_setfd __P((void *, int)); - -void sbdsp_mix_write __P((struct sbdsp_softc *, int, int)); -int sbdsp_mix_read __P((struct sbdsp_softc *, int)); - -int sbdsp_mixer_set_port __P((void *, mixer_ctrl_t *)); -int sbdsp_mixer_get_port __P((void *, mixer_ctrl_t *)); -int sbdsp_mixer_query_devinfo __P((void *, mixer_devinfo_t *)); - -#endif diff --git a/sys/arch/i386/isa/sbreg.h b/sys/arch/i386/isa/sbreg.h deleted file mode 100644 index a48795ccc947..000000000000 --- a/sys/arch/i386/isa/sbreg.h +++ /dev/null @@ -1,191 +0,0 @@ -/* $NetBSD: sbreg.h,v 1.11 1995/03/15 16:43:13 glass Exp $ */ - -/* - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * From: Header: sbreg.h,v 1.3 93/07/18 14:07:28 mccanne Exp (LBL) - * $Id: sbreg.h,v 1.11 1995/03/15 16:43:13 glass Exp $ - */ - -/* - * SoundBlaster register definitions. - * See "The Developer Kit for Sound Blaster Series, User's Guide" for more - * complete information (avialable from Creative Labs, Inc.). We refer - * to this documentation as "SBK". - * - * We handle two types of cards: the basic SB version 2.0+, and - * the SB PRO. There are several distinct pieces of the hardware: - * - * joystick port (independent of I/O base address) - * FM synth (stereo on PRO) - * mixer (PRO only) - * DSP (sic) - * CD-ROM (PRO only) - * - * The MIDI capabilities are handled by the DSP unit. - */ - -/* - * Address map. The SoundBlaster can be configured (via jumpers) for - * either base I/O address 0x220 or 0x240. The encodings below give - * the offsets to specific SB ports. SBP stands for SB port offset. - */ -#define SBP_LFM_STATUS 0 /* R left FM status port */ -#define SBP_LFM_ADDR 0 /* W left FM address register */ -#define SBP_LFM_DATA 1 /* RW left FM data port */ -#define SBP_RFM_STATUS 2 /* R right FM status port */ -#define SBP_RFM_ADDR 2 /* W right FM address register */ -#define SBP_RFM_DATA 3 /* RW right FM data port */ - -#define SBP_FM_STATUS 8 /* R FM status port */ -#define SBP_FM_ADDR 8 /* W FM address register */ -#define SBP_FM_DATA 9 /* RW FM data port */ -#define SBP_MIXER_ADDR 4 /* W mixer address register */ -#define SBP_MIXER_DATA 5 /* RW mixer data port */ -#define SBP_MIX_RESET 0 /* mixer reset port, value */ -#define SBP_MASTER_VOL 0x22 -#define SBP_FM_VOL 0x26 -#define SBP_CD_VOL 0x28 -#define SBP_LINE_VOL 0x2E -#define SBP_DAC_VOL 0x04 -#define SBP_MIC_VOL 0x0A /* warning: only one channel of - volume... */ -#define SBP_SPEAKER_VOL 0x42 -#define SBP_TREBLE_EQ 0x44 -#define SBP_BASS_EQ 0x46 - -#define SBP_SET_IRQ 0x80 /* Soft-configured irq (SB16-) */ -#define SBP_SET_DRQ 0x81 /* Soft-configured drq (SB16-) */ - -#define SBP_RECORD_SOURCE 0x0C -#define SBP_STEREO 0x0E -#define SBP_PLAYMODE_STEREO 0x2 -#define SBP_PLAYMODE_MONO 0x0 -#define SBP_PLAYMODE_MASK 0x2 -#define SBP_OUTFILTER 0x0E -#define SBP_INFILTER 0x0C - -#define SBP_RECORD_FROM(src, filteron, high) ((src) | (filteron) | (high)) -#define SBP_FILTER_ON 0x0 -#define SBP_FILTER_OFF 0x20 -#define SBP_FILTER_MASK 0x20 -#define SBP_FILTER_LOW 0 -#define SBP_FILTER_HIGH 0x08 -#define SBP_FROM_MIC 0x00 -#define SBP_FROM_CD 0x02 -#define SBP_FROM_LINE 0x06 -#define sbdsp_stereo_vol(left, right) (((left) << 4) | (right)) -#define SBP_MAXVOL 0xf /* per channel */ -#define SBP_MINVOL 0x0 /* per channel */ -#define SBP_AGAIN_TO_SBGAIN(again) ((again) >> 4) /* per channel */ -#define SBP_AGAIN_TO_MICGAIN(again) ((again) >> 5) /* mic has only 3 bits, - sorry! */ -#define SBP_LEFTGAIN(sbgain) (sbgain & 0xf0) /* left channel */ -#define SBP_RIGHTGAIN(sbgain) ((sbgain & 0xf) << 4) /* right channel */ -#define SBP_SBGAIN_TO_AGAIN(sbgain) SBP_LEFTGAIN(sbgain) -#define SBP_MICGAIN_TO_AGAIN(micgain) (micgain << 5) -#define SBP_DSP_RESET 6 /* W reset port */ -#define SB_MAGIC 0xaa /* card outputs on successful reset */ -#define SBP_DSP_READ 10 /* R read port */ -#define SBP_DSP_WRITE 12 /* W write port */ -#define SBP_DSP_WSTAT 12 /* R write status */ -#define SBP_DSP_RSTAT 14 /* R read status */ -#define SB_DSP_BUSY 0x80 -#define SB_DSP_READY 0x80 -#define SBP_CDROM_DATA 16 /* RW send cmds/recv data */ -#define SBP_CDROM_STATUS 17 /* R status port */ -#define SBP_CDROM_RESET 18 /* W reset register */ -#define SBP_CDROM_ENABLE 19 /* W enable register */ - -#define SBP_NPORT 24 -#define SB_NPORT 16 - -/* - * DSP commands. This unit handles MIDI and audio capabilities. - * The DSP can be reset, data/commands can be read or written to it, - * and it can generate interrupts. Interrupts are generated for MIDI - * input or DMA completion. They seem to have neglected the fact - * that it would be nice to have a MIDI transmission complete interrupt. - * Worse, the DMA engine is half-duplex. This means you need to do - * (timed) programmed I/O to be able to record and play simulataneously. - */ -#define SB_DSP_DACWRITE 0x10 /* programmed I/O write to DAC */ -#define SB_DSP_WDMA 0x14 /* begin 8-bit linear DMA output */ -#define SB_DSP_WDMA_2 0x16 /* begin 2-bit ADPCM DMA output */ -#define SB_DSP_ADCREAD 0x20 /* programmed I/O read from ADC */ -#define SB_DSP_RDMA 0x24 /* begin 8-bit linear DMA input */ -#define SB_MIDI_POLL 0x30 /* initiate a polling read for MIDI */ -#define SB_MIDI_READ 0x31 /* read a MIDI byte on recv intr */ -#define SB_MIDI_UART_POLL 0x34 /* enter UART mode w/ read polling */ -#define SB_MIDI_UART_INTR 0x35 /* enter UART mode w/ read intrs */ -#define SB_MIDI_WRITE 0x38 /* write a MIDI byte (non-UART mode) */ -#define SB_DSP_TIMECONST 0x40 /* set ADAC time constant */ -#define SB_DSP_BLOCKSIZE 0x48 /* set blk size for high speed xfer */ -#define SB_DSP_WDMA_4 0x74 /* begin 4-bit ADPCM DMA output */ -#define SB_DSP_WDMA_2_6 0x76 /* begin 2.6-bit ADPCM DMA output */ -#define SB_DSP_SILENCE 0x80 /* send a block of silence */ -#define SB_DSP_HS_OUTPUT 0x91 /* set high speed mode for wdma */ -#define SB_DSP_HS_INPUT 0x99 /* set high speed mode for rdma */ -#define SB_DSP_RECORD_MONO 0xA0 /* set mono recording */ -#define SB_DSP_RECORD_STEREO 0xA8 /* set stereo recording */ -#define SB_DSP_HALT 0xd0 /* temporarilty suspend DMA */ -#define SB_DSP_SPKR_ON 0xd1 /* turn speaker on */ -#define SB_DSP_SPKR_OFF 0xd3 /* turn speaker off */ -#define SB_DSP_CONT 0xd4 /* continue suspended DMA */ -#define SB_DSP_RD_SPKR 0xd8 /* get speaker status */ -#define SB_SPKR_OFF 0x00 -#define SB_SPKR_ON 0xff -#define SB_DSP_VERSION 0xe1 /* get version number */ - -/* - * The ADPCM encodings are differential, meaning each sample represents - * a difference to add to a running sum. The inital value is called the - * reference, or reference byte. Any of the ADPCM DMA transfers can specify - * that the given transfer begins with a reference byte by or'ing - * in the bit below. - */ -#define SB_DSP_REFERENCE 1 - -/* - * Macros to detect valid hardware configuration data. - */ -#define SBP_IRQ_VALID(irq) ((irq) == 5 || (irq) == 7 || (irq) == 9 || (irq) == 10) -#define SB_IRQ_VALID(irq) ((irq) == 3 || (irq) == 5 || (irq) == 7 || (irq) == 9) - -#define SBP_DRQ_VALID(chan) ((chan) == 0 || (chan) == 1 || (chan) == 3) -#define SB_DRQ_VALID(chan) ((chan) == 1) - -#define SB_BASE_VALID(base) ((base) == 0x220 || (base) == 0x240) - -#define SB_INPUT_RATE 0 -#define SB_OUTPUT_RATE 1 - diff --git a/sys/arch/i386/isa/wss.c b/sys/arch/i386/isa/wss.c deleted file mode 100644 index 3fcd3b3491fe..000000000000 --- a/sys/arch/i386/isa/wss.c +++ /dev/null @@ -1,717 +0,0 @@ -/* $NetBSD: wss.c,v 1.3 1995/04/17 12:07:50 cgd Exp $ */ - -/* - * Copyright (c) 1994 John Brezak - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: wss.c,v 1.3 1995/04/17 12:07:50 cgd Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* - * Mixer devices - */ -#define WSS_MIC_IN_LVL 0 -#define WSS_LINE_IN_LVL 1 -#define WSS_DAC_LVL 2 -#define WSS_REC_LVL 3 -#define WSS_MON_LVL 4 -#define WSS_MIC_IN_MUTE 5 -#define WSS_LINE_IN_MUTE 6 -#define WSS_DAC_MUTE 7 - -#define WSS_RECORD_SOURCE 8 - -/* Classes */ -#define WSS_INPUT_CLASS 9 -#define WSS_RECORD_CLASS 10 -#define WSS_MONITOR_CLASS 11 - -#define DEBUG /*XXX*/ -#ifdef DEBUG -#define DPRINTF(x) if (wssdebug) printf x -int wssdebug = 0; -#else -#define DPRINTF(x) -#endif - -struct wss_softc { - struct device sc_dev; /* base device */ - struct isadev sc_id; /* ISA device */ - void *sc_ih; /* interrupt vectoring */ - - struct ad1848_softc sc_ad1848; -#define wss_iobase sc_ad1848.sc_iobase -#define wss_irq sc_ad1848.sc_irq -#define wss_drq sc_ad1848.sc_drq - - int mic_mute, cd_mute, dac_mute; -}; - -struct audio_device wss_device = { - "wss,ad1848", - "", - "WSS" -}; - -int wssprobe(); -void wssattach(); -int wssopen __P((dev_t, int)); - -int wss_getdev __P((void *, struct audio_device *)); -int wss_setfd __P((void *, int)); - -int wss_set_out_port __P((void *, int)); -int wss_get_out_port __P((void *)); -int wss_set_in_port __P((void *, int)); -int wss_get_in_port __P((void *)); -int wss_mixer_set_port __P((void *, mixer_ctrl_t *)); -int wss_mixer_get_port __P((void *, mixer_ctrl_t *)); -int wss_query_devinfo __P((void *, mixer_devinfo_t *)); - -/* - * Define our interface to the higher level audio driver. - */ - -struct audio_hw_if wss_hw_if = { - wssopen, - ad1848_close, - NULL, - ad1848_set_in_sr, - ad1848_get_in_sr, - ad1848_set_out_sr, - ad1848_get_out_sr, - ad1848_query_encoding, - ad1848_set_encoding, - ad1848_get_encoding, - ad1848_set_precision, - ad1848_get_precision, - ad1848_set_channels, - ad1848_get_channels, - ad1848_round_blocksize, - wss_set_out_port, - wss_get_out_port, - wss_set_in_port, - wss_get_in_port, - ad1848_commit_settings, - ad1848_get_silence, - NULL, - NULL, - ad1848_dma_output, - ad1848_dma_input, - ad1848_halt_out_dma, - ad1848_halt_in_dma, - ad1848_cont_out_dma, - ad1848_cont_in_dma, - NULL, - wss_getdev, - wss_setfd, - wss_mixer_set_port, - wss_mixer_get_port, - wss_query_devinfo, - 0, /* not full-duplex */ - 0 -}; - -#ifndef NEWCONFIG -#define at_dma(flags, ptr, cc, chan) isa_dmastart(flags, ptr, cc, chan) -#endif - -struct cfdriver wsscd = { - NULL, "wss", wssprobe, wssattach, DV_DULL, sizeof(struct wss_softc) -}; - -/* - * Probe for the Microsoft Sound System hardware. - */ -int -wssprobe(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct wss_softc *sc = (void *)self; - register struct isa_attach_args *ia = aux; - register u_short iobase = ia->ia_iobase; - static u_char interrupt_bits[12] = { - -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20 - }; - static u_char dma_bits[4] = {1, 2, 0, 3}; - char bits; - - if (!WSS_BASE_VALID(ia->ia_iobase)) { - printf("wss: configured iobase %d invalid\n", ia->ia_iobase); - return 0; - } - - sc->wss_iobase = iobase; - - /* Is there an ad1848 chip at the WSS iobase ? */ - if (ad1848_probe(&sc->sc_ad1848) == 0) - return 0; - -#ifdef NEWCONFIG - /* - * If the IRQ wasn't compiled in, auto-detect it. - */ - if (ia->ia_irq == IRQUNK) { - ia->ia_irq = isa_discoverintr(ad1848_forceintr, &sc->sc_ad1848); - if (!WSS_IRQ_VALID(ia->ia_irq)) { - printf("wss: couldn't auto-detect interrupt"); - return 0; - } - } - else -#endif - ia->ia_iosize = WSS_NPORT; - - /* Setup WSS interrupt and DMA */ - if ((bits = interrupt_bits[sc->wss_irq]) == -1) { - printf("wss: invalid interrupt configuration (irq=%d)\n", sc->wss_irq); - return 0; - } - -#if 0 - /* XXX Dual-DMA */ - outb(sc->wss_iobase+WSS_CONFIG, (bits | 0x40)); - if ((inb(sc->wss_iobase+WSS_STATUS) & 0x40) == 0) - printf("wss: IRQ?\n"); -#endif - outb(sc->wss_iobase+WSS_CONFIG, (bits | dma_bits[sc->wss_drq])); - - return 1; -} - -/* - * Attach hardware to driver, attach hardware driver to audio - * pseudo-device driver . - */ -void -wssattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - register struct wss_softc *sc = (struct wss_softc *)self; - struct isa_attach_args *ia = (struct isa_attach_args *)aux; - register u_short iobase = ia->ia_iobase; - - sc->wss_iobase = iobase; - sc->wss_drq = ia->ia_drq; - -#ifdef NEWCONFIG - isa_establish(&sc->sc_id, &sc->sc_dev); -#endif - sc->sc_ih = isa_intr_establish(ia->ia_irq, ISA_IST_EDGE, ISA_IPL_BIO, - ad1848_intr, &sc->sc_ad1848); - - ad1848_attach(&sc->sc_ad1848); - - printf(" (vers %d)", inb(sc->wss_iobase+WSS_STATUS) & 0x1f); - printf("\n"); - - sc->sc_ad1848.parent = sc; - - if (audio_hardware_attach(&wss_hw_if, &sc->sc_ad1848) != 0) - printf("wss: could not attach to audio pseudo-device driver\n"); -} - -static int -wss_to_vol(cp, vol) - mixer_ctrl_t *cp; - struct ad1848_volume *vol; -{ - if (cp->un.value.num_channels == 1) { - vol->left = vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; - return(1); - } - else if (cp->un.value.num_channels == 2) { - vol->left = cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]; - vol->right = cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]; - return(1); - } - return(0); -} - -static int -wss_from_vol(cp, vol) - mixer_ctrl_t *cp; - struct ad1848_volume *vol; -{ - if (cp->un.value.num_channels == 1) { - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol->left; - return(1); - } - else if (cp->un.value.num_channels == 2) { - cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = vol->left; - cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = vol->right; - return(1); - } - return(0); -} - -int -wssopen(dev, flags) - dev_t dev; - int flags; -{ - struct wss_softc *sc; - int unit = AUDIOUNIT(dev); - - if (unit >= wsscd.cd_ndevs) - return ENODEV; - - sc = wsscd.cd_devs[unit]; - if (!sc) - return ENXIO; - - return ad1848_open(&sc->sc_ad1848, dev, flags); -} - -int -wss_getdev(addr, retp) - void *addr; - struct audio_device *retp; -{ - *retp = wss_device; - return 0; -} - -int -wss_setfd(addr, flag) - void *addr; - int flag; -{ - /* Can't do full-duplex */ - return(ENOTTY); -} - - -int -wss_set_out_port(addr, port) - void *addr; - int port; -{ - DPRINTF(("wss_set_out_port:\n")); - return(EINVAL); -} - -int -wss_get_out_port(addr) - void *addr; -{ - DPRINTF(("wss_get_out_port:\n")); - return(EINVAL); -} - -int -wss_set_in_port(addr, port) - void *addr; - int port; -{ - register struct ad1848_softc *ac = addr; - register struct wss_softc *sc = ac->parent; - - DPRINTF(("wss_set_in_port: %d\n", port)); - - switch(port) { - case WSS_MIC_IN_LVL: - port = MIC_IN_PORT; - break; - case WSS_LINE_IN_LVL: - port = LINE_IN_PORT; - break; - case WSS_DAC_LVL: - port = DAC_IN_PORT; - break; - default: - return(EINVAL); - /*NOTREACHED*/ - } - - return(ad1848_set_rec_port(ac, port)); -} - -int -wss_get_in_port(addr) - void *addr; -{ - register struct ad1848_softc *ac = addr; - register struct wss_softc *sc = ac->parent; - int port = WSS_MIC_IN_LVL; - - switch(ad1848_get_rec_port(ac)) { - case MIC_IN_PORT: - port = WSS_MIC_IN_LVL; - break; - case LINE_IN_PORT: - port = WSS_LINE_IN_LVL; - break; - case DAC_IN_PORT: - port = WSS_DAC_LVL; - break; - } - - DPRINTF(("wss_get_in_port: %d\n", port)); - - return(port); -} - -int -wss_mixer_set_port(addr, cp) - void *addr; - mixer_ctrl_t *cp; -{ - register struct ad1848_softc *ac = addr; - register struct wss_softc *sc = ac->parent; - struct ad1848_volume vol; - u_char eq; - int error = EINVAL; - - DPRINTF(("wss_mixer_set_port: dev=%d type=%d\n", cp->dev, cp->type)); - - switch (cp->dev) { - case WSS_MIC_IN_LVL: /* Microphone */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (wss_to_vol(cp, &vol)) - error = ad1848_set_aux2_gain(ac, &vol); - } - break; - - case WSS_MIC_IN_MUTE: /* Microphone */ - if (cp->type == AUDIO_MIXER_ENUM) { - sc->mic_mute = cp->un.ord; - DPRINTF(("mic mute %d\n", cp->un.ord)); - error = 0; - } - break; - - case WSS_LINE_IN_LVL: /* linein/CD */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (wss_to_vol(cp, &vol)) - error = ad1848_set_aux1_gain(ac, &vol); - } - break; - - case WSS_LINE_IN_MUTE: /* linein/CD */ - if (cp->type == AUDIO_MIXER_ENUM) { - sc->cd_mute = cp->un.ord; - DPRINTF(("CD mute %d\n", cp->un.ord)); - error = 0; - } - break; - - case WSS_DAC_LVL: /* dac out */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (wss_to_vol(cp, &vol)) - error = ad1848_set_out_gain(ac, &vol); - } - break; - - case WSS_DAC_MUTE: /* dac out */ - if (cp->type == AUDIO_MIXER_ENUM) { - sc->dac_mute = cp->un.ord; - DPRINTF(("DAC mute %d\n", cp->un.ord)); - error = 0; - } - break; - - case WSS_REC_LVL: /* record level */ - if (cp->type == AUDIO_MIXER_VALUE) { - if (wss_to_vol(cp, &vol)) - error = ad1848_set_rec_gain(ac, &vol); - } - break; - - case WSS_RECORD_SOURCE: - if (cp->type == AUDIO_MIXER_ENUM) { - error = ad1848_set_rec_port(ac, cp->un.ord); - } - break; - - case WSS_MON_LVL: - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) { - vol.left = cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]; - error = ad1848_set_mon_gain(ac, &vol); - } - break; - - default: - return ENXIO; - /*NOTREACHED*/ - } - - return 0; -} - -int -wss_mixer_get_port(addr, cp) - void *addr; - mixer_ctrl_t *cp; -{ - register struct ad1848_softc *ac = addr; - register struct wss_softc *sc = ac->parent; - struct ad1848_volume vol; - u_char eq; - int error = EINVAL; - - DPRINTF(("wss_mixer_get_port: port=%d\n", cp->dev)); - - switch (cp->dev) { - case WSS_MIC_IN_LVL: /* Microphone */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_aux2_gain(ac, &vol); - if (!error) - wss_from_vol(cp, &vol); - } - break; - - case WSS_MIC_IN_MUTE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = sc->mic_mute; - error = 0; - } - break; - - case WSS_LINE_IN_LVL: /* linein/CD */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_aux1_gain(ac, &vol); - if (!error) - wss_from_vol(cp, &vol); - } - break; - - case WSS_LINE_IN_MUTE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = sc->cd_mute; - error = 0; - } - break; - - case WSS_DAC_LVL: /* dac out */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_out_gain(ac, &vol); - if (!error) - wss_from_vol(cp, &vol); - } - break; - - case WSS_DAC_MUTE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = sc->dac_mute; - error = 0; - } - break; - - case WSS_REC_LVL: /* record level */ - if (cp->type == AUDIO_MIXER_VALUE) { - error = ad1848_get_rec_gain(ac, &vol); - if (!error) - wss_from_vol(cp, &vol); - } - break; - - case WSS_RECORD_SOURCE: - if (cp->type == AUDIO_MIXER_ENUM) { - cp->un.ord = ad1848_get_rec_port(ac); - error = 0; - } - break; - - case WSS_MON_LVL: /* monitor level */ - if (cp->type == AUDIO_MIXER_VALUE && cp->un.value.num_channels == 1) { - error = ad1848_get_mon_gain(ac, &vol); - if (!error) - cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = vol.left; - } - break; - - default: - error = ENXIO; - break; - } - - return(error); -} - -int -wss_query_devinfo(addr, dip) - void *addr; - register mixer_devinfo_t *dip; -{ - register struct ad1848_softc *ac = addr; - register struct wss_softc *sc = ac->parent; - - DPRINTF(("wss_query_devinfo: index=%d\n", dip->index)); - - switch(dip->index) { - case WSS_MIC_IN_LVL: /* Microphone */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = WSS_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = WSS_MIC_IN_MUTE; - strcpy(dip->label.name, AudioNmicrophone); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case WSS_LINE_IN_LVL: /* line/CD */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = WSS_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = WSS_LINE_IN_MUTE; - strcpy(dip->label.name, AudioNcd); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case WSS_DAC_LVL: /* dacout */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = WSS_INPUT_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = WSS_DAC_MUTE; - strcpy(dip->label.name, AudioNdac); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case WSS_REC_LVL: /* record level */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = WSS_RECORD_CLASS; - dip->prev = AUDIO_MIXER_LAST; - dip->next = WSS_RECORD_SOURCE; - strcpy(dip->label.name, AudioNrecord); - dip->un.v.num_channels = 2; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case WSS_MON_LVL: /* monitor level */ - dip->type = AUDIO_MIXER_VALUE; - dip->mixer_class = WSS_MONITOR_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNmonitor); - dip->un.v.num_channels = 1; - strcpy(dip->un.v.units.name, AudioNvolume); - break; - - case WSS_INPUT_CLASS: /* input class descriptor */ - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = WSS_INPUT_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioCInputs); - break; - - case WSS_MONITOR_CLASS: /* monitor class descriptor */ - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = WSS_MONITOR_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNmonitor); - break; - - case WSS_RECORD_CLASS: /* record source class */ - dip->type = AUDIO_MIXER_CLASS; - dip->mixer_class = WSS_RECORD_CLASS; - dip->next = dip->prev = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNrecord); - break; - - case WSS_MIC_IN_MUTE: - dip->mixer_class = WSS_INPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = WSS_MIC_IN_LVL; - dip->next = AUDIO_MIXER_LAST; - goto mute; - - case WSS_LINE_IN_MUTE: - dip->mixer_class = WSS_INPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = WSS_LINE_IN_LVL; - dip->next = AUDIO_MIXER_LAST; - goto mute; - - case WSS_DAC_MUTE: - dip->mixer_class = WSS_INPUT_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = WSS_DAC_LVL; - dip->next = AUDIO_MIXER_LAST; - mute: - strcpy(dip->label.name, AudioNmute); - dip->un.e.num_mem = 2; - strcpy(dip->un.e.member[0].label.name, AudioNoff); - dip->un.e.member[0].ord = 0; - strcpy(dip->un.e.member[1].label.name, AudioNon); - dip->un.e.member[1].ord = 1; - break; - - case WSS_RECORD_SOURCE: - dip->mixer_class = WSS_RECORD_CLASS; - dip->type = AUDIO_MIXER_ENUM; - dip->prev = WSS_REC_LVL; - dip->next = AUDIO_MIXER_LAST; - strcpy(dip->label.name, AudioNsource); - dip->un.e.num_mem = 3; - strcpy(dip->un.e.member[0].label.name, AudioNmicrophone); - dip->un.e.member[0].ord = WSS_MIC_IN_LVL; - strcpy(dip->un.e.member[1].label.name, AudioNcd); - dip->un.e.member[1].ord = WSS_LINE_IN_LVL; - strcpy(dip->un.e.member[2].label.name, AudioNdac); - dip->un.e.member[2].ord = WSS_DAC_LVL; - break; - - default: - return ENXIO; - /*NOTREACHED*/ - } - DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name)); - - return 0; -} diff --git a/sys/arch/i386/isa/wssreg.h b/sys/arch/i386/isa/wssreg.h deleted file mode 100644 index 765d8d1c6988..000000000000 --- a/sys/arch/i386/isa/wssreg.h +++ /dev/null @@ -1,62 +0,0 @@ -/* $NetBSD: wssreg.h,v 1.1 1995/02/21 02:28:43 brezak Exp $ */ - -/* - * Copyright (c) 1991-1993 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: wssreg.h,v 1.1 1995/02/21 02:28:43 brezak Exp $ - */ -/* - * Copyright (c) 1993 Analog Devices Inc. All rights reserved - */ - -#define WSS_NPORT 8 - -/* - * Macros to detect valid hardware configuration data. - */ -#define WSS_IRQ_VALID(mask) ((mask) & 0x00ac) /* IRQ 2,3,5,7 */ -#define WSS_BASE_VALID(base) ((base) == 0x0530 || \ - (base) == 0x0604 || \ - (base) == 0x0e80 || \ - (base) == 0x0f40) - -/* Default WSS base */ -/* WSS registers */ -#define WSS_BASE_ADDRESS 0x0530 - -/* WSS registers */ -#define WSS_CONFIG 0x00 -#define WSS_STATUS 0x03 - -#define WSS_VERS 0x04 -#define WSS_16SLOT 0x80 -#define WSS_DUALDMA 0x40