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

1998/0825/pc/ether8390.c (diff list | history)

1992/1222/sys/src/9/pc/ether8390.c:24,321993/0212/sys/src/9/pc/ether8390.c:24,34 (short | long)
1992/1222    
	RDMAwrite	= (2<<3),	/* remote DMA write */ 
	RDMAsend	= (3<<3),	/* remote DMA send packet */ 
	RDMAabort	= (4<<3),	/* abort/complete remote DMA */ 
	Page0		= (0x00<<6),	/* page select */ 
	Page1		= (0x01<<6), 
	Page2		= (0x02<<6), 
1993/0212    
	Ps0		= 0x40,		/* page select */ 
	Ps1		= 0x80,		/* page select */ 
	Page0		= 0x00, 
	Page1		= Ps0, 
	Page2		= Ps1, 
1992/1222    
}; 
 
enum {					/* Page 0, read */ 
1992/1222/sys/src/9/pc/ether8390.c:38,441993/0212/sys/src/9/pc/ether8390.c:40,46
1992/1222    
	Fifo		= 0x06,		/* FIFO */ 
	Isr		= 0x07,		/* interrupt status register (R/W) */ 
	Crda0		= 0x08,		/* current remote DMA address 0 */ 
	Crda1		= 0x08,		/* current remote DMA address 1 */ 
1993/0212    
	Crda1		= 0x09,		/* current remote DMA address 1 */ 
1992/1222    
	Rsr		= 0x0C,		/* receive status register */ 
	Cntr0		= 0x0D,		/* frame alignment errors */ 
	Cntr1		= 0x0E,		/* CRC errors */ 
1992/1222/sys/src/9/pc/ether8390.c:144,1581993/0212/sys/src/9/pc/ether8390.c:146,154
1992/1222    
	uchar	len1; 
} Hdr; 
 
typedef struct { 
	Hdr; 
	uchar	data[Dp8390BufSz-sizeof(Hdr)]; 
} Buf; 
                 
static void 
dp8390disable(Ctlr *ctlr) 
{ 
	Board *board = ctlr->board; 
	int timo; 
 
	/* 
1992/1222/sys/src/9/pc/ether8390.c:163,2161993/0212/sys/src/9/pc/ether8390.c:159,221
1992/1222    
	 * chip there if this is called when probing for a device 
	 * at boot. 
	 */ 
	outb(board->dp8390+Cr, Page0|RDMAabort|Stp); 
	for(timo = 10000; (inb(board->dp8390+Isr) & Rst) == 0 && timo; timo--) 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(ctlr->card.dp8390+Rbcr0, 0); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rst) == 0 && timo; timo--) 
1992/1222    
			; 
} 
 
1993/0212    
static void 
dp8390ring(Ctlr *ctlr) 
{ 
	dp8390outb(ctlr->card.dp8390+Pstart, ctlr->card.pstart); 
	dp8390outb(ctlr->card.dp8390+Pstop, ctlr->card.pstop); 
	dp8390outb(ctlr->card.dp8390+Bnry, ctlr->card.pstop-1); 
 
	dp8390outb(ctlr->card.dp8390+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(ctlr->card.dp8390+Curr, ctlr->card.pstart); 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
 
	ctlr->card.nxtpkt = ctlr->card.pstart; 
} 
 
1992/1222    
void 
dp8390reset(Ctlr *ctlr) 
{ 
	Board *board = ctlr->board; 
                 
	/* 
	 * This is the initialisation procedure described 
	 * as 'mandatory' in the datasheet. 
1993/0212    
	 * as 'mandatory' in the datasheet, with references 
	 * to the 3Com503 technical reference manual. 
1992/1222    
	 */  
	dp8390disable(ctlr); 
	if(board->bit16) 
		outb(board->dp8390+Dcr, Ft4|Ls|Wts); 
1993/0212    
	if(ctlr->card.bit16) 
		dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls|Wts); 
1992/1222    
	else 
		outb(board->dp8390+Dcr, Ft4|Ls); 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls); 
1992/1222    
 
	outb(board->dp8390+Rbcr0, 0); 
	outb(board->dp8390+Rbcr1, 0); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Rbcr0, 0); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, 0); 
1992/1222    
 
	outb(board->dp8390+Rcr, Ab); 
	outb(board->dp8390+Tcr, Lb); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Tcr, 0); 
	dp8390outb(ctlr->card.dp8390+Rcr, Mon); 
1992/1222    
 
	outb(board->dp8390+Bnry, board->pstart); 
	outb(board->dp8390+Pstart, board->pstart); 
	outb(board->dp8390+Pstop, board->pstop); 
                 
	outb(board->dp8390+Isr, 0xFF); 
	outb(board->dp8390+Imr, Ovwe|Txee|Rxee|Ptxe|Prxe); 
                 
	outb(board->dp8390+Cr, Page1|RDMAabort|Stp); 
                 
	/* 
	 * Can't initialise ethernet address as we may 
	 * not know it yet. 
1993/0212    
	 * Init the ring hardware and software ring pointers. 
	 * Can't initialise ethernet address as we may not know 
	 * it yet. 
1992/1222    
	 */ 
	outb(board->dp8390+Curr, board->pstart+1); 
1993/0212    
	dp8390ring(ctlr); 
	dp8390outb(ctlr->card.dp8390+Tpsr, ctlr->card.tstart); 
1992/1222    
 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Isr, 0xFF); 
	dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
 
1992/1222    
	/* 
	 * Leave the chip initialised, 
	 * but in internal loopback mode. 
	 */ 
	outb(board->dp8390+Cr, Page0|RDMAabort|Sta); 
                 
	outb(board->dp8390+Tpsr, board->tstart); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
1992/1222    
} 
 
void 
1992/1222/sys/src/9/pc/ether8390.c:218,2421993/0212/sys/src/9/pc/ether8390.c:223,249
1992/1222    
{ 
	/* 
	 * Enable the chip for transmit/receive. 
	 * The init routine leaves the chip in internal 
	 * loopback. 
1993/0212    
	 * The init routine leaves the chip in monitor 
	 * mode. 
1992/1222    
	 */ 
	outb(ctlr->board->dp8390+Tcr, 0); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Rcr, Ab); 
1992/1222    
} 
 
void 
dp8390mode(Ctlr *ctlr, int on) 
{ 
1993/0212    
	/* 
	 * Set/reset promiscuous mode. 
	 */ 
1992/1222    
	if(on) 
		outb(ctlr->board->dp8390+Rcr, Pro|Ab); 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Rcr, Pro|Ab); 
1992/1222    
	else 
		outb(ctlr->board->dp8390+Rcr, Ab); 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Rcr, Ab); 
1992/1222    
} 
 
void 
dp8390setea(Ctlr *ctlr) 
{ 
	Board *board = ctlr->board; 
	uchar cr; 
	int i; 
 
1992/1222/sys/src/9/pc/ether8390.c:247,3041993/0212/sys/src/9/pc/ether8390.c:254,300
1992/1222    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
	cr = inb(board->dp8390+Cr); 
	outb(board->dp8390+Cr, Page1|(~Page0 & cr)); 
1993/0212    
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1992/1222    
	for(i = 0; i < sizeof(ctlr->ea); i++) 
		outb(board->dp8390+Par0+i, ctlr->ea[i]); 
	outb(board->dp8390+Cr, cr); 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Par0+i, ctlr->ea[i]); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
1992/1222    
} 
 
void* 
dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len) 
{ 
	Board *board = ctlr->board; 
	uchar cr; 
	int timo; 
 
	/* 
	 * If the interface has shared memory, just 
	 * do a memmove. 
	 * In this case, 'from' is an index into the shared memory. 
	 */ 
	if(board->ram){ 
		memmove(to, (void*)(board->ramstart+from), len); 
		return to; 
	} 
                 
	/* 
	 * Read some data at offset 'from' in the board's memory 
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 
	 * 'to' in main memory, via the I/O data port. 
	 */ 
	cr = inb(board->dp8390+Cr); 
	outb(board->dp8390+Cr, Page0|RDMAabort|Sta); 
	outb(board->dp8390+Isr, Rdc); 
1993/0212    
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
1992/1222    
 
	/* 
	 * Set up the remote DMA address and count. 
	 */ 
	if(board->bit16) 
1993/0212    
	if(ctlr->card.bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
	outb(board->dp8390+Rbcr0, len & 0xFF); 
	outb(board->dp8390+Rbcr1, (len>>8) & 0xFF); 
	outb(board->dp8390+Rsar0, from & 0xFF); 
	outb(board->dp8390+Rsar1, (from>>8) & 0xFF); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Rbcr0, len & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar0, from & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar1, (from>>8) & 0xFF); 
1992/1222    
 
	/* 
	 * Start the remote DMA read and suck the data 
	 * out of the I/O port. 
	 */ 
	outb(board->dp8390+Cr, Page0|RDMAread|Sta); 
	if(board->bit16) 
		inss(board->data, to, len/2); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta); 
	if(ctlr->card.bit16) 
		inss(ctlr->card.data, to, len/2); 
1992/1222    
	else 
		insb(board->data, to, len); 
1993/0212    
		insb(ctlr->card.data, to, len); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to complete. The timeout 
1992/1222/sys/src/9/pc/ether8390.c:307,3171993/0212/sys/src/9/pc/ether8390.c:303,313
1992/1222    
	 * to the miracles of the bus, we could get this far 
	 * and still be talking to a slot full of nothing. 
	 */ 
	for(timo = 10000; (inb(board->dp8390+Isr) & Rdc) == 0 && timo; timo--) 
1993/0212    
	for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0 && timo; timo--) 
1992/1222    
			; 
 
	outb(board->dp8390+Isr, Rdc); 
	outb(board->dp8390+Cr, cr); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
1992/1222    
	return to; 
} 
 
1992/1222/sys/src/9/pc/ether8390.c:318,3691993/0212/sys/src/9/pc/ether8390.c:314,372
1992/1222    
void* 
dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len) 
{ 
	Board *board = ctlr->board; 
	uchar cr; 
1993/0212    
	ulong crda; 
1992/1222    
 
	/* 
	 * If the interface has shared memory, just 
	 * do a memmove. 
	 * In this case, 'to' is an index into the shared memory. 
	 */ 
	if(board->ram){ 
		memmove((void*)(board->ramstart+to), from, len); 
		return (void*)to; 
	} 
                 
	/* 
	 * Write some data to offset 'to' in the board's memory 
1993/0212    
	 * Write some data to offset 'to' in the card's memory 
1992/1222    
	 * using the DP8390 remote DMA facility, reading it at 
	 * 'from' in main memory, via the I/O data port. 
	 */ 
	cr = inb(board->dp8390+Cr); 
	outb(board->dp8390+Cr, Page0|RDMAabort|Sta); 
	outb(board->dp8390+Isr, Rdc); 
1993/0212    
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
1992/1222    
 
1993/0212    
	if(ctlr->card.bit16) 
		len = ROUNDUP(len, 2); 
 
1992/1222    
	/* 
	 * Set up the remote DMA address and count. 
	 * This is straight from the datasheet, hence 
	 * the initial write to Rbcr0 and Cr. 
1993/0212    
	 * This is straight from the DP8390[12D] datasheet, hence 
	 * the initial set up for read. 
1992/1222    
	 */ 
	outb(board->dp8390+Rbcr0, 0xFF); 
	outb(board->dp8390+Cr, Page0|RDMAread|Sta); 
1993/0212    
	crda = to-1-ctlr->card.bit16; 
	dp8390outb(ctlr->card.dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar0, crda & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta); 
1992/1222    
 
	if(board->bit16) 
		len = ROUNDUP(len, 2); 
	outb(board->dp8390+Rbcr0, len & 0xFF); 
	outb(board->dp8390+Rbcr1, (len>>8) & 0xFF); 
	outb(board->dp8390+Rsar0, to & 0xFF); 
	outb(board->dp8390+Rsar1, (to>>8) & 0xFF); 
1993/0212    
	for(;;){ 
		crda = dp8390inb(ctlr->card.dp8390+Crda0); 
		crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8; 
		if(crda == to){ 
			/* 
			 * Start the remote DMA write and make sure 
			 * the registers are correct. 
			 */ 
			dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAwrite|Sta); 
1992/1222    
 
1993/0212    
			crda = dp8390inb(ctlr->card.dp8390+Crda0); 
			crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8; 
			if(crda != to) 
				panic("crda write %d to %d\n", crda, to); 
 
			break; 
		} 
	} 
 
1992/1222    
	/* 
	 * Start the remote DMA write and pump the data 
	 * into the I/O port. 
1993/0212    
	 * Pump the data into the I/O port. 
1992/1222    
	 */ 
	outb(board->dp8390+Cr, Page0|RDMAwrite|Sta); 
	if(board->bit16) 
		outss(board->data, from, len/2); 
1993/0212    
	if(ctlr->card.bit16) 
		outss(ctlr->card.data, from, len/2); 
1992/1222    
	else 
		outsb(board->data, from, len); 
1993/0212    
		outsb(ctlr->card.data, from, len); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to finish. We'll need 
1992/1222/sys/src/9/pc/ether8390.c:370,4051993/0212/sys/src/9/pc/ether8390.c:373,407
1992/1222    
	 * a timeout here if this ever gets called before 
	 * we know there really is a chip there. 
	 */ 
	while((inb(board->dp8390+Isr) & Rdc) == 0) 
1993/0212    
	while((dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0) 
1992/1222    
			; 
 
	outb(board->dp8390+Isr, Rdc); 
	outb(board->dp8390+Cr, cr); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
1992/1222    
	return (void*)to; 
} 
 
1993/0212    
static uchar 
getcurr(Ctlr *ctlr) 
{ 
	uchar cr, curr; 
 
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(ctlr->card.dp8390+Curr); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
	return curr; 
} 
 
1992/1222    
void 
dp8390receive(Ctlr *ctlr) 
{ 
	Board *board = ctlr->board; 
	RingBuf *ring; 
	uchar bnry, curr, next; 
1993/0212    
	uchar curr, len1, *pkt; 
1992/1222    
	Hdr hdr; 
	ulong data; 
	int i, len; 
1993/0212    
	ulong data, len; 
1992/1222    
 
	bnry = inb(board->dp8390+Bnry); 
	next = bnry+1; 
	if(next >= board->pstop) 
		next = board->pstart; 
                 
	for(i = 0; ; i++){ 
		outb(board->dp8390+Cr, Page1|RDMAabort|Sta); 
		curr = inb(board->dp8390+Curr); 
		outb(board->dp8390+Cr, Page0|RDMAabort|Sta); 
		if(next == curr) 
			break; 
                 
1993/0212    
	for(curr = getcurr(ctlr); ctlr->card.nxtpkt != curr; curr = getcurr(ctlr)){ 
1992/1222    
		/* 
		 * 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. 
1992/1222/sys/src/9/pc/ether8390.c:411,4211993/0212/sys/src/9/pc/ether8390.c:413,423
1992/1222    
			uchar a, b, c; 
		 
			for(;;delay(10)){ 
				a = inb(board->dp8390+Clda0); 
				b = inb(board->dp8390+Clda0); 
1993/0212    
				a = dp8390inb(ctlr->card.dp8390+Clda0); 
				b = dp8390inb(ctlr->card.dp8390+Clda0); 
1992/1222    
				if(a != b) 
					continue; 
				c = inb(board->dp8390+Clda0); 
1993/0212    
				c = dp8390inb(ctlr->card.dp8390+Clda0); 
1992/1222    
				if(c != b) 
					continue; 
				break; 
1992/1222/sys/src/9/pc/ether8390.c:424,4861993/0212/sys/src/9/pc/ether8390.c:426,564
1992/1222    
 
		ctlr->inpackets++; 
 
		data = next*Dp8390BufSz; 
		dp8390read(ctlr, &hdr, data, sizeof(Hdr)); 
		len = ((hdr.len1<<8)|hdr.len0)-4; 
1993/0212    
		data = ctlr->card.nxtpkt*Dp8390BufSz; 
		(*ctlr->card.read)(ctlr, &hdr, data, sizeof(Hdr)); 
1992/1222    
 
		/* 
		 * Chip is badly scrogged, reinitialise it. 
		 * dp8390reset() calls the disable function. 
		 * There's no need to reload the ethernet 
		 * address. 
		 * 
		 * Untested. 
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    
		 */ 
		if(hdr.next < board->pstart || hdr.next >= board->pstop || len < 60){ 
print("scrogged\n"); 
			dp8390reset(ctlr); 
			dp8390attach(ctlr); 
1993/0212    
		if(hdr.next > ctlr->card.nxtpkt) 
			len1 = hdr.next - ctlr->card.nxtpkt - 1; 
		else 
			len1 = (ctlr->card.pstop-ctlr->card.nxtpkt) + (hdr.next-ctlr->card.pstart) - 1; 
		if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) 
			len1--; 
 
		len = ((len1<<8)|hdr.len0)-4; 
 
		/* 
		 * Chip is badly scrogged, reinitialise the ring. 
		 */ 
		if(hdr.next < ctlr->card.pstart || hdr.next >= ctlr->card.pstop 
		  || 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); 
			dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
			dp8390ring(ctlr); 
			dp8390outb(ctlr->card.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. 
		 */ 
1992/1222    
		ring = &ctlr->rb[ctlr->ri]; 
		if(ring->owner == Interface){ 
			ring->len = len; 
1993/0212    
		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){ 
			pkt = ring->pkt; 
1992/1222    
			data += sizeof(Hdr); 
			if((data+len) >= board->pstop*Dp8390BufSz){ 
				len = board->pstop*Dp8390BufSz - data; 
				dp8390read(ctlr, ring->pkt+len, board->pstart*Dp8390BufSz, 
					(data+ring->len) - board->pstop*Dp8390BufSz); 
1993/0212    
			ring->len = len; 
 
			if((data+len) >= ctlr->card.pstop*Dp8390BufSz){ 
				ulong count = ctlr->card.pstop*Dp8390BufSz - data; 
 
				(*ctlr->card.read)(ctlr, pkt, data, count); 
				pkt += count; 
				data = ctlr->card.pstart*Dp8390BufSz; 
				len -= count; 
1992/1222    
			} 
			dp8390read(ctlr, ring->pkt, data, len); 
1993/0212    
			if(len) 
				(*ctlr->card.read)(ctlr, pkt, data, len); 
 
1992/1222    
			ring->owner = Host; 
			ctlr->ri = NEXT(ctlr->ri, ctlr->nrb); 
		} 
 
		next = hdr.next; 
		bnry = next-1; 
		if(bnry < board->pstart) 
			bnry = board->pstop-1; 
		outb(board->dp8390+Bnry, bnry); 
1993/0212    
		/* 
		 * Finished woth this packet, update the 
		 * hardware and software ring pointers. 
		 */ 
		ctlr->card.nxtpkt = hdr.next; 
 
		hdr.next--; 
		if(hdr.next < ctlr->card.pstart) 
			hdr.next = ctlr->card.pstop-1; 
		dp8390outb(ctlr->card.dp8390+Bnry, hdr.next); 
1992/1222    
	} 
} 
 
1993/0212    
/* 
 * Initiate a transmission. Must be called splhi(). 
 */ 
1992/1222    
void 
dp8390transmit(Ctlr *ctlr) 
{ 
	Board *board; 
	RingBuf *ring; 
1993/0212    
 
	ring = &ctlr->tb[ctlr->ti]; 
	if(ctlr->tbusy == 0 && ring->owner == Interface){ 
		(*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); 
		dp8390outb(ctlr->card.dp8390+Tbcr0, ring->len & 0xFF); 
		dp8390outb(ctlr->card.dp8390+Tbcr1, (ring->len>>8) & 0xFF); 
		dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
		ctlr->tbusy = 1; 
	} 
} 
 
void 
dp8390overflow(Ctlr *ctlr) 
{ 
	uchar txp; 
	int resend; 
 
	/* 
	 * The following procedure is taken from the DP8390[12D] datasheet, 
	 * it seems pretty adamant that this is what has to be done. 
	 */ 
	txp = dp8390inb(ctlr->card.dp8390+Cr) & Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
	delay(2); 
	dp8390outb(ctlr->card.dp8390+Rbcr0, 0); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, 0); 
 
	resend = 0; 
	if(txp && (dp8390inb(ctlr->card.dp8390+Isr) & (Txe|Ptx)) == 0) 
		resend = 1; 
 
	dp8390outb(ctlr->card.dp8390+Tcr, Lb); 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
	(*ctlr->card.receive)(ctlr); 
	dp8390outb(ctlr->card.dp8390+Isr, Ovw); 
	wakeup(&ctlr->rr); 
	dp8390outb(ctlr->card.dp8390+Tcr, 0); 
 
	if(resend) 
		dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
} 
 
void 
dp8390watch(Ctlr *ctlr) 
{ 
1992/1222    
	int s; 
 
1993/0212    
	/* 
	 * Stub watchdog routine. 
	 * Whine if a transmit takes too long. 
	 */ 
1992/1222    
	s = splhi(); 
	board = ctlr->board; 
	ring = &ctlr->tb[ctlr->ti]; 
	if(ring->busy == 0 && ring->owner == Interface){ 
		dp8390write(ctlr, board->tstart*Dp8390BufSz, ring->pkt, ring->len); 
		outb(board->dp8390+Tbcr0, ring->len & 0xFF); 
		outb(board->dp8390+Tbcr1, (ring->len>>8) & 0xFF); 
		outb(board->dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
		ring->busy = 1; 
1993/0212    
	if(ctlr->tbusy){ 
		ctlr->tbusy++; 
		if(ctlr->tbusy > 1 && ctlr->debug) 
			print("TB%d|", ctlr->tbusy); 
1992/1222    
	} 
	splx(s); 
} 
1992/1222/sys/src/9/pc/ether8390.c:488,5241993/0212/sys/src/9/pc/ether8390.c:566,586
1992/1222    
void 
dp8390intr(Ctlr *ctlr) 
{ 
	Board *board = ctlr->board; 
	RingBuf *ring; 
	uchar isr; 
1993/0212    
	uchar isr, r; 
1992/1222    
 
	/* 
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
	 */ 
	while(isr = inb(board->dp8390+Isr)){ 
		outb(board->dp8390+Isr, isr); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Imr, 0x00); 
	while(isr = dp8390inb(ctlr->card.dp8390+Isr)){ 
1992/1222    
 
		if(isr & Ovw){ 
			/* 
			 * Need to do some work here: 
			 *   stop the chip; 
			 *   clear out the ring; 
			 *   re-enable the chip. 
			 * The procedure to put the chip back on 
			 * an active network is to first put it 
			 * into internal loopback mode, enable it, 
			 * then take it out of loopback. 
			 * 
			 * Untested. 
			 */ 
1993/0212    
			if(ctlr->card.overflow) 
				(*ctlr->card.overflow)(ctlr); 
			dp8390outb(ctlr->card.dp8390+Isr, Ovw); 
1992/1222    
			ctlr->overflows++; 
                 
			dp8390disable(ctlr); 
			(*ctlr->board->receive)(ctlr); 
			outb(board->dp8390+Tcr, Lb); 
			outb(board->dp8390+Cr, Page0|RDMAabort|Sta); 
			dp8390attach(ctlr); 
		} 
 
		/* 
1992/1222/sys/src/9/pc/ether8390.c:527,5611993/0212/sys/src/9/pc/ether8390.c:589,631
1992/1222    
		 * wakeup the kproc. 
		 */ 
		if(isr & (Rxe|Prx)){ 
			(*ctlr->board->receive)(ctlr); 
1993/0212    
			(*ctlr->card.receive)(ctlr); 
			dp8390outb(ctlr->card.dp8390+Isr, Rxe|Prx); 
1992/1222    
			wakeup(&ctlr->rr); 
		} 
 
		/* 
		 * Log errors and successful transmissions. 
		 */ 
		if(isr & Txe) 
			ctlr->oerrs++; 
		if(isr & Rxe){ 
			ctlr->frames += inb(board->dp8390+Cntr0); 
			ctlr->crcs += inb(board->dp8390+Cntr1); 
			ctlr->buffs += inb(board->dp8390+Cntr2); 
		} 
		if(isr & Ptx) 
			ctlr->outpackets++; 
                 
		/* 
		 * A packet completed transmission, successfully or 
		 * not. Start transmission on the next buffered packet, 
		 * and wake the output routine. 
		 */ 
		if(isr & (Txe|Ptx)){ 
1993/0212    
			r = dp8390inb(ctlr->card.dp8390+Tsr); 
			if(isr & Txe){ 
				if((r & (Cdh|Fu|Crs|Abt)) && ctlr->debug) 
					print("Tsr#%2.2ux|", r); 
				ctlr->oerrs++; 
			} 
 
			dp8390outb(ctlr->card.dp8390+Isr, Txe|Ptx); 
 
			if(isr & Ptx) 
				ctlr->outpackets++; 
 
1992/1222    
			ring = &ctlr->tb[ctlr->ti]; 
			ring->owner = Host; 
			ring->busy = 0; 
1993/0212    
			ctlr->tbusy = 0; 
1992/1222    
			ctlr->ti = NEXT(ctlr->ti, ctlr->ntb); 
			(*ctlr->board->transmit)(ctlr); 
1993/0212    
			(*ctlr->card.transmit)(ctlr); 
1992/1222    
			wakeup(&ctlr->tr); 
		} 
1993/0212    
 
		if(isr & Cnt){ 
			ctlr->frames += dp8390inb(ctlr->card.dp8390+Cntr0); 
			ctlr->crcs += dp8390inb(ctlr->card.dp8390+Cntr1); 
			ctlr->buffs += dp8390inb(ctlr->card.dp8390+Cntr2); 
			dp8390outb(ctlr->card.dp8390+Isr, Cnt); 
		} 
1992/1222    
	} 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1992/1222    
} 
1993/0212/sys/src/9/pc/ether8390.c:213,2191993/0213/sys/src/9/pc/ether8390.c:213,219 (short | long)
1993/0212    
 
1992/1222    
	/* 
	 * Leave the chip initialised, 
	 * but in internal loopback mode. 
1993/0213    
	 * but in monitor mode. 
1992/1222    
	 */ 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
1992/1222    
} 
1993/0212/sys/src/9/pc/ether8390.c:224,2321993/0213/sys/src/9/pc/ether8390.c:224,234
1992/1222    
	/* 
	 * Enable the chip for transmit/receive. 
1993/0212    
	 * The init routine leaves the chip in monitor 
	 * mode. 
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 
1993/0212/sys/src/9/pc/ether8390.c:393,3981993/0213/sys/src/9/pc/ether8390.c:395,425
1993/0212    
	return curr; 
} 
 
1993/0213    
static void 
cldaquiet(Ctlr *ctlr) 
{ 
	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)){ 
		a = dp8390inb(ctlr->card.dp8390+Clda0); 
		b = dp8390inb(ctlr->card.dp8390+Clda0); 
		if(a != b) 
			continue; 
		c = dp8390inb(ctlr->card.dp8390+Clda0); 
		if(c != b) 
			continue; 
		break; 
	} 
} 
 
1992/1222    
void 
dp8390receive(Ctlr *ctlr) 
{ 
1993/0212/sys/src/9/pc/ether8390.c:402,4281993/0213/sys/src/9/pc/ether8390.c:429,436
1993/0212    
	ulong data, len; 
1992/1222    
 
1993/0212    
	for(curr = getcurr(ctlr); ctlr->card.nxtpkt != curr; curr = getcurr(ctlr)){ 
1992/1222    
		/* 
		 * 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. 
		 */ 
		if(strcmp(arch->id, "NCRD.0") == 0){ 
			uchar a, b, c; 
		                 
			for(;;delay(10)){ 
1993/0212    
				a = dp8390inb(ctlr->card.dp8390+Clda0); 
				b = dp8390inb(ctlr->card.dp8390+Clda0); 
1992/1222    
				if(a != b) 
					continue; 
1993/0212    
				c = dp8390inb(ctlr->card.dp8390+Clda0); 
1992/1222    
				if(c != b) 
					continue; 
				break; 
			} 
		} 
1993/0213    
		if(strcmp(arch->id, "NCRD.0") == 0) 
			cldaquiet(ctlr); 
1992/1222    
 
		ctlr->inpackets++; 
 
1993/0212/sys/src/9/pc/ether8390.c:506,5161993/0213/sys/src/9/pc/ether8390.c:514,527
1993/0212    
 
	ring = &ctlr->tb[ctlr->ti]; 
	if(ctlr->tbusy == 0 && ring->owner == Interface){ 
1993/0213    
 
		ctlr->tbusy = 1; 
 
1993/0212    
		(*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); 
1993/0213    
 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Tbcr0, ring->len & 0xFF); 
		dp8390outb(ctlr->card.dp8390+Tbcr1, (ring->len>>8) & 0xFF); 
		dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
		ctlr->tbusy = 1; 
	} 
} 
 
1993/0213/sys/src/9/pc/ether8390.c:149,1561993/0915/sys/src/9/pc/ether8390.c:149,158 (short | long)
1992/1222    
static void 
dp8390disable(Ctlr *ctlr) 
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	int timo; 
 
1993/0915    
	dp8390 = ctlr->card.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/0213/sys/src/9/pc/ether8390.c:159,1681993/0915/sys/src/9/pc/ether8390.c:161,170
1992/1222    
	 * chip there if this is called when probing for a device 
	 * at boot. 
	 */ 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(ctlr->card.dp8390+Rbcr0, 0); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rst) == 0 && timo; timo--) 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--) 
1992/1222    
			; 
} 
 
1993/0213/sys/src/9/pc/ether8390.c:169,1821993/0915/sys/src/9/pc/ether8390.c:171,187
1993/0212    
static void 
dp8390ring(Ctlr *ctlr) 
{ 
	dp8390outb(ctlr->card.dp8390+Pstart, ctlr->card.pstart); 
	dp8390outb(ctlr->card.dp8390+Pstop, ctlr->card.pstop); 
	dp8390outb(ctlr->card.dp8390+Bnry, ctlr->card.pstop-1); 
1993/0915    
	ulong dp8390; 
1993/0212    
 
	dp8390outb(ctlr->card.dp8390+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(ctlr->card.dp8390+Curr, ctlr->card.pstart); 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
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/0212    
 
1993/0915    
	dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(dp8390+Curr, ctlr->card.pstart); 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
 
1993/0212    
	ctlr->card.nxtpkt = ctlr->card.pstart; 
} 
 
1993/0213/sys/src/9/pc/ether8390.c:183,1881993/0915/sys/src/9/pc/ether8390.c:188,196
1992/1222    
void 
dp8390reset(Ctlr *ctlr) 
{ 
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 
1993/0213/sys/src/9/pc/ether8390.c:190,2041993/0915/sys/src/9/pc/ether8390.c:198,212
1992/1222    
	 */  
	dp8390disable(ctlr); 
1993/0212    
	if(ctlr->card.bit16) 
		dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls|Wts); 
1993/0915    
		dp8390outb(dp8390+Dcr, Ft4|Ls|Wts); 
1992/1222    
	else 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls); 
1993/0915    
		dp8390outb(dp8390+Dcr, Ft4|Ls); 
1992/1222    
 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Rbcr0, 0); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, 0); 
1993/0915    
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
1992/1222    
 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Tcr, 0); 
	dp8390outb(ctlr->card.dp8390+Rcr, Mon); 
1993/0915    
	dp8390outb(dp8390+Tcr, 0); 
	dp8390outb(dp8390+Rcr, Mon); 
1992/1222    
 
	/* 
1993/0212    
	 * Init the ring hardware and software ring pointers. 
1993/0213/sys/src/9/pc/ether8390.c:206,2211993/0915/sys/src/9/pc/ether8390.c:214,229
1993/0212    
	 * it yet. 
1992/1222    
	 */ 
1993/0212    
	dp8390ring(ctlr); 
	dp8390outb(ctlr->card.dp8390+Tpsr, ctlr->card.tstart); 
1993/0915    
	dp8390outb(dp8390+Tpsr, ctlr->card.tstart); 
1992/1222    
 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Isr, 0xFF); 
	dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
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/0212    
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1992/1222    
} 
 
void 
1993/0213/sys/src/9/pc/ether8390.c:246,2541993/0915/sys/src/9/pc/ether8390.c:254,264
1992/1222    
void 
dp8390setea(Ctlr *ctlr) 
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	uchar cr; 
	int i; 
 
1993/0915    
	dp8390 = ctlr->card.dp8390; 
1992/1222    
	/* 
	 * Set the ethernet address into the chip. 
	 * Take care to restore the command register 
1993/0213/sys/src/9/pc/ether8390.c:256,2821993/0915/sys/src/9/pc/ether8390.c:266,316
1992/1222    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1993/0212    
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
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/0212    
		dp8390outb(ctlr->card.dp8390+Par0+i, ctlr->ea[i]); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
1993/0915    
		dp8390outb(dp8390+Par0+i, ctlr->ea[i]); 
	dp8390outb(dp8390+Cr, cr); 
1992/1222    
} 
 
1993/0915    
void 
dp8390getea(Ctlr *ctlr) 
{ 
	ulong dp8390; 
	uchar cr; 
	int i; 
 
	dp8390 = ctlr->card.dp8390; 
	/* 
	 * Set the ethernet address into the chip. 
	 * Take care to restore the command register 
	 * afterwards. We don't care about multicast 
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
	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); 
	dp8390outb(dp8390+Cr, cr); 
} 
 
1992/1222    
void* 
dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len) 
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	uchar cr; 
	int timo; 
 
1993/0915    
	dp8390 = ctlr->card.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 
	 * 'to' in main memory, via the I/O data port. 
	 */ 
1993/0212    
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(dp8390+Isr, Rdc); 
1992/1222    
 
	/* 
	 * Set up the remote DMA address and count. 
1993/0213/sys/src/9/pc/ether8390.c:283,2981993/0915/sys/src/9/pc/ether8390.c:317,332
1992/1222    
	 */ 
1993/0212    
	if(ctlr->card.bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Rbcr0, len & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar0, from & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar1, (from>>8) & 0xFF); 
1993/0915    
	dp8390outb(dp8390+Rbcr0, len & 0xFF); 
	dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(dp8390+Rsar0, from & 0xFF); 
	dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF); 
1992/1222    
 
	/* 
	 * Start the remote DMA read and suck the data 
	 * out of the I/O port. 
	 */ 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta); 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); 
1993/0212    
	if(ctlr->card.bit16) 
		inss(ctlr->card.data, to, len/2); 
1992/1222    
	else 
1993/0213/sys/src/9/pc/ether8390.c:305,3151993/0915/sys/src/9/pc/ether8390.c:339,349
1992/1222    
	 * to the miracles of the bus, we could get this far 
	 * and still be talking to a slot full of nothing. 
	 */ 
1993/0212    
	for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0 && timo; timo--) 
1993/0915    
	for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--) 
1992/1222    
			; 
 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
1993/0915    
	dp8390outb(dp8390+Isr, Rdc); 
	dp8390outb(dp8390+Cr, cr); 
1992/1222    
	return to; 
} 
 
1993/0213/sys/src/9/pc/ether8390.c:316,3321993/0915/sys/src/9/pc/ether8390.c:350,367
1992/1222    
void* 
dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len) 
{ 
1993/0915    
	ulong dp8390, crda; 
1992/1222    
	uchar cr; 
1993/0212    
	ulong crda; 
1992/1222    
 
1993/0915    
	dp8390 = ctlr->card.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 
	 * 'from' in main memory, via the I/O data port. 
	 */ 
1993/0212    
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(dp8390+Isr, Rdc); 
1992/1222    
 
1993/0212    
	if(ctlr->card.bit16) 
		len = ROUNDUP(len, 2); 
1993/0213/sys/src/9/pc/ether8390.c:337,3601993/0915/sys/src/9/pc/ether8390.c:372,395
1993/0212    
	 * the initial set up for read. 
1992/1222    
	 */ 
1993/0212    
	crda = to-1-ctlr->card.bit16; 
	dp8390outb(ctlr->card.dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar0, crda & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta); 
1993/0915    
	dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF); 
	dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF); 
	dp8390outb(dp8390+Rsar0, crda & 0xFF); 
	dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); 
1992/1222    
 
1993/0212    
	for(;;){ 
		crda = dp8390inb(ctlr->card.dp8390+Crda0); 
		crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8; 
1993/0915    
		crda = dp8390inb(dp8390+Crda0); 
		crda |= dp8390inb(dp8390+Crda1)<<8; 
1993/0212    
		if(crda == to){ 
			/* 
			 * Start the remote DMA write and make sure 
			 * the registers are correct. 
			 */ 
			dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAwrite|Sta); 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta); 
1992/1222    
 
1993/0212    
			crda = dp8390inb(ctlr->card.dp8390+Crda0); 
			crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8; 
1993/0915    
			crda = dp8390inb(dp8390+Crda0); 
			crda |= dp8390inb(dp8390+Crda1)<<8; 
1993/0212    
			if(crda != to) 
				panic("crda write %d to %d\n", crda, to); 
 
1993/0213/sys/src/9/pc/ether8390.c:375,4021993/0915/sys/src/9/pc/ether8390.c:410,437
1992/1222    
	 * a timeout here if this ever gets called before 
	 * we know there really is a chip there. 
	 */ 
1993/0212    
	while((dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0) 
1993/0915    
	while((dp8390inb(dp8390+Isr) & Rdc) == 0) 
1992/1222    
			; 
 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Isr, Rdc); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
1993/0915    
	dp8390outb(dp8390+Isr, Rdc); 
	dp8390outb(dp8390+Cr, cr); 
1992/1222    
	return (void*)to; 
} 
 
1993/0212    
static uchar 
getcurr(Ctlr *ctlr) 
1993/0915    
getcurr(ulong dp8390) 
1993/0212    
{ 
	uchar cr, curr; 
 
	cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(ctlr->card.dp8390+Curr); 
	dp8390outb(ctlr->card.dp8390+Cr, cr); 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(dp8390+Curr); 
	dp8390outb(dp8390+Cr, cr); 
1993/0212    
	return curr; 
} 
 
1993/0213    
static void 
cldaquiet(Ctlr *ctlr) 
1993/0915    
cldaquiet(ulong dp8390) 
1993/0213    
{ 
	uchar a, b, c; 
 
1993/0213/sys/src/9/pc/ether8390.c:409,4191993/0915/sys/src/9/pc/ether8390.c:444,454
1993/0213    
	 */ 
	 
	for(;;delay(10)){ 
		a = dp8390inb(ctlr->card.dp8390+Clda0); 
		b = dp8390inb(ctlr->card.dp8390+Clda0); 
1993/0915    
		a = dp8390inb(dp8390+Clda0); 
		b = dp8390inb(dp8390+Clda0); 
1993/0213    
		if(a != b) 
			continue; 
		c = dp8390inb(ctlr->card.dp8390+Clda0); 
1993/0915    
		c = dp8390inb(dp8390+Clda0); 
1993/0213    
		if(c != b) 
			continue; 
		break; 
1993/0213/sys/src/9/pc/ether8390.c:426,4361993/0915/sys/src/9/pc/ether8390.c:461,472
1992/1222    
	RingBuf *ring; 
1993/0212    
	uchar curr, len1, *pkt; 
1992/1222    
	Hdr hdr; 
1993/0212    
	ulong data, len; 
1993/0915    
	ulong dp8390, data, len; 
1992/1222    
 
1993/0212    
	for(curr = getcurr(ctlr); ctlr->card.nxtpkt != curr; curr = getcurr(ctlr)){ 
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) 
			cldaquiet(ctlr); 
1993/0915    
			cldaquiet(dp8390); 
1992/1222    
 
		ctlr->inpackets++; 
 
1993/0213/sys/src/9/pc/ether8390.c:458,4661993/0915/sys/src/9/pc/ether8390.c:494,502
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); 
			dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
1993/0212    
			dp8390ring(ctlr); 
			dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1992/1222    
			return; 
		} 
 
1993/0213/sys/src/9/pc/ether8390.c:500,5061993/0915/sys/src/9/pc/ether8390.c:536,542
1993/0212    
		hdr.next--; 
		if(hdr.next < ctlr->card.pstart) 
			hdr.next = ctlr->card.pstop-1; 
		dp8390outb(ctlr->card.dp8390+Bnry, hdr.next); 
1993/0915    
		dp8390outb(dp8390+Bnry, hdr.next); 
1992/1222    
	} 
} 
 
1993/0213/sys/src/9/pc/ether8390.c:510,5171993/0915/sys/src/9/pc/ether8390.c:546,555
1992/1222    
void 
dp8390transmit(Ctlr *ctlr) 
{ 
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/0213    
 
1993/0213/sys/src/9/pc/ether8390.c:519,5271993/0915/sys/src/9/pc/ether8390.c:557,565
1993/0213    
 
1993/0212    
		(*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len); 
1993/0213    
 
1993/0212    
		dp8390outb(ctlr->card.dp8390+Tbcr0, ring->len & 0xFF); 
		dp8390outb(ctlr->card.dp8390+Tbcr1, (ring->len>>8) & 0xFF); 
		dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0915    
		dp8390outb(dp8390+Tbcr0, ring->len & 0xFF); 
		dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF); 
		dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0212    
	} 
} 
 
1993/0213/sys/src/9/pc/ether8390.c:528,5591993/0915/sys/src/9/pc/ether8390.c:566,599
1993/0212    
void 
dp8390overflow(Ctlr *ctlr) 
{ 
1993/0915    
	ulong dp8390; 
1993/0212    
	uchar txp; 
	int resend; 
 
1993/0915    
	dp8390 = ctlr->card.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. 
	 */ 
	txp = dp8390inb(ctlr->card.dp8390+Cr) & Txp; 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp); 
1993/0915    
	txp = dp8390inb(dp8390+Cr) & Txp; 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
1993/0212    
	delay(2); 
	dp8390outb(ctlr->card.dp8390+Rbcr0, 0); 
	dp8390outb(ctlr->card.dp8390+Rbcr1, 0); 
1993/0915    
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
1993/0212    
 
	resend = 0; 
	if(txp && (dp8390inb(ctlr->card.dp8390+Isr) & (Txe|Ptx)) == 0) 
1993/0915    
	if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0) 
1993/0212    
		resend = 1; 
 
	dp8390outb(ctlr->card.dp8390+Tcr, Lb); 
	dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta); 
1993/0915    
	dp8390outb(dp8390+Tcr, Lb); 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1993/0212    
	(*ctlr->card.receive)(ctlr); 
	dp8390outb(ctlr->card.dp8390+Isr, Ovw); 
1993/0915    
	dp8390outb(dp8390+Isr, Ovw); 
1993/0212    
	wakeup(&ctlr->rr); 
	dp8390outb(ctlr->card.dp8390+Tcr, 0); 
1993/0915    
	dp8390outb(dp8390+Tcr, 0); 
1993/0212    
 
	if(resend) 
		dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0915    
		dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0212    
} 
 
void 
1993/0213/sys/src/9/pc/ether8390.c:577,5961993/0915/sys/src/9/pc/ether8390.c:617,638
1992/1222    
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; 
1992/1222    
	/* 
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
	 */ 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Imr, 0x00); 
	while(isr = dp8390inb(ctlr->card.dp8390+Isr)){ 
1993/0915    
	dp8390outb(dp8390+Imr, 0x00); 
	while(isr = dp8390inb(dp8390+Isr)){ 
1992/1222    
 
		if(isr & Ovw){ 
1993/0212    
			if(ctlr->card.overflow) 
				(*ctlr->card.overflow)(ctlr); 
			dp8390outb(ctlr->card.dp8390+Isr, Ovw); 
1993/0915    
			dp8390outb(dp8390+Isr, Ovw); 
1992/1222    
			ctlr->overflows++; 
		} 
 
1993/0213/sys/src/9/pc/ether8390.c:601,6071993/0915/sys/src/9/pc/ether8390.c:643,649
1992/1222    
		 */ 
		if(isr & (Rxe|Prx)){ 
1993/0212    
			(*ctlr->card.receive)(ctlr); 
			dp8390outb(ctlr->card.dp8390+Isr, Rxe|Prx); 
1993/0915    
			dp8390outb(dp8390+Isr, Rxe|Prx); 
1992/1222    
			wakeup(&ctlr->rr); 
		} 
 
1993/0213/sys/src/9/pc/ether8390.c:611,6171993/0915/sys/src/9/pc/ether8390.c:653,659
1992/1222    
		 * and wake the output routine. 
		 */ 
		if(isr & (Txe|Ptx)){ 
1993/0212    
			r = dp8390inb(ctlr->card.dp8390+Tsr); 
1993/0915    
			r = dp8390inb(dp8390+Tsr); 
1993/0212    
			if(isr & Txe){ 
				if((r & (Cdh|Fu|Crs|Abt)) && ctlr->debug) 
					print("Tsr#%2.2ux|", r); 
1993/0213/sys/src/9/pc/ether8390.c:618,6241993/0915/sys/src/9/pc/ether8390.c:660,666
1993/0212    
				ctlr->oerrs++; 
			} 
 
			dp8390outb(ctlr->card.dp8390+Isr, Txe|Ptx); 
1993/0915    
			dp8390outb(dp8390+Isr, Txe|Ptx); 
1993/0212    
 
			if(isr & Ptx) 
				ctlr->outpackets++; 
1993/0213/sys/src/9/pc/ether8390.c:632,6421993/0915/sys/src/9/pc/ether8390.c:674,684
1992/1222    
		} 
1993/0212    
 
		if(isr & Cnt){ 
			ctlr->frames += dp8390inb(ctlr->card.dp8390+Cntr0); 
			ctlr->crcs += dp8390inb(ctlr->card.dp8390+Cntr1); 
			ctlr->buffs += dp8390inb(ctlr->card.dp8390+Cntr2); 
			dp8390outb(ctlr->card.dp8390+Isr, Cnt); 
1993/0915    
			ctlr->frames += dp8390inb(dp8390+Cntr0); 
			ctlr->crcs += dp8390inb(dp8390+Cntr1); 
			ctlr->buffs += dp8390inb(dp8390+Cntr2); 
			dp8390outb(dp8390+Isr, Cnt); 
1993/0212    
		} 
1992/1222    
	} 
1993/0212    
	dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/0915    
	dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1992/1222    
} 
1993/0915/sys/src/9/pc/ether8390.c:8,181993/1116/sys/src/9/pc/ether8390.c:8,18 (short | long)
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    
} 
1993/1116/sys/src/9/pc/ether8390.c:147,1581993/1117/sys/src/9/pc/ether8390.c:147,158 (short | long)
1992/1222    
} Hdr; 
 
static void 
1993/1116    
dp8390disable(Ether *ether) 
1993/1117    
dp8390disable(Dp8390 *dp8390) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
1993/1117    
	ulong port; 
1992/1222    
	int timo; 
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	port = dp8390->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/1116/sys/src/9/pc/ether8390.c:161,1981993/1117/sys/src/9/pc/ether8390.c:161,198
1992/1222    
	 * chip there if this is called when probing for a device 
	 * at boot. 
	 */ 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--) 
1993/1117    
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--) 
1992/1222    
			; 
} 
 
1993/0212    
static void 
1993/1116    
dp8390ring(Ether *ether) 
1993/1117    
dp8390ring(Dp8390 *dp8390) 
1993/0212    
{ 
1993/0915    
	ulong dp8390; 
1993/1117    
	ulong port; 
1993/0212    
 
1993/1116    
	dp8390 = ether->dp8390; 
	dp8390outb(dp8390+Pstart, ether->pstart); 
	dp8390outb(dp8390+Pstop, ether->pstop); 
	dp8390outb(dp8390+Bnry, ether->pstop-1); 
1993/1117    
	port = dp8390->dp8390; 
	dp8390outb(port+Pstart, dp8390->pstart); 
	dp8390outb(port+Pstop, dp8390->pstop); 
	dp8390outb(port+Bnry, dp8390->pstop-1); 
1993/0212    
 
1993/0915    
	dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp); 
1993/1116    
	dp8390outb(dp8390+Curr, ether->pstart); 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
1993/1117    
	dp8390outb(port+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(port+Curr, dp8390->pstart); 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1993/0915    
 
1993/1116    
	ether->nxtpkt = ether->pstart; 
1993/1117    
	dp8390->nxtpkt = dp8390->pstart; 
1993/0212    
} 
 
1992/1222    
void 
1993/1116    
dp8390setea(Ether *ether) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
1993/1117    
	ulong port; 
