summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorprovos <provos@openbsd.org>1998-04-26 21:02:37 +0000
committerprovos <provos@openbsd.org>1998-04-26 21:02:37 +0000
commite99cab2be4365da63b86b0d86d6cce79f3103c64 (patch)
tree33a2d4aa3f5856eca15ef5c699b9965fbacbe977
parenthandle ENOSPC as an end-of-tape marker; gibbs@narnia.plutotech.com (diff)
downloadwireguard-openbsd-e99cab2be4365da63b86b0d86d6cce79f3103c64.tar.xz
wireguard-openbsd-e99cab2be4365da63b86b0d86d6cce79f3103c64.zip
update audio from NetBSD, mostly by Lennart Augustsson <augustss@cs.chalmers.se>
-rw-r--r--sys/arch/i386/conf/files.i3865
-rw-r--r--sys/arch/i386/i386/machdep.c24
-rw-r--r--sys/conf/files12
-rw-r--r--sys/dev/audio.c2855
-rw-r--r--sys/dev/audio_if.h107
-rw-r--r--sys/dev/audiovar.h131
-rw-r--r--sys/dev/ic/ad1848reg.h38
-rw-r--r--sys/dev/isa/ad1848.c759
-rw-r--r--sys/dev/isa/ad1848var.h50
-rw-r--r--sys/dev/isa/files.isa18
-rw-r--r--sys/dev/isa/gus.c1956
-rw-r--r--sys/dev/isa/gusreg.h45
-rw-r--r--sys/dev/isa/ics2101.c17
-rw-r--r--sys/dev/isa/ics2101var.h11
-rw-r--r--sys/dev/isa/isa.c19
-rw-r--r--sys/dev/isa/isavar.h4
-rw-r--r--sys/dev/isa/madreg.h102
-rw-r--r--sys/dev/isa/mcd.c204
-rw-r--r--sys/dev/isa/mcdreg.h5
-rw-r--r--sys/dev/isa/pas.c116
-rw-r--r--sys/dev/isa/pnpdevs3
-rw-r--r--sys/dev/isa/pnpdevs.h1
-rw-r--r--sys/dev/isa/pss.c209
-rw-r--r--sys/dev/isa/sb.c119
-rw-r--r--sys/dev/isa/sb_isa.c82
-rw-r--r--sys/dev/isa/sb_isapnp.c21
-rw-r--r--sys/dev/isa/sbdsp.c2439
-rw-r--r--sys/dev/isa/sbdspvar.h183
-rw-r--r--sys/dev/isa/sbreg.h95
-rw-r--r--sys/dev/isa/wss.c441
-rw-r--r--sys/dev/isa/wss_isa.c376
-rw-r--r--sys/dev/isa/wssvar.h83
-rw-r--r--sys/dev/mulaw.c367
-rw-r--r--sys/dev/mulaw.h23
-rw-r--r--sys/sys/audioio.h135
-rw-r--r--sys/sys/conf.h4
36 files changed, 6702 insertions, 4357 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386
index 31a2caa0336..8fc49f6e4be 100644
--- a/sys/arch/i386/conf/files.i386
+++ b/sys/arch/i386/conf/files.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: files.i386,v 1.39 1998/01/06 02:35:19 deraadt Exp $
+# $OpenBSD: files.i386,v 1.40 1998/04/26 21:03:14 provos Exp $
# $NetBSD: files.i386,v 1.73 1996/05/07 00:58:36 thorpej Exp $
#
# new style config file for i386 architecture
@@ -231,6 +231,9 @@ include "../../../compat/bsdos/files.bsdos"
include "../../../compat/freebsd/files.freebsd"
file arch/i386/i386/freebsd_machdep.c compat_freebsd
+# OSS audio driver compatibility
+include "compat/ossaudio/files.ossaudio"
+
device bios {}
attach bios at mainbus
file arch/i386/i386/bios.c bios needs-count
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index 9b5699e9c3e..2cda7503f22 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.85 1998/04/25 20:31:27 mickey Exp $ */
+/* $OpenBSD: machdep.c,v 1.86 1998/04/26 21:03:15 provos Exp $ */
/* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */
/*-
@@ -2504,8 +2504,28 @@ _bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
bus_dma_segment_t *segs;
int nsegs, off, prot, flags;
{
+ int i;
+
+ for (i = 0; i < nsegs; i++) {
+#ifdef DIAGNOSTIC
+ if (off & PGOFSET)
+ panic("_bus_dmamem_mmap: offset unaligned");
+ if (segs[i].ds_addr & PGOFSET)
+ panic("_bus_dmamem_mmap: segment unaligned");
+ if (segs[i].ds_len & PGOFSET)
+ panic("_bus_dmamem_mmap: segment size not multiple"
+ " of page size");
+#endif
+ if (off >= segs[i].ds_len) {
+ off -= segs[i].ds_len;
+ continue;
+ }
+
+ return (i386_btop((caddr_t)segs[i].ds_addr + off));
+ }
- panic("_bus_dmamem_mmap: not implemented");
+ /* Page not found. */
+ return (-1);
}
/**********************************************************************
diff --git a/sys/conf/files b/sys/conf/files
index e88734697e2..fc2821d63d3 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.77 1998/03/24 03:26:03 deraadt Exp $
+# $OpenBSD: files,v 1.78 1998/04/26 21:03:05 provos Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -9,11 +9,16 @@ define disk
define tape
define ifnet
define tty
-define audio
+define audio {}
define scsi {}
# audio device attributes
define mulaw
+define auconv
+
+# audio device, attaches to audio hardware driver
+device audio
+attach audio at audio
# net device attributes - we have generic code for arc(net), ether(net),
# and fddi.
@@ -129,6 +134,7 @@ file ddb/db_watch.c ddb
file ddb/db_write_cmd.c ddb
file ddb/db_usrreq.c ddb
file ddb/db_hangman.c ddb
+file dev/auconv.c auconv
file dev/audio.c audio needs-flag
file dev/ccd.c ccd needs-flag
file dev/ic/ncr5380sbc.c ncr5380sbc
@@ -235,6 +241,8 @@ file miscfs/procfs/procfs_fpregs.c
file miscfs/procfs/procfs_mem.c
file miscfs/procfs/procfs_note.c procfs
file miscfs/procfs/procfs_regs.c
+file miscfs/procfs/procfs_environ.c procfs
+file miscfs/procfs/procfs_eproc.c procfs
file miscfs/procfs/procfs_status.c procfs
file miscfs/procfs/procfs_subr.c procfs
file miscfs/procfs/procfs_vfsops.c procfs
diff --git a/sys/dev/audio.c b/sys/dev/audio.c
index de2ce90db06..e05a3af02df 100644
--- a/sys/dev/audio.c
+++ b/sys/dev/audio.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: audio.c,v 1.11 1998/04/25 04:57:13 millert Exp $ */
-/* $NetBSD: audio.c,v 1.26 1996/05/13 02:26:15 mycroft Exp $ */
+/* $OpenBSD: audio.c,v 1.12 1998/04/26 21:03:06 provos Exp $ */
+/* $NetBSD: audio.c,v 1.71 1997/09/06 01:14:48 augustss Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -57,11 +57,8 @@
/*
* Todo:
- * - Add softaudio() isr processing for wakeup, select and signals.
- * - Allow opens for READ and WRITE (one open each)
- * - Setup for single isr for full-duplex
- * - Add SIGIO generation for changes in the mixer device
- * - Fixup SunOS compat for mixer device changes in ioctl.
+ * - Add softaudio() isr processing for wakeup, poll, signals,
+ * and silence fill.
*/
#include "audio.h"
@@ -72,6 +69,7 @@
#include <sys/fcntl.h>
#include <sys/vnode.h>
#include <sys/select.h>
+#include <sys/poll.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/systm.h>
@@ -80,42 +78,26 @@
#include <sys/signalvar.h>
#include <sys/conf.h>
#include <sys/audioio.h>
+#include <sys/device.h>
-#include <dev/audiovar.h>
#include <dev/audio_if.h>
+#include <dev/audiovar.h>
-#ifdef AUDIO_DEBUG
-#include <machine/stdarg.h>
+#include <vm/vm.h>
+#include <vm/vm_prot.h>
-void Dprintf __P((const char *, ...));
+#include <machine/endian.h>
-void
-#ifdef __STDC__
-Dprintf(const char *fmt, ...)
-#else
-Dprintf(fmt, va_alist)
- char *fmt;
-#endif
-{
- va_list ap;
-
- va_start(ap, fmt);
- log(LOG_DEBUG, "%:", fmt, ap);
- va_end(ap);
-}
-
-#define DPRINTF(x) if (audiodebug) Dprintf x
+#ifdef AUDIO_DEBUG
+#define DPRINTF(x) if (audiodebug) printf x
int audiodebug = 0;
#else
#define DPRINTF(x)
#endif
-int naudio; /* Count of attached hardware drivers */
+#define ROUNDSIZE(x) x &= -16 /* round to nice boundary */
-int audio_blk_ms = AUDIO_BLK_MS;
-int audio_backlog = AUDIO_BACKLOG;
-
-struct audio_softc *audio_softc[NAUDIO];
+int audio_blk_ms = AUDIO_BLK_MS;
int audiosetinfo __P((struct audio_softc *, struct audio_info *));
int audiogetinfo __P((struct audio_softc *, struct audio_info *));
@@ -131,174 +113,388 @@ int audio_mmap __P((dev_t, int, int));
int mixer_open __P((dev_t, int, int, struct proc *));
int mixer_close __P((dev_t, int, int, struct proc *));
int mixer_ioctl __P((dev_t, int, caddr_t, int, struct proc *));
+static void mixer_remove __P((struct audio_softc *, struct proc *p));
+static void mixer_signal __P((struct audio_softc *));
void audio_init_record __P((struct audio_softc *));
void audio_init_play __P((struct audio_softc *));
-void audiostartr __P((struct audio_softc *));
-void audiostartp __P((struct audio_softc *));
+int audiostartr __P((struct audio_softc *));
+int audiostartp __P((struct audio_softc *));
void audio_rint __P((void *));
void audio_pint __P((void *));
-void audio_rpint __P((void *));
-int audio_check_format __P((u_int *, u_int *));
+int audio_check_params __P((struct audio_params *));
-int audio_calc_blksize __P((struct audio_softc *));
-void audio_fill_silence __P((int, u_char *, int));
+void audio_calc_blksize __P((struct audio_softc *, int));
+void audio_fill_silence __P((struct audio_params *, u_char *, int));
int audio_silence_copyout __P((struct audio_softc *, int, struct uio *));
-void audio_alloc_auzero __P((struct audio_softc *, int));
-void audio_printsc __P((struct audio_softc *));
-void audioattach __P((int));
-int audio_hardware_attach __P((struct audio_hw_if *, void *));
-void audio_init_ring __P((struct audio_buffer *, int));
-void audio_initbufs __P((struct audio_softc *));
+void audio_init_ringbuffer __P((struct audio_ringbuffer *));
+int audio_initbufs __P((struct audio_softc *));
+void audio_calcwater __P((struct audio_softc *));
static __inline int audio_sleep_timo __P((int *, char *, int));
static __inline int audio_sleep __P((int *, char *));
static __inline void audio_wakeup __P((int *));
int audio_drain __P((struct audio_softc *));
void audio_clear __P((struct audio_softc *));
+static __inline void audio_pint_silence __P((struct audio_softc *, struct audio_ringbuffer *, u_char *, int));
-#ifdef AUDIO_DEBUG
-void
-audio_printsc(sc)
- struct audio_softc *sc;
-{
- printf("hwhandle %p hw_if %p ", sc->hw_hdl, sc->hw_if);
- printf("open %x mode %x\n", sc->sc_open, sc->sc_mode);
- printf("rchan %x wchan %x ", sc->sc_rchan, sc->sc_wchan);
- printf("rring blk %x pring nblk %x\n", sc->rr.nblk, sc->pr.nblk);
- printf("rbus %x pbus %x ", sc->sc_rbus, sc->sc_pbus);
- printf("blksz %d sib %d ", sc->sc_blksize, sc->sc_smpl_in_blk);
- printf("sp50ms %d backlog %d\n", sc->sc_50ms, sc->sc_backlog);
- printf("hiwat %d lowat %d rblks %d\n", sc->sc_hiwat, sc->sc_lowat,
- sc->sc_rblks);
-}
+int audio_alloc_ring __P((struct audio_softc *, struct audio_ringbuffer *, int));
+void audio_free_ring __P((struct audio_softc *, struct audio_ringbuffer *));
+
+int audioprint __P((void *, const char *));
+
+#define __BROKEN_INDIRECT_CONFIG /* XXX */
+#ifdef __BROKEN_INDIRECT_CONFIG
+int audioprobe __P((struct device *, void *, void *));
+#else
+int audioprobe __P((struct device *, struct cfdata *, void *));
#endif
+void audioattach __P((struct device *, struct device *, void *));
+
+struct portname {
+ char *name;
+ int mask;
+};
+static struct portname itable[] = {
+ { AudioNmicrophone, AUDIO_MICROPHONE },
+ { AudioNline, AUDIO_LINE_IN },
+ { AudioNcd, AUDIO_CD },
+ { 0 }
+};
+static struct portname otable[] = {
+ { AudioNspeaker, AUDIO_SPEAKER },
+ { AudioNheadphone, AUDIO_HEADPHONE },
+ { AudioNline, AUDIO_LINE_OUT },
+ { 0 }
+};
+void au_check_ports __P((struct audio_softc *, struct au_mixer_ports *,
+ mixer_devinfo_t *, int, char *, char *,
+ struct portname *));
+int au_set_gain __P((struct audio_softc *, struct au_mixer_ports *,
+ int, int));
+void au_get_gain __P((struct audio_softc *, struct au_mixer_ports *,
+ u_int *, u_char *));
+int au_set_port __P((struct audio_softc *, struct au_mixer_ports *,
+ u_int));
+int au_get_port __P((struct audio_softc *, struct au_mixer_ports *));
+int au_get_lr_value __P((struct audio_softc *, mixer_ctrl_t *,
+ int *, int *r));
+int au_set_lr_value __P((struct audio_softc *, mixer_ctrl_t *,
+ int, int));
+int au_portof __P((struct audio_softc *, char *));
+
+
+/* The default audio mode: 8 kHz mono ulaw */
+struct audio_params audio_default =
+ { 8000, AUDIO_ENCODING_ULAW, 8, 1, 0, 1 };
+
+struct cfattach audio_ca = {
+ sizeof(struct audio_softc), audioprobe, audioattach
+};
+
+struct cfdriver audio_cd = {
+ NULL, "audio", DV_DULL
+};
-void
-audioattach(num)
- int num;
+int
+audioprobe(parent, match, aux)
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
{
+ struct audio_attach_args *sa = aux;
+
+ DPRINTF(("audioprobe: type=%d sa=%p hw=%p\n",
+ sa->type, sa, sa->hwif));
+ return (sa->type == AUDIODEV_TYPE_AUDIO) ? 1 : 0;
}
-/*
- * Called from hardware driver.
- */
-int
-audio_hardware_attach(hwp, hdlp)
- struct audio_hw_if *hwp;
- void *hdlp;
+void
+audioattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
{
- struct audio_softc *sc;
-
- if (naudio >= NAUDIO) {
- DPRINTF(("audio_hardware_attach: not enough audio devices: %d > %d\n",
- naudio, NAUDIO));
- return(EINVAL);
- }
+ struct audio_softc *sc = (void *)self;
+ struct audio_attach_args *sa = aux;
+ struct audio_hw_if *hwp = sa->hwif;
+ void *hdlp = sa->hdl;
+ int error;
+ mixer_devinfo_t mi;
+ int iclass, oclass;
- /*
- * Malloc a softc for the device
- */
- /* XXX Find the first free slot */
- audio_softc[naudio] = malloc(sizeof(struct audio_softc), M_DEVBUF, M_WAITOK);
- sc = audio_softc[naudio];
- bzero(sc, sizeof(struct audio_softc));
+ printf("\n");
- /* XXX too paranoid? */
- if (hwp->open == 0 ||
+#ifdef DIAGNOSTIC
+ if (hwp == 0 ||
+ hwp->open == 0 ||
hwp->close == 0 ||
- hwp->set_in_sr == 0 ||
- hwp->get_in_sr == 0 ||
- hwp->set_out_sr == 0 ||
- hwp->get_out_sr == 0 ||
- hwp->set_format == 0 ||
- hwp->get_encoding == 0 ||
- hwp->get_precision == 0 ||
- hwp->set_channels == 0 ||
- hwp->get_channels == 0 ||
- hwp->round_blocksize == 0 ||
- hwp->set_out_port == 0 ||
- hwp->get_out_port == 0 ||
- hwp->set_in_port == 0 ||
- hwp->get_in_port == 0 ||
- hwp->commit_settings == 0 ||
+ hwp->query_encoding == 0 ||
+ hwp->set_params == 0 ||
hwp->start_output == 0 ||
hwp->start_input == 0 ||
hwp->halt_output == 0 ||
hwp->halt_input == 0 ||
- hwp->cont_output == 0 ||
- hwp->cont_input == 0 ||
hwp->getdev == 0 ||
hwp->set_port == 0 ||
hwp->get_port == 0 ||
- hwp->query_devinfo == 0)
- return(EINVAL);
+ hwp->query_devinfo == 0 ||
+ hwp->get_props == 0) {
+ printf("audio: missing method\n");
+ sc->hw_if = 0;
+ return;
+ }
+#endif
sc->hw_if = hwp;
sc->hw_hdl = hdlp;
-
- /*
- * Alloc DMA play and record buffers
- */
- sc->rr.bp = malloc(AU_RING_SIZE, M_DEVBUF, M_WAITOK);
- if (sc->rr.bp == 0) {
- return (ENOMEM);
+ sc->sc_dev = parent;
+
+ error = audio_alloc_ring(sc, &sc->sc_pr, AU_RING_SIZE);
+ if (error) {
+ sc->hw_if = 0;
+ return;
}
- sc->pr.bp = malloc(AU_RING_SIZE, M_DEVBUF, M_WAITOK);
- if (sc->pr.bp == 0) {
- free(sc->rr.bp, M_DEVBUF);
- return (ENOMEM);
+ error = audio_alloc_ring(sc, &sc->sc_rr, AU_RING_SIZE);
+ if (error) {
+ audio_free_ring(sc, &sc->sc_pr);
+ sc->hw_if = 0;
+ return;
}
-
+
/*
* Set default softc params
*/
- sc->sc_pencoding = sc->sc_rencoding = AUDIO_ENCODING_LINEAR;
+ sc->sc_pparams = audio_default;
+ sc->sc_rparams = audio_default;
+
+ /* Set up some default values */
+ sc->sc_blkset = 0;
+ audio_calc_blksize(sc, AUMODE_RECORD);
+ audio_calc_blksize(sc, AUMODE_PLAY);
+ audio_init_ringbuffer(&sc->sc_rr);
+ audio_init_ringbuffer(&sc->sc_pr);
+ audio_calcwater(sc);
+
+ iclass = oclass = -1;
+ sc->sc_inports.index = -1;
+ sc->sc_inports.nports = 0;
+ sc->sc_inports.isenum = 0;
+ sc->sc_inports.allports = 0;
+ sc->sc_outports.index = -1;
+ sc->sc_outports.nports = 0;
+ sc->sc_outports.isenum = 0;
+ sc->sc_outports.allports = 0;
+ sc->sc_monitor_port = -1;
+ for(mi.index = 0; ; mi.index++) {
+ if (hwp->query_devinfo(hdlp, &mi) != 0)
+ break;
+ if (mi.type == AUDIO_MIXER_CLASS &&
+ strcmp(mi.label.name, AudioCrecord) == 0)
+ iclass = mi.index;
+ if (mi.type == AUDIO_MIXER_CLASS &&
+ strcmp(mi.label.name, AudioCmonitor) == 0)
+ oclass = mi.index;
+ }
+ for(mi.index = 0; ; mi.index++) {
+ if (hwp->query_devinfo(hdlp, &mi) != 0)
+ break;
+ au_check_ports(sc, &sc->sc_inports, &mi, iclass,
+ AudioNsource, AudioNrecord, itable);
+ au_check_ports(sc, &sc->sc_outports, &mi, oclass,
+ AudioNoutput, AudioNmaster, otable);
+ if (mi.mixer_class == oclass &&
+ strcmp(mi.label.name, AudioNmonitor))
+ sc->sc_monitor_port = mi.index;
+ }
+ DPRINTF(("audio_attach: inputs ports=0x%x, output ports=0x%x\n",
+ sc->sc_inports.allports, sc->sc_outports.allports));
+}
- /*
- * Return the audio unit number
- */
- hwp->audio_unit = naudio++;
+int
+au_portof(sc, name)
+ struct audio_softc *sc;
+ char *name;
+{
+ mixer_devinfo_t mi;
+
+ for(mi.index = 0;
+ sc->hw_if->query_devinfo(sc->hw_hdl, &mi) == 0;
+ mi.index++)
+ if (strcmp(mi.label.name, name) == 0)
+ return mi.index;
+ return -1;
+}
-#ifdef AUDIO_DEBUG
- printf("audio: unit %d attached\n", hwp->audio_unit);
-#endif
-
- return(0);
+void
+au_check_ports(sc, ports, mi, cls, name, mname, tbl)
+ struct audio_softc *sc;
+ struct au_mixer_ports *ports;
+ mixer_devinfo_t *mi;
+ int cls;
+ char *name;
+ char *mname;
+ struct portname *tbl;
+{
+ int i, j;
+
+ if (mi->mixer_class != cls)
+ return;
+ if (strcmp(mi->label.name, mname) == 0) {
+ ports->master = mi->index;
+ return;
+ }
+ if (strcmp(mi->label.name, name) != 0)
+ return;
+ if (mi->type == AUDIO_MIXER_ENUM) {
+ ports->index = mi->index;
+ for(i = 0; tbl[i].name; i++) {
+ for(j = 0; j < mi->un.e.num_mem; j++) {
+ if (strcmp(mi->un.e.member[j].label.name,
+ tbl[i].name) == 0) {
+ ports->aumask[ports->nports] = tbl[i].mask;
+ ports->misel [ports->nports] = mi->un.e.member[j].ord;
+ ports->miport[ports->nports++] =
+ au_portof(sc, mi->un.e.member[j].label.name);
+ ports->allports |= tbl[i].mask;
+ }
+ }
+ }
+ ports->isenum = 1;
+ } else if (mi->type == AUDIO_MIXER_SET) {
+ ports->index = mi->index;
+ for(i = 0; tbl[i].name; i++) {
+ for(j = 0; j < mi->un.s.num_mem; j++) {
+ if (strcmp(mi->un.s.member[j].label.name,
+ tbl[i].name) == 0) {
+ ports->aumask[ports->nports] = tbl[i].mask;
+ ports->misel [ports->nports] = mi->un.s.member[j].mask;
+ ports->miport[ports->nports++] =
+ au_portof(sc, mi->un.s.member[j].label.name);
+ ports->allports |= tbl[i].mask;
+ }
+ }
+ }
+ }
}
-int
-audio_hardware_detach(hwp)
- struct audio_hw_if *hwp;
+/*
+ * Called from hardware driver. This is where the MI audio driver gets
+ * probed/attached to the hardware driver.
+ */
+void
+audio_attach_mi(ahwp, mhwp, hdlp, dev)
+ struct audio_hw_if *ahwp;
+ struct midi_hw_if *mhwp;
+ void *hdlp;
+ struct device *dev;
{
- struct audio_softc *sc;
-
-#ifdef DIAGNOSTIC
- if (!hwp)
- panic("audio_hardware_detach: null hwp");
-
- if (hwp->audio_unit > naudio)
- panic("audio_hardware_detach: invalid audio unit");
-#endif
+ struct audio_attach_args arg;
+
+ if (ahwp != NULL) {
+ arg.type = AUDIODEV_TYPE_AUDIO;
+ arg.hwif = ahwp;
+ arg.hdl = hdlp;
+ (void)config_found(dev, &arg, audioprint);
+ }
+ if (mhwp != NULL) {
+ arg.type = AUDIODEV_TYPE_MIDI;
+ arg.hwif = mhwp;
+ arg.hdl = hdlp;
+ (void)config_found(dev, &arg, audioprint);
+ }
+}
- sc = audio_softc[hwp->audio_unit];
+int
+audioprint(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct audio_attach_args *arg = aux;
+ const char *type;
+
+ if (pnp != NULL) {
+ switch (arg->type) {
+ case AUDIODEV_TYPE_AUDIO:
+ type = "audio";
+ break;
+ case AUDIODEV_TYPE_MIDI:
+ type = "midi";
+ break;
+ default:
+ panic("audioprint: unknown type %d", arg->type);
+ }
+ printf("%s at %s", type, pnp);
+ }
+ return (UNCONF);
+}
- if (hwp != sc->hw_if)
- return(EINVAL);
-
- if (sc->sc_open != 0)
- return(EBUSY);
+#ifdef AUDIO_DEBUG
+void audio_printsc __P((struct audio_softc *));
+void audio_print_params __P((char *, struct audio_params *));
- sc->hw_if = 0;
+void
+audio_printsc(sc)
+ struct audio_softc *sc;
+{
+ printf("hwhandle %p hw_if %p ", sc->hw_hdl, sc->hw_if);
+ printf("open 0x%x mode 0x%x\n", sc->sc_open, sc->sc_mode);
+ printf("rchan 0x%x wchan 0x%x ", sc->sc_rchan, sc->sc_wchan);
+ printf("rring used 0x%x pring used=%d\n", sc->sc_rr.used, sc->sc_pr.used);
+ printf("rbus 0x%x pbus 0x%x ", sc->sc_rbus, sc->sc_pbus);
+ printf("blksize %d", sc->sc_pr.blksize);
+ printf("hiwat %d lowat %d\n", sc->sc_pr.usedhigh, sc->sc_pr.usedlow);
+}
- /* Free audio buffers */
- free(sc->rr.bp, M_DEVBUF);
- free(sc->pr.bp, M_DEVBUF);
+void
+audio_print_params(s, p)
+ char *s;
+ struct audio_params *p;
+{
+ printf("audio: %s sr=%ld, enc=%d, chan=%d, prec=%d\n", s,
+ p->sample_rate, p->encoding, p->channels, p->precision);
+}
+#endif
- free(sc, M_DEVBUF);
- audio_softc[hwp->audio_unit] = NULL;
+int
+audio_alloc_ring(sc, r, bufsize)
+ struct audio_softc *sc;
+ struct audio_ringbuffer *r;
+ int bufsize;
+{
+ struct audio_hw_if *hw = sc->hw_if;
+ void *hdl = sc->hw_hdl;
+ /*
+ * Alloc DMA play and record buffers
+ */
+ ROUNDSIZE(bufsize);
+ if (bufsize < AUMINBUF)
+ bufsize = AUMINBUF;
+ if (hw->round_buffersize)
+ bufsize = hw->round_buffersize(hdl, bufsize);
+ r->bufsize = bufsize;
+ if (hw->alloc)
+ r->start = hw->alloc(hdl, r->bufsize, M_DEVBUF, M_WAITOK);
+ else
+ r->start = malloc(bufsize, M_DEVBUF, M_WAITOK);
+ if (r->start == 0)
+ return ENOMEM;
+ return 0;
+}
- return(0);
+void
+audio_free_ring(sc, r)
+ struct audio_softc *sc;
+ struct audio_ringbuffer *r;
+{
+ if (sc->hw_if->free) {
+ sc->hw_if->free(sc->hw_hdl, r->start, M_DEVBUF);
+ } else {
+ free(r->start, M_DEVBUF);
+ }
}
int
@@ -311,6 +507,7 @@ audioopen(dev, flags, ifmt, p)
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
+ case AUDIOCTL_DEVICE:
return (audio_open(dev, flags, ifmt, p));
case MIXER_DEVICE:
return (mixer_open(dev, flags, ifmt, p));
@@ -332,6 +529,8 @@ audioclose(dev, flags, ifmt, p)
return (audio_close(dev, flags, ifmt, p));
case MIXER_DEVICE:
return (mixer_close(dev, flags, ifmt, p));
+ case AUDIOCTL_DEVICE:
+ return 0;
default:
return (ENXIO);
}
@@ -348,6 +547,7 @@ audioread(dev, uio, ioflag)
case SOUND_DEVICE:
case AUDIO_DEVICE:
return (audio_read(dev, uio, ioflag));
+ case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
return (ENODEV);
default:
@@ -366,6 +566,7 @@ audiowrite(dev, uio, ioflag)
case SOUND_DEVICE:
case AUDIO_DEVICE:
return (audio_write(dev, uio, ioflag));
+ case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
return (ENODEV);
default:
@@ -385,6 +586,7 @@ audioioctl(dev, cmd, addr, flag, p)
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
+ case AUDIOCTL_DEVICE:
return (audio_ioctl(dev, cmd, addr, flag, p));
case MIXER_DEVICE:
return (mixer_ioctl(dev, cmd, addr, flag, p));
@@ -404,6 +606,7 @@ audioselect(dev, events, p)
case SOUND_DEVICE:
case AUDIO_DEVICE:
return (audio_select(dev, events, p));
+ case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
return (0);
default:
@@ -416,15 +619,15 @@ audiommap(dev, off, prot)
dev_t dev;
int off, prot;
{
-
switch (AUDIODEV(dev)) {
case SOUND_DEVICE:
case AUDIO_DEVICE:
return (audio_mmap(dev, off, prot));
+ case AUDIOCTL_DEVICE:
case MIXER_DEVICE:
- return (ENODEV);
+ return -1;
default:
- return (ENXIO);
+ return -1;
}
}
@@ -432,30 +635,91 @@ audiommap(dev, off, prot)
* Audio driver
*/
void
-audio_init_ring(rp, blksize)
- struct audio_buffer *rp;
- int blksize;
+audio_init_ringbuffer(rp)
+ struct audio_ringbuffer *rp;
{
- int nblk = AU_RING_SIZE / blksize;
-
- rp->ep = rp->bp + nblk * blksize;
- rp->hp = rp->tp = rp->bp;
- rp->maxblk = nblk;
- rp->nblk = 0;
- rp->cb_drops = 0;
- rp->cb_pdrops = 0;
+ int nblks;
+ int blksize = rp->blksize;
+
+ if (blksize < AUMINBLK)
+ blksize = AUMINBLK;
+ nblks = rp->bufsize / blksize;
+ if (nblks < AUMINNOBLK) {
+ nblks = AUMINNOBLK;
+ blksize = rp->bufsize / nblks;
+ ROUNDSIZE(blksize);
+ }
+ DPRINTF(("audio_init_ringbuffer: blksize=%d\n", blksize));
+ rp->blksize = blksize;
+ rp->maxblks = nblks;
+ rp->used = 0;
+ rp->end = rp->start + nblks * blksize;
+ rp->inp = rp->outp = rp->start;
+ rp->stamp = 0;
+ rp->drops = 0;
+ rp->pause = 0;
+ rp->copying = 0;
+ rp->needfill = 0;
+ rp->mmapped = 0;
}
-void
+int
audio_initbufs(sc)
struct audio_softc *sc;
{
- int nblk = AU_RING_SIZE / sc->sc_blksize;
+ struct audio_hw_if *hw = sc->hw_if;
+ int error;
- audio_init_ring(&sc->rr, sc->sc_blksize);
- audio_init_ring(&sc->pr, sc->sc_blksize);
- sc->sc_lowat = nblk / 2;
- sc->sc_hiwat = nblk;
+ DPRINTF(("audio_initbufs: mode=0x%x\n", sc->sc_mode));
+ audio_init_ringbuffer(&sc->sc_rr);
+ if (hw->init_input && (sc->sc_mode & AUMODE_RECORD)) {
+ error = hw->init_input(sc->hw_hdl, sc->sc_rr.start,
+ sc->sc_rr.end - sc->sc_rr.start);
+ if (error)
+ return error;
+ }
+
+ audio_init_ringbuffer(&sc->sc_pr);
+ sc->sc_sil_count = 0;
+ if (hw->init_output && (sc->sc_mode & AUMODE_PLAY)) {
+ error = hw->init_output(sc->hw_hdl, sc->sc_pr.start,
+ sc->sc_pr.end - sc->sc_pr.start);
+ if (error)
+ return error;
+ }
+
+#ifdef AUDIO_INTR_TIME
+ sc->sc_pnintr = 0;
+ sc->sc_pblktime = (u_long)(
+ (double)sc->sc_pr.blksize * 1e6 /
+ (double)(sc->sc_pparams.precision / NBBY *
+ sc->sc_pparams.channels *
+ sc->sc_pparams.sample_rate));
+ DPRINTF(("audio: play blktime = %lu for %d\n",
+ sc->sc_pblktime, sc->sc_pr.blksize));
+ sc->sc_rnintr = 0;
+ sc->sc_rblktime = (u_long)(
+ (double)sc->sc_rr.blksize * 1e6 /
+ (double)(sc->sc_rparams.precision / NBBY *
+ sc->sc_rparams.channels *
+ sc->sc_rparams.sample_rate));
+ DPRINTF(("audio: record blktime = %lu for %d\n",
+ sc->sc_rblktime, sc->sc_rr.blksize));
+#endif
+
+ return 0;
+}
+
+void
+audio_calcwater(sc)
+ struct audio_softc *sc;
+{
+ sc->sc_pr.usedhigh = sc->sc_pr.end - sc->sc_pr.start;
+ sc->sc_pr.usedlow = sc->sc_pr.usedhigh * 3 / 4; /* set lowater at 75% */
+ if (sc->sc_pr.usedlow == sc->sc_pr.usedhigh)
+ sc->sc_pr.usedlow -= sc->sc_pr.blksize;
+ sc->sc_rr.usedhigh = sc->sc_pr.end - sc->sc_pr.start - sc->sc_pr.blksize;
+ sc->sc_rr.usedlow = 0;
}
static __inline int
@@ -468,13 +732,14 @@ audio_sleep_timo(chan, label, timo)
if (!label)
label = "audio";
-
+
*chan = 1;
- st = (tsleep(chan, PWAIT | PCATCH, label, timo));
+ st = tsleep(chan, PWAIT | PCATCH, label, timo);
*chan = 0;
- if (st != 0) {
- DPRINTF(("audio_sleep: %d\n", st));
- }
+#ifdef AUDIO_DEBUG
+ if (st != 0)
+ printf("audio_sleep: %d\n", st);
+#endif
return (st);
}
@@ -483,9 +748,10 @@ audio_sleep(chan, label)
int *chan;
char *label;
{
- return audio_sleep_timo(chan, label, 0);
+ return audio_sleep_timo(chan, label, 0);
}
+/* call at splaudio() */
static __inline void
audio_wakeup(chan)
int *chan;
@@ -504,31 +770,56 @@ audio_open(dev, flags, ifmt, p)
{
int unit = AUDIOUNIT(dev);
struct audio_softc *sc;
- int s, error;
+ int error;
+ int mode;
struct audio_hw_if *hw;
+ struct audio_info ai;
- if (unit >= NAUDIO || !audio_softc[unit]) {
- DPRINTF(("audio_open: invalid device unit - %d\n", unit));
- return (ENODEV);
- }
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
- sc = audio_softc[unit];
hw = sc->hw_if;
+ if (!hw)
+ return ENXIO;
- DPRINTF(("audio_open: dev=0x%x flags=0x%x sc=0x%x hdl=0x%x\n", dev, flags, sc, sc->hw_hdl));
- if (hw == 0) /* Hardware has not attached to us... */
- return (ENXIO);
+ DPRINTF(("audio_open: dev=0x%x flags=0x%x sc=%p hdl=%p\n", dev, flags, sc, sc->hw_hdl));
- if ((sc->sc_open & (AUOPEN_READ|AUOPEN_WRITE)) != 0) /* XXX use flags */
+ if (ISDEVAUDIOCTL(dev))
+ return 0;
+
+ if ((sc->sc_open & (AUOPEN_READ|AUOPEN_WRITE)) != 0)
return (EBUSY);
- if ((error = hw->open(dev, flags)) != 0)
+ error = hw->open(sc->hw_hdl, flags);
+ if (error)
return (error);
- if (flags&FREAD)
+ sc->sc_async_audio = 0;
+ sc->sc_rchan = 0;
+ sc->sc_wchan = 0;
+ sc->sc_blkset = 0; /* Block sizes not set yet */
+ sc->sc_sil_count = 0;
+ sc->sc_rbus = 0;
+ sc->sc_pbus = 0;
+ sc->sc_eof = 0;
+ sc->sc_playdrop = 0;
+
+ sc->sc_full_duplex = 0;
+/* doesn't always work right on SB.
+ (flags & (FWRITE|FREAD)) == (FWRITE|FREAD) &&
+ (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX);
+*/
+
+ mode = 0;
+ if (flags & FREAD) {
sc->sc_open |= AUOPEN_READ;
- if (flags&FWRITE)
+ mode |= AUMODE_RECORD;
+ }
+ if (flags & FWRITE) {
sc->sc_open |= AUOPEN_WRITE;
+ mode |= AUMODE_PLAY | AUMODE_PLAY_ALL;
+ }
/*
* Multiplex device: /dev/audio (MU-Law) and /dev/sound (linear)
@@ -537,79 +828,46 @@ audio_open(dev, flags, ifmt, p)
*/
if (ISDEVAUDIO(dev)) {
/* /dev/audio */
- hw->set_format(sc->hw_hdl, AUDIO_ENCODING_ULAW, 8);
- hw->set_in_sr(sc->hw_hdl, 8000);
- hw->set_out_sr(sc->hw_hdl, 8000);
- hw->set_channels(sc->hw_hdl, 1);
-
- sc->sc_pencoding = sc->sc_rencoding = AUDIO_ENCODING_ULAW;
+ sc->sc_rparams = audio_default;
+ sc->sc_pparams = audio_default;
}
-
+#ifdef DIAGNOSTIC
/*
* Sample rate and precision are supposed to be set to proper
* default values by the hardware driver, so that it may give
* us these values.
*/
-#ifdef DIAGNOSTIC
- if (hw->get_precision(sc->hw_hdl) == 0)
- panic("audio_open: hardware driver returned 0 for get_precision");
+ if (sc->sc_rparams.precision == 0 || sc->sc_pparams.precision == 0) {
+ printf("audio_open: 0 precision\n");
+ return EINVAL;
+ }
#endif
- sc->sc_50ms = 50 * hw->get_out_sr(sc->hw_hdl) / 1000;
-
- sc->sc_blksize = audio_calc_blksize(sc);
- audio_alloc_auzero(sc, sc->sc_blksize);
- sc->sc_smpl_in_blk = sc->sc_blksize /
- (hw->get_precision(sc->hw_hdl) / NBBY);
- audio_initbufs(sc);
- sc->sc_backlog = audio_backlog;
+ AUDIO_INITINFO(&ai);
+ ai.record.sample_rate = sc->sc_rparams.sample_rate;
+ ai.record.encoding = sc->sc_rparams.encoding;
+ ai.record.channels = sc->sc_rparams.channels;
+ ai.record.precision = sc->sc_rparams.precision;
+ ai.play.sample_rate = sc->sc_pparams.sample_rate;
+ ai.play.encoding = sc->sc_pparams.encoding;
+ ai.play.channels = sc->sc_pparams.channels;
+ ai.play.precision = sc->sc_pparams.precision;
+ ai.mode = mode;
+ sc->sc_pr.blksize = sc->sc_rr.blksize = 0; /* force recalculation */
+ error = audiosetinfo(sc, &ai);
+ if (error)
+ goto bad;
- DPRINTF(("audio_open: rr.bp=%x-%x pr.bp=%x-%x\n",
- sc->rr.bp, sc->rr.ep, sc->pr.bp, sc->pr.ep));
+ DPRINTF(("audio_open: done sc_mode = 0x%x\n", sc->sc_mode));
- hw->commit_settings(sc->hw_hdl);
-
- s = splaudio();
-
- /* nothing read or written yet */
- sc->sc_rseek = 0;
- sc->sc_wseek = 0;
-
- sc->sc_rchan = 0;
- sc->sc_wchan = 0;
+ return 0;
- sc->sc_rbus = 0;
- sc->sc_pbus = 0;
-
- if ((flags & FWRITE) != 0) {
- audio_init_play(sc);
- /* audio_pint(sc); ??? */
- }
- if ((flags & FREAD) != 0) {
- /* Play takes precedence if HW is half-duplex */
- if (hw->full_duplex || ((flags & FWRITE) == 0)) {
- audio_init_record(sc);
- /* audiostartr(sc); don't start recording until read */
- }
- }
- if (ISDEVAUDIO(dev)) {
- /* if open only for read or only for write, then set specific mode */
- if ((flags & (FWRITE|FREAD)) == FWRITE) {
- sc->sc_mode = AUMODE_PLAY;
- sc->pr.cb_pause = 0;
- sc->rr.cb_pause = 1;
- audiostartp(sc);
- } else if ((flags & (FWRITE|FREAD)) == FREAD) {
- sc->sc_mode = AUMODE_RECORD;
- sc->rr.cb_pause = 0;
- sc->pr.cb_pause = 1;
- audiostartr(sc);
- }
- }
- /* Play all sample, and don't pad short writes by default */
- sc->sc_mode |= AUMODE_PLAY_ALL;
- splx(s);
- return (0);
+bad:
+ hw->close(sc->hw_hdl);
+ sc->sc_open = 0;
+ sc->sc_mode = 0;
+ sc->sc_full_duplex = 0;
+ return error;
}
/*
@@ -621,9 +879,8 @@ audio_init_record(sc)
{
int s = splaudio();
- sc->sc_mode |= AUMODE_RECORD;
if (sc->hw_if->speaker_ctl &&
- (!sc->hw_if->full_duplex || (sc->sc_mode & AUMODE_PLAY) == 0))
+ (!sc->sc_full_duplex || (sc->sc_mode & AUMODE_PLAY) == 0))
sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_OFF);
splx(s);
}
@@ -637,8 +894,7 @@ audio_init_play(sc)
{
int s = splaudio();
- sc->sc_mode |= AUMODE_PLAY;
- sc->sc_rblks = sc->sc_wblks = 0;
+ sc->sc_wstamp = sc->sc_pr.stamp;
if (sc->hw_if->speaker_ctl)
sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_ON);
splx(s);
@@ -648,21 +904,57 @@ int
audio_drain(sc)
struct audio_softc *sc;
{
- int error;
+ int error, drops;
+ struct audio_ringbuffer *cb = &sc->sc_pr;
+ int s;
- while (sc->pr.nblk > 0) {
- DPRINTF(("audio_drain: nblk=%d\n", sc->pr.nblk));
+ if (sc->sc_pr.mmapped || sc->sc_pr.used <= 0)
+ return 0;
+ if (!sc->sc_pbus) {
+ /* We've never started playing, probably because the
+ * block was too short. Pad it and start now.
+ */
+ int cc;
+ u_char *inp = cb->inp;
+
+ cc = cb->blksize - (inp - cb->start) % cb->blksize;
+ audio_fill_silence(&sc->sc_pparams, inp, cc);
+ inp += cc;
+ if (inp >= cb->end)
+ inp = cb->start;
+ s = splaudio();
+ cb->used += cc;
+ cb->inp = inp;
+ error = audiostartp(sc);
+ splx(s);
+ if (error)
+ return error;
+ }
+ /*
+ * Play until a silence block has been played, then we
+ * know all has been drained.
+ * XXX This should be done some other way to avoid
+ * playing silence.
+ */
+#ifdef DIAGNOSTIC
+ if (cb->copying) {
+ printf("audio_drain: copying in progress!?!\n");
+ cb->copying = 0;
+ }
+#endif
+ drops = cb->drops;
+ error = 0;
+ s = splaudio();
+ while (cb->drops == drops && !error) {
+ DPRINTF(("audio_drain: used=%d, drops=%ld\n", sc->sc_pr.used, cb->drops));
/*
- * XXX
* When the process is exiting, it ignores all signals and
- * we can't interrupt this sleep, so we set a 1-minute
- * timeout.
+ * we can't interrupt this sleep, so we set a timeout just in case.
*/
- error = audio_sleep_timo(&sc->sc_wchan, "aud_dr", 60*hz);
- if (error)
- return (error);
+ error = audio_sleep_timo(&sc->sc_wchan, "aud_dr", 30*hz);
}
- return (0);
+ splx(s);
+ return error;
}
/*
@@ -676,34 +968,47 @@ audio_close(dev, flags, ifmt, p)
struct proc *p;
{
int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = audio_softc[unit];
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
struct audio_hw_if *hw = sc->hw_if;
int s;
DPRINTF(("audio_close: unit=%d\n", unit));
+ /* Stop recording. */
+ if (sc->sc_rbus) {
+ /*
+ * XXX Some drivers (e.g. SB) use the same routine
+ * to halt input and output so don't halt input if
+ * in full duplex mode. These drivers should be fixed.
+ */
+ if (!sc->sc_full_duplex || sc->hw_if->halt_input != sc->hw_if->halt_output)
+ sc->hw_if->halt_input(sc->hw_hdl);
+ sc->sc_rbus = 0;
+ }
/*
* Block until output drains, but allow ^C interrupt.
*/
- sc->sc_lowat = 0; /* avoid excessive wakeups */
+ sc->sc_pr.usedlow = sc->sc_pr.blksize; /* avoid excessive wakeups */
s = splaudio();
/*
* If there is pending output, let it drain (unless
* the output is paused).
*/
- if (sc->sc_pbus && sc->pr.nblk > 0 && !sc->pr.cb_pause) {
+ if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_pr.pause) {
if (!audio_drain(sc) && hw->drain)
(void)hw->drain(sc->hw_hdl);
}
hw->close(sc->hw_hdl);
- if (flags&FREAD)
+ if (flags & FREAD)
sc->sc_open &= ~AUOPEN_READ;
- if (flags&FWRITE)
+ if (flags & FWRITE)
sc->sc_open &= ~AUOPEN_WRITE;
- sc->sc_async = 0;
+ sc->sc_async_audio = 0;
+ sc->sc_mode = 0;
+ sc->sc_full_duplex = 0;
splx(s);
DPRINTF(("audio_close: done\n"));
@@ -717,83 +1022,110 @@ audio_read(dev, uio, ioflag)
int ioflag;
{
int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = audio_softc[unit];
- struct audio_hw_if *hw = sc->hw_if;
- struct audio_buffer *cb = &sc->rr;
- u_char *hp;
- int blocksize = sc->sc_blksize;
- int error, s;
-
- DPRINTF(("audio_read: cc=%d mode=%d rblks=%d\n",
- uio->uio_resid, sc->sc_mode, sc->sc_rblks));
-
- if (uio->uio_resid == 0)
- return (0);
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
+ struct audio_ringbuffer *cb = &sc->sc_rr;
+ u_char *outp;
+ int error, s, used, cc, n;
- if (uio->uio_resid < blocksize)
- return (EINVAL);
+ if (cb->mmapped)
+ return EINVAL;
- /* First sample we'll read in sample space */
- sc->sc_rseek = cb->au_stamp - AU_RING_LEN(cb);
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_read: cc=%d mode=%d\n", uio->uio_resid, sc->sc_mode);
+#endif
+ error = 0;
/*
* If hardware is half-duplex and currently playing, return
* silence blocks based on the number of blocks we have output.
*/
- if ((!hw->full_duplex) &&
+ if (!sc->sc_full_duplex &&
(sc->sc_mode & AUMODE_PLAY)) {
- do {
+ while (uio->uio_resid > 0 && !error) {
s = splaudio();
- while (sc->sc_rblks <= 0) {
- DPRINTF(("audio_read: sc_rblks=%d\n", sc->sc_rblks));
+ for(;;) {
+ cc = sc->sc_pr.stamp - sc->sc_wstamp;
+ if (cc > 0)
+ break;
+ DPRINTF(("audio_read: stamp=%lu, wstamp=%lu\n",
+ sc->sc_pr.stamp, sc->sc_wstamp));
if (ioflag & IO_NDELAY) {
splx(s);
- return (EWOULDBLOCK);
+ return EWOULDBLOCK;
}
- error = audio_sleep(&sc->sc_rchan, "aud hr");
+ error = audio_sleep(&sc->sc_rchan, "aud_hr");
if (error) {
splx(s);
- return (error);
+ return error;
}
}
splx(s);
- error = audio_silence_copyout(sc, blocksize, uio);
- if (error)
- break;
- s = splaudio();
- --sc->sc_rblks;
- splx(s);
- } while (uio->uio_resid >= blocksize);
+
+ if (uio->uio_resid < cc)
+ cc = uio->uio_resid;
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_read: reading in write mode, cc=%d\n", cc);
+#endif
+ error = audio_silence_copyout(sc, cc, uio);
+ sc->sc_wstamp += cc;
+ }
return (error);
}
- error = 0;
- do {
- while (cb->nblk <= 0) {
+ while (uio->uio_resid > 0 && !error) {
+ s = splaudio();
+ while (cb->used <= 0) {
if (ioflag & IO_NDELAY) {
- error = EWOULDBLOCK;
- return (error);
+ splx(s);
+ return EWOULDBLOCK;
+ }
+ if (!sc->sc_rbus) {
+ error = audiostartr(sc);
+ if (error) {
+ splx(s);
+ return error;
+ }
+ }
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 2)
+ printf("audio_read: sleep used=%d\n", cb->used);
+#endif
+ error = audio_sleep(&sc->sc_rchan, "aud_rd");
+ if (error) {
+ splx(s);
+ return error;
}
- s = splaudio();
- if (!sc->sc_rbus)
- audiostartr(sc);
- error = audio_sleep(&sc->sc_rchan, "aud rd");
- splx(s);
- if (error)
- return (error);
}
- hp = cb->hp;
- if (hw->sw_decode)
- hw->sw_decode(sc->hw_hdl, sc->sc_rencoding, hp, blocksize);
- error = uiomove(hp, blocksize, uio);
- if (error)
- break;
- hp += blocksize;
- if (hp >= cb->ep)
- hp = cb->bp;
- cb->hp = hp;
- --cb->nblk;
- } while (uio->uio_resid >= blocksize);
+ used = cb->used;
+ outp = cb->outp;
+ cb->copying = 1;
+ splx(s);
+ cc = used - cb->usedlow; /* maximum to read */
+ n = cb->end - outp;
+ if (n < cc)
+ cc = n; /* don't read beyond end of buffer */
+
+ if (uio->uio_resid < cc)
+ cc = uio->uio_resid; /* and no more than we want */
+ if (sc->sc_rparams.sw_code)
+ sc->sc_rparams.sw_code(sc->hw_hdl, outp, cc);
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_read: outp=%p, cc=%d\n", outp, cc);
+#endif
+ error = uiomove(outp, cc, uio);
+ used -= cc;
+ outp += cc;
+ if (outp >= cb->end)
+ outp = cb->start;
+ s = splaudio();
+ cb->outp = outp;
+ cb->used = used;
+ cb->copying = 0;
+ splx(s);
+ }
return (error);
}
@@ -803,132 +1135,131 @@ audio_clear(sc)
{
int s = splaudio();
- if (sc->sc_rbus || sc->sc_pbus) {
- sc->hw_if->halt_output(sc->hw_hdl);
+ if (sc->sc_rbus) {
+ audio_wakeup(&sc->sc_rchan);
sc->hw_if->halt_input(sc->hw_hdl);
sc->sc_rbus = 0;
+ }
+ if (sc->sc_pbus) {
+ audio_wakeup(&sc->sc_wchan);
+ sc->hw_if->halt_output(sc->hw_hdl);
sc->sc_pbus = 0;
}
- AU_RING_INIT(&sc->rr);
- AU_RING_INIT(&sc->pr);
- sc->sc_rblks = sc->sc_wblks = 0;
-
splx(s);
}
-int
-audio_calc_blksize(sc)
+void
+audio_calc_blksize(sc, mode)
struct audio_softc *sc;
+ int mode;
{
struct audio_hw_if *hw = sc->hw_if;
+ struct audio_params *parm;
+ struct audio_ringbuffer *rb;
int bs;
+
+ if (sc->sc_blkset)
+ return;
+
+ if (mode == AUMODE_PLAY) {
+ parm = &sc->sc_pparams;
+ rb = &sc->sc_pr;
+ } else {
+ parm = &sc->sc_rparams;
+ rb = &sc->sc_rr;
+ }
- bs = hw->get_out_sr(sc->hw_hdl) * audio_blk_ms / 1000;
- if (bs == 0)
- bs = 1;
- bs *= hw->get_channels(sc->hw_hdl);
- bs *= hw->get_precision(sc->hw_hdl) / NBBY;
- if (bs > AU_RING_SIZE/2)
- bs = AU_RING_SIZE/2;
- bs = hw->round_blocksize(sc->hw_hdl, bs);
- if (bs > AU_RING_SIZE)
- bs = AU_RING_SIZE;
-
- return(bs);
+ bs = parm->sample_rate * audio_blk_ms / 1000 *
+ parm->channels * parm->precision / NBBY *
+ parm->factor;
+ ROUNDSIZE(bs);
+ if (hw->round_blocksize)
+ bs = hw->round_blocksize(sc->hw_hdl, bs);
+ rb->blksize = bs;
+
+ DPRINTF(("audio_calc_blksize: %s blksize=%d\n",
+ mode == AUMODE_PLAY ? "play" : "record", bs));
}
void
-audio_fill_silence(encoding, p, n)
- int encoding;
+audio_fill_silence(params, p, n)
+ struct audio_params *params;
u_char *p;
int n;
{
- u_int auzero;
- u_char *q;
-
- switch (encoding) {
+ u_char auzero0, auzero1 = 0; /* initialize to please gcc */
+ int nfill = 1;
+
+ switch (params->encoding) {
case AUDIO_ENCODING_ULAW:
- auzero = 0x7f;
+ auzero0 = 0x7f;
break;
case AUDIO_ENCODING_ALAW:
- auzero = 0x55;
+ auzero0 = 0x55;
break;
+ case AUDIO_ENCODING_MPEG_L1_STREAM:
+ case AUDIO_ENCODING_MPEG_L1_PACKETS:
+ case AUDIO_ENCODING_MPEG_L1_SYSTEM:
+ case AUDIO_ENCODING_MPEG_L2_STREAM:
+ case AUDIO_ENCODING_MPEG_L2_PACKETS:
+ case AUDIO_ENCODING_MPEG_L2_SYSTEM:
case AUDIO_ENCODING_ADPCM: /* is this right XXX */
- case AUDIO_ENCODING_PCM8:
- case AUDIO_ENCODING_PCM16:
+ case AUDIO_ENCODING_SLINEAR_LE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ auzero0 = 0; /* fortunately this works for both 8 and 16 bits */
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ case AUDIO_ENCODING_ULINEAR_BE:
+ if (params->precision == 16) {
+ nfill = 2;
+ if (params->encoding == AUDIO_ENCODING_ULINEAR_LE) {
+ auzero0 = 0;
+ auzero1 = 0x80;
+ } else {
+ auzero0 = 0x80;
+ auzero1 = 0;
+ }
+ } else
+ auzero0 = 0x80;
+ break;
default:
- auzero = 0; /* fortunately this works for both 8 and 16 bits */
+ DPRINTF(("audio: bad encoding %d\n", params->encoding));
+ auzero0 = 0;
break;
}
- q = p;
- while (--n >= 0)
- *q++ = auzero;
+ if (nfill == 1) {
+ while (--n >= 0)
+ *p++ = auzero0; /* XXX memset */
+ } else /* nfill must be 2 */ {
+ while (n > 1) {
+ *p++ = auzero0;
+ *p++ = auzero1;
+ n -= 2;
+ }
+ }
}
-#define NSILENCE 128 /* An arbitrary even constant >= 2 */
int
audio_silence_copyout(sc, n, uio)
struct audio_softc *sc;
int n;
struct uio *uio;
{
- struct iovec *iov;
- int error = 0;
- u_char zerobuf[NSILENCE];
+ int error;
int k;
+ u_char zerobuf[128];
- audio_fill_silence(sc->sc_rencoding, zerobuf, NSILENCE);
-
- while (n > 0 && uio->uio_resid) {
- iov = uio->uio_iov;
- if (iov->iov_len == 0) {
- uio->uio_iov++;
- uio->uio_iovcnt--;
- continue;
- }
- k = min(min(n, iov->iov_len), NSILENCE);
- switch (uio->uio_segflg) {
- case UIO_USERSPACE:
- error = copyout(zerobuf, iov->iov_base, k);
- if (error)
- return (error);
- break;
-
- case UIO_SYSSPACE:
- bcopy(zerobuf, iov->iov_base, k);
- break;
- }
- iov->iov_base += k;
- iov->iov_len -= k;
- uio->uio_resid -= k;
- uio->uio_offset += k;
- n -= k;
- }
- return (error);
-}
-
-void
-audio_alloc_auzero(sc, bs)
- struct audio_softc *sc;
- int bs;
-{
- struct audio_hw_if *hw = sc->hw_if;
-
- if (sc->auzero_block)
- free(sc->auzero_block, M_DEVBUF);
+ audio_fill_silence(&sc->sc_rparams, zerobuf, sizeof zerobuf);
- sc->auzero_block = malloc(bs, M_DEVBUF, M_WAITOK);
-#ifdef DIAGNOSTIC
- if (sc->auzero_block == 0) {
- panic("audio_alloc_auzero: malloc auzero_block failed");
+ error = 0;
+ while (n > 0 && uio->uio_resid > 0 && !error) {
+ k = min(n, min(uio->uio_resid, sizeof zerobuf));
+ error = uiomove(zerobuf, k, uio);
+ n -= k;
}
-#endif
- audio_fill_silence(sc->sc_pencoding, sc->auzero_block, bs);
- if (hw->sw_encode)
- hw->sw_encode(sc->hw_hdl, sc->sc_pencoding, sc->auzero_block, bs);
+ return (error);
}
-
int
audio_write(dev, uio, ioflag)
dev_t dev;
@@ -936,171 +1267,159 @@ audio_write(dev, uio, ioflag)
int ioflag;
{
int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = audio_softc[unit];
- struct audio_hw_if *hw = sc->hw_if;
- struct audio_buffer *cb = &sc->pr;
- u_char *tp;
- int error, s, cc;
- int blocksize = sc->sc_blksize;
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
+ struct audio_ringbuffer *cb = &sc->sc_pr;
+ u_char *inp, *einp;
+ int error, s, n, cc, used;
+
+ DPRINTF(("audio_write: sc=%p(unit=%d) count=%d used=%d(hi=%d)\n", sc, unit,
+ uio->uio_resid, sc->sc_pr.used, sc->sc_pr.usedhigh));
+
+ if (cb->mmapped)
+ return EINVAL;
+
+ if (uio->uio_resid == 0) {
+ sc->sc_eof++;
+ return 0;
+ }
- DPRINTF(("audio_write: cc=%d hiwat=%d\n", uio->uio_resid, sc->sc_hiwat));
/*
* If half-duplex and currently recording, throw away data.
*/
- if (!hw->full_duplex &&
+ if (!sc->sc_full_duplex &&
(sc->sc_mode & AUMODE_RECORD)) {
uio->uio_offset += uio->uio_resid;
uio->uio_resid = 0;
DPRINTF(("audio_write: half-dpx read busy\n"));
return (0);
}
- error = 0;
- while (uio->uio_resid > 0) {
- if (cb->fill > 0) {
- if (sc->sc_pbus == 0) {
- /* playing has stopped, ignore fill */
- cb->fill = 0;
- } else {
- /* Write samples in the silence fill space.
- * We don't know where the DMA is
- * happening in the buffer, but if we
- * are lucky we will fill the buffer before
- * playing has reached the point we move to.
- * If we are unlucky some sample will
- * not be played.
- */
- cc = min(cb->fill, uio->uio_resid);
- error = uiomove(cb->otp, cc, uio);
- if (error == 0) {
- if (hw->sw_encode)
- hw->sw_encode(sc->hw_hdl,
- sc->sc_pencoding, cb->otp,
- cc);
- cb->fill -= cc;
- cb->otp += cc;
- }
- continue;
- }
- }
- if (cb->nblk >= sc->sc_hiwat) {
- do {
- DPRINTF(("audio_write: nblk=%d hiwat=%d lowat=%d\n", cb->nblk, sc->sc_hiwat, sc->sc_lowat));
- if (ioflag & IO_NDELAY)
- return (EWOULDBLOCK);
- error = audio_sleep(&sc->sc_wchan, "aud wr");
- if (error)
- return (error);
- } while (cb->nblk >= sc->sc_lowat);
- }
-#if 0
- if (cb->nblk == 0 &&
- cb->maxblk > sc->sc_backlog &&
- uio->uio_resid <= blocksize &&
- (cb->au_stamp - sc->sc_wseek) > sc->sc_50ms) {
- /*
- * the write is 'small', the buffer is empty
- * and we have been silent for at least 50ms
- * so we might be dealing with an application
- * that writes frames synchronously with
- * reading them. If so, we need an output
- * backlog to cover scheduling delays or
- * there will be gaps in the sound output.
- * Also take this opportunity to reset the
- * buffer pointers in case we ended up on
- * a bad boundary (odd byte, blksize bytes
- * from end, etc.).
- */
- DPRINTF(("audiowrite: set backlog %d\n", sc->sc_backlog));
- s = splaudio();
- cb->hp = cb->bp;
- cb->nblk = sc->sc_backlog;
- cb->tp = cb->hp + sc->sc_backlog * blocksize;
- splx(s);
- audio_fill_silence(sc->sc_pencoding, cb->hp, sc->sc_backlog * blocksize);
- }
+ if (!(sc->sc_mode & AUMODE_PLAY_ALL) && sc->sc_playdrop > 0) {
+ n = min(sc->sc_playdrop, uio->uio_resid);
+ DPRINTF(("audio_write: playdrop %d\n", n));
+ uio->uio_offset += n;
+ uio->uio_resid -= n;
+ sc->sc_playdrop -= n;
+ if (uio->uio_resid == 0)
+ return 0;
+ }
+
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_write: sr=%ld, enc=%d, prec=%d, chan=%d, sw=%p, fact=%d\n",
+ sc->sc_pparams.sample_rate, sc->sc_pparams.encoding,
+ sc->sc_pparams.precision, sc->sc_pparams.channels,
+ sc->sc_pparams.sw_code, sc->sc_pparams.factor);
#endif
- /* Calculate sample number of first sample in block we write */
+
+ error = 0;
+ while (uio->uio_resid > 0 && !error) {
s = splaudio();
- sc->sc_wseek = AU_RING_LEN(cb) + cb->au_stamp;
+ while (cb->used >= cb->usedhigh) {
+ DPRINTF(("audio_write: sleep used=%d lowat=%d hiwat=%d\n",
+ cb->used, cb->usedlow, cb->usedhigh));
+ if (ioflag & IO_NDELAY) {
+ splx(s);
+ return (EWOULDBLOCK);
+ }
+ error = audio_sleep(&sc->sc_wchan, "aud_wr");
+ if (error) {
+ splx(s);
+ return error;
+ }
+ }
+ used = cb->used;
+ inp = cb->inp;
+ cb->copying = 1;
splx(s);
-
- tp = cb->tp;
- cc = uio->uio_resid;
-
-#ifdef AUDIO_DEBUG
- if (audiodebug > 1) {
- int left = cb->ep - tp;
- Dprintf("audio_write: cc=%d tp=%p bs=%d nblk=%d left=%d\n", cc, tp, blocksize, cb->nblk, left);
+ cc = cb->usedhigh - used; /* maximum to write */
+ n = cb->end - inp;
+ if (sc->sc_pparams.factor != 1) {
+ /* Compensate for software coding expansion factor. */
+ n /= sc->sc_pparams.factor;
+ cc /= sc->sc_pparams.factor;
}
-#endif
+ if (n < cc)
+ cc = n; /* don't write beyond end of buffer */
+ if (uio->uio_resid < cc)
+ cc = uio->uio_resid; /* and no more than we have */
+
#ifdef DIAGNOSTIC
- {
- int towrite = (cc < blocksize)?cc:blocksize;
-
- /* check for an overwrite. Should never happen */
- if ((tp + towrite) > cb->ep) {
- DPRINTF(("audio_write: overwrite tp=%p towrite=%d ep=0x%x bs=%d\n",
- tp, towrite, cb->ep, blocksize));
- printf("audio_write: overwrite tp=%p towrite=%d ep=%p\n",
- tp, towrite, cb->ep);
- tp = cb->bp;
+ /*
+ * This should never happen since the block size and and
+ * block pointers are always nicely aligned.
+ */
+ if (cc == 0) {
+ printf("audio_write: cc == 0, swcode=%p, factor=%d\n",
+ sc->sc_pparams.sw_code, sc->sc_pparams.factor);
+ cb->copying = 0;
+ return EINVAL;
}
- }
#endif
- if (cc < blocksize) {
- error = uiomove(tp, cc, uio);
- if (error == 0) {
- /* fill with audio silence */
- tp += cc;
- cc = blocksize - cc;
- cb->fill = cc;
- cb->otp = tp;
- audio_fill_silence(sc->sc_pencoding, tp, cc);
- DPRINTF(("audio_write: auzero 0x%x %d 0x%x\n",
- tp, cc, *(int *)tp));
- tp += cc;
- }
- } else {
- error = uiomove(tp, blocksize, uio);
- if (error == 0) {
- tp += blocksize;
- }
- }
- if (error) {
#ifdef AUDIO_DEBUG
- printf("audio_write:(1) uiomove failed %d; cc=%d tp=%p bs=%d\n", error, cc, tp, blocksize);
+ if (audiodebug > 1)
+ printf("audio_write: uiomove cc=%d inp=%p, left=%d\n", cc, inp, uio->uio_resid);
#endif
- break;
- }
+ n = uio->uio_resid;
+ error = uiomove(inp, cc, uio);
+ cc = n - uio->uio_resid; /* number of bytes actually moved */
+#ifdef AUDIO_DEBUG
+ if (error)
+ printf("audio_write:(1) uiomove failed %d; cc=%d inp=%p\n",
+ error, cc, inp);
+#endif
+ /*
+ * Continue even if uiomove() failed because we may have
+ * gotten a partial block.
+ */
- if (hw->sw_encode)
- hw->sw_encode(sc->hw_hdl, sc->sc_pencoding, cb->tp,
- blocksize);
+ if (sc->sc_pparams.sw_code) {
+ sc->sc_pparams.sw_code(sc->hw_hdl, inp, cc);
+ /* Adjust count after the expansion. */
+ cc *= sc->sc_pparams.factor;
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_write: expanded cc=%d\n", cc);
+#endif
+ }
+
+ einp = cb->inp + cc;
+ if (einp >= cb->end)
+ einp = cb->start;
- /* wrap the ring buffer if at end */
s = splaudio();
- if ((sc->sc_mode & AUMODE_PLAY_ALL) == 0 && sc->sc_wblks)
- /*
- * discard the block if we sent out a silence
- * packet that hasn't yet been countered
- * by user data. (They must supply enough
- * data to catch up to "real time").
- */
- sc->sc_wblks--;
- else {
- if (tp >= cb->ep)
- tp = cb->bp;
- cb->tp = tp;
- ++cb->nblk; /* account for buffer filled */
-
- /*
- * If output isn't active, start it up.
- */
- if (sc->sc_pbus == 0)
- audiostartp(sc);
- }
+ /*
+ * This is a very suboptimal way of keeping track of
+ * silence in the buffer, but it is simple.
+ */
+ sc->sc_sil_count = 0;
+
+ cb->inp = einp;
+ cb->used += cc;
+ /* If the interrupt routine wants the last block filled AND
+ * the copy did not fill the last block completely it needs to
+ * be padded.
+ */
+ if (cb->needfill &&
+ (inp - cb->start) / cb->blksize ==
+ (einp - cb->start) / cb->blksize) {
+ /* Figure out how many bytes there is to a block boundary. */
+ cc = cb->blksize - (einp - cb->start) % cb->blksize;
+ DPRINTF(("audio_write: partial fill %d\n", cc));
+ } else
+ cc = 0;
+ cb->needfill = 0;
+ cb->copying = 0;
+ if (!sc->sc_pbus && !cb->pause)
+ error = audiostartp(sc); /* XXX should not clobber error */
splx(s);
+ if (cc) {
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_write: fill %d\n", cc);
+#endif
+ audio_fill_silence(&sc->sc_pparams, einp, cc);
+ }
}
return (error);
}
@@ -1114,34 +1433,45 @@ audio_ioctl(dev, cmd, addr, flag, p)
struct proc *p;
{
int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = audio_softc[unit];
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
struct audio_hw_if *hw = sc->hw_if;
- int error = 0, s;
+ struct audio_offset *ao;
+ int error = 0, s, offs, fd;
+ int rbus, pbus;
DPRINTF(("audio_ioctl(%d,'%c',%d)\n",
IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff));
switch (cmd) {
+ case FIONBIO:
+ /* All handled in the upper FS layer. */
+ break;
case FIOASYNC:
if (*(int *)addr) {
- if (sc->sc_async)
+ if (sc->sc_async_audio)
return (EBUSY);
- sc->sc_async = p;
+ sc->sc_async_audio = p;
+ DPRINTF(("audio_ioctl: FIOASYNC %p\n", p));
} else
- sc->sc_async = 0;
+ sc->sc_async_audio = 0;
break;
case AUDIO_FLUSH:
DPRINTF(("AUDIO_FLUSH\n"));
+ rbus = sc->sc_rbus;
+ pbus = sc->sc_pbus;
audio_clear(sc);
s = splaudio();
- if ((sc->sc_mode & AUMODE_PLAY) && (sc->sc_pbus == 0))
- audiostartp(sc);
- /* Again, play takes precedence on half-duplex hardware */
- if ((sc->sc_mode & AUMODE_RECORD) &&
- (hw->full_duplex ||
- ((sc->sc_mode & AUMODE_PLAY) == 0)))
- audiostartr(sc);
+ error = audio_initbufs(sc);
+ if (error) {
+ splx(s);
+ return error;
+ }
+ if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_pbus && pbus)
+ error = audiostartp(sc);
+ if (!error &&
+ (sc->sc_mode & AUMODE_RECORD) && !sc->sc_rbus && rbus)
+ error = audiostartr(sc);
splx(s);
break;
@@ -1150,25 +1480,51 @@ audio_ioctl(dev, cmd, addr, flag, p)
* when they were dropped.
*/
case AUDIO_RERROR:
- *(int *)addr = sc->rr.cb_drops;
+ *(int *)addr = sc->sc_rr.drops;
break;
case AUDIO_PERROR:
- *(int *)addr = sc->pr.cb_drops;
+ *(int *)addr = sc->sc_pr.drops;
break;
/*
- * How many samples will elapse until mike hears the first
- * sample of what we last wrote?
+ * Offsets into buffer.
*/
- case AUDIO_WSEEK:
+ case AUDIO_GETIOFFS:
+ s = splaudio();
+ /* figure out where next DMA will start */
+ ao = (struct audio_offset *)addr;
+ ao->samples = sc->sc_rr.stamp;
+ ao->deltablks = (sc->sc_rr.stamp - sc->sc_rr.stamp_last) / sc->sc_rr.blksize;
+ sc->sc_rr.stamp_last = sc->sc_rr.stamp;
+ ao->offset = sc->sc_rr.inp - sc->sc_rr.start;
+ splx(s);
+ break;
+
+ case AUDIO_GETOOFFS:
s = splaudio();
- *(u_long *)addr = sc->sc_wseek - sc->pr.au_stamp
- + AU_RING_LEN(&sc->rr);
+ /* figure out where next DMA will start */
+ ao = (struct audio_offset *)addr;
+ offs = sc->sc_pr.outp - sc->sc_pr.start + sc->sc_pr.blksize;
+ if (sc->sc_pr.start + offs >= sc->sc_pr.end)
+ offs = 0;
+ ao->samples = sc->sc_pr.stamp;
+ ao->deltablks = (sc->sc_pr.stamp - sc->sc_pr.stamp_last) / sc->sc_pr.blksize;
+ sc->sc_pr.stamp_last = sc->sc_pr.stamp;
+ ao->offset = offs;
splx(s);
break;
+
+ /*
+ * How many bytes will elapse until mike hears the first
+ * sample of what we write next?
+ */
+ case AUDIO_WSEEK:
+ *(u_long *)addr = sc->sc_rr.used;
+ break;
+
case AUDIO_SETINFO:
- DPRINTF(("AUDIO_SETINFO\n"));
+ DPRINTF(("AUDIO_SETINFO mode=0x%x\n", sc->sc_mode));
error = audiosetinfo(sc, (struct audio_info *)addr);
break;
@@ -1196,12 +1552,30 @@ audio_ioctl(dev, cmd, addr, flag, p)
case AUDIO_GETFD:
DPRINTF(("AUDIO_GETFD\n"));
- *(int *)addr = hw->full_duplex;
+ *(int *)addr = sc->sc_full_duplex;
break;
case AUDIO_SETFD:
DPRINTF(("AUDIO_SETFD\n"));
- error = hw->setfd(sc->hw_hdl, *(int *)addr);
+ fd = *(int *)addr;
+ if (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX) {
+ if (hw->setfd)
+ error = hw->setfd(sc->hw_hdl, fd);
+ else
+ error = 0;
+ if (!error)
+ sc->sc_full_duplex = fd;
+ } else {
+ if (fd)
+ error = ENOTTY;
+ else
+ error = 0;
+ }
+ break;
+
+ case AUDIO_GETPROPS:
+ DPRINTF(("AUDIO_GETPROPS\n"));
+ *(int *)addr = hw->get_props(sc->hw_hdl);
break;
default:
@@ -1221,22 +1595,17 @@ audio_select(dev, rw, p)
struct proc *p;
{
int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = audio_softc[unit];
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
int s = splaudio();
-#if 0
- DPRINTF(("audio_select: rw=%d mode=%d rblks=%d rr.nblk=%d\n",
- rw, sc->sc_mode, sc->sc_rblks, sc->rr.nblk));
-#endif
+ DPRINTF(("audio_select: rw=0x%x mode=%d\n", rw, sc->sc_mode));
+
switch (rw) {
case FREAD:
- if (sc->sc_mode & AUMODE_PLAY) {
- if (sc->sc_rblks > 0) {
- splx(s);
- return (1);
- }
- } else if (sc->rr.nblk > 0) {
+ if ((sc->sc_mode & AUMODE_PLAY) ?
+ sc->sc_pr.stamp > sc->sc_wstamp :
+ sc->sc_rr.used > sc->sc_rr.usedlow) {
splx(s);
return (1);
}
@@ -1244,18 +1613,8 @@ audio_select(dev, rw, p)
break;
case FWRITE:
- /*
- * Can write if we're recording because it gets preempted.
- * Otherwise, can write when below low water.
- * XXX this won't work right if we're in
- * record mode -- we need to note that a write
- * select has happed and flip the speaker.
- *
- * XXX The above XXX-comment is SoundBlaster-dependent,
- * right? Or maybe specific to half-duplex devices?
- */
if (sc->sc_mode & AUMODE_RECORD ||
- sc->pr.nblk <= sc->sc_lowat) {
+ sc->sc_pr.used <= sc->sc_pr.usedlow) {
splx(s);
return (1);
}
@@ -1271,64 +1630,159 @@ audio_mmap(dev, off, prot)
dev_t dev;
int off, prot;
{
- /* XXX placeholder */
- return (-1);
+ int s;
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
+ struct audio_hw_if *hw = sc->hw_if;
+ struct audio_ringbuffer *cb;
+
+ DPRINTF(("audio_mmap: off=%d, prot=%d\n", off, prot));
+
+ if (!(hw->get_props(sc->hw_hdl) & AUDIO_PROP_MMAP) || !hw->mappage)
+ return -1;
+#if 0
+/* XXX
+ * The idea here was to use the protection to determine if
+ * we are mapping the read or write buffer, but it fails.
+ * The VM system is broken in (at least) two ways.
+ * 1) If you map memory VM_PROT_WRITE you SIGSEGV
+ * when writing to it, so VM_PROT_READ|VM_PROT_WRITE
+ * has to be used for mmapping the play buffer.
+ * 2) Even if calling mmap() with VM_PROT_READ|VM_PROT_WRITE
+ * audio_mmap will get called at some point with VM_PROT_READ
+ * only.
+ * So, alas, we always map the play buffer for now.
+ */
+ if (prot == (VM_PROT_READ|VM_PROT_WRITE) ||
+ prot == VM_PROT_WRITE)
+ cb = &sc->sc_pr;
+ else if (prot == VM_PROT_READ)
+ cb = &sc->sc_rr;
+ else
+ return -1;
+#else
+ cb = &sc->sc_pr;
+#endif
+
+ if (off >= cb->bufsize)
+ return -1;
+ if (!cb->mmapped) {
+ cb->mmapped = 1;
+ if (cb == &sc->sc_pr) {
+ audio_fill_silence(&sc->sc_pparams, cb->start, cb->bufsize);
+ s = splaudio();
+ if (!sc->sc_pbus)
+ (void)audiostartp(sc);
+ splx(s);
+ } else {
+ s = splaudio();
+ if (!sc->sc_rbus)
+ (void)audiostartr(sc);
+ splx(s);
+ }
+ }
+
+ return hw->mappage(sc->hw_hdl, cb->start, off, prot);
}
-void
+int
audiostartr(sc)
struct audio_softc *sc;
{
int error;
- DPRINTF(("audiostartr: tp=%p\n", sc->rr.tp));
+ DPRINTF(("audiostartr: start=%p used=%d(hi=%d) mmapped=%d\n",
+ sc->sc_rr.start, sc->sc_rr.used, sc->sc_rr.usedhigh,
+ sc->sc_rr.mmapped));
- error = sc->hw_if->start_input(sc->hw_hdl, sc->rr.tp, sc->sc_blksize,
- audio_rint, (void *)sc);
+ error = sc->hw_if->start_input(sc->hw_hdl, sc->sc_rr.start,
+ sc->sc_rr.blksize, audio_rint, (void *)sc);
if (error) {
DPRINTF(("audiostartr failed: %d\n", error));
- audio_clear(sc);
+ return error;
}
- else
- sc->sc_rbus = 1;
+ sc->sc_rbus = 1;
+ return 0;
}
-void
+int
audiostartp(sc)
struct audio_softc *sc;
{
int error;
- DPRINTF(("audiostartp: hp=0x%x nblk=%d\n", sc->pr.hp, sc->pr.nblk));
+ DPRINTF(("audiostartp: start=%p used=%d(hi=%d) mmapped=%d\n",
+ sc->sc_pr.start, sc->sc_pr.used, sc->sc_pr.usedhigh,
+ sc->sc_pr.mmapped));
- if (sc->pr.nblk > 0) {
- u_char *hp = sc->pr.hp;
- error = sc->hw_if->start_output(sc->hw_hdl, hp, sc->sc_blksize,
- audio_rpint, (void *)sc);
+ if (sc->sc_pr.used >= sc->sc_pr.blksize || sc->sc_pr.mmapped) {
+ error = sc->hw_if->start_output(sc->hw_hdl, sc->sc_pr.outp,
+ sc->sc_pr.blksize, audio_pint, (void *)sc);
if (error) {
- DPRINTF(("audiostartp: failed: %d\n", error));
- }
- else {
- sc->sc_pbus = 1;
- hp += sc->sc_blksize;
- if (hp >= sc->pr.ep)
- hp = sc->pr.bp;
- sc->pr.hp = hp;
+ DPRINTF(("audiostartp failed: %d\n", error));
+ return error;
}
+ sc->sc_pbus = 1;
}
+ return 0;
}
/*
- * Use this routine as DMA callback if we played user data. We need to
- * account for user data and silence separately.
+ * When the play interrupt routine finds that the write isn't keeping
+ * the buffer filled it will insert silence in the buffer to make up
+ * for this. The part of the buffer that is filled with silence
+ * is kept track of in a very approcimate way: it starts at sc_sil_start
+ * and extends sc_sil_count bytes. If the writer doesn't write sc_sil_count
+ * get to encompass the whole buffer after which no more filling needs
+ * to be done. When the writer starts again sc_sil_count is set to 0.
*/
-void
-audio_rpint(v)
- void *v;
+/* XXX
+ * Putting silence into the output buffer should not really be done
+ * at splaudio, but there is no softaudio level to do it at yet.
+ */
+static __inline void
+audio_pint_silence(sc, cb, inp, cc)
+ struct audio_softc *sc;
+ struct audio_ringbuffer *cb;
+ u_char *inp;
+ int cc;
{
- struct audio_softc *sc = v;
- sc->pr.nblk--;
- audio_pint(v); /* 'twas a real audio block */
+ u_char *s, *e, *p, *q;
+
+ if (sc->sc_sil_count > 0) {
+ s = sc->sc_sil_start; /* start of silence */
+ e = s + sc->sc_sil_count; /* end of silence, may be beyond end */
+ p = inp; /* adjusted pointer to area to fill */
+ if (p < s)
+ p += cb->end - cb->start;
+ q = p+cc;
+ /* Check if there is already silence. */
+ if (!(s <= p && p < e &&
+ s <= q && q <= e)) {
+ if (s <= p)
+ sc->sc_sil_count = max(sc->sc_sil_count, q - s);
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 2)
+ printf("audio_pint_silence: fill cc=%d inp=%p, count=%d size=%d\n",
+ cc, inp, sc->sc_sil_count, (int)(cb->end - cb->start));
+#endif
+ audio_fill_silence(&sc->sc_pparams, inp, cc);
+ } else {
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 2)
+ printf("audio_pint_silence: already silent cc=%d inp=%p\n", cc, inp);
+#endif
+
+ }
+ } else {
+ sc->sc_sil_start = inp;
+ sc->sc_sil_count = cc;
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 2)
+ printf("audio_pint_silence: start fill %p %d\n", inp, cc);
+#endif
+ audio_fill_silence(&sc->sc_pparams, inp, cc);
+ }
}
/*
@@ -1342,90 +1796,128 @@ audio_pint(v)
void *v;
{
struct audio_softc *sc = v;
- u_char *hp;
- int cc = sc->sc_blksize;
struct audio_hw_if *hw = sc->hw_if;
- struct audio_buffer *cb = &sc->pr;
+ struct audio_ringbuffer *cb = &sc->sc_pr;
+ u_char *inp;
+ int cc, ccr;
int error;
-
- /*
- * XXX
- * if there is only one buffer in the ring, this test
- * always fails and the output is always silence after the
- * first block.
- */
- if (cb->nblk > 0) {
- hp = cb->hp;
- if (cb->cb_pause) {
- cb->cb_pdrops++;
+
+ if (!sc->sc_open)
+ return; /* ignore interrupt if not open */
+
+ cb->outp += cb->blksize;
+ if (cb->outp >= cb->end)
+ cb->outp = cb->start;
+ cb->stamp += cb->blksize / sc->sc_pparams.factor;
+ if (cb->mmapped) {
#ifdef AUDIO_DEBUG
- if (audiodebug > 1)
- Dprintf("audio_pint: paused %d\n", cb->cb_pdrops);
+ if (audiodebug > 2)
+ printf("audio_pint: mmapped outp=%p cc=%d inp=%p\n",
+ cb->outp, cb->blksize, cb->inp);
#endif
- goto psilence;
- }
- else {
+ (void)hw->start_output(sc->hw_hdl, cb->outp, cb->blksize,
+ audio_pint, (void *)sc);
+ return;
+ }
+
+#ifdef AUDIO_INTR_TIME
+ {
+ struct timeval tv;
+ u_long t;
+ microtime(&tv);
+ t = tv.tv_usec + 1000000 * tv.tv_sec;
+ if (sc->sc_pnintr) {
+ long lastdelta, totdelta;
+ lastdelta = t - sc->sc_plastintr - sc->sc_pblktime;
+ if (lastdelta > sc->sc_pblktime / 5) {
+ printf("audio: play interrupt(%d) off relative by %ld us (%lu)\n",
+ sc->sc_pnintr, lastdelta, sc->sc_pblktime);
+ }
+ totdelta = t - sc->sc_pfirstintr - sc->sc_pblktime * sc->sc_pnintr;
+ if (totdelta > sc->sc_pblktime / 2) {
+ sc->sc_pnintr++;
+ printf("audio: play interrupt(%d) off absolute by %ld us (%lu)\n",
+ sc->sc_pnintr, totdelta, sc->sc_pblktime);
+ sc->sc_pnintr++; /* avoid repeated messages */
+ }
+ } else
+ sc->sc_pfirstintr = t;
+ sc->sc_plastintr = t;
+ sc->sc_pnintr++;
+ }
+#endif
+
+ cb->used -= cb->blksize;
+ if (cb->used < cb->blksize) {
+ /* we don't have a full block to use */
+ if (cb->copying) {
+ /* writer is in progress, don't disturb */
+ cb->needfill = 1;
#ifdef AUDIO_DEBUG
- if (audiodebug > 1)
- Dprintf("audio_pint: hp=0x%x cc=%d\n", hp, cc);
+ if (audiodebug > 1)
+ printf("audio_pint: copying in progress\n");
#endif
- error = hw->start_output(sc->hw_hdl, hp, cc,
- audio_rpint, (void *)sc);
- if (error) {
- DPRINTF(("audio_pint restart failed: %d\n", error));
- audio_clear(sc);
- }
- else {
- hp += cc;
- if (hp >= cb->ep)
- hp = cb->bp;
- cb->hp = hp;
- cb->au_stamp += sc->sc_smpl_in_blk;
-
- ++sc->sc_rblks;
- }
+ } else {
+ inp = cb->inp;
+ cc = cb->blksize - (inp - cb->start) % cb->blksize;
+ ccr = cc / sc->sc_pparams.factor;
+ if (cb->pause)
+ cb->pdrops += ccr;
+ else {
+ cb->drops += ccr;
+ sc->sc_playdrop += ccr;
+ }
+ audio_pint_silence(sc, cb, inp, cc);
+ inp += cc;
+ if (inp >= cb->end)
+ inp = cb->start;
+ cb->inp = inp;
+ cb->used += cc;
+
+ /* Clear next block so we keep ahead of the DMA. */
+ if (cb->used + cc < cb->usedhigh)
+ audio_pint_silence(sc, cb, inp, cb->blksize);
}
}
- else {
- cb->cb_drops++;
+
#ifdef AUDIO_DEBUG
- if (audiodebug > 1)
- Dprintf("audio_pint: drops=%d auzero %d 0x%x\n", cb->cb_drops, cc, *(int *)sc->auzero_block);
+ if (audiodebug > 3)
+ printf("audio_pint: outp=%p cc=%d\n", cb->outp, cb->blksize);
#endif
- psilence:
- error = hw->start_output(sc->hw_hdl,
- sc->auzero_block, cc,
- audio_pint, (void *)sc);
- if (error) {
- DPRINTF(("audio_pint zero failed: %d\n", error));
- audio_clear(sc);
- } else
- ++sc->sc_wblks;
+ error = hw->start_output(sc->hw_hdl, cb->outp, cb->blksize,
+ audio_pint, (void *)sc);
+ if (error) {
+ /* XXX does this really help? */
+ DPRINTF(("audio_pint restart failed: %d\n", error));
+ audio_clear(sc);
}
#ifdef AUDIO_DEBUG
- DPRINTF(("audio_pint: mode=%d pause=%d nblk=%d lowat=%d\n",
- sc->sc_mode, cb->cb_pause, cb->nblk, sc->sc_lowat));
+ if (audiodebug > 3)
+ printf("audio_pint: mode=%d pause=%d used=%d lowat=%d\n",
+ sc->sc_mode, cb->pause, cb->used, cb->usedlow);
#endif
- if ((sc->sc_mode & AUMODE_PLAY) && !cb->cb_pause) {
- if (cb->nblk <= sc->sc_lowat) {
+ if ((sc->sc_mode & AUMODE_PLAY) && !cb->pause) {
+ if (cb->used <= cb->usedlow) {
audio_wakeup(&sc->sc_wchan);
selwakeup(&sc->sc_wsel);
- if (sc->sc_async)
- psignal(sc->sc_async, SIGIO);
+ if (sc->sc_async_audio) {
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 3)
+ printf("audio_pint: sending SIGIO %p\n",
+ sc->sc_async_audio);
+#endif
+ psignal(sc->sc_async_audio, SIGIO);
+ }
}
}
- /*
- * XXX
- * possible to return one or more "phantom blocks" now.
- * Only in half duplex?
- */
- if (hw->full_duplex) {
+ /* Possible to return one or more "phantom blocks" now. */
+ if (!sc->sc_full_duplex && sc->sc_rchan) {
audio_wakeup(&sc->sc_rchan);
selwakeup(&sc->sc_rsel);
- if (sc->sc_async)
- psignal(sc->sc_async, SIGIO);
+ if (sc->sc_async_audio)
+ psignal(sc->sc_async_audio, SIGIO);
}
}
@@ -1439,196 +1931,564 @@ audio_rint(v)
void *v;
{
struct audio_softc *sc = v;
- u_char *tp;
- int cc = sc->sc_blksize;
struct audio_hw_if *hw = sc->hw_if;
- struct audio_buffer *cb = &sc->rr;
+ struct audio_ringbuffer *cb = &sc->sc_rr;
int error;
-
- tp = cb->tp;
- if (cb->cb_pause) {
- cb->cb_pdrops++;
- DPRINTF(("audio_rint: pdrops %d\n", cb->cb_pdrops));
- }
- else {
- tp += cc;
- if (tp >= cb->ep)
- tp = cb->bp;
- if (++cb->nblk < cb->maxblk) {
+
+ if (!sc->sc_open)
+ return; /* ignore interrupt if not open */
+
+ cb->inp += cb->blksize;
+ if (cb->inp >= cb->end)
+ cb->inp = cb->start;
+ cb->stamp += cb->blksize;
+ if (cb->mmapped) {
#ifdef AUDIO_DEBUG
- if (audiodebug > 1)
- Dprintf("audio_rint: tp=%p cc=%d\n", tp, cc);
+ if (audiodebug > 2)
+ printf("audio_rint: mmapped inp=%p cc=%d\n",
+ cb->inp, cb->blksize);
#endif
- error = hw->start_input(sc->hw_hdl, tp, cc,
- audio_rint, (void *)sc);
- if (error) {
- DPRINTF(("audio_rint: start failed: %d\n",
- error));
- audio_clear(sc);
+ (void)hw->start_input(sc->hw_hdl, cb->inp, cb->blksize,
+ audio_rint, (void *)sc);
+ return;
+ }
+
+#ifdef AUDIO_INTR_TIME
+ {
+ struct timeval tv;
+ u_long t;
+ microtime(&tv);
+ t = tv.tv_usec + 1000000 * tv.tv_sec;
+ if (sc->sc_rnintr) {
+ long lastdelta, totdelta;
+ lastdelta = t - sc->sc_rlastintr - sc->sc_rblktime;
+ if (lastdelta > sc->sc_rblktime / 5) {
+ printf("audio: record interrupt(%d) off relative by %ld us (%lu)\n",
+ sc->sc_rnintr, lastdelta, sc->sc_rblktime);
}
- cb->au_stamp += sc->sc_smpl_in_blk;
- } else {
- /*
- * XXX
- * How do we count dropped input samples due to overrun?
- * Start a "dummy DMA transfer" when the input ring buffer
- * is full and count # of these? Seems pretty lame to
- * me, but how else are we going to do this?
- */
- cb->cb_drops++;
- sc->sc_rbus = 0;
- DPRINTF(("audio_rint: drops %d\n", cb->cb_drops));
- }
- cb->tp = tp;
-
- audio_wakeup(&sc->sc_rchan);
- selwakeup(&sc->sc_rsel);
- if (sc->sc_async)
- psignal(sc->sc_async, SIGIO);
+ totdelta = t - sc->sc_rfirstintr - sc->sc_rblktime * sc->sc_rnintr;
+ if (totdelta > sc->sc_rblktime / 2) {
+ sc->sc_rnintr++;
+ printf("audio: record interrupt(%d) off absolute by %ld us (%lu)\n",
+ sc->sc_rnintr, totdelta, sc->sc_rblktime);
+ sc->sc_rnintr++; /* avoid repeated messages */
+ }
+ } else
+ sc->sc_rfirstintr = t;
+ sc->sc_rlastintr = t;
+ sc->sc_rnintr++;
+ }
+#endif
+
+ cb->used += cb->blksize;
+ if (cb->pause) {
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_rint: pdrops %lu\n", cb->pdrops);
+#endif
+ cb->pdrops += cb->blksize;
+ cb->outp += cb->blksize;
+ cb->used -= cb->blksize;
+ } else if (cb->used + cb->blksize >= cb->usedhigh && !cb->copying) {
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1)
+ printf("audio_rint: drops %lu\n", cb->drops);
+#endif
+ cb->drops += cb->blksize;
+ cb->outp += cb->blksize;
+ cb->used -= cb->blksize;
+ }
+
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 2)
+ printf("audio_rint: inp=%p cc=%d used=%d\n",
+ cb->inp, cb->blksize, cb->used);
+#endif
+ error = hw->start_input(sc->hw_hdl, cb->inp, cb->blksize,
+ audio_rint, (void *)sc);
+ if (error) {
+ /* XXX does this really help? */
+ DPRINTF(("audio_rint: restart failed: %d\n", error));
+ audio_clear(sc);
}
+
+ audio_wakeup(&sc->sc_rchan);
+ selwakeup(&sc->sc_rsel);
+ if (sc->sc_async_audio)
+ psignal(sc->sc_async_audio, SIGIO);
}
int
-audio_check_format(encodingp, precisionp)
- u_int *encodingp, *precisionp;
+audio_check_params(p)
+ struct audio_params *p;
{
+#if defined(COMPAT_12)
+ if (p->encoding == AUDIO_ENCODING_PCM16) {
+ if (p->precision == 8)
+ p->encoding = AUDIO_ENCODING_ULINEAR;
+ else
+ p->encoding = AUDIO_ENCODING_SLINEAR;
+ } else if (p->encoding == AUDIO_ENCODING_PCM8) {
+ if (p->precision == 8)
+ p->encoding = AUDIO_ENCODING_ULINEAR;
+ else
+ return EINVAL;
+ }
+#endif
- if (*encodingp == AUDIO_ENCODING_LINEAR)
- switch (*precisionp) {
- case 8:
- *encodingp = AUDIO_ENCODING_PCM8;
- return (0);
- case 16:
- *encodingp = AUDIO_ENCODING_PCM16;
- return (0);
- default:
- return (EINVAL);
- }
+ if (p->encoding == AUDIO_ENCODING_SLINEAR)
+#if BYTE_ORDER == LITTLE_ENDIAN
+ p->encoding = AUDIO_ENCODING_SLINEAR_LE;
+#else
+ p->encoding = AUDIO_ENCODING_SLINEAR_BE;
+#endif
+ if (p->encoding == AUDIO_ENCODING_ULINEAR)
+#if BYTE_ORDER == LITTLE_ENDIAN
+ p->encoding = AUDIO_ENCODING_ULINEAR_LE;
+#else
+ p->encoding = AUDIO_ENCODING_ULINEAR_BE;
+#endif
- switch (*encodingp) {
+ switch (p->encoding) {
case AUDIO_ENCODING_ULAW:
case AUDIO_ENCODING_ALAW:
- case AUDIO_ENCODING_PCM8:
case AUDIO_ENCODING_ADPCM:
- if (*precisionp != 8)
+ if (p->precision != 8)
return (EINVAL);
break;
- case AUDIO_ENCODING_PCM16:
- if (*precisionp != 16)
+ case AUDIO_ENCODING_SLINEAR_LE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ case AUDIO_ENCODING_ULINEAR_LE:
+ case AUDIO_ENCODING_ULINEAR_BE:
+ if (p->precision != 8 && p->precision != 16)
return (EINVAL);
break;
+ case AUDIO_ENCODING_MPEG_L1_STREAM:
+ case AUDIO_ENCODING_MPEG_L1_PACKETS:
+ case AUDIO_ENCODING_MPEG_L1_SYSTEM:
+ case AUDIO_ENCODING_MPEG_L2_STREAM:
+ case AUDIO_ENCODING_MPEG_L2_PACKETS:
+ case AUDIO_ENCODING_MPEG_L2_SYSTEM:
+ break;
default:
return (EINVAL);
}
+ if (p->channels < 1 || p->channels > 8) /* sanity check # of channels */
+ return (EINVAL);
+
return (0);
}
int
+au_set_lr_value(sc, ct, l, r)
+ struct audio_softc *sc;
+ mixer_ctrl_t *ct;
+ int l, r;
+{
+ ct->type = AUDIO_MIXER_VALUE;
+ ct->un.value.num_channels = 2;
+ ct->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = l;
+ ct->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = r;
+ if (sc->hw_if->set_port(sc->hw_hdl, ct) == 0)
+ return 0;
+ ct->un.value.num_channels = 1;
+ ct->un.value.level[AUDIO_MIXER_LEVEL_MONO] = (l+r)/2;
+ return sc->hw_if->set_port(sc->hw_hdl, ct);
+}
+
+int
+au_set_gain(sc, ports, gain, balance)
+ struct audio_softc *sc;
+ struct au_mixer_ports *ports;
+ int gain;
+ int balance;
+{
+ mixer_ctrl_t ct;
+ int i, error;
+ int l, r;
+ u_int mask;
+ int nset;
+
+ if (balance == AUDIO_MID_BALANCE) {
+ l = r = gain;
+ } else if (balance < AUDIO_MID_BALANCE) {
+ r = gain;
+ l = (balance * gain) / AUDIO_MID_BALANCE;
+ } else {
+ l = gain;
+ r = ((AUDIO_RIGHT_BALANCE - balance) * gain)
+ / AUDIO_MID_BALANCE;
+ }
+ DPRINTF(("au_set_gain: gain=%d balance=%d, l=%d r=%d\n",
+ gain, balance, l, r));
+
+ if (ports->index == -1) {
+ usemaster:
+ if (ports->master == -1)
+ return 0; /* just ignore it silently */
+ ct.dev = ports->master;
+ error = au_set_lr_value(sc, &ct, l, r);
+ } else {
+ ct.dev = ports->index;
+ if (ports->isenum) {
+ ct.type = AUDIO_MIXER_ENUM;
+ error = sc->hw_if->get_port(sc->hw_hdl, &ct);
+ if (error)
+ return error;
+ for(i = 0; i < ports->nports; i++) {
+ if (ports->misel[i] == ct.un.ord) {
+ ct.dev = ports->miport[i];
+ if (ct.dev == -1 ||
+ au_set_lr_value(sc, &ct, l, r))
+ goto usemaster;
+ else
+ break;
+ }
+ }
+ } else {
+ ct.type = AUDIO_MIXER_SET;
+ error = sc->hw_if->get_port(sc->hw_hdl, &ct);
+ if (error)
+ return error;
+ mask = ct.un.mask;
+ nset = 0;
+ for(i = 0; i < ports->nports; i++) {
+ if (ports->misel[i] & mask) {
+ ct.dev = ports->miport[i];
+ if (ct.dev != -1 &&
+ au_set_lr_value(sc, &ct, l, r) == 0)
+ nset++;
+ }
+ }
+ if (nset == 0)
+ goto usemaster;
+ }
+ }
+ if (!error)
+ mixer_signal(sc);
+ return error;
+}
+
+int
+au_get_lr_value(sc, ct, l, r)
+ struct audio_softc *sc;
+ mixer_ctrl_t *ct;
+ int *l, *r;
+{
+ int error;
+
+ ct->un.value.num_channels = 2;
+ if (sc->hw_if->get_port(sc->hw_hdl, ct) == 0) {
+ *l = ct->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
+ *r = ct->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
+ } else {
+ ct->un.value.num_channels = 1;
+ error = sc->hw_if->get_port(sc->hw_hdl, ct);
+ if (error)
+ return error;
+ *r = *l = ct->un.value.level[AUDIO_MIXER_LEVEL_MONO];
+ }
+ return 0;
+}
+
+void
+au_get_gain(sc, ports, pgain, pbalance)
+ struct audio_softc *sc;
+ struct au_mixer_ports *ports;
+ u_int *pgain;
+ u_char *pbalance;
+{
+ mixer_ctrl_t ct;
+ int i, l, r, n;
+ int lgain = AUDIO_MAX_GAIN/2, rgain = AUDIO_MAX_GAIN/2;
+
+ if (ports->index == -1) {
+ usemaster:
+ if (ports->master == -1)
+ goto bad;
+ ct.dev = ports->master;
+ ct.type = AUDIO_MIXER_VALUE;
+ if (au_get_lr_value(sc, &ct, &lgain, &rgain))
+ goto bad;
+ } else {
+ ct.dev = ports->index;
+ if (ports->isenum) {
+ ct.type = AUDIO_MIXER_ENUM;
+ if (sc->hw_if->get_port(sc->hw_hdl, &ct))
+ goto bad;
+ ct.type = AUDIO_MIXER_VALUE;
+ for(i = 0; i < ports->nports; i++) {
+ if (ports->misel[i] == ct.un.ord) {
+ ct.dev = ports->miport[i];
+ if (ct.dev == -1 ||
+ au_get_lr_value(sc, &ct,
+ &lgain, &rgain))
+ goto usemaster;
+ else
+ break;
+ }
+ }
+ } else {
+ ct.type = AUDIO_MIXER_SET;
+ if (sc->hw_if->get_port(sc->hw_hdl, &ct))
+ goto bad;
+ ct.type = AUDIO_MIXER_VALUE;
+ lgain = rgain = n = 0;
+ for(i = 0; i < ports->nports; i++) {
+ if (ports->misel[i] & ct.un.mask) {
+ ct.dev = ports->miport[i];
+ if (ct.dev == -1 ||
+ au_get_lr_value(sc, &ct, &l, &r))
+ goto usemaster;
+ else {
+ lgain += l;
+ rgain += r;
+ n++;
+ }
+ }
+ }
+ if (n != 0) {
+ lgain /= n;
+ rgain /= n;
+ }
+ }
+ }
+bad:
+ if (lgain == rgain) { /* handles lgain==rgain==0 */
+ *pgain = lgain;
+ *pbalance = AUDIO_MID_BALANCE;
+ } else if (lgain < rgain) {
+ *pgain = rgain;
+ *pbalance = (AUDIO_MID_BALANCE * lgain) / rgain;
+ } else /* lgain > rgain */ {
+ *pgain = lgain;
+ *pbalance = AUDIO_RIGHT_BALANCE -
+ (AUDIO_MID_BALANCE * rgain) / lgain;
+ }
+}
+
+int
+au_set_port(sc, ports, port)
+ struct audio_softc *sc;
+ struct au_mixer_ports *ports;
+ u_int port;
+{
+ mixer_ctrl_t ct;
+ int i, error;
+
+ if (port == 0 && ports->allports == 0)
+ return 0; /* allow this special case */
+
+ if (ports->index == -1)
+ return EINVAL;
+ ct.dev = ports->index;
+ if (ports->isenum) {
+ if (port & (port-1))
+ return EINVAL; /* Only one port allowed */
+ ct.type = AUDIO_MIXER_ENUM;
+ error = EINVAL;
+ for(i = 0; i < ports->nports; i++)
+ if (ports->aumask[i] == port) {
+ ct.un.ord = ports->misel[i];
+ error = sc->hw_if->set_port(sc->hw_hdl, &ct);
+ break;
+ }
+ } else {
+ ct.type = AUDIO_MIXER_SET;
+ ct.un.mask = 0;
+ for(i = 0; i < ports->nports; i++)
+ if (ports->aumask[i] & port)
+ ct.un.mask |= ports->misel[i];
+ if (port != 0 && ct.un.mask == 0)
+ error = EINVAL;
+ else
+ error = sc->hw_if->set_port(sc->hw_hdl, &ct);
+ }
+ if (!error)
+ mixer_signal(sc);
+ return error;
+}
+
+int
+au_get_port(sc, ports)
+ struct audio_softc *sc;
+ struct au_mixer_ports *ports;
+{
+ mixer_ctrl_t ct;
+ int i, aumask;
+
+ if (ports->index == -1)
+ return 0;
+ ct.dev = ports->index;
+ ct.type = ports->isenum ? AUDIO_MIXER_ENUM : AUDIO_MIXER_SET;
+ if (sc->hw_if->get_port(sc->hw_hdl, &ct))
+ return 0;
+ aumask = 0;
+ if (ports->isenum) {
+ for(i = 0; i < ports->nports; i++)
+ if (ct.un.ord == ports->misel[i])
+ aumask = ports->aumask[i];
+ } else {
+ for(i = 0; i < ports->nports; i++)
+ if (ct.un.mask & ports->misel[i])
+ aumask |= ports->aumask[i];
+ }
+ return aumask;
+}
+
+int
audiosetinfo(sc, ai)
struct audio_softc *sc;
struct audio_info *ai;
{
struct audio_prinfo *r = &ai->record, *p = &ai->play;
- int cleared = 0, init = 0;
- int bsize, error = 0;
+ int cleared;
+ int s, setmode;
+ int error;
struct audio_hw_if *hw = sc->hw_if;
- mixer_ctrl_t ct;
- int s;
+ struct audio_params pp, rp;
+ int np, nr;
+ unsigned int blks;
+ int oldpblksize, oldrblksize;
+ int rbus, pbus;
+ u_int gain;
+ u_char balance;
if (hw == 0) /* HW has not attached */
return(ENXIO);
- if (p->sample_rate != ~0) {
- if (!cleared)
- audio_clear(sc);
- cleared = 1;
+ rbus = sc->sc_rbus;
+ pbus = sc->sc_pbus;
+ error = 0;
+ cleared = 0;
- error = hw->set_out_sr(sc->hw_hdl, p->sample_rate);
- if (error)
- return(error);
+ pp = sc->sc_pparams; /* Temporary encoding storage in */
+ rp = sc->sc_rparams; /* case setting the modes fails. */
+ nr = np = 0;
- sc->sc_50ms = 50 * hw->get_out_sr(sc->hw_hdl) / 1000;
- init = 1;
+ if (p->sample_rate != ~0) {
+ pp.sample_rate = p->sample_rate;
+ np++;
}
if (r->sample_rate != ~0) {
- if (!cleared)
- audio_clear(sc);
- cleared = 1;
-
- error = hw->set_in_sr(sc->hw_hdl, r->sample_rate);
- if (error)
- return(error);
-
- sc->sc_50ms = 50 * hw->get_in_sr(sc->hw_hdl) / 1000;
- init = 1;
+ rp.sample_rate = r->sample_rate;
+ nr++;
}
- if (p->encoding != ~0 || p->precision != ~0) {
- if (!cleared)
- audio_clear(sc);
- cleared = 1;
-
- if (p->encoding == ~0)
- p->encoding = hw->get_encoding(sc->hw_hdl);
- if (p->precision == ~0)
- p->precision = hw->get_precision(sc->hw_hdl);
- error = audio_check_format(&p->encoding, &p->precision);
- if (error)
- return(error);
- error = hw->set_format(sc->hw_hdl, p->encoding, p->precision);
- if (error)
- return(error);
-
- sc->sc_pencoding = p->encoding;
- init = 1;
+ if (p->encoding != ~0) {
+ pp.encoding = p->encoding;
+ np++;
}
- if (r->encoding != ~0 || r->precision != ~0) {
+ if (r->encoding != ~0) {
+ rp.encoding = r->encoding;
+ nr++;
+ }
+ if (p->precision != ~0) {
+ pp.precision = p->precision;
+ np++;
+ }
+ if (r->precision != ~0) {
+ rp.precision = r->precision;
+ nr++;
+ }
+ if (p->channels != ~0) {
+ pp.channels = p->channels;
+ np++;
+ }
+ if (r->channels != ~0) {
+ rp.channels = r->channels;
+ nr++;
+ }
+#ifdef AUDIO_DEBUG
+ if (audiodebug && nr)
+ audio_print_params("Setting record params", &rp);
+ if (audiodebug && np)
+ audio_print_params("Setting play params", &pp);
+#endif
+ if (nr && (error = audio_check_params(&rp)))
+ return error;
+ if (np && (error = audio_check_params(&pp)))
+ return error;
+ setmode = 0;
+ if (nr) {
if (!cleared)
audio_clear(sc);
cleared = 1;
-
- if (r->encoding == ~0)
- r->encoding = hw->get_encoding(sc->hw_hdl);
- if (r->precision == ~0)
- r->precision = hw->get_precision(sc->hw_hdl);
- error = audio_check_format(&r->encoding, &r->precision);
- if (error)
- return(error);
- error = hw->set_format(sc->hw_hdl, r->encoding, r->precision);
- if (error)
- return(error);
-
- sc->sc_rencoding = r->encoding;
- init = 1;
+ rp.sw_code = 0;
+ rp.factor = 1;
+ setmode |= AUMODE_RECORD;
}
- if (p->channels != ~0) {
+ if (np) {
if (!cleared)
audio_clear(sc);
cleared = 1;
-
- error = hw->set_channels(sc->hw_hdl, p->channels);
- if (error)
- return(error);
-
- init = 1;
+ pp.sw_code = 0;
+ pp.factor = 1;
+ setmode |= AUMODE_PLAY;
}
- if (r->channels != ~0) {
+
+ if (ai->mode != ~0) {
if (!cleared)
audio_clear(sc);
cleared = 1;
+ sc->sc_mode = ai->mode;
+ if (sc->sc_mode & AUMODE_PLAY_ALL)
+ sc->sc_mode |= AUMODE_PLAY;
+ if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_full_duplex)
+ /* Play takes precedence */
+ sc->sc_mode &= ~AUMODE_RECORD;
+ }
- error = hw->set_channels(sc->hw_hdl, r->channels);
+ if (setmode) {
+ int indep = hw->get_props(sc->hw_hdl) & AUDIO_PROP_INDEPENDENT;
+ if (!indep) {
+ if (setmode == AUMODE_RECORD)
+ pp = rp;
+ else if (setmode == AUMODE_PLAY)
+ rp = pp;
+ }
+ error = hw->set_params(sc->hw_hdl, setmode, sc->sc_mode, &pp, &rp);
if (error)
- return(error);
+ return (error);
+ if (!indep) {
+ if (setmode == AUMODE_RECORD) {
+ pp.sample_rate = rp.sample_rate;
+ pp.encoding = rp.encoding;
+ pp.channels = rp.channels;
+ pp.precision = rp.precision;
+ } else if (setmode == AUMODE_PLAY) {
+ rp.sample_rate = pp.sample_rate;
+ rp.encoding = pp.encoding;
+ rp.channels = pp.channels;
+ rp.precision = pp.precision;
+ }
+ }
+ if (setmode & AUMODE_RECORD)
+ sc->sc_rparams = rp;
+ if (setmode & AUMODE_PLAY)
+ sc->sc_pparams = pp;
+ }
- init = 1;
+ oldpblksize = sc->sc_pr.blksize;
+ oldrblksize = sc->sc_rr.blksize;
+ /* Play params can affect the record params, so recalculate blksize. */
+ if (nr || np) {
+ audio_calc_blksize(sc, AUMODE_RECORD);
+ audio_calc_blksize(sc, AUMODE_PLAY);
}
+#ifdef AUDIO_DEBUG
+ if (audiodebug > 1 && nr)
+ audio_print_params("After setting record params", &sc->sc_rparams);
+ if (audiodebug > 1 && np)
+ audio_print_params("After setting play params", &sc->sc_pparams);
+#endif
+
if (p->port != ~0) {
if (!cleared)
audio_clear(sc);
cleared = 1;
- error = hw->set_out_port(sc->hw_hdl, p->port);
+ error = au_set_port(sc, &sc->sc_outports, p->port);
if (error)
return(error);
}
@@ -1637,43 +2497,67 @@ audiosetinfo(sc, ai)
audio_clear(sc);
cleared = 1;
- error = hw->set_in_port(sc->hw_hdl, r->port);
+ error = au_set_port(sc, &sc->sc_inports, r->port);
if (error)
return(error);
}
if (p->gain != ~0) {
- ct.dev = hw->get_out_port(sc->hw_hdl);
- ct.type = AUDIO_MIXER_VALUE;
- ct.un.value.num_channels = 1;
- ct.un.value.level[AUDIO_MIXER_LEVEL_MONO] = p->gain;
- error = hw->set_port(sc->hw_hdl, &ct);
+ au_get_gain(sc, &sc->sc_outports, &gain, &balance);
+ error = au_set_gain(sc, &sc->sc_outports, p->gain, balance);
if (error)
return(error);
}
if (r->gain != ~0) {
- ct.dev = hw->get_in_port(sc->hw_hdl);
+ au_get_gain(sc, &sc->sc_inports, &gain, &balance);
+ error = au_set_gain(sc, &sc->sc_inports, r->gain, balance);
+ if (error)
+ return(error);
+ }
+
+ if (p->balance != (u_char)~0) {
+ au_get_gain(sc, &sc->sc_outports, &gain, &balance);
+ error = au_set_gain(sc, &sc->sc_outports, gain, p->balance);
+ if (error)
+ return(error);
+ }
+ if (r->balance != (u_char)~0) {
+ au_get_gain(sc, &sc->sc_inports, &gain, &balance);
+ error = au_set_gain(sc, &sc->sc_inports, gain, r->balance);
+ if (error)
+ return(error);
+ }
+
+ if (ai->monitor_gain != ~0 &&
+ sc->sc_monitor_port != -1) {
+ mixer_ctrl_t ct;
+
+ ct.dev = sc->sc_monitor_port;
ct.type = AUDIO_MIXER_VALUE;
ct.un.value.num_channels = 1;
- ct.un.value.level[AUDIO_MIXER_LEVEL_MONO] = r->gain;
- error = hw->set_port(sc->hw_hdl, &ct);
+ ct.un.value.level[AUDIO_MIXER_LEVEL_MONO] = ai->monitor_gain;
+ error = sc->hw_if->get_port(sc->hw_hdl, &ct);
if (error)
return(error);
}
if (p->pause != (u_char)~0) {
- sc->pr.cb_pause = p->pause;
- if (!p->pause) {
+ sc->sc_pr.pause = p->pause;
+ if (!p->pause && !sc->sc_pbus && (sc->sc_mode & AUMODE_PLAY)) {
s = splaudio();
- audiostartp(sc);
+ error = audiostartp(sc);
splx(s);
+ if (error)
+ return error;
}
}
if (r->pause != (u_char)~0) {
- sc->rr.cb_pause = r->pause;
- if (!r->pause) {
+ sc->sc_rr.pause = r->pause;
+ if (!r->pause && !sc->sc_rbus && (sc->sc_mode & AUMODE_RECORD)) {
s = splaudio();
- audiostartr(sc);
+ error = audiostartr(sc);
splx(s);
+ if (error)
+ return error;
}
}
@@ -1683,74 +2567,72 @@ audiosetinfo(sc, ai)
audio_clear(sc);
cleared = 1;
- if (ai->blocksize == 0)
- bsize = sc->sc_blksize;
- else if (ai->blocksize > AU_RING_SIZE/2)
- bsize = AU_RING_SIZE/2;
- else
- bsize = ai->blocksize;
- bsize = hw->round_blocksize(sc->hw_hdl, bsize);
- if (bsize > AU_RING_SIZE)
- bsize = AU_RING_SIZE;
-
- sc->sc_blksize = bsize;
- init = 1;
- } else if (init) {
- /* Block size calculated from other parameter changes. */
- sc->sc_blksize = audio_calc_blksize(sc);
- }
-
- if (init) {
- audio_alloc_auzero(sc, sc->sc_blksize);
- sc->sc_smpl_in_blk = sc->sc_blksize /
- (hw->get_precision(sc->hw_hdl) / NBBY);
- audio_initbufs(sc);
+ if (ai->blocksize == 0) {
+ audio_calc_blksize(sc, AUMODE_RECORD);
+ audio_calc_blksize(sc, AUMODE_PLAY);
+ sc->sc_blkset = 0;
+ } else {
+ int bs = ai->blocksize;
+ if (hw->round_blocksize)
+ bs = hw->round_blocksize(sc->hw_hdl, bs);
+ sc->sc_pr.blksize = sc->sc_rr.blksize = bs;
+ sc->sc_blkset = 1;
+ }
}
- if (ai->hiwat != ~0) {
- if ((unsigned)ai->hiwat > sc->pr.maxblk)
- ai->hiwat = sc->pr.maxblk;
- if (sc->sc_hiwat != 0)
- sc->sc_hiwat = ai->hiwat;
- }
- if (ai->lowat != ~0) {
- if ((unsigned)ai->lowat > sc->pr.maxblk)
- ai->lowat = sc->pr.maxblk;
- sc->sc_lowat = ai->lowat;
- }
- if (ai->backlog != ~0) {
- if ((unsigned)ai->backlog > (sc->pr.maxblk/2))
- ai->backlog = sc->pr.maxblk/2;
- sc->sc_backlog = ai->backlog;
- }
if (ai->mode != ~0) {
- if (!cleared)
- audio_clear(sc);
- cleared = 1;
-
- sc->sc_mode = ai->mode;
- if (sc->sc_mode & AUMODE_PLAY) {
+ if (sc->sc_mode & AUMODE_PLAY)
audio_init_play(sc);
- if (!hw->full_duplex) /* Play takes precedence */
- sc->sc_mode &= ~(AUMODE_RECORD);
- }
if (sc->sc_mode & AUMODE_RECORD)
audio_init_record(sc);
}
- error = hw->commit_settings(sc->hw_hdl);
- if (error)
- return (error);
+ if (hw->commit_settings) {
+ error = hw->commit_settings(sc->hw_hdl);
+ if (error)
+ return (error);
+ }
if (cleared) {
s = splaudio();
- if (sc->sc_mode & AUMODE_PLAY)
- audiostartp(sc);
- if (sc->sc_mode & AUMODE_RECORD)
- audiostartr(sc);
+ error = audio_initbufs(sc);
+ if (error) goto err;
+ if (sc->sc_pr.blksize != oldpblksize ||
+ sc->sc_rr.blksize != oldrblksize)
+ audio_calcwater(sc);
+ if ((sc->sc_mode & AUMODE_PLAY) &&
+ pbus && !sc->sc_pbus)
+ error = audiostartp(sc);
+ if (!error &&
+ (sc->sc_mode & AUMODE_RECORD) &&
+ rbus && !sc->sc_rbus)
+ error = audiostartr(sc);
+ err:
splx(s);
+ if (error)
+ return error;
}
+ /* Change water marks after initializing the buffers. */
+ if (ai->hiwat != ~0) {
+ blks = ai->hiwat;
+ if (blks > sc->sc_pr.maxblks)
+ blks = sc->sc_pr.maxblks;
+ if (blks < 2)
+ blks = 2;
+ sc->sc_pr.usedhigh = blks * sc->sc_pr.blksize;
+ }
+ if (ai->lowat != ~0) {
+ blks = ai->lowat;
+ if (blks > sc->sc_pr.maxblks - 1)
+ blks = sc->sc_pr.maxblks - 1;
+ sc->sc_pr.usedlow = blks * sc->sc_pr.blksize;
+ }
+ if (ai->hiwat != ~0 || ai->lowat != ~0) {
+ if (sc->sc_pr.usedlow > sc->sc_pr.usedhigh - sc->sc_pr.blksize)
+ sc->sc_pr.usedlow = sc->sc_pr.usedhigh - sc->sc_pr.blksize;
+ }
+
return (0);
}
@@ -1761,54 +2643,71 @@ audiogetinfo(sc, ai)
{
struct audio_prinfo *r = &ai->record, *p = &ai->play;
struct audio_hw_if *hw = sc->hw_if;
- mixer_ctrl_t ct;
if (hw == 0) /* HW has not attached */
return(ENXIO);
- p->sample_rate = hw->get_out_sr(sc->hw_hdl);
- r->sample_rate = hw->get_in_sr(sc->hw_hdl);
- p->channels = r->channels = hw->get_channels(sc->hw_hdl);
- p->precision = r->precision = hw->get_precision(sc->hw_hdl);
- p->encoding = hw->get_encoding(sc->hw_hdl);
- r->encoding = hw->get_encoding(sc->hw_hdl);
-
- r->port = hw->get_in_port(sc->hw_hdl);
- p->port = hw->get_out_port(sc->hw_hdl);
-
- ct.dev = r->port;
- ct.type = AUDIO_MIXER_VALUE;
- ct.un.value.num_channels = 1;
- if (hw->get_port(sc->hw_hdl, &ct) == 0)
- r->gain = ct.un.value.level[AUDIO_MIXER_LEVEL_MONO];
- else
- r->gain = AUDIO_MAX_GAIN/2;
+ p->sample_rate = sc->sc_pparams.sample_rate;
+ r->sample_rate = sc->sc_rparams.sample_rate;
+ p->channels = sc->sc_pparams.channels;
+ r->channels = sc->sc_rparams.channels;
+ p->precision = sc->sc_pparams.precision;
+ r->precision = sc->sc_rparams.precision;
+ p->encoding = sc->sc_pparams.encoding;
+ r->encoding = sc->sc_rparams.encoding;
+
+ r->port = au_get_port(sc, &sc->sc_inports);
+ p->port = au_get_port(sc, &sc->sc_outports);
+
+ r->avail_ports = sc->sc_inports.allports;
+ p->avail_ports = sc->sc_outports.allports;
+
+ au_get_gain(sc, &sc->sc_inports, &r->gain, &r->balance);
+ au_get_gain(sc, &sc->sc_outports, &p->gain, &p->balance);
+
+ if (sc->sc_monitor_port != -1) {
+ mixer_ctrl_t ct;
+
+ ct.dev = sc->sc_monitor_port;
+ ct.type = AUDIO_MIXER_VALUE;
+ ct.un.value.num_channels = 1;
+ if (sc->hw_if->get_port(sc->hw_hdl, &ct))
+ ai->monitor_gain = 0;
+ else
+ ai->monitor_gain =
+ ct.un.value.level[AUDIO_MIXER_LEVEL_MONO];
+ } else
+ ai->monitor_gain = 0;
- ct.dev = p->port;
- ct.un.value.num_channels = 1;
- if (hw->get_port(sc->hw_hdl, &ct) == 0)
- p->gain = ct.un.value.level[AUDIO_MIXER_LEVEL_MONO];
- else
- p->gain = AUDIO_MAX_GAIN/2;
+ p->seek = sc->sc_pr.used;
+ r->seek = sc->sc_rr.used;
+
+ p->samples = sc->sc_pr.stamp - sc->sc_pr.drops;
+ r->samples = sc->sc_rr.stamp - sc->sc_rr.drops;
- p->pause = sc->pr.cb_pause;
- r->pause = sc->rr.cb_pause;
- p->error = sc->pr.cb_drops != 0;
- r->error = sc->rr.cb_drops != 0;
+ p->eof = sc->sc_eof;
+ r->eof = 0;
- p->open = ((sc->sc_open & AUOPEN_WRITE) != 0);
- r->open = ((sc->sc_open & AUOPEN_READ) != 0);
+ p->pause = sc->sc_pr.pause;
+ r->pause = sc->sc_rr.pause;
- p->samples = sc->pr.au_stamp - sc->pr.cb_pdrops;
- r->samples = sc->rr.au_stamp - sc->rr.cb_pdrops;
+ p->error = sc->sc_pr.drops != 0;
+ r->error = sc->sc_rr.drops != 0;
- p->seek = sc->sc_wseek;
- r->seek = sc->sc_rseek;
+ p->waiting = r->waiting = 0; /* open never hangs */
- ai->blocksize = sc->sc_blksize;
- ai->hiwat = sc->sc_hiwat;
- ai->lowat = sc->sc_lowat;
- ai->backlog = sc->sc_backlog;
+ p->open = (sc->sc_open & AUOPEN_WRITE) != 0;
+ r->open = (sc->sc_open & AUOPEN_READ) != 0;
+
+ p->active = sc->sc_pbus;
+ r->active = sc->sc_rbus;
+
+ p->buffer_size = sc->sc_pr.bufsize;
+ r->buffer_size = sc->sc_rr.bufsize;
+
+ ai->blocksize = sc->sc_pr.blksize;
+ ai->hiwat = sc->sc_pr.usedhigh / sc->sc_pr.blksize;
+ ai->lowat = sc->sc_pr.usedlow / sc->sc_pr.blksize;
ai->mode = sc->sc_mode;
return (0);
@@ -1825,24 +2724,53 @@ mixer_open(dev, flags, ifmt, p)
{
int unit = AUDIOUNIT(dev);
struct audio_softc *sc;
- struct audio_hw_if *hw;
- if (unit >= NAUDIO || !audio_softc[unit]) {
- DPRINTF(("mixer_open: invalid device unit - %d\n", unit));
- return (ENODEV);
- }
+ if (unit >= audio_cd.cd_ndevs ||
+ (sc = audio_cd.cd_devs[unit]) == NULL)
+ return ENXIO;
- sc = audio_softc[unit];
- hw = sc->hw_if;
-
- DPRINTF(("mixer_open: dev=%x flags=0x%x sc=0x%x\n", dev, flags, sc));
- if (hw == 0) /* Hardware has not attached to us... */
+ if (!sc->hw_if)
return (ENXIO);
+ DPRINTF(("mixer_open: dev=0x%x flags=0x%x sc=%p\n", dev, flags, sc));
+
return (0);
}
/*
+ * Remove a process from those to be signalled on mixer activity.
+ */
+static void
+mixer_remove(sc, p)
+ struct audio_softc *sc;
+ struct proc *p;
+{
+ struct mixer_asyncs **pm, *m;
+
+ for(pm = &sc->sc_async_mixer; *pm; pm = &(*pm)->next) {
+ if ((*pm)->proc == p) {
+ m = *pm;
+ *pm = m->next;
+ free(m, M_DEVBUF);
+ return;
+ }
+ }
+}
+
+/*
+ * Signal all processes waiting for the mixer.
+ */
+static void
+mixer_signal(sc)
+ struct audio_softc *sc;
+{
+ struct mixer_asyncs *m;
+
+ for(m = sc->sc_async_mixer; m; m = m->next)
+ psignal(m->proc, SIGIO);
+}
+
+/*
* Close a mixer device
*/
/* ARGSUSED */
@@ -1852,8 +2780,13 @@ mixer_close(dev, flags, ifmt, p)
int flags, ifmt;
struct proc *p;
{
+ int unit = AUDIOUNIT(dev);
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
+
DPRINTF(("mixer_close: unit %d\n", AUDIOUNIT(dev)));
+ mixer_remove(sc, p);
+
return (0);
}
@@ -1866,42 +2799,56 @@ mixer_ioctl(dev, cmd, addr, flag, p)
struct proc *p;
{
int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = audio_softc[unit];
+ struct audio_softc *sc = audio_cd.cd_devs[unit];
struct audio_hw_if *hw = sc->hw_if;
int error = EINVAL;
DPRINTF(("mixer_ioctl(%d,'%c',%d)\n",
- IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff));
+ IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff));
switch (cmd) {
+ case FIOASYNC:
+ mixer_remove(sc, p); /* remove old entry */
+ if (*(int *)addr) {
+ struct mixer_asyncs *ma;
+ ma = malloc(sizeof (struct mixer_asyncs), M_DEVBUF, M_WAITOK);
+ ma->next = sc->sc_async_mixer;
+ ma->proc = p;
+ sc->sc_async_mixer = ma;
+ }
+ error = 0;
+ break;
+
case AUDIO_GETDEV:
- DPRINTF(("AUDIO_GETDEV\n"));
- error = hw->getdev(sc->hw_hdl, (audio_device_t *)addr);
- break;
+ DPRINTF(("AUDIO_GETDEV\n"));
+ error = hw->getdev(sc->hw_hdl, (audio_device_t *)addr);
+ break;
case AUDIO_MIXER_DEVINFO:
- DPRINTF(("AUDIO_MIXER_DEVINFO\n"));
- error = hw->query_devinfo(sc->hw_hdl, (mixer_devinfo_t *)addr);
- break;
+ DPRINTF(("AUDIO_MIXER_DEVINFO\n"));
+ error = hw->query_devinfo(sc->hw_hdl, (mixer_devinfo_t *)addr);
+ break;
case AUDIO_MIXER_READ:
- DPRINTF(("AUDIO_MIXER_READ\n"));
- error = hw->get_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
- break;
+ DPRINTF(("AUDIO_MIXER_READ\n"));
+ error = hw->get_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
+ break;
case AUDIO_MIXER_WRITE:
- DPRINTF(("AUDIO_MIXER_WRITE\n"));
- error = hw->set_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
- if (error == 0)
- error = hw->commit_settings(sc->hw_hdl);
- break;
+ DPRINTF(("AUDIO_MIXER_WRITE\n"));
+ error = hw->set_port(sc->hw_hdl, (mixer_ctrl_t *)addr);
+ if (!error && hw->commit_settings)
+ error = hw->commit_settings(sc->hw_hdl);
+ if (!error)
+ mixer_signal(sc);
+ break;
default:
- error = EINVAL;
- break;
+ error = EINVAL;
+ break;
}
DPRINTF(("mixer_ioctl(%d,'%c',%d) result %d\n",
- IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
+ IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
return (error);
}
#endif
diff --git a/sys/dev/audio_if.h b/sys/dev/audio_if.h
index ac6c67440ce..5d042eb0086 100644
--- a/sys/dev/audio_if.h
+++ b/sys/dev/audio_if.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: audio_if.h,v 1.5 1997/07/10 23:06:30 provos Exp $ */
-/* $NetBSD: audio_if.h,v 1.7 1996/03/07 15:00:10 christos Exp $ */
+/* $OpenBSD: audio_if.h,v 1.6 1998/04/26 21:03:08 provos Exp $ */
+/* $NetBSD: audio_if.h,v 1.24 1998/01/10 14:07:25 tv Exp $ */
/*
* Copyright (c) 1994 Havard Eidnes.
@@ -41,38 +41,39 @@
struct audio_softc;
+struct audio_params {
+ u_long sample_rate; /* sample rate */
+ u_int encoding; /* e.g. ulaw, linear, etc */
+ u_int precision; /* bits/sample */
+ u_int channels; /* mono(1), stereo(2) */
+ /* Software en/decode functions, set if SW coding required by HW */
+ void (*sw_code)__P((void *, u_char *, int));
+ int factor; /* coding space change */
+};
+
+/* The default audio mode: 8 kHz mono ulaw */
+extern struct audio_params audio_default;
+
struct audio_hw_if {
- int (*open)__P((dev_t, int)); /* open hardware */
+ int (*open)__P((void *, int)); /* open hardware */
void (*close)__P((void *)); /* close hardware */
int (*drain)__P((void *)); /* Optional: drain buffers */
- /* Sample rate */
- int (*set_in_sr)__P((void *, u_long));
- u_long (*get_in_sr)__P((void *));
- int (*set_out_sr)__P((void *, u_long));
- u_long (*get_out_sr)__P((void *));
-
/* Encoding. */
- /* Precision = bits/sample, usually 8 or 16 */
/* XXX should we have separate in/out? */
int (*query_encoding)__P((void *, struct audio_encoding *));
- int (*set_format)__P((void *, u_int, u_int));
- int (*get_encoding)__P((void *));
- int (*get_precision)__P((void *));
-
- /* Channels - mono(1), stereo(2) */
- int (*set_channels)__P((void *, int));
- int (*get_channels)__P((void *));
+ /* Set the audio encoding parameters (record and play).
+ * Return 0 on success, or an error code if the
+ * requested parameters are impossible.
+ * The values in the params struct may be changed (e.g. rounding
+ * to the nearest sample rate.)
+ */
+ int (*set_params)__P((void *, int, int, struct audio_params *, struct audio_params *));
+
/* Hardware may have some say in the blocksize to choose */
int (*round_blocksize)__P((void *, int));
- /* Ports (in/out ports) */
- int (*set_out_port)__P((void *, int));
- int (*get_out_port)__P((void *));
- int (*set_in_port)__P((void *, int));
- int (*get_in_port)__P((void *));
-
/*
* Changing settings may require taking device out of "data mode",
* which can be quite expensive. Also, audiosetinfo() may
@@ -83,19 +84,15 @@ struct audio_hw_if {
*/
int (*commit_settings)__P((void *));
- /* Software en/decode functions, set if SW coding required by HW */
- void (*sw_encode)__P((void *, int, u_char *, int));
- void (*sw_decode)__P((void *, int, u_char *, int));
-
/* Start input/output routines. These usually control DMA. */
+ int (*init_output)__P((void *, void *, int));
+ int (*init_input)__P((void *, void *, int));
int (*start_output)__P((void *, void *, int,
void (*)(void *), void *));
int (*start_input)__P((void *, void *, int,
void (*)(void *), void *));
int (*halt_output)__P((void *));
int (*halt_input)__P((void *));
- int (*cont_output)__P((void *));
- int (*cont_input)__P((void *));
int (*speaker_ctl)__P((void *, int));
#define SPKR_ON 1
@@ -110,25 +107,59 @@ struct audio_hw_if {
int (*query_devinfo)__P((void *, mixer_devinfo_t *));
- int full_duplex; /* non-null if HW is able to do full-duplex */
- int audio_unit;
+ /* Allocate/free memory for the ring buffer. Usually malloc/free. */
+ void *(*alloc)__P((void *, unsigned long, int, int));
+ void (*free)__P((void *, void *, int));
+ unsigned long (*round_buffersize)__P((void *, unsigned long));
+ int (*mappage)__P((void *, void *, int, int));
+
+ int (*get_props)__P((void *)); /* device properties */
};
-/* Register / deregister hardware driver */
-extern int audio_hardware_attach __P((struct audio_hw_if *, void *));
-extern int audio_hardware_detach __P((struct audio_hw_if *));
+struct midi_info {
+ char *name; /* Name of MIDI hardware */
+ int props;
+};
+#define MIDI_PROP_OUT_INTR 1
+
+struct midi_hw_if {
+ int (*open)__P((void *, int, /* open hardware */
+ void (*)__P((void *, int)),
+ void (*)__P((void *)),
+ void *));
+ void (*close)__P((void *)); /* close hardware */
+ int (*output)__P((void *, int)); /* output a byte */
+ void (*getinfo)__P((void *, struct midi_info *));
+ int (*ioctl)__P((u_long, caddr_t, int, struct proc *));
+};
+
+struct audio_attach_args {
+ int type;
+ void *hwif; /* either audio_hw_if * or midi_hw_if * */
+ void *hdl;
+};
+#define AUDIODEV_TYPE_AUDIO 0
+#define AUDIODEV_TYPE_MIDI 1
+
+/* Attach the MI driver(s) to the MD driver. */
+extern void audio_attach_mi __P((struct audio_hw_if *, struct midi_hw_if *, void *, struct device *));
/* Device identity flags */
#define SOUND_DEVICE 0
#define AUDIO_DEVICE 0x80
+#define AUDIOCTL_DEVICE 0xc0
#define MIXER_DEVICE 0x10
-#define ISDEVAUDIO(x) ((minor(x)&0xf0) == AUDIO_DEVICE)
-#define ISDEVSOUND(x) ((minor(x)&0xf0) == SOUND_DEVICE)
-#define ISDEVMIXER(x) ((minor(x)&0xf0) == MIXER_DEVICE)
-
#define AUDIOUNIT(x) (minor(x)&0x0f)
#define AUDIODEV(x) (minor(x)&0xf0)
+#define ISDEVSOUND(x) (AUDIODEV((x)) == SOUND_DEVICE)
+#define ISDEVAUDIO(x) (AUDIODEV((x)) == AUDIO_DEVICE)
+#define ISDEVAUDIOCTL(x) (AUDIODEV((x)) == AUDIOCTL_DEVICE)
+#define ISDEVMIXER(x) (AUDIODEV((x)) == MIXER_DEVICE)
+
+/*#ifndef __i386__*/
#define splaudio splbio /* XXX */
#define IPL_AUDIO IPL_BIO /* XXX */
+/*#endif*/
+
diff --git a/sys/dev/audiovar.h b/sys/dev/audiovar.h
index 4cda887e095..f712205c9a2 100644
--- a/sys/dev/audiovar.h
+++ b/sys/dev/audiovar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: audiovar.h,v 1.4 1997/07/10 23:06:30 provos Exp $ */
-/* $NetBSD: audiovar.h,v 1.7 1996/02/20 10:00:33 mycroft Exp $ */
+/* $OpenBSD: audiovar.h,v 1.5 1998/04/26 21:03:09 provos Exp $ */
+/* $NetBSD: audiovar.h,v 1.17 1997/10/19 07:42:01 augustss Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -40,56 +40,58 @@
* Initial/default block duration is both configurable and patchable.
*/
#ifndef AUDIO_BLK_MS
-#define AUDIO_BLK_MS 20 /* 20 ms */
+#define AUDIO_BLK_MS 50 /* 50 ms */
#endif
-#ifndef AUDIO_BACKLOG
-#define AUDIO_BACKLOG 3 /* 60 ms */
-#endif
-
-/*
- * Use a single page as the size of the audio ring buffers, so that
- * the data won't cross a page boundary. This way the dma carried out
- * in the hardware module will be efficient (i.e., at_dma() won't have
- * to make a copy).
- */
#ifndef AU_RING_SIZE
-#define AU_RING_SIZE NBPG
+#define AU_RING_SIZE 65536
#endif
-#define AU_RING_MOD(k) ((k) & (AU_RING_SIZE - 1))
-#define AU_RING_EMPTY(rp) ((rp)->hp == (rp)->tp)
-#define AU_RING_FULL(rp) (AU_RING_MOD((rp)->tp + 1) == (rp)->hp)
-#define AU_RING_LEN(rp) (AU_RING_MOD((rp)->tp - (rp)->hp))
-#define AU_RING_INIT(rp) { \
- (rp)->nblk = (rp)->au_stamp = 0; \
- (rp)->hp = (rp)->tp = (rp)->bp; \
- }
-
-struct audio_buffer {
- u_char *hp; /* head */
- u_char *tp; /* tail */
- u_char *bp; /* start of buffer */
- u_char *ep; /* end of buffer */
-
- int nblk; /* number of active blocks in buffer */
- int maxblk; /* max # of active blocks in buffer */
- u_long au_stamp; /* number of audio samples read/written */
-
- u_short cb_pause; /* io paused */
- u_long cb_drops; /* missed samples from over/underrun */
- u_long cb_pdrops; /* paused samples */
-
- int fill; /* number of silence pad bytes */
- u_char *otp; /* point where silence padding started */
+#define AUMINBUF 512
+#define AUMINBLK 32
+#define AUMINNOBLK 3
+struct audio_ringbuffer {
+ int bufsize; /* allocated memory */
+ int blksize; /* I/O block size */
+ int maxblks; /* no of blocks in ring */
+ u_char *start; /* start of buffer area */
+ u_char *end; /* end of buffer area */
+ u_char *inp; /* input pointer (to buffer) */
+ u_char *outp; /* output pointer (from buffer) */
+ int used; /* no of used bytes */
+ int usedlow; /* start writer when used falls below this */
+ int usedhigh; /* stop writer when used goes above this */
+ u_long stamp; /* bytes transferred */
+ u_long stamp_last; /* old value of bytes transferred */
+ u_long drops; /* missed samples from over/underrun */
+ u_long pdrops; /* paused samples */
+ char pause; /* transfer is paused */
+ char copying; /* data is being copied */
+ char needfill; /* buffer needs filling when copying is done */
+ char mmapped; /* device is mmap()-ed */
+};
+
+#define AUDIO_N_PORTS 4
+
+struct au_mixer_ports {
+ int index;
+ int master;
+ int nports;
+ u_char isenum;
+ u_int allports;
+ u_int aumask[AUDIO_N_PORTS];
+ u_int misel [AUDIO_N_PORTS];
+ u_int miport[AUDIO_N_PORTS];
};
/*
* Software state, per audio device.
*/
struct audio_softc {
- void *hw_hdl; /* Hardware driver handle */
+ struct device dev;
+ void *hw_hdl; /* Hardware driver handle */
struct audio_hw_if *hw_if; /* Hardware interface */
+ struct device *sc_dev; /* Hardware device struct */
u_char sc_open; /* single use device */
#define AUOPEN_READ 0x01
#define AUOPEN_WRITE 0x02
@@ -97,33 +99,48 @@ struct audio_softc {
struct selinfo sc_wsel; /* write selector */
struct selinfo sc_rsel; /* read selector */
- struct proc *sc_async; /* process who wants SIGIO */
+ struct proc *sc_async_audio; /* process who wants audio SIGIO */
+ struct mixer_asyncs {
+ struct mixer_asyncs *next;
+ struct proc *proc;
+ } *sc_async_mixer; /* processes who want mixer SIGIO */
/* Sleep channels for reading and writing. */
int sc_rchan;
int sc_wchan;
/* Ring buffers, separate for record and play. */
- struct audio_buffer rr; /* Record ring */
- struct audio_buffer pr; /* Play ring */
+ struct audio_ringbuffer sc_rr; /* Record ring */
+ struct audio_ringbuffer sc_pr; /* Play ring */
+
+ u_char sc_blkset; /* Blocksize has been set */
+
+ u_char *sc_sil_start; /* start of silence in buffer */
+ int sc_sil_count; /* # of silence bytes */
- u_char *auzero_block; /* a block of silence */
-
u_char sc_rbus; /* input dma in progress */
u_char sc_pbus; /* output dma in progress */
- u_long sc_wseek; /* timestamp of last frame written */
- u_long sc_rseek; /* timestamp of last frame read */
+ struct audio_params sc_pparams; /* play encoding parameters */
+ struct audio_params sc_rparams; /* record encoding parameters */
+
+ int sc_eof; /* EOF, i.e. zero sixed write, counter */
+ u_long sc_wstamp;
+ u_long sc_playdrop;
- int sc_blksize; /* recv block (chunk) size in bytes */
- int sc_smpl_in_blk; /* # samples in a block */
- int sc_50ms; /* # of samples for 50ms? */
- int sc_backlog; /* # blks of xmit backlog to generate */
- int sc_lowat; /* xmit low water mark (for wakeup) */
- int sc_hiwat; /* xmit high water mark (for wakeup) */
+ int sc_full_duplex; /* device in full duplex mode */
- int sc_rblks; /* number of phantom record blocks */
- int sc_wblks; /* number of output silence blocks */
- int sc_pencoding; /* current encoding; play */
- int sc_rencoding; /* current encoding; record */
+ struct au_mixer_ports sc_inports, sc_outports;
+ int sc_monitor_port;
+
+#ifdef AUDIO_INTR_TIME
+ u_long sc_pfirstintr; /* first time we saw a xmit interrupt */
+ int sc_pnintr; /* number of interrupts */
+ u_long sc_plastintr; /* last time we saw a xmit interrupt */
+ long sc_pblktime; /* nominal time between interrupts */
+ u_long sc_rfirstintr; /* first time we saw a rec interrupt */
+ int sc_rnintr; /* number of interrupts */
+ u_long sc_rlastintr; /* last time we saw a xrec interrupt */
+ long sc_rblktime; /* nominal time between interrupts */
+#endif
};
diff --git a/sys/dev/ic/ad1848reg.h b/sys/dev/ic/ad1848reg.h
index 6d0f45dba67..7c7c927ce0e 100644
--- a/sys/dev/ic/ad1848reg.h
+++ b/sys/dev/ic/ad1848reg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ad1848reg.h,v 1.4 1996/10/31 01:01:22 niklas Exp $ */
-/* $NetBSD: ad1848reg.h,v 1.1 1995/07/07 02:11:45 brezak Exp $ */
+/* $OpenBSD: ad1848reg.h,v 1.5 1998/04/26 21:03:12 provos Exp $ */
+/* $NetBSD: ad1848reg.h,v 1.4 1997/05/07 20:23:53 augustss Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -37,17 +37,16 @@
*/
/*
* Copyright (c) 1993 Analog Devices Inc. All rights reserved
- * (http://www.analog.com, mike.long@analog.com)
*/
/* parent driver is primarily responsible for checking this */
#define AD1848_BASE_VALID(base) (((base) & 0x003) == 0)
/* AD1848 direct registers */
-#define AD1848_IADDR 0x04
-#define AD1848_IDATA 0x05
-#define AD1848_STATUS 0x06
-#define AD1848_PIO 0x07
+#define AD1848_IADDR 0x00
+#define AD1848_IDATA 0x01
+#define AD1848_STATUS 0x02
+#define AD1848_PIO 0x03
/* Gain constants */
#define GAIN_0 0x00
@@ -89,9 +88,7 @@
/* AD1848 Sound Port bit defines */
#define SP_IN_INIT 0x80
#define MODE_CHANGE_ENABLE 0x40
-#define MODE_CHANGE_MASK 0xbf
#define TRANSFER_DISABLE 0x20
-#define TRANSFER_DISABLE_MASK 0xdf
#define ADDRESS_MASK 0xe0
/* Status bits */
@@ -101,7 +98,6 @@
/* pbright is not left */
#define PLAYBACK_UPPER 0x08
/* bplower is not upper */
-
#define SAMPLE_ERROR 0x10
#define CAPTURE_READY 0x20
#define CAPTURE_LEFT 0x40
@@ -113,53 +109,42 @@
#define LINE_INPUT 0x00
#define AUX_INPUT 0x40
#define MIC_INPUT 0x80
-#define MIXED_DAC_INPUT 0xC0
+#define MIXED_DAC_INPUT 0xc0
#define INPUT_GAIN_MASK 0xf0
#define INPUT_MIC_GAIN_ENABLE 0x20
-#define INPUT_MIC_GAIN_MASK 0xdf
#define INPUT_SOURCE_MASK 0x3f
#define AUX_INPUT_ATTEN_BITS 0x1f
#define AUX_INPUT_ATTEN_MASK 0xe0
#define AUX_INPUT_MUTE 0x80
-#define AUX_INPUT_MUTE_MASK 0x7f
#define OUTPUT_MUTE 0x80
-#define OUTPUT_MUTE_MASK 0x7f
#define OUTPUT_ATTEN_BITS 0x3f
#define OUTPUT_ATTEN_MASK 0xc0
/* Clock and Data format reg bits (some also Capture Data format) */
-#define CLOCK_SELECT_MASK 0xfe
#define CLOCK_XTAL2 0x01
#define CLOCK_XTAL1 0x00
#define CLOCK_FREQ_MASK 0xf1
-#define STEREO_MONO_MASK 0xef
-#define FMT_STEREO 0x10
#define FMT_MONO 0x00
+#define FMT_STEREO 0x10
#define FORMAT_MASK 0x1f
#define FMT_PCM8 0x00 /* 8-bit unsigned */
#define FMT_ULAW 0x20 /* 8-bit mu-law */
#define FMT_TWOS_COMP 0x40 /* 16-bit signed */
#define FMT_ALAW 0x60 /* 8-bit alaw */
-#define FMT_TWOS_COMP_BE 0xC0 /* 16-bit signed, big endian */
+#define FMT_ADPCM 0xa0 /* IMA ADPCM */
+#define FMT_TWOS_COMP_BE 0xc0 /* 16-bit signed, big endian */
/* Interface Configuration reg bits */
#define PLAYBACK_ENABLE 0x01
-#define PLAYBACK_ENABLE_MASK 0xfe
#define CAPTURE_ENABLE 0x02
-#define CAPTURE_ENABLE_MASK 0xfd
-#define SINGLE_DMA 0x04
-#define SINGLE_DMA_MASK 0xfb
#define DUAL_DMA 0x00
+#define SINGLE_DMA 0x04
#define AUTO_CAL_ENABLE 0x08
-#define AUTO_CAL_DISABLE_MASK 0xf7
#define PLAYBACK_PIO_ENABLE 0x40
-#define PLAYBACK_DMA_MASK 0xbf
#define CAPTURE_PIO_ENABLE 0x80
-#define CAPTURE_DMA_MASK 0x7f
/* Pin control bits */
#define INTERRUPT_ENABLE 0x02
-#define INTERRUPT_MASK 0xfd
#define XCTL0_ENABLE 0x40
#define XCTL1_ENABLE 0x80
@@ -176,7 +161,6 @@
#define MODE2 0x40
/* Digital Mix Control reg bits */
-#define DIGITAL_MIX1_MUTE_MASK 0xfe
#define DIGITAL_MIX1_ENABLE 0x01
#define MIX_ATTEN_MASK 0xfc
diff --git a/sys/dev/isa/ad1848.c b/sys/dev/isa/ad1848.c
index 9a7ed0fc629..2e3e495d4cf 100644
--- a/sys/dev/isa/ad1848.c
+++ b/sys/dev/isa/ad1848.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ad1848.c,v 1.9 1998/01/18 18:58:36 niklas Exp $ */
-/* $NetBSD: ad1848.c,v 1.10 1996/04/29 20:02:32 christos Exp $ */
+/* $OpenBSD: ad1848.c,v 1.10 1998/04/26 21:02:38 provos Exp $ */
+/* $NetBSD: ad1848.c,v 1.45 1998/01/30 02:02:38 augustss Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -67,11 +67,6 @@
* Portions also supplied from the SoundBlaster driver for NetBSD.
*/
-/*
- * Todo:
- * - Need datasheet for CS4231 (for use with GUS MAX)
- * - Use fast audio_dma
- */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
@@ -82,10 +77,14 @@
#include <sys/buf.h>
#include <machine/cpu.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
+#include <vm/vm.h>
+
#include <dev/audio_if.h>
+#include <dev/auconv.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -96,8 +95,7 @@
#include <dev/isa/cs4231var.h>
#ifdef AUDIO_DEBUG
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (ad1848debug) Dprintf x
+#define DPRINTF(x) if (ad1848debug) printf x
int ad1848debug = 0;
#else
#define DPRINTF(x)
@@ -144,12 +142,13 @@ static int ad1848_init_values[] = {
MONO_INPUT_MUTE|ATTEN_6, /* mute mic by default */
0, /* unused */
0, /* record format */
+ 0, /* Crystal Clock Select */
0, /* upper record count */
0 /* lower record count */
};
void ad1848_reset __P((struct ad1848_softc *));
-int ad1848_set_speed __P((struct ad1848_softc *, u_long));
+int ad1848_set_speed __P((struct ad1848_softc *, u_long *));
void ad1848_mute_monitor __P((void *, int));
static int ad_read __P((struct ad1848_softc *, int));
@@ -157,6 +156,8 @@ static __inline void ad_write __P((struct ad1848_softc *, int, int));
static void ad_set_MCE __P((struct ad1848_softc *, int));
static void wait_for_calibration __P((struct ad1848_softc *));
+#define ADREAD(sc, addr) bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_iooffs+(addr))
+#define ADWRITE(sc, addr, data) bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (sc)->sc_iooffs+(addr), (data))
static int
ad_read(sc, reg)
@@ -165,8 +166,8 @@ ad_read(sc, reg)
{
int x;
- outb(sc->sc_iobase+AD1848_IADDR, (u_char) (reg & 0xff) | sc->MCE_bit);
- x = inb(sc->sc_iobase+AD1848_IDATA);
+ ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
+ x = ADREAD(sc, AD1848_IDATA);
/* printf("(%02x<-%02x) ", reg|sc->MCE_bit, x); */
return x;
@@ -178,8 +179,8 @@ ad_write(sc, reg, data)
int reg;
int data;
{
- outb(sc->sc_iobase+AD1848_IADDR, (u_char) (reg & 0xff) | sc->MCE_bit);
- outb(sc->sc_iobase+AD1848_IDATA, (u_char) (data & 0xff));
+ ADWRITE(sc, AD1848_IADDR, (reg & 0xff) | sc->MCE_bit);
+ ADWRITE(sc, AD1848_IDATA, data & 0xff);
/* printf("(%02x->%02x) ", reg|sc->MCE_bit, data); */
}
@@ -193,14 +194,14 @@ ad_set_MCE(sc, state)
else
sc->MCE_bit = 0;
- outb(sc->sc_iobase+AD1848_IADDR, sc->MCE_bit);
+ ADWRITE(sc, AD1848_IADDR, sc->MCE_bit);
}
static void
wait_for_calibration(sc)
struct ad1848_softc *sc;
{
- int timeout = 100000;
+ int timeout;
DPRINTF(("ad1848: Auto calibration started.\n"));
/*
@@ -209,18 +210,19 @@ wait_for_calibration(sc)
* 1) Wait until the chip becomes ready (reads don't return 0x80).
* 2) Wait until the ACI bit of I11 gets on and then off.
*/
- while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ timeout = 100000;
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
timeout--;
- if (inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
DPRINTF(("ad1848: Auto calibration timed out(1).\n"));
- outb(sc->sc_iobase+AD1848_IADDR, SP_TEST_AND_INIT);
+ ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
timeout = 100000;
- while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) != SP_TEST_AND_INIT)
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) != SP_TEST_AND_INIT)
timeout--;
- if (inb(sc->sc_iobase+AD1848_IADDR) == SP_TEST_AND_INIT)
+ if (ADREAD(sc, AD1848_IADDR) == SP_TEST_AND_INIT)
DPRINTF(("ad1848: Auto calibration timed out(1.5).\n"));
if (!(ad_read(sc, SP_TEST_AND_INIT) & AUTO_CAL_IN_PROG)) {
@@ -249,7 +251,7 @@ ad1848_dump_regs(sc)
int i;
u_char r;
- printf("ad1848 status=%02x", inb(sc->sc_iobase+AD1848_STATUS));
+ printf("ad1848 status=%02x", ADREAD(sc, AD1848_STATUS));
printf(" regs: ");
for (i = 0; i < 16; i++) {
r = ad_read(sc, i);
@@ -260,8 +262,8 @@ ad1848_dump_regs(sc)
r = ad_read(sc, i);
printf("%02x ", r);
}
- printf("\n");
}
+ printf("\n");
}
#endif
@@ -283,7 +285,8 @@ ad1848_forceintr(sc)
* it is needed (and you pay the latency). Also, you might
* never need the buffer anyway.)
*/
- isadma_start(&dmabuf, 1, sc->sc_drq, DMAMODE_READ);
+ isa_dmastart(sc->sc_isa, sc->sc_drq, &dmabuf, 1, NULL,
+ DMAMODE_READ, BUS_DMA_NOWAIT);
ad_write(sc, SP_LOWER_BASE_COUNT, 0);
ad_write(sc, SP_UPPER_BASE_COUNT, 0);
@@ -292,16 +295,13 @@ ad1848_forceintr(sc)
#endif
/*
- * Probe for the ad1848 chip
+ * Map and probe for the ad1848 chip
*/
int
-ad1848_probe(sc)
+ad1848_mapprobe(sc, iobase)
struct ad1848_softc *sc;
+ int iobase;
{
- register int iobase = sc->sc_iobase;
- u_char tmp, tmp1 = 0xff, tmp2 = 0xff;
- int i;
-
if (!AD1848_BASE_VALID(iobase)) {
#ifdef AUDIO_DEBUG
printf("ad1848: configured iobase %04x invalid\n", iobase);
@@ -309,8 +309,28 @@ ad1848_probe(sc)
return 0;
}
- sc->sc_iobase = iobase;
+ sc->sc_iooffs = 0;
+ /* Map the AD1848 ports */
+ if (bus_space_map(sc->sc_iot, iobase, AD1848_NPORT, 0, &sc->sc_ioh))
+ return 0;
+
+ if (!ad1848_probe(sc)) {
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT);
+ return 0;
+ } else
+ return 1;
+}
+/*
+ * Probe for the ad1848 chip
+ */
+int
+ad1848_probe(sc)
+ struct ad1848_softc *sc;
+{
+ u_char tmp, tmp1 = 0xff, tmp2 = 0xff;
+ int i;
+
/* Is there an ad1848 chip ? */
sc->MCE_bit = MODE_CHANGE_ENABLE;
sc->mode = 1; /* MODE 1 = original ad1848/ad1846/cs4248 */
@@ -324,11 +344,12 @@ ad1848_probe(sc)
*
* If the I/O address is unused, inb() typically returns 0xff.
*/
- if (((tmp = inb(iobase+AD1848_IADDR)) & SP_IN_INIT) != 0x00) { /* Not a AD1848 */
+ tmp = ADREAD(sc, AD1848_IADDR);
+ if (tmp & SP_IN_INIT) { /* Not a AD1848 */
#if 0
DPRINTF(("ad_detect_A %x\n", tmp));
#endif
- return 0;
+ goto bad;
}
/*
@@ -342,7 +363,7 @@ ad1848_probe(sc)
if ((tmp1 = ad_read(sc, 0)) != 0xaa ||
(tmp2 = ad_read(sc, 1)) != 0x45) {
DPRINTF(("ad_detect_B (%x/%x)\n", tmp1, tmp2));
- return 0;
+ goto bad;
}
ad_write(sc, 0, 0x45);
@@ -351,7 +372,7 @@ ad1848_probe(sc)
if ((tmp1 = ad_read(sc, 0)) != 0x45 ||
(tmp2 = ad_read(sc, 1)) != 0xaa) {
DPRINTF(("ad_detect_C (%x/%x)\n", tmp1, tmp2));
- return 0;
+ goto bad;
}
/*
@@ -363,7 +384,7 @@ ad1848_probe(sc)
if ((tmp & 0x0f) != ((tmp1 = ad_read(sc, SP_MISC_INFO)) & 0x0f)) {
DPRINTF(("ad_detect_D (%x)\n", tmp1));
- return 0;
+ goto bad;
}
/*
@@ -412,7 +433,7 @@ ad1848_probe(sc)
for (i = 0; i < 16; i++)
if ((tmp1 = ad_read(sc, i)) != (tmp2 = ad_read(sc, i + 16))) {
DPRINTF(("ad_detect_F(%d/%x/%x)\n", i, tmp1, tmp2));
- return 0;
+ goto bad;
}
/*
@@ -435,7 +456,7 @@ ad1848_probe(sc)
ad_write(sc, 2, 0xaa);
if ((tmp2 = ad_read(sc, 18)) == 0xaa) { /* Rotten bits? */
DPRINTF(("ad_detect_H(%x)\n", tmp2));
- return 0;
+ goto bad;
}
/*
@@ -462,13 +483,25 @@ ad1848_probe(sc)
}
/* Wait for 1848 to init */
- while(inb(sc->sc_iobase+AD1848_IADDR) & SP_IN_INIT);
+ while(ADREAD(sc, AD1848_IADDR) & SP_IN_INIT)
+ ;
/* Wait for 1848 to autocal */
- outb(sc->sc_iobase+AD1848_IADDR, SP_TEST_AND_INIT);
- while(inb(sc->sc_iobase+AD1848_IDATA) & AUTO_CAL_IN_PROG);
+ ADWRITE(sc, AD1848_IADDR, SP_TEST_AND_INIT);
+ while(ADREAD(sc, AD1848_IDATA) & AUTO_CAL_IN_PROG)
+ ;
return 1;
+bad:
+ return 0;
+}
+
+/* Unmap the I/O ports */
+void
+ad1848_unmap(sc)
+ struct ad1848_softc *sc;
+{
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, AD1848_NPORT);
}
/*
@@ -480,28 +513,56 @@ ad1848_attach(sc)
struct ad1848_softc *sc;
{
int i;
- struct ad1848_volume vol_mid = {150, 150};
+ struct ad1848_volume vol_mid = {220, 220};
struct ad1848_volume vol_0 = {0, 0};
+ struct audio_params pparams, rparams;
+ int timeout;
sc->sc_locked = 0;
+ sc->sc_playrun = NOTRUNNING;
+ sc->sc_recrun = NOTRUNNING;
+
+ if (sc->sc_drq != -1) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq, MAX_ISADMA,
+ BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("ad1848_attach: can't create map for drq %d\n",
+ sc->sc_drq);
+ return;
+ }
+ }
+ if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq, MAX_ISADMA,
+ BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("ad1848_attach: can't creape map for drq %d\n",
+ sc->sc_recdrq);
+ return;
+ }
+ }
/* Initialize the ad1848... */
- for (i = 0; i < 16; i++)
+ for (i = 0; i < 0x10; i++) {
ad_write(sc, i, ad1848_init_values[i]);
+ timeout = 100000;
+ while (timeout > 0 && ad_read(sc, AD1848_IADDR) & SP_IN_INIT)
+ timeout--;
+ }
/* ...and additional CS4231 stuff too */
if (sc->mode == 2) {
ad_write(sc, SP_INTERFACE_CONFIG, 0); /* disable SINGLE_DMA */
- for (i = 0x10; i <= 0x1f; i++)
- if (ad1848_init_values[i] != 0)
+ for (i = 0x10; i < 0x20; i++)
+ if (ad1848_init_values[i] != 0) {
ad_write(sc, i, ad1848_init_values[i]);
+ timeout = 100000;
+ while (timeout > 0 &&
+ ad_read(sc, AD1848_IADDR) & SP_IN_INIT)
+ timeout--;
+ }
}
ad1848_reset(sc);
- /* Set default parameters (mono, 8KHz, ULAW) */
- (void) ad1848_set_channels(sc, 1);
- (void) ad1848_set_speed(sc, 8000);
- (void) ad1848_set_format(sc, AUDIO_ENCODING_ULAW, 8);
- (void) ad1848_commit_settings(sc);
+ pparams = audio_default;
+ rparams = audio_default;
+ (void) ad1848_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
/* Set default gains */
(void) ad1848_set_rec_gain(sc, &vol_mid);
@@ -520,6 +581,7 @@ ad1848_attach(sc)
(void) ad1848_set_rec_port(sc, MIC_IN_PORT);
printf(": %s", sc->chip_name);
+#undef WAITREADY
}
/*
@@ -527,10 +589,10 @@ ad1848_attach(sc)
*/
int
ad1848_set_rec_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
- register u_char reg, gain;
+ u_char reg, gain;
DPRINTF(("ad1848_set_rec_gain: %d:%d\n", gp->left, gp->right));
@@ -551,7 +613,7 @@ ad1848_set_rec_gain(sc, gp)
int
ad1848_get_rec_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->rec_gain;
@@ -560,7 +622,7 @@ ad1848_get_rec_gain(sc, gp)
int
ad1848_set_out_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -585,7 +647,7 @@ ad1848_set_out_gain(sc, gp)
int
ad1848_get_out_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->out_gain;
@@ -594,7 +656,7 @@ ad1848_get_out_gain(sc, gp)
int
ad1848_set_mon_gain(sc, gp) /* monitor gain */
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -613,7 +675,7 @@ ad1848_set_mon_gain(sc, gp) /* monitor gain */
int
ad1848_get_mon_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->mon_gain;
@@ -622,7 +684,7 @@ ad1848_get_mon_gain(sc, gp)
int
cs4231_set_mono_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg, oreg;
@@ -642,7 +704,7 @@ cs4231_set_mono_gain(sc, gp)
int
cs4231_get_mono_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->mono_gain;
@@ -651,7 +713,7 @@ cs4231_get_mono_gain(sc, gp)
int
ad1848_set_mic_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -673,7 +735,7 @@ ad1848_set_mic_gain(sc, gp)
int
ad1848_get_mic_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
if (sc->mic_gain_on)
@@ -688,7 +750,7 @@ ad1848_mute_monitor(addr, mute)
void *addr;
int mute;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
DPRINTF(("ad1848_mute_monitor: %smuting\n", mute ? "" : "un"));
if (sc->mode == 2) {
@@ -703,7 +765,7 @@ ad1848_mute_monitor(addr, mute)
void
cs4231_mute_monitor(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -724,7 +786,7 @@ cs4231_mute_monitor(sc, mute)
void
cs4231_mute_mono(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -741,7 +803,7 @@ cs4231_mute_mono(sc, mute)
void
cs4231_mute_line(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -762,7 +824,7 @@ cs4231_mute_line(sc, mute)
void
ad1848_mute_aux1(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -783,7 +845,7 @@ ad1848_mute_aux1(sc, mute)
void
ad1848_mute_aux2(sc, mute)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int mute;
{
u_char reg;
@@ -804,7 +866,7 @@ ad1848_mute_aux2(sc, mute)
int
ad1848_set_aux1_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -829,7 +891,7 @@ ad1848_set_aux1_gain(sc, gp)
int
ad1848_get_aux1_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->aux1_gain;
@@ -838,7 +900,7 @@ ad1848_get_aux1_gain(sc, gp)
int
cs4231_set_linein_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg, oregl, oregr;
@@ -864,7 +926,7 @@ cs4231_set_linein_gain(sc, gp)
int
cs4231_get_linein_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->line_gain;
@@ -873,7 +935,7 @@ cs4231_get_linein_gain(sc, gp)
int
ad1848_set_aux2_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
u_char reg;
@@ -898,7 +960,7 @@ ad1848_set_aux2_gain(sc, gp)
int
ad1848_get_aux2_gain(sc, gp)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->aux2_gain;
@@ -906,161 +968,177 @@ ad1848_get_aux2_gain(sc, gp)
}
int
-ad1848_set_in_sr(addr, sr)
- void *addr;
- u_long sr;
-{
- register struct ad1848_softc *sc = addr;
-
- DPRINTF(("ad1848_set_in_sr: %d\n", sr));
-
- return (ad1848_set_speed(sc, sr));
-}
-
-u_long
-ad1848_get_in_sr(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
-
- return (sc->speed);
-}
-
-int
-ad1848_set_out_sr(addr, sr)
- void *addr;
- u_long sr;
-{
- register struct ad1848_softc *sc = addr;
-
- DPRINTF(("ad1848_set_out_sr: %d\n", sr));
-
- return (ad1848_set_speed(sc, sr));
-}
-
-u_long
-ad1848_get_out_sr(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
-
- return (sc->speed);
-}
-
-int
ad1848_query_encoding(addr, fp)
void *addr;
struct audio_encoding *fp;
{
+ struct ad1848_softc *sc = addr;
+
switch (fp->index) {
case 0:
strcpy(fp->name, AudioEmulaw);
- fp->format_id = AUDIO_ENCODING_ULAW;
+ fp->encoding = AUDIO_ENCODING_ULAW;
+ fp->precision = 8;
+ fp->flags = 0;
break;
case 1:
strcpy(fp->name, AudioEalaw);
- fp->format_id = AUDIO_ENCODING_ALAW;
+ fp->encoding = AUDIO_ENCODING_ALAW;
+ fp->precision = 8;
+ fp->flags = 0;
break;
case 2:
- strcpy(fp->name, AudioEpcm16);
- fp->format_id = AUDIO_ENCODING_PCM16;
+ strcpy(fp->name, AudioEslinear_le);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
break;
case 3:
- strcpy(fp->name, AudioEpcm8);
- fp->format_id = AUDIO_ENCODING_PCM8;
+ strcpy(fp->name, AudioEulinear);
+ fp->encoding = AUDIO_ENCODING_ULINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
+ break;
+
+ case 4: /* only on CS4231 */
+ strcpy(fp->name, AudioEslinear_be);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ fp->precision = 16;
+ fp->flags = sc->mode == 1 ? AUDIO_ENCODINGFLAG_EMULATED : 0;
+ break;
+
+ /* emulate some modes */
+ case 5:
+ strcpy(fp->name, AudioEslinear);
+ fp->encoding = AUDIO_ENCODING_SLINEAR;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 6:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 7:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+
+ case 8: /* only on CS4231 */
+ if (sc->mode == 1)
+ return EINVAL;
+ strcpy(fp->name, AudioEadpcm);
+ fp->encoding = AUDIO_ENCODING_ADPCM;
+ fp->precision = 8;
+ fp->flags = 0;
break;
default:
- return(EINVAL);
+ return EINVAL;
/*NOTREACHED*/
}
return (0);
}
int
-ad1848_set_format(addr, encoding, precision)
+ad1848_set_params(addr, setmode, usemode, p, r)
void *addr;
- u_int encoding, precision;
+ int setmode, usemode;
+ struct audio_params *p, *r;
{
- register struct ad1848_softc *sc = addr;
- static u_char format2bits[] = {
- /* AUDIO_ENCODING_NONE */ 0,
- /* AUDIO_ENCODING_ULAW */ FMT_ULAW >> 5,
- /* AUDIO_ENCODING_ALAW */ FMT_ALAW >> 5,
- /* AUDIO_ENCODING_PCM16 */ FMT_TWOS_COMP >> 5,
- /* AUDIO_ENCODING_PCM8 */ FMT_PCM8 >> 5,
- /* AUDIO_ENCODING_ADPCM */ 0,
- };
-
- DPRINTF(("ad1848_set_format: encoding=%d precision=%d\n", encoding, precision));
-
- switch (encoding) {
+ struct ad1848_softc *sc = addr;
+ int error, bits, enc;
+ void (*pswcode) __P((void *, u_char *buf, int cnt));
+ void (*rswcode) __P((void *, u_char *buf, int cnt));
+
+ DPRINTF(("ad1848_set_params: %d %d %d %ld\n",
+ p->encoding, p->precision, p->channels, p->sample_rate));
+
+ enc = p->encoding;
+ pswcode = rswcode = 0;
+ switch (enc) {
+ case AUDIO_ENCODING_SLINEAR_LE:
+ if (p->precision == 8) {
+ enc = AUDIO_ENCODING_ULINEAR_LE;
+ pswcode = rswcode = change_sign8;
+ }
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (p->precision == 16 && sc->mode == 1) {
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ pswcode = rswcode = swap_bytes;
+ }
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ if (p->precision == 16) {
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ pswcode = rswcode = change_sign16;
+ }
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ if (p->precision == 16) {
+ enc = AUDIO_ENCODING_SLINEAR_LE;
+ pswcode = swap_bytes_change_sign16;
+ rswcode = change_sign16_swap_bytes;
+ }
+ break;
+ }
+ switch (enc) {
case AUDIO_ENCODING_ULAW:
+ bits = FMT_ULAW >> 5;
+ break;
case AUDIO_ENCODING_ALAW:
- case AUDIO_ENCODING_PCM16:
- case AUDIO_ENCODING_PCM8:
+ bits = FMT_ALAW >> 5;
+ break;
+ case AUDIO_ENCODING_ADPCM:
+ bits = FMT_ADPCM >> 5;
+ break;
+ case AUDIO_ENCODING_SLINEAR_LE:
+ if (p->precision == 16)
+ bits = FMT_TWOS_COMP >> 5;
+ else
+ return EINVAL;
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (p->precision == 16)
+ bits = FMT_TWOS_COMP_BE >> 5;
+ else
+ return EINVAL;
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ if (p->precision == 8)
+ bits = FMT_PCM8 >> 5;
+ else
+ return EINVAL;
break;
default:
- return (EINVAL);
+ return EINVAL;
}
- sc->encoding = encoding;
- sc->precision = precision;
- sc->format_bits = format2bits[encoding];
- sc->need_commit = 1;
-
- DPRINTF(("ad1848_set_format: bits=%x\n", sc->format_bits));
-
- return (0);
-}
-
-int
-ad1848_get_encoding(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
-
- return (sc->encoding);
-}
-
-int
-ad1848_get_precision(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
+ if (p->channels < 1 || p->channels > 2)
+ return EINVAL;
- return (sc->precision);
-}
-
-int
-ad1848_set_channels(addr, channels)
- void *addr;
- int channels;
-{
- register struct ad1848_softc *sc = addr;
-
- DPRINTF(("ad1848_set_channels: %d\n", channels));
+ error = ad1848_set_speed(sc, &p->sample_rate);
+ if (error)
+ return error;
- if (channels != 1 && channels != 2)
- return (EINVAL);
+ p->sw_code = pswcode;
+ r->sw_code = rswcode;
- sc->channels = channels;
+ sc->format_bits = bits;
+ sc->channels = p->channels;
+ sc->precision = p->precision;
sc->need_commit = 1;
+ DPRINTF(("ad1848_set_params succeeded, bits=%x\n", bits));
return (0);
}
int
-ad1848_get_channels(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
-
- return (sc->channels);
-}
-
-int
ad1848_set_rec_port(sc, port)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
int port;
{
u_char inp, reg;
@@ -1097,7 +1175,7 @@ ad1848_set_rec_port(sc, port)
int
ad1848_get_rec_port(sc)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
{
return(sc->rec_port);
}
@@ -1107,27 +1185,24 @@ ad1848_round_blocksize(addr, blk)
void *addr;
int blk;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
sc->sc_lastcc = -1;
- /* Don't try to DMA too much at once. */
- if (blk > NBPG)
- blk = NBPG;
-
- /* Round to a multiple of the sample size. */
- blk &= -(sc->channels * sc->precision / 8);
+ /* Round to a multiple of the biggest sample size. */
+ blk &= -4;
return (blk);
}
int
-ad1848_open(sc, dev, flags)
- struct ad1848_softc *sc;
- dev_t dev;
+ad1848_open(addr, flags)
+ void *addr;
int flags;
{
- DPRINTF(("ad1848_open: sc=0x%x\n", sc));
+ struct ad1848_softc *sc = addr;
+
+ DPRINTF(("ad1848_open: sc=%p\n", sc));
sc->sc_intr = 0;
sc->sc_lastcc = -1;
@@ -1153,17 +1228,26 @@ ad1848_close(addr)
void *addr;
{
struct ad1848_softc *sc = addr;
- register u_char r;
+ u_char r;
sc->sc_intr = 0;
DPRINTF(("ad1848_close: stop DMA\n"));
+ if (sc->sc_playrun != NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_drq);
+ sc->sc_playrun = NOTRUNNING;
+ }
+ if (sc->sc_recrun != NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_recdrq);
+ sc->sc_recrun = NOTRUNNING;
+ }
ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)0);
ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)0);
/* Disable interrupts */
DPRINTF(("ad1848_close: disable intrs\n"));
- ad_write(sc, SP_PIN_CONTROL, ad_read(sc, SP_PIN_CONTROL) & ~(INTERRUPT_ENABLE));
+ ad_write(sc, SP_PIN_CONTROL,
+ ad_read(sc, SP_PIN_CONTROL) & ~INTERRUPT_ENABLE);
DPRINTF(("ad1848_close: disable capture and playback\n"));
r = ad_read(sc, SP_INTERFACE_CONFIG);
@@ -1211,31 +1295,31 @@ ad1848_commit_settings(addr)
/* Gravis Ultrasound MAX SDK sources says something about errata
* sheets, with the implication that these inb()s are necessary.
*/
- (void) inb(sc->sc_iobase+AD1848_IDATA);
- (void) inb(sc->sc_iobase+AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
/*
* Write to I8 starts resyncronization. Wait until it completes.
*/
timeout = 100000;
- while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
timeout--;
ad_write(sc, CS_REC_FORMAT, fs);
/* Gravis Ultrasound MAX SDK sources says something about errata
* sheets, with the implication that these inb()s are necessary.
*/
- (void) inb(sc->sc_iobase+AD1848_IDATA);
- (void) inb(sc->sc_iobase+AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
+ (void)ADREAD(sc, AD1848_IDATA);
/* Now wait for resync for capture side of the house */
}
/*
* Write to I8 starts resyncronization. Wait until it completes.
*/
timeout = 100000;
- while (timeout > 0 && inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ while (timeout > 0 && ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
timeout--;
- if (inb(sc->sc_iobase+AD1848_IADDR) == SP_IN_INIT)
+ if (ADREAD(sc, AD1848_IADDR) == SP_IN_INIT)
printf("ad1848_commit: Auto calibration timed out\n");
/*
@@ -1257,7 +1341,7 @@ ad1848_commit_settings(addr)
void
ad1848_reset(sc)
- register struct ad1848_softc *sc;
+ struct ad1848_softc *sc;
{
u_char r;
@@ -1269,11 +1353,11 @@ ad1848_reset(sc)
ad_write(sc, SP_INTERFACE_CONFIG, r);
if (sc->mode == 2) {
- outb(sc->sc_iobase+AD1848_IADDR, CS_IRQ_STATUS);
- outb(sc->sc_iobase+AD1848_IDATA, 0);
+ ADWRITE(sc, AD1848_IADDR, CS_IRQ_STATUS);
+ ADWRITE(sc, AD1848_IDATA, 0);
}
/* Clear interrupt status */
- outb(sc->sc_iobase+AD1848_STATUS, 0);
+ ADWRITE(sc, AD1848_STATUS, 0);
#ifdef AUDIO_DEBUG
if (ad1848debug)
ad1848_dump_regs(sc);
@@ -1281,9 +1365,9 @@ ad1848_reset(sc)
}
int
-ad1848_set_speed(sc, arg)
- register struct ad1848_softc *sc;
- u_long arg;
+ad1848_set_speed(sc, argp)
+ struct ad1848_softc *sc;
+ u_long *argp;
{
/*
* The sampling speed is encoded in the least significant nible of I8. The
@@ -1297,6 +1381,7 @@ ad1848_set_speed(sc, arg)
int speed;
u_char bits;
} speed_struct;
+ u_long arg = *argp;
static speed_struct speed_table[] = {
{5510, (0 << 1) | 1},
@@ -1345,9 +1430,9 @@ ad1848_set_speed(sc, arg)
selected = 3;
}
- sc->speed = speed_table[selected].speed;
sc->speed_bits = speed_table[selected].bits;
sc->need_commit = 1;
+ *argp = speed_table[selected].speed;
return (0);
}
@@ -1359,7 +1444,7 @@ int
ad1848_halt_out_dma(addr)
void *addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
u_char reg;
DPRINTF(("ad1848: ad1848_halt_out_dma\n"));
@@ -1375,7 +1460,7 @@ int
ad1848_halt_in_dma(addr)
void *addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
u_char reg;
DPRINTF(("ad1848: ad1848_halt_in_dma\n"));
@@ -1388,33 +1473,21 @@ ad1848_halt_in_dma(addr)
}
int
-ad1848_cont_out_dma(addr)
- void *addr;
-{
- register struct ad1848_softc *sc = addr;
- u_char reg;
-
- DPRINTF(("ad1848: ad1848_cont_out_dma %s\n", sc->sc_locked?"(locked)":""));
-
- reg = ad_read(sc, SP_INTERFACE_CONFIG);
- ad_write(sc, SP_INTERFACE_CONFIG, (reg | PLAYBACK_ENABLE));
-
- return(0);
-}
-
-int
-ad1848_cont_in_dma(addr)
+ad1848_dma_init_input(addr, buf, cc)
void *addr;
+ void *buf;
+ int cc;
{
- register struct ad1848_softc *sc = addr;
- u_char reg;
-
- DPRINTF(("ad1848: ad1848_cont_in_dma %s\n", sc->sc_locked?"(locked)":""));
-
- reg = ad_read(sc, SP_INTERFACE_CONFIG);
- ad_write(sc, SP_INTERFACE_CONFIG, (reg | CAPTURE_ENABLE));
+ struct ad1848_softc *sc = addr;
- return(0);
+ sc->sc_recrun = DMARUNNING;
+ sc->sc_dma_flags = DMAMODE_READ | DMAMODE_LOOP;
+ sc->sc_dma_bp = buf;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_recdrq, buf, cc, NULL,
+ sc->sc_dma_flags, BUS_DMA_NOWAIT);
+ DPRINTF(("ad1848_dma_init_input: %p %d\n", buf, cc));
+ return 0;
}
/*
@@ -1428,8 +1501,8 @@ ad1848_dma_input(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct ad1848_softc *sc = addr;
- register u_char reg;
+ struct ad1848_softc *sc = addr;
+ u_char reg;
if (sc->sc_locked) {
DPRINTF(("ad1848_dma_input: locked\n"));
@@ -1438,43 +1511,74 @@ ad1848_dma_input(addr, p, cc, intr, arg)
#ifdef AUDIO_DEBUG
if (ad1848debug > 1)
- Dprintf("ad1848_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ printf("ad1848_dma_input: cc=%d %p (%p)\n", cc, intr, arg);
#endif
sc->sc_locked = 1;
sc->sc_intr = intr;
sc->sc_arg = arg;
- sc->sc_dma_flags = DMAMODE_READ;
- sc->sc_dma_bp = p;
- sc->sc_dma_cnt = cc;
- isadma_start(p, cc, sc->sc_recdrq, DMAMODE_READ);
- if (sc->precision == 16)
- cc >>= 1;
-
- if (sc->channels == 2)
- cc >>= 1;
- cc--;
+ switch (sc->sc_recrun) {
+ case NOTRUNNING:
+ sc->sc_dma_flags = DMAMODE_READ;
+ sc->sc_dma_bp = p;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_recdrq, p, cc, NULL,
+ DMAMODE_READ, BUS_DMA_NOWAIT);
+ goto startpcm;
+ case DMARUNNING:
+ sc->sc_recrun = PCMRUNNING;
+ startpcm:
+ if (sc->precision == 16)
+ cc >>= 1;
+ if (sc->channels == 2)
+ cc >>= 1;
+ cc--;
- if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_RECORD) {
- ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff));
- ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff));
+ if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_RECORD) {
+ ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff));
+ ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff));
- if (sc->mode == 2) {
- ad_write(sc, CS_LOWER_REC_CNT, (u_char)(cc & 0xff));
- ad_write(sc, CS_UPPER_REC_CNT, (u_char)((cc >> 8) & 0xff));
- }
+ if (sc->mode == 2) {
+ ad_write(sc, CS_LOWER_REC_CNT, (u_char)(cc & 0xff));
+ ad_write(sc, CS_UPPER_REC_CNT, (u_char)((cc >> 8) & 0xff));
+ }
- reg = ad_read(sc, SP_INTERFACE_CONFIG);
- ad_write(sc, SP_INTERFACE_CONFIG, (CAPTURE_ENABLE|reg));
+ reg = ad_read(sc, SP_INTERFACE_CONFIG);
+ ad_write(sc, SP_INTERFACE_CONFIG, (CAPTURE_ENABLE|reg));
- sc->sc_lastcc = cc;
- sc->sc_mode = AUMODE_RECORD;
+ sc->sc_lastcc = cc;
+ sc->sc_mode = AUMODE_RECORD;
+#ifdef AUDIO_DEBUG
+ if (ad1848debug > 1)
+ printf("ad1848_dma_input: started capture\n");
+#endif
+ }
+ case PCMRUNNING:
+ break;
}
return 0;
}
int
+ad1848_dma_init_output(addr, buf, cc)
+ void *addr;
+ void *buf;
+ int cc;
+{
+ struct ad1848_softc *sc = addr;
+
+ sc->sc_playrun = DMARUNNING;
+ sc->sc_dma_flags = DMAMODE_WRITE | DMAMODE_LOOP;
+ sc->sc_dma_bp = buf;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_drq, buf, cc, NULL,
+ sc->sc_dma_flags, BUS_DMA_NOWAIT);
+ DPRINTF(("ad1848_dma_init_output: %p %d\n", buf, cc));
+ return 0;
+}
+
+int
ad1848_dma_output(addr, p, cc, intr, arg)
void *addr;
void *p;
@@ -1482,8 +1586,8 @@ ad1848_dma_output(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct ad1848_softc *sc = addr;
- register u_char reg;
+ struct ad1848_softc *sc = addr;
+ u_char reg;
if (sc->sc_locked) {
DPRINTF(("ad1848_dma_output: locked\n"));
@@ -1491,31 +1595,43 @@ ad1848_dma_output(addr, p, cc, intr, arg)
}
#ifdef AUDIO_DEBUG
- if (ad1848debug > 1)
- Dprintf("ad1848_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ if (ad1848debug > 0)
+ printf("ad1848_dma_output: cc=%d at %p 0x%p (0x%p)\n", cc, p, intr, arg);
#endif
sc->sc_locked = 1;
sc->sc_intr = intr;
sc->sc_arg = arg;
- sc->sc_dma_flags = DMAMODE_WRITE;
- sc->sc_dma_bp = p;
- sc->sc_dma_cnt = cc;
- isadma_start(p, cc, sc->sc_drq, DMAMODE_WRITE);
-
- if (sc->precision == 16)
- cc >>= 1;
-
- if (sc->channels == 2)
- cc >>= 1;
- cc--;
-
- if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_PLAY) {
- ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff));
- ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff));
- reg = ad_read(sc, SP_INTERFACE_CONFIG);
- ad_write(sc, SP_INTERFACE_CONFIG, (PLAYBACK_ENABLE|reg));
- sc->sc_lastcc = cc;
- sc->sc_mode = AUMODE_PLAY;
+
+ switch (sc->sc_playrun) {
+ case NOTRUNNING:
+ sc->sc_dma_flags = DMAMODE_WRITE;
+ sc->sc_dma_bp = p;
+ sc->sc_dma_cnt = cc;
+ isa_dmastart(sc->sc_isa, sc->sc_drq, p, cc, NULL,
+ DMAMODE_WRITE, BUS_DMA_NOWAIT);
+ goto startpcm;
+ case DMARUNNING:
+ sc->sc_playrun = PCMRUNNING;
+ startpcm:
+ if (sc->precision == 16)
+ cc >>= 1;
+ if (sc->channels == 2)
+ cc >>= 1;
+ cc--;
+
+ if (sc->sc_lastcc != cc || sc->sc_mode != AUMODE_PLAY) {
+ ad_write(sc, SP_LOWER_BASE_COUNT, (u_char)(cc & 0xff));
+ ad_write(sc, SP_UPPER_BASE_COUNT, (u_char)((cc >> 8) & 0xff));
+
+ reg = ad_read(sc, SP_INTERFACE_CONFIG);
+ ad_write(sc, SP_INTERFACE_CONFIG, (PLAYBACK_ENABLE|reg));
+
+ sc->sc_lastcc = cc;
+ sc->sc_mode = AUMODE_PLAY;
+ }
+ break;
+ case PCMRUNNING:
+ break;
}
return 0;
@@ -1525,16 +1641,16 @@ int
ad1848_intr(arg)
void *arg;
{
- register struct ad1848_softc *sc = arg;
+ struct ad1848_softc *sc = arg;
int retval = 0;
u_char status;
/* Get intr status */
- status = inb(sc->sc_iobase+AD1848_STATUS);
+ status = ADREAD(sc, AD1848_STATUS);
#ifdef AUDIO_DEBUG
if (ad1848debug > 1)
- Dprintf("ad1848_intr: intr=0x%x status=%x\n", sc->sc_intr, status);
+ printf("ad1848_intr: intr=%p status=%x\n", sc->sc_intr, status);
#endif
sc->sc_locked = 0;
sc->sc_interrupts++;
@@ -1543,15 +1659,66 @@ ad1848_intr(arg)
if (sc->sc_intr && (status & INTERRUPT_STATUS)) {
/* ACK DMA read because it may be in a bounce buffer */
/* XXX Do write to mask DMA ? */
- if (sc->sc_dma_flags & DMAMODE_READ)
- isadma_done(sc->sc_recdrq);
+ if ((sc->sc_dma_flags & DMAMODE_READ) && sc->sc_recrun == NOTRUNNING)
+ isa_dmadone(sc->sc_isa, sc->sc_recdrq);
(*sc->sc_intr)(sc->sc_arg);
retval = 1;
}
/* clear interrupt */
if (status & INTERRUPT_STATUS)
- outb(sc->sc_iobase+AD1848_STATUS, 0);
+ ADWRITE(sc, AD1848_STATUS, 0);
return(retval);
}
+
+void *
+ad1848_malloc(addr, size, pool, flags)
+ void *addr;
+ unsigned long size;
+ int pool;
+ int flags;
+{
+ struct ad1848_softc *sc = addr;
+
+ return isa_malloc(sc->sc_isa, 4, size, pool, flags);
+}
+
+void
+ad1848_free(addr, ptr, pool)
+ void *addr;
+ void *ptr;
+ int pool;
+{
+ isa_free(ptr, pool);
+}
+
+unsigned long
+ad1848_round(addr, size)
+ void *addr;
+ unsigned long size;
+{
+ if (size > MAX_ISADMA)
+ size = MAX_ISADMA;
+ return size;
+}
+
+int
+ad1848_mappage(addr, mem, off, prot)
+ void *addr;
+ void *mem;
+ int off;
+ int prot;
+{
+ return isa_mappage(mem, off, prot);
+}
+
+int
+ad1848_get_props(addr)
+ void *addr;
+{
+ struct ad1848_softc *sc = addr;
+
+ return AUDIO_PROP_MMAP |
+ (sc->sc_drq != sc->sc_recdrq ? AUDIO_PROP_FULLDUPLEX : 0);
+}
diff --git a/sys/dev/isa/ad1848var.h b/sys/dev/isa/ad1848var.h
index 8d6e3729cbe..b5fdaf67365 100644
--- a/sys/dev/isa/ad1848var.h
+++ b/sys/dev/isa/ad1848var.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ad1848var.h,v 1.5 1997/11/07 08:06:42 niklas Exp $ */
-/* $NetBSD: ad1848var.h,v 1.8 1996/04/29 20:02:37 christos Exp $ */
+/* $OpenBSD: ad1848var.h,v 1.6 1998/04/26 21:02:39 provos Exp $ */
+/* $NetBSD: ad1848var.h,v 1.22 1998/01/19 22:18:26 augustss Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -36,7 +36,7 @@
*
*/
-#define AD1848_NPORT 8
+#define AD1848_NPORT 4
struct ad1848_volume {
u_char left;
@@ -47,9 +47,13 @@ struct ad1848_softc {
struct device sc_dev; /* base device */
struct isadev sc_id; /* ISA device */
void *sc_ih; /* interrupt vectoring */
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_ioh; /* handle */
+ int sc_iooffs; /* offset from handle */
void *parent;
-
+ struct device *sc_isa; /* ISA bus's device */
+
u_short sc_locked; /* true when doing HS DMA */
u_int sc_lastcc; /* size of last DMA xfer */
int sc_mode; /* half-duplex record/play */
@@ -60,7 +64,12 @@ struct ad1848_softc {
u_int sc_dma_cnt;
#endif
- int sc_iobase; /* I/O port base address */
+ char sc_playrun; /* running in continuous mode */
+ char sc_recrun; /* running in continuous mode */
+#define NOTRUNNING 0
+#define DMARUNNING 1
+#define PCMRUNNING 2
+
int sc_irq; /* interrupt */
int sc_drq; /* DMA */
int sc_recdrq; /* record/capture DMA */
@@ -77,8 +86,6 @@ struct ad1848_softc {
char *chip_name;
int mode;
- u_long speed;
- u_int encoding; /* ulaw/linear -- keep track */
u_int precision; /* 8/16 bits */
int channels;
@@ -89,6 +96,9 @@ struct ad1848_softc {
u_long sc_interrupts; /* number of interrupts taken */
void (*sc_intr)(void *); /* dma completion intr handler */
void *sc_arg; /* arg for sc_intr() */
+
+ /* Only used by pss XXX */
+ int sc_iobase;
};
/*
@@ -100,27 +110,23 @@ struct ad1848_softc {
#define DAC_IN_PORT 3
#ifdef _KERNEL
+int ad1848_mapprobe __P((struct ad1848_softc *, int));
int ad1848_probe __P((struct ad1848_softc *));
+void ad1848_unmap __P((struct ad1848_softc *));
void ad1848_attach __P((struct ad1848_softc *));
-int ad1848_open __P((struct ad1848_softc *, dev_t, int));
+int ad1848_open __P((void *, int));
void ad1848_close __P((void *));
void ad1848_forceintr __P((struct ad1848_softc *));
-int ad1848_set_in_sr __P((void *, u_long));
-u_long ad1848_get_in_sr __P((void *));
-int ad1848_set_out_sr __P((void *, u_long));
-u_long ad1848_get_out_sr __P((void *));
int ad1848_query_encoding __P((void *, struct audio_encoding *));
-int ad1848_set_format __P((void *, u_int, u_int));
-int ad1848_get_encoding __P((void *));
-int ad1848_get_precision __P((void *));
-int ad1848_set_channels __P((void *, int));
-int ad1848_get_channels __P((void *));
+int ad1848_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
int ad1848_round_blocksize __P((void *, int));
+int ad1848_dma_init_output __P((void *, void *, int));
+int ad1848_dma_init_input __P((void *, void *, int));
int ad1848_dma_output __P((void *, void *, int, void (*)(void *), void*));
int ad1848_dma_input __P((void *, void *, int, void (*)(void *), void*));
@@ -128,8 +134,6 @@ int ad1848_commit_settings __P((void *));
int ad1848_halt_in_dma __P((void *));
int ad1848_halt_out_dma __P((void *));
-int ad1848_cont_in_dma __P((void *));
-int ad1848_cont_out_dma __P((void *));
int ad1848_intr __P((void *));
@@ -151,4 +155,12 @@ int ad1848_set_mic_gain __P((struct ad1848_softc *, struct ad1848_volume *));
int ad1848_get_mic_gain __P((struct ad1848_softc *, struct ad1848_volume *));
void ad1848_mute_aux1 __P((struct ad1848_softc *, int /* onoff */));
void ad1848_mute_aux2 __P((struct ad1848_softc *, int /* onoff */));
+
+void *ad1848_malloc __P((void *, unsigned long, int, int));
+void ad1848_free __P((void *, void *, int));
+unsigned long ad1848_round __P((void *, unsigned long));
+int ad1848_mappage __P((void *, void *, int, int));
+
+int ad1848_get_props __P((void *));
+
#endif
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa
index 98e00a8d7c2..ba476852ccd 100644
--- a/sys/dev/isa/files.isa
+++ b/sys/dev/isa/files.isa
@@ -1,4 +1,4 @@
-# $OpenBSD: files.isa,v 1.39 1998/03/31 23:02:11 niklas Exp $
+# $OpenBSD: files.isa,v 1.40 1998/04/26 21:02:40 provos Exp $
# $NetBSD: files.isa,v 1.21 1996/05/16 03:45:55 mycroft Exp $
#
# Config.new file and device description for machine-independent ISA code.
@@ -12,7 +12,7 @@
device isa {[port = -1], [size = 0],
[iomem = -1], [iosiz = 0],
[irq = -1], [drq = -1],
- [pnpid = -1]}
+ [drq2 = -1]}
attach isa at isabus
file dev/isa/isa.c isa needs-flag
@@ -217,7 +217,7 @@ define sbdsp
file dev/isa/sbdsp.c sbdsp
# SoundBlaster family
-device sb: audio, isa_dma, sbdsp, mulaw, opti
+device sb: audio, isa_dma, sbdsp, mulaw, opti, auconv
file dev/isa/sb.c sb needs-flag
attach sb at isa with sb_isa
@@ -231,7 +231,7 @@ attach aria at isa
file dev/isa/aria.c aria needs-flag
# ProAudio Spectrum
-device pas: audio, isa_dma, sbdsp, mulaw
+device pas: audio, isa_dma, sbdsp, mulaw, auconv
attach pas at isa
file dev/isa/pas.c pas needs-flag
@@ -249,19 +249,21 @@ device pss {[port = -1], [size = 0],
[iomem = -1], [iosiz = 0],
[irq = -1], [drq = -1]}
attach pss at isa
-device sp: audio, isa_dma, ad1848
+device sp: audio, isa_dma, ad1848, auconv
attach sp at pss
file dev/isa/pss.c pss needs-flag
# Microsoft Windows Sound System
-device wss: audio, isa_dma, ad1848, opti
-attach wss at isa
+device wss: audio, isa_dma, ad1848, auconv
file dev/isa/wss.c wss needs-flag
+attach wss at isa with wss_isa
+file dev/isa/wss_isa.c wss_isa needs-flag
+
# Gravis UltraSound & UltraSound MAX.
# Use the "flags" keyword in a config file to specify an extra DMA
# channel for full-duplex operation.
-device gus: audio, isa_dma, ics2101, ad1848, mulaw
+device gus: audio, isa_dma, ics2101, ad1848, mulaw, auconv
attach gus at isa
file dev/isa/gus.c gus needs-flag
diff --git a/sys/dev/isa/gus.c b/sys/dev/isa/gus.c
index 8922f8889f7..eb01c44a1a8 100644
--- a/sys/dev/isa/gus.c
+++ b/sys/dev/isa/gus.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: gus.c,v 1.13 1998/01/18 18:58:37 niklas Exp $ */
-/* $NetBSD: gus.c,v 1.16 1996/05/12 23:52:08 mycroft Exp $ */
+/* $OpenBSD: gus.c,v 1.14 1998/04/26 21:02:41 provos Exp $ */
+/* $NetBSD: gus.c,v 1.51 1998/01/25 23:48:06 mycroft Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@@ -112,11 +112,13 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <machine/cpufunc.h>
#include <sys/audioio.h>
#include <dev/audio_if.h>
#include <dev/mulaw.h>
+#include <dev/auconv.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -177,8 +179,13 @@ struct gus_voice {
struct gus_softc {
struct device sc_dev; /* base device */
- struct isadev sc_id; /* ISA device */
+ struct device *sc_isa; /* pointer to ISA parent */
void *sc_ih; /* interrupt vector */
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_ioh1; /* handle */
+ bus_space_handle_t sc_ioh2; /* handle */
+ bus_space_handle_t sc_ioh3; /* ICS2101 handle */
+ bus_space_handle_t sc_ioh4; /* MIDI handle */
int sc_iobase; /* I/O base address */
int sc_irq; /* IRQ used */
@@ -290,37 +297,35 @@ struct ics2101_volume {
/*
* Mixer & MUX devices for CS4231
*/
-#define GUSMAX_MIX_IN 0 /* input to MUX from mixer output */
-#define GUSMAX_MONO_LVL 1 /* mic input to MUX;
+#define GUSMAX_MONO_LVL 0 /* mic input to MUX;
also mono mixer input */
-#define GUSMAX_DAC_LVL 2 /* input to MUX; also mixer input */
-#define GUSMAX_LINE_IN_LVL 3 /* input to MUX; also mixer input */
-#define GUSMAX_CD_LVL 4 /* mixer input only */
-#define GUSMAX_MONITOR_LVL 5 /* digital mix (?) */
-#define GUSMAX_OUT_LVL 6 /* output level. (?) */
-#define GUSMAX_SPEAKER_LVL 7 /* pseudo-device for mute */
-#define GUSMAX_LINE_IN_MUTE 8 /* pre-mixer */
-#define GUSMAX_DAC_MUTE 9 /* pre-mixer */
-#define GUSMAX_CD_MUTE 10 /* pre-mixer */
-#define GUSMAX_MONO_MUTE 11 /* pre-mixer--microphone/mono */
-#define GUSMAX_MONITOR_MUTE 12 /* post-mixer level/mute */
-#define GUSMAX_SPEAKER_MUTE 13 /* speaker mute */
-
-#define GUSMAX_REC_LVL 14 /* post-MUX gain */
-
-#define GUSMAX_RECORD_SOURCE 15
+#define GUSMAX_DAC_LVL 1 /* input to MUX; also mixer input */
+#define GUSMAX_LINE_IN_LVL 2 /* input to MUX; also mixer input */
+#define GUSMAX_CD_LVL 3 /* mixer input only */
+#define GUSMAX_MONITOR_LVL 4 /* digital mix (?) */
+#define GUSMAX_OUT_LVL 5 /* output level. (?) */
+#define GUSMAX_SPEAKER_LVL 6 /* pseudo-device for mute */
+#define GUSMAX_LINE_IN_MUTE 7 /* pre-mixer */
+#define GUSMAX_DAC_MUTE 8 /* pre-mixer */
+#define GUSMAX_CD_MUTE 9 /* pre-mixer */
+#define GUSMAX_MONO_MUTE 10 /* pre-mixer--microphone/mono */
+#define GUSMAX_MONITOR_MUTE 11 /* post-mixer level/mute */
+#define GUSMAX_SPEAKER_MUTE 12 /* speaker mute */
+
+#define GUSMAX_REC_LVL 13 /* post-MUX gain */
+
+#define GUSMAX_RECORD_SOURCE 14
/* Classes */
-#define GUSMAX_INPUT_CLASS 16
-#define GUSMAX_RECORD_CLASS 17
-#define GUSMAX_MONITOR_CLASS 18
-#define GUSMAX_OUTPUT_CLASS 19
+#define GUSMAX_INPUT_CLASS 15
+#define GUSMAX_RECORD_CLASS 16
+#define GUSMAX_MONITOR_CLASS 17
+#define GUSMAX_OUTPUT_CLASS 18
#ifdef AUDIO_DEBUG
#define GUSPLAYDEBUG /*XXX*/
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (gusdebug) Dprintf x
-#define DMAPRINTF(x) if (gusdmadebug) Dprintf x
+#define DPRINTF(x) if (gusdebug) printf x
+#define DMAPRINTF(x) if (gusdmadebug) printf x
int gusdebug = 0;
int gusdmadebug = 0;
#else
@@ -348,7 +353,7 @@ int dmarecord_index = 0;
* local routines
*/
-int gusopen __P((dev_t, int));
+int gusopen __P((void *, int));
void gusclose __P((void *));
void gusmax_close __P((void *));
int gusintr __P((void *));
@@ -356,62 +361,33 @@ int gus_set_in_gain __P((caddr_t, u_int, u_char));
int gus_get_in_gain __P((caddr_t));
int gus_set_out_gain __P((caddr_t, u_int, u_char));
int gus_get_out_gain __P((caddr_t));
-int gus_set_in_sr __P((void *, u_long));
-u_long gus_get_in_sr __P((void *));
-int gusmax_set_in_sr __P((void *, u_long));
-u_long gusmax_get_in_sr __P((void *));
-int gus_set_out_sr __P((void *, u_long));
-u_long gus_get_out_sr __P((void *));
-int gusmax_set_out_sr __P((void *, u_long));
-u_long gusmax_get_out_sr __P((void *));
-int gus_set_format __P((void *, u_int, u_int));
-int gus_get_encoding __P((void *));
-int gus_get_precision __P((void *));
-int gusmax_set_format __P((void *, u_int, u_int));
-int gusmax_get_encoding __P((void *));
-int gusmax_get_precision __P((void *));
-int gus_set_channels __P((void *, int));
-int gus_get_channels __P((void *));
-int gusmax_set_channels __P((void *, int));
-int gusmax_get_channels __P((void *));
+int gus_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
+int gusmax_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
int gus_round_blocksize __P((void *, int));
-int gus_set_out_port __P((void *, int));
-int gus_get_out_port __P((void *));
-int gus_set_in_port __P((void *, int));
-int gus_get_in_port __P((void *));
int gus_commit_settings __P((void *));
int gus_dma_output __P((void *, void *, int, void (*)(void *), void *));
int gus_dma_input __P((void *, void *, int, void (*)(void *), void *));
int gus_halt_out_dma __P((void *));
int gus_halt_in_dma __P((void *));
-int gus_cont_out_dma __P((void *));
-int gus_cont_in_dma __P((void *));
int gus_speaker_ctl __P((void *, int));
+int gusmaxopen __P((void *, int));
int gusmax_round_blocksize __P((void *, int));
int gusmax_commit_settings __P((void *));
int gusmax_dma_output __P((void *, void *, int, void (*)(void *), void *));
int gusmax_dma_input __P((void *, void *, int, void (*)(void *), void *));
int gusmax_halt_out_dma __P((void *));
int gusmax_halt_in_dma __P((void *));
-int gusmax_cont_out_dma __P((void *));
-int gusmax_cont_in_dma __P((void *));
int gusmax_speaker_ctl __P((void *, int));
-int gusmax_set_out_port __P((void *, int));
-int gusmax_get_out_port __P((void *));
-int gusmax_set_in_port __P((void *, int));
-int gusmax_get_in_port __P((void *));
int gus_getdev __P((void *, struct audio_device *));
STATIC void gus_deinterleave __P((struct gus_softc *, void *, int));
-STATIC void gus_expand __P((void *, int, u_char *, int));
-STATIC void gusmax_expand __P((void *, int, u_char *, int));
STATIC int gus_mic_ctl __P((void *, int));
STATIC int gus_linein_ctl __P((void *, int));
-STATIC int gus_test_iobase __P((int));
-STATIC void guspoke __P((int, long, u_char));
+STATIC int gus_test_iobase __P((bus_space_tag_t, int));
+STATIC void guspoke __P((bus_space_tag_t, bus_space_handle_t, long, u_char));
STATIC void gusdmaout __P((struct gus_softc *, int, u_long, caddr_t, int));
-STATIC void gus_init_cs4231 __P((struct gus_softc *));
+STATIC int gus_init_cs4231 __P((struct gus_softc *));
STATIC void gus_init_ics2101 __P((struct gus_softc *));
STATIC void gus_set_chan_addrs __P((struct gus_softc *));
@@ -434,9 +410,8 @@ STATIC int gus_dmain_intr __P((struct gus_softc *));
STATIC int gus_voice_intr __P((struct gus_softc *));
STATIC void gus_start_playing __P((struct gus_softc *, int));
STATIC int gus_continue_playing __P((struct gus_softc *, int));
-STATIC u_char guspeek __P((int, u_long));
+STATIC u_char guspeek __P((bus_space_tag_t, bus_space_handle_t, u_long));
STATIC u_long convert_to_16bit __P((u_long));
-STATIC int gus_setfd __P((void *, int));
STATIC int gus_mixer_set_port __P((void *, mixer_ctrl_t *));
STATIC int gus_mixer_get_port __P((void *, mixer_ctrl_t *));
STATIC int gusmax_mixer_set_port __P((void *, mixer_ctrl_t *));
@@ -444,6 +419,8 @@ STATIC int gusmax_mixer_get_port __P((void *, mixer_ctrl_t *));
STATIC int gus_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
STATIC int gusmax_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
STATIC int gus_query_encoding __P((void *, struct audio_encoding *));
+STATIC int gus_get_props __P((void *));
+STATIC int gusmax_get_props __P((void *));
STATIC void gusics_master_mute __P((struct ics2101_softc *, int));
STATIC void gusics_dac_mute __P((struct ics2101_softc *, int));
@@ -460,7 +437,12 @@ void stereo_dmaintr __P((void *));
* ISA bus driver routines
*/
+#define __BROKEN_INDIRECT_CONFIG
+#ifdef __BROKEN_INDIRECT_CONFIG
int gusprobe __P((struct device *, void *, void *));
+#else
+int gusprobe __P((struct device *, struct cfdata *, void *));
+#endif
void gusattach __P((struct device *, struct device *, void *));
struct cfattach gus_ca = {
@@ -586,8 +568,7 @@ static unsigned short gus_log_volumes[512] = {
0x0ff0, 0x0ff1, 0x0ff2, 0x0ff3, 0x0ff4, 0x0ff5, 0x0ff6, 0x0ff7, 0x0ff8,
0x0ff9, 0x0ffa, 0x0ffb, 0x0ffc, 0x0ffd, 0x0ffe, 0x0fff};
-#define SELECT_GUS_REG(port,x) outb(port+GUS_REG_SELECT,x)
-#define WHICH_GUS_REG(port) inb(port+GUS_REG_SELECT)
+#define SELECT_GUS_REG(iot,ioh1,x) bus_space_write_1(iot,ioh1,GUS_REG_SELECT,x)
#define ADDR_HIGH(x) (unsigned int) ((x >> 7L) & 0x1fffL)
#define ADDR_LOW(x) (unsigned int) ((x & 0x7fL) << 9L)
@@ -614,49 +595,70 @@ struct audio_hw_if gus_hw_if = {
gusopen,
gusclose,
NULL, /* drain */
- gus_set_in_sr,
- gus_get_in_sr,
- gus_set_out_sr,
- gus_get_out_sr,
gus_query_encoding,
- gus_set_format,
- gus_get_encoding,
- gus_get_precision,
- gus_set_channels,
- gus_get_channels,
+ gus_set_params,
gus_round_blocksize,
- gus_set_out_port,
- gus_get_out_port,
- gus_set_in_port,
- gus_get_in_port,
-
gus_commit_settings,
- gus_expand,
- mulaw_compress,
+ NULL,
+ NULL,
gus_dma_output,
gus_dma_input,
gus_halt_out_dma,
gus_halt_in_dma,
- gus_cont_out_dma,
- gus_cont_in_dma,
-
gus_speaker_ctl,
gus_getdev,
- gus_setfd,
+ NULL,
gus_mixer_set_port,
gus_mixer_get_port,
gus_mixer_query_devinfo,
- 1, /* full-duplex */
- 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gus_get_props,
};
+static struct audio_hw_if gusmax_hw_if = {
+ gusmaxopen,
+ gusmax_close,
+ NULL, /* drain */
+
+ gus_query_encoding, /* query encoding */
+
+ gusmax_set_params,
+
+ gusmax_round_blocksize,
+
+ gusmax_commit_settings,
+
+ NULL,
+ NULL,
+
+ gusmax_dma_output,
+ gusmax_dma_input,
+ gusmax_halt_out_dma,
+ gusmax_halt_in_dma,
+
+ gusmax_speaker_ctl,
+
+ gus_getdev,
+ NULL,
+ gusmax_mixer_set_port,
+ gusmax_mixer_get_port,
+ gusmax_mixer_query_devinfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gusmax_get_props,
+};
/*
* Some info about the current audio device
@@ -674,33 +676,37 @@ struct audio_device gus_device = {
int
gusprobe(parent, match, aux)
struct device *parent;
- void *match, *aux;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
{
- register struct gus_softc *sc = match;
- register struct isa_attach_args *ia = aux;
- struct cfdata *cf = sc->sc_dev.dv_cfdata;
- register int iobase = ia->ia_iobase;
- int recdrq = cf->cf_flags;
+ struct isa_attach_args *ia = aux;
+ int iobase = ia->ia_iobase;
+ int recdrq = ia->ia_drq2;
/*
* Before we do anything else, make sure requested IRQ and DRQ are
* valid for this card.
*/
- if (gus_irq_map[ia->ia_irq] == IRQUNK) {
+ /* XXX range check before indexing!! */
+ if (ia->ia_irq == IRQUNK || gus_irq_map[ia->ia_irq] == IRQUNK) {
printf("gus: invalid irq %d, card not probed\n", ia->ia_irq);
- return(0);
+ return 0;
}
- if (gus_drq_map[ia->ia_drq] == DRQUNK) {
+ if (ia->ia_drq == DRQUNK || gus_drq_map[ia->ia_drq] == DRQUNK) {
printf("gus: invalid drq %d, card not probed\n", ia->ia_drq);
- return(0);
+ return 0;
}
- if (recdrq != 0x00) {
+ if (recdrq != DRQUNK) {
if (recdrq > 7 || gus_drq_map[recdrq] == DRQUNK) {
- printf("gus: invalid flag given for second DMA channel (0x%x), card not probed\n", recdrq);
- return(0);
+ printf("gus: invalid second DMA channel (%d), card not probed\n", recdrq);
+ return 0;
}
} else
recdrq = ia->ia_drq;
@@ -708,23 +714,22 @@ gusprobe(parent, match, aux)
if (iobase == IOBASEUNK) {
int i;
for(i = 0; i < gus_addrs; i++)
- if (gus_test_iobase(gus_base_addrs[i])) {
+ if (gus_test_iobase(ia->ia_iot, gus_base_addrs[i])) {
iobase = gus_base_addrs[i];
goto done;
}
return 0;
- } else if (! gus_test_iobase(iobase))
+ } else if (!gus_test_iobase(ia->ia_iot, iobase))
return 0;
done:
- sc->sc_iobase = iobase;
- sc->sc_irq = ia->ia_irq;
- sc->sc_drq = ia->ia_drq;
- sc->sc_recdrq = recdrq;
+ if ((ia->ia_drq != -1 && !isa_drq_isfree(parent, ia->ia_drq)) ||
+ (recdrq != -1 && !isa_drq_isfree(parent, recdrq)))
+ return 0;
- ia->ia_iobase = sc->sc_iobase;
- ia->ia_iosize = 16; /* XXX */
- return(1);
+ ia->ia_iobase = iobase;
+ ia->ia_iosize = GUS_NPORT1;
+ return 1;
}
/*
@@ -733,47 +738,74 @@ done:
*/
STATIC int
-gus_test_iobase (int iobase)
+gus_test_iobase (iot, iobase)
+ bus_space_tag_t iot;
+ int iobase;
{
- int i = splgus();
+ bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
u_char s1, s2;
+ int s, rv = 0;
+
+ /* Map i/o space */
+ if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
+ return 0;
+ if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
+ goto bad1;
+
+ /* XXX Maybe we shouldn't fail on mapping this, but just assume
+ * the card is of revision 0? */
+ if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
+ goto bad2;
+
+ if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
+ goto bad3;
/*
* Reset GUS to an initial state before we do anything.
*/
+ s = splgus();
delay(500);
- SELECT_GUS_REG(iobase, GUSREG_RESET);
- outb(iobase+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
delay(500);
- SELECT_GUS_REG(iobase, GUSREG_RESET);
- outb(iobase+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
delay(500);
- splx(i);
+ splx(s);
/*
* See if we can write to the board's memory
*/
- s1 = guspeek(iobase, 0L);
- s2 = guspeek(iobase, 1L);
+ s1 = guspeek(iot, ioh2, 0L);
+ s2 = guspeek(iot, ioh2, 1L);
- guspoke(iobase, 0L, 0xaa);
- guspoke(iobase, 1L, 0x55);
+ guspoke(iot, ioh2, 0L, 0xaa);
+ guspoke(iot, ioh2, 1L, 0x55);
- if ((i=(int)guspeek(iobase, 0L)) != 0xaa) {
- return(0);
- }
+ if (guspeek(iot, ioh2, 0L) != 0xaa)
+ goto bad;
- guspoke(iobase, 0L, s1);
- guspoke(iobase, 1L, s2);
+ guspoke(iot, ioh2, 0L, s1);
+ guspoke(iot, ioh2, 1L, s2);
- return 1;
+ rv = 1;
+
+bad:
+ bus_space_unmap(iot, ioh4, GUS_NPORT4);
+bad3:
+ bus_space_unmap(iot, ioh3, GUS_NPORT3);
+bad2:
+ bus_space_unmap(iot, ioh2, GUS_NPORT2);
+bad1:
+ bus_space_unmap(iot, ioh1, GUS_NPORT1);
+ return rv;
}
/*
@@ -785,28 +817,57 @@ gusattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- register struct gus_softc *sc = (void *) self;
- register struct isa_attach_args *ia = aux;
- register int port = ia->ia_iobase;
- int i;
- register unsigned char c,d,m;
+ struct gus_softc *sc = (void *) self;
+ struct isa_attach_args *ia = aux;
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh1, ioh2, ioh3, ioh4;
+ int iobase, i;
+ unsigned char c,d,m;
+
+ sc->sc_iot = iot = ia->ia_iot;
+ iobase = ia->ia_iobase;
+
+ /* Map i/o space */
+ if (bus_space_map(iot, iobase, GUS_NPORT1, 0, &ioh1))
+ panic("%s: can't map io port range 1", self->dv_xname);
+ sc->sc_ioh1 = ioh1;
+ if (bus_space_map(iot, iobase+GUS_IOH2_OFFSET, GUS_NPORT2, 0, &ioh2))
+ panic("%s: can't map io port range 2", self->dv_xname);
+ sc->sc_ioh2 = ioh2;
+
+ /* XXX Maybe we shouldn't fail on mapping this, but just assume
+ * the card is of revision 0? */
+ if (bus_space_map(iot, iobase+GUS_IOH3_OFFSET, GUS_NPORT3, 0, &ioh3))
+ panic("%s: can't map io port range 3", self->dv_xname);
+ sc->sc_ioh3 = ioh3;
+
+ if (bus_space_map(iot, iobase+GUS_IOH4_OFFSET, GUS_NPORT4, 0, &ioh4))
+ panic("%s: can't map io port range 4", self->dv_xname);
+ sc->sc_ioh4 = ioh4;
+
+ sc->sc_iobase = iobase;
+ sc->sc_irq = ia->ia_irq;
+ sc->sc_drq = ia->ia_drq;
+ sc->sc_recdrq = ia->ia_drq2;
/*
* Figure out our board rev, and see if we need to initialize the
* mixer
*/
+ sc->sc_isa = parent;
+
delay(500);
- c = inb(port+GUS_BOARD_REV);
+ c = bus_space_read_1(iot, ioh3, GUS_BOARD_REV);
if (c != 0xff)
sc->sc_revision = c;
else
sc->sc_revision = 0;
- SELECT_GUS_REG(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
gusreset(sc, GUS_MAX_VOICES); /* initialize all voices */
gusreset(sc, GUS_MIN_VOICES); /* then set to just the ones we use */
@@ -837,54 +898,72 @@ gusattach(parent, self, aux)
* The order of these operations is very magical.
*/
- disable_intr();
+ disable_intr(); /* XXX needed? */
- outb(port+GUS_REG_CONTROL, GUS_REG_IRQCTL);
- outb(port+GUS_MIX_CONTROL, m);
- outb(port+GUS_IRQCTL_CONTROL, 0x00);
- outb(port+0x0f, 0x00);
+ bus_space_write_1(iot, ioh1, GUS_REG_CONTROL, GUS_REG_IRQCTL);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
+ bus_space_write_1(iot, ioh1, GUS_IRQCTL_CONTROL, 0x00);
+ bus_space_write_1(iot, ioh1, 0x0f, 0x00);
- outb(port+GUS_MIX_CONTROL, m);
- outb(port+GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
+ bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d | 0x80); /* magic reset? */
- outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
- outb(port+GUS_IRQ_CONTROL, c);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
+ bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
- outb(port+GUS_MIX_CONTROL, m);
- outb(port+GUS_DMA_CONTROL, d);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m);
+ bus_space_write_1(iot, ioh1, GUS_DMA_CONTROL, d);
- outb(port+GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
- outb(port+GUS_IRQ_CONTROL, c);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, m | GUSMASK_CONTROL_SEL);
+ bus_space_write_1(iot, ioh1, GUS_IRQ_CONTROL, c);
- outb(port+GUS_VOICE_SELECT, 0x00);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, 0x00);
/* enable line in, line out. leave mic disabled. */
- outb(port+GUS_MIX_CONTROL,
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL,
(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN));
- outb(port+GUS_VOICE_SELECT, 0x00);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, 0x00);
enable_intr();
sc->sc_mixcontrol =
(m | GUSMASK_LATCHES) & ~(GUSMASK_LINE_OUT|GUSMASK_LINE_IN);
+ /* XXX WILL THIS ALWAYS WORK THE WAY THEY'RE OVERLAYED?! */
+ sc->sc_codec.sc_isa = sc->sc_dev.dv_parent;
if (sc->sc_revision >= 5 && sc->sc_revision <= 9) {
sc->sc_flags |= GUS_MIXER_INSTALLED;
gus_init_ics2101(sc);
}
- if (sc->sc_revision >= 0xa) {
- gus_init_cs4231(sc);
+ if (sc->sc_revision < 0xa || !gus_init_cs4231(sc)) {
+ /* Not using the CS4231, so create our DMA maps. */
+ if (sc->sc_drq != -1) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq,
+ MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("%s: can't create map for drq %d\n",
+ sc->sc_dev.dv_xname, sc->sc_drq);
+ return;
+ }
+ }
+ if (sc->sc_recdrq != -1 && sc->sc_recdrq != sc->sc_drq) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_recdrq,
+ MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("%s: can't create map for drq %d\n",
+ sc->sc_dev.dv_xname, sc->sc_recdrq);
+ return;
+ }
+ }
}
- SELECT_GUS_REG(port, GUSREG_RESET);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
/*
* Check to see how much memory we have on this card; see if any
* "mirroring" occurs. We're assuming at least 256K already exists
* on the card; otherwise the initial probe would have failed
*/
- guspoke(port, 0L, 0x00);
+ guspoke(iot, ioh2, 0L, 0x00);
for(i = 1; i < 1024; i++) {
u_long loc;
@@ -892,13 +971,13 @@ gusattach(parent, self, aux)
* See if we've run into mirroring yet
*/
- if (guspeek(port, 0L) != 0)
+ if (guspeek(iot, ioh2, 0L) != 0)
break;
loc = i << 10;
- guspoke(port, loc, 0xaa);
- if (guspeek(port, loc) != 0xaa)
+ guspoke(iot, ioh2, loc, 0xaa);
+ if (guspeek(iot, ioh2, loc) != 0xaa)
break;
}
@@ -913,10 +992,8 @@ gusattach(parent, self, aux)
printf("%s codec/mixer, ", sc->sc_codec.chip_name);
if (sc->sc_recdrq == sc->sc_drq) {
printf("half-duplex");
- gus_hw_if.full_duplex = 0;
} else {
printf("full-duplex, record drq %d", sc->sc_recdrq);
- gus_hw_if.full_duplex = 1;
}
printf(">\n");
@@ -933,10 +1010,11 @@ gusattach(parent, self, aux)
/*
* Set some default values
+ * XXX others start with 8kHz mono mulaw
*/
sc->sc_irate = sc->sc_orate = 44100;
- sc->sc_encoding = AUDIO_ENCODING_LINEAR;
+ sc->sc_encoding = AUDIO_ENCODING_SLINEAR_LE;
sc->sc_precision = 16;
sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_DATA_SIZE16;
sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
@@ -949,38 +1027,30 @@ gusattach(parent, self, aux)
* full right.
* For mono playback, we set up both voices playing the same buffer.
*/
- outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
- SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
- outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_LEFT);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_LEFT);
- outb(sc->sc_iobase+GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
- SELECT_GUS_REG(sc->sc_iobase, GUSREG_PAN_POS);
- outb(sc->sc_iobase+GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) GUS_VOICE_RIGHT);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUS_PAN_FULL_RIGHT);
/*
* Attach to the generic audio layer
*/
- if (audio_hardware_attach(&gus_hw_if, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc) != 0)
- printf("gus: could not attach to audio pseudo-device driver\n");
+ audio_attach_mi(&gus_hw_if, 0, HAS_CODEC(sc) ? (void *)&sc->sc_codec : (void *)sc, &sc->sc_dev);
}
int
-gusopen(dev, flags)
- dev_t dev;
+gusopen(addr, flags)
+ void *addr;
int flags;
{
- int unit = AUDIOUNIT(dev);
- struct gus_softc *sc;
+ struct gus_softc *sc = addr;
DPRINTF(("gusopen() called\n"));
- if (unit >= gus_cd.cd_ndevs)
- return ENXIO;
- sc = gus_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
if (sc->sc_flags & GUS_OPEN)
return EBUSY;
@@ -996,7 +1066,7 @@ gusopen(dev, flags)
sc->sc_voc[GUS_VOICE_LEFT].current_addr = GUS_MEM_OFFSET;
if (HAS_CODEC(sc)) {
- ad1848_open(&sc->sc_codec, dev, flags);
+ ad1848_open(&sc->sc_codec, flags);
sc->sc_codec.aux1_mute = 0;
ad1848_mute_aux1(&sc->sc_codec, 0); /* turn on DAC output */
if (flags & FREAD) {
@@ -1015,51 +1085,38 @@ gusopen(dev, flags)
return 0;
}
-STATIC void
-gusmax_expand(hdl, encoding, buf, count)
- void *hdl;
- int encoding;
- u_char *buf;
- int count;
-{
- register struct ad1848_softc *ac = hdl;
-
- gus_expand(ac->parent, encoding, buf, count);
-}
-
-STATIC void
-gus_expand(hdl, encoding, buf, count)
- void *hdl;
- int encoding;
- u_char *buf;
- int count;
+int
+gusmaxopen(addr, flags)
+ void *addr;
+ int flags;
{
- struct gus_softc *sc = hdl;
-
- mulaw_expand(NULL, encoding, buf, count);
- /*
- * If we need stereo deinterleaving, do it now.
- */
- if (sc->sc_channels == 2)
- gus_deinterleave(sc, (void *)buf, count);
+ struct ad1848_softc *ac = addr;
+ return gusopen(ac->parent, flags);
}
STATIC void
gus_deinterleave(sc, buf, size)
- register struct gus_softc *sc;
+ struct gus_softc *sc;
void *buf;
int size;
{
/* deinterleave the stereo data. We can use sc->sc_deintr_buf
for scratch space. */
- register int i;
+ int i;
+
+ if (size > sc->sc_blocksize) {
+ printf("gus: deinterleave %d > %d\n", size, sc->sc_blocksize);
+ return;
+ } else if (size < sc->sc_blocksize) {
+ DPRINTF(("gus: deinterleave %d < %d\n", size, sc->sc_blocksize));
+ }
/*
* size is in bytes.
*/
if (sc->sc_precision == 16) {
- register u_short *dei = sc->sc_deintr_buf;
- register u_short *sbuf = buf;
+ u_short *dei = sc->sc_deintr_buf;
+ u_short *sbuf = buf;
size >>= 1; /* bytecnt to shortcnt */
/* copy 2nd of each pair of samples to the staging area, while
compacting the 1st of each pair into the original area. */
@@ -1079,8 +1136,8 @@ gus_deinterleave(sc, buf, size)
*/
bcopy(dei, &sbuf[size/2], i * sizeof(short));
} else {
- register u_char *dei = sc->sc_deintr_buf;
- register u_char *sbuf = buf;
+ u_char *dei = sc->sc_deintr_buf;
+ u_char *sbuf = buf;
for (i = 0; i < size/2-1; i++) {
dei[i] = sbuf[i*2+1];
sbuf[i+1] = sbuf[i*2+2];
@@ -1101,7 +1158,7 @@ gusmax_dma_output(addr, buf, size, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct ad1848_softc *ac = addr;
+ struct ad1848_softc *ac = addr;
return gus_dma_output(ac->parent, buf, size, intr, arg);
}
@@ -1164,7 +1221,7 @@ gus_dma_output(addr, buf, size, intr, arg)
u_long boarddma;
int flags;
- DMAPRINTF(("gus_dma_output %d @ %x\n", size, buf));
+ DMAPRINTF(("gus_dma_output %d @ %p\n", size, buf));
if (size != sc->sc_blocksize) {
DPRINTF(("gus_dma_output reqsize %d not sc_blocksize %d\n",
@@ -1175,9 +1232,10 @@ gus_dma_output(addr, buf, size, intr, arg)
flags = GUSMASK_DMA_WRITE;
if (sc->sc_precision == 16)
flags |= GUSMASK_DMA_DATA_SIZE;
- /* pcm16 is signed, mulaw & pcm8 are unsigned */
if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
- sc->sc_encoding == AUDIO_ENCODING_PCM8)
+ sc->sc_encoding == AUDIO_ENCODING_ALAW ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE)
flags |= GUSMASK_DMA_INVBIT;
if (sc->sc_channels == 2) {
@@ -1192,9 +1250,12 @@ gus_dma_output(addr, buf, size, intr, arg)
}
if (size == 0)
return 0;
+
+ gus_deinterleave(sc, (void *)buffer, size);
+
size >>= 1;
- boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
+ boarddma = size * sc->sc_dmabuf + GUS_MEM_OFFSET;
sc->sc_stereo.intr = intr;
sc->sc_stereo.arg = arg;
@@ -1235,8 +1296,8 @@ void
gusmax_close(addr)
void *addr;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
#if 0
ac->aux1_mute = 1;
ad1848_mute_aux1(ac, 1); /* turn off DAC output */
@@ -1254,7 +1315,7 @@ gusclose(addr)
{
struct gus_softc *sc = addr;
- DPRINTF(("gus_close: sc=0x%x\n", sc));
+ DPRINTF(("gus_close: sc=%p\n", sc));
/* if (sc->sc_flags & GUS_DMAOUT_ACTIVE) */ {
@@ -1291,9 +1352,12 @@ int
gusintr(arg)
void *arg;
{
- register struct gus_softc *sc = arg;
+ struct gus_softc *sc = arg;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
unsigned char intr;
- register int port = sc->sc_iobase;
+
int retval = 0;
DPRINTF(("gusintr\n"));
@@ -1302,15 +1366,15 @@ gusintr(arg)
#endif
if (HAS_CODEC(sc))
retval = ad1848_intr(&sc->sc_codec);
- if ((intr = inb(port+GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
+ if ((intr = bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS)) & GUSMASK_IRQ_DMATC) {
DMAPRINTF(("gusintr dma flags=%x\n", sc->sc_flags));
#ifdef DIAGNOSTIC
gusdmaintrcnt++;
#endif
retval += gus_dmaout_intr(sc);
if (sc->sc_flags & GUS_DMAIN_ACTIVE) {
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- intr = inb(port+GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
if (intr & GUSMASK_SAMPLE_DMATC) {
retval += gus_dmain_intr(sc);
}
@@ -1350,27 +1414,29 @@ int playcntr;
STATIC void
gus_dmaout_timeout(arg)
- void *arg;
+ void *arg;
{
- register struct gus_softc *sc = arg;
- register int port = sc->sc_iobase;
- int s;
-
- printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
- /*
- * Stop any DMA.
- */
+ struct gus_softc *sc = arg;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ int s;
- s = splgus();
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
+ printf("%s: dmaout timeout\n", sc->sc_dev.dv_xname);
+ /*
+ * Stop any DMA.
+ */
+ s = splgus();
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
+
#if 0
- isadma_abort(sc->sc_drq); /* XXX we will dmadone below? */
+ /* XXX we will dmadone below? */
+ isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
#endif
-
- gus_dmaout_dointr(sc);
- splx(s);
+
+ gus_dmaout_dointr(sc);
+ splx(s);
}
@@ -1383,15 +1449,16 @@ STATIC int
gus_dmaout_intr(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
/*
* If we got a DMA transfer complete from the GUS DRAM, then deal
* with it.
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- if (inb(port+GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ if (bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & GUSMASK_DMA_IRQPEND) {
untimeout(gus_dmaout_timeout, sc);
gus_dmaout_dointr(sc);
return 1;
@@ -1403,12 +1470,13 @@ STATIC void
gus_dmaout_dointr(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
/* sc->sc_dmaoutcnt - 1 because DMA controller counts from zero?. */
- isadma_done(sc->sc_drq);
+ isa_dmadone(sc->sc_dev.dv_parent, sc->sc_drq);
sc->sc_flags &= ~GUS_DMAOUT_ACTIVE; /* pending DMA is done */
- DMAPRINTF(("gus_dmaout_dointr %d @ %x\n", sc->sc_dmaoutcnt,
+ DMAPRINTF(("gus_dmaout_dointr %d @ %p\n", sc->sc_dmaoutcnt,
sc->sc_dmaoutaddr));
/*
@@ -1419,21 +1487,31 @@ gus_dmaout_dointr(sc)
* byte rather than the one we have in memory.
*/
if (sc->sc_dmabuf == sc->sc_nbufs - 1) {
- register int i;
+ int i;
switch (sc->sc_encoding) {
- case AUDIO_ENCODING_PCM16:
+ case AUDIO_ENCODING_SLINEAR_LE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (sc->sc_precision == 8)
+ goto byte;
/* we have the native format */
for (i = 1; i <= 2; i++)
- guspoke(port, sc->sc_gusaddr -
+ guspoke(iot, ioh2, sc->sc_gusaddr -
(sc->sc_nbufs - 1) * sc->sc_chanblocksize - i,
sc->sc_dmaoutaddr[sc->sc_dmaoutcnt-i]);
break;
- case AUDIO_ENCODING_PCM8:
+ case AUDIO_ENCODING_ULINEAR_LE:
+ case AUDIO_ENCODING_ULINEAR_BE:
+ guspoke(iot, ioh2, sc->sc_gusaddr -
+ (sc->sc_nbufs - 1) * sc->sc_chanblocksize - 2,
+ guspeek(iot, ioh2,
+ sc->sc_gusaddr + sc->sc_chanblocksize - 2));
+ case AUDIO_ENCODING_ALAW:
case AUDIO_ENCODING_ULAW:
+ byte:
/* we need to fetch the translated byte, then stuff it. */
- guspoke(port, sc->sc_gusaddr -
+ guspoke(iot, ioh2, sc->sc_gusaddr -
(sc->sc_nbufs - 1) * sc->sc_chanblocksize - 1,
- guspeek(port,
+ guspeek(iot, ioh2,
sc->sc_gusaddr + sc->sc_chanblocksize - 1));
break;
}
@@ -1509,11 +1587,11 @@ gus_dmaout_dointr(sc)
playcntr = ++playcntr % NDMARECS;
}
#endif
- outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
}
}
gus_bufcnt[sc->sc_bufcnt-1]++;
@@ -1546,7 +1624,8 @@ STATIC int
gus_voice_intr(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
int ignore = 0, voice, rval = 0;
unsigned char intr, status;
@@ -1557,8 +1636,8 @@ gus_voice_intr(sc)
*/
while(1) {
- SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
- intr = inb(port+GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
+ intr = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
if ((intr & (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
== (GUSMASK_WIRQ_VOLUME | GUSMASK_WIRQ_VOICE))
@@ -1587,8 +1666,8 @@ gus_voice_intr(sc)
* (this stops it from continuously generating IRQs)
*/
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL+0x80);
- status = inb(port+GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL+0x80);
+ status = bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
if (status & GUSMASK_VOICE_STOPPED) {
if (voice != GUS_VOICE_LEFT) {
DMAPRINTF(("%s: spurious voice %d stop?\n",
@@ -1692,177 +1771,179 @@ gus_voice_intr(sc)
STATIC void
gus_start_playing(sc, bufno)
-struct gus_softc *sc;
-int bufno;
+ struct gus_softc *sc;
+ int bufno;
{
- register int port = sc->sc_iobase;
- /*
- * Start the voices playing, with buffer BUFNO.
- */
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ /*
+ * Start the voices playing, with buffer BUFNO.
+ */
- /*
- * Loop or roll if we have buffers ready.
- */
+ /*
+ * Loop or roll if we have buffers ready.
+ */
- if (sc->sc_bufcnt == 1) {
- sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
- sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
- } else {
- if (bufno == sc->sc_nbufs - 1) {
- sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
- sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
+ if (sc->sc_bufcnt == 1) {
+ sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~(GUSMASK_LOOP_ENABLE);
+ sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
} else {
- sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
- sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
+ if (bufno == sc->sc_nbufs - 1) {
+ sc->sc_voc[GUS_VOICE_LEFT].voccntl |= GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[GUS_VOICE_LEFT].volcntl &= ~(GUSMASK_VOICE_ROLL);
+ } else {
+ sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[GUS_VOICE_LEFT].volcntl |= GUSMASK_VOICE_ROLL;
+ }
}
- }
- outb(port+GUS_VOICE_SELECT, GUS_VOICE_LEFT);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_LEFT);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_LEFT].volcntl);
- sc->sc_voc[GUS_VOICE_LEFT].current_addr =
- GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
- sc->sc_voc[GUS_VOICE_LEFT].end_addr =
- sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
- sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
- sc->sc_voc[GUS_VOICE_LEFT].current_addr +
- (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
- /*
- * set up right channel to just loop forever, no interrupts,
- * starting at the buffer we just filled. We'll feed it data
- * at the same time as left channel.
- */
- sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
- sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
+ sc->sc_voc[GUS_VOICE_LEFT].current_addr =
+ GUS_MEM_OFFSET + sc->sc_chanblocksize * bufno;
+ sc->sc_voc[GUS_VOICE_LEFT].end_addr =
+ sc->sc_voc[GUS_VOICE_LEFT].current_addr + sc->sc_chanblocksize - 1;
+ sc->sc_voc[GUS_VOICE_RIGHT].current_addr =
+ sc->sc_voc[GUS_VOICE_LEFT].current_addr +
+ (gus_dostereo && sc->sc_channels == 2 ? GUS_LEFT_RIGHT_OFFSET : 0);
+ /*
+ * set up right channel to just loop forever, no interrupts,
+ * starting at the buffer we just filled. We'll feed it data
+ * at the same time as left channel.
+ */
+ sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[GUS_VOICE_RIGHT].volcntl &= ~(GUSMASK_VOICE_ROLL);
#ifdef GUSPLAYDEBUG
- if (gusstats) {
- microtime(&playstats[playcntr].tv);
- playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
-
- playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
- playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
- playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
- playstats[playcntr].playbuf = bufno;
- playstats[playcntr].dmabuf = sc->sc_dmabuf;
- playstats[playcntr].bufcnt = sc->sc_bufcnt;
- playstats[playcntr].vaction = 5;
- playcntr = ++playcntr % NDMARECS;
- }
+ if (gusstats) {
+ microtime(&playstats[playcntr].tv);
+ playstats[playcntr].curaddr = sc->sc_voc[GUS_VOICE_LEFT].current_addr;
+
+ playstats[playcntr].voccntl = sc->sc_voc[GUS_VOICE_LEFT].voccntl;
+ playstats[playcntr].volcntl = sc->sc_voc[GUS_VOICE_LEFT].volcntl;
+ playstats[playcntr].endaddr = sc->sc_voc[GUS_VOICE_LEFT].end_addr;
+ playstats[playcntr].playbuf = bufno;
+ playstats[playcntr].dmabuf = sc->sc_dmabuf;
+ playstats[playcntr].bufcnt = sc->sc_bufcnt;
+ playstats[playcntr].vaction = 5;
+ playcntr = ++playcntr % NDMARECS;
+ }
#endif
- outb(port+GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
-
- gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
- gus_start_voice(sc, GUS_VOICE_LEFT, 1);
- if (sc->sc_playbuf == -1)
- /* mark start of playing */
- sc->sc_playbuf = bufno;
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, GUS_VOICE_RIGHT);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[GUS_VOICE_RIGHT].volcntl);
+
+ gus_start_voice(sc, GUS_VOICE_RIGHT, 0);
+ gus_start_voice(sc, GUS_VOICE_LEFT, 1);
+ if (sc->sc_playbuf == -1)
+ /* mark start of playing */
+ sc->sc_playbuf = bufno;
}
STATIC int
gus_continue_playing(sc, voice)
-register struct gus_softc *sc;
-int voice;
+ struct gus_softc *sc;
+ int voice;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
- /*
- * stop this voice from interrupting while we work.
- */
+ /*
+ * stop this voice from interrupting while we work.
+ */
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl & ~(GUSMASK_VOICE_IRQ));
- /*
- * update playbuf to point to the buffer the hardware just started
- * playing
- */
- sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
+ /*
+ * update playbuf to point to the buffer the hardware just started
+ * playing
+ */
+ sc->sc_playbuf = ++sc->sc_playbuf % sc->sc_nbufs;
- /*
- * account for buffer just finished
- */
- if (--sc->sc_bufcnt == 0) {
- DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
- }
- if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
- printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
- return 1;
- }
-
- /*
- * Select the end of the buffer based on the currently active
- * buffer, [plus extra contiguous buffers (if ready)].
- */
-
- /*
- * set endpoint at end of buffer we just started playing.
- *
- * The total gets -1 because end addrs are one less than you might
- * think (the end_addr is the address of the last sample to play)
- */
- gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
- sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
-
- if (sc->sc_bufcnt < 2) {
/*
- * Clear out the loop and roll flags, and rotate the currently
- * playing buffer. That way, if we don't manage to get more
- * data before this buffer finishes, we'll just stop.
+ * account for buffer just finished
*/
- sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
- sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
- playstats[playcntr].vaction = 0;
- } else {
+ if (--sc->sc_bufcnt == 0) {
+ DPRINTF(("gus: bufcnt 0 on continuing voice?\n"));
+ }
+ if (sc->sc_playbuf == sc->sc_dmabuf && (sc->sc_flags & GUS_LOCKED)) {
+ printf("%s: continue into active dmabuf?\n", sc->sc_dev.dv_xname);
+ return 1;
+ }
+
/*
- * We have some buffers to play. set LOOP if we're on the
- * last buffer in the ring, otherwise set ROLL.
+ * Select the end of the buffer based on the currently active
+ * buffer, [plus extra contiguous buffers (if ready)].
+ */
+
+ /*
+ * set endpoint at end of buffer we just started playing.
+ *
+ * The total gets -1 because end addrs are one less than you might
+ * think (the end_addr is the address of the last sample to play)
*/
- if (sc->sc_playbuf == sc->sc_nbufs - 1) {
- sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
- sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
- playstats[playcntr].vaction = 1;
+ gus_set_endaddr(sc, voice, GUS_MEM_OFFSET +
+ sc->sc_chanblocksize * (sc->sc_playbuf + 1) - 1);
+
+ if (sc->sc_bufcnt < 2) {
+ /*
+ * Clear out the loop and roll flags, and rotate the currently
+ * playing buffer. That way, if we don't manage to get more
+ * data before this buffer finishes, we'll just stop.
+ */
+ sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
+ playstats[playcntr].vaction = 0;
} else {
- sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
- sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
- playstats[playcntr].vaction = 2;
+ /*
+ * We have some buffers to play. set LOOP if we're on the
+ * last buffer in the ring, otherwise set ROLL.
+ */
+ if (sc->sc_playbuf == sc->sc_nbufs - 1) {
+ sc->sc_voc[voice].voccntl |= GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[voice].volcntl &= ~GUSMASK_VOICE_ROLL;
+ playstats[playcntr].vaction = 1;
+ } else {
+ sc->sc_voc[voice].voccntl &= ~GUSMASK_LOOP_ENABLE;
+ sc->sc_voc[voice].volcntl |= GUSMASK_VOICE_ROLL;
+ playstats[playcntr].vaction = 2;
+ }
}
- }
#ifdef GUSPLAYDEBUG
- if (gusstats) {
- microtime(&playstats[playcntr].tv);
- playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
-
- playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
- playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
- playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
- playstats[playcntr].playbuf = sc->sc_playbuf;
- playstats[playcntr].dmabuf = sc->sc_dmabuf;
- playstats[playcntr].bufcnt = sc->sc_bufcnt;
- playcntr = ++playcntr % NDMARECS;
- }
+ if (gusstats) {
+ microtime(&playstats[playcntr].tv);
+ playstats[playcntr].curaddr = gus_get_curaddr(sc, voice);
+
+ playstats[playcntr].voccntl = sc->sc_voc[voice].voccntl;
+ playstats[playcntr].volcntl = sc->sc_voc[voice].volcntl;
+ playstats[playcntr].endaddr = sc->sc_voc[voice].end_addr;
+ playstats[playcntr].playbuf = sc->sc_playbuf;
+ playstats[playcntr].dmabuf = sc->sc_dmabuf;
+ playstats[playcntr].bufcnt = sc->sc_bufcnt;
+ playcntr = ++playcntr % NDMARECS;
+ }
#endif
- /*
- * (re-)set voice parameters. This will reenable interrupts from this
- * voice.
- */
+ /*
+ * (re-)set voice parameters. This will reenable interrupts from this
+ * voice.
+ */
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
- return 0;
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].volcntl);
+ return 0;
}
/*
@@ -1876,8 +1957,9 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
u_long gusaddr;
caddr_t buffaddr;
{
- register unsigned char c = (unsigned char) flags;
- register int port = sc->sc_iobase;
+ unsigned char c = (unsigned char) flags;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
DMAPRINTF(("gusdmaout flags=%x scflags=%x\n", flags, sc->sc_flags));
@@ -1903,8 +1985,8 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
* Make sure the GUS _isn't_ setup for DMA
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(port+GUS_DATA_HIGH, 0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
/*
* Tell the PC DMA controller to start doing DMA
@@ -1912,7 +1994,8 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
sc->sc_dmaoutaddr = (u_char *) buffaddr;
sc->sc_dmaoutcnt = length;
- isadma_start(buffaddr, length, sc->sc_drq, DMAMODE_WRITE);
+ isa_dmastart(sc->sc_dev.dv_parent, sc->sc_drq, buffaddr, length,
+ NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
/*
* Set up DMA address - use the upper 16 bits ONLY
@@ -1920,15 +2003,15 @@ gusdmaout(sc, flags, gusaddr, buffaddr, length)
sc->sc_flags |= GUS_DMAOUT_ACTIVE;
- SELECT_GUS_REG(port, GUSREG_DMA_START);
- outw(port+GUS_DATA_LOW, (int) (gusaddr >> 4));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_START);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (int) (gusaddr >> 4));
/*
* Tell the GUS to start doing DMA
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(port+GUS_DATA_HIGH, c);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, c);
/*
* XXX If we don't finish in one second, give up...
@@ -1948,7 +2031,8 @@ gus_start_voice(sc, voice, intrs)
int voice;
int intrs;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
u_long start;
u_long current;
u_long end;
@@ -1978,22 +2062,22 @@ gus_start_voice(sc, voice, intrs)
* Select the voice we want to use, and program the data addresses
*/
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(start));
- SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(start));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(start));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(start));
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(current));
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(current));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(current));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(current));
- SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(end));
- SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(end));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(end));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(end));
/*
* (maybe) enable interrupts, disable voice stopping
@@ -2013,24 +2097,24 @@ gus_start_voice(sc, voice, intrs)
* from 0 up to the set volume to help reduce clicks.
*/
- SELECT_GUS_REG(port, GUSREG_START_VOLUME);
- outb(port+GUS_DATA_HIGH, 0x00);
- SELECT_GUS_REG(port, GUSREG_END_VOLUME);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x00);
- SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
- outb(port+GUS_DATA_HIGH, 63);
-
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].current_volume >> 4);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 63);
+
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
delay(50);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
}
@@ -2044,7 +2128,8 @@ gus_stop_voice(sc, voice, intrs_too)
int voice;
int intrs_too;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
sc->sc_voc[voice].voccntl |= GUSMASK_VOICE_STOPPED |
GUSMASK_STOP_VOICE;
@@ -2055,24 +2140,24 @@ gus_stop_voice(sc, voice, intrs_too)
}
DMAPRINTF(("gusintr voice notplaying=%x\n", sc->sc_flags));
- guspoke(port, 0L, 0);
+ guspoke(iot, ioh2, 0L, 0);
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
delay(100);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[voice].voccntl);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
}
@@ -2085,59 +2170,66 @@ gus_set_volume(sc, voice, volume)
struct gus_softc *sc;
int voice, volume;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
unsigned int gusvol;
gusvol = gus_log_volumes[volume < 512 ? volume : 511];
sc->sc_voc[voice].current_volume = gusvol;
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_START_VOLUME);
- outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
- SELECT_GUS_REG(port, GUSREG_END_VOLUME);
- outb(port+GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) (gusvol >> 4));
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, gusvol << 4);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
delay(500);
- outw(port+GUS_DATA_LOW, gusvol << 4);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, gusvol << 4);
}
/*
- * Interface to the audio layer - set the data encoding type
+ * Interface to the audio layer.
*/
int
-gusmax_set_format(addr, encoding, precision)
- void * addr;
- u_int encoding, precision;
+gusmax_set_params(addr, setmode, usemode, p, r)
+ void *addr;
+ int setmode, usemode;
+ struct audio_params *p, *r;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
int error;
- error = ad1848_set_format(ac, encoding, precision);
- return (error ? error : gus_set_format(sc, encoding, precision));
+ error = ad1848_set_params(ac, setmode, usemode, p, r);
+ if (error)
+ return error;
+ error = gus_set_params(sc, setmode, usemode, p, r);
+ return error;
}
int
-gus_set_format(addr, encoding, precision)
- void * addr;
- u_int encoding, precision;
+gus_set_params(addr, setmode, usemode, p, r)
+ void *addr;
+ int setmode, usemode;
+ struct audio_params *p, *r;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
int s;
- DPRINTF(("gus_set_format called\n"));
-
- switch (encoding) {
+ switch (p->encoding) {
case AUDIO_ENCODING_ULAW:
- case AUDIO_ENCODING_PCM16:
- case AUDIO_ENCODING_PCM8:
+ case AUDIO_ENCODING_ALAW:
+ case AUDIO_ENCODING_SLINEAR_LE:
+ case AUDIO_ENCODING_ULINEAR_LE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ case AUDIO_ENCODING_ULINEAR_BE:
break;
default:
return (EINVAL);
@@ -2145,7 +2237,7 @@ gus_set_format(addr, encoding, precision)
s = splaudio();
- if (precision == 8) {
+ if (p->precision == 8) {
sc->sc_voc[GUS_VOICE_LEFT].voccntl &= ~GUSMASK_DATA_SIZE16;
sc->sc_voc[GUS_VOICE_RIGHT].voccntl &= ~GUSMASK_DATA_SIZE16;
} else {
@@ -2153,40 +2245,33 @@ gus_set_format(addr, encoding, precision)
sc->sc_voc[GUS_VOICE_RIGHT].voccntl |= GUSMASK_DATA_SIZE16;
}
- sc->sc_encoding = encoding;
- sc->sc_precision = precision;
+ sc->sc_encoding = p->encoding;
+ sc->sc_precision = p->precision;
+ sc->sc_channels = p->channels;
splx(s);
- return 0;
-}
-
-int
-gusmax_set_channels(addr, channels)
- void * addr;
- int channels;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- int error;
-
- error = ad1848_set_channels(ac, channels);
- return (error ? error : gus_set_channels(sc, channels));
-}
-
-int
-gus_set_channels(addr, channels)
- void * addr;
- int channels;
-{
- register struct gus_softc *sc = addr;
+ if (p->sample_rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
+ p->sample_rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
+ if (setmode & AUMODE_RECORD)
+ sc->sc_irate = p->sample_rate;
+ if (setmode & AUMODE_PLAY)
+ sc->sc_orate = p->sample_rate;
- DPRINTF(("gus_set_channels called\n"));
-
- if (channels != 1 && channels != 2)
- return EINVAL;
-
- sc->sc_channels = channels;
+ switch (p->encoding) {
+ case AUDIO_ENCODING_ULAW:
+ p->sw_code = mulaw_to_ulinear8;
+ r->sw_code = ulinear8_to_mulaw;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ p->sw_code = alaw_to_ulinear8;
+ r->sw_code = ulinear8_to_alaw;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ case AUDIO_ENCODING_SLINEAR_BE:
+ r->sw_code = p->sw_code = swap_bytes;
+ break;
+ }
return 0;
}
@@ -2201,8 +2286,8 @@ gusmax_round_blocksize(addr, blocksize)
void * addr;
int blocksize;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
/* blocksize = ad1848_round_blocksize(ac, blocksize);*/
return gus_round_blocksize(sc, blocksize);
@@ -2213,11 +2298,12 @@ gus_round_blocksize(addr, blocksize)
void * addr;
int blocksize;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
DPRINTF(("gus_round_blocksize called\n"));
- if (sc->sc_encoding == AUDIO_ENCODING_ULAW && blocksize > 32768)
+ if ((sc->sc_encoding == AUDIO_ENCODING_ULAW ||
+ sc->sc_encoding == AUDIO_ENCODING_ALAW) && blocksize > 32768)
blocksize = 32768;
else if (blocksize > 65536)
blocksize = 65536;
@@ -2243,164 +2329,28 @@ gus_round_blocksize(addr, blocksize)
return blocksize;
}
-/*
- * Interfaces to the audio layer - return values from the software config
- * struct
- */
-
-int
-gusmax_get_encoding(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_encoding(sc);
-}
-
-int
-gus_get_encoding(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_encoding called\n"));
-
- /* XXX TODO: codec stuff */
- return sc->sc_encoding;
-}
-
-int
-gusmax_get_channels(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_channels(sc);
-}
-
-int
-gus_get_channels(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_channels called\n"));
-
- return sc->sc_channels;
-}
-
-u_long
-gus_get_in_sr(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_in_sr called\n"));
- return sc->sc_irate;
-}
-
-u_long
-gusmax_get_in_sr(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_in_sr(sc);
-}
-
-u_long
-gusmax_get_out_sr(addr)
- void * addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- return gus_get_out_sr(sc);
-}
-
-u_long
-gus_get_out_sr(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_out_sr called\n"));
- return sc->sc_orate;
-}
-
-int
-gusmax_get_precision(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_get_precision(sc->parent);
-}
-
-int
-gus_get_precision(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_get_precision called\n"));
-
- return sc->sc_precision;
-}
-
int
gus_get_out_gain(addr)
caddr_t addr;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
DPRINTF(("gus_get_out_gain called\n"));
return sc->sc_ogain / 2;
}
-/*
- * Interface to the audio layer - set the sample rate of the output voices
- */
-
-int
-gusmax_set_out_sr(addr, rate)
- void * addr;
- u_long rate;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- int error;
-
- error = ad1848_set_out_sr(ac, rate);
- return (error ? error : gus_set_out_sr(sc, rate));
-}
-
-int
-gus_set_out_sr(addr, rate)
- void * addr;
- u_long rate;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_set_out_sr called\n"));
-
- if (rate > gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES])
- rate = gus_max_frequency[sc->sc_voices - GUS_MIN_VOICES];
-
- sc->sc_orate = rate;
-
- return 0;
-}
-
STATIC inline void gus_set_voices(sc, voices)
struct gus_softc *sc;
int voices;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
/*
* Select the active number of voices
*/
- SELECT_GUS_REG(port, GUSREG_ACTIVE_VOICES);
- outb(port+GUS_DATA_HIGH, (voices-1) | 0xc0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_ACTIVE_VOICES);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (voices-1) | 0xc0);
sc->sc_voices = voices;
}
@@ -2413,10 +2363,13 @@ int
gusmax_commit_settings(addr)
void * addr;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
+ int error;
- (void) ad1848_commit_settings(ac);
+ error = ad1848_commit_settings(ac);
+ if (error)
+ return error;
return gus_commit_settings(sc);
}
@@ -2427,7 +2380,7 @@ int
gus_commit_settings(addr)
void * addr;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
int s;
DPRINTF(("gus_commit_settings called (gain = %d)\n",sc->sc_ogain));
@@ -2489,7 +2442,8 @@ gus_set_samprate(sc, voice, freq)
struct gus_softc *sc;
int voice, freq;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
unsigned int fc;
u_long temp, f = (u_long) freq;
@@ -2509,46 +2463,15 @@ gus_set_samprate(sc, voice, freq)
* Program the voice frequency, and set it in the voice data record
*/
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_FREQ_CONTROL);
- outw(port+GUS_DATA_LOW, fc);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_FREQ_CONTROL);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, fc);
sc->sc_voc[voice].rate = freq;
}
/*
- * Interface to the audio layer - set the recording sampling rate
- */
-
-int
-gusmax_set_in_sr(addr, rate)
- void * addr;
- u_long rate;
-{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
- int error;
-
- error = ad1848_set_in_sr(ac, rate);
- return (error ? error : gus_set_in_sr(sc, rate));
-}
-
-
-int
-gus_set_in_sr(addr, rate)
- void *addr;
- u_long rate;
-{
- register struct gus_softc *sc = addr;
-
- DPRINTF(("gus_set_in_sr called\n"));
-
- sc->sc_irate = rate;
-
- return 0;
-}
-/*
* Set the sample rate of the recording frequency. Formula is from the GUS
* SDK. Called at splgus().
*/
@@ -2558,7 +2481,8 @@ gus_set_recrate(sc, rate)
struct gus_softc *sc;
u_long rate;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
u_char realrate;
DPRINTF(("gus_set_recrate %lu\n", rate));
@@ -2567,8 +2491,8 @@ gus_set_recrate(sc, rate)
#endif
realrate = (9878400 >> 4)/rate - 2; /* formula from code, sigh. */
- SELECT_GUS_REG(port, GUSREG_SAMPLE_FREQ);
- outb(port+GUS_DATA_HIGH, realrate);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_FREQ);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, realrate);
}
/*
@@ -2581,7 +2505,7 @@ gusmax_speaker_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_speaker_ctl(sc->parent, newstate);
}
@@ -2590,18 +2514,20 @@ gus_speaker_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
/* Line out bit is flipped: 0 enables, 1 disables */
if ((newstate == SPKR_ON) &&
(sc->sc_mixcontrol & GUSMASK_LINE_OUT)) {
sc->sc_mixcontrol &= ~GUSMASK_LINE_OUT;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
if ((newstate == SPKR_OFF) &&
(sc->sc_mixcontrol & GUSMASK_LINE_OUT) == 0) {
sc->sc_mixcontrol |= GUSMASK_LINE_OUT;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
return 0;
@@ -2612,18 +2538,20 @@ gus_linein_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
/* Line in bit is flipped: 0 enables, 1 disables */
if ((newstate == SPKR_ON) &&
(sc->sc_mixcontrol & GUSMASK_LINE_IN)) {
sc->sc_mixcontrol &= ~GUSMASK_LINE_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
if ((newstate == SPKR_OFF) &&
(sc->sc_mixcontrol & GUSMASK_LINE_IN) == 0) {
sc->sc_mixcontrol |= GUSMASK_LINE_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
return 0;
@@ -2634,18 +2562,20 @@ gus_mic_ctl(addr, newstate)
void * addr;
int newstate;
{
- register struct gus_softc *sc = (struct gus_softc *) addr;
+ struct gus_softc *sc = (struct gus_softc *) addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
/* Mic bit is normal: 1 enables, 0 disables */
if ((newstate == SPKR_ON) &&
(sc->sc_mixcontrol & GUSMASK_MIC_IN) == 0) {
sc->sc_mixcontrol |= GUSMASK_MIC_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
if ((newstate == SPKR_OFF) &&
(sc->sc_mixcontrol & GUSMASK_MIC_IN)) {
sc->sc_mixcontrol &= ~GUSMASK_MIC_IN;
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
}
return 0;
@@ -2661,17 +2591,18 @@ gus_set_endaddr(sc, voice, addr)
int voice;
u_long addr;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
sc->sc_voc[voice].end_addr = addr;
if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
addr = convert_to_16bit(addr);
- SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
- SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
}
@@ -2685,19 +2616,20 @@ gus_set_curaddr(sc, voice, addr)
int voice;
u_long addr;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
sc->sc_voc[voice].current_addr = addr;
if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
addr = convert_to_16bit(addr);
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, ADDR_HIGH(addr));
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, ADDR_LOW(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_HIGH(addr));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, ADDR_LOW(addr));
}
@@ -2709,18 +2641,19 @@ gus_get_curaddr(sc, voice)
struct gus_softc *sc;
int voice;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
u_long addr;
- outb(port+GUS_VOICE_SELECT, (unsigned char) voice);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
- addr = (inw(port+GUS_DATA_LOW) & 0x1fff) << 7;
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
- addr |= (inw(port+GUS_DATA_LOW) >> 9L) & 0x7f;
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) voice);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH|GUSREG_READ);
+ addr = (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) & 0x1fff) << 7;
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW|GUSREG_READ);
+ addr |= (bus_space_read_2(iot, ioh2, GUS_DATA_LOW) >> 9L) & 0x7f;
if (sc->sc_voc[voice].voccntl & GUSMASK_DATA_SIZE16)
addr = (addr & 0xc0000) | ((addr & 0x1ffff) << 1); /* undo 16-bit change */
- DPRINTF(("gus voice %d curaddr %d end_addr %d\n",
+ DPRINTF(("gus voice %d curaddr %ld end_addr %ld\n",
voice, addr, sc->sc_voc[voice].end_addr));
/* XXX sanity check the address? */
@@ -2752,8 +2685,9 @@ convert_to_16bit(address)
*/
STATIC void
-guspoke(port, address, value)
- int port;
+guspoke(iot, ioh2, address, value)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh2;
long address;
unsigned char value;
{
@@ -2762,16 +2696,16 @@ guspoke(port, address, value)
* Select the DRAM address
*/
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
- outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
- outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
/*
* Actually write the data
*/
- outb(port+GUS_DRAM_DATA, value);
+ bus_space_write_1(iot, ioh2, GUS_DRAM_DATA, value);
}
/*
@@ -2779,8 +2713,9 @@ guspoke(port, address, value)
*/
STATIC unsigned char
-guspeek(port, address)
- int port;
+guspeek(iot, ioh2, address)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh2;
u_long address;
{
@@ -2788,16 +2723,16 @@ guspeek(port, address)
* Select the DRAM address
*/
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_LOW);
- outw(port+GUS_DATA_LOW, (unsigned int) (address & 0xffff));
- SELECT_GUS_REG(port, GUSREG_DRAM_ADDR_HIGH);
- outb(port+GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, (unsigned int) (address & 0xffff));
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DRAM_ADDR_HIGH);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, (unsigned char) ((address >> 16) & 0xff));
/*
* Read in the data from the board
*/
- return (unsigned char) inb(port+GUS_DRAM_DATA);
+ return (unsigned char) bus_space_read_1(iot, ioh2, GUS_DRAM_DATA);
}
/*
@@ -2809,7 +2744,10 @@ gusreset(sc, voices)
struct gus_softc *sc;
int voices;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ bus_space_handle_t ioh4 = sc->sc_ioh4;
int i,s;
s = splgus();
@@ -2818,8 +2756,8 @@ gusreset(sc, voices)
* Reset the GF1 chip
*/
- SELECT_GUS_REG(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
delay(500);
@@ -2827,8 +2765,8 @@ gusreset(sc, voices)
* Release reset
*/
- SELECT_GUS_REG(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET);
delay(500);
@@ -2836,106 +2774,108 @@ gusreset(sc, voices)
* Reset MIDI port as well
*/
- outb(GUS_MIDI_CONTROL,MIDI_RESET);
+ bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, MIDI_RESET);
delay(500);
- outb(GUS_MIDI_CONTROL,0x00);
+ bus_space_write_1(iot, ioh4, GUS_MIDI_CONTROL, 0x00);
/*
* Clear interrupts
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
- SELECT_GUS_REG(port, GUSREG_TIMER_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- outb(port+GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_TIMER_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x00);
gus_set_voices(sc, voices);
- inb(port+GUS_IRQ_STATUS);
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
- inb(port+GUS_DATA_HIGH);
+ bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
/*
* Reset voice specific information
*/
for(i = 0; i < voices; i++) {
- outb(port+GUS_VOICE_SELECT, (unsigned char) i);
+ bus_space_write_1(iot, ioh2, GUS_VOICE_SELECT, (unsigned char) i);
- SELECT_GUS_REG(port, GUSREG_VOICE_CNTL);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOICE_CNTL);
sc->sc_voc[i].voccntl = GUSMASK_VOICE_STOPPED |
GUSMASK_STOP_VOICE;
- outb(port+GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].voccntl);
sc->sc_voc[i].volcntl = GUSMASK_VOLUME_STOPPED |
GUSMASK_STOP_VOLUME;
- SELECT_GUS_REG(port, GUSREG_VOLUME_CONTROL);
- outb(port+GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, sc->sc_voc[i].volcntl);
delay(100);
gus_set_samprate(sc, i, 8000);
- SELECT_GUS_REG(port, GUSREG_START_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_START_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_END_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_END_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_VOLUME_RATE);
- outb(port+GUS_DATA_HIGH, 0x01);
- SELECT_GUS_REG(port, GUSREG_START_VOLUME);
- outb(port+GUS_DATA_HIGH, 0x10);
- SELECT_GUS_REG(port, GUSREG_END_VOLUME);
- outb(port+GUS_DATA_HIGH, 0xe0);
- SELECT_GUS_REG(port, GUSREG_CUR_VOLUME);
- outw(port+GUS_DATA_LOW, 0x0000);
-
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_HIGH);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_CUR_ADDR_LOW);
- outw(port+GUS_DATA_LOW, 0x0000);
- SELECT_GUS_REG(port, GUSREG_PAN_POS);
- outb(port+GUS_DATA_HIGH, 0x07);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_VOLUME_RATE);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x01);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_START_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x10);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_END_VOLUME);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0xe0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_VOLUME);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_HIGH);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_CUR_ADDR_LOW);
+ bus_space_write_2(iot, ioh2, GUS_DATA_LOW, 0x0000);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_PAN_POS);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0x07);
}
/*
* Clear out any pending IRQs
*/
- inb(port+GUS_IRQ_STATUS);
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- inb(port+GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_IRQ_STATUS);
- inb(port+GUS_DATA_HIGH);
+ bus_space_read_1(iot, ioh1, GUS_IRQ_STATUS);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_IRQ_STATUS);
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH);
- SELECT_GUS_REG(port, GUSREG_RESET);
- outb(port+GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
+ SELECT_GUS_REG(iot, ioh2, GUSREG_RESET);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, GUSMASK_MASTER_RESET | GUSMASK_DAC_ENABLE |
GUSMASK_IRQ_ENABLE);
splx(s);
}
-STATIC void
+STATIC int
gus_init_cs4231(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh1 = sc->sc_ioh1;
+ int port = sc->sc_iobase;
u_char ctrl;
ctrl = (port & 0xf0) >> 4; /* set port address middle nibble */
@@ -2948,60 +2888,16 @@ gus_init_cs4231(sc)
if (sc->sc_recdrq >= 4)
ctrl |= GUS_MAX_PLAYCHAN16;
- outb(port+GUS_MAX_CTRL, ctrl);
+ bus_space_write_1(iot, ioh1, GUS_MAX_CTRL, ctrl);
+ sc->sc_codec.sc_iot = sc->sc_iot;
sc->sc_codec.sc_iobase = port+GUS_MAX_CODEC_BASE;
if (ad1848_probe(&sc->sc_codec) == 0) {
sc->sc_flags &= ~GUS_CODEC_INSTALLED;
+ return (0);
} else {
struct ad1848_volume vol = {AUDIO_MAX_GAIN, AUDIO_MAX_GAIN};
- struct audio_hw_if gusmax_hw_if = {
- gusopen,
- gusmax_close,
- NULL, /* drain */
- gusmax_set_in_sr,
- gusmax_get_in_sr,
- gusmax_set_out_sr,
- gusmax_get_out_sr,
-
- ad1848_query_encoding, /* query encoding */
- gusmax_set_format,
- gusmax_get_encoding,
- gusmax_get_precision,
-
- gusmax_set_channels,
- gusmax_get_channels,
-
- gusmax_round_blocksize,
-
- gusmax_set_out_port,
- gusmax_get_out_port,
- gusmax_set_in_port,
- gusmax_get_in_port,
-
- gusmax_commit_settings,
-
- gusmax_expand, /* XXX use codec */
- mulaw_compress,
-
- gusmax_dma_output,
- gusmax_dma_input,
- gusmax_halt_out_dma,
- gusmax_halt_in_dma,
- gusmax_cont_out_dma,
- gusmax_cont_in_dma,
-
- gusmax_speaker_ctl,
-
- gus_getdev,
- gus_setfd,
- gusmax_mixer_set_port,
- gusmax_mixer_get_port,
- gusmax_mixer_query_devinfo,
- 1, /* full-duplex */
- 0,
- };
sc->sc_flags |= GUS_CODEC_INSTALLED;
sc->sc_codec.parent = sc;
sc->sc_codec.sc_drq = sc->sc_recdrq;
@@ -3011,11 +2907,13 @@ gus_init_cs4231(sc)
will do the real mixing for them. */
sc->sc_mixcontrol &= ~GUSMASK_LINE_IN; /* 0 enables. */
sc->sc_mixcontrol |= GUSMASK_MIC_IN; /* 1 enables. */
- outb(sc->sc_iobase+GUS_MIX_CONTROL, sc->sc_mixcontrol);
+ bus_space_write_1(iot, ioh1, GUS_MIX_CONTROL, sc->sc_mixcontrol);
ad1848_attach(&sc->sc_codec);
/* turn on pre-MUX microphone gain. */
ad1848_set_mic_gain(&sc->sc_codec, &vol);
+
+ return (1);
}
}
@@ -3056,128 +2954,6 @@ gus_get_in_gain(addr)
}
int
-gusmax_set_out_port(addr, port)
- void * addr;
- int port;
-{
- register struct ad1848_softc *sc = addr;
- return gus_set_out_port(sc->parent, port);
-}
-
-int
-gus_set_out_port(addr, port)
- void * addr;
- int port;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_set_out_port called\n"));
- sc->sc_out_port = port;
-
- return 0;
-}
-
-int
-gusmax_get_out_port(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_get_out_port(sc->parent);
-}
-
-int
-gus_get_out_port(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_get_out_port() called\n"));
- return sc->sc_out_port;
-}
-
-int
-gusmax_set_in_port(addr, port)
- void * addr;
- int port;
-{
- register struct ad1848_softc *sc = addr;
- DPRINTF(("gusmax_set_in_port: %d\n", port));
-
- switch(port) {
- case GUSMAX_MONO_LVL:
- port = MIC_IN_PORT;
- break;
- case GUSMAX_LINE_IN_LVL:
- port = LINE_IN_PORT;
- break;
- case GUSMAX_DAC_LVL:
- port = AUX1_IN_PORT;
- break;
- case GUSMAX_MIX_IN:
- port = DAC_IN_PORT;
- break;
- default:
- return(EINVAL);
- /*NOTREACHED*/
- }
- return(ad1848_set_rec_port(sc, port));
-}
-
-int
-gusmax_get_in_port(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- int port = GUSMAX_MONO_LVL;
-
- switch(ad1848_get_rec_port(sc)) {
- case MIC_IN_PORT:
- port = GUSMAX_MONO_LVL;
- break;
- case LINE_IN_PORT:
- port = GUSMAX_LINE_IN_LVL;
- break;
- case DAC_IN_PORT:
- port = GUSMAX_MIX_IN;
- break;
- case AUX1_IN_PORT:
- port = GUSMAX_DAC_LVL;
- break;
- }
-
- DPRINTF(("gusmax_get_in_port: %d\n", port));
-
- return(port);
-}
-
-int
-gus_set_in_port(addr, port)
- void * addr;
- int port;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_set_in_port called\n"));
- /*
- * On the GUS with ICS mixer, the ADC input is after the mixer stage,
- * so we can't set the input port.
- *
- * On the GUS with CS4231 codec/mixer, see gusmax_set_in_port().
- */
- sc->sc_in_port = port;
-
- return 0;
-}
-
-
-int
-gus_get_in_port(addr)
- void * addr;
-{
- register struct gus_softc *sc = addr;
- DPRINTF(("gus_get_in_port called\n"));
- return sc->sc_in_port;
-}
-
-
-int
gusmax_dma_input(addr, buf, size, callback, arg)
void * addr;
void *buf;
@@ -3185,7 +2961,7 @@ gusmax_dma_input(addr, buf, size, callback, arg)
void (*callback) __P((void *));
void *arg;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_dma_input(sc->parent, buf, size, callback, arg);
}
@@ -3201,9 +2977,10 @@ gus_dma_input(addr, buf, size, callback, arg)
void (*callback) __P((void *));
void *arg;
{
- register struct gus_softc *sc = addr;
- register int port = sc->sc_iobase;
- register u_char dmac;
+ struct gus_softc *sc = addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
+ u_char dmac;
DMAPRINTF(("gus_dma_input called\n"));
/*
@@ -3218,11 +2995,14 @@ gus_dma_input(addr, buf, size, callback, arg)
if (sc->sc_recdrq >= 4)
dmac |= GUSMASK_SAMPLE_DATA16;
if (sc->sc_encoding == AUDIO_ENCODING_ULAW ||
- sc->sc_encoding == AUDIO_ENCODING_PCM8)
+ sc->sc_encoding == AUDIO_ENCODING_ALAW ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_LE ||
+ sc->sc_encoding == AUDIO_ENCODING_ULINEAR_BE)
dmac |= GUSMASK_SAMPLE_INVBIT;
if (sc->sc_channels == 2)
dmac |= GUSMASK_SAMPLE_STEREO;
- isadma_start((caddr_t)buf, size, sc->sc_recdrq, DMAMODE_READ);
+ isa_dmastart(sc->sc_dev.dv_parent, sc->sc_recdrq, buf, size,
+ NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
DMAPRINTF(("gus_dma_input isadma_started\n"));
sc->sc_flags |= GUS_DMAIN_ACTIVE;
@@ -3231,8 +3011,8 @@ gus_dma_input(addr, buf, size, callback, arg)
sc->sc_dmaincnt = size;
sc->sc_dmainaddr = buf;
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- outb(port+GUS_DATA_HIGH, dmac); /* Go! */
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, dmac); /* Go! */
DMAPRINTF(("gus_dma_input returning\n"));
@@ -3249,7 +3029,7 @@ gus_dmain_intr(sc)
DMAPRINTF(("gus_dmain_intr called\n"));
if (sc->sc_dmainintr) {
- isadma_done(sc->sc_recdrq);
+ isa_dmadone(sc->sc_dev.dv_parent, sc->sc_recdrq);
callback = sc->sc_dmainintr;
arg = sc->sc_inarg;
@@ -3259,7 +3039,7 @@ gus_dmain_intr(sc)
sc->sc_inarg = 0;
sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
- DMAPRINTF(("calling dmain_intr callback %x(%x)\n", callback, arg));
+ DMAPRINTF(("calling dmain_intr callback %p(%p)\n", callback, arg));
(*callback)(arg);
return 1;
} else {
@@ -3272,7 +3052,7 @@ int
gusmax_halt_out_dma(addr)
void * addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_halt_out_dma(sc->parent);
}
@@ -3281,26 +3061,10 @@ int
gusmax_halt_in_dma(addr)
void * addr;
{
- register struct ad1848_softc *sc = addr;
+ struct ad1848_softc *sc = addr;
return gus_halt_in_dma(sc->parent);
}
-int
-gusmax_cont_out_dma(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_cont_out_dma(sc->parent);
-}
-
-int
-gusmax_cont_in_dma(addr)
- void * addr;
-{
- register struct ad1848_softc *sc = addr;
- return gus_cont_in_dma(sc->parent);
-}
-
/*
* Stop any DMA output. Called at splgus().
*/
@@ -3308,19 +3072,20 @@ int
gus_halt_out_dma(addr)
void * addr;
{
- register struct gus_softc *sc = addr;
- register int port = sc->sc_iobase;
+ struct gus_softc *sc = addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
DMAPRINTF(("gus_halt_out_dma called\n"));
/*
* Make sure the GUS _isn't_ setup for DMA
*/
- SELECT_GUS_REG(port, GUSREG_DMA_CONTROL);
- outb(sc->sc_iobase+GUS_DATA_HIGH, 0);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_DMA_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH, 0);
untimeout(gus_dmaout_timeout, sc);
- isadma_abort(sc->sc_drq);
+ isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_drq);
sc->sc_flags &= ~(GUS_DMAOUT_ACTIVE|GUS_LOCKED);
sc->sc_dmaoutintr = 0;
sc->sc_outarg = 0;
@@ -3343,20 +3108,20 @@ int
gus_halt_in_dma(addr)
void * addr;
{
- register struct gus_softc *sc = addr;
- register int port = sc->sc_iobase;
+ struct gus_softc *sc = addr;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh2 = sc->sc_ioh2;
DMAPRINTF(("gus_halt_in_dma called\n"));
/*
* Make sure the GUS _isn't_ setup for DMA
*/
- SELECT_GUS_REG(port, GUSREG_SAMPLE_CONTROL);
- outb(port+GUS_DATA_HIGH,
- inb(port+GUS_DATA_HIGH) &
- ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
-
- isadma_abort(sc->sc_recdrq);
+ SELECT_GUS_REG(iot, ioh2, GUSREG_SAMPLE_CONTROL);
+ bus_space_write_1(iot, ioh2, GUS_DATA_HIGH,
+ bus_space_read_1(iot, ioh2, GUS_DATA_HIGH) & ~(GUSMASK_SAMPLE_START|GUSMASK_SAMPLE_IRQ));
+
+ isa_dmaabort(sc->sc_dev.dv_parent, sc->sc_recdrq);
sc->sc_flags &= ~GUS_DMAIN_ACTIVE;
sc->sc_dmainintr = 0;
sc->sc_inarg = 0;
@@ -3366,34 +3131,6 @@ gus_halt_in_dma(addr)
return 0;
}
-int
-gus_cont_out_dma(addr)
- void * addr;
-{
- DPRINTF(("gus_cont_out_dma called\n"));
- return EOPNOTSUPP;
-}
-
-int
-gus_cont_in_dma(addr)
- void * addr;
-{
- DPRINTF(("gus_cont_in_dma called\n"));
- return EOPNOTSUPP;
-}
-
-
-STATIC int
-gus_setfd(addr, flag)
- void *addr;
- int flag;
-{
- if (gus_hw_if.full_duplex == 0)
- return ENOTTY;
-
- return(0); /* nothing fancy to do. */
-}
-
STATIC __inline int
gus_to_vol(cp, vol)
mixer_ctrl_t *cp;
@@ -3433,8 +3170,8 @@ gusmax_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -3584,8 +3321,8 @@ gus_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct gus_softc *sc = addr;
- register struct ics2101_softc *ic = &sc->sc_mixer;
+ struct gus_softc *sc = addr;
+ struct ics2101_softc *ic = &sc->sc_mixer;
struct ad1848_volume vol;
int error = EINVAL;
@@ -3754,8 +3491,8 @@ gusmax_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct gus_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct gus_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -3907,8 +3644,8 @@ gus_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct gus_softc *sc = addr;
- register struct ics2101_softc *ic = &sc->sc_mixer;
+ struct gus_softc *sc = addr;
+ struct ics2101_softc *ic = &sc->sc_mixer;
struct ad1848_volume vol;
int error = EINVAL;
@@ -4063,21 +3800,29 @@ gus_mixer_set_port(addr, cp)
}
STATIC int
+gus_get_props(addr)
+ void *addr;
+{
+ struct gus_softc *sc = addr;
+ return sc->sc_recdrq == sc->sc_drq ? 0 : AUDIO_PROP_FULLDUPLEX;
+}
+
+STATIC int
+gusmax_get_props(addr)
+ void *addr;
+{
+ struct ad1848_softc *ac = addr;
+ return gus_get_props(ac->parent);
+}
+
+STATIC int
gusmax_mixer_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
switch(dip->index) {
- case GUSMAX_MIX_IN: /* mixed MUX input */
- dip->type = AUDIO_MIXER_ENUM;
- dip->mixer_class = GUSMAX_INPUT_CLASS;
- dip->prev = dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmixerout);
- dip->un.e.num_mem = 0; /* XXX */
- break;
-
#if 0
case GUSMAX_MIC_IN_LVL: /* Microphone */
dip->type = AUDIO_MIXER_VALUE;
@@ -4155,7 +3900,7 @@ gusmax_mixer_query_devinfo(addr, dip)
dip->mixer_class = GUSMAX_MONITOR_CLASS;
dip->prev = AUDIO_MIXER_LAST;
dip->next = GUSMAX_SPEAKER_MUTE;
- strcpy(dip->label.name, AudioNspeaker);
+ strcpy(dip->label.name, AudioNmaster);
dip->un.v.num_channels = 2;
strcpy(dip->un.v.units.name, AudioNvolume);
break;
@@ -4227,41 +3972,41 @@ gusmax_mixer_query_devinfo(addr, dip)
strcpy(dip->label.name, AudioNsource);
dip->un.e.num_mem = 4;
strcpy(dip->un.e.member[0].label.name, AudioNoutput);
- dip->un.e.member[0].ord = GUSMAX_MIX_IN;
+ dip->un.e.member[0].ord = DAC_IN_PORT;
strcpy(dip->un.e.member[1].label.name, AudioNmicrophone);
- dip->un.e.member[1].ord = GUSMAX_MONO_LVL;
+ dip->un.e.member[1].ord = MIC_IN_PORT;
strcpy(dip->un.e.member[2].label.name, AudioNdac);
- dip->un.e.member[2].ord = GUSMAX_DAC_LVL;
+ dip->un.e.member[2].ord = AUX1_IN_PORT;
strcpy(dip->un.e.member[3].label.name, AudioNline);
- dip->un.e.member[3].ord = GUSMAX_LINE_IN_LVL;
+ dip->un.e.member[3].ord = LINE_IN_PORT;
break;
case GUSMAX_INPUT_CLASS: /* input class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_INPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ strcpy(dip->label.name, AudioCinputs);
break;
case GUSMAX_OUTPUT_CLASS: /* output class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCOutputs);
+ strcpy(dip->label.name, AudioCoutputs);
break;
case GUSMAX_MONITOR_CLASS: /* monitor class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_MONITOR_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCMonitor);
+ strcpy(dip->label.name, AudioCmonitor);
break;
case GUSMAX_RECORD_CLASS: /* record source class */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSMAX_RECORD_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCRecord);
+ strcpy(dip->label.name, AudioCrecord);
break;
default:
@@ -4275,9 +4020,9 @@ gusmax_mixer_query_devinfo(addr, dip)
STATIC int
gus_mixer_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
- register struct gus_softc *sc = addr;
+ struct gus_softc *sc = addr;
DPRINTF(("gusmax_query_devinfo: index=%d\n", dip->index));
@@ -4331,7 +4076,7 @@ gus_mixer_query_devinfo(addr, dip)
dip->mixer_class = GUSICS_OUTPUT_CLASS;
dip->prev = AUDIO_MIXER_LAST;
dip->next = GUSICS_MASTER_MUTE;
- strcpy(dip->label.name, AudioNvolume);
+ strcpy(dip->label.name, AudioNmaster);
dip->un.v.num_channels = 2;
strcpy(dip->un.v.units.name, AudioNvolume);
break;
@@ -4393,21 +4138,21 @@ mute:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSICS_INPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ strcpy(dip->label.name, AudioCinputs);
break;
case GUSICS_OUTPUT_CLASS:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSICS_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCOutputs);
+ strcpy(dip->label.name, AudioCoutputs);
break;
case GUSICS_RECORD_CLASS:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = GUSICS_RECORD_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCRecord);
+ strcpy(dip->label.name, AudioCrecord);
break;
default:
@@ -4426,16 +4171,53 @@ gus_query_encoding(addr, fp)
switch (fp->index) {
case 0:
strcpy(fp->name, AudioEmulaw);
- fp->format_id = AUDIO_ENCODING_ULAW;
+ fp->encoding = AUDIO_ENCODING_ULAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
break;
case 1:
- strcpy(fp->name, AudioEpcm16);
- fp->format_id = AUDIO_ENCODING_PCM16;
+ strcpy(fp->name, AudioEslinear);
+ fp->encoding = AUDIO_ENCODING_SLINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
break;
case 2:
- strcpy(fp->name, AudioEpcm8);
- fp->format_id = AUDIO_ENCODING_PCM8;
+ strcpy(fp->name, AudioEslinear_le);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
break;
+ case 3:
+ strcpy(fp->name, AudioEulinear);
+ fp->encoding = AUDIO_ENCODING_ULINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
+ break;
+ case 4:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
+ break;
+ case 5:
+ strcpy(fp->name, AudioEslinear_be);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 6:
+ strcpy(fp->name, AudioEulinear_be);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+ case 7:
+ strcpy(fp->name, AudioEalaw);
+ fp->encoding = AUDIO_ENCODING_ALAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ break;
+
default:
return(EINVAL);
/*NOTREACHED*/
@@ -4452,10 +4234,12 @@ STATIC void
gus_init_ics2101(sc)
struct gus_softc *sc;
{
- register int port = sc->sc_iobase;
- register struct ics2101_softc *ic = &sc->sc_mixer;
- sc->sc_mixer.sc_selio = port+GUS_MIXER_SELECT;
- sc->sc_mixer.sc_dataio = port+GUS_MIXER_DATA;
+ struct ics2101_softc *ic = &sc->sc_mixer;
+ sc->sc_mixer.sc_iot = sc->sc_iot;
+ sc->sc_mixer.sc_selio = GUS_MIXER_SELECT;
+ sc->sc_mixer.sc_selio_ioh = sc->sc_ioh3;
+ sc->sc_mixer.sc_dataio = GUS_MIXER_DATA;
+ sc->sc_mixer.sc_dataio_ioh = sc->sc_ioh2;
sc->sc_mixer.sc_flags = (sc->sc_revision == 5) ? ICS_FLIP : 0;
ics2101_mix_attenuate(ic,
diff --git a/sys/dev/isa/gusreg.h b/sys/dev/isa/gusreg.h
index 88f55d1cf81..b1b86a42e87 100644
--- a/sys/dev/isa/gusreg.h
+++ b/sys/dev/isa/gusreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: gusreg.h,v 1.3 1997/07/10 23:06:35 provos Exp $ */
-/* $NetBSD: gusreg.h,v 1.3 1996/02/05 02:22:10 jtc Exp $ */
+/* $OpenBSD: gusreg.h,v 1.4 1998/04/26 21:02:43 provos Exp $ */
+/* $NetBSD: gusreg.h,v 1.6 1997/10/09 07:57:22 jtc Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@@ -47,10 +47,13 @@
* address.
*/
-#define GUS_MIDI_CONTROL 0x100
-#define GUS_MIDI_STATUS 0x100
-#define GUS_MIDI_READ 0x101
-#define GUS_MIDI_WRITE 0x101
+#define GUS_IOH4_OFFSET 0x100
+#define GUS_NPORT4 2
+
+#define GUS_MIDI_CONTROL (0x100-GUS_IOH4_OFFSET)
+#define GUS_MIDI_STATUS (0x100-GUS_IOH4_OFFSET)
+#define GUS_MIDI_READ (0x101-GUS_IOH4_OFFSET)
+#define GUS_MIDI_WRITE (0x101-GUS_IOH4_OFFSET)
/*
* Joystick interface - note this is an absolute address, NOT an offset from
@@ -79,11 +82,18 @@
#define GUS_DMA_CONTROL 0x00b
#define GUS_IRQCTL_CONTROL 0x00b
#define GUS_JUMPER_CONTROL 0x00b
-#define GUS_VOICE_SELECT 0x102
-#define GUS_REG_SELECT 0x103
-#define GUS_DATA_LOW 0x104
-#define GUS_DATA_HIGH 0x105
-#define GUS_DRAM_DATA 0x107
+
+#define GUS_NPORT1 16
+
+#define GUS_IOH2_OFFSET 0x102
+#define GUS_VOICE_SELECT (0x102-GUS_IOH2_OFFSET)
+#define GUS_REG_SELECT (0x103-GUS_IOH2_OFFSET)
+#define GUS_DATA_LOW (0x104-GUS_IOH2_OFFSET)
+#define GUS_DATA_HIGH (0x105-GUS_IOH2_OFFSET)
+/* GUS_MIXER_SELECT 106 */
+#define GUS_DRAM_DATA (0x107-GUS_IOH2_OFFSET)
+
+#define GUS_NPORT2 6
/*
* GUS on-board global registers
@@ -229,9 +239,12 @@
* ICS Mixer registers
*/
-#define GUS_MIXER_SELECT 0x506 /* read=board rev, wr=mixer */
-#define GUS_BOARD_REV 0x506
-#define GUS_MIXER_DATA 0x106 /* data for mixer control */
+#define GUS_IOH3_OFFSET 0x506
+#define GUS_NPORT3 1
+
+#define GUS_MIXER_SELECT (0x506-GUS_IOH3_OFFSET) /* read=board rev, wr=mixer */
+#define GUS_BOARD_REV (0x506-GUS_IOH3_OFFSET)
+#define GUS_MIXER_DATA (0x106-GUS_IOH2_OFFSET) /* data for mixer control */
#define GUSMIX_CHAN_MIC ICSMIX_CHAN_0
#define GUSMIX_CHAN_LINE ICSMIX_CHAN_1
diff --git a/sys/dev/isa/ics2101.c b/sys/dev/isa/ics2101.c
index 458d1424ffd..88049e3e56d 100644
--- a/sys/dev/isa/ics2101.c
+++ b/sys/dev/isa/ics2101.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ics2101.c,v 1.3 1996/05/07 07:36:42 deraadt Exp $ */
-/* $NetBSD: ics2101.c,v 1.4 1996/04/29 20:03:10 christos Exp $ */
+/* $OpenBSD: ics2101.c,v 1.4 1998/04/26 21:02:44 provos Exp $ */
+/* $NetBSD: ics2101.c,v 1.6 1997/10/09 07:57:23 jtc Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@@ -80,6 +80,7 @@ ics2101_mix_doit(sc, chan, side, value, flags)
struct ics2101_softc *sc;
u_int chan, side, value, flags;
{
+ bus_space_tag_t iot = sc->sc_iot;
unsigned char flip_left[6] = {0x01, 0x01, 0x01, 0x02, 0x01, 0x02};
unsigned char flip_right[6] = {0x02, 0x02, 0x02, 0x01, 0x02, 0x01};
register unsigned char ctrl_addr;
@@ -128,11 +129,11 @@ ics2101_mix_doit(sc, chan, side, value, flags)
s = splaudio();
- outb(sc->sc_selio, ctrl_addr);
- outb(sc->sc_dataio, normal);
+ bus_space_write_1(iot, sc->sc_selio_ioh, sc->sc_selio, ctrl_addr);
+ bus_space_write_1(iot, sc->sc_dataio_ioh, sc->sc_dataio, normal);
- outb(sc->sc_selio, attn_addr);
- outb(sc->sc_dataio, (unsigned char) value);
+ bus_space_write_1(iot, sc->sc_selio_ioh, sc->sc_selio, attn_addr);
+ bus_space_write_1(iot, sc->sc_dataio_ioh, sc->sc_dataio, (unsigned char) value);
splx(s);
}
diff --git a/sys/dev/isa/ics2101var.h b/sys/dev/isa/ics2101var.h
index b9a61a63758..26d88f71717 100644
--- a/sys/dev/isa/ics2101var.h
+++ b/sys/dev/isa/ics2101var.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: ics2101var.h,v 1.2 1996/03/08 16:42:58 niklas Exp $ */
-/* $NetBSD: ics2101var.h,v 1.3 1996/02/05 02:22:12 jtc Exp $ */
+/* $OpenBSD: ics2101var.h,v 1.3 1998/04/26 21:02:45 provos Exp $ */
+/* $NetBSD: ics2101var.h,v 1.5 1997/10/09 07:57:24 jtc Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@@ -41,6 +41,9 @@
#define ICSMIX_RIGHT 1 /* Value for right channel */
struct ics2101_softc {
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_selio_ioh;
+ bus_space_handle_t sc_dataio_ioh;
u_short sc_selio; /* select I/O address */
u_short sc_dataio; /* data I/O address */
int sc_flags; /* Various flags */
diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c
index 3010e861fdd..39366021b0e 100644
--- a/sys/dev/isa/isa.c
+++ b/sys/dev/isa/isa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: isa.c,v 1.31 1998/01/20 21:42:25 niklas Exp $ */
+/* $OpenBSD: isa.c,v 1.32 1998/04/26 21:02:47 provos Exp $ */
/* $NetBSD: isa.c,v 1.85 1996/05/14 00:31:04 thorpej Exp $ */
/*
@@ -173,6 +173,8 @@ isaprint(aux, isa)
printf(" irq %d", ia->ia_irq);
if (ia->ia_drq != DRQUNK)
printf(" drq %d", ia->ia_drq);
+ if (ia->ia_drq2 != DRQUNK)
+ printf(" drq2 %d", ia->ia_drq2);
return (UNCONF);
}
@@ -192,12 +194,13 @@ isascan(parent, match)
ia.ia_dmat = sc->sc_dmat;
#endif /* NISADMA > 0 */
ia.ia_ic = sc->sc_ic;
- ia.ia_iobase = cf->cf_loc[0];
+ ia.ia_iobase = cf->cf_iobase;
ia.ia_iosize = 0x666;
- ia.ia_maddr = cf->cf_loc[2];
- ia.ia_msize = cf->cf_loc[3];
- ia.ia_irq = cf->cf_loc[4] == 2 ? 9 : cf->cf_loc[4];
- ia.ia_drq = cf->cf_loc[5];
+ ia.ia_maddr = cf->cf_maddr;
+ ia.ia_msize = cf->cf_msize;
+ ia.ia_irq = cf->cf_irq == 2 ? 9 : cf->cf_irq;
+ ia.ia_drq = cf->cf_drq;
+ ia.ia_drq2 = cf->cf_drq2;
ia.ia_delaybah = sc->sc_delaybah;
if (cf->cf_fstate == FSTATE_STAR) {
@@ -223,6 +226,8 @@ isascan(parent, match)
#if NISADMA > 0
if (ia.ia_drq != DRQUNK)
ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
+ if (ia.ia_drq2 != DRQUNK)
+ ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq2);
#endif /* NISAMDA > 0 */
}
if (autoconf_verbose)
@@ -244,6 +249,8 @@ isascan(parent, match)
#if NISADMA > 0
if (ia.ia_drq != DRQUNK)
ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
+ if (ia.ia_drq2 != DRQUNK)
+ ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq2);
#endif /* NISAMDA > 0 */
} else {
if (autoconf_verbose)
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index a6ef11c2547..3cbfd104aa4 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isavar.h,v 1.27 1998/01/20 18:40:33 niklas Exp $ */
+/* $OpenBSD: isavar.h,v 1.28 1998/04/26 21:02:48 provos Exp $ */
/* $NetBSD: isavar.h,v 1.26 1997/06/06 23:43:57 thorpej Exp $ */
/*-
@@ -289,6 +289,7 @@ struct isa_attach_args {
#define ia_iosize ipa_io[0].length
#define ia_irq ipa_irq[0].num
#define ia_drq ipa_drq[0].num
+#define ia_drq2 ipa_drq[1].num
#define ia_maddr ipa_mem[0].base
#define ia_msize ipa_mem[0].length
#define ia_ioh ipa_io[0].h
@@ -372,6 +373,7 @@ struct isa_softc {
#define cf_msize cf_loc[3]
#define cf_irq cf_loc[4]
#define cf_drq cf_loc[5]
+#define cf_drq2 cf_loc[6]
/*
* ISA interrupt handler manipulation.
diff --git a/sys/dev/isa/madreg.h b/sys/dev/isa/madreg.h
new file mode 100644
index 00000000000..5e6e114aaec
--- /dev/null
+++ b/sys/dev/isa/madreg.h
@@ -0,0 +1,102 @@
+/* $OpenBSD: madreg.h,v 1.1 1998/04/26 21:02:37 provos Exp $ */
+/* $NetBSD: madreg.h,v 1.4 1998/01/19 22:18:27 augustss Exp $ */
+/*
+ * Copyright (c) 1996 Lennart Augustsson
+ * Copyright (c) 1995 Hannu Savolainen
+ * Copyright (c) 1991-1993 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Variations of the suppored chips.
+ */
+
+#define MAD_NONE 0
+#define MAD_82C928 1 /* OPTi 82C928 MAD16 */
+#define MAD_OTI601D 2 /* OAK OTI-601D Mozart */
+#define MAD_82C929 3 /* OPTi 82C929 MAD16 Pro */
+#define MAD_82C931 4 /* OPTi 82C831 */
+
+/*
+ * Registers
+ *
+ * The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations).
+ * All ports are inactive by default. They can be activated by
+ * writing 0xE2 or 0xE3 to the password register. The password is valid
+ * only until the next I/O read or write.
+ */
+
+#define MAD_BASE 0xf8d
+#define MAD_NPORT 7
+
+#define MC1_PORT 0 /* SB address, CDROM interface type, joystick */
+#define MC2_PORT 1 /* CDROM address, IRQ, DMA, plus OPL4 bit */
+#define MC3_PORT 2
+#define MC_PASSWD_REG MC3_PORT
+#define MC4_PORT 3
+#define MC5_PORT 4
+#define MC6_PORT 5
+#define MC7_PORT 6
+
+#define MC1_NOCD 0x00
+#define MC1_JOYDISABLE 0x01
+#define MC1_SONY 0x02
+#define MC1_MITSUMI 0x04
+#define MC1_PANASONIC 0x06
+#define MC1_SECIDE 0x08
+#define MC1_PRIMIDE 0x0a
+
+#define MC2_CDDISABLE 0x03
+#define MC2_OPL4 0x20
+
+/* Possible WSS emulation ports */
+#define M_WSS_PORT0 0x530
+#define M_WSS_PORT1 0xe80
+#define M_WSS_PORT2 0xf40
+#define M_WSS_PORT3 0x604
+#define M_WSS_NPORTS 4
+
+/* Port 1 */
+#define M_WSS_PORT_SELECT(i) (0x80 | ((i) << 4))
+
+#define M_PASSWD_928 0xe2
+#define M_PASSWD_929 0xe3
+#define M_PASSWD_931 0xe4
+
+/* Regions of I/O space that the MAD occupies besides
+ WSS emulation and MAD_BASE. Talk about waste. */
+#define MAD_REG1 0x220
+#define MAD_LEN1 16
+#define MAD_REG2 0x380
+#define MAD_LEN2 2
+#define MAD_REG3 0x388
+#define MAD_LEN3 4
diff --git a/sys/dev/isa/mcd.c b/sys/dev/isa/mcd.c
index 107599f8965..602aee9a684 100644
--- a/sys/dev/isa/mcd.c
+++ b/sys/dev/isa/mcd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mcd.c,v 1.23 1997/11/30 22:33:21 mickey Exp $ */
-/* $NetBSD: mcd.c,v 1.49 1996/05/12 23:53:11 mycroft Exp $ */
+/* $OpenBSD: mcd.c,v 1.24 1998/04/26 21:02:49 provos Exp $ */
+/* $NetBSD: mcd.c,v 1.60 1998/01/14 12:14:41 drochner Exp $ */
/*
* Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
@@ -75,7 +75,7 @@
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <machine/pio.h>
+#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/mcdreg.h>
@@ -118,12 +118,12 @@ struct mcd_softc {
struct disk sc_dk;
void *sc_ih;
- int iobase;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
int irq, drq;
char *type;
- u_char readcmd;
- u_char attached;
int flags;
#define MCDF_LOCKED 0x01
#define MCDF_WANTED 0x02
@@ -143,8 +143,10 @@ struct mcd_softc {
#define MCD_MD_UNKNOWN -1
int lastupc;
#define MCD_UPC_UNKNOWN -1
- int debug;
struct buf buf_queue;
+ u_char readcmd;
+ u_char debug;
+ u_char probe;
};
/* prototypes */
@@ -181,7 +183,13 @@ int mcd_read_toc __P((struct mcd_softc *));
int mcd_getqchan __P((struct mcd_softc *, union mcd_qchninfo *, int));
int mcd_setlock __P((struct mcd_softc *, int));
+int mcd_find __P((bus_space_tag_t, bus_space_handle_t, struct mcd_softc *));
+#define __BROKEN_INDIRECT_CONFIG
+#ifdef __BROKEN_INDIRECT_CONFIG
int mcdprobe __P((struct device *, void *, void *));
+#else
+int mcdprobe __P((struct device *, struct cfdata *, void *));
+#endif
void mcdattach __P((struct device *, struct device *, void *));
struct cfattach mcd_ca = {
@@ -192,6 +200,7 @@ struct cfdriver mcd_cd = {
NULL, "mcd", DV_DISK
};
+void mcdgetdefaultlabel __P((dev_t, struct mcd_softc *, struct disklabel *));
void mcdgetdisklabel __P((dev_t, struct mcd_softc *));
int mcd_get_parms __P((struct mcd_softc *));
void mcdstrategy __P((struct buf *));
@@ -219,8 +228,27 @@ mcdattach(parent, self, aux)
{
struct mcd_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
+ bus_space_tag_t iot = ia->ia_iot;
+ bus_space_handle_t ioh;
struct mcd_mbox mbx;
+ /* Map i/o space */
+ if (bus_space_map(iot, ia->ia_iobase, MCD_NPORT, 0, &ioh)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ sc->sc_iot = iot;
+ sc->sc_ioh = ioh;
+
+ sc->probe = 0;
+ sc->debug = 0;
+
+ if (!mcd_find(iot, ioh, sc)) {
+ printf(": mcd_find failed\n");
+ return;
+ }
+
/*
* Initialize and attach the disk structure.
*/
@@ -611,6 +639,10 @@ mcdioctl(dev, cmd, addr, flag, p)
case DIOCWLABEL:
return EBADF;
+/* case DIOCGDEFLABEL:
+ mcdgetdefaultlabel(dev, sc, (struct disklabel *)addr);
+ return 0;
+*/
case CDIOCPLAYTRACKS:
return mcd_playtracks(sc, (struct ioc_play_track *)addr);
case CDIOCPLAYMSF:
@@ -673,20 +705,15 @@ mcdioctl(dev, cmd, addr, flag, p)
#endif
}
-/*
- * This could have been taken from scsi/cd.c, but it is not clear
- * whether the scsi cd driver is linked in.
- */
void
-mcdgetdisklabel(dev, sc)
+mcdgetdefaultlabel(dev, sc, lp)
dev_t dev;
struct mcd_softc *sc;
+ struct disklabel *lp;
{
- struct disklabel *lp = sc->sc_dk.dk_label;
char *errstring;
bzero(lp, sizeof(struct disklabel));
- bzero(sc->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
lp->d_secsize = sc->blksize;
lp->d_ntracks = 1;
@@ -711,7 +738,7 @@ mcdgetdisklabel(dev, sc)
lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
lp->d_npartitions = RAW_PART + 1;
-
+
lp->d_magic = DISKMAGIC;
lp->d_magic2 = DISKMAGIC;
lp->d_checksum = dkcksum(lp);
@@ -727,6 +754,22 @@ mcdgetdisklabel(dev, sc)
}
}
+/*
+ * This could have been taken from scsi/cd.c, but it is not clear
+ * whether the scsi cd driver is linked in.
+ */
+void
+mcdgetdisklabel(dev, sc)
+ dev_t dev;
+ struct mcd_softc *sc;
+{
+ struct disklabel *lp = sc->sc_dk.dk_label;
+
+ bzero(sc->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
+
+ mcdgetdefaultlabel(dev, sc, lp);
+}
+
int
mcd_get_parms(sc)
struct mcd_softc *sc;
@@ -775,28 +818,27 @@ mcddump(dev, blkno, va, size)
return ENXIO;
}
+/*
+ * Find the board and fill in the softc.
+ */
int
-mcdprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
+mcd_find(iot, ioh, sc)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ struct mcd_softc *sc;
{
- struct mcd_softc *sc = match;
- struct isa_attach_args *ia = aux;
- int iobase = ia->ia_iobase;
int i;
struct mcd_mbox mbx;
- sc->iobase = iobase;
-
- if( !opti_cd_setup( OPTI_MITSUMI, iobase, ia->ia_irq, ia->ia_drq ) )
- /* printf("mcdprobe: could not setup OPTi chipset.\n") */;
+ sc->sc_iot = iot;
+ sc->sc_ioh = ioh;
/* Send a reset. */
- outb(iobase + MCD_RESET, 0);
+ bus_space_write_1(iot, ioh, MCD_RESET, 0);
delay(1000000);
/* Get any pending status and throw away. */
for (i = 10; i; i--)
- inb(iobase + MCD_STATUS);
+ bus_space_read_1(iot, ioh, MCD_STATUS);
delay(1000);
/* Send get status command. */
@@ -849,22 +891,64 @@ mcdprobe(parent, match, aux)
break;
}
- sc->attached = 1;
- ia->ia_iosize = 4;
- ia->ia_msize = 0;
return 1;
+
+}
+
+int
+mcdprobe(parent, match, aux)
+ struct device *parent;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ struct isa_attach_args *ia = aux;
+ struct mcd_softc sc;
+ bus_space_tag_t iot = ia->ia_iot;
+ bus_space_handle_t ioh;
+ int rv;
+
+ /* Disallow wildcarded i/o address. */
+ if (ia->ia_iobase == -1 /*ISACF_PORT_DEFAULT*/)
+ return (0);
+
+ /* Map i/o space */
+ if (bus_space_map(iot, ia->ia_iobase, MCD_NPORT, 0, &ioh))
+ return 0;
+
+ if (!opti_cd_setup(OPTI_MITSUMI, ia->ia_iobase, ia->ia_irq, ia->ia_drq))
+ /* printf("mcdprobe: could not setup OPTi chipset.\n") */;
+
+ sc.debug = 0;
+ sc.probe = 1;
+
+ rv = mcd_find(iot, ioh, &sc);
+
+ bus_space_unmap(iot, ioh, MCD_NPORT);
+
+ if (rv) {
+ ia->ia_iosize = MCD_NPORT;
+ ia->ia_msize = 0;
+ }
+
+ return (rv);
}
int
mcd_getreply(sc)
struct mcd_softc *sc;
{
- int iobase = sc->iobase;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
int i;
/* Wait until xfer port senses data ready. */
for (i = DELAY_GETREPLY; i; i--) {
- if ((inb(iobase + MCD_XFER) & MCD_XF_STATUSUNAVAIL) == 0)
+ if ((bus_space_read_1(iot, ioh, MCD_XFER) &
+ MCD_XF_STATUSUNAVAIL) == 0)
break;
delay(DELAY_GRANULARITY);
}
@@ -872,7 +956,7 @@ mcd_getreply(sc)
return -1;
/* Get the data. */
- return inb(iobase + MCD_STATUS);
+ return bus_space_read_1(iot, ioh, MCD_STATUS);
}
int
@@ -901,7 +985,7 @@ mcd_getresult(sc, res)
if ((x = mcd_getreply(sc)) < 0) {
if (sc->debug)
printf(" timeout\n");
- else if (sc->attached)
+ else if (sc->probe)
printf("%s: timeout in getresult\n", sc->sc_dev.dv_xname);
return EIO;
}
@@ -931,8 +1015,9 @@ mcd_getresult(sc, res)
#ifdef MCDDEBUG
delay(10);
- while ((inb(sc->iobase + MCD_XFER) & MCD_XF_STATUSUNAVAIL) == 0) {
- x = inb(sc->iobase + MCD_STATUS);
+ while ((bus_space_read_1(sc->sc_iot, sc->sc_ioh, MCD_XFER) &
+ MCD_XF_STATUSUNAVAIL) == 0) {
+ x = bus_space_read_1(sc->sc_iot, sc->sc_ioh, MCD_STATUS);
printf("%s: got extra byte %02x during getstatus\n",
sc->sc_dev.dv_xname, (u_int)x);
delay(10);
@@ -973,8 +1058,9 @@ mcd_send(sc, mbx, diskin)
struct mcd_mbox *mbx;
int diskin;
{
- int iobase = sc->iobase;
int retry, i, error;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
if (sc->debug) {
printf("%s: mcd_send: %d %02x", sc->sc_dev.dv_xname,
@@ -985,9 +1071,9 @@ mcd_send(sc, mbx, diskin)
}
for (retry = MCD_RETRIES; retry; retry--) {
- outb(iobase + MCD_COMMAND, mbx->cmd.opcode);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->cmd.opcode);
for (i = 0; i < mbx->cmd.length; i++)
- outb(iobase + MCD_COMMAND, mbx->cmd.data.raw.data[i]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->cmd.data.raw.data[i]);
if ((error = mcd_getresult(sc, &mbx->res)) == 0)
break;
if (error == EINVAL)
@@ -1054,8 +1140,9 @@ mcdintr(arg)
{
struct mcd_softc *sc = arg;
struct mcd_mbx *mbx = &sc->mbx;
- int iobase = sc->iobase;
struct buf *bp = mbx->bp;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
int i;
u_char x;
@@ -1071,8 +1158,8 @@ mcdintr(arg)
goto firstblock;
sc->lastmode = MCD_MD_UNKNOWN;
- outb(iobase + MCD_COMMAND, MCD_CMDSETMODE);
- outb(iobase + MCD_COMMAND, mbx->mode);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, MCD_CMDSETMODE);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->mode);
mbx->count = RDELAY_WAITMODE;
mbx->state = MCD_S_WAITMODE;
@@ -1080,14 +1167,14 @@ mcdintr(arg)
case MCD_S_WAITMODE:
untimeout(mcd_pseudointr, sc);
for (i = 20; i; i--) {
- x = inb(iobase + MCD_XFER);
+ x = bus_space_read_1(iot, ioh, MCD_XFER);
if ((x & MCD_XF_STATUSUNAVAIL) == 0)
break;
delay(50);
}
if (i == 0)
goto hold;
- sc->status = inb(iobase + MCD_STATUS);
+ sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
mcd_setflags(sc);
if ((sc->flags & MCDF_LOADED) == 0)
goto changed;
@@ -1104,13 +1191,13 @@ mcdintr(arg)
hsg2msf(mbx->blkno, msf);
/* Send the read command. */
- outb(iobase + MCD_COMMAND, sc->readcmd);
- outb(iobase + MCD_COMMAND, msf[0]);
- outb(iobase + MCD_COMMAND, msf[1]);
- outb(iobase + MCD_COMMAND, msf[2]);
- outb(iobase + MCD_COMMAND, 0);
- outb(iobase + MCD_COMMAND, 0);
- outb(iobase + MCD_COMMAND, mbx->nblk);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, sc->readcmd);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, msf[0]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, msf[1]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, msf[2]);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, 0);
+ bus_space_write_1(iot, ioh, MCD_COMMAND, mbx->nblk);
mbx->count = RDELAY_WAITREAD;
mbx->state = MCD_S_WAITREAD;
@@ -1120,7 +1207,7 @@ mcdintr(arg)
nextblock:
loop:
for (i = 20; i; i--) {
- x = inb(iobase + MCD_XFER);
+ x = bus_space_read_1(iot, ioh, MCD_XFER);
if ((x & MCD_XF_DATAUNAVAIL) == 0)
goto gotblock;
if ((x & MCD_XF_STATUSUNAVAIL) == 0)
@@ -1129,7 +1216,7 @@ mcdintr(arg)
}
if (i == 0)
goto hold;
- sc->status = inb(iobase + MCD_STATUS);
+ sc->status = bus_space_read_1(iot, ioh, MCD_STATUS);
mcd_setflags(sc);
if ((sc->flags & MCDF_LOADED) == 0)
goto changed;
@@ -1144,9 +1231,10 @@ mcdintr(arg)
RDELAY_WAITREAD - mbx->count, 0, 0, 0);
/* Data is ready. */
- outb(iobase + MCD_CTL2, 0x04); /* XXX */
- insb(iobase + MCD_RDATA, bp->b_data + mbx->skip, mbx->sz);
- outb(iobase + MCD_CTL2, 0x0c); /* XXX */
+ bus_space_write_1(iot, ioh, MCD_CTL2, 0x04); /* XXX */
+ bus_space_read_multi_1(iot, ioh, MCD_RDATA,
+ bp->b_data + mbx->skip, mbx->sz);
+ bus_space_write_1(iot, ioh, MCD_CTL2, 0x0c); /* XXX */
mbx->blkno += 1;
mbx->skip += mbx->sz;
if (--mbx->nblk > 0)
@@ -1196,7 +1284,7 @@ changed:
#ifdef notyet
printf("%s: unit timeout; resetting\n", sc->sc_dev.dv_xname);
- outb(mbx->iobase + MCD_RESET, MCD_CMDRESET);
+ bus_space_write_1(iot, ioh, MCD_RESET, MCD_CMDRESET);
delay(300000);
(void) mcd_getstat(sc, 1);
(void) mcd_getstat(sc, 1);
@@ -1215,7 +1303,7 @@ mcd_soft_reset(sc)
sc->lastmode = MCD_MD_UNKNOWN;
sc->lastupc = MCD_UPC_UNKNOWN;
sc->audio_status = CD_AS_AUDIO_INVALID;
- outb(sc->iobase + MCD_CTL2, 0x0c); /* XXX */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, MCD_CTL2, 0x0c); /* XXX */
}
int
diff --git a/sys/dev/isa/mcdreg.h b/sys/dev/isa/mcdreg.h
index 92677c4f307..198a6c22a53 100644
--- a/sys/dev/isa/mcdreg.h
+++ b/sys/dev/isa/mcdreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mcdreg.h,v 1.2 1997/11/07 08:07:05 niklas Exp $ */
-/* $NetBSD: mcdreg.h,v 1.7 1995/07/10 01:27:27 cgd Exp $ */
+/* $OpenBSD: mcdreg.h,v 1.3 1998/04/26 21:02:50 provos Exp $ */
+/* $NetBSD: mcdreg.h,v 1.8 1997/04/04 18:59:37 christos Exp $ */
/*
* Copyright 1993 by Holger Veit (data part)
@@ -60,6 +60,7 @@ typedef unsigned char bcd_t;
#define MCD_XFER 1
#define MCD_CTL2 2 /* XXX Is this right? */
#define MCD_CONFIG 3
+#define MCD_NPORT 4
#define MCD_MASK_DMA 0x07 /* bits 2-0 = DMA channel */
#define MCD_MASK_IRQ 0x70 /* bits 6-4 = INT number */
diff --git a/sys/dev/isa/pas.c b/sys/dev/isa/pas.c
index 41236ebe549..772bcf8d431 100644
--- a/sys/dev/isa/pas.c
+++ b/sys/dev/isa/pas.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pas.c,v 1.14 1997/07/10 23:06:36 provos Exp $ */
-/* $NetBSD: pas.c,v 1.17 1996/05/12 23:53:18 mycroft Exp $ */
+/* $OpenBSD: pas.c,v 1.15 1998/04/26 21:02:51 provos Exp $ */
+/* $NetBSD: pas.c,v 1.37 1998/01/12 09:43:43 thorpej Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -35,6 +35,13 @@
*
*/
/*
+ * jfw 7/13/97 - The soundblaster code requires the generic bus-space
+ * structures to be set up properly. Rather than go to the effort of making
+ * code for a dead line fully generic, properly set up the SB structures and
+ * leave the rest x86/ISA/default-configuration specific. If you have a
+ * REAL computer, go buy a REAL sound card.
+ */
+/*
* Todo:
* - look at other PAS drivers (for PAS native suport)
* - use common sb.c once emulation is setup
@@ -50,11 +57,11 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
#include <dev/audio_if.h>
-#include <dev/mulaw.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -95,7 +102,6 @@ struct pas_softc {
};
-int pasopen __P((dev_t, int));
int pas_getdev __P((void *, struct audio_device *));
void pasconf __P((int, int, int, int));
@@ -105,41 +111,30 @@ void pasconf __P((int, int, int, int));
*/
struct audio_hw_if pas_hw_if = {
- pasopen,
+ sbdsp_open,
sbdsp_close,
- NULL,
- sbdsp_set_in_sr,
- sbdsp_get_in_sr,
- sbdsp_set_out_sr,
- sbdsp_get_out_sr,
+ 0,
sbdsp_query_encoding,
- sbdsp_set_format,
- sbdsp_get_encoding,
- sbdsp_get_precision,
- sbdsp_set_channels,
- sbdsp_get_channels,
+ sbdsp_set_params,
sbdsp_round_blocksize,
- sbdsp_set_out_port,
- sbdsp_get_out_port,
- sbdsp_set_in_port,
- sbdsp_get_in_port,
- sbdsp_commit_settings,
- mulaw_expand,
- mulaw_compress,
+ 0,
+ sbdsp_dma_init_output,
+ sbdsp_dma_init_input,
sbdsp_dma_output,
sbdsp_dma_input,
sbdsp_haltdma,
sbdsp_haltdma,
- sbdsp_contdma,
- sbdsp_contdma,
sbdsp_speaker_ctl,
pas_getdev,
- sbdsp_setfd,
+ 0,
sbdsp_mixer_set_port,
sbdsp_mixer_get_port,
sbdsp_mixer_query_devinfo,
- 0, /* not full-duplex */
- 0
+ sb_malloc,
+ sb_free,
+ sb_round,
+ sb_mappage,
+ sbdsp_get_props,
};
/* The Address Translation code is used to convert I/O register addresses to
@@ -266,11 +261,17 @@ pasprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- register struct pas_softc *sc = match;
- register struct isa_attach_args *ia = aux;
- register int iobase;
+ struct pas_softc *sc = match;
+ struct isa_attach_args *ia = aux;
+ int iobase;
u_char id, t;
+ /* ensure we can set this up as a sound blaster */
+ if (!SB_BASE_VALID(ia->ia_iobase)) {
+ printf("pas: configured SB iobase 0x%x invalid\n", ia->ia_iobase);
+ return 0;
+ }
+
/*
* WARNING: Setting an option like W:1 or so that disables
* warm boot reset of the card will screw up this detect code
@@ -342,11 +343,24 @@ pasprobe(parent, match, aux)
return (0);
}
- /* Now a SoundBlaster */
+ /* Now a SoundBlaster, so set up proper bus-space hooks
+ * appropriately
+ */
+
sc->sc_sbdsp.sc_iobase = ia->ia_iobase;
+ sc->sc_sbdsp.sc_iot = ia->ia_iot;
+
+ /* Map i/o space [we map 24 ports which is the max of the sb and pro */
+ if (bus_space_map(sc->sc_sbdsp.sc_iot, ia->ia_iobase, SBP_NPORT, 0,
+ &sc->sc_sbdsp.sc_ioh)) {
+ printf("pas: can't map i/o space 0x%x/%d in probe\n",
+ ia->ia_iobase, SBP_NPORT);
+ return 0;
+ }
+
if (sbdsp_reset(&sc->sc_sbdsp) < 0) {
DPRINTF(("pas: couldn't reset card\n"));
- return 0;
+ goto unmap;
}
/*
@@ -354,7 +368,7 @@ pasprobe(parent, match, aux)
*/
if (!SB_DRQ_VALID(ia->ia_drq)) {
printf("pas: configured dma chan %d invalid\n", ia->ia_drq);
- return 0;
+ goto unmap;
}
#ifdef NEWCONFIG
/*
@@ -365,13 +379,13 @@ pasprobe(parent, match, aux)
sbdsp_reset(&sc->sc_sbdsp);
if (!SB_IRQ_VALID(ia->ia_irq)) {
printf("pas: couldn't auto-detect interrupt");
- return 0;
+ goto unmap;
}
} else
#endif
if (!SB_IRQ_VALID(ia->ia_irq)) {
printf("pas: configured irq chan %d invalid\n", ia->ia_irq);
- return 0;
+ goto unmap;
}
sc->sc_sbdsp.sc_irq = ia->ia_irq;
@@ -380,11 +394,15 @@ pasprobe(parent, match, aux)
if (sbdsp_probe(&sc->sc_sbdsp) == 0) {
DPRINTF(("pas: sbdsp probe failed\n"));
- return 0;
+ goto unmap;
}
ia->ia_iosize = SB_NPORT;
return 1;
+
+ unmap:
+ bus_space_unmap(sc->sc_sbdsp.sc_iot, sc->sc_sbdsp.sc_ioh, SBP_NPORT);
+ return 0;
}
#ifdef NEWCONFIG
@@ -424,10 +442,9 @@ pasattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- register struct pas_softc *sc = (struct pas_softc *)self;
+ struct pas_softc *sc = (struct pas_softc *)self;
struct isa_attach_args *ia = (struct isa_attach_args *)aux;
- register int iobase = ia->ia_iobase;
- int err;
+ int iobase = ia->ia_iobase;
sc->sc_sbdsp.sc_iobase = iobase;
sc->sc_sbdsp.sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
@@ -440,26 +457,7 @@ pasattach(parent, self, aux)
sprintf(pas_device.name, "pas,%s", pasnames[sc->model]);
sprintf(pas_device.version, "%d", sc->rev);
- if ((err = audio_hardware_attach(&pas_hw_if, &sc->sc_sbdsp)) != 0)
- printf("pas: could not attach to audio pseudo-device driver (%d)\n", err);
-}
-
-int
-pasopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct pas_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= pas_cd.cd_ndevs)
- return ENODEV;
-
- sc = pas_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
- return sbdsp_open(&sc->sc_sbdsp, dev, flags);
+ audio_attach_mi(&pas_hw_if, 0, &sc->sc_sbdsp, &sc->sc_sbdsp.sc_dev);
}
int
diff --git a/sys/dev/isa/pnpdevs b/sys/dev/isa/pnpdevs
index be03594869d..f3e003a5cb2 100644
--- a/sys/dev/isa/pnpdevs
+++ b/sys/dev/isa/pnpdevs
@@ -1,4 +1,4 @@
-# $OpenBSD: pnpdevs,v 1.10 1998/03/16 05:21:55 dgregor Exp $
+# $OpenBSD: pnpdevs,v 1.11 1998/04/26 21:02:53 provos Exp $
#
# NOTE: All `com' devices also need pccom identifiers.
@@ -368,4 +368,5 @@ sb CTL0041 #SB16 PnP (CT4131)
sb CTL0042 #SB AWE64 Value
sb CTL0044 #SB AWE64 Gold
sb CTL0045 #SB AWE64 Value
+sb YMH0021 #
sb ESS1868 #
diff --git a/sys/dev/isa/pnpdevs.h b/sys/dev/isa/pnpdevs.h
index 68a5edaf949..75bb1ffe38d 100644
--- a/sys/dev/isa/pnpdevs.h
+++ b/sys/dev/isa/pnpdevs.h
@@ -58,6 +58,7 @@ struct isapnp_knowndev isapnp_knowndevs[] = {
{ "CTL0042", "sb" },
{ "CTL0044", "sb" },
{ "CTL0045", "sb" },
+ { "YMH0021", "sb" },
{ "ESS1868", "sb" },
{ NULL, NULL, }
};
diff --git a/sys/dev/isa/pss.c b/sys/dev/isa/pss.c
index 636b208cc18..c2bf800b640 100644
--- a/sys/dev/isa/pss.c
+++ b/sys/dev/isa/pss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: pss.c,v 1.12 1997/07/12 01:42:08 millert Exp $ */
-/* $NetBSD: pss.c,v 1.15 1996/05/12 23:53:23 mycroft Exp $ */
+/* $OpenBSD: pss.c,v 1.13 1998/04/26 21:02:55 provos Exp $ */
+/* $NetBSD: pss.c,v 1.38 1998/01/12 09:43:44 thorpej Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -62,6 +62,7 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
@@ -155,8 +156,7 @@ struct pcd_softc {
#endif
#ifdef AUDIO_DEBUG
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (pssdebug) Dprintf x
+#define DPRINTF(x) if (pssdebug) printf x
int pssdebug = 0;
#else
#define DPRINTF(x)
@@ -176,8 +176,6 @@ int pcdprobe __P((struct device *, void *, void *));
void pcdattach __P((struct device *, struct device *, void *));
#endif
-int spopen __P((dev_t, int));
-
int pssintr __P((void *));
#ifdef notyet
int mpuintr __P((void *));
@@ -186,12 +184,7 @@ int mpuintr __P((void *));
int pss_speaker_ctl __P((void *, int));
int pss_getdev __P((void *, struct audio_device *));
-int pss_setfd __P((void *, int));
-int pss_set_out_port __P((void *, int));
-int pss_get_out_port __P((void *));
-int pss_set_in_port __P((void *, int));
-int pss_get_in_port __P((void *));
int pss_mixer_set_port __P((void *, mixer_ctrl_t *));
int pss_mixer_get_port __P((void *, mixer_ctrl_t *));
int pss_query_devinfo __P((void *, mixer_devinfo_t *));
@@ -232,41 +225,30 @@ void wss_dump_regs __P((struct ad1848_softc *));
*/
struct audio_hw_if pss_audio_if = {
- spopen,
+ ad1848_open,
ad1848_close,
NULL,
- ad1848_set_in_sr,
- ad1848_get_in_sr,
- ad1848_set_out_sr,
- ad1848_get_out_sr,
ad1848_query_encoding,
- ad1848_set_format,
- ad1848_get_encoding,
- ad1848_get_precision,
- ad1848_set_channels,
- ad1848_get_channels,
+ ad1848_set_params,
ad1848_round_blocksize,
- pss_set_out_port,
- pss_get_out_port,
- pss_set_in_port,
- pss_get_in_port,
ad1848_commit_settings,
- NULL,
- NULL,
+ ad1848_dma_init_output,
+ ad1848_dma_init_input,
ad1848_dma_output,
ad1848_dma_input,
ad1848_halt_out_dma,
ad1848_halt_in_dma,
- ad1848_cont_out_dma,
- ad1848_cont_in_dma,
pss_speaker_ctl,
pss_getdev,
- pss_setfd,
+ NULL,
pss_mixer_set_port,
pss_mixer_get_port,
pss_query_devinfo,
- 0, /* not full-duplex */
- 0
+ ad1848_malloc,
+ ad1848_free,
+ ad1848_round,
+ ad1848_mappage,
+ ad1848_get_props,
};
@@ -845,9 +827,11 @@ spprobe(parent, match, aux)
struct ad1848_softc *sc = match;
struct pss_softc *pc = (void *) parent;
struct cfdata *cf = (void *)sc->sc_dev.dv_cfdata;
+ struct isa_attach_args *ia = aux;
u_char bits;
int i;
+ sc->sc_iot = ia->ia_iot;
sc->sc_iobase = cf->cf_iobase + WSS_CODEC;
/* Set WSS io address */
@@ -1043,7 +1027,6 @@ pssattach(parent, self, aux)
int iobase = ia->ia_iobase;
u_char vers;
struct ad1848_volume vol = {150, 150};
- int err;
sc->sc_iobase = iobase;
sc->sc_drq = ia->ia_drq;
@@ -1068,8 +1051,7 @@ pssattach(parent, self, aux)
(void)pss_set_treble(sc, AUDIO_MAX_GAIN/2);
(void)pss_set_bass(sc, AUDIO_MAX_GAIN/2);
- if ((err = audio_hardware_attach(&pss_audio_if, sc->ad1848_sc)) != 0)
- printf("pss: could not attach to audio pseudo-device driver (%d)\n", err);
+ audio_attach_mi(&pss_audio_if, 0, sc->ad1848_sc, &sc->ad1848_sc->sc_dev);
}
void
@@ -1092,10 +1074,7 @@ spattach(parent, self, aux)
sc->sc_ih = isa_intr_establish(ic, cf->cf_irq, IST_EDGE, IPL_AUDIO,
ad1848_intr, sc, sc->sc_dev.dv_xname);
- /* XXX might use pssprint func ?? */
- printf(" port 0x%x-0x%x irq %d drq %d",
- sc->sc_iobase, sc->sc_iobase+AD1848_NPORT,
- cf->cf_irq, cf->cf_drq);
+ sc->sc_isa = parent->dv_parent;
ad1848_attach(sc);
@@ -1190,26 +1169,8 @@ pss_from_vol(cp, vol)
}
int
-spopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct ad1848_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= sp_cd.cd_ndevs)
- return ENODEV;
-
- sc = sp_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
- return ad1848_open(sc, dev, flags);
-}
-
-int
pss_set_master_gain(sc, gp)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
struct ad1848_volume *gp;
{
DPRINTF(("pss_set_master_gain: %d:%d\n", gp->left, gp->right));
@@ -1236,7 +1197,7 @@ pss_set_master_gain(sc, gp)
int
pss_set_master_mode(sc, mode)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
int mode;
{
short phillips_mode;
@@ -1266,7 +1227,7 @@ pss_set_master_mode(sc, mode)
int
pss_set_treble(sc, treb)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_int treb;
{
DPRINTF(("pss_set_treble: %d\n", treb));
@@ -1287,7 +1248,7 @@ pss_set_treble(sc, treb)
int
pss_set_bass(sc, bass)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_int bass;
{
DPRINTF(("pss_set_bass: %d\n", bass));
@@ -1308,7 +1269,7 @@ pss_set_bass(sc, bass)
int
pss_get_master_gain(sc, gp)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
struct ad1848_volume *gp;
{
*gp = sc->master_volume;
@@ -1317,7 +1278,7 @@ pss_get_master_gain(sc, gp)
int
pss_get_master_mode(sc, mode)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_int *mode;
{
*mode = sc->master_mode;
@@ -1326,7 +1287,7 @@ pss_get_master_mode(sc, mode)
int
pss_get_treble(sc, tp)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_char *tp;
{
*tp = sc->monitor_treble;
@@ -1335,7 +1296,7 @@ pss_get_treble(sc, tp)
int
pss_get_bass(sc, bp)
- register struct pss_softc *sc;
+ struct pss_softc *sc;
u_char *bp;
{
*bp = sc->monitor_bass;
@@ -1354,12 +1315,12 @@ int
pssintr(arg)
void *arg;
{
- register struct pss_softc *sc = arg;
+ struct pss_softc *sc = arg;
u_short sr;
sr = inw(sc->sc_iobase+PSS_STATUS);
- DPRINTF(("pssintr: sc=%x st=%x\n", sc, sr));
+ DPRINTF(("pssintr: sc=%p st=%x\n", sc, sr));
/* Acknowledge intr */
outw(sc->sc_iobase+PSS_IRQ_ACK, 0);
@@ -1378,7 +1339,7 @@ int
mpuintr(arg)
void *arg;
{
- register struct mpu_softc *sc = arg;
+ struct mpu_softc *sc = arg;
u_char sr;
sr = inb(sc->sc_iobase+MIDI_STATUS_REG);
@@ -1395,109 +1356,19 @@ pss_getdev(addr, retp)
void *addr;
struct audio_device *retp;
{
- DPRINTF(("pss_getdev: retp=0x%x\n", retp));
+ DPRINTF(("pss_getdev: retp=%p\n", retp));
*retp = pss_device;
return 0;
}
int
-pss_setfd(addr, flag)
- void *addr;
- int flag;
-{
- /* Can't do full-duplex */
- return(ENOTTY);
-}
-
-int
-pss_set_out_port(addr, port)
- void *addr;
- int port;
-{
- register struct ad1848_softc *ac = addr;
- register struct pss_softc *sc = ac->parent;
-
- DPRINTF(("pss_set_out_port: %d\n", port));
-
- if (port != PSS_MASTER_VOL)
- return(EINVAL);
-
- sc->out_port = port;
-
- return(0);
-}
-
-int
-pss_get_out_port(addr)
- void *addr;
-{
- register struct ad1848_softc *ac = addr;
- register struct pss_softc *sc = ac->parent;
-
- DPRINTF(("pss_get_out_port: %d\n", sc->out_port));
-
- return(sc->out_port);
-}
-
-int
-pss_set_in_port(addr, port)
- void *addr;
- int port;
-{
- register struct ad1848_softc *ac = addr;
-
- DPRINTF(("pss_set_in_port: %d\n", port));
-
- switch(port) {
- case PSS_MIC_IN_LVL:
- port = MIC_IN_PORT;
- break;
- case PSS_LINE_IN_LVL:
- port = LINE_IN_PORT;
- break;
- case PSS_DAC_LVL:
- port = DAC_IN_PORT;
- break;
- default:
- return(EINVAL);
- /*NOTREACHED*/
- }
-
- return(ad1848_set_rec_port(ac, port));
-}
-
-int
-pss_get_in_port(addr)
- void *addr;
-{
- register struct ad1848_softc *ac = addr;
- int port = PSS_MIC_IN_LVL;
-
- switch(ad1848_get_rec_port(ac)) {
- case MIC_IN_PORT:
- port = PSS_MIC_IN_LVL;
- break;
- case LINE_IN_PORT:
- port = PSS_LINE_IN_LVL;
- break;
- case DAC_IN_PORT:
- port = PSS_DAC_LVL;
- break;
- }
-
- DPRINTF(("pss_get_in_port: %d\n", port));
-
- return(port);
-}
-
-int
pss_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct pss_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct pss_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -1606,8 +1477,8 @@ pss_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct pss_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct pss_softc *sc = ac->parent;
struct ad1848_volume vol;
u_char eq;
int error = EINVAL;
@@ -1723,7 +1594,7 @@ pss_mixer_get_port(addr, cp)
int
pss_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
DPRINTF(("pss_query_devinfo: index=%d\n", dip->index));
@@ -1782,7 +1653,7 @@ pss_query_devinfo(addr, dip)
dip->mixer_class = PSS_OUTPUT_CLASS;
dip->prev = AUDIO_MIXER_LAST;
dip->next = PSS_OUTPUT_MODE;
- strcpy(dip->label.name, AudioNvolume);
+ strcpy(dip->label.name, AudioNmaster);
dip->un.v.num_channels = 2;
strcpy(dip->un.v.units.name, AudioNvolume);
break;
@@ -1809,28 +1680,28 @@ pss_query_devinfo(addr, dip)
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = PSS_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNspeaker);
+ strcpy(dip->label.name, AudioCoutputs);
break;
case PSS_INPUT_CLASS: /* input class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = PSS_INPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ strcpy(dip->label.name, AudioCinputs);
break;
case PSS_MONITOR_CLASS: /* monitor class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = PSS_MONITOR_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmonitor);
+ strcpy(dip->label.name, AudioCmonitor);
break;
case PSS_RECORD_CLASS: /* record source class */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = PSS_RECORD_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNrecord);
+ strcpy(dip->label.name, AudioCrecord);
break;
case PSS_MIC_IN_MUTE:
diff --git a/sys/dev/isa/sb.c b/sys/dev/isa/sb.c
index 5bcc4010db0..06274862b28 100644
--- a/sys/dev/isa/sb.c
+++ b/sys/dev/isa/sb.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sb.c,v 1.13 1997/08/07 05:27:32 deraadt Exp $ */
-/* $NetBSD: sb.c,v 1.36 1996/05/12 23:53:33 mycroft Exp $ */
+/* $OpenBSD: sb.c,v 1.14 1998/04/26 21:02:56 provos Exp $ */
+/* $NetBSD: sb.c,v 1.57 1998/01/12 09:43:46 thorpej Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -45,11 +45,11 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
#include <dev/audio_if.h>
-#include <dev/mulaw.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
@@ -58,14 +58,6 @@
#include <dev/isa/sbvar.h>
#include <dev/isa/sbdspvar.h>
-struct sb_softc {
- struct device sc_dev; /* base device */
- struct isadev sc_id; /* ISA device */
- void *sc_ih; /* interrupt vectoring */
-
- struct sbdsp_softc sc_sbdsp;
-};
-
struct cfdriver sb_cd = {
NULL, "sb", DV_DULL
};
@@ -76,7 +68,6 @@ struct audio_device sb_device = {
"sb"
};
-int sbopen __P((dev_t, int));
int sb_getdev __P((void *, struct audio_device *));
/*
@@ -84,41 +75,30 @@ int sb_getdev __P((void *, struct audio_device *));
*/
struct audio_hw_if sb_hw_if = {
- sbopen,
+ sbdsp_open,
sbdsp_close,
- NULL,
- sbdsp_set_in_sr,
- sbdsp_get_in_sr,
- sbdsp_set_out_sr,
- sbdsp_get_out_sr,
+ 0,
sbdsp_query_encoding,
- sbdsp_set_format,
- sbdsp_get_encoding,
- sbdsp_get_precision,
- sbdsp_set_channels,
- sbdsp_get_channels,
+ sbdsp_set_params,
sbdsp_round_blocksize,
- sbdsp_set_out_port,
- sbdsp_get_out_port,
- sbdsp_set_in_port,
- sbdsp_get_in_port,
- sbdsp_commit_settings,
- mulaw_expand,
- mulaw_compress,
+ 0,
+ sbdsp_dma_init_output,
+ sbdsp_dma_init_input,
sbdsp_dma_output,
sbdsp_dma_input,
sbdsp_haltdma,
sbdsp_haltdma,
- sbdsp_contdma,
- sbdsp_contdma,
sbdsp_speaker_ctl,
sb_getdev,
- sbdsp_setfd,
+ 0,
sbdsp_mixer_set_port,
sbdsp_mixer_get_port,
sbdsp_mixer_query_devinfo,
- 0, /* not full-duplex */
- 0
+ sb_malloc,
+ sb_free,
+ sb_round,
+ sb_mappage,
+ sbdsp_get_props,
};
/*
@@ -157,7 +137,15 @@ sbmatch(sc)
return 0;
}
}
-
+
+ if (0 <= sc->sc_drq16 && sc->sc_drq16 <= 3)
+ /*
+ * XXX Some ViBRA16 cards seem to have two 8 bit DMA
+ * channels. I've no clue how to use them, so ignore
+ * one of them for now. -- augustss@netbsd.org
+ */
+ sc->sc_drq16 = -1;
+
if (ISSB16CLASS(sc)) {
if (sc->sc_drq16 == -1)
sc->sc_drq16 = sc->sc_drq8;
@@ -207,14 +195,21 @@ sbmatch(sc)
}
if (ISSB16CLASS(sc)) {
+ int w, r;
#if 0
printf("%s: old drq conf %02x\n", sc->sc_dev.dv_xname,
sbdsp_mix_read(sc, SBP_SET_DRQ));
printf("%s: try drq conf %02x\n", sc->sc_dev.dv_xname,
drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8]);
#endif
- sbdsp_mix_write(sc, SBP_SET_DRQ,
- drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8]);
+ w = drq_conf[sc->sc_drq16] | drq_conf[sc->sc_drq8];
+ sbdsp_mix_write(sc, SBP_SET_DRQ, w);
+ r = sbdsp_mix_read(sc, SBP_SET_DRQ) & 0xeb;
+ if (r != w) {
+ printf("%s: setting drq mask %02x failed, got %02x\n",
+ sc->sc_dev.dv_xname, w, r);
+ return 0;
+ }
#if 0
printf("%s: new drq conf %02x\n", sc->sc_dev.dv_xname,
sbdsp_mix_read(sc, SBP_SET_DRQ));
@@ -226,8 +221,14 @@ sbmatch(sc)
printf("%s: try irq conf %02x\n", sc->sc_dev.dv_xname,
irq_conf[sc->sc_irq]);
#endif
- sbdsp_mix_write(sc, SBP_SET_IRQ,
- irq_conf[sc->sc_irq]);
+ w = irq_conf[sc->sc_irq];
+ sbdsp_mix_write(sc, SBP_SET_IRQ, w);
+ r = sbdsp_mix_read(sc, SBP_SET_IRQ) & 0x0f;
+ if (r != w) {
+ printf("%s: setting irq mask %02x failed, got %02x\n",
+ sc->sc_dev.dv_xname, w, r);
+ return 0;
+ }
#if 0
printf("%s: new irq conf %02x\n", sc->sc_dev.dv_xname,
sbdsp_mix_read(sc, SBP_SET_IRQ));
@@ -242,16 +243,12 @@ void
sbattach(sc)
struct sbdsp_softc *sc;
{
- int error;
-
sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->sc_irq, IST_EDGE,
IPL_AUDIO, sbdsp_intr, sc, sc->sc_dev.dv_xname);
sbdsp_attach(sc);
- if ((error = audio_hardware_attach(&sb_hw_if, sc)) != 0)
- printf("%s: could not attach to audio device driver (%d)\n",
- sc->sc_dev.dv_xname, error);
+ audio_attach_mi(&sb_hw_if, 0, sc, &sc->sc_dev);
}
#ifdef NEWCONFIG
@@ -287,38 +284,26 @@ sbforceintr(aux)
*/
int
-sbopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct sbdsp_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= sb_cd.cd_ndevs)
- return ENODEV;
-
- sc = sb_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
- return sbdsp_open(sc, dev, flags);
-}
-
-int
sb_getdev(addr, retp)
void *addr;
struct audio_device *retp;
{
struct sbdsp_softc *sc = addr;
+ static char *names[] = SB_NAMES;
+ char *config;
- if (sc->sc_model & MODEL_JAZZ16)
+ if (sc->sc_model == SB_JAZZ)
strncpy(retp->name, "MV Jazz16", sizeof(retp->name));
else
strncpy(retp->name, "SoundBlaster", sizeof(retp->name));
sprintf(retp->version, "%d.%02d",
- SBVER_MAJOR(sc->sc_model),
- SBVER_MINOR(sc->sc_model));
- strncpy(retp->config, "sb", sizeof(retp->config));
+ SBVER_MAJOR(sc->sc_version),
+ SBVER_MINOR(sc->sc_version));
+ if (0 <= sc->sc_model && sc->sc_model < sizeof names / sizeof names[0])
+ config = names[sc->sc_model];
+ else
+ config = "??";
+ strncpy(retp->config, config, sizeof(retp->config));
return 0;
}
diff --git a/sys/dev/isa/sb_isa.c b/sys/dev/isa/sb_isa.c
index da747efd05f..9cba8d91df8 100644
--- a/sys/dev/isa/sb_isa.c
+++ b/sys/dev/isa/sb_isa.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sb_isa.c,v 1.1 1997/07/10 23:06:37 provos Exp $ */
-/* $NetBSD: sb_isa.c,v 1.3 1997/03/20 11:03:11 mycroft Exp $ */
+/* $OpenBSD: sb_isa.c,v 1.2 1998/04/26 21:02:57 provos Exp $ */
+/* $NetBSD: sb_isa.c,v 1.15 1997/11/30 15:32:25 drochner Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -43,6 +43,8 @@
#include <sys/device.h>
#include <sys/proc.h>
+#include <machine/bus.h>
+
#include <sys/audioio.h>
#include <dev/audio_if.h>
#include <dev/mulaw.h>
@@ -55,7 +57,14 @@
#include <dev/isa/sbdspvar.h>
+static int sbfind __P((struct device *, struct sbdsp_softc *, struct isa_attach_args *));
+
+#define __BROKEN_INDIRECT_CONFIG /* XXX */
+#ifdef __BROKEN_INDIRECT_CONFIG
int sb_isa_match __P((struct device *, void *, void *));
+#else
+int sb_isa_match __P((struct device *, struct cfdata *, void *));
+#endif
void sb_isa_attach __P((struct device *, struct device *, void *));
struct cfattach sb_isa_ca = {
@@ -72,13 +81,32 @@ struct cfattach sb_isa_ca = {
int
sb_isa_match(parent, match, aux)
struct device *parent;
- void *match, *aux;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ struct sbdsp_softc probesc, *sc = &probesc;
+
+ bzero(sc, sizeof *sc);
+#ifdef __BROKEN_INDIRECT_CONFIG
+ sc->sc_dev.dv_cfdata = ((struct device *)match)->dv_cfdata;
+#else
+ sc->sc_dev.dv_cfdata = match;
+#endif
+ strcpy(sc->sc_dev.dv_xname, "sb");
+ return sbfind(parent, sc, aux);
+}
+
+static int
+sbfind(parent, sc, ia)
+ struct device *parent;
+ struct sbdsp_softc *sc;
+ struct isa_attach_args *ia;
{
- /*
- * Indirect brokedness!
- */
- register struct sbdsp_softc *sc = match;
- register struct isa_attach_args *ia = aux;
+ int rc = 0;
if (!SB_BASE_VALID(ia->ia_iobase)) {
printf("sb: configured iobase 0x%x invalid\n", ia->ia_iobase);
@@ -87,7 +115,7 @@ sb_isa_match(parent, match, aux)
sc->sc_iot = ia->ia_iot;
- /* Map i/o space [we map 24 ports which is the max of the sb and pro */
+ /* Map i/o space [we map 24 ports which is the max of the sb and pro */
if (bus_space_map(sc->sc_iot, ia->ia_iobase, SBP_NPORT, 0,
&sc->sc_ioh)) {
printf("sb: can't map i/o space 0x%x/%d in probe\n",
@@ -95,28 +123,34 @@ sb_isa_match(parent, match, aux)
return 0;
}
- /*
- * Indirect brokedness!
- */
sc->sc_iobase = ia->ia_iobase;
sc->sc_irq = ia->ia_irq;
sc->sc_drq8 = ia->ia_drq;
- sc->sc_drq16 = -1; /* XXX */
+ sc->sc_drq16 = ia->ia_drq2;
sc->sc_ic = ia->ia_ic;
- if (!sbmatch(sc)) {
- bus_space_unmap(sc->sc_iot, sc->sc_ioh, SBP_NPORT);
- return 0;
- }
+ if (!sbmatch(sc))
+ goto bad;
+
+ if ((sc->sc_drq8 != -1 && !isa_drq_isfree(parent, sc->sc_drq8)) ||
+ (sc->sc_drq16 != -1 && !isa_drq_isfree(parent, sc->sc_drq16)))
+ goto bad;
if (ISSBPROCLASS(sc))
ia->ia_iosize = SBP_NPORT;
else
ia->ia_iosize = SB_NPORT;
+ if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
+ ia->ia_drq2 = -1;
+
ia->ia_irq = sc->sc_irq;
- return 1;
+ rc = 1;
+
+bad:
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, SBP_NPORT);
+ return rc;
}
@@ -129,5 +163,15 @@ sb_isa_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- sbattach((struct sbdsp_softc *) self);
+ struct sbdsp_softc *sc = (struct sbdsp_softc *)self;
+ struct isa_attach_args *ia = aux;
+
+ if (!sbfind(parent, sc, ia) ||
+ bus_space_map(sc->sc_iot, ia->ia_iobase, ia->ia_iosize,
+ 0, &sc->sc_ioh)) {
+ printf("%s: sbfind failed\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ sc->sc_isa = parent;
+ sbattach(sc);
}
diff --git a/sys/dev/isa/sb_isapnp.c b/sys/dev/isa/sb_isapnp.c
index 13f3038c9af..47115e98e3d 100644
--- a/sys/dev/isa/sb_isapnp.c
+++ b/sys/dev/isa/sb_isapnp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sb_isapnp.c,v 1.2 1997/12/26 09:35:38 deraadt Exp $ */
+/* $OpenBSD: sb_isapnp.c,v 1.3 1998/04/26 21:02:58 provos Exp $ */
/* $NetBSD: sb_isa.c,v 1.3 1997/03/20 11:03:11 mycroft Exp $ */
/*
@@ -93,9 +93,24 @@ sb_isapnp_attach(parent, self, aux)
sc->sc_ioh = ia->ipa_io[0].h;
sc->sc_iobase = ia->ipa_io[0].base;
sc->sc_irq = ia->ipa_irq[0].num;
- sc->sc_drq8 = ia->ipa_drq[0].num;
- sc->sc_drq16 = ia->ipa_drq[1].num;
sc->sc_ic = ia->ia_ic;
+ sc->sc_drq8 = ia->ipa_drq[0].num;
+
+ if (ia->ipa_ndrq > 1 && ia->ipa_drq[0].num != ia->ipa_drq[1].num) {
+ /* Some cards have the 16 bit drq first */
+ if (sc->sc_drq8 >= 4) {
+ sc->sc_drq16 = sc->sc_drq8;
+ sc->sc_drq8 = ia->ipa_drq[1].num;
+ } else
+ sc->sc_drq16 = ia->ipa_drq[1].num;
+ } else
+ sc->sc_drq16 = DRQUNK;
+
+ /*
+ * isapnp is a child if isa, and we needs isa for the dma
+ * routines
+ */
+ sc->sc_isa = parent->dv_parent;
if (!sbmatch(sc)) {
printf("%s: sbmatch failed\n", sc->sc_dev.dv_xname);
diff --git a/sys/dev/isa/sbdsp.c b/sys/dev/isa/sbdsp.c
index ca7ebb359d2..89cda5647d9 100644
--- a/sys/dev/isa/sbdsp.c
+++ b/sys/dev/isa/sbdsp.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sbdsp.c,v 1.11 1998/01/18 18:58:39 niklas Exp $ */
-/* $NetBSD: sbdsp.c,v 1.30 1996/10/25 07:25:48 fvdl Exp $ */
+/* $OpenBSD: sbdsp.c,v 1.12 1998/04/26 21:02:59 provos Exp $ */
+/* $NetBSD: sbdsp.c,v 1.78 1998/01/30 11:55:36 bouyer Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -40,6 +40,9 @@
* information he gleaned from Steve Haehnichen <steve@vigra.com>'s
* SBlast driver for 386BSD and DOS driver code from Daniel Sachs
* <sachs@meibm15.cen.uiuc.edu>.
+ * Lots of rewrites by Lennart Augustsson <augustss@cs.chalmers.se>
+ * with information from SB "Hardware Programming Guide" and the
+ * Linux drivers.
*/
#include <sys/param.h>
@@ -54,21 +57,21 @@
#include <machine/cpu.h>
#include <machine/intr.h>
-#include <machine/pio.h>
+#include <machine/bus.h>
#include <sys/audioio.h>
#include <dev/audio_if.h>
+#include <dev/mulaw.h>
+#include <dev/auconv.h>
#include <dev/isa/isavar.h>
#include <dev/isa/isadmavar.h>
-#include <i386/isa/icu.h> /* XXX BROKEN; WHY? */
#include <dev/isa/sbreg.h>
#include <dev/isa/sbdspvar.h>
#ifdef AUDIO_DEBUG
-extern void Dprintf __P((const char *, ...));
-#define DPRINTF(x) if (sbdspdebug) Dprintf x
+#define DPRINTF(x) if (sbdspdebug) printf x
int sbdspdebug = 0;
#else
#define DPRINTF(x)
@@ -84,10 +87,6 @@ struct {
int wmidi;
} sberr;
-int sbdsp_srtotc __P((struct sbdsp_softc *sc, int sr, int isdac,
- int *tcp, int *modep));
-u_int sbdsp_jazz16_probe __P((struct sbdsp_softc *));
-
/*
* Time constant routines follow. See SBK, section 12.
* Although they don't come out and say it (in the docs),
@@ -113,48 +112,106 @@ u_int sbdsp_jazz16_probe __P((struct sbdsp_softc *));
* output ls max 23 KHz 23 KHz
* output hs max 44.1 KHz 44.1 KHz
*/
-#define SB_LS_MIN 0x06 /* 4000 Hz */
-#define SB_8K 0x83 /* 8000 Hz */
-#define SBPRO_ADC_LS_MAX 0xd4 /* 22727 Hz */
-#define SBPRO_ADC_HS_MAX 0xea /* 45454 Hz */
-#define SBCLA_ADC_LS_MAX 0xb3 /* 12987 Hz */
-#define SBCLA_ADC_HS_MAX 0xbd /* 14925 Hz */
-#define SB_DAC_LS_MAX 0xd4 /* 22727 Hz */
-#define SB_DAC_HS_MAX 0xea /* 45454 Hz */
-
-int sbdsp16_wait __P((struct sbdsp_softc *));
+/* XXX Should we round the tc?
+#define SB_RATE_TO_TC(x) (((65536 - 256 * 1000000 / (x)) + 128) >> 8)
+*/
+#define SB_RATE_TO_TC(x) (256 - 1000000 / (x))
+#define SB_TC_TO_RATE(tc) (1000000 / (256 - (tc)))
+
+struct sbmode {
+ short model;
+ u_char channels;
+ u_char precision;
+ u_short lowrate, highrate;
+ u_char cmd;
+ u_char cmdchan;
+};
+static struct sbmode sbpmodes[] = {
+ { SB_1, 1, 8, 4000, 22727, SB_DSP_WDMA },
+ { SB_20, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
+ { SB_2x, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
+ { SB_2x, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT },
+ { SB_PRO, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP },
+ { SB_PRO, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT },
+ { SB_PRO, 2, 8, 11025, 22727, SB_DSP_HS_OUTPUT },
+ /* Yes, we write the record mode to set 16-bit playback mode. weird, huh? */
+ { SB_JAZZ, 1, 8, 4000, 22727, SB_DSP_WDMA_LOOP, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 1, 8, 22727, 45454, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 2, 8, 11025, 22727, SB_DSP_HS_OUTPUT, SB_DSP_RECORD_STEREO },
+ { SB_JAZZ, 1, 16, 4000, 22727, SB_DSP_WDMA_LOOP, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_OUTPUT, JAZZ16_RECORD_STEREO },
+ { SB_16, 1, 8, 5000, 45000, SB_DSP16_WDMA_8 },
+ { SB_16, 2, 8, 5000, 45000, SB_DSP16_WDMA_8 },
+#define PLAY16 15 /* must be the index of the next entry in the table */
+ { SB_16, 1, 16, 5000, 45000, SB_DSP16_WDMA_16 },
+ { SB_16, 2, 16, 5000, 45000, SB_DSP16_WDMA_16 },
+ { -1 }
+};
+static struct sbmode sbrmodes[] = {
+ { SB_1, 1, 8, 4000, 12987, SB_DSP_RDMA },
+ { SB_20, 1, 8, 4000, 12987, SB_DSP_RDMA_LOOP },
+ { SB_2x, 1, 8, 4000, 12987, SB_DSP_RDMA_LOOP },
+ { SB_2x, 1, 8, 12987, 14925, SB_DSP_HS_INPUT },
+ { SB_PRO, 1, 8, 4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
+ { SB_PRO, 1, 8, 22727, 45454, SB_DSP_HS_INPUT, SB_DSP_RECORD_MONO },
+ { SB_PRO, 2, 8, 11025, 22727, SB_DSP_HS_INPUT, SB_DSP_RECORD_STEREO },
+ { SB_JAZZ, 1, 8, 4000, 22727, SB_DSP_RDMA_LOOP, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 1, 8, 22727, 45454, SB_DSP_HS_INPUT, SB_DSP_RECORD_MONO },
+ { SB_JAZZ, 2, 8, 11025, 22727, SB_DSP_HS_INPUT, SB_DSP_RECORD_STEREO },
+ { SB_JAZZ, 1, 16, 4000, 22727, SB_DSP_RDMA_LOOP, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 1, 16, 22727, 45454, SB_DSP_HS_INPUT, JAZZ16_RECORD_MONO },
+ { SB_JAZZ, 2, 16, 11025, 22727, SB_DSP_HS_INPUT, JAZZ16_RECORD_STEREO },
+ { SB_16, 1, 8, 5000, 45000, SB_DSP16_RDMA_8 },
+ { SB_16, 2, 8, 5000, 45000, SB_DSP16_RDMA_8 },
+ { SB_16, 1, 16, 5000, 45000, SB_DSP16_RDMA_16 },
+ { SB_16, 2, 16, 5000, 45000, SB_DSP16_RDMA_16 },
+ { -1 }
+};
+
+void sbversion __P((struct sbdsp_softc *));
+void sbdsp_jazz16_probe __P((struct sbdsp_softc *));
+void sbdsp_set_mixer_gain __P((struct sbdsp_softc *sc, int port));
void sbdsp_to __P((void *));
void sbdsp_pause __P((struct sbdsp_softc *));
-int sbdsp16_setrate __P((struct sbdsp_softc *, int, int, int *));
-int sbdsp_tctosr __P((struct sbdsp_softc *, int));
int sbdsp_set_timeconst __P((struct sbdsp_softc *, int));
+int sbdsp16_set_rate __P((struct sbdsp_softc *, int, int));
+int sbdsp_set_in_ports __P((struct sbdsp_softc *, int));
+void sbdsp_set_ifilter __P((void *, int));
+int sbdsp_get_ifilter __P((void *));
+
+static int sbdsp_dma_setup_input __P((struct sbdsp_softc *sc));
+static int sbdsp_dma_setup_output __P((struct sbdsp_softc *sc));
+static int sbdsp_adjust __P((int, int));
#ifdef AUDIO_DEBUG
void sb_printsc __P((struct sbdsp_softc *));
-#endif
-#ifdef AUDIO_DEBUG
void
sb_printsc(sc)
struct sbdsp_softc *sc;
{
int i;
- printf("open %d dmachan %d/%d/%d iobase %x\n",
- sc->sc_open, sc->dmachan, sc->sc_drq8, sc->sc_drq16, sc->sc_iobase);
- printf("irate %d itc %d imode %d orate %d otc %d omode %d encoding %x\n",
- sc->sc_irate, sc->sc_itc, sc->sc_imode,
- sc->sc_orate, sc->sc_otc, sc->sc_omode, sc->sc_encoding);
- printf("outport %d inport %d spkron %d nintr %lu\n",
- sc->out_port, sc->in_port, sc->spkr_state, sc->sc_interrupts);
- printf("precision %d channels %d intr %p arg %p\n",
- sc->sc_precision, sc->sc_channels, sc->sc_intr, sc->sc_arg);
- printf("gain: ");
+ printf("open %d dmachan %d/%d %d/%d iobase 0x%x irq %d\n",
+ (int)sc->sc_open, sc->sc_i.run, sc->sc_o.run,
+ sc->sc_drq8, sc->sc_drq16,
+ sc->sc_iobase, sc->sc_irq);
+ printf("irate %d itc %x orate %d otc %x\n",
+ sc->sc_i.rate, sc->sc_i.tc,
+ sc->sc_o.rate, sc->sc_o.tc);
+ printf("spkron %u nintr %lu\n",
+ sc->spkr_state, sc->sc_interrupts);
+ printf("intr8 %p arg8 %p\n",
+ sc->sc_intr8, sc->sc_arg16);
+ printf("intr16 %p arg16 %p\n",
+ sc->sc_intr8, sc->sc_arg16);
+ printf("gain:");
for (i = 0; i < SB_NDEVS; i++)
- printf("%d ", sc->gain[i]);
+ printf(" %u,%u", sc->gain[i][SB_LEFT], sc->gain[i][SB_RIGHT]);
printf("\n");
}
-#endif
+#endif /* AUDIO_DEBUG */
/*
* Probe / attach routines.
@@ -173,19 +230,22 @@ sbdsp_probe(sc)
return 0;
}
/* if flags set, go and probe the jazz16 stuff */
- if (sc->sc_dev.dv_cfdata->cf_flags != 0) {
- sc->sc_model = sbdsp_jazz16_probe(sc);
- } else {
- sc->sc_model = sbversion(sc);
+ if (sc->sc_dev.dv_cfdata->cf_flags & 1)
+ sbdsp_jazz16_probe(sc);
+ else
+ sbversion(sc);
+ if (sc->sc_model == SB_UNK) {
+ /* Unknown SB model found. */
+ DPRINTF(("sbdsp: unknown SB model found\n"));
+ return 0;
}
-
return 1;
}
/*
* Try add-on stuff for Jazz16.
*/
-u_int
+void
sbdsp_jazz16_probe(sc)
struct sbdsp_softc *sc;
{
@@ -198,15 +258,16 @@ sbdsp_jazz16_probe(sc)
-1, 0x01, -1, 0x02,
-1, 0x03, -1, 0x04};
- u_int rval = sbversion(sc);
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh;
+ sbversion(sc);
+
DPRINTF(("jazz16 probe\n"));
if (bus_space_map(iot, JAZZ16_CONFIG_PORT, 1, 0, &ioh)) {
DPRINTF(("bus map failed\n"));
- return rval;
+ return;
}
if (jazz16_drq_conf[sc->sc_drq8] == (u_char)-1 ||
@@ -244,12 +305,12 @@ sbdsp_jazz16_probe(sc)
DPRINTF(("sbdsp: can't write jazz16 probe stuff\n"));
} else {
DPRINTF(("jazz16 detected!\n"));
- rval |= MODEL_JAZZ16;
+ sc->sc_model = SB_JAZZ;
+ sc->sc_mixer_model = SBM_CT1345; /* XXX really? */
}
done:
bus_space_unmap(iot, ioh, 1);
- return rval;
}
/*
@@ -260,49 +321,81 @@ void
sbdsp_attach(sc)
struct sbdsp_softc *sc;
{
+ struct audio_params pparams, rparams;
+ int i;
+ u_int v;
- /* Set defaults */
- if (ISSB16CLASS(sc))
- sc->sc_irate = sc->sc_orate = 8000;
- else if (ISSBPROCLASS(sc))
- sc->sc_itc = sc->sc_otc = SB_8K;
- else
- sc->sc_itc = sc->sc_otc = SB_8K;
- sc->sc_encoding = AUDIO_ENCODING_ULAW;
- sc->sc_precision = 8;
- sc->sc_channels = 1;
-
- (void) sbdsp_set_in_port(sc, SB_MIC_PORT);
- (void) sbdsp_set_out_port(sc, SB_SPEAKER);
-
- if (ISSBPROCLASS(sc)) {
- int i;
-
- /* set mixer to default levels, by sending a mixer
- reset command. */
+ /*
+ * Create our DMA maps.
+ */
+ if (sc->sc_drq8 != -1) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq8,
+ MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("%s: can't create map for drq %d\n",
+ sc->sc_dev.dv_xname, sc->sc_drq8);
+ return;
+ }
+ }
+ if (sc->sc_drq16 != -1 && sc->sc_drq16 != sc->sc_drq8) {
+ if (isa_dmamap_create(sc->sc_isa, sc->sc_drq16,
+ MAX_ISADMA, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW)) {
+ printf("%s: can't create map for drq %d\n",
+ sc->sc_dev.dv_xname, sc->sc_drq16);
+ return;
+ }
+ }
+
+ pparams = audio_default;
+ rparams = audio_default;
+ sbdsp_set_params(sc, AUMODE_RECORD|AUMODE_PLAY, 0, &pparams, &rparams);
+
+ sbdsp_set_in_ports(sc, 1 << SB_MIC_VOL);
+
+ if (sc->sc_mixer_model != SBM_NONE) {
+ /* Reset the mixer.*/
sbdsp_mix_write(sc, SBP_MIX_RESET, SBP_MIX_RESET);
- /* then some adjustments :) */
- sbdsp_mix_write(sc, SBP_CD_VOL,
- sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
- sbdsp_mix_write(sc, SBP_DAC_VOL,
- sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
- sbdsp_mix_write(sc, SBP_MASTER_VOL,
- sbdsp_stereo_vol(SBP_MAXVOL/2, SBP_MAXVOL/2));
- sbdsp_mix_write(sc, SBP_LINE_VOL,
- sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL));
- for (i = 0; i < SB_NDEVS; i++)
- sc->gain[i] = sbdsp_stereo_vol(SBP_MAXVOL, SBP_MAXVOL);
+ /* And set our own default values */
+ for (i = 0; i < SB_NDEVS; i++) {
+ switch(i) {
+ case SB_MIC_VOL:
+ case SB_LINE_IN_VOL:
+ v = 0;
+ break;
+ case SB_BASS:
+ case SB_TREBLE:
+ v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN/2);
+ break;
+ case SB_CD_IN_MUTE:
+ case SB_MIC_IN_MUTE:
+ case SB_LINE_IN_MUTE:
+ case SB_MIDI_IN_MUTE:
+ case SB_CD_SWAP:
+ case SB_MIC_SWAP:
+ case SB_LINE_SWAP:
+ case SB_MIDI_SWAP:
+ case SB_CD_OUT_MUTE:
+ case SB_MIC_OUT_MUTE:
+ case SB_LINE_OUT_MUTE:
+ v = 0;
+ break;
+ default:
+ v = SB_ADJUST_GAIN(sc, AUDIO_MAX_GAIN / 2);
+ break;
+ }
+ sc->gain[i][SB_LEFT] = sc->gain[i][SB_RIGHT] = v;
+ sbdsp_set_mixer_gain(sc, i);
+ }
sc->in_filter = 0; /* no filters turned on, please */
}
printf(": dsp v%d.%02d%s\n",
- SBVER_MAJOR(sc->sc_model), SBVER_MINOR(sc->sc_model),
- ISJAZZ16(sc) ? ": <Jazz16>" : "");
-}
+ SBVER_MAJOR(sc->sc_version), SBVER_MINOR(sc->sc_version),
+ sc->sc_model == SB_JAZZ ? ": <Jazz16>" : "");
-/*
- * Various routines to interface to higher level audio driver
- */
+ sc->sc_fullduplex = ISSB16CLASS(sc) &&
+ sc->sc_drq8 != -1 && sc->sc_drq16 != -1 &&
+ sc->sc_drq8 != sc->sc_drq16;
+}
void
sbdsp_mix_write(sc, mixerport, val)
@@ -312,11 +405,14 @@ sbdsp_mix_write(sc, mixerport, val)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
+ int s;
+ s = splaudio();
bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
- delay(10);
+ delay(20);
bus_space_write_1(iot, ioh, SBP_MIXER_DATA, val);
delay(30);
+ splx(s);
}
int
@@ -326,305 +422,382 @@ sbdsp_mix_read(sc, mixerport)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
+ int val;
+ int s;
+ s = splaudio();
bus_space_write_1(iot, ioh, SBP_MIXER_ADDR, mixerport);
- delay(10);
- return bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
-}
-
-int
-sbdsp_set_in_sr(addr, sr)
- void *addr;
- u_long sr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sbdsp16_setrate(sc, sr, SB_INPUT_RATE, &sc->sc_irate));
- else
- return (sbdsp_srtotc(sc, sr, SB_INPUT_RATE, &sc->sc_itc, &sc->sc_imode));
-}
-
-u_long
-sbdsp_get_in_sr(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sc->sc_irate);
- else
- return (sbdsp_tctosr(sc, sc->sc_itc));
-}
-
-int
-sbdsp_set_out_sr(addr, sr)
- void *addr;
- u_long sr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sbdsp16_setrate(sc, sr, SB_OUTPUT_RATE, &sc->sc_orate));
- else
- return (sbdsp_srtotc(sc, sr, SB_OUTPUT_RATE, &sc->sc_otc, &sc->sc_omode));
+ delay(20);
+ val = bus_space_read_1(iot, ioh, SBP_MIXER_DATA);
+ delay(30);
+ splx(s);
+ return val;
}
-u_long
-sbdsp_get_out_sr(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
-
- if (ISSB16CLASS(sc))
- return (sc->sc_orate);
- else
- return (sbdsp_tctosr(sc, sc->sc_otc));
-}
+/*
+ * Various routines to interface to higher level audio driver
+ */
int
sbdsp_query_encoding(addr, fp)
void *addr;
struct audio_encoding *fp;
{
+ struct sbdsp_softc *sc = addr;
+ int emul;
+
+ emul = ISSB16CLASS(sc) ? 0 : AUDIO_ENCODINGFLAG_EMULATED;
+
switch (fp->index) {
case 0:
- strcpy(fp->name, AudioEmulaw);
- fp->format_id = AUDIO_ENCODING_ULAW;
- break;
+ strcpy(fp->name, AudioEulinear);
+ fp->encoding = AUDIO_ENCODING_ULINEAR;
+ fp->precision = 8;
+ fp->flags = 0;
+ return 0;
case 1:
- strcpy(fp->name, AudioEpcm16);
- fp->format_id = AUDIO_ENCODING_PCM16;
- break;
- default:
- return (EINVAL);
- }
- return (0);
-}
+ strcpy(fp->name, AudioEmulaw);
+ fp->encoding = AUDIO_ENCODING_ULAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
+ case 2:
+ strcpy(fp->name, AudioEalaw);
+ fp->encoding = AUDIO_ENCODING_ALAW;
+ fp->precision = 8;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
+ case 3:
+ strcpy(fp->name, AudioEslinear);
+ fp->encoding = AUDIO_ENCODING_SLINEAR;
+ fp->precision = 8;
+ fp->flags = emul;
+ return 0;
+ }
+ if (!ISSB16CLASS(sc) && sc->sc_model != SB_JAZZ)
+ return EINVAL;
-int
-sbdsp_set_format(addr, encoding, precision)
- void *addr;
- u_int encoding, precision;
-{
- register struct sbdsp_softc *sc = addr;
-
- switch (encoding) {
- case AUDIO_ENCODING_ULAW:
- case AUDIO_ENCODING_PCM16:
- case AUDIO_ENCODING_PCM8:
- break;
+ switch(fp->index) {
+ case 4:
+ strcpy(fp->name, AudioEslinear_le);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ fp->precision = 16;
+ fp->flags = 0;
+ return 0;
+ case 5:
+ strcpy(fp->name, AudioEulinear_le);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ fp->precision = 16;
+ fp->flags = emul;
+ return 0;
+ case 6:
+ strcpy(fp->name, AudioEslinear_be);
+ fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
+ case 7:
+ strcpy(fp->name, AudioEulinear_be);
+ fp->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ fp->precision = 16;
+ fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
+ return 0;
default:
- return (EINVAL);
+ return EINVAL;
}
-
- if (precision == 16)
- if (!ISSB16CLASS(sc) && !ISJAZZ16(sc))
- return (EINVAL);
-
- sc->sc_encoding = encoding;
- sc->sc_precision = precision;
-
- return (0);
+ return 0;
}
int
-sbdsp_get_encoding(addr)
+sbdsp_set_params(addr, setmode, usemode, play, rec)
void *addr;
+ int setmode, usemode;
+ struct audio_params *play, *rec;
{
- register struct sbdsp_softc *sc = addr;
-
- return (sc->sc_encoding);
-}
+ struct sbdsp_softc *sc = addr;
+ struct sbmode *m;
+ u_int rate, tc, bmode;
+ void (*swcode) __P((void *, u_char *buf, int cnt));
+ int factor;
+ int model;
+ int chan;
+ struct audio_params *p;
+ int mode;
+
+ model = sc->sc_model;
+ if (model > SB_16)
+ model = SB_16; /* later models work like SB16 */
+
+ /* Set first record info, then play info */
+ for(mode = AUMODE_RECORD; mode != -1;
+ mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
+ if ((setmode & mode) == 0)
+ continue;
-int
-sbdsp_get_precision(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
+ p = mode == AUMODE_PLAY ? play : rec;
+ /* Locate proper commands */
+ for(m = mode == AUMODE_PLAY ? sbpmodes : sbrmodes;
+ m->model != -1; m++) {
+ if (model == m->model &&
+ p->channels == m->channels &&
+ p->precision == m->precision &&
+ p->sample_rate >= m->lowrate &&
+ p->sample_rate < m->highrate)
+ break;
+ }
+ if (m->model == -1)
+ return EINVAL;
+ rate = p->sample_rate;
+ swcode = 0;
+ factor = 1;
+ tc = 1;
+ bmode = -1;
+ if (model == SB_16) {
+ switch (p->encoding) {
+ case AUDIO_ENCODING_SLINEAR_BE:
+ if (p->precision == 16)
+ swcode = swap_bytes;
+ /* fall into */
+ case AUDIO_ENCODING_SLINEAR_LE:
+ bmode = SB_BMODE_SIGNED;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ if (p->precision == 16)
+ swcode = swap_bytes;
+ /* fall into */
+ case AUDIO_ENCODING_ULINEAR_LE:
+ bmode = SB_BMODE_UNSIGNED;
+ break;
+ case AUDIO_ENCODING_ULAW:
+ if (mode == AUMODE_PLAY) {
+ swcode = mulaw_to_ulinear16;
+ factor = 2;
+ m = &sbpmodes[PLAY16];
+ } else
+ swcode = ulinear8_to_mulaw;
+ bmode = SB_BMODE_UNSIGNED;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ if (mode == AUMODE_PLAY) {
+ swcode = alaw_to_ulinear16;
+ factor = 2;
+ m = &sbpmodes[PLAY16];
+ } else
+ swcode = ulinear8_to_alaw;
+ bmode = SB_BMODE_UNSIGNED;
+ break;
+ default:
+ return EINVAL;
+ }
+ if (p->channels == 2)
+ bmode |= SB_BMODE_STEREO;
+ } else if (m->model == SB_JAZZ && m->precision == 16) {
+ switch (p->encoding) {
+ case AUDIO_ENCODING_SLINEAR_LE:
+ break;
+ case AUDIO_ENCODING_ULINEAR_LE:
+ swcode = change_sign16;
+ break;
+ case AUDIO_ENCODING_SLINEAR_BE:
+ swcode = swap_bytes;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ swcode = mode == AUMODE_PLAY ?
+ swap_bytes_change_sign16 : change_sign16_swap_bytes;
+ break;
+ case AUDIO_ENCODING_ULAW:
+ swcode = mode == AUMODE_PLAY ?
+ mulaw_to_ulinear8 : ulinear8_to_mulaw;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ swcode = mode == AUMODE_PLAY ?
+ alaw_to_ulinear8 : ulinear8_to_alaw;
+ break;
+ default:
+ return EINVAL;
+ }
+ tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
+ p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
+ } else {
+ switch (p->encoding) {
+ case AUDIO_ENCODING_SLINEAR_BE:
+ case AUDIO_ENCODING_SLINEAR_LE:
+ swcode = change_sign8;
+ break;
+ case AUDIO_ENCODING_ULINEAR_BE:
+ case AUDIO_ENCODING_ULINEAR_LE:
+ break;
+ case AUDIO_ENCODING_ULAW:
+ swcode = mode == AUMODE_PLAY ?
+ mulaw_to_ulinear8 : ulinear8_to_mulaw;
+ break;
+ case AUDIO_ENCODING_ALAW:
+ swcode = mode == AUMODE_PLAY ?
+ alaw_to_ulinear8 : ulinear8_to_alaw;
+ break;
+ default:
+ return EINVAL;
+ }
+ tc = SB_RATE_TO_TC(p->sample_rate * p->channels);
+ p->sample_rate = SB_TC_TO_RATE(tc) / p->channels;
+ }
- return (sc->sc_precision);
-}
+ chan = m->precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
+ if (mode == AUMODE_PLAY) {
+ sc->sc_o.rate = rate;
+ sc->sc_o.tc = tc;
+ sc->sc_o.modep = m;
+ sc->sc_o.bmode = bmode;
+ sc->sc_o.dmachan = chan;
+ } else {
+ sc->sc_i.rate = rate;
+ sc->sc_i.tc = tc;
+ sc->sc_i.modep = m;
+ sc->sc_i.bmode = bmode;
+ sc->sc_i.dmachan = chan;
+ }
-int
-sbdsp_set_channels(addr, channels)
- void *addr;
- int channels;
-{
- register struct sbdsp_softc *sc = addr;
+ p->sw_code = swcode;
+ p->factor = factor;
+ DPRINTF(("sbdsp_set_params: model=%d, mode=%d, rate=%ld, prec=%d, chan=%d, enc=%d -> tc=%02x, cmd=%02x, bmode=%02x, cmdchan=%02x, swcode=%p, factor=%d\n",
+ sc->sc_model, mode, p->sample_rate, p->precision, p->channels,
+ p->encoding, tc, m->cmd, bmode, m->cmdchan, swcode, factor));
- if (ISSBPROCLASS(sc)) {
- if (channels != 1 && channels != 2)
- return (EINVAL);
- sc->sc_channels = channels;
- sc->sc_dmadir = SB_DMA_NONE;
- /*
- * XXXX
- * With 2 channels, SBPro can't do more than 22kHz.
- * No framework to check this.
- */
- } else {
- if (channels != 1)
- return (EINVAL);
- sc->sc_channels = channels;
}
-
- return (0);
-}
+ /*
+ * XXX
+ * Should wait for chip to be idle.
+ */
+ sc->sc_i.run = SB_NOTRUNNING;
+ sc->sc_o.run = SB_NOTRUNNING;
+
+ if (sc->sc_fullduplex &&
+ (usemode & (AUMODE_PLAY | AUMODE_RECORD)) == (AUMODE_PLAY | AUMODE_RECORD) &&
+ sc->sc_i.dmachan == sc->sc_o.dmachan) {
+ DPRINTF(("sbdsp_commit: fd=%d, usemode=%d, idma=%d, odma=%d\n", sc->sc_fullduplex, usemode, sc->sc_i.dmachan, sc->sc_o.dmachan));
+ if (sc->sc_o.dmachan == sc->sc_drq8) {
+ /* Use 16 bit DMA for playing by expanding the samples. */
+ play->sw_code = linear8_to_linear16;
+ play->factor = 2;
+ sc->sc_o.modep = &sbpmodes[PLAY16];
+ sc->sc_o.dmachan = sc->sc_drq16;
+ } else {
+ return EINVAL;
+ }
+ }
+ DPRINTF(("sbdsp_set_params ichan=%d, ochan=%d\n", sc->sc_i.dmachan, sc->sc_o.dmachan));
-int
-sbdsp_get_channels(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
-
- return (sc->sc_channels);
+ return 0;
}
-int
+void
sbdsp_set_ifilter(addr, which)
void *addr;
int which;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
int mixval;
- /* XXXX SB16 */
- if (ISSBPROCLASS(sc)) {
- mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
- switch (which) {
- case 0:
- mixval |= SBP_FILTER_OFF;
- break;
- case SBP_TREBLE_EQ:
- mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
- break;
- case SBP_BASS_EQ:
- mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
- break;
- default:
- return (EINVAL);
- }
- sc->in_filter = mixval & SBP_IFILTER_MASK;
- sbdsp_mix_write(sc, SBP_INFILTER, mixval);
- return (0);
- } else
- return (EINVAL);
+ mixval = sbdsp_mix_read(sc, SBP_INFILTER) & ~SBP_IFILTER_MASK;
+ switch (which) {
+ case 0:
+ mixval |= SBP_FILTER_OFF;
+ break;
+ case SB_TREBLE:
+ mixval |= SBP_FILTER_ON | SBP_IFILTER_HIGH;
+ break;
+ case SB_BASS:
+ mixval |= SBP_FILTER_ON | SBP_IFILTER_LOW;
+ break;
+ default:
+ return;
+ }
+ sc->in_filter = mixval & SBP_IFILTER_MASK;
+ sbdsp_mix_write(sc, SBP_INFILTER, mixval);
}
int
sbdsp_get_ifilter(addr)
void *addr;
{
- register struct sbdsp_softc *sc = addr;
-
- /* XXXX SB16 */
- if (ISSBPROCLASS(sc)) {
- sc->in_filter =
- sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
- switch (sc->in_filter) {
- case SBP_FILTER_ON|SBP_IFILTER_HIGH:
- return (SBP_TREBLE_EQ);
- case SBP_FILTER_ON|SBP_IFILTER_LOW:
- return (SBP_BASS_EQ);
- case SBP_FILTER_OFF:
- default:
- return (0);
- }
- } else
- return (0);
-}
-
-int
-sbdsp_set_out_port(addr, port)
- void *addr;
- int port;
-{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
- sc->out_port = port; /* Just record it */
-
- return (0);
+ sc->in_filter =
+ sbdsp_mix_read(sc, SBP_INFILTER) & SBP_IFILTER_MASK;
+ switch (sc->in_filter) {
+ case SBP_FILTER_ON|SBP_IFILTER_HIGH:
+ return SB_TREBLE;
+ case SBP_FILTER_ON|SBP_IFILTER_LOW:
+ return SB_BASS;
+ default:
+ return 0;
+ }
}
int
-sbdsp_get_out_port(addr)
- void *addr;
+sbdsp_set_in_ports(sc, mask)
+ struct sbdsp_softc *sc;
+ int mask;
{
- register struct sbdsp_softc *sc = addr;
-
- return (sc->out_port);
-}
+ int bitsl, bitsr;
+ int sbport;
+ DPRINTF(("sbdsp_set_in_ports: model=%d, mask=%x\n",
+ sc->sc_mixer_model, mask));
-int
-sbdsp_set_in_port(addr, port)
- void *addr;
- int port;
-{
- register struct sbdsp_softc *sc = addr;
- int mixport, sbport;
-
- if (ISSBPROCLASS(sc)) {
- switch (port) {
- case SB_MIC_PORT:
+ switch(sc->sc_mixer_model) {
+ case SBM_NONE:
+ return EINVAL;
+ case SBM_CT1335:
+ if (mask != (1 << SB_MIC_VOL))
+ return EINVAL;
+ break;
+ case SBM_CT1345:
+ switch (mask) {
+ case 1 << SB_MIC_VOL:
sbport = SBP_FROM_MIC;
- mixport = SBP_MIC_VOL;
break;
- case SB_LINE_IN_PORT:
+ case 1 << SB_LINE_IN_VOL:
sbport = SBP_FROM_LINE;
- mixport = SBP_LINE_VOL;
break;
- case SB_CD_PORT:
+ case 1 << SB_CD_VOL:
sbport = SBP_FROM_CD;
- mixport = SBP_CD_VOL;
break;
- case SB_DAC_PORT:
- case SB_FM_PORT:
default:
return (EINVAL);
}
- } else {
- switch (port) {
- case SB_MIC_PORT:
- sbport = SBP_FROM_MIC;
- mixport = SBP_MIC_VOL;
- break;
- default:
- return (EINVAL);
+ sbdsp_mix_write(sc, SBP_RECORD_SOURCE, sbport | sc->in_filter);
+ break;
+ case SBM_CT1XX5:
+ case SBM_CT1745:
+ if (mask & ~((1<<SB_MIDI_VOL) | (1<<SB_LINE_IN_VOL) |
+ (1<<SB_CD_VOL) | (1<<SB_MIC_VOL)))
+ return EINVAL;
+ bitsr = 0;
+ if (mask & (1<<SB_MIDI_VOL)) bitsr |= SBP_MIDI_SRC_R;
+ if (mask & (1<<SB_LINE_IN_VOL)) bitsr |= SBP_LINE_SRC_R;
+ if (mask & (1<<SB_CD_VOL)) bitsr |= SBP_CD_SRC_R;
+ bitsl = SB_SRC_R_TO_L(bitsr);
+ if (mask & (1<<SB_MIC_VOL)) {
+ bitsl |= SBP_MIC_SRC;
+ bitsr |= SBP_MIC_SRC;
}
- }
-
- sc->in_port = port; /* Just record it */
-
- /* XXXX SB16 */
- if (ISSBPROCLASS(sc)) {
- /* record from that port */
- sbdsp_mix_write(sc, SBP_RECORD_SOURCE,
- SBP_RECORD_FROM(sbport, SBP_FILTER_OFF, SBP_IFILTER_HIGH));
- /* fetch gain from that port */
- sc->gain[port] = sbdsp_mix_read(sc, mixport);
+ sbdsp_mix_write(sc, SBP_RECORD_SOURCE_L, bitsl);
+ sbdsp_mix_write(sc, SBP_RECORD_SOURCE_R, bitsr);
+ break;
}
- return (0);
-}
-
-int
-sbdsp_get_in_port(addr)
- void *addr;
-{
- register struct sbdsp_softc *sc = addr;
+ sc->in_mask = mask;
- return (sc->in_port);
+ return 0;
}
-
int
sbdsp_speaker_ctl(addr, newstate)
void *addr;
int newstate;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
if ((newstate == SPKR_ON) &&
(sc->spkr_state == SPKR_OFF)) {
@@ -636,7 +809,7 @@ sbdsp_speaker_ctl(addr, newstate)
sbdsp_spkroff(sc);
sc->spkr_state = SPKR_OFF;
}
- return(0);
+ return 0;
}
int
@@ -644,83 +817,26 @@ sbdsp_round_blocksize(addr, blk)
void *addr;
int blk;
{
- register struct sbdsp_softc *sc = addr;
-
- sc->sc_last_hs_size = 0;
-
- /* Don't try to DMA too much at once. */
- if (blk > NBPG)
- blk = NBPG;
-
- /* Round to a multiple of the sample size. */
- blk &= -(sc->sc_channels * sc->sc_precision / 8);
-
- return (blk);
+ blk &= -4; /* round to biggest sample size */
+ return blk;
}
int
-sbdsp_commit_settings(addr)
+sbdsp_open(addr, flags)
void *addr;
-{
- register struct sbdsp_softc *sc = addr;
-
- /* due to potentially unfortunate ordering in the above layers,
- re-do a few sets which may be important--input gains
- (adjust the proper channels), number of input channels (hit the
- record rate and set mode) */
-
- if (ISSBPRO(sc)) {
- /*
- * With 2 channels, SBPro can't do more than 22kHz.
- * Whack the rates down to speed if necessary.
- * Reset the time constant anyway
- * because it may have been adjusted with a different number
- * of channels, which means it might have computed the wrong
- * mode (low/high speed).
- */
- if (sc->sc_channels == 2 &&
- sbdsp_tctosr(sc, sc->sc_itc) > 22727) {
- sbdsp_srtotc(sc, 22727, SB_INPUT_RATE,
- &sc->sc_itc, &sc->sc_imode);
- } else
- sbdsp_srtotc(sc, sbdsp_tctosr(sc, sc->sc_itc),
- SB_INPUT_RATE, &sc->sc_itc,
- &sc->sc_imode);
-
- if (sc->sc_channels == 2 &&
- sbdsp_tctosr(sc, sc->sc_otc) > 22727) {
- sbdsp_srtotc(sc, 22727, SB_OUTPUT_RATE,
- &sc->sc_otc, &sc->sc_omode);
- } else
- sbdsp_srtotc(sc, sbdsp_tctosr(sc, sc->sc_otc),
- SB_OUTPUT_RATE, &sc->sc_otc,
- &sc->sc_omode);
- }
-
- /*
- * XXX
- * Should wait for chip to be idle.
- */
- sc->sc_dmadir = SB_DMA_NONE;
-
- return 0;
-}
-
-
-int
-sbdsp_open(sc, dev, flags)
- register struct sbdsp_softc *sc;
- dev_t dev;
int flags;
{
- DPRINTF(("sbdsp_open: sc=0x%x\n", sc));
+ struct sbdsp_softc *sc = addr;
+
+ DPRINTF(("sbdsp_open: sc=%p\n", sc));
if (sc->sc_open != 0 || sbdsp_reset(sc) != 0)
return ENXIO;
sc->sc_open = 1;
+ sc->sc_openflags = flags;
sc->sc_mintr = 0;
- if (ISSBPROCLASS(sc) &&
+ if (ISSBPRO(sc) &&
sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0) {
DPRINTF(("sbdsp_open: can't set mono mode\n"));
/* we'll readjust when it's time for DMA. */
@@ -743,11 +859,13 @@ sbdsp_close(addr)
{
struct sbdsp_softc *sc = addr;
- DPRINTF(("sbdsp_close: sc=0x%x\n", sc));
+ DPRINTF(("sbdsp_close: sc=%p\n", sc));
sc->sc_open = 0;
sbdsp_spkroff(sc);
sc->spkr_state = SPKR_OFF;
+ sc->sc_intr8 = 0;
+ sc->sc_intr16 = 0;
sc->sc_mintr = 0;
sbdsp_haltdma(sc);
@@ -764,17 +882,21 @@ sbdsp_close(addr)
*/
int
sbdsp_reset(sc)
- register struct sbdsp_softc *sc;
+ struct sbdsp_softc *sc;
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- sc->sc_intr = 0;
- if (sc->sc_dmadir != SB_DMA_NONE) {
- isadma_abort(sc->dmachan);
- sc->sc_dmadir = SB_DMA_NONE;
+ sc->sc_intr8 = 0;
+ sc->sc_intr16 = 0;
+ if (sc->sc_i.run != SB_NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_i.dmachan);
+ sc->sc_i.run = SB_NOTRUNNING;
+ }
+ if (sc->sc_o.run != SB_NOTRUNNING) {
+ isa_dmaabort(sc->sc_isa, sc->sc_o.dmachan);
+ sc->sc_o.run = SB_NOTRUNNING;
}
- sc->sc_last_hs_size = 0;
/*
* See SBK, section 11.3.
@@ -791,29 +913,9 @@ sbdsp_reset(sc)
return 0;
}
-int
-sbdsp16_wait(sc)
- struct sbdsp_softc *sc;
-{
- bus_space_tag_t iot = sc->sc_iot;
- bus_space_handle_t ioh = sc->sc_ioh;
- register int i;
-
- for (i = SBDSP_NPOLL; --i >= 0; ) {
- register u_char x;
- x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
- delay(10);
- if ((x & SB_DSP_BUSY) == 0)
- continue;
- return 0;
- }
- ++sberr.wdsp;
- return -1;
-}
-
/*
* Write a byte to the dsp.
- * XXX We are at the mercy of the card as we use a
+ * We are at the mercy of the card as we use a
* polling loop and wait until it can take the byte.
*/
int
@@ -823,17 +925,17 @@ sbdsp_wdsp(sc, v)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- register int i;
+ int i;
+ u_char x;
for (i = SBDSP_NPOLL; --i >= 0; ) {
- register u_char x;
x = bus_space_read_1(iot, ioh, SBP_DSP_WSTAT);
delay(10);
- if ((x & SB_DSP_BUSY) != 0)
- continue;
- bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
- delay(10);
- return 0;
+ if ((x & SB_DSP_BUSY) == 0) {
+ bus_space_write_1(iot, ioh, SBP_DSP_WRITE, v);
+ delay(10);
+ return 0;
+ }
}
++sberr.wdsp;
return -1;
@@ -848,17 +950,17 @@ sbdsp_rdsp(sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
- register int i;
+ int i;
+ u_char x;
for (i = SBDSP_NPOLL; --i >= 0; ) {
- register u_char x;
x = bus_space_read_1(iot, ioh, SBP_DSP_RSTAT);
delay(10);
- if ((x & SB_DSP_READY) == 0)
- continue;
- x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
- delay(10);
- return x;
+ if (x & SB_DSP_READY) {
+ x = bus_space_read_1(iot, ioh, SBP_DSP_READ);
+ delay(10);
+ return x;
+ }
}
++sberr.rdsp;
return -1;
@@ -915,187 +1017,166 @@ sbdsp_spkroff(sc)
}
/*
- * Read the version number out of the card. Return major code
- * in high byte, and minor code in low byte.
+ * Read the version number out of the card.
+ * Store version information in the softc.
*/
-short
+void
sbversion(sc)
struct sbdsp_softc *sc;
{
- short v;
+ int v;
+ sc->sc_model = SB_UNK;
+ sc->sc_version = 0;
if (sbdsp_wdsp(sc, SB_DSP_VERSION) < 0)
- return 0;
+ return;
v = sbdsp_rdsp(sc) << 8;
v |= sbdsp_rdsp(sc);
- return ((v >= 0) ? v : 0);
+ if (v < 0)
+ return;
+ sc->sc_version = v;
+ switch(SBVER_MAJOR(v)) {
+ case 1:
+ sc->sc_mixer_model = SBM_NONE;
+ sc->sc_model = SB_1;
+ break;
+ case 2:
+ /* Some SB2 have a mixer, some don't. */
+ sbdsp_mix_write(sc, SBP_1335_MASTER_VOL, 0x04);
+ sbdsp_mix_write(sc, SBP_1335_MIDI_VOL, 0x06);
+ /* Check if we can read back the mixer values. */
+ if ((sbdsp_mix_read(sc, SBP_1335_MASTER_VOL) & 0x0e) == 0x04 &&
+ (sbdsp_mix_read(sc, SBP_1335_MIDI_VOL) & 0x0e) == 0x06)
+ sc->sc_mixer_model = SBM_CT1335;
+ else
+ sc->sc_mixer_model = SBM_NONE;
+ if (SBVER_MINOR(v) == 0)
+ sc->sc_model = SB_20;
+ else
+ sc->sc_model = SB_2x;
+ break;
+ case 3:
+ sc->sc_mixer_model = SBM_CT1345;
+ sc->sc_model = SB_PRO;
+ break;
+ case 4:
+#if 0
+/* XXX This does not work */
+ /* Most SB16 have a tone controls, but some don't. */
+ sbdsp_mix_write(sc, SB16P_TREBLE_L, 0x80);
+ /* Check if we can read back the mixer value. */
+ if ((sbdsp_mix_read(sc, SB16P_TREBLE_L) & 0xf0) == 0x80)
+ sc->sc_mixer_model = SBM_CT1745;
+ else
+ sc->sc_mixer_model = SBM_CT1XX5;
+#else
+ sc->sc_mixer_model = SBM_CT1745;
+#endif
+#if 0
+/* XXX figure out a good way of determining the model */
+ /* XXX what about SB_32 */
+ if (SBVER_MINOR(v) == 16)
+ sc->sc_model = SB_64;
+ else
+#endif
+ sc->sc_model = SB_16;
+ break;
+ }
}
/*
- * Halt a DMA in progress. A low-speed transfer can be
- * resumed with sbdsp_contdma().
+ * Halt a DMA in progress.
*/
int
sbdsp_haltdma(addr)
void *addr;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
- DPRINTF(("sbdsp_haltdma: sc=0x%x\n", sc));
+ DPRINTF(("sbdsp_haltdma: sc=%p\n", sc));
sbdsp_reset(sc);
return 0;
}
int
-sbdsp_contdma(addr)
- void *addr;
+sbdsp_set_timeconst(sc, tc)
+ struct sbdsp_softc *sc;
+ int tc;
{
- register struct sbdsp_softc *sc = addr;
-
- DPRINTF(("sbdsp_contdma: sc=0x%x\n", sc));
+ DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
- /* XXX how do we reinitialize the DMA controller state? do we care? */
- (void)sbdsp_wdsp(sc, SB_DSP_CONT);
- return(0);
+ if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
+ sbdsp_wdsp(sc, tc) < 0)
+ return EIO;
+
+ return 0;
}
int
-sbdsp16_setrate(sc, sr, isdac, ratep)
- register struct sbdsp_softc *sc;
- int sr;
- int isdac;
- int *ratep;
+sbdsp16_set_rate(sc, cmd, rate)
+ struct sbdsp_softc *sc;
+ int cmd, rate;
{
+ DPRINTF(("sbdsp16_set_rate: sc=%p cmd=0x%02x rate=%d\n", sc, cmd, rate));
- /*
- * XXXX
- * More checks here?
- */
- if (sr < 5000 || sr > 45454)
- return (EINVAL);
- *ratep = sr;
- return (0);
+ if (sbdsp_wdsp(sc, cmd) < 0 ||
+ sbdsp_wdsp(sc, rate >> 8) < 0 ||
+ sbdsp_wdsp(sc, rate) < 0)
+ return EIO;
+ return 0;
}
-/*
- * Convert a linear sampling rate into the DAC time constant.
- * Set *mode to indicate the high/low-speed DMA operation.
- * Because of limitations of the card, not all rates are possible.
- * We return the time constant of the closest possible rate.
- * The sampling rate limits are different for the DAC and ADC,
- * so isdac indicates output, and !isdac indicates input.
- */
int
-sbdsp_srtotc(sc, sr, isdac, tcp, modep)
- register struct sbdsp_softc *sc;
- int sr;
- int isdac;
- int *tcp, *modep;
+sbdsp_dma_init_input(addr, buf, cc)
+ void *addr;
+ void *buf;
+ int cc;
{
- int tc, realtc, mode;
+ struct sbdsp_softc *sc = addr;
- /*
- * Don't forget to compute which mode we'll be in based on whether
- * we need to double the rate for stereo on SBPRO.
- */
-
- if (sr == 0) {
- tc = SB_LS_MIN;
- mode = SB_ADAC_LS;
- goto out;
- }
+ if (sc->sc_model == SB_1)
+ return 0;
+ sc->sc_i.run = SB_DMARUNNING;
+ DPRINTF(("sbdsp: dma start loop input addr=%p cc=%d chan=%d\n",
+ buf, cc, sc->sc_i.dmachan));
+ isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, buf,
+ cc, NULL, DMAMODE_READ | DMAMODE_LOOP, BUS_DMA_NOWAIT);
+ return 0;
+}
- tc = 256 - (1000000 / sr);
+static int
+sbdsp_dma_setup_input(sc)
+ struct sbdsp_softc *sc;
+{
+ int stereo = sc->sc_i.modep->channels == 2;
+ int filter;
- if (sc->sc_channels == 2 && ISSBPRO(sc))
- /* compute based on 2x sample rate when needed */
- realtc = 256 - ( 500000 / sr);
- else
- realtc = tc;
+ /* Initialize the PCM */
+ if (ISSBPRO(sc)) {
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmdchan) < 0)
+ return 0;
+ filter = stereo ? SBP_FILTER_OFF : sc->in_filter;
+ sbdsp_mix_write(sc, SBP_INFILTER,
+ (sbdsp_mix_read(sc, SBP_INFILTER) &
+ ~SBP_IFILTER_MASK) | filter);
+ }
- if (tc < SB_LS_MIN) {
- tc = SB_LS_MIN;
- mode = SB_ADAC_LS; /* NB: 2x minimum speed is still low
- * speed mode. */
- goto out;
- } else if (isdac) {
- if (realtc <= SB_DAC_LS_MAX)
- mode = SB_ADAC_LS;
- else {
- mode = SB_ADAC_HS;
- if (tc > SB_DAC_HS_MAX)
- tc = SB_DAC_HS_MAX;
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp16_set_rate(sc, SB_DSP16_INPUTRATE,
+ sc->sc_i.rate)) {
+ DPRINTF(("sbdsp_dma_setup_input: rate=%d set failed\n",
+ sc->sc_i.rate));
+ return 0;
}
} else {
- int adc_ls_max, adc_hs_max;
-
- /* XXX use better rounding--compare distance to nearest tc on both
- sides of requested speed */
- if (ISSBPROCLASS(sc)) {
- adc_ls_max = SBPRO_ADC_LS_MAX;
- adc_hs_max = SBPRO_ADC_HS_MAX;
- } else {
- adc_ls_max = SBCLA_ADC_LS_MAX;
- adc_hs_max = SBCLA_ADC_HS_MAX;
- }
-
- if (realtc <= adc_ls_max)
- mode = SB_ADAC_LS;
- else {
- mode = SB_ADAC_HS;
- if (tc > adc_hs_max)
- tc = adc_hs_max;
+ if (sbdsp_set_timeconst(sc, sc->sc_i.tc)) {
+ DPRINTF(("sbdsp_dma_setup_input: tc=%d set failed\n",
+ sc->sc_i.rate));
+ return 0;
}
}
-
-out:
- *tcp = tc;
- *modep = mode;
- return (0);
-}
-
-/*
- * Convert a DAC time constant to a sampling rate.
- * See SBK, section 12.
- */
-int
-sbdsp_tctosr(sc, tc)
- register struct sbdsp_softc *sc;
- int tc;
-{
- int adc;
-
- if (ISSBPROCLASS(sc))
- adc = SBPRO_ADC_HS_MAX;
- else
- adc = SBCLA_ADC_HS_MAX;
-
- if (tc > adc)
- tc = adc;
-
- return (1000000 / (256 - tc));
-}
-
-int
-sbdsp_set_timeconst(sc, tc)
- register struct sbdsp_softc *sc;
- int tc;
-{
- /*
- * A SBPro in stereo mode uses time constants at double the
- * actual rate.
- */
- if (ISSBPRO(sc) && sc->sc_channels == 2)
- tc = 256 - ((256 - tc) / 2);
-
- DPRINTF(("sbdsp_set_timeconst: sc=%p tc=%d\n", sc, tc));
-
- if (sbdsp_wdsp(sc, SB_DSP_TIMECONST) < 0 ||
- sbdsp_wdsp(sc, tc) < 0)
- return (EIO);
-
- return (0);
+ return 1;
}
int
@@ -1106,119 +1187,171 @@ sbdsp_dma_input(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
#ifdef AUDIO_DEBUG
if (sbdspdebug > 1)
- Dprintf("sbdsp_dma_input: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ printf("sbdsp_dma_input: sc=%p buf=%p cc=%d intr=%p(%p)\n",
+ addr, p, cc, intr, arg);
#endif
- if (sc->sc_channels == 2 && (cc & 1)) {
- DPRINTF(("sbdsp_dma_input: stereo input, odd bytecnt\n"));
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.modep->channels == 2 && (cc & 1)) {
+ DPRINTF(("stereo record odd bytes (%d)\n", cc));
return EIO;
}
+#endif
- if (sc->sc_dmadir != SB_DMA_IN) {
- if (ISSBPRO(sc)) {
- if (sc->sc_channels == 2) {
- if (ISJAZZ16(sc) && sc->sc_precision == 16) {
- if (sbdsp_wdsp(sc,
- JAZZ16_RECORD_STEREO) < 0) {
- goto badmode;
- }
- } else if (sbdsp_wdsp(sc,
- SB_DSP_RECORD_STEREO) < 0)
- goto badmode;
- sbdsp_mix_write(sc, SBP_INFILTER,
- (sbdsp_mix_read(sc, SBP_INFILTER) &
- ~SBP_IFILTER_MASK) | SBP_FILTER_OFF);
- } else {
- if (ISJAZZ16(sc) && sc->sc_precision == 16) {
- if (sbdsp_wdsp(sc,
- JAZZ16_RECORD_MONO) < 0)
- {
- goto badmode;
- }
- } else if (sbdsp_wdsp(sc, SB_DSP_RECORD_MONO) < 0)
- goto badmode;
- sbdsp_mix_write(sc, SBP_INFILTER,
- (sbdsp_mix_read(sc, SBP_INFILTER) &
- ~SBP_IFILTER_MASK) | sc->in_filter);
- }
+ if (sc->sc_i.modep->precision == 8) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.dmachan != sc->sc_drq8) {
+ printf("sbdsp_dma_input: prec=%d bad chan %d\n",
+ sc->sc_i.modep->precision, sc->sc_i.dmachan);
+ return EIO;
}
-
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, SB_DSP16_INPUTRATE) < 0 ||
- sbdsp_wdsp(sc, sc->sc_irate >> 8) < 0 ||
- sbdsp_wdsp(sc, sc->sc_irate) < 0)
- goto giveup;
- } else
- sbdsp_set_timeconst(sc, sc->sc_itc);
-
- sc->sc_dmadir = SB_DMA_IN;
- sc->dmaflags = DMAMODE_READ;
- if (ISSB2CLASS(sc))
- sc->dmaflags |= DMAMODE_LOOP;
+#endif
+ sc->sc_intr8 = intr;
+ sc->sc_arg8 = arg;
} else {
- /* Already started; just return. */
- if (ISSB2CLASS(sc))
- return 0;
+#ifdef DIAGNOSTIC
+ if (sc->sc_i.dmachan != sc->sc_drq16) {
+ printf("sbdsp_dma_input: prec=%d bad chan %d\n",
+ sc->sc_i.modep->precision, sc->sc_i.dmachan);
+ return EIO;
+ }
+#endif
+ sc->sc_intr16 = intr;
+ sc->sc_arg16 = arg;
}
-
- sc->dmaaddr = p;
- sc->dmacnt = ISSB2CLASS(sc) ? (NBPG/cc)*cc : cc;
- sc->dmachan = sc->sc_precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
- isadma_start(sc->dmaaddr, sc->dmacnt, sc->dmachan, sc->dmaflags);
- sc->sc_intr = intr;
- sc->sc_arg = arg;
-
- if (sc->sc_precision == 16)
- cc >>= 1;
- --cc;
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, sc->sc_precision == 16 ? SB_DSP16_RDMA_16 :
- SB_DSP16_RDMA_8) < 0 ||
- sbdsp_wdsp(sc, (sc->sc_precision == 16 ? 0x10 : 0x00) |
- (sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
- sbdsp16_wait(sc) ||
+
+ switch(sc->sc_i.run) {
+ case SB_NOTRUNNING:
+ /* Non-looping mode, not initialized */
+ sc->sc_i.run = SB_RUNNING;
+ if (!sbdsp_dma_setup_input(sc))
+ goto giveup;
+ /* fall into */
+ case SB_RUNNING:
+ /* Non-looping mode, start DMA */
+#ifdef AUDIO_DEBUG
+ if (sbdspdebug > 2)
+ printf("sbdsp_dma_input: dmastart buf=%p cc=%d chan=%d\n",
+ p, cc, sc->sc_i.dmachan);
+#endif
+ isa_dmastart(sc->sc_isa, sc->sc_i.dmachan, p,
+ cc, NULL, DMAMODE_READ, BUS_DMA_NOWAIT);
+
+ /* Start PCM in non-looping mode */
+ if ((sc->sc_model == SB_JAZZ && sc->sc_i.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_i.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_input: SB16 DMA start failed\n"));
+ DPRINTF(("sbdsp_dma_input: SB1 DMA start failed\n"));
goto giveup;
}
- } else if (ISSB2CLASS(sc)) {
- if (cc != sc->sc_last_hs_size) {
+ break;
+ case SB_DMARUNNING:
+ /* Looping mode, not initialized */
+ sc->sc_i.run = SB_PCMRUNNING;
+ if (!sbdsp_dma_setup_input(sc))
+ goto giveup;
+ if ((sc->sc_model == SB_JAZZ && sc->sc_i.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_i.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ /* Initialize looping PCM */
+ if (ISSB16CLASS(sc)) {
+#ifdef AUDIO_DEBUG
+ if (sbdspdebug > 2)
+ printf("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
+ sc->sc_i.modep->cmd, sc->sc_i.bmode, cc);
+#endif
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0 ||
+ sbdsp_wdsp(sc, sc->sc_i.bmode) < 0 ||
+ sbdsp_wdsp(sc, cc) < 0 ||
+ sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_input: SB16 DMA start failed\n"));
+ DPRINTF(("sbdsp16 input command cmd=0x%02x bmode=0x%02x cc=%d\n",
+ sc->sc_i.modep->cmd, sc->sc_i.bmode, cc));
+ goto giveup;
+ }
+ } else {
+ DPRINTF(("sbdsp_dma_input: set blocksize=%d\n", cc));
if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_input: SB2 DMA blocksize failed\n"));
+ goto giveup;
+ }
+ if (sbdsp_wdsp(sc, sc->sc_i.modep->cmd) < 0) {
DPRINTF(("sbdsp_dma_input: SB2 DMA start failed\n"));
goto giveup;
}
- sc->sc_last_hs_size = cc;
- }
- if (sbdsp_wdsp(sc,
- sc->sc_imode == SB_ADAC_LS ? SB_DSP_RDMA_LOOP :
- SB_DSP_HS_INPUT) < 0) {
- DPRINTF(("sbdsp_dma_input: SB2 DMA restart failed\n"));
- goto giveup;
- }
- } else {
- if (sbdsp_wdsp(sc, SB_DSP_RDMA) < 0 ||
- sbdsp_wdsp(sc, cc) < 0 ||
- sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_input: SB1 DMA start failed\n"));
- goto giveup;
}
+ break;
+ case SB_PCMRUNNING:
+ /* Looping mode, nothing to do */
+ break;
}
return 0;
giveup:
sbdsp_reset(sc);
return EIO;
+}
-badmode:
- DPRINTF(("sbdsp_dma_input: can't set %s mode\n",
- sc->sc_channels == 2 ? "stereo" : "mono"));
- return EIO;
+int
+sbdsp_dma_init_output(addr, buf, cc)
+ void *addr;
+ void *buf;
+ int cc;
+{
+ struct sbdsp_softc *sc = addr;
+
+ if (sc->sc_model == SB_1)
+ return 0;
+ sc->sc_o.run = SB_DMARUNNING;
+ DPRINTF(("sbdsp: dma start loop output buf=%p cc=%d chan=%d\n",
+ buf, cc, sc->sc_o.dmachan));
+ isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, buf,
+ cc, NULL, DMAMODE_WRITE | DMAMODE_LOOP, BUS_DMA_NOWAIT);
+ return 0;
+}
+
+static int
+sbdsp_dma_setup_output(sc)
+ struct sbdsp_softc *sc;
+{
+ int stereo = sc->sc_o.modep->channels == 2;
+ int cmd;
+
+ if (ISSBPRO(sc)) {
+ /* make sure we re-set stereo mixer bit when we start output. */
+ sbdsp_mix_write(sc, SBP_STEREO,
+ (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
+ (stereo ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
+ cmd = sc->sc_o.modep->cmdchan;
+ if (cmd && sbdsp_wdsp(sc, cmd) < 0)
+ return 0;
+ }
+
+ if (ISSB16CLASS(sc)) {
+ if (sbdsp16_set_rate(sc, SB_DSP16_OUTPUTRATE,
+ sc->sc_o.rate)) {
+ DPRINTF(("sbdsp_dma_setup_output: rate=%d set failed\n",
+ sc->sc_o.rate));
+ return 0;
+ }
+ } else {
+ if (sbdsp_set_timeconst(sc, sc->sc_o.tc)) {
+ DPRINTF(("sbdsp_dma_setup_output: tc=%d set failed\n",
+ sc->sc_o.rate));
+ return 0;
+ }
+ }
+ return 1;
}
int
@@ -1229,103 +1362,105 @@ sbdsp_dma_output(addr, p, cc, intr, arg)
void (*intr) __P((void *));
void *arg;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
#ifdef AUDIO_DEBUG
if (sbdspdebug > 1)
- Dprintf("sbdsp_dma_output: cc=%d 0x%x (0x%x)\n", cc, intr, arg);
+ printf("sbdsp_dma_output: sc=%p buf=%p cc=%d intr=%p(%p)\n", addr, p, cc, intr, arg);
#endif
- if (sc->sc_channels == 2 && (cc & 1)) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.modep->channels == 2 && (cc & 1)) {
DPRINTF(("stereo playback odd bytes (%d)\n", cc));
return EIO;
}
+#endif
- if (sc->sc_dmadir != SB_DMA_OUT) {
- if (ISSBPRO(sc)) {
- /* make sure we re-set stereo mixer bit when we start
- output. */
- sbdsp_mix_write(sc, SBP_STEREO,
- (sbdsp_mix_read(sc, SBP_STEREO) & ~SBP_PLAYMODE_MASK) |
- (sc->sc_channels == 2 ? SBP_PLAYMODE_STEREO : SBP_PLAYMODE_MONO));
- if (ISJAZZ16(sc)) {
- /* Yes, we write the record mode to set
- 16-bit playback mode. weird, huh? */
- if (sc->sc_precision == 16) {
- sbdsp_wdsp(sc,
- sc->sc_channels == 2 ?
- JAZZ16_RECORD_STEREO :
- JAZZ16_RECORD_MONO);
- } else {
- sbdsp_wdsp(sc,
- sc->sc_channels == 2 ?
- SB_DSP_RECORD_STEREO :
- SB_DSP_RECORD_MONO);
- }
- }
+ if (sc->sc_o.modep->precision == 8) {
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.dmachan != sc->sc_drq8) {
+ printf("sbdsp_dma_output: prec=%d bad chan %d\n",
+ sc->sc_o.modep->precision, sc->sc_o.dmachan);
+ return EIO;
}
-
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, SB_DSP16_OUTPUTRATE) < 0 ||
- sbdsp_wdsp(sc, sc->sc_orate >> 8) < 0 ||
- sbdsp_wdsp(sc, sc->sc_orate) < 0)
- goto giveup;
- } else
- sbdsp_set_timeconst(sc, sc->sc_otc);
-
- sc->sc_dmadir = SB_DMA_OUT;
- sc->dmaflags = DMAMODE_WRITE;
- if (ISSB2CLASS(sc))
- sc->dmaflags |= DMAMODE_LOOP;
+#endif
+ sc->sc_intr8 = intr;
+ sc->sc_arg8 = arg;
} else {
- /* Already started; just return. */
- if (ISSB2CLASS(sc))
- return 0;
+#ifdef DIAGNOSTIC
+ if (sc->sc_o.dmachan != sc->sc_drq16) {
+ printf("sbdsp_dma_output: prec=%d bad chan %d\n",
+ sc->sc_o.modep->precision, sc->sc_o.dmachan);
+ return EIO;
+ }
+#endif
+ sc->sc_intr16 = intr;
+ sc->sc_arg16 = arg;
}
- sc->dmaaddr = p;
- sc->dmacnt = ISSB2CLASS(sc) ? (NBPG/cc)*cc : cc;
- sc->dmachan = sc->sc_precision == 16 ? sc->sc_drq16 : sc->sc_drq8;
- isadma_start(sc->dmaaddr, sc->dmacnt, sc->dmachan, sc->dmaflags);
- sc->sc_intr = intr;
- sc->sc_arg = arg;
-
- if (sc->sc_precision == 16)
- cc >>= 1;
- --cc;
- if (ISSB16CLASS(sc)) {
- if (sbdsp_wdsp(sc, sc->sc_precision == 16 ? SB_DSP16_WDMA_16 :
- SB_DSP16_WDMA_8) < 0 ||
- sbdsp_wdsp(sc, (sc->sc_precision == 16 ? 0x10 : 0x00) |
- (sc->sc_channels == 2 ? 0x20 : 0x00)) < 0 ||
- sbdsp16_wait(sc) ||
+ switch(sc->sc_o.run) {
+ case SB_NOTRUNNING:
+ /* Non-looping mode, not initialized */
+ sc->sc_o.run = SB_RUNNING;
+ if (!sbdsp_dma_setup_output(sc))
+ goto giveup;
+ /* fall into */
+ case SB_RUNNING:
+ /* Non-looping mode, initialized. Start DMA and PCM */
+#ifdef AUDIO_DEBUG
+ if (sbdspdebug > 2)
+ printf("sbdsp: start dma out addr=%p, cc=%d, chan=%d\n",
+ p, cc, sc->sc_o.dmachan);
+#endif
+ isa_dmastart(sc->sc_isa, sc->sc_o.dmachan, p,
+ cc, NULL, DMAMODE_WRITE, BUS_DMA_NOWAIT);
+ if ((sc->sc_model == SB_JAZZ && sc->sc_o.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_o.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_output: SB16 DMA start failed\n"));
+ DPRINTF(("sbdsp_dma_output: SB1 DMA start failed\n"));
goto giveup;
}
- } else if (ISSB2CLASS(sc)) {
- if (cc != sc->sc_last_hs_size) {
+ break;
+ case SB_DMARUNNING:
+ /* Looping mode, not initialized */
+ sc->sc_o.run = SB_PCMRUNNING;
+ if (!sbdsp_dma_setup_output(sc))
+ goto giveup;
+ if ((sc->sc_model == SB_JAZZ && sc->sc_o.dmachan > 3) ||
+ (sc->sc_model != SB_JAZZ && sc->sc_o.modep->precision == 16))
+ cc >>= 1;
+ --cc;
+ /* Initialize looping PCM */
+ if (ISSB16CLASS(sc)) {
+ DPRINTF(("sbdsp_dma_output: SB16 cmd=0x%02x bmode=0x%02x cc=%d\n",
+ sc->sc_o.modep->cmd,sc->sc_o.bmode, cc));
+ if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0 ||
+ sbdsp_wdsp(sc, sc->sc_o.bmode) < 0 ||
+ sbdsp_wdsp(sc, cc) < 0 ||
+ sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_output: SB16 DMA start failed\n"));
+ goto giveup;
+ }
+ } else {
+ DPRINTF(("sbdsp_dma_output: set blocksize=%d\n", cc));
if (sbdsp_wdsp(sc, SB_DSP_BLOCKSIZE) < 0 ||
sbdsp_wdsp(sc, cc) < 0 ||
sbdsp_wdsp(sc, cc >> 8) < 0) {
+ DPRINTF(("sbdsp_dma_output: SB2 DMA blocksize failed\n"));
+ goto giveup;
+ }
+ if (sbdsp_wdsp(sc, sc->sc_o.modep->cmd) < 0) {
DPRINTF(("sbdsp_dma_output: SB2 DMA start failed\n"));
goto giveup;
}
- sc->sc_last_hs_size = cc;
- }
- if (sbdsp_wdsp(sc,
- sc->sc_omode == SB_ADAC_LS ? SB_DSP_WDMA_LOOP :
- SB_DSP_HS_OUTPUT) < 0) {
- DPRINTF(("sbdsp_dma_output: SB2 DMA restart failed\n"));
- goto giveup;
- }
- } else {
- if (sbdsp_wdsp(sc, SB_DSP_WDMA) < 0 ||
- sbdsp_wdsp(sc, cc) < 0 ||
- sbdsp_wdsp(sc, cc >> 8) < 0) {
- DPRINTF(("sbdsp_dma_output: SB1 DMA start failed\n"));
- goto giveup;
}
+ break;
+ case SB_PCMRUNNING:
+ /* Looping mode, nothing to do */
+ break;
}
return 0;
@@ -1338,44 +1473,61 @@ giveup:
* Only the DSP unit on the sound blaster generates interrupts.
* There are three cases of interrupt: reception of a midi byte
* (when mode is enabled), completion of dma transmission, or
- * completion of a dma reception. The three modes are mutually
- * exclusive so we know a priori which event has occurred.
+ * completion of a dma reception.
+ *
+ * If there is interrupt sharing or a spurious interrupt occurs
+ * there is no way to distinguish this on an SB2. So if you have
+ * an SB2 and experience problems, buy an SB16 (it's only $40).
*/
int
sbdsp_intr(arg)
void *arg;
{
- register struct sbdsp_softc *sc = arg;
- u_char x;
+ struct sbdsp_softc *sc = arg;
+ int loop = sc->sc_model != SB_1;
+ u_char irq;
#ifdef AUDIO_DEBUG
if (sbdspdebug > 1)
- Dprintf("sbdsp_intr: intr=0x%x\n", sc->sc_intr);
+ printf("sbdsp_intr: intr8=%p, intr16=%p\n",
+ sc->sc_intr8, sc->sc_intr16);
#endif
if (ISSB16CLASS(sc)) {
- x = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
- if ((x & 3) == 0)
+ irq = sbdsp_mix_read(sc, SBP_IRQ_STATUS);
+ if ((irq & (SBP_IRQ_DMA8 | SBP_IRQ_DMA16)) == 0) {
+ DPRINTF(("sbdsp_intr: Spurious interrupt 0x%x\n", irq));
return 0;
+ }
+ } else {
+ if (!loop && !isa_dmafinished(sc->sc_isa, sc->sc_drq8))
+ return 0;
+ irq = SBP_IRQ_DMA8;
}
- /* isadma_finished() moved to isadma.c */
sc->sc_interrupts++;
- delay(10);
+ delay(10); /* XXX why? */
#if 0
if (sc->sc_mintr != 0) {
x = sbdsp_rdsp(sc);
(*sc->sc_mintr)(sc->sc_arg, x);
} else
#endif
- if (sc->sc_intr != 0) {
- /* clear interrupt */
- x = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
- sc->sc_precision == 16 ? SBP_DSP_IRQACK16 :
- SBP_DSP_IRQACK8);
- if (!ISSB2CLASS(sc))
- isadma_done(sc->dmachan);
- (*sc->sc_intr)(sc->sc_arg);
- } else {
- return 0;
+ if (sc->sc_intr8 == 0 && sc->sc_intr16 == 0) {
+ DPRINTF(("sbdsp_intr: Unexpected interrupt 0x%x\n", irq));
+ /* XXX return 0;*/ /* Did not expect an interrupt */
+ }
+
+ /* clear interrupt */
+ if (irq & SBP_IRQ_DMA8) {
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK8);
+ if (!loop)
+ isa_dmadone(sc->sc_isa, sc->sc_drq8);
+ if (sc->sc_intr8)
+ (*sc->sc_intr8)(sc->sc_arg8);
+ }
+ if (irq & SBP_IRQ_DMA16) {
+ bus_space_read_1(sc->sc_iot, sc->sc_ioh, SBP_DSP_IRQACK16);
+ if (sc->sc_intr16)
+ (*sc->sc_intr16)(sc->sc_arg16);
}
return 1;
}
@@ -1419,13 +1571,120 @@ sbdsp_midi_output(sc, v)
}
#endif
-int
-sbdsp_setfd(addr, flag)
- void *addr;
- int flag;
+/* Mask a value 0-255, but round it first */
+#define MAXVAL 256
+static int
+sbdsp_adjust(val, mask)
+ int val, mask;
{
- /* Can't do full-duplex */
- return(ENOTTY);
+ val += (MAXVAL - mask) >> 1;
+ if (val >= MAXVAL)
+ val = MAXVAL-1;
+ return val & mask;
+}
+
+void
+sbdsp_set_mixer_gain(sc, port)
+ struct sbdsp_softc *sc;
+ int port;
+{
+ int src, gain;
+
+ switch(sc->sc_mixer_model) {
+ case SBM_NONE:
+ return;
+ case SBM_CT1335:
+ gain = SB_1335_GAIN(sc->gain[port][SB_LEFT]);
+ switch(port) {
+ case SB_MASTER_VOL:
+ src = SBP_1335_MASTER_VOL;
+ break;
+ case SB_MIDI_VOL:
+ src = SBP_1335_MIDI_VOL;
+ break;
+ case SB_CD_VOL:
+ src = SBP_1335_CD_VOL;
+ break;
+ case SB_VOICE_VOL:
+ src = SBP_1335_VOICE_VOL;
+ gain = SB_1335_MASTER_GAIN(sc->gain[port][SB_LEFT]);
+ break;
+ default:
+ return;
+ }
+ sbdsp_mix_write(sc, src, gain);
+ break;
+ case SBM_CT1345:
+ gain = SB_STEREO_GAIN(sc->gain[port][SB_LEFT],
+ sc->gain[port][SB_RIGHT]);
+ switch (port) {
+ case SB_MIC_VOL:
+ src = SBP_MIC_VOL;
+ gain = SB_MIC_GAIN(sc->gain[port][SB_LEFT]);
+ break;
+ case SB_MASTER_VOL:
+ src = SBP_MASTER_VOL;
+ break;
+ case SB_LINE_IN_VOL:
+ src = SBP_LINE_VOL;
+ break;
+ case SB_VOICE_VOL:
+ src = SBP_VOICE_VOL;
+ break;
+ case SB_MIDI_VOL:
+ src = SBP_MIDI_VOL;
+ break;
+ case SB_CD_VOL:
+ src = SBP_CD_VOL;
+ break;
+ default:
+ return;
+ }
+ sbdsp_mix_write(sc, src, gain);
+ break;
+ case SBM_CT1XX5:
+ case SBM_CT1745:
+ switch (port) {
+ case SB_MIC_VOL:
+ src = SB16P_MIC_L;
+ break;
+ case SB_MASTER_VOL:
+ src = SB16P_MASTER_L;
+ break;
+ case SB_LINE_IN_VOL:
+ src = SB16P_LINE_L;
+ break;
+ case SB_VOICE_VOL:
+ src = SB16P_VOICE_L;
+ break;
+ case SB_MIDI_VOL:
+ src = SB16P_MIDI_L;
+ break;
+ case SB_CD_VOL:
+ src = SB16P_CD_L;
+ break;
+ case SB_INPUT_GAIN:
+ src = SB16P_INPUT_GAIN_L;
+ break;
+ case SB_OUTPUT_GAIN:
+ src = SB16P_OUTPUT_GAIN_L;
+ break;
+ case SB_TREBLE:
+ src = SB16P_TREBLE_L;
+ break;
+ case SB_BASS:
+ src = SB16P_BASS_L;
+ break;
+ case SB_PCSPEAKER:
+ sbdsp_mix_write(sc, SB16P_PCSPEAKER, sc->gain[port][SB_LEFT]);
+ return;
+ default:
+ return;
+ }
+ sbdsp_mix_write(sc, src, sc->gain[port][SB_LEFT]);
+ sbdsp_mix_write(sc, SB16P_L_TO_R(src), sc->gain[port][SB_RIGHT]);
+ break;
+ }
}
int
@@ -1433,27 +1692,46 @@ sbdsp_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct sbdsp_softc *sc = addr;
- int src, gain;
+ struct sbdsp_softc *sc = addr;
+ int lgain, rgain;
+ int mask, bits;
+ int lmask, rmask, lbits, rbits;
+ int mute, swap;
DPRINTF(("sbdsp_mixer_set_port: port=%d num_channels=%d\n", cp->dev,
cp->un.value.num_channels));
- if (!ISSBPROCLASS(sc))
+ if (sc->sc_mixer_model == SBM_NONE)
return EINVAL;
- /*
- * Everything is a value except for SBPro BASS/TREBLE and
- * RECORD_SOURCE
- */
switch (cp->dev) {
- case SB_SPEAKER:
- cp->dev = SB_MASTER_VOL;
- case SB_MIC_PORT:
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
+ case SB_TREBLE:
+ case SB_BASS:
+ if (sc->sc_mixer_model == SBM_CT1345 ||
+ sc->sc_mixer_model == SBM_CT1XX5) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ switch (cp->dev) {
+ case SB_TREBLE:
+ sbdsp_set_ifilter(addr, cp->un.ord ? SB_TREBLE : 0);
+ return 0;
+ case SB_BASS:
+ sbdsp_set_ifilter(addr, cp->un.ord ? SB_BASS : 0);
+ return 0;
+ }
+ }
+ case SB_PCSPEAKER:
+ case SB_INPUT_GAIN:
+ case SB_OUTPUT_GAIN:
+ if (!ISSBM1745(sc))
+ return EINVAL;
+ case SB_MIC_VOL:
+ case SB_LINE_IN_VOL:
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return EINVAL;
+ case SB_VOICE_VOL:
+ case SB_MIDI_VOL:
+ case SB_CD_VOL:
case SB_MASTER_VOL:
if (cp->type != AUDIO_MIXER_VALUE)
return EINVAL;
@@ -1465,83 +1743,136 @@ sbdsp_mixer_set_port(addr, cp)
*/
switch (cp->dev) {
- case SB_MIC_PORT:
+ case SB_MIC_VOL:
if (cp->un.value.num_channels != 1)
return EINVAL;
- /* handle funny microphone gain */
- gain = SBP_AGAIN_TO_MICGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
+ lgain = rgain = SB_ADJUST_MIC_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
break;
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
- case SB_MASTER_VOL:
+ case SB_PCSPEAKER:
+ if (cp->un.value.num_channels != 1)
+ return EINVAL;
+ /* fall into */
+ case SB_INPUT_GAIN:
+ case SB_OUTPUT_GAIN:
+ lgain = rgain = SB_ADJUST_2_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
+ break;
+ default:
switch (cp->un.value.num_channels) {
case 1:
- gain = sbdsp_mono_vol(SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]));
+ lgain = rgain = SB_ADJUST_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO]);
break;
case 2:
- gain = sbdsp_stereo_vol(SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]),
- SBP_AGAIN_TO_SBGAIN(cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]));
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return EINVAL;
+ lgain = SB_ADJUST_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT]);
+ rgain = SB_ADJUST_GAIN(sc,
+ cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT]);
break;
default:
return EINVAL;
}
break;
- default:
- return EINVAL;
}
+ sc->gain[cp->dev][SB_LEFT] = lgain;
+ sc->gain[cp->dev][SB_RIGHT] = rgain;
- switch (cp->dev) {
- case SB_MIC_PORT:
- src = SBP_MIC_VOL;
- break;
- case SB_MASTER_VOL:
- src = SBP_MASTER_VOL;
- break;
- case SB_LINE_IN_PORT:
- src = SBP_LINE_VOL;
- break;
- case SB_DAC_PORT:
- src = SBP_DAC_VOL;
- break;
- case SB_FM_PORT:
- src = SBP_FM_VOL;
- break;
- case SB_CD_PORT:
- src = SBP_CD_VOL;
- break;
- default:
- return EINVAL;
+ sbdsp_set_mixer_gain(sc, cp->dev);
+ break;
+
+ case SB_RECORD_SOURCE:
+ if (ISSBM1745(sc)) {
+ if (cp->type != AUDIO_MIXER_SET)
+ return EINVAL;
+ return sbdsp_set_in_ports(sc, cp->un.mask);
+ } else {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ sc->in_port = cp->un.ord;
+ return sbdsp_set_in_ports(sc, 1 << cp->un.ord);
}
+ break;
- sbdsp_mix_write(sc, src, gain);
- sc->gain[cp->dev] = gain;
+ case SB_AGC:
+ if (!ISSBM1745(sc) || cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ sbdsp_mix_write(sc, SB16P_AGC, cp->un.ord & 1);
break;
- case SB_TREBLE:
- case SB_BASS:
- case SB_RECORD_SOURCE:
+ case SB_CD_OUT_MUTE:
+ mask = SB16P_SW_CD;
+ goto omute;
+ case SB_MIC_OUT_MUTE:
+ mask = SB16P_SW_MIC;
+ goto omute;
+ case SB_LINE_OUT_MUTE:
+ mask = SB16P_SW_LINE;
+ omute:
if (cp->type != AUDIO_MIXER_ENUM)
return EINVAL;
+ bits = sbdsp_mix_read(sc, SB16P_OSWITCH);
+ sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
+ if (cp->un.ord)
+ bits = bits & ~mask;
+ else
+ bits = bits | mask;
+ sbdsp_mix_write(sc, SB16P_OSWITCH, bits);
+ break;
- switch (cp->dev) {
- case SB_TREBLE:
- return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_TREBLE_EQ : 0);
- case SB_BASS:
- return sbdsp_set_ifilter(addr, cp->un.ord ? SBP_BASS_EQ : 0);
- case SB_RECORD_SOURCE:
- return sbdsp_set_in_port(addr, cp->un.ord);
+ case SB_MIC_IN_MUTE:
+ case SB_MIC_SWAP:
+ lmask = rmask = SB16P_SW_MIC;
+ goto imute;
+ case SB_CD_IN_MUTE:
+ case SB_CD_SWAP:
+ lmask = SB16P_SW_CD_L;
+ rmask = SB16P_SW_CD_R;
+ goto imute;
+ case SB_LINE_IN_MUTE:
+ case SB_LINE_SWAP:
+ lmask = SB16P_SW_LINE_L;
+ rmask = SB16P_SW_LINE_R;
+ goto imute;
+ case SB_MIDI_IN_MUTE:
+ case SB_MIDI_SWAP:
+ lmask = SB16P_SW_MIDI_L;
+ rmask = SB16P_SW_MIDI_R;
+ imute:
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return EINVAL;
+ mask = lmask | rmask;
+ lbits = sbdsp_mix_read(sc, SB16P_ISWITCH_L) & ~mask;
+ rbits = sbdsp_mix_read(sc, SB16P_ISWITCH_R) & ~mask;
+ sc->gain[cp->dev][SB_LR] = cp->un.ord != 0;
+ if (SB_IS_IN_MUTE(cp->dev)) {
+ mute = cp->dev;
+ swap = mute - SB_CD_IN_MUTE + SB_CD_SWAP;
+ } else {
+ swap = cp->dev;
+ mute = swap + SB_CD_IN_MUTE - SB_CD_SWAP;
}
-
+ if (sc->gain[swap][SB_LR]) {
+ mask = lmask;
+ lmask = rmask;
+ rmask = mask;
+ }
+ if (!sc->gain[mute][SB_LR]) {
+ lbits = lbits | lmask;
+ rbits = rbits | rmask;
+ }
+ sbdsp_mix_write(sc, SB16P_ISWITCH_L, lbits);
+ sbdsp_mix_write(sc, SB16P_ISWITCH_L, rbits);
break;
default:
return EINVAL;
}
- return (0);
+ return 0;
}
int
@@ -1549,223 +1880,441 @@ sbdsp_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct sbdsp_softc *sc = addr;
- int gain;
+ struct sbdsp_softc *sc = addr;
- DPRINTF(("sbdsp_mixer_get_port: port=%d", cp->dev));
+ DPRINTF(("sbdsp_mixer_get_port: port=%d\n", cp->dev));
- if (!ISSBPROCLASS(sc))
+ if (sc->sc_mixer_model == SBM_NONE)
return EINVAL;
switch (cp->dev) {
- case SB_SPEAKER:
- cp->dev = SB_MASTER_VOL;
- case SB_MIC_PORT:
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
+ case SB_TREBLE:
+ case SB_BASS:
+ if (sc->sc_mixer_model == SBM_CT1345 ||
+ sc->sc_mixer_model == SBM_CT1XX5) {
+ switch (cp->dev) {
+ case SB_TREBLE:
+ cp->un.ord = sbdsp_get_ifilter(addr) == SB_TREBLE;
+ return 0;
+ case SB_BASS:
+ cp->un.ord = sbdsp_get_ifilter(addr) == SB_BASS;
+ return 0;
+ }
+ }
+ case SB_PCSPEAKER:
+ case SB_INPUT_GAIN:
+ case SB_OUTPUT_GAIN:
+ if (!ISSBM1745(sc))
+ return EINVAL;
+ case SB_MIC_VOL:
+ case SB_LINE_IN_VOL:
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return EINVAL;
+ case SB_VOICE_VOL:
+ case SB_MIDI_VOL:
+ case SB_CD_VOL:
case SB_MASTER_VOL:
- gain = sc->gain[cp->dev];
-
switch (cp->dev) {
- case SB_MIC_PORT:
+ case SB_MIC_VOL:
+ case SB_PCSPEAKER:
if (cp->un.value.num_channels != 1)
return EINVAL;
-
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = SBP_MICGAIN_TO_AGAIN(gain);
- break;
- case SB_LINE_IN_PORT:
- case SB_DAC_PORT:
- case SB_FM_PORT:
- case SB_CD_PORT:
- case SB_MASTER_VOL:
+ /* fall into */
+ default:
switch (cp->un.value.num_channels) {
case 1:
- cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] = SBP_SBGAIN_TO_AGAIN(gain);
+ cp->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
+ sc->gain[cp->dev][SB_LEFT];
break;
case 2:
- cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = SBP_LEFTGAIN(gain);
- cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = SBP_RIGHTGAIN(gain);
+ cp->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
+ sc->gain[cp->dev][SB_LEFT];
+ cp->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
+ sc->gain[cp->dev][SB_RIGHT];
break;
default:
return EINVAL;
}
break;
}
-
break;
- case SB_TREBLE:
- case SB_BASS:
case SB_RECORD_SOURCE:
- switch (cp->dev) {
- case SB_TREBLE:
- cp->un.ord = sbdsp_get_ifilter(addr) == SBP_TREBLE_EQ;
- return 0;
- case SB_BASS:
- cp->un.ord = sbdsp_get_ifilter(addr) == SBP_BASS_EQ;
- return 0;
- case SB_RECORD_SOURCE:
- cp->un.ord = sbdsp_get_in_port(addr);
- return 0;
- }
+ if (ISSBM1745(sc))
+ cp->un.mask = sc->in_mask;
+ else
+ cp->un.ord = sc->in_port;
+ break;
+ case SB_AGC:
+ if (!ISSBM1745(sc))
+ return EINVAL;
+ cp->un.ord = sbdsp_mix_read(sc, SB16P_AGC);
+ break;
+
+ case SB_CD_IN_MUTE:
+ case SB_MIC_IN_MUTE:
+ case SB_LINE_IN_MUTE:
+ case SB_MIDI_IN_MUTE:
+ case SB_CD_SWAP:
+ case SB_MIC_SWAP:
+ case SB_LINE_SWAP:
+ case SB_MIDI_SWAP:
+ case SB_CD_OUT_MUTE:
+ case SB_MIC_OUT_MUTE:
+ case SB_LINE_OUT_MUTE:
+ cp->un.ord = sc->gain[cp->dev][SB_LR];
break;
default:
return EINVAL;
}
- return (0);
+ return 0;
}
int
sbdsp_mixer_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
- register struct sbdsp_softc *sc = addr;
+ struct sbdsp_softc *sc = addr;
+ int chan, class, is1745;
- DPRINTF(("sbdsp_mixer_query_devinfo: index=%d\n", dip->index));
+ DPRINTF(("sbdsp_mixer_query_devinfo: model=%d index=%d\n",
+ sc->sc_mixer_model, dip->index));
+
+ if (sc->sc_mixer_model == SBM_NONE)
+ return ENXIO;
+
+ chan = sc->sc_mixer_model == SBM_CT1335 ? 1 : 2;
+ is1745 = ISSBM1745(sc);
+ class = is1745 ? SB_INPUT_CLASS : SB_OUTPUT_CLASS;
switch (dip->index) {
- case SB_MIC_PORT:
+ case SB_MASTER_VOL:
dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNmaster);
+ dip->un.v.num_channels = chan;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+ case SB_MIDI_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmicrophone);
- dip->un.v.num_channels = 1;
+ dip->next = is1745 ? SB_MIDI_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNfmsynth);
+ dip->un.v.num_channels = chan;
strcpy(dip->un.v.units.name, AudioNvolume);
return 0;
-
- case SB_SPEAKER:
+ case SB_CD_VOL:
dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->mixer_class = class;
dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNspeaker);
- dip->un.v.num_channels = 1;
+ dip->next = is1745 ? SB_CD_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNcd);
+ dip->un.v.num_channels = chan;
strcpy(dip->un.v.units.name, AudioNvolume);
return 0;
-
- case SB_INPUT_CLASS:
- dip->type = AUDIO_MIXER_CLASS;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ case SB_VOICE_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNdac);
+ dip->un.v.num_channels = chan;
+ strcpy(dip->un.v.units.name, AudioNvolume);
return 0;
-
case SB_OUTPUT_CLASS:
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = SB_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCOutputs);
+ strcpy(dip->label.name, AudioCoutputs);
return 0;
}
- if (ISSBPROCLASS(sc)) {
- switch (dip->index) {
- case SB_LINE_IN_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNline);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- return 0;
-
- case SB_DAC_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNdac);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- return 0;
-
- case SB_CD_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNcd);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- return 0;
+ if (sc->sc_mixer_model == SBM_CT1335)
+ return ENXIO;
- case SB_FM_PORT:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNfmsynth);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- return 0;
+ switch (dip->index) {
+ case SB_MIC_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = is1745 ? SB_MIC_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNmicrophone);
+ dip->un.v.num_channels = 1;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
- case SB_MASTER_VOL:
- dip->type = AUDIO_MIXER_VALUE;
- dip->mixer_class = SB_OUTPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNvolume);
- dip->un.v.num_channels = 2;
- strcpy(dip->un.v.units.name, AudioNvolume);
- return 0;
+ case SB_LINE_IN_VOL:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = class;
+ dip->prev = AUDIO_MIXER_LAST;
+ dip->next = is1745 ? SB_LINE_IN_MUTE : AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNline);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
- case SB_RECORD_SOURCE:
- dip->mixer_class = SB_RECORD_CLASS;
+ case SB_RECORD_SOURCE:
+ dip->mixer_class = SB_RECORD_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNsource);
+ if (ISSBM1745(sc)) {
+ dip->type = AUDIO_MIXER_SET;
+ dip->un.s.num_mem = 4;
+ strcpy(dip->un.s.member[0].label.name, AudioNmicrophone);
+ dip->un.s.member[0].mask = 1 << SB_MIC_VOL;
+ strcpy(dip->un.s.member[1].label.name, AudioNcd);
+ dip->un.s.member[1].mask = 1 << SB_CD_VOL;
+ strcpy(dip->un.s.member[2].label.name, AudioNline);
+ dip->un.s.member[2].mask = 1 << SB_LINE_IN_VOL;
+ strcpy(dip->un.s.member[3].label.name, AudioNfmsynth);
+ dip->un.s.member[3].mask = 1 << SB_MIDI_VOL;
+ } else {
dip->type = AUDIO_MIXER_ENUM;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNsource);
dip->un.e.num_mem = 3;
strcpy(dip->un.e.member[0].label.name, AudioNmicrophone);
- dip->un.e.member[0].ord = SB_MIC_PORT;
+ dip->un.e.member[0].ord = SB_MIC_VOL;
strcpy(dip->un.e.member[1].label.name, AudioNcd);
- dip->un.e.member[1].ord = SB_CD_PORT;
+ dip->un.e.member[1].ord = SB_CD_VOL;
strcpy(dip->un.e.member[2].label.name, AudioNline);
- dip->un.e.member[2].ord = SB_LINE_IN_PORT;
- return 0;
+ dip->un.e.member[2].ord = SB_LINE_IN_VOL;
+ }
+ return 0;
- case SB_BASS:
+ case SB_BASS:
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNbass);
+ if (sc->sc_mixer_model == SBM_CT1745) {
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_EQUALIZATION_CLASS;
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNbass);
+ } else {
dip->type = AUDIO_MIXER_ENUM;
dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNbass);
dip->un.e.num_mem = 2;
strcpy(dip->un.e.member[0].label.name, AudioNoff);
dip->un.e.member[0].ord = 0;
strcpy(dip->un.e.member[1].label.name, AudioNon);
dip->un.e.member[1].ord = 1;
- return 0;
-
- case SB_TREBLE:
+ }
+ return 0;
+
+ case SB_TREBLE:
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNtreble);
+ if (sc->sc_mixer_model == SBM_CT1745) {
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_EQUALIZATION_CLASS;
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNtreble);
+ } else {
dip->type = AUDIO_MIXER_ENUM;
dip->mixer_class = SB_INPUT_CLASS;
- dip->prev = AUDIO_MIXER_LAST;
- dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNtreble);
dip->un.e.num_mem = 2;
strcpy(dip->un.e.member[0].label.name, AudioNoff);
dip->un.e.member[0].ord = 0;
strcpy(dip->un.e.member[1].label.name, AudioNon);
dip->un.e.member[1].ord = 1;
- return 0;
+ }
+ return 0;
+
+ case SB_RECORD_CLASS: /* record source class */
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_RECORD_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCrecord);
+ return 0;
+
+ case SB_INPUT_CLASS:
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCinputs);
+ return 0;
+
+ }
+
+ if (sc->sc_mixer_model == SBM_CT1345)
+ return ENXIO;
+
+ switch(dip->index) {
+ case SB_PCSPEAKER:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, "pc_speaker");
+ dip->un.v.num_channels = 1;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_INPUT_GAIN:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNinput);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_OUTPUT_GAIN:
+ dip->type = AUDIO_MIXER_VALUE;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioNoutput);
+ dip->un.v.num_channels = 2;
+ strcpy(dip->un.v.units.name, AudioNvolume);
+ return 0;
+
+ case SB_AGC:
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->mixer_class = SB_INPUT_CLASS;
+ dip->prev = dip->next = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, "AGC");
+ dip->un.e.num_mem = 2;
+ strcpy(dip->un.e.member[0].label.name, AudioNoff);
+ dip->un.e.member[0].ord = 0;
+ strcpy(dip->un.e.member[1].label.name, AudioNon);
+ dip->un.e.member[1].ord = 1;
+ return 0;
+
+ case SB_EQUALIZATION_CLASS:
+ dip->type = AUDIO_MIXER_CLASS;
+ dip->mixer_class = SB_EQUALIZATION_CLASS;
+ dip->next = dip->prev = AUDIO_MIXER_LAST;
+ strcpy(dip->label.name, AudioCequalization);
+ return 0;
+
+ case SB_CD_IN_MUTE:
+ dip->prev = SB_CD_VOL;
+ dip->next = SB_CD_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_MIC_IN_MUTE:
+ dip->prev = SB_MIC_VOL;
+ dip->next = SB_MIC_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_LINE_IN_MUTE:
+ dip->prev = SB_LINE_IN_VOL;
+ dip->next = SB_LINE_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_MIDI_IN_MUTE:
+ dip->prev = SB_MIDI_VOL;
+ dip->next = SB_MIDI_SWAP;
+ dip->mixer_class = SB_INPUT_CLASS;
+ goto mute;
+
+ case SB_CD_SWAP:
+ dip->prev = SB_CD_IN_MUTE;
+ dip->next = SB_CD_OUT_MUTE;
+ goto swap;
+
+ case SB_MIC_SWAP:
+ dip->prev = SB_MIC_IN_MUTE;
+ dip->next = SB_MIC_OUT_MUTE;
+ goto swap;
+
+ case SB_LINE_SWAP:
+ dip->prev = SB_LINE_IN_MUTE;
+ dip->next = SB_LINE_OUT_MUTE;
+ goto swap;
+
+ case SB_MIDI_SWAP:
+ dip->prev = SB_MIDI_IN_MUTE;
+ dip->next = AUDIO_MIXER_LAST;
+ swap:
+ dip->mixer_class = SB_INPUT_CLASS;
+ strcpy(dip->label.name, AudioNswap);
+ goto mute1;
+
+ case SB_CD_OUT_MUTE:
+ dip->prev = SB_CD_SWAP;
+ dip->next = AUDIO_MIXER_LAST;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ goto mute;
+
+ case SB_MIC_OUT_MUTE:
+ dip->prev = SB_MIC_SWAP;
+ dip->next = AUDIO_MIXER_LAST;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ goto mute;
+
+ case SB_LINE_OUT_MUTE:
+ dip->prev = SB_LINE_SWAP;
+ dip->next = AUDIO_MIXER_LAST;
+ dip->mixer_class = SB_OUTPUT_CLASS;
+ mute:
+ strcpy(dip->label.name, AudioNmute);
+ mute1:
+ dip->type = AUDIO_MIXER_ENUM;
+ dip->un.e.num_mem = 2;
+ strcpy(dip->un.e.member[0].label.name, AudioNoff);
+ dip->un.e.member[0].ord = 0;
+ strcpy(dip->un.e.member[1].label.name, AudioNon);
+ dip->un.e.member[1].ord = 1;
+ return 0;
- case SB_RECORD_CLASS: /* record source class */
- dip->type = AUDIO_MIXER_CLASS;
- dip->mixer_class = SB_RECORD_CLASS;
- dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCRecord);
- return 0;
- }
}
return ENXIO;
}
+
+void *
+sb_malloc(addr, size, pool, flags)
+ void *addr;
+ unsigned long size;
+ int pool;
+ int flags;
+{
+ struct sbdsp_softc *sc = addr;
+
+ return isa_malloc(sc->sc_isa, 4, size, pool, flags);
+}
+
+void
+sb_free(addr, ptr, pool)
+ void *addr;
+ void *ptr;
+ int pool;
+{
+ isa_free(ptr, pool);
+}
+
+unsigned long
+sb_round(addr, size)
+ void *addr;
+ unsigned long size;
+{
+ if (size > MAX_ISADMA)
+ size = MAX_ISADMA;
+ return size;
+}
+
+int
+sb_mappage(addr, mem, off, prot)
+ void *addr;
+ void *mem;
+ int off;
+ int prot;
+{
+ return isa_mappage(mem, off, prot);
+}
+
+int
+sbdsp_get_props(addr)
+ void *addr;
+{
+ struct sbdsp_softc *sc = addr;
+ return AUDIO_PROP_MMAP |
+ (sc->sc_fullduplex ? AUDIO_PROP_FULLDUPLEX : 0);
+}
diff --git a/sys/dev/isa/sbdspvar.h b/sys/dev/isa/sbdspvar.h
index 5279e227ef5..c70a012f447 100644
--- a/sys/dev/isa/sbdspvar.h
+++ b/sys/dev/isa/sbdspvar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sbdspvar.h,v 1.7 1997/07/10 23:06:38 provos Exp $ */
-/* $NetBSD: sbdspvar.h,v 1.13 1996/04/29 20:28:50 christos Exp $ */
+/* $OpenBSD: sbdspvar.h,v 1.8 1998/04/26 21:03:01 provos Exp $ */
+/* $NetBSD: sbdspvar.h,v 1.33 1997/10/19 07:42:44 augustss Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -35,29 +35,43 @@
*
*/
-#define SB_MIC_PORT 0
-#define SB_SPEAKER 1
-#define SB_INPUT_CLASS 2
-#define SB_OUTPUT_CLASS 3
-#define SB_LINE_IN_PORT 4
-#define SB_DAC_PORT 5
-#define SB_FM_PORT 6
-#define SB_CD_PORT 7
-#define SB_MASTER_VOL 8
-#define SB_TREBLE 9
-#define SB_BASS 10
-#define SB_NDEVS 11 /* XXX include classes above for
- contiguous number space on
- original SB */
+#define SB_MASTER_VOL 0
+#define SB_MIDI_VOL 1
+#define SB_CD_VOL 2
+#define SB_VOICE_VOL 3
+#define SB_OUTPUT_CLASS 4
-/*#define SB_OUTPUT_MODE 9
-#define SB_SPKR_MONO 0
-#define SB_SPKR_STEREO 1*/
+#define SB_MIC_VOL 5
+#define SB_LINE_IN_VOL 6
+#define SB_RECORD_SOURCE 7
+#define SB_TREBLE 8
+#define SB_BASS 9
+#define SB_RECORD_CLASS 10
+#define SB_INPUT_CLASS 11
-#define SB_RECORD_SOURCE 11
+#define SB_PCSPEAKER 12
+#define SB_INPUT_GAIN 13
+#define SB_OUTPUT_GAIN 14
+#define SB_AGC 15
+#define SB_EQUALIZATION_CLASS 16
-#define SB_RECORD_CLASS 12
+#define SB_CD_IN_MUTE 17
+#define SB_MIC_IN_MUTE 18
+#define SB_LINE_IN_MUTE 19
+#define SB_MIDI_IN_MUTE 20
+#define SB_CD_SWAP 21
+#define SB_MIC_SWAP 22
+#define SB_LINE_SWAP 23
+#define SB_MIDI_SWAP 24
+
+#define SB_CD_OUT_MUTE 25
+#define SB_MIC_OUT_MUTE 26
+#define SB_LINE_OUT_MUTE 27
+
+#define SB_NDEVS 28
+
+#define SB_IS_IN_MUTE(x) ((x) < SB_CD_SWAP)
/*
* Software state, per SoundBlaster card.
@@ -86,70 +100,75 @@ struct sbdsp_softc {
int sc_drq8; /* DMA (8-bit) */
int sc_drq16; /* DMA (16-bit) */
+ struct device *sc_isa; /* pointer to ISA parent */
+
u_short sc_open; /* reference count of open calls */
+ int sc_openflags; /* flags used on open */
+ u_char sc_fullduplex; /* can do full duplex */
- u_int gain[SB_NDEVS]; /* kept in SB levels: right/left each
- in a nibble */
+ u_char gain[SB_NDEVS][2]; /* kept in input levels */
+#define SB_LEFT 0
+#define SB_RIGHT 1
+#define SB_LR 0
- u_int out_port; /* output port */
- u_int in_port; /* input port */
+ u_int in_mask; /* input ports */
+ u_int in_port; /* XXX needed for MI interface */
u_int in_filter; /* one of SB_TREBLE_EQ, SB_BASS_EQ, 0 */
u_int spkr_state; /* non-null is on */
- int sc_irate, sc_itc; /* Sample rate for input */
- int sc_orate, sc_otc; /* ...and output */
-
- int sc_imode;
- int sc_omode;
-#define SB_ADAC_LS 0
-#define SB_ADAC_HS 1
+ struct sbdsp_state {
+ u_int rate; /* Sample rate */
+ u_char tc; /* Time constant */
+ struct sbmode *modep;
+ u_char bmode;
+ int dmachan; /* DMA channel */
+ u_char run;
+#define SB_NOTRUNNING 0 /* Not running, not initialized */
+#define SB_DMARUNNING 1 /* DMA has been initialized */
+#define SB_PCMRUNNING 2 /* DMA&PCM running (looping mode) */
+#define SB_RUNNING 3 /* non-looping mode */
+ } sc_i, sc_o; /* Input and output state */
u_long sc_interrupts; /* number of interrupts taken */
- void (*sc_intr)(void*); /* dma completion intr handler */
+ void (*sc_intr8)(void*); /* dma completion intr handler */
+ void *sc_arg8; /* arg for sc_intr8() */
+ void (*sc_intr16)(void*); /* dma completion intr handler */
+ void *sc_arg16; /* arg for sc_intr16() */
void (*sc_mintr)(void*, int);/* midi input intr handler */
- void *sc_arg; /* arg for sc_intr() */
-
- int dmaflags;
- caddr_t dmaaddr;
- vm_size_t dmacnt;
- int dmachan; /* active DMA channel */
- int sc_last_hs_size; /* last HS dma size */
- u_int sc_encoding; /* ulaw/linear -- keep track */
- u_int sc_precision; /* size of samples */
- int sc_channels; /* # of channels */
-
- int sc_dmadir; /* DMA direction */
-#define SB_DMA_NONE 0
-#define SB_DMA_IN 1
-#define SB_DMA_OUT 2
+ u_int sc_mixer_model;
+#define SBM_NONE 0
+#define SBM_CT1335 1
+#define SBM_CT1345 2
+#define SBM_CT1XX5 3
+#define SBM_CT1745 4
+#define ISSBM1745(x) ((x)->sc_mixer_model >= SBM_CT1XX5)
u_int sc_model; /* DSP model */
+#define SB_UNK -1
+#define SB_1 0 /* original SB */
+#define SB_20 1 /* SB 2 */
+#define SB_2x 2 /* SB 2, new version */
+#define SB_PRO 3 /* SB Pro */
+#define SB_JAZZ 4 /* Jazz 16 */
+#define SB_16 5 /* SB 16 */
+#define SB_32 6 /* SB AWE 32 */
+#define SB_64 7 /* SB AWE 64 */
+
+#define SB_NAMES { "SB_1", "SB_2.0", "SB_2.x", "SB_Pro", "Jazz_16", "SB_16", "SB_AWE_32", "SB_AWE_64" }
+
+ u_int sc_version; /* DSP version */
#define SBVER_MAJOR(v) (((v)>>8) & 0xff)
#define SBVER_MINOR(v) ((v)&0xff)
-
-#define MODEL_JAZZ16 0x80000000
};
-#define ISSB2CLASS(sc) \
- (SBVER_MAJOR((sc)->sc_model) >= 2)
-
-#define ISSBPROCLASS(sc) \
- (SBVER_MAJOR((sc)->sc_model) > 2)
-
-#define ISSBPRO(sc) \
- (SBVER_MAJOR((sc)->sc_model) == 3)
-
-#define ISSB16CLASS(sc) \
- (SBVER_MAJOR((sc)->sc_model) > 3)
-
-#define ISJAZZ16(sc) \
- ((sc)->sc_model & MODEL_JAZZ16)
-
+#define ISSBPRO(sc) ((sc)->sc_model == SB_PRO || (sc)->sc_model == SB_JAZZ)
+#define ISSBPROCLASS(sc) ((sc)->sc_model >= SB_PRO)
+#define ISSB16CLASS(sc) ((sc)->sc_model >= SB_16)
#ifdef _KERNEL
-int sbdsp_open __P((struct sbdsp_softc *, dev_t, int));
+int sbdsp_open __P((void *, int));
void sbdsp_close __P((void *));
int sbdsp_probe __P((struct sbdsp_softc *));
@@ -163,35 +182,20 @@ int sbdsp_set_out_gain_real __P((void *, u_int, u_char));
int sbdsp_get_out_gain __P((void *));
int sbdsp_set_monitor_gain __P((void *, u_int));
int sbdsp_get_monitor_gain __P((void *));
-int sbdsp_set_in_sr __P((void *, u_long));
-int sbdsp_set_in_sr_real __P((void *, u_long));
-u_long sbdsp_get_in_sr __P((void *));
-int sbdsp_set_out_sr __P((void *, u_long));
-int sbdsp_set_out_sr_real __P((void *, u_long));
-u_long sbdsp_get_out_sr __P((void *));
int sbdsp_query_encoding __P((void *, struct audio_encoding *));
-int sbdsp_set_format __P((void *, u_int, u_int));
-int sbdsp_get_encoding __P((void *));
-int sbdsp_get_precision __P((void *));
-int sbdsp_set_channels __P((void *, int));
-int sbdsp_get_channels __P((void *));
-int sbdsp_set_ifilter __P((void *, int));
-int sbdsp_get_ifilter __P((void *));
+int sbdsp_set_params __P((void *, int, int, struct audio_params *, struct audio_params *));
int sbdsp_round_blocksize __P((void *, int));
-int sbdsp_set_out_port __P((void *, int));
-int sbdsp_get_out_port __P((void *));
-int sbdsp_set_in_port __P((void *, int));
-int sbdsp_get_in_port __P((void *));
int sbdsp_get_avail_in_ports __P((void *));
int sbdsp_get_avail_out_ports __P((void *));
int sbdsp_speaker_ctl __P((void *, int));
-int sbdsp_commit_settings __P((void *));
+int sbdsp_commit __P((void *));
+int sbdsp_dma_init_input __P((void *, void *, int));
+int sbdsp_dma_init_output __P((void *, void *, int));
int sbdsp_dma_output __P((void *, void *, int, void (*)(void *), void*));
int sbdsp_dma_input __P((void *, void *, int, void (*)(void *), void*));
int sbdsp_haltdma __P((void *));
-int sbdsp_contdma __P((void *));
void sbdsp_compress __P((int, u_char *, int));
void sbdsp_expand __P((int, u_char *, int));
@@ -204,10 +208,8 @@ int sbdsp_wdsp __P((struct sbdsp_softc *, int v));
int sbdsp_rdsp __P((struct sbdsp_softc *));
int sbdsp_intr __P((void *));
-short sbversion __P((struct sbdsp_softc *));
int sbdsp_set_sr __P((struct sbdsp_softc *, u_long *, int));
-int sbdsp_setfd __P((void *, int));
void sbdsp_mix_write __P((struct sbdsp_softc *, int, int));
int sbdsp_mix_read __P((struct sbdsp_softc *, int));
@@ -216,4 +218,11 @@ int sbdsp_mixer_set_port __P((void *, mixer_ctrl_t *));
int sbdsp_mixer_get_port __P((void *, mixer_ctrl_t *));
int sbdsp_mixer_query_devinfo __P((void *, mixer_devinfo_t *));
+void *sb_malloc __P((void *, unsigned long, int, int));
+void sb_free __P((void *, void *, int));
+unsigned long sb_round __P((void *, unsigned long));
+int sb_mappage __P((void *, void *, int, int));
+
+int sbdsp_get_props __P((void *));
+
#endif
diff --git a/sys/dev/isa/sbreg.h b/sys/dev/isa/sbreg.h
index b8bd566accf..e4c8bc3d9e6 100644
--- a/sys/dev/isa/sbreg.h
+++ b/sys/dev/isa/sbreg.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: sbreg.h,v 1.3 1997/07/10 23:06:39 provos Exp $ */
-/* $NetBSD: sbreg.h,v 1.16 1996/03/16 04:00:14 jtk Exp $ */
+/* $OpenBSD: sbreg.h,v 1.4 1998/04/26 21:03:02 provos Exp $ */
+/* $NetBSD: sbreg.h,v 1.24 1997/08/24 23:24:51 augustss Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -71,21 +71,19 @@
#define SBP_FM_DATA 9 /* RW FM data port */
#define SBP_MIXER_ADDR 4 /* W mixer address register */
#define SBP_MIXER_DATA 5 /* RW mixer data port */
-#define SBP_MIX_RESET 0 /* mixer reset port, value */
+
+#define SBP_MIX_RESET 0x00 /* mixer reset port, value */
+#define SBP_1335_MASTER_VOL 0x02
+#define SBP_1335_MIDI_VOL 0x06
+#define SBP_1335_CD_VOL 0x08
+#define SBP_1335_VOICE_VOL 0x0A
+
+#define SBP_VOICE_VOL 0x04
+#define SBP_MIC_VOL 0x0A /* warning: only one channel of volume... */
#define SBP_MASTER_VOL 0x22
-#define SBP_FM_VOL 0x26
+#define SBP_MIDI_VOL 0x26
#define SBP_CD_VOL 0x28
#define SBP_LINE_VOL 0x2E
-#define SBP_DAC_VOL 0x04
-#define SBP_MIC_VOL 0x0A /* warning: only one channel of
- volume... */
-#define SBP_SPEAKER_VOL 0x42
-#define SBP_TREBLE_EQ 0x44
-#define SBP_BASS_EQ 0x46
-
-#define SBP_SET_IRQ 0x80 /* Soft-configured irq (SB16-) */
-#define SBP_SET_DRQ 0x81 /* Soft-configured drq (SB16-) */
-#define SBP_IRQ_STATUS 0x82 /* Pending IRQ status (SB16-) */
#define SBP_RECORD_SOURCE 0x0C
#define SBP_STEREO 0x0E
@@ -105,17 +103,60 @@
#define SBP_FROM_MIC 0x00
#define SBP_FROM_CD 0x02
#define SBP_FROM_LINE 0x06
-#define sbdsp_mono_vol(left) (((left) << 4) | (left))
-#define sbdsp_stereo_vol(left, right) (((left) << 4) | (right))
-#define SBP_MAXVOL 0xf /* per channel */
-#define SBP_MINVOL 0x0 /* per channel */
-#define SBP_AGAIN_TO_SBGAIN(again) ((again) >> 4) /* per channel */
-#define SBP_AGAIN_TO_MICGAIN(again) ((again) >> 5) /* mic has only 3 bits,
- sorry! */
-#define SBP_LEFTGAIN(sbgain) (sbgain & 0xf0) /* left channel */
-#define SBP_RIGHTGAIN(sbgain) ((sbgain & 0xf) << 4) /* right channel */
-#define SBP_SBGAIN_TO_AGAIN(sbgain) SBP_LEFTGAIN(sbgain)
-#define SBP_MICGAIN_TO_AGAIN(micgain) (micgain << 5)
+
+#define SBP_SET_IRQ 0x80 /* Soft-configured irq (SB16-) */
+#define SBP_SET_DRQ 0x81 /* Soft-configured drq (SB16-) */
+#define SBP_IRQ_STATUS 0x82 /* Pending IRQ status (SB16-) */
+#define SBP_IRQ_MPU401 0x04
+#define SBP_IRQ_DMA16 0x02
+#define SBP_IRQ_DMA8 0x01
+
+#define SB16P_MASTER_L 0x30
+#define SB16P_VOICE_L 0x32
+#define SB16P_MIDI_L 0x34
+#define SB16P_CD_L 0x36
+#define SB16P_LINE_L 0x38
+#define SB16P_MIC_L 0x3a
+#define SB16P_PCSPEAKER 0x3b
+#define SB16P_OSWITCH 0x3c
+#define SB16P_ISWITCH_L 0x3d
+#define SB16P_ISWITCH_R 0x3e
+#define SB16P_SW_MIC 0x01
+#define SB16P_SW_CD_R 0x02
+#define SB16P_SW_CD_L 0x04
+#define SB16P_SW_CD (SB16P_SW_CD_L|SB16P_SW_CD_R)
+#define SB16P_SW_LINE_R 0x08
+#define SB16P_SW_LINE_L 0x10
+#define SB16P_SW_LINE (SB16P_SW_LINE_L|SB16P_SW_LINE_R)
+#define SB16P_SW_MIDI_R 0x20
+#define SB16P_SW_MIDI_L 0x40
+#define SB16P_SW_MIDI (SB16P_SW_MIDI_L|SB16P_SW_MIDI_R)
+#define SB16P_INPUT_GAIN_L 0x3f
+#define SB16P_OUTPUT_GAIN_L 0x41
+#define SB16P_TREBLE_L 0x44
+#define SB16P_BASS_L 0x46
+#define SB16P_L_TO_R(l) ((l)+1)
+
+#define SB16P_AGC 0x43
+
+#define SBP_RECORD_SOURCE_L 0x3d
+#define SBP_RECORD_SOURCE_R 0x3e
+#define SBP_MIDI_SRC_R 0x20
+#define SBP_LINE_SRC_R 0x08
+#define SBP_CD_SRC_R 0x02
+#define SBP_MIC_SRC 0x01
+#define SB_SRC_R_TO_L(x) ((x) << 1)
+
+#define SB_STEREO_GAIN(left, right) ((left) | ((right) >> 4))
+#define SB_MIC_GAIN(v) ((v) >> 5)
+
+#define SB_ADJUST_MIC_GAIN(sc, x) sbdsp_adjust((x), ISSB16CLASS(sc) ? 0xf8 : 0xc0)
+#define SB_ADJUST_GAIN(sc, x) sbdsp_adjust((x), ISSB16CLASS(sc) ? 0xf8 : 0xe0)
+#define SB_ADJUST_2_GAIN(sc, x) sbdsp_adjust((x), 0xc0)
+
+#define SB_1335_GAIN(x) ((x) >> 4)
+#define SB_1335_MASTER_GAIN(x) ((x) >> 5)
+
#define SBP_DSP_RESET 6 /* W reset port */
#define SB_MAGIC 0xaa /* card outputs on successful reset */
#define SBP_DSP_READ 10 /* R read port */
@@ -179,6 +220,10 @@
#define SB_SPKR_ON 0xff
#define SB_DSP_VERSION 0xe1 /* get version number */
+#define SB_BMODE_UNSIGNED 0x00
+#define SB_BMODE_SIGNED 0x10
+#define SB_BMODE_STEREO 0x20
+
/* Some of these come from linux driver (It serves as convenient unencumbered
documentation) */
#define JAZZ16_READ_VER 0xFA /* 0x12 means ProSonic/Jazz16? */
diff --git a/sys/dev/isa/wss.c b/sys/dev/isa/wss.c
index 930516b0ec1..e14338bdd44 100644
--- a/sys/dev/isa/wss.c
+++ b/sys/dev/isa/wss.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: wss.c,v 1.14 1997/07/10 23:06:40 provos Exp $ */
-/* $NetBSD: wss.c,v 1.13 1996/05/12 23:54:16 mycroft Exp $ */
+/* $OpenBSD: wss.c,v 1.15 1998/04/26 21:03:03 provos Exp $ */
+/* $NetBSD: wss.c,v 1.42 1998/01/19 22:18:23 augustss Exp $ */
/*
* Copyright (c) 1994 John Brezak
@@ -47,6 +47,7 @@
#include <machine/cpu.h>
#include <machine/intr.h>
+#include <machine/bus.h>
#include <machine/pio.h>
#include <sys/audioio.h>
@@ -58,26 +59,8 @@
#include <dev/ic/ad1848reg.h>
#include <dev/isa/ad1848var.h>
#include <dev/isa/wssreg.h>
-#include <dev/isa/opti.h>
-
-/*
- * Mixer devices
- */
-#define WSS_MIC_IN_LVL 0
-#define WSS_LINE_IN_LVL 1
-#define WSS_DAC_LVL 2
-#define WSS_REC_LVL 3
-#define WSS_MON_LVL 4
-#define WSS_MIC_IN_MUTE 5
-#define WSS_LINE_IN_MUTE 6
-#define WSS_DAC_MUTE 7
-
-#define WSS_RECORD_SOURCE 8
-
-/* Classes */
-#define WSS_INPUT_CLASS 9
-#define WSS_RECORD_CLASS 10
-#define WSS_MONITOR_CLASS 11
+#include <dev/isa/wssvar.h>
+#include <dev/isa/madreg.h>
#ifdef AUDIO_DEBUG
#define DPRINTF(x) if (wssdebug) printf x
@@ -86,191 +69,92 @@ int wssdebug = 0;
#define DPRINTF(x)
#endif
-struct wss_softc {
- struct device sc_dev; /* base device */
- struct isadev sc_id; /* ISA device */
- void *sc_ih; /* interrupt vectoring */
-
- struct ad1848_softc sc_ad1848;
-#define wss_irq sc_ad1848.sc_irq
-#define wss_drq sc_ad1848.sc_drq
-
- int mic_mute, cd_mute, dac_mute;
-};
-
struct audio_device wss_device = {
"wss,ad1848",
"",
"WSS"
};
-int wssopen __P((dev_t, int));
int wss_getdev __P((void *, struct audio_device *));
-int wss_setfd __P((void *, int));
-int wss_set_out_port __P((void *, int));
-int wss_get_out_port __P((void *));
-int wss_set_in_port __P((void *, int));
-int wss_get_in_port __P((void *));
int wss_mixer_set_port __P((void *, mixer_ctrl_t *));
int wss_mixer_get_port __P((void *, mixer_ctrl_t *));
int wss_query_devinfo __P((void *, mixer_devinfo_t *));
static int wss_to_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
static int wss_from_vol __P((mixer_ctrl_t *, struct ad1848_volume *));
+
/*
* Define our interface to the higher level audio driver.
*/
struct audio_hw_if wss_hw_if = {
- wssopen,
+ ad1848_open,
ad1848_close,
NULL,
- ad1848_set_in_sr,
- ad1848_get_in_sr,
- ad1848_set_out_sr,
- ad1848_get_out_sr,
ad1848_query_encoding,
- ad1848_set_format,
- ad1848_get_encoding,
- ad1848_get_precision,
- ad1848_set_channels,
- ad1848_get_channels,
+ ad1848_set_params,
ad1848_round_blocksize,
- wss_set_out_port,
- wss_get_out_port,
- wss_set_in_port,
- wss_get_in_port,
ad1848_commit_settings,
- NULL,
- NULL,
+ ad1848_dma_init_output,
+ ad1848_dma_init_input,
ad1848_dma_output,
ad1848_dma_input,
ad1848_halt_out_dma,
ad1848_halt_in_dma,
- ad1848_cont_out_dma,
- ad1848_cont_in_dma,
NULL,
wss_getdev,
- wss_setfd,
+ NULL,
wss_mixer_set_port,
wss_mixer_get_port,
wss_query_devinfo,
- 0, /* not full-duplex */
- 0
+ ad1848_malloc,
+ ad1848_free,
+ ad1848_round,
+ ad1848_mappage,
+ ad1848_get_props,
};
-int wssprobe __P((struct device *, void *, void *));
-void wssattach __P((struct device *, struct device *, void *));
-
-struct cfattach wss_ca = {
- sizeof(struct wss_softc), wssprobe, wssattach
-};
-
-struct cfdriver wss_cd = {
- NULL, "wss", DV_DULL
-};
-
-/*
- * Probe for the Microsoft Sound System hardware.
- */
-int
-wssprobe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- register struct wss_softc *sc = match;
- register struct isa_attach_args *ia = aux;
- register int iobase = ia->ia_iobase;
- static u_char interrupt_bits[12] = {
- -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
- };
- static u_char dma_bits[4] = {1, 2, 0, 3};
-
- if (!WSS_BASE_VALID(ia->ia_iobase)) {
- DPRINTF(("wss: configured iobase %x invalid\n", ia->ia_iobase));
- return 0;
- }
-
- if( !opti_snd_setup( OPTI_WSS, iobase, ia->ia_irq, ia->ia_drq ) )
- DPRINTF(("ad_detect_A: could not setup OPTi chipset.\n"));
-
- sc->sc_ad1848.sc_iobase = iobase + WSS_CODEC;
-
- /* Is there an ad1848 chip at the WSS iobase ? */
- if (ad1848_probe(&sc->sc_ad1848) == 0) {
-#if 0
- DPRINTF(("ad_detect_A: no ad1848 found.\n"));
-#endif
- return 0;
- }
-
- ia->ia_iosize = WSS_NPORT;
-
- /* Setup WSS interrupt and DMA */
- if (!WSS_DRQ_VALID(ia->ia_drq)) {
- DPRINTF(("wss: configured dma chan %d invalid\n", ia->ia_drq));
- return 0;
- }
- sc->wss_drq = ia->ia_drq;
-
-#ifdef NEWCONFIG
- /*
- * If the IRQ wasn't compiled in, auto-detect it.
- */
- if (ia->ia_irq == IRQUNK) {
- ia->ia_irq = isa_discoverintr(ad1848_forceintr, &sc->sc_ad1848);
- if (!WSS_IRQ_VALID(ia->ia_irq)) {
- printf("wss: couldn't auto-detect interrupt\n");
- return 0;
- }
- }
- else
-#endif
- if (!WSS_IRQ_VALID(ia->ia_irq)) {
- DPRINTF(("wss: configured interrupt %d invalid\n", ia->ia_irq));
- return 0;
- }
-
- sc->wss_irq = ia->ia_irq;
-
- outb(iobase+WSS_CONFIG,
- (interrupt_bits[ia->ia_irq] | dma_bits[ia->ia_drq]));
-
- return 1;
-}
-
/*
* Attach hardware to driver, attach hardware driver to audio
* pseudo-device driver .
*/
void
-wssattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+wssattach(sc)
+ struct wss_softc *sc;
{
- register struct wss_softc *sc = (struct wss_softc *)self;
- struct isa_attach_args *ia = (struct isa_attach_args *)aux;
- register int iobase = ia->ia_iobase;
- int err;
+ int version;
- sc->sc_ad1848.sc_recdrq = ia->ia_drq;
+ madattach(sc);
-#ifdef NEWCONFIG
- isa_establish(&sc->sc_id, &sc->sc_dev);
-#endif
- sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_AUDIO,
+ sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->wss_irq, IST_EDGE, IPL_AUDIO,
ad1848_intr, &sc->sc_ad1848, sc->sc_dev.dv_xname);
ad1848_attach(&sc->sc_ad1848);
- printf(" (vers %d)", inb(iobase+WSS_STATUS) & WSS_VERSMASK);
+ version = bus_space_read_1(sc->sc_iot, sc->sc_ioh, WSS_STATUS) & WSS_VERSMASK;
+ printf(" (vers %d)", version);
+ switch(sc->mad_chip_type) {
+ case MAD_82C928:
+ printf(", 82C928");
+ break;
+ case MAD_OTI601D:
+ printf(", OTI-601D");
+ break;
+ case MAD_82C929:
+ printf(", 82C929");
+ break;
+ case MAD_82C931:
+ printf(", 82C931");
+ break;
+ default:
+ break;
+ }
printf("\n");
sc->sc_ad1848.parent = sc;
- if ((err = audio_hardware_attach(&wss_hw_if, &sc->sc_ad1848)) != 0)
- printf("wss: could not attach to audio pseudo-device driver (%d)\n", err);
+ audio_attach_mi(&wss_hw_if, 0, &sc->sc_ad1848, &sc->sc_dev);
}
static int
@@ -308,24 +192,6 @@ wss_from_vol(cp, vol)
}
int
-wssopen(dev, flags)
- dev_t dev;
- int flags;
-{
- struct wss_softc *sc;
- int unit = AUDIOUNIT(dev);
-
- if (unit >= wss_cd.cd_ndevs)
- return ENODEV;
-
- sc = wss_cd.cd_devs[unit];
- if (!sc)
- return ENXIO;
-
- return ad1848_open(&sc->sc_ad1848, dev, flags);
-}
-
-int
wss_getdev(addr, retp)
void *addr;
struct audio_device *retp;
@@ -335,90 +201,12 @@ wss_getdev(addr, retp)
}
int
-wss_setfd(addr, flag)
- void *addr;
- int flag;
-{
- /* Can't do full-duplex */
- return(ENOTTY);
-}
-
-
-int
-wss_set_out_port(addr, port)
- void *addr;
- int port;
-{
- DPRINTF(("wss_set_out_port:\n"));
- return(EINVAL);
-}
-
-int
-wss_get_out_port(addr)
- void *addr;
-{
- DPRINTF(("wss_get_out_port:\n"));
- return(WSS_DAC_LVL);
-}
-
-int
-wss_set_in_port(addr, port)
- void *addr;
- int port;
-{
- register struct ad1848_softc *ac = addr;
-
- DPRINTF(("wss_set_in_port: %d\n", port));
-
- switch(port) {
- case WSS_MIC_IN_LVL:
- port = MIC_IN_PORT;
- break;
- case WSS_LINE_IN_LVL:
- port = LINE_IN_PORT;
- break;
- case WSS_DAC_LVL:
- port = DAC_IN_PORT;
- break;
- default:
- return(EINVAL);
- /*NOTREACHED*/
- }
-
- return(ad1848_set_rec_port(ac, port));
-}
-
-int
-wss_get_in_port(addr)
- void *addr;
-{
- register struct ad1848_softc *ac = addr;
- int port = WSS_MIC_IN_LVL;
-
- switch(ad1848_get_rec_port(ac)) {
- case MIC_IN_PORT:
- port = WSS_MIC_IN_LVL;
- break;
- case LINE_IN_PORT:
- port = WSS_LINE_IN_LVL;
- break;
- case DAC_IN_PORT:
- port = WSS_DAC_LVL;
- break;
- }
-
- DPRINTF(("wss_get_in_port: %d\n", port));
-
- return(port);
-}
-
-int
wss_mixer_set_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct wss_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct wss_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -503,8 +291,8 @@ wss_mixer_get_port(addr, cp)
void *addr;
mixer_ctrl_t *cp;
{
- register struct ad1848_softc *ac = addr;
- register struct wss_softc *sc = ac->parent;
+ struct ad1848_softc *ac = addr;
+ struct wss_softc *sc = ac->parent;
struct ad1848_volume vol;
int error = EINVAL;
@@ -590,7 +378,7 @@ wss_mixer_get_port(addr, cp)
int
wss_query_devinfo(addr, dip)
void *addr;
- register mixer_devinfo_t *dip;
+ mixer_devinfo_t *dip;
{
DPRINTF(("wss_query_devinfo: index=%d\n", dip->index));
@@ -648,21 +436,21 @@ wss_query_devinfo(addr, dip)
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = WSS_INPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCInputs);
+ strcpy(dip->label.name, AudioCinputs);
break;
case WSS_MONITOR_CLASS: /* monitor class descriptor */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = WSS_MONITOR_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNmonitor);
+ strcpy(dip->label.name, AudioCmonitor);
break;
case WSS_RECORD_CLASS: /* record source class */
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = WSS_RECORD_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNrecord);
+ strcpy(dip->label.name, AudioCrecord);
break;
case WSS_MIC_IN_MUTE:
@@ -716,3 +504,136 @@ wss_query_devinfo(addr, dip)
return 0;
}
+
+
+/*
+ * Copyright by Hannu Savolainen 1994
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/*
+ * Initialization code for OPTi MAD16 compatible audio chips. Including
+ *
+ * OPTi 82C928 MAD16 (replaced by C929)
+ * OAK OTI-601D Mozart
+ * OPTi 82C929 MAD16 Pro
+ *
+ */
+
+u_int
+mad_read(sc, port)
+ struct wss_softc *sc;
+ int port;
+{
+ u_int tmp;
+ int pwd;
+ int s;
+
+ switch (sc->mad_chip_type) { /* Output password */
+ case MAD_82C928:
+ case MAD_OTI601D:
+ pwd = M_PASSWD_928;
+ break;
+ case MAD_82C929:
+ pwd = M_PASSWD_929;
+ break;
+ case MAD_82C931:
+ pwd = M_PASSWD_931;
+ break;
+ default:
+ panic("mad_read: Bad chip type=%d\n", sc->mad_chip_type);
+ }
+ s = splaudio(); /* don't want an interrupt between outb&inb */
+ bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
+ tmp = bus_space_read_1(sc->sc_iot, sc->mad_ioh, port);
+ splx(s);
+ return tmp;
+}
+
+void
+mad_write(sc, port, value)
+ struct wss_softc *sc;
+ int port;
+ int value;
+{
+ int pwd;
+ int s;
+
+ switch (sc->mad_chip_type) { /* Output password */
+ case MAD_82C928:
+ case MAD_OTI601D:
+ pwd = M_PASSWD_928;
+ break;
+ case MAD_82C929:
+ pwd = M_PASSWD_929;
+ break;
+ case MAD_82C931:
+ pwd = M_PASSWD_931;
+ break;
+ default:
+ panic("mad_write: Bad chip type=%d\n", sc->mad_chip_type);
+ }
+ s = splaudio();
+ bus_space_write_1(sc->sc_iot, sc->mad_ioh, MC_PASSWD_REG, pwd);
+ bus_space_write_1(sc->sc_iot, sc->mad_ioh, port, value & 0xff);
+ splx(s);
+}
+
+void
+madattach(sc)
+ struct wss_softc *sc;
+{
+ unsigned char cs4231_mode;
+ int joy;
+
+ if (sc->mad_chip_type == MAD_NONE)
+ return;
+
+ /* Do we want the joystick disabled? */
+ joy = sc->sc_dev.dv_cfdata->cf_flags & 2 ? MC1_JOYDISABLE : 0;
+
+ /* enable WSS emulation at the I/O port */
+ mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(sc->mad_ioindex) | joy);
+ mad_write(sc, MC2_PORT, 0x03); /* ? */
+ mad_write(sc, MC3_PORT, 0xf0); /* Disable SB */
+
+ cs4231_mode =
+ strncmp(sc->sc_ad1848.chip_name, "CS4248", 6) == 0 ||
+ strncmp(sc->sc_ad1848.chip_name, "CS4231", 6) == 0 ? 0x02 : 0;
+
+ if (sc->mad_chip_type == MAD_82C929) {
+ mad_write(sc, MC4_PORT, 0x92);
+ mad_write(sc, MC5_PORT, 0xA5 | cs4231_mode);
+ mad_write(sc, MC6_PORT, 0x03); /* Disable MPU401 */
+ } else {
+ mad_write(sc, MC4_PORT, 0x02);
+ mad_write(sc, MC5_PORT, 0x30 | cs4231_mode);
+ }
+
+#ifdef AUDIO_DEBUG
+ if (wssdebug) {
+ int i;
+ for (i = MC1_PORT; i <= MC7_PORT; i++)
+ DPRINTF(("port %03x after init = %02x\n", i, mad_read(sc, i)));
+ }
+#endif
+}
diff --git a/sys/dev/isa/wss_isa.c b/sys/dev/isa/wss_isa.c
new file mode 100644
index 00000000000..61df0bc35f1
--- /dev/null
+++ b/sys/dev/isa/wss_isa.c
@@ -0,0 +1,376 @@
+/* $OpenBSD: wss_isa.c,v 1.1 1998/04/26 21:02:38 provos Exp $ */
+/* $NetBSD: wss_isa.c,v 1.1 1998/01/19 22:18:24 augustss Exp $ */
+
+/*
+ * Copyright (c) 1994 John Brezak
+ * Copyright (c) 1991-1993 Regents of the University of California.
+ * All rights reserved.
+ *
+ * MAD support:
+ * Copyright (c) 1996 Lennart Augustsson
+ * Based on code which is
+ * Copyright (c) 1994 Hannu Savolainen
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/pio.h>
+
+#include <sys/audioio.h>
+#include <dev/audio_if.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+
+#include <dev/ic/ad1848reg.h>
+#include <dev/isa/ad1848var.h>
+#include <dev/isa/wssreg.h>
+#include <dev/isa/wssvar.h>
+#include <dev/isa/madreg.h>
+
+#ifdef AUDIO_DEBUG
+#define DPRINTF(x) if (wssdebug) printf x
+extern int wssdebug;
+#else
+#define DPRINTF(x)
+#endif
+
+static int wssfind __P((struct device *, struct wss_softc *, struct isa_attach_args *));
+
+static void madprobe __P((struct wss_softc *, int));
+static void madunmap __P((struct wss_softc *));
+static int detect_mad16 __P((struct wss_softc *, int));
+
+int wss_isa_probe __P((struct device *, void *, void *));
+void wss_isa_attach __P((struct device *, struct device *, void *));
+
+struct cfattach wss_isa_ca = {
+ sizeof(struct wss_softc), wss_isa_probe, wss_isa_attach
+};
+
+struct cfdriver wss_cd = {
+ NULL, "wss", DV_DULL
+};
+
+/*
+ * Probe for the Microsoft Sound System hardware.
+ */
+int
+wss_isa_probe(parent, match, aux)
+ struct device *parent;
+#define __BROKEN_INDIRECT_CONFIG
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ struct wss_softc probesc, *sc = &probesc;
+
+ bzero(sc, sizeof *sc);
+#ifdef __BROKEN_INDIRECT_CONFIG
+ sc->sc_dev.dv_cfdata = ((struct device *)match)->dv_cfdata;
+#else
+ sc->sc_dev.dv_cfdata = match;
+#endif
+ if (wssfind(parent, sc, aux)) {
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
+ ad1848_unmap(&sc->sc_ad1848);
+ madunmap(sc);
+ return 1;
+ } else
+ /* Everything is already unmapped */
+ return 0;
+}
+
+static int
+wssfind(parent, sc, ia)
+ struct device *parent;
+ struct wss_softc *sc;
+ struct isa_attach_args *ia;
+{
+ static u_char interrupt_bits[12] = {
+ -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
+ };
+ static u_char dma_bits[4] = {1, 2, 0, 3};
+
+ sc->sc_iot = ia->ia_iot;
+ if (sc->sc_dev.dv_cfdata->cf_flags & 1)
+ madprobe(sc, ia->ia_iobase);
+ else
+ sc->mad_chip_type = MAD_NONE;
+
+ if (!WSS_BASE_VALID(ia->ia_iobase)) {
+ DPRINTF(("wss: configured iobase %x invalid\n", ia->ia_iobase));
+ goto bad1;
+ }
+
+ /* Map the ports upto the AD1848 port */
+ if (bus_space_map(sc->sc_iot, ia->ia_iobase, WSS_CODEC, 0, &sc->sc_ioh))
+ goto bad1;
+
+ sc->sc_ad1848.sc_iot = sc->sc_iot;
+
+ /* Is there an ad1848 chip at (WSS iobase + WSS_CODEC)? */
+ if (ad1848_mapprobe(&sc->sc_ad1848, ia->ia_iobase + WSS_CODEC) == 0)
+ goto bad;
+
+ ia->ia_iosize = WSS_NPORT;
+
+ /* Setup WSS interrupt and DMA */
+ if (!WSS_DRQ_VALID(ia->ia_drq)) {
+ DPRINTF(("wss: configured dma chan %d invalid\n", ia->ia_drq));
+ goto bad;
+ }
+ sc->wss_drq = ia->ia_drq;
+
+ if (sc->wss_drq != DRQUNK && !isa_drq_isfree(parent, sc->wss_drq))
+ goto bad;
+
+ if (!WSS_IRQ_VALID(ia->ia_irq)) {
+ DPRINTF(("wss: configured interrupt %d invalid\n", ia->ia_irq));
+ goto bad;
+ }
+
+ sc->wss_irq = ia->ia_irq;
+
+ if (sc->sc_ad1848.mode <= 1)
+ ia->ia_drq2 = DRQUNK;
+ sc->wss_recdrq =
+ sc->sc_ad1848.mode > 1 && ia->ia_drq2 != DRQUNK ?
+ ia->ia_drq2 : ia->ia_drq;
+ if (sc->wss_recdrq != sc->wss_drq && !isa_drq_isfree(parent, sc->wss_recdrq))
+ goto bad;
+
+ /* XXX recdrq */
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh, WSS_CONFIG,
+ (interrupt_bits[ia->ia_irq] | dma_bits[ia->ia_drq]));
+
+ return 1;
+
+bad:
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, WSS_CODEC);
+bad1:
+ madunmap(sc);
+ return 0;
+}
+
+/*
+ * Attach hardware to driver, attach hardware driver to audio
+ * pseudo-device driver .
+ */
+void
+wss_isa_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct wss_softc *sc = (struct wss_softc *)self;
+ struct isa_attach_args *ia = (struct isa_attach_args *)aux;
+
+ if (!wssfind(parent, sc, ia)) {
+ printf("%s: wssfind failed\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ sc->sc_ic = ia->ia_ic;
+ sc->sc_ad1848.sc_isa = parent;
+
+ wssattach(sc);
+}
+
+/*
+ * Copyright by Hannu Savolainen 1994
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Initialization code for OPTi MAD16 compatible audio chips. Including
+ *
+ * OPTi 82C928 MAD16 (replaced by C929)
+ * OAK OTI-601D Mozart
+ * OPTi 82C929 MAD16 Pro
+ * OPTi 82C931
+ */
+
+static int
+detect_mad16(sc, chip_type)
+ struct wss_softc *sc;
+ int chip_type;
+{
+ unsigned char tmp, tmp2;
+
+ sc->mad_chip_type = chip_type;
+ /*
+ * Check that reading a register doesn't return bus float (0xff)
+ * when the card is accessed using password. This may fail in case
+ * the card is in low power mode. Normally at least the power saving mode
+ * bit should be 0.
+ */
+ if ((tmp = mad_read(sc, MC1_PORT)) == 0xff) {
+ DPRINTF(("MC1_PORT returned 0xff\n"));
+ return 0;
+ }
+
+ /*
+ * Now check that the gate is closed on first I/O after writing
+ * the password. (This is how a MAD16 compatible card works).
+ */
+ if ((tmp2 = bus_space_read_1(sc->sc_iot, sc->mad_ioh, MC1_PORT)) == tmp) {
+ DPRINTF(("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
+ return 0;
+ }
+
+ mad_write(sc, MC1_PORT, tmp ^ 0x80); /* Toggle a bit */
+
+ /* Compare the bit */
+ if ((tmp2 = mad_read(sc, MC1_PORT)) != (tmp ^ 0x80)) {
+ mad_write(sc, MC1_PORT, tmp); /* Restore */
+ DPRINTF(("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
+ return 0;
+ }
+
+ mad_write(sc, MC1_PORT, tmp); /* Restore */
+ return 1;
+}
+
+static void
+madprobe(sc, iobase)
+ struct wss_softc *sc;
+ int iobase;
+{
+ static int valid_ports[M_WSS_NPORTS] =
+ { M_WSS_PORT0, M_WSS_PORT1, M_WSS_PORT2, M_WSS_PORT3 };
+ int i;
+
+ /* Allocate bus space that the MAD chip wants */
+ if (bus_space_map(sc->sc_iot, MAD_BASE, MAD_NPORT, 0, &sc->mad_ioh))
+ goto bad0;
+ if (bus_space_map(sc->sc_iot, MAD_REG1, MAD_LEN1, 0, &sc->mad_ioh1))
+ goto bad1;
+ if (bus_space_map(sc->sc_iot, MAD_REG2, MAD_LEN2, 0, &sc->mad_ioh2))
+ goto bad2;
+ if (bus_space_map(sc->sc_iot, MAD_REG3, MAD_LEN3, 0, &sc->mad_ioh3))
+ goto bad3;
+
+ DPRINTF(("mad: Detect using password = 0xE2\n"));
+ if (!detect_mad16(sc, MAD_82C928)) {
+ /* No luck. Try different model */
+ DPRINTF(("mad: Detect using password = 0xE3\n"));
+ if (!detect_mad16(sc, MAD_82C929))
+ goto bad;
+ sc->mad_chip_type = MAD_82C929;
+ DPRINTF(("mad: 82C929 detected\n"));
+ } else {
+ sc->mad_chip_type = MAD_82C928;
+ if ((mad_read(sc, MC3_PORT) & 0x03) == 0x03) {
+ DPRINTF(("mad: Mozart detected\n"));
+ sc->mad_chip_type = MAD_OTI601D;
+ } else {
+ DPRINTF(("mad: 82C928 detected?\n"));
+ sc->mad_chip_type = MAD_82C928;
+ }
+ }
+
+#ifdef AUDIO_DEBUG
+ if (wssdebug)
+ for (i = MC1_PORT; i <= MC7_PORT; i++)
+ printf("mad: port %03x = %02x\n", i, mad_read(sc, i));
+#endif
+
+ /* Set the WSS address. */
+ for (i = 0; i < M_WSS_NPORTS; i++)
+ if (valid_ports[i] == iobase)
+ break;
+ if (i >= M_WSS_NPORTS) { /* Not a valid port */
+ printf("mad: Bad WSS base address 0x%x\n", iobase);
+ goto bad;
+ }
+ sc->mad_ioindex = i;
+ /* enable WSS emulation at the I/O port, no joystick */
+ mad_write(sc, MC1_PORT, M_WSS_PORT_SELECT(i) | MC1_JOYDISABLE);
+ mad_write(sc, MC2_PORT, 0x03); /* ? */
+ mad_write(sc, MC3_PORT, 0xf0); /* Disable SB */
+ return;
+
+bad:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
+bad3:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
+bad2:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
+bad1:
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
+bad0:
+ sc->mad_chip_type = MAD_NONE;
+}
+
+static void
+madunmap(sc)
+ struct wss_softc *sc;
+{
+ if (sc->mad_chip_type == MAD_NONE)
+ return;
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh, MAD_NPORT);
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh1, MAD_LEN1);
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh2, MAD_LEN2);
+ bus_space_unmap(sc->sc_iot, sc->mad_ioh3, MAD_LEN3);
+}
diff --git a/sys/dev/isa/wssvar.h b/sys/dev/isa/wssvar.h
new file mode 100644
index 00000000000..bd290f89476
--- /dev/null
+++ b/sys/dev/isa/wssvar.h
@@ -0,0 +1,83 @@
+/* $OpenBSD: wssvar.h,v 1.1 1998/04/26 21:02:38 provos Exp $ */
+/* $NetBSD: wssvar.h,v 1.1 1998/01/19 22:18:25 augustss Exp $ */
+
+/*
+ * Copyright (c) 1994 John Brezak
+ * Copyright (c) 1991-1993 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Mixer devices
+ */
+#define WSS_MIC_IN_LVL 0
+#define WSS_LINE_IN_LVL 1
+#define WSS_DAC_LVL 2
+#define WSS_REC_LVL 3
+#define WSS_MON_LVL 4
+#define WSS_MIC_IN_MUTE 5
+#define WSS_LINE_IN_MUTE 6
+#define WSS_DAC_MUTE 7
+
+#define WSS_RECORD_SOURCE 8
+
+/* Classes */
+#define WSS_INPUT_CLASS 9
+#define WSS_RECORD_CLASS 10
+#define WSS_MONITOR_CLASS 11
+
+struct wss_softc {
+ struct device sc_dev; /* base device */
+ struct isadev sc_id; /* ISA device */
+ void *sc_ih; /* interrupt vectoring */
+ bus_space_tag_t sc_iot; /* tag */
+ bus_space_handle_t sc_ioh; /* handle */
+ isa_chipset_tag_t sc_ic;
+
+ struct ad1848_softc sc_ad1848;
+#define wss_irq sc_ad1848.sc_irq
+#define wss_drq sc_ad1848.sc_drq
+#define wss_recdrq sc_ad1848.sc_recdrq
+
+ int mic_mute, cd_mute, dac_mute;
+
+ int mad_chip_type; /* chip type if MAD emulation of WSS */
+ int mad_ioindex;
+ bus_space_handle_t mad_ioh; /* MAD handle */
+ bus_space_handle_t mad_ioh1, mad_ioh2, mad_ioh3;
+};
+
+void wssattach __P((struct wss_softc *));
+
+u_int mad_read __P((struct wss_softc *, int));
+void mad_write __P((struct wss_softc *, int, int));
+void madattach __P((struct wss_softc *));
diff --git a/sys/dev/mulaw.c b/sys/dev/mulaw.c
index dd865ba9d89..8747c5e51ae 100644
--- a/sys/dev/mulaw.c
+++ b/sys/dev/mulaw.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: mulaw.c,v 1.2 1997/11/07 08:06:36 niklas Exp $ */
+/* $OpenBSD: mulaw.c,v 1.3 1998/04/26 21:03:10 provos Exp $ */
+/* $NetBSD: mulaw.c,v 1.8 1997/08/04 09:29:53 augustss Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -36,120 +37,304 @@
#include <sys/types.h>
#include <sys/audioio.h>
+#include <machine/endian.h>
#include <dev/mulaw.h>
-static u_char mulawtolin[256] = {
- 128, 4, 8, 12, 16, 20, 24, 28,
- 32, 36, 40, 44, 48, 52, 56, 60,
- 64, 66, 68, 70, 72, 74, 76, 78,
- 80, 82, 84, 86, 88, 90, 92, 94,
- 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 106, 107, 108, 109, 110, 111,
- 112, 112, 113, 113, 114, 114, 115, 115,
- 116, 116, 117, 117, 118, 118, 119, 119,
- 120, 120, 120, 121, 121, 121, 121, 122,
- 122, 122, 122, 123, 123, 123, 123, 124,
- 124, 124, 124, 124, 125, 125, 125, 125,
- 125, 125, 125, 125, 126, 126, 126, 126,
- 126, 126, 126, 126, 126, 126, 126, 126,
- 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127,
- 255, 251, 247, 243, 239, 235, 231, 227,
- 223, 219, 215, 211, 207, 203, 199, 195,
- 191, 189, 187, 185, 183, 181, 179, 177,
- 175, 173, 171, 169, 167, 165, 163, 161,
- 159, 158, 157, 156, 155, 154, 153, 152,
- 151, 150, 149, 148, 147, 146, 145, 144,
- 143, 143, 142, 142, 141, 141, 140, 140,
- 139, 139, 138, 138, 137, 137, 136, 136,
- 135, 135, 135, 134, 134, 134, 134, 133,
- 133, 133, 133, 132, 132, 132, 132, 131,
- 131, 131, 131, 131, 130, 130, 130, 130,
- 130, 130, 130, 130, 129, 129, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128,
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define LO 0
+#define HI 1
+#else
+#define LO 1
+#define HI 0
+#endif
+
+/*
+ * This table converts a (8 bit) mulaw value two a 16 bit value.
+ * The 16 bits are represented as an array of two butes for easier access
+ * to the individual bytes.
+ */
+static u_char mulawtolin16[256][2] = {
+ {0x02,0x84}, {0x06,0x84}, {0x0a,0x84}, {0x0e,0x84},
+ {0x12,0x84}, {0x16,0x84}, {0x1a,0x84}, {0x1e,0x84},
+ {0x22,0x84}, {0x26,0x84}, {0x2a,0x84}, {0x2e,0x84},
+ {0x32,0x84}, {0x36,0x84}, {0x3a,0x84}, {0x3e,0x84},
+ {0x41,0x84}, {0x43,0x84}, {0x45,0x84}, {0x47,0x84},
+ {0x49,0x84}, {0x4b,0x84}, {0x4d,0x84}, {0x4f,0x84},
+ {0x51,0x84}, {0x53,0x84}, {0x55,0x84}, {0x57,0x84},
+ {0x59,0x84}, {0x5b,0x84}, {0x5d,0x84}, {0x5f,0x84},
+ {0x61,0x04}, {0x62,0x04}, {0x63,0x04}, {0x64,0x04},
+ {0x65,0x04}, {0x66,0x04}, {0x67,0x04}, {0x68,0x04},
+ {0x69,0x04}, {0x6a,0x04}, {0x6b,0x04}, {0x6c,0x04},
+ {0x6d,0x04}, {0x6e,0x04}, {0x6f,0x04}, {0x70,0x04},
+ {0x70,0xc4}, {0x71,0x44}, {0x71,0xc4}, {0x72,0x44},
+ {0x72,0xc4}, {0x73,0x44}, {0x73,0xc4}, {0x74,0x44},
+ {0x74,0xc4}, {0x75,0x44}, {0x75,0xc4}, {0x76,0x44},
+ {0x76,0xc4}, {0x77,0x44}, {0x77,0xc4}, {0x78,0x44},
+ {0x78,0xa4}, {0x78,0xe4}, {0x79,0x24}, {0x79,0x64},
+ {0x79,0xa4}, {0x79,0xe4}, {0x7a,0x24}, {0x7a,0x64},
+ {0x7a,0xa4}, {0x7a,0xe4}, {0x7b,0x24}, {0x7b,0x64},
+ {0x7b,0xa4}, {0x7b,0xe4}, {0x7c,0x24}, {0x7c,0x64},
+ {0x7c,0x94}, {0x7c,0xb4}, {0x7c,0xd4}, {0x7c,0xf4},
+ {0x7d,0x14}, {0x7d,0x34}, {0x7d,0x54}, {0x7d,0x74},
+ {0x7d,0x94}, {0x7d,0xb4}, {0x7d,0xd4}, {0x7d,0xf4},
+ {0x7e,0x14}, {0x7e,0x34}, {0x7e,0x54}, {0x7e,0x74},
+ {0x7e,0x8c}, {0x7e,0x9c}, {0x7e,0xac}, {0x7e,0xbc},
+ {0x7e,0xcc}, {0x7e,0xdc}, {0x7e,0xec}, {0x7e,0xfc},
+ {0x7f,0x0c}, {0x7f,0x1c}, {0x7f,0x2c}, {0x7f,0x3c},
+ {0x7f,0x4c}, {0x7f,0x5c}, {0x7f,0x6c}, {0x7f,0x7c},
+ {0x7f,0x88}, {0x7f,0x90}, {0x7f,0x98}, {0x7f,0xa0},
+ {0x7f,0xa8}, {0x7f,0xb0}, {0x7f,0xb8}, {0x7f,0xc0},
+ {0x7f,0xc8}, {0x7f,0xd0}, {0x7f,0xd8}, {0x7f,0xe0},
+ {0x7f,0xe8}, {0x7f,0xf0}, {0x7f,0xf8}, {0x80,0x00},
+ {0xfd,0x7c}, {0xf9,0x7c}, {0xf5,0x7c}, {0xf1,0x7c},
+ {0xed,0x7c}, {0xe9,0x7c}, {0xe5,0x7c}, {0xe1,0x7c},
+ {0xdd,0x7c}, {0xd9,0x7c}, {0xd5,0x7c}, {0xd1,0x7c},
+ {0xcd,0x7c}, {0xc9,0x7c}, {0xc5,0x7c}, {0xc1,0x7c},
+ {0xbe,0x7c}, {0xbc,0x7c}, {0xba,0x7c}, {0xb8,0x7c},
+ {0xb6,0x7c}, {0xb4,0x7c}, {0xb2,0x7c}, {0xb0,0x7c},
+ {0xae,0x7c}, {0xac,0x7c}, {0xaa,0x7c}, {0xa8,0x7c},
+ {0xa6,0x7c}, {0xa4,0x7c}, {0xa2,0x7c}, {0xa0,0x7c},
+ {0x9e,0xfc}, {0x9d,0xfc}, {0x9c,0xfc}, {0x9b,0xfc},
+ {0x9a,0xfc}, {0x99,0xfc}, {0x98,0xfc}, {0x97,0xfc},
+ {0x96,0xfc}, {0x95,0xfc}, {0x94,0xfc}, {0x93,0xfc},
+ {0x92,0xfc}, {0x91,0xfc}, {0x90,0xfc}, {0x8f,0xfc},
+ {0x8f,0x3c}, {0x8e,0xbc}, {0x8e,0x3c}, {0x8d,0xbc},
+ {0x8d,0x3c}, {0x8c,0xbc}, {0x8c,0x3c}, {0x8b,0xbc},
+ {0x8b,0x3c}, {0x8a,0xbc}, {0x8a,0x3c}, {0x89,0xbc},
+ {0x89,0x3c}, {0x88,0xbc}, {0x88,0x3c}, {0x87,0xbc},
+ {0x87,0x5c}, {0x87,0x1c}, {0x86,0xdc}, {0x86,0x9c},
+ {0x86,0x5c}, {0x86,0x1c}, {0x85,0xdc}, {0x85,0x9c},
+ {0x85,0x5c}, {0x85,0x1c}, {0x84,0xdc}, {0x84,0x9c},
+ {0x84,0x5c}, {0x84,0x1c}, {0x83,0xdc}, {0x83,0x9c},
+ {0x83,0x6c}, {0x83,0x4c}, {0x83,0x2c}, {0x83,0x0c},
+ {0x82,0xec}, {0x82,0xcc}, {0x82,0xac}, {0x82,0x8c},
+ {0x82,0x6c}, {0x82,0x4c}, {0x82,0x2c}, {0x82,0x0c},
+ {0x81,0xec}, {0x81,0xcc}, {0x81,0xac}, {0x81,0x8c},
+ {0x81,0x74}, {0x81,0x64}, {0x81,0x54}, {0x81,0x44},
+ {0x81,0x34}, {0x81,0x24}, {0x81,0x14}, {0x81,0x04},
+ {0x80,0xf4}, {0x80,0xe4}, {0x80,0xd4}, {0x80,0xc4},
+ {0x80,0xb4}, {0x80,0xa4}, {0x80,0x94}, {0x80,0x84},
+ {0x80,0x78}, {0x80,0x70}, {0x80,0x68}, {0x80,0x60},
+ {0x80,0x58}, {0x80,0x50}, {0x80,0x48}, {0x80,0x40},
+ {0x80,0x38}, {0x80,0x30}, {0x80,0x28}, {0x80,0x20},
+ {0x80,0x18}, {0x80,0x10}, {0x80,0x08}, {0x80,0x00},
};
static u_char lintomulaw[256] = {
- 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 2, 2, 2, 2, 3, 3, 3,
- 3, 4, 4, 4, 4, 5, 5, 5,
- 5, 6, 6, 6, 6, 7, 7, 7,
- 7, 8, 8, 8, 8, 9, 9, 9,
- 9, 10, 10, 10, 10, 11, 11, 11,
- 11, 12, 12, 12, 12, 13, 13, 13,
- 13, 14, 14, 14, 14, 15, 15, 15,
- 15, 16, 16, 17, 17, 18, 18, 19,
- 19, 20, 20, 21, 21, 22, 22, 23,
- 23, 24, 24, 25, 25, 26, 26, 27,
- 27, 28, 28, 29, 29, 30, 30, 31,
- 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46,
- 47, 48, 50, 52, 54, 56, 58, 60,
- 62, 65, 69, 73, 77, 83, 91, 103,
- 255, 231, 219, 211, 205, 201, 197, 193,
- 190, 188, 186, 184, 182, 180, 178, 176,
- 175, 174, 173, 172, 171, 170, 169, 168,
- 167, 166, 165, 164, 163, 162, 161, 160,
- 159, 159, 158, 158, 157, 157, 156, 156,
- 155, 155, 154, 154, 153, 153, 152, 152,
- 151, 151, 150, 150, 149, 149, 148, 148,
- 147, 147, 146, 146, 145, 145, 144, 144,
- 143, 143, 143, 143, 142, 142, 142, 142,
- 141, 141, 141, 141, 140, 140, 140, 140,
- 139, 139, 139, 139, 138, 138, 138, 138,
- 137, 137, 137, 137, 136, 136, 136, 136,
- 135, 135, 135, 135, 134, 134, 134, 134,
- 133, 133, 133, 133, 132, 132, 132, 132,
- 131, 131, 131, 131, 130, 130, 130, 130,
- 129, 129, 129, 129, 128, 128, 128, 128,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
+ 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05,
+ 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07,
+ 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
+ 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d,
+ 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f,
+ 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13,
+ 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17,
+ 0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b,
+ 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f,
+ 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
+ 0x2f, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c,
+ 0x3e, 0x41, 0x45, 0x49, 0x4d, 0x53, 0x5b, 0x67,
+ 0xff, 0xe7, 0xdb, 0xd3, 0xcd, 0xc9, 0xc5, 0xc1,
+ 0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0,
+ 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
+ 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
+ 0x9f, 0x9f, 0x9e, 0x9e, 0x9d, 0x9d, 0x9c, 0x9c,
+ 0x9b, 0x9b, 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x98,
+ 0x97, 0x97, 0x96, 0x96, 0x95, 0x95, 0x94, 0x94,
+ 0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x90, 0x90,
+ 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e,
+ 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c,
+ 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a,
+ 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88,
+ 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86,
+ 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84,
+ 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
+ 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80,
+};
+
+static u_char alawtolin16[256][2] = {
+ {0x6a,0x80}, {0x6b,0x80}, {0x68,0x80}, {0x69,0x80},
+ {0x6e,0x80}, {0x6f,0x80}, {0x6c,0x80}, {0x6d,0x80},
+ {0x62,0x80}, {0x63,0x80}, {0x60,0x80}, {0x61,0x80},
+ {0x66,0x80}, {0x67,0x80}, {0x64,0x80}, {0x65,0x80},
+ {0x75,0x40}, {0x75,0xc0}, {0x74,0x40}, {0x74,0xc0},
+ {0x77,0x40}, {0x77,0xc0}, {0x76,0x40}, {0x76,0xc0},
+ {0x71,0x40}, {0x71,0xc0}, {0x70,0x40}, {0x70,0xc0},
+ {0x73,0x40}, {0x73,0xc0}, {0x72,0x40}, {0x72,0xc0},
+ {0x2a,0x00}, {0x2e,0x00}, {0x22,0x00}, {0x26,0x00},
+ {0x3a,0x00}, {0x3e,0x00}, {0x32,0x00}, {0x36,0x00},
+ {0x0a,0x00}, {0x0e,0x00}, {0x02,0x00}, {0x06,0x00},
+ {0x1a,0x00}, {0x1e,0x00}, {0x12,0x00}, {0x16,0x00},
+ {0x55,0x00}, {0x57,0x00}, {0x51,0x00}, {0x53,0x00},
+ {0x5d,0x00}, {0x5f,0x00}, {0x59,0x00}, {0x5b,0x00},
+ {0x45,0x00}, {0x47,0x00}, {0x41,0x00}, {0x43,0x00},
+ {0x4d,0x00}, {0x4f,0x00}, {0x49,0x00}, {0x4b,0x00},
+ {0x7e,0xa8}, {0x7e,0xb8}, {0x7e,0x88}, {0x7e,0x98},
+ {0x7e,0xe8}, {0x7e,0xf8}, {0x7e,0xc8}, {0x7e,0xd8},
+ {0x7e,0x28}, {0x7e,0x38}, {0x7e,0x08}, {0x7e,0x18},
+ {0x7e,0x68}, {0x7e,0x78}, {0x7e,0x48}, {0x7e,0x58},
+ {0x7f,0xa8}, {0x7f,0xb8}, {0x7f,0x88}, {0x7f,0x98},
+ {0x7f,0xe8}, {0x7f,0xf8}, {0x7f,0xc8}, {0x7f,0xd8},
+ {0x7f,0x28}, {0x7f,0x38}, {0x7f,0x08}, {0x7f,0x18},
+ {0x7f,0x68}, {0x7f,0x78}, {0x7f,0x48}, {0x7f,0x58},
+ {0x7a,0xa0}, {0x7a,0xe0}, {0x7a,0x20}, {0x7a,0x60},
+ {0x7b,0xa0}, {0x7b,0xe0}, {0x7b,0x20}, {0x7b,0x60},
+ {0x78,0xa0}, {0x78,0xe0}, {0x78,0x20}, {0x78,0x60},
+ {0x79,0xa0}, {0x79,0xe0}, {0x79,0x20}, {0x79,0x60},
+ {0x7d,0x50}, {0x7d,0x70}, {0x7d,0x10}, {0x7d,0x30},
+ {0x7d,0xd0}, {0x7d,0xf0}, {0x7d,0x90}, {0x7d,0xb0},
+ {0x7c,0x50}, {0x7c,0x70}, {0x7c,0x10}, {0x7c,0x30},
+ {0x7c,0xd0}, {0x7c,0xf0}, {0x7c,0x90}, {0x7c,0xb0},
+ {0x95,0x80}, {0x94,0x80}, {0x97,0x80}, {0x96,0x80},
+ {0x91,0x80}, {0x90,0x80}, {0x93,0x80}, {0x92,0x80},
+ {0x9d,0x80}, {0x9c,0x80}, {0x9f,0x80}, {0x9e,0x80},
+ {0x99,0x80}, {0x98,0x80}, {0x9b,0x80}, {0x9a,0x80},
+ {0x8a,0xc0}, {0x8a,0x40}, {0x8b,0xc0}, {0x8b,0x40},
+ {0x88,0xc0}, {0x88,0x40}, {0x89,0xc0}, {0x89,0x40},
+ {0x8e,0xc0}, {0x8e,0x40}, {0x8f,0xc0}, {0x8f,0x40},
+ {0x8c,0xc0}, {0x8c,0x40}, {0x8d,0xc0}, {0x8d,0x40},
+ {0xd6,0x00}, {0xd2,0x00}, {0xde,0x00}, {0xda,0x00},
+ {0xc6,0x00}, {0xc2,0x00}, {0xce,0x00}, {0xca,0x00},
+ {0xf6,0x00}, {0xf2,0x00}, {0xfe,0x00}, {0xfa,0x00},
+ {0xe6,0x00}, {0xe2,0x00}, {0xee,0x00}, {0xea,0x00},
+ {0xab,0x00}, {0xa9,0x00}, {0xaf,0x00}, {0xad,0x00},
+ {0xa3,0x00}, {0xa1,0x00}, {0xa7,0x00}, {0xa5,0x00},
+ {0xbb,0x00}, {0xb9,0x00}, {0xbf,0x00}, {0xbd,0x00},
+ {0xb3,0x00}, {0xb1,0x00}, {0xb7,0x00}, {0xb5,0x00},
+ {0x81,0x58}, {0x81,0x48}, {0x81,0x78}, {0x81,0x68},
+ {0x81,0x18}, {0x81,0x08}, {0x81,0x38}, {0x81,0x28},
+ {0x81,0xd8}, {0x81,0xc8}, {0x81,0xf8}, {0x81,0xe8},
+ {0x81,0x98}, {0x81,0x88}, {0x81,0xb8}, {0x81,0xa8},
+ {0x80,0x58}, {0x80,0x48}, {0x80,0x78}, {0x80,0x68},
+ {0x80,0x18}, {0x80,0x08}, {0x80,0x38}, {0x80,0x28},
+ {0x80,0xd8}, {0x80,0xc8}, {0x80,0xf8}, {0x80,0xe8},
+ {0x80,0x98}, {0x80,0x88}, {0x80,0xb8}, {0x80,0xa8},
+ {0x85,0x60}, {0x85,0x20}, {0x85,0xe0}, {0x85,0xa0},
+ {0x84,0x60}, {0x84,0x20}, {0x84,0xe0}, {0x84,0xa0},
+ {0x87,0x60}, {0x87,0x20}, {0x87,0xe0}, {0x87,0xa0},
+ {0x86,0x60}, {0x86,0x20}, {0x86,0xe0}, {0x86,0xa0},
+ {0x82,0xb0}, {0x82,0x90}, {0x82,0xf0}, {0x82,0xd0},
+ {0x82,0x30}, {0x82,0x10}, {0x82,0x70}, {0x82,0x50},
+ {0x83,0xb0}, {0x83,0x90}, {0x83,0xf0}, {0x83,0xd0},
+ {0x83,0x30}, {0x83,0x10}, {0x83,0x70}, {0x83,0x50},
};
+static u_char lintoalaw[256] = {
+ 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b,
+ 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
+ 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f,
+ 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
+ 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23,
+ 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
+ 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27,
+ 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
+ 0x3a, 0x3a, 0x3b, 0x3b, 0x38, 0x38, 0x39, 0x39,
+ 0x3e, 0x3e, 0x3f, 0x3f, 0x3c, 0x3c, 0x3d, 0x3d,
+ 0x32, 0x32, 0x33, 0x33, 0x30, 0x30, 0x31, 0x31,
+ 0x36, 0x36, 0x37, 0x37, 0x34, 0x34, 0x35, 0x35,
+ 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
+ 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
+ 0x1a, 0x18, 0x1e, 0x1c, 0x12, 0x10, 0x16, 0x14,
+ 0x6a, 0x6e, 0x62, 0x66, 0x7a, 0x72, 0x4a, 0x5a,
+ 0xd5, 0xc5, 0xf5, 0xfd, 0xe5, 0xe1, 0xed, 0xe9,
+ 0x95, 0x97, 0x91, 0x93, 0x9d, 0x9f, 0x99, 0x9b,
+ 0x85, 0x84, 0x87, 0x86, 0x81, 0x80, 0x83, 0x82,
+ 0x8d, 0x8c, 0x8f, 0x8e, 0x89, 0x88, 0x8b, 0x8a,
+ 0xb5, 0xb5, 0xb4, 0xb4, 0xb7, 0xb7, 0xb6, 0xb6,
+ 0xb1, 0xb1, 0xb0, 0xb0, 0xb3, 0xb3, 0xb2, 0xb2,
+ 0xbd, 0xbd, 0xbc, 0xbc, 0xbf, 0xbf, 0xbe, 0xbe,
+ 0xb9, 0xb9, 0xb8, 0xb8, 0xbb, 0xbb, 0xba, 0xba,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4,
+ 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6,
+ 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0,
+ 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2,
+ 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac,
+ 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae,
+ 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8,
+ 0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
+};
+
+void
+mulaw_to_ulinear8(v, p, cc)
+ void *v;
+ u_char *p;
+ int cc;
+{
+ /* Use the 16 bit table for 8 bits too. */
+ while (--cc >= 0) {
+ *p = mulawtolin16[*p][0];
+ ++p;
+ }
+}
+
+void
+mulaw_to_ulinear16(v, p, cc)
+ void *v;
+ u_char *p;
+ int cc;
+{
+ u_char *q = p;
+
+ p += cc;
+ q += cc * 2;
+ while (--cc >= 0) {
+ *--q = mulawtolin16[*--p][LO];
+ *--q = mulawtolin16[*p ][HI];
+ }
+}
+
void
-mulaw_compress(hdl, e, p, cc)
- void *hdl;
- int e;
+ulinear8_to_mulaw(v, p, cc)
+ void *v;
u_char *p;
int cc;
{
- u_char *tab;
-
- switch (e) {
- case AUDIO_ENCODING_ULAW:
- tab = lintomulaw;
- break;
- default:
- return;
+ while (--cc >= 0) {
+ *p = lintomulaw[*p];
+ ++p;
}
+}
+void
+alaw_to_ulinear8(v, p, cc)
+ void *v;
+ u_char *p;
+ int cc;
+{
+ /* Use the 16 bit table for 8 bits too. */
while (--cc >= 0) {
- *p = tab[*p];
+ *p = alawtolin16[*p][0];
++p;
}
}
void
-mulaw_expand(hdl, e, p, cc)
- void *hdl;
- int e;
+alaw_to_ulinear16(v, p, cc)
+ void *v;
u_char *p;
int cc;
{
- u_char *tab;
-
- switch (e) {
- case AUDIO_ENCODING_ULAW:
- tab = mulawtolin;
- break;
- default:
- return;
+ u_char *q = p;
+
+ p += cc;
+ q += cc * 2;
+ while (--cc >= 0) {
+ *--q = alawtolin16[*--p][LO];
+ *--q = alawtolin16[*p ][HI];
}
-
+}
+
+void
+ulinear8_to_alaw(v, p, cc)
+ void *v;
+ u_char *p;
+ int cc;
+{
while (--cc >= 0) {
- *p = tab[*p];
+ *p = lintoalaw[*p];
++p;
}
}
diff --git a/sys/dev/mulaw.h b/sys/dev/mulaw.h
index a7c310aeecb..bf70d089a67 100644
--- a/sys/dev/mulaw.h
+++ b/sys/dev/mulaw.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mulaw.h,v 1.2 1996/04/18 23:47:03 niklas Exp $ */
-/* $NetBSD: mulaw.h,v 1.2 1996/02/27 22:29:42 jtc Exp $ */
+/* $OpenBSD: mulaw.h,v 1.3 1998/04/26 21:03:11 provos Exp $ */
+/* $NetBSD: mulaw.h,v 1.8 1997/10/09 08:11:10 jtc Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -27,8 +27,8 @@
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
@@ -37,8 +37,13 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- * Convert 8-bit mu-law to/from 8 bit unsigned linear (PCM8)
- */
-extern void mulaw_compress __P((void *hw_hdl, int encoding, unsigned char *buf, int cnt));
-extern void mulaw_expand __P((void *hw_hdl, int encoding, unsigned char *buf, int cnt));
+/* Convert 8-bit mu-law to 16 bit unsigned linear. */
+extern void mulaw_to_ulinear16 __P((void *, u_char *buf, int cnt));
+/* Convert 8-bit mu-law to/from 8 bit unsigned linear. */
+extern void mulaw_to_ulinear8 __P((void *, u_char *buf, int cnt));
+extern void ulinear8_to_mulaw __P((void *, u_char *buf, int cnt));
+/* Convert 8-bit a-law to 16 bit unsigned linear. */
+extern void alaw_to_ulinear16 __P((void *, u_char *buf, int cnt));
+/* Convert 8-bit a-law to/from 8 bit unsigned linear. */
+extern void alaw_to_ulinear8 __P((void *, u_char *buf, int cnt));
+extern void ulinear8_to_alaw __P((void *, u_char *buf, int cnt));
diff --git a/sys/sys/audioio.h b/sys/sys/audioio.h
index 0c775418596..dcdae1a95b0 100644
--- a/sys/sys/audioio.h
+++ b/sys/sys/audioio.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: audioio.h,v 1.6 1997/07/11 22:24:32 provos Exp $ */
-/* $NetBSD: audioio.h,v 1.6 1996/04/09 20:55:22 cgd Exp $ */
+/* $OpenBSD: audioio.h,v 1.7 1998/04/26 21:03:17 provos Exp $ */
+/* $NetBSD: audioio.h,v 1.18 1997/10/28 03:26:45 mikel Exp $ */
/*
* Copyright (c) 1991-1993 Regents of the University of California.
@@ -45,18 +45,21 @@ struct audio_prinfo {
u_int sample_rate; /* sample rate in bit/s */
u_int channels; /* number of channels, usually 1 or 2 */
u_int precision; /* number of bits/sample */
- u_int encoding; /* data encoding (AUDIO_ENCODING_* above) */
+ u_int encoding; /* data encoding (AUDIO_ENCODING_* below) */
u_int gain; /* volume level */
u_int port; /* selected I/O port */
u_long seek; /* BSD extension */
- u_int ispare[3];
+ u_int avail_ports; /* available I/O ports */
+ u_int buffer_size; /* total size audio buffer */
+ u_int _ispare[1];
/* Current state of device: */
u_int samples; /* number of samples */
u_int eof; /* End Of File (zero-size writes) counter */
u_char pause; /* non-zero if paused, zero to resume */
u_char error; /* non-zero if underflow/overflow ocurred */
u_char waiting; /* non-zero if another process hangs in open */
- u_char cspare[3];
+ u_char balance; /* stereo channel balance */
+ u_char cspare[2];
u_char open; /* non-zero if currently open */
u_char active; /* non-zero if I/O is currently active */
};
@@ -65,23 +68,24 @@ typedef struct audio_prinfo audio_prinfo_t;
struct audio_info {
struct audio_prinfo play; /* Info for play (output) side */
struct audio_prinfo record; /* Info for record (input) side */
- u_int __spare;
+
+ u_int monitor_gain; /* input to output mix */
/* BSD extensions */
- u_int blocksize; /* input blocking threshold */
+ u_int blocksize; /* H/W read/write block size */
u_int hiwat; /* output high water mark */
u_int lowat; /* output low water mark */
- u_int backlog; /* samples of output backlog to gen. */
+ u_int _ispare1;
u_int mode; /* current device mode */
#define AUMODE_PLAY 0x01
#define AUMODE_RECORD 0x02
-#define AUMODE_PLAY_ALL 0x04 /* play all samples--no real-time correction */
+#define AUMODE_PLAY_ALL 0x04 /* don't do real-time correction */
};
typedef struct audio_info audio_info_t;
#ifdef _KERNEL
#define AUDIO_INITINFO(p)\
- { register int n = sizeof(struct audio_info); \
- register u_char *q = (u_char *) p; \
+ { int n = sizeof(struct audio_info); \
+ u_char *q = (u_char *) p; \
while (n-- > 0) *q++ = 0xff; }
#else
@@ -100,25 +104,70 @@ typedef struct audio_device {
char config[MAX_AUDIO_DEV_LEN];
} audio_device_t;
+typedef struct audio_offset {
+ u_int samples; /* Total number of bytes transferred */
+ u_int deltablks; /* Blocks transferred since last checked */
+ u_int offset; /* Physical transfer offset in buffer */
+} audio_offset_t;
+
/*
* Supported audio encodings
*/
/* Encoding ID's */
-#define AUDIO_ENCODING_NONE 0 /* no encoding assigned */
-#define AUDIO_ENCODING_ULAW 1
-#define AUDIO_ENCODING_ALAW 2
-#define AUDIO_ENCODING_PCM16 3
-#define AUDIO_ENCODING_LINEAR AUDIO_ENCODING_PCM16
-#define AUDIO_ENCODING_PCM8 4
-#define AUDIO_ENCODING_ADPCM 5
+#define AUDIO_ENCODING_NONE 0 /* no encoding assigned */
+#define AUDIO_ENCODING_ULAW 1 /* ITU G.711 mu-law */
+#define AUDIO_ENCODING_ALAW 2 /* ITU G.711 A-law */
+#define AUDIO_ENCODING_PCM16 3 /* signed linear PCM, obsolete */
+#define AUDIO_ENCODING_LINEAR AUDIO_ENCODING_PCM16 /* SunOS compat */
+#define AUDIO_ENCODING_PCM8 4 /* unsigned linear PCM, obsolete */
+#define AUDIO_ENCODING_LINEAR8 AUDIO_ENCODING_PCM8 /* SunOS compat */
+#define AUDIO_ENCODING_ADPCM 5 /* adaptive differential PCM */
+#define AUDIO_ENCODING_SLINEAR_LE 6
+#define AUDIO_ENCODING_SLINEAR_BE 7
+#define AUDIO_ENCODING_ULINEAR_LE 8
+#define AUDIO_ENCODING_ULINEAR_BE 9
+#define AUDIO_ENCODING_SLINEAR 10
+#define AUDIO_ENCODING_ULINEAR 11
+#define AUDIO_ENCODING_MPEG_L1_STREAM 12
+#define AUDIO_ENCODING_MPEG_L1_PACKETS 13
+#define AUDIO_ENCODING_MPEG_L1_SYSTEM 14
+#define AUDIO_ENCODING_MPEG_L2_STREAM 15
+#define AUDIO_ENCODING_MPEG_L2_PACKETS 16
+#define AUDIO_ENCODING_MPEG_L2_SYSTEM 17
typedef struct audio_encoding {
- int index;
- char name[MAX_AUDIO_DEV_LEN];
- int format_id;
+ int index;
+ char name[MAX_AUDIO_DEV_LEN];
+ int encoding;
+ int precision;
+ int flags;
+#define AUDIO_ENCODINGFLAG_EMULATED 1 /* software emulation mode */
} audio_encoding_t;
/*
+ * Balance settings.
+ */
+#define AUDIO_LEFT_BALANCE 0 /* left channel only */
+#define AUDIO_MID_BALANCE 32 /* equal left/right channel */
+#define AUDIO_RIGHT_BALANCE 64 /* right channel only */
+#define AUDIO_BALANCE_SHIFT 3
+
+/*
+ * Output ports
+ */
+#define AUDIO_SPEAKER 0x01 /* built-in speaker */
+#define AUDIO_HEADPHONE 0x02 /* headphone jack */
+#define AUDIO_LINE_OUT 0x04 /* line out */
+
+/*
+ * Input ports
+ */
+#define AUDIO_MICROPHONE 0x01 /* microphone */
+#define AUDIO_LINE_IN 0x02 /* line in */
+#define AUDIO_CD 0x04 /* on-board CD inputs */
+#define AUDIO_INTERNAL_CD_IN AUDIO_CD /* internal CDROM */
+
+/*
* Audio device operations
*/
#define AUDIO_GETINFO _IOR('A', 21, struct audio_info)
@@ -132,6 +181,12 @@ typedef struct audio_encoding {
#define AUDIO_GETFD _IOR('A', 29, int)
#define AUDIO_SETFD _IOWR('A', 30, int)
#define AUDIO_PERROR _IOR('A', 31, int)
+#define AUDIO_GETIOFFS _IOR('A', 32, struct audio_offset)
+#define AUDIO_GETOOFFS _IOR('A', 33, struct audio_offset)
+#define AUDIO_GETPROPS _IOR('A', 34, int)
+#define AUDIO_PROP_FULLDUPLEX 0x01
+#define AUDIO_PROP_MMAP 0x02
+#define AUDIO_PROP_INDEPENDENT 0x04
/*
* Mixer device
@@ -212,8 +267,8 @@ typedef struct mixer_ctrl {
*/
#define AudioNmicrophone "mic"
#define AudioNline "line"
-#define AudioNcd "CD"
-#define AudioNdac "DAC"
+#define AudioNcd "cd"
+#define AudioNdac "dac"
#define AudioNrecord "record"
#define AudioNvolume "volume"
#define AudioNmonitor "monitor"
@@ -239,18 +294,28 @@ typedef struct mixer_ctrl {
#define AudioNwave "wave"
#define AudioNmidi "midi"
#define AudioNmixerout "mixerout"
+#define AudioNswap "swap" /* swap left and right channels */
-#define AudioElinear "linear"
-#define AudioEmulaw "mulaw"
-#define AudioEalaw "alaw"
-#define AudioEpcm16 "PCM-16"
-#define AudioEpcm8 "PCM-8"
-#define AudioEadpcm "ADPCM"
+#define AudioEmulaw "mulaw"
+#define AudioEalaw "alaw"
+#define AudioEadpcm "adpcm"
+#define AudioEslinear "slinear"
+#define AudioEslinear_le "slinear_le"
+#define AudioEslinear_be "slinear_be"
+#define AudioEulinear "ulinear"
+#define AudioEulinear_le "ulinear_le"
+#define AudioEulinear_be "ulinear_be"
+#define AudioEmpeg_l1_stream "mpeg_l1_stream"
+#define AudioEmpeg_l1_packets "mpeg_l1_packets"
+#define AudioEmpeg_l1_system "mpeg_l1_system"
+#define AudioEmpeg_l2_stream "mpeg_l2_stream"
+#define AudioEmpeg_l2_packets "mpeg_l2_packets"
+#define AudioEmpeg_l2_system "mpeg_l2_system"
-#define AudioCInputs "Inputs"
-#define AudioCOutputs "Outputs"
-#define AudioCRecord "Record"
-#define AudioCMonitor "Monitor"
-#define AudioCEqualization "Equalization"
+#define AudioCinputs "inputs"
+#define AudioCoutputs "outputs"
+#define AudioCrecord "record"
+#define AudioCmonitor "monitor"
+#define AudioCequalization "equalization"
-#endif /* _SYS_AUDIOIO_H_ */
+#endif /* !_SYS_AUDIOIO_H_ */
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index b7549a27e34..ab0eec54ce9 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.24 1998/04/01 20:14:16 matthieu Exp $ */
+/* $OpenBSD: conf.h,v 1.25 1998/04/26 21:03:18 provos Exp $ */
/* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */
/*-
@@ -317,7 +317,7 @@ extern struct cdevsw cdevsw[];
#define cdev_audio_init(c,n) { \
dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
- 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev }
+ 0, dev_init(c,n,select), dev_init(c,n,mmap) }
#define cdev_svr4_net_init(c,n) { \
dev_init(c,n,open), (dev_type_close((*))) enodev, \