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