1992/1222    
	uchar cr; 
	int i; 
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	port = ((Dp8390*)ether->private)->dp8390; 
1992/1222    
	/* 
	 * Set the ethernet address into the chip. 
	 * Take care to restore the command register 
1993/1116/sys/src/9/pc/ether8390.c:200,2201993/1117/sys/src/9/pc/ether8390.c:200,220
1992/1222    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1117    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
		dp8390outb(dp8390+Par0+i, ether->ea[i]); 
1993/0915    
	dp8390outb(dp8390+Cr, cr); 
1993/1117    
		dp8390outb(port+Par0+i, ether->ea[i]); 
	dp8390outb(port+Cr, cr); 
1992/1222    
} 
 
1993/0915    
void 
1993/1116    
dp8390getea(Ether *ether) 
1993/0915    
{ 
	ulong dp8390; 
1993/1117    
	ulong port; 
1993/0915    
	uchar cr; 
	int i; 
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	port = ((Dp8390*)ether->private)->dp8390; 
1993/0915    
	/* 
1993/1116    
	 * Get the ethernet address from the chip. 
1993/0915    
	 * Take care to restore the command register 
1993/1116/sys/src/9/pc/ether8390.c:222,2701993/1117/sys/src/9/pc/ether8390.c:222,270
1993/0915    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1117    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
		ether->ea[i] = dp8390inb(dp8390+Par0+i); 
1993/0915    
	dp8390outb(dp8390+Cr, cr); 
1993/1117    
		ether->ea[i] = dp8390inb(port+Par0+i); 
	dp8390outb(port+Cr, cr); 
1993/0915    
} 
 
1993/1116    
static void* 
dp8390read(Ether *ether, void *to, ulong from, ulong len) 
1993/1117    
dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
1993/1117    
	ulong port; 
1992/1222    
	uchar cr; 
	int timo; 
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	port = dp8390->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 
	 * 'to' in main memory, via the I/O data port. 
	 */ 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(dp8390+Isr, Rdc); 
1993/1117    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1992/1222    
 
	/* 
	 * Set up the remote DMA address and count. 
	 */ 
1993/1116    
	if(ether->bit16) 
1993/1117    
	if(dp8390->bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
1993/0915    
	dp8390outb(dp8390+Rbcr0, len & 0xFF); 
	dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(dp8390+Rsar0, from & 0xFF); 
	dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF); 
1993/1117    
	dp8390outb(port+Rbcr0, len & 0xFF); 
	dp8390outb(port+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(port+Rsar0, from & 0xFF); 
	dp8390outb(port+Rsar1, (from>>8) & 0xFF); 
1992/1222    
 
	/* 
	 * Start the remote DMA read and suck the data 
	 * out of the I/O port. 
	 */ 
1993/0915    
	dp8390outb(dp8390+Cr, Page0|RDMAread|Sta); 
1993/1116    
	if(ether->bit16) 
		inss(ether->data, to, len/2); 
1993/1117    
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
	if(dp8390->bit16) 
		inss(dp8390->data, to, len/2); 
1992/1222    
	else 
1993/1116    
		insb(ether->data, to, len); 
1993/1117    
		insb(dp8390->data, to, len); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to complete. The timeout 
1993/1116/sys/src/9/pc/ether8390.c:273,2831993/1117/sys/src/9/pc/ether8390.c:273,283
1992/1222    
	 * to the miracles of the bus, we could get this far 
	 * and still be talking to a slot full of nothing. 
	 */ 
1993/0915    
	for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--) 
1993/1117    
	for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--) 
1992/1222    
			; 
 
1993/0915    
	dp8390outb(dp8390+Isr, Rdc); 
	dp8390outb(dp8390+Cr, cr); 
1993/1117    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1992/1222    
	return to; 
} 
 
1993/1116/sys/src/9/pc/ether8390.c:287,2931993/1117/sys/src/9/pc/ether8390.c:287,293
1993/0915    
	ulong dp8390, crda; 
1992/1222    
	uchar cr; 
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->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/1116/sys/src/9/pc/ether8390.c:373,3791993/1117/sys/src/9/pc/ether8390.c:373,379
1993/1116    
	ushort type; 
	Netfile *f, **fp, **ep; 
1992/1222    
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	for(curr = getcurr(dp8390); ether->nxtpkt != curr; curr = getcurr(dp8390)){ 
		ether->inpackets++; 
1992/1222    
 
1993/1116/sys/src/9/pc/ether8390.c:461,4671993/1117/sys/src/9/pc/ether8390.c:461,467
1993/0915    
	ulong dp8390; 
1992/1222    
	RingBuf *ring; 
1993/0212    
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	ring = ðer->tb[ether->ti]; 
	if(ether->tbusy == 0 && ring->owner == Interface){ 
1993/0213    
 
1993/1116/sys/src/9/pc/ether8390.c:482,4881993/1117/sys/src/9/pc/ether8390.c:482,488
1993/0212    
	uchar txp; 
	int resend; 
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->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/1116/sys/src/9/pc/ether8390.c:514,5201993/1117/sys/src/9/pc/ether8390.c:514,520
1993/0915    
	ulong dp8390; 
1993/0212    
	uchar isr, r; 
1992/1222    
 
1993/1116    
	dp8390 = ether->dp8390; 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1992/1222    
	/* 
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
1993/1116/sys/src/9/pc/ether8390.c:570,5751993/1117/sys/src/9/pc/ether8390.c:570,578
1993/1116    
static void 
promiscuous(Ether *ether, int on) 
{ 
1993/1117    
	ulong dp8390; 
 
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	/* 
	 * Set/reset promiscuous mode. 
	 */ 
1993/1116/sys/src/9/pc/ether8390.c:582,5871993/1117/sys/src/9/pc/ether8390.c:585,593
1993/1116    
void 
dp8390attach(Ether *ether) 
{ 
1993/1117    
	ulong dp8390; 
 
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	/* 
	 * Enable the chip for transmit/receive. 
	 * The init routine leaves the chip in monitor 
1993/1116/sys/src/9/pc/ether8390.c:597,6031993/1117/sys/src/9/pc/ether8390.c:603,609
1993/1116    
{ 
	ulong dp8390; 
 
	dp8390 = ether->dp8390; 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	/* 
	 * This is the initialisation procedure described 
	 * as 'mandatory' in the datasheet, with references 
1993/1117/sys/src/9/pc/ether8390.c:14,191993/1118/sys/src/9/pc/ether8390.c:14,22 (short | long)
1992/1222    
 
1993/1116    
#include "etherif.h" 
1992/1222    
 
1993/1118    
extern int dp8390inb(ulong); 
extern void dp8390outb(ulong, uchar); 
 
1992/1222    
enum { 
	Cr		= 0x00,		/* command register, all pages */ 
 
1993/1117/sys/src/9/pc/ether8390.c:149,1581993/1118/sys/src/9/pc/ether8390.c:152,160
1992/1222    
static void 
1993/1117    
dp8390disable(Dp8390 *dp8390) 
1992/1222    
{ 
1993/1117    
	ulong port; 
1993/1118    
	ulong port = dp8390->dp8390; 
1992/1222    
	int timo; 
 
1993/1117    
	port = dp8390->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/1117/sys/src/9/pc/ether8390.c:171,1791993/1118/sys/src/9/pc/ether8390.c:173,180
1993/0212    
static void 
1993/1117    
dp8390ring(Dp8390 *dp8390) 
1993/0212    
{ 
1993/1117    
	ulong port; 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
 
1993/1117    
	port = dp8390->dp8390; 
	dp8390outb(port+Pstart, dp8390->pstart); 
	dp8390outb(port+Pstop, dp8390->pstop); 
	dp8390outb(port+Bnry, dp8390->pstop-1); 
1993/1117/sys/src/9/pc/ether8390.c:188,1981993/1118/sys/src/9/pc/ether8390.c:189,198
1992/1222    
void 
1993/1116    
dp8390setea(Ether *ether) 
1992/1222    
{ 
1993/1117    
	ulong port; 
1993/1118    
	ulong port = ((Dp8390*)ether->private)->dp8390; 
1992/1222    
	uchar cr; 
	int i; 
 
1993/1117    
	port = ((Dp8390*)ether->private)->dp8390; 
1992/1222    
	/* 
	 * Set the ethernet address into the chip. 
	 * Take care to restore the command register 
1993/1117/sys/src/9/pc/ether8390.c:210,2201993/1118/sys/src/9/pc/ether8390.c:210,219
1993/0915    
void 
1993/1116    
dp8390getea(Ether *ether) 
1993/0915    
{ 
1993/1117    
	ulong port; 
1993/1118    
	ulong port = ((Dp8390*)ether->private)->dp8390; 
1993/0915    
	uchar cr; 
	int i; 
 
1993/1117    
	port = ((Dp8390*)ether->private)->dp8390; 
1993/0915    
	/* 
1993/1116    
	 * Get the ethernet address from the chip. 
1993/0915    
	 * Take care to restore the command register 
1993/1117/sys/src/9/pc/ether8390.c:232,2421993/1118/sys/src/9/pc/ether8390.c:231,240
1993/1116    
static void* 
1993/1117    
dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) 
1992/1222    
{ 
1993/1117    
	ulong port; 
1993/1118    
	ulong port = dp8390->dp8390; 
1992/1222    
	uchar cr; 
	int timo; 
 
1993/1117    
	port = dp8390->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/1117/sys/src/9/pc/ether8390.c:282,3031993/1118/sys/src/9/pc/ether8390.c:280,301
1992/1222    
} 
 
1993/1116    
static void* 
dp8390write(Ether *ether, ulong to, void *from, ulong len) 
1993/1118    
dp8390write(Dp8390 *dp8390, ulong to, void *from, ulong len) 
1992/1222    
{ 
1993/0915    
	ulong dp8390, crda; 
1993/1118    
	ulong port = dp8390->dp8390; 
	ulong crda; 
1992/1222    
	uchar cr; 
 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->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 
	 * 'from' in main memory, via the I/O data port. 
	 */ 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(dp8390+Isr, Rdc); 
1993/1118    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1992/1222    
 
1993/1116    
	if(ether->bit16) 
1993/1118    
	if(dp8390->bit16) 
1993/0212    
		len = ROUNDUP(len, 2); 
 
1992/1222    
	/* 
1993/1117/sys/src/9/pc/ether8390.c:305,3291993/1118/sys/src/9/pc/ether8390.c:303,327
1993/0212    
	 * This is straight from the DP8390[12D] datasheet, hence 
	 * the initial set up for read. 
1992/1222    
	 */ 
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/1118    
	crda = to-1-dp8390->bit16; 
	dp8390outb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	dp8390outb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	dp8390outb(port+Rsar0, crda & 0xFF); 
	dp8390outb(port+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
1992/1222    
 
1993/0212    
	for(;;){ 
1993/0915    
		crda = dp8390inb(dp8390+Crda0); 
		crda |= dp8390inb(dp8390+Crda1)<<8; 
1993/1118    
		crda = dp8390inb(port+Crda0); 
		crda |= dp8390inb(port+Crda1)<<8; 
1993/0212    
		if(crda == to){ 
			/* 
			 * Start the remote DMA write and make sure 
			 * the registers are correct. 
			 */ 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta); 
1993/1118    
			dp8390outb(port+Cr, Page0|RDMAwrite|Sta); 
1992/1222    
 
1993/0915    
			crda = dp8390inb(dp8390+Crda0); 
			crda |= dp8390inb(dp8390+Crda1)<<8; 
1993/1118    
			crda = dp8390inb(port+Crda0); 
			crda |= dp8390inb(port+Crda1)<<8; 
1993/0212    
			if(crda != to) 
				panic("crda write %d to %d\n", crda, to); 
 
1993/1117/sys/src/9/pc/ether8390.c:334,3431993/1118/sys/src/9/pc/ether8390.c:332,341
1992/1222    
	/* 
1993/0212    
	 * Pump the data into the I/O port. 
1992/1222    
	 */ 
1993/1116    
	if(ether->bit16) 
		outss(ether->data, from, len/2); 
1993/1118    
	if(dp8390->bit16) 
		outss(dp8390->data, from, len/2); 
1992/1222    
	else 
1993/1116    
		outsb(ether->data, from, len); 
1993/1118    
		outsb(dp8390->data, from, len); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to finish. We'll need 
1993/1117/sys/src/9/pc/ether8390.c:344,3661993/1118/sys/src/9/pc/ether8390.c:342,365
1992/1222    
	 * a timeout here if this ever gets called before 
	 * we know there really is a chip there. 
	 */ 
1993/0915    
	while((dp8390inb(dp8390+Isr) & Rdc) == 0) 
1993/1118    
	while((dp8390inb(port+Isr) & Rdc) == 0) 
1992/1222    
			; 
 
1993/0915    
	dp8390outb(dp8390+Isr, Rdc); 
	dp8390outb(dp8390+Cr, cr); 
1993/1118    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1992/1222    
	return (void*)to; 
} 
 
1993/0212    
static uchar 
1993/0915    
getcurr(ulong dp8390) 
1993/1118    
getcurr(Dp8390 *dp8390) 
1993/0212    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
	uchar cr, curr; 
 
1993/0915    
	cr = dp8390inb(dp8390+Cr) & ~Txp; 
	dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(dp8390+Curr); 
	dp8390outb(dp8390+Cr, cr); 
1993/1118    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(port+Curr); 
	dp8390outb(port+Cr, cr); 
1993/0212    
	return curr; 
} 
 
1993/1117/sys/src/9/pc/ether8390.c:367,3841993/1118/sys/src/9/pc/ether8390.c:366,388
1993/0213    
static void 
1993/1116    
receive(Ether *ether) 
1993/0213    
{ 
1993/0212    
	uchar curr, len1, *pkt; 
1993/1118    
	Dp8390 *dp8390; 
	uchar curr, *pkt; 
1992/1222    
	Hdr hdr; 
1993/0915    
	ulong dp8390, data, len; 
1993/1118    
	ulong port, data, len, len1; 
1993/1116    
	ushort type; 
	Netfile *f, **fp, **ep; 
1992/1222    
 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	for(curr = getcurr(dp8390); ether->nxtpkt != curr; curr = getcurr(dp8390)){ 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
	for(curr = getcurr(dp8390); dp8390->nxtpkt != curr; curr = getcurr(dp8390)){ 
1993/1116    
		ether->inpackets++; 
1992/1222    
 
1993/1116    
		data = ether->nxtpkt*Dp8390BufSz; 
		(*ether->read)(ctlr, &hdr, data, sizeof(Hdr)); 
1993/1118    
		data = dp8390->nxtpkt*Dp8390BufSz; 
		if(dp8390->ram) 
			memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr)); 
		else 
			dp8390read(dp8390, &hdr, data, sizeof(Hdr)); 
1992/1222    
 
		/* 
1993/0212    
		 * Don't believe the upper byte count, work it 
1993/1117/sys/src/9/pc/ether8390.c:385,3941993/1118/sys/src/9/pc/ether8390.c:389,398
1993/0212    
		 * out from the software next-page pointer and 
		 * the current next-page pointer. 
1992/1222    
		 */ 
1993/1116    
		if(hdr.next > ether->nxtpkt) 
			len1 = hdr.next - ether->nxtpkt - 1; 
1993/1118    
		if(hdr.next > dp8390->nxtpkt) 
			len1 = hdr.next - dp8390->nxtpkt - 1; 
1993/0212    
		else 
1993/1116    
			len1 = (ether->pstop-ether->nxtpkt) + (hdr.next-ether->pstart) - 1; 
1993/1118    
			len1 = (dp8390->pstop-dp8390->nxtpkt) + (hdr.next-dp8390->pstart) - 1; 
1993/0212    
		if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) 
			len1--; 
 
1993/1117/sys/src/9/pc/ether8390.c:397,4091993/1118/sys/src/9/pc/ether8390.c:401,413
1993/0212    
		/* 
		 * Chip is badly scrogged, reinitialise the ring. 
		 */ 
1993/1116    
		if(hdr.next < ether->pstart || hdr.next >= ether->pstop 
1993/1118    
		if(hdr.next < dp8390->pstart || hdr.next >= dp8390->pstop 
1993/0212    
		  || len < 60 || len > sizeof(Etherpkt)){ 
			print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|", 
1993/1118    
			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", 
1993/0212    
				hdr.status, hdr.next, hdr.len0, hdr.len1, len); 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
1993/1116    
			dp8390ring(ether); 
1993/0915    
			dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1993/1118    
			dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
			dp8390ring(dp8390); 
			dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1992/1222    
			return; 
		} 
 
1993/1117/sys/src/9/pc/ether8390.c:412,4311993/1118/sys/src/9/pc/ether8390.c:416,442
1993/1116    
		 * If the packet wraps round the hardware ring, read it in two pieces. 
1993/0212    
		 */ 
1993/1116    
		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){ 
			pkt = ether->rpkt; 
1993/1118    
			pkt = (uchar*)ðer->rpkt; 
1992/1222    
			data += sizeof(Hdr); 
1993/0212    
			ring->len = len; 
1993/1118    
			len1 = len; 
1993/0212    
 
1993/1116    
			if((data+len) >= ether->pstop*Dp8390BufSz){ 
				ulong count = ether->pstop*Dp8390BufSz - data; 
1993/1118    
			if((data+len1) >= dp8390->pstop*Dp8390BufSz){ 
				ulong count = dp8390->pstop*Dp8390BufSz - data; 
1993/0212    
 
1993/1116    
				(*ether->read)(ctlr, pkt, data, count); 
1993/1118    
				if(dp8390->ram) 
					memmove(pkt, (void*)(ether->mem+data), count); 
				else 
					dp8390read(dp8390, pkt, data, count); 
1993/0212    
				pkt += count; 
1993/1116    
				data = ether->pstart*Dp8390BufSz; 
1993/0212    
				len -= count; 
1993/1118    
				data = dp8390->pstart*Dp8390BufSz; 
				len1 -= count; 
1992/1222    
			} 
1993/0212    
			if(len) 
1993/1116    
				(*ether->read)(ctlr, pkt, data, len); 
1993/1118    
			if(len1){ 
				if(dp8390->ram) 
					memmove(pkt, (void*)(ether->mem+data), len1); 
				else 
					dp8390read(dp8390, pkt, data, len1); 
			} 
1993/0212    
 
1993/1116    
			/* 
			 * Copy the packet to whoever wants it. 
1993/1117/sys/src/9/pc/ether8390.c:440,5301993/1118/sys/src/9/pc/ether8390.c:451,564
1992/1222    
		} 
 
1993/0212    
		/* 
		 * Finished woth this packet, update the 
1993/1118    
		 * Finished with this packet, update the 
1993/0212    
		 * hardware and software ring pointers. 
		 */ 
1993/1116    
		ether->nxtpkt = hdr.next; 
1993/1118    
		dp8390->nxtpkt = hdr.next; 
1993/0212    
 
		hdr.next--; 
1993/1116    
		if(hdr.next < ether->pstart) 
			hdr.next = ether->pstop-1; 
1993/0915    
		dp8390outb(dp8390+Bnry, hdr.next); 
1993/1118    
		if(hdr.next < dp8390->pstart) 
			hdr.next = dp8390->pstop-1; 
		dp8390outb(port+Bnry, hdr.next); 
1992/1222    
	} 
} 
 
1993/0212    
/* 
 * Initiate a transmission. Must be called splhi(). 
 */ 
1992/1222    
void 
1993/1116    
dp8390transmit(Ether *ether) 
1993/1118    
static int 
istxbusy(void *arg) 
1992/1222    
{ 
1993/0915    
	ulong dp8390; 
1992/1222    
	RingBuf *ring; 
1993/1118    
	return ((Dp8390*)arg)->busy == 0; 
} 
1993/0212    
 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	ring = ðer->tb[ether->ti]; 
	if(ether->tbusy == 0 && ring->owner == Interface){ 
1993/1118    
static long 
write(Ether *ether, void *buf, long n) 
{ 
	Dp8390 *dp8390; 
	ulong port; 
1993/0213    
 
1993/1116    
		ether->tbusy = 1; 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
1993/0213    
 
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); 
		dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
1993/1118    
	qlock(ðer->tlock); 
	if(waserror()) { 
		qunlock(ðer->tlock); 
		nexterror(); 
1993/0212    
	} 
1993/1118    
 
	tsleep(ðer->tr, istxbusy, dp8390, 10000); 
	if(dp8390->busy) 
		print("dp8390: transmitter jammed\n"); 
	dp8390->busy = 1; 
 
	if(dp8390->ram) 
		memmove((void*)(ether->mem+dp8390->tstart*Dp8390BufSz), buf, n); 
	else 
		dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, buf, n); 
 
	dp8390outb(port+Tbcr0, n & 0xFF); 
	dp8390outb(port+Tbcr1, (n>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
 
	poperror(); 
	qunlock(ðer->tlock); 
 
	return n; 
1993/0212    
} 
 
1993/1116    
static void 
overflow(Ether *ether) 
1993/0212    
{ 
1993/0915    
	ulong dp8390; 
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1993/0212    
	uchar txp; 
	int resend; 
 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->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    
	txp = dp8390inb(dp8390+Cr) & Txp; 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp); 
1993/1118    
	txp = dp8390inb(port+Cr) & Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1993/0212    
	delay(2); 
1993/0915    
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
1993/1118    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1993/0212    
 
	resend = 0; 
1993/0915    
	if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0) 
1993/1118    
	if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0) 
1993/0212    
		resend = 1; 
 
1993/0915    
	dp8390outb(dp8390+Tcr, Lb); 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1993/1116    
	(*ether->receive)(ether); 
1993/0915    
	dp8390outb(dp8390+Isr, Ovw); 
1993/1116    
	wakeup(ðer->rr); 
1993/0915    
	dp8390outb(dp8390+Tcr, 0); 
1993/1118    
	dp8390outb(port+Tcr, Lb); 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	receive(ether); 
	dp8390outb(port+Isr, Ovw); 
	dp8390outb(port+Tcr, 0); 
1993/0212    
 
	if(resend) 
1993/0915    
		dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta); 
1993/1118    
		dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0212    
} 
 
1993/1116    
static void 
interrupt(Ether *ether) 
1993/0212    
{ 
1993/0915    
	ulong dp8390; 
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1993/0212    
	uchar isr, r; 
1992/1222    
 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
 
1992/1222    
	/* 
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
	 */ 
1993/0915    
	dp8390outb(dp8390+Imr, 0x00); 
	while(isr = dp8390inb(dp8390+Isr)){ 
1993/1118    
	dp8390outb(port+Imr, 0x00); 
	while(isr = dp8390inb(port+Isr)){ 
1992/1222    
 
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1993/0915    
			dp8390outb(dp8390+Isr, Ovw); 
1993/1118    
			dp8390outb(port+Isr, Ovw); 
1993/1116    
			ether->overflows++; 
1992/1222    
		} 
 
1993/1117/sys/src/9/pc/ether8390.c:534,5401993/1118/sys/src/9/pc/ether8390.c:568,574
1992/1222    
		 */ 
		if(isr & (Rxe|Prx)){ 
1993/1116    
			receive(ether); 
1993/0915    
			dp8390outb(dp8390+Isr, Rxe|Prx); 
1993/1118    
			dp8390outb(port+Isr, Rxe|Prx); 
1992/1222    
		} 
 
		/* 
1993/1117/sys/src/9/pc/ether8390.c:543,5931993/1118/sys/src/9/pc/ether8390.c:577,626
1992/1222    
		 * and wake the output routine. 
		 */ 
		if(isr & (Txe|Ptx)){ 
1993/0915    
			r = dp8390inb(dp8390+Tsr); 
1993/1118    
			r = dp8390inb(port+Tsr); 
1993/0212    
			if(isr & Txe){ 
1993/1116    
				if((r & (Cdh|Fu|Crs|Abt)) && ether->debug) 
1993/0212    
					print("Tsr#%2.2ux|", r); 
1993/1118    
				if((r & (Cdh|Fu|Crs|Abt))) 
					print("dp8390: Tsr#%2.2ux\n", r); 
1993/1116    
				ether->oerrs++; 
1993/0212    
			} 
 
1993/0915    
			dp8390outb(dp8390+Isr, Txe|Ptx); 
1993/1118    
			dp8390outb(port+Isr, Txe|Ptx); 
1993/0212    
 
			if(isr & Ptx) 
1993/1116    
				ether->outpackets++; 
1993/1118    
			dp8390->busy = 0; 
1993/1116    
			wakeup(ðer->tr); 
1992/1222    
		} 
1993/0212    
 
		if(isr & Cnt){ 
1993/1116    
			ether->frames += dp8390inb(dp8390+Cntr0); 
			ether->crcs += dp8390inb(dp8390+Cntr1); 
			ether->buffs += dp8390inb(dp8390+Cntr2); 
1993/0915    
			dp8390outb(dp8390+Isr, Cnt); 
1993/1118    
			ether->frames += dp8390inb(port+Cntr0); 
			ether->crcs += dp8390inb(port+Cntr1); 
			ether->buffs += dp8390inb(port+Cntr2); 
			dp8390outb(port+Isr, Cnt); 
1993/0212    
		} 
1992/1222    
	} 
1993/0915    
	dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1118    
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
} 
 
static void 
promiscuous(Ether *ether, int on) 
1993/1118    
promiscuous(void *arg, int on) 
1993/1116    
{ 
1993/1117    
	ulong dp8390; 
1993/1118    
	Dp8390 *dp8390 = ((Ether*)arg)->private; 
1993/1117    
 
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	/* 
	 * Set/reset promiscuous mode. 
	 */ 
	if(on) 
		dp8390outb(ether->dp8390+Rcr, Pro|Ab); 
1993/1118    
		dp8390outb(dp8390->dp8390+Rcr, Pro|Ab); 
1993/1116    
	else 
		dp8390outb(ether->dp8390+Rcr, Ab); 
1993/1118    
		dp8390outb(dp8390->dp8390+Rcr, Ab); 
1993/1116    
} 
 
void 
dp8390attach(Ether *ether) 
1993/1118    
static void 
attach(Ether *ether) 
1993/1116    
{ 
1993/1117    
	ulong dp8390; 
1993/1118    
	Dp8390 *dp8390 = ether->private; 
1993/1117    
 
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1116    
	/* 
	 * Enable the chip for transmit/receive. 
	 * The init routine leaves the chip in monitor 
1993/1117/sys/src/9/pc/ether8390.c:594,6251993/1118/sys/src/9/pc/ether8390.c:627,661
1993/1116    
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
	 */ 
	dp8390outb(ether->dp8390+Rcr, Ab); 
	dp8390inb(ether->dp8390+Cntr2); 
1993/1118    
	dp8390outb(dp8390->dp8390+Rcr, Ab); 
	dp8390inb(dp8390->dp8390+Cntr2); 
1993/1116    
} 
 
static int 
1993/1118    
int 
1993/1116    
dp8390reset(Ether *ether) 
{ 
	ulong dp8390; 
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1993/1116    
 
1993/1117    
	dp8390 = ((Dp8390*)ether->private)->dp8390; 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
 
1993/1116    
	/* 
	 * 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); 
1993/1118    
	dp8390disable(dp8390); 
	if(dp8390->bit16) 
		dp8390outb(port+Dcr, Ft4|Ls|Wts); 
1993/1116    
	else 
		dp8390outb(dp8390+Dcr, Ft4|Ls); 
1993/1118    
		dp8390outb(port+Dcr, Ft4|Ls); 
1993/1116    
 
	dp8390outb(dp8390+Rbcr0, 0); 
	dp8390outb(dp8390+Rbcr1, 0); 
1993/1118    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1993/1116    
 
	dp8390outb(dp8390+Tcr, 0); 
	dp8390outb(dp8390+Rcr, Mon); 
1993/1118    
	dp8390outb(port+Tcr, 0); 
	dp8390outb(port+Rcr, Mon); 
1993/1116    
 
	/* 
	 * Init the ring hardware and software ring pointers. 
1993/1117/sys/src/9/pc/ether8390.c:626,6421993/1118/sys/src/9/pc/ether8390.c:662,678
1993/1116    
	 * Can't initialise ethernet address as we may not know 
	 * it yet. 
	 */ 
	dp8390ring(ether); 
	dp8390outb(dp8390+Tpsr, ether->tstart); 
1993/1118    
	dp8390ring(dp8390); 
	dp8390outb(port+Tpsr, dp8390->tstart); 
1993/1116    
 
	dp8390outb(dp8390+Isr, 0xFF); 
	dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1118    
	dp8390outb(port+Isr, 0xFF); 
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
 
	/* 
	 * Leave the chip initialised, 
	 * but in monitor mode. 
	 */ 
	dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta); 
1993/1118    
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1993/1116    
 
	/* 
	 * Set up the software configuration. 
1993/1118/sys/src/9/pc/ether8390.c:446,4521993/1119/sys/src/9/pc/ether8390.c:446,455 (short | long)
1993/1116    
			for(fp = ether->f; fp < ep; fp++) { 
				f = *fp; 
				if(f && (f->type == type || f->type < 0)) 
1993/1119    
{ 
print("Q%d|", len); 
1993/1116    
					qproduce(f->in, ðer->rpkt, len); 
1993/1119    
} 
1993/1116    
			} 
1992/1222    
		} 
 
1993/1118/sys/src/9/pc/ether8390.c:464,4721993/1119/sys/src/9/pc/ether8390.c:467,475
1992/1222    
} 
 
1993/1118    
static int 
istxbusy(void *arg) 
1993/1119    
istxavail(void *arg) 
1992/1222    
{ 
1993/1118    
	return ((Dp8390*)arg)->busy == 0; 
1993/1119    
	return ((Ether*)arg)->tlen == 0; 
1993/1118    
} 
1993/0212    
 
1993/1118    
static long 
1993/1118/sys/src/9/pc/ether8390.c:478,4941993/1119/sys/src/9/pc/ether8390.c:481,493
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
1993/0213    
 
1993/1118    
	qlock(ðer->tlock); 
	if(waserror()) { 
		qunlock(ðer->tlock); 
		nexterror(); 
1993/1119    
	tsleep(ðer->tr, istxavail, ether, 10000); 
	if(ether->tlen){ 
		print("dp8390: transmitter jammed\n"); 
		return 0; 
1993/0212    
	} 
1993/1119    
	ether->tlen = n; 
1993/1118    
 
	tsleep(ðer->tr, istxbusy, dp8390, 10000); 
	if(dp8390->busy) 
		print("dp8390: transmitter jammed\n"); 
	dp8390->busy = 1; 
                 
	if(dp8390->ram) 
		memmove((void*)(ether->mem+dp8390->tstart*Dp8390BufSz), buf, n); 
	else 
1993/1118/sys/src/9/pc/ether8390.c:498,5061993/1119/sys/src/9/pc/ether8390.c:497,502
1993/1118    
	dp8390outb(port+Tbcr1, (n>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
 
	poperror(); 
	qunlock(ðer->tlock); 
                 
	return n; 
1993/0212    
} 
 
1993/1118/sys/src/9/pc/ether8390.c:555,5601993/1119/sys/src/9/pc/ether8390.c:551,557
1992/1222    
	 */ 
1993/1118    
	dp8390outb(port+Imr, 0x00); 
	while(isr = dp8390inb(port+Isr)){ 
1993/1119    
print("I%2.2ux|", isr); 
1992/1222    
 
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1993/1118/sys/src/9/pc/ether8390.c:588,5941993/1119/sys/src/9/pc/ether8390.c:585,591
1993/0212    
 
			if(isr & Ptx) 
1993/1116    
				ether->outpackets++; 
1993/1118    
			dp8390->busy = 0; 
1993/1119    
			ether->tlen = 0; 
1993/1116    
			wakeup(ðer->tr); 
1992/1222    
		} 
1993/0212    
 
1993/1119/sys/src/9/pc/ether8390.c:446,4551993/1120/sys/src/9/pc/ether8390.c:446,452 (short | long)
1993/1116    
			for(fp = ether->f; fp < ep; fp++) { 
				f = *fp; 
				if(f && (f->type == type || f->type < 0)) 
1993/1119    
{ 
print("Q%d|", len); 
1993/1116    
					qproduce(f->in, ðer->rpkt, len); 
1993/1119    
} 
1993/1116    
			} 
1992/1222    
		} 
 
1993/1119/sys/src/9/pc/ether8390.c:473,4821993/1120/sys/src/9/pc/ether8390.c:470,480
1993/1118    
} 
1993/0212    
 
