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

1996/0601/pc/devether.c (diff list | history)

1996/0601/sys/src/9/pc/devether.c:1,2621996/0607/sys/src/9/pc/devether.c:1,276 (short | long | prev | next)
1992/0403    
#include "u.h" 
#include "../port/lib.h" 
#include "mem.h" 
#include "dat.h" 
#include "fns.h" 
#include "io.h" 
1993/1113    
#include "ureg.h" 
#include "../port/error.h" 
#include "../port/netif.h" 
1992/0403    
 
1993/1113    
#include "etherif.h" 
1992/1222    
 
1993/1113    
static Ether *ether[MaxEther]; 
1992/0403    
 
1993/1113    
void 
etherinit(void) 
{ 
} 
1992/1222    
 
1993/1113    
Chan* 
etherattach(char *spec) 
{ 
	ulong ctlrno; 
	char *p; 
	Chan *c; 
1992/0404    
 
1993/1113    
	ctlrno = 0; 
	if(spec && *spec){ 
		ctlrno = strtoul(spec, &p, 0); 
		if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) 
			error(Ebadarg); 
	} 
	if(ether[ctlrno] == 0) 
		error(Enodev); 
1992/0403    
 
1993/1113    
	c = devattach('l', spec); 
	c->dev = ctlrno; 
	if(ether[ctlrno]->attach) 
		(*ether[ctlrno]->attach)(ether[ctlrno]); 
	return c; 
} 
1992/0922    
 
1992/0425    
Chan* 
1992/0424    
etherclone(Chan *c, Chan *nc) 
1992/0411    
{ 
1992/0424    
	return devclone(c, nc); 
} 
1992/0411    
 
1992/0424    
int 
etherwalk(Chan *c, char *name) 
{ 
1993/1113    
	return netifwalk(ether[c->dev], c, name); 
1992/0424    
} 
 
void 
etherstat(Chan *c, char *dp) 
{ 
1993/1113    
	netifstat(ether[c->dev], c, dp); 
1992/0424    
} 
 
Chan* 
etheropen(Chan *c, int omode) 
{ 
1993/1113    
	return netifopen(ether[c->dev], c, omode); 
1992/0424    
} 
 
void 
1995/0726    
ethercreate(Chan*, char*, int, ulong) 
1992/0424    
{ 
} 
 
void 
etherclose(Chan *c) 
{ 
1993/1113    
	netifclose(ether[c->dev], c); 
1992/0424    
} 
 
long 
1993/1113    
etherread(Chan *c, void *buf, long n, ulong offset) 
1992/0424    
{ 
1993/1113    
	return netifread(ether[c->dev], c, buf, n, offset); 
1996/0607    
	Ether *ctlr; 
 
	ctlr = ether[c->dev]; 
	if((c->qid.path & CHDIR) == 0 && ctlr->ifstat){ 
		/* 
		 * With some controllers it is necessary to reach 
		 * into the chip to extract statistics. 
		 */ 
		if(NETTYPE(c->qid.path) == Nifstatqid) 
			return (*ctlr->ifstat)(ctlr, buf, n, offset); 
		else if(NETTYPE(c->qid.path) == Nstatqid) 
			(*ctlr->ifstat)(ctlr, buf, 0, offset); 
	} 
 
	return netifread(ctlr, c, buf, n, offset); 
1992/0411    
} 
 
1995/0108    
Block* 
etherbread(Chan *c, long n, ulong offset) 
{ 
	return devbread(c, n, offset); 
} 
 
1992/0424    
void 
1995/0822    
etherremove(Chan*) 
1992/0424    
{ 
} 
 
void 
etherwstat(Chan *c, char *dp) 
{ 
1993/1113    
	netifwstat(ether[c->dev], c, dp); 
1992/0424    
} 
 
1993/1120    
void 
1995/0721    
etherrloop(Ether *ctlr, Etherpkt *pkt, long len) 
1993/1120    
{ 
1995/0713    
	Block *bp; 
1993/1120    
	ushort type; 
1995/0801    
	int i, n; 
1993/1120    
	Netfile *f, **fp, **ep; 
 
	type = (pkt->type[0]<<8)|pkt->type[1]; 
	ep = &ctlr->f[Ntypes]; 
	for(fp = ctlr->f; fp < ep; fp++){ 
1995/0721    
		if((f = *fp) && (f->type == type || f->type < 0)){ 
1995/0713    
			if(f->type > -2){ 
				if(qproduce(f->in, pkt->d, len) < 0) 
					ctlr->soverflows++; 
			} else { 
				if(qwindow(f->in) <= 0) 
					continue; 
1995/0801    
				if(len > 64) 
					n = 64; 
				else 
					n = len; 
				bp = iallocb(n); 
1995/0713    
				if(bp == 0) 
					continue; 
1995/0801    
				memmove(bp->wp, pkt->d, n); 
1995/0713    
				i = TK2MS(m->ticks); 
1995/0731    
				bp->wp[58] = len>>8; 
				bp->wp[59] = len; 
1995/0713    
				bp->wp[60] = i>>24; 
				bp->wp[61] = i>>16; 
				bp->wp[62] = i>>8; 
				bp->wp[63] = i; 
				bp->wp += 64; 
				qpass(f->in, bp); 
			} 
		} 
1993/1120    
	} 
} 
 
