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

1993/1116/pc/ether8390.c (diff list | history)

1993/0915/sys/src/9/pc/ether8390.c:8,181993/1116/sys/src/9/pc/ether8390.c:8,18 (short | long | prev | next)
1992/1222    
#include "mem.h" 
#include "dat.h" 
#include "fns.h" 
#include "../port/error.h" 
#include "io.h" 
#include "devtab.h" 
1993/1116    
#include "../port/error.h" 
#include "../port/netif.h" 
1992/1222    
 
#include "ether.h" 
1993/1116    
#include "etherif.h" 
1992/1222    
 
enum { 
	Cr		= 0x00,		/* command register, all pages */ 
1993/0915/sys/src/9/pc/ether8390.c:147,1581993/1116/sys/src/9/pc/ether8390.c:147,158
1992/1222    
} Hdr; 
 
static void 
dp8390disable(Ctlr *ctlr) 
1993/1116    
dp8390disable(Ether *ether) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	int timo; 
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1993/1116    
	dp8390 = ether->dp8390; 
1992/1222    
	/* 
	 * Stop the chip. Set the Stp bit and wait for the chip 
	 * to finish whatever was on its tiny mind before it sets 
1993/0915/sys/src/9/pc/ether8390.c:169,2641993/1116/sys/src/9/pc/ether8390.c:169,198
1992/1222    
} 
 
1993/0212    
static void 
dp8390ring(Ctlr *ctlr) 
1993/1116    
dp8390ring(Ether *ether) 
1993/0212    
{ 
1993/0915    
	ulong dp8390; 
1993/0212    
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
	dp8390outb(dp8390+Pstart, ctlr->card.pstart); 
	dp8390outb(dp8390+Pstop, ctlr->card.pstop); 
	dp8390outb(dp8390+Bnry, ctlr->card.pstop-1); 
1993/1116    
	dp8390 = ether->dp8390; 
	dp8390outb(dp8390+Pstart, ether->pstart); 
	dp8390outb(dp8390+Pstop, ether->pstop); 
	dp8390outb(dp8390+Bnry, ether->pstop-1); 
1993/0212    
 
1993/0915    
	dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(dp8390+Curr, ctlr->card.pstart); 
1993/1116    
	dp8390outb(dp8390+Curr, ether->pstart); 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
 
1993/0212    
	ctlr->card.nxtpkt = ctlr->card.pstart; 
1993/1116    
	ether->nxtpkt = ether->pstart; 
1993/0212    
} 
 
1992/1222    
void 
dp8390reset(Ctlr *ctlr) 
1993/1116    
dp8390setea(Ether *ether) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
                 
	dp8390 = ctlr->card.dp8390; 
1992/1222    
	/* 
	 * This is the initialisation procedure described 
1993/0212    
	 * as 'mandatory' in the datasheet, with references 
	 * to the 3Com503 technical reference manual. 
1992/1222    
	 */  
	dp8390disable(ctlr); 
1993/0212    
	if(ctlr->card.bit16) 
1993/0915    
		dp8390outb(dp8390+Dcr, Ft4|Ls|Wts); 
1992/1222    
	else 
1993/0915    
		dp8390outb(dp8390+Dcr, Ft4|Ls); 
1992/1222    
                 
1993/0915    
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
1992/1222    
                 
1993/0915    
	dp8390outb(dp8390+Tcr, 0); 
	dp8390outb(dp8390+Rcr, Mon); 
1992/1222    
                 
	/* 
1993/0212    
	 * Init the ring hardware and software ring pointers. 
	 * Can't initialise ethernet address as we may not know 
	 * it yet. 
1992/1222    
	 */ 
1993/0212    
	dp8390ring(ctlr); 
1993/0915    
	dp8390outb(dp8390+Tpsr, ctlr->card.tstart); 
1992/1222    
                 
1993/0915    
	dp8390outb(dp8390+Isr, 0xFF); 
	dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/0212    
                 
1992/1222    
	/* 
	 * Leave the chip initialised, 
1993/0213    
	 * but in monitor mode. 
1992/1222    
	 */ 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1992/1222    
} 
                 
void 
dp8390attach(Ctlr *ctlr) 
{ 
	/* 
	 * Enable the chip for transmit/receive. 
1993/0212    
	 * The init routine leaves the chip in monitor 
1993/0213    
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
1992/1222    
	 */ 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Rcr, Ab); 
1993/0213    
	dp8390inb(ctlr->card.dp8390+Cntr2); 
1992/1222    
} 
                 
void 
dp8390mode(Ctlr *ctlr, int on) 
{ 
1993/0212    
	/* 
	 * Set/reset promiscuous mode. 
	 */ 
1992/1222    
	if(on) 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Rcr, Pro|Ab); 
1992/1222    
	else 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Rcr, Ab); 
1992/1222    
} 
                 
void 
dp8390setea(Ctlr *ctlr) 
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	uchar cr; 
	int i; 
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1993/1116    
	dp8390 = ether->dp8390; 
1992/1222    
	/* 
	 * Set the ethernet address into the chip. 
	 * Take care to restore the command register 
1993/0915/sys/src/9/pc/ether8390.c:268,2881993/1116/sys/src/9/pc/ether8390.c:202,222
1992/1222    
	 */ 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1992/1222    
	for(i = 0; i < sizeof(ctlr->ea); i++) 
1993/0915    
		dp8390outb(dp8390+Par0+i, ctlr->ea[i]); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
		dp8390outb(dp8390+Par0+i, ether->ea[i]); 
1993/0915    
	dp8390outb(dp8390+Cr, cr); 
1992/1222    
} 
 
1993/0915    
void 
dp8390getea(Ctlr *ctlr) 
1993/1116    
dp8390getea(Ether *ether) 
1993/0915    
{ 
	ulong dp8390; 
	uchar cr; 
	int i; 
 
	dp8390 = ctlr->card.dp8390; 
1993/1116    
	dp8390 = ether->dp8390; 
1993/0915    
	/* 
	 * Set the ethernet address into the chip. 
1993/1116    
	 * Get the ethernet address from the chip. 
1993/0915    
	 * Take care to restore the command register 
	 * afterwards. We don't care about multicast 
	 * addresses as we never set the multicast 
1993/0915/sys/src/9/pc/ether8390.c:290,3081993/1116/sys/src/9/pc/ether8390.c:224,242
1993/0915    
	 */ 
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	for(i = 0; i < sizeof(ctlr->ea); i++) 
		ctlr->ea[i] = dp8390inb(dp8390+Par0+i); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
		ether->ea[i] = dp8390inb(dp8390+Par0+i); 
1993/0915    
	dp8390outb(dp8390+Cr, cr); 
} 
 
1992/1222    
void* 
dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len) 
1993/1116    
static void* 
dp8390read(Ether *ether, void *to, ulong from, ulong len) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	uchar cr; 
	int timo; 
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1993/1116    
	dp8390 = ether->dp8390; 
1992/1222    
	/* 
1993/0212    
	 * Read some data at offset 'from' in the card's memory 
1992/1222    
	 * using the DP8390 remote DMA facility, and place it at 
1993/0915/sys/src/9/pc/ether8390.c:315,3211993/1116/sys/src/9/pc/ether8390.c:249,255
1992/1222    
	/* 
	 * Set up the remote DMA address and count. 
	 */ 
1993/0212    
	if(ctlr->card.bit16) 
1993/1116    
	if(ether->bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
1993/0915    
	dp8390outb(dp8390+Rbcr0, len & 0xFF); 
	dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF); 
1993/0915/sys/src/9/pc/ether8390.c:327,3361993/1116/sys/src/9/pc/ether8390.c:261,270
1992/1222    
	 * out of the I/O port. 
	 */ 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); 
1993/0212    
	if(ctlr->card.bit16) 
		inss(ctlr->card.data, to, len/2); 
1993/1116    
	if(ether->bit16) 
		inss(ether->data, to, len/2); 
1992/1222    
	else 
1993/0212    
		insb(ctlr->card.data, to, len); 
1993/1116    
		insb(ether->data, to, len); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to complete. The timeout 
1993/0915/sys/src/9/pc/ether8390.c:347,3591993/1116/sys/src/9/pc/ether8390.c:281,293
1992/1222    
	return to; 
} 
 
void* 
dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len) 
1993/1116    
static void* 
dp8390write(Ether *ether, ulong to, void *from, ulong len) 
1992/1222    
{ 
1993/0915    
	ulong dp8390, crda; 
1992/1222    
	uchar cr; 
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1993/1116    
	dp8390 = ether->dp8390; 
1992/1222    
	/* 
1993/0212    
	 * Write some data to offset 'to' in the card's memory 
1992/1222    
	 * using the DP8390 remote DMA facility, reading it at 
1993/0915/sys/src/9/pc/ether8390.c:363,3691993/1116/sys/src/9/pc/ether8390.c:297,303
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(dp8390+Isr, Rdc); 
1992/1222    
 
1993/0212    
	if(ctlr->card.bit16) 
1993/1116    
	if(ether->bit16) 
1993/0212    
		len = ROUNDUP(len, 2); 
 
1992/1222    
	/* 
1993/0915/sys/src/9/pc/ether8390.c:371,3791993/1116/sys/src/9/pc/ether8390.c:305,313
1993/0212    
	 * This is straight from the DP8390[12D] datasheet, hence 
	 * the initial set up for read. 
1992/1222    
	 */ 
1993/0212    
	crda = to-1-ctlr->card.bit16; 
1993/0915    
	dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); 
	dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); 
1993/1116    
	crda = to-1-ether->bit16; 
	dp8390outb(dp8390+Rbcr0, (len+1+ether->bit16) & 0xFF); 
	dp8390outb(dp8390+Rbcr1, ((len+1+ether->bit16)>>8) & 0xFF); 
1993/0915    
	dp8390outb(dp8390+Rsar0, crda & 0xFF); 
	dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); 
1993/0915/sys/src/9/pc/ether8390.c:400,4091993/1116/sys/src/9/pc/ether8390.c:334,343
1992/1222    
	/* 
1993/0212    
	 * Pump the data into the I/O port. 
1992/1222    
	 */ 
1993/0212    
	if(ctlr->card.bit16) 
		outss(ctlr->card.data, from, len/2); 
1993/1116    
	if(ether->bit16) 
		outss(ether->data, from, len/2); 
1992/1222    
	else 
1993/0212    
		outsb(ctlr->card.data, from, len); 
1993/1116    
		outsb(ether->data, from, len); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to finish. We'll need 
1993/0915/sys/src/9/pc/ether8390.c:431,4871993/1116/sys/src/9/pc/ether8390.c:365,394
1993/0212    
} 
 
1993/0213    
static void 
1993/0915    
cldaquiet(ulong dp8390) 
1993/1116    
receive(Ether *ether) 
1993/0213    
{ 
	uchar a, b, c; 
                 
	/* 
	 * Hack to keep away from the card's memory while it is receiving 
	 * a packet. This is only a problem on the NCR 3170 Safari. 
	 * 
	 * We peek at the current local DMA registers and, if they are 
	 * changing, wait. 
	 */ 
	                 
	for(;;delay(10)){ 
1993/0915    
		a = dp8390inb(dp8390+Clda0); 
		b = dp8390inb(dp8390+Clda0); 
1993/0213    
		if(a != b) 
			continue; 
1993/0915    
		c = dp8390inb(dp8390+Clda0); 
1993/0213    
		if(c != b) 
			continue; 
		break; 
	} 
} 
                 
1992/1222    
void 
dp8390receive(Ctlr *ctlr) 
{ 
	RingBuf *ring; 
1993/0212    
	uchar curr, len1, *pkt; 
1992/1222    
	Hdr hdr; 
1993/0915    
	ulong dp8390, data, len; 
1993/1116    
	ushort type; 
	Netfile *f, **fp, **ep; 
1992/1222    
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
	for(curr = getcurr(dp8390); ctlr->card.nxtpkt != curr; curr = getcurr(dp8390)){ 
1993/0213    
		if(strcmp(arch->id, "NCRD.0") == 0) 
1993/0915    
			cldaquiet(dp8390); 
1993/1116    
	dp8390 = ether->dp8390; 
	for(curr = getcurr(dp8390); ether->nxtpkt != curr; curr = getcurr(dp8390)){ 
		ether->inpackets++; 
1992/1222    
 
		ctlr->inpackets++; 
1993/1116    
		data = ether->nxtpkt*Dp8390BufSz; 
		(*ether->read)(ctlr, &hdr, data, sizeof(Hdr)); 
1992/1222    
 
1993/0212    
		data = ctlr->card.nxtpkt*Dp8390BufSz; 
		(*ctlr->card.read)(ctlr, &hdr, data, sizeof(Hdr)); 
1992/1222    
                 
		/* 
1993/0212    
		 * Don't believe the upper byte count, work it 
		 * out from the software next-page pointer and 
		 * the current next-page pointer. 
1992/1222    
		 */ 
1993/0212    
		if(hdr.next > ctlr->card.nxtpkt) 
			len1 = hdr.next - ctlr->card.nxtpkt - 1; 
1993/1116    
		if(hdr.next > ether->nxtpkt) 
			len1 = hdr.next - ether->nxtpkt - 1; 
1993/0212    
		else 
			len1 = (ctlr->card.pstop-ctlr->card.nxtpkt) + (hdr.next-ctlr->card.pstart) - 1; 
1993/1116    
			len1 = (ether->pstop-ether->nxtpkt) + (hdr.next-ether->pstart) - 1; 
1993/0212    
		if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) 
			len1--; 
 
1993/0915/sys/src/9/pc/ether8390.c:490,5301993/1116/sys/src/9/pc/ether8390.c:397,442
1993/0212    
		/* 
		 * Chip is badly scrogged, reinitialise the ring. 
		 */ 
		if(hdr.next < ctlr->card.pstart || hdr.next >= ctlr->card.pstop 
1993/1116    
		if(hdr.next < ether->pstart || hdr.next >= ether->pstop 
1993/0212    
		  || len < 60 || len > sizeof(Etherpkt)){ 
			print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|", 
				hdr.status, hdr.next, hdr.len0, hdr.len1, len); 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
1993/0212    
			dp8390ring(ctlr); 
1993/1116    
			dp8390ring(ether); 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1992/1222    
			return; 
		} 
 
1993/0212    
		/* 
		 * If it's a good packet and we have a place to put it, 
		 * read it in to the software ring. 
		 * If the packet wraps round the hardware ring, read it 
		 * in two pieces. 
1993/1116    
		 * If it's a good packet read it in to the software buffer. 
		 * If the packet wraps round the hardware ring, read it in two pieces. 
1993/0212    
		 */ 
1992/1222    
		ring = &ctlr->rb[ctlr->ri]; 
1993/0212    
		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){ 
			pkt = ring->pkt; 
1993/1116    
		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){ 
			pkt = ether->rpkt; 
1992/1222    
			data += sizeof(Hdr); 
1993/0212    
			ring->len = len; 
 
			if((data+len) >= ctlr->card.pstop*Dp8390BufSz){ 
				ulong count = ctlr->card.pstop*Dp8390BufSz - data; 
1993/1116    
			if((data+len) >= ether->pstop*Dp8390BufSz){ 
				ulong count = ether->pstop*Dp8390BufSz - data; 
1993/0212    
 
				(*ctlr->card.read)(ctlr, pkt, data, count); 
1993/1116    
				(*ether->read)(ctlr, pkt, data, count); 
1993/0212    
				pkt += count; 
				data = ctlr->card.pstart*Dp8390BufSz; 
1993/1116    
				data = ether->pstart*Dp8390BufSz; 
1993/0212    
				len -= count; 
1992/1222    
			} 
1993/0212    
			if(len) 
				(*ctlr->card.read)(ctlr, pkt, data, len); 
1993/1116    
				(*ether->read)(ctlr, pkt, data, len); 
1993/0212    
 
1992/1222    
			ring->owner = Host; 
			ctlr->ri = NEXT(ctlr->ri, ctlr->nrb); 
1993/1116    
			/* 
			 * Copy the packet to whoever wants it. 
			 */ 
			type = (ether->rpkt.type[0]<<8)|ether->rpkt.type[1]; 
			ep = ðer->f[Ntypes]; 
			for(fp = ether->f; fp < ep; fp++) { 
				f = *fp; 
				if(f && (f->type == type || f->type < 0)) 
					qproduce(f->in, ðer->rpkt, len); 
			} 
1992/1222    
		} 
 
1993/0212    
		/* 
1993/0915/sys/src/9/pc/ether8390.c:531,5411993/1116/sys/src/9/pc/ether8390.c:443,453
1993/0212    
		 * Finished woth this packet, update the 
		 * hardware and software ring pointers. 
		 */ 
		ctlr->card.nxtpkt = hdr.next; 
1993/1116    
		ether->nxtpkt = hdr.next; 
1993/0212    
 
		hdr.next--; 
		if(hdr.next < ctlr->card.pstart) 
			hdr.next = ctlr->card.pstop-1; 
1993/1116    
		if(hdr.next < ether->pstart) 
			hdr.next = ether->pstop-1; 
1993/0915    
		dp8390outb(dp8390+Bnry, hdr.next); 
1992/1222    
	} 
} 
1993/0915/sys/src/9/pc/ether8390.c:544,5611993/1116/sys/src/9/pc/ether8390.c:456,473
1993/0212    
 * Initiate a transmission. Must be called splhi(). 
 */ 
