arcnet.c 27.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2
/*
 * Linux ARCnet driver - device-independent routines
3
 *
L
Linus Torvalds 已提交
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.
 *
 * **********************
23
 *
L
Linus Torvalds 已提交
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.
28
 *  - arcnet.c v0.00 dated 1/1/94 and apparently by
L
Linus Torvalds 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
 *     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>
 */

44
#define VERSION "arcnet: v3.94 BETA 2007/02/08 - by Avery Pennarun et al.\n"
L
Linus Torvalds 已提交
45 46 47 48 49 50 51 52 53

#include <linux/module.h>
#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>
#include <linux/arcdevice.h>
54
#include <linux/jiffies.h>
L
Linus Torvalds 已提交
55 56 57 58 59 60 61 62 63

/* "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);

64
static void arcnet_rx(struct net_device *dev, int bufnum);
L
Linus Torvalds 已提交
65

66
/* one ArcProto per possible proto ID.  None of the elements of
L
Linus Torvalds 已提交
67 68 69 70
 * 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.
 */
71 72
struct ArcProto *arc_proto_map[256], *arc_proto_default,
	*arc_bcast_proto, *arc_raw_proto;
L
Linus Torvalds 已提交
73

74
static struct ArcProto arc_proto_null = {
L
Linus Torvalds 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
	.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;

EXPORT_SYMBOL(arc_proto_map);
EXPORT_SYMBOL(arc_proto_default);
EXPORT_SYMBOL(arc_bcast_proto);
EXPORT_SYMBOL(arc_raw_proto);
EXPORT_SYMBOL(arcnet_unregister_proto);
EXPORT_SYMBOL(arcnet_debug);
EXPORT_SYMBOL(alloc_arcdev);
EXPORT_SYMBOL(arcnet_interrupt);
96 97 98 99
EXPORT_SYMBOL(arcnet_open);
EXPORT_SYMBOL(arcnet_close);
EXPORT_SYMBOL(arcnet_send_packet);
EXPORT_SYMBOL(arcnet_timeout);
L
Linus Torvalds 已提交
100 101 102

/* Internal function prototypes */
static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
103 104
			 unsigned short type, const void *daddr,
			 const void *saddr, unsigned len);
L
Linus Torvalds 已提交
105 106 107 108 109 110 111 112 113 114 115 116
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;

117
	printk("arcnet loaded.\n");
L
Linus Torvalds 已提交
118 119

#ifdef ALPHA_WARNING
120
	if (BUGLVL(D_EXTRA)) {
L
Linus Torvalds 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134
		printk("arcnet: ***\n"
		"arcnet: * Read arcnet.txt for important release notes!\n"
		       "arcnet: *\n"
		       "arcnet: * This is an ALPHA version! (Last stable release: v3.02)  E-mail\n"
		       "arcnet: * me if you have any questions, comments, or bug reports.\n"
		       "arcnet: ***\n");
	}
