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