?? eth1394.c
字號:
/* * 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 + -