From fa8501367e6fda36ef08a275cc5bf1f91bf410b1 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 2 May 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-05-02 --- bitsy/devuda1341.c | 146 +++++++++++++++++++++++++++------------------ bitsy/main.c | 2 +- bitsy/sa1110dma.c | 10 ++-- port/chan.c | 8 ++- port/devdraw.c | 2 +- port/sysfile.c | 6 ++ 6 files changed, 108 insertions(+), 66 deletions(-) diff --git a/bitsy/devuda1341.c b/bitsy/devuda1341.c index 60359bc4d038c85e110141fe574f0c4229b30f78..9f4a942265df2d5f5941e5203b6aa3aea9f82728 100644 --- a/bitsy/devuda1341.c +++ b/bitsy/devuda1341.c @@ -19,7 +19,7 @@ #include "io.h" #include "sa1110dma.h" -static int debug = 2; +static int debug = 0; /* * GPIO based L3 bus support. @@ -139,15 +139,15 @@ struct IOstate { QLock; Lock ilock; - Rendez vous; - Chan *chan; /* chan of open */ - int dma; /* dma chan, alloc on open, free on close */ - int bufinit; /* boolean, if buffers allocated */ - Buf buf[Nbuf]; /* buffers and queues */ + Rendez vous; + Chan *chan; /* chan of open */ + int dma; /* dma chan, alloc on open, free on close */ + int bufinit; /* boolean, if buffers allocated */ + Buf buf[Nbuf]; /* buffers and queues */ volatile Buf *current; /* next dma to finish */ - volatile Buf *next; /* next candidate for dma */ + volatile Buf *next; /* next candidate for dma */ volatile Buf *filling; /* buffer being filled */ -/* just be be cute (and to have defines like linux, a real operating system) */ +/* to have defines just like linux — there's a real operating system */ #define emptying filling }; @@ -166,6 +166,9 @@ static struct IOstate o; } audio; +Buf zeroes; +int zerodma; /* dma buffer used for sending zero */ + static struct { ulong bytes; @@ -173,6 +176,7 @@ static struct ulong idledma; ulong faildma; ulong samedma; + ulong empties; } iostats; static struct @@ -183,14 +187,14 @@ static struct int irval; } volumes[] = { -[Vaudio] {"audio", Fout|Fmono, 80, 80}, -[Vmic] {"mic", Fin|Fmono, 0, 0}, -[Vtreb] {"treb", Fout|Fmono, 50, 50}, -[Vbass] {"bass", Fout|Fmono, 50, 50}, +[Vaudio] {"audio", Fout|Fmono, 80, 80}, +[Vmic] {"mic", Fin|Fmono, 0, 0}, +[Vtreb] {"treb", Fout|Fmono, 50, 50}, +[Vbass] {"bass", Fout|Fmono, 50, 50}, [Vspeed] {"speed", Fin|Fout|Fmono, Speed, Speed}, -[Vfilter] {"filter", Fout|Fmono, 0, 0}, -[Vinvert] {"invert", Fin|Fout|Fmono, 0, 0}, -[Nvol] {0} +[Vfilter] {"filter", Fout|Fmono, 0, 0}, +[Vinvert] {"invert", Fin|Fout|Fmono, 0, 0}, +[Nvol] {0} }; static void setreg(char *name, int val, int n); @@ -397,8 +401,15 @@ bufinit(IOstate *b) for (i = 0; i < Nbuf; i++) { b->buf[i].virt = xalloc(Bufsize); b->buf[i].phys = PADDR(b->buf[i].virt); + memset(b->buf[i].virt, 0xAA, Bufsize); } b->bufinit = 1; + + if (b == &audio.o) { + zeroes.virt = xalloc(Bufsize); + zeroes.phys = PADDR(b->buf[i].virt); + memset(zeroes.virt, 0, Bufsize); + } }; static void @@ -681,6 +692,15 @@ sendaudio(IOstate *s) { if (debug > 1) print("#A: sendaudio\n"); ilock(&s->ilock); + if ((audio.amode & Aread) && s->next == s->filling && dmaidle(s->dma)) { + // send an empty buffer to provide an input clock + zerodma |= dmastart(s->dma, zeroes.phys, Bufsize) & 0xff; + if (zerodma == 0) + if (debug) print("emptyfail\n"); + iostats.empties++; + iunlock(&s->ilock); + return; + } while (s->next != s->filling) { assert(s->next->nbytes); if ((n = dmastart(s->dma, s->next->phys, s->next->nbytes)) == 0) { @@ -688,7 +708,7 @@ sendaudio(IOstate *s) { break; } iostats.totaldma++; - switch (n) { + switch (n >> 8) { case 1: iostats.idledma++; break; @@ -724,7 +744,7 @@ recvaudio(IOstate *s) { break; } iostats.totaldma++; - switch (n) { + switch (n >> 8) { case 1: iostats.idledma++; break; @@ -791,14 +811,20 @@ audiointr(void *x, ulong ndma) { else iprint("-"); } - /* Only interrupt routine touches s->current */ - s->current++; - if (s->current == &s->buf[Nbuf]) - s->current = &s->buf[0]; - if (ndma > 0) { - if (s == &audio.o) + if (s == &audio.i || (ndma & ~zerodma)) { + /* A dma, not of a zero buffer completed, update current + * Only interrupt routine touches s->current + */ + s->current->nbytes = (s == &audio.i)? Bufsize: 0; + s->current++; + if (s->current == &s->buf[Nbuf]) + s->current = &s->buf[0]; + } + if (ndma) { + if (s == &audio.o) { + zerodma &= ~ndma; sendaudio(s); - else if (s == &audio.i) + } else if (s == &audio.i) recvaudio(s); } wakeup(&s->vous); @@ -862,19 +888,23 @@ audioopen(Chan *c, int mode) s->dma = dmaalloc(1, 0, 4, 2, SSPRecvDMA, Port4SSP, audiointr, (void*)s); audio.amode |= Aread; } - if (omode & Awrite) { - outenable(); + if (omode & (Aread|Awrite) && (audio.amode & Awrite) == 0) { s = &audio.o; - audio.amode |= Awrite; if(s->bufinit == 0) bufinit(s); setempty(s); s->chan = c; s->dma = dmaalloc(0, 0, 4, 2, SSPXmitDMA, Port4SSP, audiointr, (void*)s); + } + if (omode & Awrite) { audio.amode |= Awrite; + outenable(); } mxvolume(); qunlock(&audio); + if (audio.amode == Aread) + sendaudio(&audio.o); + if (debug) print("open done\n"); break; } @@ -905,19 +935,34 @@ audioclose(Chan *c) if (debug > 1) print("#A: close\n"); if(c->flag & COPEN) { qlock(&audio); - if(waserror()){ - qunlock(&audio); - nexterror(); + if (audio.i.chan == c) { + /* closing the read end */ + audio.amode &= ~Aread; + s = &audio.i; + qlock(s); + indisable(); + setempty(s); + dmafree(s->dma); + qunlock(s); + if ((audio.amode & Awrite) == 0) { + s = &audio.o; + qlock(s); + while(waserror()) { + dmawait(s->dma); + if (dmaidle(s->dma)) + break; + } + outdisable(); + setempty(s); + dmafree(s->dma); + qunlock(s); + } } if (audio.o.chan == c) { /* closing the write end */ audio.amode &= ~Awrite; s = &audio.o; qlock(s); - if(waserror()){ - qunlock(s); - nexterror(); - } if (s->filling->nbytes) { /* send remaining partial buffer */ s->filling++; @@ -925,34 +970,22 @@ audioclose(Chan *c) s->filling = &s->buf[0]; sendaudio(s); } - dmawait(s->dma); - outdisable(); - setempty(s); - dmafree(s->dma); - qunlock(s); - poperror(); - } - if (audio.i.chan == c) { - /* closing the read end */ - audio.amode &= ~Aread; - s = &audio.i; - qlock(s); - if(waserror()){ - qunlock(s); - nexterror(); + while(waserror()) { + dmawait(s->dma); + if (dmaidle(s->dma)) + break; } - indisable(); + outdisable(); setempty(s); - dmafree(s->dma); + if ((audio.amode & Aread) == 0) + dmafree(s->dma); qunlock(s); - poperror(); } if (audio.amode == 0) { /* turn audio off */ egpiobits(EGPIO_audio_ic_power | EGPIO_codec_reset, 0); } qunlock(&audio); - poperror(); if (debug) { print("total dmas: %lud\n", iostats.totaldma); print("dmas while idle: %lud\n", iostats.idledma); @@ -1009,10 +1042,9 @@ audioread(Chan *c, void *v, long n, vlong off) sleep(&s->vous, audioqnotempty, s); } - m = Bufsize - s->emptying->nbytes; - if(m > n) - m = n; - memmove(p, s->emptying->virt + s->emptying->nbytes, m); + m = (s->emptying->nbytes > n)? n: s->emptying->nbytes; + memmove(p, s->emptying->virt + Bufsize - + s->emptying->nbytes, m); s->emptying->nbytes -= m; n -= m; diff --git a/bitsy/main.c b/bitsy/main.c index eec0c6ac14d53ecb3f267210b2b36179f840155c..110e72b1ef4dba245bbf54fa7cad6186aedc747c 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -381,7 +381,7 @@ machinit(void) gpioregs->altfunc |= GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o |GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o - |GPIO_SSP_CLK_i|GPIO_SSP_RXD_i; + |GPIO_SSP_CLK_i; /* map in special H3650 io pins */ egpioreg = mapspecial(EGPIOREGS, 4); diff --git a/bitsy/sa1110dma.c b/bitsy/sa1110dma.c index f1f74a2a427b2f42df14a07cc476cd46081ec86a..f95093d3829f585932860d82ca3bee1a98cc60e0 100644 --- a/bitsy/sa1110dma.c +++ b/bitsy/sa1110dma.c @@ -7,7 +7,7 @@ #include "../port/error.h" #include "sa1110dma.h" -static int debug = 2; +static int debug = 0; /* * DMA helper routines @@ -140,26 +140,28 @@ dmastart(int chan, ulong addr, int count) { return 0; } cachewbregion(addr, count); - n = 1; + n = 0x100; if ((status & (1<type]->close(c); - poperror(); + if(waserror()){ + print("cclose error: type %C; error %s\n", devtab[c->type]->dc, up!=nil? up->error : "no user"); //BUG + return; } + devtab[c->type]->close(c); chanfree(c); + poperror(); } int diff --git a/port/devdraw.c b/port/devdraw.c index e86ec9fa4e9b5d2d2805a4fd8a3d3bb08133e091..35cb094207d63d00cbd1990854c090ba8c16b678 100644 --- a/port/devdraw.c +++ b/port/devdraw.c @@ -959,7 +959,7 @@ drawclose(Chan *c) Client *cl; Refresh *r; - if(c->qid.path & CHDIR) + if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */ return; qlock(&sdraw); if(waserror()){ diff --git a/port/sysfile.c b/port/sysfile.c index b1c9c7348a4c14ceedbc11b464f3f1c4d39c5ff0..c54c5694337677e876ff60c930a7540c2f86cb71 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -455,6 +455,9 @@ syspread(ulong *arg) ulong u[2]; } o; + if(arg[3] == ~0UL && arg[4] == ~0UL) + return sysread(arg); + n = arg[2]; validaddr(arg[1], n, 1); c = fdtochan(arg[0], OREAD, 1, 1); @@ -557,6 +560,9 @@ syspwrite(ulong *arg) ulong u[2]; } o; + if(arg[3] == ~0UL && arg[4] == ~0UL) + return syswrite(arg); + validaddr(arg[1], arg[2], 0); n = arg[2]; c = fdtochan(arg[0], OWRITE, 1, 1);