#endif

	/* 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;

135 136 137 138 139
	if (BUGLVL(D_DURING))
		printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n",
		       sizeof(struct arc_hardware), sizeof(struct arc_rfc1201),
		       sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap),
		       sizeof(struct archdr));
L
Linus Torvalds 已提交
140 141 142 143 144 145 146 147 148 149 150

	return 0;
}

static void __exit arcnet_exit(void)
{
}

module_init(arcnet_init);
module_exit(arcnet_exit);

151
/* Dump the contents of an sk_buff */
L
Linus Torvalds 已提交
152 153 154 155
#if ARCNET_DEBUG_MAX & D_SKB
void arcnet_dump_skb(struct net_device *dev,
		     struct sk_buff *skb, char *desc)
{
156
	char hdr[32];
L
Linus Torvalds 已提交
157

158 159 160 161
	/* 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);
L
Linus Torvalds 已提交
162 163 164 165 166
}

EXPORT_SYMBOL(arcnet_dump_skb);
#endif

167
/* Dump the contents of an ARCnet buffer */
L
Linus Torvalds 已提交
168
#if (ARCNET_DEBUG_MAX & (D_RX | D_TX))
169 170
static void arcnet_dump_packet(struct net_device *dev, int bufnum,
			       char *desc, int take_arcnet_lock)
L
Linus Torvalds 已提交
171
{
172
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
173 174 175
	int i, length;
	unsigned long flags = 0;
	static uint8_t buf[512];
176
	char hdr[32];
L
Linus Torvalds 已提交
177 178

	/* hw.copy_from_card expects IRQ context so take the IRQ lock
179 180
	 * to keep it single threaded
	 */
181
	if (take_arcnet_lock)
L
Linus Torvalds 已提交
182 183 184
		spin_lock_irqsave(&lp->lock, flags);

	lp->hw.copy_from_card(dev, bufnum, 0, buf, 512);
185
	if (take_arcnet_lock)
L
Linus Torvalds 已提交
186 187 188 189 190
		spin_unlock_irqrestore(&lp->lock, flags);

	/* if the offset[0] byte is nonzero, this is a 256-byte packet */
	length = (buf[2] ? 256 : 512);

191 192 193 194
	/* 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);
L
Linus Torvalds 已提交
195 196
}

197 198
#else

199
#define arcnet_dump_packet(dev, bufnum, desc, take_arcnet_lock) do { } while (0)
200

L
Linus Torvalds 已提交
201 202
#endif

203
/* Unregister a protocol driver from the arc_proto_map.  Protocol drivers
L
Linus Torvalds 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
 * 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;
	}
}

224
/* Add a buffer to the queue.  Only the interrupt handler is allowed to do
L
Linus Torvalds 已提交
225
 * this, unless interrupts are disabled.
226
 *
L
Linus Torvalds 已提交
227 228 229 230 231
 * 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)
{
232
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
233 234 235 236 237
	int i;

	lp->buf_queue[lp->first_free_buf++] = bufnum;
	lp->first_free_buf %= 5;

238
	if (BUGLVL(D_DURING)) {
L
Linus Torvalds 已提交
239 240
		BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ",
		       bufnum);
241
		for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5)
L
Linus Torvalds 已提交
242 243 244 245 246
			BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
		BUGMSG2(D_DURING, "\n");
	}
}

247 248
/* Get a buffer from the queue.
 * If this returns -1, there are no buffers available.
L
Linus Torvalds 已提交
249 250 251
 */
static int get_arcbuf(struct net_device *dev)
{
252
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
253 254 255 256 257 258
	int buf = -1, i;

	if (!atomic_dec_and_test(&lp->buf_lock)) {
		/* already in this function */
		BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n",
		       lp->buf_lock.counter);
259
	} else {			/* we can continue */
L
Linus Torvalds 已提交
260 261 262
		if (lp->next_buf >= 5)
			lp->next_buf -= 5;

263
		if (lp->next_buf == lp->first_free_buf) {
L
Linus Torvalds 已提交
264
			BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n");
265
		} else {
L
Linus Torvalds 已提交
266 267 268 269 270
			buf = lp->buf_queue[lp->next_buf++];
			lp->next_buf %= 5;
		}
	}

271
	if (BUGLVL(D_DURING)) {
L
Linus Torvalds 已提交
272
		BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf);
273
		for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5)
L
Linus Torvalds 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287
			BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
		BUGMSG2(D_DURING, "\n");
	}

	atomic_inc(&lp->buf_lock);
	return buf;
}

static int choose_mtu(void)
{
	int count, mtu = 65535;

	/* choose the smallest MTU of all available encaps */
	for (count = 0; count < 256; count++) {
288 289
		if (arc_proto_map[count] != &arc_proto_null &&
		    arc_proto_map[count]->mtu < mtu) {
L
Linus Torvalds 已提交
290 291 292 293 294 295 296
			mtu = arc_proto_map[count]->mtu;
		}
	}

	return mtu == 65535 ? XMTU : mtu;
}

297 298 299 300
static const struct header_ops arcnet_header_ops = {
	.create = arcnet_header,
};

301 302 303 304 305 306
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,
};
L
Linus Torvalds 已提交
307 308 309 310 311

/* Setup a struct device for ARCnet. */
static void arcdev_setup(struct net_device *dev)
{
	dev->type = ARPHRD_ARCNET;
312
	dev->netdev_ops = &arcnet_netdev_ops;
313
	dev->header_ops = &arcnet_header_ops;
L
Linus Torvalds 已提交
314 315 316 317 318 319 320 321 322 323 324 325
	dev->hard_header_len = sizeof(struct archdr);
	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;
}

