aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/oaknet.c
diff options
context:
space:
mode:
authorAdrian Bunk <bunk@stusta.de>2007-01-04 13:53:30 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-05 16:58:47 -0500
commit83d98b401c053d760e38571595d8f4fa76ee271b (patch)
tree07cd5b817b577f1d20da50f13b16cfd510f2e990 /drivers/net/oaknet.c
parent24a427cf76984726641ea0d8163e61e99119069d (diff)
remove the broken OAKNET driver
The OAKNET driver: - has been marked as BROKEN for more than two years and - is still marked as BROKEN. Drivers that had been marked as BROKEN for such a long time seem to be unlikely to be revived in the forseeable future. But if anyone wants to ever revive this driver, the code is still present in the older kernel releases. Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/oaknet.c')
-rw-r--r--drivers/net/oaknet.c666
1 files changed, 0 insertions, 666 deletions
diff --git a/drivers/net/oaknet.c b/drivers/net/oaknet.c
deleted file mode 100644
index 702e3e95612a..000000000000
--- a/drivers/net/oaknet.c
+++ /dev/null
@@ -1,666 +0,0 @@
1/*
2 *
3 * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
4 *
5 * Module name: oaknet.c
6 *
7 * Description:
8 * Driver for the National Semiconductor DP83902AV Ethernet controller
9 * on-board the IBM PowerPC "Oak" evaluation board. Adapted from the
10 * various other 8390 drivers written by Donald Becker and Paul Gortmaker.
11 *
12 * Additional inspiration from the "tcd8390.c" driver from TiVo, Inc.
13 * and "enetLib.c" from IBM.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/errno.h>
19#include <linux/delay.h>
20#include <linux/netdevice.h>
21#include <linux/etherdevice.h>
22#include <linux/init.h>
23#include <linux/jiffies.h>
24
25#include <asm/board.h>
26#include <asm/io.h>
27
28#include "8390.h"
29
30
31/* Preprocessor Defines */
32
33#if !defined(TRUE) || TRUE != 1
34#define TRUE 1
35#endif
36
37#if !defined(FALSE) || FALSE != 0
38#define FALSE 0
39#endif
40
41#define OAKNET_START_PG 0x20 /* First page of TX buffer */
42#define OAKNET_STOP_PG 0x40 /* Last pagge +1 of RX ring */
43
44#define OAKNET_WAIT (2 * HZ / 100) /* 20 ms */
45
46/* Experimenting with some fixes for a broken driver... */
47
48#define OAKNET_DISINT
49#define OAKNET_HEADCHECK
50#define OAKNET_RWFIX
51
52
53/* Global Variables */
54
55static const char *name = "National DP83902AV";
56
57static struct net_device *oaknet_devs;
58
59
60/* Function Prototypes */
61
62static int oaknet_open(struct net_device *dev);
63static int oaknet_close(struct net_device *dev);
64
65static void oaknet_reset_8390(struct net_device *dev);
66static void oaknet_get_8390_hdr(struct net_device *dev,
67 struct e8390_pkt_hdr *hdr, int ring_page);
68static void oaknet_block_input(struct net_device *dev, int count,
69 struct sk_buff *skb, int ring_offset);
70static void oaknet_block_output(struct net_device *dev, int count,
71 const unsigned char *buf, int start_page);
72
73static void oaknet_dma_error(struct net_device *dev, const char *name);
74
75
76/*
77 * int oaknet_init()
78 *
79 * Description:
80 * This routine performs all the necessary platform-specific initiali-
81 * zation and set-up for the IBM "Oak" evaluation board's National
82 * Semiconductor DP83902AV "ST-NIC" Ethernet controller.
83 *
84 * Input(s):
85 * N/A
86 *
87 * Output(s):
88 * N/A
89 *
90 * Returns:
91 * 0 if OK, otherwise system error number on error.
92 *
93 */
94static int __init oaknet_init(void)
95{
96 register int i;
97 int reg0, regd;
98 int ret = -ENOMEM;
99 struct net_device *dev;
100#if 0
101 unsigned long ioaddr = OAKNET_IO_BASE;
102#else
103 unsigned long ioaddr = ioremap(OAKNET_IO_BASE, OAKNET_IO_SIZE);
104#endif
105 bd_t *bip = (bd_t *)__res;
106
107 if (!ioaddr)
108 return -ENOMEM;
109
110 dev = alloc_ei_netdev();
111 if (!dev)
112 goto out_unmap;
113
114 ret = -EBUSY;
115 if (!request_region(OAKNET_IO_BASE, OAKNET_IO_SIZE, name))
116 goto out_dev;
117
118 /* Quick register check to see if the device is really there. */
119
120 ret = -ENODEV;
121 if ((reg0 = ei_ibp(ioaddr)) == 0xFF)
122 goto out_region;
123
124 /*
125 * That worked. Now a more thorough check, using the multicast
126 * address registers, that the device is definitely out there
127 * and semi-functional.
128 */
129
130 ei_obp(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
131 regd = ei_ibp(ioaddr + 0x0D);
132 ei_obp(0xFF, ioaddr + 0x0D);
133 ei_obp(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
134 ei_ibp(ioaddr + EN0_COUNTER0);
135
136 /* It's no good. Fix things back up and leave. */
137
138 ret = -ENODEV;
139 if (ei_ibp(ioaddr + EN0_COUNTER0) != 0) {
140 ei_obp(reg0, ioaddr);
141 ei_obp(regd, ioaddr + 0x0D);
142 goto out_region;
143 }
144
145 SET_MODULE_OWNER(dev);
146
147 /*
148 * This controller is on an embedded board, so the base address
149 * and interrupt assignments are pre-assigned and unchageable.
150 */
151
152 dev->base_addr = ioaddr;
153 dev->irq = OAKNET_INT;
154
155 /*
156 * Disable all chip interrupts for now and ACK all pending
157 * interrupts.
158 */
159
160 ei_obp(0x0, ioaddr + EN0_IMR);
161 ei_obp(0xFF, ioaddr + EN0_ISR);
162
163 /* Attempt to get the interrupt line */
164
165 ret = -EAGAIN;
166 if (request_irq(dev->irq, ei_interrupt, 0, name, dev)) {
167 printk("%s: unable to request interrupt %d.\n",
168 name, dev->irq);
169 goto out_region;
170 }
171
172 /* Tell the world about what and where we've found. */
173
174 printk("%s: %s at", dev->name, name);
175 for (i = 0; i < ETHER_ADDR_LEN; ++i) {
176 dev->dev_addr[i] = bip->bi_enetaddr[i];
177 printk("%c%.2x", (i ? ':' : ' '), dev->dev_addr[i]);
178 }
179 printk(", found at %#lx, using IRQ %d.\n", dev->base_addr, dev->irq);
180
181 /* Set up some required driver fields and then we're done. */
182
183 ei_status.name = name;
184 ei_status.word16 = FALSE;
185 ei_status.tx_start_page = OAKNET_START_PG;
186 ei_status.rx_start_page = OAKNET_START_PG + TX_PAGES;
187 ei_status.stop_page = OAKNET_STOP_PG;
188
189 ei_status.reset_8390 = &oaknet_reset_8390;
190 ei_status.block_input = &oaknet_block_input;
191 ei_status.block_output = &oaknet_block_output;
192 ei_status.get_8390_hdr = &oaknet_get_8390_hdr;
193
194 dev->open = oaknet_open;
195 dev->stop = oaknet_close;
196#ifdef CONFIG_NET_POLL_CONTROLLER
197 dev->poll_controller = ei_poll;
198#endif
199
200 NS8390_init(dev, FALSE);
201 ret = register_netdev(dev);
202 if (ret)
203 goto out_irq;
204
205 oaknet_devs = dev;
206 return 0;
207
208out_irq;
209 free_irq(dev->irq, dev);
210out_region:
211 release_region(OAKNET_IO_BASE, OAKNET_IO_SIZE);
212out_dev:
213 free_netdev(dev);
214out_unmap:
215 iounmap(ioaddr);
216 return ret;
217}
218
219/*
220 * static int oaknet_open()
221 *
222 * Description:
223 * This routine is a modest wrapper around ei_open, the 8390-generic,
224 * driver open routine. This just increments the module usage count
225 * and passes along the status from ei_open.
226 *
227 * Input(s):
228 * *dev - Pointer to the device structure for this driver.
229 *
230 * Output(s):
231 * *dev - Pointer to the device structure for this driver, potentially
232 * modified by ei_open.
233 *
234 * Returns:
235 * 0 if OK, otherwise < 0 on error.
236 *
237 */
238static int
239oaknet_open(struct net_device *dev)
240{
241 int status = ei_open(dev);
242 return (status);
243}
244
245/*
246 * static int oaknet_close()
247 *
248 * Description:
249 * This routine is a modest wrapper around ei_close, the 8390-generic,
250 * driver close routine. This just decrements the module usage count
251 * and passes along the status from ei_close.
252 *
253 * Input(s):
254 * *dev - Pointer to the device structure for this driver.
255 *
256 * Output(s):
257 * *dev - Pointer to the device structure for this driver, potentially
258 * modified by ei_close.
259 *
260 * Returns:
261 * 0 if OK, otherwise < 0 on error.
262 *
263 */
264static int
265oaknet_close(struct net_device *dev)
266{
267 int status = ei_close(dev);
268 return (status);
269}
270
271/*
272 * static void oaknet_reset_8390()
273 *
274 * Description:
275 * This routine resets the DP83902 chip.
276 *
277 * Input(s):
278 * *dev - Pointer to the device structure for this driver.
279 *
280 * Output(s):
281 * N/A
282 *
283 * Returns:
284 * N/A
285 *
286 */
287static void
288oaknet_reset_8390(struct net_device *dev)
289{
290 int base = E8390_BASE;
291
292 /*
293 * We have no provision of reseting the controller as is done
294 * in other drivers, such as "ne.c". However, the following
295 * seems to work well enough in the TiVo driver.
296 */
297
298 printk("Resetting %s...\n", dev->name);
299 ei_obp(E8390_STOP | E8390_NODMA | E8390_PAGE0, base + E8390_CMD);
300 ei_status.txing = 0;
301 ei_status.dmaing = 0;
302}
303
304/*
305 * static void oaknet_get_8390_hdr()
306 *
307 * Description:
308 * This routine grabs the 8390-specific header. It's similar to the
309 * block input routine, but we don't need to be concerned with ring wrap
310 * as the header will be at the start of a page, so we optimize accordingly.
311 *
312 * Input(s):
313 * *dev - Pointer to the device structure for this driver.
314 * *hdr - Pointer to storage for the 8390-specific packet header.
315 * ring_page - ?
316 *
317 * Output(s):
318 * *hdr - Pointer to the 8390-specific packet header for the just-
319 * received frame.
320 *
321 * Returns:
322 * N/A
323 *
324 */
325static void
326oaknet_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
327 int ring_page)
328{
329 int base = dev->base_addr;
330
331 /*
332 * This should NOT happen. If it does, it is the LAST thing you'll
333 * see.
334 */
335
336 if (ei_status.dmaing) {
337 oaknet_dma_error(dev, "oaknet_get_8390_hdr");
338 return;
339 }
340
341 ei_status.dmaing |= 0x01;
342 outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, base + OAKNET_CMD);
343 outb_p(sizeof(struct e8390_pkt_hdr), base + EN0_RCNTLO);
344 outb_p(0, base + EN0_RCNTHI);
345 outb_p(0, base + EN0_RSARLO); /* On page boundary */
346 outb_p(ring_page, base + EN0_RSARHI);
347 outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD);
348
349 if (ei_status.word16)
350 insw(base + OAKNET_DATA, hdr,
351 sizeof(struct e8390_pkt_hdr) >> 1);
352 else
353 insb(base + OAKNET_DATA, hdr,
354 sizeof(struct e8390_pkt_hdr));
355
356 /* Byte-swap the packet byte count */
357
358 hdr->count = le16_to_cpu(hdr->count);
359
360 outb_p(ENISR_RDC, base + EN0_ISR); /* ACK Remote DMA interrupt */
361 ei_status.dmaing &= ~0x01;
362}
363
364/*
365 * XXX - Document me.
366 */
367static void
368oaknet_block_input(struct net_device *dev, int count, struct sk_buff *skb,
369 int ring_offset)
370{
371 int base = OAKNET_BASE;
372 char *buf = skb->data;
373
374 /*
375 * This should NOT happen. If it does, it is the LAST thing you'll
376 * see.
377 */
378
379 if (ei_status.dmaing) {
380 oaknet_dma_error(dev, "oaknet_block_input");
381 return;
382 }
383
384#ifdef OAKNET_DISINT
385 save_flags(flags);
386 cli();
387#endif
388
389 ei_status.dmaing |= 0x01;
390 ei_obp(E8390_NODMA + E8390_PAGE0 + E8390_START, base + E8390_CMD);
391 ei_obp(count & 0xff, base + EN0_RCNTLO);
392 ei_obp(count >> 8, base + EN0_RCNTHI);
393 ei_obp(ring_offset & 0xff, base + EN0_RSARLO);
394 ei_obp(ring_offset >> 8, base + EN0_RSARHI);
395 ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);
396 if (ei_status.word16) {
397 ei_isw(base + E8390_DATA, buf, count >> 1);
398 if (count & 0x01) {
399 buf[count - 1] = ei_ib(base + E8390_DATA);
400#ifdef OAKNET_HEADCHECK
401 bytes++;
402#endif
403 }
404 } else {
405 ei_isb(base + E8390_DATA, buf, count);
406 }
407#ifdef OAKNET_HEADCHECK
408 /*
409 * This was for the ALPHA version only, but enough people have
410 * been encountering problems so it is still here. If you see
411 * this message you either 1) have a slightly incompatible clone
412 * or 2) have noise/speed problems with your bus.
413 */
414
415 /* DMA termination address check... */
416 {
417 int addr, tries = 20;
418 do {
419 /* DON'T check for 'ei_ibp(EN0_ISR) & ENISR_RDC' here
420 -- it's broken for Rx on some cards! */
421 int high = ei_ibp(base + EN0_RSARHI);
422 int low = ei_ibp(base + EN0_RSARLO);
423 addr = (high << 8) + low;
424 if (((ring_offset + bytes) & 0xff) == low)
425 break;
426 } while (--tries > 0);
427 if (tries <= 0)
428 printk("%s: RX transfer address mismatch,"
429 "%#4.4x (expected) vs. %#4.4x (actual).\n",
430 dev->name, ring_offset + bytes, addr);
431 }
432#endif
433 ei_obp(ENISR_RDC, base + EN0_ISR); /* ACK Remote DMA interrupt */
434 ei_status.dmaing &= ~0x01;
435
436#ifdef OAKNET_DISINT
437 restore_flags(flags);
438#endif
439}
440
441/*
442 * static void oaknet_block_output()
443 *
444 * Description:
445 * This routine...
446 *
447 * Input(s):
448 * *dev - Pointer to the device structure for this driver.
449 * count - Number of bytes to be transferred.
450 * *buf -
451 * start_page -
452 *
453 * Output(s):
454 * N/A
455 *
456 * Returns:
457 * N/A
458 *
459 */
460static void
461oaknet_block_output(struct net_device *dev, int count,
462 const unsigned char *buf, int start_page)
463{
464 int base = E8390_BASE;
465#if 0
466 int bug;
467#endif
468 unsigned long start;
469#ifdef OAKNET_DISINT
470 unsigned long flags;
471#endif
472#ifdef OAKNET_HEADCHECK
473 int retries = 0;
474#endif
475
476 /* Round the count up for word writes. */
477
478 if (ei_status.word16 && (count & 0x1))
479 count++;
480
481 /*
482 * This should NOT happen. If it does, it is the LAST thing you'll
483 * see.
484 */
485
486 if (ei_status.dmaing) {
487 oaknet_dma_error(dev, "oaknet_block_output");
488 return;
489 }
490
491#ifdef OAKNET_DISINT
492 save_flags(flags);
493 cli();
494#endif
495
496 ei_status.dmaing |= 0x01;
497
498 /* Make sure we are in page 0. */
499
500 ei_obp(E8390_PAGE0 + E8390_START + E8390_NODMA, base + E8390_CMD);
501
502#ifdef OAKNET_HEADCHECK
503retry:
504#endif
505
506#if 0
507 /*
508 * The 83902 documentation states that the processor needs to
509 * do a "dummy read" before doing the remote write to work
510 * around a chip bug they don't feel like fixing.
511 */
512
513 bug = 0;
514 while (1) {
515 unsigned int rdhi;
516 unsigned int rdlo;
517
518 /* Now the normal output. */
519 ei_obp(ENISR_RDC, base + EN0_ISR);
520 ei_obp(count & 0xff, base + EN0_RCNTLO);
521 ei_obp(count >> 8, base + EN0_RCNTHI);
522 ei_obp(0x00, base + EN0_RSARLO);
523 ei_obp(start_page, base + EN0_RSARHI);
524
525 if (bug++)
526 break;
527
528 /* Perform the dummy read */
529 rdhi = ei_ibp(base + EN0_CRDAHI);
530 rdlo = ei_ibp(base + EN0_CRDALO);
531 ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);
532
533 while (1) {
534 unsigned int nrdhi;
535 unsigned int nrdlo;
536 nrdhi = ei_ibp(base + EN0_CRDAHI);
537 nrdlo = ei_ibp(base + EN0_CRDALO);
538 if ((rdhi != nrdhi) || (rdlo != nrdlo))
539 break;
540 }
541 }
542#else
543#ifdef OAKNET_RWFIX
544 /*
545 * Handle the read-before-write bug the same way as the
546 * Crynwr packet driver -- the Nat'l Semi. method doesn't work.
547 * Actually this doesn't always work either, but if you have
548 * problems with your 83902 this is better than nothing!
549 */
550
551 ei_obp(0x42, base + EN0_RCNTLO);
552 ei_obp(0x00, base + EN0_RCNTHI);
553 ei_obp(0x42, base + EN0_RSARLO);
554 ei_obp(0x00, base + EN0_RSARHI);
555 ei_obp(E8390_RREAD + E8390_START, base + E8390_CMD);
556 /* Make certain that the dummy read has occurred. */
557 udelay(6);
558#endif
559
560 ei_obp(ENISR_RDC, base + EN0_ISR);
561
562 /* Now the normal output. */
563 ei_obp(count & 0xff, base + EN0_RCNTLO);
564 ei_obp(count >> 8, base + EN0_RCNTHI);
565 ei_obp(0x00, base + EN0_RSARLO);
566 ei_obp(start_page, base + EN0_RSARHI);
567#endif /* 0/1 */
568
569 ei_obp(E8390_RWRITE + E8390_START, base + E8390_CMD);
570 if (ei_status.word16) {
571 ei_osw(E8390_BASE + E8390_DATA, buf, count >> 1);
572 } else {
573 ei_osb(E8390_BASE + E8390_DATA, buf, count);
574 }
575
576#ifdef OAKNET_DISINT
577 restore_flags(flags);
578#endif
579
580 start = jiffies;
581
582#ifdef OAKNET_HEADCHECK
583 /*
584 * This was for the ALPHA version only, but enough people have
585 * been encountering problems so it is still here.
586 */
587
588 {
589 /* DMA termination address check... */
590 int addr, tries = 20;
591 do {
592 int high = ei_ibp(base + EN0_RSARHI);
593 int low = ei_ibp(base + EN0_RSARLO);
594 addr = (high << 8) + low;
595 if ((start_page << 8) + count == addr)
596 break;
597 } while (--tries > 0);
598
599 if (tries <= 0) {
600 printk("%s: Tx packet transfer address mismatch,"
601 "%#4.4x (expected) vs. %#4.4x (actual).\n",
602 dev->name, (start_page << 8) + count, addr);
603 if (retries++ == 0)
604 goto retry;
605 }
606 }
607#endif
608
609 while ((ei_ibp(base + EN0_ISR) & ENISR_RDC) == 0) {
610 if (time_after(jiffies, start + OAKNET_WAIT)) {
611 printk("%s: timeout waiting for Tx RDC.\n", dev->name);
612 oaknet_reset_8390(dev);
613 NS8390_init(dev, TRUE);
614 break;
615 }
616 }
617
618 ei_obp(ENISR_RDC, base + EN0_ISR); /* Ack intr. */
619 ei_status.dmaing &= ~0x01;
620}
621
622/*
623 * static void oaknet_dma_error()
624 *
625 * Description:
626 * This routine prints out a last-ditch informative message to the console
627 * indicating that a DMA error occurred. If you see this, it's the last
628 * thing you'll see.
629 *
630 * Input(s):
631 * *dev - Pointer to the device structure for this driver.
632 * *name - Informative text (e.g. function name) indicating where the
633 * DMA error occurred.
634 *
635 * Output(s):
636 * N/A
637 *
638 * Returns:
639 * N/A
640 *
641 */
642static void
643oaknet_dma_error(struct net_device *dev, const char *name)
644{
645 printk(KERN_EMERG "%s: DMAing conflict in %s."
646 "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
647 dev->name, name, ei_status.dmaing, ei_status.irqlock,
648 dev->interrupt);
649}
650
651/*
652 * Oak Ethernet module unload interface.
653 */
654static void __exit oaknet_cleanup_module (void)
655{
656 /* Convert to loop once driver supports multiple devices. */
657 unregister_netdev(oaknet_dev);
658 free_irq(oaknet_devs->irq, oaknet_devs);
659 release_region(oaknet_devs->base_addr, OAKNET_IO_SIZE);
660 iounmap(ioaddr);
661 free_netdev(oaknet_devs);
662}
663
664module_init(oaknet_init);
665module_exit(oaknet_cleanup_module);
666MODULE_LICENSE("GPL");