plan 9 kernel history: overview | file list | diff list

1992/0410/pc/devether.c (diff list | history)

1992/0409/sys/src/9/pc/devether.c:18,391992/0410/sys/src/9/pc/devether.c:18,44 (short | long | prev | next)
1992/0403    
#include "io.h" 
#include "devtab.h" 
 
1992/0410    
static int debug; 
 
1992/0403    
typedef struct Ctlr Ctlr; 
typedef struct Pktype Pktype; 
1992/0410    
typedef struct Type Type; 
1992/0404    
typedef struct Ring Ring; 
1992/0403    
 
enum { 
	IObase		= 0x360, 
1992/0404    
	RAMbase		= 0xC8000, 
1992/0410    
	RAMbase		= 0xD0000, 
1992/0404    
	RAMsize		= 8*1024, 
	BUFsize		= 256, 
1992/0403    
 
1992/0410    
	RINGbase	= 6,		/* gak */ 
	RINGsize	= 32,		/* gak */ 
 
1992/0404    
	Nctlr		= 1, 
	NPktype		= 9,		/* types/interface */ 
1992/0410    
	NType		= 9,		/* types/interface */ 
1992/0404    
}; 
 
1992/0408    
#define NEXT(x, l)	((((x)+1)%(l)) == 0 ? 6: (((x)+1)%(l))) 
#define PREV(x, l)	(((x)-1) == 5 ? (l-1): ((x)-1)) 
1992/0410    
#define NEXT(x, l)	((((x)+1)%(l)) == 0 ? RINGbase: (((x)+1)%(l))) 
#define PREV(x, l)	(((x)-1) < RINGbase ? (l-1): ((x)-1)) 
1992/0408    
 
1992/0404    
/* 
 * register offsets from IObase 
1992/0409/sys/src/9/pc/devether.c:77,831992/0410/sys/src/9/pc/devether.c:82,87
1992/0404    
	Rxe		= 0x04,		/*	receive error */ 
	Txe		= 0x08,		/*	transmit error */ 
	Ovw		= 0x10,		/*	overwrite warning */ 
	Rst		= 0x80,		/*	reset status */ 
}; 
1992/0403    
 
1992/0404    
struct Ring { 
1992/0409/sys/src/9/pc/devether.c:91,971992/0410/sys/src/9/pc/devether.c:95,101
1992/0403    
/* 
 * one per ethernet packet type 
 */ 
struct Pktype { 
1992/0410    
struct Type { 
1992/0403    
	QLock; 
	int	type;			/* ethernet type */ 
	int	prom;			/* promiscuous mode */ 
1992/0409/sys/src/9/pc/devether.c:119,1251992/0410/sys/src/9/pc/devether.c:123,129
1992/0403    
 
	int	iobase;			/* I/O base address */ 
 
	Pktype	pktype[NPktype]; 
1992/0410    
	Type	type[NType]; 
1992/0403    
	uchar	ea[6]; 
	uchar	ba[6]; 
 
1992/0409/sys/src/9/pc/devether.c:127,1331992/0410/sys/src/9/pc/devether.c:131,137
1992/0403    
	uchar	kproc;			/* true if kproc started */ 
	char	name[NAMELEN];		/* name of kproc */ 
	Network	net; 
	Netprot	prot[NPktype]; 
1992/0410    
	Netprot	prot[NType]; 
1992/0403    
 
