summaryrefslogtreecommitdiff
path: root/sys/dev/isa/sbdsp.c
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1999-01-02 00:02:57 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1999-01-02 00:02:57 +0000
commit16eef665101a8c1334032296ea7d1584ff9c7e57 (patch)
tree5cc9b881cb0bdd13a85c95e2cbd124b47ddc4645 /sys/dev/isa/sbdsp.c
parent890d46b55a21bec77e2f60dbf22d16199ccdbaa7 (diff)
Midi & sequencer support from NetBSD, mostly by Lennart Augustsson
Diffstat (limited to 'sys/dev/isa/sbdsp.c')
-rw-r--r--sys/dev/isa/sbdsp.c641
1 files changed, 322 insertions, 319 deletions
diff --git a/sys/dev/isa/sbdsp.c b/sys/dev/isa/sbdsp.c
index 89cda5647d9..e3c6de44cc4 100644
--- a/sys/dev/isa/sbdsp.c
+++ b/sys/dev/isa/sbdsp.c
@@ -1,5 +1,4 @@
-/* $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 $ */
+/* $OpenBSD: sbdsp.c,v 1.13 1999/01/02 00:02:47 niklas Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -45,6 +44,8 @@
* Linux drivers.
*/
+#include "midi.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
@@ -61,6 +62,7 @@
#include <sys/audioio.h>
#include <dev/audio_if.h>
+#include <dev/midi_if.h>
#include <dev/mulaw.h>
#include <dev/auconv.h>
@@ -70,11 +72,14 @@
#include <dev/isa/sbreg.h>
#include <dev/isa/sbdspvar.h>
+
#ifdef AUDIO_DEBUG
#define DPRINTF(x) if (sbdspdebug) printf x
+#define DPRINTFN(n,x) if (sbdspdebug >= (n)) printf x
int sbdspdebug = 0;
#else
#define DPRINTF(x)
+#define DPRINTFN(n,x)
#endif
#ifndef SBDSP_NPOLL
@@ -180,12 +185,14 @@ 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));
+int sbdsp_block_output __P((void *));
+int sbdsp_block_input __P((void *));
static int sbdsp_adjust __P((int, int));
+int sbdsp_midi_intr __P((void *));
+
#ifdef AUDIO_DEBUG
-void sb_printsc __P((struct sbdsp_softc *));
+void sb_printsc __P((struct sbdsp_softc *));
void
sb_printsc(sc)
@@ -524,13 +531,33 @@ sbdsp_set_params(addr, setmode, usemode, play, rec)
struct audio_params *p;
int mode;
+ if (sc->sc_open == SB_OPEN_MIDI)
+ return EBUSY;
+
model = sc->sc_model;
if (model > SB_16)
model = SB_16; /* later models work like SB16 */
+ /*
+ * Prior to the SB16, we have only one clock, so make the sample
+ * rates match.
+ */
+ if (!ISSB16CLASS(sc) &&
+ play->sample_rate != rec->sample_rate &&
+ usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
+ if (setmode == AUMODE_PLAY) {
+ rec->sample_rate = play->sample_rate;
+ setmode |= AUMODE_RECORD;
+ } else if (setmode == AUMODE_RECORD) {
+ play->sample_rate = rec->sample_rate;
+ setmode |= AUMODE_PLAY;
+ } else
+ return (EINVAL);
+ }
+
/* Set first record info, then play info */
- for(mode = AUMODE_RECORD; mode != -1;
- mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
+ for (mode = AUMODE_RECORD; mode != -1;
+ mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
if ((setmode & mode) == 0)
continue;
@@ -664,6 +691,7 @@ sbdsp_set_params(addr, setmode, usemode, play, rec)
p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode, factor));
}
+
/*
* XXX
* Should wait for chip to be idle.
@@ -672,9 +700,9 @@ sbdsp_set_params(addr, setmode, usemode, play, rec)
sc->sc_o.run = SB_NOTRUNNING;
if (sc->sc_fullduplex &&
- (usemode & (AUMODE_PLAY | AUMODE_RECORD)) == (AUMODE_PLAY | AUMODE_RECORD) &&
+ usemode == (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));
+ DPRINTF(("sbdsp_set_params: 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;
@@ -685,7 +713,8 @@ sbdsp_set_params(addr, setmode, usemode, play, rec)
return EINVAL;
}
}
- DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n", sc->sc_i.dmachan, sc->sc_o.dmachan));
+ DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n",
+ sc->sc_i.dmachan, sc->sc_o.dmachan));
return 0;
}
@@ -742,6 +771,9 @@ sbdsp_set_in_ports(sc, mask)
int bitsl, bitsr;
int sbport;
+ if (sc->sc_open == SB_OPEN_MIDI)
+ return EBUSY;
+
DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
sc->sc_mixer_model, mask));
@@ -786,7 +818,6 @@ sbdsp_set_in_ports(sc, mask)
sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
break;
}
-
sc->in_mask = mask;
return 0;
@@ -799,6 +830,9 @@ sbdsp_speaker_ctl(addr, newstate)
{
struct sbdsp_softc *sc = addr;
+ if (sc->sc_open == SB_OPEN_MIDI)
+ return EBUSY;
+
if ((newstate == SPKR_ON) &&
(sc->spkr_state == SPKR_OFF)) {
sbdsp_spkron(sc);
@@ -817,8 +851,7 @@ sbdsp_round_blocksize(addr, blk)
void *addr;
int blk;
{
- blk &= -4; /* round to biggest sample size */
- return blk;
+ return blk & -4; /* round to biggest sample size */
}
int
@@ -830,12 +863,14 @@ sbdsp_open(addr, flags)
DPRINTF(("sbdsp_open: sc=%p\n", sc));
- if (sc->sc_open != 0 || sbdsp_reset(sc) != 0)
- return ENXIO;
+ if (sc->sc_open != SB_CLOSED)
+ return EBUSY;
+ if (sbdsp_reset(sc) != 0)
+ return EIO;
- sc->sc_open = 1;
+ sc->sc_open = SB_OPEN_AUDIO;
sc->sc_openflags = flags;
- sc->sc_mintr = 0;
+ sc->sc_intrm = 0;
if (ISSBPRO(sc) &&
sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
DPRINTF(("sbdsp_open: can't set mono mode\n"));
@@ -861,12 +896,12 @@ sbdsp_close(addr)
DPRINTF(("sbdsp_close: sc=%p\n", sc));
- sc->sc_open = 0;
+ sc->sc_open = SB_CLOSED;
sbdsp_spkroff(sc);
sc->spkr_state = SPKR_OFF;
sc->sc_intr8 = 0;
sc->sc_intr16 = 0;
- sc->sc_mintr = 0;
+ sc->sc_intrm = 0;
sbdsp_haltdma(sc);
DPRINTF(("sbdsp_close: closed\n"));
@@ -1079,7 +1114,7 @@ sbversion(sc)
sc->sc_model = SB_64;
else
#endif
- sc->sc_model = SB_16;
+ sc->sc_model = SB_16;
break;
}
}
@@ -1128,345 +1163,272 @@ sbdsp16_set_rate(sc, cmd, rate)
}
int
-sbdsp_dma_init_input(addr, buf, cc)
+sbdsp_trigger_input(addr, start, end, blksize, intr, arg, param)
void *addr;
- void *buf;
- int cc;
+ void *start, *end;
+ int blksize;
+ void (*intr) __P((void *));
+ void *arg;
+ struct audio_params *param;
{
struct sbdsp_softc *sc = addr;
+ int stereo = param->channels == 2;
+ int width = param->precision * param->factor;
+ int filter;
- 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;
-}
+#ifdef DIAGNOSTIC
+ if (stereo && (blksize & 1)) {
+ DPRINTF(("stereo record odd bytes (%d)\n", blksize));
+ return (EIO);
+ }
+#endif
-static int
-sbdsp_dma_setup_input(sc)
- struct sbdsp_softc *sc;
-{
- int stereo = sc->sc_i.modep->channels == 2;
- int filter;
+ sc->sc_intrr = intr;
+ sc->sc_argr = arg;
+
+ if (width == 8) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.dmachan != sc->sc_drq8) {
+ printf("sbdsp_trigger_input: width=%d bad chan %d\n",
+ width, sc->sc_i.dmachan);
+ return (EIO);
+ }
+#endif
+ sc->sc_intr8 = sbdsp_block_input;
+ sc->sc_arg8 = addr;
+ } else {
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.dmachan != sc->sc_drq16) {
+ printf("sbdsp_trigger_input: width=%d bad chan %d\n",
+ width, sc->sc_i.dmachan);
+ return (EIO);
+ }
+#endif
+ sc->sc_intr16 = sbdsp_block_input;
+ sc->sc_arg16 = addr;
+ }
+
+ if ((sc->sc_model == SB_JAZZ) ? (sc->sc_i.dmachan > 3) : (width == 16))
+ blksize >>= 1;
+ --blksize;
+ sc->sc_i.blksize = blksize;
- /* Initialize the PCM */
if (ISSBPRO(sc)) {
if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
- return 0;
+ return (EIO);
filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
sbdsp_mix_write(sc, SBP_INFILTER,
- (sbdsp_mix_read(sc, SBP_INFILTER) &
- ~SBP_IFILTER_MASK) | filter);
+ (sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK) |
+ filter);
}
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",
+ if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE, sc->sc_i.rate)) {
+ DPRINTF(("sbdsp_trigger_input: rate=%d set failed\n",
sc->sc_i.rate));
- return 0;
+ return (EIO);
}
} else {
if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
- DPRINTF(("sbdsp_dma_setup_input: tc=%d set failed\n",
+ DPRINTF(("sbdsp_trigger_input: tc=%d set failed\n",
sc->sc_i.rate));
- return 0;
+ return (EIO);
}
}
- return 1;
+
+ DPRINTF(("sbdsp: dma start loop input start=%p end=%p chan=%d\n",
+ start, end, sc->sc_i.dmachan));
+ isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, start, end - start,
+ NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
+
+ return sbdsp_block_input(addr);
}
int
-sbdsp_dma_input(addr, p, cc, intr, arg)
+sbdsp_block_input(addr)
void *addr;
- void *p;
- int cc;
- void (*intr) __P((void *));
- void *arg;
{
struct sbdsp_softc *sc = addr;
+ int cc = sc->sc_i.blksize;
-#ifdef AUDIO_DEBUG
- if (sbdspdebug > 1)
- printf("sbdsp_dma_input: sc=%p buf=%p cc=%d intr=%p(%p)\n",
- addr, p, cc, intr, arg);
-#endif
-#ifdef DIAGNOSTIC
- if (sc->sc_i.modep->channels == 2 && (cc & 1)) {
- DPRINTF(("stereo record odd bytes (%d)\n", cc));
- return EIO;
- }
-#endif
+ DPRINTFN(2, ("sbdsp_block_input: sc=%p cc=%d\n", addr, cc));
- 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;
- }
-#endif
- sc->sc_intr8 = intr;
- sc->sc_arg8 = arg;
- } else {
-#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;
- }
-
- 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:
+ if (sc->sc_i.run != SB_NOTRUNNING)
+ sc->sc_intrr(sc->sc_argr);
+
+ if (sc->sc_model == SB_1) {
/* 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: SB1 DMA start failed\n"));
- goto giveup;
+ DPRINTF(("sbdsp_block_input: SB1 DMA start failed\n"));
+ return (EIO);
}
- 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;
+ sc->sc_i.run = SB_RUNNING;
+ } else if (sc->sc_i.run == SB_NOTRUNNING) {
/* 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
+ DPRINTFN(3, ("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
+ sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
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;
+ DPRINTF(("sbdsp_block_input: SB16 DMA start failed\n"));
+ return (EIO);
}
} else {
- DPRINTF(("sbdsp_dma_input: set blocksize=%d\n", cc));
+ DPRINTF(("sbdsp_block_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;
+ DPRINTF(("sbdsp_block_input: SB2 DMA blocksize failed\n"));
+ return (EIO);
}
if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
- DPRINTF(("sbdsp_dma_input: SB2 DMA start failed\n"));
- goto giveup;
+ DPRINTF(("sbdsp_block_input: SB2 DMA start failed\n"));
+ return (EIO);
}
}
- break;
- case SB_PCMRUNNING:
- /* Looping mode, nothing to do */
- break;
+ sc->sc_i.run = SB_LOOPING;
}
- return 0;
-giveup:
- sbdsp_reset(sc);
- return EIO;
+ return (0);
}
int
-sbdsp_dma_init_output(addr, buf, cc)
+sbdsp_trigger_output(addr, start, end, blksize, intr, arg, param)
void *addr;
- void *buf;
- int cc;
+ void *start, *end;
+ int blksize;
+ void (*intr) __P((void *));
+ void *arg;
+ struct audio_params *param;
{
struct sbdsp_softc *sc = addr;
+ int stereo = param->channels == 2;
+ int width = param->precision * param->factor;
+ int cmd;
- 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;
-}
+#ifdef DIAGNOSTIC
+ if (stereo && (blksize & 1)) {
+ DPRINTF(("stereo playback odd bytes (%d)\n", blksize));
+ return (EIO);
+ }
+#endif
-static int
-sbdsp_dma_setup_output(sc)
- struct sbdsp_softc *sc;
-{
- int stereo = sc->sc_o.modep->channels == 2;
- int cmd;
+ sc->sc_intrp = intr;
+ sc->sc_argp = arg;
+
+ if (width == 8) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.dmachan != sc->sc_drq8) {
+ printf("sbdsp_trigger_output: width=%d bad chan %d\n",
+ width, sc->sc_o.dmachan);
+ return (EIO);
+ }
+#endif
+ sc->sc_intr8 = sbdsp_block_output;
+ sc->sc_arg8 = addr;
+ } else {
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.dmachan != sc->sc_drq16) {
+ printf("sbdsp_trigger_output: width=%d bad chan %d\n",
+ width, sc->sc_o.dmachan);
+ return (EIO);
+ }
+#endif
+ sc->sc_intr16 = sbdsp_block_output;
+ sc->sc_arg16 = addr;
+ }
+
+ if ((sc->sc_model == SB_JAZZ) ? (sc->sc_o.dmachan > 3) : (width == 16))
+ blksize >>= 1;
+ --blksize;
+ sc->sc_o.blksize = blksize;
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));
+ (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;
+ return (EIO);
}
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",
+ if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE, sc->sc_o.rate)) {
+ DPRINTF(("sbdsp_trigger_output: rate=%d set failed\n",
sc->sc_o.rate));
- return 0;
+ return (EIO);
}
} else {
if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
- DPRINTF(("sbdsp_dma_setup_output: tc=%d set failed\n",
+ DPRINTF(("sbdsp_trigger_output: tc=%d set failed\n",
sc->sc_o.rate));
- return 0;
+ return (EIO);
}
}
- return 1;
+
+ DPRINTF(("sbdsp: dma start loop output start=%p end=%p chan=%d\n",
+ start, end, sc->sc_o.dmachan));
+ isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, start, end - start,
+ NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
+
+ return sbdsp_block_output(addr);
}
int
-sbdsp_dma_output(addr, p, cc, intr, arg)
+sbdsp_block_output(addr)
void *addr;
- void *p;
- int cc;
- void (*intr) __P((void *));
- void *arg;
{
struct sbdsp_softc *sc = addr;
+ int cc = sc->sc_o.blksize;
-#ifdef AUDIO_DEBUG
- if (sbdspdebug > 1)
- printf("sbdsp_dma_output: sc=%p buf=%p cc=%d intr=%p(%p)\n", addr, p, cc, intr, arg);
-#endif
-#ifdef DIAGNOSTIC
- if (sc->sc_o.modep->channels == 2 && (cc & 1)) {
- DPRINTF(("stereo playback odd bytes (%d)\n", cc));
- return EIO;
- }
-#endif
+ DPRINTFN(2, ("sbdsp_block_output: sc=%p cc=%d\n", addr, cc));
- 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;
- }
-#endif
- sc->sc_intr8 = intr;
- sc->sc_arg8 = arg;
- } else {
-#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;
- }
+ if (sc->sc_o.run != SB_NOTRUNNING)
+ sc->sc_intrp(sc->sc_argp);
- 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:
+ if (sc->sc_model == SB_1) {
/* 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: SB1 DMA start failed\n"));
- goto giveup;
+ DPRINTF(("sbdsp_block_output: SB1 DMA start failed\n"));
+ return (EIO);
}
- 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;
+ sc->sc_o.run = SB_RUNNING;
+ } else if (sc->sc_o.run == SB_NOTRUNNING) {
/* 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));
+ DPRINTF(("sbdsp_block_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;
+ DPRINTF(("sbdsp_block_output: SB16 DMA start failed\n"));
+ return (EIO);
}
} else {
- DPRINTF(("sbdsp_dma_output: set blocksize=%d\n", cc));
+ DPRINTF(("sbdsp_block_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;
+ DPRINTF(("sbdsp_block_output: SB2 DMA blocksize failed\n"));
+ return (EIO);
}
if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
- DPRINTF(("sbdsp_dma_output: SB2 DMA start failed\n"));
- goto giveup;
+ DPRINTF(("sbdsp_block_output: SB2 DMA start failed\n"));
+ return (EIO);
}
}
- break;
- case SB_PCMRUNNING:
- /* Looping mode, nothing to do */
- break;
+ sc->sc_o.run = SB_LOOPING;
}
- return 0;
-giveup:
- sbdsp_reset(sc);
- return EIO;
+ return (0);
}
/*
@@ -1484,94 +1446,44 @@ sbdsp_intr(arg)
void *arg;
{
struct sbdsp_softc *sc = arg;
- int loop = sc->sc_model != SB_1;
u_char irq;
-#ifdef AUDIO_DEBUG
- if (sbdspdebug > 1)
- printf("sbdsp_intr: intr8=%p, intr16=%p\n",
- sc->sc_intr8, sc->sc_intr16);
-#endif
+ DPRINTFN(2, ("sbdsp_intr: intr8=%p, intr16=%p\n",
+ sc->sc_intr8, sc->sc_intr16));
if (ISSB16CLASS(sc)) {
irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
- if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16)) == 0) {
+ if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16 | SBP_IRQ_MPU401)) == 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;
+ /* XXXX CHECK FOR INTERRUPT */
irq = SBP_IRQ_DMA8;
}
+
sc->sc_interrupts++;
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_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);
+ 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);
+ sc->sc_intr16(sc->sc_arg16);
}
+#if NMIDI > 0
+ if ((irq & SBP_IRQ_MPU401) && sc->sc_hasmpu) {
+ mpu401_intr(&sc->sc_mpu_sc);
+ }
+#endif
return 1;
}
-#if 0
-/*
- * Enter midi uart mode and arrange for read interrupts
- * to vector to `intr'. This puts the card in a mode
- * which allows only midi I/O; the card must be reset
- * to leave this mode. Unfortunately, the card does not
- * use transmit interrupts, so bytes must be output
- * using polling. To keep the polling overhead to a
- * minimum, output should be driven off a timer.
- * This is a little tricky since only 320us separate
- * consecutive midi bytes.
- */
-void
-sbdsp_set_midi_mode(sc, intr, arg)
- struct sbdsp_softc *sc;
- void (*intr)();
- void *arg;
-{
-
- sbdsp_wdsp(sc, SB_MIDI_UART_INTR);
- sc->sc_mintr = intr;
- sc->sc_intr = 0;
- sc->sc_arg = arg;
-}
-
-/*
- * Write a byte to the midi port, when in midi uart mode.
- */
-void
-sbdsp_midi_output(sc, v)
- struct sbdsp_softc *sc;
- int v;
-{
-
- if (sbdsp_wdsp(sc, v) < 0)
- ++sberr.wmidi;
-}
-#endif
-
-/* Mask a value 0-255, but round it first */
+/* Like val & mask, but make sure the result is correctly rounded. */
#define MAXVAL 256
static int
sbdsp_adjust(val, mask)
@@ -1698,6 +1610,9 @@ sbdsp_mixer_set_port(addr, cp)
int lmask, rmask, lbits, rbits;
int mute, swap;
+ if (sc->sc_open == SB_OPEN_MIDI)
+ return EBUSY;
+
DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
cp->un.value.num_channels));
@@ -1882,6 +1797,9 @@ sbdsp_mixer_get_port(addr, cp)
{
struct sbdsp_softc *sc = addr;
+ if (sc->sc_open == SB_OPEN_MIDI)
+ return EBUSY;
+
DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
if (sc->sc_mixer_model == SBM_NONE)
@@ -2175,7 +2093,7 @@ sbdsp_mixer_query_devinfo(addr, dip)
dip->type = AUDIO_MIXER_ENUM;
dip->mixer_class = SB_INPUT_CLASS;
dip->prev = dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, "AGC");
+ 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;
@@ -2315,6 +2233,91 @@ sbdsp_get_props(addr)
void *addr;
{
struct sbdsp_softc *sc = addr;
- return AUDIO_PROP_MMAP |
+ return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT |
(sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
}
+
+#if NMIDI > 0
+/*
+ * MIDI related routines.
+ */
+
+int
+sbdsp_midi_open(addr, flags, iintr, ointr, arg)
+ void *addr;
+ int flags;
+ void (*iintr)__P((void *, int));
+ void (*ointr)__P((void *));
+ void *arg;
+{
+ struct sbdsp_softc *sc = addr;
+
+ DPRINTF(("sbdsp_midi_open: sc=%p\n", sc));
+
+ if (sc->sc_open != SB_CLOSED)
+ return EBUSY;
+ if (sbdsp_reset(sc) != 0)
+ return EIO;
+
+ if (sc->sc_model >= SB_20)
+ if (sbdsp_wdsp(sc, SB_MIDI_UART_INTR)) /* enter UART mode */
+ return EIO;
+ sc->sc_open = SB_OPEN_MIDI;
+ sc->sc_openflags = flags;
+ sc->sc_intr8 = sbdsp_midi_intr;
+ sc->sc_arg8 = addr;
+ sc->sc_intrm = iintr;
+ sc->sc_argm = arg;
+ return 0;
+}
+
+void
+sbdsp_midi_close(addr)
+ void *addr;
+{
+ struct sbdsp_softc *sc = addr;
+
+ DPRINTF(("sbdsp_midi_close: sc=%p\n", sc));
+
+ if (sc->sc_model >= SB_20)
+ sbdsp_reset(sc); /* exit UART mode */
+ sc->sc_open = SB_CLOSED;
+ sc->sc_intrm = 0;
+}
+
+int
+sbdsp_midi_output(addr, d)
+ void *addr;
+ int d;
+{
+ struct sbdsp_softc *sc = addr;
+
+ if (sc->sc_model < SB_20 && sbdsp_wdsp(sc, SB_MIDI_WRITE))
+ return EIO;
+ if (sbdsp_wdsp(sc, d))
+ return EIO;
+ return 0;
+}
+
+void
+sbdsp_midi_getinfo(addr, mi)
+ void *addr;
+ struct midi_info *mi;
+{
+ struct sbdsp_softc *sc = addr;
+
+ mi->name = sc->sc_model < SB_20 ? "SB MIDI cmd" : "SB MIDI UART";
+ mi->props = MIDI_PROP_CAN_INPUT;
+}
+
+int
+sbdsp_midi_intr(addr)
+ void *addr;
+{
+ struct sbdsp_softc *sc = addr;
+
+ sc->sc_intrm(sc->sc_argm, sbdsp_rdsp(sc));
+ return (0);
+}
+
+#endif