diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-01-18 13:12:41 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-01-18 13:12:41 +0100 |
commit | 6a0e85ad9c25f6daec732c563a05d5ab21d8ce5a (patch) | |
tree | 09b5d8ccd5a13247c17ba26f451d7015953a6278 | |
parent | d5e642d52d5701d00c052de59baeefdf50492dbe (diff) |
audioac97: audio recording
-rw-r--r-- | sys/src/9/pc/audioac97.c | 86 | ||||
-rw-r--r-- | sys/src/9/port/audioif.h | 3 | ||||
-rw-r--r-- | sys/src/9/port/devaudio.c | 23 |
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; |