xref: /inferno-os/os/boot/pc/etherec2t.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth /*
2*74a4d8c2SCharles.Forsyth  * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c
3*74a4d8c2SCharles.Forsyth  */
4*74a4d8c2SCharles.Forsyth #include "u.h"
5*74a4d8c2SCharles.Forsyth #include "lib.h"
6*74a4d8c2SCharles.Forsyth #include "mem.h"
7*74a4d8c2SCharles.Forsyth #include "dat.h"
8*74a4d8c2SCharles.Forsyth #include "fns.h"
9*74a4d8c2SCharles.Forsyth #include "io.h"
10*74a4d8c2SCharles.Forsyth 
11*74a4d8c2SCharles.Forsyth #include "etherif.h"
12*74a4d8c2SCharles.Forsyth #include "ether8390.h"
13*74a4d8c2SCharles.Forsyth 
14*74a4d8c2SCharles.Forsyth enum {
15*74a4d8c2SCharles.Forsyth 	Data		= 0x10,		/* offset from I/O base of data port */
16*74a4d8c2SCharles.Forsyth 	Reset		= 0x1F,		/* offset from I/O base of reset port */
17*74a4d8c2SCharles.Forsyth };
18*74a4d8c2SCharles.Forsyth 
19*74a4d8c2SCharles.Forsyth static char* ec2tpcmcia[] = {
20*74a4d8c2SCharles.Forsyth 	"EC2T",				/* Linksys Combo PCMCIA EthernetCard */
21*74a4d8c2SCharles.Forsyth 	"PCMPC100",			/* EtherFast 10/100 PC Card */
22*74a4d8c2SCharles.Forsyth 	"EN2216",			/* Accton EtherPair-PCMCIA */
23*74a4d8c2SCharles.Forsyth 	"FA410TX",			/* Netgear FA410TX */
24*74a4d8c2SCharles.Forsyth 	"Network Everywhere",		/* Linksys NP10T 10BaseT Card */
25*74a4d8c2SCharles.Forsyth 	nil,
26*74a4d8c2SCharles.Forsyth };
27*74a4d8c2SCharles.Forsyth 
28*74a4d8c2SCharles.Forsyth int
ec2treset(Ether * ether)29*74a4d8c2SCharles.Forsyth ec2treset(Ether* ether)
30*74a4d8c2SCharles.Forsyth {
31*74a4d8c2SCharles.Forsyth 	ushort buf[16];
32*74a4d8c2SCharles.Forsyth 	ulong port;
33*74a4d8c2SCharles.Forsyth 	Dp8390 *ctlr;
34*74a4d8c2SCharles.Forsyth 	int i, slot;
35*74a4d8c2SCharles.Forsyth 	uchar ea[Eaddrlen], sum, x;
36*74a4d8c2SCharles.Forsyth 	char *type;
37*74a4d8c2SCharles.Forsyth 
38*74a4d8c2SCharles.Forsyth 	/*
39*74a4d8c2SCharles.Forsyth 	 * Set up the software configuration.
40*74a4d8c2SCharles.Forsyth 	 * Use defaults for port, irq, mem and size
41*74a4d8c2SCharles.Forsyth 	 * if not specified.
42*74a4d8c2SCharles.Forsyth 	 * The manual says 16KB memory, the box
43*74a4d8c2SCharles.Forsyth 	 * says 32KB. The manual seems to be correct.
44*74a4d8c2SCharles.Forsyth 	 */
45*74a4d8c2SCharles.Forsyth 	if(ether->port == 0)
46*74a4d8c2SCharles.Forsyth 		ether->port = 0x300;
47*74a4d8c2SCharles.Forsyth 	if(ether->irq == 0)
48*74a4d8c2SCharles.Forsyth 		ether->irq = 9;
49*74a4d8c2SCharles.Forsyth 	if(ether->mem == 0)
50*74a4d8c2SCharles.Forsyth 		ether->mem = 0x4000;
51*74a4d8c2SCharles.Forsyth 	if(ether->size == 0)
52*74a4d8c2SCharles.Forsyth 		ether->size = 16*1024;
53*74a4d8c2SCharles.Forsyth 	port = ether->port;
54*74a4d8c2SCharles.Forsyth 
55*74a4d8c2SCharles.Forsyth 	//if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
56*74a4d8c2SCharles.Forsyth 	//	return -1;
57*74a4d8c2SCharles.Forsyth 	slot = -1;
58*74a4d8c2SCharles.Forsyth 	type = nil;
59*74a4d8c2SCharles.Forsyth 	for(i = 0; ec2tpcmcia[i] != nil; i++){
60*74a4d8c2SCharles.Forsyth 		type = ec2tpcmcia[i];
61*74a4d8c2SCharles.Forsyth 		if((slot = pcmspecial(type, ether)) >= 0)
62*74a4d8c2SCharles.Forsyth 			break;
63*74a4d8c2SCharles.Forsyth 	}
64*74a4d8c2SCharles.Forsyth 	if(ec2tpcmcia[i] == nil){
65*74a4d8c2SCharles.Forsyth 		for(i = 0; i < ether->nopt; i++){
66*74a4d8c2SCharles.Forsyth 			if(cistrncmp(ether->opt[i], "id=", 3))
67*74a4d8c2SCharles.Forsyth 				continue;
68*74a4d8c2SCharles.Forsyth 			type = &ether->opt[i][3];
69*74a4d8c2SCharles.Forsyth 			if((slot = pcmspecial(type, ether)) >= 0)
70*74a4d8c2SCharles.Forsyth 				break;
71*74a4d8c2SCharles.Forsyth 		}
72*74a4d8c2SCharles.Forsyth 	}
73*74a4d8c2SCharles.Forsyth 	if(slot < 0){
74*74a4d8c2SCharles.Forsyth 	//	iofree(port);
75*74a4d8c2SCharles.Forsyth 		return -1;
76*74a4d8c2SCharles.Forsyth 	}
77*74a4d8c2SCharles.Forsyth 
78*74a4d8c2SCharles.Forsyth 	ether->ctlr = malloc(sizeof(Dp8390));
79*74a4d8c2SCharles.Forsyth 	ctlr = ether->ctlr;
80*74a4d8c2SCharles.Forsyth 	ctlr->width = 2;
81*74a4d8c2SCharles.Forsyth 	ctlr->ram = 0;
82*74a4d8c2SCharles.Forsyth 
83*74a4d8c2SCharles.Forsyth 	ctlr->port = port;
84*74a4d8c2SCharles.Forsyth 	ctlr->data = port+Data;
85*74a4d8c2SCharles.Forsyth 
86*74a4d8c2SCharles.Forsyth 	ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
87*74a4d8c2SCharles.Forsyth 	ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
88*74a4d8c2SCharles.Forsyth 	ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
89*74a4d8c2SCharles.Forsyth 
90*74a4d8c2SCharles.Forsyth 	ctlr->dummyrr = 0;
91*74a4d8c2SCharles.Forsyth 	for(i = 0; i < ether->nopt; i++){
92*74a4d8c2SCharles.Forsyth 		if(cistrcmp(ether->opt[i], "nodummyrr") == 0)
93*74a4d8c2SCharles.Forsyth 			ctlr->dummyrr = 0;
94*74a4d8c2SCharles.Forsyth 		else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0)
95*74a4d8c2SCharles.Forsyth 			ctlr->dummyrr = strtol(&ether->opt[i][8], nil, 0);
96*74a4d8c2SCharles.Forsyth 	}
97*74a4d8c2SCharles.Forsyth 
98*74a4d8c2SCharles.Forsyth 	/*
99*74a4d8c2SCharles.Forsyth 	 * Reset the board. This is done by doing a read
100*74a4d8c2SCharles.Forsyth 	 * followed by a write to the Reset address.
101*74a4d8c2SCharles.Forsyth 	 */
102*74a4d8c2SCharles.Forsyth 	buf[0] = inb(port+Reset);
103*74a4d8c2SCharles.Forsyth 	delay(2);
104*74a4d8c2SCharles.Forsyth 	outb(port+Reset, buf[0]);
105*74a4d8c2SCharles.Forsyth 	delay(2);
106*74a4d8c2SCharles.Forsyth 
107*74a4d8c2SCharles.Forsyth 	/*
108*74a4d8c2SCharles.Forsyth 	 * Init the (possible) chip, then use the (possible)
109*74a4d8c2SCharles.Forsyth 	 * chip to read the (possible) PROM for ethernet address
110*74a4d8c2SCharles.Forsyth 	 * and a marker byte.
111*74a4d8c2SCharles.Forsyth 	 * Could just look at the DP8390 command register after
112*74a4d8c2SCharles.Forsyth 	 * initialisation has been tried, but that wouldn't be
113*74a4d8c2SCharles.Forsyth 	 * enough, there are other ethernet boards which could
114*74a4d8c2SCharles.Forsyth 	 * match.
115*74a4d8c2SCharles.Forsyth 	 */
116*74a4d8c2SCharles.Forsyth 	dp8390reset(ether);
117*74a4d8c2SCharles.Forsyth 	sum = 0;
118*74a4d8c2SCharles.Forsyth 	if(cistrcmp(type, "PCMPC100") == 0 || cistrcmp(type, "FA410TX") == 0){
119*74a4d8c2SCharles.Forsyth 		/*
120*74a4d8c2SCharles.Forsyth 		 * The PCMPC100 has the ethernet address in I/O space.
121*74a4d8c2SCharles.Forsyth 		 * There's a checksum over 8 bytes which sums to 0xFF.
122*74a4d8c2SCharles.Forsyth 		 */
123*74a4d8c2SCharles.Forsyth 		for(i = 0; i < 8; i++){
124*74a4d8c2SCharles.Forsyth 			x = inb(port+0x14+i);
125*74a4d8c2SCharles.Forsyth 			sum += x;
126*74a4d8c2SCharles.Forsyth 			buf[i] = (x<<8)|x;
127*74a4d8c2SCharles.Forsyth 		}
128*74a4d8c2SCharles.Forsyth 	}
129*74a4d8c2SCharles.Forsyth 	else{
130*74a4d8c2SCharles.Forsyth 		memset(buf, 0, sizeof(buf));
131*74a4d8c2SCharles.Forsyth 		dp8390read(ctlr, buf, 0, sizeof(buf));
132*74a4d8c2SCharles.Forsyth 		if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
133*74a4d8c2SCharles.Forsyth 			sum = 0xFF;
134*74a4d8c2SCharles.Forsyth 	}
135*74a4d8c2SCharles.Forsyth 	if(sum != 0xFF){
136*74a4d8c2SCharles.Forsyth 		pcmspecialclose(slot);
137*74a4d8c2SCharles.Forsyth 		//iofree(ether->port);
138*74a4d8c2SCharles.Forsyth 		free(ether->ctlr);
139*74a4d8c2SCharles.Forsyth 		return -1;
140*74a4d8c2SCharles.Forsyth 	}
141*74a4d8c2SCharles.Forsyth 
142*74a4d8c2SCharles.Forsyth 	/*
143*74a4d8c2SCharles.Forsyth 	 * Stupid machine. Shorts were asked for,
144*74a4d8c2SCharles.Forsyth 	 * shorts were delivered, although the PROM is a byte array.
145*74a4d8c2SCharles.Forsyth 	 * Set the ethernet address.
146*74a4d8c2SCharles.Forsyth 	 */
147*74a4d8c2SCharles.Forsyth 	memset(ea, 0, Eaddrlen);
148*74a4d8c2SCharles.Forsyth 	if(memcmp(ea, ether->ea, Eaddrlen) == 0){
149*74a4d8c2SCharles.Forsyth 		for(i = 0; i < sizeof(ether->ea); i++)
150*74a4d8c2SCharles.Forsyth 			ether->ea[i] = buf[i];
151*74a4d8c2SCharles.Forsyth 	}
152*74a4d8c2SCharles.Forsyth 	dp8390setea(ether);
153*74a4d8c2SCharles.Forsyth 
154*74a4d8c2SCharles.Forsyth 	return 0;
155*74a4d8c2SCharles.Forsyth }
156