Subject: kern/1185: audio driver prematurely considers buffers transferred to hardware
To: None <gnats-admin@sun-lamp.pc.cs.cmu.edu>
From: John Kohl <jtk@kolvir.blrc.ma.us>
List: netbsd-bugs
Date: 07/02/1995 15:50:04
>Number:         1185
>Category:       kern
>Synopsis:       the audio driver counts buffers as completed before they are
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jul  2 15:50:03 1995
>Originator:     John Kohl
>Organization:
NetBSD Kernel Hackers `R` Us
>Release:        -current, June 30
>Environment:
	
System: NetBSD kolvir 1.0A NetBSD 1.0A (KOLVIR) #559: Sun Jul 2 14:50:32 EDT 1995 jtk@kolvir:/u1/NetBSD-current/src/sys/arch/i386/compile/KOLVIR i386


>Description:
The audio driver may overwrite memory that has not yet been transferred
to audio output hardware, because it considers the buffer done when it
starts the transfer rather than when the transfer is completed.

>How-To-Repeat:
Copy a short 8-bit mono linear encoding sound file to a GUS card, and
listen carefully.

>Fix:
===================================================================
RCS file: RCS/audio.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 audio.c
--- audio.c	1995/06/06 03:53:56	1.1.1.1
+++ audio.c	1995/07/02 19:18:25
@@ -1016,7 +1036,7 @@
 		if (tp >= cb->ep)
 			tp = cb->bp;
 		cb->tp = tp;
-		++cb->nblk;
+		++cb->nblk;	/* account for buffer filled */
 
 		/*
 		 * If output isn't active, start it up.
@@ -1208,7 +1228,6 @@
 		    	DPRINTF(("audiostartp failed: %d\n", rval));
 		}
 		else {
-			--sc->pr.nblk;
 			sc->sc_pbus = 1;
 			hp += sc->sc_blksize;
 			if (hp >= sc->pr.ep)
@@ -1234,7 +1253,9 @@
 	struct audio_buffer *cb = &sc->pr;
 	int err;
 	
-	if (cb->nblk > 0) {
+	/* account for buffer drained, after the hardware has finished
+	   the DMA. */
+	if (--cb->nblk > 0) {
 		hp = cb->hp;
 		if (cb->cb_pause) {
 		    cb->cb_pdrops++;
@@ -1255,7 +1276,6 @@
 			    audio_clear(sc);
 		    }
 		    else {
-		    	    --cb->nblk;
 		    	    hp += cc;
 			    if (hp >= cb->ep)
 				    hp = cb->bp;
>Audit-Trail:
>Unformatted: