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

📄 eth1394.c

📁 这是关于ieee1394的最新源码,上面包含了所有更新的部分!
💻 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 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 * - 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/unaligned.h>#include <net/arp.h>#include "config_roms.h"#include "csr1212.h"#include "eth1394.h"#include "highlevel.h"#include "ieee1394.h"#include "ieee1394_core.h"#include "ieee1394_hotplug.h"#include "ieee1394_transactions.h"#include "ieee1394_types.h"#include "iso.h"#include "nodemgr.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__)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;};struct pdg_list {	struct list_head list;		/* partial datagram list per node	*/	unsigned int sz;		/* partial datagram list size per node	*/	spinlock_t lock;		/* partial datagram lock		*/};struct eth1394_host_info {	struct hpsb_host *host;	struct net_device *dev;};struct eth1394_node_ref {	struct unit_directory *ud;	struct list_head list;};struct eth1394_node_info {	u16 maxpayload;			/* Max payload			*/	u8 sspd;			/* Max speed			*/	u64 fifo;			/* FIFO address			*/	struct pdg_list pdg;		/* partial RX datagram lists	*/	int dgl;			/* Outgoing datagram label	*/};/* Our ieee1394 highlevel driver */#define ETH1394_DRIVER_NAME "eth1394"static const char driver_name[] = ETH1394_DRIVER_NAME;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. */static int max_partial_datagrams = 25;module_param(max_partial_datagrams, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(max_partial_datagrams,		 "Maximum number of partially received fragmented datagrams "		 "(default = 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 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 struct ethtool_ops ethtool_ops;static int ether1394_write(struct hpsb_host *host, int srcid, int destid,			   quadlet_t *data, u64 addr, size_t len, u16 flags);static void ether1394_add_host (struct hpsb_host *host);static void ether1394_remove_host (struct hpsb_host *host);static void ether1394_host_reset (struct hpsb_host *host);/* Function for incoming 1394 packets */static struct hpsb_address_ops addr_ops = {	.write =	ether1394_write,};/* Ieee1394 highlevel driver functions */static struct hpsb_highlevel eth1394_highlevel = {	.name =		driver_name,	.add_host =	ether1394_add_host,	.remove_host =	ether1394_remove_host,	.host_reset =	ether1394_host_reset,};/* This is called after an "ifup" */static int ether1394_open (struct net_device *dev){	struct eth1394_priv *priv = netdev_priv(dev);	int ret = 0;	/* Something bad happened, don't even try */	if (priv->bc_state == ETHER1394_BC_ERROR) {		/* we'll try again */		priv->iso = hpsb_iso_recv_init(priv->host,					       ETHER1394_ISO_BUF_SIZE,					       ETHER1394_GASP_BUFFERS,					       priv->broadcast_channel,					       HPSB_ISO_DMA_PACKET_PER_BUFFER,					       1, ether1394_iso);		if (priv->iso == NULL) {			ETH1394_PRINT(KERN_ERR, dev->name,				      "Could not allocate isochronous receive "				      "context for the broadcast channel\n");			priv->bc_state = ETHER1394_BC_ERROR;			ret = -EAGAIN;		} else {			if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0)				priv->bc_state = ETHER1394_BC_STOPPED;			else				priv->bc_state = ETHER1394_BC_RUNNING;		}	}	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 *)netdev_priv(dev))->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 *)netdev_priv(dev))->host->driver->name);	highlevel_host_reset (((struct eth1394_priv *)netdev_priv(dev))->host);	netif_wake_queue (dev);}static int ether1394_change_mtu(struct net_device *dev, int new_mtu){	struct eth1394_priv *priv = netdev_priv(dev);	if ((new_mtu < 68) ||	    (new_mtu > min(ETH1394_DATA_LEN,			   (int)((1 << (priv->host->csr.max_rec + 1)) -				 (sizeof(union eth1394_hdr) +				  ETHER1394_GASP_OVERHEAD)))))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static void purge_partial_datagram(struct list_head *old){	struct partial_datagram *pd = list_entry(old, struct partial_datagram, list);	struct list_head *lh, *n;	list_for_each_safe(lh, n, &pd->frag_info) {		struct fragment_info *fi = list_entry(lh, struct fragment_info, list);		list_del(lh);		kfree(fi);	}	list_del(old);	kfree_skb(pd->skb);	kfree(pd);}/****************************************** * 1394 bus activity functions ******************************************/static struct eth1394_node_ref *eth1394_find_node(struct list_head *inl,						  struct unit_directory *ud){	struct eth1394_node_ref *node;	list_for_each_entry(node, inl, list)		if (node->ud == ud)			return node;	return NULL;}static struct eth1394_node_ref *eth1394_find_node_guid(struct list_head *inl,						       u64 guid){	struct eth1394_node_ref *node;	list_for_each_entry(node, inl, list)		if (node->ud->ne->guid == guid)			return node;	return NULL;}static struct eth1394_node_ref *eth1394_find_node_nodeid(struct list_head *inl,							 nodeid_t nodeid){	struct eth1394_node_ref *node;	list_for_each_entry(node, inl, list) {		if (node->ud->ne->nodeid == nodeid)			return node;	}	return NULL;}static int eth1394_probe(struct device *dev){	struct unit_directory *ud;	struct eth1394_host_info *hi;	struct eth1394_priv *priv;	struct eth1394_node_ref *new_node;	struct eth1394_node_info *node_info;	ud = container_of(dev, struct unit_directory, device);	hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);	if (!hi)		return -ENOENT;	new_node = kmalloc(sizeof(*new_node),			   in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);	if (!new_node)		return -ENOMEM;	node_info = kmalloc(sizeof(*node_info),			    in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);	if (!node_info) {		kfree(new_node);		return -ENOMEM;	}	spin_lock_init(&node_info->pdg.lock);	INIT_LIST_HEAD(&node_info->pdg.list);	node_info->pdg.sz = 0;	node_info->fifo = CSR1212_INVALID_ADDR_SPACE;	ud->device.driver_data = node_info;	new_node->ud = ud;	priv = netdev_priv(hi->dev);	list_add_tail(&new_node->list, &priv->ip_node_list);	return 0;}static int eth1394_remove(struct device *dev){	struct unit_directory *ud;	struct eth1394_host_info *hi;	struct eth1394_priv *priv;	struct eth1394_node_ref *old_node;	struct eth1394_node_info *node_info;	struct list_head *lh, *n;	unsigned long flags;	ud = container_of(dev, struct unit_directory, device);	hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);	if (!hi)		return -ENOENT;	priv = netdev_priv(hi->dev);	old_node = eth1394_find_node(&priv->ip_node_list, ud);	if (old_node) {		list_del(&old_node->list);		kfree(old_node);		node_info = (struct eth1394_node_info*)ud->device.driver_data;		spin_lock_irqsave(&node_info->pdg.lock, flags);		/* The partial datagram list should be empty, but we'll just		 * make sure anyway... */		list_for_each_safe(lh, n, &node_info->pdg.list) {			purge_partial_datagram(lh);		}		spin_unlock_irqrestore(&node_info->pdg.lock, flags);		kfree(node_info);		ud->device.driver_data = NULL;	}	return 0;}static int eth1394_update(struct unit_directory *ud){	struct eth1394_host_info *hi;	struct eth1394_priv *priv;	struct eth1394_node_ref *node;	struct eth1394_node_info *node_info;	hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);	if (!hi)		return -ENOENT;	priv = netdev_priv(hi->dev);	node = eth1394_find_node(&priv->ip_node_list, ud);	if (!node) {		node = kmalloc(sizeof(*node),			       in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);		if (!node)			return -ENOMEM;		node_info = kmalloc(sizeof(*node_info),				    in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);		if (!node_info) {			kfree(node);			return -ENOMEM;		}

⌨️ 快捷键说明

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