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

1993/0906/carrera/devether.c (diff list | history)

1993/0905/sys/src/9/carrera/devether.c:16,241993/0906/sys/src/9/carrera/devether.c:16,34 (short | long | prev | next)
1993/0904    
#define SONICADDR	((Sonic*)Sonicbase) 
1993/0903    
 
1993/0904    
#define RD(rn)		(delay(1), *(ulong*)((ulong)&SONICADDR->rn^4)) 
#define WR(rn, v)	(delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = v) 
1993/0905    
#define ISquad(s)	if((ulong)s & 0x7) panic("sonoc: Quad alignment"); 
1993/0906    
#define WR(rn, v)	(delay(1), *(ulong*)((ulong)&SONICADDR->rn^4) = (v)) 
#define ISquad(s)	if((ulong)s & 0x7) panic("sonic: Quad alignment"); 
1993/0903    
 
1993/0906    
typedef struct Pbuf Pbuf; 
struct Pbuf 
{ 
	uchar	d[6]; 
	uchar	s[6]; 
	uchar	type[2]; 
	uchar	data[1500]; 
	uchar	crc[4]; 
}; 
 
1993/0904    
typedef struct 
{ 
	ulong	cr;		/* command */ 
1993/0905/sys/src/9/carrera/devether.c:32,381993/0906/sys/src/9/carrera/devether.c:42,51
1993/0904    
	ulong	pad0x08[5];	/*  */ 
	ulong	urda;		/* upper receive descriptor address */ 
	ulong	crda;		/* current receive descriptor address */ 
	ulong	pad0x0F[4];	/*  */ 
1993/0906    
	ulong	crba0;		/* DO NOT WRITE THESE */ 
	ulong	crba1; 
	ulong	rbwc0; 
	ulong	rbwc1; 
1993/0904    
	ulong	eobc;		/* end of buffer word count */ 
	ulong	urra;		/* upper receive resource address */ 
	ulong	rsa;		/* resource start address */ 
1993/0905/sys/src/9/carrera/devether.c:111,1161993/0906/sys/src/9/carrera/devether.c:124,132
1993/0904    
	Hbl	= 0x2000,	/* CD heartbeat lost */ 
	Br	= 0x4000,	/* bus retry occurred */ 
	AllIntr	= 0x7771,	/* all of the above */ 
1993/0906    
 
	Rxbuf	= sizeof(Pbuf)+4, 
	Txbuf	= sizeof(Pbuf), 
1993/0903    
}; 
 
1993/0904    
/* 
1993/0905/sys/src/9/carrera/devether.c:118,1311993/0906/sys/src/9/carrera/devether.c:134,147
1993/0904    
 */ 
typedef struct 
{ 
	uchar	pad0[2]; 
	ushort	ptr0;		/* buffer pointer in the RRA */ 
	uchar	pad1[2]; 
	ushort	ptr1; 
	uchar	pad2[2]; 
	ushort	wc0;		/* buffer word count in the RRA */ 
	uchar	pad3[2]; 
	ushort	wc1; 
1993/0906    
	ushort	pad1; 
	ushort		ptr1;		/* buffer pointer in the RRA */ 
	ushort  pad2; 
	ushort		ptr0; 
	ushort  pad3; 
	ushort		wc1;		/* buffer word count in the RRA */ 
	ushort  pad4; 
	ushort		wc0; 
1993/0904    
} RXrsc; 
1993/0903    
 
/* 
1993/0905/sys/src/9/carrera/devether.c:133,1521993/0906/sys/src/9/carrera/devether.c:149,169
1993/0903    
 */ 
typedef struct 
{ 
1993/0904    
	uchar	pad0[2]; 
	ushort	status;		/* receive status */ 
	uchar	pad1[2]; 
	ushort	count;		/* packet byte count */ 
	uchar	pad2[2]; 
	ushort	ptr0;		/* buffer pointer */ 
	uchar	pad3[2]; 
	ushort	ptr1; 
	uchar	pad4[2]; 
	ushort	seqno;		/*  */ 
	uchar	pad5[2]; 
	ushort	link;		/* descriptor link and EOL */ 
	uchar	pad6[2]; 
	ushort	owner;		/* in use */ 
1993/0906    
	ushort	pad0; 
		ushort	count;		/* packet byte count */ 
	ushort	pad1; 
		ushort	status;		/* receive status */ 
	ushort	pad2; 
		ushort	ptr1;		/* buffer pointer */ 
	ushort	pad3; 
		ushort	ptr0; 
	ushort  pad4; 
		ushort	link;		/* descriptor link and EOL */ 
	ushort	pad5; 
		ushort	seqno;		/*  */ 
	ulong	pad6; 
	ushort  pad7; 
		ushort	owner;		/* in use */ 
1993/0904    
} RXpkt; 
1993/0903    
 
