root/arch/m68k/emu/nfeth.c

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

DEFINITIONS

This source file includes following definitions.
  1. nfeth_open
  2. nfeth_stop
  3. recv_packet
  4. nfeth_interrupt
  5. nfeth_xmit
  6. nfeth_tx_timeout
  7. nfeth_probe
  8. nfeth_init
  9. nfeth_cleanup

   1 /*
   2  * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
   3  *
   4  * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
   5  *
   6  * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
   7  *
   8  * This software may be used and distributed according to the terms of
   9  * the GNU General Public License (GPL), incorporated herein by reference.
  10  */
  11 
  12 #define DRV_VERSION     "0.3"
  13 #define DRV_RELDATE     "10/12/2005"
  14 
  15 #define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
  16 
  17 #include <linux/netdevice.h>
  18 #include <linux/etherdevice.h>
  19 #include <linux/interrupt.h>
  20 #include <linux/module.h>
  21 #include <asm/natfeat.h>
  22 #include <asm/virtconvert.h>
  23 
  24 enum {
  25         GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */
  26         XIF_INTLEVEL,   /* no parameters, return Interrupt Level in d0 */
  27         XIF_IRQ,        /* acknowledge interrupt from host */
  28         XIF_START,      /* (ethX), called on 'ifup', start receiver thread */
  29         XIF_STOP,       /* (ethX), called on 'ifdown', stop the thread */
  30         XIF_READLENGTH, /* (ethX), return size of network data block to read */
  31         XIF_READBLOCK,  /* (ethX, buffer, size), read block of network data */
  32         XIF_WRITEBLOCK, /* (ethX, buffer, size), write block of network data */
  33         XIF_GET_MAC,    /* (ethX, buffer, size), return MAC HW addr in buffer */
  34         XIF_GET_IPHOST, /* (ethX, buffer, size), return IP address of host */
  35         XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */
  36         XIF_GET_NETMASK /* (ethX, buffer, size), return IP netmask */
  37 };
  38 
  39 #define MAX_UNIT        8
  40 
  41 /* These identify the driver base version and may not be removed. */
  42 static const char version[] =
  43         KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE
  44         " S.Opichal, M.Jurik, P.Stehlik\n"
  45         KERN_INFO " http://aranym.org/\n";
  46 
  47 MODULE_AUTHOR("Milan Jurik");
  48 MODULE_DESCRIPTION("Atari NFeth driver");
  49 MODULE_LICENSE("GPL");
  50 
  51 
  52 static long nfEtherID;
  53 static int nfEtherIRQ;
  54 
  55 struct nfeth_private {
  56         int ethX;
  57 };
  58 
  59 static struct net_device *nfeth_dev[MAX_UNIT];
  60 
  61 static int nfeth_open(struct net_device *dev)
  62 {
  63         struct nfeth_private *priv = netdev_priv(dev);
  64         int res;
  65 
  66         res = nf_call(nfEtherID + XIF_START, priv->ethX);
  67         netdev_dbg(dev, "%s: %d\n", __func__, res);
  68 
  69         /* Ready for data */
  70         netif_start_queue(dev);
  71 
  72         return 0;
  73 }
  74 
  75 static int nfeth_stop(struct net_device *dev)
  76 {
  77         struct nfeth_private *priv = netdev_priv(dev);
  78 
  79         /* No more data */
  80         netif_stop_queue(dev);
  81 
  82         nf_call(nfEtherID + XIF_STOP, priv->ethX);
  83 
  84         return 0;
  85 }
  86 
  87 /*
  88  * Read a packet out of the adapter and pass it to the upper layers
  89  */
  90 static inline void recv_packet(struct net_device *dev)
  91 {
  92         struct nfeth_private *priv = netdev_priv(dev);
  93         unsigned short pktlen;
  94         struct sk_buff *skb;
  95 
  96         /* read packet length (excluding 32 bit crc) */
  97         pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
  98 
  99         netdev_dbg(dev, "%s: %u\n", __func__, pktlen);
 100 
 101         if (!pktlen) {
 102                 netdev_dbg(dev, "%s: pktlen == 0\n", __func__);
 103                 dev->stats.rx_errors++;
 104                 return;
 105         }
 106 
 107         skb = dev_alloc_skb(pktlen + 2);
 108         if (!skb) {
 109                 netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n",
 110                            __func__);
 111                 dev->stats.rx_dropped++;
 112                 return;
 113         }
 114 
 115         skb->dev = dev;
 116         skb_reserve(skb, 2);            /* 16 Byte align  */
 117         skb_put(skb, pktlen);           /* make room */
 118         nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data),
 119                 pktlen);
 120 
 121         skb->protocol = eth_type_trans(skb, dev);
 122         netif_rx(skb);
 123         dev->stats.rx_packets++;
 124         dev->stats.rx_bytes += pktlen;
 125 
 126         /* and enqueue packet */
 127         return;
 128 }
 129 
 130 static irqreturn_t nfeth_interrupt(int irq, void *dev_id)
 131 {
 132         int i, m, mask;
 133 
 134         mask = nf_call(nfEtherID + XIF_IRQ, 0);
 135         for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
 136                 if (mask & m && nfeth_dev[i]) {
 137                         recv_packet(nfeth_dev[i]);
 138                         nf_call(nfEtherID + XIF_IRQ, m);
 139                 }
 140         }
 141         return IRQ_HANDLED;
 142 }
 143 
 144 static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
 145 {
 146         unsigned int len;
 147         char *data, shortpkt[ETH_ZLEN];
 148         struct nfeth_private *priv = netdev_priv(dev);
 149 
 150         data = skb->data;
 151         len = skb->len;
 152         if (len < ETH_ZLEN) {
 153                 memset(shortpkt, 0, ETH_ZLEN);
 154                 memcpy(shortpkt, data, len);
 155                 data = shortpkt;
 156                 len = ETH_ZLEN;
 157         }
 158 
 159         netdev_dbg(dev, "%s: send %u bytes\n", __func__, len);
 160         nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
 161                 len);
 162 
 163         dev->stats.tx_packets++;
 164         dev->stats.tx_bytes += len;
 165 
 166         dev_kfree_skb(skb);
 167         return 0;
 168 }
 169 
 170 static void nfeth_tx_timeout(struct net_device *dev)
 171 {
 172         dev->stats.tx_errors++;
 173         netif_wake_queue(dev);
 174 }
 175 
 176 static const struct net_device_ops nfeth_netdev_ops = {
 177         .ndo_open               = nfeth_open,
 178         .ndo_stop               = nfeth_stop,
 179         .ndo_start_xmit         = nfeth_xmit,
 180         .ndo_tx_timeout         = nfeth_tx_timeout,
 181         .ndo_validate_addr      = eth_validate_addr,
 182         .ndo_set_mac_address    = eth_mac_addr,
 183 };
 184 
 185 static struct net_device * __init nfeth_probe(int unit)
 186 {
 187         struct net_device *dev;
 188         struct nfeth_private *priv;
 189         char mac[ETH_ALEN], host_ip[32], local_ip[32];
 190         int err;
 191 
 192         if (!nf_call(nfEtherID + XIF_GET_MAC, unit, virt_to_phys(mac),
 193                      ETH_ALEN))
 194                 return NULL;
 195 
 196         dev = alloc_etherdev(sizeof(struct nfeth_private));
 197         if (!dev)
 198                 return NULL;
 199 
 200         dev->irq = nfEtherIRQ;
 201         dev->netdev_ops = &nfeth_netdev_ops;
 202 
 203         memcpy(dev->dev_addr, mac, ETH_ALEN);
 204 
 205         priv = netdev_priv(dev);
 206         priv->ethX = unit;
 207 
 208         err = register_netdev(dev);
 209         if (err) {
 210                 free_netdev(dev);
 211                 return NULL;
 212         }
 213 
 214         nf_call(nfEtherID + XIF_GET_IPHOST, unit,
 215                 virt_to_phys(host_ip), sizeof(host_ip));
 216         nf_call(nfEtherID + XIF_GET_IPATARI, unit,
 217                 virt_to_phys(local_ip), sizeof(local_ip));
 218 
 219         netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip,
 220                     local_ip, mac);
 221 
 222         return dev;
 223 }
 224 
 225 static int __init nfeth_init(void)
 226 {
 227         long ver;
 228         int error, i;
 229 
 230         nfEtherID = nf_get_id("ETHERNET");
 231         if (!nfEtherID)
 232                 return -ENODEV;
 233 
 234         ver = nf_call(nfEtherID + GET_VERSION);
 235         pr_info("API %lu\n", ver);
 236 
 237         nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
 238         error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
 239                             "eth emu", nfeth_interrupt);
 240         if (error) {
 241                 pr_err("request for irq %d failed %d", nfEtherIRQ, error);
 242                 return error;
 243         }
 244 
 245         for (i = 0; i < MAX_UNIT; i++)
 246                 nfeth_dev[i] = nfeth_probe(i);
 247 
 248         return 0;
 249 }
 250 
 251 static void __exit nfeth_cleanup(void)
 252 {
 253         int i;
 254 
 255         for (i = 0; i < MAX_UNIT; i++) {
 256                 if (nfeth_dev[i]) {
 257                         unregister_netdev(nfeth_dev[0]);
 258                         free_netdev(nfeth_dev[0]);
 259                 }
 260         }
 261         free_irq(nfEtherIRQ, nfeth_interrupt);
 262 }
 263 
 264 module_init(nfeth_init);
 265 module_exit(nfeth_cleanup);

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