⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eth1394.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * eth1394.c -- Ethernet driver for Linux IEEE-1394 Subsystem *  * Copyright (C) 2001-2003 Ben Collins <bcollins@debian.org> *               2000 Bonin Franck <boninf@free.fr> *               2003 Steve Kinneberg <kinnebergsteve@acmsystems.com> * * Mainly based on work by Emanuel Pirker and Andreas E. Bombe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* This driver intends to support RFC 2734, which describes a method for * transporting IPv4 datagrams over IEEE-1394 serial busses. This driver * will ultimately support that method, but currently falls short in * several areas. * * TODO: * RFC 2734 related: * - Add Config ROM entry * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2. * * Non-RFC 2734 related: * - Handle fragmented skb's coming from the networking layer. * - Move generic GASP reception to core 1394 code * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead * - Stability improvements * - Performance enhancements * - Change hardcoded 1394 bus address region to a dynamic memory space allocation * - Consider garbage collecting old partial datagrams after X amount of time */#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/inetdevice.h>#include <linux/etherdevice.h>#include <linux/if_arp.h>#include <linux/if_ether.h>#include <linux/ip.h>#include <linux/in.h>#include <linux/tcp.h>#include <linux/skbuff.h>#include <linux/bitops.h>#include <linux/ethtool.h>#include <asm/uaccess.h>#include <asm/delay.h>#include <asm/semaphore.h>#include <net/arp.h>#include "ieee1394_types.h"#include "ieee1394_core.h"#include "ieee1394_transactions.h"#include "ieee1394.h"#include "highlevel.h"#include "iso.h"#include "nodemgr.h"#include "eth1394.h"#define ETH1394_PRINT_G(level, fmt, args...) \	printk(level "%s: " fmt, driver_name, ## args)#define ETH1394_PRINT(level, dev_name, fmt, args...) \	printk(level "%s: %s: " fmt, driver_name, dev_name, ## args)#define DEBUG(fmt, args...) \	printk(KERN_ERR "%s:%s[%d]: " fmt "\n", driver_name, __FUNCTION__, __LINE__, ## args)#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)static char version[] __devinitdata =	"$Rev: 1043 $ Ben Collins <bcollins@debian.org>";struct fragment_info {	struct list_head list;	int offset;	int len;};struct partial_datagram {	struct list_head list;	u16 dgl;	u16 dg_size;	u16 ether_type;	struct sk_buff *skb;	char *pbuf;	struct list_head frag_info;};/* Our ieee1394 highlevel driver */static const char driver_name[] = "eth1394";static kmem_cache_t *packet_task_cache;static struct hpsb_highlevel eth1394_highlevel;/* Use common.lf to determine header len */static const int hdr_type_len[] = {	sizeof (struct eth1394_uf_hdr),	sizeof (struct eth1394_ff_hdr),	sizeof (struct eth1394_sf_hdr),	sizeof (struct eth1394_sf_hdr)};/* Change this to IEEE1394_SPEED_S100 to make testing easier */#define ETH1394_SPEED_DEF	IEEE1394_SPEED_MAX/* For now, this needs to be 1500, so that XP works with us */#define ETH1394_DATA_LEN	ETH_DATA_LENstatic const u16 eth1394_speedto_maxpayload[] = {/*     S100, S200, S400, S800, S1600, S3200 */	512, 1024, 2048, 4096,  4096,  4096};MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");MODULE_LICENSE("GPL");/* The max_partial_datagrams parameter is the maximum number of fragmented * datagrams per node that eth1394 will keep in memory.  Providing an upper * bound allows us to limit the amount of memory that partial datagrams * consume in the event that some partial datagrams are never completed.  This * should probably change to a sysctl item or the like if possible. */MODULE_PARM(max_partial_datagrams, "i");MODULE_PARM_DESC(max_partial_datagrams,		 "Maximum number of partially received fragmented datagrams "		 "(default = 25).");static int max_partial_datagrams = 25;static int ether1394_header(struct sk_buff *skb, struct net_device *dev,			    unsigned short type, void *daddr, void *saddr,			    unsigned len);static int ether1394_rebuild_header(struct sk_buff *skb);static int ether1394_header_parse(struct sk_buff *skb, unsigned char *haddr);static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh);static void ether1394_header_cache_update(struct hh_cache *hh,					  struct net_device *dev,					  unsigned char * haddr);static int ether1394_mac_addr(struct net_device *dev, void *p);static inline void purge_partial_datagram(struct list_head *old);static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);static void ether1394_iso(struct hpsb_iso *iso);static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr);static void eth1394_iso_shutdown(struct eth1394_priv *priv){	priv->bc_state = ETHER1394_BC_CLOSED;	if (priv->iso != NULL) {		if (!in_interrupt())			hpsb_iso_shutdown(priv->iso);		priv->iso = NULL;	}}static int ether1394_init_bc(struct net_device *dev){	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;	/* First time sending?  Need a broadcast channel for ARP and for	 * listening on */	if (priv->bc_state == ETHER1394_BC_CHECK) {		quadlet_t bc;		/* Get the local copy of the broadcast channel and check its		 * validity (the IRM should validate it for us) */		bc = priv->host->csr.broadcast_channel;		if ((bc & 0xc0000000) != 0xc0000000) {			/* broadcast channel not validated yet */			ETH1394_PRINT(KERN_WARNING, dev->name,				      "Error BROADCAST_CHANNEL register valid "				      "bit not set, can't send IP traffic\n");			eth1394_iso_shutdown(priv);			return -EAGAIN;		}		if (priv->broadcast_channel != (bc & 0x3f)) {			/* This really shouldn't be possible, but just in case			 * the IEEE 1394 spec changes regarding broadcast			 * channels in the future. */			eth1394_iso_shutdown(priv);			if (in_interrupt())				return -EAGAIN;			priv->broadcast_channel = bc & 0x3f;			ETH1394_PRINT(KERN_INFO, dev->name,				      "Changing to broadcast channel %d...\n",				      priv->broadcast_channel);			priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096,						       16, priv->broadcast_channel,						       1, ether1394_iso);			if (priv->iso == NULL) {				ETH1394_PRINT(KERN_ERR, dev->name,					      "failed to change broadcast "					      "channel\n");				return -EAGAIN;			}		}		if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) {			ETH1394_PRINT(KERN_ERR, dev->name,				      "Could not start data stream reception\n");			eth1394_iso_shutdown(priv);			return -EAGAIN;		}		priv->bc_state = ETHER1394_BC_OPENED;	}    	return 0;}/* This is called after an "ifup" */static int ether1394_open (struct net_device *dev){	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;	unsigned long flags;	int ret;	/* Something bad happened, don't even try */	if (priv->bc_state == ETHER1394_BC_CLOSED)		return -EAGAIN;	spin_lock_irqsave(&priv->lock, flags);	ret = ether1394_init_bc(dev);	spin_unlock_irqrestore(&priv->lock, flags);	if (ret)		return ret;	netif_start_queue (dev);	return 0;}/* This is called after an "ifdown" */static int ether1394_stop (struct net_device *dev){	netif_stop_queue (dev);	return 0;}/* Return statistics to the caller */static struct net_device_stats *ether1394_stats (struct net_device *dev){	return &(((struct eth1394_priv *)dev->priv)->stats);}/* What to do if we timeout. I think a host reset is probably in order, so * that's what we do. Should we increment the stat counters too?  */static void ether1394_tx_timeout (struct net_device *dev){	ETH1394_PRINT (KERN_ERR, dev->name, "Timeout, resetting host %s\n",		       ((struct eth1394_priv *)(dev->priv))->host->driver->name);	highlevel_host_reset (((struct eth1394_priv *)(dev->priv))->host);	netif_wake_queue (dev);}static int ether1394_change_mtu(struct net_device *dev, int new_mtu){	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;	int phy_id = NODEID_TO_NODE(priv->host->node_id);	if ((new_mtu < 68) || (new_mtu > min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] -					     (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD)))))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static inline void ether1394_register_limits(int nodeid, u16 maxpayload,					     unsigned char sspd, u64 eui, u64 fifo,					     struct eth1394_priv *priv){	if (nodeid < 0 || nodeid >= ALL_NODES) {		ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid);		return;	}	priv->maxpayload[nodeid]	= maxpayload;	priv->sspd[nodeid]		= sspd;	priv->fifo[nodeid]		= fifo;	priv->eui[nodeid]		= eui;	priv->maxpayload[ALL_NODES] = min(priv->maxpayload[ALL_NODES], maxpayload);	priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd);	return;}static void ether1394_reset_priv (struct net_device *dev, int set_mtu){	unsigned long flags;	int i;	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;	struct hpsb_host *host = priv->host;	int phy_id = NODEID_TO_NODE(host->node_id);	u64 guid = *((u64*)&(host->csr.rom[3]));	u16 maxpayload = 1 << (((be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf) + 1);	spin_lock_irqsave (&priv->lock, flags);	/* Clear the speed/payload/offset tables */	memset (priv->maxpayload, 0, sizeof (priv->maxpayload));	memset (priv->sspd, 0, sizeof (priv->sspd));	memset (priv->fifo, 0, sizeof (priv->fifo));	priv->sspd[ALL_NODES] = ETH1394_SPEED_DEF;	priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[priv->sspd[ALL_NODES]];	priv->bc_state = ETHER1394_BC_CHECK;	/* Register our limits now */	ether1394_register_limits(phy_id, maxpayload,				  host->speed_map[(phy_id << 6) + phy_id],				  guid, ETHER1394_REGION_ADDR, priv);	/* We'll use our maxpayload as the default mtu */	if (set_mtu) {		dev->mtu = min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] -			       (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD)));		/* Set our hardware address while we're at it */		*(u64*)dev->dev_addr = guid;		*(u64*)dev->broadcast = ~0x0ULL;	}	spin_unlock_irqrestore (&priv->lock, flags);	for (i = 0; i < ALL_NODES; i++) {		struct list_head *lh, *n;		spin_lock_irqsave(&priv->pdg[i].lock, flags);		if (!set_mtu) {			list_for_each_safe(lh, n, &priv->pdg[i].list) {				purge_partial_datagram(lh);			}		}		INIT_LIST_HEAD(&(priv->pdg[i].list));		priv->pdg[i].sz = 0;		spin_unlock_irqrestore(&priv->pdg[i].lock, flags);	}}/* This function is called by register_netdev */static int ether1394_init_dev (struct net_device *dev){	/* Our functions */	dev->open		= ether1394_open;	dev->stop		= ether1394_stop;	dev->hard_start_xmit	= ether1394_tx;	dev->get_stats		= ether1394_stats;	dev->tx_timeout		= ether1394_tx_timeout;	dev->change_mtu		= ether1394_change_mtu;	dev->hard_header	= ether1394_header;	dev->rebuild_header	= ether1394_rebuild_header;	dev->hard_header_cache	= ether1394_header_cache;	dev->header_cache_update= ether1394_header_cache_update;	dev->hard_header_parse	= ether1394_header_parse;	dev->set_mac_address	= ether1394_mac_addr;	dev->do_ioctl		= ether1394_do_ioctl;	/* Some constants */	dev->watchdog_timeo	= ETHER1394_TIMEOUT;	dev->flags		= IFF_BROADCAST | IFF_MULTICAST;	dev->features		= NETIF_F_HIGHDMA;	dev->addr_len		= ETH1394_ALEN;	dev->hard_header_len 	= ETH1394_HLEN;	dev->type		= ARPHRD_IEEE1394;	ether1394_reset_priv (dev, 1);	return 0;}/* * This function is called every time a card is found. It is generally called * when the module is installed. This is where we add all of our ethernet * devices. One for each host. */static void ether1394_add_host (struct hpsb_host *host)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -