diff options
Diffstat (limited to 'drivers/net/arcnet/arcnet.c')
-rw-r--r-- | drivers/net/arcnet/arcnet.c | 1102 |
1 files changed, 1102 insertions, 0 deletions
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c new file mode 100644 index 000000000000..4f9f69e22c1b --- /dev/null +++ b/drivers/net/arcnet/arcnet.c | |||
@@ -0,0 +1,1102 @@ | |||
1 | /* | ||
2 | * Linux ARCnet driver - device-independent routines | ||
3 | * | ||
4 | * Written 1997 by David Woodhouse. | ||
5 | * Written 1994-1999 by Avery Pennarun. | ||
6 | * Written 1999-2000 by Martin Mares <mj@ucw.cz>. | ||
7 | * Derived from skeleton.c by Donald Becker. | ||
8 | * | ||
9 | * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) | ||
10 | * for sponsoring the further development of this driver. | ||
11 | * | ||
12 | * ********************** | ||
13 | * | ||
14 | * The original copyright was as follows: | ||
15 | * | ||
16 | * skeleton.c Written 1993 by Donald Becker. | ||
17 | * Copyright 1993 United States Government as represented by the | ||
18 | * Director, National Security Agency. This software may only be used | ||
19 | * and distributed according to the terms of the GNU General Public License as | ||
20 | * modified by SRC, incorporated herein by reference. | ||
21 | * | ||
22 | * ********************** | ||
23 | * | ||
24 | * The change log is now in a file called ChangeLog in this directory. | ||
25 | * | ||
26 | * Sources: | ||
27 | * - Crynwr arcnet.com/arcether.com packet drivers. | ||
28 | * - arcnet.c v0.00 dated 1/1/94 and apparently by | ||
29 | * Donald Becker - it didn't work :) | ||
30 | * - skeleton.c v0.05 dated 11/16/93 by Donald Becker | ||
31 | * (from Linux Kernel 1.1.45) | ||
32 | * - RFC's 1201 and 1051 - re: TCP/IP over ARCnet | ||
33 | * - The official ARCnet COM9026 data sheets (!) thanks to | ||
34 | * Ken Cornetet <kcornete@nyx10.cs.du.edu> | ||
35 | * - The official ARCnet COM20020 data sheets. | ||
36 | * - Information on some more obscure ARCnet controller chips, thanks | ||
37 | * to the nice people at SMSC. | ||
38 | * - net/inet/eth.c (from kernel 1.1.50) for header-building info. | ||
39 | * - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su> | ||
40 | * - Textual information and more alternate source from Joachim Koenig | ||
41 | * <jojo@repas.de> | ||
42 | */ | ||
43 | |||
44 | #define VERSION "arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al.\n" | ||
45 | |||
46 | #include <linux/module.h> | ||
47 | #include <linux/config.h> | ||
48 | #include <linux/types.h> | ||
49 | #include <linux/delay.h> | ||
50 | #include <linux/netdevice.h> | ||
51 | #include <linux/if_arp.h> | ||
52 | #include <net/arp.h> | ||
53 | #include <linux/init.h> | ||
54 | #include <linux/arcdevice.h> | ||
55 | |||
56 | /* "do nothing" functions for protocol drivers */ | ||
57 | static void null_rx(struct net_device *dev, int bufnum, | ||
58 | struct archdr *pkthdr, int length); | ||
59 | static int null_build_header(struct sk_buff *skb, struct net_device *dev, | ||
60 | unsigned short type, uint8_t daddr); | ||
61 | static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, | ||
62 | int length, int bufnum); | ||
63 | |||
64 | |||
65 | /* | ||
66 | * one ArcProto per possible proto ID. None of the elements of | ||
67 | * arc_proto_map are allowed to be NULL; they will get set to | ||
68 | * arc_proto_default instead. It also must not be NULL; if you would like | ||
69 | * to set it to NULL, set it to &arc_proto_null instead. | ||
70 | */ | ||
71 | struct ArcProto *arc_proto_map[256], *arc_proto_default, | ||
72 | *arc_bcast_proto, *arc_raw_proto; | ||
73 | |||
74 | struct ArcProto arc_proto_null = | ||
75 | { | ||
76 | .suffix = '?', | ||
77 | .mtu = XMTU, | ||
78 | .is_ip = 0, | ||
79 | .rx = null_rx, | ||
80 | .build_header = null_build_header, | ||
81 | .prepare_tx = null_prepare_tx, | ||
82 | .continue_tx = NULL, | ||
83 | .ack_tx = NULL | ||
84 | }; | ||
85 | |||
86 | /* Exported function prototypes */ | ||
87 | int arcnet_debug = ARCNET_DEBUG; | ||
88 | |||
89 | EXPORT_SYMBOL(arc_proto_map); | ||
90 | EXPORT_SYMBOL(arc_proto_default); | ||
91 | EXPORT_SYMBOL(arc_bcast_proto); | ||
92 | EXPORT_SYMBOL(arc_raw_proto); | ||
93 | EXPORT_SYMBOL(arc_proto_null); | ||
94 | EXPORT_SYMBOL(arcnet_unregister_proto); | ||
95 | EXPORT_SYMBOL(arcnet_debug); | ||
96 | EXPORT_SYMBOL(alloc_arcdev); | ||
97 | EXPORT_SYMBOL(arcnet_interrupt); | ||
98 | |||
99 | /* Internal function prototypes */ | ||
100 | static int arcnet_open(struct net_device *dev); | ||
101 | static int arcnet_close(struct net_device *dev); | ||
102 | static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev); | ||
103 | static void arcnet_timeout(struct net_device *dev); | ||
104 | static int arcnet_header(struct sk_buff *skb, struct net_device *dev, | ||
105 | unsigned short type, void *daddr, void *saddr, | ||
106 | unsigned len); | ||
107 | static int arcnet_rebuild_header(struct sk_buff *skb); | ||
108 | static struct net_device_stats *arcnet_get_stats(struct net_device *dev); | ||
109 | static int go_tx(struct net_device *dev); | ||
110 | |||
111 | static int debug = ARCNET_DEBUG; | ||
112 | module_param(debug, int, 0); | ||
113 | MODULE_LICENSE("GPL"); | ||
114 | |||
115 | static int __init arcnet_init(void) | ||
116 | { | ||
117 | int count; | ||
118 | |||
119 | arcnet_debug = debug; | ||
120 | |||
121 | printk(VERSION); | ||
122 | |||
123 | #ifdef ALPHA_WARNING | ||
124 | BUGLVL(D_EXTRA) { | ||
125 | printk("arcnet: ***\n" | ||
126 | "arcnet: * Read arcnet.txt for important release notes!\n" | ||
127 | "arcnet: *\n" | ||
128 | "arcnet: * This is an ALPHA version! (Last stable release: v3.02) E-mail\n" | ||
129 | "arcnet: * me if you have any questions, comments, or bug reports.\n" | ||
130 | "arcnet: ***\n"); | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | /* initialize the protocol map */ | ||
135 | arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null; | ||
136 | for (count = 0; count < 256; count++) | ||
137 | arc_proto_map[count] = arc_proto_default; | ||
138 | |||
139 | BUGLVL(D_DURING) | ||
140 | printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", | ||
141 | sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), | ||
142 | sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), | ||
143 | sizeof(struct archdr)); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void __exit arcnet_exit(void) | ||
149 | { | ||
150 | } | ||
151 | |||
152 | module_init(arcnet_init); | ||
153 | module_exit(arcnet_exit); | ||
154 | |||
155 | /* | ||
156 | * Dump the contents of an sk_buff | ||
157 | */ | ||
158 | #if ARCNET_DEBUG_MAX & D_SKB | ||
159 | void arcnet_dump_skb(struct net_device *dev, | ||
160 | struct sk_buff *skb, char *desc) | ||
161 | { | ||
162 | int i; | ||
163 | |||
164 | printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc); | ||
165 | for (i = 0; i < skb->len; i++) { | ||
166 | if (i % 16 == 0) | ||
167 | printk("\n" KERN_DEBUG "[%04X] ", i); | ||
168 | printk("%02X ", ((u_char *) skb->data)[i]); | ||
169 | } | ||
170 | printk("\n"); | ||
171 | } | ||
172 | |||
173 | EXPORT_SYMBOL(arcnet_dump_skb); | ||
174 | #endif | ||
175 | |||
176 | |||
177 | /* | ||
178 | * Dump the contents of an ARCnet buffer | ||
179 | */ | ||
180 | #if (ARCNET_DEBUG_MAX & (D_RX | D_TX)) | ||
181 | void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, | ||
182 | int take_arcnet_lock) | ||
183 | { | ||
184 | struct arcnet_local *lp = dev->priv; | ||
185 | int i, length; | ||
186 | unsigned long flags = 0; | ||
187 | static uint8_t buf[512]; | ||
188 | |||
189 | /* hw.copy_from_card expects IRQ context so take the IRQ lock | ||
190 | to keep it single threaded */ | ||
191 | if(take_arcnet_lock) | ||
192 | spin_lock_irqsave(&lp->lock, flags); | ||
193 | |||
194 | lp->hw.copy_from_card(dev, bufnum, 0, buf, 512); | ||
195 | if(take_arcnet_lock) | ||
196 | spin_unlock_irqrestore(&lp->lock, flags); | ||
197 | |||
198 | /* if the offset[0] byte is nonzero, this is a 256-byte packet */ | ||
199 | length = (buf[2] ? 256 : 512); | ||
200 | |||
201 | printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc); | ||
202 | for (i = 0; i < length; i++) { | ||
203 | if (i % 16 == 0) | ||
204 | printk("\n" KERN_DEBUG "[%04X] ", i); | ||
205 | printk("%02X ", buf[i]); | ||
206 | } | ||
207 | printk("\n"); | ||
208 | |||
209 | } | ||
210 | |||
211 | EXPORT_SYMBOL(arcnet_dump_packet); | ||
212 | #endif | ||
213 | |||
214 | |||
215 | /* | ||
216 | * Unregister a protocol driver from the arc_proto_map. Protocol drivers | ||
217 | * are responsible for registering themselves, but the unregister routine | ||
218 | * is pretty generic so we'll do it here. | ||
219 | */ | ||
220 | void arcnet_unregister_proto(struct ArcProto *proto) | ||
221 | { | ||
222 | int count; | ||
223 | |||
224 | if (arc_proto_default == proto) | ||
225 | arc_proto_default = &arc_proto_null; | ||
226 | if (arc_bcast_proto == proto) | ||
227 | arc_bcast_proto = arc_proto_default; | ||
228 | if (arc_raw_proto == proto) | ||
229 | arc_raw_proto = arc_proto_default; | ||
230 | |||
231 | for (count = 0; count < 256; count++) { | ||
232 | if (arc_proto_map[count] == proto) | ||
233 | arc_proto_map[count] = arc_proto_default; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | |||
238 | /* | ||
239 | * Add a buffer to the queue. Only the interrupt handler is allowed to do | ||
240 | * this, unless interrupts are disabled. | ||
241 | * | ||
242 | * Note: we don't check for a full queue, since there aren't enough buffers | ||
243 | * to more than fill it. | ||
244 | */ | ||
245 | static void release_arcbuf(struct net_device *dev, int bufnum) | ||
246 | { | ||
247 | struct arcnet_local *lp = dev->priv; | ||
248 | int i; | ||
249 | |||
250 | lp->buf_queue[lp->first_free_buf++] = bufnum; | ||
251 | lp->first_free_buf %= 5; | ||
252 | |||
253 | BUGLVL(D_DURING) { | ||
254 | BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", | ||
255 | bufnum); | ||
256 | for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) | ||
257 | BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); | ||
258 | BUGMSG2(D_DURING, "\n"); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | |||
263 | /* | ||
264 | * Get a buffer from the queue. If this returns -1, there are no buffers | ||
265 | * available. | ||
266 | */ | ||
267 | static int get_arcbuf(struct net_device *dev) | ||
268 | { | ||
269 | struct arcnet_local *lp = dev->priv; | ||
270 | int buf = -1, i; | ||
271 | |||
272 | if (!atomic_dec_and_test(&lp->buf_lock)) { | ||
273 | /* already in this function */ | ||
274 | BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", | ||
275 | lp->buf_lock.counter); | ||
276 | } | ||
277 | else { /* we can continue */ | ||
278 | if (lp->next_buf >= 5) | ||
279 | lp->next_buf -= 5; | ||
280 | |||
281 | if (lp->next_buf == lp->first_free_buf) | ||
282 | BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n"); | ||
283 | else { | ||
284 | buf = lp->buf_queue[lp->next_buf++]; | ||
285 | lp->next_buf %= 5; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | |||
290 | BUGLVL(D_DURING) { | ||
291 | BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); | ||
292 | for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) | ||
293 | BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); | ||
294 | BUGMSG2(D_DURING, "\n"); | ||
295 | } | ||
296 | |||
297 | atomic_inc(&lp->buf_lock); | ||
298 | return buf; | ||
299 | } | ||
300 | |||
301 | |||
302 | static int choose_mtu(void) | ||
303 | { | ||
304 | int count, mtu = 65535; | ||
305 | |||
306 | /* choose the smallest MTU of all available encaps */ | ||
307 | for (count = 0; count < 256; count++) { | ||
308 | if (arc_proto_map[count] != &arc_proto_null | ||
309 | && arc_proto_map[count]->mtu < mtu) { | ||
310 | mtu = arc_proto_map[count]->mtu; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | return mtu == 65535 ? XMTU : mtu; | ||
315 | } | ||
316 | |||
317 | |||
318 | /* Setup a struct device for ARCnet. */ | ||
319 | static void arcdev_setup(struct net_device *dev) | ||
320 | { | ||
321 | dev->type = ARPHRD_ARCNET; | ||
322 | dev->hard_header_len = sizeof(struct archdr); | ||
323 | dev->mtu = choose_mtu(); | ||
324 | |||
325 | dev->addr_len = ARCNET_ALEN; | ||
326 | dev->tx_queue_len = 100; | ||
327 | dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */ | ||
328 | dev->watchdog_timeo = TX_TIMEOUT; | ||
329 | |||
330 | /* New-style flags. */ | ||
331 | dev->flags = IFF_BROADCAST; | ||
332 | |||
333 | /* | ||
334 | * Put in this stuff here, so we don't have to export the symbols to | ||
335 | * the chipset drivers. | ||
336 | */ | ||
337 | dev->open = arcnet_open; | ||
338 | dev->stop = arcnet_close; | ||
339 | dev->hard_start_xmit = arcnet_send_packet; | ||
340 | dev->tx_timeout = arcnet_timeout; | ||
341 | dev->get_stats = arcnet_get_stats; | ||
342 | dev->hard_header = arcnet_header; | ||
343 | dev->rebuild_header = arcnet_rebuild_header; | ||
344 | } | ||
345 | |||
346 | struct net_device *alloc_arcdev(char *name) | ||
347 | { | ||
348 | struct net_device *dev; | ||
349 | |||
350 | dev = alloc_netdev(sizeof(struct arcnet_local), | ||
351 | name && *name ? name : "arc%d", arcdev_setup); | ||
352 | if(dev) { | ||
353 | struct arcnet_local *lp = (struct arcnet_local *) dev->priv; | ||
354 | spin_lock_init(&lp->lock); | ||
355 | } | ||
356 | |||
357 | return dev; | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * Open/initialize the board. This is called sometime after booting when | ||
362 | * the 'ifconfig' program is run. | ||
363 | * | ||
364 | * This routine should set everything up anew at each open, even registers | ||
365 | * that "should" only need to be set once at boot, so that there is | ||
366 | * non-reboot way to recover if something goes wrong. | ||
367 | */ | ||
368 | static int arcnet_open(struct net_device *dev) | ||
369 | { | ||
370 | struct arcnet_local *lp = dev->priv; | ||
371 | int count, newmtu, error; | ||
372 | |||
373 | BUGMSG(D_INIT,"opened."); | ||
374 | |||
375 | if (!try_module_get(lp->hw.owner)) | ||
376 | return -ENODEV; | ||
377 | |||
378 | BUGLVL(D_PROTO) { | ||
379 | int count; | ||
380 | BUGMSG(D_PROTO, "protocol map (default is '%c'): ", | ||
381 | arc_proto_default->suffix); | ||
382 | for (count = 0; count < 256; count++) | ||
383 | BUGMSG2(D_PROTO, "%c", arc_proto_map[count]->suffix); | ||
384 | BUGMSG2(D_PROTO, "\n"); | ||
385 | } | ||
386 | |||
387 | |||
388 | BUGMSG(D_INIT, "arcnet_open: resetting card.\n"); | ||
389 | |||
390 | /* try to put the card in a defined state - if it fails the first | ||
391 | * time, actually reset it. | ||
392 | */ | ||
393 | error = -ENODEV; | ||
394 | if (ARCRESET(0) && ARCRESET(1)) | ||
395 | goto out_module_put; | ||
396 | |||
397 | newmtu = choose_mtu(); | ||
398 | if (newmtu < dev->mtu) | ||
399 | dev->mtu = newmtu; | ||
400 | |||
401 | BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu); | ||
402 | |||
403 | /* autodetect the encapsulation for each host. */ | ||
404 | memset(lp->default_proto, 0, sizeof(lp->default_proto)); | ||
405 | |||
406 | /* the broadcast address is special - use the 'bcast' protocol */ | ||
407 | for (count = 0; count < 256; count++) { | ||
408 | if (arc_proto_map[count] == arc_bcast_proto) { | ||
409 | lp->default_proto[0] = count; | ||
410 | break; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | /* initialize buffers */ | ||
415 | atomic_set(&lp->buf_lock, 1); | ||
416 | |||
417 | lp->next_buf = lp->first_free_buf = 0; | ||
418 | release_arcbuf(dev, 0); | ||
419 | release_arcbuf(dev, 1); | ||
420 | release_arcbuf(dev, 2); | ||
421 | release_arcbuf(dev, 3); | ||
422 | lp->cur_tx = lp->next_tx = -1; | ||
423 | lp->cur_rx = -1; | ||
424 | |||
425 | lp->rfc1201.sequence = 1; | ||
426 | |||
427 | /* bring up the hardware driver */ | ||
428 | if (lp->hw.open) | ||
429 | lp->hw.open(dev); | ||
430 | |||
431 | if (dev->dev_addr[0] == 0) | ||
432 | BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved " | ||
433 | "for broadcasts!\n"); | ||
434 | else if (dev->dev_addr[0] == 255) | ||
435 | BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " | ||
436 | "DOS networking programs!\n"); | ||
437 | |||
438 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
439 | if (ASTATUS() & RESETflag) { | ||
440 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
441 | ACOMMAND(CFLAGScmd | RESETclear); | ||
442 | } | ||
443 | |||
444 | |||
445 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
446 | /* make sure we're ready to receive IRQ's. */ | ||
447 | AINTMASK(0); | ||
448 | udelay(1); /* give it time to set the mask before | ||
449 | * we reset it again. (may not even be | ||
450 | * necessary) | ||
451 | */ | ||
452 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
453 | lp->intmask = NORXflag | RECONflag; | ||
454 | AINTMASK(lp->intmask); | ||
455 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
456 | |||
457 | netif_start_queue(dev); | ||
458 | |||
459 | return 0; | ||
460 | |||
461 | out_module_put: | ||
462 | module_put(lp->hw.owner); | ||
463 | return error; | ||
464 | } | ||
465 | |||
466 | |||
467 | /* The inverse routine to arcnet_open - shuts down the card. */ | ||
468 | static int arcnet_close(struct net_device *dev) | ||
469 | { | ||
470 | struct arcnet_local *lp = dev->priv; | ||
471 | |||
472 | netif_stop_queue(dev); | ||
473 | |||
474 | /* flush TX and disable RX */ | ||
475 | AINTMASK(0); | ||
476 | ACOMMAND(NOTXcmd); /* stop transmit */ | ||
477 | ACOMMAND(NORXcmd); /* disable receive */ | ||
478 | mdelay(1); | ||
479 | |||
480 | /* shut down the card */ | ||
481 | lp->hw.close(dev); | ||
482 | module_put(lp->hw.owner); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | |||
487 | static int arcnet_header(struct sk_buff *skb, struct net_device *dev, | ||
488 | unsigned short type, void *daddr, void *saddr, | ||
489 | unsigned len) | ||
490 | { | ||
491 | struct arcnet_local *lp = dev->priv; | ||
492 | uint8_t _daddr, proto_num; | ||
493 | struct ArcProto *proto; | ||
494 | |||
495 | BUGMSG(D_DURING, | ||
496 | "create header from %d to %d; protocol %d (%Xh); size %u.\n", | ||
497 | saddr ? *(uint8_t *) saddr : -1, | ||
498 | daddr ? *(uint8_t *) daddr : -1, | ||
499 | type, type, len); | ||
500 | |||
501 | if (skb->len!=0 && len != skb->len) | ||
502 | BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", | ||
503 | skb->len, len); | ||
504 | |||
505 | |||
506 | /* Type is host order - ? */ | ||
507 | if(type == ETH_P_ARCNET) { | ||
508 | proto = arc_raw_proto; | ||
509 | BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n",proto->suffix); | ||
510 | _daddr = daddr ? *(uint8_t *) daddr : 0; | ||
511 | } | ||
512 | else if (!daddr) { | ||
513 | /* | ||
514 | * if the dest addr isn't provided, we can't choose an encapsulation! | ||
515 | * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a | ||
516 | * real header when we do rebuild_header. | ||
517 | */ | ||
518 | *(uint16_t *) skb_push(skb, 2) = type; | ||
519 | if (skb->nh.raw - skb->mac.raw != 2) | ||
520 | BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n", | ||
521 | (int)(skb->nh.raw - skb->mac.raw)); | ||
522 | return -2; /* return error -- can't transmit yet! */ | ||
523 | } | ||
524 | else { | ||
525 | /* otherwise, we can just add the header as usual. */ | ||
526 | _daddr = *(uint8_t *) daddr; | ||
527 | proto_num = lp->default_proto[_daddr]; | ||
528 | proto = arc_proto_map[proto_num]; | ||
529 | BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", | ||
530 | proto_num, proto->suffix); | ||
531 | if (proto == &arc_proto_null && arc_bcast_proto != proto) { | ||
532 | BUGMSG(D_DURING, "actually, let's use '%c' instead.\n", | ||
533 | arc_bcast_proto->suffix); | ||
534 | proto = arc_bcast_proto; | ||
535 | } | ||
536 | } | ||
537 | return proto->build_header(skb, dev, type, _daddr); | ||
538 | } | ||
539 | |||
540 | |||
541 | /* | ||
542 | * Rebuild the ARCnet hard header. This is called after an ARP (or in the | ||
543 | * future other address resolution) has completed on this sk_buff. We now | ||
544 | * let ARP fill in the destination field. | ||
545 | */ | ||
546 | static int arcnet_rebuild_header(struct sk_buff *skb) | ||
547 | { | ||
548 | struct net_device *dev = skb->dev; | ||
549 | struct arcnet_local *lp = dev->priv; | ||
550 | int status = 0; /* default is failure */ | ||
551 | unsigned short type; | ||
552 | uint8_t daddr=0; | ||
553 | struct ArcProto *proto; | ||
554 | |||
555 | if (skb->nh.raw - skb->mac.raw != 2) { | ||
556 | BUGMSG(D_NORMAL, | ||
557 | "rebuild_header: shouldn't be here! (hdrsize=%d)\n", | ||
558 | (int)(skb->nh.raw - skb->mac.raw)); | ||
559 | return 0; | ||
560 | } | ||
561 | type = *(uint16_t *) skb_pull(skb, 2); | ||
562 | BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type); | ||
563 | |||
564 | if (type == ETH_P_IP) { | ||
565 | #ifdef CONFIG_INET | ||
566 | BUGMSG(D_DURING, "rebuild header for ethernet protocol %Xh\n", type); | ||
567 | status = arp_find(&daddr, skb) ? 1 : 0; | ||
568 | BUGMSG(D_DURING, " rebuilt: dest is %d; protocol %Xh\n", | ||
569 | daddr, type); | ||
570 | #endif | ||
571 | } else { | ||
572 | BUGMSG(D_NORMAL, | ||
573 | "I don't understand ethernet protocol %Xh addresses!\n", type); | ||
574 | lp->stats.tx_errors++; | ||
575 | lp->stats.tx_aborted_errors++; | ||
576 | } | ||
577 | |||
578 | /* if we couldn't resolve the address... give up. */ | ||
579 | if (!status) | ||
580 | return 0; | ||
581 | |||
582 | /* add the _real_ header this time! */ | ||
583 | proto = arc_proto_map[lp->default_proto[daddr]]; | ||
584 | proto->build_header(skb, dev, type, daddr); | ||
585 | |||
586 | return 1; /* success */ | ||
587 | } | ||
588 | |||
589 | |||
590 | |||
591 | /* Called by the kernel in order to transmit a packet. */ | ||
592 | static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) | ||
593 | { | ||
594 | struct arcnet_local *lp = dev->priv; | ||
595 | struct archdr *pkt; | ||
596 | struct arc_rfc1201 *soft; | ||
597 | struct ArcProto *proto; | ||
598 | int txbuf; | ||
599 | unsigned long flags; | ||
600 | int freeskb = 0; | ||
601 | |||
602 | BUGMSG(D_DURING, | ||
603 | "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", | ||
604 | ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol); | ||
605 | |||
606 | pkt = (struct archdr *) skb->data; | ||
607 | soft = &pkt->soft.rfc1201; | ||
608 | proto = arc_proto_map[soft->proto]; | ||
609 | |||
610 | BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", | ||
611 | skb->len, pkt->hard.dest); | ||
612 | BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); | ||
613 | |||
614 | /* fits in one packet? */ | ||
615 | if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) { | ||
616 | BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n"); | ||
617 | dev_kfree_skb(skb); | ||
618 | return 0; /* don't try again */ | ||
619 | } | ||
620 | |||
621 | /* We're busy transmitting a packet... */ | ||
622 | netif_stop_queue(dev); | ||
623 | |||
624 | spin_lock_irqsave(&lp->lock, flags); | ||
625 | AINTMASK(0); | ||
626 | |||
627 | txbuf = get_arcbuf(dev); | ||
628 | if (txbuf != -1) { | ||
629 | if (proto->prepare_tx(dev, pkt, skb->len, txbuf) && | ||
630 | !proto->ack_tx) { | ||
631 | /* done right away and we don't want to acknowledge | ||
632 | the package later - forget about it now */ | ||
633 | lp->stats.tx_bytes += skb->len; | ||
634 | freeskb = 1; | ||
635 | } else { | ||
636 | /* do it the 'split' way */ | ||
637 | lp->outgoing.proto = proto; | ||
638 | lp->outgoing.skb = skb; | ||
639 | lp->outgoing.pkt = pkt; | ||
640 | |||
641 | if (proto->continue_tx && | ||
642 | proto->continue_tx(dev, txbuf)) { | ||
643 | BUGMSG(D_NORMAL, | ||
644 | "bug! continue_tx finished the first time! " | ||
645 | "(proto='%c')\n", proto->suffix); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | lp->next_tx = txbuf; | ||
650 | } else { | ||
651 | freeskb = 1; | ||
652 | } | ||
653 | |||
654 | BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); | ||
655 | /* make sure we didn't ignore a TX IRQ while we were in here */ | ||
656 | AINTMASK(0); | ||
657 | |||
658 | BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); | ||
659 | lp->intmask |= TXFREEflag|EXCNAKflag; | ||
660 | AINTMASK(lp->intmask); | ||
661 | BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); | ||
662 | |||
663 | spin_unlock_irqrestore(&lp->lock, flags); | ||
664 | if (freeskb) { | ||
665 | dev_kfree_skb(skb); | ||
666 | } | ||
667 | return 0; /* no need to try again */ | ||
668 | } | ||
669 | |||
670 | |||
671 | /* | ||
672 | * Actually start transmitting a packet that was loaded into a buffer | ||
673 | * by prepare_tx. This should _only_ be called by the interrupt handler. | ||
674 | */ | ||
675 | static int go_tx(struct net_device *dev) | ||
676 | { | ||
677 | struct arcnet_local *lp = dev->priv; | ||
678 | |||
679 | BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n", | ||
680 | ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx); | ||
681 | |||
682 | if (lp->cur_tx != -1 || lp->next_tx == -1) | ||
683 | return 0; | ||
684 | |||
685 | BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0); | ||
686 | |||
687 | lp->cur_tx = lp->next_tx; | ||
688 | lp->next_tx = -1; | ||
689 | |||
690 | /* start sending */ | ||
691 | ACOMMAND(TXcmd | (lp->cur_tx << 3)); | ||
692 | |||
693 | dev->trans_start = jiffies; | ||
694 | lp->stats.tx_packets++; | ||
695 | lp->lasttrans_dest = lp->lastload_dest; | ||
696 | lp->lastload_dest = 0; | ||
697 | lp->excnak_pending = 0; | ||
698 | lp->intmask |= TXFREEflag|EXCNAKflag; | ||
699 | |||
700 | return 1; | ||
701 | } | ||
702 | |||
703 | |||
704 | /* Called by the kernel when transmit times out */ | ||
705 | static void arcnet_timeout(struct net_device *dev) | ||
706 | { | ||
707 | unsigned long flags; | ||
708 | struct arcnet_local *lp = dev->priv; | ||
709 | int status = ASTATUS(); | ||
710 | char *msg; | ||
711 | |||
712 | spin_lock_irqsave(&lp->lock, flags); | ||
713 | if (status & TXFREEflag) { /* transmit _DID_ finish */ | ||
714 | msg = " - missed IRQ?"; | ||
715 | } else { | ||
716 | msg = ""; | ||
717 | lp->stats.tx_aborted_errors++; | ||
718 | lp->timed_out = 1; | ||
719 | ACOMMAND(NOTXcmd | (lp->cur_tx << 3)); | ||
720 | } | ||
721 | lp->stats.tx_errors++; | ||
722 | |||
723 | /* make sure we didn't miss a TX or a EXC NAK IRQ */ | ||
724 | AINTMASK(0); | ||
725 | lp->intmask |= TXFREEflag|EXCNAKflag; | ||
726 | AINTMASK(lp->intmask); | ||
727 | |||
728 | spin_unlock_irqrestore(&lp->lock, flags); | ||
729 | |||
730 | if (jiffies - lp->last_timeout > 10*HZ) { | ||
731 | BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", | ||
732 | msg, status, lp->intmask, lp->lasttrans_dest); | ||
733 | lp->last_timeout = jiffies; | ||
734 | } | ||
735 | |||
736 | if (lp->cur_tx == -1) | ||
737 | netif_wake_queue(dev); | ||
738 | } | ||
739 | |||
740 | |||
741 | /* | ||
742 | * The typical workload of the driver: Handle the network interface | ||
743 | * interrupts. Establish which device needs attention, and call the correct | ||
744 | * chipset interrupt handler. | ||
745 | */ | ||
746 | irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
747 | { | ||
748 | struct net_device *dev = dev_id; | ||
749 | struct arcnet_local *lp; | ||
750 | int recbuf, status, diagstatus, didsomething, boguscount; | ||
751 | int retval = IRQ_NONE; | ||
752 | |||
753 | BUGMSG(D_DURING, "\n"); | ||
754 | |||
755 | BUGMSG(D_DURING, "in arcnet_interrupt\n"); | ||
756 | |||
757 | lp = dev->priv; | ||
758 | if (!lp) | ||
759 | BUG(); | ||
760 | |||
761 | spin_lock(&lp->lock); | ||
762 | |||
763 | /* | ||
764 | * RESET flag was enabled - if device is not running, we must clear it right | ||
765 | * away (but nothing else). | ||
766 | */ | ||
767 | if (!netif_running(dev)) { | ||
768 | if (ASTATUS() & RESETflag) | ||
769 | ACOMMAND(CFLAGScmd | RESETclear); | ||
770 | AINTMASK(0); | ||
771 | spin_unlock(&lp->lock); | ||
772 | return IRQ_HANDLED; | ||
773 | } | ||
774 | |||
775 | BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", | ||
776 | ASTATUS(), lp->intmask); | ||
777 | |||
778 | boguscount = 5; | ||
779 | do { | ||
780 | status = ASTATUS(); | ||
781 | diagstatus = (status >> 8) & 0xFF; | ||
782 | |||
783 | BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", | ||
784 | __FILE__,__LINE__,__FUNCTION__,status); | ||
785 | didsomething = 0; | ||
786 | |||
787 | /* | ||
788 | * RESET flag was enabled - card is resetting and if RX is | ||
789 | * disabled, it's NOT because we just got a packet. | ||
790 | * | ||
791 | * The card is in an undefined state. Clear it out and start over. | ||
792 | */ | ||
793 | if (status & RESETflag) { | ||
794 | BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status); | ||
795 | arcnet_close(dev); | ||
796 | arcnet_open(dev); | ||
797 | |||
798 | /* get out of the interrupt handler! */ | ||
799 | break; | ||
800 | } | ||
801 | /* | ||
802 | * RX is inhibited - we must have received something. Prepare to | ||
803 | * receive into the next buffer. | ||
804 | * | ||
805 | * We don't actually copy the received packet from the card until | ||
806 | * after the transmit handler runs (and possibly launches the next | ||
807 | * tx); this should improve latency slightly if we get both types | ||
808 | * of interrupts at once. | ||
809 | */ | ||
810 | recbuf = -1; | ||
811 | if (status & lp->intmask & NORXflag) { | ||
812 | recbuf = lp->cur_rx; | ||
813 | BUGMSG(D_DURING, "Buffer #%d: receive irq (status=%Xh)\n", | ||
814 | recbuf, status); | ||
815 | |||
816 | lp->cur_rx = get_arcbuf(dev); | ||
817 | if (lp->cur_rx != -1) { | ||
818 | BUGMSG(D_DURING, "enabling receive to buffer #%d\n", | ||
819 | lp->cur_rx); | ||
820 | ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts); | ||
821 | } | ||
822 | didsomething++; | ||
823 | } | ||
824 | |||
825 | if((diagstatus & EXCNAKflag)) { | ||
826 | BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", | ||
827 | diagstatus); | ||
828 | |||
829 | ACOMMAND(NOTXcmd); /* disable transmit */ | ||
830 | lp->excnak_pending = 1; | ||
831 | |||
832 | ACOMMAND(EXCNAKclear); | ||
833 | lp->intmask &= ~(EXCNAKflag); | ||
834 | didsomething++; | ||
835 | } | ||
836 | |||
837 | |||
838 | /* a transmit finished, and we're interested in it. */ | ||
839 | if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { | ||
840 | lp->intmask &= ~(TXFREEflag|EXCNAKflag); | ||
841 | |||
842 | BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); | ||
843 | |||
844 | if (lp->cur_tx != -1 && !lp->timed_out) { | ||
845 | if(!(status & TXACKflag)) { | ||
846 | if (lp->lasttrans_dest != 0) { | ||
847 | BUGMSG(D_EXTRA, | ||
848 | "transmit was not acknowledged! " | ||
849 | "(status=%Xh, dest=%02Xh)\n", | ||
850 | status, lp->lasttrans_dest); | ||
851 | lp->stats.tx_errors++; | ||
852 | lp->stats.tx_carrier_errors++; | ||
853 | } else { | ||
854 | BUGMSG(D_DURING, | ||
855 | "broadcast was not acknowledged; that's normal " | ||
856 | "(status=%Xh, dest=%02Xh)\n", | ||
857 | status, lp->lasttrans_dest); | ||
858 | } | ||
859 | } | ||
860 | |||
861 | if (lp->outgoing.proto && | ||
862 | lp->outgoing.proto->ack_tx) { | ||
863 | int ackstatus; | ||
864 | if(status & TXACKflag) | ||
865 | ackstatus=2; | ||
866 | else if(lp->excnak_pending) | ||
867 | ackstatus=1; | ||
868 | else | ||
869 | ackstatus=0; | ||
870 | |||
871 | lp->outgoing.proto | ||
872 | ->ack_tx(dev, ackstatus); | ||
873 | } | ||
874 | } | ||
875 | if (lp->cur_tx != -1) | ||
876 | release_arcbuf(dev, lp->cur_tx); | ||
877 | |||
878 | lp->cur_tx = -1; | ||
879 | lp->timed_out = 0; | ||
880 | didsomething++; | ||
881 | |||
882 | /* send another packet if there is one */ | ||
883 | go_tx(dev); | ||
884 | |||
885 | /* continue a split packet, if any */ | ||
886 | if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) { | ||
887 | int txbuf = get_arcbuf(dev); | ||
888 | if (txbuf != -1) { | ||
889 | if (lp->outgoing.proto->continue_tx(dev, txbuf)) { | ||
890 | /* that was the last segment */ | ||
891 | lp->stats.tx_bytes += lp->outgoing.skb->len; | ||
892 | if(!lp->outgoing.proto->ack_tx) | ||
893 | { | ||
894 | dev_kfree_skb_irq(lp->outgoing.skb); | ||
895 | lp->outgoing.proto = NULL; | ||
896 | } | ||
897 | } | ||
898 | lp->next_tx = txbuf; | ||
899 | } | ||
900 | } | ||
901 | /* inform upper layers of idleness, if necessary */ | ||
902 | if (lp->cur_tx == -1) | ||
903 | netif_wake_queue(dev); | ||
904 | } | ||
905 | /* now process the received packet, if any */ | ||
906 | if (recbuf != -1) { | ||
907 | BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0); | ||
908 | |||
909 | arcnet_rx(dev, recbuf); | ||
910 | release_arcbuf(dev, recbuf); | ||
911 | |||
912 | didsomething++; | ||
913 | } | ||
914 | if (status & lp->intmask & RECONflag) { | ||
915 | ACOMMAND(CFLAGScmd | CONFIGclear); | ||
916 | lp->stats.tx_carrier_errors++; | ||
917 | |||
918 | BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n", | ||
919 | status); | ||
920 | |||
921 | /* is the RECON info empty or old? */ | ||
922 | if (!lp->first_recon || !lp->last_recon || | ||
923 | jiffies - lp->last_recon > HZ * 10) { | ||
924 | if (lp->network_down) | ||
925 | BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n"); | ||
926 | lp->first_recon = lp->last_recon = jiffies; | ||
927 | lp->num_recons = lp->network_down = 0; | ||
928 | |||
929 | BUGMSG(D_DURING, "recon: clearing counters.\n"); | ||
930 | } else { /* add to current RECON counter */ | ||
931 | lp->last_recon = jiffies; | ||
932 | lp->num_recons++; | ||
933 | |||
934 | BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n", | ||
935 | lp->num_recons, | ||
936 | (lp->last_recon - lp->first_recon) / HZ, | ||
937 | lp->network_down); | ||
938 | |||
939 | /* if network is marked up; | ||
940 | * and first_recon and last_recon are 60+ apart; | ||
941 | * and the average no. of recons counted is | ||
942 | * > RECON_THRESHOLD/min; | ||
943 | * then print a warning message. | ||
944 | */ | ||
945 | if (!lp->network_down | ||
946 | && (lp->last_recon - lp->first_recon) <= HZ * 60 | ||
947 | && lp->num_recons >= RECON_THRESHOLD) { | ||
948 | lp->network_down = 1; | ||
949 | BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n"); | ||
950 | } else if (!lp->network_down | ||
951 | && lp->last_recon - lp->first_recon > HZ * 60) { | ||
952 | /* reset counters if we've gone for over a minute. */ | ||
953 | lp->first_recon = lp->last_recon; | ||
954 | lp->num_recons = 1; | ||
955 | } | ||
956 | } | ||
957 | } else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) { | ||
958 | if (lp->network_down) | ||
959 | BUGMSG(D_NORMAL, "cabling restored?\n"); | ||
960 | lp->first_recon = lp->last_recon = 0; | ||
961 | lp->num_recons = lp->network_down = 0; | ||
962 | |||
963 | BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); | ||
964 | } | ||
965 | |||
966 | if(didsomething) { | ||
967 | retval |= IRQ_HANDLED; | ||
968 | } | ||
969 | } | ||
970 | while (--boguscount && didsomething); | ||
971 | |||
972 | BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n", | ||
973 | ASTATUS(), boguscount); | ||
974 | BUGMSG(D_DURING, "\n"); | ||
975 | |||
976 | |||
977 | AINTMASK(0); | ||
978 | udelay(1); | ||
979 | AINTMASK(lp->intmask); | ||
980 | |||
981 | spin_unlock(&lp->lock); | ||
982 | return retval; | ||
983 | } | ||
984 | |||
985 | |||
986 | /* | ||
987 | * This is a generic packet receiver that calls arcnet??_rx depending on the | ||
988 | * protocol ID found. | ||
989 | */ | ||
990 | void arcnet_rx(struct net_device *dev, int bufnum) | ||
991 | { | ||
992 | struct arcnet_local *lp = dev->priv; | ||
993 | struct archdr pkt; | ||
994 | struct arc_rfc1201 *soft; | ||
995 | int length, ofs; | ||
996 | |||
997 | soft = &pkt.soft.rfc1201; | ||
998 | |||
999 | lp->hw.copy_from_card(dev, bufnum, 0, &pkt, sizeof(ARC_HDR_SIZE)); | ||
1000 | if (pkt.hard.offset[0]) { | ||
1001 | ofs = pkt.hard.offset[0]; | ||
1002 | length = 256 - ofs; | ||
1003 | } else { | ||
1004 | ofs = pkt.hard.offset[1]; | ||
1005 | length = 512 - ofs; | ||
1006 | } | ||
1007 | |||
1008 | /* get the full header, if possible */ | ||
1009 | if (sizeof(pkt.soft) <= length) | ||
1010 | lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft)); | ||
1011 | else { | ||
1012 | memset(&pkt.soft, 0, sizeof(pkt.soft)); | ||
1013 | lp->hw.copy_from_card(dev, bufnum, ofs, soft, length); | ||
1014 | } | ||
1015 | |||
1016 | BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh " | ||
1017 | "(%d+4 bytes)\n", | ||
1018 | bufnum, pkt.hard.source, pkt.hard.dest, length); | ||
1019 | |||
1020 | lp->stats.rx_packets++; | ||
1021 | lp->stats.rx_bytes += length + ARC_HDR_SIZE; | ||
1022 | |||
1023 | /* call the right receiver for the protocol */ | ||
1024 | if (arc_proto_map[soft->proto]->is_ip) { | ||
1025 | BUGLVL(D_PROTO) { | ||
1026 | struct ArcProto | ||
1027 | *oldp = arc_proto_map[lp->default_proto[pkt.hard.source]], | ||
1028 | *newp = arc_proto_map[soft->proto]; | ||
1029 | |||
1030 | if (oldp != newp) { | ||
1031 | BUGMSG(D_PROTO, | ||
1032 | "got protocol %02Xh; encap for host %02Xh is now '%c'" | ||
1033 | " (was '%c')\n", soft->proto, pkt.hard.source, | ||
1034 | newp->suffix, oldp->suffix); | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | /* broadcasts will always be done with the last-used encap. */ | ||
1039 | lp->default_proto[0] = soft->proto; | ||
1040 | |||
1041 | /* in striking contrast, the following isn't a hack. */ | ||
1042 | lp->default_proto[pkt.hard.source] = soft->proto; | ||
1043 | } | ||
1044 | /* call the protocol-specific receiver. */ | ||
1045 | arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length); | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | |||
1050 | /* | ||
1051 | * Get the current statistics. This may be called with the card open or | ||
1052 | * closed. | ||
1053 | */ | ||
1054 | static struct net_device_stats *arcnet_get_stats(struct net_device *dev) | ||
1055 | { | ||
1056 | struct arcnet_local *lp = dev->priv; | ||
1057 | return &lp->stats; | ||
1058 | } | ||
1059 | |||
1060 | |||
1061 | static void null_rx(struct net_device *dev, int bufnum, | ||
1062 | struct archdr *pkthdr, int length) | ||
1063 | { | ||
1064 | BUGMSG(D_PROTO, | ||
1065 | "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", | ||
1066 | pkthdr->soft.rfc1201.proto, pkthdr->hard.source); | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | static int null_build_header(struct sk_buff *skb, struct net_device *dev, | ||
1071 | unsigned short type, uint8_t daddr) | ||
1072 | { | ||
1073 | struct arcnet_local *lp = dev->priv; | ||
1074 | |||
1075 | BUGMSG(D_PROTO, | ||
1076 | "tx: can't build header for encap %02Xh; load a protocol driver.\n", | ||
1077 | lp->default_proto[daddr]); | ||
1078 | |||
1079 | /* always fails */ | ||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | |||
1084 | /* the "do nothing" prepare_tx function warns that there's nothing to do. */ | ||
1085 | static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, | ||
1086 | int length, int bufnum) | ||
1087 | { | ||
1088 | struct arcnet_local *lp = dev->priv; | ||
1089 | struct arc_hardware newpkt; | ||
1090 | |||
1091 | BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n"); | ||
1092 | |||
1093 | /* send a packet to myself -- will never get received, of course */ | ||
1094 | newpkt.source = newpkt.dest = dev->dev_addr[0]; | ||
1095 | |||
1096 | /* only one byte of actual data (and it's random) */ | ||
1097 | newpkt.offset[0] = 0xFF; | ||
1098 | |||
1099 | lp->hw.copy_to_card(dev, bufnum, 0, &newpkt, ARC_HDR_SIZE); | ||
1100 | |||
1101 | return 1; /* done */ | ||
1102 | } | ||