1992/1222    
void 
dp8390transmit(Ctlr *ctlr) 
1993/1116    
dp8390transmit(Ether *ether) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	RingBuf *ring; 
1993/0212    
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1993/0212    
	ring = &ctlr->tb[ctlr->ti]; 
	if(ctlr->tbusy == 0 && ring->owner == Interface){ 
1993/1116    
	dp8390 = ether->dp8390; 
	ring = ðer->tb[ether->ti]; 
	if(ether->tbusy == 0 && ring->owner == Interface){ 
1993/0213    
 
		ctlr->tbusy = 1; 
1993/1116    
		ether->tbusy = 1; 
1993/0213    
 
1993/0212    
		(*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); 
1993/1116    
		(*ether->write)(ctlr, ether->tstart*Dp8390BufSz, ring->pkt, ring->len); 
1993/0213    
 
1993/0915    
		dp8390outb(dp8390+Tbcr0, ring->len & 0xFF); 
		dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF); 
1993/0915/sys/src/9/pc/ether8390.c:563,5761993/1116/sys/src/9/pc/ether8390.c:475,488
1993/0212    
	} 
} 
 
void 
dp8390overflow(Ctlr *ctlr) 
1993/1116    
static void 
overflow(Ether *ether) 
1993/0212    
{ 
1993/0915    
	ulong dp8390; 
1993/0212    
	uchar txp; 
	int resend; 
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1993/1116    
	dp8390 = ether->dp8390; 
1993/0212    
	/* 
	 * The following procedure is taken from the DP8390[12D] datasheet, 
	 * it seems pretty adamant that this is what has to be done. 
1993/0915/sys/src/9/pc/ether8390.c:587,5951993/1116/sys/src/9/pc/ether8390.c:499,507
1993/0212    
 
1993/0915    
	dp8390outb(dp8390+Tcr, Lb); 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1993/0212    
	(*ctlr->card.receive)(ctlr); 
1993/1116    
	(*ether->receive)(ether); 
1993/0915    
	dp8390outb(dp8390+Isr, Ovw); 
1993/0212    
	wakeup(&ctlr->rr); 
1993/1116    
	wakeup(ðer->rr); 
1993/0915    
	dp8390outb(dp8390+Tcr, 0); 
1993/0212    
 
	if(resend) 
1993/0915/sys/src/9/pc/ether8390.c:596,6271993/1116/sys/src/9/pc/ether8390.c:508,520
1993/0915    
		dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0212    
} 
 
void 
dp8390watch(Ctlr *ctlr) 
1993/1116    
static void 
interrupt(Ether *ether) 
1993/0212    
{ 
1992/1222    
	int s; 
                 
1993/0212    
	/* 
	 * Stub watchdog routine. 
	 * Whine if a transmit takes too long. 
	 */ 
1992/1222    
	s = splhi(); 
1993/0212    
	if(ctlr->tbusy){ 
		ctlr->tbusy++; 
		if(ctlr->tbusy > 1 && ctlr->debug) 
			print("TB%d|", ctlr->tbusy); 
1992/1222    
	} 
	splx(s); 
} 
                 
void 
dp8390intr(Ctlr *ctlr) 
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	RingBuf *ring; 
1993/0212    
	uchar isr, r; 
1992/1222    
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1993/1116    
	dp8390 = ether->dp8390; 
1992/1222    
	/* 
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
1993/0915/sys/src/9/pc/ether8390.c:630,6501993/1116/sys/src/9/pc/ether8390.c:523,540
1993/0915    
	while(isr = dp8390inb(dp8390+Isr)){ 
1992/1222    
 
		if(isr & Ovw){ 
1993/0212    
			if(ctlr->card.overflow) 
				(*ctlr->card.overflow)(ctlr); 
1993/1116    
			overflow(ether); 
1993/0915    
			dp8390outb(dp8390+Isr, Ovw); 
1992/1222    
			ctlr->overflows++; 
1993/1116    
			ether->overflows++; 
1992/1222    
		} 
 
		/* 
		 * We have received packets. 
		 * Take a spin round the ring and 
		 * wakeup the kproc. 
1993/1116    
		 * Take a spin round the ring. and 
1992/1222    
		 */ 
		if(isr & (Rxe|Prx)){ 
1993/0212    
			(*ctlr->card.receive)(ctlr); 
1993/1116    
			receive(ether); 
1993/0915    
			dp8390outb(dp8390+Isr, Rxe|Prx); 
1992/1222    
			wakeup(&ctlr->rr); 
		} 
 
		/* 
1993/0915/sys/src/9/pc/ether8390.c:655,6841993/1116/sys/src/9/pc/ether8390.c:545,646
1992/1222    
		if(isr & (Txe|Ptx)){ 
1993/0915    
			r = dp8390inb(dp8390+Tsr); 
1993/0212    
			if(isr & Txe){ 
				if((r & (Cdh|Fu|Crs|Abt)) && ctlr->debug) 
1993/1116    
				if((r & (Cdh|Fu|Crs|Abt)) && ether->debug) 
1993/0212    
					print("Tsr#%2.2ux|", r); 
				ctlr->oerrs++; 
1993/1116    
				ether->oerrs++; 
1993/0212    
			} 
 
1993/0915    
			dp8390outb(dp8390+Isr, Txe|Ptx); 
1993/0212    
 
			if(isr & Ptx) 
				ctlr->outpackets++; 
                 
1992/1222    
			ring = &ctlr->tb[ctlr->ti]; 
			ring->owner = Host; 
1993/0212    
			ctlr->tbusy = 0; 
1992/1222    
			ctlr->ti = NEXT(ctlr->ti, ctlr->ntb); 
1993/0212    
			(*ctlr->card.transmit)(ctlr); 
1992/1222    
			wakeup(&ctlr->tr); 
1993/1116    
				ether->outpackets++; 
			wakeup(ðer->tr); 
1992/1222    
		} 
1993/0212    
 
		if(isr & Cnt){ 
1993/0915    
			ctlr->frames += dp8390inb(dp8390+Cntr0); 
			ctlr->crcs += dp8390inb(dp8390+Cntr1); 
			ctlr->buffs += dp8390inb(dp8390+Cntr2); 
1993/1116    
			ether->frames += dp8390inb(dp8390+Cntr0); 
			ether->crcs += dp8390inb(dp8390+Cntr1); 
			ether->buffs += dp8390inb(dp8390+Cntr2); 
1993/0915    
			dp8390outb(dp8390+Isr, Cnt); 
1993/0212    
		} 
1992/1222    
	} 
1993/0915    
	dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
} 
 
static void 
promiscuous(Ether *ether, int on) 
{ 
	/* 
	 * Set/reset promiscuous mode. 
	 */ 
	if(on) 
		dp8390outb(ether->dp8390+Rcr, Pro|Ab); 
	else 
		dp8390outb(ether->dp8390+Rcr, Ab); 
} 
 
void 
dp8390attach(Ether *ether) 
{ 
	/* 
	 * Enable the chip for transmit/receive. 
	 * The init routine leaves the chip in monitor 
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
	 */ 
	dp8390outb(ether->dp8390+Rcr, Ab); 
	dp8390inb(ether->dp8390+Cntr2); 
} 
 
static int 
dp8390reset(Ether *ether) 
{ 
	ulong dp8390; 
 
	dp8390 = ether->dp8390; 
	/* 
	 * This is the initialisation procedure described 
	 * as 'mandatory' in the datasheet, with references 
	 * to the 3Com503 technical reference manual. 
	 */  
	dp8390disable(ether); 
	if(ether->bit16) 
		dp8390outb(dp8390+Dcr, Ft4|Ls|Wts); 
	else 
		dp8390outb(dp8390+Dcr, Ft4|Ls); 
 
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
 
	dp8390outb(dp8390+Tcr, 0); 
	dp8390outb(dp8390+Rcr, Mon); 
 
	/* 
	 * Init the ring hardware and software ring pointers. 
	 * Can't initialise ethernet address as we may not know 
	 * it yet. 
	 */ 
	dp8390ring(ether); 
	dp8390outb(dp8390+Tpsr, ether->tstart); 
 
	dp8390outb(dp8390+Isr, 0xFF); 
	dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
 
	/* 
	 * Leave the chip initialised, 
	 * but in monitor mode. 
	 */ 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
 
	/* 
	 * Set up the software configuration. 
	 */ 
	ether->attach = attach; 
	ether->write = write; 
	ether->interrupt = interrupt; 
 
	ether->promiscuous = promiscuous; 
	ether->arg = ether; 
 
	return 0; 
1992/1222    
} 


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