M carrera/devrtc.c => carrera/devrtc.c +122 -17
@@ 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);
}
M ip/devip.c => ip/devip.c +16 -8
@@ 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;
+}
M ip/gre.c => ip/gre.c +7 -5
@@ 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
M ip/icmp.c => ip/icmp.c +9 -2
@@ 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
M ip/il.c => ip/il.c +10 -3
@@ 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
M ip/ip.h => ip/ip.h +2 -1
@@ 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
M ip/tcp.c => ip/tcp.c +15 -7
@@ 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
M ip/udp.c => ip/udp.c +4 -2
@@ 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
M pc/archmp.c => pc/archmp.c +3 -0
@@ 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).
M pc/etherelnk3.c => pc/etherelnk3.c +20 -1
@@ 443,16 443,35 @@ 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)
{
int port, x;
M pc/main.c => pc/main.c +85 -82
@@ 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);
M port/netif.c => port/netif.c +46 -13
@@ 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));
+ }
}
}
M port/netif.h => port/netif.h +3 -0
@@ 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 */