summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/pcaudio.c
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1996-06-09 14:23:13 +0000
committerjoerg <joerg@FreeBSD.org>1996-06-09 14:23:13 +0000
commit7d866de4251a56c68ead8b471b32fe48c47c9f43 (patch)
tree1c2dcd3e17992ac0c6a118d51b8c23ab6a89aaa5 /sys/i386/isa/pcaudio.c
parent0eba79aa48ac8c7e08d0586d84e45ac47cda671c (diff)
downloadFreeBSD-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.c46
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;
OpenPOWER on IntegriCloud