git: 9front

Download patch

ref: 6f51f15f52602f7b202ee6fa29544afbfd9685e6
parent: d1a1fdf634f6345733f29de9aa217071a27a219a
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Jan 18 08:12:41 EST 2013

audioac97: audio recording

--- a/sys/src/9/pc/audioac97.c
+++ b/sys/src/9/pc/audioac97.c
@@ -242,7 +242,6 @@
 {
 	Audio *adev;
 	Ctlr *ctlr;
-	Ring *ring;
 	ulong stat;
 
 	adev = arg;
@@ -249,17 +248,39 @@
 	ctlr = adev->ctlr;
 	stat = csr32r(ctlr, Sta);
 	stat &= S2ri | Sri | Pri | Mint | Point | Piint | Moint | Miint | Gsci;
-	if(stat & Point){
+	if(stat & (Point|Piint|Mint)){
 		ilock(ctlr);
-		if(ctlr->sis7012)
-			csr16w(ctlr, Out + Picb, csr16r(ctlr, Out + Picb) & ~Dch);
-		else
-			csr16w(ctlr, Out + Sr, csr16r(ctlr, Out + Sr) & ~Dch);
-		ring = &ctlr->outring;
-		ring->ri = csr8r(ctlr, Out + Civ) * Blocksize;
+		if(stat & Point){
+			ctlr->outring.ri = csr8r(ctlr, Out + Civ) * Blocksize;
+			wakeup(&ctlr->outring.r);
+
+			if(ctlr->sis7012)
+				csr16w(ctlr, Out + Picb, csr16r(ctlr, Out + Picb) & ~Dch);
+			else
+				csr16w(ctlr, Out + Sr, csr16r(ctlr, Out + Sr) & ~Dch);
+			stat &= ~Point;
+		}
+		if(stat & Piint){
+			ctlr->inring.wi = csr8r(ctlr, In + Civ) * Blocksize;
+			wakeup(&ctlr->inring.r);
+
+			if(ctlr->sis7012)
+				csr16w(ctlr, In + Picb, csr16r(ctlr, In + Picb) & ~Dch);
+			else
+				csr16w(ctlr, In + Sr, csr16r(ctlr, In + Sr) & ~Dch);
+			stat &= ~Piint;
+		}
+		if(stat & Mint){
+			ctlr->micring.wi = csr8r(ctlr, Mic + Civ) * Blocksize;
+			wakeup(&ctlr->micring.r);
+
+			if(ctlr->sis7012)
+				csr16w(ctlr, Mic + Picb, csr16r(ctlr, Mic + Picb) & ~Dch);
+			else
+				csr16w(ctlr, Mic + Sr, csr16r(ctlr, Mic + Sr) & ~Dch);
+			stat &= ~Mint;
+		}
 		iunlock(ctlr);
-		wakeup(&ring->r);
-		stat &= ~Point;	
 	}
 	if(stat) /* have seen 0x400, which is sdin0 resume */
 		iprint("#A%d: ac97 unhandled interrupt(s): stat 0x%lux\n",
@@ -282,10 +303,17 @@
 }
 
 static int
+inavail(void *arg)
+{
+	Ring *r = arg;
+	return buffered(r);
+}
+
+static int
 outavail(void *arg)
 {
-	Ctlr *ctlr = arg;
-	return available(&ctlr->outring);
+	Ring *r = arg;
+	return available(r);
 }
 
 static int
@@ -297,6 +325,37 @@
 }
 
 static long
+ac97read(Audio *adev, void *vp, long n, vlong)
+{
+	uchar *p, *e;
+	Ctlr *ctlr;
+	Ring *ring;
+	ulong oi, ni;
+
+	p = vp;
+	e = p + n;
+	ctlr = adev->ctlr;
+	ring = &ctlr->inring;
+	while(p < e) {
+		oi = ring->ri / Blocksize;
+		if((n = readring(ring, p, e - p)) <= 0){
+			csr8w(ctlr, In + Lvi, (oi - 1) % Ndesc);
+			csr8w(ctlr, In + Cr, Ioce | Rpbm);
+			sleep(&ring->r, inavail, ring);
+			continue;
+		}
+		ni = ring->ri / Blocksize;
+		while(oi != ni){
+			csr8w(ctlr, In + Lvi, (oi - 1) % Ndesc);
+			csr8w(ctlr, In + Cr, Ioce | Rpbm);
+			oi = (oi + 1) % Ndesc;
+		}
+		p += n;
+	}
+	return p - (uchar*)vp;
+}
+
+static long
 ac97write(Audio *adev, void *vp, long n, vlong)
 {
 	uchar *p, *e;
@@ -311,7 +370,7 @@
 	while(p < e) {
 		oi = ring->wi / Blocksize;
 		if((n = writering(ring, p, e - p)) <= 0){
-			sleep(&ring->r, outavail, ctlr);
+			sleep(&ring->r, outavail, ring);
 			continue;
 		}
 		ni = ring->wi / Blocksize;
@@ -520,6 +579,7 @@
 
 	ac97mixreset(adev, ac97mixw, ac97mixr);
 
+	adev->read = ac97read;
 	adev->write = ac97write;
 	adev->close = ac97close;
 	adev->buffered = ac97buffered;
--- a/sys/src/9/port/audioif.h
+++ b/sys/src/9/port/audioif.h
@@ -8,7 +8,8 @@
 	void *ctlr;
 	void *mixer;
 
-	Ref audioopen;
+	Ref audioopenr;
+	Ref audioopenw;
 
 	long (*read)(Audio *, void *, long, vlong);
 	long (*write)(Audio *, void *, long, vlong);
--- a/sys/src/9/port/devaudio.c
+++ b/sys/src/9/port/devaudio.c
@@ -170,12 +170,24 @@
 {
 	Audiochan *ac;
 	Audio *adev;
+	int mode;
 
 	ac = c->aux;
 	adev = ac->adev;
-	if((c->qid.path == Qaudio) && (incref(&adev->audioopen) != 1)){
-		decref(&adev->audioopen);
-		error(Ebusy);
+	if(c->qid.path == Qaudio){
+		mode = openmode(omode);
+		if(mode == OWRITE || mode == ORDWR)
+			if(incref(&adev->audioopenw) != 1){
+				decref(&adev->audioopenw);
+				error(Ebusy);
+			}
+		if(mode == OREAD || mode == ORDWR)
+			if(incref(&adev->audioopenr) != 1){
+				decref(&adev->audioopenr);
+				if(mode == ORDWR)
+					decref(&adev->audioopenw);
+				error(Ebusy);
+			}
 	}
 	return devopen(c, omode, audiodir, nelem(audiodir), devgen);
 }
@@ -303,7 +315,10 @@
 				poperror();
 			}
 		}
-		decref(&adev->audioopen);
+		if(c->mode == OWRITE || c->mode == ORDWR)
+			decref(&adev->audioopenw);
+		if(c->mode == OREAD || c->mode == ORDWR)
+			decref(&adev->audioopenr);
 	}
 	if(ac->owner == c){
 		ac->owner = nil;
--