326
struct net_device *alloc_arcdev(const char *name)
L
Linus Torvalds 已提交
327 328 329 330
{
	struct net_device *dev;

	dev = alloc_netdev(sizeof(struct arcnet_local),
331 332
			   name && *name ? name : "arc%d", NET_NAME_UNKNOWN,
			   arcdev_setup);
333
	if (dev) {
334
		struct arcnet_local *lp = netdev_priv(dev);
J
Joe Perches 已提交
335

L
Linus Torvalds 已提交
336 337 338 339 340 341
		spin_lock_init(&lp->lock);
	}

	return dev;
}

342
/* Open/initialize the board.  This is called sometime after booting when
L
Linus Torvalds 已提交
343 344 345 346 347 348
 * 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.
 */
349
int arcnet_open(struct net_device *dev)
L
Linus Torvalds 已提交
350
{
351
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
352 353
	int count, newmtu, error;

354
	BUGMSG(D_INIT, "opened.");
L
Linus Torvalds 已提交
355 356 357 358

	if (!try_module_get(lp->hw.owner))
		return -ENODEV;

359
	if (BUGLVL(D_PROTO)) {
L
Linus Torvalds 已提交
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 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
		BUGMSG(D_PROTO, "protocol map (default is '%c'): ",
		       arc_proto_default->suffix);
		for (count = 0; count < 256; count++)
			BUGMSG2(D_PROTO, "%c", arc_proto_map[count]->suffix);
		BUGMSG2(D_PROTO, "\n");
	}

	BUGMSG(D_INIT, "arcnet_open: resetting card.\n");

	/* try to put the card in a defined state - if it fails the first
	 * time, actually reset it.
	 */
	error = -ENODEV;
	if (ARCRESET(0) && ARCRESET(1))
		goto out_module_put;

	newmtu = choose_mtu();
	if (newmtu < dev->mtu)
		dev->mtu = newmtu;

	BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu);

	/* 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)
J
Joe Perches 已提交
411
		BUGMSG(D_NORMAL, "WARNING!  Station address 00 is reserved for broadcasts!\n");
L
Linus Torvalds 已提交
412
	else if (dev->dev_addr[0] == 255)
J
Joe Perches 已提交
413
		BUGMSG(D_NORMAL, "WARNING!  Station address FF may confuse DOS networking programs!\n");
L
Linus Torvalds 已提交
414

415
	BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
L
Linus Torvalds 已提交
416
	if (ASTATUS() & RESETflag) {
417
		BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
L
Linus Torvalds 已提交
418 419 420
		ACOMMAND(CFLAGScmd | RESETclear);
	}

421
	BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
L
Linus Torvalds 已提交
422 423 424 425 426 427
	/* make sure we're ready to receive IRQ's. */
	AINTMASK(0);
	udelay(1);		/* give it time to set the mask before
				 * we reset it again. (may not even be
				 * necessary)
				 */
428
	BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
L
Linus Torvalds 已提交
429 430
	lp->intmask = NORXflag | RECONflag;
	AINTMASK(lp->intmask);
431
	BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
L
Linus Torvalds 已提交
432 433 434 435 436 437 438 439 440 441 442

	netif_start_queue(dev);

	return 0;

 out_module_put:
	module_put(lp->hw.owner);
	return error;
}

/* The inverse routine to arcnet_open - shuts down the card. */
443
int arcnet_close(struct net_device *dev)
L
Linus Torvalds 已提交
444
{
445
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461

	netif_stop_queue(dev);

	/* flush TX and disable RX */
	AINTMASK(0);
	ACOMMAND(NOTXcmd);	/* stop transmit */
	ACOMMAND(NORXcmd);	/* disable receive */
	mdelay(1);

	/* shut down the card */
	lp->hw.close(dev);
	module_put(lp->hw.owner);
	return 0;
}

static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
462 463
			 unsigned short type, const void *daddr,
			 const void *saddr, unsigned len)
