~kris/9p

9hist

9443499037a67210f4c9282c5b89c280413f4799 — David du Colombier 29 years ago 97ad80a
Plan 9 from Bell Labs 1997-04-18
4 files changed, 61 insertions(+), 45 deletions(-)

M pc/devether.c
M pc/ether8390.c
M pc/ether8390.h
M pc/etherelnk3.c
M pc/devether.c => pc/devether.c +1 -3
@@ 398,9 398,7 @@ ethercrc(uchar *p, int len)
	for(i = 0; i < len; i++){
		b = *p++;
		for(j = 0; j < 8; j++){
			crc = (crc>>1);
			if((crc^b) & 1)
				crc ^= POLY;
			crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
			b >>= 1;
		}
	}

M pc/ether8390.c => pc/ether8390.c +59 -41
@@ 604,77 604,95 @@ interrupt(Ureg*, void* arg)
	unlock(ctlr);
}

static uchar allmar[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

static void
setfilter(Ether *ether, Dp8390 *ctlr)
{
	uchar r, cr;
	int i;
	uchar *mar;

	r = Ab;
	mar = 0;
	if(ether->prom){
		r |= Pro|Am;
		mar = allmar;
	} else if(ether->nmaddr){
		r |= Am;
		mar = ctlr->mar;
	}
	if(mar){
		cr = regr(ctlr, Cr) & ~Txp;
		regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
		for(i = 0; i < 8; i++)
			regw(ctlr, Mar0+i, *(mar++));
		regw(ctlr, Cr, cr);
	}
	regw(ctlr, Rcr, r);
}

static void
promiscuous(void *arg, int on)
{
	Ether *ether;
	Dp8390 *ctlr;
	uchar r;

	USED(on);

	ether = arg;
	ctlr = ether->ctlr;

	/*
	 * Set/reset promiscuous mode.
	 */
	r = Ab;
	if(on)
		r |= Pro;
	if(ether->nmaddr)
		r |= Am;
	ilock(ctlr);
	regw(ctlr, Rcr, r);
	setfilter(ether, ctlr);
	iunlock(ctlr);
}

static void
setbit(Dp8390 *ctlr, int bit, int on)
{
	int i, h;

	i = bit/8;
	h = bit%8;
	if(on){
		if(++(ctlr->mref[bit]) == 1)
			ctlr->mar[i] |= 1<<h;
	} else {
		if(--(ctlr->mref[bit]) <= 0){
			ctlr->mref[bit] = 0;
			ctlr->mar[i] &= ~(1<<h);
		}
	}
}

static uchar reverse[64];

static void
multicast(void* arg, uchar *addr, int on)
{
	Ether *ether;
	Dp8390 *ctlr;
	uchar r, cr;
	int i;
	ulong h;

	USED(addr, on);
	USED(on);

	ether = arg;
	ctlr = ether->ctlr;
	if(reverse[1] == 0){
		for(i = 0; i < 64; i++)
			reverse[i] = ((i&1)<<5) | ((i&2)<<3) | ((i&4)<<1)
					| ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5);
	}

	/*
	 *  change filter bits
	 */
	h = ethercrc(addr, 6);
	h = h>>(32-6);
	i = h/8;
	h = h%8;
	ilock(ctlr);
	cr = regr(ctlr, Cr) & ~Txp;
	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));
	r = regr(ctlr, Mar0+i);
	if(on){
		if(++(ctlr->mref[h]) == 1)
			r |= 1<<h;
	} else {
		if(--(ctlr->mref[h]) <= 0){
			ctlr->mref[h] = 0;
			r &= ~(1<<h);
		}
	}	
	regw(ctlr, Mar0+i, r);
	regw(ctlr, Cr, cr);
	iunlock(ctlr);

	/*
	 * Set/reset promiscuous mode.
	 */
	r = Ab;
	if(ether->nmaddr)
		r |= Am;
	if(ether->prom)
		r |= Pro;
	ilock(ctlr);
	regw(ctlr, Rcr, r);
	setbit(ctlr, reverse[h&0x3f], on);
	setfilter(ether, ctlr);
	iunlock(ctlr);
}


M pc/ether8390.h => pc/ether8390.h +1 -0
@@ 20,6 20,7 @@ typedef struct {
	int	txbusy;			/* transmit */
	uchar	tstart;			/* 8390 ring addresses */

	uchar	mar[8];			/* shadow multicast address registers */
	int	mref[64];		/* reference counts for multicast groups */
} Dp8390;


M pc/etherelnk3.c => pc/etherelnk3.c +0 -1
@@ 467,7 467,6 @@ multicast(void* arg, uchar *addr, int on)
	ether = (Ether*)arg;
	port = ether->port;

print("multicast nmaddr == %d\n", ether->nmaddr);
	filter = receiveBroadcast|receiveIndividual;
	if(ether->nmaddr)
		filter |= receiveMulticast;