This source file includes following definitions.
- wd_probe
- wd_probe1
- wd_open
- wd_reset_8390
- wd_get_8390_hdr
- wd_block_input
- wd_block_output
- wd_close_card
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 static const char *version =
28 "wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
29
30 #include <linux/module.h>
31
32 #include <linux/kernel.h>
33 #include <linux/sched.h>
34 #include <linux/errno.h>
35 #include <linux/string.h>
36 #include <asm/io.h>
37 #include <asm/system.h>
38
39 #include <linux/netdevice.h>
40 #include <linux/etherdevice.h>
41 #include "8390.h"
42
43
44 static unsigned int wd_portlist[] =
45 {0x300, 0x280, 0x380, 0x240, 0};
46
47 int wd_probe(struct device *dev);
48 int wd_probe1(struct device *dev, int ioaddr);
49
50 static int wd_open(struct device *dev);
51 static void wd_reset_8390(struct device *dev);
52 static void wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
53 int ring_page);
54 static void wd_block_input(struct device *dev, int count,
55 struct sk_buff *skb, int ring_offset);
56 static void wd_block_output(struct device *dev, int count,
57 const unsigned char *buf, const start_page);
58 static int wd_close_card(struct device *dev);
59
60
61 #define WD_START_PG 0x00
62 #define WD03_STOP_PG 0x20
63 #define WD13_STOP_PG 0x40
64
65 #define WD_CMDREG 0
66 #define WD_RESET 0x80
67 #define WD_MEMENB 0x40
68 #define WD_CMDREG5 5
69 #define ISA16 0x80
70 #define NIC16 0x40
71 #define WD_NIC_OFFSET 16
72 #define WD_IO_EXTENT 32
73
74
75
76
77
78
79
80
81
82
83 #ifdef HAVE_DEVLIST
84 struct netdev_entry wd_drv =
85 {"wd", wd_probe1, WD_IO_EXTENT, wd_portlist};
86 #else
87
88 int wd_probe(struct device *dev)
89 {
90 int i;
91 int base_addr = dev ? dev->base_addr : 0;
92
93 if (base_addr > 0x1ff)
94 return wd_probe1(dev, base_addr);
95 else if (base_addr != 0)
96 return ENXIO;
97
98 for (i = 0; wd_portlist[i]; i++) {
99 int ioaddr = wd_portlist[i];
100 if (check_region(ioaddr, WD_IO_EXTENT))
101 continue;
102 if (wd_probe1(dev, ioaddr) == 0)
103 return 0;
104 }
105
106 return ENODEV;
107 }
108 #endif
109
110 int wd_probe1(struct device *dev, int ioaddr)
111 {
112 int i;
113 int checksum = 0;
114 int ancient = 0;
115 int word16 = 0;
116 const char *model_name;
117 static unsigned version_printed = 0;
118
119 for (i = 0; i < 8; i++)
120 checksum += inb(ioaddr + 8 + i);
121 if (inb(ioaddr + 8) == 0xff
122 || inb(ioaddr + 9) == 0xff
123 || (checksum & 0xff) != 0xFF)
124 return ENODEV;
125
126
127 if (dev == NULL) {
128 printk("wd.c: Passed a NULL device.\n");
129 dev = init_etherdev(0, 0);
130 }
131
132
133 if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
134 printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
135 dev->mem_start = 0;
136 dev->mem_end = 0;
137 }
138
139 if (ei_debug && version_printed++ == 0)
140 printk(version);
141
142 printk("%s: WD80x3 at %#3x, ", dev->name, ioaddr);
143 for (i = 0; i < 6; i++)
144 printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i));
145
146
147
148
149
150
151 if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
152 unsigned char reg5 = inb(ioaddr+5);
153
154 switch (inb(ioaddr+2)) {
155 case 0x03: word16 = 0; model_name = "PDI8023-8"; break;
156 case 0x05: word16 = 0; model_name = "PDUC8023"; break;
157 case 0x0a: word16 = 1; model_name = "PDI8023-16"; break;
158
159 default: word16 = 0; model_name = "PDI8023"; break;
160 }
161 dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12;
162 dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
163 } else {
164
165
166
167
168
169
170 for (i = 0; i < 6; i++)
171 if (inb(ioaddr+i) != inb(ioaddr+8+i))
172 break;
173 if (i >= 6) {
174 ancient = 1;
175 model_name = "WD8003-old";
176 word16 = 0;
177 } else {
178 int tmp = inb(ioaddr+1);
179 outb( tmp ^ 0x01, ioaddr+1 );
180 if (((inb( ioaddr+1) & 0x01) == 0x01)
181 && (tmp & 0x01) == 0x01 ) {
182 int asic_reg5 = inb(ioaddr+WD_CMDREG5);
183
184 outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
185 outb(tmp, ioaddr+1);
186 model_name = "WD8013";
187 word16 = 1;
188 } else {
189 model_name = "WD8003";
190 word16 = 0;
191 }
192 outb(tmp, ioaddr+1);
193 }
194 #ifndef final_version
195 if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
196 printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
197 word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
198 #endif
199 }
200
201 #if defined(WD_SHMEM) && WD_SHMEM > 0x80000
202
203 dev->mem_start = WD_SHMEM;
204 #else
205 if (dev->mem_start == 0) {
206
207 int reg0 = inb(ioaddr);
208 if (reg0 == 0xff || reg0 == 0) {
209
210 dev->mem_start = 0xd0000;
211 printk(" assigning address %#lx", dev->mem_start);
212 } else {
213 int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
214
215 if (high_addr_bits == 0x1f || word16 == 0)
216 high_addr_bits = 0x01;
217 dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
218 }
219 }
220 #endif
221
222
223 dev->base_addr = ioaddr+WD_NIC_OFFSET;
224
225 if (dev->irq < 2) {
226 int irqmap[] = {9,3,5,7,10,11,15,4};
227 int reg1 = inb(ioaddr+1);
228 int reg4 = inb(ioaddr+4);
229 if (ancient || reg1 == 0xff) {
230 short nic_addr = ioaddr+WD_NIC_OFFSET;
231
232
233
234
235 outb_p(E8390_NODMA + E8390_STOP, nic_addr);
236 outb(0x00, nic_addr+EN0_IMR);
237 autoirq_setup(0);
238 outb_p(0xff, nic_addr + EN0_IMR);
239 outb_p(0x00, nic_addr + EN0_RCNTLO);
240 outb_p(0x00, nic_addr + EN0_RCNTHI);
241 outb(E8390_RREAD+E8390_START, nic_addr);
242 dev->irq = autoirq_report(2);
243 outb_p(0x00, nic_addr+EN0_IMR);
244
245 if (ei_debug > 2)
246 printk(" autoirq is %d", dev->irq);
247 if (dev->irq < 2)
248 dev->irq = word16 ? 10 : 5;
249 } else
250 dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
251 } else if (dev->irq == 2)
252 dev->irq = 9;
253
254
255
256 if (request_irq(dev->irq, ei_interrupt, 0, model_name, NULL)) {
257 printk (" unable to get IRQ %d.\n", dev->irq);
258 return EAGAIN;
259 }
260
261
262 if (ethdev_init(dev)) {
263 printk (" unable to get memory for dev->priv.\n");
264 free_irq(dev->irq, NULL);
265 return -ENOMEM;
266 }
267
268
269 request_region(ioaddr, WD_IO_EXTENT, model_name);
270
271 ei_status.name = model_name;
272 ei_status.word16 = word16;
273 ei_status.tx_start_page = WD_START_PG;
274 ei_status.rx_start_page = WD_START_PG + TX_PAGES;
275
276
277 dev->rmem_start = dev->mem_start + TX_PAGES*256;
278
279
280 if (dev->mem_end != 0) {
281 ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
282 } else {
283 ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
284 dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
285 }
286 dev->rmem_end = dev->mem_end;
287
288 printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
289 model_name, dev->irq, dev->mem_start, dev->mem_end-1);
290
291 ei_status.reset_8390 = &wd_reset_8390;
292 ei_status.block_input = &wd_block_input;
293 ei_status.block_output = &wd_block_output;
294 ei_status.get_8390_hdr = &wd_get_8390_hdr;
295 dev->open = &wd_open;
296 dev->stop = &wd_close_card;
297 NS8390_init(dev, 0);
298
299 #if 1
300
301
302 if (inb(ioaddr+14) & 0x20)
303 outb(inb(ioaddr+4)|0x80, ioaddr+4);
304 #endif
305
306 return 0;
307 }
308
309 static int
310 wd_open(struct device *dev)
311 {
312 int ioaddr = dev->base_addr - WD_NIC_OFFSET;
313
314
315
316 ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB;
317 ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
318
319 if (ei_status.word16)
320 outb(ei_status.reg5, ioaddr+WD_CMDREG5);
321 outb(ei_status.reg0, ioaddr);
322
323 ei_open(dev);
324 MOD_INC_USE_COUNT;
325 return 0;
326 }
327
328 static void
329 wd_reset_8390(struct device *dev)
330 {
331 int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET;
332
333 outb(WD_RESET, wd_cmd_port);
334 if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies);
335 ei_status.txing = 0;
336
337
338 outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
339 if (ei_status.word16)
340 outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
341
342 if (ei_debug > 1) printk("reset done\n");
343 return;
344 }
345
346
347
348
349
350 static void
351 wd_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
352 {
353
354 int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET;
355 unsigned long hdr_start = dev->mem_start + ((ring_page - WD_START_PG)<<8);
356
357
358
359 if (ei_status.word16)
360 outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
361
362 #ifdef notdef
363
364 memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
365 #else
366 ((unsigned int*)hdr)[0] = readl(hdr_start);
367 #endif
368 }
369
370
371
372
373
374
375 static void
376 wd_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
377 {
378 int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET;
379 unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
380
381 if (xfer_start + count > dev->rmem_end) {
382
383 int semi_count = dev->rmem_end - xfer_start;
384 memcpy_fromio(skb->data, xfer_start, semi_count);
385 count -= semi_count;
386 memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
387 } else {
388
389 eth_io_copy_and_sum(skb, xfer_start, count, 0);
390 }
391
392
393 if (ei_status.word16)
394 outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
395 }
396
397 static void
398 wd_block_output(struct device *dev, int count, const unsigned char *buf,
399 int start_page)
400 {
401 int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET;
402 long shmem = dev->mem_start + ((start_page - WD_START_PG)<<8);
403
404
405 if (ei_status.word16) {
406
407 outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
408 memcpy_toio(shmem, buf, count);
409 outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
410 } else
411 memcpy_toio(shmem, buf, count);
412 }
413
414
415 static int
416 wd_close_card(struct device *dev)
417 {
418 int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET;
419
420 if (ei_debug > 1)
421 printk("%s: Shutting down ethercard.\n", dev->name);
422 ei_close(dev);
423
424
425 if (ei_status.word16)
426 outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
427
428
429 outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
430
431 MOD_DEC_USE_COUNT;
432
433 return 0;
434 }
435
436
437 #ifdef MODULE
438 #define MAX_WD_CARDS 4
439 #define NAMELEN 8
440 static char namelist[NAMELEN * MAX_WD_CARDS] = { 0, };
441 static struct device dev_wd[MAX_WD_CARDS] = {
442 {
443 NULL,
444 0, 0, 0, 0,
445 0, 0,
446 0, 0, 0, NULL, NULL
447 },
448 };
449
450 static int io[MAX_WD_CARDS] = { 0, };
451 static int irq[MAX_WD_CARDS] = { 0, };
452 static int mem[MAX_WD_CARDS] = { 0, };
453 static int mem_end[MAX_WD_CARDS] = { 0, };
454
455
456
457 int
458 init_module(void)
459 {
460 int this_dev, found = 0;
461
462 for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
463 struct device *dev = &dev_wd[this_dev];
464 dev->name = namelist+(NAMELEN*this_dev);
465 dev->irq = irq[this_dev];
466 dev->base_addr = io[this_dev];
467 dev->mem_start = mem[this_dev];
468 dev->mem_end = mem_end[this_dev];
469 dev->init = wd_probe;
470 if (io[this_dev] == 0) {
471 if (this_dev != 0) break;
472 printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n");
473 }
474 if (register_netdev(dev) != 0) {
475 printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
476 if (found != 0) return 0;
477 return -ENXIO;
478 }
479 found++;
480 }
481
482 return 0;
483 }
484
485 void
486 cleanup_module(void)
487 {
488 int this_dev;
489
490 for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
491 struct device *dev = &dev_wd[this_dev];
492 if (dev->priv != NULL) {
493 int ioaddr = dev->base_addr - WD_NIC_OFFSET;
494 kfree(dev->priv);
495 dev->priv = NULL;
496 free_irq(dev->irq, NULL);
497 irq2dev_map[dev->irq] = NULL;
498 release_region(ioaddr, WD_IO_EXTENT);
499 unregister_netdev(dev);
500 }
501 }
502 }
503 #endif
504
505
506
507
508
509
510
511
512
513