L
Linus Torvalds 已提交
464
{
465
	const struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
466 467 468 469
	uint8_t _daddr, proto_num;
	struct ArcProto *proto;

	BUGMSG(D_DURING,
470 471 472
	       "create header from %d to %d; protocol %d (%Xh); size %u.\n",
	       saddr ? *(uint8_t *)saddr : -1,
	       daddr ? *(uint8_t *)daddr : -1,
L
Linus Torvalds 已提交
473 474
	       type, type, len);

475
	if (skb->len != 0 && len != skb->len)
L
Linus Torvalds 已提交
476 477 478
		BUGMSG(D_NORMAL, "arcnet_header: Yikes!  skb->len(%d) != len(%d)!\n",
		       skb->len, len);

479 480 481 482 483
	/* Type is host order - ? */
	if (type == ETH_P_ARCNET) {
		proto = arc_raw_proto;
		BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n", proto->suffix);
		_daddr = daddr ? *(uint8_t *)daddr : 0;
484
	} else if (!daddr) {
485 486 487 488
		/* 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.
L
Linus Torvalds 已提交
489
		 */
490
		*(uint16_t *)skb_push(skb, 2) = type;
491
		/* XXX: Why not use skb->mac_len? */
492
		if (skb->network_header - skb->mac_header != 2)
L
Linus Torvalds 已提交
493
			BUGMSG(D_NORMAL, "arcnet_header: Yikes!  diff (%d) is not 2!\n",
494
			       (int)(skb->network_header - skb->mac_header));
L
Linus Torvalds 已提交
495
		return -2;	/* return error -- can't transmit yet! */
496
	} else {
L
Linus Torvalds 已提交
497
		/* otherwise, we can just add the header as usual. */
498
		_daddr = *(uint8_t *)daddr;
L
Linus Torvalds 已提交
499 500 501 502 503 504 505 506 507 508 509 510 511 512
		proto_num = lp->default_proto[_daddr];
		proto = arc_proto_map[proto_num];
		BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n",
		       proto_num, proto->suffix);
		if (proto == &arc_proto_null && arc_bcast_proto != proto) {
			BUGMSG(D_DURING, "actually, let's use '%c' instead.\n",
			       arc_bcast_proto->suffix);
			proto = arc_bcast_proto;
		}
	}
	return proto->build_header(skb, dev, type, _daddr);
}

/* Called by the kernel in order to transmit a packet. */
513
netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
514
			       struct net_device *dev)
L
Linus Torvalds 已提交
515
{
516
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
517 518 519 520 521
	struct archdr *pkt;
	struct arc_rfc1201 *soft;
	struct ArcProto *proto;
	int txbuf;
	unsigned long flags;
522
	int freeskb, retval;
L
Linus Torvalds 已提交
523 524 525

	BUGMSG(D_DURING,
	       "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
526
	       ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol);
L
Linus Torvalds 已提交
527

528
	pkt = (struct archdr *)skb->data;
L
Linus Torvalds 已提交
529 530 531 532
	soft = &pkt->soft.rfc1201;
	proto = arc_proto_map[soft->proto];

	BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n",
533
	       skb->len, pkt->hard.dest);
534 535
	if (BUGLVL(D_SKB))
		arcnet_dump_skb(dev, skb, "tx");
L
Linus Torvalds 已提交
536 537 538 539 540

	/* fits in one packet? */
	if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) {
		BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n");
		dev_kfree_skb(skb);
541
		return NETDEV_TX_OK;	/* don't try again */
L
Linus Torvalds 已提交
542 543 544 545 546 547 548
	}

	/* We're busy transmitting a packet... */
	netif_stop_queue(dev);

	spin_lock_irqsave(&lp->lock, flags);
	AINTMASK(0);
549
	if (lp->next_tx == -1)
550
		txbuf = get_arcbuf(dev);
551
	else
552
		txbuf = -1;
553

L
Linus Torvalds 已提交
554 555 556 557
	if (txbuf != -1) {
		if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&
		    !proto->ack_tx) {
			/* done right away and we don't want to acknowledge
558 559
			 *  the package later - forget about it now
			 */
560
			dev->stats.tx_bytes += skb->len;
L
Linus Torvalds 已提交
561 562 563 564 565 566 567
			freeskb = 1;
		} else {
			/* do it the 'split' way */
			lp->outgoing.proto = proto;
			lp->outgoing.skb = skb;
			lp->outgoing.pkt = pkt;

568 569
			freeskb = 0;

L
Linus Torvalds 已提交
570 571
			if (proto->continue_tx &&
			    proto->continue_tx(dev, txbuf)) {
572
				BUGMSG(D_NORMAL,
J
Joe Perches 已提交
573 574
				       "bug! continue_tx finished the first time! (proto='%c')\n",
				       proto->suffix);
L
Linus Torvalds 已提交
575 576
			}
		}
577
		retval = NETDEV_TX_OK;
L
Linus Torvalds 已提交
578 579
		lp->next_tx = txbuf;
	} else {
580 581
		retval = NETDEV_TX_BUSY;
		freeskb = 0;
L
Linus Torvalds 已提交
582 583
	}

584
	BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS());
L
Linus Torvalds 已提交
585 586 587
	/* make sure we didn't ignore a TX IRQ while we were in here */
	AINTMASK(0);

588 589
	BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
	lp->intmask |= TXFREEflag | EXCNAKflag;
L
Linus Torvalds 已提交
590
	AINTMASK(lp->intmask);
591
	BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS());
L
Linus Torvalds 已提交
592 593

	spin_unlock_irqrestore(&lp->lock, flags);
594
	if (freeskb)
L
Linus Torvalds 已提交
595
		dev_kfree_skb(skb);
596

597
	return retval;		/* no need to try again */
L
Linus Torvalds 已提交
598 599
}

600
/* Actually start transmitting a packet that was loaded into a buffer
L
Linus Torvalds 已提交
601 602 603 604
 * by prepare_tx.  This should _only_ be called by the interrupt handler.
 */
static int go_tx(struct net_device *dev)
{
605
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
606 607 608 609 610 611 612

	BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n",
	       ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx);

	if (lp->cur_tx != -1 || lp->next_tx == -1)
		return 0;

613 614
	if (BUGLVL(D_TX))
		arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0);
L
Linus Torvalds 已提交
615 616 617 618 619 620 621

	lp->cur_tx = lp->next_tx;
	lp->next_tx = -1;

	/* start sending */
	ACOMMAND(TXcmd | (lp->cur_tx << 3));

622
	dev->stats.tx_packets++;
L
Linus Torvalds 已提交
623 624 625
	lp->lasttrans_dest = lp->lastload_dest;
	lp->lastload_dest = 0;
	lp->excnak_pending = 0;
626
	lp->intmask |= TXFREEflag | EXCNAKflag;
L
Linus Torvalds 已提交
627 628 629 630 631

	return 1;
}

/* Called by the kernel when transmit times out */
632
void arcnet_timeout(struct net_device *dev)
L
Linus Torvalds 已提交
633 634
{
	unsigned long flags;
635
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
636 637 638 639 640 641 642 643
	int status = ASTATUS();
	char *msg;

	spin_lock_irqsave(&lp->lock, flags);
	if (status & TXFREEflag) {	/* transmit _DID_ finish */
		msg = " - missed IRQ?";
	} else {
		msg = "";
644
		dev->stats.tx_aborted_errors++;
L
Linus Torvalds 已提交
645 646 647
		lp->timed_out = 1;
		ACOMMAND(NOTXcmd | (lp->cur_tx << 3));
	}
648
	dev->stats.tx_errors++;
L
Linus Torvalds 已提交
649 650 651

	/* make sure we didn't miss a TX or a EXC NAK IRQ */
	AINTMASK(0);
652
	lp->intmask |= TXFREEflag | EXCNAKflag;
L
Linus Torvalds 已提交
653
	AINTMASK(lp->intmask);
654

L
Linus Torvalds 已提交
655 656
	spin_unlock_irqrestore(&lp->lock, flags);

657
	if (time_after(jiffies, lp->last_timeout + 10 * HZ)) {
L
Linus Torvalds 已提交
658 659 660 661 662 663 664 665 666
		BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n",
		       msg, status, lp->intmask, lp->lasttrans_dest);
		lp->last_timeout = jiffies;
	}

	if (lp->cur_tx == -1)
		netif_wake_queue(dev);
}

