summaryrefslogtreecommitdiff
path: root/sys/dev/isa
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
parent890d46b55a21bec77e2f60dbf22d16199ccdbaa7 (diff)
Midi & sequencer support from NetBSD, mostly by Lennart Augustsson
Diffstat (limited to 'sys/dev/isa')
-rw-r--r--sys/dev/isa/files.isa30
-rw-r--r--sys/dev/isa/gus.c5
-rw-r--r--sys/dev/isa/midi_pcppi.c165
-rw-r--r--sys/dev/isa/mpu401.c226
-rw-r--r--sys/dev/isa/mpu401var.h57
-rw-r--r--sys/dev/isa/opl_isa.c105
-rw-r--r--sys/dev/isa/opl_sb.c113
-rw-r--r--sys/dev/isa/pas.c23
-rw-r--r--sys/dev/isa/pcppi.c235
-rw-r--r--sys/dev/isa/pcppireg.h11
-rw-r--r--sys/dev/isa/pcppivar.h37
-rw-r--r--sys/dev/isa/pss.c4
-rw-r--r--sys/dev/isa/sb.c136
-rw-r--r--sys/dev/isa/sb_isapnp.c23
-rw-r--r--sys/dev/isa/sbdsp.c641
-rw-r--r--sys/dev/isa/sbdspvar.h54
-rw-r--r--sys/dev/isa/spkr.c502
-rw-r--r--sys/dev/isa/spkrio.h19
-rw-r--r--sys/dev/isa/wss.c4
-rw-r--r--sys/dev/isa/ym.c4
20 files changed, 1993 insertions, 401 deletions
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index 62da4a6e5a1..eb45fe2bf1e 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,7 +1,7 @@
-# $OpenBSD: files.isa,v 1.48 1998/12/27 09:41:56 deraadt Exp $
+# $OpenBSD: files.isa,v 1.49 1999/01/02 00:02:45 niklas 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.
+# Config file and device description for machine-independent ISA code.
# Included by ports that need it. Requires that the SCSI files be
# defined first.
@@ -231,17 +231,24 @@ file dev/isa/if_sm_isa.c sm_isa
# ISA Sound hardware
#
+# MPU401 MIDI UART compatibles
+define mpu401
+file dev/isa/mpu401.c mpu401 & midi
+
# the SoundBlaster DSP, or close likenesses; used by other drivers
-define sbdsp
+define sbdsp { }
file dev/isa/sbdsp.c sbdsp
# SoundBlaster family
-device sb: audio, isa_dma, sbdsp, mulaw, opti, auconv
+device sb: audio, isa_dma, sbdsp, mulaw, opti, auconv, mpu401, midibus
file dev/isa/sb.c sb needs-flag
attach sb at isa with sb_isa
file dev/isa/sb_isa.c sb & (sb_isa | sb_isapnp) needs-flag
+attach opl at sbdsp with opl_sb
+file dev/isa/opl_sb.c opl_sb
+
# Soundcards based on Sierra's Aria chipset.
# Such as the Prometheus Aria 16 or the Diamond
# sonic sound.
@@ -286,6 +293,20 @@ device gus: audio, isa_dma, ics2101, ad1848, mulaw, auconv
attach gus at isa
file dev/isa/gus.c gus needs-flag
+# Yamaha OPL2/OPL3 FM synth
+attach opl at isa with opl_isa
+file dev/isa/opl_isa.c opl_isa
+
+# PC PPI + TIMER 1 (speaker interface)
+device pcppi {}
+attach pcppi at isa
+file dev/isa/pcppi.c pcppi needs-flag
+device spkr
+attach spkr at pcppi
+file dev/isa/spkr.c spkr needs-flag
+attach midi at pcppi with midi_pcppi: midisyn
+file dev/isa/midi_pcppi.c midi_pcppi
+
#
# PCMCIA PCIC (i82365SL and compatibles):
#
@@ -296,4 +317,3 @@ file dev/isa/gus.c gus needs-flag
#file dev/isa/pcmcia_pcic.c pcic | pcicmaster
#file dev/isa/pcmcia_isa.c pcmcia
-
diff --git a/sys/dev/isa/gus.c b/sys/dev/isa/gus.c
index 50a6de1db83..d7e244e246a 100644
--- a/sys/dev/isa/gus.c
+++ b/sys/dev/isa/gus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gus.c,v 1.18 1998/11/03 21:14:59 downsj Exp $ */
+/* $OpenBSD: gus.c,v 1.19 1999/01/02 00:02:45 niklas Exp $ */
/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
/*-
@@ -1039,7 +1039,8 @@ gusattach(parent, self, aux)
* Attach to the generic audio layer
*/
- audio_attach_mi(&gus_hw_if, 0, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc, &sc->sc_dev);
+ audio_attach_mi(&gus_hw_if,
+ HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc, &sc->sc_dev);
}
int
diff --git a/sys/dev/isa/midi_pcppi.c b/sys/dev/isa/midi_pcppi.c
new file mode 100644
index 00000000000..c42ae87fe5d
--- /dev/null
+++ b/sys/dev/isa/midi_pcppi.c
@@ -0,0 +1,165 @@
+/* $OpenBSD: midi_pcppi.c,v 1.1 1999/01/02 00:02:42 niklas Exp $ */
+/* $NetBSD: midi_pcppi.c,v 1.4 1998/11/25 22:17:06 augustss Exp $ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@netbsd.org).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/select.h>
+#include <sys/audioio.h>
+#include <sys/midiio.h>
+
+#include <dev/isa/pcppivar.h>
+
+#include <dev/audio_if.h>
+#include <dev/midi_if.h>
+#include <dev/midivar.h>
+#include <dev/midisynvar.h>
+
+#define MAX_DURATION 30 /* turn off sound automagically after 30 s */
+
+struct midi_pcppi_softc {
+ struct midi_softc sc_mididev;
+ midisyn sc_midisyn;
+};
+
+#define __BROKEN_INDIRECT_CONFIG /* XXX */
+#ifdef __BROKEN_INDIRECT_CONFIG
+int midi_pcppi_match __P((struct device *, void *, void *));
+#else
+int midi_pcppi_match __P((struct device *, struct cfdata *, void *));
+#endif
+void midi_pcppi_attach __P((struct device *, struct device *, void *));
+
+void midi_pcppi_on __P((midisyn *, u_int32_t, u_int32_t, u_int32_t));
+void midi_pcppi_off __P((midisyn *, u_int32_t, u_int32_t, u_int32_t));
+void midi_pcppi_close __P((midisyn *));
+
+struct cfattach midi_pcppi_ca = {
+ sizeof(struct midi_pcppi_softc), midi_pcppi_match, midi_pcppi_attach
+};
+
+struct midisyn_methods midi_pcppi_hw = {
+ 0, /* open */
+ midi_pcppi_close,
+ 0, /* ioctl */
+ 0, /* allocv */
+ midi_pcppi_on,
+ midi_pcppi_off,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+int midi_pcppi_attached = 0; /* Not very nice */
+
+int
+midi_pcppi_match(parent, match, aux)
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ return (!midi_pcppi_attached);
+}
+
+void
+midi_pcppi_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct midi_pcppi_softc *sc = (struct midi_pcppi_softc *)self;
+ struct pcppi_attach_args *pa = (struct pcppi_attach_args *)aux;
+ midisyn *ms;
+
+ ms = &sc->sc_midisyn;
+ ms->mets = &midi_pcppi_hw;
+ strcpy(ms->name, "PC speaker");
+ ms->nvoice = 1;
+ ms->flags = MS_DOALLOC | MS_FREQXLATE;
+ ms->data = pa->pa_cookie;
+
+ midi_pcppi_attached++;
+
+ midisyn_attach(&sc->sc_mididev, ms);
+ midi_attach(&sc->sc_mididev, parent);
+}
+
+void
+midi_pcppi_on(ms, chan, note, vel)
+ midisyn *ms;
+ u_int32_t chan, note, vel;
+{
+ pcppi_tag_t t = ms->data;
+
+ /*printf("ON %p %d\n", t, MIDISYN_FREQ_TO_HZ(note));*/
+ pcppi_bell(t, MIDISYN_FREQ_TO_HZ(note), MAX_DURATION * hz, 0);
+}
+
+void
+midi_pcppi_off(ms, chan, note, vel)
+ midisyn *ms;
+ u_int32_t chan, note, vel;
+{
+ pcppi_tag_t t = ms->data;
+
+ /*printf("OFF %p %d\n", t, note >> 16);*/
+ pcppi_bell(t, 0, 0, 0);
+}
+
+void
+midi_pcppi_close(ms)
+ midisyn *ms;
+{
+ pcppi_tag_t t = ms->data;
+
+ /* Make sure we are quiet. */
+ pcppi_bell(t, 0, 0, 0);
+}
diff --git a/sys/dev/isa/mpu401.c b/sys/dev/isa/mpu401.c
new file mode 100644
index 00000000000..6463690724a
--- /dev/null
+++ b/sys/dev/isa/mpu401.c
@@ -0,0 +1,226 @@
+/* $OpenBSD: mpu401.c,v 1.1 1999/01/02 00:02:42 niklas Exp $ */
+/* $NetBSD: mpu401.c,v 1.3 1998/11/25 22:17:06 augustss Exp $ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@netbsd.org).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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 <vm/vm.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/midi_if.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+
+#include <dev/isa/mpu401var.h>
+
+#define splaudio() splbio() /* XXX found in audio_if.h normally */
+
+#ifdef AUDIO_DEBUG
+#define DPRINTF(x) if (mpu401debug) printf x
+#define DPRINTFN(n,x) if (mpu401debug >= (n)) printf x
+int mpu401debug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+#define MPU401_NPORT 2
+#define MPU_DATA 0
+#define MPU_COMMAND 1
+#define MPU_RESET 0xff
+#define MPU_UART_MODE 0x3f
+#define MPU_ACK 0xfe
+#define MPU_STATUS 1
+#define MPU_OUTPUT_BUSY 0x40
+#define MPU_INPUT_EMPTY 0x80
+
+#define MPU_MAXWAIT 10000 /* usec/10 to wait */
+
+#define MPU_GETSTATUS(iot, ioh) (bus_space_read_1(iot, ioh, MPU_STATUS))
+
+int mpu401_reset(struct mpu401_softc *);
+static __inline int mpu401_waitready(struct mpu401_softc *);
+void mpu401_readinput(struct mpu401_softc *);
+
+int
+mpu401_find(sc)
+ struct mpu401_softc *sc;
+{
+ if (MPU_GETSTATUS(sc->iot, sc->ioh) == 0xff) {
+ DPRINTF(("mpu401_find: No status\n"));
+ goto bad;
+ }
+ sc->open = 0;
+ sc->intr = 0;
+ if (mpu401_reset(sc) == 0)
+ return 1;
+bad:
+ return 0;
+}
+
+static __inline int
+mpu401_waitready(sc)
+ struct mpu401_softc *sc;
+{
+ int i;
+
+ for(i = 0; i < MPU_MAXWAIT; i++) {
+ if (!(MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_OUTPUT_BUSY))
+ return 0;
+ delay(10);
+ }
+ return 1;
+}
+
+int
+mpu401_reset(sc)
+ struct mpu401_softc *sc;
+{
+ bus_space_tag_t iot = sc->iot;
+ bus_space_handle_t ioh = sc->ioh;
+ int i;
+ int s;
+
+ if (mpu401_waitready(sc)) {
+ DPRINTF(("mpu401_reset: not ready\n"));
+ return EIO;
+ }
+ s = splaudio(); /* Don't let the interrupt get our ACK. */
+ bus_space_write_1(iot, ioh, MPU_COMMAND, MPU_RESET);
+ for(i = 0; i < 2*MPU_MAXWAIT; i++) {
+ if (!(MPU_GETSTATUS(iot, ioh) & MPU_INPUT_EMPTY) &&
+ bus_space_read_1(iot, ioh, MPU_DATA) == MPU_ACK) {
+ splx(s);
+ return 0;
+ }
+ }
+ splx(s);
+ DPRINTF(("mpu401_reset: No ACK\n"));
+ return EIO;
+}
+
+int
+mpu401_open(sc, flags, iintr, ointr, arg)
+ struct mpu401_softc *sc;
+ int flags;
+ void (*iintr)__P((void *, int));
+ void (*ointr)__P((void *));
+ void *arg;
+{
+ DPRINTF(("mpu401_open: sc=%p\n", sc));
+
+ if (sc->open)
+ return EBUSY;
+ if (mpu401_reset(sc) != 0)
+ return EIO;
+
+ bus_space_write_1(sc->iot, sc->ioh, MPU_COMMAND, MPU_UART_MODE);
+ sc->open = 1;
+ sc->intr = iintr;
+ sc->arg = arg;
+ return 0;
+}
+
+void
+mpu401_close(sc)
+ struct mpu401_softc *sc;
+{
+ DPRINTF(("mpu401_close: sc=%p\n", sc));
+
+ sc->open = 0;
+ sc->intr = 0;
+ mpu401_reset(sc); /* exit UART mode */
+}
+
+void
+mpu401_readinput(sc)
+ struct mpu401_softc *sc;
+{
+ bus_space_tag_t iot = sc->iot;
+ bus_space_handle_t ioh = sc->ioh;
+ int data;
+
+ while(!(MPU_GETSTATUS(iot, ioh) & MPU_INPUT_EMPTY)) {
+ data = bus_space_read_1(iot, ioh, MPU_DATA);
+ DPRINTFN(3, ("mpu401_rea: sc=%p 0x%02x\n", sc, data));
+ if (sc->intr)
+ sc->intr(sc->arg, data);
+ }
+}
+
+int
+mpu401_output(sc, d)
+ struct mpu401_softc *sc;
+ int d;
+{
+ int s;
+
+ DPRINTFN(3, ("mpu401_output: sc=%p 0x%02x\n", sc, d));
+ if (!(MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_INPUT_EMPTY)) {
+ s = splaudio();
+ mpu401_readinput(sc);
+ splx(s);
+ }
+ if (mpu401_waitready(sc)) {
+ DPRINTF(("mpu401_output: not ready\n"));
+ return EIO;
+ }
+ bus_space_write_1(sc->iot, sc->ioh, MPU_DATA, d);
+ return 0;
+}
+
+void
+mpu401_intr(sc)
+ struct mpu401_softc *sc;
+{
+ if (MPU_GETSTATUS(sc->iot, sc->ioh) & MPU_INPUT_EMPTY) {
+ DPRINTF(("mpu401_intr: no data\n"));
+ return;
+ }
+ mpu401_readinput(sc);
+}
diff --git a/sys/dev/isa/mpu401var.h b/sys/dev/isa/mpu401var.h
new file mode 100644
index 00000000000..a197e4f6184
--- /dev/null
+++ b/sys/dev/isa/mpu401var.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: mpu401var.h,v 1.1 1999/01/02 00:02:43 niklas Exp $ */
+/* $NetBSD: mpu401var.h,v 1.3 1998/11/25 22:17:06 augustss Exp $ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@netbsd.org).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct mpu401_softc {
+ bus_space_tag_t iot; /* tag */
+ bus_space_handle_t ioh; /* handle */
+ int iobase;
+ int open;
+ void (*intr)__P((void*, int)); /* midi input intr handler */
+ void *arg; /* arg for intr() */
+};
+
+struct midi_hw_if mpu401_midi_hw_if;
+
+void mpu401_intr __P((struct mpu401_softc *));
+int mpu401_find __P((struct mpu401_softc *));
+int mpu401_open __P((struct mpu401_softc *, int,
+ void (*iintr)__P((void *, int)),
+ void (*ointr)__P((void *)), void *arg));
+void mpu401_close __P((struct mpu401_softc *));
+int mpu401_output __P((struct mpu401_softc *, int));
diff --git a/sys/dev/isa/opl_isa.c b/sys/dev/isa/opl_isa.c
new file mode 100644
index 00000000000..ff326b6ede5
--- /dev/null
+++ b/sys/dev/isa/opl_isa.c
@@ -0,0 +1,105 @@
+/* $OpenBSD: opl_isa.c,v 1.1 1999/01/02 00:02:44 niklas Exp $ */
+/* $NetBSD: opl_isa.c,v 1.1 1998/08/26 13:33:59 augustss Exp $ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Author: Lennart Augustsson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/select.h>
+#include <sys/audioio.h>
+#include <sys/midiio.h>
+
+#include <machine/bus.h>
+
+#include <dev/audio_if.h>
+#include <dev/midi_if.h>
+
+#include <dev/ic/oplreg.h>
+#include <dev/ic/oplvar.h>
+
+#include <dev/isa/isavar.h>
+
+#define OPL_SIZE 4
+
+int opl_isa_match __P((struct device *, struct cfdata *, void *));
+void opl_isa_attach __P((struct device *, struct device *, void *));
+
+struct cfattach opl_isa_ca = {
+ sizeof (struct opl_softc), opl_isa_match, opl_isa_attach
+};
+
+int
+opl_isa_match(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct isa_attach_args *ia = aux;
+ struct opl_softc sc;
+ int r;
+
+ memset(&sc, 0, sizeof sc);
+ sc.iot = ia->ia_iot;
+ if (bus_space_map(sc.iot, ia->ia_iobase, OPL_SIZE, 0, &sc.ioh))
+ return (0);
+ r = opl_find(&sc);
+ bus_space_unmap(sc.iot, sc.ioh, OPL_SIZE);
+ return (r);
+}
+
+void
+opl_isa_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct opl_softc *sc = (struct opl_softc *)self;
+ struct isa_attach_args *ia = aux;
+
+ if (bus_space_map(sc->iot, ia->ia_iobase, OPL_SIZE, 0, &sc->ioh)) {
+ printf("opl_isa_attach: bus_space_map failed\n");
+ return;
+ }
+ sc->offs = 0;
+
+ opl_attach(sc);
+}
diff --git a/sys/dev/isa/opl_sb.c b/sys/dev/isa/opl_sb.c
new file mode 100644
index 00000000000..b2a41c3fe92
--- /dev/null
+++ b/sys/dev/isa/opl_sb.c
@@ -0,0 +1,113 @@
+/* $OpenBSD: opl_sb.c,v 1.1 1999/01/02 00:02:45 niklas Exp $ */
+/* $NetBSD: opl_sb.c,v 1.4 1998/12/08 14:26:57 augustss Exp $ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@netbsd.org).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/select.h>
+#include <sys/audioio.h>
+#include <sys/midiio.h>
+
+#include <machine/bus.h>
+
+#include <dev/audio_if.h>
+#include <dev/midi_if.h>
+#include <dev/ic/oplreg.h>
+#include <dev/ic/oplvar.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/sbdspvar.h>
+
+#define __BROKEN_INDIRECT_CONFIG /* XXX */
+#ifdef __BROKEN_INDIRECT_CONFIG
+int opl_sb_match __P((struct device *, void *, void *));
+#else
+int opl_sb_match __P((struct device *, struct cfdata *, void *));
+#endif
+void opl_sb_attach __P((struct device *, struct device *, void *));
+
+struct cfattach opl_sb_ca = {
+ sizeof (struct opl_softc), opl_sb_match, opl_sb_attach
+};
+
+int
+opl_sb_match(parent, match, aux)
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ struct audio_attach_args *aa = (struct audio_attach_args *)aux;
+ struct sbdsp_softc *ssc = (struct sbdsp_softc *)parent;
+ struct opl_softc sc;
+
+ if (aa->type != AUDIODEV_TYPE_OPL)
+ return (0);
+ memset(&sc, 0, sizeof sc);
+ sc.ioh = ssc->sc_ioh;
+ sc.iot = ssc->sc_iot;
+ return (opl_find(&sc));
+}
+
+void
+opl_sb_attach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ struct sbdsp_softc *ssc = (struct sbdsp_softc *)parent;
+ struct opl_softc *sc = (struct opl_softc *)self;
+
+ sc->ioh = ssc->sc_ioh;
+ sc->iot = ssc->sc_iot;
+ sc->offs = 0;
+ sc->spkrctl = sbdsp_speaker_ctl;
+ sc->spkrarg = ssc;
+ strcpy(sc->syn.name, "SB ");
+
+ opl_attach(sc);
+}
diff --git a/sys/dev/isa/pas.c b/sys/dev/isa/pas.c
index 771bf81ad58..77a3108b062 100644
--- a/sys/dev/isa/pas.c
+++ b/sys/dev/isa/pas.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pas.c,v 1.17 1998/11/03 21:15:00 downsj Exp $ */
+/* $OpenBSD: pas.c,v 1.18 1999/01/02 00:02:46 niklas Exp $ */
/* $NetBSD: pas.c,v 1.37 1998/01/12 09:43:43 thorpej Exp $ */
/*
@@ -62,6 +62,7 @@
#include <sys/audioio.h>
#include <dev/audio_if.h>
+#include <dev/midi_if.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -113,20 +114,20 @@ void pasconf __P((int, int, int, int));
struct audio_hw_if pas_hw_if = {
sbdsp_open,
sbdsp_close,
- NULL,
+ 0,
sbdsp_query_encoding,
sbdsp_set_params,
sbdsp_round_blocksize,
- NULL,
- sbdsp_dma_init_output,
- sbdsp_dma_init_input,
- sbdsp_dma_output,
- sbdsp_dma_input,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
sbdsp_haltdma,
sbdsp_haltdma,
sbdsp_speaker_ctl,
pas_getdev,
- NULL,
+ 0,
sbdsp_mixer_set_port,
sbdsp_mixer_get_port,
sbdsp_mixer_query_devinfo,
@@ -135,8 +136,8 @@ struct audio_hw_if pas_hw_if = {
sb_round,
sb_mappage,
sbdsp_get_props,
- NULL,
- NULL
+ sbdsp_trigger_output,
+ sbdsp_trigger_input
};
/* The Address Translation code is used to convert I/O register addresses to
@@ -459,7 +460,7 @@ pasattach(parent, self, aux)
sprintf(pas_device.name, "pas,%s", pasnames[sc->model]);
sprintf(pas_device.version, "%d", sc->rev);
- audio_attach_mi(&pas_hw_if, 0, &sc->sc_sbdsp, &sc->sc_sbdsp.sc_dev);
+ audio_attach_mi(&pas_hw_if, &sc->sc_sbdsp, &sc->sc_sbdsp.sc_dev);
}
int
diff --git a/sys/dev/isa/pcppi.c b/sys/dev/isa/pcppi.c
new file mode 100644
index 00000000000..3fdba2b4dcb
--- /dev/null
+++ b/sys/dev/isa/pcppi.c
@@ -0,0 +1,235 @@
+/* $OpenBSD: pcppi.c,v 1.1 1999/01/02 00:02:44 niklas Exp $ */
+/* $NetBSD: pcppi.c,v 1.1 1998/04/15 20:26:18 drochner Exp $ */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+
+#include <machine/bus.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/pcppireg.h>
+#include <dev/isa/pcppivar.h>
+
+#include <dev/ic/i8253reg.h>
+
+struct pcppi_softc {
+ struct device sc_dv;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ppi_ioh, sc_pit1_ioh;
+
+ int sc_bellactive, sc_bellpitch;
+ int sc_slp;
+};
+
+#define __BROKEN_INDIRECT_CONFIG /* XXX */
+#ifdef __BROKEN_INDIRECT_CONFIG
+int pcppi_match __P((struct device *, void *, void *));
+#else
+int pcppi_match __P((struct device *, struct cfdata *, void *));
+#endif
+void pcppi_attach __P((struct device *, struct device *, void *));
+
+struct cfattach pcppi_ca = {
+ sizeof(struct pcppi_softc), pcppi_match, pcppi_attach,
+};
+
+struct cfdriver pcppi_cd = {
+ NULL, "pcppi", DV_DULL
+};
+
+static void pcppi_bell_stop __P((void*));
+
+#define PCPPIPRI (PZERO - 1)
+
+int
+pcppi_match(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;
+ bus_space_handle_t ppi_ioh, pit1_ioh;
+ int have_pit1, have_ppi, rv;
+ u_int8_t v, nv;
+
+ /* If values are hardwired to something that they can't be, punt. */
+ if ((ia->ia_iobase != IOBASEUNK && ia->ia_iobase != IO_PPI) ||
+ ia->ia_maddr != MADDRUNK || ia->ia_msize != 0 ||
+ ia->ia_irq != IRQUNK || ia->ia_drq != DRQUNK)
+ return (0);
+
+ rv = 0;
+ have_pit1 = have_ppi = 0;
+
+ if (bus_space_map(ia->ia_iot, IO_TIMER1, 4, 0, &pit1_ioh))
+ goto lose;
+ have_pit1 = 1;
+ if (bus_space_map(ia->ia_iot, IO_PPI, 1, 0, &ppi_ioh))
+ goto lose;
+ have_ppi = 1;
+
+ /*
+ * Check for existence of PPI. Realistically, this is either going to
+ * be here or nothing is going to be here.
+ *
+ * We don't want to have any chance of changing speaker output (which
+ * this test might, if it crashes in the middle, or something;
+ * normally it's be to quick to produce anthing audible), but
+ * many "combo chip" mock-PPI's don't seem to support the top bit
+ * of Port B as a settable bit. The bottom bit has to be settable,
+ * since the speaker driver hardware still uses it.
+ */
+ v = bus_space_read_1(ia->ia_iot, ppi_ioh, 0); /* XXX */
+ bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v ^ 0x01); /* XXX */
+ nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0); /* XXX */
+ if (((nv ^ v) & 0x01) == 0x01)
+ rv = 1;
+ bus_space_write_1(ia->ia_iot, ppi_ioh, 0, v); /* XXX */
+ nv = bus_space_read_1(ia->ia_iot, ppi_ioh, 0); /* XXX */
+ if (((nv ^ v) & 0x01) != 0x00) {
+ rv = 0;
+ goto lose;
+ }
+
+ /*
+ * We assume that the programmable interval timer is there.
+ */
+
+lose:
+ if (have_pit1)
+ bus_space_unmap(ia->ia_iot, pit1_ioh, 4);
+ if (have_ppi)
+ bus_space_unmap(ia->ia_iot, ppi_ioh, 1);
+ if (rv) {
+ ia->ia_iobase = IO_PPI;
+ ia->ia_iosize = 0x1;
+ ia->ia_msize = 0x0;
+ }
+ return (rv);
+}
+
+void
+pcppi_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pcppi_softc *sc = (struct pcppi_softc *)self;
+ struct isa_attach_args *ia = aux;
+ bus_space_tag_t iot;
+ struct pcppi_attach_args pa;
+
+ sc->sc_iot = iot = ia->ia_iot;
+
+ if (bus_space_map(iot, IO_TIMER1, 4, 0, &sc->sc_pit1_ioh) ||
+ bus_space_map(iot, IO_PPI, 1, 0, &sc->sc_ppi_ioh))
+ panic("pcppi_attach: couldn't map");
+
+ printf("\n");
+
+ sc->sc_bellactive = sc->sc_bellpitch = sc->sc_slp = 0;
+
+ pa.pa_cookie = sc;
+ while (config_found(self, &pa, 0));
+}
+
+void
+pcppi_bell(self, pitch, period, slp)
+ pcppi_tag_t self;
+ int pitch, period;
+ int slp;
+{
+ struct pcppi_softc *sc = self;
+ int s1, s2;
+
+ s1 = spltty(); /* ??? */
+ if (sc->sc_bellactive) {
+ untimeout(pcppi_bell_stop, sc);
+ if (sc->sc_slp)
+ wakeup(pcppi_bell_stop);
+ }
+ if (pitch == 0 || period == 0) {
+ pcppi_bell_stop(sc);
+ sc->sc_bellpitch = 0;
+ splx(s1);
+ return;
+ }
+ if (!sc->sc_bellactive || sc->sc_bellpitch != pitch) {
+ s2 = splhigh();
+ bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_MODE,
+ TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
+ bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2,
+ TIMER_DIV(pitch) % 256);
+ bus_space_write_1(sc->sc_iot, sc->sc_pit1_ioh, TIMER_CNTR2,
+ TIMER_DIV(pitch) / 256);
+ splx(s2);
+ /* enable speaker */
+ bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0,
+ bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0)
+ | PIT_SPKR);
+ }
+ sc->sc_bellpitch = pitch;
+
+ sc->sc_bellactive = 1;
+ timeout(pcppi_bell_stop, sc, period);
+ if (slp) {
+ sc->sc_slp = 1;
+ tsleep(pcppi_bell_stop, PCPPIPRI | PCATCH, "bell", 0);
+ sc->sc_slp = 0;
+ }
+ splx(s1);
+}
+
+static void
+pcppi_bell_stop(arg)
+ void *arg;
+{
+ struct pcppi_softc *sc = arg;
+ int s;
+
+ s = spltty(); /* ??? */
+ /* disable bell */
+ bus_space_write_1(sc->sc_iot, sc->sc_ppi_ioh, 0,
+ bus_space_read_1(sc->sc_iot, sc->sc_ppi_ioh, 0)
+ & ~PIT_SPKR);
+ sc->sc_bellactive = 0;
+ if (sc->sc_slp)
+ wakeup(pcppi_bell_stop);
+ splx(s);
+}
diff --git a/sys/dev/isa/pcppireg.h b/sys/dev/isa/pcppireg.h
new file mode 100644
index 00000000000..8667ab80e6d
--- /dev/null
+++ b/sys/dev/isa/pcppireg.h
@@ -0,0 +1,11 @@
+/* $OpenBSD: pcppireg.h,v 1.1 1999/01/02 00:02:44 niklas Exp $ */
+/* $NetBSD: pcppireg.h,v 1.1 1998/04/15 20:26:18 drochner Exp $ */
+
+/*
+ * PPI speaker control values
+ */
+
+#define PIT_ENABLETMR2 0x01 /* Enable timer/counter 2 */
+#define PIT_SPKRDATA 0x02 /* Direct to speaker */
+
+#define PIT_SPKR (PIT_ENABLETMR2|PIT_SPKRDATA)
diff --git a/sys/dev/isa/pcppivar.h b/sys/dev/isa/pcppivar.h
new file mode 100644
index 00000000000..fb61b38e9fa
--- /dev/null
+++ b/sys/dev/isa/pcppivar.h
@@ -0,0 +1,37 @@
+/* $OpenBSD: pcppivar.h,v 1.1 1999/01/02 00:02:45 niklas Exp $ */
+/* $NetBSD: pcppivar.h,v 1.1 1998/04/15 20:26:18 drochner Exp $ */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+typedef void *pcppi_tag_t;
+
+struct pcppi_attach_args {
+ pcppi_tag_t pa_cookie;
+};
+
+void pcppi_bell __P((pcppi_tag_t, int, int, int));
diff --git a/sys/dev/isa/pss.c b/sys/dev/isa/pss.c
index 0013819440a..acbc6b2e1b1 100644
--- a/sys/dev/isa/pss.c
+++ b/sys/dev/isa/pss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pss.c,v 1.16 1998/11/03 21:15:01 downsj Exp $ */
+/* $OpenBSD: pss.c,v 1.17 1999/01/02 00:02:46 niklas Exp $ */
/* $NetBSD: pss.c,v 1.38 1998/01/12 09:43:44 thorpej Exp $ */
/*
@@ -1050,7 +1050,7 @@ pssattach(parent, self, aux)
(void)pss_set_treble(sc, AUDIO_MAX_GAIN/2);
(void)pss_set_bass(sc, AUDIO_MAX_GAIN/2);
- audio_attach_mi(&pss_audio_if, 0, sc->ad1848_sc, &sc->ad1848_sc->sc_dev);
+ audio_attach_mi(&pss_audio_if, sc->ad1848_sc, &sc->ad1848_sc->sc_dev);
}
void
diff --git a/sys/dev/isa/sb.c b/sys/dev/isa/sb.c
index 46ee9b33aaa..10306436c48 100644
--- a/sys/dev/isa/sb.c
+++ b/sys/dev/isa/sb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sb.c,v 1.16 1998/11/03 21:15:01 downsj Exp $ */
+/* $OpenBSD: sb.c,v 1.17 1999/01/02 00:02:47 niklas Exp $ */
/* $NetBSD: sb.c,v 1.57 1998/01/12 09:43:46 thorpej Exp $ */
/*
@@ -35,6 +35,8 @@
*
*/
+#include "midi.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
@@ -50,6 +52,7 @@
#include <sys/audioio.h>
#include <dev/audio_if.h>
+#include <dev/midi_if.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -62,6 +65,31 @@ struct cfdriver sb_cd = {
NULL, "sb", DV_DULL
};
+#if NMIDI > 0
+int sb_mpu401_open __P((void *, int,
+ void (*iintr)__P((void *, int)),
+ void (*ointr)__P((void *)), void *arg));
+void sb_mpu401_close __P((void *));
+int sb_mpu401_output __P((void *, int));
+void sb_mpu401_getinfo __P((void *, struct midi_info *));
+
+struct midi_hw_if sb_midi_hw_if = {
+ sbdsp_midi_open,
+ sbdsp_midi_close,
+ sbdsp_midi_output,
+ sbdsp_midi_getinfo,
+ 0, /* ioctl */
+};
+
+struct midi_hw_if sb_mpu401_hw_if = {
+ sb_mpu401_open,
+ sb_mpu401_close,
+ sb_mpu401_output,
+ sb_mpu401_getinfo,
+ 0, /* ioctl */
+};
+#endif
+
struct audio_device sb_device = {
"SoundBlaster",
"x",
@@ -77,20 +105,20 @@ int sb_getdev __P((void *, struct audio_device *));
struct audio_hw_if sb_hw_if = {
sbdsp_open,
sbdsp_close,
- NULL,
+ 0,
sbdsp_query_encoding,
sbdsp_set_params,
sbdsp_round_blocksize,
- NULL,
- sbdsp_dma_init_output,
- sbdsp_dma_init_input,
- sbdsp_dma_output,
- sbdsp_dma_input,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
sbdsp_haltdma,
sbdsp_haltdma,
sbdsp_speaker_ctl,
sb_getdev,
- NULL,
+ 0,
sbdsp_mixer_set_port,
sbdsp_mixer_get_port,
sbdsp_mixer_query_devinfo,
@@ -99,8 +127,8 @@ struct audio_hw_if sb_hw_if = {
sb_round,
sb_mappage,
sbdsp_get_props,
- NULL,
- NULL
+ sbdsp_trigger_output,
+ sbdsp_trigger_input
};
#ifdef AUDIO_DEBUG
@@ -249,41 +277,35 @@ void
sbattach(sc)
struct sbdsp_softc *sc;
{
+ struct audio_attach_args arg;
+#if NMIDI > 0
+ struct midi_hw_if *mhw = &sb_midi_hw_if;
+#endif
+
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);
- audio_attach_mi(&sb_hw_if, 0, sc, &sc->sc_dev);
-}
-
-#ifdef NEWCONFIG
-void
-sbforceintr(aux)
- void *aux;
-{
- static char dmabuf;
- struct sbdsp_softc *sc = aux;
-
- /*
- * Set up a DMA read of one byte.
- * XXX Note that at this point we haven't called
- * at_setup_dmachan(). This is okay because it just
- * allocates a buffer in case it needs to make a copy,
- * and it won't need to make a copy for a 1 byte buffer.
- * (I think that calling at_setup_dmachan() should be optional;
- * if you don't call it, it will be called the first time
- * it is needed (and you pay the latency). Also, you might
- * never need the buffer anyway.)
- */
- at_dma(DMAMODE_READ, &dmabuf, 1, sc->sc_drq8);
- if (sbdsp_wdsp(sc, SB_DSP_RDMA) == 0) {
- (void)sbdsp_wdsp(sc, 0);
- (void)sbdsp_wdsp(sc, 0);
+#if NMIDI > 0
+ sc->sc_hasmpu = 0;
+ if (ISSB16CLASS(sc) && sc->sc_mpu_sc.iobase != 0) {
+ sc->sc_mpu_sc.iot = sc->sc_iot;
+ if (mpu401_find(&sc->sc_mpu_sc)) {
+ sc->sc_hasmpu = 1;
+ mhw = &sb_mpu401_hw_if;
+ }
}
-}
+ midi_attach_mi(mhw, sc, &sc->sc_dev);
#endif
+ audio_attach_mi(&sb_hw_if, sc, &sc->sc_dev);
+
+ arg.type = AUDIODEV_TYPE_OPL;
+ arg.hwif = 0;
+ arg.hdl = 0;
+ (void)config_found(&sc->sc_dev, &arg, audioprint);
+}
/*
* Various routines to interface to higher level audio driver
@@ -313,3 +335,43 @@ sb_getdev(addr, retp)
return 0;
}
+
+#if NMIDI > 0
+
+#define SBMPU(a) (&((struct sbdsp_softc *)addr)->sc_mpu_sc)
+
+int
+sb_mpu401_open(addr, flags, iintr, ointr, arg)
+ void *addr;
+ int flags;
+ void (*iintr)__P((void *, int));
+ void (*ointr)__P((void *));
+ void *arg;
+{
+ return mpu401_open(SBMPU(addr), flags, iintr, ointr, arg);
+}
+
+int
+sb_mpu401_output(addr, d)
+ void *addr;
+ int d;
+{
+ return mpu401_output(SBMPU(addr), d);
+}
+
+void
+sb_mpu401_close(addr)
+ void *addr;
+{
+ mpu401_close(SBMPU(addr));
+}
+
+void
+sb_mpu401_getinfo(addr, mi)
+ void *addr;
+ struct midi_info *mi;
+{
+ mi->name = "SB MPU-401 UART";
+ mi->props = 0;
+}
+#endif
diff --git a/sys/dev/isa/sb_isapnp.c b/sys/dev/isa/sb_isapnp.c
index 774052dd5f7..c3b70a3a0e4 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.5 1998/05/13 20:07:47 deraadt Exp $ */
+/* $OpenBSD: sb_isapnp.c,v 1.6 1999/01/02 00:02:47 niklas Exp $ */
/* $NetBSD: sb_isa.c,v 1.3 1997/03/20 11:03:11 mycroft Exp $ */
/*
@@ -45,6 +45,7 @@
#include <sys/audioio.h>
#include <dev/audio_if.h>
+#include <dev/midi_if.h>
#include <dev/mulaw.h>
#include <dev/isa/isavar.h>
@@ -107,14 +108,22 @@ sb_isapnp_attach(parent, self, aux)
} 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 NMIDI > 0
+ if (ia->ipa_nio > 1) {
+ sc->sc_mpu_sc.iobase = ia->ipa_io[1].base;
+ sc->sc_mpu_sc.ioh = ia->ipa_io[1].h;
+ } else
+ sc->sc_mpu_sc.iobase = 0;
+#endif
- if (!sbmatch(sc))
+ if (!sbmatch(sc)) {
+ printf("%s: sbmatch failed\n", sc->sc_dev.dv_xname);
return;
+ }
+
+ printf("%s: %s %s", sc->sc_dev.dv_xname, ia->ipa_devident,
+ ia->ipa_devclass);
+ sc->sc_isa = parent;
sbattach(sc);
}
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
diff --git a/sys/dev/isa/sbdspvar.h b/sys/dev/isa/sbdspvar.h
index c70a012f447..3f8e5b5cb7e 100644
--- a/sys/dev/isa/sbdspvar.h
+++ b/sys/dev/isa/sbdspvar.h
@@ -1,5 +1,5 @@
-/* $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 $ */
+/* $OpenBSD: sbdspvar.h,v 1.9 1999/01/02 00:02:47 niklas Exp $ */
+/* $NetBSD: sbdspvar.h,v 1.37 1998/08/10 00:20:39 mycroft Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -35,6 +35,11 @@
*
*/
+#include "midi.h"
+#if NMIDI > 0
+#include <dev/isa/mpu401var.h>
+#endif
+
#define SB_MASTER_VOL 0
#define SB_MIDI_VOL 1
#define SB_CD_VOL 2
@@ -94,15 +99,18 @@ struct sbdsp_softc {
bus_space_tag_t sc_iot; /* tag */
bus_space_handle_t sc_ioh; /* handle */
void *sc_ih; /* interrupt vectoring */
+ struct device *sc_isa;
int sc_iobase; /* I/O port base address */
int sc_irq; /* interrupt */
+ int sc_ist; /* interrupt share type */
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_open; /* reference count of open calls */
+#define SB_CLOSED 0
+#define SB_OPEN_AUDIO 1
+#define SB_OPEN_MIDI 2
int sc_openflags; /* flags used on open */
u_char sc_fullduplex; /* can do full duplex */
@@ -123,19 +131,25 @@ struct sbdsp_softc {
struct sbmode *modep;
u_char bmode;
int dmachan; /* DMA channel */
+ int blksize; /* Block size, preadjusted */
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 */
+#define SB_LOOPING 2 /* DMA&PCM running (looping mode) */
} sc_i, sc_o; /* Input and output state */
u_long sc_interrupts; /* number of interrupts taken */
- void (*sc_intr8)(void*); /* dma completion intr handler */
+
+ int (*sc_intr8)(void*); /* dma completion intr handler */
void *sc_arg8; /* arg for sc_intr8() */
- void (*sc_intr16)(void*); /* dma completion intr handler */
+ int (*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_intrp)(void*); /* PCM output intr handler */
+ void *sc_argp; /* arg for sc_intrp() */
+ void (*sc_intrr)(void*); /* PCM input intr handler */
+ void *sc_argr; /* arg for sc_intrr() */
+ void (*sc_intrm)(void*, int);/* midi input intr handler */
+ void *sc_argm; /* arg for sc_intrm() */
u_int sc_mixer_model;
#define SBM_NONE 0
@@ -161,6 +175,11 @@ struct sbdsp_softc {
u_int sc_version; /* DSP version */
#define SBVER_MAJOR(v) (((v)>>8) & 0xff)
#define SBVER_MINOR(v) ((v)&0xff)
+
+#if NMIDI > 0
+ int sc_hasmpu;
+ struct mpu401_softc sc_mpu_sc; /* MPU401 Uart state */
+#endif
};
#define ISSBPRO(sc) ((sc)->sc_model == SB_PRO || (sc)->sc_model == SB_JAZZ)
@@ -190,10 +209,10 @@ int sbdsp_get_avail_out_ports __P((void *));
int sbdsp_speaker_ctl __P((void *, int));
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_trigger_output __P((void *, void *, void *, int, void (*)(void *),
+ void *, struct audio_params *));
+int sbdsp_trigger_input __P((void *, void *, void *, int, void (*)(void *),
+ void *, struct audio_params *));
int sbdsp_haltdma __P((void *));
@@ -225,4 +244,11 @@ int sb_mappage __P((void *, void *, int, int));
int sbdsp_get_props __P((void *));
+
+int sbdsp_midi_open __P((void *, int,
+ void (*iintr)__P((void *, int)),
+ void (*ointr)__P((void *)), void *arg));
+void sbdsp_midi_close __P((void *));
+int sbdsp_midi_output __P((void *, int));
+void sbdsp_midi_getinfo __P((void *, struct midi_info *));
#endif
diff --git a/sys/dev/isa/spkr.c b/sys/dev/isa/spkr.c
new file mode 100644
index 00000000000..09b2181861e
--- /dev/null
+++ b/sys/dev/isa/spkr.c
@@ -0,0 +1,502 @@
+/* $OpenBSD: spkr.c,v 1.1 1999/01/02 00:02:43 niklas Exp $ */
+/* $NetBSD: spkr.c,v 1.1 1998/04/15 20:26:18 drochner Exp $ */
+
+/*
+ * spkr.c -- device driver for console speaker on 80386
+ *
+ * v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
+ * modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su>
+ * 386bsd only clean version, all SYSV stuff removed
+ * use hz value from param.c
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/conf.h>
+
+#include <dev/isa/pcppivar.h>
+
+#include <dev/isa/spkrio.h>
+
+cdev_decl(spkr);
+
+int spkrprobe __P((struct device *, struct cfdata *, void *));
+void spkrattach __P((struct device *, struct device *, void *));
+
+struct spkr_softc {
+ struct device sc_dev;
+};
+
+struct cfattach spkr_ca = {
+ sizeof(struct spkr_softc), spkrprobe, spkrattach
+};
+
+static pcppi_tag_t ppicookie;
+
+#define SPKRPRI (PZERO - 1)
+
+static void tone __P((u_int, u_int));
+static void rest __P((int));
+static void playinit __P((void));
+static void playtone __P((int, int, int));
+static void playstring __P((char *, int));
+
+static
+void tone(hz, ticks)
+/* emit tone of frequency hz for given number of ticks */
+ u_int hz, ticks;
+{
+ pcppi_bell(ppicookie, hz, ticks, 1);
+}
+
+static void
+rest(ticks)
+/* rest for given number of ticks */
+ int ticks;
+{
+ /*
+ * Set timeout to endrest function, then give up the timeslice.
+ * This is so other processes can execute while the rest is being
+ * waited out.
+ */
+#ifdef SPKRDEBUG
+ printf("rest: %d\n", ticks);
+#endif /* SPKRDEBUG */
+ if (ticks > 0)
+ tsleep(rest, SPKRPRI | PCATCH, "rest", ticks);
+}
+
+/**************** PLAY STRING INTERPRETER BEGINS HERE **********************
+ *
+ * Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement;
+ * M[LNS] are missing and the ~ synonym and octave-tracking facility is added.
+ * Requires tone(), rest(), and endtone(). String play is not interruptible
+ * except possibly at physical block boundaries.
+ */
+
+typedef int bool;
+#define TRUE 1
+#define FALSE 0
+
+#define toupper(c) ((c) - ' ' * (((c) >= 'a') && ((c) <= 'z')))
+#define isdigit(c) (((c) >= '0') && ((c) <= '9'))
+#define dtoi(c) ((c) - '0')
+
+static int octave; /* currently selected octave */
+static int whole; /* whole-note time at current tempo, in ticks */
+static int value; /* whole divisor for note time, quarter note = 1 */
+static int fill; /* controls spacing of notes */
+static bool octtrack; /* octave-tracking on? */
+static bool octprefix; /* override current octave-tracking state? */
+
+/*
+ * Magic number avoidance...
+ */
+#define SECS_PER_MIN 60 /* seconds per minute */
+#define WHOLE_NOTE 4 /* quarter notes per whole note */
+#define MIN_VALUE 64 /* the most we can divide a note by */
+#define DFLT_VALUE 4 /* default value (quarter-note) */
+#define FILLTIME 8 /* for articulation, break note in parts */
+#define STACCATO 6 /* 6/8 = 3/4 of note is filled */
+#define NORMAL 7 /* 7/8ths of note interval is filled */
+#define LEGATO 8 /* all of note interval is filled */
+#define DFLT_OCTAVE 4 /* default octave */
+#define MIN_TEMPO 32 /* minimum tempo */
+#define DFLT_TEMPO 120 /* default tempo */
+#define MAX_TEMPO 255 /* max tempo */
+#define NUM_MULT 3 /* numerator of dot multiplier */
+#define DENOM_MULT 2 /* denominator of dot multiplier */
+
+/* letter to half-tone: A B C D E F G */
+static int notetab[8] = {9, 11, 0, 2, 4, 5, 7};
+
+/*
+ * This is the American Standard A440 Equal-Tempered scale with frequencies
+ * rounded to nearest integer. Thank Goddess for the good ol' CRC Handbook...
+ * our octave 0 is standard octave 2.
+ */
+#define OCTAVE_NOTES 12 /* semitones per octave */
+static int pitchtab[] =
+{
+/* C C# D D# E F F# G G# A A# B*/
+/* 0 */ 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123,
+/* 1 */ 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
+/* 2 */ 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
+/* 3 */ 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
+/* 4 */ 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975,
+/* 5 */ 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
+/* 6 */ 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902,
+};
+#define NOCTAVES (sizeof(pitchtab) / sizeof(pitchtab[0]) / OCTAVE_NOTES)
+
+static void
+playinit()
+{
+ octave = DFLT_OCTAVE;
+ whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
+ fill = NORMAL;
+ value = DFLT_VALUE;
+ octtrack = FALSE;
+ octprefix = TRUE; /* act as though there was an initial O(n) */
+}
+
+static void
+playtone(pitch, value, sustain)
+/* play tone of proper duration for current rhythm signature */
+ int pitch, value, sustain;
+{
+ register int sound, silence, snum = 1, sdenom = 1;
+
+ /* this weirdness avoids floating-point arithmetic */
+ for (; sustain; sustain--)
+ {
+ snum *= NUM_MULT;
+ sdenom *= DENOM_MULT;
+ }
+
+ if (pitch == -1)
+ rest(whole * snum / (value * sdenom));
+ else
+ {
+ sound = (whole * snum) / (value * sdenom)
+ - (whole * (FILLTIME - fill)) / (value * FILLTIME);
+ silence = whole * (FILLTIME-fill) * snum / (FILLTIME * value * sdenom);
+
+#ifdef SPKRDEBUG
+ printf("playtone: pitch %d for %d ticks, rest for %d ticks\n",
+ pitch, sound, silence);
+#endif /* SPKRDEBUG */
+
+ tone(pitchtab[pitch], sound);
+ if (fill != LEGATO)
+ rest(silence);
+ }
+}
+
+static void
+playstring(cp, slen)
+/* interpret and play an item from a notation string */
+ char *cp;
+ int slen;
+{
+ int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
+
+#define GETNUM(cp, v) for(v=0; slen > 0 && isdigit(cp[1]); ) \
+ {v = v * 10 + (*++cp - '0'); slen--;}
+ for (; slen--; cp++)
+ {
+ int sustain, timeval, tempo;
+ register char c = toupper(*cp);
+
+#ifdef SPKRDEBUG
+ printf("playstring: %c (%x)\n", c, c);
+#endif /* SPKRDEBUG */
+
+ switch (c)
+ {
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
+
+ /* compute pitch */
+ pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES;
+
+ /* this may be followed by an accidental sign */
+ if (slen > 0 && (cp[1] == '#' || cp[1] == '+'))
+ {
+ ++pitch;
+ ++cp;
+ slen--;
+ }
+ else if (slen > 0 && cp[1] == '-')
+ {
+ --pitch;
+ ++cp;
+ slen--;
+ }
+
+ /*
+ * If octave-tracking mode is on, and there has been no octave-
+ * setting prefix, find the version of the current letter note
+ * closest to the last regardless of octave.
+ */
+ if (octtrack && !octprefix)
+ {
+ if (abs(pitch-lastpitch) > abs(pitch+OCTAVE_NOTES-lastpitch))
+ {
+ ++octave;
+ pitch += OCTAVE_NOTES;
+ }
+
+ if (abs(pitch-lastpitch) > abs((pitch-OCTAVE_NOTES)-lastpitch))
+ {
+ --octave;
+ pitch -= OCTAVE_NOTES;
+ }
+ }
+ octprefix = FALSE;
+ lastpitch = pitch;
+
+ /* ...which may in turn be followed by an override time value */
+ GETNUM(cp, timeval);
+ if (timeval <= 0 || timeval > MIN_VALUE)
+ timeval = value;
+
+ /* ...and/or sustain dots */
+ for (sustain = 0; slen > 0 && cp[1] == '.'; cp++)
+ {
+ slen--;
+ sustain++;
+ }
+
+ /* time to emit the actual tone */
+ playtone(pitch, timeval, sustain);
+ break;
+
+ case 'O':
+ if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n'))
+ {
+ octprefix = octtrack = FALSE;
+ ++cp;
+ slen--;
+ }
+ else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l'))
+ {
+ octtrack = TRUE;
+ ++cp;
+ slen--;
+ }
+ else
+ {
+ GETNUM(cp, octave);
+ if (octave >= NOCTAVES)
+ octave = DFLT_OCTAVE;
+ octprefix = TRUE;
+ }
+ break;
+
+ case '>':
+ if (octave < NOCTAVES - 1)
+ octave++;
+ octprefix = TRUE;
+ break;
+
+ case '<':
+ if (octave > 0)
+ octave--;
+ octprefix = TRUE;
+ break;
+
+ case 'N':
+ GETNUM(cp, pitch);
+ for (sustain = 0; slen > 0 && cp[1] == '.'; cp++)
+ {
+ slen--;
+ sustain++;
+ }
+ playtone(pitch - 1, value, sustain);
+ break;
+
+ case 'L':
+ GETNUM(cp, value);
+ if (value <= 0 || value > MIN_VALUE)
+ value = DFLT_VALUE;
+ break;
+
+ case 'P':
+ case '~':
+ /* this may be followed by an override time value */
+ GETNUM(cp, timeval);
+ if (timeval <= 0 || timeval > MIN_VALUE)
+ timeval = value;
+ for (sustain = 0; slen > 0 && cp[1] == '.'; cp++)
+ {
+ slen--;
+ sustain++;
+ }
+ playtone(-1, timeval, sustain);
+ break;
+
+ case 'T':
+ GETNUM(cp, tempo);
+ if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
+ tempo = DFLT_TEMPO;
+ whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
+ break;
+
+ case 'M':
+ if (slen > 0 && (cp[1] == 'N' || cp[1] == 'n'))
+ {
+ fill = NORMAL;
+ ++cp;
+ slen--;
+ }
+ else if (slen > 0 && (cp[1] == 'L' || cp[1] == 'l'))
+ {
+ fill = LEGATO;
+ ++cp;
+ slen--;
+ }
+ else if (slen > 0 && (cp[1] == 'S' || cp[1] == 's'))
+ {
+ fill = STACCATO;
+ ++cp;
+ slen--;
+ }
+ break;
+ }
+ }
+}
+
+/******************* UNIX DRIVER HOOKS BEGIN HERE **************************
+ *
+ * This section implements driver hooks to run playstring() and the tone(),
+ * endtone(), and rest() functions defined above.
+ */
+
+static int spkr_active; /* exclusion flag */
+static void *spkr_inbuf;
+
+static int spkr_attached = 0;
+
+int
+spkrprobe (parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ return (!spkr_attached);
+}
+
+void
+spkrattach(parent, self, aux)
+ struct device *parent;
+ struct device *self;
+ void *aux;
+{
+ printf("\n");
+ ppicookie = ((struct pcppi_attach_args *)aux)->pa_cookie;
+ spkr_attached = 1;
+}
+
+int
+spkropen(dev, flags, mode, p)
+ dev_t dev;
+ int flags;
+ int mode;
+ struct proc *p;
+{
+#ifdef SPKRDEBUG
+ printf("spkropen: entering with dev = %x\n", dev);
+#endif /* SPKRDEBUG */
+
+ if (minor(dev) != 0 || !spkr_attached)
+ return(ENXIO);
+ else if (spkr_active)
+ return(EBUSY);
+ else
+ {
+ playinit();
+ spkr_inbuf = malloc(DEV_BSIZE, M_DEVBUF, M_WAITOK);
+ spkr_active = 1;
+ }
+ return(0);
+}
+
+int
+spkrwrite(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ register int n;
+ int error;
+#ifdef SPKRDEBUG
+ printf("spkrwrite: entering with dev = %x, count = %d\n",
+ dev, uio->uio_resid);
+#endif /* SPKRDEBUG */
+
+ if (minor(dev) != 0)
+ return(ENXIO);
+ else
+ {
+ n = min(DEV_BSIZE, uio->uio_resid);
+ error = uiomove(spkr_inbuf, n, uio);
+ if (!error)
+ playstring((char *)spkr_inbuf, n);
+ return(error);
+ }
+}
+
+int spkrclose(dev, flags, mode, p)
+ dev_t dev;
+ int flags;
+ int mode;
+ struct proc *p;
+{
+#ifdef SPKRDEBUG
+ printf("spkrclose: entering with dev = %x\n", dev);
+#endif /* SPKRDEBUG */
+
+ if (minor(dev) != 0)
+ return(ENXIO);
+ else
+ {
+ tone(0, 0);
+ free(spkr_inbuf, M_DEVBUF);
+ spkr_active = 0;
+ }
+ return(0);
+}
+
+int spkrioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+#ifdef SPKRDEBUG
+ printf("spkrioctl: entering with dev = %x, cmd = %lx\n", dev, cmd);
+#endif /* SPKRDEBUG */
+
+ if (minor(dev) != 0)
+ return(ENXIO);
+ else if (cmd == SPKRTONE)
+ {
+ tone_t *tp = (tone_t *)data;
+
+ if (tp->frequency == 0)
+ rest(tp->duration);
+ else
+ tone(tp->frequency, tp->duration);
+ }
+ else if (cmd == SPKRTUNE)
+ {
+ tone_t *tp = (tone_t *)(*(caddr_t *)data);
+ tone_t ttp;
+ int error;
+
+ for (; ; tp++) {
+ error = copyin(tp, &ttp, sizeof(tone_t));
+ if (error)
+ return(error);
+ if (ttp.duration == 0)
+ break;
+ if (ttp.frequency == 0)
+ rest(ttp.duration);
+ else
+ tone(ttp.frequency, ttp.duration);
+ }
+ }
+ else
+ return(EINVAL);
+ return(0);
+}
+
+/* spkr.c ends here */
diff --git a/sys/dev/isa/spkrio.h b/sys/dev/isa/spkrio.h
new file mode 100644
index 00000000000..a852cf0782f
--- /dev/null
+++ b/sys/dev/isa/spkrio.h
@@ -0,0 +1,19 @@
+/* $OpenBSD: spkrio.h,v 1.1 1999/01/02 00:02:43 niklas Exp $ */
+/* $NetBSD: spkrio.h,v 1.1 1998/04/15 20:26:19 drochner Exp $ */
+
+/*
+ * spkr.h -- interface definitions for speaker ioctl()
+ */
+
+#ifndef _DEV_ISA_SPKR_H_
+#define _DEV_ISA_SPKR_H_
+
+#define SPKRTONE _IOW('S', 1, tone_t) /* emit tone */
+#define SPKRTUNE _IO('S', 2) /* emit tone sequence */
+
+typedef struct {
+ int frequency; /* in hertz */
+ int duration; /* in 1/100ths of a second */
+} tone_t;
+
+#endif /* _DEV_ISA_SPKR_H_ */
diff --git a/sys/dev/isa/wss.c b/sys/dev/isa/wss.c
index 9476f45fb4e..c49eb337d44 100644
--- a/sys/dev/isa/wss.c
+++ b/sys/dev/isa/wss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wss.c,v 1.17 1998/11/03 21:15:01 downsj Exp $ */
+/* $OpenBSD: wss.c,v 1.18 1999/01/02 00:02:48 niklas Exp $ */
/* $NetBSD: wss.c,v 1.42 1998/01/19 22:18:23 augustss Exp $ */
/*
@@ -153,7 +153,7 @@ wssattach(sc)
sc->sc_ad1848.parent = sc;
- audio_attach_mi(&wss_hw_if, 0, &sc->sc_ad1848, &sc->sc_dev);
+ audio_attach_mi(&wss_hw_if, &sc->sc_ad1848, &sc->sc_dev);
}
int
diff --git a/sys/dev/isa/ym.c b/sys/dev/isa/ym.c
index a4eb9551466..04611a1c815 100644
--- a/sys/dev/isa/ym.c
+++ b/sys/dev/isa/ym.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ym.c,v 1.3 1998/12/29 09:10:30 deraadt Exp $ */
+/* $OpenBSD: ym.c,v 1.4 1999/01/02 00:02:48 niklas Exp $ */
/*
@@ -134,7 +134,7 @@ ym_attach(sc)
sc->mic_mute = 1;
ym_mute(sc, SA3_MIC, sc->mic_mute);
- audio_attach_mi(&ym_hw_if, 0, &sc->sc_ad1848, &sc->sc_dev);
+ audio_attach_mi(&ym_hw_if, &sc->sc_ad1848, &sc->sc_dev);
}
static __inline int