Module Name: src Committed By: mlelstv Date: Tue Jan 24 08:17:11 UTC 2023
Modified Files: src/sys/dev/pad: pad.c padvar.h Log Message: Pace I/O timing to match the audio interface. Enable interrupts while copying buffers. To generate a diff of this commit: cvs rdiff -u -r1.78 -r1.79 src/sys/dev/pad/pad.c cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pad/padvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pad/pad.c diff -u src/sys/dev/pad/pad.c:1.78 src/sys/dev/pad/pad.c:1.79 --- src/sys/dev/pad/pad.c:1.78 Thu Mar 31 19:30:16 2022 +++ src/sys/dev/pad/pad.c Tue Jan 24 08:17:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: pad.c,v 1.78 2022/03/31 19:30:16 pgoyette Exp $ */ +/* $NetBSD: pad.c,v 1.79 2023/01/24 08:17:11 mlelstv Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.78 2022/03/31 19:30:16 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pad.c,v 1.79 2023/01/24 08:17:11 mlelstv Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -148,7 +148,7 @@ static const struct audio_format pad_for extern void padattach(int); static int pad_add_block(struct pad_softc *, uint8_t *, int); -static int pad_get_block(struct pad_softc *, pad_block_t *, int); +static int pad_get_block(struct pad_softc *, pad_block_t *, int, int); static dev_type_open(pad_open); @@ -280,7 +280,7 @@ pad_childdet(device_t self, device_t chi static int pad_add_block(struct pad_softc *sc, uint8_t *blk, int blksize) { - int l; + int foff, flen, tlen; KASSERT(blksize >= 0); KASSERT(mutex_owned(&sc->sc_intr_lock)); @@ -289,18 +289,27 @@ pad_add_block(struct pad_softc *sc, uint sc->sc_buflen > PAD_BUFSIZE - (unsigned)blksize) return ENOBUFS; - if (sc->sc_wpos + blksize <= PAD_BUFSIZE) - memcpy(sc->sc_audiobuf + sc->sc_wpos, blk, blksize); - else { - l = PAD_BUFSIZE - sc->sc_wpos; - memcpy(sc->sc_audiobuf + sc->sc_wpos, blk, l); - memcpy(sc->sc_audiobuf, blk + l, blksize - l); + foff = sc->sc_wpos; + if (sc->sc_wpos + blksize <= PAD_BUFSIZE) { + flen = blksize; + tlen = 0; + } else { + flen = PAD_BUFSIZE - sc->sc_wpos; + tlen = blksize - flen; } - sc->sc_wpos += blksize; + sc->sc_wpos = foff + blksize; if (sc->sc_wpos >= PAD_BUFSIZE) sc->sc_wpos -= PAD_BUFSIZE; + /* + * release interrupt lock for bulk copy to audio buffer + */ + mutex_exit(&sc->sc_intr_lock); + memcpy(sc->sc_audiobuf + foff, blk, flen); + memcpy(sc->sc_audiobuf, blk + flen, tlen); + mutex_enter(&sc->sc_intr_lock); + sc->sc_buflen += blksize; cv_broadcast(&sc->sc_condvar); @@ -308,13 +317,16 @@ pad_add_block(struct pad_softc *sc, uint } static int -pad_get_block(struct pad_softc *sc, pad_block_t *pb, int maxblksize) +pad_get_block(struct pad_softc *sc, pad_block_t *pb, int maxblksize, int dowait) { int l, blksize, error; KASSERT(maxblksize > 0); KASSERT(mutex_owned(&sc->sc_intr_lock)); + if (sc->sc_buflen == 0 && !dowait) + return EAGAIN; + while (sc->sc_buflen == 0) { DPRINTF("%s: wait\n", __func__); error = cv_wait_sig(&sc->sc_condvar, &sc->sc_intr_lock); @@ -500,14 +512,20 @@ pad_read(struct pad_softc *sc, off_t *of int ioflag) { pad_block_t pb; - int err; + int err, first; err = 0; + first = 1; DPRINTF("%s: resid=%zu\n", __func__, uio->uio_resid); while (uio->uio_resid > 0) { mutex_enter(&sc->sc_intr_lock); - err = pad_get_block(sc, &pb, MIN(uio->uio_resid, INT_MAX)); + err = pad_get_block(sc, &pb, MIN(uio->uio_resid, INT_MAX), first); mutex_exit(&sc->sc_intr_lock); + first = 0; + if (err == EAGAIN) { + err = 0; + break; + } if (err) break; @@ -557,7 +575,8 @@ pad_start_output(void *opaque, void *blo { struct pad_softc *sc = opaque; int err; - int ms; + u_int framesize; + int ticks; KASSERT(mutex_owned(&sc->sc_intr_lock)); @@ -566,10 +585,20 @@ pad_start_output(void *opaque, void *blo DPRINTF("%s: blksize=%d\n", __func__, blksize); err = pad_add_block(sc, block, blksize); + if (err) { + DPRINTF("%s: failed: %d\n", __func__, err); + /* "Silently" drop overflows, but keep pace */ + err = 0; + } + + framesize = PADCHAN * (PADPREC / NBBY) * PADFREQ; + + sc->sc_resid += blksize; + ticks = mstohz(sc->sc_resid * 1000 / framesize); + sc->sc_resid -= hztoms(ticks) * framesize / 1000; - ms = blksize * 1000 / PADCHAN / (PADPREC / NBBY) / PADFREQ; DPRINTF("%s: callout ms=%d\n", __func__, ms); - callout_schedule(&sc->sc_pcallout, mstohz(ms)); + callout_schedule(&sc->sc_pcallout, ticks); return err; } @@ -587,6 +616,7 @@ pad_halt_output(void *opaque) sc->sc_intr = NULL; sc->sc_intrarg = NULL; sc->sc_buflen = 0; + sc->sc_resid = 0; sc->sc_rpos = sc->sc_wpos = 0; return 0; Index: src/sys/dev/pad/padvar.h diff -u src/sys/dev/pad/padvar.h:1.16 src/sys/dev/pad/padvar.h:1.17 --- src/sys/dev/pad/padvar.h:1.16 Mon Jun 14 18:44:45 2021 +++ src/sys/dev/pad/padvar.h Tue Jan 24 08:17:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: padvar.h,v 1.16 2021/06/14 18:44:45 riastradh Exp $ */ +/* $NetBSD: padvar.h,v 1.17 2023/01/24 08:17:11 mlelstv Exp $ */ /*- * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca> @@ -57,6 +57,8 @@ struct pad_softc { u_int sc_wpos; uint8_t sc_swvol; + + u_int sc_resid; }; #endif /* !_SYS_DEV_PAD_PADVAR_H */