667
/* The typical workload of the driver: Handle the network interface
L
Linus Torvalds 已提交
668 669 670
 * interrupts. Establish which device needs attention, and call the correct
 * chipset interrupt handler.
 */
671
irqreturn_t arcnet_interrupt(int irq, void *dev_id)
L
Linus Torvalds 已提交
672 673 674 675 676 677 678 679 680
{
	struct net_device *dev = dev_id;
	struct arcnet_local *lp;
	int recbuf, status, diagstatus, didsomething, boguscount;
	int retval = IRQ_NONE;

	BUGMSG(D_DURING, "\n");

	BUGMSG(D_DURING, "in arcnet_interrupt\n");
681 682

	lp = netdev_priv(dev);
683
	BUG_ON(!lp);
684

L
Linus Torvalds 已提交
685 686
	spin_lock(&lp->lock);

687 688
	/* RESET flag was enabled - if device is not running, we must
	 * clear it right away (but nothing else).
L
Linus Torvalds 已提交
689 690 691 692 693 694
	 */
	if (!netif_running(dev)) {
		if (ASTATUS() & RESETflag)
			ACOMMAND(CFLAGScmd | RESETclear);
		AINTMASK(0);
		spin_unlock(&lp->lock);
695
		return retval;
L
Linus Torvalds 已提交
696 697 698 699 700 701 702 703
	}

	BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
	       ASTATUS(), lp->intmask);

	boguscount = 5;
	do {
		status = ASTATUS();
704
		diagstatus = (status >> 8) & 0xFF;
L
Linus Torvalds 已提交
705 706

		BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n",
707
		       __FILE__, __LINE__, __func__, status);
L
Linus Torvalds 已提交
708 709
		didsomething = 0;

710
		/* RESET flag was enabled - card is resetting and if RX is
L
Linus Torvalds 已提交
711
		 * disabled, it's NOT because we just got a packet.
712
		 *
713 714
		 * The card is in an undefined state.
		 * Clear it out and start over.
L
Linus Torvalds 已提交
715 716 717 718 719 720 721 722 723
		 */
		if (status & RESETflag) {
			BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status);
			arcnet_close(dev);
			arcnet_open(dev);

			/* get out of the interrupt handler! */
			break;
		}
724 725
		/* RX is inhibited - we must have received something.
		 * Prepare to receive into the next buffer.
726
		 *
727 728 729 730
		 * 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.
L
Linus Torvalds 已提交
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
		 */
		recbuf = -1;
		if (status & lp->intmask & NORXflag) {
			recbuf = lp->cur_rx;
			BUGMSG(D_DURING, "Buffer #%d: receive irq (status=%Xh)\n",
			       recbuf, status);

			lp->cur_rx = get_arcbuf(dev);
			if (lp->cur_rx != -1) {
				BUGMSG(D_DURING, "enabling receive to buffer #%d\n",
				       lp->cur_rx);
				ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts);
			}
			didsomething++;
		}

747
		if ((diagstatus & EXCNAKflag)) {
L
Linus Torvalds 已提交
748 749 750
			BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n",
			       diagstatus);

751 752
			ACOMMAND(NOTXcmd);      /* disable transmit */
			lp->excnak_pending = 1;
L
Linus Torvalds 已提交
753

754
			ACOMMAND(EXCNAKclear);
L
Linus Torvalds 已提交
755
			lp->intmask &= ~(EXCNAKflag);
756 757
			didsomething++;
		}