1993/1118    
static long 
write(Ether *ether, void *buf, long n) 
1993/1120    
write(Ether *ether, void *buf, long len) 
1993/1118    
{ 
	Dp8390 *dp8390; 
	ulong port; 
1993/1120    
	Etherpkt *pkt; 
1993/0213    
 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
1993/1119/sys/src/9/pc/ether8390.c:486,5031993/1120/sys/src/9/pc/ether8390.c:484,521
1993/1119    
		print("dp8390: transmitter jammed\n"); 
		return 0; 
1993/0212    
	} 
1993/1119    
	ether->tlen = n; 
1993/1120    
	ether->tlen = len; 
1993/1118    
 
1993/1120    
	/* 
	 * If it's a shared-memory interface, copy the packet 
	 * directly to the shared-memory area. Otherwise, copy 
	 * it to a staging buffer so the I/O-port write can be 
	 * done in one. 
	 */ 
1993/1118    
	if(dp8390->ram) 
		memmove((void*)(ether->mem+dp8390->tstart*Dp8390BufSz), buf, n); 
1993/1120    
		pkt = (Etherpkt*)(ether->mem+dp8390->tstart*Dp8390BufSz); 
1993/1118    
	else 
		dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, buf, n); 
1993/1120    
		pkt = ðer->tpkt; 
	memmove(pkt, buf, len); 
1993/1118    
 
	dp8390outb(port+Tbcr0, n & 0xFF); 
	dp8390outb(port+Tbcr1, (n>>8) & 0xFF); 
1993/1120    
	/* 
	 * Give the packet a source address and make sure it 
	 * is of minimum length. 
	 */ 
	memmove(pkt->s, ether->ea, sizeof(ether->ea)); 
	if(len < ETHERMINTU){ 
		memset(pkt->d+len, 0, ETHERMINTU-len); 
		len = ETHERMINTU; 
	} 
 
	if(dp8390->ram == 0) 
		dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); 
 
	dp8390outb(port+Tbcr0, len & 0xFF); 
	dp8390outb(port+Tbcr1, (len>>8) & 0xFF); 
1993/1118    
	dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
 
	return n; 
1993/1120    
	return len; 
1993/0212    
} 
 
1993/1116    
static void 
1993/1119/sys/src/9/pc/ether8390.c:551,5571993/1120/sys/src/9/pc/ether8390.c:569,574
1992/1222    
	 */ 
1993/1118    
	dp8390outb(port+Imr, 0x00); 
	while(isr = dp8390inb(port+Isr)){ 
1993/1119    
print("I%2.2ux|", isr); 
1992/1222    
 
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1993/1120/sys/src/9/pc/ether8390.c:554,5651993/1124/sys/src/9/pc/ether8390.c:554,569 (short | long)
1993/0212    
} 
 
1993/1116    
static void 
interrupt(Ether *ether) 
1993/1124    
interrupt(Ureg *ur, void *arg) 
1993/0212    
{ 
1993/1124    
	Ether *ether; 
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1993/0212    
	uchar isr, r; 
1992/1222    
 
1993/1124    
	USED(ur); 
 
	ether = arg; 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
 
1993/1124/sys/src/9/pc/ether8390.c:228,2341994/0128/sys/src/9/pc/ether8390.c:228,234 (short | long)
1993/1117    
	dp8390outb(port+Cr, cr); 
1993/0915    
} 
 
1993/1116    
static void* 
1994/0128    
void* 
1993/1117    
dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) 
1992/1222    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/1124/sys/src/9/pc/ether8390.c:279,2851994/0128/sys/src/9/pc/ether8390.c:279,285
1992/1222    
	return to; 
} 
 
1993/1116    
static void* 
1994/0128    
void* 
1993/1118    
dp8390write(Dp8390 *dp8390, ulong to, void *from, ulong len) 
1992/1222    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1994/0128/sys/src/9/pc/ether8390.c:14,211994/0130/sys/src/9/pc/ether8390.c:14,21 (short | long)
1992/1222    
 
1993/1116    
#include "etherif.h" 
1992/1222    
 
1993/1118    
extern int dp8390inb(ulong); 
extern void dp8390outb(ulong, uchar); 
1994/0130    
extern int slowinb(ulong); 
extern void slowoutb(ulong, uchar); 
1993/1118    
 
1992/1222    
enum { 
	Cr		= 0x00,		/* command register, all pages */ 
1994/0128/sys/src/9/pc/ether8390.c:163,1721994/0130/sys/src/9/pc/ether8390.c:163,172
1992/1222    
	 * chip there if this is called when probing for a device 
	 * at boot. 
	 */ 
1993/1117    
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--) 
1994/0130    
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
	for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--) 
1992/1222    
			; 
} 
 
1994/0128/sys/src/9/pc/ether8390.c:175,1871994/0130/sys/src/9/pc/ether8390.c:175,187
1993/0212    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
 
1993/1117    
	dp8390outb(port+Pstart, dp8390->pstart); 
	dp8390outb(port+Pstop, dp8390->pstop); 
	dp8390outb(port+Bnry, dp8390->pstop-1); 
1994/0130    
	slowoutb(port+Pstart, dp8390->pstart); 
	slowoutb(port+Pstop, dp8390->pstop); 
	slowoutb(port+Bnry, dp8390->pstop-1); 
1993/0212    
 
1993/1117    
	dp8390outb(port+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(port+Curr, dp8390->pstart); 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1994/0130    
	slowoutb(port+Cr, Page1|RDMAabort|Stp); 
	slowoutb(port+Curr, dp8390->pstart); 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/0915    
 
1993/1117    
	dp8390->nxtpkt = dp8390->pstart; 
1993/0212    
} 
1994/0128/sys/src/9/pc/ether8390.c:200,2101994/0130/sys/src/9/pc/ether8390.c:200,210
1992/1222    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1993/1117    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1993/1117    
		dp8390outb(port+Par0+i, ether->ea[i]); 
	dp8390outb(port+Cr, cr); 
1994/0130    
		slowoutb(port+Par0+i, ether->ea[i]); 
	slowoutb(port+Cr, cr); 
1992/1222    
} 
 
1993/0915    
void 
1994/0128/sys/src/9/pc/ether8390.c:221,2311994/0130/sys/src/9/pc/ether8390.c:221,231
1993/0915    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1993/1117    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1993/1117    
		ether->ea[i] = dp8390inb(port+Par0+i); 
	dp8390outb(port+Cr, cr); 
1994/0130    
		ether->ea[i] = slowinb(port+Par0+i); 
	slowoutb(port+Cr, cr); 
1993/0915    
} 
 
1994/0128    
void* 
1994/0128/sys/src/9/pc/ether8390.c:240,2481994/0130/sys/src/9/pc/ether8390.c:240,248
1992/1222    
	 * using the DP8390 remote DMA facility, and place it at 
	 * 'to' in main memory, via the I/O data port. 
	 */ 
1993/1117    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1992/1222    
 
	/* 
	 * Set up the remote DMA address and count. 
1994/0128/sys/src/9/pc/ether8390.c:249,2641994/0130/sys/src/9/pc/ether8390.c:249,264
1992/1222    
	 */ 
1993/1117    
	if(dp8390->bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
1993/1117    
	dp8390outb(port+Rbcr0, len & 0xFF); 
	dp8390outb(port+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(port+Rsar0, from & 0xFF); 
	dp8390outb(port+Rsar1, (from>>8) & 0xFF); 
1994/0130    
	slowoutb(port+Rbcr0, len & 0xFF); 
	slowoutb(port+Rbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Rsar0, from & 0xFF); 
	slowoutb(port+Rsar1, (from>>8) & 0xFF); 
1992/1222    
 
	/* 
	 * Start the remote DMA read and suck the data 
	 * out of the I/O port. 
	 */ 
1993/1117    
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
1994/0130    
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1993/1117    
	if(dp8390->bit16) 
		inss(dp8390->data, to, len/2); 
1992/1222    
	else 
1994/0128/sys/src/9/pc/ether8390.c:271,2811994/0130/sys/src/9/pc/ether8390.c:271,281
1992/1222    
	 * to the miracles of the bus, we could get this far 
	 * and still be talking to a slot full of nothing. 
	 */ 
1993/1117    
	for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--) 
1994/0130    
	for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--) 
1992/1222    
			; 
 
1993/1117    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1994/0130    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1992/1222    
	return to; 
} 
 
1994/0128/sys/src/9/pc/ether8390.c:291,2991994/0130/sys/src/9/pc/ether8390.c:291,299
1992/1222    
	 * using the DP8390 remote DMA facility, reading it at 
	 * 'from' in main memory, via the I/O data port. 
	 */ 
1993/1118    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1992/1222    
 
1993/1118    
	if(dp8390->bit16) 
1993/0212    
		len = ROUNDUP(len, 2); 
1994/0128/sys/src/9/pc/ether8390.c:304,3271994/0130/sys/src/9/pc/ether8390.c:304,327
1993/0212    
	 * the initial set up for read. 
1992/1222    
	 */ 
1993/1118    
	crda = to-1-dp8390->bit16; 
	dp8390outb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	dp8390outb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	dp8390outb(port+Rsar0, crda & 0xFF); 
	dp8390outb(port+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
1994/0130    
	slowoutb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	slowoutb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	slowoutb(port+Rsar0, crda & 0xFF); 
	slowoutb(port+Rsar1, (crda>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1992/1222    
 
1993/0212    
	for(;;){ 
1993/1118    
		crda = dp8390inb(port+Crda0); 
		crda |= dp8390inb(port+Crda1)<<8; 
1994/0130    
		crda = slowinb(port+Crda0); 
		crda |= slowinb(port+Crda1)<<8; 
1993/0212    
		if(crda == to){ 
			/* 
			 * Start the remote DMA write and make sure 
			 * the registers are correct. 
			 */ 
1993/1118    
			dp8390outb(port+Cr, Page0|RDMAwrite|Sta); 
1994/0130    
			slowoutb(port+Cr, Page0|RDMAwrite|Sta); 
1992/1222    
 
1993/1118    
			crda = dp8390inb(port+Crda0); 
			crda |= dp8390inb(port+Crda1)<<8; 
1994/0130    
			crda = slowinb(port+Crda0); 
			crda |= slowinb(port+Crda1)<<8; 
1993/0212    
			if(crda != to) 
				panic("crda write %d to %d\n", crda, to); 
 
1994/0128/sys/src/9/pc/ether8390.c:342,3521994/0130/sys/src/9/pc/ether8390.c:342,352
1992/1222    
	 * a timeout here if this ever gets called before 
	 * we know there really is a chip there. 
	 */ 
1993/1118    
	while((dp8390inb(port+Isr) & Rdc) == 0) 
1994/0130    
	while((slowinb(port+Isr) & Rdc) == 0) 
1992/1222    
			; 
 
1993/1118    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1994/0130    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1992/1222    
	return (void*)to; 
} 
 
1994/0128/sys/src/9/pc/ether8390.c:356,3651994/0130/sys/src/9/pc/ether8390.c:356,365
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
	uchar cr, curr; 
 
1993/1118    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(port+Curr); 
	dp8390outb(port+Cr, cr); 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = slowinb(port+Curr); 
	slowoutb(port+Cr, cr); 
1993/0212    
	return curr; 
} 
 
1994/0128/sys/src/9/pc/ether8390.c:405,4131994/0130/sys/src/9/pc/ether8390.c:405,413
1993/0212    
		  || len < 60 || len > sizeof(Etherpkt)){ 
1993/1118    
			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", 
1993/0212    
				hdr.status, hdr.next, hdr.len0, hdr.len1, len); 
1993/1118    
			dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1994/0130    
			slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/1118    
			dp8390ring(dp8390); 
			dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1994/0130    
			slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1992/1222    
			return; 
		} 
 
1994/0128/sys/src/9/pc/ether8390.c:459,4651994/0130/sys/src/9/pc/ether8390.c:459,465
1993/0212    
		hdr.next--; 
1993/1118    
		if(hdr.next < dp8390->pstart) 
			hdr.next = dp8390->pstop-1; 
		dp8390outb(port+Bnry, hdr.next); 
1994/0130    
		slowoutb(port+Bnry, hdr.next); 
1992/1222    
	} 
} 
 
1994/0128/sys/src/9/pc/ether8390.c:511,5191994/0130/sys/src/9/pc/ether8390.c:511,519
1993/1120    
	if(dp8390->ram == 0) 
		dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); 
 
	dp8390outb(port+Tbcr0, len & 0xFF); 
	dp8390outb(port+Tbcr1, (len>>8) & 0xFF); 
1993/1118    
	dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1994/0130    
	slowoutb(port+Tbcr0, len & 0xFF); 
	slowoutb(port+Tbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1993/1118    
 
1993/1120    
	return len; 
1993/0212    
} 
1994/0128/sys/src/9/pc/ether8390.c:533,5561994/0130/sys/src/9/pc/ether8390.c:533,556
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/1118    
	txp = dp8390inb(port+Cr) & Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1994/0130    
	txp = slowinb(port+Cr) & Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/0212    
	delay(2); 
1993/1118    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1994/0130    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1993/0212    
 
	resend = 0; 
1993/1118    
	if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0) 
1994/0130    
	if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0) 
1993/0212    
		resend = 1; 
 
1993/1118    
	dp8390outb(port+Tcr, Lb); 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1994/0130    
	slowoutb(port+Tcr, Lb); 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1993/1118    
	receive(ether); 
	dp8390outb(port+Isr, Ovw); 
	dp8390outb(port+Tcr, 0); 
1994/0130    
	slowoutb(port+Isr, Ovw); 
	slowoutb(port+Tcr, 0); 
1993/0212    
 
	if(resend) 
1993/1118    
		dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1994/0130    
		slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0212    
} 
 
1993/1116    
static void 
1994/0128/sys/src/9/pc/ether8390.c:571,5821994/0130/sys/src/9/pc/ether8390.c:571,582
1992/1222    
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
	 */ 
1993/1118    
	dp8390outb(port+Imr, 0x00); 
	while(isr = dp8390inb(port+Isr)){ 
1994/0130    
	slowoutb(port+Imr, 0x00); 
	while(isr = slowinb(port+Isr)){ 
1992/1222    
 
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1993/1118    
			dp8390outb(port+Isr, Ovw); 
1994/0130    
			slowoutb(port+Isr, Ovw); 
1993/1116    
			ether->overflows++; 
1992/1222    
		} 
 
1994/0128/sys/src/9/pc/ether8390.c:586,5921994/0130/sys/src/9/pc/ether8390.c:586,592
1992/1222    
		 */ 
		if(isr & (Rxe|Prx)){ 
1993/1116    
			receive(ether); 
1993/1118    
			dp8390outb(port+Isr, Rxe|Prx); 
1994/0130    
			slowoutb(port+Isr, Rxe|Prx); 
1992/1222    
		} 
 
		/* 
1994/0128/sys/src/9/pc/ether8390.c:595,6011994/0130/sys/src/9/pc/ether8390.c:595,601
1992/1222    
		 * and wake the output routine. 
		 */ 
		if(isr & (Txe|Ptx)){ 
1993/1118    
			r = dp8390inb(port+Tsr); 
1994/0130    
			r = slowinb(port+Tsr); 
1993/0212    
			if(isr & Txe){ 
1993/1118    
				if((r & (Cdh|Fu|Crs|Abt))) 
					print("dp8390: Tsr#%2.2ux\n", r); 
1994/0128/sys/src/9/pc/ether8390.c:602,6081994/0130/sys/src/9/pc/ether8390.c:602,608
1993/1116    
				ether->oerrs++; 
1993/0212    
			} 
 
1993/1118    
			dp8390outb(port+Isr, Txe|Ptx); 
1994/0130    
			slowoutb(port+Isr, Txe|Ptx); 
1993/0212    
 
			if(isr & Ptx) 
1993/1116    
				ether->outpackets++; 
1994/0128/sys/src/9/pc/ether8390.c:611,6231994/0130/sys/src/9/pc/ether8390.c:611,623
1992/1222    
		} 
1993/0212    
 
		if(isr & Cnt){ 
1993/1118    
			ether->frames += dp8390inb(port+Cntr0); 
			ether->crcs += dp8390inb(port+Cntr1); 
			ether->buffs += dp8390inb(port+Cntr2); 
			dp8390outb(port+Isr, Cnt); 
1994/0130    
			ether->frames += slowinb(port+Cntr0); 
			ether->crcs += slowinb(port+Cntr1); 
			ether->buffs += slowinb(port+Cntr2); 
			slowoutb(port+Isr, Cnt); 
1993/0212    
		} 
1992/1222    
	} 
1993/1118    
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1994/0130    
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
} 
 
static void 
1994/0128/sys/src/9/pc/ether8390.c:629,6371994/0130/sys/src/9/pc/ether8390.c:629,637
1993/1116    
	 * Set/reset promiscuous mode. 
	 */ 
	if(on) 
1993/1118    
		dp8390outb(dp8390->dp8390+Rcr, Pro|Ab); 
1994/0130    
		slowoutb(dp8390->dp8390+Rcr, Pro|Ab); 
1993/1116    
	else 
1993/1118    
		dp8390outb(dp8390->dp8390+Rcr, Ab); 
1994/0130    
		slowoutb(dp8390->dp8390+Rcr, Ab); 
1993/1116    
} 
 
1993/1118    
static void 
1994/0128/sys/src/9/pc/ether8390.c:645,6521994/0130/sys/src/9/pc/ether8390.c:645,652
1993/1116    
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
	 */ 
1993/1118    
	dp8390outb(dp8390->dp8390+Rcr, Ab); 
	dp8390inb(dp8390->dp8390+Cntr2); 
1994/0130    
	slowoutb(dp8390->dp8390+Rcr, Ab); 
	slowinb(dp8390->dp8390+Cntr2); 
1993/1116    
} 
 
1993/1118    
int 
1994/0128/sys/src/9/pc/ether8390.c:665,6791994/0130/sys/src/9/pc/ether8390.c:665,679
1993/1116    
	 */  
1993/1118    
	dp8390disable(dp8390); 
	if(dp8390->bit16) 
		dp8390outb(port+Dcr, Ft4|Ls|Wts); 
1994/0130    
		slowoutb(port+Dcr, Ft4|Ls|Wts); 
1993/1116    
	else 
1993/1118    
		dp8390outb(port+Dcr, Ft4|Ls); 
1994/0130    
		slowoutb(port+Dcr, Ft4|Ls); 
1993/1116    
 
1993/1118    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1994/0130    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1993/1116    
 
1993/1118    
	dp8390outb(port+Tcr, 0); 
	dp8390outb(port+Rcr, Mon); 
1994/0130    
	slowoutb(port+Tcr, 0); 
	slowoutb(port+Rcr, Mon); 
1993/1116    
 
	/* 
	 * Init the ring hardware and software ring pointers. 
1994/0128/sys/src/9/pc/ether8390.c:681,6961994/0130/sys/src/9/pc/ether8390.c:681,696
1993/1116    
	 * it yet. 
	 */ 
1993/1118    
	dp8390ring(dp8390); 
	dp8390outb(port+Tpsr, dp8390->tstart); 
1994/0130    
	slowoutb(port+Tpsr, dp8390->tstart); 
1993/1116    
 
1993/1118    
	dp8390outb(port+Isr, 0xFF); 
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1994/0130    
	slowoutb(port+Isr, 0xFF); 
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
 
	/* 
	 * Leave the chip initialised, 
	 * but in monitor mode. 
	 */ 
1993/1118    
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1994/0130    
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1993/1116    
 
	/* 
	 * Set up the software configuration. 
1994/0130/sys/src/9/pc/ether8390.c:285,2911994/0201/sys/src/9/pc/ether8390.c:285,293 (short | long)
1993/1118    
	ulong port = dp8390->dp8390; 
	ulong crda; 
1992/1222    
	uchar cr; 
1994/0201    
	int s, tries; 
1992/1222    
 
1994/0201    
	s = splhi(); 
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 
1994/0130/sys/src/9/pc/ether8390.c:336,3411994/0201/sys/src/9/pc/ether8390.c:338,344
1993/1118    
		outss(dp8390->data, from, len/2); 
1992/1222    
	else 
1993/1118    
		outsb(dp8390->data, from, len); 
1994/0201    
	splx(s); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to finish. We'll need 
1994/0130/sys/src/9/pc/ether8390.c:342,3491994/0201/sys/src/9/pc/ether8390.c:345,356
1992/1222    
	 * a timeout here if this ever gets called before 
	 * we know there really is a chip there. 
	 */ 
1994/0201    
	tries = 0; 
1994/0130    
	while((slowinb(port+Isr) & Rdc) == 0) 
1992/1222    
			; 
1994/0201    
		if(tries++ >= 10000000){ 
			print("dp8390write whoops\n"); 
			break; 
		} 
1992/1222    
 
1994/0130    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1994/0201/sys/src/9/pc/ether8390.c:287,2931994/0202/sys/src/9/pc/ether8390.c:287,298 (short | long)
1992/1222    
	uchar cr; 
1994/0201    
	int s, tries; 
1992/1222    
 
1994/0202    
	/* 
	 * Keep out interrupts since reading and writing 
	 * use the same DMA engine. 
	 */ 
1994/0201    
	s = splhi(); 
1994/0202    
 
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 
1994/0201/sys/src/9/pc/ether8390.c:338,3591994/0202/sys/src/9/pc/ether8390.c:343,365
1993/1118    
		outss(dp8390->data, from, len/2); 
1992/1222    
	else 
1993/1118    
		outsb(dp8390->data, from, len); 
1994/0201    
	splx(s); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to finish. We'll need 
	 * a timeout here if this ever gets called before 
	 * we know there really is a chip there. 
1994/0202    
	 * Wait for the remote DMA to finish. It should 
	 * be almost immediate. 
1992/1222    
	 */ 
1994/0201    
	tries = 0; 
1994/0130    
	while((slowinb(port+Isr) & Rdc) == 0) 
1994/0201    
		if(tries++ >= 10000000){ 
			print("dp8390write whoops\n"); 
1994/0202    
	while((slowinb(port+Isr) & Rdc) == 0){ 
		if(tries++ >= 100000){ 
			print("dp8390write dma timed out\n"); 
1994/0201    
			break; 
		} 
1994/0202    
	} 
1992/1222    
 
1994/0130    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1994/0202    
	splx(s); 
 
1992/1222    
	return (void*)to; 
} 
 
1994/0201/sys/src/9/pc/ether8390.c:377,3841994/0202/sys/src/9/pc/ether8390.c:383,388
1993/1118    
	uchar curr, *pkt; 
1992/1222    
	Hdr hdr; 
1993/1118    
	ulong port, data, len, len1; 
1993/1116    
	ushort type; 
	Netfile *f, **fp, **ep; 
1992/1222    
 
1993/1118    
	dp8390 = ether->private; 
	port = dp8390->dp8390; 
1994/0201/sys/src/9/pc/ether8390.c:421,4261994/0202/sys/src/9/pc/ether8390.c:425,433
1993/0212    
		/* 
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. 
1994/0202    
		 * 
		 * We could conceivably remove the copy into rpkt here by wrapping 
		 * this up with the etherrloop code. 
1993/0212    
		 */ 
1993/1116    
		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){ 
1993/1118    
			pkt = (uchar*)ðer->rpkt; 
1994/0201/sys/src/9/pc/ether8390.c:448,4601994/0202/sys/src/9/pc/ether8390.c:455,461
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); 
			} 
1994/0202    
			etherrloop(ether, ðer->rpkt, len); 
1992/1222    
		} 
 
1993/0212    
		/* 
1994/0202/sys/src/9/pc/ether8390.c:455,4611994/0715/sys/src/9/pc/ether8390.c:455,461 (short | long)
1993/1116    
			/* 
			 * Copy the packet to whoever wants it. 
			 */ 
1994/0202    
			etherrloop(ether, ðer->rpkt, len); 
1994/0715    
			etherrloop(ether, ðer->rpkt, len, 1); 
1992/1222    
		} 
 
1993/0212    
		/* 
1994/0715/sys/src/9/pc/ether8390.c:14,221995/0408/sys/src/9/pc/ether8390.c:14,19 (short | long)
1992/1222    
 
1993/1116    
#include "etherif.h" 
1992/1222    
 
1994/0130    
extern int slowinb(ulong); 
extern void slowoutb(ulong, uchar); 
1993/1118    
                 
1992/1222    
enum { 
	Cr		= 0x00,		/* command register, all pages */ 
 
1994/0715/sys/src/9/pc/ether8390.c:149,1541995/0408/sys/src/9/pc/ether8390.c:146,171
1992/1222    
	uchar	len1; 
} Hdr; 
 
1995/0408    
/* 
 *  the 8390 register accesses must not be too close together 
 */ 
void 
dp8390outb(ulong port, uchar x) 
{ 
	outb(port, x); 
	microdelay(0); 
} 
 
long 
dp8390inb(ulong port) 
{ 
	long x; 
 
	x = inb(port); 
	microdelay(0); 
	return x; 
} 
 
1992/1222    
static void 
1993/1117    
dp8390disable(Dp8390 *dp8390) 
1992/1222    
{ 
1994/0715/sys/src/9/pc/ether8390.c:163,1721995/0408/sys/src/9/pc/ether8390.c:180,189
1992/1222    
	 * chip there if this is called when probing for a device 
	 * at boot. 
	 */ 
1994/0130    
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
	for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--) 
1995/0408    
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--) 
1992/1222    
			; 
} 
 
1994/0715/sys/src/9/pc/ether8390.c:175,1871995/0408/sys/src/9/pc/ether8390.c:192,204
1993/0212    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
 
1994/0130    
	slowoutb(port+Pstart, dp8390->pstart); 
	slowoutb(port+Pstop, dp8390->pstop); 
	slowoutb(port+Bnry, dp8390->pstop-1); 
1995/0408    
	dp8390outb(port+Pstart, dp8390->pstart); 
	dp8390outb(port+Pstop, dp8390->pstop); 
	dp8390outb(port+Bnry, dp8390->pstop-1); 
1993/0212    
 
1994/0130    
	slowoutb(port+Cr, Page1|RDMAabort|Stp); 
	slowoutb(port+Curr, dp8390->pstart); 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1995/0408    
	dp8390outb(port+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(port+Curr, dp8390->pstart); 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1993/0915    
 
1993/1117    
	dp8390->nxtpkt = dp8390->pstart; 
1993/0212    
} 
1994/0715/sys/src/9/pc/ether8390.c:200,2101995/0408/sys/src/9/pc/ether8390.c:217,227
1992/1222    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1994/0130    
		slowoutb(port+Par0+i, ether->ea[i]); 
	slowoutb(port+Cr, cr); 
1995/0408    
		dp8390outb(port+Par0+i, ether->ea[i]); 
	dp8390outb(port+Cr, cr); 
1992/1222    
} 
 
1993/0915    
void 
1994/0715/sys/src/9/pc/ether8390.c:221,2311995/0408/sys/src/9/pc/ether8390.c:238,248
1993/0915    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1994/0130    
		ether->ea[i] = slowinb(port+Par0+i); 
	slowoutb(port+Cr, cr); 
1995/0408    
		ether->ea[i] = dp8390inb(port+Par0+i); 
	dp8390outb(port+Cr, cr); 
1993/0915    
} 
 
1994/0128    
void* 
1994/0715/sys/src/9/pc/ether8390.c:240,2481995/0408/sys/src/9/pc/ether8390.c:257,265
1992/1222    
	 * using the DP8390 remote DMA facility, and place it at 
	 * 'to' in main memory, via the I/O data port. 
	 */ 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1992/1222    
 
	/* 
	 * Set up the remote DMA address and count. 
1994/0715/sys/src/9/pc/ether8390.c:249,2641995/0408/sys/src/9/pc/ether8390.c:266,281
1992/1222    
	 */ 
1993/1117    
	if(dp8390->bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
1994/0130    
	slowoutb(port+Rbcr0, len & 0xFF); 
	slowoutb(port+Rbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Rsar0, from & 0xFF); 
	slowoutb(port+Rsar1, (from>>8) & 0xFF); 
1995/0408    
	dp8390outb(port+Rbcr0, len & 0xFF); 
	dp8390outb(port+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(port+Rsar0, from & 0xFF); 
	dp8390outb(port+Rsar1, (from>>8) & 0xFF); 
1992/1222    
 
	/* 
	 * Start the remote DMA read and suck the data 
	 * out of the I/O port. 
	 */ 
1994/0130    
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1995/0408    
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
1993/1117    
	if(dp8390->bit16) 
		inss(dp8390->data, to, len/2); 
1992/1222    
	else 
1994/0715/sys/src/9/pc/ether8390.c:271,2811995/0408/sys/src/9/pc/ether8390.c:288,298
1992/1222    
	 * to the miracles of the bus, we could get this far 
	 * and still be talking to a slot full of nothing. 
	 */ 
1994/0130    
	for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--) 
1995/0408    
	for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--) 
1992/1222    
			; 
 
1994/0130    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1995/0408    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1992/1222    
	return to; 
} 
 
1994/0715/sys/src/9/pc/ether8390.c:298,3061995/0408/sys/src/9/pc/ether8390.c:315,323
1992/1222    
	 * using the DP8390 remote DMA facility, reading it at 
	 * 'from' in main memory, via the I/O data port. 
	 */ 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1992/1222    
 
1993/1118    
	if(dp8390->bit16) 
1993/0212    
		len = ROUNDUP(len, 2); 
1994/0715/sys/src/9/pc/ether8390.c:311,3341995/0408/sys/src/9/pc/ether8390.c:328,351
1993/0212    
	 * the initial set up for read. 
1992/1222    
	 */ 
1993/1118    
	crda = to-1-dp8390->bit16; 
1994/0130    
	slowoutb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	slowoutb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	slowoutb(port+Rsar0, crda & 0xFF); 
	slowoutb(port+Rsar1, (crda>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1995/0408    
	dp8390outb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	dp8390outb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	dp8390outb(port+Rsar0, crda & 0xFF); 
	dp8390outb(port+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
1992/1222    
 
1993/0212    
	for(;;){ 
1994/0130    
		crda = slowinb(port+Crda0); 
		crda |= slowinb(port+Crda1)<<8; 
1995/0408    
		crda = dp8390inb(port+Crda0); 
		crda |= dp8390inb(port+Crda1)<<8; 
1993/0212    
		if(crda == to){ 
			/* 
			 * Start the remote DMA write and make sure 
			 * the registers are correct. 
			 */ 
1994/0130    
			slowoutb(port+Cr, Page0|RDMAwrite|Sta); 
1995/0408    
			dp8390outb(port+Cr, Page0|RDMAwrite|Sta); 
1992/1222    
 
1994/0130    
			crda = slowinb(port+Crda0); 
			crda |= slowinb(port+Crda1)<<8; 
1995/0408    
			crda = dp8390inb(port+Crda0); 
			crda |= dp8390inb(port+Crda1)<<8; 
1993/0212    
			if(crda != to) 
				panic("crda write %d to %d\n", crda, to); 
 
1994/0715/sys/src/9/pc/ether8390.c:349,3551995/0408/sys/src/9/pc/ether8390.c:366,372
1994/0202    
	 * be almost immediate. 
1992/1222    
	 */ 
1994/0201    
	tries = 0; 
1994/0202    
	while((slowinb(port+Isr) & Rdc) == 0){ 
1995/0408    
	while((dp8390inb(port+Isr) & Rdc) == 0){ 
1994/0202    
		if(tries++ >= 100000){ 
			print("dp8390write dma timed out\n"); 
1994/0201    
			break; 
1994/0715/sys/src/9/pc/ether8390.c:356,3631995/0408/sys/src/9/pc/ether8390.c:373,380
1994/0201    
		} 
1994/0202    
	} 
1992/1222    
 
1994/0130    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1995/0408    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1994/0202    
	splx(s); 
 
1992/1222    
	return (void*)to; 
1994/0715/sys/src/9/pc/ether8390.c:369,3781995/0408/sys/src/9/pc/ether8390.c:386,395
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
	uchar cr, curr; 
 
1994/0130    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = slowinb(port+Curr); 
	slowoutb(port+Cr, cr); 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(port+Curr); 
	dp8390outb(port+Cr, cr); 
1993/0212    
	return curr; 
} 
 
1994/0715/sys/src/9/pc/ether8390.c:416,4241995/0408/sys/src/9/pc/ether8390.c:433,441
1993/0212    
		  || len < 60 || len > sizeof(Etherpkt)){ 
1993/1118    
			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", 
1993/0212    
				hdr.status, hdr.next, hdr.len0, hdr.len1, len); 
1994/0130    
			slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1995/0408    
			dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1993/1118    
			dp8390ring(dp8390); 
1994/0130    
			slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1995/0408    
			dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1992/1222    
			return; 
		} 
 
1994/0715/sys/src/9/pc/ether8390.c:467,4731995/0408/sys/src/9/pc/ether8390.c:484,490
1993/0212    
		hdr.next--; 
1993/1118    
		if(hdr.next < dp8390->pstart) 
			hdr.next = dp8390->pstop-1; 
1994/0130    
		slowoutb(port+Bnry, hdr.next); 
1995/0408    
		dp8390outb(port+Bnry, hdr.next); 
1992/1222    
	} 
} 
 
1994/0715/sys/src/9/pc/ether8390.c:519,5271995/0408/sys/src/9/pc/ether8390.c:536,544
1993/1120    
	if(dp8390->ram == 0) 
		dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); 
 
1994/0130    
	slowoutb(port+Tbcr0, len & 0xFF); 
	slowoutb(port+Tbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1995/0408    
	dp8390outb(port+Tbcr0, len & 0xFF); 
	dp8390outb(port+Tbcr1, (len>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1993/1118    
 
1993/1120    
	return len; 
1993/0212    
} 
1994/0715/sys/src/9/pc/ether8390.c:541,5641995/0408/sys/src/9/pc/ether8390.c:558,581
1993/0212    
	 * The following procedure is taken from the DP8390[12D] datasheet, 
	 * it seems pretty adamant that this is what has to be done. 
	 */ 
1994/0130    
	txp = slowinb(port+Cr) & Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1995/0408    
	txp = dp8390inb(port+Cr) & Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1993/0212    
	delay(2); 
1994/0130    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1995/0408    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1993/0212    
 
	resend = 0; 
1994/0130    
	if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0) 
1995/0408    
	if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0) 
1993/0212    
		resend = 1; 
 
1994/0130    
	slowoutb(port+Tcr, Lb); 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1995/0408    
	dp8390outb(port+Tcr, Lb); 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1993/1118    
	receive(ether); 
1994/0130    
	slowoutb(port+Isr, Ovw); 
	slowoutb(port+Tcr, 0); 
1995/0408    
	dp8390outb(port+Isr, Ovw); 
	dp8390outb(port+Tcr, 0); 
1993/0212    
 
	if(resend) 
1994/0130    
		slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1995/0408    
		dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0212    
} 
 
1993/1116    
static void 
1994/0715/sys/src/9/pc/ether8390.c:579,5901995/0408/sys/src/9/pc/ether8390.c:596,607
1992/1222    
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
	 */ 
1994/0130    
	slowoutb(port+Imr, 0x00); 
	while(isr = slowinb(port+Isr)){ 
1995/0408    
	dp8390outb(port+Imr, 0x00); 
	while(isr = dp8390inb(port+Isr)){ 
1992/1222    
 
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1994/0130    
			slowoutb(port+Isr, Ovw); 
1995/0408    
			dp8390outb(port+Isr, Ovw); 
1993/1116    
			ether->overflows++; 
1992/1222    
		} 
 
1994/0715/sys/src/9/pc/ether8390.c:594,6001995/0408/sys/src/9/pc/ether8390.c:611,617
1992/1222    
		 */ 
		if(isr & (Rxe|Prx)){ 
1993/1116    
			receive(ether); 
1994/0130    
			slowoutb(port+Isr, Rxe|Prx); 
1995/0408    
			dp8390outb(port+Isr, Rxe|Prx); 
1992/1222    
		} 
 
		/* 
1994/0715/sys/src/9/pc/ether8390.c:603,6091995/0408/sys/src/9/pc/ether8390.c:620,626
1992/1222    
		 * and wake the output routine. 
		 */ 
		if(isr & (Txe|Ptx)){ 
1994/0130    
			r = slowinb(port+Tsr); 
1995/0408    
			r = dp8390inb(port+Tsr); 
1993/0212    
			if(isr & Txe){ 
1993/1118    
				if((r & (Cdh|Fu|Crs|Abt))) 
					print("dp8390: Tsr#%2.2ux\n", r); 
1994/0715/sys/src/9/pc/ether8390.c:610,6161995/0408/sys/src/9/pc/ether8390.c:627,633
1993/1116    
				ether->oerrs++; 
1993/0212    
			} 
 
1994/0130    
			slowoutb(port+Isr, Txe|Ptx); 
1995/0408    
			dp8390outb(port+Isr, Txe|Ptx); 
1993/0212    
 
			if(isr & Ptx) 
1993/1116    
				ether->outpackets++; 
1994/0715/sys/src/9/pc/ether8390.c:619,6311995/0408/sys/src/9/pc/ether8390.c:636,648
1992/1222    
		} 
1993/0212    
 
		if(isr & Cnt){ 
1994/0130    
			ether->frames += slowinb(port+Cntr0); 
			ether->crcs += slowinb(port+Cntr1); 
			ether->buffs += slowinb(port+Cntr2); 
			slowoutb(port+Isr, Cnt); 
1995/0408    
			ether->frames += dp8390inb(port+Cntr0); 
			ether->crcs += dp8390inb(port+Cntr1); 
			ether->buffs += dp8390inb(port+Cntr2); 
			dp8390outb(port+Isr, Cnt); 
1993/0212    
		} 
1992/1222    
	} 
1994/0130    
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1995/0408    
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
} 
 
static void 
1994/0715/sys/src/9/pc/ether8390.c:637,6451995/0408/sys/src/9/pc/ether8390.c:654,662
1993/1116    
	 * Set/reset promiscuous mode. 
	 */ 
	if(on) 
1994/0130    
		slowoutb(dp8390->dp8390+Rcr, Pro|Ab); 
1995/0408    
		dp8390outb(dp8390->dp8390+Rcr, Pro|Ab); 
1993/1116    
	else 
1994/0130    
		slowoutb(dp8390->dp8390+Rcr, Ab); 
1995/0408    
		dp8390outb(dp8390->dp8390+Rcr, Ab); 
1993/1116    
} 
 
1993/1118    
static void 
1994/0715/sys/src/9/pc/ether8390.c:653,6601995/0408/sys/src/9/pc/ether8390.c:670,677
1993/1116    
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
	 */ 
1994/0130    
	slowoutb(dp8390->dp8390+Rcr, Ab); 
	slowinb(dp8390->dp8390+Cntr2); 
1995/0408    
	dp8390outb(dp8390->dp8390+Rcr, Ab); 
	dp8390inb(dp8390->dp8390+Cntr2); 
1993/1116    
} 
 
1993/1118    
int 
1994/0715/sys/src/9/pc/ether8390.c:673,6871995/0408/sys/src/9/pc/ether8390.c:690,704
1993/1116    
	 */  
1993/1118    
	dp8390disable(dp8390); 
	if(dp8390->bit16) 
1994/0130    
		slowoutb(port+Dcr, Ft4|Ls|Wts); 
1995/0408    
		dp8390outb(port+Dcr, Ft4|Ls|Wts); 
1993/1116    
	else 
1994/0130    
		slowoutb(port+Dcr, Ft4|Ls); 
1995/0408    
		dp8390outb(port+Dcr, Ft4|Ls); 
1993/1116    
 
1994/0130    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1995/0408    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1993/1116    
 
1994/0130    
	slowoutb(port+Tcr, 0); 
	slowoutb(port+Rcr, Mon); 
1995/0408    
	dp8390outb(port+Tcr, 0); 
	dp8390outb(port+Rcr, Mon); 
1993/1116    
 
	/* 
	 * Init the ring hardware and software ring pointers. 
1994/0715/sys/src/9/pc/ether8390.c:689,7041995/0408/sys/src/9/pc/ether8390.c:706,721
1993/1116    
	 * it yet. 
	 */ 
1993/1118    
	dp8390ring(dp8390); 
1994/0130    
	slowoutb(port+Tpsr, dp8390->tstart); 
1995/0408    
	dp8390outb(port+Tpsr, dp8390->tstart); 
1993/1116    
 
1994/0130    
	slowoutb(port+Isr, 0xFF); 
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1995/0408    
	dp8390outb(port+Isr, 0xFF); 
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
 
	/* 
	 * Leave the chip initialised, 
	 * but in monitor mode. 
	 */ 
1994/0130    
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1995/0408    
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1993/1116    
 
	/* 
	 * Set up the software configuration. 
1995/0408/sys/src/9/pc/ether8390.c:14,191995/0409/sys/src/9/pc/ether8390.c:14,22 (short | long)
1992/1222    
 
1993/1116    
#include "etherif.h" 
1992/1222    
 
1995/0409    
extern int slowinb(ulong); 
extern void slowoutb(ulong, uchar); 
 
1992/1222    
enum { 
	Cr		= 0x00,		/* command register, all pages */ 
 
