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/init.h>
28#include <linux/if_arp.h>
29#include <net/arp.h>
30#include <linux/netdevice.h>
31#include <linux/skbuff.h>
32#include <linux/arcdevice.h>
33
34#define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n"
35
36
37static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev);
38static void rx(struct net_device *dev, int bufnum,
39	       struct archdr *pkthdr, int length);
40static int build_header(struct sk_buff *skb, unsigned short type,
41			uint8_t daddr);
42static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
43		      int bufnum);
44
45
46struct ArcProto rfc1051_proto =
47{
48	's',
49	XMTU - RFC1051_HDR_SIZE,
50	rx,
51	build_header,
52	prepare_tx
53};
54
55
56void __init arcnet_rfc1051_init(void)
57{
58	arc_proto_map[ARC_P_IP_RFC1051]
59	    = arc_proto_map[ARC_P_ARP_RFC1051]
60	    = &rfc1051_proto;
61
62	/* if someone else already owns the broadcast, we won't take it */
63	if (arc_bcast_proto == arc_proto_default)
64		arc_bcast_proto = &rfc1051_proto;
65
66}
67
68
69#ifdef MODULE
70
71MODULE_LICENSE("GPL");
72
73int __init init_module(void)
74{
75	printk(VERSION);
76	arcnet_rfc1051_init();
77	return 0;
78}
79
80void cleanup_module(void)
81{
82	arcnet_unregister_proto(&rfc1051_proto);
83}
84
85#endif				/* MODULE */
86
87
88/*
89 * Determine a packet's protocol ID.
90 *
91 * With ARCnet we have to convert everything to Ethernet-style stuff.
92 */
93static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev)
94{
95	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
96	struct archdr *pkt = (struct archdr *) skb->data;
97	struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
98	int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
99
100	/* Pull off the arcnet header. */
101	skb->mac.raw = skb->data;
102	skb_pull(skb, hdr_size);
103
104	if (pkt->hard.dest == 0)
105		skb->pkt_type = PACKET_BROADCAST;
106	else if (dev->flags & IFF_PROMISC) {
107		/* if we're not sending to ourselves :) */
108		if (pkt->hard.dest != dev->dev_addr[0])
109			skb->pkt_type = PACKET_OTHERHOST;
110	}
111	/* now return the protocol number */
112	switch (soft->proto) {
113	case ARC_P_IP_RFC1051:
114		return htons(ETH_P_IP);
115	case ARC_P_ARP_RFC1051:
116		return htons(ETH_P_ARP);
117
118	default:
119		lp->stats.rx_errors++;
120		lp->stats.rx_crc_errors++;
121		return 0;
122	}
123
124	return htons(ETH_P_IP);
125}
126
127
128/* packet receiver */
129static void rx(struct net_device *dev, int bufnum,
130	       struct archdr *pkthdr, int length)
131{
132	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
133	struct sk_buff *skb;
134	struct archdr *pkt = pkthdr;
135	int ofs;
136
137	BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
138
139	if (length >= MinTU)
140		ofs = 512 - length;
141	else
142		ofs = 256 - length;
143
144	skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
145	if (skb == NULL) {
146		BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
147		lp->stats.rx_dropped++;
148		return;
149	}
150	skb_put(skb, length + ARC_HDR_SIZE);
151	skb->dev = dev;
152
153	pkt = (struct archdr *) skb->data;
154
155	/* up to sizeof(pkt->soft) has already been copied from the card */
156	memcpy(pkt, pkthdr, sizeof(struct archdr));
157	if (length > sizeof(pkt->soft))
158		lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
159				      pkt->soft.raw + sizeof(pkt->soft),
160				      length - sizeof(pkt->soft));
161
162	BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
163
164	skb->protocol = type_trans(skb, dev);
165	netif_rx(skb);
166	dev->last_rx = jiffies;
167}
168
169
170/*
171 * Create the ARCnet hard/soft headers for RFC1051.
172 */
173static int build_header(struct sk_buff *skb, unsigned short type,
174			uint8_t daddr)
175{
176	struct net_device *dev = skb->dev;
177	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
178	int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
179	struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
180	struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
181
182	/* set the protocol ID according to RFC1051 */
183	switch (type) {
184	case ETH_P_IP:
185		soft->proto = ARC_P_IP_RFC1051;
186		break;
187	case ETH_P_ARP:
188		soft->proto = ARC_P_ARP_RFC1051;
189		break;
190	default:
191		BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n",
192		       type, type);
193		lp->stats.tx_errors++;
194		lp->stats.tx_aborted_errors++;
195		return 0;
196	}
197
198
199	/*
200	 * Set the source hardware address.
201	 *
202	 * This is pretty pointless for most purposes, but it can help in
203	 * debugging.  ARCnet does not allow us to change the source address in
204	 * the actual packet sent)
205	 */
206	pkt->hard.source = *dev->dev_addr;
207
208	/* see linux/net/ethernet/eth.c to see where I got the following */
209
210	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
211		pkt->hard.dest = 0;
212		return hdr_size;
213	}
214	/* otherwise, just fill it in and go! */
215	pkt->hard.dest = daddr;
216
217	return hdr_size;	/* success */
218}
219
220
221static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
222		      int bufnum)
223{
224	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
225	struct arc_hardware *hard = &pkt->hard;
226	int ofs;
227
228	BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
229	       lp->next_tx, lp->cur_tx, bufnum);
230
231	length -= ARC_HDR_SIZE;	/* hard header is not included in packet length */
232
233	if (length > XMTU) {
234		/* should never happen! other people already check for this. */
235		BUGMSG(D_NORMAL, "Bug!  prepare_tx with size %d (> %d)\n",
236		       length, XMTU);
237		length = XMTU;
238	}
239	if (length > MinTU) {
240		hard->offset[0] = 0;
241		hard->offset[1] = ofs = 512 - length;
242	} else if (length > MTU) {
243		hard->offset[0] = 0;
244		hard->offset[1] = ofs = 512 - length - 3;
245	} else
246		hard->offset[0] = ofs = 256 - length;
247
248	lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
249	lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
250
251	lp->lastload_dest = hard->dest;
252
253	return 1;		/* done */
254}
255