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

📄 eth1394.c

📁 这个是uClinux下的ieee1394驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * eth1394.c -- Ethernet driver for Linux IEEE-1394 Subsystem *  * Copyright (C) 2001 Ben Collins <bcollins@debian.org> *               2000 Bonin Franck <boninf@free.fr> * * 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. *//* State of this driver: * * 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. A few issues are: * *   - Does not support send/recv over Async streams using GASP *     packet formats, as per the RFC for ARP requests. *   - Does not yet support fragmented packets. *   - Relies on hardware address being equal to the nodeid for some things. *   - Does not support multicast *   - Hardcoded address for sending packets, instead of using discovery *     (ARP, see first item) */#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/tcp.h>#include <linux/skbuff.h>#include <asm/delay.h>#include <asm/semaphore.h>#include <asm/bitops.h>#include <net/arp.h>#include "ieee1394_types.h"#include "ieee1394_core.h"#include "ieee1394_transactions.h"#include "ieee1394.h"#include "highlevel.h"#include "eth1394.h"#define ETH1394_PRINT_G(level, fmt, args...) \	printk(level ETHER1394_DRIVER_NAME": "fmt, ## args)#define ETH1394_PRINT(level, dev_name, fmt, args...) \	printk(level ETHER1394_DRIVER_NAME": %s: " fmt, dev_name, ## args)#define DEBUG(fmt, args...) \	printk(KERN_ERR fmt, ## args)static char version[] __devinitdata =	"$Rev: 546 $ Ben Collins <bcollins@debian.org>";/* Our ieee1394 highlevel driver */#define ETHER1394_DRIVER_NAME "ether1394"static kmem_cache_t *packet_task_cache;static struct hpsb_highlevel *hl_handle = NULL;/* Card handling */static LIST_HEAD (host_info_list);static spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;/* Use common.lf to determine header len */static int hdr_type_len[] = {	sizeof (struct eth1394_uf_hdr),	sizeof (struct eth1394_ff_hdr),	sizeof (struct eth1394_sf_hdr),	sizeof (struct eth1394_sf_hdr)};MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");MODULE_LICENSE("GPL");/* Find our host_info struct for a given host pointer. Must be called * under spinlock.  */static inline struct host_info *find_host_info (struct hpsb_host *host){	struct list_head *lh;	struct host_info *hi;	lh = host_info_list.next;	while (lh != &host_info_list) {		hi = list_entry (lh, struct host_info, list);		if (hi->host == host)			return hi;		lh = lh->next;	}	return NULL;}/* Find the network device for our host */static inline struct net_device *ether1394_find_dev (struct hpsb_host *host){	struct host_info *hi;	spin_lock_irq (&host_info_lock);	hi = find_host_info (host);	spin_unlock_irq (&host_info_lock);	if (hi == NULL)		return NULL;	return hi->dev;}/* This is called after an "ifup" */static int ether1394_open (struct net_device *dev){	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;	/* Set the spinlock before grabbing IRQ! */	priv->lock = SPIN_LOCK_UNLOCKED;	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);}/* We need to encapsulate the standard header with our own. We use the * ethernet header's proto for our own. * * XXX: This is where we need to create a list of skb's for fragmented * packets.  */static inline void ether1394_encapsulate (struct sk_buff *skb, struct net_device *dev,			    int proto){	union eth1394_hdr *hdr =		(union eth1394_hdr *)skb_push (skb, hdr_type_len[ETH1394_HDR_LF_UF]);	hdr->common.lf = ETH1394_HDR_LF_UF;	hdr->words.word1 = htons(hdr->words.word1);	hdr->uf.ether_type = proto;	return;}/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the * entire arphdr) is the same format as the ip1394 header, so they * overlap. The rest needs to be munged a bit. The remainder of the * arphdr is formatted based on hwaddr len and ipaddr len. We know what * they'll be, so it's easy to judge.  */static inline void ether1394_arp_to_1394arp (struct sk_buff *skb, struct net_device *dev){	struct eth1394_priv *priv =		(struct eth1394_priv *)(dev->priv);	u16 phy_id = priv->host->node_id & NODE_MASK;	unsigned char *arp_ptr = (unsigned char *)skb->data;	struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;	unsigned char arp_data[2*(dev->addr_len+4)];	/* Copy the main data that we need */	arp_ptr = memcpy (arp_data, arp_ptr + sizeof(struct arphdr), sizeof (arp_data));	/* Extend the buffer enough for our new header */	skb_put (skb, sizeof (struct eth1394_arp) -		 (sizeof (arp_data) + sizeof (struct arphdr)));#define PROCESS_MEMBER(ptr,val,len) \  memcpy (val, ptr, len); ptr += len	arp_ptr += arp1394->hw_addr_len;	PROCESS_MEMBER (arp_ptr, &arp1394->sip, arp1394->ip_addr_len);	arp_ptr += arp1394->hw_addr_len;	PROCESS_MEMBER (arp_ptr, &arp1394->tip, arp1394->ip_addr_len);#undef PROCESS_MEMBER	/* Now add our own flavor of arp header fields to the orig one */	arp1394->hw_addr_len	= IP1394_HW_ADDR_LEN;	arp1394->hw_type	= __constant_htons (ARPHRD_IEEE1394);	arp1394->s_uniq_id	= cpu_to_le64 (priv->eui[phy_id]);	arp1394->max_rec	= priv->max_rec[phy_id];	arp1394->sspd		= priv->sspd[phy_id];	arp1394->fifo_hi	= htons (priv->fifo_hi[phy_id]);	arp1394->fifo_lo	= htonl (priv->fifo_lo[phy_id]);	return;}static int ether1394_change_mtu(struct net_device *dev, int new_mtu){	if ((new_mtu < 68) || (new_mtu > ETHER1394_REGION_ADDR_LEN))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static inline void ether1394_register_limits (int nodeid, unsigned char max_rec,				       unsigned char sspd, u64 eui, u16 fifo_hi,				       u32 fifo_lo, struct eth1394_priv *priv){	int i;	if (nodeid < 0 || nodeid >= ALL_NODES) {		ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid);		return;	}	priv->max_rec[nodeid]	= max_rec;	priv->sspd[nodeid]	= sspd;	priv->fifo_hi[nodeid]	= fifo_hi;	priv->fifo_lo[nodeid]	= fifo_lo;	priv->eui[nodeid]	= eui;	/* 63 is used for broadcasts to all hosts. It is equal to the	 * minimum of all registered nodes. A registered node is one with	 * a nonzero offset. Set the values rediculously high to start. We	 * know we have atleast one to change the default to.  */	sspd = 0xff;	max_rec = 0xff;	for (i = 0; i < ALL_NODES; i++) {		if (!priv->fifo_hi && !priv->fifo_lo) continue; /* Unregistered */		if (priv->max_rec[i] < max_rec) max_rec = priv->max_rec[i];		if (priv->sspd[i] < sspd) sspd = priv->sspd[i];	}	priv->max_rec[ALL_NODES] = max_rec;	priv->sspd[ALL_NODES] = sspd;	return;}static void ether1394_reset_priv (struct net_device *dev, int set_mtu){	unsigned long flags;	struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv;	int phy_id = priv->host->node_id & NODE_MASK;	spin_lock_irqsave (&priv->lock, flags);	/* Clear the speed/payload/offset tables */	memset (priv->max_rec, 0, sizeof (priv->max_rec));	memset (priv->sspd, 0, sizeof (priv->sspd));	memset (priv->fifo_hi, 0, sizeof (priv->fifo_hi));	memset (priv->fifo_lo, 0, sizeof (priv->fifo_lo));	/* Register our limits now */	ether1394_register_limits (phy_id, (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf,				   priv->host->speed_map[(phy_id << 6) + phy_id],				   (u64)(((u64)be32_to_cpu(priv->host->csr.rom[3]) << 32) |				   be32_to_cpu(priv->host->csr.rom[4])),				   ETHER1394_REGION_ADDR >> 32,				   ETHER1394_REGION_ADDR & 0xffffffff, priv);	/* We'll use our max_rec as the default mtu */	if (set_mtu)		dev->mtu = (1 << (priv->max_rec[phy_id] + 1)) - sizeof (union eth1394_hdr);	/* Set our hardware address while we're at it */	*(nodeid_t *)dev->dev_addr = htons (priv->host->node_id);	spin_unlock_irqrestore (&priv->lock, flags);}static int ether1394_tx (struct sk_buff *skb, struct net_device *dev);/* 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;	/* Some constants */	dev->watchdog_timeo	= ETHER1394_TIMEOUT;	dev->flags		= IFF_BROADCAST; /* TODO: Support MCAP */	dev->features		= NETIF_F_NO_CSUM|NETIF_F_SG|NETIF_F_HIGHDMA|NETIF_F_FRAGLIST;	dev->addr_len		= 2;	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){	struct host_info *hi = NULL;	struct net_device *dev = NULL;	struct eth1394_priv *priv;	static int version_printed = 0;	if (version_printed++ == 0)		ETH1394_PRINT_G (KERN_INFO, "%s\n", version);	dev = alloc_etherdev(sizeof (struct eth1394_priv));	if (dev == NULL)		goto out;	SET_MODULE_OWNER(dev);	dev->init = ether1394_init_dev;	priv = (struct eth1394_priv *)dev->priv;	priv->host = host;	hi = (struct host_info *)kmalloc (sizeof (struct host_info),					  GFP_KERNEL);	if (hi == NULL)		goto out;	if (register_netdev (dev)) {		ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n");		kfree (dev);		return;	}

⌨️ 快捷键说明

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