summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1999-07-05 20:08:38 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1999-07-05 20:08:38 +0000
commit93a39446fdd66928d22630a8c18516fdba9086d6 (patch)
treed6793c2851c8ca7fac14fcb42cb8a16b5fff0e5d
parent7a6ba954e72649baf6b772099c5b3d169f268c9e (diff)
first attempt at isapnp gus support
-rw-r--r--sys/dev/isa/files.isa7
-rw-r--r--sys/dev/isa/files.isapnp4
-rw-r--r--sys/dev/isa/gus.c1073
-rw-r--r--sys/dev/isa/gus_isa.c237
-rw-r--r--sys/dev/isa/gus_isapnp.c172
-rw-r--r--sys/dev/isa/gusvar.h423
-rw-r--r--sys/dev/isa/isavar.h16
7 files changed, 1181 insertions, 751 deletions
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index bed6e32209b..341f47f0a71 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,4 +1,4 @@
-# $OpenBSD: files.isa,v 1.53 1999/06/22 16:20:04 niklas Exp $
+# $OpenBSD: files.isa,v 1.54 1999/07/05 20:08:36 deraadt Exp $
# $NetBSD: files.isa,v 1.21 1996/05/16 03:45:55 mycroft Exp $
#
# Config file and device description for machine-independent ISA code.
@@ -293,10 +293,13 @@ file dev/isa/opl_ess.c opl_ess
# Gravis UltraSound & UltraSound MAX.
# Use the "flags" keyword in a config file to specify an extra DMA
# channel for full-duplex operation.
+
device gus: audio, isa_dma, ics2101, ad1848, mulaw, auconv
-attach gus at isa
file dev/isa/gus.c gus needs-flag
+attach gus at isa with gus_isa
+file dev/isa/gus_isa.c gus & (gus_isa | gus_isapnp) needs-flag
+
# Yamaha OPL2/OPL3 FM synth
attach opl at isa with opl_isa
file dev/isa/opl_isa.c opl_isa
diff --git a/sys/dev/isa/files.isapnp b/sys/dev/isa/files.isapnp
index 75cfa74129c..6a68afed2a9 100644
--- a/sys/dev/isa/files.isapnp
+++ b/sys/dev/isa/files.isapnp
@@ -1,4 +1,4 @@
-# $OpenBSD: files.isapnp,v 1.15 1999/06/22 16:20:03 niklas Exp $
+# $OpenBSD: files.isapnp,v 1.16 1999/07/05 20:08:37 deraadt Exp $
# $NetBSD: files.isapnp,v 1.7 1997/10/16 17:16:36 matt Exp $
#
# Config file and device description for machine-independent ISAPnP code.
@@ -30,6 +30,8 @@ attach wss at isapnp with wss_isapnp
file dev/isa/wss_isapnp.c wss & (wss_isa | wss_isapnp) needs-flag
attach ess at isapnp with ess_isapnp
file dev/isa/ess_isapnp.c ess & ess_isapnp needs-flag
+attach gus at isapnp with gus_isapnp
+file dev/isa/gus_isapnp.c gus & (gus_isa | gus_isapnp) needs-flag
attach le at isapnp with le_isapnp
diff --git a/sys/dev/isa/gus.c b/sys/dev/isa/gus.c
index 6bedb6f2202..f2353592f77 100644
--- a/sys/dev/isa/gus.c
+++ b/sys/dev/isa/gus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gus.c,v 1.20 1999/01/24 15:58:53 mickey Exp $ */
+/* $OpenBSD: gus.c,v 1.21 1999/07/05 20:08:37 deraadt Exp $ */
/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
/*-
@@ -95,9 +95,6 @@
*
*/
-#include "gus.h"
-#if NGUS > 0
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
@@ -130,196 +127,7 @@
#include <dev/isa/ad1848var.h>
#include <dev/isa/cs4231var.h>
#include "gusreg.h"
-
-#ifdef AUDIO_DEBUG
-#define STATIC /* empty; for debugging symbols */
-#else
-#define STATIC static
-#endif
-
-/*
- * Software state of a single "voice" on the GUS
- */
-
-struct gus_voice {
-
- /*
- * Various control bits
- */
-
- unsigned char voccntl; /* State of voice control register */
- unsigned char volcntl; /* State of volume control register */
- unsigned char pan_pos; /* Position of volume panning (4 bits) */
- int rate; /* Sample rate of voice being played back */
-
- /*
- * Address of the voice data into the GUS's DRAM. 20 bits each
- */
-
- u_long start_addr; /* Starting address of voice data loop area */
- u_long end_addr; /* Ending address of voice data loop */
- u_long current_addr; /* Beginning address of voice data
- (start playing here) */
-
- /*
- * linear volume values for the GUS's volume ramp. 0-511 (9 bits).
- * These values must be translated into the logarithmic values using
- * gus_log_volumes[]
- */
-
- int start_volume; /* Starting position of volume ramp */
- int current_volume; /* Current position of volume on volume ramp */
- int end_volume; /* Ending position of volume on volume ramp */
-};
-
-/*
- * Software state of GUS
- */
-
-struct gus_softc {
- struct device sc_dev; /* base device */
- struct device *sc_isa; /* pointer to ISA parent */
- void *sc_ih; /* interrupt vector */
- bus_space_tag_t sc_iot; /* tag */
- bus_space_handle_t sc_ioh1; /* handle */
- bus_space_handle_t sc_ioh2; /* handle */
- bus_space_handle_t sc_ioh3; /* ICS2101 handle */
- bus_space_handle_t sc_ioh4; /* MIDI handle */
-
- int sc_iobase; /* I/O base address */
- int sc_irq; /* IRQ used */
- int sc_drq; /* DMA channel for play */
- int sc_recdrq; /* DMA channel for recording */
-
- int sc_flags; /* Various flags about the GUS */
-#define GUS_MIXER_INSTALLED 0x01 /* An ICS mixer is installed */
-#define GUS_LOCKED 0x02 /* GUS is busy doing multi-phase DMA */
-#define GUS_CODEC_INSTALLED 0x04 /* CS4231 installed/MAX */
-#define GUS_PLAYING 0x08 /* GUS is playing a voice */
-#define GUS_DMAOUT_ACTIVE 0x10 /* GUS is busy doing audio DMA */
-#define GUS_DMAIN_ACTIVE 0x20 /* GUS is busy sampling */
-#define GUS_OPEN 0x100 /* GUS is open */
- int sc_dsize; /* Size of GUS DRAM */
- int sc_voices; /* Number of active voices */
- u_char sc_revision; /* Board revision of GUS */
- u_char sc_mixcontrol; /* Value of GUS_MIX_CONTROL register */
-
- u_long sc_orate; /* Output sampling rate */
- u_long sc_irate; /* Input sampling rate */
-
- int sc_encoding; /* Current data encoding type */
- int sc_precision; /* # of bits of precision */
- int sc_channels; /* Number of active channels */
- int sc_blocksize; /* Current blocksize */
- int sc_chanblocksize; /* Current blocksize for each in-use
- channel */
- short sc_nbufs; /* how many on-GUS bufs per-channel */
- short sc_bufcnt; /* how many need to be played */
- void *sc_deintr_buf; /* deinterleave buffer for stereo */
-
- int sc_ogain; /* Output gain control */
- u_char sc_out_port; /* Current out port (generic only) */
- u_char sc_in_port; /* keep track of it when no codec */
-
- void (*sc_dmaoutintr) __P((void*)); /* DMA completion intr handler */
- void *sc_outarg; /* argument for sc_dmaoutintr() */
- u_char *sc_dmaoutaddr; /* for isadma_done */
- u_long sc_gusaddr; /* where did we just put it? */
- int sc_dmaoutcnt; /* for isadma_done */
-
- void (*sc_dmainintr) __P((void*)); /* DMA completion intr handler */
- void *sc_inarg; /* argument for sc_dmaoutintr() */
- u_char *sc_dmainaddr; /* for isadma_done */
- int sc_dmaincnt; /* for isadma_done */
-
- struct stereo_dma_intr {
- void (*intr)__P((void *));
- void *arg;
- u_char *buffer;
- u_long dmabuf;
- int size;
- int flags;
- } sc_stereo;
-
- /*
- * State information for linear audio layer
- */
-
- int sc_dmabuf; /* Which ring buffer we're DMA'ing to */
- int sc_playbuf; /* Which ring buffer we're playing */
-
- /*
- * Voice information array. All voice-specific information is stored
- * here
- */
-
- struct gus_voice sc_voc[32]; /* Voice data for each voice */
- union {
- struct ics2101_softc sc_mixer_u;
- struct ad1848_softc sc_codec_u;
- } u;
-#define sc_mixer u.sc_mixer_u
-#define sc_codec u.sc_codec_u
-};
-
-struct ics2101_volume {
- u_char left;
- u_char right;
-};
-
-#define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED)
-#define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED)
-
-/*
- * Mixer devices for ICS2101
- */
-/* MIC IN mute, line in mute, line out mute are first since they can be done
- even if no ICS mixer. */
-#define GUSICS_MIC_IN_MUTE 0
-#define GUSICS_LINE_IN_MUTE 1
-#define GUSICS_MASTER_MUTE 2
-#define GUSICS_CD_MUTE 3
-#define GUSICS_DAC_MUTE 4
-#define GUSICS_MIC_IN_LVL 5
-#define GUSICS_LINE_IN_LVL 6
-#define GUSICS_CD_LVL 7
-#define GUSICS_DAC_LVL 8
-#define GUSICS_MASTER_LVL 9
-
-#define GUSICS_RECORD_SOURCE 10
-
-/* Classes */
-#define GUSICS_INPUT_CLASS 11
-#define GUSICS_OUTPUT_CLASS 12
-#define GUSICS_RECORD_CLASS 13
-
-/*
- * Mixer & MUX devices for CS4231
- */
-#define GUSMAX_MONO_LVL 0 /* mic input to MUX;
- also mono mixer input */
-#define GUSMAX_DAC_LVL 1 /* input to MUX; also mixer input */
-#define GUSMAX_LINE_IN_LVL 2 /* input to MUX; also mixer input */
-#define GUSMAX_CD_LVL 3 /* mixer input only */
-#define GUSMAX_MONITOR_LVL 4 /* digital mix (?) */
-#define GUSMAX_OUT_LVL 5 /* output level. (?) */
-#define GUSMAX_SPEAKER_LVL 6 /* pseudo-device for mute */
-#define GUSMAX_LINE_IN_MUTE 7 /* pre-mixer */
-#define GUSMAX_DAC_MUTE 8 /* pre-mixer */
-#define GUSMAX_CD_MUTE 9 /* pre-mixer */
-#define GUSMAX_MONO_MUTE 10 /* pre-mixer--microphone/mono */
-#define GUSMAX_MONITOR_MUTE 11 /* post-mixer level/mute */
-#define GUSMAX_SPEAKER_MUTE 12 /* speaker mute */
-
-#define GUSMAX_REC_LVL 13 /* post-MUX gain */
-
-#define GUSMAX_RECORD_SOURCE 14
-
-/* Classes */
-#define GUSMAX_INPUT_CLASS 15
-#define GUSMAX_RECORD_CLASS 16
-#define GUSMAX_MONITOR_CLASS 17
-#define GUSMAX_OUTPUT_CLASS 18
+#include "gusvar.h"
#ifdef AUDIO_DEBUG
#define GUSPLAYDEBUG /*XXX*/
@@ -336,130 +144,25 @@ int gus_dostereo = 1;
#define NDMARECS 2048
#ifdef GUSPLAYDEBUG
int gusstats = 0;
-struct dma_record {
- struct timeval tv;
- u_long gusaddr;
- caddr_t bsdaddr;
- u_short count;
- u_char channel;
- u_char direction;
-} dmarecords[NDMARECS];
-
-int dmarecord_index = 0;
-#endif
-
-/*
- * local routines
- */
-int gusopen __P((void *, int));
-void gusclose __P((void *));
-void gusmax_close __P((void *));
-int gusintr __P((void *));
-int gus_set_in_gain __P((caddr_t, u_int, u_char));
-int gus_get_in_gain __P((caddr_t));
-int gus_set_out_gain __P((caddr_t, u_int, u_char));
-int gus_get_out_gain __P((caddr_t));
-int gus_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
-int gusmax_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
-int gus_round_blocksize __P((void *, int));
-int gus_commit_settings __P((void *));
-int gus_dma_output __P((void *, void *, int, void (*)(void *), void *));
-int gus_dma_input __P((void *, void *, int, void (*)(void *), void *));
-int gus_halt_out_dma __P((void *));
-int gus_halt_in_dma __P((void *));
-int gus_speaker_ctl __P((void *, int));
-int gusmaxopen __P((void *, int));
-int gusmax_round_blocksize __P((void *, int));
-int gusmax_commit_settings __P((void *));
-int gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *));
-int gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *));
-int gusmax_halt_out_dma __P((void *));
-int gusmax_halt_in_dma __P((void *));
-int gusmax_speaker_ctl __P((void *, int));
-int gus_getdev __P((void *, struct audio_device *));
-
-STATIC void gus_deinterleave __P((struct gus_softc *, void *, int));
-
-STATIC int gus_mic_ctl __P((void *, int));
-STATIC int gus_linein_ctl __P((void *, int));
-STATIC int gus_test_iobase __P((bus_space_tag_t, int));
-STATIC void guspoke __P((bus_space_tag_t, bus_space_handle_t, long, u_char));
-STATIC void gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int));
-STATIC int gus_init_cs4231 __P((struct gus_softc *));
-STATIC void gus_init_ics2101 __P((struct gus_softc *));
-
-STATIC void gus_set_chan_addrs __P((struct gus_softc *));
-STATIC void gusreset __P((struct gus_softc *, int));
-STATIC void gus_set_voices __P((struct gus_softc *, int));
-STATIC void gus_set_volume __P((struct gus_softc *, int, int));
-STATIC void gus_set_samprate __P((struct gus_softc *, int, int));
-STATIC void gus_set_recrate __P((struct gus_softc *, u_long));
-STATIC void gus_start_voice __P((struct gus_softc *, int, int));
-STATIC void gus_stop_voice __P((struct gus_softc *, int, int));
-STATIC void gus_set_endaddr __P((struct gus_softc *, int, u_long));
-#ifdef GUSPLAYDEBUG
-STATIC void gus_set_curaddr __P((struct gus_softc *, int, u_long));
-STATIC u_long gus_get_curaddr __P((struct gus_softc *, int));
-#endif
-STATIC int gus_dmaout_intr __P((struct gus_softc *));
-STATIC void gus_dmaout_dointr __P((struct gus_softc *));
-STATIC void gus_dmaout_timeout __P((void *));
-STATIC int gus_dmain_intr __P((struct gus_softc *));
-STATIC int gus_voice_intr __P((struct gus_softc *));
-STATIC void gus_start_playing __P((struct gus_softc *, int));
-STATIC int gus_continue_playing __P((struct gus_softc *, int));
-STATIC u_char guspeek __P((bus_space_tag_t, bus_space_handle_t, u_long));
-STATIC u_long convert_to_16bit __P((u_long));
-STATIC int gus_mixer_set_port __P((void *, mixer_ctrl_t *));
-STATIC int gus_mixer_get_port __P((void *, mixer_ctrl_t *));
-STATIC int gusmax_mixer_set_port __P((void *, mixer_ctrl_t *));
-STATIC int gusmax_mixer_get_port __P((void *, mixer_ctrl_t *));
-STATIC int gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
-STATIC int gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
-STATIC int gus_query_encoding __P((void *, struct audio_encoding *));
-STATIC int gus_get_props __P((void *));
-STATIC int gusmax_get_props __P((void *));
-
-STATIC void gusics_master_mute __P((struct ics2101_softc *, int));
-STATIC void gusics_dac_mute __P((struct ics2101_softc *, int));
-STATIC void gusics_mic_mute __P((struct ics2101_softc *, int));
-STATIC void gusics_linein_mute __P((struct ics2101_softc *, int));
-STATIC void gusics_cd_mute __P((struct ics2101_softc *, int));
-
-void stereo_dmaintr __P((void *));
-
-/*
- * ISA bus driver routines
- */
+struct dma_record dmarecords[NDMARECS];
-#define __BROKEN_INDIRECT_CONFIG
-#ifdef __BROKEN_INDIRECT_CONFIG
-int gusprobe __P((struct device *, void *, void *));
-#else
-int gusprobe __P((struct device *, struct cfdata *, void *));
+int dmarecord_index = 0;
#endif
-void gusattach __P((struct device *, struct device *, void *));
-
-struct cfattach gus_ca = {
- sizeof(struct gus_softc), gusprobe, gusattach,
-};
struct cfdriver gus_cd = {
NULL, "gus", DV_DULL
};
-
/*
* A mapping from IRQ/DRQ values to the values used in the GUS's internal
* registers. A zero means that the referenced IRQ/DRQ is invalid
*/
-
-static int gus_irq_map[] = {
+int gus_irq_map[] = {
IRQUNK, IRQUNK, 1, 3, IRQUNK, 2, IRQUNK, 4, IRQUNK, 1, IRQUNK, 5, 6,
IRQUNK, IRQUNK, 7
};
-static int gus_drq_map[] = {
+int gus_drq_map[] = {
DRQUNK, 1, DRQUNK, 2, DRQUNK, 3, 4, 5
};
@@ -467,10 +170,10 @@ static int gus_drq_map[] = {
* A list of valid base addresses for the GUS
*/
-static int gus_base_addrs[] = {
+int gus_base_addrs[] = {
0x210, 0x220, 0x230, 0x240, 0x250, 0x260
};
-static int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]);
+int gus_addrs = sizeof(gus_base_addrs) / sizeof(gus_base_addrs[0]);
/*
* Maximum frequency values of the GUS based on the number of currently active
@@ -564,29 +267,9 @@ static unsigned short gus_log_volumes[512] = {
0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff};
-#define SELECT_GUS_REG(iot,ioh1,x) bus_space_write_1(iot,ioh1,GUS_REG_SELECT,x)
-#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
-#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
-
-#define GUS_MIN_VOICES 14 /* Minimum possible number of voices */
-#define GUS_MAX_VOICES 32 /* Maximum possible number of voices */
-#define GUS_VOICE_LEFT 0 /* Voice used for left (and mono) playback */
-#define GUS_VOICE_RIGHT 1 /* Voice used for right playback */
-#define GUS_MEM_OFFSET 32 /* Offset into GUS memory to begin of buffer */
-#define GUS_BUFFER_MULTIPLE 1024 /* Audio buffers are multiples of this */
-#define GUS_MEM_FOR_BUFFERS 131072 /* use this many bytes on-GUS */
-#define GUS_LEFT_RIGHT_OFFSET (sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET)
-
-#define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */
-
-/* splgus() must be splaudio() */
-
-#define splgus splaudio
-
/*
* Interface to higher level audio driver
*/
-
struct audio_hw_if gus_hw_if = {
gusopen,
gusclose,
@@ -662,385 +345,12 @@ static struct audio_hw_if gusmax_hw_if = {
/*
* Some info about the current audio device
*/
-
struct audio_device gus_device = {
"UltraSound",
"",
"gus",
};
-#define FLIP_REV 5 /* This rev has flipped mixer chans */
-
-
-int
-gusprobe(parent, match, aux)
- struct device *parent;
-#ifdef __BROKEN_INDIRECT_CONFIG
- void *match;
-#else
- struct cfdata *match;
-#endif
- void *aux;
-{
- struct isa_attach_args *ia = aux;
- int iobase = ia->ia_iobase;
- int recdrq = ia->ia_drq2;
-
- /*
- * Before we do anything else, make sure requested IRQ and DRQ are
- * valid for this card.
- */
-
- /* XXX range check before indexing!! */
- if (ia->ia_irq == IRQUNK || gus_irq_map[ia->ia_irq] == IRQUNK) {
- DPRINTF(("gus: invalid irq %d, card not probed\n", ia->ia_irq));
- return 0;
- }
-
- if (ia->ia_drq == DRQUNK || gus_drq_map[ia->ia_drq] == DRQUNK) {
- DPRINTF(("gus: invalid drq %d, card not probed\n", ia->ia_drq));
- return 0;
- }
-
- if (recdrq != DRQUNK) {
- if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
- DPRINTF(("gus: invalid second DMA channel (%d), card not probed\n", recdrq));
- return 0;
- }
- } else
- recdrq = ia->ia_drq;
-
- if (iobase == IOBASEUNK) {
- int i;
- for(i = 0; i < gus_addrs; i++)
- if (gus_test_iobase(ia->ia_iot, gus_base_addrs[i])) {
- iobase = gus_base_addrs[i];
- goto done;
- }
- return 0;
- } else if (!gus_test_iobase(ia->ia_iot, iobase))
- return 0;
-
-done:
- if ((ia->ia_drq != -1 && !isa_drq_isfree(parent, ia->ia_drq)) ||
- (recdrq != -1 && !isa_drq_isfree(parent, recdrq)))
- return 0;
-
- ia->ia_iobase = iobase;
- ia->ia_iosize = GUS_NPORT1;
- return 1;
-}
-
-/*
- * Test to see if a particular I/O base is valid for the GUS. Return true
- * if it is.
- */
-
-STATIC int
-gus_test_iobase (iot, iobase)
- bus_space_tag_t iot;
- int iobase;
-{
- bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
- u_char s1, s2;
- int s, rv = 0;
-
- /* Map i/o space */
- if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
- return 0;
- if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
- goto bad1;
-
- /* XXX Maybe we shouldn't fail on mapping this, but just assume
- * the card is of revision 0? */
- if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
- goto bad2;
-
- if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
- goto bad3;
-
- /*
- * Reset GUS to an initial state before we do anything.
- */
-
- s = splgus();
- delay(500);
-
- SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
- bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
-
- delay(500);
-
- SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
- bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
-
- delay(500);
-
- splx(s);
-
- /*
- * See if we can write to the board's memory
- */
-
- s1 = guspeek(iot, ioh2, 0L);
- s2 = guspeek(iot, ioh2, 1L);
-
- guspoke(iot, ioh2, 0L, 0xaa);
- guspoke(iot, ioh2, 1L, 0x55);
-
- if (guspeek(iot, ioh2, 0L) != 0xaa)
- goto bad;
-
- guspoke(iot, ioh2, 0L, s1);
- guspoke(iot, ioh2, 1L, s2);
-
- rv = 1;
-
-bad:
- bus_space_unmap(iot, ioh4, GUS_NPORT4);
-bad3:
- bus_space_unmap(iot, ioh3, GUS_NPORT3);
-bad2:
- bus_space_unmap(iot, ioh2, GUS_NPORT2);
-bad1:
- bus_space_unmap(iot, ioh1, GUS_NPORT1);
- return rv;
-}
-
-/*
- * Setup the GUS for use; called shortly after probe
- */
-
-void
-gusattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct gus_softc *sc = (void *) self;
- struct isa_attach_args *ia = aux;
- bus_space_tag_t iot;
- bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
- int iobase, i;
- unsigned char c,d,m;
-
- sc->sc_iot = iot = ia->ia_iot;
- iobase = ia->ia_iobase;
-
- /* Map i/o space */
- if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
- panic("%s: can't map io port range 1", self->dv_xname);
- sc->sc_ioh1 = ioh1;
- if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
- panic("%s: can't map io port range 2", self->dv_xname);
- sc->sc_ioh2 = ioh2;
-
- /* XXX Maybe we shouldn't fail on mapping this, but just assume
- * the card is of revision 0? */
- if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
- panic("%s: can't map io port range 3", self->dv_xname);
- sc->sc_ioh3 = ioh3;
-
- if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
- panic("%s: can't map io port range 4", self->dv_xname);
- sc->sc_ioh4 = ioh4;
-
- sc->sc_iobase = iobase;
- sc->sc_irq = ia->ia_irq;
- sc->sc_drq = ia->ia_drq;
- sc->sc_recdrq = ia->ia_drq2;
-
- /*
- * Figure out our board rev, and see if we need to initialize the
- * mixer
- */
-
- sc->sc_isa = parent;
-
- delay(500);
-
- c = bus_space_read_1(iot, ioh3, GUS_BOARD_REV);
- if (c != 0xff)
- sc->sc_revision = c;
- else
- sc->sc_revision = 0;
-
-
- SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
- bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
-
- gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
- gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
-
- /*
- * Setup the IRQ and DRQ lines in software, using values from
- * config file
- */
-
- m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT; /* disable all */
-
- c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
-
- if (sc->sc_recdrq == sc->sc_drq)
- d = (unsigned char) (gus_drq_map[sc->sc_drq] |
- GUSMASK_BOTH_RQ);
- else
- d = (unsigned char) (gus_drq_map[sc->sc_drq] |
- gus_drq_map[sc->sc_recdrq] << 3);
-
- /*
- * Program the IRQ and DMA channels on the GUS. Note that we hardwire
- * the GUS to only use one IRQ channel, but we give the user the
- * option of using two DMA channels (the other one given by the flags
- * option in the config file). Two DMA channels are needed for full-
- * duplex operation.
- *
- * The order of these operations is very magical.
- */
-
- disable_intr(); /* XXX needed? */
-
- bus_space_write_1(iot, ioh1, GUS_REG_CONTROL, GUS_REG_IRQCTL);
- bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
- bus_space_write_1(iot, ioh1, GUS_IRQCTL_CONTROL, 0x00);
- bus_space_write_1(iot, ioh1, 0x0f, 0x00);
-
- bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
- bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
-
- bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
- bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
-
- bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
- bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d);
-
- bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
- bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
-
- bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, 0x00);
-
- /* enable line in, line out. leave mic disabled. */
- bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL,
- (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
- bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, 0x00);
-
- enable_intr();
-
- sc->sc_mixcontrol =
- (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
-
- /* XXX WILL THIS ALWAYS WORK THE WAY THEY'RE OVERLAYED?! */
- sc->sc_codec.sc_isa = sc->sc_dev.dv_parent;
-
- if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
- sc->sc_flags |= GUS_MIXER_INSTALLED;
- gus_init_ics2101(sc);
- }
- if (sc->sc_revision < 0xa || !gus_init_cs4231(sc)) {
- /* Not using the CS4231, so create our DMA maps. */
- if (sc->sc_drq != -1) {
- if (isa_dmamap_create(sc->sc_isa, sc->sc_drq,
- MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
- printf("%s: can't create map for drq %d\n",
- sc->sc_dev.dv_xname, sc->sc_drq);
- return;
- }
- }
- if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
- if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq,
- MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
- printf("%s: can't create map for drq %d\n",
- sc->sc_dev.dv_xname, sc->sc_recdrq);
- return;
- }
- }
- }
-
- SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
- /*
- * Check to see how much memory we have on this card; see if any
- * "mirroring" occurs. We're assuming at least 256K already exists
- * on the card; otherwise the initial probe would have failed
- */
-
- guspoke(iot, ioh2, 0L, 0x00);
- for(i = 1; i < 1024; i++) {
- u_long loc;
-
- /*
- * See if we've run into mirroring yet
- */
-
- if (guspeek(iot, ioh2, 0L) != 0)
- break;
-
- loc = i << 10;
-
- guspoke(iot, ioh2, loc, 0xaa);
- if (guspeek(iot, ioh2, loc) != 0xaa)
- break;
- }
-
- sc->sc_dsize = i;
- sprintf(gus_device.version, "3.%d", sc->sc_revision);
-
- printf("\n <Gravis UltraSound version 3.%d, %dKB DRAM, ",
- sc->sc_revision, sc->sc_dsize);
- if (HAS_MIXER(sc))
- printf("ICS2101 mixer, ");
- if (HAS_CODEC(sc))
- printf("%s codec/mixer, ", sc->sc_codec.chip_name);
- if (sc->sc_recdrq == sc->sc_drq) {
- printf("half-duplex");
- } else {
- printf("full-duplex, record drq %d", sc->sc_recdrq);
- }
-
- printf(">\n");
-
- /*
- * Setup a default interrupt handler
- */
-
- /* XXX we shouldn't have to use splgus == splclock, nor should
- * we use IPL_CLOCK.
- */
- sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
- IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
-
- /*
- * Set some default values
- * XXX others start with 8kHz mono mulaw
- */
-
- sc->sc_irate = sc->sc_orate = 44100;
- sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
- sc->sc_precision = 16;
- sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
- sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
- sc->sc_channels = 1;
- sc->sc_ogain = 340;
- gus_commit_settings(sc);
-
- /*
- * We always put the left channel full left & right channel
- * full right.
- * For mono playback, we set up both voices playing the same buffer.
- */
- bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
- SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
- bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
-
- bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
- SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
- bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
-
- /*
- * Attach to the generic audio layer
- */
-
- audio_attach_mi(&gus_hw_if,
- HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc, &sc->sc_dev);
-}
int
gusopen(addr, flags)
@@ -1094,7 +404,7 @@ gusmaxopen(addr, flags)
return gusopen(ac->parent, flags);
}
-STATIC void
+void
gus_deinterleave(sc, buf, size)
struct gus_softc *sc;
void *buf;
@@ -1412,7 +722,7 @@ struct playcont {
int playcntr;
-STATIC void
+void
gus_dmaout_timeout(arg)
void *arg;
{
@@ -1445,7 +755,7 @@ gus_dmaout_timeout(arg)
* a DMA transfer for playback/record requests from the audio layer.
*/
-STATIC int
+int
gus_dmaout_intr(sc)
struct gus_softc *sc;
{
@@ -1466,7 +776,7 @@ gus_dmaout_intr(sc)
return 0;
}
-STATIC void
+void
gus_dmaout_dointr(sc)
struct gus_softc *sc;
{
@@ -1620,7 +930,7 @@ gus_dmaout_dointr(sc)
* Service voice interrupts
*/
-STATIC int
+int
gus_voice_intr(sc)
struct gus_softc *sc;
{
@@ -1769,7 +1079,7 @@ gus_voice_intr(sc)
return 0;
}
-STATIC void
+void
gus_start_playing(sc, bufno)
struct gus_softc *sc;
int bufno;
@@ -1849,7 +1159,7 @@ gus_start_playing(sc, bufno)
sc->sc_playbuf = bufno;
}
-STATIC int
+int
gus_continue_playing(sc, voice)
struct gus_softc *sc;
int voice;
@@ -1950,7 +1260,7 @@ gus_continue_playing(sc, voice)
* Send/receive data into GUS's DRAM using DMA. Called at splgus()
*/
-STATIC void
+void
gusdmaout(sc, flags, gusaddr, buffaddr, length)
struct gus_softc *sc;
int flags, length;
@@ -2025,7 +1335,7 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
* splgus().
*/
-STATIC void
+void
gus_start_voice(sc, voice, intrs)
struct gus_softc *sc;
int voice;
@@ -2122,7 +1432,7 @@ gus_start_voice(sc, voice, intrs)
* Stop a given voice. called at splgus()
*/
-STATIC void
+void
gus_stop_voice(sc, voice, intrs_too)
struct gus_softc *sc;
int voice;
@@ -2165,7 +1475,7 @@ gus_stop_voice(sc, voice, intrs_too)
/*
* Set the volume of a given voice. Called at splgus().
*/
-STATIC void
+void
gus_set_volume(sc, voice, volume)
struct gus_softc *sc;
int voice, volume;
@@ -2339,7 +1649,7 @@ gus_get_out_gain(addr)
return sc->sc_ogain / 2;
}
-STATIC inline void gus_set_voices(sc, voices)
+inline void gus_set_voices(sc, voices)
struct gus_softc *sc;
int voices;
{
@@ -2399,7 +1709,7 @@ gus_commit_settings(addr)
return 0;
}
-STATIC void
+void
gus_set_chan_addrs(sc)
struct gus_softc *sc;
{
@@ -2437,7 +1747,7 @@ struct gus_softc *sc;
* Set the sample rate of the given voice. Called at splgus().
*/
-STATIC void
+void
gus_set_samprate(sc, voice, freq)
struct gus_softc *sc;
int voice, freq;
@@ -2476,7 +1786,7 @@ gus_set_samprate(sc, voice, freq)
* SDK. Called at splgus().
*/
-STATIC void
+void
gus_set_recrate(sc, rate)
struct gus_softc *sc;
u_long rate;
@@ -2533,7 +1843,7 @@ gus_speaker_ctl(addr, newstate)
return 0;
}
-STATIC int
+int
gus_linein_ctl(addr, newstate)
void * addr;
int newstate;
@@ -2557,7 +1867,7 @@ gus_linein_ctl(addr, newstate)
return 0;
}
-STATIC int
+int
gus_mic_ctl(addr, newstate)
void * addr;
int newstate;
@@ -2585,7 +1895,7 @@ gus_mic_ctl(addr, newstate)
* Set the end address of a give voice. Called at splgus()
*/
-STATIC void
+void
gus_set_endaddr(sc, voice, addr)
struct gus_softc *sc;
int voice;
@@ -2610,7 +1920,7 @@ gus_set_endaddr(sc, voice, addr)
/*
* Set current address. called at splgus()
*/
-STATIC void
+void
gus_set_curaddr(sc, voice, addr)
struct gus_softc *sc;
int voice;
@@ -2636,7 +1946,7 @@ gus_set_curaddr(sc, voice, addr)
/*
* Get current GUS playback address. Called at splgus().
*/
-STATIC u_long
+u_long
gus_get_curaddr(sc, voice)
struct gus_softc *sc;
int voice;
@@ -2666,7 +1976,7 @@ gus_get_curaddr(sc, voice)
* have NO idea
*/
-STATIC u_long
+u_long
convert_to_16bit(address)
u_long address;
{
@@ -2684,7 +1994,7 @@ convert_to_16bit(address)
* Write a value into the GUS's DRAM
*/
-STATIC void
+void
guspoke(iot, ioh2, address, value)
bus_space_tag_t iot;
bus_space_handle_t ioh2;
@@ -2712,7 +2022,7 @@ guspoke(iot, ioh2, address, value)
* Read a value from the GUS's DRAM
*/
-STATIC unsigned char
+unsigned char
guspeek(iot, ioh2, address)
bus_space_tag_t iot;
bus_space_handle_t ioh2;
@@ -2739,7 +2049,7 @@ guspeek(iot, ioh2, address)
* Reset the Gravis UltraSound card, completely
*/
-STATIC void
+void
gusreset(sc, voices)
struct gus_softc *sc;
int voices;
@@ -2869,7 +2179,7 @@ gusreset(sc, voices)
}
-STATIC int
+int
gus_init_cs4231(sc)
struct gus_softc *sc;
{
@@ -3020,7 +2330,7 @@ gus_dma_input(addr, buf, size, callback, arg)
return 0;
}
-STATIC int
+int
gus_dmain_intr(sc)
struct gus_softc *sc;
{
@@ -3132,7 +2442,7 @@ gus_halt_in_dma(addr)
}
-static ad1848_devmap_t gusmapping[] = {
+ad1848_devmap_t gusmapping[] = {
{GUSMAX_DAC_LVL, AD1848_KIND_LVL, AD1848_AUX1_CHANNEL},
{GUSMAX_LINE_IN_LVL, AD1848_KIND_LVL, AD1848_LINE_CHANNEL},
{GUSMAX_MONO_LVL, AD1848_KIND_LVL, AD1848_MONO_CHANNEL},
@@ -3148,9 +2458,9 @@ static ad1848_devmap_t gusmapping[] = {
{GUSMAX_RECORD_SOURCE, AD1848_KIND_RECORDSOURCE, -1}
};
-static int nummap = sizeof(gusmapping) / sizeof(gusmapping[0]);
+int nummap = sizeof(gusmapping) / sizeof(gusmapping[0]);
-STATIC int
+int
gusmax_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
@@ -3191,7 +2501,7 @@ gusmax_mixer_get_port(addr, cp)
return(error);
}
-STATIC int
+int
gus_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
@@ -3316,7 +2626,7 @@ gus_mixer_get_port(addr, cp)
return error;
}
-STATIC void
+void
gusics_master_mute(ic, mute)
struct ics2101_softc *ic;
int mute;
@@ -3325,7 +2635,7 @@ gusics_master_mute(ic, mute)
ics2101_mix_mute(ic, GUSMIX_CHAN_MASTER, ICSMIX_RIGHT, mute);
}
-STATIC void
+void
gusics_mic_mute(ic, mute)
struct ics2101_softc *ic;
int mute;
@@ -3334,7 +2644,7 @@ gusics_mic_mute(ic, mute)
ics2101_mix_mute(ic, GUSMIX_CHAN_MIC, ICSMIX_RIGHT, mute);
}
-STATIC void
+void
gusics_linein_mute(ic, mute)
struct ics2101_softc *ic;
int mute;
@@ -3343,7 +2653,7 @@ gusics_linein_mute(ic, mute)
ics2101_mix_mute(ic, GUSMIX_CHAN_LINE, ICSMIX_RIGHT, mute);
}
-STATIC void
+void
gusics_cd_mute(ic, mute)
struct ics2101_softc *ic;
int mute;
@@ -3352,7 +2662,7 @@ gusics_cd_mute(ic, mute)
ics2101_mix_mute(ic, GUSMIX_CHAN_CD, ICSMIX_RIGHT, mute);
}
-STATIC void
+void
gusics_dac_mute(ic, mute)
struct ics2101_softc *ic;
int mute;
@@ -3361,7 +2671,7 @@ gusics_dac_mute(ic, mute)
ics2101_mix_mute(ic, GUSMIX_CHAN_DAC, ICSMIX_RIGHT, mute);
}
-STATIC int
+int
gusmax_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
@@ -3402,7 +2712,7 @@ gusmax_mixer_set_port(addr, cp)
return error;
}
-STATIC int
+int
gus_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
@@ -3562,7 +2872,7 @@ gus_mixer_set_port(addr, cp)
return error;
}
-STATIC int
+int
gus_get_props(addr)
void *addr;
{
@@ -3571,7 +2881,7 @@ gus_get_props(addr)
(sc->sc_recdrq == sc->sc_drq ? 0 : AUDIO_PROP_FULLDUPLEX);
}
-STATIC int
+int
gusmax_get_props(addr)
void *addr;
{
@@ -3579,7 +2889,7 @@ gusmax_get_props(addr)
return gus_get_props(ac->parent);
}
-STATIC int
+int
gusmax_mixer_query_devinfo(addr, dip)
void *addr;
mixer_devinfo_t *dip;
@@ -3781,7 +3091,7 @@ gusmax_mixer_query_devinfo(addr, dip)
return 0;
}
-STATIC int
+int
gus_mixer_query_devinfo(addr, dip)
void *addr;
mixer_devinfo_t *dip;
@@ -3927,7 +3237,7 @@ mute:
return 0;
}
-STATIC int
+int
gus_query_encoding(addr, fp)
void *addr;
struct audio_encoding *fp;
@@ -3994,7 +3304,7 @@ gus_query_encoding(addr, fp)
* level. Levels as suggested by GUS SDK code.
*/
-STATIC void
+void
gus_init_ics2101(sc)
struct gus_softc *sc;
{
@@ -4074,4 +3384,283 @@ gus_init_ics2101(sc)
}
-#endif /* NGUS */
+
+void
+gus_subattach(sc, ia)
+ struct gus_softc *sc;
+ struct isa_attach_args *ia;
+{
+ int i;
+ bus_space_tag_t iot;
+ unsigned char c,d,m;
+
+ iot = sc->sc_iot;
+
+ /*
+ * Figure out our board rev, and see if we need to initialize the
+ * mixer
+ */
+
+ c = bus_space_read_1(iot, sc->sc_ioh3, GUS_BOARD_REV);
+ if (c != 0xff)
+ sc->sc_revision = c;
+ else
+ sc->sc_revision = 0;
+
+ SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, 0x00);
+
+ gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
+ gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
+
+ /*
+ * Setup the IRQ and DRQ lines in software, using values from
+ * config file
+ */
+
+ m = GUSMASK_LINE_IN|GUSMASK_LINE_OUT; /* disable all */
+
+ c = ((unsigned char) gus_irq_map[ia->ia_irq]) | GUSMASK_BOTH_RQ;
+
+ if (sc->sc_recdrq == sc->sc_drq)
+ d = (unsigned char) (gus_drq_map[sc->sc_drq] |
+ GUSMASK_BOTH_RQ);
+ else
+ d = (unsigned char) (gus_drq_map[sc->sc_drq] |
+ gus_drq_map[sc->sc_recdrq] << 3);
+
+ /*
+ * Program the IRQ and DMA channels on the GUS. Note that we hardwire
+ * the GUS to only use one IRQ channel, but we give the user the
+ * option of using two DMA channels (the other one given by the flags
+ * option in the config file). Two DMA channels are needed for full-
+ * duplex operation.
+ *
+ * The order of these operations is very magical.
+ */
+
+ disable_intr(); /* XXX needed? */
+
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_REG_CONTROL, GUS_REG_IRQCTL);
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQCTL_CONTROL, 0x00);
+ bus_space_write_1(iot, sc->sc_ioh1, 0x0f, 0x00);
+
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
+
+ /* magic reset? */
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_DMA_CONTROL, d | 0x80);
+
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
+ m | GUSMASK_CONTROL_SEL);
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQ_CONTROL, c);
+
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL, m);
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_DMA_CONTROL, d);
+
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
+ m | GUSMASK_CONTROL_SEL);
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_IRQ_CONTROL, c);
+
+ bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT, 0x00);
+
+ /* enable line in, line out. leave mic disabled. */
+ bus_space_write_1(iot, sc->sc_ioh1, GUS_MIX_CONTROL,
+ (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
+ bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT, 0x00);
+
+ enable_intr();
+
+ sc->sc_mixcontrol =
+ (m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
+
+ sc->sc_codec.sc_isa = sc->sc_isa;
+
+ if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
+ sc->sc_flags |= GUS_MIXER_INSTALLED;
+ gus_init_ics2101(sc);
+ }
+ if (sc->sc_revision < 0xa || !gus_init_cs4231(sc)) {
+ /* Not using the CS4231, so create our DMA maps. */
+ if (sc->sc_drq != -1) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq,
+ MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("%s: can't create map for drq %d\n",
+ sc->sc_dev.dv_xname, sc->sc_drq);
+ return;
+ }
+ }
+ if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq,
+ MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("%s: can't create map for drq %d\n",
+ sc->sc_dev.dv_xname, sc->sc_recdrq);
+ return;
+ }
+ }
+ }
+
+ SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_RESET);
+ /*
+ * Check to see how much memory we have on this card; see if any
+ * "mirroring" occurs. We're assuming at least 256K already exists
+ * on the card; otherwise the initial probe would have failed
+ */
+
+ guspoke(iot, sc->sc_ioh2, 0L, 0x00);
+ for(i = 1; i < 1024; i++) {
+ u_long loc;
+
+ /*
+ * See if we've run into mirroring yet
+ */
+
+ if (guspeek(iot, sc->sc_ioh2, 0L) != 0)
+ break;
+
+ loc = i << 10;
+
+ guspoke(iot, sc->sc_ioh2, loc, 0xaa);
+ if (guspeek(iot, sc->sc_ioh2, loc) != 0xaa)
+ break;
+ }
+
+ sc->sc_dsize = i;
+ sprintf(gus_device.version, "3.%d", sc->sc_revision);
+
+ printf(": ver 3.%d, %dKB DRAM, ",
+ sc->sc_revision, sc->sc_dsize);
+ if (HAS_MIXER(sc))
+ printf("ICS2101 mixer, ");
+ if (HAS_CODEC(sc))
+ printf("%s codec/mixer, ", sc->sc_codec.chip_name);
+ if (sc->sc_recdrq == sc->sc_drq) {
+ printf("half-duplex");
+ } else {
+ printf("full-duplex, record drq %d", sc->sc_recdrq);
+ }
+
+ printf("\n");
+
+ /*
+ * Setup a default interrupt handler
+ */
+
+ /* XXX we shouldn't have to use splgus == splclock, nor should
+ * we use IPL_CLOCK.
+ */
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_AUDIO, gusintr, sc /* sc->sc_gusdsp */, sc->sc_dev.dv_xname);
+
+ /*
+ * Set some default values
+ * XXX others start with 8kHz mono mulaw
+ */
+
+ sc->sc_irate = sc->sc_orate = 44100;
+ sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
+ sc->sc_precision = 16;
+ sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
+ sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
+ sc->sc_channels = 1;
+ sc->sc_ogain = 340;
+ gus_commit_settings(sc);
+
+ /*
+ * We always put the left channel full left & right channel
+ * full right.
+ * For mono playback, we set up both voices playing the same buffer.
+ */
+ bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT,
+ (u_char)GUS_VOICE_LEFT);
+ SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_PAN_POS);
+ bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
+
+ bus_space_write_1(iot, sc->sc_ioh2, GUS_VOICE_SELECT,
+ (u_char)GUS_VOICE_RIGHT);
+ SELECT_GUS_REG(iot, sc->sc_ioh2, GUSREG_PAN_POS);
+ bus_space_write_1(iot, sc->sc_ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
+
+ /*
+ * Attach to the generic audio layer
+ */
+
+ audio_attach_mi(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec :
+ (void *)sc, &sc->sc_dev);
+}
+
+/*
+ * Test to see if a particular I/O base is valid for the GUS. Return true
+ * if it is.
+ */
+
+int
+gus_test_iobase (iot, iobase)
+ bus_space_tag_t iot;
+ int iobase;
+{
+ bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
+ u_char s1, s2;
+ int s, rv = 0;
+
+ /* Map i/o space */
+ if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
+ return 0;
+ if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
+ goto bad1;
+
+ /* XXX Maybe we shouldn't fail on mapping this, but just assume
+ * the card is of revision 0? */
+ if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
+ goto bad2;
+
+ if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
+ goto bad3;
+
+ /*
+ * Reset GUS to an initial state before we do anything.
+ */
+
+ s = splgus();
+ delay(500);
+
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
+
+ delay(500);
+
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
+
+ delay(500);
+
+ splx(s);
+
+ /*
+ * See if we can write to the board's memory
+ */
+
+ s1 = guspeek(iot, ioh2, 0L);
+ s2 = guspeek(iot, ioh2, 1L);
+
+ guspoke(iot, ioh2, 0L, 0xaa);
+ guspoke(iot, ioh2, 1L, 0x55);
+
+ if (guspeek(iot, ioh2, 0L) != 0xaa)
+ goto bad;
+
+ guspoke(iot, ioh2, 0L, s1);
+ guspoke(iot, ioh2, 1L, s2);
+
+ rv = 1;
+
+bad:
+ bus_space_unmap(iot, ioh4, GUS_NPORT4);
+bad3:
+ bus_space_unmap(iot, ioh3, GUS_NPORT3);
+bad2:
+ bus_space_unmap(iot, ioh2, GUS_NPORT2);
+bad1:
+ bus_space_unmap(iot, ioh1, GUS_NPORT1);
+ return rv;
+}
diff --git a/sys/dev/isa/gus_isa.c b/sys/dev/isa/gus_isa.c
new file mode 100644
index 00000000000..b7e213b7ade
--- /dev/null
+++ b/sys/dev/isa/gus_isa.c
@@ -0,0 +1,237 @@
+/* $OpenBSD: gus_isa.c,v 1.1 1999/07/05 20:08:37 deraadt Exp $ */
+/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Ken Hornstein and John Kohl.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ *
+ * TODO:
+ * . figure out why mixer activity while sound is playing causes problems
+ * (phantom interrupts?)
+ * . figure out a better deinterleave strategy that avoids sucking up
+ * CPU, memory and cache bandwidth. (Maybe a special encoding?
+ * Maybe use the double-speed sampling/hardware deinterleave trick
+ * from the GUS SDK?) A 486/33 isn't quite fast enough to keep
+ * up with 44.1kHz 16-bit stereo output without some drop-outs.
+ * . use CS4231 for 16-bit sampling, for a-law and mu-law playback.
+ * . actually test full-duplex sampling(recording) and playback.
+ */
+
+/*
+ * Gravis UltraSound driver
+ *
+ * For more detailed information, see the GUS developers' kit
+ * available on the net at:
+ *
+ * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
+ * gusdkXXX.zip (developers' kit--get rev 2.22 or later)
+ * See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
+ *
+ */
+
+/*
+ * The GUS Max has a slightly strange set of connections between the CS4231
+ * and the GF1 and the DMA interconnects. It's set up so that the CS4231 can
+ * be playing while the GF1 is loading patches from the system.
+ *
+ * Here's a recreation of the DMA interconnect diagram:
+ *
+ * GF1
+ * +---------+ digital
+ * | | record ASIC
+ * | |--------------+
+ * | | | +--------+
+ * | | play (dram) | +----+ | |
+ * | |--------------(------|-\ | | +-+ |
+ * +---------+ | | >-|----|---|C|--|------ dma chan 1
+ * | +---|-/ | | +-+ |
+ * | | +----+ | | |
+ * | | +----+ | | |
+ * +---------+ +-+ +--(---|-\ | | | |
+ * | | play |8| | | >-|----|----+---|------ dma chan 2
+ * | ---C----|--------|/|------(---|-/ | | |
+ * | ^ |record |1| | +----+ | |
+ * | | | /----|6|------+ +--------+
+ * | ---+----|--/ +-+
+ * +---------+
+ * CS4231 8-to-16 bit bus conversion, if needed
+ *
+ *
+ * "C" is an optional combiner.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/mulaw.h>
+#include <dev/auconv.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <i386/isa/icu.h>
+
+#include <dev/ic/ics2101reg.h>
+#include <dev/ic/cs4231reg.h>
+#include <dev/ic/ad1848reg.h>
+#include <dev/isa/ics2101var.h>
+#include <dev/isa/ad1848var.h>
+#include <dev/isa/cs4231var.h>
+#include "gusreg.h"
+#include "gusvar.h"
+
+/*
+ * ISA bus driver routines
+ */
+
+int gus_isa_match __P((struct device *, void *, void *));
+void gus_isa_attach __P((struct device *, struct device *, void *));
+
+struct cfattach gus_isa_ca = {
+ sizeof(struct gus_softc), gus_isa_match, gus_isa_attach,
+};
+
+int
+gus_isa_match(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ struct isa_attach_args *ia = aux;
+ int iobase = ia->ia_iobase;
+ int recdrq = ia->ia_drq2;
+
+ /*
+ * Before we do anything else, make sure requested IRQ and DRQ are
+ * valid for this card.
+ */
+
+ /* XXX range check before indexing!! */
+ if (ia->ia_irq == IRQUNK || gus_irq_map[ia->ia_irq] == IRQUNK) {
+ DPRINTF(("gus: invalid irq %d, card not probed\n", ia->ia_irq));
+ return 0;
+ }
+
+ if (ia->ia_drq == DRQUNK || gus_drq_map[ia->ia_drq] == DRQUNK) {
+ DPRINTF(("gus: invalid drq %d, card not probed\n", ia->ia_drq));
+ return 0;
+ }
+
+ if (recdrq != DRQUNK) {
+ if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
+ DPRINTF(("gus: invalid second DMA channel (%d), card not probed\n", recdrq));
+ return 0;
+ }
+ } else
+ recdrq = ia->ia_drq;
+
+ if (iobase == IOBASEUNK) {
+ int i;
+ for(i = 0; i < gus_addrs; i++)
+ if (gus_test_iobase(ia->ia_iot, gus_base_addrs[i])) {
+ iobase = gus_base_addrs[i];
+ goto done;
+ }
+ return 0;
+ } else if (!gus_test_iobase(ia->ia_iot, iobase))
+ return 0;
+
+done:
+ if ((ia->ia_drq != -1 && !isa_drq_isfree(parent, ia->ia_drq)) ||
+ (recdrq != -1 && !isa_drq_isfree(parent, recdrq)))
+ return 0;
+
+ ia->ia_iobase = iobase;
+ ia->ia_iosize = GUS_NPORT1;
+ return 1;
+}
+
+
+/*
+ * Setup the GUS for use; called shortly after probe
+ */
+
+void
+gus_isa_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct gus_softc *sc = (void *) self;
+ struct isa_attach_args *ia = aux;
+
+ sc->sc_iot = ia->ia_iot;
+ sc->sc_iobase = ia->ia_iobase;
+
+ /* Map i/o space */
+ if (bus_space_map(sc->sc_iot, sc->sc_iobase, GUS_NPORT1, 0, &sc->sc_ioh1))
+ panic("%s: can't map io port range 1", self->dv_xname);
+ if (bus_space_map(sc->sc_iot, sc->sc_iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0,
+ &sc->sc_ioh2))
+ panic("%s: can't map io port range 2", self->dv_xname);
+
+ /* XXX Maybe we shouldn't fail on mapping this, but just assume
+ * the card is of revision 0? */
+ if (bus_space_map(sc->sc_iot, sc->sc_iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0,
+ &sc->sc_ioh3))
+ panic("%s: can't map io port range 3", self->dv_xname);
+
+ if (bus_space_map(sc->sc_iot, sc->sc_iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0,
+ &sc->sc_ioh4))
+ panic("%s: can't map io port range 4", self->dv_xname);
+
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_drq = ia->ia_drq;
+ sc->sc_recdrq = ia->ia_drq2;
+ sc->sc_isa = parent;
+
+ gus_subattach(sc, aux);
+}
diff --git a/sys/dev/isa/gus_isapnp.c b/sys/dev/isa/gus_isapnp.c
new file mode 100644
index 00000000000..55d54d28a74
--- /dev/null
+++ b/sys/dev/isa/gus_isapnp.c
@@ -0,0 +1,172 @@
+/* $OpenBSD: gus_isapnp.c,v 1.1 1999/07/05 20:08:37 deraadt Exp $ */
+/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Ken Hornstein and John Kohl.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ *
+ * TODO:
+ * . figure out why mixer activity while sound is playing causes problems
+ * (phantom interrupts?)
+ * . figure out a better deinterleave strategy that avoids sucking up
+ * CPU, memory and cache bandwidth. (Maybe a special encoding?
+ * Maybe use the double-speed sampling/hardware deinterleave trick
+ * from the GUS SDK?) A 486/33 isn't quite fast enough to keep
+ * up with 44.1kHz 16-bit stereo output without some drop-outs.
+ * . use CS4231 for 16-bit sampling, for a-law and mu-law playback.
+ * . actually test full-duplex sampling(recording) and playback.
+ */
+
+/*
+ * Gravis UltraSound driver
+ *
+ * For more detailed information, see the GUS developers' kit
+ * available on the net at:
+ *
+ * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
+ * gusdkXXX.zip (developers' kit--get rev 2.22 or later)
+ * See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
+ *
+ */
+
+/*
+ * The GUS Max has a slightly strange set of connections between the CS4231
+ * and the GF1 and the DMA interconnects. It's set up so that the CS4231 can
+ * be playing while the GF1 is loading patches from the system.
+ *
+ * Here's a recreation of the DMA interconnect diagram:
+ *
+ * GF1
+ * +---------+ digital
+ * | | record ASIC
+ * | |--------------+
+ * | | | +--------+
+ * | | play (dram) | +----+ | |
+ * | |--------------(------|-\ | | +-+ |
+ * +---------+ | | >-|----|---|C|--|------ dma chan 1
+ * | +---|-/ | | +-+ |
+ * | | +----+ | | |
+ * | | +----+ | | |
+ * +---------+ +-+ +--(---|-\ | | | |
+ * | | play |8| | | >-|----|----+---|------ dma chan 2
+ * | ---C----|--------|/|------(---|-/ | | |
+ * | ^ |record |1| | +----+ | |
+ * | | | /----|6|------+ +--------+
+ * | ---+----|--/ +-+
+ * +---------+
+ * CS4231 8-to-16 bit bus conversion, if needed
+ *
+ *
+ * "C" is an optional combiner.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/cpufunc.h>
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+#include <dev/mulaw.h>
+#include <dev/auconv.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <i386/isa/icu.h>
+
+#include <dev/ic/ics2101reg.h>
+#include <dev/ic/cs4231reg.h>
+#include <dev/ic/ad1848reg.h>
+#include <dev/isa/ics2101var.h>
+#include <dev/isa/ad1848var.h>
+#include <dev/isa/cs4231var.h>
+#include "gusreg.h"
+#include "gusvar.h"
+
+int gus_isapnp_match __P((struct device *, void *, void *));
+void gus_isapnp_attach __P((struct device *, struct device *, void *));
+
+struct cfattach gus_isapnp_ca = {
+ sizeof(struct gus_softc), gus_isapnp_match, gus_isapnp_attach
+};
+
+/*
+ * Probe for the GUS hardware.
+ */
+int
+gus_isapnp_match(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ return 1;
+}
+
+void
+gus_isapnp_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct gus_softc *sc = (void *) self;
+ struct isa_attach_args *ipa = aux;
+
+ sc->sc_iot = ipa->ia_iot;
+ sc->sc_iobase = ipa->ia_iobase;
+
+ sc->sc_ioh1 = ipa->ipa_io[0].h; /* p2xr */
+ sc->sc_ioh2 = ipa->ipa_io[1].h; /* p3xr */
+ sc->sc_ioh3 = ipa->ipa_io[2].h; /* codec/mixer */
+ sc->sc_ioh4 = NULL; /* midi */
+
+ sc->sc_irq = ipa->ipa_irq[0].num;
+ sc->sc_drq = ipa->ipa_drq[1].num;
+ sc->sc_recdrq = ipa->ipa_drq[0].num;
+ sc->sc_isa = parent->dv_parent;
+
+ gus_subattach(sc, ipa);
+}
diff --git a/sys/dev/isa/gusvar.h b/sys/dev/isa/gusvar.h
new file mode 100644
index 00000000000..59d73afc633
--- /dev/null
+++ b/sys/dev/isa/gusvar.h
@@ -0,0 +1,423 @@
+/* $OpenBSD: gusvar.h,v 1.1 1999/07/05 20:08:37 deraadt Exp $ */
+/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
+
+/*-
+ * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Ken Hornstein and John Kohl.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ *
+ * TODO:
+ * . figure out why mixer activity while sound is playing causes problems
+ * (phantom interrupts?)
+ * . figure out a better deinterleave strategy that avoids sucking up
+ * CPU, memory and cache bandwidth. (Maybe a special encoding?
+ * Maybe use the double-speed sampling/hardware deinterleave trick
+ * from the GUS SDK?) A 486/33 isn't quite fast enough to keep
+ * up with 44.1kHz 16-bit stereo output without some drop-outs.
+ * . use CS4231 for 16-bit sampling, for a-law and mu-law playback.
+ * . actually test full-duplex sampling(recording) and playback.
+ */
+
+/*
+ * Gravis UltraSound driver
+ *
+ * For more detailed information, see the GUS developers' kit
+ * available on the net at:
+ *
+ * ftp://freedom.nmsu.edu/pub/ultrasound/gravis/util/
+ * gusdkXXX.zip (developers' kit--get rev 2.22 or later)
+ * See ultrawrd.doc inside--it's MS Word (ick), but it's the bible
+ *
+ */
+
+/*
+ * The GUS Max has a slightly strange set of connections between the CS4231
+ * and the GF1 and the DMA interconnects. It's set up so that the CS4231 can
+ * be playing while the GF1 is loading patches from the system.
+ *
+ * Here's a recreation of the DMA interconnect diagram:
+ *
+ * GF1
+ * +---------+ digital
+ * | | record ASIC
+ * | |--------------+
+ * | | | +--------+
+ * | | play (dram) | +----+ | |
+ * | |--------------(------|-\ | | +-+ |
+ * +---------+ | | >-|----|---|C|--|------ dma chan 1
+ * | +---|-/ | | +-+ |
+ * | | +----+ | | |
+ * | | +----+ | | |
+ * +---------+ +-+ +--(---|-\ | | | |
+ * | | play |8| | | >-|----|----+---|------ dma chan 2
+ * | ---C----|--------|/|------(---|-/ | | |
+ * | ^ |record |1| | +----+ | |
+ * | | | /----|6|------+ +--------+
+ * | ---+----|--/ +-+
+ * +---------+
+ * CS4231 8-to-16 bit bus conversion, if needed
+ *
+ *
+ * "C" is an optional combiner.
+ *
+ */
+
+/*
+ * Software state of a single "voice" on the GUS
+ */
+struct gus_voice {
+
+ /*
+ * Various control bits
+ */
+
+ unsigned char voccntl; /* State of voice control register */
+ unsigned char volcntl; /* State of volume control register */
+ unsigned char pan_pos; /* Position of volume panning (4 bits) */
+ int rate; /* Sample rate of voice being played back */
+
+ /*
+ * Address of the voice data into the GUS's DRAM. 20 bits each
+ */
+
+ u_long start_addr; /* Starting address of voice data loop area */
+ u_long end_addr; /* Ending address of voice data loop */
+ u_long current_addr; /* Beginning address of voice data
+ (start playing here) */
+
+ /*
+ * linear volume values for the GUS's volume ramp. 0-511 (9 bits).
+ * These values must be translated into the logarithmic values using
+ * gus_log_volumes[]
+ */
+
+ int start_volume; /* Starting position of volume ramp */
+ int current_volume; /* Current position of volume on volume ramp */
+ int end_volume; /* Ending position of volume on volume ramp */
+};
+
+/*
+ * Software state of GUS
+ */
+struct gus_softc {
+ struct device sc_dev; /* base device */
+ struct device *sc_isa; /* pointer to ISA parent */
+ void *sc_ih; /* interrupt vector */
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_ioh1; /* handle */
+ bus_space_handle_t sc_ioh2; /* handle */
+ bus_space_handle_t sc_ioh3; /* ICS2101 handle */
+ bus_space_handle_t sc_ioh4; /* MIDI handle */
+
+ int sc_iobase; /* I/O base address */
+ int sc_irq; /* IRQ used */
+ int sc_drq; /* DMA channel for play */
+ int sc_recdrq; /* DMA channel for recording */
+
+ int sc_flags; /* Various flags about the GUS */
+#define GUS_MIXER_INSTALLED 0x01 /* An ICS mixer is installed */
+#define GUS_LOCKED 0x02 /* GUS is busy doing multi-phase DMA */
+#define GUS_CODEC_INSTALLED 0x04 /* CS4231 installed/MAX */
+#define GUS_PLAYING 0x08 /* GUS is playing a voice */
+#define GUS_DMAOUT_ACTIVE 0x10 /* GUS is busy doing audio DMA */
+#define GUS_DMAIN_ACTIVE 0x20 /* GUS is busy sampling */
+#define GUS_OPEN 0x100 /* GUS is open */
+ int sc_dsize; /* Size of GUS DRAM */
+ int sc_voices; /* Number of active voices */
+ u_char sc_revision; /* Board revision of GUS */
+ u_char sc_mixcontrol; /* Value of GUS_MIX_CONTROL register */
+
+ u_long sc_orate; /* Output sampling rate */
+ u_long sc_irate; /* Input sampling rate */
+
+ int sc_encoding; /* Current data encoding type */
+ int sc_precision; /* # of bits of precision */
+ int sc_channels; /* Number of active channels */
+ int sc_blocksize; /* Current blocksize */
+ int sc_chanblocksize; /* Current blocksize for each in-use
+ channel */
+ short sc_nbufs; /* how many on-GUS bufs per-channel */
+ short sc_bufcnt; /* how many need to be played */
+ void *sc_deintr_buf; /* deinterleave buffer for stereo */
+
+ int sc_ogain; /* Output gain control */
+ u_char sc_out_port; /* Current out port (generic only) */
+ u_char sc_in_port; /* keep track of it when no codec */
+
+ void (*sc_dmaoutintr) __P((void*)); /* DMA completion intr handler */
+ void *sc_outarg; /* argument for sc_dmaoutintr() */
+ u_char *sc_dmaoutaddr; /* for isadma_done */
+ u_long sc_gusaddr; /* where did we just put it? */
+ int sc_dmaoutcnt; /* for isadma_done */
+
+ void (*sc_dmainintr) __P((void*)); /* DMA completion intr handler */
+ void *sc_inarg; /* argument for sc_dmaoutintr() */
+ u_char *sc_dmainaddr; /* for isadma_done */
+ int sc_dmaincnt; /* for isadma_done */
+
+ struct stereo_dma_intr {
+ void (*intr)__P((void *));
+ void *arg;
+ u_char *buffer;
+ u_long dmabuf;
+ int size;
+ int flags;
+ } sc_stereo;
+
+ /*
+ * State information for linear audio layer
+ */
+
+ int sc_dmabuf; /* Which ring buffer we're DMA'ing to */
+ int sc_playbuf; /* Which ring buffer we're playing */
+
+ /*
+ * Voice information array. All voice-specific information is stored
+ * here
+ */
+
+ struct gus_voice sc_voc[32]; /* Voice data for each voice */
+ union {
+ struct ics2101_softc sc_mixer_u;
+ struct ad1848_softc sc_codec_u;
+ } u;
+#define sc_mixer u.sc_mixer_u
+#define sc_codec u.sc_codec_u
+};
+
+struct ics2101_volume {
+ u_char left;
+ u_char right;
+};
+
+#define HAS_CODEC(sc) ((sc)->sc_flags & GUS_CODEC_INSTALLED)
+#define HAS_MIXER(sc) ((sc)->sc_flags & GUS_MIXER_INSTALLED)
+
+/*
+ * Mixer devices for ICS2101
+ */
+/* MIC IN mute, line in mute, line out mute are first since they can be done
+ even if no ICS mixer. */
+#define GUSICS_MIC_IN_MUTE 0
+#define GUSICS_LINE_IN_MUTE 1
+#define GUSICS_MASTER_MUTE 2
+#define GUSICS_CD_MUTE 3
+#define GUSICS_DAC_MUTE 4
+#define GUSICS_MIC_IN_LVL 5
+#define GUSICS_LINE_IN_LVL 6
+#define GUSICS_CD_LVL 7
+#define GUSICS_DAC_LVL 8
+#define GUSICS_MASTER_LVL 9
+
+#define GUSICS_RECORD_SOURCE 10
+
+/* Classes */
+#define GUSICS_INPUT_CLASS 11
+#define GUSICS_OUTPUT_CLASS 12
+#define GUSICS_RECORD_CLASS 13
+
+/*
+ * Mixer & MUX devices for CS4231
+ */
+#define GUSMAX_MONO_LVL 0 /* mic input to MUX;
+ also mono mixer input */
+#define GUSMAX_DAC_LVL 1 /* input to MUX; also mixer input */
+#define GUSMAX_LINE_IN_LVL 2 /* input to MUX; also mixer input */
+#define GUSMAX_CD_LVL 3 /* mixer input only */
+#define GUSMAX_MONITOR_LVL 4 /* digital mix (?) */
+#define GUSMAX_OUT_LVL 5 /* output level. (?) */
+#define GUSMAX_SPEAKER_LVL 6 /* pseudo-device for mute */
+#define GUSMAX_LINE_IN_MUTE 7 /* pre-mixer */
+#define GUSMAX_DAC_MUTE 8 /* pre-mixer */
+#define GUSMAX_CD_MUTE 9 /* pre-mixer */
+#define GUSMAX_MONO_MUTE 10 /* pre-mixer--microphone/mono */
+#define GUSMAX_MONITOR_MUTE 11 /* post-mixer level/mute */
+#define GUSMAX_SPEAKER_MUTE 12 /* speaker mute */
+
+#define GUSMAX_REC_LVL 13 /* post-MUX gain */
+
+#define GUSMAX_RECORD_SOURCE 14
+
+/* Classes */
+#define GUSMAX_INPUT_CLASS 15
+#define GUSMAX_RECORD_CLASS 16
+#define GUSMAX_MONITOR_CLASS 17
+#define GUSMAX_OUTPUT_CLASS 18
+
+#ifdef AUDIO_DEBUG
+#define GUSPLAYDEBUG /*XXX*/
+#define DPRINTF(x) if (gusdebug) printf x
+#define DMAPRINTF(x) if (gusdmadebug) printf x
+extern int gusdebug = 0;
+extern int gusdmadebug = 0;
+#else
+#define DPRINTF(x)
+#define DMAPRINTF(x)
+#endif
+extern int gus_dostereo;
+
+#define NDMARECS 2048
+#ifdef GUSPLAYDEBUG
+extern int gusstats = 0;
+struct dma_record {
+ struct timeval tv;
+ u_long gusaddr;
+ caddr_t bsdaddr;
+ u_short count;
+ u_char channel;
+ u_char direction;
+};
+
+extern struct dma_record dmarecords[NDMARECS];
+
+extern int dmarecord_index = 0;
+#endif
+
+/*
+ * local routines
+ */
+
+int gusopen __P((void *, int));
+void gusclose __P((void *));
+void gusmax_close __P((void *));
+int gusintr __P((void *));
+int gus_set_in_gain __P((caddr_t, u_int, u_char));
+int gus_get_in_gain __P((caddr_t));
+int gus_set_out_gain __P((caddr_t, u_int, u_char));
+int gus_get_out_gain __P((caddr_t));
+int gus_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
+int gusmax_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
+int gus_round_blocksize __P((void *, int));
+int gus_commit_settings __P((void *));
+int gus_dma_output __P((void *, void *, int, void (*)(void *), void *));
+int gus_dma_input __P((void *, void *, int, void (*)(void *), void *));
+int gus_halt_out_dma __P((void *));
+int gus_halt_in_dma __P((void *));
+int gus_speaker_ctl __P((void *, int));
+int gusmaxopen __P((void *, int));
+int gusmax_round_blocksize __P((void *, int));
+int gusmax_commit_settings __P((void *));
+int gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *));
+int gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *));
+int gusmax_halt_out_dma __P((void *));
+int gusmax_halt_in_dma __P((void *));
+int gusmax_speaker_ctl __P((void *, int));
+int gus_getdev __P((void *, struct audio_device *));
+
+void gus_deinterleave __P((struct gus_softc *, void *, int));
+
+int gus_mic_ctl __P((void *, int));
+int gus_linein_ctl __P((void *, int));
+int gus_test_iobase __P((bus_space_tag_t, int));
+void guspoke __P((bus_space_tag_t, bus_space_handle_t, long, u_char));
+void gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int));
+int gus_init_cs4231 __P((struct gus_softc *));
+void gus_init_ics2101 __P((struct gus_softc *));
+
+void gus_set_chan_addrs __P((struct gus_softc *));
+void gusreset __P((struct gus_softc *, int));
+void gus_set_voices __P((struct gus_softc *, int));
+void gus_set_volume __P((struct gus_softc *, int, int));
+void gus_set_samprate __P((struct gus_softc *, int, int));
+void gus_set_recrate __P((struct gus_softc *, u_long));
+void gus_start_voice __P((struct gus_softc *, int, int));
+void gus_stop_voice __P((struct gus_softc *, int, int));
+void gus_set_endaddr __P((struct gus_softc *, int, u_long));
+#ifdef GUSPLAYDEBUG
+void gus_set_curaddr __P((struct gus_softc *, int, u_long));
+u_long gus_get_curaddr __P((struct gus_softc *, int));
+#endif
+int gus_dmaout_intr __P((struct gus_softc *));
+void gus_dmaout_dointr __P((struct gus_softc *));
+void gus_dmaout_timeout __P((void *));
+int gus_dmain_intr __P((struct gus_softc *));
+int gus_voice_intr __P((struct gus_softc *));
+void gus_start_playing __P((struct gus_softc *, int));
+int gus_continue_playing __P((struct gus_softc *, int));
+u_char guspeek __P((bus_space_tag_t, bus_space_handle_t, u_long));
+u_long convert_to_16bit __P((u_long));
+int gus_mixer_set_port __P((void *, mixer_ctrl_t *));
+int gus_mixer_get_port __P((void *, mixer_ctrl_t *));
+int gusmax_mixer_set_port __P((void *, mixer_ctrl_t *));
+int gusmax_mixer_get_port __P((void *, mixer_ctrl_t *));
+int gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
+int gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
+int gus_query_encoding __P((void *, struct audio_encoding *));
+int gus_get_props __P((void *));
+int gusmax_get_props __P((void *));
+
+void gusics_master_mute __P((struct ics2101_softc *, int));
+void gusics_dac_mute __P((struct ics2101_softc *, int));
+void gusics_mic_mute __P((struct ics2101_softc *, int));
+void gusics_linein_mute __P((struct ics2101_softc *, int));
+void gusics_cd_mute __P((struct ics2101_softc *, int));
+
+void stereo_dmaintr __P((void *));
+
+extern int gus_irq_map[];
+extern int gus_drq_map[];
+extern int gus_base_addrs[];
+extern int gus_addrs;
+extern int gus_max_frequency[];
+
+extern unsigned short gus_log_volumes[];
+
+#define SELECT_GUS_REG(iot,ioh1,x) bus_space_write_1(iot,ioh1,GUS_REG_SELECT,x)
+#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
+#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
+
+#define GUS_MIN_VOICES 14 /* Minimum possible number of voices */
+#define GUS_MAX_VOICES 32 /* Maximum possible number of voices */
+#define GUS_VOICE_LEFT 0 /* Voice used for left (and mono) playback */
+#define GUS_VOICE_RIGHT 1 /* Voice used for right playback */
+#define GUS_MEM_OFFSET 32 /* Offset into GUS memory to begin of buffer */
+#define GUS_BUFFER_MULTIPLE 1024 /* Audio buffers are multiples of this */
+#define GUS_MEM_FOR_BUFFERS 131072 /* use this many bytes on-GUS */
+#define GUS_LEFT_RIGHT_OFFSET (sc->sc_nbufs * sc->sc_chanblocksize + GUS_MEM_OFFSET)
+
+#define GUS_PREC_BYTES (sc->sc_precision >> 3) /* precision to bytes */
+
+/* splgus() must be splaudio() */
+
+#define splgus splaudio
+
+extern struct audio_hw_if gus_hw_if;
+extern struct audio_hw_if gusmax_hw_if;
+extern struct audio_device gus_device;
+
+#define FLIP_REV 5 /* This rev has flipped mixer chans */
+
+void gus_subattach __P((struct gus_softc *, struct isa_attach_args *));
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index e522f7e5dc1..ebab4a5a47f 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isavar.h,v 1.36 1999/06/22 16:28:27 espie Exp $ */
+/* $OpenBSD: isavar.h,v 1.37 1999/07/05 20:08:37 deraadt Exp $ */
/* $NetBSD: isavar.h,v 1.26 1997/06/06 23:43:57 thorpej Exp $ */
/*-
@@ -194,12 +194,16 @@ ERROR: COMPILING ISAPNP FOR UNSUPPORTED MACHINE, OR MORE THAN ONE.
*/
struct isapnp_softc {
struct device sc_dev;
- int sc_read_port;
- bus_space_tag_t sc_iot;
- bus_space_tag_t sc_memt;
+ TAILQ_HEAD(, isadev)
+ sc_subdevs; /* list of all children */
+
+ bus_space_tag_t sc_iot; /* isa io space tag */
+ bus_space_tag_t sc_memt; /* isa mem space tag */
#if NISADMA > 0
- bus_dma_tag_t sc_dmat;
-#endif
+ bus_dma_tag_t sc_dmat; /* isa DMA tag */
+#endif /* NISADMA > 0 */
+
+ int sc_read_port;
bus_space_handle_t sc_addr_ioh;
bus_space_handle_t sc_wrdata_ioh;
bus_space_handle_t sc_read_ioh;