linux/drivers/net/arcnet/arcnet.c

/*
 * Linux ARCnet driver - device-independent routines
 *
 * Written 1997 by David Woodhouse.
 * Written 1994-1999 by Avery Pennarun.
 * Written 1999-2000 by Martin Mares <[email protected]>.
 * 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.
 *
 * **********************
 *
 * The change log is now in a file called ChangeLog in this directory.
 *
 * Sources:
 *  - Crynwr arcnet.com/arcether.com packet drivers.
 *  - arcnet.c v0.00 dated 1/1/94 and apparently by
 *     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 <[email protected]>
 *  - 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 <[email protected]>
 *  - Textual information and more alternate source from Joachim Koenig
 *     <[email protected]>
 */

#define pr_fmt(fmt)

#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/jiffies.h>
#include <linux/errqueue.h>

#include <linux/leds.h>
#include <linux/workqueue.h>

#include "arcdevice.h"
#include "com9026.h"

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

static void arcnet_rx(struct net_device *dev, int bufnum);

/* one ArcProto per possible proto ID.  None of the elements of
 * 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.
 */
struct ArcProto *arc_proto_map[256];
EXPORT_SYMBOL();

struct ArcProto *arc_proto_default;
EXPORT_SYMBOL();

struct ArcProto *arc_bcast_proto;
EXPORT_SYMBOL();

struct ArcProto *arc_raw_proto;
EXPORT_SYMBOL();

static struct ArcProto arc_proto_null =;

/* Exported function prototypes */
int arcnet_debug =;
EXPORT_SYMBOL();

/* Internal function prototypes */
static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
			 unsigned short type, const void *daddr,
			 const void *saddr, unsigned len);
static int go_tx(struct net_device *dev);

static int debug =;
module_param(debug, int, 0);
MODULE_DESCRIPTION();
MODULE_LICENSE();

static int __init arcnet_init(void)
{}

static void __exit arcnet_exit(void)
{}

module_init();
module_exit(arcnet_exit);

/* Dump the contents of an sk_buff */
#if ARCNET_DEBUG_MAX & D_SKB
void arcnet_dump_skb(struct net_device *dev,
		     struct sk_buff *skb, char *desc)
{
	char hdr[32];

	/* 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);
}
EXPORT_SYMBOL(arcnet_dump_skb);
#endif

/* Dump the contents of an ARCnet buffer */
#if (ARCNET_DEBUG_MAX & (D_RX | D_TX))
static void arcnet_dump_packet(struct net_device *dev, int bufnum,
			       char *desc, int take_arcnet_lock)
{
	struct arcnet_local *lp = netdev_priv(dev);
	int i, length;
	unsigned long flags = 0;
	static uint8_t buf[512];
	char hdr[32];

	/* hw.copy_from_card expects IRQ context so take the IRQ lock
	 * to keep it single threaded
	 */
	if (take_arcnet_lock)
		spin_lock_irqsave(&lp->lock, flags);

	lp->hw.copy_from_card(dev, bufnum, 0, buf, 512);
	if (take_arcnet_lock)
		spin_unlock_irqrestore(&lp->lock, flags);

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

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

#else

#define arcnet_dump_packet(dev, bufnum, desc, take_arcnet_lock)

#endif

/* Trigger a LED event in response to a ARCNET device event */
void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
{}
EXPORT_SYMBOL_GPL();

static void arcnet_led_release(struct device *gendev, void *res)
{}

/* 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)
{}
EXPORT_SYMBOL_GPL();

/* Unregister a protocol driver from the arc_proto_map.  Protocol drivers
 * 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)
{}
EXPORT_SYMBOL();

/* Add a buffer to the queue.  Only the interrupt handler is allowed to do
 * this, unless interrupts are disabled.
 *
 * 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)
{}

/* Get a buffer from the queue.
 * If this returns -1, there are no buffers available.
 */
static int get_arcbuf(struct net_device *dev)
{}

static int choose_mtu(void)
{}

static const struct header_ops arcnet_header_ops =;

static const struct net_device_ops arcnet_netdev_ops =;

/* Setup a struct device for ARCnet. */
static void arcdev_setup(struct net_device *dev)
{}

static void arcnet_timer(struct timer_list *t)
{}

static void reset_device_work(struct work_struct *work)
{}

static void arcnet_reply_work(struct work_struct *t)
{
	struct arcnet_local *lp = from_work(lp, t, reply_work);

	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)
		dev_kfree_skb_irq(ackskb);

	local_irq_enable();
};

struct net_device *alloc_arcdev(const char *name)
{}
EXPORT_SYMBOL();

void free_arcdev(struct net_device *dev)
{}
EXPORT_SYMBOL();

/* Open/initialize the board.  This is called sometime after booting when
 * 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.
 */
int arcnet_open(struct net_device *dev)
{}
EXPORT_SYMBOL();

/* The inverse routine to arcnet_open - shuts down the card. */
int arcnet_close(struct net_device *dev)
{}
EXPORT_SYMBOL();

static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
			 unsigned short type, const void *daddr,
			 const void *saddr, unsigned len)
{}

/* Called by the kernel in order to transmit a packet. */
netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
			       struct net_device *dev)
{}
EXPORT_SYMBOL();

/* Actually start transmitting a packet that was loaded into a buffer
 * by prepare_tx.  This should _only_ be called by the interrupt handler.
 */
static int go_tx(struct net_device *dev)
{}

/* Called by the kernel when transmit times out */
void arcnet_timeout(struct net_device *dev, unsigned int txqueue)
{}
EXPORT_SYMBOL();

/* The typical workload of the driver: Handle the network interface
 * interrupts. Establish which device needs attention, and call the correct
 * chipset interrupt handler.
 */
irqreturn_t arcnet_interrupt(int irq, void *dev_id)
{}
EXPORT_SYMBOL();

/* This is a generic packet receiver that calls arcnet??_rx depending on the
 * protocol ID found.
 */
static void arcnet_rx(struct net_device *dev, int bufnum)
{}

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)
{}

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