This source file includes following definitions.
- neprobe
- neprobe1
- ne_reset_8390
- ne_block_input
- ne_block_output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 static char *version =
20 "ne.c:v0.99-12B 8/12/93 Donald Becker (becker@super.org)\n";
21
22 #include <linux/config.h>
23 #include <linux/kernel.h>
24 #include <linux/sched.h>
25 #include <asm/system.h>
26 #include <asm/io.h>
27 #ifndef port_read
28 #include "iow.h"
29 #endif
30
31 #include "dev.h"
32 #include "8390.h"
33
34 #define NE_BASE (dev->base_addr)
35 #define NE_CMD 0x00
36 #define NE_DATAPORT 0x10
37 #define NE_RESET 0x1f
38
39 #define NE1SM_START_PG 0x20
40 #define NE1SM_STOP_PG 0x40
41 #define NESM_START_PG 0x40
42 #define NESM_STOP_PG 0x80
43
44 int neprobe(int ioaddr, struct device *dev);
45 static int neprobe1(int ioaddr, struct device *dev, int verbose);
46
47 static void ne_reset_8390(struct device *dev);
48 static int ne_block_input(struct device *dev, int count,
49 char *buf, int ring_offset);
50 static void ne_block_output(struct device *dev, const int count,
51 const unsigned char *buf, const int start_page);
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 int neprobe(int ioaddr, struct device *dev)
76 {
77 int *port, ports[] = {0x300, 0x280, 0x320, 0x340, 0x360, 0};
78
79 if (ioaddr > 0x100)
80 return neprobe1(ioaddr, dev, 1);
81
82 for (port = &ports[0]; *port; port++)
83 if (inb_p(*port) != 0xff && neprobe1(*port, dev, 0))
84 return dev->base_addr = *port;
85 return 0;
86 }
87
88 static int neprobe1(int ioaddr, struct device *dev, int verbose)
89 {
90 int i;
91 unsigned char SA_prom[32];
92 int wordlength = 2;
93 char *name;
94 int start_page, stop_page;
95 int neX000, ctron, dlink;
96 int reg0 = inb(ioaddr);
97
98 if ( reg0 == 0xFF)
99 return 0;
100
101
102 { int regd;
103 outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
104 regd = inb_p(ioaddr + 0x0d);
105 outb_p(0xff, ioaddr + 0x0d);
106 outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
107 inb_p(ioaddr + EN0_COUNTER0);
108 if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
109 outb_p(reg0, ioaddr);
110 outb(regd, ioaddr + 0x0d);
111 return 0;
112 }
113 }
114
115 printk("NE*000 ethercard probe at %#3x:", ioaddr);
116
117
118
119
120
121
122 {
123 struct {char value, offset; } program_seq[] = {
124 {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD},
125 {0x48, EN0_DCFG},
126 {0x00, EN0_RCNTLO},
127 {0x00, EN0_RCNTHI},
128 {0x00, EN0_IMR},
129 {0xFF, EN0_ISR},
130 {E8390_RXOFF, EN0_RXCR},
131 {E8390_TXOFF, EN0_TXCR},
132 {32, EN0_RCNTLO},
133 {0x00, EN0_RCNTHI},
134 {0x00, EN0_RSARLO},
135 {0x00, EN0_RSARHI},
136 {E8390_RREAD+E8390_START, E8390_CMD},
137 };
138 for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
139 outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
140 }
141 for(i = 0; i < 32 ; i+=2) {
142 SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
143 SA_prom[i+1] = inb_p(ioaddr + NE_DATAPORT);
144 if (SA_prom[i] != SA_prom[i+1])
145 wordlength = 1;
146 }
147
148 if (wordlength == 2) {
149
150 int tmp;
151 outb_p(0x49, ioaddr + EN0_DCFG);
152 tmp = inb_p(NE_BASE + NE_RESET);
153 outb(tmp, NE_BASE + NE_RESET);
154
155 for (i = 0; i < 16; i++)
156 SA_prom[i] = SA_prom[i+i];
157 }
158
159 #if defined(show_all_SAPROM)
160
161 for(i = 0; i < sizeof(SA_prom); i++)
162 printk(" %2.2x", SA_prom[i]);
163 #else
164 for(i = 0; i < ETHER_ADDR_LEN; i++) {
165 dev->dev_addr[i] = SA_prom[i];
166 printk(" %2.2x", SA_prom[i]);
167 }
168 #endif
169
170 neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
171 ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
172 dlink = (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01);
173
174
175 if (neX000 || dlink) {
176 if (wordlength == 2) {
177 name = dlink ? "DE200" : "NE2000";
178 start_page = NESM_START_PG;
179 stop_page = NESM_STOP_PG;
180 } else {
181 name = dlink ? "DE100" : "D-Link";
182 start_page = NE1SM_START_PG;
183 stop_page = NE1SM_STOP_PG;
184 }
185 } else if (ctron) {
186 name = "Cabletron";
187 start_page = 0x01;
188 stop_page = (wordlength == 2) ? 0x40 : 0x20;
189 } else {
190 printk(" not found.\n");
191 return 0;
192 }
193
194 if (dev->irq < 2) {
195 autoirq_setup(0);
196 outb_p(0x50, ioaddr + EN0_IMR);
197 outb_p(0x00, ioaddr + EN0_RCNTLO);
198 outb_p(0x00, ioaddr + EN0_RCNTHI);
199 outb_p(E8390_RREAD+E8390_START, ioaddr);
200 outb_p(0x00, ioaddr + EN0_IMR);
201 dev->irq = autoirq_report(0);
202 if (ei_debug > 2)
203 printk(" autoirq is %d", dev->irq);
204 } else if (dev->irq == 2)
205
206
207 dev->irq = 9;
208
209
210
211 {
212 int irqval = irqaction (dev->irq, &ei_sigaction);
213 if (irqval) {
214 printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
215 return 0;
216 }
217 }
218
219 printk("\n%s: %s found at %#x, using IRQ %d.\n",
220 dev->name, name, ioaddr, dev->irq);
221
222 dev->base_addr = ioaddr;
223
224 ethdev_init(dev);
225
226 if (ei_debug > 0)
227 printk(version);
228
229 ei_status.name = name;
230 ei_status.tx_start_page = start_page;
231 ei_status.stop_page = stop_page;
232 ei_status.word16 = (wordlength == 2);
233
234 ei_status.rx_start_page = start_page + TX_PAGES;
235 #ifdef PACKETBUF_MEMSIZE
236
237 ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
238 #endif
239
240 ei_status.reset_8390 = &ne_reset_8390;
241 ei_status.block_input = &ne_block_input;
242 ei_status.block_output = &ne_block_output;
243 NS8390_init(dev, 0);
244 return dev->base_addr;
245 }
246
247
248
249 static void
250 ne_reset_8390(struct device *dev)
251 {
252 int tmp = inb_p(NE_BASE + NE_RESET);
253 int reset_start_time = jiffies;
254
255 if (ei_debug > 1) printk("resetting the 8390 t=%d...", jiffies);
256 ei_status.txing = 0;
257
258 outb_p(tmp, NE_BASE + NE_RESET);
259
260 while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
261 if (jiffies - reset_start_time > 2) {
262 printk("%s: ne_reset_8390() did not complete.\n", dev->name);
263 break;
264 }
265 }
266
267
268
269
270
271
272 static int
273 ne_block_input(struct device *dev, int count, char *buf, int ring_offset)
274 {
275 int xfer_count = count;
276 int nic_base = dev->base_addr;
277
278 if (ei_status.dmaing) {
279 if (ei_debug > 0)
280 printk("%s: DMAing conflict in ne_block_input."
281 "[DMAstat:%1x][irqlock:%1x]\n",
282 dev->name, ei_status.dmaing, ei_status.irqlock);
283 return 0;
284 }
285 ei_status.dmaing |= 0x01;
286 outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
287 outb_p(count & 0xff, nic_base + EN0_RCNTLO);
288 outb_p(count >> 8, nic_base + EN0_RCNTHI);
289 outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
290 outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
291 outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
292 if (ei_status.word16) {
293 port_read(NE_BASE + NE_DATAPORT,buf,count>>1);
294 if (count & 0x01)
295 buf[count-1] = inb(NE_BASE + NE_DATAPORT), xfer_count++;
296 } else {
297 port_read_b(NE_BASE + NE_DATAPORT, buf, count);
298 }
299
300
301
302
303
304 if (ei_debug > 1) {
305 int addr, tries = 20;
306 do {
307
308
309 int high = inb_p(nic_base + EN0_RSARHI);
310 int low = inb_p(nic_base + EN0_RSARLO);
311 addr = (high << 8) + low;
312 if (((ring_offset + xfer_count) & 0xff) == low)
313 break;
314 } while (--tries > 0);
315 if (tries <= 0)
316 printk("%s: RX transfer address mismatch,"
317 "%#4.4x (expected) vs. %#4.4x (actual).\n",
318 dev->name, ring_offset + xfer_count, addr);
319 }
320 ei_status.dmaing &= ~0x01;
321 return ring_offset + count;
322 }
323
324 static void
325 ne_block_output(struct device *dev, int count,
326 const unsigned char *buf, const int start_page)
327 {
328 int retries = 0;
329 int nic_base = NE_BASE;
330
331
332
333
334 if (ei_status.word16 && (count & 0x01))
335 count++;
336 if (ei_status.dmaing) {
337 if (ei_debug > 0)
338 printk("%s: DMAing conflict in ne_block_output."
339 "[DMAstat:%1x][irqlock:%1x]\n",
340 dev->name, ei_status.dmaing, ei_status.irqlock);
341 return;
342 }
343 ei_status.dmaing |= 0x02;
344
345 outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
346
347 retry:
348 #if defined(rw_bugfix)
349
350
351
352
353 outb_p(0x42, nic_base + EN0_RCNTLO);
354 outb_p(0x00, nic_base + EN0_RCNTHI);
355 outb_p(0x42, nic_base + EN0_RSARLO);
356 outb_p(0x00, nic_base + EN0_RSARHI);
357 outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
358
359 SLOW_DOWN_IO;
360 SLOW_DOWN_IO;
361 SLOW_DOWN_IO;
362 #endif
363
364
365 outb_p(count & 0xff, nic_base + EN0_RCNTLO);
366 outb_p(count >> 8, nic_base + EN0_RCNTHI);
367 outb_p(0x00, nic_base + EN0_RSARLO);
368 outb_p(start_page, nic_base + EN0_RSARHI);
369
370 outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
371 if (ei_status.word16) {
372 port_write(NE_BASE + NE_DATAPORT, buf, count>>1);
373 } else {
374 port_write_b(NE_BASE + NE_DATAPORT, buf, count);
375 }
376
377
378
379 if (ei_debug > 1) {
380 int addr, tries = 20;
381 do {
382
383
384 int high = inb_p(nic_base + EN0_RSARHI);
385 int low = inb_p(nic_base + EN0_RSARLO);
386 addr = (high << 8) + low;
387 if ((start_page << 8) + count == addr)
388 break;
389 } while (--tries > 0);
390 if (tries <= 0) {
391 printk("%s: Tx packet transfer address mismatch,"
392 "%#4.4x (expected) vs. %#4.4x (actual).\n",
393 dev->name, (start_page << 8) + count, addr);
394 if (retries++ == 0)
395 goto retry;
396 }
397 }
398 ei_status.dmaing &= ~0x02;
399 return;
400 }
401
402
403
404
405
406
407
408
409