From bb057084b22eb93eeca977bed0906e7644cc10d4 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 16 Nov 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-11-16 --- bitsy/devuda1341.c | 108 +++++++++++++++++++++------------------------ bitsy/io.h | 15 +++++++ bitsy/main.c | 11 +++++ bitsy/sa1110dma.c | 66 ++++++++++++++++----------- pc/devi82365.c | 67 +++++++++++++++++----------- 5 files changed, 159 insertions(+), 108 deletions(-) diff --git a/bitsy/devuda1341.c b/bitsy/devuda1341.c index 25f49c08ff5feb65dc9d2f042d8e99a6492786cb..bd3e2a79ca07901f3869e5ef285e0e1ef2fc470a 100644 --- a/bitsy/devuda1341.c +++ b/bitsy/devuda1341.c @@ -138,7 +138,6 @@ struct IOstate int dma; /* dma chan, alloc on open, free on close */ int bufinit; /* boolean, if buffers allocated */ Buf buf[Nbuf]; /* buffers and queues */ - Ref active; /* # of dmas in progress */ volatile Buf *current; /* next dma to finish */ volatile Buf *next; /* next candidate for dma */ volatile Buf *filling; /* buffer being filled */ @@ -159,6 +158,14 @@ static struct IOstate o; } audio; +static struct +{ + ulong bytes; + ulong totaldma; + ulong idledma; + ulong faildma; +} iostats; + static struct { char* name; @@ -404,22 +411,7 @@ audioqnotfull(void *x) IOstate *s = x; /* called with lock */ - return s->active.ref == 0 || s->filling != s->current; -} - -static int -audioqnotempty(IOstate *s) -{ - /* called with lock */ - return s->next != s->filling; -} - -static int -audioidle(void *x) -{ - IOstate *s = x; - /* called with lock */ - return s->active.ref == 0; + return dmaidle(s->dma) || s->filling != s->current; } static void @@ -436,50 +428,46 @@ audioenable(void) L3_init(); /* Setup the uarts */ - ppcregs->assignment &= (1<<18); /* Could be the other way round! */ + ppcregs->assignment &= ~(1<<18); gpioregs->altfunc &= ~(GPIO_SSP_TXD_o | GPIO_SSP_RXD_i | GPIO_SSP_SCLK_o | GPIO_SSP_SFRM_o); gpioregs->altfunc |= (GPIO_SSP_CLK_i); gpioregs->direction &= ~(GPIO_SSP_CLK_i); - sspregs->control0 = 0xf<<0 | 0x1<<4 | 0x3<<8; - sspregs->control1 = 0<<3 + 0<<4 + 1<<5; - - sspregs->control0 |= 1<<7; /* enable */ + sspregs->control0 = 0; + sspregs->control0 = 0x031f; /* 16 bits, TI frames, serial clock rate 3 */ + sspregs->control1 = 0x0020; /* ext clock */ + sspregs->control0 = 0x039f; /* enable */ /* Enable the audio power */ audiopower(1); amplifierpower(1); audiomute(0); + /* external clock configured for 44100 samples/sec */ gpioregs->direction |= (GPIO_CLK_SET0_o|GPIO_CLK_SET1_o); - /* external clock configured for 44100 samples/sec */ - gpioregs->set = GPIO_CLK_SET0_o; - gpioregs->clear = GPIO_CLK_SET1_o; - +/* This is purportedly the wrong way round: 0 should be set, 1 cleared */ + gpioregs->set = GPIO_CLK_SET0_o|GPIO_CLK_SET1_o; +// gpioregs->clear = GPIO_CLK_SET1_o; + /* Wait for the UDA1341 to wake up */ delay(100); - print("Ser4SSSR=0x%lux\n", sspregs->status); - - gpioregs->clear = EGPIO_codec_reset; - gpioregs->set = EGPIO_codec_reset; /* Reset the chip */ - data[0] = 2<<4 /* system clock */ | 1<<1 /* lsb16 */ | 1<<6 /* reset */; + data[0] = 2<set = EGPIO_codec_reset; + gpioregs->clear = EGPIO_codec_reset; + /* write uda 1341 status[0] */ + data[0] &= ~(1<control0 = 0x%lux\n", sspregs->control0); + print("\tsspregs->control1 = 0x%lux\n", sspregs->control1); + } } static void sendaudio(IOstate *b) { /* interrupt routine calls this too */ + int n; + if (debug > 1) print("#A: sendaudio\n"); ilock(&b->ilock); while (b->next != b->filling) { assert(b->next->nbytes); - incref(&b->active); - if (dmastart(b->dma, b->next->virt, b->next->nbytes) == 0) { - decref(&b->active); + if ((n = dmastart(b->dma, b->next->virt, b->next->nbytes)) == 0) { + iostats.faildma++; break; } + iostats.totaldma++; + if (n == 1) iostats.idledma++; if (debug > 1) print("#A: dmastart @%p\n", b->next); b->next->nbytes = 0; b->next++; @@ -536,7 +521,7 @@ sendaudio(IOstate *b) { } static void -audiointr(void *x, ulong) { +audiointr(void *x, ulong ndma) { IOstate *s = x; if (s == &audio.o) { @@ -545,8 +530,8 @@ audiointr(void *x, ulong) { s->current++; if (s->current == &s->buf[Nbuf]) s->current = &s->buf[0]; - decref(&s->active); - sendaudio(s); + if (ndma > 0) + sendaudio(s); } wakeup(&s->vous); } @@ -596,6 +581,7 @@ audioopen(Chan *c, int omode) error(Einuse); } audioenable(); + memset(&iostats, 0, sizeof(iostats)); if (omode & Aread) { /* read */ audio.amode |= Aread; @@ -663,10 +649,13 @@ audioclose(Chan *c) audio.o.filling = &audio.o.buf[0]; sendaudio(&audio.o); } - while(!audioidle(&audio.o)) - sleep(&audio.o.vous, audioidle, &audio.o); + delay(2000); + // dmawait(audio.o.dma); + if (!dmaidle(audio.o.dma)) + print("dma still busy\n"); amplifierpower(0); setempty(&audio.o); + dmafree(audio.o.dma); } if (audio.i.chan == c) { /* closing the read end */ @@ -680,6 +669,9 @@ audioclose(Chan *c) poperror(); qunlock(&audio.o); qunlock(&audio); + print("total dmas: %lud\n", iostats.totaldma); + print("dmas while idle: %lud\n", iostats.idledma); + print("dmas while busy: %lud\n", iostats.faildma); } break; } @@ -857,7 +849,7 @@ audiowrite(Chan *c, void *vp, long n, vlong) } while(n > 0) { /* wait if dma in progress */ - while (a->active.ref && a->filling == a->current) { + while (!dmaidle(a->dma) && a->filling == a->current) { if (debug > 1) print("#A: sleep\n"); sleep(&a->vous, audioqnotfull, a); } diff --git a/bitsy/io.h b/bitsy/io.h index 90044d97f0d7d994c6d6d206717e493e0a1e2e4f..b28f153a8b7568bde04131f90ee8ee08bff987ee 100644 --- a/bitsy/io.h +++ b/bitsy/io.h @@ -248,3 +248,18 @@ struct SSPregs { ulong status; }; extern SSPregs *sspregs; + +/* Multimedia Communications Port controller registers */ +typedef struct MCPregs MCPregs; +struct MCPregs { + ulong control0; + ulong reserved0; + ulong data0; + ulong data1; + ulong data2; + ulong reserved1; + ulong status; + ulong reserved[11]; + ulong control1; +}; +extern MCPregs *mcpregs; diff --git a/bitsy/main.c b/bitsy/main.c index 49dace194eeb702305153c2f441b626edb31e5b0..3acb36cef473ec1ffee025a2bffaf41eca840d80 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -16,6 +16,7 @@ int noprint; static void gpioinit(void); static void ppcinit(void); static void sspinit(void); +static void mcpinit(void); void main(void) @@ -39,6 +40,7 @@ main(void) mmuinit(); gpioinit(); ppcinit(); + mcpinit(); sspinit(); trapinit(); sa1100_uartsetup(1); @@ -386,6 +388,15 @@ ppcinit(void) { ppcregs = mapspecial(PPCREGS, 32); } +MCPregs *mcpregs; + +static void +mcpinit(void) { + mcpregs = mapspecial(MCPREGS, 0x34); + mcpregs->status &= ~(1<<16); + /* Turn MCP operations off */ +} + SSPregs *sspregs; static void diff --git a/bitsy/sa1110dma.c b/bitsy/sa1110dma.c index 5350dc7284b924be4d2e1982b2270965d7fc108e..0e0e2b58f708737872ee23b2941e2e53feb9f379 100644 --- a/bitsy/sa1110dma.c +++ b/bitsy/sa1110dma.c @@ -41,8 +41,8 @@ enum { }; typedef struct DMAchan { + Lock; int allocated; - Ref active; Rendez r; void (*intr)(void*, ulong); void *param; @@ -116,51 +116,58 @@ dmafree(int i) { ulong dmastart(int chan, void *addr, int count) { - ulong status; + ulong status, n; + ilock(&dma.chan[chan]); status = dmaregs[chan].dcsr_rd; - if (debug > 1) print("dma: dmastart 0x%lux\n", status); + if (debug > 1) + iprint("dma: dmastart 0x%lux\n", status); - if (dma.chan[chan].active.ref >= 2) { - if (debug > 1) print("\n"); + if ((status & (1<dcsr_rd; if (debug > 1) iprint("dma: interrupt channel %d, status 0x%lux\n", i, dcsr); @@ -182,12 +190,20 @@ dmaintr(Ureg*, void *x) iprint("error, channel %d, status 0x%lux\n", i, dcsr); donebit = 1<<((dcsr&1<dcsr_clr |= donebit; - if (dma.chan[i].intr) - (*dma.chan[i].intr)(dma.chan[i].param, 3-dma.chan[i].active.ref); - /* must call interrupt routine before calling decref */ - decref(&dma.chan[i].active); + regs->dcsr_clr = donebit; + /* try the other bit as well */ + donebit ^= 1<dcsr_clr = donebit; + } + iunlock(&dma.chan[i]); + if (dma.chan[i].intr) { + dcsr &= 1<special) continue; /* already taken */ - enabled = 0; - /* make sure we don't power on cards when we already know what's - * in them. We'll reread every two minutes if necessary + + /* + * make sure we don't power on cards when we already know what's + * in them. We'll reread every two minutes if necessary */ - if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000) { + enabled = 0; + if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000){ increfp(pp); enabled++; } if(pp->occupied) { - if(strstr(pp->verstr, idstr)) { - if (!enabled) + if(strstr(pp->verstr, idstr)){ + if (!enabled){ + enabled = 1; increfp(pp); + } if(isa == 0 || pcmio(pp->slotno, isa) == 0){ pp->special = 1; return pp->slotno; @@ -557,7 +561,9 @@ i82365probe(int x, int d, int dev) outb(x, Rid + (dev<<7)); id = inb(d); if((id & 0xf0) != 0x80) - return 0; /* not this family */ + return 0; /* not a memory & I/O card */ + if((id & 0x0f) == 0x00) + return 0; /* no revision number, not possible */ cp = xalloc(sizeof(I82365)); cp->xreg = x; @@ -588,22 +594,28 @@ i82365probe(int x, int d, int dev) break; } +#ifdef adsf + /* if it's not a Cirrus, it could be a Vadem... */ if(cp->type == Ti82365){ + /* unlock the Vadem extended regs */ outb(x, 0x0E + (dev<<7)); outb(x, 0x37 + (dev<<7)); + + /* make the id register show the Vadem id */ outb(x, 0x3A + (dev<<7)); c = inb(d); outb(d, c|0xC0); outb(x, Rid + (dev<<7)); c = inb(d); - if(c != id && !(c & 0x08)) - print("#y%d: id %uX changed to %uX\n", ncontroller, id, c); if(c & 0x08) cp->type = Tvg46x; + + /* go back to Intel compatible id */ outb(x, 0x3A + (dev<<7)); c = inb(d); outb(d, c & ~0xC0); } +#endif asdf /* low power mode */ outb(x, Rmisc2 + (dev<<7)); @@ -661,14 +673,14 @@ i82365reset(void) /* look for controllers if the ports aren't already taken */ if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){ - i82365probe(0x3E0, 0x3E1, 0) || + i82365probe(0x3E0, 0x3E1, 0); i82365probe(0x3E0, 0x3E1, 1); if(ncontroller == 0) iofree(0x3E0); } if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){ i = ncontroller; - i82365probe(0x3E2, 0x3E3, 0) || + i82365probe(0x3E2, 0x3E3, 0); i82365probe(0x3E2, 0x3E3, 1); if(ncontroller == i) iofree(0x3E2); @@ -690,6 +702,7 @@ i82365reset(void) pp->base = (cp->dev<<7) | (j<<6); pp->cp = cp; pp->msec = ~0; + pp->verstr[0] = 0; slotdis(pp); /* interrupt on status change */ @@ -813,8 +826,7 @@ pcmread(int slotno, int attr, void *a, long n, vlong off) static long i82365read(Chan *c, void *a, long n, vlong off) { - char *p; - int len; + char *p, *buf, *e; Slot *pp; ulong offset = off; @@ -825,26 +837,30 @@ i82365read(Chan *c, void *a, long n, vlong off) case Qattr: return pcmread(SLOTNO(c), TYPE(c) == Qattr, a, n, off); case Qctl: - p = malloc(READSTR); - len = 0; + buf = p = malloc(READSTR); + e = p + READSTR; pp = slot + SLOTNO(c); - if(pp->occupied) - len += snprint(p+len, READSTR-len, "occupied\n"); + buf[0] = 0; + if(pp->occupied){ + p = seprint(p, e, "occupied\n"); + if(pp->verstr[0]) + p = seprint(p, e, "version %s\n", pp->verstr); + } if(pp->enabled) - len += snprint(p+len, READSTR-len, "enabled\n"); + p = seprint(p, e, "enabled\n"); if(pp->powered) - len += snprint(p+len, READSTR-len, "powered\n"); + p = seprint(p, e, "powered\n"); if(pp->configed) - len += snprint(p+len, READSTR-len, "configed\n"); + p = seprint(p, e, "configed\n"); if(pp->wrprot) - len += snprint(p+len, READSTR-len, "write protected\n"); + p = seprint(p, e, "write protected\n"); if(pp->busy) - len += snprint(p+len, READSTR-len, "busy\n"); - snprint(p+len, READSTR-len, "battery lvl %d\n", pp->battery); + p = seprint(p, e, "busy\n"); + seprint(p, e, "battery lvl %d\n", pp->battery); - n = readstr(offset, a, n, p); - free(p); + n = readstr(offset, a, n, buf); + free(buf); return n; } @@ -1183,6 +1199,7 @@ cisread(Slot *pp) pp->cpresent = 0; pp->configed = 0; pp->nctab = 0; + pp->verstr[0] = 0; for(i = 0; i < nelem(cistab); i++) { if((nv = pcmcistuple(pp->slotno, cistab[i].n, -1, v, sizeof(v))) >= 0) {