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