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