summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-01-18 13:12:41 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2013-01-18 13:12:41 +0100
commit6a0e85ad9c25f6daec732c563a05d5ab21d8ce5a (patch)
tree09b5d8ccd5a13247c17ba26f451d7015953a6278
parentd5e642d52d5701d00c052de59baeefdf50492dbe (diff)
audioac97: audio recording
-rw-r--r--sys/src/9/pc/audioac97.c86
-rw-r--r--sys/src/9/port/audioif.h3
-rw-r--r--sys/src/9/port/devaudio.c23
3 files changed, 94 insertions, 18 deletions
diff --git a/sys/src/9/pc/audioac97.c b/sys/src/9/pc/audioac97.c
index 977fa4cf3..5bb5b0cf9 100644
--- a/sys/src/9/pc/audioac97.c
+++ b/sys/src/9/pc/audioac97.c
@@ -242,24 +242,45 @@ ac97interrupt(Ureg *, void *arg)
{
Audio *adev;
Ctlr *ctlr;
- Ring *ring;
ulong stat;
adev = arg;
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 @@ ac97status(Audio *adev, void *a, long n, vlong)
}
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 @@ outrate(void *arg)
}
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 @@ ac97write(Audio *adev, void *vp, long n, vlong)
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 @@ Found:
ac97mixreset(adev, ac97mixw, ac97mixr);
+ adev->read = ac97read;
adev->write = ac97write;
adev->close = ac97close;
adev->buffered = ac97buffered;
diff --git a/sys/src/9/port/audioif.h b/sys/src/9/port/audioif.h
index 6ec66e319..d82c166c2 100644
--- a/sys/src/9/port/audioif.h
+++ b/sys/src/9/port/audioif.h
@@ -8,7 +8,8 @@ struct Audio
void *ctlr;
void *mixer;
- Ref audioopen;
+ Ref audioopenr;
+ Ref audioopenw;
long (*read)(Audio *, void *, long, vlong);
long (*write)(Audio *, void *, long, vlong);
diff --git a/sys/src/9/port/devaudio.c b/sys/src/9/port/devaudio.c
index fc8b39deb..eceed5af0 100644
--- a/sys/src/9/port/devaudio.c
+++ b/sys/src/9/port/devaudio.c
@@ -170,12 +170,24 @@ audioopen(Chan *c, int omode)
{
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 @@ audioclose(Chan *c)
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;