1993/0904    
/* 
1993/0905/sys/src/9/carrera/devether.c:154,1751993/0906/sys/src/9/carrera/devether.c:171,192
1993/0904    
 */ 
typedef struct 
{ 
	uchar	pad0[2]; 
	ushort	status;		/* transmit status */ 
	uchar	pad1[2]; 
	ushort	config;		/*  */ 
	uchar	pad2[2]; 
	ushort	size;		/* byte count of entire packet */ 
	uchar	pad3[2]; 
	ushort	count;		/* fragment count */ 
	uchar	pad4[2]; 
	ushort	ptr0;		/* packet pointer */ 
	uchar	pad5[2]; 
	ushort	ptr1; 
	uchar	pad6[2]; 
	ushort	fsize;		/* fragment size */ 
	uchar	pad7[2]; 
	ushort	link;		/* descriptor link */ 
1993/0906    
	ushort	pad1; 
		ushort	config;		/*  */ 
	ushort	pad0; 
		ushort	status;		/* transmit status */ 
	ushort	pad3; 
		ushort	count;		/* fragment count */ 
	ushort	pad2; 
		ushort	size;		/* byte count of entire packet */ 
	ushort	pad5; 
		ushort	ptr1; 
	ushort	pad4; 
		ushort	ptr0;		/* packet pointer */ 
	ushort	pad7; 
		ushort	link;		/* descriptor link */ 
	ushort	pad6; 
		ushort	fsize;		/* fragment size */ 
1993/0904    
} TXpkt; 
 
enum{ 
1993/0905/sys/src/9/carrera/devether.c:186,2011993/0906/sys/src/9/carrera/devether.c:203,219
1993/0904    
 */ 
1993/0905    
typedef struct 
{ 
1993/0904    
	uchar	pad0[2]; 
	ushort	cep;		/* CAM entry pointer */ 
	uchar	pad1[2]; 
	ushort	cap0;		/* CAM address port 0 */ 
	uchar	pad2[2]; 
	ushort	cap1;		/* CAM address port 1 */ 
	uchar	pad3[2]; 
	ushort	cap2;		/* CAM address port 2 */ 
	uchar	pad4[2]; 
	ushort	ce;		/* CAM enable */ 
1993/0906    
	ushort	pad0; 
		ushort	cap0;		/* CAM address port 0 */ 
	ushort	pad1; 
		ushort	cep;		/* CAM entry pointer */ 
	ushort	pad2; 
		ushort	cap2;		/* CAM address port 2 */ 
	ushort	pad3; 
		ushort	cap1;		/* CAM address port 1 */ 
	ulong	pad4; 
	ushort	pad5; 
		ushort	ce;		/* CAM enable */ 
1993/0904    
} Cam; 
 
typedef struct Ether Ether; 
1993/0905/sys/src/9/carrera/devether.c:204,2111993/0906/sys/src/9/carrera/devether.c:222,227
1993/0903    
	uchar	ea[6]; 
1993/0904    
	uchar	ba[6]; 
1993/0903    
 
1993/0904    
	Sonic	*sonic;		/* SONIC registers */ 
1993/0903    
                 
	QLock	tlock;		/* lock for grabbing transmitter queue */ 
	Rendez	tr;		/* wait here for free xmit buffer */ 
1993/0904    
	int	th;		/* first transmit buffer owned by host */	 
1993/0905/sys/src/9/carrera/devether.c:214,2261993/0906/sys/src/9/carrera/devether.c:230,243
1993/0904    
	int	rh;		/* first receive buffer owned by host */ 
	int	ri;		/* first receive buffer owned by interface */ 
 
