From 58e97a10c9e0ca4cfeb12a4a26bb5b37218dcb30 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 7 Nov 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-11-07 --- bitsy/clock.c | 73 +-------- bitsy/devflash.c | 57 +++++++ bitsy/devuda1341.c | 373 +++++++++++++++++++++++++++++++++++++++++++++ boot/boot.c | 30 +++- boot/boot.h | 2 +- boot/bootip.c | 1 + pc/devi82365.c | 32 ++-- port/netif.c | 3 +- 8 files changed, 485 insertions(+), 86 deletions(-) diff --git a/bitsy/clock.c b/bitsy/clock.c index d4d74df0eeaa39e3416566f8e94435f0cd3d7878..c50bae830c913d21e42c9661125c8e60c7e1e843 100644 --- a/bitsy/clock.c +++ b/bitsy/clock.c @@ -7,44 +7,6 @@ #include "ureg.h" #include "../port/error.h" -typedef struct OSTimer -{ - ulong osmr[4]; /* match registers */ - ulong oscr; /* counter register */ - ulong ossr; /* status register */ - ulong ower; /* watchdog enable register */ - ulong oier; /* timer interrupt enable register */ -} OSTimer; - -static OSTimer *timerregs = (OSTimer*)OSTIMERREGS; -static int clockinited; - -static void clockintr(Ureg*, void*); - -typedef struct Clock0link Clock0link; -typedef struct Clock0link { - void (*clock)(void); - Clock0link* link; -} Clock0link; - -static Clock0link *clock0link; -static Lock clock0lock; - -void -addclock0link(void (*clock)(void)) -{ - Clock0link *lp; - - if((lp = malloc(sizeof(Clock0link))) == 0){ - print("addclock0link: too many links\n"); - return; - } - ilock(&clock0lock); - lp->clock = clock; - lp->link = clock0link; - clock0link = lp; - iunlock(&clock0lock); -} void clockinit(void) @@ -83,40 +45,7 @@ clockintr(Ureg *ureg, void*) /* post interrupt 1/HZ secs from now */ timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ; - m->ticks++; - - if(m->proc) - m->proc->pc = ureg->pc; - - if(inclockintr) - return; /* interrupted ourself */ - - inclockintr = 1; - - accounttime(); - if(kproftimer != nil) - (*kproftimer)(ureg->pc); - - checkalarms(); - ilock(&clock0lock); - for(lp = clock0link; lp; lp = lp->link) - lp->clock(); - iunlock(&clock0lock); - - if(active.exiting && (active.machs & (1<machno))) - exit(0); - inclockintr = 0; - - if(up == 0 || up->state != Running) - return; - - if(anyready()) - sched(); - - if((ureg->psr & PsrMask) == PsrMusr) { - (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1); - segclock(ureg->pc); - } + portclock(); } void diff --git a/bitsy/devflash.c b/bitsy/devflash.c index 0e915c4c2360d8739c798a36f3573c9c4791e34e..a2014e46cd3ac05f878a8e30053dbf6efe864fb2 100644 --- a/bitsy/devflash.c +++ b/bitsy/devflash.c @@ -15,3 +15,60 @@ struct FlashPart ulong start; /* byte offsets */ ulong end; }; + +static ulong *flash = (ulong*)FLASHZERO; + +/* + * on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit + * accesses, one to the low half of the chip and the other to the high + * half. Therefore for all command accesses, ushort indices in the + * manuals turn into ulong indices in our code. Also, by copying all + * 16 bit commands to both halves of a 32 bit command, we erase 2 + * sectors for each request erase request. + */ + +/* + * common flash memory interface + */ +enum +{ + CFIidoff= 0x10, + CFIsysoff= 0x1B, + CFIgeomoff= 0x27, +}; + +struct CFIid +{ + ulong q; + ulong r; + ulong y; + ulong cmd_set; + ulong vendor_alg; + ulong ext_alg_addr[2]; + ulong alt_cmd_set; + ulong alt_vendor_alg; + ulong alt_ext_ald_addr[2]; + +}; + +struct CFIsys +{ + ulong vcc_min; /* 100 mv */ + ulong vcc_max; + ulong vpp_min; + ulong vpp_max; + ulong word_wr_to; /* 2**n µs */ + ulong buf_wr_to; /* 2**n µs */ + ulong block_erase_to; /* 2**n ms */ + ulong chip_erase_to; /* 2**n ms */ + ulong max_word_wr_to; /* 2**n µs */ + ulong max_buf_wr_to; /* 2**n µs */ + ulong max_block_erase_to; /* 2**n ms */ + ulong max_chip_erase_to; /* 2**n ms */ +}; + +struct CFIgeom +{ + ulong size; /* 2**n bytes */ + ulong +}; diff --git a/bitsy/devuda1341.c b/bitsy/devuda1341.c index 5c8a882b39bbffa467c91226aa0580bfedb00fb6..8fd102f23c13fdb7cca7d2ef0f356e4b5b3a8f59 100644 --- a/bitsy/devuda1341.c +++ b/bitsy/devuda1341.c @@ -460,3 +460,376 @@ audioinit(void) return 0; } + +static void +audioinit(void) +{} + + +static Chan* +audioattach(char *param) +{ + return devattach('A', param); +} + +static int +audiowalk(Chan *c, char *name) +{ + return devwalk(c, name, audiodir, nelem(audiodir), devgen); +} + +static void +audiostat(Chan *c, char *db) +{ + devstat(c, db, audiodir, nelem(audiodir), devgen); +} + +static Chan* +audioopen(Chan *c, int omode) +{ + int amode; + + switch(c->qid.path & ~CHDIR) { + default: + error(Eperm); + break; + + case Qstatus: + if((omode&7) != OREAD) + error(Eperm); + case Qvolume: + case Qdir: + break; + + case Qaudio: + amode = Awrite; + switch (omode & 0x7) + case OREAD: + break; + case OWRITE + qlock(&audio); + if(audio.amode != Aclosed){ + qunlock(&audio); + error(Einuse); + } + if(audio.bufinit == 0) { + audio.bufinit = 1; + sbbufinit(); + } + audio.amode = amode; + setempty(); + audio.curcount = 0; + qunlock(&audio); + mxvolume(); + break; + } + c = devopen(c, omode, audiodir, nelem(audiodir), devgen); + c->mode = openmode(omode); + c->flag |= COPEN; + c->offset = 0; + + return c; +} + +static void +audioclose(Chan *c) +{ + Buf *b; + + switch(c->qid.path & ~CHDIR) { + default: + error(Eperm); + break; + + case Qdir: + case Qvolume: + case Qstatus: + break; + + case Qaudio: + if(c->flag & COPEN) { + qlock(&audio); + if(audio.amode == Awrite) { + /* flush out last partial buffer */ + b = audio.filling; + if(b) { + audio.filling = 0; + memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount); + swab(b->virt); + putbuf(&audio.full, b); + } + if(!audio.active && audio.full.first) + pokeaudio(); + } + audio.amode = Aclosed; + if(waserror()){ + qunlock(&audio); + nexterror(); + } + while(audio.active) + waitaudio(); + setempty(); + poperror(); + qunlock(&audio); + } + break; + } +} + +static long +audioread(Chan *c, void *v, long n, vlong off) +{ + int liv, riv, lov, rov; + long m, n0; + char buf[300]; + Buf *b; + int j; + ulong offset = off; + char *a; + + n0 = n; + a = v; + switch(c->qid.path & ~CHDIR) { + default: + error(Eperm); + break; + + case Qdir: + return devdirread(c, a, n, audiodir, nelem(audiodir), devgen); + + case Qaudio: + if(audio.amode != Aread) + error(Emode); + qlock(&audio); + if(waserror()){ + qunlock(&audio); + nexterror(); + } + while(n > 0) { + b = audio.filling; + if(b == 0) { + b = getbuf(&audio.full); + if(b == 0) { + waitaudio(); + continue; + } + audio.filling = b; + swab(b->virt); + audio.curcount = 0; + } + m = Bufsize-audio.curcount; + if(m > n) + m = n; + memmove(a, b->virt+audio.curcount, m); + + audio.curcount += m; + n -= m; + a += m; + if(audio.curcount >= Bufsize) { + audio.filling = 0; + putbuf(&audio.empty, b); + } + } + poperror(); + qunlock(&audio); + break; + + case Qstatus: + buf[0] = 0; + snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n", + audio.totcount, audio.tottime); + return readstr(offset, a, n, buf); + + case Qvolume: + j = 0; + buf[0] = 0; + for(m=0; volumes[m].name; m++){ + liv = audio.livol[m]; + riv = audio.rivol[m]; + lov = audio.lovol[m]; + rov = audio.rovol[m]; + j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name); + if((volumes[m].flag & Fmono) || liv==riv && lov==rov){ + if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov) + j += snprint(buf+j, sizeof(buf)-j, " %d", liv); + else{ + if(volumes[m].flag & Fin) + j += snprint(buf+j, sizeof(buf)-j, + " in %d", liv); + if(volumes[m].flag & Fout) + j += snprint(buf+j, sizeof(buf)-j, + " out %d", lov); + } + }else{ + if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && + liv==lov && riv==rov) + j += snprint(buf+j, sizeof(buf)-j, + " left %d right %d", + liv, riv); + else{ + if(volumes[m].flag & Fin) + j += snprint(buf+j, sizeof(buf)-j, + " in left %d right %d", + liv, riv); + if(volumes[m].flag & Fout) + j += snprint(buf+j, sizeof(buf)-j, + " out left %d right %d", + lov, rov); + } + } + j += snprint(buf+j, sizeof(buf)-j, "\n"); + } + return readstr(offset, a, n, buf); + } + return n0-n; +} + +static long +audiowrite(Chan *c, void *vp, long n, vlong) +{ + long m, n0; + int i, nf, v, left, right, in, out; + char buf[255], *field[Ncmd]; + Buf *b; + char *a; + + a = vp; + n0 = n; + switch(c->qid.path & ~CHDIR) { + default: + error(Eperm); + break; + + case Qvolume: + v = Vaudio; + left = 1; + right = 1; + in = 1; + out = 1; + if(n > sizeof(buf)-1) + n = sizeof(buf)-1; + memmove(buf, a, n); + buf[n] = '\0'; + + nf = getfields(buf, field, Ncmd, 1, " \t\n"); + for(i = 0; i < nf; i++){ + /* + * a number is volume + */ + if(field[i][0] >= '0' && field[i][0] <= '9') { + m = strtoul(field[i], 0, 10); + if(left && out) + audio.lovol[v] = m; + if(left && in) + audio.livol[v] = m; + if(right && out) + audio.rovol[v] = m; + if(right && in) + audio.rivol[v] = m; + mxvolume(); + goto cont0; + } + + for(m=0; volumes[m].name; m++) { + if(strcmp(field[i], volumes[m].name) == 0) { + v = m; + in = 1; + out = 1; + left = 1; + right = 1; + goto cont0; + } + } + + if(strcmp(field[i], "reset") == 0) { + resetlevel(); + mxvolume(); + goto cont0; + } + if(strcmp(field[i], "in") == 0) { + in = 1; + out = 0; + goto cont0; + } + if(strcmp(field[i], "out") == 0) { + in = 0; + out = 1; + goto cont0; + } + if(strcmp(field[i], "left") == 0) { + left = 1; + right = 0; + goto cont0; + } + if(strcmp(field[i], "right") == 0) { + left = 0; + right = 1; + goto cont0; + } + error(Evolume); + break; + cont0:; + } + break; + + case Qaudio: + if(audio.amode != Awrite) + error(Emode); + qlock(&audio); + if(waserror()){ + qunlock(&audio); + nexterror(); + } + while(n > 0) { + b = audio.filling; + if(b == 0) { + b = getbuf(&audio.empty); + if(b == 0) { + waitaudio(); + continue; + } + audio.filling = b; + audio.curcount = 0; + } + + m = Bufsize-audio.curcount; + if(m > n) + m = n; + memmove(b->virt+audio.curcount, a, m); + + audio.curcount += m; + n -= m; + a += m; + if(audio.curcount >= Bufsize) { + audio.filling = 0; + swab(b->virt); + putbuf(&audio.full, b); + } + } + poperror(); + qunlock(&audio); + break; + } + return n0 - n; +} + +Dev audiodevtab = { + 'A', + "audio", + + devreset, + audioinit, + audioattach, + devclone, + audiowalk, + audiostat, + audioopen, + devcreate, + audioclose, + audioread, + devbread, + audiowrite, + devbwrite, + devremove, + devwstat, +}; diff --git a/boot/boot.c b/boot/boot.c index 7ff97a24267c587d6177846fe171977c8e8d81c9..f93c8bcc99ccc94446b206b18de4162a99809c2e 100644 --- a/boot/boot.c +++ b/boot/boot.c @@ -199,6 +199,34 @@ findmethod(char *a) return 0; } +int +parsecmd(char *s, char **av, int n) +{ + int ac; + + n--; + for(ac = 0; ac < n; ac++){ + while(*s == ' ' || *s == '\t') + s++; + if(*s == 0 || *s == '\n' || *s == '\r') + break; + if(*s == '\''){ + s++; + av[ac] = s; + while(*s && *s != '\'') + s++; + } else { + av[ac] = s; + while(*s && *s != ' ' && *s != '\t') + s++; + } + if(*s != 0) + *s++ = 0; + } + av[ac] = 0; + return ac; +} + /* * ask user from whence cometh the root file system */ @@ -234,7 +262,7 @@ rootserver(char *arg) outin(prompt, reply, sizeof(reply)); mp = findmethod(reply); if(mp){ - bargc = getfields(reply, bargv, Nbarg-1, 1, " "); + bargc = parsecmd(reply, bargv, Nbarg); cp = strchr(reply, '!'); if(cp) strcpy(sys, cp+1); diff --git a/boot/boot.h b/boot/boot.h index 690b794a9eaeda4965df68b0af483ce4b1ef5953..6944415d831f30d15b0f5590e9fc487e65f65e3d 100644 --- a/boot/boot.h +++ b/boot/boot.h @@ -22,7 +22,7 @@ extern uchar hostkey[]; extern char username[NAMELEN]; enum { - Nbarg= 16, + Nbarg= 32, }; extern int bargc; extern char *bargv[Nbarg]; diff --git a/boot/bootip.c b/boot/bootip.c index b376fed47e069daf318450e9bc9526563dfc93da..5091eef39fc2d77f65b1d1fc3b4ae97f2da7270a 100644 --- a/boot/bootip.c +++ b/boot/bootip.c @@ -43,6 +43,7 @@ configip(void) case 'b': case 'h': case 'm': + case 'c': p = ARGF(); USED(p); break; diff --git a/pc/devi82365.c b/pc/devi82365.c index 1157afd2500a9e7c731dacbbb20a93b8bd49549b..520218dd110554eb2cb8ac0cfb57ed2dd6b623a6 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -178,6 +178,7 @@ struct Slot uchar busy; /* cis info */ + ulong msec; /* time of last slotinfo call */ char verstr[512]; /* version string */ uchar cpresent; /* config registers present */ ulong caddr; /* relative address of config registers */ @@ -236,6 +237,7 @@ slotinfo(Slot *pp) pp->battery = (isr & 3) == 3; pp->wrprot = isr & (1<<4); pp->busy = isr & (1<<5); + pp->msec = TK2MS(MACHP(0)->ticks); } static int @@ -438,28 +440,35 @@ pcmspecial(char *idstr, ISAConf *isa) { Slot *pp; extern char *strstr(char*, char*); - static int resetdone; + int enabled; i82365reset(); -print("pcmcia: looking for %s: ", idstr); for(pp = slot; pp < lastslot; pp++){ if(pp->special) continue; /* already taken */ - increfp(pp); + 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 + */ + if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000) { + increfp(pp); + enabled++; + } if(pp->occupied) { -print("[%8.8s]", pp->verstr); - if(strstr(pp->verstr, idstr)) - if(isa == 0 || pcmio(pp->slotno, isa) == 0){ - pp->special = 1; -print(" - found\n"); - return pp->slotno; + if(strstr(pp->verstr, idstr)) { + if (!enabled) + increfp(pp); + if(isa == 0 || pcmio(pp->slotno, isa) == 0){ + pp->special = 1; + return pp->slotno; + } } } else pp->special = 1; - decrefp(pp); + if (enabled) + decrefp(pp); } -print("\n"); return -1; } @@ -680,6 +689,7 @@ i82365reset(void) pp->memlen = 64*MB; pp->base = (cp->dev<<7) | (j<<6); pp->cp = cp; + pp->msec = ~0; slotdis(pp); /* interrupt on status change */ diff --git a/port/netif.c b/port/netif.c index e93e0b96741c8f4d30f3fc1d5ea78de64adf95a0..c2f8ff01d87e67ab2cc22f48a8e58298375d5232 100644 --- a/port/netif.c +++ b/port/netif.c @@ -318,7 +318,8 @@ netifwrite(Netif *nif, Chan *c, void *a, long n) p = netmulti(nif, f, binaddr, 0); if(p) error(p); - } + } else + n = -1; qunlock(nif); poperror(); return n;