Move around splaudio() to (hopefully) get rid of some rare race conditions.

Add a missing call to round_blocksize.
Add some MIDI stuff that will be used in the future.
This commit is contained in:
augustss 1997-09-06 01:14:48 +00:00
parent 0b471e545e
commit ffcdaf144d
2 changed files with 70 additions and 36 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: audio.c,v 1.70 1997/08/27 18:54:28 thorpej 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.
@ -161,12 +161,6 @@ struct cfdriver audio_cd = {
NULL, "audio", DV_DULL
};
struct audio_attach_args {
struct audio_hw_if *ahw;
struct midi_hw_if *mhw;
void *hdl;
};
int
audioprobe(parent, match, aux)
struct device *parent;
@ -179,6 +173,10 @@ audioprobe(parent, match, 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;
}
@ -195,6 +193,8 @@ audioattach(parent, self, aux)
printf("\n");
sa->audiodone++;
#ifdef DIAGNOSTIC
if (hwp == 0 ||
hwp->open == 0 ||
@ -255,7 +255,7 @@ audioattach(parent, self, aux)
/*
* Called from hardware driver. This is where the MI audio driver gets
* probed/attached to the hardare driver.
* probed/attached to the hardware driver.
*/
void
audio_attach_mi(ahwp, mhwp, hdlp, dev)
@ -269,7 +269,9 @@ audio_attach_mi(ahwp, mhwp, hdlp, dev)
arg.ahw = ahwp;
arg.mhw = mhwp;
arg.hdl = hdlp;
(void)config_found(dev, &arg, 0);
arg.audiodone = arg.mididone = 0;
while(config_found(dev, &arg, 0))
;
}
#ifdef AUDIO_DEBUG
@ -573,7 +575,7 @@ audio_sleep_timo(chan, label, timo)
if (!label)
label = "audio";
*chan = 1;
st = tsleep(chan, PWAIT | PCATCH, label, timo);
*chan = 0;
@ -592,6 +594,7 @@ audio_sleep(chan, label)
return audio_sleep_timo(chan, label, 0);
}
/* call at splaudio() */
static __inline void
audio_wakeup(chan)
int *chan;
@ -746,6 +749,7 @@ audio_drain(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;
@ -753,7 +757,7 @@ audio_drain(sc)
/* We've never started playing, probably because the
* block was too short. Pad it and start now.
*/
int s, cc;
int cc;
u_char *inp = cb->inp;
cc = cb->blksize - (inp - cb->start) % cb->blksize;
@ -782,17 +786,18 @@ audio_drain(sc)
}
#endif
drops = cb->drops;
while (cb->drops == 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);
if (error)
return (error);
}
return (0);
splx(s);
return error;
}
/*
@ -879,12 +884,12 @@ audio_read(dev, uio, ioflag)
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");
if (error) {
splx(s);
return (error);
return error;
}
}
splx(s);
@ -901,27 +906,29 @@ audio_read(dev, uio, ioflag)
return (error);
}
while (uio->uio_resid > 0 && !error) {
s = splaudio();
while (cb->used <= 0) {
if (ioflag & IO_NDELAY) {
error = EWOULDBLOCK;
return (error);
splx(s);
return EWOULDBLOCK;
}
s = splaudio();
if (!sc->sc_rbus) {
error = audiostartr(sc);
if (error) goto err;
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");
err:
splx(s);
if (error)
return (error);
if (error) {
splx(s);
return error;
}
}
s = splaudio();
used = cb->used;
outp = cb->outp;
cb->copying = 1;
@ -1133,16 +1140,20 @@ audio_write(dev, uio, ioflag)
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)
if (ioflag & IO_NDELAY) {
splx(s);
return (EWOULDBLOCK);
}
error = audio_sleep(&sc->sc_wchan, "aud wr");
if (error)
return (error);
if (error) {
splx(s);
return error;
}
}
s = splaudio();
used = cb->used;
inp = cb->inp;
cb->copying = 1;
@ -1226,7 +1237,7 @@ audio_write(dev, uio, ioflag)
cb->needfill = 0;
cb->copying = 0;
if (!sc->sc_pbus && !cb->pause)
error = audiostartp(sc);
error = audiostartp(sc); /* XXX should not clobber error */
splx(s);
if (cc) {
#ifdef AUDIO_DEBUG
@ -2090,14 +2101,15 @@ audiosetinfo(sc, ai)
audio_clear(sc);
cleared = 1;
/* No need to check the blocksize, audio_initbufs() does that. */
if (ai->blocksize == 0) {
audio_calc_blksize(sc, AUMODE_RECORD);
audio_calc_blksize(sc, AUMODE_PLAY);
sc->sc_blkset = 0;
} else {
sc->sc_pr.blksize = ai->blocksize;
sc->sc_rr.blksize = ai->blocksize;
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;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: audio_if.h,v 1.20 1997/08/24 22:31:30 augustss Exp $ */
/* $NetBSD: audio_if.h,v 1.21 1997/09/06 01:14:49 augustss Exp $ */
/*
* Copyright (c) 1994 Havard Eidnes.
@ -123,7 +123,29 @@ struct audio_hw_if {
int (*get_props)__P((void *)); /* device properties */
};
struct midi_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 {
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 *));