1995/0408/sys/src/9/pc/ether8390.c:146,1711995/0409/sys/src/9/pc/ether8390.c:149,154
1992/1222    
	uchar	len1; 
} Hdr; 
 
1995/0408    
/* 
 *  the 8390 register accesses must not be too close together 
 */ 
void 
dp8390outb(ulong port, uchar x) 
{ 
	outb(port, x); 
	microdelay(0); 
} 
                 
long 
dp8390inb(ulong port) 
{ 
	long x; 
                 
	x = inb(port); 
	microdelay(0); 
	return x; 
} 
                 
1992/1222    
static void 
1993/1117    
dp8390disable(Dp8390 *dp8390) 
1992/1222    
{ 
1995/0408/sys/src/9/pc/ether8390.c:180,1891995/0409/sys/src/9/pc/ether8390.c:163,172
1992/1222    
	 * chip there if this is called when probing for a device 
	 * at boot. 
	 */ 
1995/0408    
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
	for(timo = 10000; (dp8390inb(port+Isr) & Rst) == 0 && timo; timo--) 
1995/0409    
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
	for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--) 
1992/1222    
			; 
} 
 
1995/0408/sys/src/9/pc/ether8390.c:192,2041995/0409/sys/src/9/pc/ether8390.c:175,187
1993/0212    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
 
1995/0408    
	dp8390outb(port+Pstart, dp8390->pstart); 
	dp8390outb(port+Pstop, dp8390->pstop); 
	dp8390outb(port+Bnry, dp8390->pstop-1); 
1995/0409    
	slowoutb(port+Pstart, dp8390->pstart); 
	slowoutb(port+Pstop, dp8390->pstop); 
	slowoutb(port+Bnry, dp8390->pstop-1); 
1993/0212    
 
1995/0408    
	dp8390outb(port+Cr, Page1|RDMAabort|Stp); 
	dp8390outb(port+Curr, dp8390->pstart); 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1995/0409    
	slowoutb(port+Cr, Page1|RDMAabort|Stp); 
	slowoutb(port+Curr, dp8390->pstart); 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/0915    
 
1993/1117    
	dp8390->nxtpkt = dp8390->pstart; 
1993/0212    
} 
1995/0408/sys/src/9/pc/ether8390.c:217,2271995/0409/sys/src/9/pc/ether8390.c:200,210
1992/1222    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1995/0408    
		dp8390outb(port+Par0+i, ether->ea[i]); 
	dp8390outb(port+Cr, cr); 
1995/0409    
		slowoutb(port+Par0+i, ether->ea[i]); 
	slowoutb(port+Cr, cr); 
1992/1222    
} 
 
1993/0915    
void 
1995/0408/sys/src/9/pc/ether8390.c:238,2481995/0409/sys/src/9/pc/ether8390.c:221,231
1993/0915    
	 * addresses as we never set the multicast 
	 * enable. 
	 */ 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1995/0408    
		ether->ea[i] = dp8390inb(port+Par0+i); 
	dp8390outb(port+Cr, cr); 
1995/0409    
		ether->ea[i] = slowinb(port+Par0+i); 
	slowoutb(port+Cr, cr); 
1993/0915    
} 
 
1994/0128    
void* 
1995/0408/sys/src/9/pc/ether8390.c:257,2651995/0409/sys/src/9/pc/ether8390.c:240,248
1992/1222    
	 * using the DP8390 remote DMA facility, and place it at 
	 * 'to' in main memory, via the I/O data port. 
	 */ 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1992/1222    
 
	/* 
	 * Set up the remote DMA address and count. 
1995/0408/sys/src/9/pc/ether8390.c:266,2811995/0409/sys/src/9/pc/ether8390.c:249,264
1992/1222    
	 */ 
1993/1117    
	if(dp8390->bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
1995/0408    
	dp8390outb(port+Rbcr0, len & 0xFF); 
	dp8390outb(port+Rbcr1, (len>>8) & 0xFF); 
	dp8390outb(port+Rsar0, from & 0xFF); 
	dp8390outb(port+Rsar1, (from>>8) & 0xFF); 
1995/0409    
	slowoutb(port+Rbcr0, len & 0xFF); 
	slowoutb(port+Rbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Rsar0, from & 0xFF); 
	slowoutb(port+Rsar1, (from>>8) & 0xFF); 
1992/1222    
 
	/* 
	 * Start the remote DMA read and suck the data 
	 * out of the I/O port. 
	 */ 
1995/0408    
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
1995/0409    
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1993/1117    
	if(dp8390->bit16) 
		inss(dp8390->data, to, len/2); 
1992/1222    
	else 
1995/0408/sys/src/9/pc/ether8390.c:288,2981995/0409/sys/src/9/pc/ether8390.c:271,281
1992/1222    
	 * to the miracles of the bus, we could get this far 
	 * and still be talking to a slot full of nothing. 
	 */ 
1995/0408    
	for(timo = 10000; (dp8390inb(port+Isr) & Rdc) == 0 && timo; timo--) 
1995/0409    
	for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--) 
1992/1222    
			; 
 
1995/0408    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1995/0409    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1992/1222    
	return to; 
} 
 
1995/0408/sys/src/9/pc/ether8390.c:315,3231995/0409/sys/src/9/pc/ether8390.c:298,306
1992/1222    
	 * using the DP8390 remote DMA facility, reading it at 
	 * 'from' in main memory, via the I/O data port. 
	 */ 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
	dp8390outb(port+Isr, Rdc); 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1992/1222    
 
1993/1118    
	if(dp8390->bit16) 
1993/0212    
		len = ROUNDUP(len, 2); 
1995/0408/sys/src/9/pc/ether8390.c:328,3511995/0409/sys/src/9/pc/ether8390.c:311,334
1993/0212    
	 * the initial set up for read. 
1992/1222    
	 */ 
1993/1118    
	crda = to-1-dp8390->bit16; 
1995/0408    
	dp8390outb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	dp8390outb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	dp8390outb(port+Rsar0, crda & 0xFF); 
	dp8390outb(port+Rsar1, (crda>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAread|Sta); 
1995/0409    
	slowoutb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	slowoutb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	slowoutb(port+Rsar0, crda & 0xFF); 
	slowoutb(port+Rsar1, (crda>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1992/1222    
 
1993/0212    
	for(;;){ 
1995/0408    
		crda = dp8390inb(port+Crda0); 
		crda |= dp8390inb(port+Crda1)<<8; 
1995/0409    
		crda = slowinb(port+Crda0); 
		crda |= slowinb(port+Crda1)<<8; 
1993/0212    
		if(crda == to){ 
			/* 
			 * Start the remote DMA write and make sure 
			 * the registers are correct. 
			 */ 
1995/0408    
			dp8390outb(port+Cr, Page0|RDMAwrite|Sta); 
1995/0409    
			slowoutb(port+Cr, Page0|RDMAwrite|Sta); 
1992/1222    
 
1995/0408    
			crda = dp8390inb(port+Crda0); 
			crda |= dp8390inb(port+Crda1)<<8; 
1995/0409    
			crda = slowinb(port+Crda0); 
			crda |= slowinb(port+Crda1)<<8; 
1993/0212    
			if(crda != to) 
				panic("crda write %d to %d\n", crda, to); 
 
1995/0408/sys/src/9/pc/ether8390.c:366,3721995/0409/sys/src/9/pc/ether8390.c:349,355
1994/0202    
	 * be almost immediate. 
1992/1222    
	 */ 
1994/0201    
	tries = 0; 
1995/0408    
	while((dp8390inb(port+Isr) & Rdc) == 0){ 
1995/0409    
	while((slowinb(port+Isr) & Rdc) == 0){ 
1994/0202    
		if(tries++ >= 100000){ 
			print("dp8390write dma timed out\n"); 
1994/0201    
			break; 
1995/0408/sys/src/9/pc/ether8390.c:373,3801995/0409/sys/src/9/pc/ether8390.c:356,363
1994/0201    
		} 
1994/0202    
	} 
1992/1222    
 
1995/0408    
	dp8390outb(port+Isr, Rdc); 
	dp8390outb(port+Cr, cr); 
1995/0409    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1994/0202    
	splx(s); 
 
1992/1222    
	return (void*)to; 
1995/0408/sys/src/9/pc/ether8390.c:386,3951995/0409/sys/src/9/pc/ether8390.c:369,378
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
	uchar cr, curr; 
 
1995/0408    
	cr = dp8390inb(port+Cr) & ~Txp; 
	dp8390outb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = dp8390inb(port+Curr); 
	dp8390outb(port+Cr, cr); 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = slowinb(port+Curr); 
	slowoutb(port+Cr, cr); 
1993/0212    
	return curr; 
} 
 
1995/0408/sys/src/9/pc/ether8390.c:433,4411995/0409/sys/src/9/pc/ether8390.c:416,424
1993/0212    
		  || len < 60 || len > sizeof(Etherpkt)){ 
1993/1118    
			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", 
1993/0212    
				hdr.status, hdr.next, hdr.len0, hdr.len1, len); 
1995/0408    
			dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1995/0409    
			slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/1118    
			dp8390ring(dp8390); 
1995/0408    
			dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1995/0409    
			slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1992/1222    
			return; 
		} 
 
1995/0408/sys/src/9/pc/ether8390.c:484,4901995/0409/sys/src/9/pc/ether8390.c:467,473
1993/0212    
		hdr.next--; 
1993/1118    
		if(hdr.next < dp8390->pstart) 
			hdr.next = dp8390->pstop-1; 
1995/0408    
		dp8390outb(port+Bnry, hdr.next); 
1995/0409    
		slowoutb(port+Bnry, hdr.next); 
1992/1222    
	} 
} 
 
1995/0408/sys/src/9/pc/ether8390.c:536,5441995/0409/sys/src/9/pc/ether8390.c:519,527
1993/1120    
	if(dp8390->ram == 0) 
		dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); 
 
1995/0408    
	dp8390outb(port+Tbcr0, len & 0xFF); 
	dp8390outb(port+Tbcr1, (len>>8) & 0xFF); 
	dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1995/0409    
	slowoutb(port+Tbcr0, len & 0xFF); 
	slowoutb(port+Tbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1993/1118    
 
1993/1120    
	return len; 
1993/0212    
} 
1995/0408/sys/src/9/pc/ether8390.c:558,5811995/0409/sys/src/9/pc/ether8390.c:541,564
1993/0212    
	 * The following procedure is taken from the DP8390[12D] datasheet, 
	 * it seems pretty adamant that this is what has to be done. 
	 */ 
1995/0408    
	txp = dp8390inb(port+Cr) & Txp; 
	dp8390outb(port+Cr, Page0|RDMAabort|Stp); 
1995/0409    
	txp = slowinb(port+Cr) & Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/0212    
	delay(2); 
1995/0408    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1995/0409    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1993/0212    
 
	resend = 0; 
1995/0408    
	if(txp && (dp8390inb(port+Isr) & (Txe|Ptx)) == 0) 
1995/0409    
	if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0) 
1993/0212    
		resend = 1; 
 
1995/0408    
	dp8390outb(port+Tcr, Lb); 
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1995/0409    
	slowoutb(port+Tcr, Lb); 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1993/1118    
	receive(ether); 
1995/0408    
	dp8390outb(port+Isr, Ovw); 
	dp8390outb(port+Tcr, 0); 
1995/0409    
	slowoutb(port+Isr, Ovw); 
	slowoutb(port+Tcr, 0); 
1993/0212    
 
	if(resend) 
1995/0408    
		dp8390outb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1995/0409    
		slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1993/0212    
} 
 
1993/1116    
static void 
1995/0408/sys/src/9/pc/ether8390.c:596,6071995/0409/sys/src/9/pc/ether8390.c:579,590
1992/1222    
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
	 */ 
1995/0408    
	dp8390outb(port+Imr, 0x00); 
	while(isr = dp8390inb(port+Isr)){ 
1995/0409    
	slowoutb(port+Imr, 0x00); 
	while(isr = slowinb(port+Isr)){ 
1992/1222    
 
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1995/0408    
			dp8390outb(port+Isr, Ovw); 
1995/0409    
			slowoutb(port+Isr, Ovw); 
1993/1116    
			ether->overflows++; 
1992/1222    
		} 
 
1995/0408/sys/src/9/pc/ether8390.c:611,6171995/0409/sys/src/9/pc/ether8390.c:594,600
1992/1222    
		 */ 
		if(isr & (Rxe|Prx)){ 
1993/1116    
			receive(ether); 
1995/0408    
			dp8390outb(port+Isr, Rxe|Prx); 
1995/0409    
			slowoutb(port+Isr, Rxe|Prx); 
1992/1222    
		} 
 
		/* 
1995/0408/sys/src/9/pc/ether8390.c:620,6261995/0409/sys/src/9/pc/ether8390.c:603,609
1992/1222    
		 * and wake the output routine. 
		 */ 
		if(isr & (Txe|Ptx)){ 
1995/0408    
			r = dp8390inb(port+Tsr); 
1995/0409    
			r = slowinb(port+Tsr); 
1993/0212    
			if(isr & Txe){ 
1993/1118    
				if((r & (Cdh|Fu|Crs|Abt))) 
					print("dp8390: Tsr#%2.2ux\n", r); 
1995/0408/sys/src/9/pc/ether8390.c:627,6331995/0409/sys/src/9/pc/ether8390.c:610,616
1993/1116    
				ether->oerrs++; 
1993/0212    
			} 
 
1995/0408    
			dp8390outb(port+Isr, Txe|Ptx); 
1995/0409    
			slowoutb(port+Isr, Txe|Ptx); 
1993/0212    
 
			if(isr & Ptx) 
1993/1116    
				ether->outpackets++; 
1995/0408/sys/src/9/pc/ether8390.c:636,6481995/0409/sys/src/9/pc/ether8390.c:619,631
1992/1222    
		} 
1993/0212    
 
		if(isr & Cnt){ 
1995/0408    
			ether->frames += dp8390inb(port+Cntr0); 
			ether->crcs += dp8390inb(port+Cntr1); 
			ether->buffs += dp8390inb(port+Cntr2); 
			dp8390outb(port+Isr, Cnt); 
1995/0409    
			ether->frames += slowinb(port+Cntr0); 
			ether->crcs += slowinb(port+Cntr1); 
			ether->buffs += slowinb(port+Cntr2); 
			slowoutb(port+Isr, Cnt); 
1993/0212    
		} 
1992/1222    
	} 
1995/0408    
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1995/0409    
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
} 
 
static void 
1995/0408/sys/src/9/pc/ether8390.c:654,6621995/0409/sys/src/9/pc/ether8390.c:637,645
1993/1116    
	 * Set/reset promiscuous mode. 
	 */ 
	if(on) 
1995/0408    
		dp8390outb(dp8390->dp8390+Rcr, Pro|Ab); 
1995/0409    
		slowoutb(dp8390->dp8390+Rcr, Pro|Ab); 
1993/1116    
	else 
1995/0408    
		dp8390outb(dp8390->dp8390+Rcr, Ab); 
1995/0409    
		slowoutb(dp8390->dp8390+Rcr, Ab); 
1993/1116    
} 
 
1993/1118    
static void 
1995/0408/sys/src/9/pc/ether8390.c:670,6771995/0409/sys/src/9/pc/ether8390.c:653,660
1993/1116    
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
	 */ 
1995/0408    
	dp8390outb(dp8390->dp8390+Rcr, Ab); 
	dp8390inb(dp8390->dp8390+Cntr2); 
1995/0409    
	slowoutb(dp8390->dp8390+Rcr, Ab); 
	slowinb(dp8390->dp8390+Cntr2); 
1993/1116    
} 
 
1993/1118    
int 
1995/0408/sys/src/9/pc/ether8390.c:690,7041995/0409/sys/src/9/pc/ether8390.c:673,687
1993/1116    
	 */  
1993/1118    
	dp8390disable(dp8390); 
	if(dp8390->bit16) 
1995/0408    
		dp8390outb(port+Dcr, Ft4|Ls|Wts); 
1995/0409    
		slowoutb(port+Dcr, Ft4|Ls|Wts); 
1993/1116    
	else 
1995/0408    
		dp8390outb(port+Dcr, Ft4|Ls); 
1995/0409    
		slowoutb(port+Dcr, Ft4|Ls); 
1993/1116    
 
1995/0408    
	dp8390outb(port+Rbcr0, 0); 
	dp8390outb(port+Rbcr1, 0); 
1995/0409    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1993/1116    
 
1995/0408    
	dp8390outb(port+Tcr, 0); 
	dp8390outb(port+Rcr, Mon); 
1995/0409    
	slowoutb(port+Tcr, 0); 
	slowoutb(port+Rcr, Mon); 
1993/1116    
 
	/* 
	 * Init the ring hardware and software ring pointers. 
1995/0408/sys/src/9/pc/ether8390.c:706,7211995/0409/sys/src/9/pc/ether8390.c:689,704
1993/1116    
	 * it yet. 
	 */ 
1993/1118    
	dp8390ring(dp8390); 
1995/0408    
	dp8390outb(port+Tpsr, dp8390->tstart); 
1995/0409    
	slowoutb(port+Tpsr, dp8390->tstart); 
1993/1116    
 
1995/0408    
	dp8390outb(port+Isr, 0xFF); 
	dp8390outb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1995/0409    
	slowoutb(port+Isr, 0xFF); 
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1993/1116    
 
	/* 
	 * Leave the chip initialised, 
	 * but in monitor mode. 
	 */ 
1995/0408    
	dp8390outb(port+Cr, Page0|RDMAabort|Sta); 
1995/0409    
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1993/1116    
 
	/* 
	 * Set up the software configuration. 
1995/0409/sys/src/9/pc/ether8390.c:189,1951995/0721/sys/src/9/pc/ether8390.c:189,195 (short | long)
1992/1222    
void 
1993/1116    
dp8390setea(Ether *ether) 
1992/1222    
{ 
1993/1118    
	ulong port = ((Dp8390*)ether->private)->dp8390; 
1995/0721    
	ulong port = ((Dp8390*)ether->ctlr)->dp8390; 
1992/1222    
	uchar cr; 
	int i; 
 
1995/0409/sys/src/9/pc/ether8390.c:210,2161995/0721/sys/src/9/pc/ether8390.c:210,216
1993/0915    
void 
1993/1116    
dp8390getea(Ether *ether) 
1993/0915    
{ 
1993/1118    
	ulong port = ((Dp8390*)ether->private)->dp8390; 
1995/0721    
	ulong port = ((Dp8390*)ether->ctlr)->dp8390; 
1993/0915    
	uchar cr; 
	int i; 
 
1995/0409/sys/src/9/pc/ether8390.c:384,3901995/0721/sys/src/9/pc/ether8390.c:384,390
1992/1222    
	Hdr hdr; 
1993/1118    
	ulong port, data, len, len1; 
1992/1222    
 
1993/1118    
	dp8390 = ether->private; 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
	for(curr = getcurr(dp8390); dp8390->nxtpkt != curr; curr = getcurr(dp8390)){ 
1993/1116    
		ether->inpackets++; 
1995/0409/sys/src/9/pc/ether8390.c:455,4611995/0721/sys/src/9/pc/ether8390.c:455,461
1993/1116    
			/* 
			 * Copy the packet to whoever wants it. 
			 */ 
1994/0715    
			etherrloop(ether, ðer->rpkt, len, 1); 
1995/0721    
			etherrloop(ether, ðer->rpkt, len); 
1992/1222    
		} 
 
1993/0212    
		/* 
1995/0409/sys/src/9/pc/ether8390.c:484,4901995/0721/sys/src/9/pc/ether8390.c:484,490
1993/1118    
	ulong port; 
1993/1120    
	Etherpkt *pkt; 
1993/0213    
 
1993/1118    
	dp8390 = ether->private; 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
1993/0213    
 
1993/1119    
	tsleep(ðer->tr, istxavail, ether, 10000); 
1995/0409/sys/src/9/pc/ether8390.c:534,5401995/0721/sys/src/9/pc/ether8390.c:534,540
1993/0212    
	uchar txp; 
	int resend; 
 
1993/1118    
	dp8390 = ether->private; 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
 
1993/0212    
	/* 
1995/0409/sys/src/9/pc/ether8390.c:572,5781995/0721/sys/src/9/pc/ether8390.c:572,578
1993/1124    
	USED(ur); 
 
	ether = arg; 
1993/1118    
	dp8390 = ether->private; 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
 
1992/1222    
	/* 
1995/0409/sys/src/9/pc/ether8390.c:631,6371995/0721/sys/src/9/pc/ether8390.c:631,637
1993/1116    
static void 
1993/1118    
promiscuous(void *arg, int on) 
1993/1116    
{ 
1993/1118    
	Dp8390 *dp8390 = ((Ether*)arg)->private; 
1995/0721    
	Dp8390 *dp8390 = ((Ether*)arg)->ctlr; 
1993/1117    
 
1993/1116    
	/* 
	 * Set/reset promiscuous mode. 
1995/0409/sys/src/9/pc/ether8390.c:645,6511995/0721/sys/src/9/pc/ether8390.c:645,651
1993/1118    
static void 
attach(Ether *ether) 
1993/1116    
{ 
1993/1118    
	Dp8390 *dp8390 = ether->private; 
1995/0721    
	Dp8390 *dp8390 = ether->ctlr; 
1993/1117    
 
1993/1116    
	/* 
	 * Enable the chip for transmit/receive. 
1995/0409/sys/src/9/pc/ether8390.c:663,6691995/0721/sys/src/9/pc/ether8390.c:663,669
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1993/1116    
 
1993/1118    
	dp8390 = ether->private; 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
 
1993/1116    
	/* 
1995/0721/sys/src/9/pc/ether8390.c:646,6511995/0801/sys/src/9/pc/ether8390.c:646,652 (short | long)
1993/1118    
attach(Ether *ether) 
1993/1116    
{ 
1995/0721    
	Dp8390 *dp8390 = ether->ctlr; 
1995/0801    
	int x; 
1993/1117    
 
1993/1116    
	/* 
	 * Enable the chip for transmit/receive. 
1995/0721/sys/src/9/pc/ether8390.c:653,6581995/0801/sys/src/9/pc/ether8390.c:654,662
1993/1116    
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
	 */ 
1995/0801    
	x = Ab; 
	if(ether->prom) 
		x |= Pro; 
1995/0409    
	slowoutb(dp8390->dp8390+Rcr, Ab); 
	slowinb(dp8390->dp8390+Cntr2); 
1993/1116    
} 
1995/0801/sys/src/9/pc/ether8390.c:562,5681995/0829/sys/src/9/pc/ether8390.c:562,568 (short | long)
1993/0212    
} 
 