	RXrsc	rra[Nrb];	/* receive resource area */ 
	RXpkt	rda[Nrb];	/* receive descriptor area */ 
	uchar	rb[Nrb][sizeof(Etherpkt)+4];	/* receive buffer area */ 
	TXpkt	tda[Ntb];	/* transmit descriptor area */ 
	uchar	tb[Ntb][sizeof(Etherpkt)];	/* transmit buffer area */ 
	Cam	cda;		/* CAM descriptor area */ 
1993/0906    
	RXrsc	*rra;		/* receive resource area */ 
	RXpkt	*rda;		/* receive descriptor area */ 
	TXpkt	*tda;		/* transmit descriptor area */ 
	Cam	*cda;		/* CAM descriptor area */ 
1993/0904    
 
1993/0906    
	uchar	*rb[Nrb];	/* receive buffer area */ 
	uchar	*tb[Ntb];	/* transmit buffer area */ 
 
1993/0903    
	Netif; 
1993/0904    
}; 
1993/0903    
 
1993/0905/sys/src/9/carrera/devether.c:231,2511993/0906/sys/src/9/carrera/devether.c:248,276
1993/0904    
#define LS16(addr)	(PADDR(addr) & 0xFFFF) 
#define MS16(addr)	((PADDR(addr)>>16) & 0xFFFF) 
 
1993/0906    
void sonicswap(void*, int); 
 
1993/0903    
static void 
1993/0906    
wus(ushort *a, ushort v) 
{ 
	a[0] = v; 
	a[-1] = v; 
} 
 
static void 
1993/0904    
reset(Ether *ctlr) 
1993/0903    
{ 
1993/0904    
	int i; 
1993/0906    
	ushort lolen, hilen, loadr, hiadr; 
1993/0903    
 
1993/0904    
	/* 
	 * Reset the SONIC, toggle the Rst bit. 
	 * Set the data config register for synchronous termination 
	 * and 32-bit data-path width. 
	 * Clear the descriptor and buffer area. 
1993/0906    
	 * Setup the descriptor and buffer area. 
1993/0904    
	 */ 
	WR(cr, Rst); 
1993/0905    
	WR(dcr, 0x2423);	/* 5-19 Carrera manual */ 
iprint("eobc #%lux\n", RD(eobc)); 
1993/0904    
	WR(cr, 0); 
1993/0903    
 
1993/0904    
	/* 
	 * Initialise the receive resource area (RRA) and 
1993/0905/sys/src/9/carrera/devether.c:254,2761993/0906/sys/src/9/carrera/devether.c:279,312
1993/0904    
	 * We use a simple scheme of one packet per descriptor. 
	 * We achieve this by setting the EOBC register to be 
	 * 2 (16-bit words) less than the buffer size; 
	 * thus the size of the receive buffers must be sizeof(Etherpkt)+4. 
1993/0906    
	 * thus the size of the receive buffers must be sizeof(Pbuf)+4. 
1993/0904    
	 * Set up the receive descriptors as a ring. 
	 */ 
1993/0906    
 
	lolen = (Rxbuf/2) & 0xFFFF; 
	hilen = ((Rxbuf/2)>>16) & 0xFFFF; 
 
1993/0905    
	for(i = 0; i < Nrb; i++) { 
1993/0904    
		ctlr->rra[i].wc0 = (sizeof(ctlr->rb[0])/2) & 0xFFFF; 
		ctlr->rra[i].wc1 = ((sizeof(ctlr->rb[0])/2)>>16) & 0xFFFF; 
1993/0906    
		wus(&ctlr->rra[i].wc0, lolen); 
		wus(&ctlr->rra[i].wc1, hilen); 
1993/0903    
 
1993/0904    
		ctlr->rda[i].link = LS16(&ctlr->rda[NEXT(i, Nrb)]); 
1993/0906    
		ctlr->rda[i].link =  LS16(&ctlr->rda[NEXT(i, Nrb)]); 
1993/0904    
		ctlr->rda[i].owner = Interface; 
1993/0903    
 
1993/0904    
		ctlr->rra[i].ptr0 = ctlr->rda[i].ptr0 = LS16(ctlr->rb[i]); 
		ctlr->rra[i].ptr1 = ctlr->rda[i].ptr1 = MS16(ctlr->rb[i]); 
1993/0906    
		loadr = LS16(ctlr->rb[i]); 
		wus(&ctlr->rra[i].ptr0, loadr); 
		wus(&ctlr->rda[i].ptr0, loadr); 
 
		hiadr = MS16(ctlr->rb[i]); 
		wus(&ctlr->rra[i].ptr1, hiadr); 
		wus(&ctlr->rda[i].ptr1, hiadr); 
1993/0904    
	} 
1993/0903    
 
1993/0906    
	/* 
	 * Check the important resources are QUAD aligned 
	 */ 
1993/0905    
	ISquad(ctlr->rra); 
	ISquad(ctlr->rda); 
	ISquad(ctlr->rb); 
 
1993/0904    
	/* 
	 * Terminate the receive descriptor ring 
1993/0905/sys/src/9/carrera/devether.c:280,2871993/0906/sys/src/9/carrera/devether.c:316,322
1993/0903    
 
1993/0904    
	WR(crda, LS16(ctlr->rda)); 
	WR(urda, MS16(ctlr->rda)); 
	WR(eobc, sizeof(ctlr->rb[0])/2 - 2); 
1993/0905    
iprint("eobc #%lux\n", RD(eobc)); 
1993/0906    
	WR(eobc, Rxbuf/2 - 2); 
1993/0903    
 
1993/0904    
	/* 
	 * Load the SONIC registers to describe the RRA. 
1993/0905/sys/src/9/carrera/devether.c:289,2961993/0906/sys/src/9/carrera/devether.c:324,329
1993/0904    
	 * rea. This means that since we've already allocated all 
	 * the buffers, we'll never get a 'receive buffer area 
	 * exhausted' interrupt and the rrp will just wrap round. 
	 * Tell the SONIC to load the RRA and wait for 
	 * it to complete. 
	 */ 
	WR(urra, MS16(&ctlr->rra[0])); 
	WR(rsa, LS16(&ctlr->rra[0])); 
1993/0905/sys/src/9/carrera/devether.c:298,3071993/0906/sys/src/9/carrera/devether.c:331,336
1993/0904    
	WR(rea, LS16(&ctlr->rra[Nrb])); 
	WR(rwp, LS16(&ctlr->rra[Nrb+1])); 
1993/0903    
 
1993/0904    
	WR(cr, Rrra); 
	while(RD(cr) & Rrra) 
		; 
                 
	/* 
	 * Initialise the transmit descriptor area (TDA). 
	 * Each descriptor describes one packet, we make no use 
1993/0905/sys/src/9/carrera/devether.c:339,3561993/0906/sys/src/9/carrera/devether.c:368,393
1993/0904    
	 * broadcast is defined by the SONIC as all 1s. 
	 * 
	 * Load the SONIC registers to describe the CDA. 
	 * Tell the SONIC to load the CDA and wait for it 
	 * to complete. 
	 */ 
	ctlr->cda.cep = 0; 
	ctlr->cda.cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0]; 
	ctlr->cda.cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2]; 
	ctlr->cda.cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4]; 
	ctlr->cda.ce = 1; 
1993/0906    
	ctlr->cda->cep = 0; 
	ctlr->cda->cap0 = (ctlr->ea[1]<<8)|ctlr->ea[0]; 
	ctlr->cda->cap1 = (ctlr->ea[3]<<8)|ctlr->ea[2]; 
	ctlr->cda->cap2 = (ctlr->ea[5]<<8)|ctlr->ea[4]; 
	ctlr->cda->ce = 1; 
1993/0904    
 
	WR(cdp, LS16(&ctlr->cda)); 
1993/0906    
	WR(cdp, LS16(ctlr->cda)); 
1993/0904    
	WR(cdc, 1); 
 
1993/0906    
	/* 
	 * End the reset 
	 * Load the Resource Descriptors and Cam contents 
	 */ 
	WR(cr, 0); 
 
	WR(cr, Rrra); 
	while(RD(cr) & Rrra) 
		; 
 
1993/0904    
	WR(cr, Lcam); 
	while(RD(cr) & Lcam) 
		; 
1993/0905/sys/src/9/carrera/devether.c:366,4081993/0906/sys/src/9/carrera/devether.c:403,444
1993/0903    
} 
 
void 
1993/0905    
pxp(RXpkt *rxpkt) 
1993/0906    
sonicpkt(Ether *ctlr, RXpkt *r, Pbuf *p) 
1993/0905    
{ 
	print("%lux %lux\n", rxpkt->pad0[0], rxpkt->pad0[1]); 
	print("status %lux\n", rxpkt->status);		/* receive status */ 
	print("%lux %lux\n", rxpkt->pad1[0], rxpkt->pad1[1]); 
	print("count %lux\n", rxpkt->count);		/* packet byte count */ 
	print("%lux %lux\n", rxpkt->pad2[0], rxpkt->pad2[1]); 
	print("ptr0 %lux\n", rxpkt->ptr0);		/* buffer pointer */ 
	print("%lux %lux\n", rxpkt->pad3[0], rxpkt->pad3[1]); 
	print("ptr1 %lux\n", rxpkt->ptr1); 
	print("%lux %lux\n", rxpkt->pad4[0], rxpkt->pad4[1]); 
	print("seqno %lux\n", rxpkt->seqno);		/*  */ 
	print("%lux %lux\n", rxpkt->pad5[0], rxpkt->pad5[1]); 
	print("link %lux\n", rxpkt->link);		/* descriptor link and EOL */ 
	print("%lux %lux\n", rxpkt->pad6[0], rxpkt->pad6[1]); 
	print("owner %lux\n", rxpkt->owner);		/* in use */ 
1993/0906    
	int len; 
	ushort type; 
	Netfile *f, **fp, **ep; 
 
	/* 
	 * Sonic delivers CRC as part of the packet count 
	 */ 
	len = (r->count & 0xFFFF)-4; 
 
	sonicswap(p, len); 
 
	type = (p->type[0]<<8) | p->type[1]; 
	ep = &ctlr->f[Ntypes]; 
	for(fp = ctlr->f; fp < ep; fp++) { 
		f = *fp; 
		if(f && (f->type == type || f->type < 0)) 
			qproduce(f->in, p->d, len); 
	} 
1993/0905    
} 
 
void 
1993/0903    
etherintr(void) 
{ 
	int x; 
	ushort t; 
1993/0904    
	Ether *ctlr; 
1993/0906    
	Ether *c; 
1993/0904    
	ulong status; 
	TXpkt *txpkt; 
	RXpkt *rxpkt; 
	Etherpkt *p; 
	Netfile *f, **fp; 
1993/0903    
 
1993/0904    
	ctlr = ether[0]; 
1993/0906    
	c = ether[0]; 
1993/0903    
 
1993/0904    
	for(;;) { 
		status = RD(isr) & AllIntr; 
		if(status == 0) 
			break; 
1993/0905    
print("s %lux\n", status);	 
1993/0904    
 
		WR(isr, status); 
	 
1993/0905/sys/src/9/carrera/devether.c:410,4161993/0906/sys/src/9/carrera/devether.c:446,452
1993/0904    
		 * Transmission complete, for good or bad. 
		 */ 
		if(status & (Txdn|Txer)){ 
			txpkt = &ctlr->tda[ctlr->ti]; 
1993/0906    
			txpkt = &c->tda[c->ti]; 
1993/0904    
			while(txpkt->status != Host){ 
				if(txpkt->status == Interface){ 
					WR(ctda, LS16(txpkt)); 
1993/0905/sys/src/9/carrera/devether.c:419,4291993/0906/sys/src/9/carrera/devether.c:455,465
1993/0904    
				} 
	 
				if((txpkt->status & Ptx) == 0) 
					ctlr->oerrs++; 
1993/0906    
					c->oerrs++; 
1993/0904    
	 
				txpkt->status = Host; 
				ctlr->ti = NEXT(ctlr->ti, Ntb); 
				txpkt = &ctlr->tda[ctlr->ti]; 
1993/0906    
				c->ti = NEXT(c->ti, Ntb); 
				txpkt = &c->tda[c->ti]; 
1993/0904    
			} 
			status &= ~(Txdn|Txer); 
1993/0903    
		} 
1993/0905/sys/src/9/carrera/devether.c:434,4711993/0906/sys/src/9/carrera/devether.c:470,493
1993/0904    
		/* 
		 * A packet arrived or we ran out of descriptors. 
		 */ 
		rxpkt = &ctlr->rda[ctlr->rh]; 
1993/0905    
pxp(rxpkt); 
1993/0906    
		rxpkt = &c->rda[c->rh]; 
1993/0904    
		while(rxpkt->owner == Host){ 
			ctlr->inpackets++; 
1993/0906    
			c->inpackets++; 
1993/0904    
	 
			/* 
			 * If the packet was received OK, pass it up, 
			 * otherwise log the error. 
			 * SONIC gives us the CRC in the packet, so 
			 * remember to subtract it from the length. 
			 */ 
                 
			if(rxpkt->status & Prx) { 
				x = (rxpkt->count & 0xFFFF)-4; 
				p = (Etherpkt*)ctlr->rb[ctlr->rh]; 
				t = (p->type[0]<<8) | p->type[1]; 
				for(fp = ctlr->f; fp < &ctlr->f[Ntypes]; fp++){ 
					f = *fp; 
					if(f == 0) 
						continue; 
					if(f->type == t || f->type < 0) 
						qproduce(f->in, p->d, x); 
				} 
1993/0903    
			} 
1993/0906    
			if(rxpkt->status & Prx) 
				sonicpkt(c, rxpkt, (Pbuf*)c->rb[c->rh]); 
1993/0904    
			else 
			if(rxpkt->status & Fae) 
				ctlr->frames++; 
1993/0906    
				c->frames++; 
1993/0904    
			else 
			if(rxpkt->status & Crc) 
				ctlr->crcs++; 
1993/0906    
				c->crcs++; 
1993/0904    
			else 
				ctlr->buffs++; 
1993/0906    
				c->buffs++; 
1993/0904    
	 
			/* 
			 * Finished with this packet, it becomes the 
1993/0905/sys/src/9/carrera/devether.c:475,4841993/0906/sys/src/9/carrera/devether.c:497,506
1993/0904    
			 */ 
			rxpkt->link |= Eol; 
			rxpkt->owner = Interface; 
			ctlr->rda[PREV(ctlr->rh, Nrb)].link &= ~Eol; 
			ctlr->rh = NEXT(ctlr->rh, Nrb); 
1993/0906    
			c->rda[PREV(c->rh, Nrb)].link &= ~Eol; 
			c->rh = NEXT(c->rh, Nrb); 
1993/0904    
	 
			rxpkt = &ctlr->rda[ctlr->rh]; 
1993/0906    
			rxpkt = &c->rda[c->rh]; 
1993/0903    
		} 
1993/0904    
		status &= ~(Pktrx|Rde); 
1993/0903    
 
1993/0905/sys/src/9/carrera/devether.c:494,5091993/0906/sys/src/9/carrera/devether.c:516,531
1993/0904    
		 * Warnings that something is afoot. 
		 */ 
		if(status & Hbl){ 
1993/0905    
			iprint("sonic: cd heartbeat lost\n"); 
1993/0906    
			print("sonic: cd heartbeat lost\n"); 
1993/0904    
			status &= ~Hbl; 
1993/0903    
		} 
1993/0904    
		if(status & Br){ 
1993/0905    
			iprint("sonic: bus retry occurred\n"); 
1993/0906    
			print("sonic: bus retry occurred\n"); 
1993/0904    
			status &= ~Br; 
		} 
	 
		if(status & AllIntr) 
1993/0905    
			iprint("sonic #%lux\n", status); 
1993/0906    
			print("sonic #%lux\n", status); 
1993/0903    
	} 
} 
 
