From ae37eaa082570514122fee906fb7a28e7b51b212 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 10 May 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-05-10 --- bitsy/devuda1341.c | 75 ++++++++++++++++++++++++++++++---------------- pc/devarch.c | 5 ++++ pc/etherelnk3.c | 6 ++++ port/devenv.c | 18 ++++++++++- port/devproc.c | 16 +++++++++- port/portdat.h | 1 + port/portfns.h | 3 +- port/proc.c | 53 ++++++++++++++++++++++++++++++++ 8 files changed, 148 insertions(+), 29 deletions(-) diff --git a/bitsy/devuda1341.c b/bitsy/devuda1341.c index 2b2b10a64a02f2902a1dcf488322253de76935aa..4b838e47d6bfb6e65c08df4f5dec840959e1343e 100644 --- a/bitsy/devuda1341.c +++ b/bitsy/devuda1341.c @@ -114,7 +114,7 @@ enum Vinvert, Nvol, - Bufsize = /* 4* */ 1024, /* 46 ms each */ + Bufsize = 4* 1024, /* 46 ms each */ Nbuf = 32, /* 1.5 seconds total */ Speed = 44100, @@ -222,8 +222,8 @@ static struct [Vinvert] {"invert", Fin|Fout|Fmono, 0, 0}, [Nvol] {0} }; - static int rate = Speed; /* Current sample rate */ +static int bufsize = Bufsize; /* Current buffer size */ static void setreg(char *name, int val, int n); /* @@ -758,7 +758,7 @@ sendaudio(IOstate *s) { 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, Flushbuf, Bufsize) & 0xff; + zerodma |= dmastart(s->dma, Flushbuf, bufsize) & 0xff; if (zerodma == 0) if (debug) print("emptyfail\n"); iostats.empties++; @@ -803,7 +803,7 @@ recvaudio(IOstate *s) { ilock(&s->ilock); while (s->next != s->emptying) { assert(s->next->nbytes == 0); - if ((n = dmastart(s->dma, s->next->phys, Bufsize)) == 0) { + if ((n = dmastart(s->dma, s->next->phys, bufsize)) == 0) { iostats.faildma++; break; } @@ -879,7 +879,7 @@ audiointr(void *x, ulong ndma) { /* 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->nbytes = (s == &audio.i)? bufsize: 0; s->current++; if (s->current == &s->buf[Nbuf]) s->current = &s->buf[0]; @@ -1107,7 +1107,7 @@ audioread(Chan *c, void *v, long n, vlong off) } m = (s->emptying->nbytes > n)? n: s->emptying->nbytes; - memmove(p, s->emptying->virt + Bufsize - + memmove(p, s->emptying->virt + bufsize - s->emptying->nbytes, m); s->emptying->nbytes -= m; @@ -1127,7 +1127,7 @@ audioread(Chan *c, void *v, long n, vlong off) case Qspeed: buf[0] = '\0'; - snprint(buf, sizeof(buf), "speed %d\n", rate); + snprint(buf, sizeof(buf), "speed %d\ndmasize %d\n", rate, bufsize); return readstr(offset, p, n, buf); case Qvolume: @@ -1174,6 +1174,29 @@ audioread(Chan *c, void *v, long n, vlong off) return n0-n; } +static void +setrate(int newrate) +{ + switch (newrate) { + case 16000: + case 22050: + case 44100: + case 48000: + volumes[Vspeed].ilval = volumes[Vspeed].irval = rate = newrate; + break; + default: + error(Ebadarg); + } +} + +static void +setbufsize(int newbufsize) +{ + if (newbufsize < 0 || newbufsize > 8 * 1024 || newbufsize % sizeof(ulong)) + error(Ebadarg); + bufsize = newbufsize; +} + static long audiowrite(Chan *c, void *vp, long n, vlong) { @@ -1196,24 +1219,24 @@ audiowrite(Chan *c, void *vp, long n, vlong) memmove(buf, p, n); buf[n] = '\0'; nf = getfields(buf, field, Ncmd, 1, " \t\n"); - if (nf != 2 && nf != 1) error(Ebadarg); - if (nf == 2) { - if (strcmp(field[0], "speed")) - error(Ebadarg); - i = 1; - } - else + if (nf == 1) + /* The user just supplied a number */ + setrate((int)strtol(field[0], (char **)nil, 0)); + else { i = 0; - i = (int)strtol(field[i], (char **)nil, 0); - switch (i) { - case 16000: - case 22050: - case 44100: - case 48000: - volumes[Vspeed].ilval = volumes[Vspeed].irval = rate = i; - break; - default: - error(Ebadarg); + while (i < nf) { + int newval; + + if (i + 1 >= nf) error(Ebadarg); + newval = (int)strtol(field[i + 1], (char **)nil, 0); + if (!strcmp(field[i], "speed")) + setrate(newval); + else if (!strcmp(field[i], "dmasize")) + setbufsize(newval); + else + error(Ebadarg); + i += 2; + } } break; @@ -1316,7 +1339,7 @@ audiowrite(Chan *c, void *vp, long n, vlong) if (debug > 1) print("#A: sleep\n"); sleep(&a->vous, audioqnotfull, a); } - m = Bufsize - a->filling->nbytes; + m = bufsize - a->filling->nbytes; if(m > n) m = n; memmove(a->filling->virt + a->filling->nbytes, p, m); @@ -1324,7 +1347,7 @@ audiowrite(Chan *c, void *vp, long n, vlong) a->filling->nbytes += m; n -= m; p += m; - if(a->filling->nbytes >= Bufsize) { + if(a->filling->nbytes >= bufsize) { if (debug > 1) print("#A: filled @%p\n", a->filling); a->filling++; if (a->filling == &a->buf[Nbuf]) diff --git a/pc/devarch.c b/pc/devarch.c index 2b9425a3111d178972ebb42ef18fc5419727fcb7..04c0bd13a1f6ae1195939c82b54ffab9b62eb4d8 100644 --- a/pc/devarch.c +++ b/pc/devarch.c @@ -133,6 +133,11 @@ ioalloc(int port, int size, int align, char *tag) return -1; } } else { + // Only 64KB I/O space on the x86. + if((port+size) >= 0x10000){ + unlock(&iomap); + return -1; + } // see if the space clashes with previously allocated ports for(l = &iomap.m; *l; l = &(*l)->next){ m = *l; diff --git a/pc/etherelnk3.c b/pc/etherelnk3.c index dd3d3500cb8b9aff9280319f6182d755cab46fe4..86a2a04c30663d8c4dd74129fc83a884462514e0 100644 --- a/pc/etherelnk3.c +++ b/pc/etherelnk3.c @@ -1443,6 +1443,12 @@ tcm59Xpci(void) p = nil; while(p = pcimatch(p, 0x10B7, 0)){ + /* + * Not prepared to deal with memory-mapped + * devices yet. + */ + if(!(p->mem[0].bar & 0x01)) + continue; port = p->mem[0].bar & ~0x01; if(ioalloc(port, p->mem[0].size, 0, "tcm59Xpci") < 0){ print("tcm59Xpci: port 0x%uX in use\n", port); diff --git a/port/devenv.c b/port/devenv.c index 98aad7664354a7cab5d271a905aecb740fb37480..1e71f8d751bd0b207ba77363717c68b796e79103 100644 --- a/port/devenv.c +++ b/port/devenv.c @@ -57,7 +57,23 @@ envattach(char *spec) static int envwalk(Chan *c, char *name) { - return devwalk(c, name, 0, 0, envgen); + Evalue *e; + Egrp *eg; + int rv; + + if(c->qid.path == CHDIR && name[0] != '.'){ + rv = 0; + eg = up->egrp; + qlock(eg); + for(e = eg->entries; e; e = e->link) + if(strcmp(e->name, name) == 0){ + rv = 1; + c->qid = e->qid; + } + qunlock(eg); + return rv; + } else + return devwalk(c, name, 0, 0, envgen); } static void diff --git a/port/devproc.c b/port/devproc.c index 1e6b8af40982f6f5913597afd6c15a51b74222ac..96b65175683424d1694a7860b17bc390a8701c43 100644 --- a/port/devproc.c +++ b/port/devproc.c @@ -150,7 +150,21 @@ procattach(char *spec) static int procwalk(Chan *c, char *name) { - return devwalk(c, name, 0, 0, procgen); + int s; + int pid; + + if(c->qid.path == CHDIR && name[0] != '.'){ + /* this is a hack to speed walks through a large directory */ + pid = strtol(name, &name, 0); + if(pid < 0 || *name != 0) + return 0; + s = procindex(pid); + if(s < 0) + return 0; + c->qid = (Qid){CHDIR|((s+1)<error[0] = '\0'; memset(p->seg, 0, sizeof p->seg); p->pid = incref(&pidalloc); + pidhash(p); p->noteid = incref(¬eidalloc); if(p->pid==0 || p->noteid==0) panic("pidalloc"); @@ -825,6 +830,7 @@ pexit(char *exitstr, int freemem) qunlock(&up->seglock); lock(&up->exl); /* Prevent my children from leaving waits */ + pidunhash(up); up->pid = 0; wakeup(&up->waitr); unlock(&up->exl); @@ -1213,3 +1219,50 @@ accounttime(void) n = (nrdy+n)*1000; m->load = (m->load*19+n)/20; } + +static void +pidhash(Proc *p) +{ + int h; + + h = p->pid % nelem(procalloc.ht); + lock(&procalloc); + p->pidhash = procalloc.ht[h]; + procalloc.ht[h] = p; + unlock(&procalloc); +} + +static void +pidunhash(Proc *p) +{ + int h; + Proc **l; + + h = p->pid % nelem(procalloc.ht); + lock(&procalloc); + for(l = &procalloc.ht[h]; *l != nil; l = &(*l)->pidhash) + if(*l == p){ + *l = p->pidhash; + break; + } + unlock(&procalloc); +} + +int +procindex(int pid) +{ + Proc *p; + int h; + int s; + + s = -1; + h = pid % nelem(procalloc.ht); + lock(&procalloc); + for(p = procalloc.ht[h]; p != nil; p = p->pidhash) + if(p->pid == pid){ + s = p - procalloc.arena; + break; + } + unlock(&procalloc); + return s; +}