1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 __be16 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, struct net_device *dev,
41 unsigned short type, uint8_t daddr);
42static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
43 int bufnum);
44
45
46static struct ArcProto rfc1051_proto =
47{
48 .suffix = 's',
49 .mtu = XMTU - RFC1051_HDR_SIZE,
50 .is_ip = 1,
51 .rx = rx,
52 .build_header = build_header,
53 .prepare_tx = prepare_tx,
54 .continue_tx = NULL,
55 .ack_tx = NULL
56};
57
58
59static int __init arcnet_rfc1051_init(void)
60{
61 printk(VERSION);
62
63 arc_proto_map[ARC_P_IP_RFC1051]
64 = arc_proto_map[ARC_P_ARP_RFC1051]
65 = &rfc1051_proto;
66
67
68 if (arc_bcast_proto == arc_proto_default)
69 arc_bcast_proto = &rfc1051_proto;
70
71 return 0;
72}
73
74static void __exit arcnet_rfc1051_exit(void)
75{
76 arcnet_unregister_proto(&rfc1051_proto);
77}
78
79module_init(arcnet_rfc1051_init);
80module_exit(arcnet_rfc1051_exit);
81
82MODULE_LICENSE("GPL");
83
84
85
86
87
88
89static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
90{
91 struct archdr *pkt = (struct archdr *) skb->data;
92 struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
93 int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
94
95
96 skb_reset_mac_header(skb);
97 skb_pull(skb, hdr_size);
98
99 if (pkt->hard.dest == 0)
100 skb->pkt_type = PACKET_BROADCAST;
101 else if (dev->flags & IFF_PROMISC) {
102
103 if (pkt->hard.dest != dev->dev_addr[0])
104 skb->pkt_type = PACKET_OTHERHOST;
105 }
106
107 switch (soft->proto) {
108 case ARC_P_IP_RFC1051:
109 return htons(ETH_P_IP);
110 case ARC_P_ARP_RFC1051:
111 return htons(ETH_P_ARP);
112
113 default:
114 dev->stats.rx_errors++;
115 dev->stats.rx_crc_errors++;
116 return 0;
117 }
118
119 return htons(ETH_P_IP);
120}
121
122
123
124static void rx(struct net_device *dev, int bufnum,
125 struct archdr *pkthdr, int length)
126{
127 struct arcnet_local *lp = netdev_priv(dev);
128 struct sk_buff *skb;
129 struct archdr *pkt = pkthdr;
130 int ofs;
131
132 BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length);
133
134 if (length >= MinTU)
135 ofs = 512 - length;
136 else
137 ofs = 256 - length;
138
139 skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC);
140 if (skb == NULL) {
141 BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
142 dev->stats.rx_dropped++;
143 return;
144 }
145 skb_put(skb, length + ARC_HDR_SIZE);
146 skb->dev = dev;
147
148 pkt = (struct archdr *) skb->data;
149
150
151 memcpy(pkt, pkthdr, sizeof(struct archdr));
152 if (length > sizeof(pkt->soft))
153 lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft),
154 pkt->soft.raw + sizeof(pkt->soft),
155 length - sizeof(pkt->soft));
156
157 BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
158
159 skb->protocol = type_trans(skb, dev);
160 netif_rx(skb);
161}
162
163
164
165
166
167static int build_header(struct sk_buff *skb, struct net_device *dev,
168 unsigned short type, uint8_t daddr)
169{
170 int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
171 struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
172 struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
173
174
175 switch (type) {
176 case ETH_P_IP:
177 soft->proto = ARC_P_IP_RFC1051;
178 break;
179 case ETH_P_ARP:
180 soft->proto = ARC_P_ARP_RFC1051;
181 break;
182 default:
183 BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n",
184 type, type);
185 dev->stats.tx_errors++;
186 dev->stats.tx_aborted_errors++;
187 return 0;
188 }
189
190
191
192
193
194
195
196
197
198 pkt->hard.source = *dev->dev_addr;
199
200
201
202 if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
203
204
205
206
207 pkt->hard.dest = 0;
208 return hdr_size;
209 }
210
211 pkt->hard.dest = daddr;
212
213 return hdr_size;
214}
215
216
217static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
218 int bufnum)
219{
220 struct arcnet_local *lp = netdev_priv(dev);
221 struct arc_hardware *hard = &pkt->hard;
222 int ofs;
223
224 BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",
225 lp->next_tx, lp->cur_tx, bufnum);
226
227 length -= ARC_HDR_SIZE;
228
229 if (length > XMTU) {
230
231 BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n",
232 length, XMTU);
233 length = XMTU;
234 }
235 if (length > MinTU) {
236 hard->offset[0] = 0;
237 hard->offset[1] = ofs = 512 - length;
238 } else if (length > MTU) {
239 hard->offset[0] = 0;
240 hard->offset[1] = ofs = 512 - length - 3;
241 } else
242 hard->offset[0] = ofs = 256 - length;
243
244 lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);
245 lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length);
246
247 lp->lastload_dest = hard->dest;
248
249 return 1;
250}
251