1993/0905/sys/src/9/carrera/devether.c:524,5291993/0906/sys/src/9/carrera/devether.c:546,592
1993/0904    
		WR(rcr, reg&~Pro); 
1993/0903    
} 
 
1993/0906    
static void 
initbufs(Ether *c) 
{ 
	int i; 
	uchar *mem; 
 
	mem = xspanalloc(64*1024, BY2PG, 0); 
	mem = CACHELINE(uchar, mem); 
 
	/* 
	 * Descriptors must be built in uncached space 
	 */ 
	c->rra = UNCACHED(RXrsc, mem); 
	mem = QUAD(uchar, mem+Nrb*sizeof(RXrsc)); 
 
	c->rda = UNCACHED(RXpkt, mem); 
	mem = QUAD(uchar, mem+Nrb*sizeof(RXpkt)); 
 
	c->tda = UNCACHED(TXpkt, mem); 
	mem = QUAD(uchar, mem+Ntb*sizeof(TXpkt)); 
 
	c->cda = UNCACHED(Cam, mem); 
 
	/* 
	 * DMA buffers are cache coherent - but we must not straddle 
	 * a cache line 
	 */ 
	mem = CACHELINE(uchar, mem+sizeof(Cam)); 
 
	for(i = 0; i < Nrb; i++) { 
		c->rb[i] = UNCACHED(uchar, mem); 
		mem += sizeof(Pbuf)+4; 
		mem = QUAD(uchar, mem); 
	} 
	for(i = 0; i < Ntb; i++) { 
		c->tb[i] = UNCACHED(uchar, mem); 
		mem += sizeof(Pbuf); 
		mem = QUAD(uchar, mem); 
	} 
} 
 
