Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/pc/ether8003.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname pc/ether8003.c 1992/1222
## diff -e /dev/null /n/bootesdump/1992/1222/sys/src/9/pc/ether8003.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "io.h"
#include "devtab.h"

#include "ether.h"

enum {					/* 83C584 Bus Interface Controller */
	Msr		= 0x00,		/* Memory Select Register */
	Icr		= 0x01,		/* Interface Configuration Register */
	Iar		= 0x02,		/* I/O Address Register */
	Bio		= 0x03,		/* BIOS ROM Address Register */
	Irr		= 0x04,		/* Interrupt Request Register */
	Laar		= 0x05,		/* LA Address Register */
	Ijr		= 0x06,		/* Initialisation Jumpers */
	Gp2		= 0x07,		/* General Purpose Data Register */
	Lar		= 0x08,		/* LAN Address Registers */
	Id		= 0x0E,		/* Board ID byte */
	Cksum		= 0x0F,		/* Checksum */
};

enum {					/* Msr */
	Rst		= 0x80,		/* software reset */
	Menb		= 0x40,		/* memory enable */
};

enum {					/* Laar */
	ZeroWS16	= (1<<5),	/* zero wait states for 16-bit ops */
	L16en		= (1<<6),	/* enable 16-bit LAN operation */
	M16en		= (1<<7),	/* enable 16-bit memory access */
};

/*
 * Mapping from configuration bits to interrupt level.
 */
static int intrmap[] = {
	9, 3, 5, 7, 10, 11, 15, 4,
};

/*
 * Get configuration parameters, enable memory.
 */
static int
reset(Ctlr *ctlr)
{
	Board *board = ctlr->board;
	int i;
	uchar msr, icr, laar, irr, sum;

	/*
	 * Look for the interface. We read the LAN address ROM
	 * and validate the checksum - the sum of all 8 bytes
	 * should be 0xFF.
	 */
	for(board->io = 0x200; board->io < 0x400; board->io += 0x20){
		sum = 0;
		for(i = 0; i < sizeof(ctlr->ea); i++){
			ctlr->ea[i] = inb(board->io+Lar+i);
			sum += ctlr->ea[i];
		}
		sum += inb(board->io+Id);
		sum += inb(board->io+Cksum);
		if(sum == 0xFF)
			break;
	}
	if(board->io >= 0x400)
		return -1;

	/*
	 * Found it, reset it.
	 * Be careful to preserve the Msr address bits,
	 * they don't get reloaded from the EEPROM on reset.
	 */
	msr = inb(board->io+Msr);
	outb(board->io+Msr, Rst|msr);
	delay(1);
	outb(board->io+Msr, msr);
	delay(2);

	/*
	 * Check for old, dumb 8003E, which doesn't have an interface
	 * chip. Only the msr exists out of the 1st eight registers, reads
	 * of the others just alias the 2nd eight registers, the LAN
	 * address ROM. We can check icr, irr and laar against the ethernet
	 * address read above and if they match it's an 8003E (or an
	 * 8003EBT, 8003S, 8003SH or 8003WT, we don't care), in which
	 * case the default irq gets used.
	 */
	msr = inb(board->io+Msr);
	icr = inb(board->io+Icr);
	laar = inb(board->io+Laar);
	irr = inb(board->io+Irr);
	if(icr != ctlr->ea[1] || irr != ctlr->ea[4] || laar != ctlr->ea[5])
		board->irq = intrmap[((irr>>5) & 0x3)|(icr & 0x4)];
	else {
		msr = (((ulong)board->ramstart)>>13) & 0x3F;
		icr = laar = 0;
		board->watch = 0;
	}

	/*
	 * Set up the bus-size, RAM address and RAM size
	 * from the info in the configuration registers.
	 */
	board->bit16 = icr & 0x1;

	board->ram = 1;
	board->ramstart = KZERO|((msr & 0x3F)<<13);
	if(board->bit16)
		board->ramstart |= (laar & 0x1F)<<19;
	else
		board->ramstart |= 0x80000;

	if(icr & (1<<3))
		board->ramstop = 32*1024;
	else
		board->ramstop = 8*1024;
	if(board->bit16)
		board->ramstop <<= 1;
	board->ramstop += board->ramstart;

	/*
	 * Set the DP8390 ring addresses.
	 */
	board->dp8390 = board->io+0x10;
	board->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
	board->pstop = HOWMANY(board->ramstop-board->ramstart, Dp8390BufSz);
	board->tstart = 0;

	print("WD80x3 I/O addr %lux width %d addr %lux size %d irq %d:",
		board->io, board->bit16 ? 16: 8, board->ramstart,
		board->ramstop-board->ramstart, board->irq);
	for(i = 0; i < sizeof(ctlr->ea); i++)
		print(" %2.2ux", ctlr->ea[i]);
	print("\n");

	/*
	 * Enable interface RAM, set interface width.
	 */
	outb(board->io+Msr, Menb|msr);
	if(board->bit16)
		outb(board->io+Laar, laar|L16en|M16en|ZeroWS16);

	/*
	 * Finally, init the 8390 and set the
	 * ethernet address.
	 */
	dp8390reset(ctlr);
	dp8390setea(ctlr);

	return 0;
}