1993/1116    
static void 
1993/1124    
interrupt(Ureg *ur, void *arg) 
1995/0829    
interrupt(Ureg*, void *arg) 
1993/0212    
{ 
1993/1124    
	Ether *ether; 
1993/1118    
	Dp8390 *dp8390; 
1995/0801/sys/src/9/pc/ether8390.c:569,5761995/0829/sys/src/9/pc/ether8390.c:569,574
1993/1118    
	ulong port; 
1993/0212    
	uchar isr, r; 
1992/1222    
 
1993/1124    
	USED(ur); 
                 
	ether = arg; 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
1995/0801/sys/src/9/pc/ether8390.c:580,5861995/0829/sys/src/9/pc/ether8390.c:578,584
1992/1222    
	 * clear all the interrupts and process. 
	 */ 
1995/0409    
	slowoutb(port+Imr, 0x00); 
	while(isr = slowinb(port+Isr)){ 
1995/0829    
	while(isr = (slowinb(port+Isr) & (Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe))){ 
1992/1222    
 
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1995/0801/sys/src/9/pc/ether8390.c:657,6631995/0829/sys/src/9/pc/ether8390.c:655,661
1995/0801    
	x = Ab; 
	if(ether->prom) 
		x |= Pro; 
1995/0409    
	slowoutb(dp8390->dp8390+Rcr, Ab); 
1995/0829    
	slowoutb(dp8390->dp8390+Rcr, x); 
1995/0409    
	slowinb(dp8390->dp8390+Cntr2); 
1993/1116    
} 
 
1995/0829/sys/src/9/pc/ether8390.c:207,2331996/0420/sys/src/9/pc/ether8390.c:207,212 (short | long)
1995/0409    
	slowoutb(port+Cr, cr); 
1992/1222    
} 
 
1993/0915    
void 
1993/1116    
dp8390getea(Ether *ether) 
1993/0915    
{ 
1995/0721    
	ulong port = ((Dp8390*)ether->ctlr)->dp8390; 
1993/0915    
	uchar cr; 
	int i; 
                 
	/* 
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 
	 * enable. 
	 */ 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1995/0409    
		ether->ea[i] = slowinb(port+Par0+i); 
	slowoutb(port+Cr, cr); 
1993/0915    
} 
                 
1994/0128    
void* 
1993/1117    
dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) 
1992/1222    
{ 
1996/0420/sys/src/9/pc/ether8390.c:1,61997/0327/sys/src/9/pc/ether8390.c:1,5 (short | long)
1992/1222    
/* 
 * National Semiconductor DP8390 
 * and SMC 83C90 
1997/0327    
 * National Semiconductor DP8390 and clone 
1992/1222    
 * Network Interface Controller. 
 */ 
#include "u.h" 
1996/0420/sys/src/9/pc/ether8390.c:13,401997/0327/sys/src/9/pc/ether8390.c:12,23
1993/1116    
#include "../port/netif.h" 
1992/1222    
 
1993/1116    
#include "etherif.h" 
1997/0327    
#include "ether8390.h" 
1992/1222    
 
1995/0409    
extern int slowinb(ulong); 
extern void slowoutb(ulong, uchar); 
                 
1992/1222    
enum { 
1997/0327    
enum {					/* NIC core registers */ 
1992/1222    
	Cr		= 0x00,		/* command register, all pages */ 
 
	Stp		= 0x01,		/* stop */ 
	Sta		= 0x02,		/* start */ 
	Txp		= 0x04,		/* transmit packet */ 
	RDMAread	= (1<<3),	/* remote DMA read */ 
	RDMAwrite	= (2<<3),	/* remote DMA write */ 
	RDMAsend	= (3<<3),	/* remote DMA send packet */ 
	RDMAabort	= (4<<3),	/* abort/complete remote DMA */ 
1993/0212    
	Ps0		= 0x40,		/* page select */ 
	Ps1		= 0x80,		/* page select */ 
	Page0		= 0x00, 
	Page1		= Ps0, 
	Page2		= Ps1, 
1992/1222    
}; 
                 
enum {					/* Page 0, read */ 
1997/0327    
					/* Page 0, read */ 
1992/1222    
	Clda0		= 0x01,		/* current local DMA address 0 */ 
	Clda1		= 0x02,		/* current local DMA address 1 */ 
	Bnry		= 0x03,		/* boundary pointer (R/W) */ 
1996/0420/sys/src/9/pc/ether8390.c:48,561997/0327/sys/src/9/pc/ether8390.c:31,38
1992/1222    
	Cntr0		= 0x0D,		/* frame alignment errors */ 
	Cntr1		= 0x0E,		/* CRC errors */ 
	Cntr2		= 0x0F,		/* missed packet errors */ 
}; 
 
enum {					/* Page 0, write */ 
1997/0327    
					/* Page 0, write */ 
1992/1222    
	Pstart		= 0x01,		/* page start register */ 
	Pstop		= 0x02,		/* page stop register */ 
	Tpsr		= 0x04,		/* transmit page start address */ 
1996/0420/sys/src/9/pc/ether8390.c:64,781997/0327/sys/src/9/pc/ether8390.c:46,77
1992/1222    
	Tcr		= 0x0D,		/* transmit configuration register */ 
	Dcr		= 0x0E,		/* data configuration register */ 
	Imr		= 0x0F,		/* interrupt mask */ 
}; 
 
enum {					/* Page 1, read/write */ 
1997/0327    
					/* Page 1, read/write */ 
1992/1222    
	Par0		= 0x01,		/* physical address register 0 */ 
	Curr		= 0x07,		/* current page register */ 
	Mar0		= 0x08,		/* multicast address register 0 */ 
}; 
 
enum {					/* Interrupt Status Register */ 
1997/0327    
enum {					/* Cr */ 
	Stp		= 0x01,		/* stop */ 
	Sta		= 0x02,		/* start */ 
	Txp		= 0x04,		/* transmit packet */ 
	Rd0		= 0x08,		/* remote DMA command */ 
	Rd1		= 0x10,	 
	Rd2		= 0x20, 
	RdREAD		= Rd0,		/* remote read */ 
	RdWRITE		= Rd1,		/* remote write */ 
	RdSEND		= Rd1|Rd0,	/* send packet */ 
	RdABORT		= Rd2,		/* abort/complete remote DMA */ 
	Ps0		= 0x40,		/* page select */ 
	Ps1		= 0x80, 
	Page0		= 0x00, 
	Page1		= Ps0, 
	Page2		= Ps1, 
}; 
 
enum {					/* Isr/Imr */ 
1992/1222    
	Prx		= 0x01,		/* packet received */ 
	Ptx		= 0x02,		/* packet transmitted */ 
	Rxe		= 0x04,		/* receive error */ 
1996/0420/sys/src/9/pc/ether8390.c:83,1181997/0327/sys/src/9/pc/ether8390.c:82,114
1992/1222    
	Rst		= 0x80,		/* reset status */ 
}; 
 
enum {					/* Interrupt Mask Register */ 
	Prxe		= 0x01,		/* packet received interrupt enable */ 
	Ptxe		= 0x02,		/* packet transmitted interrupt enable */ 
	Rxee		= 0x04,		/* receive error interrupt enable */ 
	Txee		= 0x08,		/* transmit error interrupt enable */ 
	Ovwe		= 0x10,		/* overwrite warning interrupt enable */ 
	Cnte		= 0x20,		/* counter overflow interrupt enable */ 
	Rdce		= 0x40,		/* DMA complete interrupt enable */ 
}; 
                 
enum {					/* Data Configuration register */ 
1997/0327    
enum {					/* Dcr */ 
1992/1222    
	Wts		= 0x01,		/* word transfer select */ 
	Bos		= 0x02,		/* byte order select */ 
	Las		= 0x04,		/* long address select */ 
	Ls		= 0x08,		/* loopback select */ 
	Arm		= 0x10,		/* auto-initialise remote */ 
	Ft1		= (0x00<<5),	/* FIFO threshhold select 1 byte/word */ 
	Ft2		= (0x01<<5),	/* FIFO threshhold select 2 bytes/words */ 
	Ft4		= (0x02<<5),	/* FIFO threshhold select 4 bytes/words */ 
	Ft6		= (0x03<<5),	/* FIFO threshhold select 6 bytes/words */ 
1997/0327    
	Ft0		= 0x20,		/* FIFO threshold select */ 
	Ft1		= 0x40, 
	Ft1WORD		= 0x00, 
	Ft2WORD		= Ft0, 
	Ft4WORD		= Ft1, 
	Ft6WORD		= Ft1|Ft0, 
1992/1222    
}; 
 
enum {					/* Transmit Configuration Register */ 
1997/0327    
enum {					/* Tcr */ 
1992/1222    
	Crc		= 0x01,		/* inhibit CRC */ 
	Lb		= 0x02,		/* internal loopback */ 
1997/0327    
	Lb0		= 0x02,		/* encoded loopback control */ 
	Lb1		= 0x04, 
	LpbkNORMAL	= 0x00,		/* normal operation */ 
	LpbkNIC		= Lb0,		/* internal NIC module loopback */ 
	LpbkENDEC	= Lb1,		/* internal ENDEC module loopback */ 
	LpbkEXTERNAL	= Lb1|Lb0,	/* external loopback */ 
1992/1222    
	Atd		= 0x08,		/* auto transmit disable */ 
	Ofst		= 0x10,		/* collision offset enable */ 
}; 
 
enum {					/* Transmit Status Register */ 
1997/0327    
enum {					/* Tsr */ 
1992/1222    
	Ptxok		= 0x01,		/* packet transmitted */ 
	Col		= 0x04,		/* transmit collided */ 
	Abt		= 0x08,		/* tranmit aborted */ 
1996/0420/sys/src/9/pc/ether8390.c:122,1281997/0327/sys/src/9/pc/ether8390.c:118,124
1992/1222    
	Owc		= 0x80,		/* out of window collision */ 
}; 
 
enum {					/* Receive Configuration Register */ 
1997/0327    
enum {					/* Rcr */ 
1992/1222    
	Sep		= 0x01,		/* save errored packets */ 
	Ar		= 0x02,		/* accept runt packets */ 
	Ab		= 0x04,		/* accept broadcast */ 
1996/0420/sys/src/9/pc/ether8390.c:131,1371997/0327/sys/src/9/pc/ether8390.c:127,133
1992/1222    
	Mon		= 0x20,		/* monitor mode */ 
}; 
 
enum {					/* Receive Status Register */ 
1997/0327    
enum {					/* Rsr */ 
1992/1222    
	Prxok		= 0x01,		/* packet received intact */ 
	Crce		= 0x02,		/* CRC error */ 
	Fae		= 0x04,		/* frame alignment error */ 
1996/0420/sys/src/9/pc/ether8390.c:149,2161997/0327/sys/src/9/pc/ether8390.c:145,201
1992/1222    
	uchar	len1; 
} Hdr; 
 
static void 
1993/1117    
dp8390disable(Dp8390 *dp8390) 
1997/0327    
void 
dp8390getea(Ether* ether, uchar* ea) 
1992/1222    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1992/1222    
	int timo; 
1997/0327    
	Dp8390 *ctlr; 
	uchar cr; 
	int i; 
1992/1222    
 
1997/0327    
	ctlr = ether->ctlr; 
 
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 
	 * the Rst bit. 
	 * We need the timeout because there may not be a real 
	 * chip there if this is called when probing for a device 
	 * at boot. 
1997/0327    
	 * Get the ethernet address from the chip. 
	 * Take care to restore the command register 
	 * afterwards. 
1992/1222    
	 */ 
1995/0409    
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
	for(timo = 10000; (slowinb(port+Isr) & Rst) == 0 && timo; timo--) 
1992/1222    
			; 
1997/0327    
	ilock(ctlr); 
	cr = regr(ctlr, Cr) & ~Txp; 
	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); 
	for(i = 0; i < Eaddrlen; i++) 
		ea[i] = regr(ctlr, Par0+i); 
	regw(ctlr, Cr, cr); 
	iunlock(ctlr); 
1992/1222    
} 
 
1993/0212    
static void 
1993/1117    
dp8390ring(Dp8390 *dp8390) 
1993/0212    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
                 
1995/0409    
	slowoutb(port+Pstart, dp8390->pstart); 
	slowoutb(port+Pstop, dp8390->pstop); 
	slowoutb(port+Bnry, dp8390->pstop-1); 
1993/0212    
                 
1995/0409    
	slowoutb(port+Cr, Page1|RDMAabort|Stp); 
	slowoutb(port+Curr, dp8390->pstart); 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/0915    
                 
1993/1117    
	dp8390->nxtpkt = dp8390->pstart; 
1993/0212    
} 
                 
1992/1222    
void 
1993/1116    
dp8390setea(Ether *ether) 
1997/0327    
dp8390setea(Ether* ether) 
1992/1222    
{ 
1995/0721    
	ulong port = ((Dp8390*)ether->ctlr)->dp8390; 
1992/1222    
	uchar cr; 
	int i; 
1997/0327    
	uchar cr; 
	Dp8390 *ctlr; 
1992/1222    
 
1997/0327    
	ctlr = ether->ctlr; 
 
1992/1222    
	/* 
	 * Set the ethernet address into the chip. 
	 * Take care to restore the command register 
	 * afterwards. We don't care about multicast 
	 * addresses as we never set the multicast 
	 * enable. 
1997/0327    
	 * afterwards. Don't care about multicast 
	 * addresses as multicast is never enabled 
	 * (currently). 
1992/1222    
	 */ 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
1993/1116    
	for(i = 0; i < sizeof(ether->ea); i++) 
1995/0409    
		slowoutb(port+Par0+i, ether->ea[i]); 
	slowoutb(port+Cr, cr); 
1997/0327    
	ilock(ctlr); 
	cr = regr(ctlr, Cr) & ~Txp; 
	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); 
	for(i = 0; i < Eaddrlen; i++) 
		regw(ctlr, Par0+i, ether->ea[i]); 
	regw(ctlr, Cr, cr); 
	iunlock(ctlr); 
1992/1222    
} 
 
1994/0128    
void* 
1993/1117    
dp8390read(Dp8390 *dp8390, void *to, ulong from, ulong len) 
1997/0327    
static void* 
_dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len) 
1992/1222    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1992/1222    
	uchar cr; 
	int timo; 
 
1996/0420/sys/src/9/pc/ether8390.c:219,3781997/0327/sys/src/9/pc/ether8390.c:204,378
1992/1222    
	 * using the DP8390 remote DMA facility, and place it at 
	 * 'to' in main memory, via the I/O data port. 
	 */ 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1997/0327    
	cr = regr(ctlr, Cr) & ~Txp; 
	regw(ctlr, Cr, Page0|RdABORT|Sta); 
	regw(ctlr, Isr, Rdc); 
1992/1222    
 
	/* 
	 * Set up the remote DMA address and count. 
	 */ 
1993/1117    
	if(dp8390->bit16) 
1992/1222    
		len = ROUNDUP(len, 2); 
1995/0409    
	slowoutb(port+Rbcr0, len & 0xFF); 
	slowoutb(port+Rbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Rsar0, from & 0xFF); 
	slowoutb(port+Rsar1, (from>>8) & 0xFF); 
1997/0327    
	len = ROUNDUP(len, ctlr->width); 
	regw(ctlr, Rbcr0, len & 0xFF); 
	regw(ctlr, Rbcr1, (len>>8) & 0xFF); 
	regw(ctlr, Rsar0, from & 0xFF); 
	regw(ctlr, Rsar1, (from>>8) & 0xFF); 
1992/1222    
 
	/* 
	 * Start the remote DMA read and suck the data 
	 * out of the I/O port. 
	 */ 
1995/0409    
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1993/1117    
	if(dp8390->bit16) 
		inss(dp8390->data, to, len/2); 
1992/1222    
	else 
1993/1117    
		insb(dp8390->data, to, len); 
1997/0327    
	regw(ctlr, Cr, Page0|RdREAD|Sta); 
	rdread(ctlr, to, len); 
1992/1222    
 
	/* 
	 * Wait for the remote DMA to complete. The timeout 
	 * is necessary because we may call this routine on 
1997/0327    
	 * is necessary because this routine may be called on 
1992/1222    
	 * a non-existent chip during initialisation and, due 
	 * to the miracles of the bus, we could get this far 
	 * and still be talking to a slot full of nothing. 
1997/0327    
	 * to the miracles of the bus, it's possible to get this 
	 * far and still be talking to a slot full of nothing. 
1992/1222    
	 */ 
1995/0409    
	for(timo = 10000; (slowinb(port+Isr) & Rdc) == 0 && timo; timo--) 
1997/0327    
	for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--) 
1992/1222    
			; 
 
1995/0409    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1997/0327    
	regw(ctlr, Isr, Rdc); 
	regw(ctlr, Cr, cr); 
 
1992/1222    
	return to; 
} 
 
1994/0128    
void* 
1993/1118    
dp8390write(Dp8390 *dp8390, ulong to, void *from, ulong len) 
1997/0327    
dp8390read(Dp8390* ctlr, void* to, ulong from, ulong len) 
1992/1222    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1997/0327    
	void *v; 
 
	ilock(ctlr); 
	v = dp8390read(ctlr, to, from, len); 
	iunlock(ctlr); 
 
	return v; 
} 
 
static void* 
dp8390write(Dp8390* ctlr, ulong to, void* from, ulong len) 
{ 
1993/1118    
	ulong crda; 
1992/1222    
	uchar cr; 
1994/0201    
	int s, tries; 
1997/0327    
	int timo, width; 
1992/1222    
 
1994/0202    
	/* 
	 * Keep out interrupts since reading and writing 
	 * use the same DMA engine. 
	 */ 
1994/0201    
	s = splhi(); 
1994/0202    
                 
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 
	 * 'from' in main memory, via the I/O data port. 
	 */ 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
	slowoutb(port+Isr, Rdc); 
1997/0327    
	cr = regr(ctlr, Cr) & ~Txp; 
	regw(ctlr, Cr, Page0|RdABORT|Sta); 
	regw(ctlr, Isr, Rdc); 
1992/1222    
 
1993/1118    
	if(dp8390->bit16) 
1993/0212    
		len = ROUNDUP(len, 2); 
1997/0327    
	len = ROUNDUP(len, ctlr->width); 
1993/0212    
 
1992/1222    
	/* 
	 * Set up the remote DMA address and count. 
1993/0212    
	 * This is straight from the DP8390[12D] datasheet, hence 
	 * the initial set up for read. 
1997/0327    
	 * This is straight from the DP8390[12D] datasheet, 
	 * hence the initial set up for read. 
	 * Assumption here that the A7000 EtherV card will 
	 * never need a dummyrr. 
1992/1222    
	 */ 
1993/1118    
	crda = to-1-dp8390->bit16; 
1995/0409    
	slowoutb(port+Rbcr0, (len+1+dp8390->bit16) & 0xFF); 
	slowoutb(port+Rbcr1, ((len+1+dp8390->bit16)>>8) & 0xFF); 
	slowoutb(port+Rsar0, crda & 0xFF); 
	slowoutb(port+Rsar1, (crda>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAread|Sta); 
1992/1222    
                 
1993/0212    
	for(;;){ 
1995/0409    
		crda = slowinb(port+Crda0); 
		crda |= slowinb(port+Crda1)<<8; 
1993/0212    
		if(crda == to){ 
			/* 
			 * Start the remote DMA write and make sure 
			 * the registers are correct. 
			 */ 
1995/0409    
			slowoutb(port+Cr, Page0|RDMAwrite|Sta); 
1992/1222    
                 
1995/0409    
			crda = slowinb(port+Crda0); 
			crda |= slowinb(port+Crda1)<<8; 
1993/0212    
			if(crda != to) 
				panic("crda write %d to %d\n", crda, to); 
                 
			break; 
1997/0327    
	if(ctlr->dummyrr && (ctlr->width == 1 || ctlr->width == 2)){ 
		if(ctlr->width == 2) 
			width = 1; 
		else 
			width = 0; 
		crda = to-1-width; 
		regw(ctlr, Rbcr0, (len+1+width) & 0xFF); 
		regw(ctlr, Rbcr1, ((len+1+width)>>8) & 0xFF); 
		regw(ctlr, Rsar0, crda & 0xFF); 
		regw(ctlr, Rsar1, (crda>>8) & 0xFF); 
		regw(ctlr, Cr, Page0|RdREAD|Sta); 
	 
		for(;;){ 
			crda = regr(ctlr, Crda0); 
			crda |= regr(ctlr, Crda1)<<8; 
			if(crda == to){ 
				/* 
				 * Start the remote DMA write and make sure 
				 * the registers are correct. 
				 */ 
				regw(ctlr, Cr, Page0|RdWRITE|Sta); 
	 
				crda = regr(ctlr, Crda0); 
				crda |= regr(ctlr, Crda1)<<8; 
				if(crda != to) 
					panic("crda write %d to %d\n", crda, to); 
	 
				break; 
			} 
1993/0212    
		} 
	} 
1997/0327    
	else{ 
		regw(ctlr, Rsar0, to & 0xFF); 
		regw(ctlr, Rsar1, (to>>8) & 0xFF); 
		regw(ctlr, Rbcr0, len & 0xFF); 
		regw(ctlr, Rbcr1, (len>>8) & 0xFF); 
		regw(ctlr, Cr, Page0|RdWRITE|Sta); 
	} 
1993/0212    
 
1992/1222    
	/* 
1993/0212    
	 * Pump the data into the I/O port. 
1997/0327    
	 * Pump the data into the I/O port 
	 * then wait for the remote DMA to finish. 
1992/1222    
	 */ 
1993/1118    
	if(dp8390->bit16) 
		outss(dp8390->data, from, len/2); 
1992/1222    
	else 
1993/1118    
		outsb(dp8390->data, from, len); 
1997/0327    
	rdwrite(ctlr, from, len); 
	for(timo = 10000; (regr(ctlr, Isr) & Rdc) == 0 && timo; timo--) 
			; 
1992/1222    
 
	/* 
1994/0202    
	 * Wait for the remote DMA to finish. It should 
	 * be almost immediate. 
1992/1222    
	 */ 
1994/0201    
	tries = 0; 
1995/0409    
	while((slowinb(port+Isr) & Rdc) == 0){ 
1994/0202    
		if(tries++ >= 100000){ 
			print("dp8390write dma timed out\n"); 
1994/0201    
			break; 
		} 
1994/0202    
	} 
1997/0327    
	regw(ctlr, Isr, Rdc); 
	regw(ctlr, Cr, cr); 
1992/1222    
 
1995/0409    
	slowoutb(port+Isr, Rdc); 
	slowoutb(port+Cr, cr); 
1994/0202    
	splx(s); 
                 
1992/1222    
	return (void*)to; 
} 
 
1997/0327    
static void 
ringinit(Dp8390* ctlr) 
{ 
	regw(ctlr, Pstart, ctlr->pstart); 
	regw(ctlr, Pstop, ctlr->pstop); 
	regw(ctlr, Bnry, ctlr->pstop-1); 
 
	regw(ctlr, Cr, Page1|RdABORT|Stp); 
	regw(ctlr, Curr, ctlr->pstart); 
	regw(ctlr, Cr, Page0|RdABORT|Stp); 
 
	ctlr->nxtpkt = ctlr->pstart; 
} 
 
1993/0212    
static uchar 
1993/1118    
getcurr(Dp8390 *dp8390) 
1997/0327    
getcurr(Dp8390* ctlr) 
1993/0212    
{ 
1993/1118    
	ulong port = dp8390->dp8390; 
1993/0212    
	uchar cr, curr; 
 
1995/0409    
	cr = slowinb(port+Cr) & ~Txp; 
	slowoutb(port+Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = slowinb(port+Curr); 
	slowoutb(port+Cr, cr); 
1997/0327    
	cr = regr(ctlr, Cr) & ~Txp; 
	regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr)); 
	curr = regr(ctlr, Curr); 
	regw(ctlr, Cr, cr); 
 
1993/0212    
	return curr; 
} 
 
1993/0213    
static void 
1993/1116    
receive(Ether *ether) 
1997/0327    
receive(Ether* ether) 
1993/0213    
{ 
1993/1118    
	Dp8390 *dp8390; 
	uchar curr, *pkt; 
1997/0327    
	Dp8390 *ctlr; 
	uchar curr, *p; 
1992/1222    
	Hdr hdr; 
1993/1118    
	ulong port, data, len, len1; 
1997/0327    
	ulong count, data, len; 
	Block *bp; 
1992/1222    
 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
	for(curr = getcurr(dp8390); dp8390->nxtpkt != curr; curr = getcurr(dp8390)){ 
1993/1116    
		ether->inpackets++; 
1992/1222    
                 
1993/1118    
		data = dp8390->nxtpkt*Dp8390BufSz; 
		if(dp8390->ram) 
1997/0327    
	ctlr = ether->ctlr; 
	for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){ 
		data = ctlr->nxtpkt*Dp8390BufSz; 
		if(ctlr->ram) 
1993/1118    
			memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr)); 
		else 
			dp8390read(dp8390, &hdr, data, sizeof(Hdr)); 
1997/0327    
			_dp8390read(ctlr, &hdr, data, sizeof(Hdr)); 
1992/1222    
 
		/* 
1993/0212    
		 * Don't believe the upper byte count, work it 
1996/0420/sys/src/9/pc/ether8390.c:379,4401997/0327/sys/src/9/pc/ether8390.c:379,438
1993/0212    
		 * out from the software next-page pointer and 
		 * the current next-page pointer. 
1992/1222    
		 */ 
1993/1118    
		if(hdr.next > dp8390->nxtpkt) 
			len1 = hdr.next - dp8390->nxtpkt - 1; 
1997/0327    
		if(hdr.next > ctlr->nxtpkt) 
			len = hdr.next - ctlr->nxtpkt - 1; 
1993/0212    
		else 
1993/1118    
			len1 = (dp8390->pstop-dp8390->nxtpkt) + (hdr.next-dp8390->pstart) - 1; 
1997/0327    
			len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1; 
1993/0212    
		if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr))) 
			len1--; 
1997/0327    
			len--; 
1993/0212    
 
		len = ((len1<<8)|hdr.len0)-4; 
1997/0327    
		len = ((len<<8)|hdr.len0)-4; 
1993/0212    
 
		/* 
		 * Chip is badly scrogged, reinitialise the ring. 
		 */ 
1993/1118    
		if(hdr.next < dp8390->pstart || hdr.next >= dp8390->pstop 
1997/0327    
		if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop 
1993/0212    
		  || len < 60 || len > sizeof(Etherpkt)){ 
1993/1118    
			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d\n", 
1993/0212    
				hdr.status, hdr.next, hdr.len0, hdr.len1, len); 
1995/0409    
			slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1993/1118    
			dp8390ring(dp8390); 
1995/0409    
			slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1997/0327    
			regw(ctlr, Cr, Page0|RdABORT|Stp); 
			ringinit(ctlr); 
			regw(ctlr, Cr, Page0|RdABORT|Sta); 
 
1992/1222    
			return; 
		} 
 
1993/0212    
		/* 
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. 
1994/0202    
		 * 
		 * We could conceivably remove the copy into rpkt here by wrapping 
		 * this up with the etherrloop code. 
1997/0327    
		 * If the packet wraps round the hardware ring, read it in 
		 * two pieces. 
1993/0212    
		 */ 
1993/1116    
		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok){ 
1993/1118    
			pkt = (uchar*)ðer->rpkt; 
1997/0327    
		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && (bp = iallocb(len))){ 
			p = bp->rp; 
			bp->wp = p+len; 
1992/1222    
			data += sizeof(Hdr); 
1993/1118    
			len1 = len; 
1993/0212    
 
1993/1118    
			if((data+len1) >= dp8390->pstop*Dp8390BufSz){ 
				ulong count = dp8390->pstop*Dp8390BufSz - data; 
1993/0212    
                 
1993/1118    
				if(dp8390->ram) 
					memmove(pkt, (void*)(ether->mem+data), count); 
1997/0327    
			if((data+len) >= ctlr->pstop*Dp8390BufSz){ 
				count = ctlr->pstop*Dp8390BufSz - data; 
				if(ctlr->ram) 
					memmove(p, (void*)(ether->mem+data), count); 
1993/1118    
				else 
					dp8390read(dp8390, pkt, data, count); 
1993/0212    
				pkt += count; 
1993/1118    
				data = dp8390->pstart*Dp8390BufSz; 
				len1 -= count; 
1997/0327    
					_dp8390read(ctlr, p, data, count); 
				p += count; 
				data = ctlr->pstart*Dp8390BufSz; 
				len -= count; 
1992/1222    
			} 
1993/1118    
			if(len1){ 
				if(dp8390->ram) 
					memmove(pkt, (void*)(ether->mem+data), len1); 
1997/0327    
			if(len){ 
				if(ctlr->ram) 
					memmove(p, (void*)(ether->mem+data), len); 
1993/1118    
				else 
					dp8390read(dp8390, pkt, data, len1); 
1997/0327    
					_dp8390read(ctlr, p, data, len); 
1993/1118    
			} 
1993/0212    
 
1993/1116    
			/* 
			 * Copy the packet to whoever wants it. 
			 */ 
1995/0721    
			etherrloop(ether, ðer->rpkt, len); 
1997/0327    
			etheriq(ether, bp, 1); 
1992/1222    
		} 
 
1993/0212    
		/* 
1996/0420/sys/src/9/pc/ether8390.c:441,5771997/0327/sys/src/9/pc/ether8390.c:439,576
1993/1118    
		 * Finished with this packet, update the 
1993/0212    
		 * hardware and software ring pointers. 
		 */ 
1993/1118    
		dp8390->nxtpkt = hdr.next; 
1997/0327    
		ctlr->nxtpkt = hdr.next; 
1993/0212    
 
		hdr.next--; 
1993/1118    
		if(hdr.next < dp8390->pstart) 
			hdr.next = dp8390->pstop-1; 
1995/0409    
		slowoutb(port+Bnry, hdr.next); 
1997/0327    
		if(hdr.next < ctlr->pstart) 
			hdr.next = ctlr->pstop-1; 
		regw(ctlr, Bnry, hdr.next); 
1992/1222    
	} 
} 
 
1993/1118    
static int 
1993/1119    
istxavail(void *arg) 
1997/0327    
static void 
txstart(Ether* ether) 
1992/1222    
{ 
1993/1119    
	return ((Ether*)arg)->tlen == 0; 
1993/1118    
} 
1997/0327    
	int len; 
	Dp8390 *ctlr; 
	Block *bp; 
	uchar minpkt[ETHERMINTU], *rp; 
1993/0212    
 
1993/1118    
static long 
1993/1120    
write(Ether *ether, void *buf, long len) 
1993/1118    
{ 
	Dp8390 *dp8390; 
	ulong port; 
1993/1120    
	Etherpkt *pkt; 
1997/0327    
	ctlr = ether->ctlr; 
1993/0213    
 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
1993/0213    
                 
1993/1119    
	tsleep(ðer->tr, istxavail, ether, 10000); 
	if(ether->tlen){ 
		print("dp8390: transmitter jammed\n"); 
		return 0; 
1993/0212    
	} 
1993/1120    
	ether->tlen = len; 
1993/1118    
                 
1993/1120    
	/* 
	 * If it's a shared-memory interface, copy the packet 
	 * directly to the shared-memory area. Otherwise, copy 
	 * it to a staging buffer so the I/O-port write can be 
	 * done in one. 
1997/0327    
	 * This routine is called both from the top level and from interrupt 
	 * level and expects to be called with ctlr already locked. 
1993/1120    
	 */ 
1993/1118    
	if(dp8390->ram) 
1993/1120    
		pkt = (Etherpkt*)(ether->mem+dp8390->tstart*Dp8390BufSz); 
1993/1118    
	else 
1993/1120    
		pkt = ðer->tpkt; 
	memmove(pkt, buf, len); 
1997/0327    
	if(ctlr->txbusy) 
		return; 
	bp = qget(ether->oq); 
	if(bp == nil) 
		return; 
1993/1118    
 
1993/1120    
	/* 
	 * Give the packet a source address and make sure it 
	 * is of minimum length. 
1997/0327    
	 * Make sure the packet is of minimum length; 
	 * copy it to the card's memory by the appropriate means; 
	 * start the transmission. 
1993/1120    
	 */ 
	memmove(pkt->s, ether->ea, sizeof(ether->ea)); 
1997/0327    
	len = BLEN(bp); 
	rp = bp->rp; 
1993/1120    
	if(len < ETHERMINTU){ 
		memset(pkt->d+len, 0, ETHERMINTU-len); 
1997/0327    
		rp = minpkt; 
		memmove(rp, bp->rp, len); 
		memset(rp+len, 0, ETHERMINTU-len); 
1993/1120    
		len = ETHERMINTU; 
	} 
 
	if(dp8390->ram == 0) 
		dp8390write(dp8390, dp8390->tstart*Dp8390BufSz, pkt, len); 
1997/0327    
	if(ctlr->ram) 
		memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len); 
	else 
		dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len); 
	freeb(bp); 
1993/1120    
 
1995/0409    
	slowoutb(port+Tbcr0, len & 0xFF); 
	slowoutb(port+Tbcr1, (len>>8) & 0xFF); 
	slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1997/0327    
	regw(ctlr, Tbcr0, len & 0xFF); 
	regw(ctlr, Tbcr1, (len>>8) & 0xFF); 
	regw(ctlr, Cr, Page0|RdABORT|Txp|Sta); 
1993/1118    
 
1993/1120    
	return len; 
1997/0327    
	ether->outpackets++; 
	ctlr->txbusy = 1; 
1993/0212    
} 
 
1993/1116    
static void 
1997/0327    
transmit(Ether* ether) 
{ 
	Dp8390 *ctlr; 
 
	ctlr = ether->ctlr; 
 
	ilock(ctlr); 
	txstart(ether); 
	iunlock(ctlr); 
} 
 
static void 
1993/1116    
overflow(Ether *ether) 
1993/0212    
{ 
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1997/0327    
	Dp8390 *ctlr; 
1993/0212    
	uchar txp; 
	int resend; 
 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
1997/0327    
	ctlr = ether->ctlr; 
1993/1118    
 
1993/0212    
	/* 
	 * The following procedure is taken from the DP8390[12D] datasheet, 
	 * it seems pretty adamant that this is what has to be done. 
	 */ 
1995/0409    
	txp = slowinb(port+Cr) & Txp; 
	slowoutb(port+Cr, Page0|RDMAabort|Stp); 
1997/0327    
	txp = regr(ctlr, Cr) & Txp; 
	regw(ctlr, Cr, Page0|RdABORT|Stp); 
1993/0212    
	delay(2); 
1995/0409    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1997/0327    
	regw(ctlr, Rbcr0, 0); 
	regw(ctlr, Rbcr1, 0); 
1993/0212    
 
	resend = 0; 
1995/0409    
	if(txp && (slowinb(port+Isr) & (Txe|Ptx)) == 0) 
1997/0327    
	if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0) 
1993/0212    
		resend = 1; 
 
1995/0409    
	slowoutb(port+Tcr, Lb); 
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1997/0327    
	regw(ctlr, Tcr, LpbkNIC); 
	regw(ctlr, Cr, Page0|RdABORT|Sta); 
1993/1118    
	receive(ether); 
1995/0409    
	slowoutb(port+Isr, Ovw); 
	slowoutb(port+Tcr, 0); 
1997/0327    
	regw(ctlr, Isr, Ovw); 
	regw(ctlr, Tcr, 0); 
1993/0212    
 
	if(resend) 
1995/0409    
		slowoutb(port+Cr, Page0|RDMAabort|Txp|Sta); 
1997/0327    
		regw(ctlr, Cr, Page0|RdABORT|Txp|Sta); 
1993/0212    
} 
 
1993/1116    
static void 
1995/0829    
interrupt(Ureg*, void *arg) 
1997/0327    
interrupt(Ureg*, void* arg) 
1993/0212    
{ 
1993/1124    
	Ether *ether; 
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1997/0327    
	Dp8390 *ctlr; 
1993/0212    
	uchar isr, r; 
1992/1222    
 
1993/1124    
	ether = arg; 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
1997/0327    
	ctlr = ether->ctlr; 
1993/1118    
 
1992/1222    
	/* 
	 * While there is something of interest, 
	 * clear all the interrupts and process. 
	 */ 
1995/0409    
	slowoutb(port+Imr, 0x00); 
1995/0829    
	while(isr = (slowinb(port+Isr) & (Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe))){ 
1992/1222    
                 
1997/0327    
	lock(ctlr); 
	regw(ctlr, Imr, 0x00); 
	while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){ 
1992/1222    
		if(isr & Ovw){ 
1993/1116    
			overflow(ether); 
1995/0409    
			slowoutb(port+Isr, Ovw); 
1997/0327    
			regw(ctlr, Isr, Ovw); 
1993/1116    
			ether->overflows++; 
1992/1222    
		} 
 
		/* 
		 * We have received packets. 
1993/1116    
		 * Take a spin round the ring. and 
1997/0327    
		 * Packets have been received. 
		 * Take a spin round the ring. 
1992/1222    
		 */ 
		if(isr & (Rxe|Prx)){ 
1993/1116    
			receive(ether); 
1995/0409    
			slowoutb(port+Isr, Rxe|Prx); 
1997/0327    
			regw(ctlr, Isr, Rxe|Prx); 
1992/1222    
		} 
 
		/* 
1996/0420/sys/src/9/pc/ether8390.c:580,6301997/0327/sys/src/9/pc/ether8390.c:579,638
1992/1222    
		 * and wake the output routine. 
		 */ 
		if(isr & (Txe|Ptx)){ 
1995/0409    
			r = slowinb(port+Tsr); 
1993/0212    
			if(isr & Txe){ 
1993/1118    
				if((r & (Cdh|Fu|Crs|Abt))) 
					print("dp8390: Tsr#%2.2ux\n", r); 
1997/0327    
			r = regr(ctlr, Tsr); 
			if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){ 
				print("dp8390: Tsr#%2.2ux|", r); 
1993/1116    
				ether->oerrs++; 
1993/0212    
			} 
 
1995/0409    
			slowoutb(port+Isr, Txe|Ptx); 
1997/0327    
			regw(ctlr, Isr, Txe|Ptx); 
1993/0212    
 
			if(isr & Ptx) 
1993/1116    
				ether->outpackets++; 
1993/1119    
			ether->tlen = 0; 
1993/1116    
			wakeup(ðer->tr); 
1997/0327    
			ctlr->txbusy = 0; 
			txstart(ether); 
1992/1222    
		} 
1993/0212    
 
		if(isr & Cnt){ 
1995/0409    
			ether->frames += slowinb(port+Cntr0); 
			ether->crcs += slowinb(port+Cntr1); 
			ether->buffs += slowinb(port+Cntr2); 
			slowoutb(port+Isr, Cnt); 
1997/0327    
			ether->frames += regr(ctlr, Cntr0); 
			ether->crcs += regr(ctlr, Cntr1); 
			ether->buffs += regr(ctlr, Cntr2); 
			regw(ctlr, Isr, Cnt); 
1993/0212    
		} 
1992/1222    
	} 
1995/0409    
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1997/0327    
	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx); 
	unlock(ctlr); 
1993/1116    
} 
 
static void 
1993/1118    
promiscuous(void *arg, int on) 
1993/1116    
{ 
1995/0721    
	Dp8390 *dp8390 = ((Ether*)arg)->ctlr; 
1997/0327    
	Ether *ether; 
	Dp8390 *ctlr; 
	uchar r; 
1993/1117    
 
1997/0327    
	ether = arg; 
	ctlr = ether->ctlr; 
 
1993/1116    
	/* 
	 * Set/reset promiscuous mode. 
	 */ 
1997/0327    
	r = Ab; 
1993/1116    
	if(on) 
1995/0409    
		slowoutb(dp8390->dp8390+Rcr, Pro|Ab); 
1993/1116    
	else 
1995/0409    
		slowoutb(dp8390->dp8390+Rcr, Ab); 
1997/0327    
		r |= Pro; 
	ilock(ctlr); 
	regw(ctlr, Rcr, r); 
	iunlock(ctlr); 
1993/1116    
} 
 
1993/1118    
static void 
attach(Ether *ether) 
1997/0327    
attach(Ether* ether) 
1993/1116    
{ 
1995/0721    
	Dp8390 *dp8390 = ether->ctlr; 
1995/0801    
	int x; 
1997/0327    
	Dp8390 *ctlr; 
	uchar r; 
1993/1117    
 
1997/0327    
	ctlr = ether->ctlr; 
 
1993/1116    
	/* 
	 * Enable the chip for transmit/receive. 
	 * The init routine leaves the chip in monitor 
1996/0420/sys/src/9/pc/ether8390.c:631,6921997/0327/sys/src/9/pc/ether8390.c:639,722
1993/1116    
	 * mode. Clear the missed-packet counter, it 
	 * increments while in monitor mode. 
	 */ 
1995/0801    
	x = Ab; 
1997/0327    
	r = Ab; 
1995/0801    
	if(ether->prom) 
		x |= Pro; 
1995/0829    
	slowoutb(dp8390->dp8390+Rcr, x); 
1995/0409    
	slowinb(dp8390->dp8390+Cntr2); 
1997/0327    
		r |= Pro; 
	ilock(ctlr); 
	regw(ctlr, Rcr, r); 
	r = regr(ctlr, Cntr2); 
	iunlock(ctlr); 
	USED(r); 
1993/1116    
} 
 
1997/0327    
static void 
disable(Dp8390* ctlr) 
{ 
	int timo; 
 
	/* 
	 * Stop the chip. Set the Stp bit and wait for the chip 
	 * to finish whatever was on its tiny mind before it sets 
	 * the Rst bit. 
	 * The timeout is needed because there may not be a real 
	 * chip there if this is called when probing for a device 
	 * at boot. 
	 */ 
	regw(ctlr, Cr, Page0|RdABORT|Stp); 
	regw(ctlr, Rbcr0, 0); 
	regw(ctlr, Rbcr1, 0); 
	for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--) 
			; 
} 
 
1993/1118    
int 
1993/1116    
dp8390reset(Ether *ether) 
1997/0327    
dp8390reset(Ether* ether) 
1993/1116    
{ 
1993/1118    
	Dp8390 *dp8390; 
	ulong port; 
1997/0327    
	Dp8390 *ctlr; 
1993/1116    
 
1995/0721    
	dp8390 = ether->ctlr; 
1993/1118    
	port = dp8390->dp8390; 
1997/0327    
	ctlr = ether->ctlr; 
1993/1118    
 
1993/1116    
	/* 
	 * This is the initialisation procedure described 
	 * as 'mandatory' in the datasheet, with references 
	 * to the 3Com503 technical reference manual. 
1997/0327    
	 * to the 3C503 technical reference manual. 
1993/1116    
	 */  
1993/1118    
	dp8390disable(dp8390); 
	if(dp8390->bit16) 
1995/0409    
		slowoutb(port+Dcr, Ft4|Ls|Wts); 
1997/0327    
	disable(ctlr); 
	if(ctlr->width != 1) 
		regw(ctlr, Dcr, Ft4WORD|Ls|Wts); 
1993/1116    
	else 
1995/0409    
		slowoutb(port+Dcr, Ft4|Ls); 
1997/0327    
		regw(ctlr, Dcr, Ft4WORD|Ls); 
1993/1116    
 
1995/0409    
	slowoutb(port+Rbcr0, 0); 
	slowoutb(port+Rbcr1, 0); 
1997/0327    
	regw(ctlr, Rbcr0, 0); 
	regw(ctlr, Rbcr1, 0); 
1993/1116    
 
1995/0409    
	slowoutb(port+Tcr, 0); 
	slowoutb(port+Rcr, Mon); 
1997/0327    
	regw(ctlr, Tcr, 0); 
	regw(ctlr, Rcr, Mon); 
1993/1116    
 
	/* 
	 * Init the ring hardware and software ring pointers. 
	 * Can't initialise ethernet address as we may not know 
	 * it yet. 
1997/0327    
	 * Can't initialise ethernet address as it may not be 
	 * known yet. 
1993/1116    
	 */ 
1993/1118    
	dp8390ring(dp8390); 
1995/0409    
	slowoutb(port+Tpsr, dp8390->tstart); 
1997/0327    
	ringinit(ctlr); 
	regw(ctlr, Tpsr, ctlr->tstart); 
1993/1116    
 
1995/0409    
	slowoutb(port+Isr, 0xFF); 
	slowoutb(port+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe); 
1997/0327    
	regw(ctlr, Isr, 0xFF); 
	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx); 
1993/1116    
 
	/* 
	 * Leave the chip initialised, 
	 * but in monitor mode. 
	 */ 
1995/0409    
	slowoutb(port+Cr, Page0|RDMAabort|Sta); 
1997/0327    
	regw(ctlr, Cr, Page0|RdABORT|Sta); 
1993/1116    
 
	/* 
	 * Set up the software configuration. 
	 */ 
	ether->attach = attach; 
	ether->write = write; 
1997/0327    
	ether->transmit = transmit; 
1993/1116    
	ether->interrupt = interrupt; 
1997/0327    
	ether->ifstat = 0; 
1993/1116    
 
	ether->promiscuous = promiscuous; 
	ether->arg = ether; 
1997/0327/sys/src/9/pc/ether8390.c:620,6251997/0415/sys/src/9/pc/ether8390.c:620,627 (short | long)
1997/0327    
	r = Ab; 
1993/1116    
	if(on) 
1997/0327    
		r |= Pro; 
1997/0415    
	if(ether->nmaddr) 
		r |= Am; 
1997/0327    
	ilock(ctlr); 
	regw(ctlr, Rcr, r); 
	iunlock(ctlr); 
1997/0327/sys/src/9/pc/ether8390.c:626,6311997/0415/sys/src/9/pc/ether8390.c:628,684
1993/1116    
} 
 
1993/1118    
static void 
1997/0415    
multicast(void* arg, uchar *addr, int on) 
{ 
	Ether *ether; 
	Dp8390 *ctlr; 
	uchar r, cr; 
	int i; 
	ulong h; 
 
	USED(addr, on); 
 
	ether = arg; 
	ctlr = ether->ctlr; 
 
	/* 
	 *  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); 
	iunlock(ctlr); 
} 
 
static void 
1997/0327    
attach(Ether* ether) 
1993/1116    
{ 
1997/0327    
	Dp8390 *ctlr; 
1997/0327/sys/src/9/pc/ether8390.c:642,6471997/0415/sys/src/9/pc/ether8390.c:695,702
1997/0327    
	r = Ab; 
1995/0801    
	if(ether->prom) 
1997/0327    
		r |= Pro; 
1997/0415    
	if(ether->nmaddr) 
		r |= Am; 
1997/0327    
	ilock(ctlr); 
	regw(ctlr, Rcr, r); 
	r = regr(ctlr, Cntr2); 
1997/0327/sys/src/9/pc/ether8390.c:719,7241997/0415/sys/src/9/pc/ether8390.c:774,780
1997/0327    
	ether->ifstat = 0; 
1993/1116    
 
	ether->promiscuous = promiscuous; 
1997/0415    
	ether->multicast = multicast; 
1993/1116    
	ether->arg = ether; 
 
	return 0; 
1997/0415/sys/src/9/pc/ether8390.c:604,6801997/0418/sys/src/9/pc/ether8390.c:604,698 (short | long)
1997/0327    
	unlock(ctlr); 
1993/1116    
} 
 
1997/0418    
static uchar allmar[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 
 
1993/1116    
static void 
1997/0418    
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 
1993/1118    
promiscuous(void *arg, int on) 
1993/1116    
{ 
1997/0327    
	Ether *ether; 
	Dp8390 *ctlr; 
	uchar r; 
1993/1117    
 
1997/0418    
	USED(on); 
 
1997/0327    
	ether = arg; 
	ctlr = ether->ctlr; 
 
1993/1116    
	/* 
	 * Set/reset promiscuous mode. 
	 */ 
1997/0327    
	r = Ab; 
1993/1116    
	if(on) 
1997/0327    
		r |= Pro; 
1997/0415    
	if(ether->nmaddr) 
		r |= Am; 
1997/0327    
	ilock(ctlr); 
	regw(ctlr, Rcr, r); 
1997/0418    
	setfilter(ether, ctlr); 
1997/0327    
	iunlock(ctlr); 
1993/1116    
} 
 
1993/1118    
static void 
1997/0418    
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 
1997/0415    
multicast(void* arg, uchar *addr, int on) 
{ 
	Ether *ether; 
	Dp8390 *ctlr; 
	uchar r, cr; 
	int i; 
	ulong h; 
 
	USED(addr, on); 
1997/0418    
	USED(on); 
1997/0415    
 
	ether = arg; 
	ctlr = ether->ctlr; 
1997/0418    
	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); 
	} 
1997/0415    
 
	/* 
	 *  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); 
1997/0418    
	setbit(ctlr, reverse[h&0x3f], on); 
	setfilter(ether, ctlr); 
1997/0415    
	iunlock(ctlr); 
} 
 
1997/0418/sys/src/9/pc/ether8390.c:246,2521998/0129/sys/src/9/pc/ether8390.c:246,252 (short | long)
1997/0327    
	void *v; 
 
	ilock(ctlr); 
	v = dp8390read(ctlr, to, from, len); 
1998/0129    
	v = _dp8390read(ctlr, to, from, len); 
1997/0327    
	iunlock(ctlr); 
 
	return v; 
1998/0129/sys/src/9/pc/ether8390.c:633,6451998/0319/sys/src/9/pc/ether8390.c:633,643 (short | long)
Change dev read and write to use vlong offset. Formatting edits.
rsc Fri Mar 4 12:44:25 2005
1997/0418    
} 
 
static void 
1993/1118    
promiscuous(void *arg, int on) 
1998/0319    
promiscuous(void *arg, int ) 
1993/1116    
{ 
1997/0327    
	Ether *ether; 
	Dp8390 *ctlr; 
1993/1117    
 
1997/0418    
	USED(on); 
                 
1997/0327    
	ether = arg; 
	ctlr = ether->ctlr; 
 
1998/0129/sys/src/9/pc/ether8390.c:675,6821998/0319/sys/src/9/pc/ether8390.c:673,678
1997/0415    
	Dp8390 *ctlr; 
	int i; 
	ulong h; 
                 
1997/0418    
	USED(on); 
1997/0415    
 
	ether = arg; 
	ctlr = ether->ctlr; 
Too many diffs (26 > 25). Stopping.


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