1993/0903    
void 
etherreset(void) 
{ 
1993/0905/sys/src/9/carrera/devether.c:535,5461993/0906/sys/src/9/carrera/devether.c:598,608
1993/0904    
	 * Set the physical ethernet address and 
	 * prime the interrupt handler. 
	 */ 
	if(ether[0] == 0) { 
		ether[0] = xspanalloc(sizeof(Ether), BY2PG, 64*1024); 
1993/0905    
 
		if(PADDR(ether[0])+sizeof(Ether) > Ntranslation*BY2PG) 
			panic("sonic: 16M io map"); 
                 
1993/0906    
	if(ether[0] == 0) { 
		ctlr = malloc(sizeof(Ether)); 
		ether[0] = ctlr; 
		initbufs(ctlr); 
1993/0905    
		enetaddr(ether[0]->ea); 
1993/0903    
	} 
1993/0904    
	ctlr = ether[0]; 
1993/0905/sys/src/9/carrera/devether.c:559,5701993/0906/sys/src/9/carrera/devether.c:621,626
1993/0903    
} 
 
void 
1993/0905    
enab(void) 
{ 
	WR(cr, Rxen); 
} 
                 
void 
1993/0903    
etherinit(void) 
{ 
} 
1993/0905/sys/src/9/carrera/devether.c:578,5841993/0906/sys/src/9/carrera/devether.c:634,639
1993/0905    
		enable = 1; 
		WR(cr, Rxen); 
	} 
                 
1993/0903    
	return devattach('l', spec); 
} 
 
1993/0905/sys/src/9/carrera/devether.c:629,6421993/0906/sys/src/9/carrera/devether.c:684,695
1993/0903    
long 
etherwrite(Chan *c, void *buf, long n, ulong offset) 
{ 
1993/0904    
	Etherpkt *p; 
1993/0906    
	Pbuf *p; 
1993/0904    
	TXpkt *txpkt; 
	Ether *ctlr = ether[0]; 
1993/0903    
 
	USED(offset); 
 
1993/0905    
iprint("ether tx\n"); 
                 
1993/0903    
	if(n > ETHERMAXTU) 
		error(Ebadarg); 
 
1993/0905/sys/src/9/carrera/devether.c:651,6571993/0906/sys/src/9/carrera/devether.c:704,710
1993/0905    
	if(!isoutbuf(ctlr)) 
1993/0903    
		print("ether transmitter jammed\n"); 
1993/0904    
	else { 
		p =(Etherpkt*)ctlr->tb[ctlr->th]; 
1993/0906    
		p =(Pbuf*)ctlr->tb[ctlr->th]; 
1993/0903    
		memmove(p->d, buf, n); 
		if(n < 60) { 
			memset(p->d+n, 0, 60-n); 
1993/0905/sys/src/9/carrera/devether.c:658,6631993/0906/sys/src/9/carrera/devether.c:711,717
1993/0903    
			n = 60; 
		} 
1993/0904    
		memmove(p->s, ctlr->ea, sizeof(ctlr->ea)); 
1993/0906    
		sonicswap(p, n); 
1993/0904    
 
		txpkt = &ctlr->tda[ctlr->th]; 
		txpkt->size = n; 
1993/0905/sys/src/9/carrera/devether.c:671,6781993/0906/sys/src/9/carrera/devether.c:725,730
1993/0903    
	} 
1993/0904    
	qunlock(&ctlr->tlock); 
1993/0905    
 
iprint("tx done %d\n", n); 
                 
1993/0903    
	return n; 
} 
 
1993/0905/sys/src/9/carrera/devether.c:692,6951993/0906/sys/src/9/carrera/devether.c:744,766
1993/0903    
etherwstat(Chan *c, char *dp) 
{ 
1993/0904    
	netifwstat(ether[0], c, dp); 
1993/0906    
} 
 
#define swiz(s)	(s<<24)|((s>>8)&0xff00)|((s<<8)&0xff0000)|(s>>24) 
 
void 
sonicswap(void *a, int n) 
{ 
	ulong *p, t0, t1; 
 
	n = ((n+8)/8)*8; 
	p = a; 
	while(n) { 
		t0 = p[0]; 
		t1 = p[1]; 
		p[0] = swiz(t1); 
		p[1] = swiz(t0); 
		p += 2; 
		n -= 8; 
	} 
1993/0903    
} 


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