static void
watch(Ctlr *ctlr)
{
	Board *board = ctlr->board;
	uchar msr;
	int s;

	s = splhi();
	msr = inb(board->io+Msr);
	/*
	 * If the board has reset itself,
	 * start again.
	 */
	if((msr & Menb) == 0){
		delay(100);

		dp8390reset(ctlr);
		etherinit();

		wakeup(&ctlr->tr);
		wakeup(&ctlr->rr);
	}
	splx(s);
}

/*
 * Defaults are set for the dumb 8003E
 * which can't be autoconfigured.
 */
Board ether8003 = {
	reset,
	0,			/* init */
	dp8390attach,
	dp8390mode,
	dp8390receive,
	dp8390transmit,
	dp8390intr,
	watch,

	0x280,			/* addr */
	3,			/* irq */
	0,			/* bit16 */

	1,			/* ram */
	0xD0000,		/* ramstart */
	0xD0000+8*1024,		/* ramstop */
};
.
## diffname pc/ether8003.c 1992/1224
## diff -e /n/bootesdump/1992/1222/sys/src/9/pc/ether8003.c /n/bootesdump/1992/1224/sys/src/9/pc/ether8003.c
197c
	0x280,			/* io */
.
134c
	print("WD8003 I/O addr %lux width %d addr %lux size %d irq %d:",
.
## diffname pc/ether8003.c 1993/0212
## diff -e /n/bootesdump/1992/1224/sys/src/9/pc/ether8003.c /n/bootesdump/1993/0212/sys/src/9/pc/ether8003.c
201,203c
	read,				/* read */
	write,				/* write */

	dp8390receive,			/* receive */
	dp8390transmit,			/* transmit */
	dp8390intr,			/* interrupt */
	watch,				/* watch */
	0,				/* overflow */

	0x280,				/* io */
	3,				/* irq */
	0,				/* bit16 */

	1,				/* ram */
	0xD0000,			/* ramstart */
	0xD0000+8*1024,			/* ramstop */
.
197,199c
	reset,				/* reset */
	0,				/* init */
	dp8390attach,			/* attach */
	dp8390mode,			/* mode */
.
187,195c
Card ether8003 = {
	"WD8003",			/* ident */
.
168c
	 * If the card has reset itself,
.
166c
	msr = inb(ctlr->card.io+Msr);
.
161d
157a
static void*
read(Ctlr *ctlr, void *to, ulong from, ulong len)
{
	/*
	 * In this case, 'from' is an index into the shared memory.
	 */
	memmove(to, (void*)(ctlr->card.ramstart+from), len);
	return to;
}

static void*
write(Ctlr *ctlr, ulong to, void *from, ulong len)
{
	/*
	 * In this case, 'to' is an index into the shared memory.
	 */
	memmove((void*)(ctlr->card.ramstart+to), from, len);
	return (void*)to;
}

.
144,146c
	outb(ctlr->card.io+Msr, Menb|msr);
	if(ctlr->card.bit16)
		outb(ctlr->card.io+Laar, laar|L16en|M16en|ZeroWS16);
.
134,140d
129,132c
	ctlr->card.dp8390 = ctlr->card.io+0x10;
	ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
	ctlr->card.pstop = HOWMANY(ctlr->card.ramstop-ctlr->card.ramstart, Dp8390BufSz);
	ctlr->card.tstart = 0;
.
121,124c
		ctlr->card.ramstop = 8*1024;
	if(ctlr->card.bit16)
		ctlr->card.ramstop <<= 1;
	ctlr->card.ramstop += ctlr->card.ramstart;
.
119c
		ctlr->card.ramstop = 32*1024;
.
116c
		ctlr->card.ramstart |= 0x80000;
.
111,114c
	ctlr->card.ram = 1;
	ctlr->card.ramstart = KZERO|((msr & 0x3F)<<13);
	if(ctlr->card.bit16)
		ctlr->card.ramstart |= (laar & 0x1F)<<19;
.
109c
	ctlr->card.bit16 = icr & 0x1;
.
102c
		ctlr->card.watch = 0;
.
100c
		msr = (((ulong)ctlr->card.ramstart)>>13) & 0x3F;
.
98c
		ctlr->card.irq = intrmap[((irr>>5) & 0x3)|(icr & 0x4)];
.
93,96c
	msr = inb(ctlr->card.io+Msr);
	icr = inb(ctlr->card.io+Icr);
	laar = inb(ctlr->card.io+Laar);
	irr = inb(ctlr->card.io+Irr);
.
81c
	outb(ctlr->card.io+Msr, msr);
.
78,79c
	msr = inb(ctlr->card.io+Msr);
	outb(ctlr->card.io+Msr, Rst|msr);
.
70c
	if(ctlr->card.io >= 0x400)
.
65,66c
		sum += inb(ctlr->card.io+Id);
		sum += inb(ctlr->card.io+Cksum);
.
62c
			ctlr->ea[i] = inb(ctlr->card.io+Lar+i);
.
59c
	for(ctlr->card.io = 0x200; ctlr->card.io < 0x400; ctlr->card.io += 0x20){
.
50d
22c
	Id		= 0x0E,		/* Card ID byte */
.
## diffname pc/ether8003.c 1993/0223
## diff -e /n/bootesdump/1993/0212/sys/src/9/pc/ether8003.c /n/bootesdump/1993/0223/sys/src/9/pc/ether8003.c
138c
		outb(ctlr->card.io+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
.
136c
	outb(ctlr->card.io+Msr, ic[Msr]|Menb);
.
117c
	if(ic[Icr] & (1<<3))
.
113c
		ctlr->card.ramstart |= (ic[Laar] & 0x1F)<<19;
.
110,111c
		ic[Icr] = inb(ctlr->card.io+Icr);
		if(ctlr->card.bit16 && (ic[Icr] & Bit16) == 0)
			ctlr->card.bit16 = 0;
	}

	ctlr->card.ramstart = KZERO|((ic[Msr] & 0x3F)<<13);
.
104,108c
		/*
		 * Check if 16-bit card.
		 * If Bit16 is read/write, then we have an 8-bit card.
		 * If Bit16 is set, we're in a 16-bit slot.
		 */
		outb(ctlr->card.io+Icr, ic[Icr]^Bit16);
		inb(ctlr->card.io+Msr);				/* wiggle bus */
		if((inb(ctlr->card.io+Icr) & Bit16) == (ic[Icr] & Bit16)){
			ctlr->card.bit16 = 1;
			ic[Icr] &= ~Bit16;
		}
		outb(ctlr->card.io+Icr, ic[Icr]);
.
102a
	else{
		/*
		 * As a final sanity check for the 8013EBT, which doesn't have
		 * the 83C584 interface chip, but has 2 real registers, write Gp2 and if
		 * it reads back the same, it's not an 8013EBT.
		 */
		outb(ctlr->card.io+Gp2, 0xAA);
		inb(ctlr->card.io+Msr);				/* wiggle bus */
		if(inb(ctlr->card.io+Gp2) != 0xAA){
			memset(ic, 0, sizeof(ic));
			ic[Msr] = (((ulong)ctlr->card.ramstart)>>13) & 0x3F;
			ctlr->card.watch = 0;
			ctlr->card.irq = 2;			/* special */
		}
		else
			ctlr->card.irq = intrmap[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
.
92,100c
	if(memcmp(&ctlr->ea[1], &ic[1], 5) == 0){
		memset(ic, 0, sizeof(ic));
		ic[Msr] = (((ulong)ctlr->card.ramstart)>>13) & 0x3F;
.
73,83d
62a
			ic[i] = inb(ctlr->card.io+i);
.
56a
	 * While we're at it, get the (possible) interface chip
	 * registers, we'll use them to check for aliasing later.
.
51c
	uchar ic[8], sum;
.
45a
 * There are opportunities here for buckets of code.
 * We'll try to resist.
.
30a
enum {					/* Icr */
	Bit16		= 0x01,		/* 16-bit bus */
	Other		= 0x02,		/* other register access */
	Ir2		= 0x04,		/* IR2 */
	Msz		= 0x08,		/* SRAM size */
	Rla		= 0x10,		/* recall LAN address */
	Rx7		= 0x20,		/* recall all but I/O and LAN address */
	Rio		= 0x40,		/* recall I/O address from EEROM */
	Sto		= 0x80,		/* non-volatile EEROM store */
};

.
16a
	Ear		= 0x03,		/* EEROM Address Register (shared with Bio) */
.
11a
/*
 * Western Digital/Standard Microsystems Corporation cards (WD80[01]3).
 * Configuration code based on that provided by SMC.
 */
.
## diffname pc/ether8003.c 1993/0302
## diff -e /n/bootesdump/1993/0223/sys/src/9/pc/ether8003.c /n/bootesdump/1993/0302/sys/src/9/pc/ether8003.c
137,138c
		if(ctlr->card.bit16 && (inb(ctlr->card.io+Icr) & Bit16) == 0)
.
## diffname pc/ether8003.c 1993/0915
## diff -e /n/bootesdump/1993/0302/sys/src/9/pc/ether8003.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether8003.c
189,252d
183,187c
	addethercard("WD8003", wd8003reset);
.
180,181c
void
ether8003link(void)
.
168c
		outb(wd8003+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
.
166c
	outb(wd8003+Msr, ic[Msr]|Menb);
.
161a
	ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
	ctlr->card.pstop = HOWMANY(ctlr->card.size, Dp8390BufSz);
.
158,160c
	ctlr->card.dp8390 = wd8003+0x10;
.
152,153c
		ctlr->card.size <<= 1;
.
148,150c
		ctlr->card.size = 32*1024;
.
145c
		ctlr->card.mem |= 0x80000;
.
143c
		ctlr->card.mem |= (ic[Laar] & 0x1F)<<19;
.
141c
	ctlr->card.mem = KZERO|((ic[Msr] & 0x3F)<<13);
.
137c
		if(ctlr->card.bit16 && (inb(wd8003+Icr) & Bit16) == 0)
.
135c
		outb(wd8003+Icr, ic[Icr]);
.
129,131c
		outb(wd8003+Icr, ic[Icr]^Bit16);
		inb(wd8003+Msr);				/* wiggle bus */
		if((inb(wd8003+Icr) & Bit16) == (ic[Icr] & Bit16)){
.
119d
117c
			ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F;
.
113,115c
		outb(wd8003+Gp2, 0xAA);
		inb(wd8003+Msr);				/* wiggle bus */
		if(inb(wd8003+Gp2) != 0xAA){
.
104c
		ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F;
.
90c
	sum += inb(wd8003+Id);
	sum += inb(wd8003+Cksum);
	if(sum != 0xFF)
.
78,88c
	sum = 0;
	for(i = 0; i < sizeof(ctlr->ea); i++){
		ctlr->ea[i] = inb(wd8003+Lar+i);
		sum += ctlr->ea[i];
		ic[i] = inb(wd8003+i);
.
71a
	 * Set up the software configuration.
	 * Use defaults for port, irq, mem and size if not specified.
	 * Defaults are set for the dumb 8003E which can't be
	 * autoconfigured.
	 */
	if(ctlr->card.port == 0)
		ctlr->card.port = 0x280;
	if(ctlr->card.irq == 0)
		ctlr->card.irq = 3;
	if(ctlr->card.mem == 0)
		ctlr->card.mem = 0xD0000;
	if(ctlr->card.size == 0)
		ctlr->card.size = 8*1024;

	ctlr->card.reset = wd8003reset;
	ctlr->card.attach = dp8390attach;
	ctlr->card.mode = dp8390mode;
	ctlr->card.read = read;
	ctlr->card.write = write;
	ctlr->card.receive = dp8390receive;
	ctlr->card.transmit = dp8390transmit;
	ctlr->card.intr = dp8390intr;
	ctlr->card.watch = watch;
	ctlr->card.ram = 1;

	wd8003 = ctlr->card.port;
	/*
.
69a
	ulong wd8003;
.
65,66c
int
wd8003reset(Ctlr *ctlr)
.
59a
static void*
read(Ctlr *ctlr, void *to, ulong from, ulong len)
{
	/*
	 * In this case, 'from' is an index into the shared memory.
	 */
	memmove(to, (void*)(ctlr->card.mem+from), len);
	return to;
}

static void*
write(Ctlr *ctlr, ulong to, void *from, ulong len)
{
	/*
	 * In this case, 'to' is an index into the shared memory.
	 */
	memmove((void*)(ctlr->card.mem+to), from, len);
	return (void*)to;
}

static void
watch(Ctlr *ctlr)
{
	uchar msr;
	int s;

	s = splhi();
	msr = inb(ctlr->card.port+Msr);
	/*
	 * If the card has reset itself,
	 * start again.
	 */
	if((msr & Menb) == 0){
		delay(100);

		dp8390reset(ctlr);
		etherinit();

		wakeup(&ctlr->tr);
		wakeup(&ctlr->rr);
	}
	splx(s);
}

.
## diffname pc/ether8003.c 1993/1116
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether8003.c
247c
	addethercard("WD8003", reset);
.
10c
#include "etherif.h"
.
8c
#include "../port/error.h"
#include "../port/netif.h"
.
6d
## diffname pc/ether8003.c 1993/1118
## diff -e /n/fornaxdump/1993/1116/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether8003.c
238,239c
	dp8390reset(ether);
	dp8390setea(ether);
.
230,232c
	outb(port+Msr, ic[Msr]|Menb);
	if(dp8390->bit16)
		outb(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
.
222,225c
	dp8390->dp8390 = port+0x10;
	dp8390->tstart = 0;
	dp8390->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
	dp8390->pstop = HOWMANY(ether->size, Dp8390BufSz);
.
215,217c
		ether->size = 32*1024;
	if(dp8390->bit16)
		ether->size <<= 1;
.
212c
		ether->mem |= 0x80000;
.
208,210c
	ether->mem = KZERO|((ic[Msr] & 0x3F)<<13);
	if(dp8390->bit16)
		ether->mem |= (ic[Laar] & 0x1F)<<19;
.
204,205c
		if(dp8390->bit16 && (inb(port+Icr) & Bit16) == 0)
			dp8390->bit16 = 0;
.
202c
		outb(port+Icr, ic[Icr]);
.
196,199c
		outb(port+Icr, ic[Icr]^Bit16);
		inb(port+Msr);				/* wiggle bus */
		if((inb(port+Icr) & Bit16) == (ic[Icr] & Bit16)){
			dp8390->bit16 = 1;
.
189c
			ether->irq = intrmap[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
.
185,186c
			ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
.
181,183c
		outb(port+Gp2, 0xAA);
		inb(port+Msr);				/* wiggle bus */
		if(inb(port+Gp2) != 0xAA){
.
172,173c
		ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
.
170c
	if(memcmp(&ether->ea[1], &ic[1], 5) == 0){
.
160a
	ether->private = malloc(sizeof(Dp8390));
	dp8390 = ether->private;
	dp8390->ram = 1;

.
156,157c
	sum += inb(port+Id);
	sum += inb(port+Cksum);
.
151,154c
	for(i = 0; i < sizeof(ether->ea); i++){
		ether->ea[i] = inb(port+Lar+i);
		sum += ether->ea[i];
		ic[i] = inb(port+i);
.
149a
	port = ether->port;
.
131,142d
122,129c
	if(ether->port == 0)
		ether->port = 0x280;
	if(ether->irq == 0)
		ether->irq = 3;
	if(ether->mem == 0)
		ether->mem = 0xD0000;
	if(ether->size == 0)
		ether->size = 8*1024;
.
114c
	ulong port;
	Dp8390 *dp8390;
.
109,110c
static int
reset(Ether *ether)
.
60,103d
## diffname pc/ether8003.c 1993/1119
## diff -e /n/fornaxdump/1993/1118/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether8003.c
186a
memmove(ether->ea, debugea, 6);
.
59a
static uchar debugea[6] = {
	0x00, 0x60, 0x8c, 0x00, 0x1a, 0x42,
};

.
## diffname pc/ether8003.c 1993/1120
## diff -e /n/fornaxdump/1993/1119/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1993/1120/sys/src/brazil/pc/ether8003.c
191d
60,63d
## diffname pc/ether8003.c 1994/0128
## diff -e /n/fornaxdump/1993/1120/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1994/0128/sys/src/brazil/pc/ether8003.c
186a
	if((ether->ea[0]|ether->ea[1]|ether->ea[2]|ether->ea[3]|ether->ea[4]|ether->ea[5]) == 0){
		for(i = 0; i < sizeof(ether->ea); i++)
			ether->ea[i] = ea[i];
	}
.
98c
		ea[i] = inb(port+Lar+i);
.
69c
	uchar ea[Eaddrlen], ic[8], sum;
.
## diffname pc/ether8003.c 1994/0202
## diff -e /n/fornaxdump/1994/0128/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether8003.c
99c
		sum += ea[i];
.
## diffname pc/ether8003.c 1994/0810
## diff -e /n/fornaxdump/1994/0202/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1994/0810/sys/src/brazil/pc/ether8003.c
97c
	for(i = 0; i < sizeof(ea); i++){
.
## diffname pc/ether8003.c 1994/1210
## diff -e /n/fornaxdump/1994/0810/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1994/1210/sys/src/brazil/pc/ether8003.c
192a
	if(getisa(ether->mem, ether->size, 0) == 0)
		panic("ether8003: %lux reused", ether->mem);

.
## diffname pc/ether8003.c 1995/0126
## diff -e /n/fornaxdump/1994/1210/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1995/0126/sys/src/brazil/pc/ether8003.c
194c
		panic("ether8003: 0x%lux reused", ether->mem);
.
## diffname pc/ether8003.c 1995/0721
## diff -e /n/fornaxdump/1995/0126/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether8003.c
107,108c
	ether->ctlr = malloc(sizeof(Dp8390));
	dp8390 = ether->ctlr;
.
## diffname pc/ether8003.c 1995/0829
## diff -e /n/fornaxdump/1995/0721/sys/src/brazil/pc/ether8003.c /n/fornaxdump/1995/0829/sys/src/brazil/pc/ether8003.c
174,180d
167a
	 * Enable interface RAM, set interface width.
	 */
	outb(port+Msr, ic[Msr]|Menb);
	if(dp8390->bit16)
		outb(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
}

static void
reset8216(Ether *ether, uchar[8])
{
	uchar hcr, irq, x;
	ulong addr, port;
	Dp8390 *dp8390;

	dp8390 = ether->ctlr;
	dp8390->bit16 = 1;
	port = ether->port;

	/*
	 * Switch to the alternate register set and retrieve the memory
	 * and irq information.
	 */
	hcr = inb(port+Hcr);
	outb(port+Hcr, 0x80|hcr);
	addr = inb(port+0x0B) & 0xFF;
	irq = inb(port+0x0D);
	outb(port+Hcr, hcr);

	ether->mem = KZERO|(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
	ether->size = 8192*(1<<((addr>>4) & 0x03));
	ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];

	/*
	 * Enable interface RAM, set interface width,
	 * and enable interrupts.
	 */
	x = inb(port+Msr) & ~Rst;
	outb(port+Msr, Menb|x);
	x = inb(port+Laar);
	outb(port+Laar, M16en|x);
	outb(port+Ijr, Ienable);
}

/*
 * Get configuration parameters, enable memory.
 * There are opportunities here for buckets of code.
 * We'll try to resist.
 */
static int
reset(Ether *ether)
{
	int i;
	uchar ea[Eaddrlen], ic[8], id, sum;
	ulong port;
	Dp8390 *dp8390;

	/*
	 * Set up the software configuration.
	 * Use defaults for port, irq, mem and size if not specified.
	 * Defaults are set for the dumb 8003E which can't be
	 * autoconfigured.
	 */
	if(ether->port == 0)
		ether->port = 0x280;
	if(ether->irq == 0)
		ether->irq = 3;
	if(ether->mem == 0)
		ether->mem = 0xD0000;
	if(ether->size == 0)
		ether->size = 8*1024;

	/*
	 * Look for the interface. We read the LAN address ROM
	 * and validate the checksum - the sum of all 8 bytes
	 * should be 0xFF.
	 * While we're at it, get the (possible) interface chip
	 * registers, we'll use them to check for aliasing later.
	 */
	port = ether->port;
	sum = 0;
	for(i = 0; i < sizeof(ea); i++){
		ea[i] = inb(port+Lar+i);
		sum += ea[i];
		ic[i] = inb(port+i);
	}
	id = inb(port+Id);
	sum += id;
	sum += inb(port+Cksum);
	if(sum != 0xFF)
		return -1;

	ether->ctlr = malloc(sizeof(Dp8390));
	dp8390 = ether->ctlr;
	dp8390->ram = 1;

	if((id & 0xFE) == 0x2A)
		reset8216(ether, ic);
	else
		reset8003(ether, ea, ic);

	/*
.
137c
			ether->irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
.
120c
	if(memcmp(&ea[1], &ic[1], 5) == 0){
.
107,110d
96,105d
73,94c
	dp8390 = ether->ctlr;
.
71a
	ulong port;
.
68,70d
60,66c
static int irq8216[8] = {
	0, 9, 3, 5, 7, 10, 11, 15,
};

static void
reset8003(Ether *ether, uchar ea[Eaddrlen], uchar ic[8])
.
56c
static int irq8003[8] = {
.
52a
enum {					/* Ijr */
	Ienable		= 0x01,		/* 8216 interrupt enable */
};

.
48,50c
	ZeroWS16	= 0x20,		/* zero wait states for 16-bit ops */
	L16en		= 0x40,		/* enable 16-bit LAN operation */
	M16en		= 0x80,		/* enable 16-bit memory access */
.
22a
	Hcr		= 0x04,		/* 8216 hardware control */
.
13a
 * Also handles 8216 cards (Elite Ultra).
.
## diffname pc/ether8003.c 1997/0327
## diff -e /n/fornaxdump/1995/0829/sys/src/brazil/pc/ether8003.c /n/emeliedump/1997/0327/sys/src/brazil/pc/ether8003.c
255c
	if(umbmalloc(ether->mem, ether->size, 0) == 0)
.
249c
	memset(nullea, 0, Eaddrlen);
	if(memcmp(nullea, ether->ea, Eaddrlen) == 0){
.
245,246c
	 * Finally, init the 8390,set the ethernet address
	 * and claim the memory used.
.
239,242c
	ctlr->port = port+0x10;
	ctlr->tstart = 0;
	ctlr->pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
	ctlr->pstop = HOWMANY(ether->size, Dp8390BufSz);
.
228,229c
	ctlr = ether->ctlr;
	ctlr->ram = 1;
.
190c
	Dp8390 *ctlr;
.
188c
	uchar ea[Eaddrlen], ic[8], id, nullea[Eaddrlen], sum;
.
185c
reset(Ether* ether)
.
181,182c
 * There are opportunities here for buckets of code, try to resist.
.
169,170c
	 * Enable interface RAM, set interface width, and enable interrupts.
.
153a
	ctlr->width = 2;

.
150,151c
	ctlr = ether->ctlr;
.
148c
	Dp8390 *ctlr;
.
144c
reset8216(Ether* ether, uchar[8])
.
139c
	if(ctlr->width == 2)
.
132c
	if(ctlr->width == 2)
.
125c
	if(ctlr->width == 2)
.
120,121c
		if(ctlr->width == 2 && (inb(port+Icr) & Bit16) == 0)
			ctlr->width = 1;
.
115c
			ctlr->width = 2;
.
109,110c
		 * If Bit16 is read/write, then it's an 8-bit card.
		 * If Bit16 is set, it's in a 16-bit slot.
.
95,96c
		 * the 83C584 interface chip, but has 2 real registers, write Gp2
		 * and if it reads back the same, it's not an 8013EBT.
.
85c
	 * 8003EBT, 8003S, 8003SH or 8003WT, doesn't matter), in which
.
83c
	 * address ROM. Can check Icr, Irr and Laar against the ethernet
.
81c
	 * chip. Only Msr exists out of the 1st eight registers, reads
.
76c
	ctlr = ether->ctlr;
.
73c
	Dp8390 *ctlr;
.
71c
reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
.
15c
 * Configuration code based on that provided by SMC a long time ago.
.
10a
#include "ether8390.h"
.
## diffname pc/ether8003.c 1997/0329
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/ether8003.c /n/emeliedump/1997/0329/sys/src/brazil/pc/ether8003.c
256,257c
	if(umbrmalloc(PADDR(ether->mem), ether->size, 0) == 0)
		panic("ether8003: 0x%luX unavailable", PADDR(ether->mem));
.
245c
	 * Finally, init the 8390, set the ethernet address
.
## diffname pc/ether8003.c 1997/0331
## diff -e /n/emeliedump/1997/0329/sys/src/brazil/pc/ether8003.c /n/emeliedump/1997/0331/sys/src/brazil/pc/ether8003.c
256,257c
	if(umbrwmalloc(PADDR(ether->mem), ether->size, 0) == 0)
		print("ether8003: warning - 0x%luX unavailable", PADDR(ether->mem));
.
211,212c
	 * At the same time, get the (possible) interface chip
	 * registers, they'll be used later to check for aliasing.
.
208c
	 * Look for the interface. Read the LAN address ROM
.
## diffname pc/ether8003.c 1997/1101
## diff -e /n/emeliedump/1997/0331/sys/src/brazil/pc/ether8003.c /n/emeliedump/1997/1101/sys/src/brazil/pc/ether8003.c
166c
	ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
.
125c
	ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
.
## diffname pc/ether8003.c 1999/0714
## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/ether8003.c /n/emeliedump/1999/0714/sys/src/brazil/pc/ether8003.c
225a
	}
.
224c
	if(sum != 0xFF){
		iofree(ether->port);
.
205a
	if(ioalloc(ether->port, 0x20, 0, "wd8003") < 0)
		return -1;
.
## diffname pc/ether8003.c 2000/0612
## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/ether8003.c /n/emeliedump/2000/0612/sys/src/9/pc/ether8003.c
261c
		print("ether8003: warning - 0x%luX unavailable\n",
			PADDR(ether->mem));
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.