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

1993/0212/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 | prev | next)
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    
} 


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