linux/drivers/net/arcnet/rfc1051.c
<<
>>
Prefs
   1/*
   2 * Linux ARCnet driver - RFC1051 ("simple" standard) packet encapsulation
   3 * 
   4 * Written 1994-1999 by Avery Pennarun.
   5 * Derived from skeleton.c by Donald Becker.
   6 *
   7 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com)
   8 *  for sponsoring the further development of this driver.
   9 *
  10 * **********************
  11 *
  12 * The original copyright of skeleton.c was as follows:
  13 *
  14 * skeleton.c Written 1993 by Donald Becker.
  15 * Copyright 1993 United States Government as represented by the
  16 * Director, National Security Agency.  This software may only be used
  17 * and distributed according to the terms of the GNU General Public License as
  18 * modified by SRC, incorporated herein by reference.
  19 *
  20 * **********************
  21 *
  22 * For more details, see drivers/net/arcnet.c
  23 *
  24 * **********************
  25 */
  26#include <linux/module.h>
  27#include <linux/gfp.h>
  28#include <linux/init.h>
  29#include <linux/if_arp.h>
  30#include <net/arp.h>
  31#include <linux/netdevice.h>
  32#include <linux/skbuff.h>
  33#include <linux/arcdevice.h>
  34
  35#define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n"
  36
  37
  38static __be16 type_trans(struct sk_buff *skb, struct net_device *dev);
  39static void rx(struct net_device *dev, int bufnum,
  40               struct archdr *pkthdr, int length);
  41static int build_header(struct sk_buff *skb, struct net_device *dev,
  42                        unsigned short type, uint8_t daddr);
  43static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
  44                      int bufnum);
  45
  46
  47static struct ArcProto rfc1051_proto =
  48{
  49        .suffix         = 's',
  50        .mtu            = XMTU - RFC1051_HDR_SIZE,
  51        .is_ip          = 1,
  52        .rx             = rx,
  53        .build_header   = build_header,
  54        .prepare_tx     = prepare_tx,
  55        .continue_tx    = NULL,
  56        .ack_tx         = NULL
  57};
  58
  59
  60static int __init arcnet_rfc1051_init(void)
  61{
  62        printk(VERSION);
  63
  64        arc_proto_map[ARC_P_IP_RFC1051]
  65            = arc_proto_map[ARC_P_ARP_RFC1051]
  66            = &rfc1051_proto;
  67
  68        /* if someone else already owns the broadcast, we won't take it */
  69        if (arc_bcast_proto == arc_proto_default)
  70                arc_bcast_proto = &rfc1051_proto;
  71
  72        return 0;
  73}
  74
  75static void __exit arcnet_rfc1051_exit(void)
  76{
  77        arcnet_unregister_proto(&rfc1051_proto);
  78}
  79
  80module_init(arcnet_rfc1051_init);
  81module_exit(arcnet_rfc1051_exit);
  82
  83MODULE_LICENSE("GPL");
  84
  85/*
  86 * Determine a packet's protocol ID.
  87 * 
  88 * With ARCnet we have to convert everything to Ethernet-style stuff.
  89 */
  90static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
  91{
  92        struct archdr *pkt = (struct archdr *) skb->data;
  93        struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
  94        int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
  95
  96        /* Pull off the arcnet header. */
  97        skb_reset_mac_header(skb);
  98        skb_pull(skb, hdr_size);
  99
 100        if (pkt->hard.dest == 0)
 101                skb->pkt_type = PACKET_BROADCAST;
 102        else if (dev->flags & IFF_PROMISC) {
 103                /* if we're not sending to ourselves :) */
 104                if (pkt->hard.dest != dev->dev_addr[0])
 105                        skb->pkt_type = PACKET_OTHERHOST;
 106        }
 107        /* now return the protocol number */
 108        switch (soft->proto) {
 109        case ARC_P_IP_RFC1051:
 110                return htons(ETH_P_IP);
 111        case ARC_P_ARP_RFC1051:
 112                return htons(ETH_P_ARP);
 113
 114        default:
 115                dev->stats.rx_errors++;
 116                dev->stats.rx_crc_errors++;
 117                return 0;
 118        }
 119
 120        return htons(ETH_P_IP);
 121}
 122
 123
 124/* packet receiver */
 125static void rx(struct net_device *dev, int bufnum,
 126               struct archdr *pkthdr, int length)
 127{
 128        struct arcnet_local *lp = netdev_priv(dev);
 129        struct sk_buff *skb;
 130        struct archdr *pkt = pkthdr;
 131        int ofs;
 132
 133        BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
 134
 135        if (length >= MinTU)
 136                ofs = 512 - length;
 137        else
 138                ofs = 256 - length;
 139
 140        skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
 141        if (skb == NULL) {
 142                BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
 143                dev->stats.rx_dropped++;
 144                return;
 145        }
 146        skb_put(skb, length + ARC_HDR_SIZE);
 147        skb->dev = dev;
 148
 149        pkt = (struct archdr *) skb->data;
 150
 151        /* up to sizeof(pkt->soft) has already been copied from the card */
 152        memcpy(pkt, pkthdr, sizeof(struct archdr));
 153        if (length > sizeof(pkt->soft))
 154                lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
 155                                      pkt->soft.raw + sizeof(pkt->soft),
 156                                      length - sizeof(pkt->soft));
 157
 158        BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
 159
 160        skb->protocol = type_trans(skb, dev);
 161        netif_rx(skb);
 162}
 163
 164
 165/*
 166 * Create the ARCnet hard/soft headers for RFC1051.
 167 */
 168static int build_header(struct sk_buff *skb, struct net_device *dev,
 169                        unsigned short type, uint8_t daddr)
 170{
 171        int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
 172        struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
 173        struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
 174
 175        /* set the protocol ID according to RFC1051 */
 176        switch (type) {
 177        case ETH_P_IP:
 178                soft->proto = ARC_P_IP_RFC1051;
 179                break;
 180        case ETH_P_ARP:
 181                soft->proto = ARC_P_ARP_RFC1051;
 182                break;
 183        default:
 184                BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n",
 185                       type, type);
 186                dev->stats.tx_errors++;
 187                dev->stats.tx_aborted_errors++;
 188                return 0;
 189        }
 190
 191
 192        /*
 193         * Set the source hardware address.
 194         *
 195         * This is pretty pointless for most purposes, but it can help in
 196         * debugging.  ARCnet does not allow us to change the source address in
 197         * the actual packet sent)
 198         */
 199        pkt->hard.source = *dev->dev_addr;
 200
 201        /* see linux/net/ethernet/eth.c to see where I got the following */
 202
 203        if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
 204                /* 
 205                 * FIXME: fill in the last byte of the dest ipaddr here to better
 206                 * comply with RFC1051 in "noarp" mode.
 207                 */
 208                pkt->hard.dest = 0;
 209                return hdr_size;
 210        }
 211        /* otherwise, just fill it in and go! */
 212        pkt->hard.dest = daddr;
 213
 214        return hdr_size;        /* success */
 215}
 216
 217
 218static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
 219                      int bufnum)
 220{
 221        struct arcnet_local *lp = netdev_priv(dev);
 222        struct arc_hardware *hard = &pkt->hard;
 223        int ofs;
 224
 225        BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
 226               lp->next_tx, lp->cur_tx, bufnum);
 227
 228        length -= ARC_HDR_SIZE; /* hard header is not included in packet length */
 229
 230        if (length > XMTU) {
 231                /* should never happen! other people already check for this. */
 232                BUGMSG(D_NORMAL, "Bug!  prepare_tx with size %d (> %d)\n",
 233                       length, XMTU);
 234                length = XMTU;
 235        }
 236        if (length > MinTU) {
 237                hard->offset[0] = 0;
 238                hard->offset[1] = ofs = 512 - length;
 239        } else if (length > MTU) {
 240                hard->offset[0] = 0;
 241                hard->offset[1] = ofs = 512 - length - 3;
 242        } else
 243                hard->offset[0] = ofs = 256 - length;
 244
 245        lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
 246        lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
 247
 248        lp->lastload_dest = hard->dest;
 249
 250        return 1;               /* done */
 251}
 252