From ace7c98584268f279d05192954098b0a92bc0fb2 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 3 Apr 1997 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1997-04-03 --- carrera/devrtc.c | 139 ++++++++++++++++++++++++++++++++++----- ip/devip.c | 24 ++++--- ip/gre.c | 12 ++-- ip/icmp.c | 11 +++- ip/il.c | 13 +++- ip/ip.h | 3 +- ip/tcp.c | 22 +++++-- ip/udp.c | 6 +- pc/archmp.c | 3 + pc/etherelnk3.c | 21 +++++- pc/main.c | 167 ++++++++++++++++++++++++----------------------- port/netif.c | 59 +++++++++++++---- port/netif.h | 3 + 13 files changed, 342 insertions(+), 141 deletions(-) diff --git a/carrera/devrtc.c b/carrera/devrtc.c index 6800a369af5b55a7738418a0d07a7fe5ff5e8a0b..af6fe6424fe1e4eb6c859aa00a0f4810f3b586be 100644 --- a/carrera/devrtc.c +++ b/carrera/devrtc.c @@ -35,8 +35,13 @@ enum Month= 0x08, Year= 0x09, Status= 0x0A, + StatusB= 0x0B, + StatusC= 0x0C, + StatusD= 0x0D, Nvsize = 4096, + + Nclock= 6, }; Dirtab rtcdir[]={ @@ -47,9 +52,31 @@ Dirtab rtcdir[]={ static ulong rtc2sec(Rtc*); static void sec2rtc(ulong, Rtc*); +static uchar statusB; + +static void +getstatusB(void) +{ + int i, x; + uchar r; + + for(i = 0; i < 10000; i++){ + x = (*(uchar*)Rtcindex)&~0x7f; + *(uchar*)Rtcindex = x|Status; + r = *(uchar*)Rtcdata; + if(r & 0x80) + continue; + + *(uchar*)Rtcindex = x|StatusB; + statusB = *(uchar*)Rtcdata; + break; + } +} + static Chan* rtcattach(char *spec) { + getstatusB(); return devattach('r', spec); } @@ -98,36 +125,102 @@ bcd2binary(int reg) return (x&0xf) + 10*(x>>4); } +#define GETBCD(o) ((clock[o]&0xf) + 10*(clock[o]>>4)) + +static void +dumprtcstatus(void) +{ + int i, x; + uchar status[4], r; + + for(i = 0; i < 10000; i++){ + x = (*(uchar*)Rtcindex)&~0x7f; + *(uchar*)Rtcindex = x|Status; + r = *(uchar*)Rtcdata; + if(r & 0x80) + continue; + + status[0] = r; + *(uchar*)Rtcindex = x|StatusB; + status[1] = *(uchar*)Rtcdata; + *(uchar*)Rtcindex = x|StatusC; + status[2] = *(uchar*)Rtcdata; + *(uchar*)Rtcindex = x|StatusD; + status[3] = *(uchar*)Rtcdata; + + *(uchar*)Rtcindex = x|Status; + r = *(uchar*)Rtcdata; + if((r & 0x80) == 0) + break; + } + + print("RTC: %uX %uX %uX %uX\n", status[0], status[1], status[2], status[3]); +} + static long _rtctime(void) { Rtc rtc; int i, x; + uchar clock[Nclock], r; + int busy; + /* don't do the read until the clock is no longer busy */ + busy = 0; for(i = 0; i < 10000; i++){ x = (*(uchar*)Rtcindex)&~0x7f; *(uchar*)Rtcindex = x|Status; - x = *(uchar*)Rtcdata; - if(x & 0x80) + r = *(uchar*)Rtcdata; + if(r & 0x80){ + busy++; continue; + } - /* - * read and convert from bcd - */ - rtc.sec = bcd2binary(Seconds); - rtc.min = bcd2binary(Minutes); - rtc.hour = bcd2binary(Hours); - rtc.mday = bcd2binary(Mday); - rtc.mon = bcd2binary(Month); - rtc.year = bcd2binary(Year)+1970; + /* read clock values */ + *(uchar*)Rtcindex = x|Seconds; + clock[0] = *(uchar*)Rtcdata; + *(uchar*)Rtcindex = x|Minutes; + clock[1] = *(uchar*)Rtcdata; + *(uchar*)Rtcindex = x|Hours; + clock[2] = *(uchar*)Rtcdata; + *(uchar*)Rtcindex = x|Mday; + clock[3] = *(uchar*)Rtcdata; + *(uchar*)Rtcindex = x|Month; + clock[4] = *(uchar*)Rtcdata; + *(uchar*)Rtcindex = x|Year; + clock[5] = *(uchar*)Rtcdata; - x = (*(uchar*)Rtcindex)&~0x7f; *(uchar*)Rtcindex = x|Status; - x = *(uchar*)Rtcdata; - if((x & 0x80) == 0) + r = *(uchar*)Rtcdata; + if((r & 0x80) == 0) break; } + if(statusB & 0x04){ + rtc.sec = clock[0]; + rtc.min = clock[1]; + rtc.hour = clock[2]; + rtc.mday = clock[3]; + rtc.mon = clock[4]; + rtc.year = clock[5]; + } + else{ + /* + * convert from BCD + */ + rtc.sec = GETBCD(0); + rtc.min = GETBCD(1); + rtc.hour = GETBCD(2); + rtc.mday = GETBCD(3); + rtc.mon = GETBCD(4); + rtc.year = GETBCD(5); + } + + /* + * the world starts jan 1 1970 + */ + rtc.year += 1970; + return rtc2sec(&rtc); } @@ -136,6 +229,8 @@ static Lock rtlock; long rtctime(void) { +#define notdef +#ifdef notdef int i; long t, ot; @@ -149,11 +244,16 @@ rtctime(void) if(ot == t) break; } - if(i == 100) print("we are boofheads\n"); - iunlock(&rtlock); + if(i == 100) print("we are boofheads\n"); + return t; +#else + extern ulong boottime; + + return boottime+TK2SEC(MACHP(0)->ticks); +#endif /* notdef */ } static long @@ -169,6 +269,7 @@ rtcread(Chan *c, void *buf, long n, ulong offset) case Qrtc: qlock(&rtclock); t = rtctime(); +dumprtcstatus(); qunlock(&rtclock); n = readnum(offset, buf, n, t, 12); return n; @@ -192,9 +293,13 @@ static void binary2bcd(int reg, uchar val) { uchar x; + x = (*(uchar*)Rtcindex)&~0x7f; *(uchar*)Rtcindex = x|reg; - *(uchar*)Rtcdata = (val % 10) | (((val / 10) % 10)<<4); + if(statusB & 0x04) + *(uchar*)Rtcdata = val; + else + *(uchar*)Rtcdata = (val % 10) | (((val / 10) % 10)<<4); } diff --git a/ip/devip.c b/ip/devip.c index e295620cb2f052d5686e0a17ee3fcabd526b3ea5..e84395105b64bf225b754b31fd8e07cde48a457d 100644 --- a/ip/devip.c +++ b/ip/devip.c @@ -648,16 +648,11 @@ ipwrite(Chan* ch, char* a, long n, ulong) qunlock(&c->car); nexterror(); } - switch(nfield){ - default: - error("bad args to announce"); - case 2: - setladdrport(c, fields[1]); - break; - } c->state = Announcing; c->cerr[0] = '\0'; - x->announce(c); + p = x->announce(c, fields, nfield); + if(p != nil) + error(p); sleep(&c->cr, announced, c); if(c->cerr[0] != '\0') error(c->cerr); @@ -938,3 +933,16 @@ Fsstdconnect(Conv *c, char *argv[], int argc) } return nil; } + +char* +Fsstdannounce(Conv* c, char* argv[], int argc) +{ + switch(argc){ + default: + return "bad args to announce"; + case 2: + setladdrport(c, argv[1]); + break; + } + return nil; +} diff --git a/ip/gre.c b/ip/gre.c index 4e82a7c41d79b6694785a5f93842c6d8859f9543..76245b27695b345af50a7fa3316ce4e8d51e5e22 100644 --- a/ip/gre.c +++ b/ip/gre.c @@ -73,9 +73,11 @@ greconnect(Conv *c, char **argv, int argc) } unlock(p); - Fsconnected(&fs, c, err); + if(err != nil) + return err; + Fsconnected(&fs, c, nil); - return err; + return nil; } static int @@ -93,10 +95,10 @@ grecreate(Conv *c) c->wq = qopen(64*1024, 0, 0, 0); } -static void -greannounce(Conv *c) +static char* +greannounce(Conv*, char**, int) { - Fsconnected(&fs, c, "pktifc does not support announce"); + return "pktifc does not support announce"; } static void diff --git a/ip/icmp.c b/ip/icmp.c index 9232135b92ec213e08c0f073bdbbf627c11818dd..f211314c6e96ec3d69002e1ed80d823c843132fb 100644 --- a/ip/icmp.c +++ b/ip/icmp.c @@ -73,10 +73,17 @@ icmpcreate(Conv *c) c->wq = qopen(64*1024, 0, 0, 0); } -static void -icmpannounce(Conv *c) +static char* +icmpannounce(Conv *c, char **argv, int argc) { + char *e; + + e = Fsstdannounce(c, argv, argc); + if(e != nil); + return e; Fsconnected(&fs, c, nil); + + return nil; } static void diff --git a/ip/il.c b/ip/il.c index 4fb800f3c96ffe7cc40094f3af52d5984f44ec7b..0d6da926eb590629b030455fe7583d6be2479a61 100644 --- a/ip/il.c +++ b/ip/il.c @@ -178,13 +178,20 @@ ilstate(char **msg, Conv *c) } /* called with c locked */ -static void -ilannounce(Conv *c) +static char* +ilannounce(Conv *c, char **argv, int argc) { char *e; + e = Fsstdannounce(c, argv, argc); + if(e != nil); + return e; e = ilstart(c, IL_LISTEN, 20); - Fsconnected(&fs, c, e); + if(e != nil) + return e; + Fsconnected(&fs, c, nil); + + return nil; } static void diff --git a/ip/ip.h b/ip/ip.h index 8195c4bb824d39369c80fc0863b9b78b6f0eb27d..8d7f0a9c4eb4fd56b2ac64085eccffa852c8a474 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -140,7 +140,7 @@ struct Proto void (*kick)(Conv*, int); char* (*connect)(Conv*, char**, int); - void (*announce)(Conv*); + char* (*announce)(Conv*, char**, int); int (*state)(char**, Conv*); void (*create)(Conv*); void (*close)(Conv*); @@ -179,6 +179,7 @@ int Fsbuiltinproto(Fs*, byte); Conv* Fsprotoclone(Proto*, char*); Proto* Fsrcvpcol(Fs*, byte); char* Fsstdconnect(Conv*, char**, int); +char* Fsstdannounce(Conv*, char**, int); /* log flags */ enum diff --git a/ip/tcp.c b/ip/tcp.c index 2cf9aeffb9d699f6bedf88cd7685c531d546ab40..955ffd0d424924638d7e6455358468df9dd87bbc 100644 --- a/ip/tcp.c +++ b/ip/tcp.c @@ -239,13 +239,14 @@ tcpsetstate(Conv *s, byte newstate) static char* tcpconnect(Conv *c, char **argv, int argc) { - char *rv; + char *e; - rv = Fsstdconnect(c, argv, argc); - if(rv) - return rv; + e = Fsstdconnect(c, argv, argc); + if(e != nil) + return e; tcpstart(c, TCP_CONNECT, QMAX); - return rv; + + return nil; } int @@ -273,11 +274,18 @@ tcpstate(char **msg, Conv *c) return isclose; } -static void -tcpannounce(Conv *c) +static char* +tcpannounce(Conv *c, char **argv, int argc) { + char *e; + + e = Fsstdannounce(c, argv, argc); + if(e != nil) + return e; tcpstart(c, TCP_LISTEN, QMAX); Fsconnected(&fs, c, nil); + + return nil; } static void diff --git a/ip/udp.c b/ip/udp.c index ae694d42c4623112478d34774e5b480d3ab7cd75..13da4dfd51275c1f7e65b79e6e1acba263ce5bbd 100644 --- a/ip/udp.c +++ b/ip/udp.c @@ -80,10 +80,12 @@ udpstate(char **s, Conv *c) return 1; } -static void -udpannounce(Conv *c) +static char* +udpannounce(Conv *c, char**, int) { Fsconnected(&fs, c, nil); + + return nil; } static void diff --git a/pc/archmp.c b/pc/archmp.c index 482aabb756883f03f1218eaba2cb0cf1d609e425..07369f09f81cd5cb6aa8079dbaab269a33cb455d 100644 --- a/pc/archmp.c +++ b/pc/archmp.c @@ -61,6 +61,9 @@ identify(void) uchar *p, sum; ulong length; + if(getconf("*nomp")) + return 1; + /* * Search for an MP configuration table. For now, * don't accept the default configurations (physaddr == 0). diff --git a/pc/etherelnk3.c b/pc/etherelnk3.c index 243a3ace0530dc0e29512be5f916c40f360c761f..3270d1ddff789b4b8c65725a54fd5565a2fb4baa 100644 --- a/pc/etherelnk3.c +++ b/pc/etherelnk3.c @@ -443,15 +443,34 @@ static void promiscuous(void* arg, int on) { int filter, port; + Ether *ether; - port = ((Ether*)arg)->port; + ether = (Ether*)arg; + port = ether->port; filter = receiveBroadcast|receiveIndividual; + if(ether->nmaddr) + filter |= receiveMulticast; if(on) filter |= receiveAllFrames; COMMAND(port, SetRxFilter, filter); } +static void +multicast(void* arg, char *addr, int on) +{ + int filter, port; + Ether *ether; + + ether = (Ether*)arg; + port = ether->port; + + filter = receiveBroadcast|receiveIndividual; + if(ether->nmaddr) + filter |= receiveMulticast; + COMMAND(port, SetRxFilter, filter); +} + static void attach(Ether* ether) { diff --git a/pc/main.c b/pc/main.c index 03f5d09c8913cb686efeb72a05fd3e5fa115e12d..ee96e45996585bf0a77188c9ead73946cfa72bb5 100644 --- a/pc/main.c +++ b/pc/main.c @@ -32,27 +32,84 @@ extern void ns16552install(void); /* botch: config */ static int isoldbcom; +static int +getcfields(char* lp, char** fields, int n, char* sep) +{ + int i; + + for(i = 0; lp && *lp && i < n; i++){ + while(*lp && strchr(sep, *lp) != 0) + *lp++ = 0; + if(*lp == 0) + break; + fields[i] = lp; + while(*lp && strchr(sep, *lp) == 0){ + if(*lp == '\\' && *(lp+1) == '\n') + *lp++ = ' '; + lp++; + } + } + + return i; +} + static void -bcompatibility(void) +options(void) { uchar *bda; + long i, n; + char *cp, *line[MAXCONF], *p, *q; - if(strncmp(BOOTARGS, "ZORT 0\r\n", 8) == 0) - return; - isoldbcom = 1; + if(strncmp(BOOTARGS, "ZORT 0\r\n", 8)){ + isoldbcom = 1; + + memmove(BOOTARGS, KADDR(1024), BOOTARGSLEN); + memmove(BOOTLINE, KADDR(0x100), BOOTLINELEN); + + bda = KADDR(0x400); + bda[0x13] = 639; + bda[0x14] = 639>>8; + } + + /* + * parse configuration args from dos file plan9.ini + */ + cp = BOOTARGS; /* where b.com leaves its config */ + cp[BOOTARGSLEN-1] = 0; - memmove(BOOTARGS, KADDR(1024), BOOTARGSLEN); - memmove(BOOTLINE, KADDR(0x100), BOOTLINELEN); + /* + * Strip out '\r', change '\t' -> ' '. + */ + p = cp; + for(q = cp; *q; q++){ + if(*q == '\r') + continue; + if(*q == '\t') + *q = ' '; + *p++ = *q; + } + *p = 0; - bda = KADDR(0x400); - bda[0x13] = 639; - bda[0x14] = 639>>8; + n = getcfields(cp, line, MAXCONF, "\n"); + for(i = 0; i < n; i++){ + if(*line[i] == '#') + continue; + cp = strchr(line[i], '='); + if(cp == 0) + continue; + *cp++ = 0; + if(cp - line[i] >= NAMELEN+1) + *(line[i]+NAMELEN-1) = 0; + confname[nconf] = line[i]; + confval[nconf] = cp; + nconf++; + } } void main(void) { - outb(0x3F2, 0x00); /* botch: turn off the floppy motor */ + outb(0x3F2, 0x00); /* botch: turn off the floppy motor */ /* * There is a little leeway here in the ordering but care must be @@ -60,7 +117,7 @@ main(void) * function dependencies * ======== ============ * machinit depends on: m->machno, m->pdb - * cpuidentify depends on :m + * cpuidentify depends on: m * confinit calls: meminit * meminit depends on: cpuidentify (needs to know processor * type for caching, etc.) @@ -75,9 +132,9 @@ main(void) machinit(); active.machs = 1; active.exiting = 0; + options(); screeninit(); cpuidentify(); - bcompatibility(); confinit(); archinit(); xinit(); @@ -303,85 +360,31 @@ getconf(char *name) int i; for(i = 0; i < nconf; i++) - if(strcmp(confname[i], name) == 0) + if(cistrcmp(confname[i], name) == 0) return confval[i]; return 0; } -static int -getcfields(char* lp, char** fields, int n, char* sep) -{ - int i; - - for(i = 0; lp && *lp && i < n; i++){ - while(*lp && strchr(sep, *lp) != 0) - *lp++ = 0; - if(*lp == 0) - break; - fields[i] = lp; - while(*lp && strchr(sep, *lp) == 0){ - if(*lp == '\\' && *(lp+1) == '\n') - *lp++ = ' '; - lp++; - } - } - - return i; -} - void confinit(void) { - long i, j, n; - int pcnt; - char *cp; - char *line[MAXCONF], *p, *q; - extern int defmaxmsg; + char *p; + int i, pcnt; ulong maxmem; + extern int defmaxmsg; - /* - * parse configuration args from dos file plan9.ini - */ - cp = BOOTARGS; /* where b.com leaves its config */ - cp[BOOTARGSLEN-1] = 0; - - /* - * Strip out '\r', change '\t' -> ' '. - */ - p = cp; - for(q = cp; *q; q++){ - if(*q == '\r') - continue; - if(*q == '\t') - *q = ' '; - *p++ = *q; - } - *p = 0; - - maxmem = 0; - pcnt = 0; - n = getcfields(cp, line, MAXCONF, "\n"); - for(j = 0; j < n; j++){ - if(*line[j] == '#') - continue; - cp = strchr(line[j], '='); - if(cp == 0) - continue; - *cp++ = 0; - if(cp - line[j] >= NAMELEN+1) - *(line[j]+NAMELEN-1) = 0; - confname[nconf] = line[j]; - confval[nconf] = cp; - if(cistrcmp(confname[nconf], "*maxmem") == 0) - maxmem = strtoul(confval[nconf], 0, 0); - if(cistrcmp(confname[nconf], "*kernelpercent") == 0) - pcnt = 100 - strtol(confval[nconf], 0, 0); - if(cistrcmp(confname[nconf], "*defmaxmsg") == 0){ - i = strtol(confval[nconf], 0, 0); - if(i < defmaxmsg && i >=128) - defmaxmsg = i; - } - nconf++; + if(p = getconf("*maxmem")) + maxmem = strtoul(p, 0, 0); + else + maxmem = 0; + if(p = getconf("*kernelpercent")) + pcnt = 100 - strtol(p, 0, 0); + else + pcnt = 0; + if(p = getconf("*defmaxmsg")){ + i = strtol(p, 0, 0); + if(i < defmaxmsg && i >=128) + defmaxmsg = i; } meminit(maxmem); diff --git a/port/netif.c b/port/netif.c index b63d018141e5f441f900494a95ca303f3ddf003a..bdb7138fc99c59b445a6182f92bbbf6af7305b93 100644 --- a/port/netif.c +++ b/port/netif.c @@ -9,7 +9,7 @@ static int netown(Netfile*, char*, int); static int openfile(Netif*, int); static char* matchtoken(char*, char*); -static void netmulti(Netif*, char*, int); +static void netmulti(Netif*, Netfile*, char*, int); /* * set up a new network interface @@ -226,7 +226,7 @@ netifwrite(Netif *nif, Chan *c, void *a, long n) qlock(nif); f = nif->f[NETID(c->qid.path)]; - if(p = matchtoken(buf, "connect")){ + if((p = matchtoken(buf, "connect")) != 0){ f->type = atoi(p); if(f->type < 0) nif->all++; @@ -235,10 +235,10 @@ netifwrite(Netif *nif, Chan *c, void *a, long n) nif->prom++; if(nif->prom == 1 && nif->promiscuous != nil) nif->promiscuous(nif->arg, 1); - } else if(p = matchtoken(buf, "addmulti")){ - netmulti(nif, p, 1); - } else if(p = matchtoken(buf, "remmulti")){ - netmulti(nif, p, 0); + } else if((p = matchtoken(buf, "addmulti")) != 0){ + netmulti(nif, f, p, 1); + } else if((p = matchtoken(buf, "remmulti")) != 0){ + netmulti(nif, f, p, 0); } qunlock(nif); return n; @@ -273,6 +273,7 @@ netifclose(Netif *nif, Chan *c) { Netfile *f; int t; + Netaddr *ap; if((c->flag & COPEN) == 0) return; @@ -291,6 +292,16 @@ netifclose(Netif *nif, Chan *c) qunlock(nif); f->prom = 0; } + if(f->nmaddr){ + qlock(nif); + t = 0; + for(ap = nif->maddr; ap; ap = ap->next){ + if(f->maddr[t/8] & (1<<(t%8))) + netmulti(nif, f, ap->addr, 0); + } + qunlock(nif); + f->nmaddr = 0; + } if(f->type < 0){ qlock(nif); --(nif->all); @@ -450,40 +461,62 @@ nhgets(void *p) return (a[0]<<8)|(a[1]<<0); } -/* called with nif locked */ +/* + * keep track of multicast addresses + */ static void -netmulti(Netif *nif, char *addr, int add) +netmulti(Netif *nif, Netfile *f, char *addr, int add) { Netaddr **l, *ap; + int i; + uchar hexaddr[Nmaxaddr]; if(nif->multicast == nil) return; + if(strlen(addr) != 2*nif->alen) + return; + l = &nif->maddr; + i = 0; for(ap = *l; ap; ap = *l){ if(strcmp(addr, ap->addr) == 0) break; + i++; l = &ap->next; } if(add){ if(ap == 0){ - ap = smalloc(sizeof(*ap)); + *l = ap = smalloc(sizeof(*ap)); ap->addr = smalloc(strlen(addr)+1); strcpy(ap->addr, addr); - ap->next = nif->maddr; + ap->next = 0; ap->ref = 1; - nif->maddr = ap; } else { ap->ref++; } - if(ap->ref == 1) + if(ap->ref == 1){ + nif->nmaddr++; nif->multicast(nif->arg, addr, 1); + } + if(i < 8*sizeof(f->maddr)){ + if((f->maddr[i/8] & (1<<(i%8))) == 0) + f->nmaddr++; + f->maddr[i/8] |= 1<<(i%8); + } } else { if(ap == 0 || ap->ref == 0) return; ap->ref--; - if(ap->ref == 0) + if(ap->ref == 0){ + nif->nmaddr--; nif->multicast(nif->arg, addr, 0); + } + if(i < 8*sizeof(f->maddr)){ + if((f->maddr[i/8] & (1<<(i%8))) != 0) + f->nmaddr--; + f->maddr[i/8] &= ~(1<<(i%8)); + } } } diff --git a/port/netif.h b/port/netif.h index 8d22fdc4f168fe933431c84dd36a390a46b2687c..f276bd8c23f0ecd41af72ac16a8ac232e35654a5 100644 --- a/port/netif.h +++ b/port/netif.h @@ -37,6 +37,8 @@ struct Netfile int type; /* multiplexor type */ int prom; /* promiscuous mode */ + uchar maddr[8]; /* bitmask of multicast addresses requested */ + int nmaddr; /* number of multicast addresses */ Queue *in; /* input buffer */ }; @@ -69,6 +71,7 @@ struct Netif uchar addr[Nmaxaddr]; uchar bcast[Nmaxaddr]; Netaddr *maddr; /* multicast addresses */ + int nmaddr; /* number of multicast addresses */ int prom; /* number of promiscuous opens */ int all; /* number of -1 multiplexors */