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