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