root/drivers/net/ethernet/amd/hplance.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hplance_init_one
  2. hplance_remove_one
  3. hplance_init
  4. hplance_writerap
  5. hplance_writerdp
  6. hplance_readrdp
  7. hplance_open
  8. hplance_close
  9. hplance_init_module
  10. hplance_cleanup_module

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* hplance.c  : the  Linux/hp300/lance ethernet driver
   3  *
   4  * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
   5  * Based on the Sun Lance driver and the NetBSD HP Lance driver
   6  * Uses the generic 7990.c LANCE code.
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/kernel.h>
  11 #include <linux/types.h>
  12 #include <linux/interrupt.h>
  13 #include <linux/ioport.h>
  14 #include <linux/string.h>
  15 #include <linux/delay.h>
  16 #include <linux/init.h>
  17 #include <linux/errno.h>
  18 /* Used for the temporal inet entries and routing */
  19 #include <linux/socket.h>
  20 #include <linux/route.h>
  21 #include <linux/dio.h>
  22 #include <linux/netdevice.h>
  23 #include <linux/etherdevice.h>
  24 #include <linux/skbuff.h>
  25 
  26 #include <asm/io.h>
  27 #include <asm/pgtable.h>
  28 
  29 #include "hplance.h"
  30 
  31 /* We have 16392 bytes of RAM for the init block and buffers. This places
  32  * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
  33  * buffers and 2 Tx buffers, it takes (8 + 2) * 1544 bytes.
  34  */
  35 #define LANCE_LOG_TX_BUFFERS 1
  36 #define LANCE_LOG_RX_BUFFERS 3
  37 
  38 #include "7990.h"                                 /* use generic LANCE code */
  39 
  40 /* Our private data structure */
  41 struct hplance_private {
  42         struct lance_private lance;
  43 };
  44 
  45 /* function prototypes... This is easy because all the grot is in the
  46  * generic LANCE support. All we have to support is probing for boards,
  47  * plus board-specific init, open and close actions.
  48  * Oh, and we need to tell the generic code how to read and write LANCE registers...
  49  */
  50 static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent);
  51 static void hplance_init(struct net_device *dev, struct dio_dev *d);
  52 static void hplance_remove_one(struct dio_dev *d);
  53 static void hplance_writerap(void *priv, unsigned short value);
  54 static void hplance_writerdp(void *priv, unsigned short value);
  55 static unsigned short hplance_readrdp(void *priv);
  56 static int hplance_open(struct net_device *dev);
  57 static int hplance_close(struct net_device *dev);
  58 
  59 static struct dio_device_id hplance_dio_tbl[] = {
  60         { DIO_ID_LAN },
  61         { 0 }
  62 };
  63 
  64 static struct dio_driver hplance_driver = {
  65         .name      = "hplance",
  66         .id_table  = hplance_dio_tbl,
  67         .probe     = hplance_init_one,
  68         .remove    = hplance_remove_one,
  69 };
  70 
  71 static const struct net_device_ops hplance_netdev_ops = {
  72         .ndo_open               = hplance_open,
  73         .ndo_stop               = hplance_close,
  74         .ndo_start_xmit         = lance_start_xmit,
  75         .ndo_set_rx_mode        = lance_set_multicast,
  76         .ndo_validate_addr      = eth_validate_addr,
  77         .ndo_set_mac_address    = eth_mac_addr,
  78 #ifdef CONFIG_NET_POLL_CONTROLLER
  79         .ndo_poll_controller    = lance_poll,
  80 #endif
  81 };
  82 
  83 /* Find all the HP Lance boards and initialise them... */
  84 static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent)
  85 {
  86         struct net_device *dev;
  87         int err = -ENOMEM;
  88 
  89         dev = alloc_etherdev(sizeof(struct hplance_private));
  90         if (!dev)
  91                 goto out;
  92 
  93         err = -EBUSY;
  94         if (!request_mem_region(dio_resource_start(d),
  95                                 dio_resource_len(d), d->name))
  96                 goto out_free_netdev;
  97 
  98         hplance_init(dev, d);
  99         err = register_netdev(dev);
 100         if (err)
 101                 goto out_release_mem_region;
 102 
 103         dio_set_drvdata(d, dev);
 104 
 105         printk(KERN_INFO "%s: %s; select code %d, addr %pM, irq %d\n",
 106                dev->name, d->name, d->scode, dev->dev_addr, d->ipl);
 107 
 108         return 0;
 109 
 110  out_release_mem_region:
 111         release_mem_region(dio_resource_start(d), dio_resource_len(d));
 112  out_free_netdev:
 113         free_netdev(dev);
 114  out:
 115         return err;
 116 }
 117 
 118 static void hplance_remove_one(struct dio_dev *d)
 119 {
 120         struct net_device *dev = dio_get_drvdata(d);
 121 
 122         unregister_netdev(dev);
 123         release_mem_region(dio_resource_start(d), dio_resource_len(d));
 124         free_netdev(dev);
 125 }
 126 
 127 /* Initialise a single lance board at the given DIO device */
 128 static void hplance_init(struct net_device *dev, struct dio_dev *d)
 129 {
 130         unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
 131         struct hplance_private *lp;
 132         int i;
 133 
 134         /* reset the board */
 135         out_8(va + DIO_IDOFF, 0xff);
 136         udelay(100);                              /* ariba! ariba! udelay! udelay! */
 137 
 138         /* Fill the dev fields */
 139         dev->base_addr = va;
 140         dev->netdev_ops = &hplance_netdev_ops;
 141         dev->dma = 0;
 142 
 143         for (i = 0; i < 6; i++) {
 144                 /* The NVRAM holds our ethernet address, one nibble per byte,
 145                  * at bytes NVRAMOFF+1,3,5,7,9...
 146                  */
 147                 dev->dev_addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
 148                         | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
 149         }
 150 
 151         lp = netdev_priv(dev);
 152         lp->lance.name = d->name;
 153         lp->lance.base = va;
 154         lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
 155         lp->lance.lance_init_block = NULL;              /* LANCE addr of same RAM */
 156         lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
 157         lp->lance.irq = d->ipl;
 158         lp->lance.writerap = hplance_writerap;
 159         lp->lance.writerdp = hplance_writerdp;
 160         lp->lance.readrdp = hplance_readrdp;
 161         lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
 162         lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
 163         lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
 164         lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
 165 }
 166 
 167 /* This is disgusting. We have to check the DIO status register for ack every
 168  * time we read or write the LANCE registers.
 169  */
 170 static void hplance_writerap(void *priv, unsigned short value)
 171 {
 172         struct lance_private *lp = (struct lance_private *)priv;
 173         do {
 174                 out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value);
 175         } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
 176 }
 177 
 178 static void hplance_writerdp(void *priv, unsigned short value)
 179 {
 180         struct lance_private *lp = (struct lance_private *)priv;
 181         do {
 182                 out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value);
 183         } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
 184 }
 185 
 186 static unsigned short hplance_readrdp(void *priv)
 187 {
 188         struct lance_private *lp = (struct lance_private *)priv;
 189         __u16 value;
 190         do {
 191                 value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP);
 192         } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
 193         return value;
 194 }
 195 
 196 static int hplance_open(struct net_device *dev)
 197 {
 198         int status;
 199         struct lance_private *lp = netdev_priv(dev);
 200 
 201         status = lance_open(dev);                 /* call generic lance open code */
 202         if (status)
 203                 return status;
 204         /* enable interrupts at board level. */
 205         out_8(lp->base + HPLANCE_STATUS, LE_IE);
 206 
 207         return 0;
 208 }
 209 
 210 static int hplance_close(struct net_device *dev)
 211 {
 212         struct lance_private *lp = netdev_priv(dev);
 213 
 214         out_8(lp->base + HPLANCE_STATUS, 0);    /* disable interrupts at boardlevel */
 215         lance_close(dev);
 216         return 0;
 217 }
 218 
 219 static int __init hplance_init_module(void)
 220 {
 221         return dio_register_driver(&hplance_driver);
 222 }
 223 
 224 static void __exit hplance_cleanup_module(void)
 225 {
 226         dio_unregister_driver(&hplance_driver);
 227 }
 228 
 229 module_init(hplance_init_module);
 230 module_exit(hplance_cleanup_module);
 231 
 232 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */