summaryrefslogtreecommitdiff
path: root/sys/arch/amiga
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1998-04-26 22:31:11 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1998-04-26 22:31:11 +0000
commit57ac98438bc1c769d1b9410e73c57bdf24e578ba (patch)
treec7059380ab4f60d9df5b0eb9775cf931aa598e9a /sys/arch/amiga
parent863410555c46c321a02002a7da8d93946b7b619d (diff)
Get audio framework from MI-land, scrap the local variant. Some NetBSD merging
Diffstat (limited to 'sys/arch/amiga')
-rw-r--r--sys/arch/amiga/amiga/conf.c6
-rw-r--r--sys/arch/amiga/conf/GENERIC4
-rw-r--r--sys/arch/amiga/conf/files.amiga17
-rw-r--r--sys/arch/amiga/dev/aucc.c101
-rw-r--r--sys/arch/amiga/dev/audio.c2377
-rw-r--r--sys/arch/amiga/dev/audio_if.h172
-rw-r--r--sys/arch/amiga/dev/audiovar.h130
7 files changed, 29 insertions, 2778 deletions
diff --git a/sys/arch/amiga/amiga/conf.c b/sys/arch/amiga/amiga/conf.c
index 6d2d7408ef9..196e24b7750 100644
--- a/sys/arch/amiga/amiga/conf.c
+++ b/sys/arch/amiga/amiga/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.19 1997/10/16 06:48:12 niklas Exp $ */
+/* $OpenBSD: conf.c,v 1.20 1998/04/26 22:30:57 niklas Exp $ */
/* $NetBSD: conf.c,v 1.42 1997/01/07 11:35:03 mrg Exp $ */
/*-
@@ -101,7 +101,7 @@ dev_decl(filedesc,open);
#include "com.h"
#include "lpt.h"
#include "uk.h"
-#include "new_audio.h"
+#include "audio.h"
cdev_decl(audio);
struct cdevsw cdevsw[] =
@@ -145,7 +145,7 @@ struct cdevsw cdevsw[] =
cdev_uk_init(NUK,uk), /* 36: unknown SCSI */
cdev_disk_init(NWD,wd), /* 37: ST506/ESDI/IDE disk */
cdev_disk_init(NACD,acd), /* 38: ATAPI CD-ROM */
- cdev_audio_init(NNEW_AUDIO,audio), /* 39: cc audio interface */
+ cdev_audio_init(NAUDIO,audio), /* 39: cc audio interface */
cdev_ch_init(NCH,ch), /* 40: SCSI autochanger */
cdev_disk_init(NRD,rd), /* 41: RAM disk */
};
diff --git a/sys/arch/amiga/conf/GENERIC b/sys/arch/amiga/conf/GENERIC
index 72c11a46a3a..95d0fbabfc2 100644
--- a/sys/arch/amiga/conf/GENERIC
+++ b/sys/arch/amiga/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.23 1997/10/07 11:04:52 niklas Exp $
+# $OpenBSD: GENERIC,v 1.24 1998/04/26 22:30:59 niklas Exp $
# $NetBSD: GENERIC,v 1.85 1997/08/27 19:32:49 is Exp $
#
@@ -148,7 +148,7 @@ com* at drsupio? port ? # DraCo serial
a2kbbc0 at mainbus0 # A2000 battery backed clock
a34kbbc0 at mainbus0 # A3000/A4000 battery backed clock
aucc* at mainbus0 # Amiga CC audio
-new_audio* at aucc?
+audio* at aucc?
# Ethernet cards
le* at zbus0 # Lance ethernet.
diff --git a/sys/arch/amiga/conf/files.amiga b/sys/arch/amiga/conf/files.amiga
index 1a403a7ca14..9ba612d74d0 100644
--- a/sys/arch/amiga/conf/files.amiga
+++ b/sys/arch/amiga/conf/files.amiga
@@ -1,4 +1,4 @@
-# $OpenBSD: files.amiga,v 1.27 1998/04/05 09:09:09 niklas Exp $
+# $OpenBSD: files.amiga,v 1.28 1998/04/26 22:31:01 niklas Exp $
# $NetBSD: files.amiga,v 1.62 1997/08/27 19:32:47 is Exp $
@@ -7,17 +7,6 @@ maxpartitions 16
maxusers 2 8 64
-# Transient audio stuff that will end up in the MI parts
-define new_audio {}
-define auconv
-
-# audio device, attaches to audio hardware driver
-device new_audio
-attach new_audio at new_audio
-
-file dev/auconv.c auconv
-file arch/amiga/dev/audio.c new_audio needs-flag
-
device mainbus {}
attach mainbus at root
@@ -62,8 +51,8 @@ device par
attach par at mainbus
file arch/amiga/dev/par.c par needs-count
-# audio XXX s/new_audio/audio/ after the new audio is generally used.
-device aucc: new_audio
+# audio
+device aucc: audio
attach aucc at mainbus
file arch/amiga/dev/aucc.c aucc needs-flag
diff --git a/sys/arch/amiga/dev/aucc.c b/sys/arch/amiga/dev/aucc.c
index 391e710a192..38593edb6f1 100644
--- a/sys/arch/amiga/dev/aucc.c
+++ b/sys/arch/amiga/dev/aucc.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: aucc.c,v 1.2 1997/10/07 11:04:56 niklas Exp $ */
-/* $NetBSD: aucc.c,v 1.18 1997/08/24 22:31:23 augustss Exp $ */
-#undef AUDIO_DEBUG
+/* $OpenBSD: aucc.c,v 1.3 1998/04/26 22:31:03 niklas Exp $ */
+/* $NetBSD: aucc.c,v 1.22 1998/01/12 10:39:10 thorpej Exp $ */
+
/*
* Copyright (c) 1997 Stephan Thesing
* All rights reserved.
@@ -40,15 +40,16 @@
#include <sys/ioctl.h>
#include <sys/device.h>
#include <sys/proc.h>
+#include <sys/audioio.h>
+
+#include <dev/audio_if.h>
#include <machine/cpu.h>
-#include <machine/audioio.h>
#include <amiga/amiga/cc.h>
#include <amiga/amiga/custom.h>
#include <amiga/amiga/device.h>
-#include <amiga/dev/audio_if.h>
#include <amiga/dev/auccvar.h>
#ifdef LEV6_DEFER
@@ -169,10 +170,6 @@ void aucc_close __P((void *));
int aucc_set_out_sr __P((void *, u_long));
int aucc_query_encoding __P((void *, struct audio_encoding *));
int aucc_round_blocksize __P((void *, int));
-int aucc_set_out_port __P((void *, int));
-int aucc_get_out_port __P((void *));
-int aucc_set_in_port __P((void *, int));
-int aucc_get_in_port __P((void *));
int aucc_commit_settings __P((void *));
int aucc_start_output __P((void *, void *, int, void (*)(void *),
void *));
@@ -180,8 +177,6 @@ int aucc_start_input __P((void *, void *, int, void (*)(void *),
void *));
int aucc_halt_output __P((void *));
int aucc_halt_input __P((void *));
-int aucc_cont_output __P((void *));
-int aucc_cont_input __P((void *));
int aucc_getdev __P((void *, struct audio_device *));
int aucc_set_port __P((void *, mixer_ctrl_t *));
int aucc_get_port __P((void *, mixer_ctrl_t *));
@@ -198,10 +193,6 @@ struct audio_hw_if sa_hw_if = {
aucc_query_encoding,
aucc_set_params,
aucc_round_blocksize,
- aucc_set_out_port,
- aucc_get_out_port,
- aucc_set_in_port,
- aucc_get_in_port,
aucc_commit_settings,
NULL,
NULL,
@@ -209,8 +200,6 @@ struct audio_hw_if sa_hw_if = {
aucc_start_input,
aucc_halt_output,
aucc_halt_input,
- aucc_cont_output,
- aucc_cont_input,
NULL,
aucc_getdev,
NULL,
@@ -378,7 +367,7 @@ aucc_query_encoding(addr, fp)
{
switch (fp->index) {
case 0:
- strcpy(fp->name, AudioElinear);
+ strcpy(fp->name, AudioEslinear);
fp->encoding = AUDIO_ENCODING_SLINEAR;
fp->precision = 8;
fp->flags = 0;
@@ -460,46 +449,6 @@ aucc_round_blocksize(addr, blk)
}
int
-aucc_set_out_port(addr, port) /* can set channels */
- void *addr;
- int port;
-{
- struct aucc_softc *sc = addr;
-
- /* port is mask for channels 0..3 */
- if ((port < 0) || (port > 15))
- return (EINVAL);
-
- sc->sc_channelmask = port;
-
- return (0);
-}
-
-int
-aucc_get_out_port(addr)
- void *addr;
-{
- struct aucc_softc *sc = addr;
-
- return (sc->sc_channelmask);
-}
-
-int
-aucc_set_in_port(addr, port)
- void *addr;
- int port;
-{
- return (EINVAL); /* no input possible */
-}
-
-int
-aucc_get_in_port(addr)
- void *addr;
-{
- return (0);
-}
-
-int
aucc_commit_settings(addr)
void *addr;
{
@@ -679,23 +628,6 @@ aucc_halt_input(addr)
}
int
-aucc_cont_output(addr)
- void *addr;
-{
- DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
- /* reenable DMA XXX */
- return (ENXIO);
-}
-
-int
-aucc_cont_input(addr)
- void *addr;
-{
- DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
- return (0);
-}
-
-int
aucc_getdev(addr, retp)
void *addr;
struct audio_device *retp;
@@ -735,11 +667,20 @@ aucc_set_port(addr, cp)
#endif
/* set volume for channel 0..i-1 */
- if (i > 1)
+
+ /* evil workaround for xanim bug, IMO */
+ if ((sc->sc_channels == 1) && (i == 2)) {
+ sc->sc_channel[0].nd_volume =
+ sc->sc_channel[3].nd_volume =
+ cp->un.value.level[0] >> 2;
+ sc->sc_channel[1].nd_volume =
+ sc->sc_channel[2].nd_volume =
+ cp->un.value.level[1] >> 2;
+ } else if (i > 1) {
for (j = 0; j < i; j++)
sc->sc_channel[j].nd_volume =
cp->un.value.level[j] >> 2;
- else if (sc->sc_channels > 1)
+ } else if (sc->sc_channels > 1)
for (j = 0; j < sc->sc_channels; j++)
sc->sc_channel[j].nd_volume =
cp->un.value.level[0] >> 2;
@@ -809,7 +750,7 @@ aucc_query_devinfo(addr, dip)
dip->type = AUDIO_MIXER_SET;
dip->mixer_class = AUCC_OUTPUT_CLASS;
dip->prev = dip->next = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioNspeaker);
+ strcpy(dip->label.name, AudioNmaster);
for (i = 0; i < 16; i++) {
sprintf(dip->un.s.member[i].label.name,
"channelmask%d", i);
@@ -831,11 +772,11 @@ aucc_query_devinfo(addr, dip)
dip->type = AUDIO_MIXER_CLASS;
dip->mixer_class = AUCC_OUTPUT_CLASS;
dip->next = dip->prev = AUDIO_MIXER_LAST;
- strcpy(dip->label.name, AudioCOutputs);
+ strcpy(dip->label.name, AudioCoutputs);
break;
+
default:
return (ENXIO);
- /*NOTREACHED*/
}
DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
diff --git a/sys/arch/amiga/dev/audio.c b/sys/arch/amiga/dev/audio.c
deleted file mode 100644
index 538615a72c0..00000000000
--- a/sys/arch/amiga/dev/audio.c
+++ /dev/null
@@ -1,2377 +0,0 @@
-/* $OpenBSD: audio.c,v 1.1 1997/10/07 11:04:57 niklas 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.
- * 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.
- */
-
-/*
- * This is a (partially) SunOS-compatible /dev/audio driver for Net- & OpenBSD.
- *
- * This code tries to do something half-way sensible with
- * half-duplex hardware, such as with the SoundBlaster hardware. With
- * half-duplex hardware allowing O_RDWR access doesn't really make
- * sense. However, closing and opening the device to "turn around the
- * line" is relatively expensive and costs a card reset (which can
- * take some time, at least for the SoundBlaster hardware). Instead
- * we allow O_RDWR access, and provide an ioctl to set the "mode",
- * i.e. playing or recording.
- *
- * If you write to a half-duplex device in record mode, the data is
- * tossed. If you read from the device in play mode, you get silence
- * filled buffers at the rate at which samples are naturally
- * generated.
- *
- * If you try to set both play and record mode on a half-duplex
- * device, playing takes precedence.
- */
-
-/*
- * Todo:
- * - Add softaudio() isr processing for wakeup, poll, signals,
- * and silence fill.
- */
-
-#include "new_audio.h"
-#if NNEW_AUDIO > 0
-
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#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>
-#include <sys/syslog.h>
-#include <sys/kernel.h>
-#include <sys/signalvar.h>
-#include <sys/conf.h>
-#include <sys/device.h>
-
-#include <machine/audioio.h>
-#include <machine/endian.h>
-
-#include <amiga/dev/audio_if.h>
-#include <amiga/dev/audiovar.h>
-
-#include <vm/vm.h>
-#include <vm/vm_prot.h>
-
-#ifdef AUDIO_DEBUG
-#define DPRINTF(x) if (audiodebug) printf x
-int audiodebug = 0;
-#else
-#define DPRINTF(x)
-#endif
-
-#define ROUNDSIZE(x) x &= -16 /* round to nice boundary */
-
-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 *));
-
-int audio_open __P((dev_t, int, int, struct proc *));
-int audio_close __P((dev_t, int, int, struct proc *));
-int audio_read __P((dev_t, struct uio *, int));
-int audio_write __P((dev_t, struct uio *, int));
-int audio_ioctl __P((dev_t, int, caddr_t, int, struct proc *));
-int audio_select __P((dev_t, int, struct proc *));
-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 *));
-int audiostartr __P((struct audio_softc *));
-int audiostartp __P((struct audio_softc *));
-void audio_rint __P((void *));
-void audio_pint __P((void *));
-int audio_check_params __P((struct audio_params *));
-
-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_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));
-
-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 *));
-
-int audioprobe __P((struct device *, void *, void *));
-void audioattach __P((struct device *, struct device *, void *));
-
-/* The default audio mode: 8 kHz mono ulaw */
-struct audio_params audio_default =
- { 8000, AUDIO_ENCODING_ULAW, 8, 1, 0, 1 };
-
-struct cfattach new_audio_ca = {
- sizeof(struct audio_softc), audioprobe, audioattach
-};
-
-struct cfdriver new_audio_cd = {
- NULL, "audio", DV_DULL
-};
-
-int
-audioprobe(parent, match, aux)
- struct device *parent;
- void *match;
- void *aux;
-{
- struct audio_attach_args *sa = aux;
-
- DPRINTF(("audioprobe: done=%d sa=%p hw=%p\n",
- sa->audiodone, sa, sa->ahw));
- if (sa->audiodone)
- return 0;
- return sa->ahw != 0;
-}
-
-void
-audioattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
- struct audio_softc *sc = (void *)self;
- struct audio_attach_args *sa = aux;
- struct audio_hw_if *hwp = sa->ahw;
- void *hdlp = sa->hdl;
- int error;
-
- printf("\n");
-
- sa->audiodone++;
-
-#ifdef DIAGNOSTIC
- if (hwp == 0 ||
- hwp->open == 0 ||
- hwp->close == 0 ||
- hwp->query_encoding == 0 ||
- hwp->set_params == 0 ||
- hwp->set_out_port == 0 ||
- hwp->get_out_port == 0 ||
- hwp->set_in_port == 0 ||
- hwp->get_in_port == 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 ||
- hwp->get_props == 0) {
- printf("audio: missing method\n");
- sc->hw_if = 0;
- return;
- }
-#endif
-
- sc->hw_if = hwp;
- sc->hw_hdl = hdlp;
- sc->sc_dev = parent;
-
- error = audio_alloc_ring(sc, &sc->sc_pr, AU_RING_SIZE);
- if (error) {
- sc->hw_if = 0;
- return;
- }
- 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_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);
-}
-
-/*
- * 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_attach_args arg;
-
- arg.ahw = ahwp;
- arg.mhw = mhwp;
- arg.hdl = hdlp;
- arg.audiodone = arg.mididone = 0;
- while(config_found(dev, &arg, 0))
- ;
-}
-
-#ifdef AUDIO_DEBUG
-void audio_printsc __P((struct audio_softc *));
-void audio_print_params __P((char *, struct audio_params *));
-
-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);
-}
-
-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
-
-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;
-}
-
-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
-audioopen(dev, flags, ifmt, p)
- dev_t dev;
- int flags, ifmt;
- struct proc *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));
- default:
- return (ENXIO);
- }
-}
-
-int
-audioclose(dev, flags, ifmt, p)
- dev_t dev;
- int flags, ifmt;
- struct proc *p;
-{
-
- switch (AUDIODEV(dev)) {
- case SOUND_DEVICE:
- case AUDIO_DEVICE:
- 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);
- }
-}
-
-int
-audioread(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
-
- switch (AUDIODEV(dev)) {
- case SOUND_DEVICE:
- case AUDIO_DEVICE:
- return (audio_read(dev, uio, ioflag));
- case AUDIOCTL_DEVICE:
- case MIXER_DEVICE:
- return (ENODEV);
- default:
- return (ENXIO);
- }
-}
-
-int
-audiowrite(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
-
- switch (AUDIODEV(dev)) {
- case SOUND_DEVICE:
- case AUDIO_DEVICE:
- return (audio_write(dev, uio, ioflag));
- case AUDIOCTL_DEVICE:
- case MIXER_DEVICE:
- return (ENODEV);
- default:
- return (ENXIO);
- }
-}
-
-int
-audioioctl(dev, cmd, addr, flag, p)
- dev_t dev;
- u_long cmd;
- caddr_t addr;
- int flag;
- struct proc *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));
- default:
- return (ENXIO);
- }
-}
-
-int
-audioselect(dev, events, p)
- dev_t dev;
- int events;
- struct proc *p;
-{
-
- switch (AUDIODEV(dev)) {
- case SOUND_DEVICE:
- case AUDIO_DEVICE:
- return (audio_select(dev, events, p));
- case AUDIOCTL_DEVICE:
- case MIXER_DEVICE:
- return (0);
- default:
- return (0);
- }
-}
-
-int
-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 -1;
- default:
- return -1;
- }
-}
-
-/*
- * Audio driver
- */
-void
-audio_init_ringbuffer(rp)
- struct audio_ringbuffer *rp;
-{
- 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;
-}
-
-int
-audio_initbufs(sc)
- struct audio_softc *sc;
-{
- struct audio_hw_if *hw = sc->hw_if;
- int error;
-
- 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
-audio_sleep_timo(chan, label, timo)
- int *chan;
- char *label;
- int timo;
-{
- int st;
-
- if (!label)
- label = "audio";
-
- *chan = 1;
- st = tsleep(chan, PWAIT | PCATCH, label, timo);
- *chan = 0;
-#ifdef AUDIO_DEBUG
- if (st != 0)
- printf("audio_sleep: %d\n", st);
-#endif
- return (st);
-}
-
-static __inline int
-audio_sleep(chan, label)
- int *chan;
- char *label;
-{
- return audio_sleep_timo(chan, label, 0);
-}
-
-/* call at splaudio() */
-static __inline void
-audio_wakeup(chan)
- int *chan;
-{
- if (*chan) {
- wakeup(chan);
- *chan = 0;
- }
-}
-
-int
-audio_open(dev, flags, ifmt, p)
- dev_t dev;
- int flags, ifmt;
- struct proc *p;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc;
- int error;
- int mode;
- struct audio_hw_if *hw;
- struct audio_info ai;
-
- if (unit >= new_audio_cd.cd_ndevs ||
- (sc = new_audio_cd.cd_devs[unit]) == NULL)
- return ENXIO;
-
- hw = sc->hw_if;
- if (!hw)
- return ENXIO;
-
- DPRINTF(("audio_open: dev=0x%x flags=0x%x sc=%p hdl=%p\n", dev, flags, sc, sc->hw_hdl));
-
- if (ISDEVAUDIOCTL(dev))
- return 0;
-
- if ((sc->sc_open & (AUOPEN_READ|AUOPEN_WRITE)) != 0)
- return (EBUSY);
-
- error = hw->open(sc->hw_hdl, flags);
- if (error)
- return (error);
-
- 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;
- 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)
- * The /dev/audio is always (re)set to 8-bit MU-Law mono
- * For the other devices, you get what they were last set to.
- */
- if (ISDEVAUDIO(dev)) {
- /* /dev/audio */
- 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.
- */
- if (sc->sc_rparams.precision == 0 || sc->sc_pparams.precision == 0) {
- printf("audio_open: 0 precision\n");
- return EINVAL;
- }
-#endif
-
- 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: done sc_mode = 0x%x\n", sc->sc_mode));
-
- return 0;
-
-bad:
- hw->close(sc->hw_hdl);
- sc->sc_open = 0;
- sc->sc_mode = 0;
- sc->sc_full_duplex = 0;
- return error;
-}
-
-/*
- * Must be called from task context.
- */
-void
-audio_init_record(sc)
- struct audio_softc *sc;
-{
- int s = splaudio();
-
- if (sc->hw_if->speaker_ctl &&
- (!sc->sc_full_duplex || (sc->sc_mode & AUMODE_PLAY) == 0))
- sc->hw_if->speaker_ctl(sc->hw_hdl, SPKR_OFF);
- splx(s);
-}
-
-/*
- * Must be called from task context.
- */
-void
-audio_init_play(sc)
- struct audio_softc *sc;
-{
- int s = splaudio();
-
- 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);
-}
-
-int
-audio_drain(sc)
- struct audio_softc *sc;
-{
- int error, drops;
- struct audio_ringbuffer *cb = &sc->sc_pr;
- int s;
-
- 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));
- /*
- * When the process is exiting, it ignores all signals and
- * we can't interrupt this sleep, so we set a timeout just in case.
- */
- error = audio_sleep_timo(&sc->sc_wchan, "aud_dr", 30*hz);
- }
- splx(s);
- return error;
-}
-
-/*
- * Close an audio chip.
- */
-/* ARGSUSED */
-int
-audio_close(dev, flags, ifmt, p)
- dev_t dev;
- int flags, ifmt;
- struct proc *p;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_audio_cd.cd_devs[unit];
- struct audio_hw_if *hw = sc->hw_if;
- int s;
-
- DPRINTF(("audio_close: unit=%d\n", unit));
-
- /*
- * Block until output drains, but allow ^C interrupt.
- */
- 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_pr.pause) {
- if (!audio_drain(sc) && hw->drain)
- (void)hw->drain(sc->hw_hdl);
- }
-
- hw->close(sc->hw_hdl);
-
- if (flags & FREAD)
- sc->sc_open &= ~AUOPEN_READ;
- if (flags & FWRITE)
- sc->sc_open &= ~AUOPEN_WRITE;
-
- sc->sc_async_audio = 0;
- sc->sc_mode = 0;
- sc->sc_full_duplex = 0;
- splx(s);
- DPRINTF(("audio_close: done\n"));
-
- return (0);
-}
-
-int
-audio_read(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_audio_cd.cd_devs[unit];
- struct audio_ringbuffer *cb = &sc->sc_rr;
- u_char *outp;
- int error, s, used, cc, n;
-
- if (cb->mmapped)
- return EINVAL;
-
-#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 (!sc->sc_full_duplex &&
- (sc->sc_mode & AUMODE_PLAY)) {
- while (uio->uio_resid > 0 && !error) {
- s = splaudio();
- 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;
- }
- error = audio_sleep(&sc->sc_rchan, "aud_hr");
- if (error) {
- splx(s);
- return error;
- }
- }
- splx(s);
-
- 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);
- }
- while (uio->uio_resid > 0 && !error) {
- s = splaudio();
- while (cb->used <= 0) {
- if (ioflag & IO_NDELAY) {
- 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;
- }
- }
- 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);
-}
-
-void
-audio_clear(sc)
- struct audio_softc *sc;
-{
- int s = splaudio();
-
- 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;
- }
- splx(s);
-}
-
-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 = 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(params, p, n)
- struct audio_params *params;
- u_char *p;
- int n;
-{
- u_char auzero0, auzero1 = 0; /* initialize to please gcc */
- int nfill = 1;
-
- switch (params->encoding) {
- case AUDIO_ENCODING_ULAW:
- auzero0 = 0x7f;
- break;
- case AUDIO_ENCODING_ALAW:
- auzero0 = 0x55;
- break;
- case AUDIO_ENCODING_ADPCM: /* is this right XXX */
- 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:
- printf("audio: bad encoding %d\n", params->encoding);
- auzero0 = 0;
- break;
- }
- if (nfill == 1) {
- while (--n >= 0)
- *p++ = auzero0; /* XXX memset */
- } else /* nfill must be 2 */ {
- while (n > 1) {
- *p++ = auzero0;
- *p++ = auzero1;
- n -= 2;
- }
- }
-}
-
-int
-audio_silence_copyout(sc, n, uio)
- struct audio_softc *sc;
- int n;
- struct uio *uio;
-{
- int error;
- int k;
- u_char zerobuf[128];
-
- audio_fill_silence(&sc->sc_rparams, zerobuf, sizeof zerobuf);
-
- 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;
- }
- return (error);
-}
-
-int
-audio_write(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_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;
- }
-
- /*
- * If half-duplex and currently recording, throw away data.
- */
- 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);
- }
-
- 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
-
- error = 0;
- while (uio->uio_resid > 0 && !error) {
- s = splaudio();
- 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);
- 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;
- }
- 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
- /*
- * 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
-#ifdef AUDIO_DEBUG
- if (audiodebug > 1)
- printf("audio_write: uiomove cc=%d inp=%p, left=%d\n", cc, inp, uio->uio_resid);
-#endif
- 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 (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;
-
- s = splaudio();
- /*
- * 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);
-}
-
-int
-audio_ioctl(dev, cmd, addr, flag, p)
- dev_t dev;
- int cmd;
- caddr_t addr;
- int flag;
- struct proc *p;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_audio_cd.cd_devs[unit];
- struct audio_hw_if *hw = sc->hw_if;
- struct audio_offset *ao;
- int error = 0, s, offs, fd;
-
- 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_audio)
- return (EBUSY);
- sc->sc_async_audio = p;
- DPRINTF(("audio_ioctl: FIOASYNC %p\n", p));
- } else
- sc->sc_async_audio = 0;
- break;
-
- case AUDIO_FLUSH:
- DPRINTF(("AUDIO_FLUSH\n"));
- audio_clear(sc);
- s = splaudio();
- error = audio_initbufs(sc);
- if (error) {
- splx(s);
- return error;
- }
- if ((sc->sc_mode & AUMODE_PLAY) && !sc->sc_pbus)
- error = audiostartp(sc);
- if (!error &&
- (sc->sc_mode & AUMODE_RECORD) && !sc->sc_rbus)
- error = audiostartr(sc);
- splx(s);
- break;
-
- /*
- * Number of read (write) samples dropped. We don't know where or
- * when they were dropped.
- */
- case AUDIO_RERROR:
- *(int *)addr = sc->sc_rr.drops;
- break;
-
- case AUDIO_PERROR:
- *(int *)addr = sc->sc_pr.drops;
- break;
-
- /*
- * Offsets into buffer.
- */
- 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();
- /* 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 mode=0x%x\n", sc->sc_mode));
- error = audiosetinfo(sc, (struct audio_info *)addr);
- break;
-
- case AUDIO_GETINFO:
- DPRINTF(("AUDIO_GETINFO\n"));
- error = audiogetinfo(sc, (struct audio_info *)addr);
- break;
-
- case AUDIO_DRAIN:
- DPRINTF(("AUDIO_DRAIN\n"));
- error = audio_drain(sc);
- if (!error && hw->drain)
- error = hw->drain(sc->hw_hdl);
- break;
-
- case AUDIO_GETDEV:
- DPRINTF(("AUDIO_GETDEV\n"));
- error = hw->getdev(sc->hw_hdl, (audio_device_t *)addr);
- break;
-
- case AUDIO_GETENC:
- DPRINTF(("AUDIO_GETENC\n"));
- error = hw->query_encoding(sc->hw_hdl, (struct audio_encoding *)addr);
- break;
-
-#ifdef COMPAT_12
- /* GETPROPS contains the same info (and more) */
- case AUDIO_GETFD:
- DPRINTF(("AUDIO_GETFD\n"));
- *(int *)addr =
- (hw->get_props(sc->hw_hdl) & AUDIO_PROP_FULLDUPLEX) != 0;
- break;
-#endif
- case AUDIO_SETFD:
- DPRINTF(("AUDIO_SETFD\n"));
- 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:
- DPRINTF(("audio_ioctl: unknown ioctl\n"));
- error = EINVAL;
- break;
- }
- DPRINTF(("audio_ioctl(%d,'%c',%d) result %d\n",
- IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
- return (error);
-}
-
-int
-audio_select(dev, rw, p)
- dev_t dev;
- int rw;
- struct proc *p;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_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
- switch (rw) {
-
- case FREAD:
- 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);
- }
- selrecord(p, &sc->sc_rsel);
- break;
-
- case FWRITE:
- if (sc->sc_mode & AUMODE_RECORD ||
- sc->sc_pr.used <= sc->sc_pr.usedlow) {
- splx(s);
- return (1);
- }
- selrecord(p, &sc->sc_wsel);
- break;
- }
- splx(s);
- return (0);
-}
-
-int
-audio_mmap(dev, off, prot)
- dev_t dev;
- int off, prot;
-{
- int s;
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_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);
-}
-
-int
-audiostartr(sc)
- struct audio_softc *sc;
-{
- int error;
-
- 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->sc_rr.start,
- sc->sc_rr.blksize, audio_rint, (void *)sc);
- if (error) {
- DPRINTF(("audiostartr failed: %d\n", error));
- return error;
- }
- sc->sc_rbus = 1;
- return 0;
-}
-
-int
-audiostartp(sc)
- struct audio_softc *sc;
-{
- int error;
-
- 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->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));
- return error;
- }
- sc->sc_pbus = 1;
- }
- return 0;
-}
-
-/*
- * 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.
- */
-/* 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;
-{
- 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);
- }
-}
-
-/*
- * Called from HW driver module on completion of dma output.
- * Start output of new block, wrap in ring buffer if needed.
- * If no more buffers to play, output zero instead.
- * Do a wakeup if necessary.
- */
-void
-audio_pint(v)
- void *v;
-{
- struct audio_softc *sc = v;
- struct audio_hw_if *hw = sc->hw_if;
- struct audio_ringbuffer *cb = &sc->sc_pr;
- u_char *inp;
- int cc, ccr;
- int error;
-
- 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 > 2)
- printf("audio_pint: mmapped outp=%p cc=%d inp=%p\n",
- cb->outp, cb->blksize, cb->inp);
-#endif
- (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)
- printf("audio_pint: copying in progress\n");
-#endif
- } 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);
- }
- }
-
-#ifdef AUDIO_DEBUG
- if (audiodebug > 3)
- printf("audio_pint: outp=%p cc=%d\n", cb->outp, cb->blksize);
-#endif
- 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
- 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->pause) {
- if (cb->used <= cb->usedlow) {
- audio_wakeup(&sc->sc_wchan);
- selwakeup(&sc->sc_wsel);
- 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);
- }
- }
- }
-
- /* 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_audio)
- psignal(sc->sc_async_audio, SIGIO);
- }
-}
-
-/*
- * Called from HW driver module on completion of dma input.
- * Mark it as input in the ring buffer (fiddle pointers).
- * Do a wakeup if necessary.
- */
-void
-audio_rint(v)
- void *v;
-{
- struct audio_softc *sc = v;
- struct audio_hw_if *hw = sc->hw_if;
- struct audio_ringbuffer *cb = &sc->sc_rr;
- int error;
-
- 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 > 2)
- printf("audio_rint: mmapped inp=%p cc=%d\n",
- cb->inp, cb->blksize);
-#endif
- (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);
- }
- 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_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 (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 (p->encoding) {
- case AUDIO_ENCODING_ULAW:
- case AUDIO_ENCODING_ALAW:
- case AUDIO_ENCODING_ADPCM:
- if (p->precision != 8)
- return (EINVAL);
- break;
- 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;
- default:
- return (EINVAL);
- }
-
- if (p->channels < 1 || p->channels > 8) /* sanity check # of channels */
- return (EINVAL);
-
- return (0);
-}
-
-int
-audiosetinfo(sc, ai)
- struct audio_softc *sc;
- struct audio_info *ai;
-{
- struct audio_prinfo *r = &ai->record, *p = &ai->play;
- int cleared;
- int s, setmode;
- int error;
- struct audio_hw_if *hw = sc->hw_if;
- mixer_ctrl_t ct;
- struct audio_params pp, rp;
- int np, nr;
- unsigned int blks;
- int oldpblksize, oldrblksize;
- int rbus, pbus;
-
- if (hw == 0) /* HW has not attached */
- return(ENXIO);
-
- rbus = sc->sc_rbus;
- pbus = sc->sc_pbus;
- error = 0;
- cleared = 0;
-
- pp = sc->sc_pparams; /* Temporary encoding storage in */
- rp = sc->sc_rparams; /* case setting the modes fails. */
- nr = np = 0;
-
- if (p->sample_rate != ~0) {
- pp.sample_rate = p->sample_rate;
- np++;
- }
- if (r->sample_rate != ~0) {
- rp.sample_rate = r->sample_rate;
- nr++;
- }
- if (p->encoding != ~0) {
- pp.encoding = p->encoding;
- np++;
- }
- 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;
- rp.sw_code = 0;
- rp.factor = 1;
- setmode |= AUMODE_RECORD;
- }
- if (np) {
- if (!cleared)
- audio_clear(sc);
- cleared = 1;
- pp.sw_code = 0;
- pp.factor = 1;
- setmode |= AUMODE_PLAY;
- }
-
- 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;
- }
-
- 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);
- 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;
- }
-
- 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);
- if (error)
- return(error);
- }
- if (r->port != ~0) {
- if (!cleared)
- audio_clear(sc);
- cleared = 1;
-
- error = hw->set_in_port(sc->hw_hdl, 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);
- if (error)
- return(error);
- }
- if (r->gain != ~0) {
- ct.dev = hw->get_in_port(sc->hw_hdl);
- 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);
- if (error)
- return(error);
- }
-
- if (p->pause != (u_char)~0) {
- sc->sc_pr.pause = p->pause;
- if (!p->pause && !sc->sc_pbus) {
- s = splaudio();
- error = audiostartp(sc);
- splx(s);
- if (error)
- return error;
- }
- }
- if (r->pause != (u_char)~0) {
- sc->sc_rr.pause = r->pause;
- if (!r->pause && !sc->sc_rbus) {
- s = splaudio();
- error = audiostartr(sc);
- splx(s);
- if (error)
- return error;
- }
- }
-
- if (ai->blocksize != ~0) {
- /* Block size specified explicitly. */
- if (!cleared)
- audio_clear(sc);
- cleared = 1;
-
- 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->mode != ~0) {
- if (sc->sc_mode & AUMODE_PLAY)
- audio_init_play(sc);
- if (sc->sc_mode & AUMODE_RECORD)
- audio_init_record(sc);
- }
-
- if (hw->commit_settings) {
- error = hw->commit_settings(sc->hw_hdl);
- if (error)
- return (error);
- if (p->gain != ~0 || r->gain != ~0)
- mixer_signal(sc);
- }
-
- if (cleared) {
- s = splaudio();
- 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 < 1)
- blks = 1;
- 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;
- }
-
- return (0);
-}
-
-int
-audiogetinfo(sc, ai)
- struct audio_softc *sc;
- struct audio_info *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 = 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 = 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;
-
- 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->eof = sc->sc_eof;
- r->eof = 0;
-
- p->pause = sc->sc_pr.pause;
- r->pause = sc->sc_rr.pause;
-
- p->error = sc->sc_pr.drops != 0;
- r->error = sc->sc_rr.drops != 0;
-
- p->waiting = r->waiting = 0; /* open never hangs */
-
- 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;
-
- ai->buffersize = sc->sc_pr.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->backlog = 0; /* unused */
- ai->mode = sc->sc_mode;
-
- return (0);
-}
-
-/*
- * Mixer driver
- */
-int
-mixer_open(dev, flags, ifmt, p)
- dev_t dev;
- int flags, ifmt;
- struct proc *p;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc;
-
- if (unit >= new_audio_cd.cd_ndevs ||
- (sc = new_audio_cd.cd_devs[unit]) == NULL)
- return ENXIO;
-
- 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 waitinf 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 */
-int
-mixer_close(dev, flags, ifmt, p)
- dev_t dev;
- int flags, ifmt;
- struct proc *p;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_audio_cd.cd_devs[unit];
-
- DPRINTF(("mixer_close: unit %d\n", AUDIOUNIT(dev)));
-
- mixer_remove(sc, p);
-
- return (0);
-}
-
-int
-mixer_ioctl(dev, cmd, addr, flag, p)
- dev_t dev;
- int cmd;
- caddr_t addr;
- int flag;
- struct proc *p;
-{
- int unit = AUDIOUNIT(dev);
- struct audio_softc *sc = new_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));
-
- 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;
-
- case AUDIO_MIXER_DEVINFO:
- 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;
-
- case AUDIO_MIXER_WRITE:
- 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;
- }
- DPRINTF(("mixer_ioctl(%d,'%c',%d) result %d\n",
- IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd&0xff, error));
- return (error);
-}
-#endif
diff --git a/sys/arch/amiga/dev/audio_if.h b/sys/arch/amiga/dev/audio_if.h
deleted file mode 100644
index 7daecc79b34..00000000000
--- a/sys/arch/amiga/dev/audio_if.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/* $OpenBSD: audio_if.h,v 1.1 1997/10/07 11:04:59 niklas Exp $ */
-/* $NetBSD: audio_if.h,v 1.21 1997/09/06 01:14:49 augustss Exp $ */
-
-/*
- * Copyright (c) 1994 Havard Eidnes.
- * 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.
- *
- */
-
-/*
- * Generic interface to hardware driver.
- */
-
-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((void *, int)); /* open hardware */
- void (*close)__P((void *)); /* close hardware */
- int (*drain)__P((void *)); /* Optional: drain buffers */
-
- /* Encoding. */
- /* XXX should we have separate in/out? */
- int (*query_encoding)__P((void *, struct audio_encoding *));
-
- /* 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
- * change several settings in quick succession. To avoid
- * having to take the device in/out of "data mode", we provide
- * this function which indicates completion of settings
- * adjustment.
- */
- int (*commit_settings)__P((void *));
-
- /* 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
-#define SPKR_OFF 0
-
- int (*getdev)__P((void *, struct audio_device *));
- int (*setfd)__P((void *, int));
-
- /* Mixer (in/out ports) */
- int (*set_port)__P((void *, mixer_ctrl_t *));
- int (*get_port)__P((void *, mixer_ctrl_t *));
-
- int (*query_devinfo)__P((void *, mixer_devinfo_t *));
-
- /* 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 */
-};
-
-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 {
- struct audio_hw_if *ahw;
- struct midi_hw_if *mhw;
- void *hdl;
- char audiodone, mididone;
-};
-
-/* 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 AUDIOUNIT(x) (minor(x)&0x0f)
-#define AUDIODEV(x) (minor(x)&0xf0)
-
-#define ISDEVSOUND(x) (AUDIODEV(minor(x)) == SOUND_DEVICE)
-#define ISDEVAUDIO(x) (AUDIODEV(minor(x)) == AUDIO_DEVICE)
-#define ISDEVAUDIOCTL(x) (AUDIODEV(minor(x)) == AUDIOCTL_DEVICE)
-#define ISDEVMIXER(x) (AUDIODEV(minor(x)) == MIXER_DEVICE)
-
-#ifndef __i386__
-#define splaudio splbio /* XXX */
-#define IPL_AUDIO IPL_BIO /* XXX */
-#endif
-
diff --git a/sys/arch/amiga/dev/audiovar.h b/sys/arch/amiga/dev/audiovar.h
deleted file mode 100644
index 6e91e1c3b82..00000000000
--- a/sys/arch/amiga/dev/audiovar.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* $OpenBSD: audiovar.h,v 1.1 1997/10/07 11:04:59 niklas Exp $ */
-/* $NetBSD: audiovar.h,v 1.16 1997/08/19 23:49:58 augustss Exp $ */
-
-/*
- * 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.
- *
- * From: Header: audiovar.h,v 1.3 93/07/18 14:07:25 mccanne Exp (LBL)
- */
-
-/*
- * Initial/default block duration is both configurable and patchable.
- */
-#ifndef AUDIO_BLK_MS
-#define AUDIO_BLK_MS 50 /* 50 ms */
-#endif
-
-#ifndef AU_RING_SIZE
-#define AU_RING_SIZE 65536
-#endif
-
-#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 */
-};
-
-/*
- * Software state, per audio device.
- */
-struct audio_softc {
- 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
- u_char sc_mode; /* bitmask for RECORD/PLAY */
-
- struct selinfo sc_wsel; /* write selector */
- struct selinfo sc_rsel; /* read selector */
- 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_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 sc_rbus; /* input dma in progress */
- u_char sc_pbus; /* output dma in progress */
-
- 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_full_duplex; /* device in full duplex mode */
-
-#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
-};