	int	inpackets; 
	int	outpackets; 
1992/0409/sys/src/9/pc/devether.c:152,1681992/0410/sys/src/9/pc/devether.c:156,172
1992/0403    
{ 
1992/0406    
	Ctlr *cp; 
1992/0403    
	int len, n; 
1992/0406    
	Pktype *pp; 
1992/0410    
	Type *tp; 
1992/0403    
	Etherpkt *p; 
	Block *nbp; 
 
1992/0406    
	cp = ((Pktype *)q->ptr)->ctlr; 
1992/0410    
	cp = ((Type *)q->ptr)->ctlr; 
1992/0403    
	if(bp->type == M_CTL){ 
1992/0406    
		pp = q->ptr; 
1992/0410    
		tp = q->ptr; 
1992/0403    
		if(streamparse("connect", bp)) 
1992/0406    
			pp->type = strtol((char *)bp->rptr, 0, 0); 
1992/0410    
			tp->type = strtol((char *)bp->rptr, 0, 0); 
1992/0403    
		else if(streamparse("promiscuous", bp)) { 
1992/0406    
			pp->prom = 1; 
1992/0410    
			tp->prom = 1; 
1992/0406    
			qlock(cp); 
			cp->prom++; 
			if(cp->prom == 1) 
1992/0409/sys/src/9/pc/devether.c:264,2791992/0410/sys/src/9/pc/devether.c:268,283
1992/0403    
etherstopen(Queue *q, Stream *s) 
{ 
1992/0404    
	Ctlr *cp = &ctlr[0]; 
	Pktype *pp; 
1992/0410    
	Type *tp; 
1992/0403    
 
1992/0404    
	pp = &cp->pktype[s->id]; 
	qlock(pp); 
	RD(q)->ptr = WR(q)->ptr = pp; 
	pp->type = 0; 
	pp->q = RD(q); 
	pp->inuse = 1; 
	pp->ctlr = cp; 
	qunlock(pp); 
1992/0410    
	tp = &cp->type[s->id]; 
	qlock(tp); 
	RD(q)->ptr = WR(q)->ptr = tp; 
	tp->type = 0; 
	tp->q = RD(q); 
	tp->inuse = 1; 
	tp->ctlr = cp; 
	qunlock(tp); 
1992/0403    
} 
 
/* 
1992/0409/sys/src/9/pc/devether.c:285,3071992/0410/sys/src/9/pc/devether.c:289,311
1992/0403    
static void 
etherstclose(Queue *q) 
{ 
1992/0404    
	Pktype *pp; 
1992/0410    
	Type *tp; 
1992/0403    
 
1992/0404    
	pp = (Pktype *)(q->ptr); 
	if(pp->prom){ 
		qlock(pp->ctlr); 
		pp->ctlr->prom--; 
1992/0405    
		if(pp->ctlr->prom == 0) 
1992/0404    
			outb(pp->ctlr->iobase+Rcr, 0x04);/* AB */ 
		qunlock(pp->ctlr); 
1992/0410    
	tp = (Type *)(q->ptr); 
	if(tp->prom){ 
		qlock(tp->ctlr); 
		tp->ctlr->prom--; 
		if(tp->ctlr->prom == 0) 
			outb(tp->ctlr->iobase+Rcr, 0x04);/* AB */ 
		qunlock(tp->ctlr); 
1992/0403    
	} 
1992/0404    
	qlock(pp); 
	pp->type = 0; 
	pp->q = 0; 
	pp->prom = 0; 
	pp->inuse = 0; 
	netdisown(&pp->ctlr->net, pp - pp->ctlr->pktype); 
	qunlock(pp); 
1992/0410    
	qlock(tp); 
	tp->type = 0; 
	tp->q = 0; 
	tp->prom = 0; 
	tp->inuse = 0; 
	netdisown(&tp->ctlr->net, tp - tp->ctlr->type); 
	qunlock(tp); 
1992/0403    
} 
 
static Qinfo info = { 
1992/0409/sys/src/9/pc/devether.c:316,3331992/0410/sys/src/9/pc/devether.c:320,337
1992/0404    
clonecon(Chan *c) 
1992/0403    
{ 
1992/0404    
	Ctlr *cp = &ctlr[0]; 
	Pktype *pp; 
1992/0410    
	Type *tp; 
1992/0403    
 
1992/0404    
	for(pp = cp->pktype; pp < &cp->pktype[NPktype]; pp++){ 
		qlock(pp); 
		if(pp->inuse || pp->q){ 
			qunlock(pp); 
1992/0410    
	for(tp = cp->type; tp < &cp->type[NType]; tp++){ 
		qlock(tp); 
		if(tp->inuse || tp->q){ 
			qunlock(tp); 
1992/0403    
			continue; 
		} 
1992/0404    
		pp->inuse = 1; 
		netown(&cp->net, pp - cp->pktype, u->p->user, 0); 
		qunlock(pp); 
		return pp - cp->pktype; 
1992/0410    
		tp->inuse = 1; 
		netown(&cp->net, tp - cp->type, u->p->user, 0); 
		qunlock(tp); 
		return tp - cp->type; 
1992/0403    
	} 
	exhausted("ether channels"); 
} 
1992/0409/sys/src/9/pc/devether.c:349,3581992/0410/sys/src/9/pc/devether.c:353,362
1992/0403    
typefill(Chan *c, char *p, int n) 
{ 
	char buf[16]; 
1992/0404    
	Pktype *pp; 
1992/0410    
	Type *tp; 
1992/0403    
 
1992/0404    
	pp = &ctlr[0].pktype[STREAMID(c->qid.path)]; 
	sprint(buf, "%d", pp->type); 
1992/0410    
	tp = &ctlr[0].type[STREAMID(c->qid.path)]; 
	sprint(buf, "%d", tp->type); 
1992/0403    
	strncpy(p, buf, n); 
} 
 
1992/0409/sys/src/9/pc/devether.c:360,3661992/0410/sys/src/9/pc/devether.c:364,370
1992/0403    
intr(Ureg *ur) 
{ 
1992/0404    
	Ctlr *cp = &ctlr[0]; 
	uchar isr, curr; 
1992/0410    
	uchar isr, bnry, curr; 
1992/0404    
 
	while(isr = inb(cp->iobase+Isr)){ 
		outb(cp->iobase+Isr, isr); 
1992/0409/sys/src/9/pc/devether.c:369,3751992/0410/sys/src/9/pc/devether.c:373,379
1992/0404    
		if(isr & Rxe){ 
			cp->frames += inb(cp->iobase+Cntr0); 
			cp->crcs += inb(cp->iobase+Cntr1); 
			cp->buffs += inb(cp->iobase+Cntr2); 
1992/0410    
			cp->overflows += inb(cp->iobase+Cntr2); 
1992/0404    
		} 
		if(isr & Ptx) 
			cp->outpackets++; 
1992/0409/sys/src/9/pc/devether.c:377,3841992/0410/sys/src/9/pc/devether.c:381,391
1992/0407    
			cp->xbusy = 0; 
			wakeup(&cp->xr); 
1992/0404    
		} 
1992/0409    
		if(isr & Ovw) 
1992/0408    
			cp->overflows++; 
1992/0410    
		if(isr & Ovw){ 
			bnry = inb(cp->iobase+Bnry); 
			outb(cp->iobase+bnry, bnry); 
			cp->buffs++; 
		} 
1992/0404    
		/* 
		 * we have received packets. 
		 * this is the only place, other than the init code, 
1992/0409/sys/src/9/pc/devether.c:386,3971992/0410/sys/src/9/pc/devether.c:393,404
1992/0405    
		 * we must be sure to reset it back to Page0 in case 
1992/0404    
		 * we interrupted some other part of this driver. 
		 */ 
		if(isr & (Ovw|Prx)){ 
1992/0410    
		if(isr & (Rxe|Prx)){ 
1992/0404    
			outb(cp->iobase+Cr, 0x62);	/* Page1, RD2|STA */ 
			cp->curr = inb(cp->iobase+Curr); 
1992/0409    
if(cp->curr == 0) 
    print("C0: b%d i%ux\n", cp->bnry, isr); 
1992/0404    
			outb(cp->iobase+Cr, 0x22);	/* Page0, RD2|STA */ 
1992/0410    
if(debug) 
    print("I%d/%d/%d|", isr, cp->curr, cp->bnry); 
1992/0404    
			wakeup(&cp->rr); 
		} 
	} 
1992/0409/sys/src/9/pc/devether.c:414,4241992/0410/sys/src/9/pc/devether.c:421,431
1992/0404    
	outb(cp->iobase+Rbcr1, 0); 
	outb(cp->iobase+Rcr, 0x04);		/* AB */ 
	outb(cp->iobase+Tcr, 0x20);		/* LB0 */ 
	cp->bnry = 6; 
1992/0410    
	cp->bnry = RINGbase; 
1992/0408    
	outb(cp->iobase+Bnry, cp->bnry); 
1992/0407    
	cp->ring = (Ring*)(KZERO|RAMbase); 
1992/0404    
	outb(cp->iobase+Pstart, 6);		/* 6*256 */ 
	outb(cp->iobase+Pstop, 32);		/* 8*1024/256 */ 
1992/0410    
	outb(cp->iobase+Pstart, RINGbase); 
	outb(cp->iobase+Pstop, RINGsize); 
1992/0404    
	outb(cp->iobase+Isr, 0xFF); 
	outb(cp->iobase+Imr, 0x1F);		/* OVWE|TXEE|RXEE|PTXE|PRXE */ 
1992/0403    
 
1992/0409/sys/src/9/pc/devether.c:443,4511992/0410/sys/src/9/pc/devether.c:450,462
1992/0404    
	cp->iobase = IObase; 
1992/0409    
	msr = 0x40|inb(cp->iobase); 
	outb(cp->iobase, msr); 
1992/0410    
msr=0x40|inb(cp->iobase+0x05); 
outb(cp->iobase+0x05, msr); 
1992/0409    
for(i = 0; i < 0x10; i++) 
    print("#%2.2ux ", inb(cp->iobase+i)); 
print("\n"); 
1992/0410    
msr=0x40|inb(cp->iobase+0x05); 
outb(cp->iobase+0x05, msr); 
1992/0404    
	for(i = 0; i < sizeof(cp->ea); i++) 
		cp->ea[i] = inb(cp->iobase+EA+i); 
1992/0408    
	init(cp); 
1992/0409/sys/src/9/pc/devether.c:453,4591992/0410/sys/src/9/pc/devether.c:464,470
1992/0404    
	memset(cp->ba, 0xFF, sizeof(cp->ba)); 
1992/0403    
 
1992/0404    
	cp->net.name = "ether"; 
	cp->net.nconv = NPktype; 
1992/0410    
	cp->net.nconv = NType; 
1992/0404    
	cp->net.devp = &info; 
	cp->net.protop = 0; 
	cp->net.listen = 0; 
1992/0409/sys/src/9/pc/devether.c:467,4901992/0410/sys/src/9/pc/devether.c:478,503
1992/0403    
} 
 
1992/0404    
static void 
etherup(Ctlr *cp, Etherpkt *p, int len) 
1992/0410    
etherup(Ctlr *cp, uchar *d0, int len0, uchar *d1, int len1) 
1992/0404    
{ 
1992/0410    
	Etherpkt *p; 
1992/0404    
	Block *bp; 
	Pktype *pp; 
1992/0410    
	Type *tp; 
1992/0404    
	int t; 
 
	t = (p->type[0]<<8) | p->type[1]; 
	for(pp = &cp->pktype[0]; pp < &cp->pktype[NPktype]; pp++){ 
1992/0410    
	p = (Etherpkt*)d0; 
	t = (p->type[0]<<8)|p->type[1]; 
	for(tp = &cp->type[0]; tp < &cp->type[NType]; tp++){ 
1992/0404    
		/* 
		 *  check before locking just to save a lock 
		 */ 
		if(pp->q == 0 || (t != pp->type && pp->type != -1)) 
1992/0410    
		if(tp->q == 0 || (t != tp->type && tp->type != -1)) 
1992/0404    
			continue; 
 
		/* 
		 *  only a trace channel gets packets destined for other machines 
		 */ 
		if(pp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d))) 
1992/0410    
		if(tp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d))) 
1992/0404    
			continue; 
 
		/* 
1992/0409/sys/src/9/pc/devether.c:491,5111992/0410/sys/src/9/pc/devether.c:504,526
1992/0404    
		 *  check after locking to make sure things didn't 
		 *  change under foot 
		 */ 
		if(canqlock(pp) == 0) 
1992/0410    
		if(canqlock(tp) == 0) 
1992/0404    
			continue; 
		if(pp->q == 0 || pp->q->next->len > Streamhi || (t != pp->type && pp->type != -1)){ 
			qunlock(pp); 
1992/0410    
		if(tp->q == 0 || tp->q->next->len > Streamhi || (t != tp->type && tp->type != -1)){ 
			qunlock(tp); 
1992/0404    
			continue; 
		} 
		if(waserror() == 0){ 
			bp = allocb(len); 
			memmove(bp->rptr, (uchar *)p, len); 
			bp->wptr += len; 
1992/0410    
			bp = allocb(len0+len1); 
			memmove(bp->rptr, d0, len0); 
			if(len1) 
				memmove(bp->rptr+len0, d1, len1); 
			bp->wptr += len0+len1; 
1992/0404    
			bp->flags |= S_DELIM; 
			PUTNEXT(pp->q, bp); 
1992/0410    
			PUTNEXT(tp->q, bp); 
1992/0404    
		} 
		poperror(); 
		qunlock(pp); 
1992/0410    
		qunlock(tp); 
1992/0404    
	} 
} 
 
1992/0409/sys/src/9/pc/devether.c:526,5321992/0410/sys/src/9/pc/devether.c:541,547
1992/0403    
{ 
1992/0404    
	Ctlr *cp = arg; 
1992/0403    
 
1992/0408    
	return NEXT(cp->bnry, 32) != cp->curr; 
1992/0410    
	return NEXT(cp->bnry, RINGsize) != cp->curr; 
1992/0403    
} 
 
static void 
1992/0409/sys/src/9/pc/devether.c:536,5411992/0410/sys/src/9/pc/devether.c:551,557
1992/0404    
	Block *bp; 
	uchar bnry, curr; 
	Ring *rp; 
1992/0410    
	int len0, len1; 
1992/0403    
 
	if(waserror()){ 
1992/0404    
		print("%s noted\n", cp->name); 
1992/0409/sys/src/9/pc/devether.c:551,5571992/0410/sys/src/9/pc/devether.c:567,573
1992/0406    
		 */ 
1992/0404    
		while(bp = getq(&cp->rq)){ 
			cp->inpackets++; 
			etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); 
1992/0410    
			etherup(cp, bp->rptr, BLEN(bp), 0, 0); 
1992/0404    
			freeb(bp); 
		} 
1992/0408    
 
1992/0409/sys/src/9/pc/devether.c:558,5701992/0410/sys/src/9/pc/devether.c:574,599
1992/0406    
		/* 
		 * process any received packets 
		 */ 
1992/0408    
		bnry = NEXT(cp->bnry, 32); 
1992/0410    
		bnry = NEXT(cp->bnry, RINGsize); 
1992/0408    
		while(bnry != cp->curr){ 
			rp = &cp->ring[bnry]; 
1992/0406    
			cp->inpackets++; 
1992/0407    
			etherup(cp, (Etherpkt*)rp->data, ((rp->len1<<8)+rp->len0)-4); 
1992/0410    
			len0 = ((rp->len1<<8)+rp->len0)-4; 
			len1 = 0; 
 
			if(rp->data+len0 >= (uchar*)&cp->ring[RINGsize]){ 
				len1 = rp->data+len0 - (uchar*)&cp->ring[RINGsize]; 
				len0 = (uchar*)&cp->ring[RINGsize] - rp->data; 
			} 
 
			etherup(cp, rp->data, len0, (uchar*)&cp->ring[RINGbase], len1); 
 
 
 
if(debug) 
    print("K%d/%d/%d|", bnry, rp->next, PREV(rp->next, RINGsize)); 
1992/0408    
			bnry = rp->next; 
			cp->bnry = PREV(bnry, 32); 
1992/0410    
			cp->bnry = PREV(bnry, RINGsize); 
1992/0407    
			outb(cp->iobase+Bnry, cp->bnry); 
1992/0406    
		} 
1992/0403    
	} 
1992/0409/sys/src/9/pc/devether.c:661,6661992/0410/sys/src/9/pc/devether.c:690,696
1992/0409    
	int s; 
 
	s = splhi(); 
1992/0410    
debug++; 
1992/0409    
	bnry = inb(cp->iobase+Bnry); 
	outb(cp->iobase+Cr, 0x62);			/* Page1, RD2|STA */ 
	curr = inb(cp->iobase+Curr); 
1992/0409/sys/src/9/pc/devether.c:668,6741992/0410/sys/src/9/pc/devether.c:698,704
1992/0409    
	isr = inb(cp->iobase+Isr); 
	print("b%d c%d x%d B%d C%d I%ux", 
	    cp->bnry, cp->curr, cp->xbusy, bnry, curr, isr); 
	print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->opackets, 
1992/0410    
	print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->outpackets, 
1992/0409    
	    cp->crcs, cp->oerrs, cp->frames, cp->overflows, cp->buffs); 
	splx(s); 
1992/0403    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)