|
|
1.1 root 1: /* wd.c: A WD80x3 ethernet driver for linux. */
2: /*
3: Written 1993-94 by Donald Becker.
4:
5: Copyright 1993 United States Government as represented by the
6: Director, National Security Agency.
7:
8: This software may be used and distributed according to the terms
9: of the GNU Public License, incorporated herein by reference.
10:
11: The author may be reached as [email protected], or C/O
12: Center of Excellence in Space Data and Information Sciences
13: Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
14:
15: This is a driver for WD8003 and WD8013 "compatible" ethercards.
16:
17: Thanks to Russ Nelson ([email protected]) for loaning me a WD8013.
18:
19: Changelog:
20:
21: Paul Gortmaker : multiple card support for module users, support
22: for non-standard memory sizes.
23:
24:
25: */
26:
27: static const char *version =
28: "wd.c:v1.10 9/23/94 Donald Becker ([email protected])\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: /* A zero-terminated list of I/O addresses to be probed. */
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 int start_page);
58: static int wd_close_card(struct device *dev);
59:
60:
61: #define WD_START_PG 0x00 /* First page of TX buffer */
62: #define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */
63: #define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */
64:
65: #define WD_CMDREG 0 /* Offset to ASIC command register. */
66: #define WD_RESET 0x80 /* Board reset, in WD_CMDREG. */
67: #define WD_MEMENB 0x40 /* Enable the shared memory. */
68: #define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */
69: #define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */
70: #define NIC16 0x40 /* Enable 16 bit access from the 8390. */
71: #define WD_NIC_OFFSET 16 /* Offset to the 8390 from the base_addr. */
72: #define WD_IO_EXTENT 32
73:
74:
75: /* Probe for the WD8003 and WD8013. These cards have the station
76: address PROM at I/O ports <base>+8 to <base>+13, with a checksum
77: following. A Soundblaster can have the same checksum as an WDethercard,
78: so we have an extra exclusionary check for it.
79:
80: The wd_probe1() routine initializes the card and fills the
81: station address field. */
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) /* Check a single specified location. */
94: return wd_probe1(dev, base_addr);
95: else if (base_addr != 0) /* Don't probe at all. */
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; /* An old card without config registers. */
115: int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */
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 /* Extra check to avoid soundcard. */
122: || inb(ioaddr + 9) == 0xff
123: || (checksum & 0xff) != 0xFF)
124: return ENODEV;
125:
126: /* We should have a "dev" from Space.c or the static module table. */
127: if (dev == NULL) {
128: printk("wd.c: Passed a NULL device.\n");
129: dev = init_etherdev(0, 0);
130: }
131:
132: /* Check for semi-valid mem_start/end values if supplied. */
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: /* The following PureData probe code was contributed by
147: Mike Jagdis <[email protected]>. Puredata does software
148: configuration differently from others so we have to check for them.
149: This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
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: /* Either 0x01 (dumb) or they've released a new version. */
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 { /* End of PureData probe */
164: /* This method of checking for a 16-bit board is borrowed from the
165: we.c driver. A simpler method is just to look in ASIC reg. 0x03.
166: I'm comparing the two method in alpha test to make certain they
167: return the same result. */
168: /* Check for the old 8 bit board - it has register 0/8 aliasing.
169: Do NOT check i>=6 here -- it hangs the old 8003 boards! */
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); /* fiddle with 16bit bit */
179: outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */
180: if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */
181: && (tmp & 0x01) == 0x01 ) { /* In a 16 slot. */
182: int asic_reg5 = inb(ioaddr+WD_CMDREG5);
183: /* Magic to set ASIC to word-wide mode. */
184: outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
185: outb(tmp, ioaddr+1);
186: model_name = "WD8013";
187: word16 = 1; /* We have a 16bit board here! */
188: } else {
189: model_name = "WD8003";
190: word16 = 0;
191: }
192: outb(tmp, ioaddr+1); /* Restore original reg1 value. */
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: /* Allow a compile-time override. */
203: dev->mem_start = WD_SHMEM;
204: #else
205: if (dev->mem_start == 0) {
206: /* Sanity and old 8003 check */
207: int reg0 = inb(ioaddr);
208: if (reg0 == 0xff || reg0 == 0) {
209: /* Future plan: this could check a few likely locations first. */
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: /* Some boards don't have the register 5 -- it returns 0xff. */
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: /* The 8390 isn't at the base address -- the ASIC regs are there! */
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) { /* Ack!! No way to read the IRQ! */
230: short nic_addr = ioaddr+WD_NIC_OFFSET;
231:
232: /* We have an old-style ethercard that doesn't report its IRQ
233: line. Do autoirq to find the IRQ line. Note that this IS NOT
234: a reliable way to trigger an interrupt. */
235: outb_p(E8390_NODMA + E8390_STOP, nic_addr);
236: outb(0x00, nic_addr+EN0_IMR); /* Disable all intrs. */
237: autoirq_setup(0);
238: outb_p(0xff, nic_addr + EN0_IMR); /* Enable all interrupts. */
239: outb_p(0x00, nic_addr + EN0_RCNTLO);
240: outb_p(0x00, nic_addr + EN0_RCNTHI);
241: outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
242: dev->irq = autoirq_report(2);
243: outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
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) /* Fixup bogosity: IRQ2 is really IRQ9 */
252: dev->irq = 9;
253:
254: /* Snarf the interrupt now. There's no point in waiting since we cannot
255: share and the board will usually be enabled. */
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: /* Allocate dev->priv and fill in 8390 specific dev fields. */
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: /* OK, were are certain this is going to work. Setup the device. */
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: /* Don't map in the shared memory until the board is actually opened. */
277: dev->rmem_start = dev->mem_start + TX_PAGES*256;
278:
279: /* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
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: /* Enable interrupt generation on softconfig cards -- M.U */
301: /* .. but possibly potentially unsafe - Donald */
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; /* WD_CMDREG */
313:
314: /* Map in the shared memory. Always set register 0 last to remain
315: compatible with very old boards. */
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); /* WD_CMDREG */
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; /* WD_CMDREG */
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: /* Set up the ASIC registers, just in case something changed them. */
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: /* Grab the 8390 specific header. Similar to the block_input routine, but
347: we don't need to be concerned with ring wrap as the header will be at
348: the start of a page, so we optimize accordingly. */
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; /* WD_CMDREG */
355: unsigned long hdr_start = dev->mem_start + ((ring_page - WD_START_PG)<<8);
356:
357: /* We'll always get a 4 byte header read followed by a packet read, so
358: we enable 16 bit mode before the header, and disable after the body. */
359: if (ei_status.word16)
360: outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
361:
362: #ifdef notdef
363: /* Officially this is what we are doing, but the readl() is faster */
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: /* Block input and output are easy on shared memory ethercards, and trivial
371: on the Western digital card where there is no choice of how to do it.
372: The only complications are that the ring buffer wraps, and need to map
373: switch between 8- and 16-bit modes. */
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; /* WD_CMDREG */
379: unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
380:
381: if (xfer_start + count > dev->rmem_end) {
382: /* We must wrap the input move. */
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: /* Packet is in one chunk -- we can copy + cksum. */
389: eth_io_copy_and_sum(skb, xfer_start, count, 0);
390: }
391:
392: /* Turn off 16 bit access so that reboot works. ISA brain-damage */
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; /* WD_CMDREG */
402: long shmem = dev->mem_start + ((start_page - WD_START_PG)<<8);
403:
404:
405: if (ei_status.word16) {
406: /* Turn on and off 16 bit access so that reboot works. */
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; /* WD_CMDREG */
419:
420: if (ei_debug > 1)
421: printk("%s: Shutting down ethercard.\n", dev->name);
422: ei_close(dev);
423:
424: /* Change from 16-bit to 8-bit shared memory so reboot works. */
425: if (ei_status.word16)
426: outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
427:
428: /* And disable the shared memory. */
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 /* Max number of wd cards per module */
439: #define NAMELEN 8 /* # of chars for storing dev->name */
440: static char namelist[NAMELEN * MAX_WD_CARDS] = { 0, };
441: static struct device dev_wd[MAX_WD_CARDS] = {
442: {
443: NULL, /* assign a chunk of namelist[] below */
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, }; /* for non std. mem size */
454:
455: /* This is set up so that only a single autoprobe takes place per call.
456: ISA device autoprobes on a running machine are not recommended. */
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; /* only autoprobe 1st one */
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; /* Got at least one. */
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 /* MODULE */
504:
505:
506: /*
507: * Local variables:
508: * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c wd.c"
509: * version-control: t
510: * tab-width: 4
511: * kept-new-versions: 5
512: * End:
513: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.