diff options
author | joerg <joerg@FreeBSD.org> | 1996-06-09 14:23:13 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 1996-06-09 14:23:13 +0000 |
commit | 7d866de4251a56c68ead8b471b32fe48c47c9f43 (patch) | |
tree | 1c2dcd3e17992ac0c6a118d51b8c23ab6a89aaa5 /sys/i386/isa/pcaudio.c | |
parent | 0eba79aa48ac8c7e08d0586d84e45ac47cda671c (diff) | |
download | FreeBSD-src-7d866de4251a56c68ead8b471b32fe48c47c9f43.zip FreeBSD-src-7d866de4251a56c68ead8b471b32fe48c47c9f43.tar.gz |
Fix the spl handling. There's still the effect that the timers have
sometimes already been released at the time pcaclose() is called, but
this is now prevented from deadlocking by checking for a running timer
at the start of pca_wait().
At least, i can now play xboing again with pcaudio, this used to hang
the entire system previously within a few seconds.
Diffstat (limited to 'sys/i386/isa/pcaudio.c')
-rw-r--r-- | sys/i386/isa/pcaudio.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/sys/i386/isa/pcaudio.c b/sys/i386/isa/pcaudio.c index 5ede8f0..6b31817 100644 --- a/sys/i386/isa/pcaudio.c +++ b/sys/i386/isa/pcaudio.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcaudio.c,v 1.26 1995/12/22 15:27:48 bde Exp $ + * $Id: pcaudio.c,v 1.27 1996/03/28 14:28:47 scrappy Exp $ */ #include "pca.h" @@ -166,6 +166,9 @@ pca_init() static int pca_start(void) { + int x = splhigh(); + int rv = 0; + /* use the first buffer */ pca_status.current = 0; pca_status.index = 0; @@ -173,21 +176,24 @@ pca_start(void) pca_status.buffer = pca_status.buf[pca_status.current]; pca_status.oldval = inb(IO_PPI) | 0x03; /* acquire the timers */ - if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT)) { - return -1; - } - if (acquire_timer0(INTERRUPT_RATE, pcaintr)) { + if (acquire_timer2(TIMER_LSB|TIMER_ONESHOT)) + rv = -1; + else if (acquire_timer0(INTERRUPT_RATE, pcaintr)) { release_timer2(); - return -1; - } - pca_status.timer_on = 1; - return 0; + rv = -1; + } else + pca_status.timer_on = 1; + + splx(x); + return rv; } static void pca_stop(void) { + int x = splhigh(); + /* release the timers */ release_timer0(); release_timer2(); @@ -198,37 +204,49 @@ pca_stop(void) pca_status.current = 0; pca_status.buffer = pca_status.buf[pca_status.current]; pca_status.timer_on = 0; + splx(x); } static void pca_pause() { + int x = splhigh(); + release_timer0(); release_timer2(); pca_status.timer_on = 0; + splx(x); } static void pca_continue() { + int x = splhigh(); + pca_status.oldval = inb(IO_PPI) | 0x03; acquire_timer2(TIMER_LSB|TIMER_ONESHOT); acquire_timer0(INTERRUPT_RATE, pcaintr); pca_status.timer_on = 1; + splx(x); } static int pca_wait(void) { - int error; + int error, x; + + if (!pca_status.timer_on) + return 0; while (pca_status.in_use[0] || pca_status.in_use[1]) { + x = spltty(); pca_sleep = 1; error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_drain", 0); pca_sleep = 0; + splx(x); if (error != 0 && error != ERESTART) { pca_stop(); return error; @@ -332,7 +350,7 @@ pcaclose(dev_t dev, int flags, int fmt, struct proc *p) static int pcawrite(dev_t dev, struct uio *uio, int flag) { - int count, error, which; + int count, error, which, x; /* only audio device can be written */ if (minor(dev) > 0) @@ -340,9 +358,11 @@ pcawrite(dev_t dev, struct uio *uio, int flag) while ((count = min(BUF_SIZE, uio->uio_resid)) > 0) { if (pca_status.in_use[0] && pca_status.in_use[1]) { + x = spltty(); pca_sleep = 1; error = tsleep(&pca_sleep, PZERO|PCATCH, "pca_wait", 0); pca_sleep = 0; + splx(x); if (error != 0 && error != ERESTART) { pca_stop(); return error; @@ -457,10 +477,8 @@ pcaintr(struct clockframe *frame) pca_status.in_use[pca_status.current] = 0; pca_status.current ^= 1; pca_status.buffer = pca_status.buf[pca_status.current]; - if (pca_sleep) { + if (pca_sleep) wakeup(&pca_sleep); - pca_sleep = 0; - } if (pca_status.wsel.si_pid) { selwakeup((struct selinfo *)&pca_status.wsel.si_pid); pca_status.wsel.si_pid = 0; |