summaryrefslogtreecommitdiffstats
path: root/sys/dev/isa
diff options
context:
space:
mode:
authorprovos <provos@openbsd.org>1998-04-26 21:02:37 +0000
committerprovos <provos@openbsd.org>1998-04-26 21:02:37 +0000
commite99cab2be4365da63b86b0d86d6cce79f3103c64 (patch)
tree33a2d4aa3f5856eca15ef5c699b9965fbacbe977 /sys/dev/isa
parenthandle ENOSPC as an end-of-tape marker; gibbs@narnia.plutotech.com (diff)
downloadwireguard-openbsd-e99cab2be4365da63b86b0d86d6cce79f3103c64.tar.xz
wireguard-openbsd-e99cab2be4365da63b86b0d86d6cce79f3103c64.zip
update audio from NetBSD, mostly by Lennart Augustsson <augustss@cs.chalmers.se>
Diffstat (limited to 'sys/dev/isa')
-rw-r--r--sys/dev/isa/ad1848.c759
-rw-r--r--sys/dev/isa/ad1848var.h50
-rw-r--r--sys/dev/isa/files.isa18
-rw-r--r--sys/dev/isa/gus.c1956
-rw-r--r--sys/dev/isa/gusreg.h45
-rw-r--r--sys/dev/isa/ics2101.c17
-rw-r--r--sys/dev/isa/ics2101var.h11
-rw-r--r--sys/dev/isa/isa.c19
-rw-r--r--sys/dev/isa/isavar.h4
-rw-r--r--sys/dev/isa/madreg.h102
-rw-r--r--sys/dev/isa/mcd.c204
-rw-r--r--sys/dev/isa/mcdreg.h5
-rw-r--r--sys/dev/isa/pas.c116
-rw-r--r--sys/dev/isa/pnpdevs3
-rw-r--r--sys/dev/isa/pnpdevs.h1
-rw-r--r--sys/dev/isa/pss.c209
-rw-r--r--sys/dev/isa/sb.c119
-rw-r--r--sys/dev/isa/sb_isa.c82
-rw-r--r--sys/dev/isa/sb_isapnp.c21
-rw-r--r--sys/dev/isa/sbdsp.c2439
-rw-r--r--sys/dev/isa/sbdspvar.h183
-rw-r--r--sys/dev/isa/sbreg.h95
-rw-r--r--sys/dev/isa/wss.c441
-rw-r--r--sys/dev/isa/wss_isa.c376
-rw-r--r--sys/dev/isa/wssvar.h83
25 files changed, 4219 insertions, 3139 deletions
diff --git a/sys/dev/isa/ad1848.c b/sys/dev/isa/ad1848.c
index 9a7ed0fc629..2e3e495d4cf 100644
--- a/sys/dev/isa/ad1848.c
+++ b/sys/dev/isa/ad1848.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ad1848.c,v 1.9 1998/01/18 18:58:36 niklas Exp $ */
-/* $NetBSD: ad1848.c,v 1.10 1996/04/29 20:02:32 christos Exp $ */
+/* $OpenBSD: ad1848.c,v 1.10 1998/04/26 21:02:38 provos Exp $ */
+/* $NetBSD: ad1848.c,v 1.45 1998/01/30 02:02:38 augustss Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -67,11 +67,6 @@
* Portions also supplied from the SoundBlaster driver for NetBSD.
*/
-/*
- * Todo:
- * - Need datasheet for CS4231 (for use with GUS MAX)
- * - Use fast audio_dma
- */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
@@ -82,10 +77,14 @@
#include <sys/buf.h>
#include <machine/cpu.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
+#include <vm/vm.h>
+
#include <dev/audio_if.h>
+#include <dev/auconv.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -96,8 +95,7 @@
#include <dev/isa/cs4231var.h>
#ifdef AUDIO_DEBUG
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (ad1848debug) Dprintf x
+#define DPRINTF(x) if (ad1848debug) printf x
int ad1848debug = 0;
#else
#define DPRINTF(x)
@@ -144,12 +142,13 @@ static int ad1848_init_values[] = {
MONO_INPUT_MUTE|ATTEN_6, /* mute mic by default */
0, /* unused */
0, /* record format */
+ 0, /* Crystal Clock Select */
0, /* upper record count */
0 /* lower record count */
};
void ad1848_reset __P((struct ad1848_softc *));
-int ad1848_set_speed __P((struct ad1848_softc *, u_long));
+int ad1848_set_speed __P((struct ad1848_softc *, u_long *));
void ad1848_mute_monitor __P((void *, int));
static int ad_read __P((struct ad1848_softc *, int));
@@ -157,6 +156,8 @@ static __inline void ad_write __P((struct ad1848_softc *, int, int));
static void ad_set_MCE __P((struct ad1848_softc *, int));
static void wait_for_calibration __P((struct ad1848_softc *));
+#define ADREAD(sc, addr) bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_iooffs+(addr))
+#define ADWRITE(sc, addr, data) bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_iooffs+(addr), (data))
static int
ad_read(sc, reg)
@@ -165,8 +166,8 @@ ad_read(sc, reg)
{
int x;
- outb(sc->sc_iobase+AD1848_IADDR, (u_char) (reg & 0xff) | sc->MCE_bit);
- x = inb(sc->sc_iobase+AD1848_IDATA);
+ ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
+ x = ADREAD(sc, AD1848_IDATA);
/* printf("(%02x<-%02x) ", reg|sc->MCE_bit, x); */
return x;
@@ -178,8 +179,8 @@ ad_write(sc, reg, data)
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));
+ ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
+ ADWRITE(sc, AD1848_IDATA, data & 0xff);
/* printf("(%02x->%02x) ", reg|sc->MCE_bit, data); */
}
@@ -193,14 +194,14 @@ ad_set_MCE(sc, state)
else
sc->MCE_bit = 0;
- outb(sc->sc_iobase+AD1848_IADDR, sc->MCE_bit);
+ ADWRITE(sc, AD1848_IADDR, sc->MCE_bit);
}
static void
wait_for_calibration(sc)
struct ad1848_softc *sc;
{
- int timeout = 100000;
+ int timeout;
DPRINTF(("ad1848: Auto calibration started.\n"));
/*
@@ -209,18 +210,19 @@ wait_for_calibration(sc)
* 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 = 100000;
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
timeout--;
- if (inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
DPRINTF(("ad1848: Auto calibration timed out(1).\n"));
- outb(sc->sc_iobase+AD1848_IADDR, SP_TEST_AND_INIT);
+ ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
timeout = 100000;
- while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) != SP_TEST_AND_INIT)
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) != SP_TEST_AND_INIT)
timeout--;
- if (inb(sc->sc_iobase+AD1848_IADDR) == SP_TEST_AND_INIT)
+ if (ADREAD(sc, AD1848_IADDR) == SP_TEST_AND_INIT)
DPRINTF(("ad1848: Auto calibration timed out(1.5).\n"));
if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) {
@@ -249,7 +251,7 @@ ad1848_dump_regs(sc)
int i;
u_char r;
- printf("ad1848 status=%02x", inb(sc->sc_iobase+AD1848_STATUS));
+ printf("ad1848 status=%02x", ADREAD(sc, AD1848_STATUS));
printf(" regs: ");
for (i = 0; i < 16; i++) {
r = ad_read(sc, i);
@@ -260,8 +262,8 @@ ad1848_dump_regs(sc)
r = ad_read(sc, i);
printf("%02x ", r);
}
- printf("\n");
}
+ printf("\n");
}
#endif
@@ -283,7 +285,8 @@ ad1848_forceintr(sc)
* it is needed (and you pay the latency). Also, you might
* never need the buffer anyway.)
*/
- isadma_start(&dmabuf, 1, sc->sc_drq, DMAMODE_READ);
+ isa_dmastart(sc->sc_isa, sc->sc_drq, &dmabuf, 1, NULL,
+ DMAMODE_READ, BUS_DMA_NOWAIT);
ad_write(sc, SP_LOWER_BASE_COUNT, 0);
ad_write(sc, SP_UPPER_BASE_COUNT, 0);
@@ -292,16 +295,13 @@ ad1848_forceintr(sc)
#endif
/*
- * Probe for the ad1848 chip
+ * Map and probe for the ad1848 chip
*/
int
-ad1848_probe(sc)
+ad1848_mapprobe(sc, iobase)
struct ad1848_softc *sc;
+ int iobase;
{
- register int iobase = sc->sc_iobase;
- u_char tmp, tmp1 = 0xff, tmp2 = 0xff;
- int i;
-
if (!AD1848_BASE_VALID(iobase)) {
#ifdef AUDIO_DEBUG
printf("ad1848: configured iobase %04x invalid\n", iobase);
@@ -309,8 +309,28 @@ ad1848_probe(sc)
return 0;
}
- sc->sc_iobase = iobase;
+ sc->sc_iooffs = 0;
+ /* Map the AD1848 ports */
+ if (bus_space_map(sc->sc_iot, iobase, AD1848_NPORT, 0, &sc->sc_ioh))
+ return 0;
+
+ if (!ad1848_probe(sc)) {
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT);
+ return 0;
+ } else
+ return 1;
+}
+/*
+ * Probe for the ad1848 chip
+ */
+int
+ad1848_probe(sc)
+ struct ad1848_softc *sc;
+{
+ u_char tmp, tmp1 = 0xff, tmp2 = 0xff;
+ int i;
+
/* Is there an ad1848 chip ? */
sc->MCE_bit = MODE_CHANGE_ENABLE;
sc->mode = 1; /* MODE 1 = original ad1848/ad1846/cs4248 */
@@ -324,11 +344,12 @@ ad1848_probe(sc)
*
* If the I/O address is unused, inb() typically returns 0xff.
*/
- if (((tmp = inb(iobase+AD1848_IADDR)) & SP_IN_INIT) != 0x00) { /* Not a AD1848 */
+ tmp = ADREAD(sc, AD1848_IADDR);
+ if (tmp & SP_IN_INIT) { /* Not a AD1848 */
#if 0
DPRINTF(("ad_detect_A %x\n", tmp));
#endif
- return 0;
+ goto bad;
}
/*
@@ -342,7 +363,7 @@ ad1848_probe(sc)
if ((tmp1 = ad_read(sc, 0)) != 0xaa ||
(tmp2 = ad_read(sc, 1)) != 0x45) {
DPRINTF(("ad_detect_B (%x/%x)\n", tmp1, tmp2));
- return 0;
+ goto bad;
}
ad_write(sc, 0, 0x45);
@@ -351,7 +372,7 @@ ad1848_probe(sc)
if ((tmp1 = ad_read(sc, 0)) != 0x45 ||
(tmp2 = ad_read(sc, 1)) != 0xaa) {
DPRINTF(("ad_detect_C (%x/%x)\n", tmp1, tmp2));
- return 0;
+ goto bad;
}
/*
@@ -363,7 +384,7 @@ ad1848_probe(sc)
if ((tmp & 0x0f) != ((tmp1 = ad_read(sc, SP_MISC_INFO)) & 0x0f)) {
DPRINTF(("ad_detect_D (%x)\n", tmp1));
- return 0;
+ goto bad;
}
/*
@@ -412,7 +433,7 @@ ad1848_probe(sc)
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;
+ goto bad;
}
/*
@@ -435,7 +456,7 @@ ad1848_probe(sc)
ad_write(sc, 2, 0xaa);
if ((tmp2 = ad_read(sc, 18)) == 0xaa) { /* Rotten bits? */
DPRINTF(("ad_detect_H(%x)\n", tmp2));
- return 0;
+ goto bad;
}
/*
@@ -462,13 +483,25 @@ ad1848_probe(sc)
}
/* Wait for 1848 to init */
- while(inb(sc->sc_iobase+AD1848_IADDR) & SP_IN_INIT);
+ while(ADREAD(sc, 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);
+ ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
+ while(ADREAD(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG)
+ ;
return 1;
+bad:
+ return 0;
+}
+
+/* Unmap the I/O ports */
+void
+ad1848_unmap(sc)
+ struct ad1848_softc *sc;
+{
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT);
}
/*
@@ -480,28 +513,56 @@ ad1848_attach(sc)
struct ad1848_softc *sc;
{
int i;
- struct ad1848_volume vol_mid = {150, 150};
+ struct ad1848_volume vol_mid = {220, 220};
struct ad1848_volume vol_0 = {0, 0};
+ struct audio_params pparams, rparams;
+ int timeout;
sc->sc_locked = 0;
+ sc->sc_playrun = NOTRUNNING;
+ sc->sc_recrun = NOTRUNNING;
+
+ if (sc->sc_drq != -1) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq, MAX_ISADMA,
+ BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("ad1848_attach: can't create map for drq %d\n",
+ 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("ad1848_attach: can't creape map for drq %d\n",
+ sc->sc_recdrq);
+ return;
+ }
+ }
/* Initialize the ad1848... */
- for (i = 0; i < 16; i++)
+ for (i = 0; i < 0x10; i++) {
ad_write(sc, i, ad1848_init_values[i]);
+ timeout = 100000;
+ while (timeout > 0 && ad_read(sc, AD1848_IADDR) & SP_IN_INIT)
+ timeout--;
+ }
/* ...and additional CS4231 stuff too */
if (sc->mode == 2) {
ad_write(sc, SP_INTERFACE_CONFIG, 0); /* disable SINGLE_DMA */
- for (i = 0x10; i <= 0x1f; i++)
- if (ad1848_init_values[i] != 0)
+ for (i = 0x10; i < 0x20; i++)
+ if (ad1848_init_values[i] != 0) {
ad_write(sc, i, ad1848_init_values[i]);
+ timeout = 100000;
+ while (timeout > 0 &&
+ ad_read(sc, AD1848_IADDR) & SP_IN_INIT)
+ timeout--;
+ }
}
ad1848_reset(sc);
- /* Set default parameters (mono, 8KHz, ULAW) */
- (void) ad1848_set_channels(sc, 1);
- (void) ad1848_set_speed(sc, 8000);
- (void) ad1848_set_format(sc, AUDIO_ENCODING_ULAW, 8);
- (void) ad1848_commit_settings(sc);
+ pparams = audio_default;
+ rparams = audio_default;
+ (void) ad1848_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
/* Set default gains */
(void) ad1848_set_rec_gain(sc, &vol_mid);
@@ -520,6 +581,7 @@ ad1848_attach(sc)
(void) ad1848_set_rec_port(sc, MIC_IN_PORT);
printf(": %s", sc->chip_name);
+#undef WAITREADY
}
/*
@@ -527,10 +589,10 @@ ad1848_attach(sc)
*/
int
ad1848_set_rec_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
- register u_char reg, gain;
+ u_char reg, gain;
DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right));
@@ -551,7 +613,7 @@ ad1848_set_rec_gain(sc, gp)
int
ad1848_get_rec_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->rec_gain;
@@ -560,7 +622,7 @@ ad1848_get_rec_gain(sc, gp)
int
ad1848_set_out_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -585,7 +647,7 @@ ad1848_set_out_gain(sc, gp)
int
ad1848_get_out_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->out_gain;
@@ -594,7 +656,7 @@ ad1848_get_out_gain(sc, gp)
int
ad1848_set_mon_gain(sc, gp) /* monitor gain */
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -613,7 +675,7 @@ ad1848_set_mon_gain(sc, gp) /* monitor gain */
int
ad1848_get_mon_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->mon_gain;
@@ -622,7 +684,7 @@ ad1848_get_mon_gain(sc, gp)
int
cs4231_set_mono_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg, oreg;
@@ -642,7 +704,7 @@ cs4231_set_mono_gain(sc, gp)
int
cs4231_get_mono_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->mono_gain;
@@ -651,7 +713,7 @@ cs4231_get_mono_gain(sc, gp)
int
ad1848_set_mic_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -673,7 +735,7 @@ ad1848_set_mic_gain(sc, gp)
int
ad1848_get_mic_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
if (sc->mic_gain_on)
@@ -688,7 +750,7 @@ ad1848_mute_monitor(addr, mute)
void *addr;
int mute;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
DPRINTF(("ad1848_mute_monitor: %smuting\n", mute ? "" : "un"));
if (sc->mode == 2) {
@@ -703,7 +765,7 @@ ad1848_mute_monitor(addr, mute)
void
cs4231_mute_monitor(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -724,7 +786,7 @@ cs4231_mute_monitor(sc, mute)
void
cs4231_mute_mono(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -741,7 +803,7 @@ cs4231_mute_mono(sc, mute)
void
cs4231_mute_line(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -762,7 +824,7 @@ cs4231_mute_line(sc, mute)
void
ad1848_mute_aux1(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -783,7 +845,7 @@ ad1848_mute_aux1(sc, mute)
void
ad1848_mute_aux2(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -804,7 +866,7 @@ ad1848_mute_aux2(sc, mute)
int
ad1848_set_aux1_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -829,7 +891,7 @@ ad1848_set_aux1_gain(sc, gp)
int
ad1848_get_aux1_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->aux1_gain;
@@ -838,7 +900,7 @@ ad1848_get_aux1_gain(sc, gp)
int
cs4231_set_linein_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg, oregl, oregr;
@@ -864,7 +926,7 @@ cs4231_set_linein_gain(sc, gp)
int
cs4231_get_linein_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->line_gain;
@@ -873,7 +935,7 @@ cs4231_get_linein_gain(sc, gp)
int
ad1848_set_aux2_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -898,7 +960,7 @@ ad1848_set_aux2_gain(sc, gp)
int
ad1848_get_aux2_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->aux2_gain;
@@ -906,161 +968,177 @@ ad1848_get_aux2_gain(sc, gp)
}
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));
-
- return (ad1848_set_speed(sc, sr));
-}
-
-u_long
-ad1848_get_in_sr(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
-
- return (sc->speed);
-}
-
-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));
-
- return (ad1848_set_speed(sc, sr));
-}
-
-u_long
-ad1848_get_out_sr(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
-
- return (sc->speed);
-}
-
-int
ad1848_query_encoding(addr, fp)
void *addr;
struct audio_encoding *fp;
{
+ struct ad1848_softc *sc = addr;
+
switch (fp->index) {
case 0:
strcpy(fp->name, AudioEmulaw);
- fp->format_id = AUDIO_ENCODING_ULAW;
+ fp->encoding = AUDIO_ENCODING_ULAW;
+ fp->precision = 8;
+ fp->flags = 0;
break;
case 1:
strcpy(fp->name, AudioEalaw);
- fp->format_id = AUDIO_ENCODING_ALAW;
+ fp->encoding = AUDIO_ENCODING_ALAW;
+ fp->precision = 8;
+ fp->flags = 0;
break;
case 2:
- strcpy(fp->name, AudioEpcm16);
- fp->format_id = AUDIO_ENCODING_PCM16;
+ strcpy(fp->name, AudioEslinear_le);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
break;
case 3:
- strcpy(fp->name, AudioEpcm8);
- fp->format_id = AUDIO_ENCODING_PCM8;
+ strcpy(fp->name, AudioEulinear);
+ fp->encoding = AUDIO_ENCODING_ULINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
+ break;
+
+ case 4: /* only on CS4231 */
+ strcpy(fp->name, AudioEslinear_be);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ fp->precision = 16;
+ fp->flags = sc->mode == 1 ? AUDIO_ENCODINGFLAG_EMULATED : 0;
+ break;
+
+ /* emulate some modes */
+ case 5:
+ strcpy(fp->name, AudioEslinear);
+ fp->encoding = AUDIO_ENCODING_SLINEAR;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 6:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 7:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+
+ case 8: /* only on CS4231 */
+ if (sc->mode == 1)
+ return EINVAL;
+ strcpy(fp->name, AudioEadpcm);
+ fp->encoding = AUDIO_ENCODING_ADPCM;
+ fp->precision = 8;
+ fp->flags = 0;
break;
default:
- return(EINVAL);
+ return EINVAL;
/*NOTREACHED*/
}
return (0);
}
int
-ad1848_set_format(addr, encoding, precision)
+ad1848_set_params(addr, setmode, usemode, p, r)
void *addr;
- u_int encoding, precision;
+ int setmode, usemode;
+ struct audio_params *p, *r;
{
- register struct ad1848_softc *sc = addr;
- static u_char format2bits[] = {
- /* AUDIO_ENCODING_NONE */ 0,
- /* AUDIO_ENCODING_ULAW */ FMT_ULAW >> 5,
- /* AUDIO_ENCODING_ALAW */ FMT_ALAW >> 5,
- /* AUDIO_ENCODING_PCM16 */ FMT_TWOS_COMP >> 5,
- /* AUDIO_ENCODING_PCM8 */ FMT_PCM8 >> 5,
- /* AUDIO_ENCODING_ADPCM */ 0,
- };
-
- DPRINTF(("ad1848_set_format: encoding=%d precision=%d\n", encoding, precision));
-
- switch (encoding) {
+ struct ad1848_softc *sc = addr;
+ int error, bits, enc;
+ void (*pswcode) __P((void *, u_char *buf, int cnt));
+ void (*rswcode) __P((void *, u_char *buf, int cnt));
+
+ DPRINTF(("ad1848_set_params: %d %d %d %ld\n",
+ p->encoding, p->precision, p->channels, p->sample_rate));
+
+ enc = p->encoding;
+ pswcode = rswcode = 0;
+ switch (enc) {
+ case AUDIO_ENCODING_SLINEAR_LE:
+ if (p->precision == 8) {
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ pswcode = rswcode = change_sign8;
+ }
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (p->precision == 16 && sc->mode == 1) {
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ pswcode = rswcode = swap_bytes;
+ }
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ if (p->precision == 16) {
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ pswcode = rswcode = change_sign16;
+ }
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ if (p->precision == 16) {
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ pswcode = swap_bytes_change_sign16;
+ rswcode = change_sign16_swap_bytes;
+ }
+ break;
+ }
+ switch (enc) {
case AUDIO_ENCODING_ULAW:
+ bits = FMT_ULAW >> 5;
+ break;
case AUDIO_ENCODING_ALAW:
- case AUDIO_ENCODING_PCM16:
- case AUDIO_ENCODING_PCM8:
+ bits = FMT_ALAW >> 5;
+ break;
+ case AUDIO_ENCODING_ADPCM:
+ bits = FMT_ADPCM >> 5;
+ break;
+ case AUDIO_ENCODING_SLINEAR_LE:
+ if (p->precision == 16)
+ bits = FMT_TWOS_COMP >> 5;
+ else
+ return EINVAL;
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (p->precision == 16)
+ bits = FMT_TWOS_COMP_BE >> 5;
+ else
+ return EINVAL;
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ if (p->precision == 8)
+ bits = FMT_PCM8 >> 5;
+ else
+ return EINVAL;
break;
default:
- return (EINVAL);
+ return EINVAL;
}
- sc->encoding = encoding;
- sc->precision = precision;
- sc->format_bits = format2bits[encoding];
- sc->need_commit = 1;
-
- DPRINTF(("ad1848_set_format: bits=%x\n", sc->format_bits));
-
- return (0);
-}
-
-int
-ad1848_get_encoding(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
-
- return (sc->encoding);
-}
-
-int
-ad1848_get_precision(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
+ if (p->channels < 1 || p->channels > 2)
+ return EINVAL;
- return (sc->precision);
-}
-
-int
-ad1848_set_channels(addr, channels)
- void *addr;
- int channels;
-{
- register struct ad1848_softc *sc = addr;
-
- DPRINTF(("ad1848_set_channels: %d\n", channels));
+ error = ad1848_set_speed(sc, &p->sample_rate);
+ if (error)
+ return error;
- if (channels != 1 && channels != 2)
- return (EINVAL);
+ p->sw_code = pswcode;
+ r->sw_code = rswcode;
- sc->channels = channels;
+ sc->format_bits = bits;
+ sc->channels = p->channels;
+ sc->precision = p->precision;
sc->need_commit = 1;
+ DPRINTF(("ad1848_set_params succeeded, bits=%x\n", bits));
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;
+ struct ad1848_softc *sc;
int port;
{
u_char inp, reg;
@@ -1097,7 +1175,7 @@ ad1848_set_rec_port(sc, port)
int
ad1848_get_rec_port(sc)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
{
return(sc->rec_port);
}
@@ -1107,27 +1185,24 @@ ad1848_round_blocksize(addr, blk)
void *addr;
int blk;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
sc->sc_lastcc = -1;
- /* Don't try to DMA too much at once. */
- if (blk > NBPG)
- blk = NBPG;
-
- /* Round to a multiple of the sample size. */
- blk &= -(sc->channels * sc->precision / 8);
+ /* Round to a multiple of the biggest sample size. */
+ blk &= -4;
return (blk);
}
int
-ad1848_open(sc, dev, flags)
- struct ad1848_softc *sc;
- dev_t dev;
+ad1848_open(addr, flags)
+ void *addr;
int flags;
{
- DPRINTF(("ad1848_open: sc=0x%x\n", sc));
+ struct ad1848_softc *sc = addr;
+
+ DPRINTF(("ad1848_open: sc=%p\n", sc));
sc->sc_intr = 0;
sc->sc_lastcc = -1;
@@ -1153,17 +1228,26 @@ ad1848_close(addr)
void *addr;
{
struct ad1848_softc *sc = addr;
- register u_char r;
+ u_char r;
sc->sc_intr = 0;
DPRINTF(("ad1848_close: stop DMA\n"));
+ if (sc->sc_playrun != NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_drq);
+ sc->sc_playrun = NOTRUNNING;
+ }
+ if (sc->sc_recrun != NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_recdrq);
+ sc->sc_recrun = NOTRUNNING;
+ }
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));
+ 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);
@@ -1211,31 +1295,31 @@ ad1848_commit_settings(addr)
/* Gravis Ultrasound MAX SDK sources says something about errata
* sheets, with the implication that these inb()s are necessary.
*/
- (void) inb(sc->sc_iobase+AD1848_IDATA);
- (void) inb(sc->sc_iobase+AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
/*
* Write to I8 starts resyncronization. Wait until it completes.
*/
timeout = 100000;
- while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
timeout--;
ad_write(sc, CS_REC_FORMAT, fs);
/* Gravis Ultrasound MAX SDK sources says something about errata
* sheets, with the implication that these inb()s are necessary.
*/
- (void) inb(sc->sc_iobase+AD1848_IDATA);
- (void) inb(sc->sc_iobase+AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
/* Now wait for resync for capture side of the house */
}
/*
* Write to I8 starts resyncronization. Wait until it completes.
*/
timeout = 100000;
- while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
timeout--;
- if (inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
printf("ad1848_commit: Auto calibration timed out\n");
/*
@@ -1257,7 +1341,7 @@ ad1848_commit_settings(addr)
void
ad1848_reset(sc)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
{
u_char r;
@@ -1269,11 +1353,11 @@ ad1848_reset(sc)
ad_write(sc, SP_INTERFACE_CONFIG, r);
if (sc->mode == 2) {
- outb(sc->sc_iobase+AD1848_IADDR, CS_IRQ_STATUS);
- outb(sc->sc_iobase+AD1848_IDATA, 0);
+ ADWRITE(sc, AD1848_IADDR, CS_IRQ_STATUS);
+ ADWRITE(sc, AD1848_IDATA, 0);
}
/* Clear interrupt status */
- outb(sc->sc_iobase+AD1848_STATUS, 0);
+ ADWRITE(sc, AD1848_STATUS, 0);
#ifdef AUDIO_DEBUG
if (ad1848debug)
ad1848_dump_regs(sc);
@@ -1281,9 +1365,9 @@ ad1848_reset(sc)
}
int
-ad1848_set_speed(sc, arg)
- register struct ad1848_softc *sc;
- u_long arg;
+ad1848_set_speed(sc, argp)
+ struct ad1848_softc *sc;
+ u_long *argp;
{
/*
* The sampling speed is encoded in the least significant nible of I8. The
@@ -1297,6 +1381,7 @@ ad1848_set_speed(sc, arg)
int speed;
u_char bits;
} speed_struct;
+ u_long arg = *argp;
static speed_struct speed_table[] = {
{5510, (0 << 1) | 1},
@@ -1345,9 +1430,9 @@ ad1848_set_speed(sc, arg)
selected = 3;
}
- sc->speed = speed_table[selected].speed;
sc->speed_bits = speed_table[selected].bits;
sc->need_commit = 1;
+ *argp = speed_table[selected].speed;
return (0);
}
@@ -1359,7 +1444,7 @@ int
ad1848_halt_out_dma(addr)
void *addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
u_char reg;
DPRINTF(("ad1848: ad1848_halt_out_dma\n"));
@@ -1375,7 +1460,7 @@ int
ad1848_halt_in_dma(addr)
void *addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
u_char reg;
DPRINTF(("ad1848: ad1848_halt_in_dma\n"));
@@ -1388,33 +1473,21 @@ ad1848_halt_in_dma(addr)
}
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)
+ad1848_dma_init_input(addr, buf, cc)
void *addr;
+ void *buf;
+ int cc;
{
- 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));
+ struct ad1848_softc *sc = addr;
- return(0);
+ sc->sc_recrun = DMARUNNING;
+ sc->sc_dma_flags = DMAMODE_READ | DMAMODE_LOOP;
+ sc->sc_dma_bp = buf;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_recdrq, buf, cc, NULL,
+ sc->sc_dma_flags, BUS_DMA_NOWAIT);
+ DPRINTF(("ad1848_dma_init_input: %p %d\n", buf, cc));
+ return 0;
}
/*
@@ -1428,8 +1501,8 @@ ad1848_dma_input(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct ad1848_softc *sc = addr;
- register u_char reg;
+ struct ad1848_softc *sc = addr;
+ u_char reg;
if (sc->sc_locked) {
DPRINTF(("ad1848_dma_input: locked\n"));
@@ -1438,43 +1511,74 @@ ad1848_dma_input(addr, p, cc, intr, arg)
#ifdef AUDIO_DEBUG
if (ad1848debug > 1)
- Dprintf("ad1848_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ printf("ad1848_dma_input: cc=%d %p (%p)\n", cc, intr, arg);
#endif
sc->sc_locked = 1;
sc->sc_intr = intr;
sc->sc_arg = arg;
- sc->sc_dma_flags = DMAMODE_READ;
- sc->sc_dma_bp = p;
- sc->sc_dma_cnt = cc;
- isadma_start(p, cc, sc->sc_recdrq, DMAMODE_READ);
- if (sc->precision == 16)
- cc >>= 1;
-
- if (sc->channels == 2)
- cc >>= 1;
- cc--;
+ switch (sc->sc_recrun) {
+ case NOTRUNNING:
+ sc->sc_dma_flags = DMAMODE_READ;
+ sc->sc_dma_bp = p;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_recdrq, p, cc, NULL,
+ DMAMODE_READ, BUS_DMA_NOWAIT);
+ goto startpcm;
+ case DMARUNNING:
+ sc->sc_recrun = PCMRUNNING;
+ startpcm:
+ if (sc->precision == 16)
+ cc >>= 1;
+ if (sc->channels == 2)
+ cc >>= 1;
+ cc--;
- if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_RECORD) {
- 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->sc_lastcc != cc || sc->sc_mode != AUMODE_RECORD) {
+ 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, CS_LOWER_REC_CNT, (u_char)(cc & 0xff));
- ad_write(sc, CS_UPPER_REC_CNT, (u_char)((cc >> 8) & 0xff));
- }
+ if (sc->mode == 2) {
+ ad_write(sc, CS_LOWER_REC_CNT, (u_char)(cc & 0xff));
+ ad_write(sc, CS_UPPER_REC_CNT, (u_char)((cc >> 8) & 0xff));
+ }
- reg = ad_read(sc, SP_INTERFACE_CONFIG);
- ad_write(sc, SP_INTERFACE_CONFIG, (CAPTURE_ENABLE|reg));
+ 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;
+ sc->sc_lastcc = cc;
+ sc->sc_mode = AUMODE_RECORD;
+#ifdef AUDIO_DEBUG
+ if (ad1848debug > 1)
+ printf("ad1848_dma_input: started capture\n");
+#endif
+ }
+ case PCMRUNNING:
+ break;
}
return 0;
}
int
+ad1848_dma_init_output(addr, buf, cc)
+ void *addr;
+ void *buf;
+ int cc;
+{
+ struct ad1848_softc *sc = addr;
+
+ sc->sc_playrun = DMARUNNING;
+ sc->sc_dma_flags = DMAMODE_WRITE | DMAMODE_LOOP;
+ sc->sc_dma_bp = buf;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_drq, buf, cc, NULL,
+ sc->sc_dma_flags, BUS_DMA_NOWAIT);
+ DPRINTF(("ad1848_dma_init_output: %p %d\n", buf, cc));
+ return 0;
+}
+
+int
ad1848_dma_output(addr, p, cc, intr, arg)
void *addr;
void *p;
@@ -1482,8 +1586,8 @@ ad1848_dma_output(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct ad1848_softc *sc = addr;
- register u_char reg;
+ struct ad1848_softc *sc = addr;
+ u_char reg;
if (sc->sc_locked) {
DPRINTF(("ad1848_dma_output: locked\n"));
@@ -1491,31 +1595,43 @@ ad1848_dma_output(addr, p, cc, intr, arg)
}
#ifdef AUDIO_DEBUG
- if (ad1848debug > 1)
- Dprintf("ad1848_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ if (ad1848debug > 0)
+ printf("ad1848_dma_output: cc=%d at %p 0x%p (0x%p)\n", cc, p, intr, arg);
#endif
sc->sc_locked = 1;
sc->sc_intr = intr;
sc->sc_arg = arg;
- sc->sc_dma_flags = DMAMODE_WRITE;
- sc->sc_dma_bp = p;
- sc->sc_dma_cnt = cc;
- isadma_start(p, cc, sc->sc_drq, DMAMODE_WRITE);
-
- if (sc->precision == 16)
- cc >>= 1;
-
- if (sc->channels == 2)
- cc >>= 1;
- cc--;
-
- if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_PLAY) {
- 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;
+
+ switch (sc->sc_playrun) {
+ case NOTRUNNING:
+ sc->sc_dma_flags = DMAMODE_WRITE;
+ sc->sc_dma_bp = p;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_drq, p, cc, NULL,
+ DMAMODE_WRITE, BUS_DMA_NOWAIT);
+ goto startpcm;
+ case DMARUNNING:
+ sc->sc_playrun = PCMRUNNING;
+ startpcm:
+ if (sc->precision == 16)
+ cc >>= 1;
+ if (sc->channels == 2)
+ cc >>= 1;
+ cc--;
+
+ if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_PLAY) {
+ 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;
+ }
+ break;
+ case PCMRUNNING:
+ break;
}
return 0;
@@ -1525,16 +1641,16 @@ int
ad1848_intr(arg)
void *arg;
{
- register struct ad1848_softc *sc = arg;
+ struct ad1848_softc *sc = arg;
int retval = 0;
u_char status;
/* Get intr status */
- status = inb(sc->sc_iobase+AD1848_STATUS);
+ status = ADREAD(sc, AD1848_STATUS);
#ifdef AUDIO_DEBUG
if (ad1848debug > 1)
- Dprintf("ad1848_intr: intr=0x%x status=%x\n", sc->sc_intr, status);
+ printf("ad1848_intr: intr=%p status=%x\n", sc->sc_intr, status);
#endif
sc->sc_locked = 0;
sc->sc_interrupts++;
@@ -1543,15 +1659,66 @@ ad1848_intr(arg)
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 & DMAMODE_READ)
- isadma_done(sc->sc_recdrq);
+ if ((sc->sc_dma_flags & DMAMODE_READ) && sc->sc_recrun == NOTRUNNING)
+ isa_dmadone(sc->sc_isa, sc->sc_recdrq);
(*sc->sc_intr)(sc->sc_arg);
retval = 1;
}
/* clear interrupt */
if (status & INTERRUPT_STATUS)
- outb(sc->sc_iobase+AD1848_STATUS, 0);
+ ADWRITE(sc, AD1848_STATUS, 0);
return(retval);
}
+
+void *
+ad1848_malloc(addr, size, pool, flags)
+ void *addr;
+ unsigned long size;
+ int pool;
+ int flags;
+{
+ struct ad1848_softc *sc = addr;
+
+ return isa_malloc(sc->sc_isa, 4, size, pool, flags);
+}
+
+void
+ad1848_free(addr, ptr, pool)
+ void *addr;
+ void *ptr;
+ int pool;
+{
+ isa_free(ptr, pool);
+}
+
+unsigned long
+ad1848_round(addr, size)
+ void *addr;
+ unsigned long size;
+{
+ if (size > MAX_ISADMA)
+ size = MAX_ISADMA;
+ return size;
+}
+
+int
+ad1848_mappage(addr, mem, off, prot)
+ void *addr;
+ void *mem;
+ int off;
+ int prot;
+{
+ return isa_mappage(mem, off, prot);
+}
+
+int
+ad1848_get_props(addr)
+ void *addr;
+{
+ struct ad1848_softc *sc = addr;
+
+ return AUDIO_PROP_MMAP |
+ (sc->sc_drq != sc->sc_recdrq ? AUDIO_PROP_FULLDUPLEX : 0);
+}
diff --git a/sys/dev/isa/ad1848var.h b/sys/dev/isa/ad1848var.h
index 8d6e3729cbe..b5fdaf67365 100644
--- a/sys/dev/isa/ad1848var.h
+++ b/sys/dev/isa/ad1848var.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ad1848var.h,v 1.5 1997/11/07 08:06:42 niklas Exp $ */
-/* $NetBSD: ad1848var.h,v 1.8 1996/04/29 20:02:37 christos Exp $ */
+/* $OpenBSD: ad1848var.h,v 1.6 1998/04/26 21:02:39 provos Exp $ */
+/* $NetBSD: ad1848var.h,v 1.22 1998/01/19 22:18:26 augustss Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -36,7 +36,7 @@
*
*/
-#define AD1848_NPORT 8
+#define AD1848_NPORT 4
struct ad1848_volume {
u_char left;
@@ -47,9 +47,13 @@ struct ad1848_softc {
struct device sc_dev; /* base device */
struct isadev sc_id; /* ISA device */
void *sc_ih; /* interrupt vectoring */
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_ioh; /* handle */
+ int sc_iooffs; /* offset from handle */
void *parent;
-
+ struct device *sc_isa; /* ISA bus's device */
+
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 */
@@ -60,7 +64,12 @@ struct ad1848_softc {
u_int sc_dma_cnt;
#endif
- int sc_iobase; /* I/O port base address */
+ char sc_playrun; /* running in continuous mode */
+ char sc_recrun; /* running in continuous mode */
+#define NOTRUNNING 0
+#define DMARUNNING 1
+#define PCMRUNNING 2
+
int sc_irq; /* interrupt */
int sc_drq; /* DMA */
int sc_recdrq; /* record/capture DMA */
@@ -77,8 +86,6 @@ struct ad1848_softc {
char *chip_name;
int mode;
- u_long speed;
- u_int encoding; /* ulaw/linear -- keep track */
u_int precision; /* 8/16 bits */
int channels;
@@ -89,6 +96,9 @@ struct ad1848_softc {
u_long sc_interrupts; /* number of interrupts taken */
void (*sc_intr)(void *); /* dma completion intr handler */
void *sc_arg; /* arg for sc_intr() */
+
+ /* Only used by pss XXX */
+ int sc_iobase;
};
/*
@@ -100,27 +110,23 @@ struct ad1848_softc {
#define DAC_IN_PORT 3
#ifdef _KERNEL
+int ad1848_mapprobe __P((struct ad1848_softc *, int));
int ad1848_probe __P((struct ad1848_softc *));
+void ad1848_unmap __P((struct ad1848_softc *));
void ad1848_attach __P((struct ad1848_softc *));
-int ad1848_open __P((struct ad1848_softc *, dev_t, int));
+int ad1848_open __P((void *, 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_format __P((void *, u_int, u_int));
-int ad1848_get_encoding __P((void *));
-int ad1848_get_precision __P((void *));
-int ad1848_set_channels __P((void *, int));
-int ad1848_get_channels __P((void *));
+int ad1848_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
int ad1848_round_blocksize __P((void *, int));
+int ad1848_dma_init_output __P((void *, void *, int));
+int ad1848_dma_init_input __P((void *, void *, int));
int ad1848_dma_output __P((void *, void *, int, void (*)(void *), void*));
int ad1848_dma_input __P((void *, void *, int, void (*)(void *), void*));
@@ -128,8 +134,6 @@ int ad1848_commit_settings __P((void *));
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 *));
@@ -151,4 +155,12 @@ int ad1848_set_mic_gain __P((struct ad1848_softc *, struct ad1848_volume *));
int ad1848_get_mic_gain __P((struct ad1848_softc *, struct ad1848_volume *));
void ad1848_mute_aux1 __P((struct ad1848_softc *, int /* onoff */));
void ad1848_mute_aux2 __P((struct ad1848_softc *, int /* onoff */));
+
+void *ad1848_malloc __P((void *, unsigned long, int, int));
+void ad1848_free __P((void *, void *, int));
+unsigned long ad1848_round __P((void *, unsigned long));
+int ad1848_mappage __P((void *, void *, int, int));
+
+int ad1848_get_props __P((void *));
+
#endif
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index 98e00a8d7c2..ba476852ccd 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,4 +1,4 @@
-# $OpenBSD: files.isa,v 1.39 1998/03/31 23:02:11 niklas Exp $
+# $OpenBSD: files.isa,v 1.40 1998/04/26 21:02:40 provos Exp $
# $NetBSD: files.isa,v 1.21 1996/05/16 03:45:55 mycroft Exp $
#
# Config.new file and device description for machine-independent ISA code.
@@ -12,7 +12,7 @@
device isa {[port = -1], [size = 0],
[iomem = -1], [iosiz = 0],
[irq = -1], [drq = -1],
- [pnpid = -1]}
+ [drq2 = -1]}
attach isa at isabus
file dev/isa/isa.c isa needs-flag
@@ -217,7 +217,7 @@ define sbdsp
file dev/isa/sbdsp.c sbdsp
# SoundBlaster family
-device sb: audio, isa_dma, sbdsp, mulaw, opti
+device sb: audio, isa_dma, sbdsp, mulaw, opti, auconv
file dev/isa/sb.c sb needs-flag
attach sb at isa with sb_isa
@@ -231,7 +231,7 @@ attach aria at isa
file dev/isa/aria.c aria needs-flag
# ProAudio Spectrum
-device pas: audio, isa_dma, sbdsp, mulaw
+device pas: audio, isa_dma, sbdsp, mulaw, auconv
attach pas at isa
file dev/isa/pas.c pas needs-flag
@@ -249,19 +249,21 @@ device pss {[port = -1], [size = 0],
[iomem = -1], [iosiz = 0],
[irq = -1], [drq = -1]}
attach pss at isa
-device sp: audio, isa_dma, ad1848
+device sp: audio, isa_dma, ad1848, auconv
attach sp at pss
file dev/isa/pss.c pss needs-flag
# Microsoft Windows Sound System
-device wss: audio, isa_dma, ad1848, opti
-attach wss at isa
+device wss: audio, isa_dma, ad1848, auconv
file dev/isa/wss.c wss needs-flag
+attach wss at isa with wss_isa
+file dev/isa/wss_isa.c wss_isa needs-flag
+
# 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
+device gus: audio, isa_dma, ics2101, ad1848, mulaw, auconv
attach gus at isa
file dev/isa/gus.c gus needs-flag
diff --git a/sys/dev/isa/gus.c b/sys/dev/isa/gus.c
index 8922f8889f7..eb01c44a1a8 100644
--- a/sys/dev/isa/gus.c
+++ b/sys/dev/isa/gus.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: gus.c,v 1.13 1998/01/18 18:58:37 niklas Exp $ */
-/* $NetBSD: gus.c,v 1.16 1996/05/12 23:52:08 mycroft Exp $ */
+/* $OpenBSD: gus.c,v 1.14 1998/04/26 21:02:41 provos Exp $ */
+/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * 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
@@ -112,11 +112,13 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.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>
@@ -177,8 +179,13 @@ struct gus_voice {
struct gus_softc {
struct device sc_dev; /* base device */
- struct isadev sc_id; /* ISA 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 */
@@ -290,37 +297,35 @@ struct ics2101_volume {
/*
* Mixer & MUX devices for CS4231
*/
-#define GUSMAX_MIX_IN 0 /* input to MUX from mixer output */
-#define GUSMAX_MONO_LVL 1 /* mic input to MUX;
+#define GUSMAX_MONO_LVL 0 /* mic input to MUX;
also mono mixer input */
-#define GUSMAX_DAC_LVL 2 /* input to MUX; also mixer input */
-#define GUSMAX_LINE_IN_LVL 3 /* input to MUX; also mixer input */
-#define GUSMAX_CD_LVL 4 /* mixer input only */
-#define GUSMAX_MONITOR_LVL 5 /* digital mix (?) */
-#define GUSMAX_OUT_LVL 6 /* output level. (?) */
-#define GUSMAX_SPEAKER_LVL 7 /* pseudo-device for mute */
-#define GUSMAX_LINE_IN_MUTE 8 /* pre-mixer */
-#define GUSMAX_DAC_MUTE 9 /* pre-mixer */
-#define GUSMAX_CD_MUTE 10 /* pre-mixer */
-#define GUSMAX_MONO_MUTE 11 /* pre-mixer--microphone/mono */
-#define GUSMAX_MONITOR_MUTE 12 /* post-mixer level/mute */
-#define GUSMAX_SPEAKER_MUTE 13 /* speaker mute */
-
-#define GUSMAX_REC_LVL 14 /* post-MUX gain */
-
-#define GUSMAX_RECORD_SOURCE 15
+#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 16
-#define GUSMAX_RECORD_CLASS 17
-#define GUSMAX_MONITOR_CLASS 18
-#define GUSMAX_OUTPUT_CLASS 19
+#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*/
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (gusdebug) Dprintf x
-#define DMAPRINTF(x) if (gusdmadebug) Dprintf x
+#define DPRINTF(x) if (gusdebug) printf x
+#define DMAPRINTF(x) if (gusdmadebug) printf x
int gusdebug = 0;
int gusdmadebug = 0;
#else
@@ -348,7 +353,7 @@ int dmarecord_index = 0;
* local routines
*/
-int gusopen __P((dev_t, int));
+int gusopen __P((void *, int));
void gusclose __P((void *));
void gusmax_close __P((void *));
int gusintr __P((void *));
@@ -356,62 +361,33 @@ 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_in_sr __P((void *, u_long));
-u_long gus_get_in_sr __P((void *));
-int gusmax_set_in_sr __P((void *, u_long));
-u_long gusmax_get_in_sr __P((void *));
-int gus_set_out_sr __P((void *, u_long));
-u_long gus_get_out_sr __P((void *));
-int gusmax_set_out_sr __P((void *, u_long));
-u_long gusmax_get_out_sr __P((void *));
-int gus_set_format __P((void *, u_int, u_int));
-int gus_get_encoding __P((void *));
-int gus_get_precision __P((void *));
-int gusmax_set_format __P((void *, u_int, u_int));
-int gusmax_get_encoding __P((void *));
-int gusmax_get_precision __P((void *));
-int gus_set_channels __P((void *, int));
-int gus_get_channels __P((void *));
-int gusmax_set_channels __P((void *, int));
-int gusmax_get_channels __P((void *));
+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_set_out_port __P((void *, int));
-int gus_get_out_port __P((void *));
-int gus_set_in_port __P((void *, int));
-int gus_get_in_port __P((void *));
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_cont_out_dma __P((void *));
-int gus_cont_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_cont_out_dma __P((void *));
-int gusmax_cont_in_dma __P((void *));
int gusmax_speaker_ctl __P((void *, int));
-int gusmax_set_out_port __P((void *, int));
-int gusmax_get_out_port __P((void *));
-int gusmax_set_in_port __P((void *, int));
-int gusmax_get_in_port __P((void *));
int gus_getdev __P((void *, struct audio_device *));
STATIC void gus_deinterleave __P((struct gus_softc *, void *, int));
-STATIC void gus_expand __P((void *, int, u_char *, int));
-STATIC void gusmax_expand __P((void *, int, u_char *, int));
STATIC int gus_mic_ctl __P((void *, int));
STATIC int gus_linein_ctl __P((void *, int));
-STATIC int gus_test_iobase __P((int));
-STATIC void guspoke __P((int, long, u_char));
+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 void gus_init_cs4231 __P((struct gus_softc *));
+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 *));
@@ -434,9 +410,8 @@ 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((int, u_long));
+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_setfd __P((void *, int));
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 *));
@@ -444,6 +419,8 @@ 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));
@@ -460,7 +437,12 @@ void stereo_dmaintr __P((void *));
* ISA bus driver routines
*/
+#define __BROKEN_INDIRECT_CONFIG
+#ifdef __BROKEN_INDIRECT_CONFIG
int gusprobe __P((struct device *, void *, void *));
+#else
+int gusprobe __P((struct device *, struct cfdata *, void *));
+#endif
void gusattach __P((struct device *, struct device *, void *));
struct cfattach gus_ca = {
@@ -586,8 +568,7 @@ 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(port,x) outb(port+GUS_REG_SELECT,x)
-#define WHICH_GUS_REG(port) inb(port+GUS_REG_SELECT)
+#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)
@@ -614,49 +595,70 @@ struct audio_hw_if gus_hw_if = {
gusopen,
gusclose,
NULL, /* drain */
- gus_set_in_sr,
- gus_get_in_sr,
- gus_set_out_sr,
- gus_get_out_sr,
gus_query_encoding,
- gus_set_format,
- gus_get_encoding,
- gus_get_precision,
- gus_set_channels,
- gus_get_channels,
+ gus_set_params,
gus_round_blocksize,
- gus_set_out_port,
- gus_get_out_port,
- gus_set_in_port,
- gus_get_in_port,
-
gus_commit_settings,
- gus_expand,
- mulaw_compress,
+ NULL,
+ NULL,
gus_dma_output,
gus_dma_input,
gus_halt_out_dma,
gus_halt_in_dma,
- gus_cont_out_dma,
- gus_cont_in_dma,
-
gus_speaker_ctl,
gus_getdev,
- gus_setfd,
+ NULL,
gus_mixer_set_port,
gus_mixer_get_port,
gus_mixer_query_devinfo,
- 1, /* full-duplex */
- 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gus_get_props,
};
+static struct audio_hw_if gusmax_hw_if = {
+ gusmaxopen,
+ gusmax_close,
+ NULL, /* drain */
+
+ gus_query_encoding, /* query encoding */
+
+ gusmax_set_params,
+
+ gusmax_round_blocksize,
+
+ gusmax_commit_settings,
+
+ NULL,
+ NULL,
+
+ gusmax_dma_output,
+ gusmax_dma_input,
+ gusmax_halt_out_dma,
+ gusmax_halt_in_dma,
+
+ gusmax_speaker_ctl,
+
+ gus_getdev,
+ NULL,
+ gusmax_mixer_set_port,
+ gusmax_mixer_get_port,
+ gusmax_mixer_query_devinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gusmax_get_props,
+};
/*
* Some info about the current audio device
@@ -674,33 +676,37 @@ struct audio_device gus_device = {
int
gusprobe(parent, match, aux)
struct device *parent;
- void *match, *aux;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
{
- register struct gus_softc *sc = match;
- register struct isa_attach_args *ia = aux;
- struct cfdata *cf = sc->sc_dev.dv_cfdata;
- register int iobase = ia->ia_iobase;
- int recdrq = cf->cf_flags;
+ 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.
*/
- if (gus_irq_map[ia->ia_irq] == IRQUNK) {
+ /* XXX range check before indexing!! */
+ if (ia->ia_irq == IRQUNK || gus_irq_map[ia->ia_irq] == IRQUNK) {
printf("gus: invalid irq %d, card not probed\n", ia->ia_irq);
- return(0);
+ return 0;
}
- if (gus_drq_map[ia->ia_drq] == DRQUNK) {
+ if (ia->ia_drq == DRQUNK || gus_drq_map[ia->ia_drq] == DRQUNK) {
printf("gus: invalid drq %d, card not probed\n", ia->ia_drq);
- return(0);
+ return 0;
}
- if (recdrq != 0x00) {
+ if (recdrq != DRQUNK) {
if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
- printf("gus: invalid flag given for second DMA channel (0x%x), card not probed\n", recdrq);
- return(0);
+ printf("gus: invalid second DMA channel (%d), card not probed\n", recdrq);
+ return 0;
}
} else
recdrq = ia->ia_drq;
@@ -708,23 +714,22 @@ gusprobe(parent, match, aux)
if (iobase == IOBASEUNK) {
int i;
for(i = 0; i < gus_addrs; i++)
- if (gus_test_iobase(gus_base_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(iobase))
+ } else if (!gus_test_iobase(ia->ia_iot, iobase))
return 0;
done:
- sc->sc_iobase = iobase;
- sc->sc_irq = ia->ia_irq;
- sc->sc_drq = ia->ia_drq;
- sc->sc_recdrq = recdrq;
+ if ((ia->ia_drq != -1 && !isa_drq_isfree(parent, ia->ia_drq)) ||
+ (recdrq != -1 && !isa_drq_isfree(parent, recdrq)))
+ return 0;
- ia->ia_iobase = sc->sc_iobase;
- ia->ia_iosize = 16; /* XXX */
- return(1);
+ ia->ia_iobase = iobase;
+ ia->ia_iosize = GUS_NPORT1;
+ return 1;
}
/*
@@ -733,47 +738,74 @@ done:
*/
STATIC int
-gus_test_iobase (int iobase)
+gus_test_iobase (iot, iobase)
+ bus_space_tag_t iot;
+ int iobase;
{
- int i = splgus();
+ 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(iobase, GUSREG_RESET);
- outb(iobase+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
delay(500);
- SELECT_GUS_REG(iobase, GUSREG_RESET);
- outb(iobase+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
delay(500);
- splx(i);
+ splx(s);
/*
* See if we can write to the board's memory
*/
- s1 = guspeek(iobase, 0L);
- s2 = guspeek(iobase, 1L);
+ s1 = guspeek(iot, ioh2, 0L);
+ s2 = guspeek(iot, ioh2, 1L);
- guspoke(iobase, 0L, 0xaa);
- guspoke(iobase, 1L, 0x55);
+ guspoke(iot, ioh2, 0L, 0xaa);
+ guspoke(iot, ioh2, 1L, 0x55);
- if ((i=(int)guspeek(iobase, 0L)) != 0xaa) {
- return(0);
- }
+ if (guspeek(iot, ioh2, 0L) != 0xaa)
+ goto bad;
- guspoke(iobase, 0L, s1);
- guspoke(iobase, 1L, s2);
+ guspoke(iot, ioh2, 0L, s1);
+ guspoke(iot, ioh2, 1L, s2);
- return 1;
+ 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;
}
/*
@@ -785,28 +817,57 @@ gusattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- register struct gus_softc *sc = (void *) self;
- register struct isa_attach_args *ia = aux;
- register int port = ia->ia_iobase;
- int i;
- register unsigned char c,d,m;
+ 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 = inb(port+GUS_BOARD_REV);
+ 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(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, 0x00);
+ 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 */
@@ -837,54 +898,72 @@ gusattach(parent, self, aux)
* The order of these operations is very magical.
*/
- disable_intr();
+ disable_intr(); /* XXX needed? */
- outb(port+GUS_REG_CONTROL, GUS_REG_IRQCTL);
- outb(port+GUS_MIX_CONTROL, m);
- outb(port+GUS_IRQCTL_CONTROL, 0x00);
- outb(port+0x0f, 0x00);
+ 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);
- outb(port+GUS_MIX_CONTROL, m);
- outb(port+GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
+ bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
- outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
- outb(port+GUS_IRQ_CONTROL, c);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
+ bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
- outb(port+GUS_MIX_CONTROL, m);
- outb(port+GUS_DMA_CONTROL, d);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
+ bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d);
- outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
- outb(port+GUS_IRQ_CONTROL, c);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
+ bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
- outb(port+GUS_VOICE_SELECT, 0x00);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, 0x00);
/* enable line in, line out. leave mic disabled. */
- outb(port+GUS_MIX_CONTROL,
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL,
(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
- outb(port+GUS_VOICE_SELECT, 0x00);
+ 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);
+ 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(port, GUSREG_RESET);
+ 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(port, 0L, 0x00);
+ guspoke(iot, ioh2, 0L, 0x00);
for(i = 1; i < 1024; i++) {
u_long loc;
@@ -892,13 +971,13 @@ gusattach(parent, self, aux)
* See if we've run into mirroring yet
*/
- if (guspeek(port, 0L) != 0)
+ if (guspeek(iot, ioh2, 0L) != 0)
break;
loc = i << 10;
- guspoke(port, loc, 0xaa);
- if (guspeek(port, loc) != 0xaa)
+ guspoke(iot, ioh2, loc, 0xaa);
+ if (guspeek(iot, ioh2, loc) != 0xaa)
break;
}
@@ -913,10 +992,8 @@ gusattach(parent, self, aux)
printf("%s codec/mixer, ", sc->sc_codec.chip_name);
if (sc->sc_recdrq == sc->sc_drq) {
printf("half-duplex");
- gus_hw_if.full_duplex = 0;
} else {
printf("full-duplex, record drq %d", sc->sc_recdrq);
- gus_hw_if.full_duplex = 1;
}
printf(">\n");
@@ -933,10 +1010,11 @@ gusattach(parent, self, aux)
/*
* Set some default values
+ * XXX others start with 8kHz mono mulaw
*/
sc->sc_irate = sc->sc_orate = 44100;
- sc->sc_encoding = AUDIO_ENCODING_LINEAR;
+ 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;
@@ -949,38 +1027,30 @@ gusattach(parent, self, aux)
* full right.
* For mono playback, we set up both voices playing the same buffer.
*/
- outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
- SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
- outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
+ 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);
- outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
- SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
- outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
+ 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
*/
- if (audio_hardware_attach(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc) != 0)
- printf("gus: could not attach to audio pseudo-device driver\n");
+ audio_attach_mi(&gus_hw_if, 0, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc, &sc->sc_dev);
}
int
-gusopen(dev, flags)
- dev_t dev;
+gusopen(addr, flags)
+ void *addr;
int flags;
{
- int unit = AUDIOUNIT(dev);
- struct gus_softc *sc;
+ struct gus_softc *sc = addr;
DPRINTF(("gusopen() called\n"));
- if (unit >= gus_cd.cd_ndevs)
- return ENXIO;
- sc = gus_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
if (sc->sc_flags & GUS_OPEN)
return EBUSY;
@@ -996,7 +1066,7 @@ gusopen(dev, flags)
sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
if (HAS_CODEC(sc)) {
- ad1848_open(&sc->sc_codec, dev, flags);
+ ad1848_open(&sc->sc_codec, flags);
sc->sc_codec.aux1_mute = 0;
ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */
if (flags & FREAD) {
@@ -1015,51 +1085,38 @@ gusopen(dev, flags)
return 0;
}
-STATIC void
-gusmax_expand(hdl, encoding, buf, count)
- void *hdl;
- int encoding;
- u_char *buf;
- int count;
-{
- register struct ad1848_softc *ac = hdl;
-
- gus_expand(ac->parent, encoding, buf, count);
-}
-
-STATIC void
-gus_expand(hdl, encoding, buf, count)
- void *hdl;
- int encoding;
- u_char *buf;
- int count;
+int
+gusmaxopen(addr, flags)
+ void *addr;
+ int flags;
{
- struct gus_softc *sc = hdl;
-
- mulaw_expand(NULL, encoding, buf, count);
- /*
- * If we need stereo deinterleaving, do it now.
- */
- if (sc->sc_channels == 2)
- gus_deinterleave(sc, (void *)buf, count);
+ struct ad1848_softc *ac = addr;
+ return gusopen(ac->parent, flags);
}
STATIC void
gus_deinterleave(sc, buf, size)
- register struct gus_softc *sc;
+ struct gus_softc *sc;
void *buf;
int size;
{
/* deinterleave the stereo data. We can use sc->sc_deintr_buf
for scratch space. */
- register int i;
+ int i;
+
+ if (size > sc->sc_blocksize) {
+ printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize);
+ return;
+ } else if (size < sc->sc_blocksize) {
+ DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize));
+ }
/*
* size is in bytes.
*/
if (sc->sc_precision == 16) {
- register u_short *dei = sc->sc_deintr_buf;
- register u_short *sbuf = buf;
+ u_short *dei = sc->sc_deintr_buf;
+ u_short *sbuf = buf;
size >>= 1; /* bytecnt to shortcnt */
/* copy 2nd of each pair of samples to the staging area, while
compacting the 1st of each pair into the original area. */
@@ -1079,8 +1136,8 @@ gus_deinterleave(sc, buf, size)
*/
bcopy(dei, &sbuf[size/2], i * sizeof(short));
} else {
- register u_char *dei = sc->sc_deintr_buf;
- register u_char *sbuf = buf;
+ u_char *dei = sc->sc_deintr_buf;
+ u_char *sbuf = buf;
for (i = 0; i < size/2-1; i++) {
dei[i] = sbuf[i*2+1];
sbuf[i+1] = sbuf[i*2+2];
@@ -1101,7 +1158,7 @@ gusmax_dma_output(addr, buf, size, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct ad1848_softc *ac = addr;
+ struct ad1848_softc *ac = addr;
return gus_dma_output(ac->parent, buf, size, intr, arg);
}
@@ -1164,7 +1221,7 @@ gus_dma_output(addr, buf, size, intr, arg)
u_long boarddma;
int flags;
- DMAPRINTF(("gus_dma_output %d @ %x\n", size, buf));
+ DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf));
if (size != sc->sc_blocksize) {
DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
@@ -1175,9 +1232,10 @@ gus_dma_output(addr, buf, size, intr, arg)
flags = GUSMASK_DMA_WRITE;
if (sc->sc_precision == 16)
flags |= GUSMASK_DMA_DATA_SIZE;
- /* pcm16 is signed, mulaw & pcm8 are unsigned */
if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
- sc->sc_encoding == AUDIO_ENCODING_PCM8)
+ sc->sc_encoding == AUDIO_ENCODING_ALAW ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE)
flags |= GUSMASK_DMA_INVBIT;
if (sc->sc_channels == 2) {
@@ -1192,9 +1250,12 @@ gus_dma_output(addr, buf, size, intr, arg)
}
if (size == 0)
return 0;
+
+ gus_deinterleave(sc, (void *)buffer, size);
+
size >>= 1;
- boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
+ boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
sc->sc_stereo.intr = intr;
sc->sc_stereo.arg = arg;
@@ -1235,8 +1296,8 @@ void
gusmax_close(addr)
void *addr;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
#if 0
ac->aux1_mute = 1;
ad1848_mute_aux1(ac, 1); /* turn off DAC output */
@@ -1254,7 +1315,7 @@ gusclose(addr)
{
struct gus_softc *sc = addr;
- DPRINTF(("gus_close: sc=0x%x\n", sc));
+ DPRINTF(("gus_close: sc=%p\n", sc));
/* if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
@@ -1291,9 +1352,12 @@ int
gusintr(arg)
void *arg;
{
- register struct gus_softc *sc = arg;
+ struct gus_softc *sc = arg;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
unsigned char intr;
- register int port = sc->sc_iobase;
+
int retval = 0;
DPRINTF(("gusintr\n"));
@@ -1302,15 +1366,15 @@ gusintr(arg)
#endif
if (HAS_CODEC(sc))
retval = ad1848_intr(&sc->sc_codec);
- if ((intr = inb(port+GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
+ if ((intr = bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
#ifdef DIAGNOSTIC
gusdmaintrcnt++;
#endif
retval += gus_dmaout_intr(sc);
if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- intr = inb(port+GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
if (intr & GUSMASK_SAMPLE_DMATC) {
retval += gus_dmain_intr(sc);
}
@@ -1350,27 +1414,29 @@ int playcntr;
STATIC void
gus_dmaout_timeout(arg)
- void *arg;
+ void *arg;
{
- register struct gus_softc *sc = arg;
- register int port = sc->sc_iobase;
- int s;
-
- printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
- /*
- * Stop any DMA.
- */
+ struct gus_softc *sc = arg;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ int s;
- s = splgus();
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
+ printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
+ /*
+ * Stop any DMA.
+ */
+ s = splgus();
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
+
#if 0
- isadma_abort(sc->sc_drq); /* XXX we will dmadone below? */
+ /* XXX we will dmadone below? */
+ isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
#endif
-
- gus_dmaout_dointr(sc);
- splx(s);
+
+ gus_dmaout_dointr(sc);
+ splx(s);
}
@@ -1383,15 +1449,16 @@ STATIC int
gus_dmaout_intr(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
/*
* If we got a DMA transfer complete from the GUS DRAM, then deal
* with it.
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- if (inb(port+GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ if (bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
untimeout(gus_dmaout_timeout, sc);
gus_dmaout_dointr(sc);
return 1;
@@ -1403,12 +1470,13 @@ STATIC void
gus_dmaout_dointr(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
- isadma_done(sc->sc_drq);
+ isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq);
sc->sc_flags &= ~GUS_DMAOUT_ACTIVE; /* pending DMA is done */
- DMAPRINTF(("gus_dmaout_dointr %d @ %x\n", sc->sc_dmaoutcnt,
+ DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt,
sc->sc_dmaoutaddr));
/*
@@ -1419,21 +1487,31 @@ gus_dmaout_dointr(sc)
* byte rather than the one we have in memory.
*/
if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
- register int i;
+ int i;
switch (sc->sc_encoding) {
- case AUDIO_ENCODING_PCM16:
+ case AUDIO_ENCODING_SLINEAR_LE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (sc->sc_precision == 8)
+ goto byte;
/* we have the native format */
for (i = 1; i <= 2; i++)
- guspoke(port, sc->sc_gusaddr -
+ guspoke(iot, ioh2, sc->sc_gusaddr -
(sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
break;
- case AUDIO_ENCODING_PCM8:
+ case AUDIO_ENCODING_ULINEAR_LE:
+ case AUDIO_ENCODING_ULINEAR_BE:
+ guspoke(iot, ioh2, sc->sc_gusaddr -
+ (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2,
+ guspeek(iot, ioh2,
+ sc->sc_gusaddr + sc->sc_chanblocksize - 2));
+ case AUDIO_ENCODING_ALAW:
case AUDIO_ENCODING_ULAW:
+ byte:
/* we need to fetch the translated byte, then stuff it. */
- guspoke(port, sc->sc_gusaddr -
+ guspoke(iot, ioh2, sc->sc_gusaddr -
(sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
- guspeek(port,
+ guspeek(iot, ioh2,
sc->sc_gusaddr + sc->sc_chanblocksize - 1));
break;
}
@@ -1509,11 +1587,11 @@ gus_dmaout_dointr(sc)
playcntr = ++playcntr % NDMARECS;
}
#endif
- outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
}
}
gus_bufcnt[sc->sc_bufcnt-1]++;
@@ -1546,7 +1624,8 @@ STATIC int
gus_voice_intr(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
int ignore = 0, voice, rval = 0;
unsigned char intr, status;
@@ -1557,8 +1636,8 @@ gus_voice_intr(sc)
*/
while(1) {
- SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
- intr = inb(port+GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
+ intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
== (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
@@ -1587,8 +1666,8 @@ gus_voice_intr(sc)
* (this stops it from continuously generating IRQs)
*/
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL+0x80);
- status = inb(port+GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL+0x80);
+ status = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
if (status & GUSMASK_VOICE_STOPPED) {
if (voice != GUS_VOICE_LEFT) {
DMAPRINTF(("%s: spurious voice %d stop?\n",
@@ -1692,177 +1771,179 @@ gus_voice_intr(sc)
STATIC void
gus_start_playing(sc, bufno)
-struct gus_softc *sc;
-int bufno;
+ struct gus_softc *sc;
+ int bufno;
{
- register int port = sc->sc_iobase;
- /*
- * Start the voices playing, with buffer BUFNO.
- */
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ /*
+ * Start the voices playing, with buffer BUFNO.
+ */
- /*
- * Loop or roll if we have buffers ready.
- */
+ /*
+ * Loop or roll if we have buffers ready.
+ */
- if (sc->sc_bufcnt == 1) {
- sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
- sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
- } else {
- if (bufno == sc->sc_nbufs - 1) {
- sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
- sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
+ if (sc->sc_bufcnt == 1) {
+ sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
+ sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
} else {
- sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
- sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
+ if (bufno == sc->sc_nbufs - 1) {
+ sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
+ } else {
+ sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
+ }
}
- }
- outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
- sc->sc_voc[GUS_VOICE_LEFT].current_addr =
- GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
- sc->sc_voc[GUS_VOICE_LEFT].end_addr =
- sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
- sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
- sc->sc_voc[GUS_VOICE_LEFT].current_addr +
- (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
- /*
- * set up right channel to just loop forever, no interrupts,
- * starting at the buffer we just filled. We'll feed it data
- * at the same time as left channel.
- */
- sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
- sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
+ sc->sc_voc[GUS_VOICE_LEFT].current_addr =
+ GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
+ sc->sc_voc[GUS_VOICE_LEFT].end_addr =
+ sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
+ sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
+ sc->sc_voc[GUS_VOICE_LEFT].current_addr +
+ (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
+ /*
+ * set up right channel to just loop forever, no interrupts,
+ * starting at the buffer we just filled. We'll feed it data
+ * at the same time as left channel.
+ */
+ sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
#ifdef GUSPLAYDEBUG
- if (gusstats) {
- microtime(&playstats[playcntr].tv);
- playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
-
- playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
- playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
- playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
- playstats[playcntr].playbuf = bufno;
- playstats[playcntr].dmabuf = sc->sc_dmabuf;
- playstats[playcntr].bufcnt = sc->sc_bufcnt;
- playstats[playcntr].vaction = 5;
- playcntr = ++playcntr % NDMARECS;
- }
+ if (gusstats) {
+ microtime(&playstats[playcntr].tv);
+ playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
+
+ playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
+ playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
+ playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
+ playstats[playcntr].playbuf = bufno;
+ playstats[playcntr].dmabuf = sc->sc_dmabuf;
+ playstats[playcntr].bufcnt = sc->sc_bufcnt;
+ playstats[playcntr].vaction = 5;
+ playcntr = ++playcntr % NDMARECS;
+ }
#endif
- outb(port+GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
-
- gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
- gus_start_voice(sc, GUS_VOICE_LEFT, 1);
- if (sc->sc_playbuf == -1)
- /* mark start of playing */
- sc->sc_playbuf = bufno;
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
+
+ gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
+ gus_start_voice(sc, GUS_VOICE_LEFT, 1);
+ if (sc->sc_playbuf == -1)
+ /* mark start of playing */
+ sc->sc_playbuf = bufno;
}
STATIC int
gus_continue_playing(sc, voice)
-register struct gus_softc *sc;
-int voice;
+ struct gus_softc *sc;
+ int voice;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
- /*
- * stop this voice from interrupting while we work.
- */
+ /*
+ * stop this voice from interrupting while we work.
+ */
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
- /*
- * update playbuf to point to the buffer the hardware just started
- * playing
- */
- sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
+ /*
+ * update playbuf to point to the buffer the hardware just started
+ * playing
+ */
+ sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
- /*
- * account for buffer just finished
- */
- if (--sc->sc_bufcnt == 0) {
- DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
- }
- if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
- printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
- return 1;
- }
-
- /*
- * Select the end of the buffer based on the currently active
- * buffer, [plus extra contiguous buffers (if ready)].
- */
-
- /*
- * set endpoint at end of buffer we just started playing.
- *
- * The total gets -1 because end addrs are one less than you might
- * think (the end_addr is the address of the last sample to play)
- */
- gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
- sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
-
- if (sc->sc_bufcnt < 2) {
/*
- * Clear out the loop and roll flags, and rotate the currently
- * playing buffer. That way, if we don't manage to get more
- * data before this buffer finishes, we'll just stop.
+ * account for buffer just finished
*/
- sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
- sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
- playstats[playcntr].vaction = 0;
- } else {
+ if (--sc->sc_bufcnt == 0) {
+ DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
+ }
+ if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
+ printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
+ return 1;
+ }
+
/*
- * We have some buffers to play. set LOOP if we're on the
- * last buffer in the ring, otherwise set ROLL.
+ * Select the end of the buffer based on the currently active
+ * buffer, [plus extra contiguous buffers (if ready)].
+ */
+
+ /*
+ * set endpoint at end of buffer we just started playing.
+ *
+ * The total gets -1 because end addrs are one less than you might
+ * think (the end_addr is the address of the last sample to play)
*/
- if (sc->sc_playbuf == sc->sc_nbufs - 1) {
- sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
- sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
- playstats[playcntr].vaction = 1;
+ gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
+ sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
+
+ if (sc->sc_bufcnt < 2) {
+ /*
+ * Clear out the loop and roll flags, and rotate the currently
+ * playing buffer. That way, if we don't manage to get more
+ * data before this buffer finishes, we'll just stop.
+ */
+ sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
+ playstats[playcntr].vaction = 0;
} else {
- sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
- sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
- playstats[playcntr].vaction = 2;
+ /*
+ * We have some buffers to play. set LOOP if we're on the
+ * last buffer in the ring, otherwise set ROLL.
+ */
+ if (sc->sc_playbuf == sc->sc_nbufs - 1) {
+ sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
+ playstats[playcntr].vaction = 1;
+ } else {
+ sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
+ playstats[playcntr].vaction = 2;
+ }
}
- }
#ifdef GUSPLAYDEBUG
- if (gusstats) {
- microtime(&playstats[playcntr].tv);
- playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
-
- playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
- playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
- playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
- playstats[playcntr].playbuf = sc->sc_playbuf;
- playstats[playcntr].dmabuf = sc->sc_dmabuf;
- playstats[playcntr].bufcnt = sc->sc_bufcnt;
- playcntr = ++playcntr % NDMARECS;
- }
+ if (gusstats) {
+ microtime(&playstats[playcntr].tv);
+ playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
+
+ playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
+ playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
+ playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
+ playstats[playcntr].playbuf = sc->sc_playbuf;
+ playstats[playcntr].dmabuf = sc->sc_dmabuf;
+ playstats[playcntr].bufcnt = sc->sc_bufcnt;
+ playcntr = ++playcntr % NDMARECS;
+ }
#endif
- /*
- * (re-)set voice parameters. This will reenable interrupts from this
- * voice.
- */
+ /*
+ * (re-)set voice parameters. This will reenable interrupts from this
+ * voice.
+ */
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
- return 0;
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
+ return 0;
}
/*
@@ -1876,8 +1957,9 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
u_long gusaddr;
caddr_t buffaddr;
{
- register unsigned char c = (unsigned char) flags;
- register int port = sc->sc_iobase;
+ unsigned char c = (unsigned char) flags;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
@@ -1903,8 +1985,8 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
* Make sure the GUS _isn't_ setup for DMA
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(port+GUS_DATA_HIGH, 0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
/*
* Tell the PC DMA controller to start doing DMA
@@ -1912,7 +1994,8 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
sc->sc_dmaoutaddr = (u_char *) buffaddr;
sc->sc_dmaoutcnt = length;
- isadma_start(buffaddr, length, sc->sc_drq, DMAMODE_WRITE);
+ isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length,
+ NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
/*
* Set up DMA address - use the upper 16 bits ONLY
@@ -1920,15 +2003,15 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
sc->sc_flags |= GUS_DMAOUT_ACTIVE;
- SELECT_GUS_REG(port, GUSREG_DMA_START);
- outw(port+GUS_DATA_LOW, (int) (gusaddr >> 4));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_START);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (int) (gusaddr >> 4));
/*
* Tell the GUS to start doing DMA
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(port+GUS_DATA_HIGH, c);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, c);
/*
* XXX If we don't finish in one second, give up...
@@ -1948,7 +2031,8 @@ gus_start_voice(sc, voice, intrs)
int voice;
int intrs;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
u_long start;
u_long current;
u_long end;
@@ -1978,22 +2062,22 @@ gus_start_voice(sc, voice, intrs)
* Select the voice we want to use, and program the data addresses
*/
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(start));
- SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(start));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(start));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(start));
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(current));
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(current));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(current));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(current));
- SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(end));
- SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(end));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(end));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(end));
/*
* (maybe) enable interrupts, disable voice stopping
@@ -2013,24 +2097,24 @@ gus_start_voice(sc, voice, intrs)
* from 0 up to the set volume to help reduce clicks.
*/
- SELECT_GUS_REG(port, GUSREG_START_VOLUME);
- outb(port+GUS_DATA_HIGH, 0x00);
- SELECT_GUS_REG(port, GUSREG_END_VOLUME);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x00);
- SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
- outb(port+GUS_DATA_HIGH, 63);
-
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 63);
+
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
delay(50);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
}
@@ -2044,7 +2128,8 @@ gus_stop_voice(sc, voice, intrs_too)
int voice;
int intrs_too;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
GUSMASK_STOP_VOICE;
@@ -2055,24 +2140,24 @@ gus_stop_voice(sc, voice, intrs_too)
}
DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
- guspoke(port, 0L, 0);
+ guspoke(iot, ioh2, 0L, 0);
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
delay(100);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
}
@@ -2085,59 +2170,66 @@ gus_set_volume(sc, voice, volume)
struct gus_softc *sc;
int voice, volume;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
unsigned int gusvol;
gusvol = gus_log_volumes[volume < 512 ? volume : 511];
sc->sc_voc[voice].current_volume = gusvol;
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_START_VOLUME);
- outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
- SELECT_GUS_REG(port, GUSREG_END_VOLUME);
- outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, gusvol << 4);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
delay(500);
- outw(port+GUS_DATA_LOW, gusvol << 4);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
}
/*
- * Interface to the audio layer - set the data encoding type
+ * Interface to the audio layer.
*/
int
-gusmax_set_format(addr, encoding, precision)
- void * addr;
- u_int encoding, precision;
+gusmax_set_params(addr, setmode, usemode, p, r)
+ void *addr;
+ int setmode, usemode;
+ struct audio_params *p, *r;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
int error;
- error = ad1848_set_format(ac, encoding, precision);
- return (error ? error : gus_set_format(sc, encoding, precision));
+ error = ad1848_set_params(ac, setmode, usemode, p, r);
+ if (error)
+ return error;
+ error = gus_set_params(sc, setmode, usemode, p, r);
+ return error;
}
int
-gus_set_format(addr, encoding, precision)
- void * addr;
- u_int encoding, precision;
+gus_set_params(addr, setmode, usemode, p, r)
+ void *addr;
+ int setmode, usemode;
+ struct audio_params *p, *r;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
int s;
- DPRINTF(("gus_set_format called\n"));
-
- switch (encoding) {
+ switch (p->encoding) {
case AUDIO_ENCODING_ULAW:
- case AUDIO_ENCODING_PCM16:
- case AUDIO_ENCODING_PCM8:
+ case AUDIO_ENCODING_ALAW:
+ case AUDIO_ENCODING_SLINEAR_LE:
+ case AUDIO_ENCODING_ULINEAR_LE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ case AUDIO_ENCODING_ULINEAR_BE:
break;
default:
return (EINVAL);
@@ -2145,7 +2237,7 @@ gus_set_format(addr, encoding, precision)
s = splaudio();
- if (precision == 8) {
+ if (p->precision == 8) {
sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
} else {
@@ -2153,40 +2245,33 @@ gus_set_format(addr, encoding, precision)
sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
}
- sc->sc_encoding = encoding;
- sc->sc_precision = precision;
+ sc->sc_encoding = p->encoding;
+ sc->sc_precision = p->precision;
+ sc->sc_channels = p->channels;
splx(s);
- return 0;
-}
-
-int
-gusmax_set_channels(addr, channels)
- void * addr;
- int channels;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- int error;
-
- error = ad1848_set_channels(ac, channels);
- return (error ? error : gus_set_channels(sc, channels));
-}
-
-int
-gus_set_channels(addr, channels)
- void * addr;
- int channels;
-{
- register struct gus_softc *sc = addr;
+ if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
+ p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
+ if (setmode & AUMODE_RECORD)
+ sc->sc_irate = p->sample_rate;
+ if (setmode & AUMODE_PLAY)
+ sc->sc_orate = p->sample_rate;
- DPRINTF(("gus_set_channels called\n"));
-
- if (channels != 1 && channels != 2)
- return EINVAL;
-
- sc->sc_channels = channels;
+ switch (p->encoding) {
+ case AUDIO_ENCODING_ULAW:
+ p->sw_code = mulaw_to_ulinear8;
+ r->sw_code = ulinear8_to_mulaw;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ p->sw_code = alaw_to_ulinear8;
+ r->sw_code = ulinear8_to_alaw;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ r->sw_code = p->sw_code = swap_bytes;
+ break;
+ }
return 0;
}
@@ -2201,8 +2286,8 @@ gusmax_round_blocksize(addr, blocksize)
void * addr;
int blocksize;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
/* blocksize = ad1848_round_blocksize(ac, blocksize);*/
return gus_round_blocksize(sc, blocksize);
@@ -2213,11 +2298,12 @@ gus_round_blocksize(addr, blocksize)
void * addr;
int blocksize;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
DPRINTF(("gus_round_blocksize called\n"));
- if (sc->sc_encoding == AUDIO_ENCODING_ULAW && blocksize > 32768)
+ if ((sc->sc_encoding == AUDIO_ENCODING_ULAW ||
+ sc->sc_encoding == AUDIO_ENCODING_ALAW) && blocksize > 32768)
blocksize = 32768;
else if (blocksize > 65536)
blocksize = 65536;
@@ -2243,164 +2329,28 @@ gus_round_blocksize(addr, blocksize)
return blocksize;
}
-/*
- * Interfaces to the audio layer - return values from the software config
- * struct
- */
-
-int
-gusmax_get_encoding(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_encoding(sc);
-}
-
-int
-gus_get_encoding(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_encoding called\n"));
-
- /* XXX TODO: codec stuff */
- return sc->sc_encoding;
-}
-
-int
-gusmax_get_channels(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_channels(sc);
-}
-
-int
-gus_get_channels(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_channels called\n"));
-
- return sc->sc_channels;
-}
-
-u_long
-gus_get_in_sr(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_in_sr called\n"));
- return sc->sc_irate;
-}
-
-u_long
-gusmax_get_in_sr(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_in_sr(sc);
-}
-
-u_long
-gusmax_get_out_sr(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_out_sr(sc);
-}
-
-u_long
-gus_get_out_sr(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_out_sr called\n"));
- return sc->sc_orate;
-}
-
-int
-gusmax_get_precision(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_get_precision(sc->parent);
-}
-
-int
-gus_get_precision(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_precision called\n"));
-
- return sc->sc_precision;
-}
-
int
gus_get_out_gain(addr)
caddr_t addr;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
DPRINTF(("gus_get_out_gain called\n"));
return sc->sc_ogain / 2;
}
-/*
- * Interface to the audio layer - set the sample rate of the output voices
- */
-
-int
-gusmax_set_out_sr(addr, rate)
- void * addr;
- u_long rate;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- int error;
-
- error = ad1848_set_out_sr(ac, rate);
- return (error ? error : gus_set_out_sr(sc, rate));
-}
-
-int
-gus_set_out_sr(addr, rate)
- void * addr;
- u_long rate;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_set_out_sr called\n"));
-
- if (rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
- rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
-
- sc->sc_orate = rate;
-
- return 0;
-}
-
STATIC inline void gus_set_voices(sc, voices)
struct gus_softc *sc;
int voices;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
/*
* Select the active number of voices
*/
- SELECT_GUS_REG(port, GUSREG_ACTIVE_VOICES);
- outb(port+GUS_DATA_HIGH, (voices-1) | 0xc0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_ACTIVE_VOICES);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (voices-1) | 0xc0);
sc->sc_voices = voices;
}
@@ -2413,10 +2363,13 @@ int
gusmax_commit_settings(addr)
void * addr;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
+ int error;
- (void) ad1848_commit_settings(ac);
+ error = ad1848_commit_settings(ac);
+ if (error)
+ return error;
return gus_commit_settings(sc);
}
@@ -2427,7 +2380,7 @@ int
gus_commit_settings(addr)
void * addr;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
int s;
DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
@@ -2489,7 +2442,8 @@ gus_set_samprate(sc, voice, freq)
struct gus_softc *sc;
int voice, freq;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
unsigned int fc;
u_long temp, f = (u_long) freq;
@@ -2509,46 +2463,15 @@ gus_set_samprate(sc, voice, freq)
* Program the voice frequency, and set it in the voice data record
*/
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_FREQ_CONTROL);
- outw(port+GUS_DATA_LOW, fc);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_FREQ_CONTROL);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, fc);
sc->sc_voc[voice].rate = freq;
}
/*
- * Interface to the audio layer - set the recording sampling rate
- */
-
-int
-gusmax_set_in_sr(addr, rate)
- void * addr;
- u_long rate;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- int error;
-
- error = ad1848_set_in_sr(ac, rate);
- return (error ? error : gus_set_in_sr(sc, rate));
-}
-
-
-int
-gus_set_in_sr(addr, rate)
- void *addr;
- u_long rate;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_set_in_sr called\n"));
-
- sc->sc_irate = rate;
-
- return 0;
-}
-/*
* Set the sample rate of the recording frequency. Formula is from the GUS
* SDK. Called at splgus().
*/
@@ -2558,7 +2481,8 @@ gus_set_recrate(sc, rate)
struct gus_softc *sc;
u_long rate;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
u_char realrate;
DPRINTF(("gus_set_recrate %lu\n", rate));
@@ -2567,8 +2491,8 @@ gus_set_recrate(sc, rate)
#endif
realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
- SELECT_GUS_REG(port, GUSREG_SAMPLE_FREQ);
- outb(port+GUS_DATA_HIGH, realrate);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_FREQ);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, realrate);
}
/*
@@ -2581,7 +2505,7 @@ gusmax_speaker_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_speaker_ctl(sc->parent, newstate);
}
@@ -2590,18 +2514,20 @@ gus_speaker_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
/* Line out bit is flipped: 0 enables, 1 disables */
if ((newstate == SPKR_ON) &&
(sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
if ((newstate == SPKR_OFF) &&
(sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
return 0;
@@ -2612,18 +2538,20 @@ gus_linein_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
/* Line in bit is flipped: 0 enables, 1 disables */
if ((newstate == SPKR_ON) &&
(sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
if ((newstate == SPKR_OFF) &&
(sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
sc->sc_mixcontrol |= GUSMASK_LINE_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
return 0;
@@ -2634,18 +2562,20 @@ gus_mic_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
/* Mic bit is normal: 1 enables, 0 disables */
if ((newstate == SPKR_ON) &&
(sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
sc->sc_mixcontrol |= GUSMASK_MIC_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
if ((newstate == SPKR_OFF) &&
(sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
return 0;
@@ -2661,17 +2591,18 @@ gus_set_endaddr(sc, voice, addr)
int voice;
u_long addr;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
sc->sc_voc[voice].end_addr = addr;
if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
addr = convert_to_16bit(addr);
- SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
- SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
}
@@ -2685,19 +2616,20 @@ gus_set_curaddr(sc, voice, addr)
int voice;
u_long addr;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
sc->sc_voc[voice].current_addr = addr;
if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
addr = convert_to_16bit(addr);
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
}
@@ -2709,18 +2641,19 @@ gus_get_curaddr(sc, voice)
struct gus_softc *sc;
int voice;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
u_long addr;
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
- addr = (inw(port+GUS_DATA_LOW) & 0x1fff) << 7;
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
- addr |= (inw(port+GUS_DATA_LOW) >> 9L) & 0x7f;
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
+ addr = (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) & 0x1fff) << 7;
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
+ addr |= (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) >> 9L) & 0x7f;
if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
- DPRINTF(("gus voice %d curaddr %d end_addr %d\n",
+ DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n",
voice, addr, sc->sc_voc[voice].end_addr));
/* XXX sanity check the address? */
@@ -2752,8 +2685,9 @@ convert_to_16bit(address)
*/
STATIC void
-guspoke(port, address, value)
- int port;
+guspoke(iot, ioh2, address, value)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh2;
long address;
unsigned char value;
{
@@ -2762,16 +2696,16 @@ guspoke(port, address, value)
* Select the DRAM address
*/
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
- outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
- outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
/*
* Actually write the data
*/
- outb(port+GUS_DRAM_DATA, value);
+ bus_space_write_1(iot, ioh2, GUS_DRAM_DATA, value);
}
/*
@@ -2779,8 +2713,9 @@ guspoke(port, address, value)
*/
STATIC unsigned char
-guspeek(port, address)
- int port;
+guspeek(iot, ioh2, address)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh2;
u_long address;
{
@@ -2788,16 +2723,16 @@ guspeek(port, address)
* Select the DRAM address
*/
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
- outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
- outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
/*
* Read in the data from the board
*/
- return (unsigned char) inb(port+GUS_DRAM_DATA);
+ return (unsigned char) bus_space_read_1(iot, ioh2, GUS_DRAM_DATA);
}
/*
@@ -2809,7 +2744,10 @@ gusreset(sc, voices)
struct gus_softc *sc;
int voices;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ bus_space_handle_t ioh4 = sc->sc_ioh4;
int i,s;
s = splgus();
@@ -2818,8 +2756,8 @@ gusreset(sc, voices)
* Reset the GF1 chip
*/
- SELECT_GUS_REG(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
delay(500);
@@ -2827,8 +2765,8 @@ gusreset(sc, voices)
* Release reset
*/
- SELECT_GUS_REG(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
delay(500);
@@ -2836,106 +2774,108 @@ gusreset(sc, voices)
* Reset MIDI port as well
*/
- outb(GUS_MIDI_CONTROL,MIDI_RESET);
+ bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, MIDI_RESET);
delay(500);
- outb(GUS_MIDI_CONTROL,0x00);
+ bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, 0x00);
/*
* Clear interrupts
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
- SELECT_GUS_REG(port, GUSREG_TIMER_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_TIMER_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
gus_set_voices(sc, voices);
- inb(port+GUS_IRQ_STATUS);
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
- inb(port+GUS_DATA_HIGH);
+ bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
/*
* Reset voice specific information
*/
for(i = 0; i < voices; i++) {
- outb(port+GUS_VOICE_SELECT, (unsigned char) i);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) i);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
GUSMASK_STOP_VOICE;
- outb(port+GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
GUSMASK_STOP_VOLUME;
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
delay(100);
gus_set_samprate(sc, i, 8000);
- SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
- outb(port+GUS_DATA_HIGH, 0x01);
- SELECT_GUS_REG(port, GUSREG_START_VOLUME);
- outb(port+GUS_DATA_HIGH, 0x10);
- SELECT_GUS_REG(port, GUSREG_END_VOLUME);
- outb(port+GUS_DATA_HIGH, 0xe0);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x0000);
-
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_PAN_POS);
- outb(port+GUS_DATA_HIGH, 0x07);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x01);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x10);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0xe0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x07);
}
/*
* Clear out any pending IRQs
*/
- inb(port+GUS_IRQ_STATUS);
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
- inb(port+GUS_DATA_HIGH);
+ bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
GUSMASK_IRQ_ENABLE);
splx(s);
}
-STATIC void
+STATIC int
gus_init_cs4231(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
+ int port = sc->sc_iobase;
u_char ctrl;
ctrl = (port & 0xf0) >> 4; /* set port address middle nibble */
@@ -2948,60 +2888,16 @@ gus_init_cs4231(sc)
if (sc->sc_recdrq >= 4)
ctrl |= GUS_MAX_PLAYCHAN16;
- outb(port+GUS_MAX_CTRL, ctrl);
+ bus_space_write_1(iot, ioh1, GUS_MAX_CTRL, ctrl);
+ sc->sc_codec.sc_iot = sc->sc_iot;
sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
if (ad1848_probe(&sc->sc_codec) == 0) {
sc->sc_flags &= ~GUS_CODEC_INSTALLED;
+ return (0);
} else {
struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
- struct audio_hw_if gusmax_hw_if = {
- gusopen,
- gusmax_close,
- NULL, /* drain */
- gusmax_set_in_sr,
- gusmax_get_in_sr,
- gusmax_set_out_sr,
- gusmax_get_out_sr,
-
- ad1848_query_encoding, /* query encoding */
- gusmax_set_format,
- gusmax_get_encoding,
- gusmax_get_precision,
-
- gusmax_set_channels,
- gusmax_get_channels,
-
- gusmax_round_blocksize,
-
- gusmax_set_out_port,
- gusmax_get_out_port,
- gusmax_set_in_port,
- gusmax_get_in_port,
-
- gusmax_commit_settings,
-
- gusmax_expand, /* XXX use codec */
- mulaw_compress,
-
- gusmax_dma_output,
- gusmax_dma_input,
- gusmax_halt_out_dma,
- gusmax_halt_in_dma,
- gusmax_cont_out_dma,
- gusmax_cont_in_dma,
-
- gusmax_speaker_ctl,
-
- gus_getdev,
- gus_setfd,
- gusmax_mixer_set_port,
- gusmax_mixer_get_port,
- gusmax_mixer_query_devinfo,
- 1, /* full-duplex */
- 0,
- };
sc->sc_flags |= GUS_CODEC_INSTALLED;
sc->sc_codec.parent = sc;
sc->sc_codec.sc_drq = sc->sc_recdrq;
@@ -3011,11 +2907,13 @@ gus_init_cs4231(sc)
will do the real mixing for them. */
sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
ad1848_attach(&sc->sc_codec);
/* turn on pre-MUX microphone gain. */
ad1848_set_mic_gain(&sc->sc_codec, &vol);
+
+ return (1);
}
}
@@ -3056,128 +2954,6 @@ gus_get_in_gain(addr)
}
int
-gusmax_set_out_port(addr, port)
- void * addr;
- int port;
-{
- register struct ad1848_softc *sc = addr;
- return gus_set_out_port(sc->parent, port);
-}
-
-int
-gus_set_out_port(addr, port)
- void * addr;
- int port;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_set_out_port called\n"));
- sc->sc_out_port = port;
-
- return 0;
-}
-
-int
-gusmax_get_out_port(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_get_out_port(sc->parent);
-}
-
-int
-gus_get_out_port(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_get_out_port() called\n"));
- return sc->sc_out_port;
-}
-
-int
-gusmax_set_in_port(addr, port)
- void * addr;
- int port;
-{
- register struct ad1848_softc *sc = addr;
- DPRINTF(("gusmax_set_in_port: %d\n", port));
-
- switch(port) {
- case GUSMAX_MONO_LVL:
- port = MIC_IN_PORT;
- break;
- case GUSMAX_LINE_IN_LVL:
- port = LINE_IN_PORT;
- break;
- case GUSMAX_DAC_LVL:
- port = AUX1_IN_PORT;
- break;
- case GUSMAX_MIX_IN:
- port = DAC_IN_PORT;
- break;
- default:
- return(EINVAL);
- /*NOTREACHED*/
- }
- return(ad1848_set_rec_port(sc, port));
-}
-
-int
-gusmax_get_in_port(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- int port = GUSMAX_MONO_LVL;
-
- switch(ad1848_get_rec_port(sc)) {
- case MIC_IN_PORT:
- port = GUSMAX_MONO_LVL;
- break;
- case LINE_IN_PORT:
- port = GUSMAX_LINE_IN_LVL;
- break;
- case DAC_IN_PORT:
- port = GUSMAX_MIX_IN;
- break;
- case AUX1_IN_PORT:
- port = GUSMAX_DAC_LVL;
- break;
- }
-
- DPRINTF(("gusmax_get_in_port: %d\n", port));
-
- return(port);
-}
-
-int
-gus_set_in_port(addr, port)
- void * addr;
- int port;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_set_in_port called\n"));
- /*
- * On the GUS with ICS mixer, the ADC input is after the mixer stage,
- * so we can't set the input port.
- *
- * On the GUS with CS4231 codec/mixer, see gusmax_set_in_port().
- */
- sc->sc_in_port = port;
-
- return 0;
-}
-
-
-int
-gus_get_in_port(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_get_in_port called\n"));
- return sc->sc_in_port;
-}
-
-
-int
gusmax_dma_input(addr, buf, size, callback, arg)
void * addr;
void *buf;
@@ -3185,7 +2961,7 @@ gusmax_dma_input(addr, buf, size, callback, arg)
void (*callback) __P((void *));
void *arg;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_dma_input(sc->parent, buf, size, callback, arg);
}
@@ -3201,9 +2977,10 @@ gus_dma_input(addr, buf, size, callback, arg)
void (*callback) __P((void *));
void *arg;
{
- register struct gus_softc *sc = addr;
- register int port = sc->sc_iobase;
- register u_char dmac;
+ struct gus_softc *sc = addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ u_char dmac;
DMAPRINTF(("gus_dma_input called\n"));
/*
@@ -3218,11 +2995,14 @@ gus_dma_input(addr, buf, size, callback, arg)
if (sc->sc_recdrq >= 4)
dmac |= GUSMASK_SAMPLE_DATA16;
if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
- sc->sc_encoding == AUDIO_ENCODING_PCM8)
+ sc->sc_encoding == AUDIO_ENCODING_ALAW ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE)
dmac |= GUSMASK_SAMPLE_INVBIT;
if (sc->sc_channels == 2)
dmac |= GUSMASK_SAMPLE_STEREO;
- isadma_start((caddr_t)buf, size, sc->sc_recdrq, DMAMODE_READ);
+ isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size,
+ NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
DMAPRINTF(("gus_dma_input isadma_started\n"));
sc->sc_flags |= GUS_DMAIN_ACTIVE;
@@ -3231,8 +3011,8 @@ gus_dma_input(addr, buf, size, callback, arg)
sc->sc_dmaincnt = size;
sc->sc_dmainaddr = buf;
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- outb(port+GUS_DATA_HIGH, dmac); /* Go! */
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, dmac); /* Go! */
DMAPRINTF(("gus_dma_input returning\n"));
@@ -3249,7 +3029,7 @@ gus_dmain_intr(sc)
DMAPRINTF(("gus_dmain_intr called\n"));
if (sc->sc_dmainintr) {
- isadma_done(sc->sc_recdrq);
+ isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq);
callback = sc->sc_dmainintr;
arg = sc->sc_inarg;
@@ -3259,7 +3039,7 @@ gus_dmain_intr(sc)
sc->sc_inarg = 0;
sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
- DMAPRINTF(("calling dmain_intr callback %x(%x)\n", callback, arg));
+ DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg));
(*callback)(arg);
return 1;
} else {
@@ -3272,7 +3052,7 @@ int
gusmax_halt_out_dma(addr)
void * addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_halt_out_dma(sc->parent);
}
@@ -3281,26 +3061,10 @@ int
gusmax_halt_in_dma(addr)
void * addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_halt_in_dma(sc->parent);
}
-int
-gusmax_cont_out_dma(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_cont_out_dma(sc->parent);
-}
-
-int
-gusmax_cont_in_dma(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_cont_in_dma(sc->parent);
-}
-
/*
* Stop any DMA output. Called at splgus().
*/
@@ -3308,19 +3072,20 @@ int
gus_halt_out_dma(addr)
void * addr;
{
- register struct gus_softc *sc = addr;
- register int port = sc->sc_iobase;
+ struct gus_softc *sc = addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
DMAPRINTF(("gus_halt_out_dma called\n"));
/*
* Make sure the GUS _isn't_ setup for DMA
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
untimeout(gus_dmaout_timeout, sc);
- isadma_abort(sc->sc_drq);
+ isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
sc->sc_dmaoutintr = 0;
sc->sc_outarg = 0;
@@ -3343,20 +3108,20 @@ int
gus_halt_in_dma(addr)
void * addr;
{
- register struct gus_softc *sc = addr;
- register int port = sc->sc_iobase;
+ struct gus_softc *sc = addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
DMAPRINTF(("gus_halt_in_dma called\n"));
/*
* Make sure the GUS _isn't_ setup for DMA
*/
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- outb(port+GUS_DATA_HIGH,
- inb(port+GUS_DATA_HIGH) &
- ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
-
- isadma_abort(sc->sc_recdrq);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH,
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
+
+ isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq);
sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
sc->sc_dmainintr = 0;
sc->sc_inarg = 0;
@@ -3366,34 +3131,6 @@ gus_halt_in_dma(addr)
return 0;
}
-int
-gus_cont_out_dma(addr)
- void * addr;
-{
- DPRINTF(("gus_cont_out_dma called\n"));
- return EOPNOTSUPP;
-}
-
-int
-gus_cont_in_dma(addr)
- void * addr;
-{
- DPRINTF(("gus_cont_in_dma called\n"));
- return EOPNOTSUPP;
-}
-
-
-STATIC int
-gus_setfd(addr, flag)
- void *addr;
- int flag;
-{
- if (gus_hw_if.full_duplex == 0)
- return ENOTTY;
-
- return(0); /* nothing fancy to do. */
-}
-
STATIC __inline int
gus_to_vol(cp, vol)
mixer_ctrl_t *cp;
@@ -3433,8 +3170,8 @@ gusmax_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -3584,8 +3321,8 @@ gus_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct gus_softc *sc = addr;
- register struct ics2101_softc *ic = &sc->sc_mixer;
+ struct gus_softc *sc = addr;
+ struct ics2101_softc *ic = &sc->sc_mixer;
struct ad1848_volume vol;
int error = EINVAL;
@@ -3754,8 +3491,8 @@ gusmax_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -3907,8 +3644,8 @@ gus_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct gus_softc *sc = addr;
- register struct ics2101_softc *ic = &sc->sc_mixer;
+ struct gus_softc *sc = addr;
+ struct ics2101_softc *ic = &sc->sc_mixer;
struct ad1848_volume vol;
int error = EINVAL;
@@ -4063,21 +3800,29 @@ gus_mixer_set_port(addr, cp)
}
STATIC int
+gus_get_props(addr)
+ void *addr;
+{
+ struct gus_softc *sc = addr;
+ return sc->sc_recdrq == sc->sc_drq ? 0 : AUDIO_PROP_FULLDUPLEX;
+}
+
+STATIC int
+gusmax_get_props(addr)
+ void *addr;
+{
+ struct ad1848_softc *ac = addr;
+ return gus_get_props(ac->parent);
+}
+
+STATIC int
gusmax_mixer_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
switch(dip->index) {
- case GUSMAX_MIX_IN: /* mixed MUX input */
- dip->type = AUDIO_MIXER_ENUM;
- dip->mixer_class = GUSMAX_INPUT_CLASS;
- dip->prev = dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmixerout);
- dip->un.e.num_mem = 0; /* XXX */
- break;
-
#if 0
case GUSMAX_MIC_IN_LVL: /* Microphone */
dip->type = AUDIO_MIXER_VALUE;
@@ -4155,7 +3900,7 @@ gusmax_mixer_query_devinfo(addr, dip)
dip->mixer_class = GUSMAX_MONITOR_CLASS;
dip->prev = AUDIO_MIXER_LAST;
dip->next = GUSMAX_SPEAKER_MUTE;
- strcpy(dip->label.name, AudioNspeaker);
+ strcpy(dip->label.name, AudioNmaster);
dip->un.v.num_channels = 2;
strcpy(dip->un.v.units.name, AudioNvolume);
break;
@@ -4227,41 +3972,41 @@ gusmax_mixer_query_devinfo(addr, dip)
strcpy(dip->label.name, AudioNsource);
dip->un.e.num_mem = 4;
strcpy(dip->un.e.member[0].label.name, AudioNoutput);
- dip->un.e.member[0].ord = GUSMAX_MIX_IN;
+ dip->un.e.member[0].ord = DAC_IN_PORT;
strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
- dip->un.e.member[1].ord = GUSMAX_MONO_LVL;
+ dip->un.e.member[1].ord = MIC_IN_PORT;
strcpy(dip->un.e.member[2].label.name, AudioNdac);
- dip->un.e.member[2].ord = GUSMAX_DAC_LVL;
+ dip->un.e.member[2].ord = AUX1_IN_PORT;
strcpy(dip->un.e.member[3].label.name, AudioNline);
- dip->un.e.member[3].ord = GUSMAX_LINE_IN_LVL;
+ dip->un.e.member[3].ord = LINE_IN_PORT;
break;
case GUSMAX_INPUT_CLASS: /* input class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_INPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ strcpy(dip->label.name, AudioCinputs);
break;
case GUSMAX_OUTPUT_CLASS: /* output class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCOutputs);
+ strcpy(dip->label.name, AudioCoutputs);
break;
case GUSMAX_MONITOR_CLASS: /* monitor class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_MONITOR_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCMonitor);
+ strcpy(dip->label.name, AudioCmonitor);
break;
case GUSMAX_RECORD_CLASS: /* record source class */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_RECORD_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCRecord);
+ strcpy(dip->label.name, AudioCrecord);
break;
default:
@@ -4275,9 +4020,9 @@ gusmax_mixer_query_devinfo(addr, dip)
STATIC int
gus_mixer_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
@@ -4331,7 +4076,7 @@ gus_mixer_query_devinfo(addr, dip)
dip->mixer_class = GUSICS_OUTPUT_CLASS;
dip->prev = AUDIO_MIXER_LAST;
dip->next = GUSICS_MASTER_MUTE;
- strcpy(dip->label.name, AudioNvolume);
+ strcpy(dip->label.name, AudioNmaster);
dip->un.v.num_channels = 2;
strcpy(dip->un.v.units.name, AudioNvolume);
break;
@@ -4393,21 +4138,21 @@ mute:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSICS_INPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ strcpy(dip->label.name, AudioCinputs);
break;
case GUSICS_OUTPUT_CLASS:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSICS_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCOutputs);
+ strcpy(dip->label.name, AudioCoutputs);
break;
case GUSICS_RECORD_CLASS:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSICS_RECORD_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCRecord);
+ strcpy(dip->label.name, AudioCrecord);
break;
default:
@@ -4426,16 +4171,53 @@ gus_query_encoding(addr, fp)
switch (fp->index) {
case 0:
strcpy(fp->name, AudioEmulaw);
- fp->format_id = AUDIO_ENCODING_ULAW;
+ fp->encoding = AUDIO_ENCODING_ULAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
break;
case 1:
- strcpy(fp->name, AudioEpcm16);
- fp->format_id = AUDIO_ENCODING_PCM16;
+ strcpy(fp->name, AudioEslinear);
+ fp->encoding = AUDIO_ENCODING_SLINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
break;
case 2:
- strcpy(fp->name, AudioEpcm8);
- fp->format_id = AUDIO_ENCODING_PCM8;
+ strcpy(fp->name, AudioEslinear_le);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
break;
+ case 3:
+ strcpy(fp->name, AudioEulinear);
+ fp->encoding = AUDIO_ENCODING_ULINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
+ break;
+ case 4:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
+ break;
+ case 5:
+ strcpy(fp->name, AudioEslinear_be);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 6:
+ strcpy(fp->name, AudioEulinear_be);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 7:
+ strcpy(fp->name, AudioEalaw);
+ fp->encoding = AUDIO_ENCODING_ALAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+
default:
return(EINVAL);
/*NOTREACHED*/
@@ -4452,10 +4234,12 @@ STATIC void
gus_init_ics2101(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
- register struct ics2101_softc *ic = &sc->sc_mixer;
- sc->sc_mixer.sc_selio = port+GUS_MIXER_SELECT;
- sc->sc_mixer.sc_dataio = port+GUS_MIXER_DATA;
+ struct ics2101_softc *ic = &sc->sc_mixer;
+ sc->sc_mixer.sc_iot = sc->sc_iot;
+ sc->sc_mixer.sc_selio = GUS_MIXER_SELECT;
+ sc->sc_mixer.sc_selio_ioh = sc->sc_ioh3;
+ sc->sc_mixer.sc_dataio = GUS_MIXER_DATA;
+ sc->sc_mixer.sc_dataio_ioh = sc->sc_ioh2;
sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
ics2101_mix_attenuate(ic,
diff --git a/sys/dev/isa/gusreg.h b/sys/dev/isa/gusreg.h
index 88f55d1cf81..b1b86a42e87 100644
--- a/sys/dev/isa/gusreg.h
+++ b/sys/dev/isa/gusreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: gusreg.h,v 1.3 1997/07/10 23:06:35 provos Exp $ */
-/* $NetBSD: gusreg.h,v 1.3 1996/02/05 02:22:10 jtc Exp $ */
+/* $OpenBSD: gusreg.h,v 1.4 1998/04/26 21:02:43 provos Exp $ */
+/* $NetBSD: gusreg.h,v 1.6 1997/10/09 07:57:22 jtc Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * 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
@@ -47,10 +47,13 @@
* address.
*/
-#define GUS_MIDI_CONTROL 0x100
-#define GUS_MIDI_STATUS 0x100
-#define GUS_MIDI_READ 0x101
-#define GUS_MIDI_WRITE 0x101
+#define GUS_IOH4_OFFSET 0x100
+#define GUS_NPORT4 2
+
+#define GUS_MIDI_CONTROL (0x100-GUS_IOH4_OFFSET)
+#define GUS_MIDI_STATUS (0x100-GUS_IOH4_OFFSET)
+#define GUS_MIDI_READ (0x101-GUS_IOH4_OFFSET)
+#define GUS_MIDI_WRITE (0x101-GUS_IOH4_OFFSET)
/*
* Joystick interface - note this is an absolute address, NOT an offset from
@@ -79,11 +82,18 @@
#define GUS_DMA_CONTROL 0x00b
#define GUS_IRQCTL_CONTROL 0x00b
#define GUS_JUMPER_CONTROL 0x00b
-#define GUS_VOICE_SELECT 0x102
-#define GUS_REG_SELECT 0x103
-#define GUS_DATA_LOW 0x104
-#define GUS_DATA_HIGH 0x105
-#define GUS_DRAM_DATA 0x107
+
+#define GUS_NPORT1 16
+
+#define GUS_IOH2_OFFSET 0x102
+#define GUS_VOICE_SELECT (0x102-GUS_IOH2_OFFSET)
+#define GUS_REG_SELECT (0x103-GUS_IOH2_OFFSET)
+#define GUS_DATA_LOW (0x104-GUS_IOH2_OFFSET)
+#define GUS_DATA_HIGH (0x105-GUS_IOH2_OFFSET)
+/* GUS_MIXER_SELECT 106 */
+#define GUS_DRAM_DATA (0x107-GUS_IOH2_OFFSET)
+
+#define GUS_NPORT2 6
/*
* GUS on-board global registers
@@ -229,9 +239,12 @@
* ICS Mixer registers
*/
-#define GUS_MIXER_SELECT 0x506 /* read=board rev, wr=mixer */
-#define GUS_BOARD_REV 0x506
-#define GUS_MIXER_DATA 0x106 /* data for mixer control */
+#define GUS_IOH3_OFFSET 0x506
+#define GUS_NPORT3 1
+
+#define GUS_MIXER_SELECT (0x506-GUS_IOH3_OFFSET) /* read=board rev, wr=mixer */
+#define GUS_BOARD_REV (0x506-GUS_IOH3_OFFSET)
+#define GUS_MIXER_DATA (0x106-GUS_IOH2_OFFSET) /* data for mixer control */
#define GUSMIX_CHAN_MIC ICSMIX_CHAN_0
#define GUSMIX_CHAN_LINE ICSMIX_CHAN_1
diff --git a/sys/dev/isa/ics2101.c b/sys/dev/isa/ics2101.c
index 458d1424ffd..88049e3e56d 100644
--- a/sys/dev/isa/ics2101.c
+++ b/sys/dev/isa/ics2101.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ics2101.c,v 1.3 1996/05/07 07:36:42 deraadt Exp $ */
-/* $NetBSD: ics2101.c,v 1.4 1996/04/29 20:03:10 christos Exp $ */
+/* $OpenBSD: ics2101.c,v 1.4 1998/04/26 21:02:44 provos Exp $ */
+/* $NetBSD: ics2101.c,v 1.6 1997/10/09 07:57:23 jtc Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * 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
@@ -80,6 +80,7 @@ ics2101_mix_doit(sc, chan, side, value, flags)
struct ics2101_softc *sc;
u_int chan, side, value, flags;
{
+ bus_space_tag_t iot = sc->sc_iot;
unsigned char flip_left[6] = {0x01, 0x01, 0x01, 0x02, 0x01, 0x02};
unsigned char flip_right[6] = {0x02, 0x02, 0x02, 0x01, 0x02, 0x01};
register unsigned char ctrl_addr;
@@ -128,11 +129,11 @@ ics2101_mix_doit(sc, chan, side, value, flags)
s = splaudio();
- outb(sc->sc_selio, ctrl_addr);
- outb(sc->sc_dataio, normal);
+ bus_space_write_1(iot, sc->sc_selio_ioh, sc->sc_selio, ctrl_addr);
+ bus_space_write_1(iot, sc->sc_dataio_ioh, sc->sc_dataio, normal);
- outb(sc->sc_selio, attn_addr);
- outb(sc->sc_dataio, (unsigned char) value);
+ bus_space_write_1(iot, sc->sc_selio_ioh, sc->sc_selio, attn_addr);
+ bus_space_write_1(iot, sc->sc_dataio_ioh, sc->sc_dataio, (unsigned char) value);
splx(s);
}
diff --git a/sys/dev/isa/ics2101var.h b/sys/dev/isa/ics2101var.h
index b9a61a63758..26d88f71717 100644
--- a/sys/dev/isa/ics2101var.h
+++ b/sys/dev/isa/ics2101var.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ics2101var.h,v 1.2 1996/03/08 16:42:58 niklas Exp $ */
-/* $NetBSD: ics2101var.h,v 1.3 1996/02/05 02:22:12 jtc Exp $ */
+/* $OpenBSD: ics2101var.h,v 1.3 1998/04/26 21:02:45 provos Exp $ */
+/* $NetBSD: ics2101var.h,v 1.5 1997/10/09 07:57:24 jtc Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * 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
@@ -41,6 +41,9 @@
#define ICSMIX_RIGHT 1 /* Value for right channel */
struct ics2101_softc {
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_selio_ioh;
+ bus_space_handle_t sc_dataio_ioh;
u_short sc_selio; /* select I/O address */
u_short sc_dataio; /* data I/O address */
int sc_flags; /* Various flags */
diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c
index 3010e861fdd..39366021b0e 100644
--- a/sys/dev/isa/isa.c
+++ b/sys/dev/isa/isa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa.c,v 1.31 1998/01/20 21:42:25 niklas Exp $ */
+/* $OpenBSD: isa.c,v 1.32 1998/04/26 21:02:47 provos Exp $ */
/* $NetBSD: isa.c,v 1.85 1996/05/14 00:31:04 thorpej Exp $ */
/*
@@ -173,6 +173,8 @@ isaprint(aux, isa)
printf(" irq %d", ia->ia_irq);
if (ia->ia_drq != DRQUNK)
printf(" drq %d", ia->ia_drq);
+ if (ia->ia_drq2 != DRQUNK)
+ printf(" drq2 %d", ia->ia_drq2);
return (UNCONF);
}
@@ -192,12 +194,13 @@ isascan(parent, match)
ia.ia_dmat = sc->sc_dmat;
#endif /* NISADMA > 0 */
ia.ia_ic = sc->sc_ic;
- ia.ia_iobase = cf->cf_loc[0];
+ ia.ia_iobase = cf->cf_iobase;
ia.ia_iosize = 0x666;
- ia.ia_maddr = cf->cf_loc[2];
- ia.ia_msize = cf->cf_loc[3];
- ia.ia_irq = cf->cf_loc[4] == 2 ? 9 : cf->cf_loc[4];
- ia.ia_drq = cf->cf_loc[5];
+ ia.ia_maddr = cf->cf_maddr;
+ ia.ia_msize = cf->cf_msize;
+ ia.ia_irq = cf->cf_irq == 2 ? 9 : cf->cf_irq;
+ ia.ia_drq = cf->cf_drq;
+ ia.ia_drq2 = cf->cf_drq2;
ia.ia_delaybah = sc->sc_delaybah;
if (cf->cf_fstate == FSTATE_STAR) {
@@ -223,6 +226,8 @@ isascan(parent, match)
#if NISADMA > 0
if (ia.ia_drq != DRQUNK)
ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
+ if (ia.ia_drq2 != DRQUNK)
+ ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq2);
#endif /* NISAMDA > 0 */
}
if (autoconf_verbose)
@@ -244,6 +249,8 @@ isascan(parent, match)
#if NISADMA > 0
if (ia.ia_drq != DRQUNK)
ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
+ if (ia.ia_drq2 != DRQUNK)
+ ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq2);
#endif /* NISAMDA > 0 */
} else {
if (autoconf_verbose)
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index a6ef11c2547..3cbfd104aa4 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isavar.h,v 1.27 1998/01/20 18:40:33 niklas Exp $ */
+/* $OpenBSD: isavar.h,v 1.28 1998/04/26 21:02:48 provos Exp $ */
/* $NetBSD: isavar.h,v 1.26 1997/06/06 23:43:57 thorpej Exp $ */
/*-
@@ -289,6 +289,7 @@ struct isa_attach_args {
#define ia_iosize ipa_io[0].length
#define ia_irq ipa_irq[0].num
#define ia_drq ipa_drq[0].num
+#define ia_drq2 ipa_drq[1].num
#define ia_maddr ipa_mem[0].base
#define ia_msize ipa_mem[0].length
#define ia_ioh ipa_io[0].h
@@ -372,6 +373,7 @@ struct isa_softc {
#define cf_msize cf_loc[3]
#define cf_irq cf_loc[4]
#define cf_drq cf_loc[5]
+#define cf_drq2 cf_loc[6]
/*
* ISA interrupt handler manipulation.
diff --git a/sys/dev/isa/madreg.h b/sys/dev/isa/madreg.h
new file mode 100644
index 00000000000..5e6e114aaec
--- /dev/null
+++ b/sys/dev/isa/madreg.h
@@ -0,0 +1,102 @@
+/* $OpenBSD: madreg.h,v 1.1 1998/04/26 21:02:37 provos Exp $ */
+/* $NetBSD: madreg.h,v 1.4 1998/01/19 22:18:27 augustss Exp $ */
+/*
+ * Copyright (c) 1996 Lennart Augustsson
+ * Copyright (c) 1995 Hannu Savolainen
+ * 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.
+ *
+ */
+
+/*
+ * Variations of the suppored chips.
+ */
+
+#define MAD_NONE 0
+#define MAD_82C928 1 /* OPTi 82C928 MAD16 */
+#define MAD_OTI601D 2 /* OAK OTI-601D Mozart */
+#define MAD_82C929 3 /* OPTi 82C929 MAD16 Pro */
+#define MAD_82C931 4 /* OPTi 82C831 */
+
+/*
+ * Registers
+ *
+ * The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations).
+ * All ports are inactive by default. They can be activated by
+ * writing 0xE2 or 0xE3 to the password register. The password is valid
+ * only until the next I/O read or write.
+ */
+
+#define MAD_BASE 0xf8d
+#define MAD_NPORT 7
+
+#define MC1_PORT 0 /* SB address, CDROM interface type, joystick */
+#define MC2_PORT 1 /* CDROM address, IRQ, DMA, plus OPL4 bit */
+#define MC3_PORT 2
+#define MC_PASSWD_REG MC3_PORT
+#define MC4_PORT 3
+#define MC5_PORT 4
+#define MC6_PORT 5
+#define MC7_PORT 6
+
+#define MC1_NOCD 0x00
+#define MC1_JOYDISABLE 0x01
+#define MC1_SONY 0x02
+#define MC1_MITSUMI 0x04
+#define MC1_PANASONIC 0x06
+#define MC1_SECIDE 0x08
+#define MC1_PRIMIDE 0x0a
+
+#define MC2_CDDISABLE 0x03
+#define MC2_OPL4 0x20
+
+/* Possible WSS emulation ports */
+#define M_WSS_PORT0 0x530
+#define M_WSS_PORT1 0xe80
+#define M_WSS_PORT2 0xf40
+#define M_WSS_PORT3 0x604
+#define M_WSS_NPORTS 4
+
+/* Port 1 */
+#define M_WSS_PORT_SELECT(i) (0x80 | ((i) << 4))
+
+#define M_PASSWD_928 0xe2
+#define M_PASSWD_929 0xe3
+#define M_PASSWD_931 0xe4
+
+/* Regions of I/O space that the MAD occupies besides
+ WSS emulation and MAD_BASE. Talk about waste. */
+#define MAD_REG1 0x220
+#define MAD_LEN1 16
+#define MAD_REG2 0x380
+#define MAD_LEN2 2
+#define MAD_REG3 0x388
+#define MAD_LEN3 4
diff --git a/sys/dev/isa/mcd.c b/sys/dev/isa/mcd.c
index 107599f8965..602aee9a684 100644
--- a/sys/dev/isa/mcd.c
+++ b/sys/dev/isa/mcd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mcd.c,v 1.23 1997/11/30 22:33:21 mickey Exp $ */
-/* $NetBSD: mcd.c,v 1.49 1996/05/12 23:53:11 mycroft Exp $ */
+/* $OpenBSD: mcd.c,v 1.24 1998/04/26 21:02:49 provos Exp $ */
+/* $NetBSD: mcd.c,v 1.60 1998/01/14 12:14:41 drochner Exp $ */
/*
* Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -75,7 +75,7 @@
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <machine/pio.h>
+#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/mcdreg.h>
@@ -118,12 +118,12 @@ struct mcd_softc {
struct disk sc_dk;
void *sc_ih;
- int iobase;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
int irq, drq;
char *type;
- u_char readcmd;
- u_char attached;
int flags;
#define MCDF_LOCKED 0x01
#define MCDF_WANTED 0x02
@@ -143,8 +143,10 @@ struct mcd_softc {
#define MCD_MD_UNKNOWN -1
int lastupc;
#define MCD_UPC_UNKNOWN -1
- int debug;
struct buf buf_queue;
+ u_char readcmd;
+ u_char debug;
+ u_char probe;
};
/* prototypes */
@@ -181,7 +183,13 @@ int mcd_read_toc __P((struct mcd_softc *));
int mcd_getqchan __P((struct mcd_softc *, union mcd_qchninfo *, int));
int mcd_setlock __P((struct mcd_softc *, int));
+int mcd_find __P((bus_space_tag_t, bus_space_handle_t, struct mcd_softc *));
+#define __BROKEN_INDIRECT_CONFIG
+#ifdef __BROKEN_INDIRECT_CONFIG
int mcdprobe __P((struct device *, void *, void *));
+#else
+int mcdprobe __P((struct device *, struct cfdata *, void *));
+#endif
void mcdattach __P((struct device *, struct device *, void *));
struct cfattach mcd_ca = {
@@ -192,6 +200,7 @@ struct cfdriver mcd_cd = {
NULL, "mcd", DV_DISK
};
+void mcdgetdefaultlabel __P((dev_t, struct mcd_softc *, struct disklabel *));
void mcdgetdisklabel __P((dev_t, struct mcd_softc *));
int mcd_get_parms __P((struct mcd_softc *));
void mcdstrategy __P((struct buf *));
@@ -219,8 +228,27 @@ mcdattach(parent, self, aux)
{
struct mcd_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
+ bus_space_tag_t iot = ia->ia_iot;
+ bus_space_handle_t ioh;
struct mcd_mbox mbx;
+ /* Map i/o space */
+ if (bus_space_map(iot, ia->ia_iobase, MCD_NPORT, 0, &ioh)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ sc->sc_iot = iot;
+ sc->sc_ioh = ioh;
+
+ sc->probe = 0;
+ sc->debug = 0;
+
+ if (!mcd_find(iot, ioh, sc)) {
+ printf(": mcd_find failed\n");
+ return;
+ }
+
/*
* Initialize and attach the disk structure.
*/
@@ -611,6 +639,10 @@ mcdioctl(dev, cmd, addr, flag, p)
case DIOCWLABEL:
return EBADF;
+/* case DIOCGDEFLABEL:
+ mcdgetdefaultlabel(dev, sc, (struct disklabel *)addr);
+ return 0;
+*/
case CDIOCPLAYTRACKS:
return mcd_playtracks(sc, (struct ioc_play_track *)addr);
case CDIOCPLAYMSF:
@@ -673,20 +705,15 @@ mcdioctl(dev, cmd, addr, flag, p)
#endif
}
-/*
- * This could have been taken from scsi/cd.c, but it is not clear
- * whether the scsi cd driver is linked in.
- */
void
-mcdgetdisklabel(dev, sc)
+mcdgetdefaultlabel(dev, sc, lp)
dev_t dev;
struct mcd_softc *sc;
+ struct disklabel *lp;
{
- struct disklabel *lp = sc->sc_dk.dk_label;
char *errstring;
bzero(lp, sizeof(struct disklabel));
- bzero(sc->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
lp->d_secsize = sc->blksize;
lp->d_ntracks = 1;
@@ -711,7 +738,7 @@ mcdgetdisklabel(dev, sc)
lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
lp->d_npartitions = RAW_PART + 1;
-
+
lp->d_magic = DISKMAGIC;
lp->d_magic2 = DISKMAGIC;
lp->d_checksum = dkcksum(lp);
@@ -727,6 +754,22 @@ mcdgetdisklabel(dev, sc)
}
}
+/*
+ * This could have been taken from scsi/cd.c, but it is not clear
+ * whether the scsi cd driver is linked in.
+ */
+void
+mcdgetdisklabel(dev, sc)
+ dev_t dev;
+ struct mcd_softc *sc;
+{
+ struct disklabel *lp = sc->sc_dk.dk_label;
+
+ bzero(sc->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
+
+ mcdgetdefaultlabel(dev, sc, lp);
+}
+
int
mcd_get_parms(sc)
struct mcd_softc *sc;
@@ -775,28 +818,27 @@ mcddump(dev, blkno, va, size)
return ENXIO;
}
+/*
+ * Find the board and fill in the softc.
+ */
int
-mcdprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
+mcd_find(iot, ioh, sc)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ struct mcd_softc *sc;
{
- struct mcd_softc *sc = match;
- struct isa_attach_args *ia = aux;
- int iobase = ia->ia_iobase;
int i;
struct mcd_mbox mbx;
- sc->iobase = iobase;
-
- if( !opti_cd_setup( OPTI_MITSUMI, iobase, ia->ia_irq, ia->ia_drq ) )
- /* printf("mcdprobe: could not setup OPTi chipset.\n") */;
+ sc->sc_iot = iot;
+ sc->sc_ioh = ioh;
/* Send a reset. */
- outb(iobase + MCD_RESET, 0);
+ bus_space_write_1(iot, ioh, MCD_RESET, 0);
delay(1000000);
/* Get any pending status and throw away. */
for (i = 10; i; i--)
- inb(iobase + MCD_STATUS);
+ bus_space_read_1(iot, ioh, MCD_STATUS);
delay(1000);
/* Send get status command. */
@@ -849,22 +891,64 @@ mcdprobe(parent, match, aux)
break;
}
- sc->attached = 1;
- ia->ia_iosize = 4;
- ia->ia_msize = 0;
return 1;
+
+}
+
+int
+mcdprobe(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;
+ struct mcd_softc sc;
+ bus_space_tag_t iot = ia->ia_iot;
+ bus_space_handle_t ioh;
+ int rv;
+
+ /* Disallow wildcarded i/o address. */
+ if (ia->ia_iobase == -1 /*ISACF_PORT_DEFAULT*/)
+ return (0);
+
+ /* Map i/o space */
+ if (bus_space_map(iot, ia->ia_iobase, MCD_NPORT, 0, &ioh))
+ return 0;
+
+ if (!opti_cd_setup(OPTI_MITSUMI, ia->ia_iobase, ia->ia_irq, ia->ia_drq))
+ /* printf("mcdprobe: could not setup OPTi chipset.\n") */;
+
+ sc.debug = 0;
+ sc.probe = 1;
+
+ rv = mcd_find(iot, ioh, &sc);
+
+ bus_space_unmap(iot, ioh, MCD_NPORT);
+
+ if (rv) {
+ ia->ia_iosize = MCD_NPORT;
+ ia->ia_msize = 0;
+ }
+
+ return (rv);
}
int
mcd_getreply(sc)
struct mcd_softc *sc;
{
- int iobase = sc->iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
int i;
/* Wait until xfer port senses data ready. */
for (i = DELAY_GETREPLY; i; i--) {
- if ((inb(iobase + MCD_XFER) & MCD_XF_STATUSUNAVAIL) == 0)
+ if ((bus_space_read_1(iot, ioh, MCD_XFER) &
+ MCD_XF_STATUSUNAVAIL) == 0)
break;
delay(DELAY_GRANULARITY);
}
@@ -872,7 +956,7 @@ mcd_getreply(sc)
return -1;
/* Get the data. */
- return inb(iobase + MCD_STATUS);
+ return bus_space_read_1(iot, ioh, MCD_STATUS);
}
int
@@ -901,7 +985,7 @@ mcd_getresult(sc, res)
if ((x = mcd_getreply(sc)) < 0) {
if (sc->debug)
printf(" timeout\n");
- else if (sc->attached)
+ else if (sc->probe)
printf("%s: timeout in getresult\n", sc->sc_dev.dv_xname);
return EIO;
}
@@ -931,8 +1015,9 @@ mcd_getresult(sc, res)
#ifdef MCDDEBUG
delay(10);
- while ((inb(sc->iobase + MCD_XFER) & MCD_XF_STATUSUNAVAIL) == 0) {
- x = inb(sc->iobase + MCD_STATUS);
+ while ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, MCD_XFER) &
+ MCD_XF_STATUSUNAVAIL) == 0) {
+ x = bus_space_read_1(sc->sc_iot, sc->sc_ioh, MCD_STATUS);
printf("%s: got extra byte %02x during getstatus\n",
sc->sc_dev.dv_xname, (u_int)x);
delay(10);
@@ -973,8 +1058,9 @@ mcd_send(sc, mbx, diskin)
struct mcd_mbox *mbx;
int diskin;
{
- int iobase = sc->iobase;
int retry, i, error;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
if (sc->debug) {
printf("%s: mcd_send: %d %02x", sc->sc_dev.dv_xname,
@@ -985,9 +1071,9 @@ mcd_send(sc, mbx, diskin)
}
for (retry = MCD_RETRIES; retry; retry--) {
- outb(iobase + MCD_COMMAND, mbx->cmd.opcode);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->cmd.opcode);
for (i = 0; i < mbx->cmd.length; i++)
- outb(iobase + MCD_COMMAND, mbx->cmd.data.raw.data[i]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->cmd.data.raw.data[i]);
if ((error = mcd_getresult(sc, &mbx->res)) == 0)
break;
if (error == EINVAL)
@@ -1054,8 +1140,9 @@ mcdintr(arg)
{
struct mcd_softc *sc = arg;
struct mcd_mbx *mbx = &sc->mbx;
- int iobase = sc->iobase;
struct buf *bp = mbx->bp;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
int i;
u_char x;
@@ -1071,8 +1158,8 @@ mcdintr(arg)
goto firstblock;
sc->lastmode = MCD_MD_UNKNOWN;
- outb(iobase + MCD_COMMAND, MCD_CMDSETMODE);
- outb(iobase + MCD_COMMAND, mbx->mode);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, MCD_CMDSETMODE);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->mode);
mbx->count = RDELAY_WAITMODE;
mbx->state = MCD_S_WAITMODE;
@@ -1080,14 +1167,14 @@ mcdintr(arg)
case MCD_S_WAITMODE:
untimeout(mcd_pseudointr, sc);
for (i = 20; i; i--) {
- x = inb(iobase + MCD_XFER);
+ x = bus_space_read_1(iot, ioh, MCD_XFER);
if ((x & MCD_XF_STATUSUNAVAIL) == 0)
break;
delay(50);
}
if (i == 0)
goto hold;
- sc->status = inb(iobase + MCD_STATUS);
+ sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
mcd_setflags(sc);
if ((sc->flags & MCDF_LOADED) == 0)
goto changed;
@@ -1104,13 +1191,13 @@ mcdintr(arg)
hsg2msf(mbx->blkno, msf);
/* Send the read command. */
- outb(iobase + MCD_COMMAND, sc->readcmd);
- outb(iobase + MCD_COMMAND, msf[0]);
- outb(iobase + MCD_COMMAND, msf[1]);
- outb(iobase + MCD_COMMAND, msf[2]);
- outb(iobase + MCD_COMMAND, 0);
- outb(iobase + MCD_COMMAND, 0);
- outb(iobase + MCD_COMMAND, mbx->nblk);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, sc->readcmd);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, msf[0]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, msf[1]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, msf[2]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->nblk);
mbx->count = RDELAY_WAITREAD;
mbx->state = MCD_S_WAITREAD;
@@ -1120,7 +1207,7 @@ mcdintr(arg)
nextblock:
loop:
for (i = 20; i; i--) {
- x = inb(iobase + MCD_XFER);
+ x = bus_space_read_1(iot, ioh, MCD_XFER);
if ((x & MCD_XF_DATAUNAVAIL) == 0)
goto gotblock;
if ((x & MCD_XF_STATUSUNAVAIL) == 0)
@@ -1129,7 +1216,7 @@ mcdintr(arg)
}
if (i == 0)
goto hold;
- sc->status = inb(iobase + MCD_STATUS);
+ sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
mcd_setflags(sc);
if ((sc->flags & MCDF_LOADED) == 0)
goto changed;
@@ -1144,9 +1231,10 @@ mcdintr(arg)
RDELAY_WAITREAD - mbx->count, 0, 0, 0);
/* Data is ready. */
- outb(iobase + MCD_CTL2, 0x04); /* XXX */
- insb(iobase + MCD_RDATA, bp->b_data + mbx->skip, mbx->sz);
- outb(iobase + MCD_CTL2, 0x0c); /* XXX */
+ bus_space_write_1(iot, ioh, MCD_CTL2, 0x04); /* XXX */
+ bus_space_read_multi_1(iot, ioh, MCD_RDATA,
+ bp->b_data + mbx->skip, mbx->sz);
+ bus_space_write_1(iot, ioh, MCD_CTL2, 0x0c); /* XXX */
mbx->blkno += 1;
mbx->skip += mbx->sz;
if (--mbx->nblk > 0)
@@ -1196,7 +1284,7 @@ changed:
#ifdef notyet
printf("%s: unit timeout; resetting\n", sc->sc_dev.dv_xname);
- outb(mbx->iobase + MCD_RESET, MCD_CMDRESET);
+ bus_space_write_1(iot, ioh, MCD_RESET, MCD_CMDRESET);
delay(300000);
(void) mcd_getstat(sc, 1);
(void) mcd_getstat(sc, 1);
@@ -1215,7 +1303,7 @@ mcd_soft_reset(sc)
sc->lastmode = MCD_MD_UNKNOWN;
sc->lastupc = MCD_UPC_UNKNOWN;
sc->audio_status = CD_AS_AUDIO_INVALID;
- outb(sc->iobase + MCD_CTL2, 0x0c); /* XXX */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, MCD_CTL2, 0x0c); /* XXX */
}
int
diff --git a/sys/dev/isa/mcdreg.h b/sys/dev/isa/mcdreg.h
index 92677c4f307..198a6c22a53 100644
--- a/sys/dev/isa/mcdreg.h
+++ b/sys/dev/isa/mcdreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mcdreg.h,v 1.2 1997/11/07 08:07:05 niklas Exp $ */
-/* $NetBSD: mcdreg.h,v 1.7 1995/07/10 01:27:27 cgd Exp $ */
+/* $OpenBSD: mcdreg.h,v 1.3 1998/04/26 21:02:50 provos Exp $ */
+/* $NetBSD: mcdreg.h,v 1.8 1997/04/04 18:59:37 christos Exp $ */
/*
* Copyright 1993 by Holger Veit (data part)
@@ -60,6 +60,7 @@ typedef unsigned char bcd_t;
#define MCD_XFER 1
#define MCD_CTL2 2 /* XXX Is this right? */
#define MCD_CONFIG 3
+#define MCD_NPORT 4
#define MCD_MASK_DMA 0x07 /* bits 2-0 = DMA channel */
#define MCD_MASK_IRQ 0x70 /* bits 6-4 = INT number */
diff --git a/sys/dev/isa/pas.c b/sys/dev/isa/pas.c
index 41236ebe549..772bcf8d431 100644
--- a/sys/dev/isa/pas.c
+++ b/sys/dev/isa/pas.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pas.c,v 1.14 1997/07/10 23:06:36 provos Exp $ */
-/* $NetBSD: pas.c,v 1.17 1996/05/12 23:53:18 mycroft Exp $ */
+/* $OpenBSD: pas.c,v 1.15 1998/04/26 21:02:51 provos Exp $ */
+/* $NetBSD: pas.c,v 1.37 1998/01/12 09:43:43 thorpej Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -35,6 +35,13 @@
*
*/
/*
+ * jfw 7/13/97 - The soundblaster code requires the generic bus-space
+ * structures to be set up properly. Rather than go to the effort of making
+ * code for a dead line fully generic, properly set up the SB structures and
+ * leave the rest x86/ISA/default-configuration specific. If you have a
+ * REAL computer, go buy a REAL sound card.
+ */
+/*
* Todo:
* - look at other PAS drivers (for PAS native suport)
* - use common sb.c once emulation is setup
@@ -50,11 +57,11 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
#include <dev/audio_if.h>
-#include <dev/mulaw.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -95,7 +102,6 @@ struct pas_softc {
};
-int pasopen __P((dev_t, int));
int pas_getdev __P((void *, struct audio_device *));
void pasconf __P((int, int, int, int));
@@ -105,41 +111,30 @@ void pasconf __P((int, int, int, int));
*/
struct audio_hw_if pas_hw_if = {
- pasopen,
+ sbdsp_open,
sbdsp_close,
- NULL,
- sbdsp_set_in_sr,
- sbdsp_get_in_sr,
- sbdsp_set_out_sr,
- sbdsp_get_out_sr,
+ 0,
sbdsp_query_encoding,
- sbdsp_set_format,
- sbdsp_get_encoding,
- sbdsp_get_precision,
- sbdsp_set_channels,
- sbdsp_get_channels,
+ sbdsp_set_params,
sbdsp_round_blocksize,
- sbdsp_set_out_port,
- sbdsp_get_out_port,
- sbdsp_set_in_port,
- sbdsp_get_in_port,
- sbdsp_commit_settings,
- mulaw_expand,
- mulaw_compress,
+ 0,
+ sbdsp_dma_init_output,
+ sbdsp_dma_init_input,
sbdsp_dma_output,
sbdsp_dma_input,
sbdsp_haltdma,
sbdsp_haltdma,
- sbdsp_contdma,
- sbdsp_contdma,
sbdsp_speaker_ctl,
pas_getdev,
- sbdsp_setfd,
+ 0,
sbdsp_mixer_set_port,
sbdsp_mixer_get_port,
sbdsp_mixer_query_devinfo,
- 0, /* not full-duplex */
- 0
+ sb_malloc,
+ sb_free,
+ sb_round,
+ sb_mappage,
+ sbdsp_get_props,
};
/* The Address Translation code is used to convert I/O register addresses to
@@ -266,11 +261,17 @@ pasprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- register struct pas_softc *sc = match;
- register struct isa_attach_args *ia = aux;
- register int iobase;
+ struct pas_softc *sc = match;
+ struct isa_attach_args *ia = aux;
+ int iobase;
u_char id, t;
+ /* ensure we can set this up as a sound blaster */
+ if (!SB_BASE_VALID(ia->ia_iobase)) {
+ printf("pas: configured SB iobase 0x%x invalid\n", ia->ia_iobase);
+ return 0;
+ }
+
/*
* WARNING: Setting an option like W:1 or so that disables
* warm boot reset of the card will screw up this detect code
@@ -342,11 +343,24 @@ pasprobe(parent, match, aux)
return (0);
}
- /* Now a SoundBlaster */
+ /* Now a SoundBlaster, so set up proper bus-space hooks
+ * appropriately
+ */
+
sc->sc_sbdsp.sc_iobase = ia->ia_iobase;
+ sc->sc_sbdsp.sc_iot = ia->ia_iot;
+
+ /* Map i/o space [we map 24 ports which is the max of the sb and pro */
+ if (bus_space_map(sc->sc_sbdsp.sc_iot, ia->ia_iobase, SBP_NPORT, 0,
+ &sc->sc_sbdsp.sc_ioh)) {
+ printf("pas: can't map i/o space 0x%x/%d in probe\n",
+ ia->ia_iobase, SBP_NPORT);
+ return 0;
+ }
+
if (sbdsp_reset(&sc->sc_sbdsp) < 0) {
DPRINTF(("pas: couldn't reset card\n"));
- return 0;
+ goto unmap;
}
/*
@@ -354,7 +368,7 @@ pasprobe(parent, match, aux)
*/
if (!SB_DRQ_VALID(ia->ia_drq)) {
printf("pas: configured dma chan %d invalid\n", ia->ia_drq);
- return 0;
+ goto unmap;
}
#ifdef NEWCONFIG
/*
@@ -365,13 +379,13 @@ pasprobe(parent, match, aux)
sbdsp_reset(&sc->sc_sbdsp);
if (!SB_IRQ_VALID(ia->ia_irq)) {
printf("pas: couldn't auto-detect interrupt");
- return 0;
+ goto unmap;
}
} else
#endif
if (!SB_IRQ_VALID(ia->ia_irq)) {
printf("pas: configured irq chan %d invalid\n", ia->ia_irq);
- return 0;
+ goto unmap;
}
sc->sc_sbdsp.sc_irq = ia->ia_irq;
@@ -380,11 +394,15 @@ pasprobe(parent, match, aux)
if (sbdsp_probe(&sc->sc_sbdsp) == 0) {
DPRINTF(("pas: sbdsp probe failed\n"));
- return 0;
+ goto unmap;
}
ia->ia_iosize = SB_NPORT;
return 1;
+
+ unmap:
+ bus_space_unmap(sc->sc_sbdsp.sc_iot, sc->sc_sbdsp.sc_ioh, SBP_NPORT);
+ return 0;
}
#ifdef NEWCONFIG
@@ -424,10 +442,9 @@ pasattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- register struct pas_softc *sc = (struct pas_softc *)self;
+ struct pas_softc *sc = (struct pas_softc *)self;
struct isa_attach_args *ia = (struct isa_attach_args *)aux;
- register int iobase = ia->ia_iobase;
- int err;
+ int iobase = ia->ia_iobase;
sc->sc_sbdsp.sc_iobase = iobase;
sc->sc_sbdsp.sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
@@ -440,26 +457,7 @@ pasattach(parent, self, aux)
sprintf(pas_device.name, "pas,%s", pasnames[sc->model]);
sprintf(pas_device.version, "%d", sc->rev);
- if ((err = audio_hardware_attach(&pas_hw_if, &sc->sc_sbdsp)) != 0)
- printf("pas: could not attach to audio pseudo-device driver (%d)\n", err);
-}
-
-int
-pasopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct pas_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= pas_cd.cd_ndevs)
- return ENODEV;
-
- sc = pas_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
- return sbdsp_open(&sc->sc_sbdsp, dev, flags);
+ audio_attach_mi(&pas_hw_if, 0, &sc->sc_sbdsp, &sc->sc_sbdsp.sc_dev);
}
int
diff --git a/sys/dev/isa/pnpdevs b/sys/dev/isa/pnpdevs
index be03594869d..f3e003a5cb2 100644
--- a/sys/dev/isa/pnpdevs
+++ b/sys/dev/isa/pnpdevs
@@ -1,4 +1,4 @@
-# $OpenBSD: pnpdevs,v 1.10 1998/03/16 05:21:55 dgregor Exp $
+# $OpenBSD: pnpdevs,v 1.11 1998/04/26 21:02:53 provos Exp $
#
# NOTE: All `com' devices also need pccom identifiers.
@@ -368,4 +368,5 @@ sb CTL0041 #SB16 PnP (CT4131)
sb CTL0042 #SB AWE64 Value
sb CTL0044 #SB AWE64 Gold
sb CTL0045 #SB AWE64 Value
+sb YMH0021 #
sb ESS1868 #
diff --git a/sys/dev/isa/pnpdevs.h b/sys/dev/isa/pnpdevs.h
index 68a5edaf949..75bb1ffe38d 100644
--- a/sys/dev/isa/pnpdevs.h
+++ b/sys/dev/isa/pnpdevs.h
@@ -58,6 +58,7 @@ struct isapnp_knowndev isapnp_knowndevs[] = {
{ "CTL0042", "sb" },
{ "CTL0044", "sb" },
{ "CTL0045", "sb" },
+ { "YMH0021", "sb" },
{ "ESS1868", "sb" },
{ NULL, NULL, }
};
diff --git a/sys/dev/isa/pss.c b/sys/dev/isa/pss.c
index 636b208cc18..c2bf800b640 100644
--- a/sys/dev/isa/pss.c
+++ b/sys/dev/isa/pss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pss.c,v 1.12 1997/07/12 01:42:08 millert Exp $ */
-/* $NetBSD: pss.c,v 1.15 1996/05/12 23:53:23 mycroft Exp $ */
+/* $OpenBSD: pss.c,v 1.13 1998/04/26 21:02:55 provos Exp $ */
+/* $NetBSD: pss.c,v 1.38 1998/01/12 09:43:44 thorpej Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -62,6 +62,7 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
@@ -155,8 +156,7 @@ struct pcd_softc {
#endif
#ifdef AUDIO_DEBUG
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (pssdebug) Dprintf x
+#define DPRINTF(x) if (pssdebug) printf x
int pssdebug = 0;
#else
#define DPRINTF(x)
@@ -176,8 +176,6 @@ int pcdprobe __P((struct device *, void *, void *));
void pcdattach __P((struct device *, struct device *, void *));
#endif
-int spopen __P((dev_t, int));
-
int pssintr __P((void *));
#ifdef notyet
int mpuintr __P((void *));
@@ -186,12 +184,7 @@ 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 *));
@@ -232,41 +225,30 @@ void wss_dump_regs __P((struct ad1848_softc *));
*/
struct audio_hw_if pss_audio_if = {
- spopen,
+ ad1848_open,
ad1848_close,
NULL,
- ad1848_set_in_sr,
- ad1848_get_in_sr,
- ad1848_set_out_sr,
- ad1848_get_out_sr,
ad1848_query_encoding,
- ad1848_set_format,
- ad1848_get_encoding,
- ad1848_get_precision,
- ad1848_set_channels,
- ad1848_get_channels,
+ ad1848_set_params,
ad1848_round_blocksize,
- pss_set_out_port,
- pss_get_out_port,
- pss_set_in_port,
- pss_get_in_port,
ad1848_commit_settings,
- NULL,
- NULL,
+ ad1848_dma_init_output,
+ ad1848_dma_init_input,
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,
+ NULL,
pss_mixer_set_port,
pss_mixer_get_port,
pss_query_devinfo,
- 0, /* not full-duplex */
- 0
+ ad1848_malloc,
+ ad1848_free,
+ ad1848_round,
+ ad1848_mappage,
+ ad1848_get_props,
};
@@ -845,9 +827,11 @@ spprobe(parent, match, aux)
struct ad1848_softc *sc = match;
struct pss_softc *pc = (void *) parent;
struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
+ struct isa_attach_args *ia = aux;
u_char bits;
int i;
+ sc->sc_iot = ia->ia_iot;
sc->sc_iobase = cf->cf_iobase + WSS_CODEC;
/* Set WSS io address */
@@ -1043,7 +1027,6 @@ pssattach(parent, self, aux)
int iobase = ia->ia_iobase;
u_char vers;
struct ad1848_volume vol = {150, 150};
- int err;
sc->sc_iobase = iobase;
sc->sc_drq = ia->ia_drq;
@@ -1068,8 +1051,7 @@ pssattach(parent, self, aux)
(void)pss_set_treble(sc, AUDIO_MAX_GAIN/2);
(void)pss_set_bass(sc, AUDIO_MAX_GAIN/2);
- if ((err = audio_hardware_attach(&pss_audio_if, sc->ad1848_sc)) != 0)
- printf("pss: could not attach to audio pseudo-device driver (%d)\n", err);
+ audio_attach_mi(&pss_audio_if, 0, sc->ad1848_sc, &sc->ad1848_sc->sc_dev);
}
void
@@ -1092,10 +1074,7 @@ spattach(parent, self, aux)
sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
ad1848_intr, sc, sc->sc_dev.dv_xname);
- /* 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);
+ sc->sc_isa = parent->dv_parent;
ad1848_attach(sc);
@@ -1190,26 +1169,8 @@ pss_from_vol(cp, vol)
}
int
-spopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct ad1848_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= sp_cd.cd_ndevs)
- return ENODEV;
-
- sc = sp_cd.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 pss_softc *sc;
struct ad1848_volume *gp;
{
DPRINTF(("pss_set_master_gain: %d:%d\n", gp->left, gp->right));
@@ -1236,7 +1197,7 @@ pss_set_master_gain(sc, gp)
int
pss_set_master_mode(sc, mode)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
int mode;
{
short phillips_mode;
@@ -1266,7 +1227,7 @@ pss_set_master_mode(sc, mode)
int
pss_set_treble(sc, treb)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_int treb;
{
DPRINTF(("pss_set_treble: %d\n", treb));
@@ -1287,7 +1248,7 @@ pss_set_treble(sc, treb)
int
pss_set_bass(sc, bass)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_int bass;
{
DPRINTF(("pss_set_bass: %d\n", bass));
@@ -1308,7 +1269,7 @@ pss_set_bass(sc, bass)
int
pss_get_master_gain(sc, gp)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->master_volume;
@@ -1317,7 +1278,7 @@ pss_get_master_gain(sc, gp)
int
pss_get_master_mode(sc, mode)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_int *mode;
{
*mode = sc->master_mode;
@@ -1326,7 +1287,7 @@ pss_get_master_mode(sc, mode)
int
pss_get_treble(sc, tp)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_char *tp;
{
*tp = sc->monitor_treble;
@@ -1335,7 +1296,7 @@ pss_get_treble(sc, tp)
int
pss_get_bass(sc, bp)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_char *bp;
{
*bp = sc->monitor_bass;
@@ -1354,12 +1315,12 @@ int
pssintr(arg)
void *arg;
{
- register struct pss_softc *sc = arg;
+ struct pss_softc *sc = arg;
u_short sr;
sr = inw(sc->sc_iobase+PSS_STATUS);
- DPRINTF(("pssintr: sc=%x st=%x\n", sc, sr));
+ DPRINTF(("pssintr: sc=%p st=%x\n", sc, sr));
/* Acknowledge intr */
outw(sc->sc_iobase+PSS_IRQ_ACK, 0);
@@ -1378,7 +1339,7 @@ int
mpuintr(arg)
void *arg;
{
- register struct mpu_softc *sc = arg;
+ struct mpu_softc *sc = arg;
u_char sr;
sr = inb(sc->sc_iobase+MIDI_STATUS_REG);
@@ -1395,109 +1356,19 @@ pss_getdev(addr, retp)
void *addr;
struct audio_device *retp;
{
- DPRINTF(("pss_getdev: retp=0x%x\n", retp));
+ DPRINTF(("pss_getdev: retp=%p\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;
-
- 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;
- 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_softc *ac = addr;
+ struct pss_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -1606,8 +1477,8 @@ 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_softc *ac = addr;
+ struct pss_softc *sc = ac->parent;
struct ad1848_volume vol;
u_char eq;
int error = EINVAL;
@@ -1723,7 +1594,7 @@ pss_mixer_get_port(addr, cp)
int
pss_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
DPRINTF(("pss_query_devinfo: index=%d\n", dip->index));
@@ -1782,7 +1653,7 @@ pss_query_devinfo(addr, dip)
dip->mixer_class = PSS_OUTPUT_CLASS;
dip->prev = AUDIO_MIXER_LAST;
dip->next = PSS_OUTPUT_MODE;
- strcpy(dip->label.name, AudioNvolume);
+ strcpy(dip->label.name, AudioNmaster);
dip->un.v.num_channels = 2;
strcpy(dip->un.v.units.name, AudioNvolume);
break;
@@ -1809,28 +1680,28 @@ pss_query_devinfo(addr, dip)
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = PSS_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNspeaker);
+ strcpy(dip->label.name, AudioCoutputs);
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);
+ 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);
+ strcpy(dip->label.name, AudioCmonitor);
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);
+ strcpy(dip->label.name, AudioCrecord);
break;
case PSS_MIC_IN_MUTE:
diff --git a/sys/dev/isa/sb.c b/sys/dev/isa/sb.c
index 5bcc4010db0..06274862b28 100644
--- a/sys/dev/isa/sb.c
+++ b/sys/dev/isa/sb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sb.c,v 1.13 1997/08/07 05:27:32 deraadt Exp $ */
-/* $NetBSD: sb.c,v 1.36 1996/05/12 23:53:33 mycroft Exp $ */
+/* $OpenBSD: sb.c,v 1.14 1998/04/26 21:02:56 provos Exp $ */
+/* $NetBSD: sb.c,v 1.57 1998/01/12 09:43:46 thorpej Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -45,11 +45,11 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
#include <dev/audio_if.h>
-#include <dev/mulaw.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -58,14 +58,6 @@
#include <dev/isa/sbvar.h>
#include <dev/isa/sbdspvar.h>
-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;
-};
-
struct cfdriver sb_cd = {
NULL, "sb", DV_DULL
};
@@ -76,7 +68,6 @@ struct audio_device sb_device = {
"sb"
};
-int sbopen __P((dev_t, int));
int sb_getdev __P((void *, struct audio_device *));
/*
@@ -84,41 +75,30 @@ int sb_getdev __P((void *, struct audio_device *));
*/
struct audio_hw_if sb_hw_if = {
- sbopen,
+ sbdsp_open,
sbdsp_close,
- NULL,
- sbdsp_set_in_sr,
- sbdsp_get_in_sr,
- sbdsp_set_out_sr,
- sbdsp_get_out_sr,
+ 0,
sbdsp_query_encoding,
- sbdsp_set_format,
- sbdsp_get_encoding,
- sbdsp_get_precision,
- sbdsp_set_channels,
- sbdsp_get_channels,
+ sbdsp_set_params,
sbdsp_round_blocksize,
- sbdsp_set_out_port,
- sbdsp_get_out_port,
- sbdsp_set_in_port,
- sbdsp_get_in_port,
- sbdsp_commit_settings,
- mulaw_expand,
- mulaw_compress,
+ 0,
+ sbdsp_dma_init_output,
+ sbdsp_dma_init_input,
sbdsp_dma_output,
sbdsp_dma_input,
sbdsp_haltdma,
sbdsp_haltdma,
- sbdsp_contdma,
- sbdsp_contdma,
sbdsp_speaker_ctl,
sb_getdev,
- sbdsp_setfd,
+ 0,
sbdsp_mixer_set_port,
sbdsp_mixer_get_port,
sbdsp_mixer_query_devinfo,
- 0, /* not full-duplex */
- 0
+ sb_malloc,
+ sb_free,
+ sb_round,
+ sb_mappage,
+ sbdsp_get_props,
};
/*
@@ -157,7 +137,15 @@ sbmatch(sc)
return 0;
}
}
-
+
+ if (0 <= sc->sc_drq16 && sc->sc_drq16 <= 3)
+ /*
+ * XXX Some ViBRA16 cards seem to have two 8 bit DMA
+ * channels. I've no clue how to use them, so ignore
+ * one of them for now. -- augustss@netbsd.org
+ */
+ sc->sc_drq16 = -1;
+
if (ISSB16CLASS(sc)) {
if (sc->sc_drq16 == -1)
sc->sc_drq16 = sc->sc_drq8;
@@ -207,14 +195,21 @@ sbmatch(sc)
}
if (ISSB16CLASS(sc)) {
+ int w, r;
#if 0
printf("%s: old drq conf %02x\n", sc->sc_dev.dv_xname,
sbdsp_mix_read(sc, SBP_SET_DRQ));
printf("%s: try drq conf %02x\n", sc->sc_dev.dv_xname,
drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8]);
#endif
- sbdsp_mix_write(sc, SBP_SET_DRQ,
- drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8]);
+ w = drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8];
+ sbdsp_mix_write(sc, SBP_SET_DRQ, w);
+ r = sbdsp_mix_read(sc, SBP_SET_DRQ) & 0xeb;
+ if (r != w) {
+ printf("%s: setting drq mask %02x failed, got %02x\n",
+ sc->sc_dev.dv_xname, w, r);
+ return 0;
+ }
#if 0
printf("%s: new drq conf %02x\n", sc->sc_dev.dv_xname,
sbdsp_mix_read(sc, SBP_SET_DRQ));
@@ -226,8 +221,14 @@ sbmatch(sc)
printf("%s: try irq conf %02x\n", sc->sc_dev.dv_xname,
irq_conf[sc->sc_irq]);
#endif
- sbdsp_mix_write(sc, SBP_SET_IRQ,
- irq_conf[sc->sc_irq]);
+ w = irq_conf[sc->sc_irq];
+ sbdsp_mix_write(sc, SBP_SET_IRQ, w);
+ r = sbdsp_mix_read(sc, SBP_SET_IRQ) & 0x0f;
+ if (r != w) {
+ printf("%s: setting irq mask %02x failed, got %02x\n",
+ sc->sc_dev.dv_xname, w, r);
+ return 0;
+ }
#if 0
printf("%s: new irq conf %02x\n", sc->sc_dev.dv_xname,
sbdsp_mix_read(sc, SBP_SET_IRQ));
@@ -242,16 +243,12 @@ void
sbattach(sc)
struct sbdsp_softc *sc;
{
- int error;
-
sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->sc_irq, IST_EDGE,
IPL_AUDIO, sbdsp_intr, sc, sc->sc_dev.dv_xname);
sbdsp_attach(sc);
- if ((error = audio_hardware_attach(&sb_hw_if, sc)) != 0)
- printf("%s: could not attach to audio device driver (%d)\n",
- sc->sc_dev.dv_xname, error);
+ audio_attach_mi(&sb_hw_if, 0, sc, &sc->sc_dev);
}
#ifdef NEWCONFIG
@@ -287,38 +284,26 @@ sbforceintr(aux)
*/
int
-sbopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct sbdsp_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= sb_cd.cd_ndevs)
- return ENODEV;
-
- sc = sb_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
- return sbdsp_open(sc, dev, flags);
-}
-
-int
sb_getdev(addr, retp)
void *addr;
struct audio_device *retp;
{
struct sbdsp_softc *sc = addr;
+ static char *names[] = SB_NAMES;
+ char *config;
- if (sc->sc_model & MODEL_JAZZ16)
+ if (sc->sc_model == SB_JAZZ)
strncpy(retp->name, "MV Jazz16", sizeof(retp->name));
else
strncpy(retp->name, "SoundBlaster", sizeof(retp->name));
sprintf(retp->version, "%d.%02d",
- SBVER_MAJOR(sc->sc_model),
- SBVER_MINOR(sc->sc_model));
- strncpy(retp->config, "sb", sizeof(retp->config));
+ SBVER_MAJOR(sc->sc_version),
+ SBVER_MINOR(sc->sc_version));
+ if (0 <= sc->sc_model && sc->sc_model < sizeof names / sizeof names[0])
+ config = names[sc->sc_model];
+ else
+ config = "??";
+ strncpy(retp->config, config, sizeof(retp->config));
return 0;
}
diff --git a/sys/dev/isa/sb_isa.c b/sys/dev/isa/sb_isa.c
index da747efd05f..9cba8d91df8 100644
--- a/sys/dev/isa/sb_isa.c
+++ b/sys/dev/isa/sb_isa.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sb_isa.c,v 1.1 1997/07/10 23:06:37 provos Exp $ */
-/* $NetBSD: sb_isa.c,v 1.3 1997/03/20 11:03:11 mycroft Exp $ */
+/* $OpenBSD: sb_isa.c,v 1.2 1998/04/26 21:02:57 provos Exp $ */
+/* $NetBSD: sb_isa.c,v 1.15 1997/11/30 15:32:25 drochner Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -43,6 +43,8 @@
#include <sys/device.h>
#include <sys/proc.h>
+#include <machine/bus.h>
+
#include <sys/audioio.h>
#include <dev/audio_if.h>
#include <dev/mulaw.h>
@@ -55,7 +57,14 @@
#include <dev/isa/sbdspvar.h>
+static int sbfind __P((struct device *, struct sbdsp_softc *, struct isa_attach_args *));
+
+#define __BROKEN_INDIRECT_CONFIG /* XXX */
+#ifdef __BROKEN_INDIRECT_CONFIG
int sb_isa_match __P((struct device *, void *, void *));
+#else
+int sb_isa_match __P((struct device *, struct cfdata *, void *));
+#endif
void sb_isa_attach __P((struct device *, struct device *, void *));
struct cfattach sb_isa_ca = {
@@ -72,13 +81,32 @@ struct cfattach sb_isa_ca = {
int
sb_isa_match(parent, match, aux)
struct device *parent;
- void *match, *aux;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ struct sbdsp_softc probesc, *sc = &probesc;
+
+ bzero(sc, sizeof *sc);
+#ifdef __BROKEN_INDIRECT_CONFIG
+ sc->sc_dev.dv_cfdata = ((struct device *)match)->dv_cfdata;
+#else
+ sc->sc_dev.dv_cfdata = match;
+#endif
+ strcpy(sc->sc_dev.dv_xname, "sb");
+ return sbfind(parent, sc, aux);
+}
+
+static int
+sbfind(parent, sc, ia)
+ struct device *parent;
+ struct sbdsp_softc *sc;
+ struct isa_attach_args *ia;
{
- /*
- * Indirect brokedness!
- */
- register struct sbdsp_softc *sc = match;
- register struct isa_attach_args *ia = aux;
+ int rc = 0;
if (!SB_BASE_VALID(ia->ia_iobase)) {
printf("sb: configured iobase 0x%x invalid\n", ia->ia_iobase);
@@ -87,7 +115,7 @@ sb_isa_match(parent, match, aux)
sc->sc_iot = ia->ia_iot;
- /* Map i/o space [we map 24 ports which is the max of the sb and pro */
+ /* Map i/o space [we map 24 ports which is the max of the sb and pro */
if (bus_space_map(sc->sc_iot, ia->ia_iobase, SBP_NPORT, 0,
&sc->sc_ioh)) {
printf("sb: can't map i/o space 0x%x/%d in probe\n",
@@ -95,28 +123,34 @@ sb_isa_match(parent, match, aux)
return 0;
}
- /*
- * Indirect brokedness!
- */
sc->sc_iobase = ia->ia_iobase;
sc->sc_irq = ia->ia_irq;
sc->sc_drq8 = ia->ia_drq;
- sc->sc_drq16 = -1; /* XXX */
+ sc->sc_drq16 = ia->ia_drq2;
sc->sc_ic = ia->ia_ic;
- if (!sbmatch(sc)) {
- bus_space_unmap(sc->sc_iot, sc->sc_ioh, SBP_NPORT);
- return 0;
- }
+ if (!sbmatch(sc))
+ goto bad;
+
+ if ((sc->sc_drq8 != -1 && !isa_drq_isfree(parent, sc->sc_drq8)) ||
+ (sc->sc_drq16 != -1 && !isa_drq_isfree(parent, sc->sc_drq16)))
+ goto bad;
if (ISSBPROCLASS(sc))
ia->ia_iosize = SBP_NPORT;
else
ia->ia_iosize = SB_NPORT;
+ if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
+ ia->ia_drq2 = -1;
+
ia->ia_irq = sc->sc_irq;
- return 1;
+ rc = 1;
+
+bad:
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, SBP_NPORT);
+ return rc;
}
@@ -129,5 +163,15 @@ sb_isa_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- sbattach((struct sbdsp_softc *) self);
+ struct sbdsp_softc *sc = (struct sbdsp_softc *)self;
+ struct isa_attach_args *ia = aux;
+
+ if (!sbfind(parent, sc, ia) ||
+ bus_space_map(sc->sc_iot, ia->ia_iobase, ia->ia_iosize,
+ 0, &sc->sc_ioh)) {
+ printf("%s: sbfind failed\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ sc->sc_isa = parent;
+ sbattach(sc);
}
diff --git a/sys/dev/isa/sb_isapnp.c b/sys/dev/isa/sb_isapnp.c
index 13f3038c9af..47115e98e3d 100644
--- a/sys/dev/isa/sb_isapnp.c
+++ b/sys/dev/isa/sb_isapnp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sb_isapnp.c,v 1.2 1997/12/26 09:35:38 deraadt Exp $ */
+/* $OpenBSD: sb_isapnp.c,v 1.3 1998/04/26 21:02:58 provos Exp $ */
/* $NetBSD: sb_isa.c,v 1.3 1997/03/20 11:03:11 mycroft Exp $ */
/*
@@ -93,9 +93,24 @@ sb_isapnp_attach(parent, self, aux)
sc->sc_ioh = ia->ipa_io[0].h;
sc->sc_iobase = ia->ipa_io[0].base;
sc->sc_irq = ia->ipa_irq[0].num;
- sc->sc_drq8 = ia->ipa_drq[0].num;
- sc->sc_drq16 = ia->ipa_drq[1].num;
sc->sc_ic = ia->ia_ic;
+ sc->sc_drq8 = ia->ipa_drq[0].num;
+
+ if (ia->ipa_ndrq > 1 && ia->ipa_drq[0].num != ia->ipa_drq[1].num) {
+ /* Some cards have the 16 bit drq first */
+ if (sc->sc_drq8 >= 4) {
+ sc->sc_drq16 = sc->sc_drq8;
+ sc->sc_drq8 = ia->ipa_drq[1].num;
+ } else
+ sc->sc_drq16 = ia->ipa_drq[1].num;
+ } else
+ sc->sc_drq16 = DRQUNK;
+
+ /*
+ * isapnp is a child if isa, and we needs isa for the dma
+ * routines
+ */
+ sc->sc_isa = parent->dv_parent;
if (!sbmatch(sc)) {
printf("%s: sbmatch failed\n", sc->sc_dev.dv_xname);
diff --git a/sys/dev/isa/sbdsp.c b/sys/dev/isa/sbdsp.c
index ca7ebb359d2..89cda5647d9 100644
--- a/sys/dev/isa/sbdsp.c
+++ b/sys/dev/isa/sbdsp.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sbdsp.c,v 1.11 1998/01/18 18:58:39 niklas Exp $ */
-/* $NetBSD: sbdsp.c,v 1.30 1996/10/25 07:25:48 fvdl Exp $ */
+/* $OpenBSD: sbdsp.c,v 1.12 1998/04/26 21:02:59 provos Exp $ */
+/* $NetBSD: sbdsp.c,v 1.78 1998/01/30 11:55:36 bouyer Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -40,6 +40,9 @@
* information he gleaned from Steve Haehnichen <steve@vigra.com>'s
* SBlast driver for 386BSD and DOS driver code from Daniel Sachs
* <sachs@meibm15.cen.uiuc.edu>.
+ * Lots of rewrites by Lennart Augustsson <augustss@cs.chalmers.se>
+ * with information from SB "Hardware Programming Guide" and the
+ * Linux drivers.
*/
#include <sys/param.h>
@@ -54,21 +57,21 @@
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <machine/pio.h>
+#include <machine/bus.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> /* XXX BROKEN; WHY? */
#include <dev/isa/sbreg.h>
#include <dev/isa/sbdspvar.h>
#ifdef AUDIO_DEBUG
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (sbdspdebug) Dprintf x
+#define DPRINTF(x) if (sbdspdebug) printf x
int sbdspdebug = 0;
#else
#define DPRINTF(x)
@@ -84,10 +87,6 @@ struct {
int wmidi;
} sberr;
-int sbdsp_srtotc __P((struct sbdsp_softc *sc, int sr, int isdac,
- int *tcp, int *modep));
-u_int sbdsp_jazz16_probe __P((struct sbdsp_softc *));
-
/*
* Time constant routines follow. See SBK, section 12.
* Although they don't come out and say it (in the docs),
@@ -113,48 +112,106 @@ u_int sbdsp_jazz16_probe __P((struct sbdsp_softc *));
* output ls max 23 KHz 23 KHz
* output hs max 44.1 KHz 44.1 KHz
*/
-#define SB_LS_MIN 0x06 /* 4000 Hz */
-#define SB_8K 0x83 /* 8000 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 */
-
-int sbdsp16_wait __P((struct sbdsp_softc *));
+/* XXX Should we round the tc?
+#define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
+*/
+#define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
+#define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
+
+struct sbmode {
+ short model;
+ u_char channels;
+ u_char precision;
+ u_short lowrate, highrate;
+ u_char cmd;
+ u_char cmdchan;
+};
+static struct sbmode sbpmodes[] = {
+ { SB_1, 1, 8, 4000, 22727, SB_DSP_WDMA },
+ { SB_20, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
+ { SB_2x, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
+ { SB_2x, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT },
+ { SB_PRO, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
+ { SB_PRO, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT },
+ { SB_PRO, 2, 8, 11025, 22727, SB_DSP_HS_OUTPUT },
+ /* Yes, we write the record mode to set 16-bit playback mode. weird, huh? */
+ { SB_JAZZ, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 2, 8, 11025, 22727, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_STEREO },
+ { SB_JAZZ, 1, 16, 4000, 22727, SB_DSP_WDMA_LOOP, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_STEREO },
+ { SB_16, 1, 8, 5000, 45000, SB_DSP16_WDMA_8 },
+ { SB_16, 2, 8, 5000, 45000, SB_DSP16_WDMA_8 },
+#define PLAY16 15 /* must be the index of the next entry in the table */
+ { SB_16, 1, 16, 5000, 45000, SB_DSP16_WDMA_16 },
+ { SB_16, 2, 16, 5000, 45000, SB_DSP16_WDMA_16 },
+ { -1 }
+};
+static struct sbmode sbrmodes[] = {
+ { SB_1, 1, 8, 4000, 12987, SB_DSP_RDMA },
+ { SB_20, 1, 8, 4000, 12987, SB_DSP_RDMA_LOOP },
+ { SB_2x, 1, 8, 4000, 12987, SB_DSP_RDMA_LOOP },
+ { SB_2x, 1, 8, 12987, 14925, SB_DSP_HS_INPUT },
+ { SB_PRO, 1, 8, 4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
+ { SB_PRO, 1, 8, 22727, 45454, SB_DSP_HS_INPUT, SB_DSP_RECORD_MONO },
+ { SB_PRO, 2, 8, 11025, 22727, SB_DSP_HS_INPUT, SB_DSP_RECORD_STEREO },
+ { SB_JAZZ, 1, 8, 4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 1, 8, 22727, 45454, SB_DSP_HS_INPUT, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 2, 8, 11025, 22727, SB_DSP_HS_INPUT, SB_DSP_RECORD_STEREO },
+ { SB_JAZZ, 1, 16, 4000, 22727, SB_DSP_RDMA_LOOP, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_INPUT, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_INPUT, JAZZ16_RECORD_STEREO },
+ { SB_16, 1, 8, 5000, 45000, SB_DSP16_RDMA_8 },
+ { SB_16, 2, 8, 5000, 45000, SB_DSP16_RDMA_8 },
+ { SB_16, 1, 16, 5000, 45000, SB_DSP16_RDMA_16 },
+ { SB_16, 2, 16, 5000, 45000, SB_DSP16_RDMA_16 },
+ { -1 }
+};
+
+void sbversion __P((struct sbdsp_softc *));
+void sbdsp_jazz16_probe __P((struct sbdsp_softc *));
+void sbdsp_set_mixer_gain __P((struct sbdsp_softc *sc, int port));
void sbdsp_to __P((void *));
void sbdsp_pause __P((struct sbdsp_softc *));
-int sbdsp16_setrate __P((struct sbdsp_softc *, int, int, int *));
-int sbdsp_tctosr __P((struct sbdsp_softc *, int));
int sbdsp_set_timeconst __P((struct sbdsp_softc *, int));
+int sbdsp16_set_rate __P((struct sbdsp_softc *, int, int));
+int sbdsp_set_in_ports __P((struct sbdsp_softc *, int));
+void sbdsp_set_ifilter __P((void *, int));
+int sbdsp_get_ifilter __P((void *));
+
+static int sbdsp_dma_setup_input __P((struct sbdsp_softc *sc));
+static int sbdsp_dma_setup_output __P((struct sbdsp_softc *sc));
+static int sbdsp_adjust __P((int, int));
#ifdef AUDIO_DEBUG
void sb_printsc __P((struct sbdsp_softc *));
-#endif
-#ifdef AUDIO_DEBUG
void
sb_printsc(sc)
struct sbdsp_softc *sc;
{
int i;
- printf("open %d dmachan %d/%d/%d iobase %x\n",
- sc->sc_open, sc->dmachan, sc->sc_drq8, sc->sc_drq16, sc->sc_iobase);
- printf("irate %d itc %d imode %d orate %d otc %d omode %d encoding %x\n",
- sc->sc_irate, sc->sc_itc, sc->sc_imode,
- sc->sc_orate, sc->sc_otc, sc->sc_omode, sc->sc_encoding);
- printf("outport %d inport %d spkron %d nintr %lu\n",
- sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
- printf("precision %d channels %d intr %p arg %p\n",
- sc->sc_precision, sc->sc_channels, sc->sc_intr, sc->sc_arg);
- printf("gain: ");
+ printf("open %d dmachan %d/%d %d/%d iobase 0x%x irq %d\n",
+ (int)sc->sc_open, sc->sc_i.run, sc->sc_o.run,
+ sc->sc_drq8, sc->sc_drq16,
+ sc->sc_iobase, sc->sc_irq);
+ printf("irate %d itc %x orate %d otc %x\n",
+ sc->sc_i.rate, sc->sc_i.tc,
+ sc->sc_o.rate, sc->sc_o.tc);
+ printf("spkron %u nintr %lu\n",
+ sc->spkr_state, sc->sc_interrupts);
+ printf("intr8 %p arg8 %p\n",
+ sc->sc_intr8, sc->sc_arg16);
+ printf("intr16 %p arg16 %p\n",
+ sc->sc_intr8, sc->sc_arg16);
+ printf("gain:");
for (i = 0; i < SB_NDEVS; i++)
- printf("%d ", sc->gain[i]);
+ printf(" %u,%u", sc->gain[i][SB_LEFT], sc->gain[i][SB_RIGHT]);
printf("\n");
}
-#endif
+#endif /* AUDIO_DEBUG */
/*
* Probe / attach routines.
@@ -173,19 +230,22 @@ sbdsp_probe(sc)
return 0;
}
/* if flags set, go and probe the jazz16 stuff */
- if (sc->sc_dev.dv_cfdata->cf_flags != 0) {
- sc->sc_model = sbdsp_jazz16_probe(sc);
- } else {
- sc->sc_model = sbversion(sc);
+ if (sc->sc_dev.dv_cfdata->cf_flags & 1)
+ sbdsp_jazz16_probe(sc);
+ else
+ sbversion(sc);
+ if (sc->sc_model == SB_UNK) {
+ /* Unknown SB model found. */
+ DPRINTF(("sbdsp: unknown SB model found\n"));
+ return 0;
}
-
return 1;
}
/*
* Try add-on stuff for Jazz16.
*/
-u_int
+void
sbdsp_jazz16_probe(sc)
struct sbdsp_softc *sc;
{
@@ -198,15 +258,16 @@ sbdsp_jazz16_probe(sc)
-1, 0x01, -1, 0x02,
-1, 0x03, -1, 0x04};
- u_int rval = sbversion(sc);
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh;
+ sbversion(sc);
+
DPRINTF(("jazz16 probe\n"));
if (bus_space_map(iot, JAZZ16_CONFIG_PORT, 1, 0, &ioh)) {
DPRINTF(("bus map failed\n"));
- return rval;
+ return;
}
if (jazz16_drq_conf[sc->sc_drq8] == (u_char)-1 ||
@@ -244,12 +305,12 @@ sbdsp_jazz16_probe(sc)
DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
} else {
DPRINTF(("jazz16 detected!\n"));
- rval |= MODEL_JAZZ16;
+ sc->sc_model = SB_JAZZ;
+ sc->sc_mixer_model = SBM_CT1345; /* XXX really? */
}
done:
bus_space_unmap(iot, ioh, 1);
- return rval;
}
/*
@@ -260,49 +321,81 @@ void
sbdsp_attach(sc)
struct sbdsp_softc *sc;
{
+ struct audio_params pparams, rparams;
+ int i;
+ u_int v;
- /* Set defaults */
- if (ISSB16CLASS(sc))
- sc->sc_irate = sc->sc_orate = 8000;
- else if (ISSBPROCLASS(sc))
- sc->sc_itc = sc->sc_otc = SB_8K;
- else
- sc->sc_itc = sc->sc_otc = SB_8K;
- sc->sc_encoding = AUDIO_ENCODING_ULAW;
- sc->sc_precision = 8;
- sc->sc_channels = 1;
-
- (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. */
+ /*
+ * Create our DMA maps.
+ */
+ if (sc->sc_drq8 != -1) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq8,
+ 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_drq8);
+ return;
+ }
+ }
+ if (sc->sc_drq16 != -1 && sc->sc_drq16 != sc->sc_drq8) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq16,
+ 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_drq16);
+ return;
+ }
+ }
+
+ pparams = audio_default;
+ rparams = audio_default;
+ sbdsp_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
+
+ sbdsp_set_in_ports(sc, 1 << SB_MIC_VOL);
+
+ if (sc->sc_mixer_model != SBM_NONE) {
+ /* Reset the mixer.*/
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/2, SBP_MAXVOL/2));
- 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);
+ /* And set our own default values */
+ for (i = 0; i < SB_NDEVS; i++) {
+ switch(i) {
+ case SB_MIC_VOL:
+ case SB_LINE_IN_VOL:
+ v = 0;
+ break;
+ case SB_BASS:
+ case SB_TREBLE:
+ v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN/2);
+ break;
+ case SB_CD_IN_MUTE:
+ case SB_MIC_IN_MUTE:
+ case SB_LINE_IN_MUTE:
+ case SB_MIDI_IN_MUTE:
+ case SB_CD_SWAP:
+ case SB_MIC_SWAP:
+ case SB_LINE_SWAP:
+ case SB_MIDI_SWAP:
+ case SB_CD_OUT_MUTE:
+ case SB_MIC_OUT_MUTE:
+ case SB_LINE_OUT_MUTE:
+ v = 0;
+ break;
+ default:
+ v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
+ break;
+ }
+ sc->gain[i][SB_LEFT] = sc->gain[i][SB_RIGHT] = v;
+ sbdsp_set_mixer_gain(sc, i);
+ }
sc->in_filter = 0; /* no filters turned on, please */
}
printf(": dsp v%d.%02d%s\n",
- SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model),
- ISJAZZ16(sc) ? ": <Jazz16>" : "");
-}
+ SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
+ sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
-/*
- * Various routines to interface to higher level audio driver
- */
+ sc->sc_fullduplex = ISSB16CLASS(sc) &&
+ sc->sc_drq8 != -1 && sc->sc_drq16 != -1 &&
+ sc->sc_drq8 != sc->sc_drq16;
+}
void
sbdsp_mix_write(sc, mixerport, val)
@@ -312,11 +405,14 @@ sbdsp_mix_write(sc, mixerport, val)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
+ int s;
+ s = splaudio();
bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
- delay(10);
+ delay(20);
bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
delay(30);
+ splx(s);
}
int
@@ -326,305 +422,382 @@ sbdsp_mix_read(sc, mixerport)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
+ int val;
+ int s;
+ s = splaudio();
bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
- delay(10);
- return bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
-}
-
-int
-sbdsp_set_in_sr(addr, sr)
- void *addr;
- u_long sr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sbdsp16_setrate(sc, sr, SB_INPUT_RATE, &sc->sc_irate));
- else
- return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
-}
-
-u_long
-sbdsp_get_in_sr(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sc->sc_irate);
- else
- return (sbdsp_tctosr(sc, sc->sc_itc));
-}
-
-int
-sbdsp_set_out_sr(addr, sr)
- void *addr;
- u_long sr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sbdsp16_setrate(sc, sr, SB_OUTPUT_RATE, &sc->sc_orate));
- else
- return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
+ delay(20);
+ val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
+ delay(30);
+ splx(s);
+ return val;
}
-u_long
-sbdsp_get_out_sr(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sc->sc_orate);
- else
- return (sbdsp_tctosr(sc, sc->sc_otc));
-}
+/*
+ * Various routines to interface to higher level audio driver
+ */
int
sbdsp_query_encoding(addr, fp)
void *addr;
struct audio_encoding *fp;
{
+ struct sbdsp_softc *sc = addr;
+ int emul;
+
+ emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
+
switch (fp->index) {
case 0:
- strcpy(fp->name, AudioEmulaw);
- fp->format_id = AUDIO_ENCODING_ULAW;
- break;
+ strcpy(fp->name, AudioEulinear);
+ fp->encoding = AUDIO_ENCODING_ULINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
+ return 0;
case 1:
- strcpy(fp->name, AudioEpcm16);
- fp->format_id = AUDIO_ENCODING_PCM16;
- break;
- default:
- return (EINVAL);
- }
- return (0);
-}
+ strcpy(fp->name, AudioEmulaw);
+ fp->encoding = AUDIO_ENCODING_ULAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
+ case 2:
+ strcpy(fp->name, AudioEalaw);
+ fp->encoding = AUDIO_ENCODING_ALAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
+ case 3:
+ strcpy(fp->name, AudioEslinear);
+ fp->encoding = AUDIO_ENCODING_SLINEAR;
+ fp->precision = 8;
+ fp->flags = emul;
+ return 0;
+ }
+ if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
+ return EINVAL;
-int
-sbdsp_set_format(addr, encoding, precision)
- void *addr;
- u_int encoding, precision;
-{
- register struct sbdsp_softc *sc = addr;
-
- switch (encoding) {
- case AUDIO_ENCODING_ULAW:
- case AUDIO_ENCODING_PCM16:
- case AUDIO_ENCODING_PCM8:
- break;
+ switch(fp->index) {
+ case 4:
+ strcpy(fp->name, AudioEslinear_le);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
+ return 0;
+ case 5:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ fp->precision = 16;
+ fp->flags = emul;
+ return 0;
+ case 6:
+ strcpy(fp->name, AudioEslinear_be);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
+ case 7:
+ strcpy(fp->name, AudioEulinear_be);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
default:
- return (EINVAL);
+ return EINVAL;
}
-
- if (precision == 16)
- if (!ISSB16CLASS(sc) && !ISJAZZ16(sc))
- return (EINVAL);
-
- sc->sc_encoding = encoding;
- sc->sc_precision = precision;
-
- return (0);
+ return 0;
}
int
-sbdsp_get_encoding(addr)
+sbdsp_set_params(addr, setmode, usemode, play, rec)
void *addr;
+ int setmode, usemode;
+ struct audio_params *play, *rec;
{
- register struct sbdsp_softc *sc = addr;
-
- return (sc->sc_encoding);
-}
+ struct sbdsp_softc *sc = addr;
+ struct sbmode *m;
+ u_int rate, tc, bmode;
+ void (*swcode) __P((void *, u_char *buf, int cnt));
+ int factor;
+ int model;
+ int chan;
+ struct audio_params *p;
+ int mode;
+
+ model = sc->sc_model;
+ if (model > SB_16)
+ model = SB_16; /* later models work like SB16 */
+
+ /* Set first record info, then play info */
+ for(mode = AUMODE_RECORD; mode != -1;
+ mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
+ if ((setmode & mode) == 0)
+ continue;
-int
-sbdsp_get_precision(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
+ p = mode == AUMODE_PLAY ? play : rec;
+ /* Locate proper commands */
+ for(m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
+ m->model != -1; m++) {
+ if (model == m->model &&
+ p->channels == m->channels &&
+ p->precision == m->precision &&
+ p->sample_rate >= m->lowrate &&
+ p->sample_rate < m->highrate)
+ break;
+ }
+ if (m->model == -1)
+ return EINVAL;
+ rate = p->sample_rate;
+ swcode = 0;
+ factor = 1;
+ tc = 1;
+ bmode = -1;
+ if (model == SB_16) {
+ switch (p->encoding) {
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (p->precision == 16)
+ swcode = swap_bytes;
+ /* fall into */
+ case AUDIO_ENCODING_SLINEAR_LE:
+ bmode = SB_BMODE_SIGNED;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ if (p->precision == 16)
+ swcode = swap_bytes;
+ /* fall into */
+ case AUDIO_ENCODING_ULINEAR_LE:
+ bmode = SB_BMODE_UNSIGNED;
+ break;
+ case AUDIO_ENCODING_ULAW:
+ if (mode == AUMODE_PLAY) {
+ swcode = mulaw_to_ulinear16;
+ factor = 2;
+ m = &sbpmodes[PLAY16];
+ } else
+ swcode = ulinear8_to_mulaw;
+ bmode = SB_BMODE_UNSIGNED;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ if (mode == AUMODE_PLAY) {
+ swcode = alaw_to_ulinear16;
+ factor = 2;
+ m = &sbpmodes[PLAY16];
+ } else
+ swcode = ulinear8_to_alaw;
+ bmode = SB_BMODE_UNSIGNED;
+ break;
+ default:
+ return EINVAL;
+ }
+ if (p->channels == 2)
+ bmode |= SB_BMODE_STEREO;
+ } else if (m->model == SB_JAZZ && m->precision == 16) {
+ switch (p->encoding) {
+ case AUDIO_ENCODING_SLINEAR_LE:
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ swcode = change_sign16;
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ swcode = swap_bytes;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ swcode = mode == AUMODE_PLAY ?
+ swap_bytes_change_sign16 : change_sign16_swap_bytes;
+ break;
+ case AUDIO_ENCODING_ULAW:
+ swcode = mode == AUMODE_PLAY ?
+ mulaw_to_ulinear8 : ulinear8_to_mulaw;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ swcode = mode == AUMODE_PLAY ?
+ alaw_to_ulinear8 : ulinear8_to_alaw;
+ break;
+ default:
+ return EINVAL;
+ }
+ tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
+ p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
+ } else {
+ switch (p->encoding) {
+ case AUDIO_ENCODING_SLINEAR_BE:
+ case AUDIO_ENCODING_SLINEAR_LE:
+ swcode = change_sign8;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ case AUDIO_ENCODING_ULINEAR_LE:
+ break;
+ case AUDIO_ENCODING_ULAW:
+ swcode = mode == AUMODE_PLAY ?
+ mulaw_to_ulinear8 : ulinear8_to_mulaw;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ swcode = mode == AUMODE_PLAY ?
+ alaw_to_ulinear8 : ulinear8_to_alaw;
+ break;
+ default:
+ return EINVAL;
+ }
+ tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
+ p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
+ }
- return (sc->sc_precision);
-}
+ chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
+ if (mode == AUMODE_PLAY) {
+ sc->sc_o.rate = rate;
+ sc->sc_o.tc = tc;
+ sc->sc_o.modep = m;
+ sc->sc_o.bmode = bmode;
+ sc->sc_o.dmachan = chan;
+ } else {
+ sc->sc_i.rate = rate;
+ sc->sc_i.tc = tc;
+ sc->sc_i.modep = m;
+ sc->sc_i.bmode = bmode;
+ sc->sc_i.dmachan = chan;
+ }
-int
-sbdsp_set_channels(addr, channels)
- void *addr;
- int channels;
-{
- register struct sbdsp_softc *sc = addr;
+ p->sw_code = swcode;
+ p->factor = factor;
+ DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%ld, prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, bmode=%02x, cmdchan=%02x, swcode=%p, factor=%d\n",
+ sc->sc_model, mode, p->sample_rate, p->precision, p->channels,
+ p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode, factor));
- if (ISSBPROCLASS(sc)) {
- if (channels != 1 && channels != 2)
- return (EINVAL);
- sc->sc_channels = channels;
- sc->sc_dmadir = SB_DMA_NONE;
- /*
- * XXXX
- * With 2 channels, SBPro can't do more than 22kHz.
- * No framework to check this.
- */
- } else {
- if (channels != 1)
- return (EINVAL);
- sc->sc_channels = channels;
}
-
- return (0);
-}
+ /*
+ * XXX
+ * Should wait for chip to be idle.
+ */
+ sc->sc_i.run = SB_NOTRUNNING;
+ sc->sc_o.run = SB_NOTRUNNING;
+
+ if (sc->sc_fullduplex &&
+ (usemode & (AUMODE_PLAY | AUMODE_RECORD)) == (AUMODE_PLAY | AUMODE_RECORD) &&
+ sc->sc_i.dmachan == sc->sc_o.dmachan) {
+ DPRINTF(("sbdsp_commit: fd=%d, usemode=%d, idma=%d, odma=%d\n", sc->sc_fullduplex, usemode, sc->sc_i.dmachan, sc->sc_o.dmachan));
+ if (sc->sc_o.dmachan == sc->sc_drq8) {
+ /* Use 16 bit DMA for playing by expanding the samples. */
+ play->sw_code = linear8_to_linear16;
+ play->factor = 2;
+ sc->sc_o.modep = &sbpmodes[PLAY16];
+ sc->sc_o.dmachan = sc->sc_drq16;
+ } else {
+ return EINVAL;
+ }
+ }
+ DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n", sc->sc_i.dmachan, sc->sc_o.dmachan));
-int
-sbdsp_get_channels(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
-
- return (sc->sc_channels);
+ return 0;
}
-int
+void
sbdsp_set_ifilter(addr, which)
void *addr;
int which;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
int mixval;
- /* XXXX SB16 */
- if (ISSBPROCLASS(sc)) {
- mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
- switch (which) {
- case 0:
- mixval |= SBP_FILTER_OFF;
- break;
- case SBP_TREBLE_EQ:
- mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
- break;
- case SBP_BASS_EQ:
- mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
- break;
- default:
- return (EINVAL);
- }
- sc->in_filter = mixval & SBP_IFILTER_MASK;
- sbdsp_mix_write(sc, SBP_INFILTER, mixval);
- return (0);
- } else
- return (EINVAL);
+ mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
+ switch (which) {
+ case 0:
+ mixval |= SBP_FILTER_OFF;
+ break;
+ case SB_TREBLE:
+ mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
+ break;
+ case SB_BASS:
+ mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
+ break;
+ default:
+ return;
+ }
+ sc->in_filter = mixval & SBP_IFILTER_MASK;
+ sbdsp_mix_write(sc, SBP_INFILTER, mixval);
}
int
sbdsp_get_ifilter(addr)
void *addr;
{
- register struct sbdsp_softc *sc = addr;
-
- /* XXXX SB16 */
- if (ISSBPROCLASS(sc)) {
- sc->in_filter =
- sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
- switch (sc->in_filter) {
- case SBP_FILTER_ON|SBP_IFILTER_HIGH:
- return (SBP_TREBLE_EQ);
- case SBP_FILTER_ON|SBP_IFILTER_LOW:
- return (SBP_BASS_EQ);
- case SBP_FILTER_OFF:
- default:
- return (0);
- }
- } else
- return (0);
-}
-
-int
-sbdsp_set_out_port(addr, port)
- void *addr;
- int port;
-{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
- sc->out_port = port; /* Just record it */
-
- return (0);
+ sc->in_filter =
+ sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
+ switch (sc->in_filter) {
+ case SBP_FILTER_ON|SBP_IFILTER_HIGH:
+ return SB_TREBLE;
+ case SBP_FILTER_ON|SBP_IFILTER_LOW:
+ return SB_BASS;
+ default:
+ return 0;
+ }
}
int
-sbdsp_get_out_port(addr)
- void *addr;
+sbdsp_set_in_ports(sc, mask)
+ struct sbdsp_softc *sc;
+ int mask;
{
- register struct sbdsp_softc *sc = addr;
-
- return (sc->out_port);
-}
+ int bitsl, bitsr;
+ int sbport;
+ DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
+ sc->sc_mixer_model, mask));
-int
-sbdsp_set_in_port(addr, port)
- void *addr;
- int port;
-{
- register struct sbdsp_softc *sc = addr;
- int mixport, sbport;
-
- if (ISSBPROCLASS(sc)) {
- switch (port) {
- case SB_MIC_PORT:
+ switch(sc->sc_mixer_model) {
+ case SBM_NONE:
+ return EINVAL;
+ case SBM_CT1335:
+ if (mask != (1 << SB_MIC_VOL))
+ return EINVAL;
+ break;
+ case SBM_CT1345:
+ switch (mask) {
+ case 1 << SB_MIC_VOL:
sbport = SBP_FROM_MIC;
- mixport = SBP_MIC_VOL;
break;
- case SB_LINE_IN_PORT:
+ case 1 << SB_LINE_IN_VOL:
sbport = SBP_FROM_LINE;
- mixport = SBP_LINE_VOL;
break;
- case SB_CD_PORT:
+ case 1 << SB_CD_VOL:
sbport = SBP_FROM_CD;
- mixport = SBP_CD_VOL;
break;
- case SB_DAC_PORT:
- case SB_FM_PORT:
default:
return (EINVAL);
}
- } else {
- switch (port) {
- case SB_MIC_PORT:
- sbport = SBP_FROM_MIC;
- mixport = SBP_MIC_VOL;
- break;
- default:
- return (EINVAL);
+ sbdsp_mix_write(sc, SBP_RECORD_SOURCE, sbport | sc->in_filter);
+ break;
+ case SBM_CT1XX5:
+ case SBM_CT1745:
+ if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
+ (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
+ return EINVAL;
+ bitsr = 0;
+ if (mask & (1<<SB_MIDI_VOL)) bitsr |= SBP_MIDI_SRC_R;
+ if (mask & (1<<SB_LINE_IN_VOL)) bitsr |= SBP_LINE_SRC_R;
+ if (mask & (1<<SB_CD_VOL)) bitsr |= SBP_CD_SRC_R;
+ bitsl = SB_SRC_R_TO_L(bitsr);
+ if (mask & (1<<SB_MIC_VOL)) {
+ bitsl |= SBP_MIC_SRC;
+ bitsr |= SBP_MIC_SRC;
}
- }
-
- sc->in_port = port; /* Just record it */
-
- /* XXXX SB16 */
- if (ISSBPROCLASS(sc)) {
- /* record from that port */
- sbdsp_mix_write(sc, SBP_RECORD_SOURCE,
- SBP_RECORD_FROM(sbport, SBP_FILTER_OFF, SBP_IFILTER_HIGH));
- /* fetch gain from that port */
- sc->gain[port] = sbdsp_mix_read(sc, mixport);
+ sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
+ sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
+ break;
}
- return (0);
-}
-
-int
-sbdsp_get_in_port(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
+ sc->in_mask = mask;
- return (sc->in_port);
+ return 0;
}
-
int
sbdsp_speaker_ctl(addr, newstate)
void *addr;
int newstate;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
if ((newstate == SPKR_ON) &&
(sc->spkr_state == SPKR_OFF)) {
@@ -636,7 +809,7 @@ sbdsp_speaker_ctl(addr, newstate)
sbdsp_spkroff(sc);
sc->spkr_state = SPKR_OFF;
}
- return(0);
+ return 0;
}
int
@@ -644,83 +817,26 @@ sbdsp_round_blocksize(addr, blk)
void *addr;
int blk;
{
- register struct sbdsp_softc *sc = addr;
-
- sc->sc_last_hs_size = 0;
-
- /* Don't try to DMA too much at once. */
- if (blk > NBPG)
- blk = NBPG;
-
- /* Round to a multiple of the sample size. */
- blk &= -(sc->sc_channels * sc->sc_precision / 8);
-
- return (blk);
+ blk &= -4; /* round to biggest sample size */
+ return blk;
}
int
-sbdsp_commit_settings(addr)
+sbdsp_open(addr, flags)
void *addr;
-{
- register struct sbdsp_softc *sc = 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) */
-
- if (ISSBPRO(sc)) {
- /*
- * With 2 channels, SBPro can't do more than 22kHz.
- * Whack the rates down to speed if necessary.
- * Reset the time constant anyway
- * because it may have been adjusted with a different number
- * of channels, which means it might have computed the wrong
- * mode (low/high speed).
- */
- if (sc->sc_channels == 2 &&
- sbdsp_tctosr(sc, sc->sc_itc) > 22727) {
- sbdsp_srtotc(sc, 22727, SB_INPUT_RATE,
- &sc->sc_itc, &sc->sc_imode);
- } else
- sbdsp_srtotc(sc, sbdsp_tctosr(sc, sc->sc_itc),
- SB_INPUT_RATE, &sc->sc_itc,
- &sc->sc_imode);
-
- if (sc->sc_channels == 2 &&
- sbdsp_tctosr(sc, sc->sc_otc) > 22727) {
- sbdsp_srtotc(sc, 22727, SB_OUTPUT_RATE,
- &sc->sc_otc, &sc->sc_omode);
- } else
- sbdsp_srtotc(sc, sbdsp_tctosr(sc, sc->sc_otc),
- SB_OUTPUT_RATE, &sc->sc_otc,
- &sc->sc_omode);
- }
-
- /*
- * XXX
- * Should wait for chip to be idle.
- */
- sc->sc_dmadir = SB_DMA_NONE;
-
- 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));
+ struct sbdsp_softc *sc = addr;
+
+ DPRINTF(("sbdsp_open: sc=%p\n", sc));
if (sc->sc_open != 0 || sbdsp_reset(sc) != 0)
return ENXIO;
sc->sc_open = 1;
+ sc->sc_openflags = flags;
sc->sc_mintr = 0;
- if (ISSBPROCLASS(sc) &&
+ if (ISSBPRO(sc) &&
sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
DPRINTF(("sbdsp_open: can't set mono mode\n"));
/* we'll readjust when it's time for DMA. */
@@ -743,11 +859,13 @@ sbdsp_close(addr)
{
struct sbdsp_softc *sc = addr;
- DPRINTF(("sbdsp_close: sc=0x%x\n", sc));
+ DPRINTF(("sbdsp_close: sc=%p\n", sc));
sc->sc_open = 0;
sbdsp_spkroff(sc);
sc->spkr_state = SPKR_OFF;
+ sc->sc_intr8 = 0;
+ sc->sc_intr16 = 0;
sc->sc_mintr = 0;
sbdsp_haltdma(sc);
@@ -764,17 +882,21 @@ sbdsp_close(addr)
*/
int
sbdsp_reset(sc)
- register struct sbdsp_softc *sc;
+ struct sbdsp_softc *sc;
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- sc->sc_intr = 0;
- if (sc->sc_dmadir != SB_DMA_NONE) {
- isadma_abort(sc->dmachan);
- sc->sc_dmadir = SB_DMA_NONE;
+ sc->sc_intr8 = 0;
+ sc->sc_intr16 = 0;
+ if (sc->sc_i.run != SB_NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_i.dmachan);
+ sc->sc_i.run = SB_NOTRUNNING;
+ }
+ if (sc->sc_o.run != SB_NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_o.dmachan);
+ sc->sc_o.run = SB_NOTRUNNING;
}
- sc->sc_last_hs_size = 0;
/*
* See SBK, section 11.3.
@@ -791,29 +913,9 @@ sbdsp_reset(sc)
return 0;
}
-int
-sbdsp16_wait(sc)
- struct sbdsp_softc *sc;
-{
- bus_space_tag_t iot = sc->sc_iot;
- bus_space_handle_t ioh = sc->sc_ioh;
- register int i;
-
- for (i = SBDSP_NPOLL; --i >= 0; ) {
- register u_char x;
- x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
- delay(10);
- if ((x & SB_DSP_BUSY) == 0)
- continue;
- return 0;
- }
- ++sberr.wdsp;
- return -1;
-}
-
/*
* Write a byte to the dsp.
- * XXX We are at the mercy of the card as we use a
+ * We are at the mercy of the card as we use a
* polling loop and wait until it can take the byte.
*/
int
@@ -823,17 +925,17 @@ sbdsp_wdsp(sc, v)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- register int i;
+ int i;
+ u_char x;
for (i = SBDSP_NPOLL; --i >= 0; ) {
- register u_char x;
x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
delay(10);
- if ((x & SB_DSP_BUSY) != 0)
- continue;
- bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
- delay(10);
- return 0;
+ if ((x & SB_DSP_BUSY) == 0) {
+ bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
+ delay(10);
+ return 0;
+ }
}
++sberr.wdsp;
return -1;
@@ -848,17 +950,17 @@ sbdsp_rdsp(sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- register int i;
+ int i;
+ u_char x;
for (i = SBDSP_NPOLL; --i >= 0; ) {
- register u_char x;
x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
delay(10);
- if ((x & SB_DSP_READY) == 0)
- continue;
- x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
- delay(10);
- return x;
+ if (x & SB_DSP_READY) {
+ x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
+ delay(10);
+ return x;
+ }
}
++sberr.rdsp;
return -1;
@@ -915,187 +1017,166 @@ sbdsp_spkroff(sc)
}
/*
- * Read the version number out of the card. Return major code
- * in high byte, and minor code in low byte.
+ * Read the version number out of the card.
+ * Store version information in the softc.
*/
-short
+void
sbversion(sc)
struct sbdsp_softc *sc;
{
- short v;
+ int v;
+ sc->sc_model = SB_UNK;
+ sc->sc_version = 0;
if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
- return 0;
+ return;
v = sbdsp_rdsp(sc) << 8;
v |= sbdsp_rdsp(sc);
- return ((v >= 0) ? v : 0);
+ if (v < 0)
+ return;
+ sc->sc_version = v;
+ switch(SBVER_MAJOR(v)) {
+ case 1:
+ sc->sc_mixer_model = SBM_NONE;
+ sc->sc_model = SB_1;
+ break;
+ case 2:
+ /* Some SB2 have a mixer, some don't. */
+ sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
+ sbdsp_mix_write(sc, SBP_1335_MIDI_VOL, 0x06);
+ /* Check if we can read back the mixer values. */
+ if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
+ (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL) & 0x0e) == 0x06)
+ sc->sc_mixer_model = SBM_CT1335;
+ else
+ sc->sc_mixer_model = SBM_NONE;
+ if (SBVER_MINOR(v) == 0)
+ sc->sc_model = SB_20;
+ else
+ sc->sc_model = SB_2x;
+ break;
+ case 3:
+ sc->sc_mixer_model = SBM_CT1345;
+ sc->sc_model = SB_PRO;
+ break;
+ case 4:
+#if 0
+/* XXX This does not work */
+ /* Most SB16 have a tone controls, but some don't. */
+ sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
+ /* Check if we can read back the mixer value. */
+ if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
+ sc->sc_mixer_model = SBM_CT1745;
+ else
+ sc->sc_mixer_model = SBM_CT1XX5;
+#else
+ sc->sc_mixer_model = SBM_CT1745;
+#endif
+#if 0
+/* XXX figure out a good way of determining the model */
+ /* XXX what about SB_32 */
+ if (SBVER_MINOR(v) == 16)
+ sc->sc_model = SB_64;
+ else
+#endif
+ sc->sc_model = SB_16;
+ break;
+ }
}
/*
- * Halt a DMA in progress. A low-speed transfer can be
- * resumed with sbdsp_contdma().
+ * Halt a DMA in progress.
*/
int
sbdsp_haltdma(addr)
void *addr;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
- DPRINTF(("sbdsp_haltdma: sc=0x%x\n", sc));
+ DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
sbdsp_reset(sc);
return 0;
}
int
-sbdsp_contdma(addr)
- void *addr;
+sbdsp_set_timeconst(sc, tc)
+ struct sbdsp_softc *sc;
+ int tc;
{
- register struct sbdsp_softc *sc = addr;
-
- DPRINTF(("sbdsp_contdma: sc=0x%x\n", sc));
+ DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
- /* XXX how do we reinitialize the DMA controller state? do we care? */
- (void)sbdsp_wdsp(sc, SB_DSP_CONT);
- return(0);
+ if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
+ sbdsp_wdsp(sc, tc) < 0)
+ return EIO;
+
+ return 0;
}
int
-sbdsp16_setrate(sc, sr, isdac, ratep)
- register struct sbdsp_softc *sc;
- int sr;
- int isdac;
- int *ratep;
+sbdsp16_set_rate(sc, cmd, rate)
+ struct sbdsp_softc *sc;
+ int cmd, rate;
{
+ DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
- /*
- * XXXX
- * More checks here?
- */
- if (sr < 5000 || sr > 45454)
- return (EINVAL);
- *ratep = sr;
- return (0);
+ if (sbdsp_wdsp(sc, cmd) < 0 ||
+ sbdsp_wdsp(sc, rate >> 8) < 0 ||
+ sbdsp_wdsp(sc, rate) < 0)
+ return EIO;
+ return 0;
}
-/*
- * 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, isdac, tcp, modep)
- register struct sbdsp_softc *sc;
- int sr;
- int isdac;
- int *tcp, *modep;
+sbdsp_dma_init_input(addr, buf, cc)
+ void *addr;
+ void *buf;
+ int cc;
{
- int tc, realtc, mode;
+ struct sbdsp_softc *sc = addr;
- /*
- * Don't forget to compute which mode we'll be in based on whether
- * we need to double the rate for stereo on SBPRO.
- */
-
- if (sr == 0) {
- tc = SB_LS_MIN;
- mode = SB_ADAC_LS;
- goto out;
- }
+ if (sc->sc_model == SB_1)
+ return 0;
+ sc->sc_i.run = SB_DMARUNNING;
+ DPRINTF(("sbdsp: dma start loop input addr=%p cc=%d chan=%d\n",
+ buf, cc, sc->sc_i.dmachan));
+ isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, buf,
+ cc, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
+ return 0;
+}
- tc = 256 - (1000000 / sr);
+static int
+sbdsp_dma_setup_input(sc)
+ struct sbdsp_softc *sc;
+{
+ int stereo = sc->sc_i.modep->channels == 2;
+ int filter;
- if (sc->sc_channels == 2 && ISSBPRO(sc))
- /* compute based on 2x sample rate when needed */
- realtc = 256 - ( 500000 / sr);
- else
- realtc = tc;
+ /* Initialize the PCM */
+ if (ISSBPRO(sc)) {
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
+ return 0;
+ filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
+ sbdsp_mix_write(sc, SBP_INFILTER,
+ (sbdsp_mix_read(sc, SBP_INFILTER) &
+ ~SBP_IFILTER_MASK) | filter);
+ }
- if (tc < SB_LS_MIN) {
- tc = SB_LS_MIN;
- mode = SB_ADAC_LS; /* NB: 2x minimum speed is still low
- * speed mode. */
- goto out;
- } else if (isdac) {
- if (realtc <= SB_DAC_LS_MAX)
- mode = SB_ADAC_LS;
- else {
- mode = SB_ADAC_HS;
- if (tc > SB_DAC_HS_MAX)
- tc = SB_DAC_HS_MAX;
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE,
+ sc->sc_i.rate)) {
+ DPRINTF(("sbdsp_dma_setup_input: rate=%d set failed\n",
+ sc->sc_i.rate));
+ return 0;
}
} else {
- int adc_ls_max, adc_hs_max;
-
- /* 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 (realtc <= adc_ls_max)
- mode = SB_ADAC_LS;
- else {
- mode = SB_ADAC_HS;
- if (tc > adc_hs_max)
- tc = adc_hs_max;
+ if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
+ DPRINTF(("sbdsp_dma_setup_input: tc=%d set failed\n",
+ sc->sc_i.rate));
+ return 0;
}
}
-
-out:
- *tcp = tc;
- *modep = mode;
- return (0);
-}
-
-/*
- * 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_timeconst(sc, tc)
- register struct sbdsp_softc *sc;
- int tc;
-{
- /*
- * A SBPro in stereo mode uses time constants at double the
- * actual rate.
- */
- if (ISSBPRO(sc) && sc->sc_channels == 2)
- tc = 256 - ((256 - tc) / 2);
-
- DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
-
- if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
- sbdsp_wdsp(sc, tc) < 0)
- return (EIO);
-
- return (0);
+ return 1;
}
int
@@ -1106,119 +1187,171 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
#ifdef AUDIO_DEBUG
if (sbdspdebug > 1)
- Dprintf("sbdsp_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ printf("sbdsp_dma_input: sc=%p buf=%p cc=%d intr=%p(%p)\n",
+ addr, p, cc, intr, arg);
#endif
- if (sc->sc_channels == 2 && (cc & 1)) {
- DPRINTF(("sbdsp_dma_input: stereo input, odd bytecnt\n"));
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.modep->channels == 2 && (cc & 1)) {
+ DPRINTF(("stereo record odd bytes (%d)\n", cc));
return EIO;
}
+#endif
- if (sc->sc_dmadir != SB_DMA_IN) {
- if (ISSBPRO(sc)) {
- if (sc->sc_channels == 2) {
- if (ISJAZZ16(sc) && sc->sc_precision == 16) {
- if (sbdsp_wdsp(sc,
- JAZZ16_RECORD_STEREO) < 0) {
- goto badmode;
- }
- } else if (sbdsp_wdsp(sc,
- SB_DSP_RECORD_STEREO) < 0)
- goto badmode;
- sbdsp_mix_write(sc, SBP_INFILTER,
- (sbdsp_mix_read(sc, SBP_INFILTER) &
- ~SBP_IFILTER_MASK) | SBP_FILTER_OFF);
- } else {
- if (ISJAZZ16(sc) && sc->sc_precision == 16) {
- if (sbdsp_wdsp(sc,
- JAZZ16_RECORD_MONO) < 0)
- {
- goto badmode;
- }
- } else if (sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0)
- goto badmode;
- sbdsp_mix_write(sc, SBP_INFILTER,
- (sbdsp_mix_read(sc, SBP_INFILTER) &
- ~SBP_IFILTER_MASK) | sc->in_filter);
- }
+ if (sc->sc_i.modep->precision == 8) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.dmachan != sc->sc_drq8) {
+ printf("sbdsp_dma_input: prec=%d bad chan %d\n",
+ sc->sc_i.modep->precision, sc->sc_i.dmachan);
+ return EIO;
}
-
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, SB_DSP16_INPUTRATE) < 0 ||
- sbdsp_wdsp(sc, sc->sc_irate >> 8) < 0 ||
- sbdsp_wdsp(sc, sc->sc_irate) < 0)
- goto giveup;
- } else
- sbdsp_set_timeconst(sc, sc->sc_itc);
-
- sc->sc_dmadir = SB_DMA_IN;
- sc->dmaflags = DMAMODE_READ;
- if (ISSB2CLASS(sc))
- sc->dmaflags |= DMAMODE_LOOP;
+#endif
+ sc->sc_intr8 = intr;
+ sc->sc_arg8 = arg;
} else {
- /* Already started; just return. */
- if (ISSB2CLASS(sc))
- return 0;
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.dmachan != sc->sc_drq16) {
+ printf("sbdsp_dma_input: prec=%d bad chan %d\n",
+ sc->sc_i.modep->precision, sc->sc_i.dmachan);
+ return EIO;
+ }
+#endif
+ sc->sc_intr16 = intr;
+ sc->sc_arg16 = arg;
}
-
- sc->dmaaddr = p;
- sc->dmacnt = ISSB2CLASS(sc) ? (NBPG/cc)*cc : cc;
- sc->dmachan = sc->sc_precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
- isadma_start(sc->dmaaddr, sc->dmacnt, sc->dmachan, sc->dmaflags);
- sc->sc_intr = intr;
- sc->sc_arg = arg;
-
- if (sc->sc_precision == 16)
- cc >>= 1;
- --cc;
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, sc->sc_precision == 16 ? SB_DSP16_RDMA_16 :
- SB_DSP16_RDMA_8) < 0 ||
- sbdsp_wdsp(sc, (sc->sc_precision == 16 ? 0x10 : 0x00) |
- (sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
- sbdsp16_wait(sc) ||
+
+ switch(sc->sc_i.run) {
+ case SB_NOTRUNNING:
+ /* Non-looping mode, not initialized */
+ sc->sc_i.run = SB_RUNNING;
+ if (!sbdsp_dma_setup_input(sc))
+ goto giveup;
+ /* fall into */
+ case SB_RUNNING:
+ /* Non-looping mode, start DMA */
+#ifdef AUDIO_DEBUG
+ if (sbdspdebug > 2)
+ printf("sbdsp_dma_input: dmastart buf=%p cc=%d chan=%d\n",
+ p, cc, sc->sc_i.dmachan);
+#endif
+ isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, p,
+ cc, NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
+
+ /* Start PCM in non-looping mode */
+ if ((sc->sc_model == SB_JAZZ && sc->sc_i.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_i.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_input: SB16 DMA start failed\n"));
+ DPRINTF(("sbdsp_dma_input: SB1 DMA start failed\n"));
goto giveup;
}
- } else if (ISSB2CLASS(sc)) {
- if (cc != sc->sc_last_hs_size) {
+ break;
+ case SB_DMARUNNING:
+ /* Looping mode, not initialized */
+ sc->sc_i.run = SB_PCMRUNNING;
+ if (!sbdsp_dma_setup_input(sc))
+ goto giveup;
+ if ((sc->sc_model == SB_JAZZ && sc->sc_i.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_i.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ /* Initialize looping PCM */
+ if (ISSB16CLASS(sc)) {
+#ifdef AUDIO_DEBUG
+ if (sbdspdebug > 2)
+ printf("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
+ sc->sc_i.modep->cmd, sc->sc_i.bmode, cc);
+#endif
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
+ sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
+ sbdsp_wdsp(sc, cc) < 0 ||
+ sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_input: SB16 DMA start failed\n"));
+ DPRINTF(("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
+ sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
+ goto giveup;
+ }
+ } else {
+ DPRINTF(("sbdsp_dma_input: set blocksize=%d\n", cc));
if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_input: SB2 DMA blocksize failed\n"));
+ goto giveup;
+ }
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
DPRINTF(("sbdsp_dma_input: SB2 DMA start failed\n"));
goto giveup;
}
- sc->sc_last_hs_size = cc;
- }
- if (sbdsp_wdsp(sc,
- sc->sc_imode == SB_ADAC_LS ? SB_DSP_RDMA_LOOP :
- SB_DSP_HS_INPUT) < 0) {
- DPRINTF(("sbdsp_dma_input: SB2 DMA restart failed\n"));
- goto giveup;
- }
- } else {
- if (sbdsp_wdsp(sc, SB_DSP_RDMA) < 0 ||
- sbdsp_wdsp(sc, cc) < 0 ||
- sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_input: SB1 DMA start failed\n"));
- goto giveup;
}
+ break;
+ case SB_PCMRUNNING:
+ /* Looping mode, nothing to do */
+ break;
}
return 0;
giveup:
sbdsp_reset(sc);
return EIO;
+}
-badmode:
- DPRINTF(("sbdsp_dma_input: can't set %s mode\n",
- sc->sc_channels == 2 ? "stereo" : "mono"));
- return EIO;
+int
+sbdsp_dma_init_output(addr, buf, cc)
+ void *addr;
+ void *buf;
+ int cc;
+{
+ struct sbdsp_softc *sc = addr;
+
+ if (sc->sc_model == SB_1)
+ return 0;
+ sc->sc_o.run = SB_DMARUNNING;
+ DPRINTF(("sbdsp: dma start loop output buf=%p cc=%d chan=%d\n",
+ buf, cc, sc->sc_o.dmachan));
+ isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, buf,
+ cc, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
+ return 0;
+}
+
+static int
+sbdsp_dma_setup_output(sc)
+ struct sbdsp_softc *sc;
+{
+ int stereo = sc->sc_o.modep->channels == 2;
+ int cmd;
+
+ if (ISSBPRO(sc)) {
+ /* 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) |
+ (stereo ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
+ cmd = sc->sc_o.modep->cmdchan;
+ if (cmd && sbdsp_wdsp(sc, cmd) < 0)
+ return 0;
+ }
+
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE,
+ sc->sc_o.rate)) {
+ DPRINTF(("sbdsp_dma_setup_output: rate=%d set failed\n",
+ sc->sc_o.rate));
+ return 0;
+ }
+ } else {
+ if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
+ DPRINTF(("sbdsp_dma_setup_output: tc=%d set failed\n",
+ sc->sc_o.rate));
+ return 0;
+ }
+ }
+ return 1;
}
int
@@ -1229,103 +1362,105 @@ sbdsp_dma_output(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
#ifdef AUDIO_DEBUG
if (sbdspdebug > 1)
- Dprintf("sbdsp_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ printf("sbdsp_dma_output: sc=%p buf=%p cc=%d intr=%p(%p)\n", addr, p, cc, intr, arg);
#endif
- if (sc->sc_channels == 2 && (cc & 1)) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.modep->channels == 2 && (cc & 1)) {
DPRINTF(("stereo playback odd bytes (%d)\n", cc));
return EIO;
}
+#endif
- if (sc->sc_dmadir != SB_DMA_OUT) {
- if (ISSBPRO(sc)) {
- /* 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_channels == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
- if (ISJAZZ16(sc)) {
- /* Yes, we write the record mode to set
- 16-bit playback mode. weird, huh? */
- if (sc->sc_precision == 16) {
- sbdsp_wdsp(sc,
- sc->sc_channels == 2 ?
- JAZZ16_RECORD_STEREO :
- JAZZ16_RECORD_MONO);
- } else {
- sbdsp_wdsp(sc,
- sc->sc_channels == 2 ?
- SB_DSP_RECORD_STEREO :
- SB_DSP_RECORD_MONO);
- }
- }
+ if (sc->sc_o.modep->precision == 8) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.dmachan != sc->sc_drq8) {
+ printf("sbdsp_dma_output: prec=%d bad chan %d\n",
+ sc->sc_o.modep->precision, sc->sc_o.dmachan);
+ return EIO;
}
-
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, SB_DSP16_OUTPUTRATE) < 0 ||
- sbdsp_wdsp(sc, sc->sc_orate >> 8) < 0 ||
- sbdsp_wdsp(sc, sc->sc_orate) < 0)
- goto giveup;
- } else
- sbdsp_set_timeconst(sc, sc->sc_otc);
-
- sc->sc_dmadir = SB_DMA_OUT;
- sc->dmaflags = DMAMODE_WRITE;
- if (ISSB2CLASS(sc))
- sc->dmaflags |= DMAMODE_LOOP;
+#endif
+ sc->sc_intr8 = intr;
+ sc->sc_arg8 = arg;
} else {
- /* Already started; just return. */
- if (ISSB2CLASS(sc))
- return 0;
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.dmachan != sc->sc_drq16) {
+ printf("sbdsp_dma_output: prec=%d bad chan %d\n",
+ sc->sc_o.modep->precision, sc->sc_o.dmachan);
+ return EIO;
+ }
+#endif
+ sc->sc_intr16 = intr;
+ sc->sc_arg16 = arg;
}
- sc->dmaaddr = p;
- sc->dmacnt = ISSB2CLASS(sc) ? (NBPG/cc)*cc : cc;
- sc->dmachan = sc->sc_precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
- isadma_start(sc->dmaaddr, sc->dmacnt, sc->dmachan, sc->dmaflags);
- sc->sc_intr = intr;
- sc->sc_arg = arg;
-
- if (sc->sc_precision == 16)
- cc >>= 1;
- --cc;
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, sc->sc_precision == 16 ? SB_DSP16_WDMA_16 :
- SB_DSP16_WDMA_8) < 0 ||
- sbdsp_wdsp(sc, (sc->sc_precision == 16 ? 0x10 : 0x00) |
- (sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
- sbdsp16_wait(sc) ||
+ switch(sc->sc_o.run) {
+ case SB_NOTRUNNING:
+ /* Non-looping mode, not initialized */
+ sc->sc_o.run = SB_RUNNING;
+ if (!sbdsp_dma_setup_output(sc))
+ goto giveup;
+ /* fall into */
+ case SB_RUNNING:
+ /* Non-looping mode, initialized. Start DMA and PCM */
+#ifdef AUDIO_DEBUG
+ if (sbdspdebug > 2)
+ printf("sbdsp: start dma out addr=%p, cc=%d, chan=%d\n",
+ p, cc, sc->sc_o.dmachan);
+#endif
+ isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, p,
+ cc, NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
+ if ((sc->sc_model == SB_JAZZ && sc->sc_o.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_o.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_output: SB16 DMA start failed\n"));
+ DPRINTF(("sbdsp_dma_output: SB1 DMA start failed\n"));
goto giveup;
}
- } else if (ISSB2CLASS(sc)) {
- if (cc != sc->sc_last_hs_size) {
+ break;
+ case SB_DMARUNNING:
+ /* Looping mode, not initialized */
+ sc->sc_o.run = SB_PCMRUNNING;
+ if (!sbdsp_dma_setup_output(sc))
+ goto giveup;
+ if ((sc->sc_model == SB_JAZZ && sc->sc_o.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_o.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ /* Initialize looping PCM */
+ if (ISSB16CLASS(sc)) {
+ DPRINTF(("sbdsp_dma_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
+ sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
+ if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
+ sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
+ sbdsp_wdsp(sc, cc) < 0 ||
+ sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_output: SB16 DMA start failed\n"));
+ goto giveup;
+ }
+ } else {
+ DPRINTF(("sbdsp_dma_output: set blocksize=%d\n", cc));
if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_output: SB2 DMA blocksize failed\n"));
+ goto giveup;
+ }
+ if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
DPRINTF(("sbdsp_dma_output: SB2 DMA start failed\n"));
goto giveup;
}
- sc->sc_last_hs_size = cc;
- }
- if (sbdsp_wdsp(sc,
- sc->sc_omode == SB_ADAC_LS ? SB_DSP_WDMA_LOOP :
- SB_DSP_HS_OUTPUT) < 0) {
- DPRINTF(("sbdsp_dma_output: SB2 DMA restart failed\n"));
- goto giveup;
- }
- } else {
- if (sbdsp_wdsp(sc, SB_DSP_WDMA) < 0 ||
- sbdsp_wdsp(sc, cc) < 0 ||
- sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_output: SB1 DMA start failed\n"));
- goto giveup;
}
+ break;
+ case SB_PCMRUNNING:
+ /* Looping mode, nothing to do */
+ break;
}
return 0;
@@ -1338,44 +1473,61 @@ giveup:
* 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.
+ * completion of a dma reception.
+ *
+ * If there is interrupt sharing or a spurious interrupt occurs
+ * there is no way to distinguish this on an SB2. So if you have
+ * an SB2 and experience problems, buy an SB16 (it's only $40).
*/
int
sbdsp_intr(arg)
void *arg;
{
- register struct sbdsp_softc *sc = arg;
- u_char x;
+ struct sbdsp_softc *sc = arg;
+ int loop = sc->sc_model != SB_1;
+ u_char irq;
#ifdef AUDIO_DEBUG
if (sbdspdebug > 1)
- Dprintf("sbdsp_intr: intr=0x%x\n", sc->sc_intr);
+ printf("sbdsp_intr: intr8=%p, intr16=%p\n",
+ sc->sc_intr8, sc->sc_intr16);
#endif
if (ISSB16CLASS(sc)) {
- x = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
- if ((x & 3) == 0)
+ irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
+ if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16)) == 0) {
+ DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
return 0;
+ }
+ } else {
+ if (!loop && !isa_dmafinished(sc->sc_isa, sc->sc_drq8))
+ return 0;
+ irq = SBP_IRQ_DMA8;
}
- /* isadma_finished() moved to isadma.c */
sc->sc_interrupts++;
- delay(10);
+ delay(10); /* XXX why? */
#if 0
if (sc->sc_mintr != 0) {
x = sbdsp_rdsp(sc);
(*sc->sc_mintr)(sc->sc_arg, x);
} else
#endif
- if (sc->sc_intr != 0) {
- /* clear interrupt */
- x = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
- sc->sc_precision == 16 ? SBP_DSP_IRQACK16 :
- SBP_DSP_IRQACK8);
- if (!ISSB2CLASS(sc))
- isadma_done(sc->dmachan);
- (*sc->sc_intr)(sc->sc_arg);
- } else {
- return 0;
+ if (sc->sc_intr8 == 0 && sc->sc_intr16 == 0) {
+ DPRINTF(("sbdsp_intr: Unexpected interrupt 0x%x\n", irq));
+ /* XXX return 0;*/ /* Did not expect an interrupt */
+ }
+
+ /* clear interrupt */
+ if (irq & SBP_IRQ_DMA8) {
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
+ if (!loop)
+ isa_dmadone(sc->sc_isa, sc->sc_drq8);
+ if (sc->sc_intr8)
+ (*sc->sc_intr8)(sc->sc_arg8);
+ }
+ if (irq & SBP_IRQ_DMA16) {
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
+ if (sc->sc_intr16)
+ (*sc->sc_intr16)(sc->sc_arg16);
}
return 1;
}
@@ -1419,13 +1571,120 @@ sbdsp_midi_output(sc, v)
}
#endif
-int
-sbdsp_setfd(addr, flag)
- void *addr;
- int flag;
+/* Mask a value 0-255, but round it first */
+#define MAXVAL 256
+static int
+sbdsp_adjust(val, mask)
+ int val, mask;
{
- /* Can't do full-duplex */
- return(ENOTTY);
+ val += (MAXVAL - mask) >> 1;
+ if (val >= MAXVAL)
+ val = MAXVAL-1;
+ return val & mask;
+}
+
+void
+sbdsp_set_mixer_gain(sc, port)
+ struct sbdsp_softc *sc;
+ int port;
+{
+ int src, gain;
+
+ switch(sc->sc_mixer_model) {
+ case SBM_NONE:
+ return;
+ case SBM_CT1335:
+ gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
+ switch(port) {
+ case SB_MASTER_VOL:
+ src = SBP_1335_MASTER_VOL;
+ break;
+ case SB_MIDI_VOL:
+ src = SBP_1335_MIDI_VOL;
+ break;
+ case SB_CD_VOL:
+ src = SBP_1335_CD_VOL;
+ break;
+ case SB_VOICE_VOL:
+ src = SBP_1335_VOICE_VOL;
+ gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
+ break;
+ default:
+ return;
+ }
+ sbdsp_mix_write(sc, src, gain);
+ break;
+ case SBM_CT1345:
+ gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
+ sc->gain[port][SB_RIGHT]);
+ switch (port) {
+ case SB_MIC_VOL:
+ src = SBP_MIC_VOL;
+ gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
+ break;
+ case SB_MASTER_VOL:
+ src = SBP_MASTER_VOL;
+ break;
+ case SB_LINE_IN_VOL:
+ src = SBP_LINE_VOL;
+ break;
+ case SB_VOICE_VOL:
+ src = SBP_VOICE_VOL;
+ break;
+ case SB_MIDI_VOL:
+ src = SBP_MIDI_VOL;
+ break;
+ case SB_CD_VOL:
+ src = SBP_CD_VOL;
+ break;
+ default:
+ return;
+ }
+ sbdsp_mix_write(sc, src, gain);
+ break;
+ case SBM_CT1XX5:
+ case SBM_CT1745:
+ switch (port) {
+ case SB_MIC_VOL:
+ src = SB16P_MIC_L;
+ break;
+ case SB_MASTER_VOL:
+ src = SB16P_MASTER_L;
+ break;
+ case SB_LINE_IN_VOL:
+ src = SB16P_LINE_L;
+ break;
+ case SB_VOICE_VOL:
+ src = SB16P_VOICE_L;
+ break;
+ case SB_MIDI_VOL:
+ src = SB16P_MIDI_L;
+ break;
+ case SB_CD_VOL:
+ src = SB16P_CD_L;
+ break;
+ case SB_INPUT_GAIN:
+ src = SB16P_INPUT_GAIN_L;
+ break;
+ case SB_OUTPUT_GAIN:
+ src = SB16P_OUTPUT_GAIN_L;
+ break;
+ case SB_TREBLE:
+ src = SB16P_TREBLE_L;
+ break;
+ case SB_BASS:
+ src = SB16P_BASS_L;
+ break;
+ case SB_PCSPEAKER:
+ sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
+ return;
+ default:
+ return;
+ }
+ sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
+ sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
+ break;
+ }
}
int
@@ -1433,27 +1692,46 @@ sbdsp_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct sbdsp_softc *sc = addr;
- int src, gain;
+ struct sbdsp_softc *sc = addr;
+ int lgain, rgain;
+ int mask, bits;
+ int lmask, rmask, lbits, rbits;
+ int mute, swap;
DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
cp->un.value.num_channels));
- if (!ISSBPROCLASS(sc))
+ if (sc->sc_mixer_model == SBM_NONE)
return EINVAL;
- /*
- * Everything is a value except for SBPro BASS/TREBLE and
- * RECORD_SOURCE
- */
switch (cp->dev) {
- case SB_SPEAKER:
- cp->dev = SB_MASTER_VOL;
- case SB_MIC_PORT:
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
+ case SB_TREBLE:
+ case SB_BASS:
+ if (sc->sc_mixer_model == SBM_CT1345 ||
+ sc->sc_mixer_model == SBM_CT1XX5) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ switch (cp->dev) {
+ case SB_TREBLE:
+ sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
+ return 0;
+ case SB_BASS:
+ sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
+ return 0;
+ }
+ }
+ case SB_PCSPEAKER:
+ case SB_INPUT_GAIN:
+ case SB_OUTPUT_GAIN:
+ if (!ISSBM1745(sc))
+ return EINVAL;
+ case SB_MIC_VOL:
+ case SB_LINE_IN_VOL:
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return EINVAL;
+ case SB_VOICE_VOL:
+ case SB_MIDI_VOL:
+ case SB_CD_VOL:
case SB_MASTER_VOL:
if (cp->type != AUDIO_MIXER_VALUE)
return EINVAL;
@@ -1465,83 +1743,136 @@ sbdsp_mixer_set_port(addr, cp)
*/
switch (cp->dev) {
- case SB_MIC_PORT:
+ case SB_MIC_VOL:
if (cp->un.value.num_channels != 1)
return EINVAL;
- /* handle funny microphone gain */
- gain = SBP_AGAIN_TO_MICGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
+ lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
break;
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
- case SB_MASTER_VOL:
+ case SB_PCSPEAKER:
+ if (cp->un.value.num_channels != 1)
+ return EINVAL;
+ /* fall into */
+ case SB_INPUT_GAIN:
+ case SB_OUTPUT_GAIN:
+ lgain = rgain = SB_ADJUST_2_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
+ break;
+ default:
switch (cp->un.value.num_channels) {
case 1:
- gain = sbdsp_mono_vol(SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]));
+ lgain = rgain = SB_ADJUST_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
break;
case 2:
- gain = sbdsp_stereo_vol(SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]),
- SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]));
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return EINVAL;
+ lgain = SB_ADJUST_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
+ rgain = SB_ADJUST_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
break;
default:
return EINVAL;
}
break;
- default:
- return EINVAL;
}
+ sc->gain[cp->dev][SB_LEFT] = lgain;
+ sc->gain[cp->dev][SB_RIGHT] = rgain;
- switch (cp->dev) {
- case SB_MIC_PORT:
- src = SBP_MIC_VOL;
- break;
- case SB_MASTER_VOL:
- src = SBP_MASTER_VOL;
- 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;
- default:
- return EINVAL;
+ sbdsp_set_mixer_gain(sc, cp->dev);
+ break;
+
+ case SB_RECORD_SOURCE:
+ if (ISSBM1745(sc)) {
+ if (cp->type != AUDIO_MIXER_SET)
+ return EINVAL;
+ return sbdsp_set_in_ports(sc, cp->un.mask);
+ } else {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ sc->in_port = cp->un.ord;
+ return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
}
+ break;
- sbdsp_mix_write(sc, src, gain);
- sc->gain[cp->dev] = gain;
+ case SB_AGC:
+ if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
break;
- case SB_TREBLE:
- case SB_BASS:
- case SB_RECORD_SOURCE:
+ case SB_CD_OUT_MUTE:
+ mask = SB16P_SW_CD;
+ goto omute;
+ case SB_MIC_OUT_MUTE:
+ mask = SB16P_SW_MIC;
+ goto omute;
+ case SB_LINE_OUT_MUTE:
+ mask = SB16P_SW_LINE;
+ omute:
if (cp->type != AUDIO_MIXER_ENUM)
return EINVAL;
+ bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
+ sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
+ if (cp->un.ord)
+ bits = bits & ~mask;
+ else
+ bits = bits | mask;
+ sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
+ break;
- switch (cp->dev) {
- case SB_TREBLE:
- return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_TREBLE_EQ : 0);
- case SB_BASS:
- return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_BASS_EQ : 0);
- case SB_RECORD_SOURCE:
- return sbdsp_set_in_port(addr, cp->un.ord);
+ case SB_MIC_IN_MUTE:
+ case SB_MIC_SWAP:
+ lmask = rmask = SB16P_SW_MIC;
+ goto imute;
+ case SB_CD_IN_MUTE:
+ case SB_CD_SWAP:
+ lmask = SB16P_SW_CD_L;
+ rmask = SB16P_SW_CD_R;
+ goto imute;
+ case SB_LINE_IN_MUTE:
+ case SB_LINE_SWAP:
+ lmask = SB16P_SW_LINE_L;
+ rmask = SB16P_SW_LINE_R;
+ goto imute;
+ case SB_MIDI_IN_MUTE:
+ case SB_MIDI_SWAP:
+ lmask = SB16P_SW_MIDI_L;
+ rmask = SB16P_SW_MIDI_R;
+ imute:
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ mask = lmask | rmask;
+ lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
+ rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
+ sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
+ if (SB_IS_IN_MUTE(cp->dev)) {
+ mute = cp->dev;
+ swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
+ } else {
+ swap = cp->dev;
+ mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
}
-
+ if (sc->gain[swap][SB_LR]) {
+ mask = lmask;
+ lmask = rmask;
+ rmask = mask;
+ }
+ if (!sc->gain[mute][SB_LR]) {
+ lbits = lbits | lmask;
+ rbits = rbits | rmask;
+ }
+ sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
+ sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
break;
default:
return EINVAL;
}
- return (0);
+ return 0;
}
int
@@ -1549,223 +1880,441 @@ sbdsp_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct sbdsp_softc *sc = addr;
- int gain;
+ struct sbdsp_softc *sc = addr;
- DPRINTF(("sbdsp_mixer_get_port: port=%d", cp->dev));
+ DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
- if (!ISSBPROCLASS(sc))
+ if (sc->sc_mixer_model == SBM_NONE)
return EINVAL;
switch (cp->dev) {
- case SB_SPEAKER:
- cp->dev = SB_MASTER_VOL;
- case SB_MIC_PORT:
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
+ case SB_TREBLE:
+ case SB_BASS:
+ if (sc->sc_mixer_model == SBM_CT1345 ||
+ sc->sc_mixer_model == SBM_CT1XX5) {
+ switch (cp->dev) {
+ case SB_TREBLE:
+ cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
+ return 0;
+ case SB_BASS:
+ cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
+ return 0;
+ }
+ }
+ case SB_PCSPEAKER:
+ case SB_INPUT_GAIN:
+ case SB_OUTPUT_GAIN:
+ if (!ISSBM1745(sc))
+ return EINVAL;
+ case SB_MIC_VOL:
+ case SB_LINE_IN_VOL:
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return EINVAL;
+ case SB_VOICE_VOL:
+ case SB_MIDI_VOL:
+ case SB_CD_VOL:
case SB_MASTER_VOL:
- gain = sc->gain[cp->dev];
-
switch (cp->dev) {
- case SB_MIC_PORT:
+ case SB_MIC_VOL:
+ case SB_PCSPEAKER:
if (cp->un.value.num_channels != 1)
return EINVAL;
-
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = SBP_MICGAIN_TO_AGAIN(gain);
- break;
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
- case SB_MASTER_VOL:
+ /* fall into */
+ default:
switch (cp->un.value.num_channels) {
case 1:
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = SBP_SBGAIN_TO_AGAIN(gain);
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
+ sc->gain[cp->dev][SB_LEFT];
break;
case 2:
- cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = SBP_LEFTGAIN(gain);
- cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = SBP_RIGHTGAIN(gain);
+ cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
+ sc->gain[cp->dev][SB_LEFT];
+ cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
+ sc->gain[cp->dev][SB_RIGHT];
break;
default:
return EINVAL;
}
break;
}
-
break;
- case SB_TREBLE:
- case SB_BASS:
case SB_RECORD_SOURCE:
- switch (cp->dev) {
- case SB_TREBLE:
- cp->un.ord = sbdsp_get_ifilter(addr) == SBP_TREBLE_EQ;
- return 0;
- case SB_BASS:
- cp->un.ord = sbdsp_get_ifilter(addr) == SBP_BASS_EQ;
- return 0;
- case SB_RECORD_SOURCE:
- cp->un.ord = sbdsp_get_in_port(addr);
- return 0;
- }
+ if (ISSBM1745(sc))
+ cp->un.mask = sc->in_mask;
+ else
+ cp->un.ord = sc->in_port;
+ break;
+ case SB_AGC:
+ if (!ISSBM1745(sc))
+ return EINVAL;
+ cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
+ break;
+
+ case SB_CD_IN_MUTE:
+ case SB_MIC_IN_MUTE:
+ case SB_LINE_IN_MUTE:
+ case SB_MIDI_IN_MUTE:
+ case SB_CD_SWAP:
+ case SB_MIC_SWAP:
+ case SB_LINE_SWAP:
+ case SB_MIDI_SWAP:
+ case SB_CD_OUT_MUTE:
+ case SB_MIC_OUT_MUTE:
+ case SB_LINE_OUT_MUTE:
+ cp->un.ord = sc->gain[cp->dev][SB_LR];
break;
default:
return EINVAL;
}
- return (0);
+ return 0;
}
int
sbdsp_mixer_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
+ int chan, class, is1745;
- DPRINTF(("sbdsp_mixer_query_devinfo: index=%d\n", dip->index));
+ DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
+ sc->sc_mixer_model, dip->index));
+
+ if (sc->sc_mixer_model == SBM_NONE)
+ return ENXIO;
+
+ chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
+ is1745 = ISSBM1745(sc);
+ class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
switch (dip->index) {
- case SB_MIC_PORT:
+ case SB_MASTER_VOL:
dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNmaster);
+ dip->un.v.num_channels = chan;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+ case SB_MIDI_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmicrophone);
- dip->un.v.num_channels = 1;
+ dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNfmsynth);
+ dip->un.v.num_channels = chan;
strcpy(dip->un.v.units.name, AudioNvolume);
return 0;
-
- case SB_SPEAKER:
+ case SB_CD_VOL:
dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->mixer_class = class;
dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNspeaker);
- dip->un.v.num_channels = 1;
+ dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNcd);
+ dip->un.v.num_channels = chan;
strcpy(dip->un.v.units.name, AudioNvolume);
return 0;
-
- 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);
+ case SB_VOICE_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNdac);
+ dip->un.v.num_channels = chan;
+ strcpy(dip->un.v.units.name, AudioNvolume);
return 0;
-
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);
+ strcpy(dip->label.name, AudioCoutputs);
return 0;
}
- 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);
- return 0;
-
- 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);
- return 0;
-
- 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);
- return 0;
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return ENXIO;
- 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, AudioNfmsynth);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- return 0;
+ switch (dip->index) {
+ case SB_MIC_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNmicrophone);
+ dip->un.v.num_channels = 1;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
- case SB_MASTER_VOL:
- 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, AudioNvolume);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- return 0;
+ case SB_LINE_IN_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNline);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
- case SB_RECORD_SOURCE:
- dip->mixer_class = SB_RECORD_CLASS;
+ case SB_RECORD_SOURCE:
+ dip->mixer_class = SB_RECORD_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNsource);
+ if (ISSBM1745(sc)) {
+ dip->type = AUDIO_MIXER_SET;
+ dip->un.s.num_mem = 4;
+ strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
+ dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
+ strcpy(dip->un.s.member[1].label.name, AudioNcd);
+ dip->un.s.member[1].mask = 1 << SB_CD_VOL;
+ strcpy(dip->un.s.member[2].label.name, AudioNline);
+ dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
+ strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
+ dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
+ } else {
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;
+ dip->un.e.member[0].ord = SB_MIC_VOL;
strcpy(dip->un.e.member[1].label.name, AudioNcd);
- dip->un.e.member[1].ord = SB_CD_PORT;
+ dip->un.e.member[1].ord = SB_CD_VOL;
strcpy(dip->un.e.member[2].label.name, AudioNline);
- dip->un.e.member[2].ord = SB_LINE_IN_PORT;
- return 0;
+ dip->un.e.member[2].ord = SB_LINE_IN_VOL;
+ }
+ return 0;
- case SB_BASS:
+ case SB_BASS:
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNbass);
+ if (sc->sc_mixer_model == SBM_CT1745) {
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_EQUALIZATION_CLASS;
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNbass);
+ } else {
dip->type = AUDIO_MIXER_ENUM;
dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNbass);
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;
- return 0;
-
- case SB_TREBLE:
+ }
+ return 0;
+
+ case SB_TREBLE:
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNtreble);
+ if (sc->sc_mixer_model == SBM_CT1745) {
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_EQUALIZATION_CLASS;
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNtreble);
+ } else {
dip->type = AUDIO_MIXER_ENUM;
dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNtreble);
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;
- return 0;
+ }
+ return 0;
+
+ case SB_RECORD_CLASS: /* record source class */
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_RECORD_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCrecord);
+ return 0;
+
+ 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);
+ return 0;
+
+ }
+
+ if (sc->sc_mixer_model == SBM_CT1345)
+ return ENXIO;
+
+ switch(dip->index) {
+ case SB_PCSPEAKER:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, "pc_speaker");
+ dip->un.v.num_channels = 1;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_INPUT_GAIN:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNinput);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_OUTPUT_GAIN:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNoutput);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_AGC:
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, "AGC");
+ 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;
+ return 0;
+
+ case SB_EQUALIZATION_CLASS:
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_EQUALIZATION_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCequalization);
+ return 0;
+
+ case SB_CD_IN_MUTE:
+ dip->prev = SB_CD_VOL;
+ dip->next = SB_CD_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_MIC_IN_MUTE:
+ dip->prev = SB_MIC_VOL;
+ dip->next = SB_MIC_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_LINE_IN_MUTE:
+ dip->prev = SB_LINE_IN_VOL;
+ dip->next = SB_LINE_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_MIDI_IN_MUTE:
+ dip->prev = SB_MIDI_VOL;
+ dip->next = SB_MIDI_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_CD_SWAP:
+ dip->prev = SB_CD_IN_MUTE;
+ dip->next = SB_CD_OUT_MUTE;
+ goto swap;
+
+ case SB_MIC_SWAP:
+ dip->prev = SB_MIC_IN_MUTE;
+ dip->next = SB_MIC_OUT_MUTE;
+ goto swap;
+
+ case SB_LINE_SWAP:
+ dip->prev = SB_LINE_IN_MUTE;
+ dip->next = SB_LINE_OUT_MUTE;
+ goto swap;
+
+ case SB_MIDI_SWAP:
+ dip->prev = SB_MIDI_IN_MUTE;
+ dip->next = AUDIO_MIXER_LAST;
+ swap:
+ dip->mixer_class = SB_INPUT_CLASS;
+ strcpy(dip->label.name, AudioNswap);
+ goto mute1;
+
+ case SB_CD_OUT_MUTE:
+ dip->prev = SB_CD_SWAP;
+ dip->next = AUDIO_MIXER_LAST;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ goto mute;
+
+ case SB_MIC_OUT_MUTE:
+ dip->prev = SB_MIC_SWAP;
+ dip->next = AUDIO_MIXER_LAST;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ goto mute;
+
+ case SB_LINE_OUT_MUTE:
+ dip->prev = SB_LINE_SWAP;
+ dip->next = AUDIO_MIXER_LAST;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ mute:
+ strcpy(dip->label.name, AudioNmute);
+ mute1:
+ dip->type = AUDIO_MIXER_ENUM;
+ 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;
+ return 0;
- case SB_RECORD_CLASS: /* record source class */
- dip->type = AUDIO_MIXER_CLASS;
- dip->mixer_class = SB_RECORD_CLASS;
- dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCRecord);
- return 0;
- }
}
return ENXIO;
}
+
+void *
+sb_malloc(addr, size, pool, flags)
+ void *addr;
+ unsigned long size;
+ int pool;
+ int flags;
+{
+ struct sbdsp_softc *sc = addr;
+
+ return isa_malloc(sc->sc_isa, 4, size, pool, flags);
+}
+
+void
+sb_free(addr, ptr, pool)
+ void *addr;
+ void *ptr;
+ int pool;
+{
+ isa_free(ptr, pool);
+}
+
+unsigned long
+sb_round(addr, size)
+ void *addr;
+ unsigned long size;
+{
+ if (size > MAX_ISADMA)
+ size = MAX_ISADMA;
+ return size;
+}
+
+int
+sb_mappage(addr, mem, off, prot)
+ void *addr;
+ void *mem;
+ int off;
+ int prot;
+{
+ return isa_mappage(mem, off, prot);
+}
+
+int
+sbdsp_get_props(addr)
+ void *addr;
+{
+ struct sbdsp_softc *sc = addr;
+ return AUDIO_PROP_MMAP |
+ (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
+}
diff --git a/sys/dev/isa/sbdspvar.h b/sys/dev/isa/sbdspvar.h
index 5279e227ef5..c70a012f447 100644
--- a/sys/dev/isa/sbdspvar.h
+++ b/sys/dev/isa/sbdspvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sbdspvar.h,v 1.7 1997/07/10 23:06:38 provos Exp $ */
-/* $NetBSD: sbdspvar.h,v 1.13 1996/04/29 20:28:50 christos Exp $ */
+/* $OpenBSD: sbdspvar.h,v 1.8 1998/04/26 21:03:01 provos Exp $ */
+/* $NetBSD: sbdspvar.h,v 1.33 1997/10/19 07:42:44 augustss Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -35,29 +35,43 @@
*
*/
-#define SB_MIC_PORT 0
-#define SB_SPEAKER 1
-#define SB_INPUT_CLASS 2
-#define SB_OUTPUT_CLASS 3
-#define SB_LINE_IN_PORT 4
-#define SB_DAC_PORT 5
-#define SB_FM_PORT 6
-#define SB_CD_PORT 7
-#define SB_MASTER_VOL 8
-#define SB_TREBLE 9
-#define SB_BASS 10
-#define SB_NDEVS 11 /* XXX include classes above for
- contiguous number space on
- original SB */
+#define SB_MASTER_VOL 0
+#define SB_MIDI_VOL 1
+#define SB_CD_VOL 2
+#define SB_VOICE_VOL 3
+#define SB_OUTPUT_CLASS 4
-/*#define SB_OUTPUT_MODE 9
-#define SB_SPKR_MONO 0
-#define SB_SPKR_STEREO 1*/
+#define SB_MIC_VOL 5
+#define SB_LINE_IN_VOL 6
+#define SB_RECORD_SOURCE 7
+#define SB_TREBLE 8
+#define SB_BASS 9
+#define SB_RECORD_CLASS 10
+#define SB_INPUT_CLASS 11
-#define SB_RECORD_SOURCE 11
+#define SB_PCSPEAKER 12
+#define SB_INPUT_GAIN 13
+#define SB_OUTPUT_GAIN 14
+#define SB_AGC 15
+#define SB_EQUALIZATION_CLASS 16
-#define SB_RECORD_CLASS 12
+#define SB_CD_IN_MUTE 17
+#define SB_MIC_IN_MUTE 18
+#define SB_LINE_IN_MUTE 19
+#define SB_MIDI_IN_MUTE 20
+#define SB_CD_SWAP 21
+#define SB_MIC_SWAP 22
+#define SB_LINE_SWAP 23
+#define SB_MIDI_SWAP 24
+
+#define SB_CD_OUT_MUTE 25
+#define SB_MIC_OUT_MUTE 26
+#define SB_LINE_OUT_MUTE 27
+
+#define SB_NDEVS 28
+
+#define SB_IS_IN_MUTE(x) ((x) < SB_CD_SWAP)
/*
* Software state, per SoundBlaster card.
@@ -86,70 +100,75 @@ struct sbdsp_softc {
int sc_drq8; /* DMA (8-bit) */
int sc_drq16; /* DMA (16-bit) */
+ struct device *sc_isa; /* pointer to ISA parent */
+
u_short sc_open; /* reference count of open calls */
+ int sc_openflags; /* flags used on open */
+ u_char sc_fullduplex; /* can do full duplex */
- u_int gain[SB_NDEVS]; /* kept in SB levels: right/left each
- in a nibble */
+ u_char gain[SB_NDEVS][2]; /* kept in input levels */
+#define SB_LEFT 0
+#define SB_RIGHT 1
+#define SB_LR 0
- u_int out_port; /* output port */
- u_int in_port; /* input port */
+ u_int in_mask; /* input ports */
+ u_int in_port; /* XXX needed for MI interface */
u_int in_filter; /* one of SB_TREBLE_EQ, SB_BASS_EQ, 0 */
u_int spkr_state; /* non-null is on */
- int sc_irate, sc_itc; /* Sample rate for input */
- int sc_orate, sc_otc; /* ...and output */
-
- int sc_imode;
- int sc_omode;
-#define SB_ADAC_LS 0
-#define SB_ADAC_HS 1
+ struct sbdsp_state {
+ u_int rate; /* Sample rate */
+ u_char tc; /* Time constant */
+ struct sbmode *modep;
+ u_char bmode;
+ int dmachan; /* DMA channel */
+ u_char run;
+#define SB_NOTRUNNING 0 /* Not running, not initialized */
+#define SB_DMARUNNING 1 /* DMA has been initialized */
+#define SB_PCMRUNNING 2 /* DMA&PCM running (looping mode) */
+#define SB_RUNNING 3 /* non-looping mode */
+ } sc_i, sc_o; /* Input and output state */
u_long sc_interrupts; /* number of interrupts taken */
- void (*sc_intr)(void*); /* dma completion intr handler */
+ void (*sc_intr8)(void*); /* dma completion intr handler */
+ void *sc_arg8; /* arg for sc_intr8() */
+ void (*sc_intr16)(void*); /* dma completion intr handler */
+ void *sc_arg16; /* arg for sc_intr16() */
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 dmachan; /* active DMA channel */
- int sc_last_hs_size; /* last HS dma size */
- u_int sc_encoding; /* ulaw/linear -- keep track */
- u_int sc_precision; /* size of samples */
- int sc_channels; /* # of channels */
-
- int sc_dmadir; /* DMA direction */
-#define SB_DMA_NONE 0
-#define SB_DMA_IN 1
-#define SB_DMA_OUT 2
+ u_int sc_mixer_model;
+#define SBM_NONE 0
+#define SBM_CT1335 1
+#define SBM_CT1345 2
+#define SBM_CT1XX5 3
+#define SBM_CT1745 4
+#define ISSBM1745(x) ((x)->sc_mixer_model >= SBM_CT1XX5)
u_int sc_model; /* DSP model */
+#define SB_UNK -1
+#define SB_1 0 /* original SB */
+#define SB_20 1 /* SB 2 */
+#define SB_2x 2 /* SB 2, new version */
+#define SB_PRO 3 /* SB Pro */
+#define SB_JAZZ 4 /* Jazz 16 */
+#define SB_16 5 /* SB 16 */
+#define SB_32 6 /* SB AWE 32 */
+#define SB_64 7 /* SB AWE 64 */
+
+#define SB_NAMES { "SB_1", "SB_2.0", "SB_2.x", "SB_Pro", "Jazz_16", "SB_16", "SB_AWE_32", "SB_AWE_64" }
+
+ u_int sc_version; /* DSP version */
#define SBVER_MAJOR(v) (((v)>>8) & 0xff)
#define SBVER_MINOR(v) ((v)&0xff)
-
-#define MODEL_JAZZ16 0x80000000
};
-#define ISSB2CLASS(sc) \
- (SBVER_MAJOR((sc)->sc_model) >= 2)
-
-#define ISSBPROCLASS(sc) \
- (SBVER_MAJOR((sc)->sc_model) > 2)
-
-#define ISSBPRO(sc) \
- (SBVER_MAJOR((sc)->sc_model) == 3)
-
-#define ISSB16CLASS(sc) \
- (SBVER_MAJOR((sc)->sc_model) > 3)
-
-#define ISJAZZ16(sc) \
- ((sc)->sc_model & MODEL_JAZZ16)
-
+#define ISSBPRO(sc) ((sc)->sc_model == SB_PRO || (sc)->sc_model == SB_JAZZ)
+#define ISSBPROCLASS(sc) ((sc)->sc_model >= SB_PRO)
+#define ISSB16CLASS(sc) ((sc)->sc_model >= SB_16)
#ifdef _KERNEL
-int sbdsp_open __P((struct sbdsp_softc *, dev_t, int));
+int sbdsp_open __P((void *, int));
void sbdsp_close __P((void *));
int sbdsp_probe __P((struct sbdsp_softc *));
@@ -163,35 +182,20 @@ 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_format __P((void *, u_int, u_int));
-int sbdsp_get_encoding __P((void *));
-int sbdsp_get_precision __P((void *));
-int sbdsp_set_channels __P((void *, int));
-int sbdsp_get_channels __P((void *));
-int sbdsp_set_ifilter __P((void *, int));
-int sbdsp_get_ifilter __P((void *));
+int sbdsp_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
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_commit __P((void *));
+int sbdsp_dma_init_input __P((void *, void *, int));
+int sbdsp_dma_init_output __P((void *, void *, int));
int sbdsp_dma_output __P((void *, void *, int, void (*)(void *), void*));
int sbdsp_dma_input __P((void *, void *, int, void (*)(void *), void*));
int sbdsp_haltdma __P((void *));
-int sbdsp_contdma __P((void *));
void sbdsp_compress __P((int, u_char *, int));
void sbdsp_expand __P((int, u_char *, int));
@@ -204,10 +208,8 @@ int sbdsp_wdsp __P((struct sbdsp_softc *, int v));
int sbdsp_rdsp __P((struct sbdsp_softc *));
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));
@@ -216,4 +218,11 @@ 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 *));
+void *sb_malloc __P((void *, unsigned long, int, int));
+void sb_free __P((void *, void *, int));
+unsigned long sb_round __P((void *, unsigned long));
+int sb_mappage __P((void *, void *, int, int));
+
+int sbdsp_get_props __P((void *));
+
#endif
diff --git a/sys/dev/isa/sbreg.h b/sys/dev/isa/sbreg.h
index b8bd566accf..e4c8bc3d9e6 100644
--- a/sys/dev/isa/sbreg.h
+++ b/sys/dev/isa/sbreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sbreg.h,v 1.3 1997/07/10 23:06:39 provos Exp $ */
-/* $NetBSD: sbreg.h,v 1.16 1996/03/16 04:00:14 jtk Exp $ */
+/* $OpenBSD: sbreg.h,v 1.4 1998/04/26 21:03:02 provos Exp $ */
+/* $NetBSD: sbreg.h,v 1.24 1997/08/24 23:24:51 augustss Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -71,21 +71,19 @@
#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_MIX_RESET 0x00 /* mixer reset port, value */
+#define SBP_1335_MASTER_VOL 0x02
+#define SBP_1335_MIDI_VOL 0x06
+#define SBP_1335_CD_VOL 0x08
+#define SBP_1335_VOICE_VOL 0x0A
+
+#define SBP_VOICE_VOL 0x04
+#define SBP_MIC_VOL 0x0A /* warning: only one channel of volume... */
#define SBP_MASTER_VOL 0x22
-#define SBP_FM_VOL 0x26
+#define SBP_MIDI_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_IRQ_STATUS 0x82 /* Pending IRQ status (SB16-) */
#define SBP_RECORD_SOURCE 0x0C
#define SBP_STEREO 0x0E
@@ -105,17 +103,60 @@
#define SBP_FROM_MIC 0x00
#define SBP_FROM_CD 0x02
#define SBP_FROM_LINE 0x06
-#define sbdsp_mono_vol(left) (((left) << 4) | (left))
-#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_SET_IRQ 0x80 /* Soft-configured irq (SB16-) */
+#define SBP_SET_DRQ 0x81 /* Soft-configured drq (SB16-) */
+#define SBP_IRQ_STATUS 0x82 /* Pending IRQ status (SB16-) */
+#define SBP_IRQ_MPU401 0x04
+#define SBP_IRQ_DMA16 0x02
+#define SBP_IRQ_DMA8 0x01
+
+#define SB16P_MASTER_L 0x30
+#define SB16P_VOICE_L 0x32
+#define SB16P_MIDI_L 0x34
+#define SB16P_CD_L 0x36
+#define SB16P_LINE_L 0x38
+#define SB16P_MIC_L 0x3a
+#define SB16P_PCSPEAKER 0x3b
+#define SB16P_OSWITCH 0x3c
+#define SB16P_ISWITCH_L 0x3d
+#define SB16P_ISWITCH_R 0x3e
+#define SB16P_SW_MIC 0x01
+#define SB16P_SW_CD_R 0x02
+#define SB16P_SW_CD_L 0x04
+#define SB16P_SW_CD (SB16P_SW_CD_L|SB16P_SW_CD_R)
+#define SB16P_SW_LINE_R 0x08
+#define SB16P_SW_LINE_L 0x10
+#define SB16P_SW_LINE (SB16P_SW_LINE_L|SB16P_SW_LINE_R)
+#define SB16P_SW_MIDI_R 0x20
+#define SB16P_SW_MIDI_L 0x40
+#define SB16P_SW_MIDI (SB16P_SW_MIDI_L|SB16P_SW_MIDI_R)
+#define SB16P_INPUT_GAIN_L 0x3f
+#define SB16P_OUTPUT_GAIN_L 0x41
+#define SB16P_TREBLE_L 0x44
+#define SB16P_BASS_L 0x46
+#define SB16P_L_TO_R(l) ((l)+1)
+
+#define SB16P_AGC 0x43
+
+#define SBP_RECORD_SOURCE_L 0x3d
+#define SBP_RECORD_SOURCE_R 0x3e
+#define SBP_MIDI_SRC_R 0x20
+#define SBP_LINE_SRC_R 0x08
+#define SBP_CD_SRC_R 0x02
+#define SBP_MIC_SRC 0x01
+#define SB_SRC_R_TO_L(x) ((x) << 1)
+
+#define SB_STEREO_GAIN(left, right) ((left) | ((right) >> 4))
+#define SB_MIC_GAIN(v) ((v) >> 5)
+
+#define SB_ADJUST_MIC_GAIN(sc, x) sbdsp_adjust((x), ISSB16CLASS(sc) ? 0xf8 : 0xc0)
+#define SB_ADJUST_GAIN(sc, x) sbdsp_adjust((x), ISSB16CLASS(sc) ? 0xf8 : 0xe0)
+#define SB_ADJUST_2_GAIN(sc, x) sbdsp_adjust((x), 0xc0)
+
+#define SB_1335_GAIN(x) ((x) >> 4)
+#define SB_1335_MASTER_GAIN(x) ((x) >> 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 */
@@ -179,6 +220,10 @@
#define SB_SPKR_ON 0xff
#define SB_DSP_VERSION 0xe1 /* get version number */
+#define SB_BMODE_UNSIGNED 0x00
+#define SB_BMODE_SIGNED 0x10
+#define SB_BMODE_STEREO 0x20
+
/* Some of these come from linux driver (It serves as convenient unencumbered
documentation) */
#define JAZZ16_READ_VER 0xFA /* 0x12 means ProSonic/Jazz16? */
diff --git a/sys/dev/isa/wss.c b/sys/dev/isa/wss.c
index 930516b0ec1..e14338bdd44 100644
--- a/sys/dev/isa/wss.c
+++ b/sys/dev/isa/wss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wss.c,v 1.14 1997/07/10 23:06:40 provos Exp $ */
-/* $NetBSD: wss.c,v 1.13 1996/05/12 23:54:16 mycroft Exp $ */
+/* $OpenBSD: wss.c,v 1.15 1998/04/26 21:03:03 provos Exp $ */
+/* $NetBSD: wss.c,v 1.42 1998/01/19 22:18:23 augustss Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -47,6 +47,7 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
@@ -58,26 +59,8 @@
#include <dev/ic/ad1848reg.h>
#include <dev/isa/ad1848var.h>
#include <dev/isa/wssreg.h>
-#include <dev/isa/opti.h>
-
-/*
- * 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
+#include <dev/isa/wssvar.h>
+#include <dev/isa/madreg.h>
#ifdef AUDIO_DEBUG
#define DPRINTF(x) if (wssdebug) printf x
@@ -86,191 +69,92 @@ int wssdebug = 0;
#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_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 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 *));
static int wss_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
static int wss_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
+
/*
* Define our interface to the higher level audio driver.
*/
struct audio_hw_if wss_hw_if = {
- wssopen,
+ ad1848_open,
ad1848_close,
NULL,
- ad1848_set_in_sr,
- ad1848_get_in_sr,
- ad1848_set_out_sr,
- ad1848_get_out_sr,
ad1848_query_encoding,
- ad1848_set_format,
- ad1848_get_encoding,
- ad1848_get_precision,
- ad1848_set_channels,
- ad1848_get_channels,
+ ad1848_set_params,
ad1848_round_blocksize,
- wss_set_out_port,
- wss_get_out_port,
- wss_set_in_port,
- wss_get_in_port,
ad1848_commit_settings,
- NULL,
- NULL,
+ ad1848_dma_init_output,
+ ad1848_dma_init_input,
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,
+ NULL,
wss_mixer_set_port,
wss_mixer_get_port,
wss_query_devinfo,
- 0, /* not full-duplex */
- 0
+ ad1848_malloc,
+ ad1848_free,
+ ad1848_round,
+ ad1848_mappage,
+ ad1848_get_props,
};
-int wssprobe __P((struct device *, void *, void *));
-void wssattach __P((struct device *, struct device *, void *));
-
-struct cfattach wss_ca = {
- sizeof(struct wss_softc), wssprobe, wssattach
-};
-
-struct cfdriver wss_cd = {
- NULL, "wss", DV_DULL
-};
-
-/*
- * Probe for the Microsoft Sound System hardware.
- */
-int
-wssprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- register struct wss_softc *sc = match;
- register struct isa_attach_args *ia = aux;
- register int 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};
-
- if (!WSS_BASE_VALID(ia->ia_iobase)) {
- DPRINTF(("wss: configured iobase %x invalid\n", ia->ia_iobase));
- return 0;
- }
-
- if( !opti_snd_setup( OPTI_WSS, iobase, ia->ia_irq, ia->ia_drq ) )
- DPRINTF(("ad_detect_A: could not setup OPTi chipset.\n"));
-
- sc->sc_ad1848.sc_iobase = iobase + WSS_CODEC;
-
- /* Is there an ad1848 chip at the WSS iobase ? */
- if (ad1848_probe(&sc->sc_ad1848) == 0) {
-#if 0
- DPRINTF(("ad_detect_A: no ad1848 found.\n"));
-#endif
- return 0;
- }
-
- ia->ia_iosize = WSS_NPORT;
-
- /* Setup WSS interrupt and DMA */
- if (!WSS_DRQ_VALID(ia->ia_drq)) {
- DPRINTF(("wss: configured dma chan %d invalid\n", ia->ia_drq));
- return 0;
- }
- sc->wss_drq = ia->ia_drq;
-
-#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\n");
- return 0;
- }
- }
- else
-#endif
- if (!WSS_IRQ_VALID(ia->ia_irq)) {
- DPRINTF(("wss: configured interrupt %d invalid\n", ia->ia_irq));
- return 0;
- }
-
- sc->wss_irq = ia->ia_irq;
-
- outb(iobase+WSS_CONFIG,
- (interrupt_bits[ia->ia_irq] | dma_bits[ia->ia_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;
+wssattach(sc)
+ struct wss_softc *sc;
{
- register struct wss_softc *sc = (struct wss_softc *)self;
- struct isa_attach_args *ia = (struct isa_attach_args *)aux;
- register int iobase = ia->ia_iobase;
- int err;
+ int version;
- sc->sc_ad1848.sc_recdrq = ia->ia_drq;
+ madattach(sc);
-#ifdef NEWCONFIG
- isa_establish(&sc->sc_id, &sc->sc_dev);
-#endif
- sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
+ sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->wss_irq, IST_EDGE, IPL_AUDIO,
ad1848_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
ad1848_attach(&sc->sc_ad1848);
- printf(" (vers %d)", inb(iobase+WSS_STATUS) & WSS_VERSMASK);
+ version = bus_space_read_1(sc->sc_iot, sc->sc_ioh, WSS_STATUS) & WSS_VERSMASK;
+ printf(" (vers %d)", version);
+ switch(sc->mad_chip_type) {
+ case MAD_82C928:
+ printf(", 82C928");
+ break;
+ case MAD_OTI601D:
+ printf(", OTI-601D");
+ break;
+ case MAD_82C929:
+ printf(", 82C929");
+ break;
+ case MAD_82C931:
+ printf(", 82C931");
+ break;
+ default:
+ break;
+ }
printf("\n");
sc->sc_ad1848.parent = sc;
- if ((err = audio_hardware_attach(&wss_hw_if, &sc->sc_ad1848)) != 0)
- printf("wss: could not attach to audio pseudo-device driver (%d)\n", err);
+ audio_attach_mi(&wss_hw_if, 0, &sc->sc_ad1848, &sc->sc_dev);
}
static int
@@ -308,24 +192,6 @@ wss_from_vol(cp, vol)
}
int
-wssopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct wss_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= wss_cd.cd_ndevs)
- return ENODEV;
-
- sc = wss_cd.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;
@@ -335,90 +201,12 @@ wss_getdev(addr, retp)
}
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(WSS_DAC_LVL);
-}
-
-int
-wss_set_in_port(addr, port)
- void *addr;
- int port;
-{
- register struct ad1848_softc *ac = addr;
-
- 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;
- 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_softc *ac = addr;
+ struct wss_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -503,8 +291,8 @@ 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_softc *ac = addr;
+ struct wss_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -590,7 +378,7 @@ wss_mixer_get_port(addr, cp)
int
wss_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
DPRINTF(("wss_query_devinfo: index=%d\n", dip->index));
@@ -648,21 +436,21 @@ wss_query_devinfo(addr, dip)
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = WSS_INPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ 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);
+ strcpy(dip->label.name, AudioCmonitor);
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);
+ strcpy(dip->label.name, AudioCrecord);
break;
case WSS_MIC_IN_MUTE:
@@ -716,3 +504,136 @@ wss_query_devinfo(addr, dip)
return 0;
}
+
+
+/*
+ * 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.
+ *
+ */
+/*
+ * Initialization code for OPTi MAD16 compatible audio chips. Including
+ *
+ * OPTi 82C928 MAD16 (replaced by C929)
+ * OAK OTI-601D Mozart
+ * OPTi 82C929 MAD16 Pro
+ *
+ */
+
+u_int
+mad_read(sc, port)
+ struct wss_softc *sc;
+ int port;
+{
+ u_int tmp;
+ int pwd;
+ int s;
+
+ switch (sc->mad_chip_type) { /* Output password */
+ case MAD_82C928:
+ case MAD_OTI601D:
+ pwd = M_PASSWD_928;
+ break;
+ case MAD_82C929:
+ pwd = M_PASSWD_929;
+ break;
+ case MAD_82C931:
+ pwd = M_PASSWD_931;
+ break;
+ default:
+ panic("mad_read: Bad chip type=%d\n", sc->mad_chip_type);
+ }
+ s = splaudio(); /* don't want an interrupt between outb&inb */
+ bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
+ tmp = bus_space_read_1(sc->sc_iot, sc->mad_ioh, port);
+ splx(s);
+ return tmp;
+}
+
+void
+mad_write(sc, port, value)
+ struct wss_softc *sc;
+ int port;
+ int value;
+{
+ int pwd;
+ int s;
+
+ switch (sc->mad_chip_type) { /* Output password */
+ case MAD_82C928:
+ case MAD_OTI601D:
+ pwd = M_PASSWD_928;
+ break;
+ case MAD_82C929:
+ pwd = M_PASSWD_929;
+ break;
+ case MAD_82C931:
+ pwd = M_PASSWD_931;
+ break;
+ default:
+ panic("mad_write: Bad chip type=%d\n", sc->mad_chip_type);
+ }
+ s = splaudio();
+ bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
+ bus_space_write_1(sc->sc_iot, sc->mad_ioh, port, value & 0xff);
+ splx(s);
+}
+
+void
+madattach(sc)
+ struct wss_softc *sc;
+{
+ unsigned char cs4231_mode;
+ int joy;
+
+ if (sc->mad_chip_type == MAD_NONE)
+ return;
+
+ /* Do we want the joystick disabled? */
+ joy = sc->sc_dev.dv_cfdata->cf_flags & 2 ? MC1_JOYDISABLE : 0;
+
+ /* enable WSS emulation at the I/O port */
+ mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(sc->mad_ioindex) | joy);
+ mad_write(sc, MC2_PORT, 0x03); /* ? */
+ mad_write(sc, MC3_PORT, 0xf0); /* Disable SB */
+
+ cs4231_mode =
+ strncmp(sc->sc_ad1848.chip_name, "CS4248", 6) == 0 ||
+ strncmp(sc->sc_ad1848.chip_name, "CS4231", 6) == 0 ? 0x02 : 0;
+
+ if (sc->mad_chip_type == MAD_82C929) {
+ mad_write(sc, MC4_PORT, 0x92);
+ mad_write(sc, MC5_PORT, 0xA5 | cs4231_mode);
+ mad_write(sc, MC6_PORT, 0x03); /* Disable MPU401 */
+ } else {
+ mad_write(sc, MC4_PORT, 0x02);
+ mad_write(sc, MC5_PORT, 0x30 | cs4231_mode);
+ }
+
+#ifdef AUDIO_DEBUG
+ if (wssdebug) {
+ int i;
+ for (i = MC1_PORT; i <= MC7_PORT; i++)
+ DPRINTF(("port %03x after init = %02x\n", i, mad_read(sc, i)));
+ }
+#endif
+}
diff --git a/sys/dev/isa/wss_isa.c b/sys/dev/isa/wss_isa.c
new file mode 100644
index 00000000000..61df0bc35f1
--- /dev/null
+++ b/sys/dev/isa/wss_isa.c
@@ -0,0 +1,376 @@
+/* $OpenBSD: wss_isa.c,v 1.1 1998/04/26 21:02:38 provos Exp $ */
+/* $NetBSD: wss_isa.c,v 1.1 1998/01/19 22:18:24 augustss Exp $ */
+
+/*
+ * Copyright (c) 1994 John Brezak
+ * Copyright (c) 1991-1993 Regents of the University of California.
+ * All rights reserved.
+ *
+ * MAD support:
+ * Copyright (c) 1996 Lennart Augustsson
+ * Based on code which is
+ * Copyright (c) 1994 Hannu Savolainen
+ *
+ * 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.
+ *
+ */
+#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 <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/pio.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+
+#include <dev/ic/ad1848reg.h>
+#include <dev/isa/ad1848var.h>
+#include <dev/isa/wssreg.h>
+#include <dev/isa/wssvar.h>
+#include <dev/isa/madreg.h>
+
+#ifdef AUDIO_DEBUG
+#define DPRINTF(x) if (wssdebug) printf x
+extern int wssdebug;
+#else
+#define DPRINTF(x)
+#endif
+
+static int wssfind __P((struct device *, struct wss_softc *, struct isa_attach_args *));
+
+static void madprobe __P((struct wss_softc *, int));
+static void madunmap __P((struct wss_softc *));
+static int detect_mad16 __P((struct wss_softc *, int));
+
+int wss_isa_probe __P((struct device *, void *, void *));
+void wss_isa_attach __P((struct device *, struct device *, void *));
+
+struct cfattach wss_isa_ca = {
+ sizeof(struct wss_softc), wss_isa_probe, wss_isa_attach
+};
+
+struct cfdriver wss_cd = {
+ NULL, "wss", DV_DULL
+};
+
+/*
+ * Probe for the Microsoft Sound System hardware.
+ */
+int
+wss_isa_probe(parent, match, aux)
+ struct device *parent;
+#define __BROKEN_INDIRECT_CONFIG
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ struct wss_softc probesc, *sc = &probesc;
+
+ bzero(sc, sizeof *sc);
+#ifdef __BROKEN_INDIRECT_CONFIG
+ sc->sc_dev.dv_cfdata = ((struct device *)match)->dv_cfdata;
+#else
+ sc->sc_dev.dv_cfdata = match;
+#endif
+ if (wssfind(parent, sc, aux)) {
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
+ ad1848_unmap(&sc->sc_ad1848);
+ madunmap(sc);
+ return 1;
+ } else
+ /* Everything is already unmapped */
+ return 0;
+}
+
+static int
+wssfind(parent, sc, ia)
+ struct device *parent;
+ struct wss_softc *sc;
+ struct isa_attach_args *ia;
+{
+ 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};
+
+ sc->sc_iot = ia->ia_iot;
+ if (sc->sc_dev.dv_cfdata->cf_flags & 1)
+ madprobe(sc, ia->ia_iobase);
+ else
+ sc->mad_chip_type = MAD_NONE;
+
+ if (!WSS_BASE_VALID(ia->ia_iobase)) {
+ DPRINTF(("wss: configured iobase %x invalid\n", ia->ia_iobase));
+ goto bad1;
+ }
+
+ /* Map the ports upto the AD1848 port */
+ if (bus_space_map(sc->sc_iot, ia->ia_iobase, WSS_CODEC, 0, &sc->sc_ioh))
+ goto bad1;
+
+ sc->sc_ad1848.sc_iot = sc->sc_iot;
+
+ /* Is there an ad1848 chip at (WSS iobase + WSS_CODEC)? */
+ if (ad1848_mapprobe(&sc->sc_ad1848, ia->ia_iobase + WSS_CODEC) == 0)
+ goto bad;
+
+ ia->ia_iosize = WSS_NPORT;
+
+ /* Setup WSS interrupt and DMA */
+ if (!WSS_DRQ_VALID(ia->ia_drq)) {
+ DPRINTF(("wss: configured dma chan %d invalid\n", ia->ia_drq));
+ goto bad;
+ }
+ sc->wss_drq = ia->ia_drq;
+
+ if (sc->wss_drq != DRQUNK && !isa_drq_isfree(parent, sc->wss_drq))
+ goto bad;
+
+ if (!WSS_IRQ_VALID(ia->ia_irq)) {
+ DPRINTF(("wss: configured interrupt %d invalid\n", ia->ia_irq));
+ goto bad;
+ }
+
+ sc->wss_irq = ia->ia_irq;
+
+ if (sc->sc_ad1848.mode <= 1)
+ ia->ia_drq2 = DRQUNK;
+ sc->wss_recdrq =
+ sc->sc_ad1848.mode > 1 && ia->ia_drq2 != DRQUNK ?
+ ia->ia_drq2 : ia->ia_drq;
+ if (sc->wss_recdrq != sc->wss_drq && !isa_drq_isfree(parent, sc->wss_recdrq))
+ goto bad;
+
+ /* XXX recdrq */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, WSS_CONFIG,
+ (interrupt_bits[ia->ia_irq] | dma_bits[ia->ia_drq]));
+
+ return 1;
+
+bad:
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
+bad1:
+ madunmap(sc);
+ return 0;
+}
+
+/*
+ * Attach hardware to driver, attach hardware driver to audio
+ * pseudo-device driver .
+ */
+void
+wss_isa_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct wss_softc *sc = (struct wss_softc *)self;
+ struct isa_attach_args *ia = (struct isa_attach_args *)aux;
+
+ if (!wssfind(parent, sc, ia)) {
+ printf("%s: wssfind failed\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ sc->sc_ic = ia->ia_ic;
+ sc->sc_ad1848.sc_isa = parent;
+
+ wssattach(sc);
+}
+
+/*
+ * 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.
+ *
+ */
+
+/*
+ * Initialization code for OPTi MAD16 compatible audio chips. Including
+ *
+ * OPTi 82C928 MAD16 (replaced by C929)
+ * OAK OTI-601D Mozart
+ * OPTi 82C929 MAD16 Pro
+ * OPTi 82C931
+ */
+
+static int
+detect_mad16(sc, chip_type)
+ struct wss_softc *sc;
+ int chip_type;
+{
+ unsigned char tmp, tmp2;
+
+ sc->mad_chip_type = chip_type;
+ /*
+ * Check that reading a register doesn't return bus float (0xff)
+ * when the card is accessed using password. This may fail in case
+ * the card is in low power mode. Normally at least the power saving mode
+ * bit should be 0.
+ */
+ if ((tmp = mad_read(sc, MC1_PORT)) == 0xff) {
+ DPRINTF(("MC1_PORT returned 0xff\n"));
+ return 0;
+ }
+
+ /*
+ * Now check that the gate is closed on first I/O after writing
+ * the password. (This is how a MAD16 compatible card works).
+ */
+ if ((tmp2 = bus_space_read_1(sc->sc_iot, sc->mad_ioh, MC1_PORT)) == tmp) {
+ DPRINTF(("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
+ return 0;
+ }
+
+ mad_write(sc, MC1_PORT, tmp ^ 0x80); /* Toggle a bit */
+
+ /* Compare the bit */
+ if ((tmp2 = mad_read(sc, MC1_PORT)) != (tmp ^ 0x80)) {
+ mad_write(sc, MC1_PORT, tmp); /* Restore */
+ DPRINTF(("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
+ return 0;
+ }
+
+ mad_write(sc, MC1_PORT, tmp); /* Restore */
+ return 1;
+}
+
+static void
+madprobe(sc, iobase)
+ struct wss_softc *sc;
+ int iobase;
+{
+ static int valid_ports[M_WSS_NPORTS] =
+ { M_WSS_PORT0, M_WSS_PORT1, M_WSS_PORT2, M_WSS_PORT3 };
+ int i;
+
+ /* Allocate bus space that the MAD chip wants */
+ if (bus_space_map(sc->sc_iot, MAD_BASE, MAD_NPORT, 0, &sc->mad_ioh))
+ goto bad0;
+ if (bus_space_map(sc->sc_iot, MAD_REG1, MAD_LEN1, 0, &sc->mad_ioh1))
+ goto bad1;
+ if (bus_space_map(sc->sc_iot, MAD_REG2, MAD_LEN2, 0, &sc->mad_ioh2))
+ goto bad2;
+ if (bus_space_map(sc->sc_iot, MAD_REG3, MAD_LEN3, 0, &sc->mad_ioh3))
+ goto bad3;
+
+ DPRINTF(("mad: Detect using password = 0xE2\n"));
+ if (!detect_mad16(sc, MAD_82C928)) {
+ /* No luck. Try different model */
+ DPRINTF(("mad: Detect using password = 0xE3\n"));
+ if (!detect_mad16(sc, MAD_82C929))
+ goto bad;
+ sc->mad_chip_type = MAD_82C929;
+ DPRINTF(("mad: 82C929 detected\n"));
+ } else {
+ sc->mad_chip_type = MAD_82C928;
+ if ((mad_read(sc, MC3_PORT) & 0x03) == 0x03) {
+ DPRINTF(("mad: Mozart detected\n"));
+ sc->mad_chip_type = MAD_OTI601D;
+ } else {
+ DPRINTF(("mad: 82C928 detected?\n"));
+ sc->mad_chip_type = MAD_82C928;
+ }
+ }
+
+#ifdef AUDIO_DEBUG
+ if (wssdebug)
+ for (i = MC1_PORT; i <= MC7_PORT; i++)
+ printf("mad: port %03x = %02x\n", i, mad_read(sc, i));
+#endif
+
+ /* Set the WSS address. */
+ for (i = 0; i < M_WSS_NPORTS; i++)
+ if (valid_ports[i] == iobase)
+ break;
+ if (i >= M_WSS_NPORTS) { /* Not a valid port */
+ printf("mad: Bad WSS base address 0x%x\n", iobase);
+ goto bad;
+ }
+ sc->mad_ioindex = i;
+ /* enable WSS emulation at the I/O port, no joystick */
+ mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(i) | MC1_JOYDISABLE);
+ mad_write(sc, MC2_PORT, 0x03); /* ? */
+ mad_write(sc, MC3_PORT, 0xf0); /* Disable SB */
+ return;
+
+bad:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
+bad3:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
+bad2:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
+bad1:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
+bad0:
+ sc->mad_chip_type = MAD_NONE;
+}
+
+static void
+madunmap(sc)
+ struct wss_softc *sc;
+{
+ if (sc->mad_chip_type == MAD_NONE)
+ return;
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
+}
diff --git a/sys/dev/isa/wssvar.h b/sys/dev/isa/wssvar.h
new file mode 100644
index 00000000000..bd290f89476
--- /dev/null
+++ b/sys/dev/isa/wssvar.h
@@ -0,0 +1,83 @@
+/* $OpenBSD: wssvar.h,v 1.1 1998/04/26 21:02:38 provos Exp $ */
+/* $NetBSD: wssvar.h,v 1.1 1998/01/19 22:18:25 augustss 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.
+ *
+ */
+
+/*
+ * 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
+
+struct wss_softc {
+ struct device sc_dev; /* base device */
+ struct isadev sc_id; /* ISA device */
+ void *sc_ih; /* interrupt vectoring */
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_ioh; /* handle */
+ isa_chipset_tag_t sc_ic;
+
+ struct ad1848_softc sc_ad1848;
+#define wss_irq sc_ad1848.sc_irq
+#define wss_drq sc_ad1848.sc_drq
+#define wss_recdrq sc_ad1848.sc_recdrq
+
+ int mic_mute, cd_mute, dac_mute;
+
+ int mad_chip_type; /* chip type if MAD emulation of WSS */
+ int mad_ioindex;
+ bus_space_handle_t mad_ioh; /* MAD handle */
+ bus_space_handle_t mad_ioh1, mad_ioh2, mad_ioh3;
+};
+
+void wssattach __P((struct wss_softc *));
+
+u_int mad_read __P((struct wss_softc *, int));
+void mad_write __P((struct wss_softc *, int, int));
+void madattach __P((struct wss_softc *));