~kris/9p

9hist

ace7c98584268f279d05192954098b0a92bc0fb2 — David du Colombier 29 years ago 5d2bed4
Plan 9 from Bell Labs 1997-04-03
13 files changed, 342 insertions(+), 141 deletions(-)

M carrera/devrtc.c
M ip/devip.c
M ip/gre.c
M ip/icmp.c
M ip/il.c
M ip/ip.h
M ip/tcp.c
M ip/udp.c
M pc/archmp.c
M pc/etherelnk3.c
M pc/main.c
M port/netif.c
M port/netif.h
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 */