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 = ðer->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(ðer->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