L
Linus Torvalds 已提交
758 759 760

		/* a transmit finished, and we're interested in it. */
		if ((status & lp->intmask & TXFREEflag) || lp->timed_out) {
761
			lp->intmask &= ~(TXFREEflag | EXCNAKflag);
L
Linus Torvalds 已提交
762 763 764 765

			BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status);

			if (lp->cur_tx != -1 && !lp->timed_out) {
766
				if (!(status & TXACKflag)) {
L
Linus Torvalds 已提交
767 768
					if (lp->lasttrans_dest != 0) {
						BUGMSG(D_EXTRA,
J
Joe Perches 已提交
769
						       "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
L
Linus Torvalds 已提交
770
						       status, lp->lasttrans_dest);
771 772
						dev->stats.tx_errors++;
						dev->stats.tx_carrier_errors++;
L
Linus Torvalds 已提交
773 774
					} else {
						BUGMSG(D_DURING,
J
Joe Perches 已提交
775
						       "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
L
Linus Torvalds 已提交
776 777 778 779 780 781
						       status, lp->lasttrans_dest);
					}
				}

				if (lp->outgoing.proto &&
				    lp->outgoing.proto->ack_tx) {
782
					int ackstatus;
J
Joe Perches 已提交
783

784 785 786 787 788 789 790 791 792
					if (status & TXACKflag)
						ackstatus = 2;
					else if (lp->excnak_pending)
						ackstatus = 1;
					else
						ackstatus = 0;

					lp->outgoing.proto
						->ack_tx(dev, ackstatus);
L
Linus Torvalds 已提交
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
				}
			}
			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 */
			if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) {
				int txbuf = get_arcbuf(dev);
J
Joe Perches 已提交
808

L
Linus Torvalds 已提交
809 810 811
				if (txbuf != -1) {
					if (lp->outgoing.proto->continue_tx(dev, txbuf)) {
						/* that was the last segment */
812
						dev->stats.tx_bytes += lp->outgoing.skb->len;
813
						if (!lp->outgoing.proto->ack_tx) {
814 815 816
							dev_kfree_skb_irq(lp->outgoing.skb);
							lp->outgoing.proto = NULL;
						}
L
Linus Torvalds 已提交
817 818 819 820 821 822 823 824 825 826
					}
					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) {
827 828
			if (BUGLVL(D_RX))
				arcnet_dump_packet(dev, recbuf, "rx irq", 0);
L
Linus Torvalds 已提交
829 830 831 832 833 834 835 836

			arcnet_rx(dev, recbuf);
			release_arcbuf(dev, recbuf);

			didsomething++;
		}
		if (status & lp->intmask & RECONflag) {
			ACOMMAND(CFLAGScmd | CONFIGclear);
837
			dev->stats.tx_carrier_errors++;
L
Linus Torvalds 已提交
838 839 840

			BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",
			       status);
841
			/* MYRECON bit is at bit 7 of diagstatus */
842 843
			if (diagstatus & 0x80)
				BUGMSG(D_RECON, "Put out that recon myself\n");
L
Linus Torvalds 已提交
844 845 846

			/* is the RECON info empty or old? */
			if (!lp->first_recon || !lp->last_recon ||
847
			    time_after(jiffies, lp->last_recon + HZ * 10)) {
L
Linus Torvalds 已提交
848 849 850 851 852 853 854 855 856 857 858 859
				if (lp->network_down)
					BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n");
				lp->first_recon = lp->last_recon = jiffies;
				lp->num_recons = lp->network_down = 0;

				BUGMSG(D_DURING, "recon: clearing counters.\n");
			} else {	/* add to current RECON counter */
				lp->last_recon = jiffies;
				lp->num_recons++;

				BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n",
				       lp->num_recons,
860
				       (lp->last_recon - lp->first_recon) / HZ,
L
Linus Torvalds 已提交
861 862 863 864 865 866 867 868
				       lp->network_down);

				/* 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.
				 */
869 870 871
				if (!lp->network_down &&
				    (lp->last_recon - lp->first_recon) <= HZ * 60 &&
				    lp->num_recons >= RECON_THRESHOLD) {
L
Linus Torvalds 已提交
872 873
					lp->network_down = 1;
					BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n");
874 875
				} else if (!lp->network_down &&
					   lp->last_recon - lp->first_recon > HZ * 60) {
L
Linus Torvalds 已提交
876 877 878 879 880
					/* reset counters if we've gone for over a minute. */
					lp->first_recon = lp->last_recon;
					lp->num_recons = 1;
				}
			}
881
		} else if (lp->network_down &&
882
			   time_after(jiffies, lp->last_recon + HZ * 10)) {
L
Linus Torvalds 已提交
883 884 885 886 887 888 889 890
			if (lp->network_down)
				BUGMSG(D_NORMAL, "cabling restored?\n");
			lp->first_recon = lp->last_recon = 0;
			lp->num_recons = lp->network_down = 0;

			BUGMSG(D_DURING, "not recon: clearing counters anyway.\n");
		}

891
		if (didsomething)
L
Linus Torvalds 已提交
892
			retval |= IRQ_HANDLED;
893
	} while (--boguscount && didsomething);
L
Linus Torvalds 已提交
894 895 896 897 898 899 900 901

	BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n",
	       ASTATUS(), boguscount);
	BUGMSG(D_DURING, "\n");

	AINTMASK(0);
	udelay(1);
	AINTMASK(lp->intmask);
902

L
Linus Torvalds 已提交
903 904 905 906
	spin_unlock(&lp->lock);
	return retval;
}

907
/* This is a generic packet receiver that calls arcnet??_rx depending on the
L
Linus Torvalds 已提交
908 909
 * protocol ID found.
 */
910
static void arcnet_rx(struct net_device *dev, int bufnum)
L
Linus Torvalds 已提交
911
{
912
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
913 914 915 916 917 918
	struct archdr pkt;
	struct arc_rfc1201 *soft;
	int length, ofs;

	soft = &pkt.soft.rfc1201;

D
Dan Carpenter 已提交
919
	lp->hw.copy_from_card(dev, bufnum, 0, &pkt, ARC_HDR_SIZE);
L
Linus Torvalds 已提交
920 921 922 923 924 925 926 927 928
	if (pkt.hard.offset[0]) {
		ofs = pkt.hard.offset[0];
		length = 256 - ofs;
	} else {
		ofs = pkt.hard.offset[1];
		length = 512 - ofs;
	}

	/* get the full header, if possible */
929
	if (sizeof(pkt.soft) <= length) {
L
Linus Torvalds 已提交
930
		lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft));
931
	} else {
L
Linus Torvalds 已提交
932 933 934 935
		memset(&pkt.soft, 0, sizeof(pkt.soft));
		lp->hw.copy_from_card(dev, bufnum, ofs, soft, length);
	}

J
Joe Perches 已提交
936
	BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n",
L
Linus Torvalds 已提交
937 938
	       bufnum, pkt.hard.source, pkt.hard.dest, length);

939 940
	dev->stats.rx_packets++;
	dev->stats.rx_bytes += length + ARC_HDR_SIZE;
L
Linus Torvalds 已提交
941 942 943

	/* call the right receiver for the protocol */
	if (arc_proto_map[soft->proto]->is_ip) {
944
		if (BUGLVL(D_PROTO)) {
L
Linus Torvalds 已提交
945 946 947 948 949 950
			struct ArcProto
			*oldp = arc_proto_map[lp->default_proto[pkt.hard.source]],
			*newp = arc_proto_map[soft->proto];

			if (oldp != newp) {
				BUGMSG(D_PROTO,
J
Joe Perches 已提交
951 952
				       "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n",
				       soft->proto, pkt.hard.source,
L
Linus Torvalds 已提交
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
				       newp->suffix, oldp->suffix);
			}
		}

		/* 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. */
		lp->default_proto[pkt.hard.source] = soft->proto;
	}
	/* call the protocol-specific receiver. */
	arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length);
}

static void null_rx(struct net_device *dev, int bufnum,
		    struct archdr *pkthdr, int length)
{
	BUGMSG(D_PROTO,
971
	       "rx: don't know how to deal with proto %02Xh from host %02Xh.\n",
L
Linus Torvalds 已提交
972 973 974 975 976 977
	       pkthdr->soft.rfc1201.proto, pkthdr->hard.source);
}

static int null_build_header(struct sk_buff *skb, struct net_device *dev,
			     unsigned short type, uint8_t daddr)
{
978
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
979 980 981 982 983 984 985 986 987 988 989 990 991

	BUGMSG(D_PROTO,
	       "tx: can't build header for encap %02Xh; load a protocol driver.\n",
	       lp->default_proto[daddr]);

	/* always fails */
	return 0;
}

/* 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)
{
992
	struct arcnet_local *lp = netdev_priv(dev);
L
Linus Torvalds 已提交
993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
	struct arc_hardware newpkt;

	BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n");

	/* 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 */
}