hplance.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:8k
源码类别:

Linux/Unix编程

开发平台:

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(void *priv, unsigned short value);
  53. static void hplance_writerdp(void *priv, unsigned short value);
  54. static unsigned short hplance_readrdp(void *priv);
  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.         void *va = dio_scodetoviraddr(scode);
  92.         struct hplance_private *lp;
  93.         int i;
  94.         
  95. #ifdef MODULE
  96. dev = init_etherdev(0, sizeof(struct hplance_private));
  97. if (!dev)
  98. return -ENOMEM;
  99. #else
  100. dev->priv = kmalloc(sizeof(struct hplance_private), GFP_KERNEL);
  101. if (dev->priv == NULL)
  102. return -ENOMEM;
  103. memset(dev->priv, 0, sizeof(struct hplance_private));
  104. #endif
  105. SET_MODULE_OWNER(dev);
  106.         printk("%s: %s; select code %d, addr", dev->name, name, scode);
  107.         /* reset the board */
  108.         out_8(va+DIO_IDOFF, 0xff);
  109.         udelay(100);                              /* ariba! ariba! udelay! udelay! */
  110.         /* Fill the dev fields */
  111.         dev->base_addr = (unsigned long)va;
  112.         dev->open = &hplance_open;
  113.         dev->stop = &hplance_close;
  114.         dev->hard_start_xmit = &lance_start_xmit;
  115.         dev->get_stats = &lance_get_stats;
  116.         dev->set_multicast_list = &lance_set_multicast;
  117.         dev->dma = 0;
  118.         
  119.         for (i=0; i<6; i++)
  120.         {
  121.                 /* The NVRAM holds our ethernet address, one nibble per byte,
  122.                  * at bytes NVRAMOFF+1,3,5,7,9...
  123.                  */
  124.                 dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
  125.                         | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
  126.                 printk("%c%2.2x", i == 0 ? ' ' : ':', dev->dev_addr[i]);
  127.         }
  128.         
  129.         lp = (struct hplance_private *)dev->priv;
  130.         lp->lance.name = (char*)name;                   /* discards const, shut up gcc */
  131.         lp->lance.ll = (struct lance_regs *)(va + HPLANCE_REGOFF);
  132.         lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
  133.         lp->lance.lance_init_block = 0;                 /* LANCE addr of same RAM */
  134.         lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
  135.         lp->lance.irq = dio_scodetoipl(scode);
  136.         lp->lance.writerap = hplance_writerap;
  137.         lp->lance.writerdp = hplance_writerdp;
  138.         lp->lance.readrdp = hplance_readrdp;
  139.         lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
  140.         lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
  141.         lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
  142.         lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
  143.         lp->scode = scode;
  144. lp->base = va;
  145.         ether_setup(dev);
  146. printk(", irq %dn", lp->lance.irq);
  147. #ifdef MODULE
  148.         dev->ifindex = dev_new_index();
  149.         lp->next_module = root_hplance_dev;
  150.         root_hplance_dev = lp;
  151. #endif /* MODULE */
  152.         dio_config_board(scode);                  /* tell bus scanning code this one's taken */
  153.         return 0;
  154. }
  155. /* This is disgusting. We have to check the DIO status register for ack every
  156.  * time we read or write the LANCE registers.
  157.  */
  158. static void hplance_writerap(void *priv, unsigned short value)
  159. {
  160. struct hplance_private *lp = (struct hplance_private *)priv;
  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(void *priv, unsigned short value)
  167. {
  168. struct hplance_private *lp = (struct hplance_private *)priv;
  169.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  170.         do {
  171.                 lp->lance.ll->rdp = value;
  172.         } while ((hpregs->status & LE_ACK) == 0);
  173. }
  174. static unsigned short hplance_readrdp(void *priv)
  175. {
  176.         unsigned short val;
  177. struct hplance_private *lp = (struct hplance_private *)priv;
  178.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  179.         do {
  180.                 val = lp->lance.ll->rdp;
  181.         } while ((hpregs->status & LE_ACK) == 0);
  182.         return val;
  183. }
  184. static int hplance_open(struct net_device *dev)
  185. {
  186.         int status;
  187.         struct hplance_private *lp = (struct hplance_private *)dev->priv;
  188.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  189.         
  190.         status = lance_open(dev);                 /* call generic lance open code */
  191.         if (status)
  192.                 return status;
  193.         /* enable interrupts at board level. */
  194.         out_8(&(hpregs->status), LE_IE);
  195.         return 0;
  196. }
  197. static int hplance_close(struct net_device *dev)
  198. {
  199.         struct hplance_private *lp = (struct hplance_private *)dev->priv;
  200.         struct hplance_reg *hpregs = (struct hplance_reg *)lp->base;
  201.         out_8(&(hpregs->status), 8);              /* disable interrupts at boardlevel */
  202.         lance_close(dev);
  203.         return 0;
  204. }
  205. #ifdef MODULE
  206. MODULE_LICENSE("GPL");
  207. int init_module(void)
  208. {
  209.         root_lance_dev = NULL;
  210.         return hplance_probe(NULL);
  211. }
  212. void cleanup_module(void)
  213. {
  214.         /* Walk the chain of devices, unregistering them */
  215.         struct hplance_private *lp;
  216.         while (root_hplance_dev) {
  217.                 lp = root_hplance_dev->next_module;
  218.                 dio_unconfig_board(lp->scode);
  219.                 unregister_netdev(root_lance_dev->dev);
  220.                 kfree(root_lance_dev->dev);
  221.                 root_lance_dev = lp;
  222.         }
  223. }
  224. #endif /* MODULE */