~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/net/oaknet.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.