static int 
etherwloop(Ether *ctlr, Etherpkt *pkt, long len) 
{ 
1995/0721    
	int s, different; 
1993/1120    
 
1995/0721    
	different = memcmp(pkt->d, ctlr->ea, sizeof(pkt->d)); 
1995/1004    
	if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)) && ctlr->prom == 0) 
1993/1120    
		return 0; 
 
	s = splhi(); 
1995/0721    
	etherrloop(ctlr, pkt, len); 
1993/1120    
	splx(s); 
1994/0702    
 
1995/0721    
	return different == 0; 
1993/1120    
} 
 
1993/1113    
long 
1995/0822    
etherwrite(Chan *c, void *buf, long n, ulong) 
1992/0407    
{ 
1993/1113    
	Ether *ctlr; 
1992/0407    
 
1993/1113    
	if(n > ETHERMAXTU) 
		error(Ebadarg); 
	ctlr = ether[c->dev]; 
1992/0407    
 
1993/1113    
	if(NETTYPE(c->qid.path) != Ndataqid) 
		return netifwrite(ctlr, c, buf, n); 
1992/0403    
 
1993/1120    
	if(etherwloop(ctlr, buf, n)) 
		return n; 
 
1992/1222    
	qlock(&ctlr->tlock); 
1992/0403    
	if(waserror()){ 
1992/1222    
		qunlock(&ctlr->tlock); 
1992/0403    
		nexterror(); 
	} 
1993/1113    
	n = (*ctlr->write)(ctlr, buf, n); 
	qunlock(&ctlr->tlock); 
1995/0822    
	poperror(); 
1992/0403    
 
1993/1113    
	return n; 
1995/0108    
} 
 
long 
etherbwrite(Chan *c, Block *bp, ulong offset) 
{ 
	return devbwrite(c, bp, offset); 
1992/0403    
} 
 
1993/1113    
static struct { 
	char	*type; 
	int	(*reset)(Ether*); 
1993/1119    
} cards[MaxEther+1]; 
1992/0403    
 
1993/1113    
void 
addethercard(char *t, int (*r)(Ether*)) 
1992/0403    
{ 
1993/1113    
	static int ncard; 
1992/0403    
 
1993/1119    
	if(ncard == MaxEther) 
1993/1113    
		panic("too many ether cards"); 
	cards[ncard].type = t; 
	cards[ncard].reset = r; 
	ncard++; 
1992/0403    
} 
 
1992/0424    
void 
etherreset(void) 
{ 
1993/1113    
	Ether *ctlr; 
	int i, n, ctlrno; 
1992/0410    
 
1993/1113    
	for(ctlr = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ 
		if(ctlr == 0) 
			ctlr = malloc(sizeof(Ether)); 
		memset(ctlr, 0, sizeof(Ether)); 
1996/0601    
		ctlr->ctlrno = ctlrno; 
		ctlr->mbps = 10; 
1993/1113    
		if(isaconfig("ether", ctlrno, ctlr) == 0) 
			continue; 
		for(n = 0; cards[n].type; n++){ 
			if(strcmp(cards[n].type, ctlr->type)) 
				continue; 
			if((*cards[n].reset)(ctlr)) 
				break; 
1992/1222    
 
			/* 
			 * IRQ2 doesn't really exist, it's used to gang the interrupt 
			 * controllers together. A device set to IRQ2 will appear on 
			 * the second interrupt controller as IRQ9. 
			 */ 
1993/1113    
			if(ctlr->irq == 2) 
				ctlr->irq = 9; 
1994/0713    
			setvec(Int0vec+ctlr->irq, ctlr->interrupt, ctlr); 
1993/0212    
 
1996/0601    
			print("ether%d: %s: %dMbps port 0x%luX irq %d", 
1996/0607    
			print("ether#%d: %s: %dMbps port 0x%luX irq %d", 
1996/0601    
				ctlrno, ctlr->type, ctlr->mbps, ctlr->port, ctlr->irq); 
1995/0504    
			if(ctlr->mem) 
1995/0513    
				print(" addr 0x%luX", ctlr->mem & ~KZERO); 
1995/0505    
			if(ctlr->size) 
1995/0513    
				print(" size 0x%luX", ctlr->size); 
1996/0601    
			print(": "); 
1993/1113    
			for(i = 0; i < sizeof(ctlr->ea); i++) 
1996/0601    
				print("%2.2uX", ctlr->ea[i]); 
1993/1113    
			print("\n"); 
1993/0212    
 
1996/0601    
			if(ctlr->mbps == 100) 
				netifinit(ctlr, "ether", Ntypes, 100*1024); 
1996/0607    
				netifinit(ctlr, "ether", Ntypes, 128*1024); 
1996/0601    
			else 
				netifinit(ctlr, "ether", Ntypes, 32*1024); 
1993/1113    
			ctlr->alen = Eaddrlen; 
			memmove(ctlr->addr, ctlr->ea, sizeof(ctlr->ea)); 
			memmove(ctlr->bcast, etherbcast, sizeof(etherbcast)); 
1992/0410    
 
1993/1113    
			ether[ctlrno] = ctlr; 
			ctlr = 0; 
1993/1120    
			break; 
1993/1113    
		} 
1992/0403    
	} 
1993/1113    
	if(ctlr) 
		free(ctlr); 
1992/0403    
} 


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