hplance.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* hplance.c  : the  Linux/hp300/lance ethernet driver
  2.  *
  3.  * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
  4.  * Based on the Sun Lance driver and the NetBSD HP Lance driver
  5.  * Uses the generic 7990.c LANCE code.
  6.  */
  7. #include <linux/module.h>
  8. #include <linux/kernel.h>
  9. #include <linux/sched.h>
  10. #include <linux/types.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/ptrace.h>
  13. #include <linux/ioport.h>
  14. #include <linux/slab.h>
  15. #include <linux/string.h>
  16. #include <linux/delay.h>
  17. #include <linux/init.h>
  18. #include <linux/errno.h>
  19. #include <asm/system.h>
  20. #include <asm/io.h>
  21. #include <asm/pgtable.h>
  22. /* Used for the temporal inet entries and routing */
  23. #include <linux/socket.h>
  24. #include <linux/route.h>
  25. #include <linux/dio.h>
  26. #include <linux/netdevice.h>
  27. #include <linux/etherdevice.h>
  28. #include <linux/skbuff.h>
  29. #include "hplance.h"
  30. /* We have 16834 bytes of RAM for the init block and buffers. This places
  31.  * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
  32.  * buffers and 2 Tx buffers.
  33.  */
  34. #define LANCE_LOG_TX_BUFFERS 1
  35. #define LANCE_LOG_RX_BUFFERS 3
  36. #include "7990.h"                                 /* use generic LANCE code */
  37. /* Our private data structure */
  38. struct hplance_private {
  39.   struct lance_private lance;
  40.   unsigned int scode;
  41.   void *base;
  42. };
  43. /* function prototypes... This is easy because all the grot is in the
  44.  * generic LANCE support. All we have to support is probing for boards,
  45.  * plus board-specific init, open and close actions. 
  46.  * Oh, and we need to tell the generic code how to read and write LANCE registers...
  47.  */
  48. int hplance_probe(struct net_device *dev);
  49. static int hplance_init(struct net_device *dev, int scode);
  50. static int hplance_open(struct net_device *dev);
  51. static int hplance_close(struct net_device *dev);
  52. static void hplance_writerap(struct hplance_private *lp, unsigned short value);
  53. static void hplance_writerdp(struct hplance_private *lp, unsigned short value);
  54. static unsigned short hplance_readrdp(struct hplance_private *lp);
  55. #ifdef MODULE
  56. static struct hplance_private *root_hplance_dev;
  57. #endif
  58. /* Find all the HP Lance boards and initialise them... */
  59. int __init hplance_probe(struct net_device *dev)
  60. {
  61.         int cards = 0, called = 0;
  62.         if (!MACH_IS_HP300 || called)
  63.                 return(ENODEV);
  64.         called++;
  65.         
  66.         /* Isn't DIO nice? */
  67.         for(;;)
  68.         {
  69.                 int v, scode = dio_find(DIO_ID_LAN);
  70.                                 
  71.                 if (!scode)
  72.                         break;
  73.                 
  74.                 if(cards)
  75.                         dev = NULL;      /* don't trash previous device, make a new one */
  76.                 cards++;
  77.                 
  78.                 v = hplance_init(dev, scode);
  79.                 if (v)                            /* error, abort immediately */
  80.                         return v;
  81.         }
  82.         /* OK, return success, or ENODEV if we didn't find any cards */
  83.         if (!cards)
  84.                 return -ENODEV;
  85.         return 0;
  86. }
  87. /* Initialise a single lance board at the given select code */
  88. static int __init hplance_init(struct net_device *dev, int scode)
  89. {
  90.         /* const char *name = dio_scodetoname(scode); */
  91.         static const char name[] = "HP LANCE";
  92.         void *va = dio_scodetoviraddr(scode);
  93.         struct hplance_private *lp;
  94.         int i;
  95.         
  96. #ifdef MODULE
  97. dev = init_etherdev(0, sizeof(struct hplance_private));
  98. if (!dev)
  99. return -ENOMEM;
  100. #else
  101. dev->priv = kmalloc(sizeof(struct hplance_private), GFP_KERNEL);
  102. if (dev->priv == NULL)
  103. return -ENOMEM;
  104. memset(dev->priv, 0, sizeof(struct hplance_private));
  105. #endif
  106. SET_MODULE_OWNER(dev);
  107.         printk("%s: HP LANCE; select code %d, addr", dev->name, scode);
  108.         /* reset the board */
  109.         writeb(0xff,va+DIO_IDOFF);
  110.         udelay(100);                              /* ariba! ariba! udelay! udelay! */
  111.         /* Fill the dev fields */
  112.         dev->base_addr = (unsigned long)va;
  113.         dev->open = &hplance_open;
  114.         dev->stop = &hplance_close;
  115.         dev->hard_start_xmit = &lance_start_xmit;
  116.         dev->get_stats = &lance_get_stats;
  117.         dev->set_multicast_list = &lance_set_multicast;
  118.         dev->dma = 0;
  119.         
  120.         for (i=0; i<6; i++)
  121.         {
  122.                 /* The NVRAM holds our ethernet address, one nibble per byte,
  123.                  * at bytes NVRAMOFF+1,3,5,7,9...
  124.                  */
  125.                 dev->dev_addr[i] = ((readb(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
  126.                         | (readb(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
  127.                 printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]);
  128.         }
  129.         
  130.         lp = (struct hplance_private *)dev->priv;
  131.         lp->lance.name = (char*)name;                   /* discards const, shut up gcc */
  132.         lp->lance.ll = (struct lance_regs *)(va + HPLANCE_REGOFF);
  133.         lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
  134.         lp->lance.lance_init_block = 0;                 /* LANCE addr of same RAM */
  135.         lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
  136.         lp->lance.irq = dio_scodetoipl(scode);
  137.         lp->lance.writerap = hplance_writerap;
  138.         lp->lance.writerdp = hplance_writerdp;
  139.         lp->lance.readrdp = hplance_readrdp;
  140.         lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
  141.         lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
  142.         lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
  143.         lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
  144.         lp->scode = scode;
  145. lp->base = va;
  146.         ether_setup(dev);
  147. printk(", irq %dn", lp->lance.irq);
  148. #ifdef MODULE
  149.         dev->ifindex = dev_new_index();
  150.         lp->next_module = root_hplance_dev;
  151.         root_hplance_dev = lp;
  152. #endif /* MODULE */
  153.         dio_config_board(scode);                  /* tell bus scanning code this one's taken */
  154.         return 0;
  155. }
  156. /* This is disgusting. We have to check the DIO status register for ack every
  157.  * time we read or write the LANCE registers.
  158.  */
  159. static void hplance_writerap(struct hplance_private *lp, unsigned short value)
  160. {
  161.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  162.         do {
  163.                 lp->lance.ll->rap = value;
  164.         } while ((hpregs->status & LE_ACK) == 0);
  165. }
  166. static void hplance_writerdp(struct hplance_private *lp, unsigned short value)
  167. {
  168.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  169.         do {
  170.                 lp->lance.ll->rdp = value;
  171.         } while ((hpregs->status & LE_ACK) == 0);
  172. }
  173. static unsigned short hplance_readrdp(struct hplance_private *lp)
  174. {
  175.         unsigned short val;
  176.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  177.         do {
  178.                 val = lp->lance.ll->rdp;
  179.         } while ((hpregs->status & LE_ACK) == 0);
  180.         return val;
  181. }
  182. static int hplance_open(struct net_device *dev)
  183. {
  184.         int status;
  185.         struct hplance_private *lp = (struct hplance_private *)dev->priv;
  186.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  187.         
  188.         status = lance_open(dev);                 /* call generic lance open code */
  189.         if (status)
  190.                 return status;
  191.         /* enable interrupts at board level. */
  192.         writeb(LE_IE, &(hpregs->status));
  193.         return 0;
  194. }
  195. static int hplance_close(struct net_device *dev)
  196. {
  197.         struct hplance_private *lp = (struct hplance_private *)dev->priv;
  198.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  199.         writeb(0,&(hpregs->status));              /* disable interrupts at boardlevel */
  200.         lance_close(dev);
  201.         return 0;
  202. }
  203. #ifdef MODULE
  204. MODULE_LICENSE("GPL");
  205. int init_module(void)
  206. {
  207.         root_lance_dev = NULL;
  208.         return hplance_probe(NULL);
  209. }
  210. void cleanup_module(void)
  211. {
  212.         /* Walk the chain of devices, unregistering them */
  213.         struct hplance_private *lp;
  214.         while (root_hplance_dev) {
  215.                 lp = root_hplance_dev->next_module;
  216.                 dio_unconfig_board(lp->scode);
  217.                 unregister_netdev(root_lance_dev->dev);
  218.                 kfree(root_lance_dev->dev);
  219.                 root_lance_dev = lp;
  220.         }
  221. }
  222. #endif /* MODULE */