📄 eth1394.c
字号:
return 0;
return eth1394_new_node(hi, ud);
}
static struct ieee1394_device_id eth1394_id_table[] = {
{
.match_flags = (IEEE1394_MATCH_SPECIFIER_ID |
IEEE1394_MATCH_VERSION),
.specifier_id = ETHER1394_GASP_SPECIFIER_ID,
.version = ETHER1394_GASP_VERSION,
},
{}
};
MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
static struct hpsb_protocol_driver eth1394_proto_driver = {
.name = driver_name,
.id_table = eth1394_id_table,
.update = eth1394_update,
.driver = {
.probe = eth1394_probe,
.remove = eth1394_remove,
},
};
static void ether1394_reset_priv(struct net_device *dev, int set_mtu)
{
unsigned long flags;
int i;
struct eth1394_priv *priv = netdev_priv(dev);
struct hpsb_host *host = priv->host;
u64 guid = get_unaligned((u64 *)&(host->csr.rom->bus_info_data[3]));
int max_speed = IEEE1394_SPEED_MAX;
spin_lock_irqsave(&priv->lock, flags);
memset(priv->ud_list, 0, sizeof(priv->ud_list));
priv->bc_maxpayload = 512;
/* Determine speed limit */
/* FIXME: This is broken for nodes with link speed < PHY speed,
* and it is suboptimal for S200B...S800B hardware.
* The result of nodemgr's speed probe should be used somehow. */
for (i = 0; i < host->node_count; i++) {
/* take care of S100B...S400B PHY ports */
if (host->speed[i] == SELFID_SPEED_UNKNOWN) {
max_speed = IEEE1394_SPEED_100;
break;
}
if (max_speed > host->speed[i])
max_speed = host->speed[i];
}
priv->bc_sspd = max_speed;
if (set_mtu) {
/* Use the RFC 2734 default 1500 octets or the maximum payload
* as initial MTU */
dev->mtu = min(1500, ether1394_max_mtu(host));
/* Set our hardware address while we're at it */
memcpy(dev->dev_addr, &guid, sizeof(u64));
memset(dev->broadcast, 0xff, sizeof(u64));
}
spin_unlock_irqrestore(&priv->lock, flags);
}
static void ether1394_init_dev(struct net_device *dev)
{
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;
SET_ETHTOOL_OPS(dev, ðtool_ops);
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;
/* FIXME: This value was copied from ether_setup(). Is it too much? */
dev->tx_queue_len = 1000;
}
/*
* Wake the queue up after commonly encountered transmit failure conditions are
* hopefully over. Currently only tlabel exhaustion is accounted for.
*/
static void ether1394_wake_queue(struct work_struct *work)
{
struct eth1394_priv *priv;
struct hpsb_packet *packet;
priv = container_of(work, struct eth1394_priv, wake);
packet = hpsb_alloc_packet(0);
/* This is really bad, but unjam the queue anyway. */
if (!packet)
goto out;
packet->host = priv->host;
packet->node_id = priv->wake_node;
/*
* A transaction label is all we really want. If we get one, it almost
* always means we can get a lot more because the ieee1394 core recycled
* a whole batch of tlabels, at last.
*/
if (hpsb_get_tlabel(packet) == 0)
hpsb_free_tlabel(packet);
hpsb_free_packet(packet);
out:
netif_wake_queue(priv->wake_dev);
}
/*
* 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 eth1394_host_info *hi = NULL;
struct net_device *dev = NULL;
struct eth1394_priv *priv;
u64 fifo_addr;
if (hpsb_config_rom_ip1394_add(host) != 0) {
ETH1394_PRINT_G(KERN_ERR, "Can't add IP-over-1394 ROM entry\n");
return;
}
fifo_addr = hpsb_allocate_and_register_addrspace(
ð1394_highlevel, host, &addr_ops,
ETHER1394_REGION_ADDR_LEN, ETHER1394_REGION_ADDR_LEN,
CSR1212_INVALID_ADDR_SPACE, CSR1212_INVALID_ADDR_SPACE);
if (fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
ETH1394_PRINT_G(KERN_ERR, "Cannot register CSR space\n");
hpsb_config_rom_ip1394_remove(host);
return;
}
dev = alloc_netdev(sizeof(*priv), "eth%d", ether1394_init_dev);
if (dev == NULL) {
ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
goto out;
}
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &host->device);
priv = netdev_priv(dev);
INIT_LIST_HEAD(&priv->ip_node_list);
spin_lock_init(&priv->lock);
priv->host = host;
priv->local_fifo = fifo_addr;
INIT_WORK(&priv->wake, ether1394_wake_queue);
priv->wake_dev = dev;
hi = hpsb_create_hostinfo(ð1394_highlevel, host, sizeof(*hi));
if (hi == NULL) {
ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
goto out;
}
ether1394_reset_priv(dev, 1);
if (register_netdev(dev)) {
ETH1394_PRINT_G(KERN_ERR, "Cannot register the driver\n");
goto out;
}
ETH1394_PRINT(KERN_INFO, dev->name, "IPv4 over IEEE 1394 (fw-host%d)\n",
host->id);
hi->host = host;
hi->dev = dev;
/* Ignore validity in hopes that it will be set in the future. It'll
* be checked when the eth device is opened. */
priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
ether1394_recv_init(priv);
return;
out:
if (dev)
free_netdev(dev);
if (hi)
hpsb_destroy_hostinfo(ð1394_highlevel, host);
hpsb_unregister_addrspace(ð1394_highlevel, host, fifo_addr);
hpsb_config_rom_ip1394_remove(host);
}
/* Remove a card from our list */
static void ether1394_remove_host(struct hpsb_host *host)
{
struct eth1394_host_info *hi;
struct eth1394_priv *priv;
hi = hpsb_get_hostinfo(ð1394_highlevel, host);
if (!hi)
return;
priv = netdev_priv(hi->dev);
hpsb_unregister_addrspace(ð1394_highlevel, host, priv->local_fifo);
hpsb_config_rom_ip1394_remove(host);
if (priv->iso)
hpsb_iso_shutdown(priv->iso);
unregister_netdev(hi->dev);
free_netdev(hi->dev);
}
/* A bus reset happened */
static void ether1394_host_reset(struct hpsb_host *host)
{
struct eth1394_host_info *hi;
struct eth1394_priv *priv;
struct net_device *dev;
struct list_head *lh, *n;
struct eth1394_node_ref *node;
struct eth1394_node_info *node_info;
unsigned long flags;
hi = hpsb_get_hostinfo(ð1394_highlevel, host);
/* This can happen for hosts that we don't use */
if (!hi)
return;
dev = hi->dev;
priv = netdev_priv(dev);
/* Reset our private host data, but not our MTU */
netif_stop_queue(dev);
ether1394_reset_priv(dev, 0);
list_for_each_entry(node, &priv->ip_node_list, list) {
node_info = node->ud->device.driver_data;
spin_lock_irqsave(&node_info->pdg.lock, flags);
list_for_each_safe(lh, n, &node_info->pdg.list)
purge_partial_datagram(lh);
INIT_LIST_HEAD(&(node_info->pdg.list));
node_info->pdg.sz = 0;
spin_unlock_irqrestore(&node_info->pdg.lock, flags);
}
netif_wake_queue(dev);
}
/******************************************
* HW Header net device functions
******************************************/
/* These functions have been adapted from net/ethernet/eth.c */
/* Create a fake MAC header for an arbitrary protocol layer.
* saddr=NULL means use device source address
* daddr=NULL means leave destination address (eg unresolved arp). */
static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len)
{
struct eth1394hdr *eth =
(struct eth1394hdr *)skb_push(skb, ETH1394_HLEN);
eth->h_proto = htons(type);
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
memset(eth->h_dest, 0, dev->addr_len);
return dev->hard_header_len;
}
if (daddr) {
memcpy(eth->h_dest, daddr, dev->addr_len);
return dev->hard_header_len;
}
return -dev->hard_header_len;
}
/* Rebuild the faked MAC header. This is called after an ARP
* (or in future other address resolution) has completed on this
* sk_buff. We now let ARP fill in the other fields.
*
* This routine CANNOT use cached dst->neigh!
* Really, it is used only when dst->neigh is wrong.
*/
static int ether1394_rebuild_header(struct sk_buff *skb)
{
struct eth1394hdr *eth = (struct eth1394hdr *)skb->data;
if (eth->h_proto == htons(ETH_P_IP))
return arp_find((unsigned char *)ð->h_dest, skb);
ETH1394_PRINT(KERN_DEBUG, skb->dev->name,
"unable to resolve type %04x addresses\n",
ntohs(eth->h_proto));
return 0;
}
static int ether1394_header_parse(struct sk_buff *skb, unsigned char *haddr)
{
struct net_device *dev = skb->dev;
memcpy(haddr, dev->dev_addr, ETH1394_ALEN);
return ETH1394_ALEN;
}
static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh)
{
unsigned short type = hh->hh_type;
struct net_device *dev = neigh->dev;
struct eth1394hdr *eth =
(struct eth1394hdr *)((u8 *)hh->hh_data + 16 - ETH1394_HLEN);
if (type == htons(ETH_P_802_3))
return -1;
eth->h_proto = type;
memcpy(eth->h_dest, neigh->ha, dev->addr_len);
hh->hh_len = ETH1394_HLEN;
return 0;
}
/* Called by Address Resolution module to notify changes in address. */
static void ether1394_header_cache_update(struct hh_cache *hh,
struct net_device *dev,
unsigned char * haddr)
{
memcpy((u8 *)hh->hh_data + 16 - ETH1394_HLEN, haddr, dev->addr_len);
}
/******************************************
* Datagram reception code
******************************************/
/* Copied from net/ethernet/eth.c */
static u16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct eth1394hdr *eth;
unsigned char *rawp;
skb_reset_mac_header(skb);
skb_pull(skb, ETH1394_HLEN);
eth = eth1394_hdr(skb);
if (*eth->h_dest & 1) {
if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len) == 0)
skb->pkt_type = PACKET_BROADCAST;
#if 0
else
skb->pkt_type = PACKET_MULTICAST;
#endif
} else {
if (memcmp(eth->h_dest, dev->dev_addr, dev->addr_len))
skb->pkt_type = PACKET_OTHERHOST;
}
if (ntohs(eth->h_proto) >= 1536)
return eth->h_proto;
rawp = skb->data;
if (*(unsigned short *)rawp == 0xFFFF)
return htons(ETH_P_802_3);
return htons(ETH_P_802_2);
}
/* Parse an encapsulated IP1394 header into an ethernet frame packet.
* We also perform ARP translation here, if need be. */
static u16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev,
nodeid_t srcid, nodeid_t destid,
u16 ether_type)
{
struct eth1394_priv *priv = netdev_priv(dev);
u64 dest_hw;
unsigned short ret = 0;
/* Setup our hw addresses. We use these to build the ethernet header. */
if (destid == (LOCAL_BUS | ALL_NODES))
dest_hw = ~0ULL; /* broadcast */
else
dest_hw = cpu_to_be64((u64)priv->host->csr.guid_hi << 32 |
priv->host->csr.guid_lo);
/* If this is an ARP packet, convert it. First, we want to make
* use of some of the fields, since they tell us a little bit
* about the sending machine. */
if (ether_type == htons(ETH_P_ARP)) {
struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
struct arphdr *arp = (struct arphdr *)skb->data;
unsigned char *arp_ptr = (unsigned char *)(arp + 1);
u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 |
ntohl(arp1394->fifo_lo);
u8 max_rec = min(priv->host->csr.max_rec,
(u8)(arp1394->max_rec));
int sspd = arp1394->sspd;
u16 maxpayload;
struct eth1394_node_ref *node;
struct eth1394_node_info *node_info;
__be64 guid;
/* Sanity check. MacOSX seems to be sending us 131 in this
* field (atleast on my Panther G5). Not sure why. */
if (sspd > 5 || sspd < 0)
sspd = 0;
maxpayload = min(eth1394_speedto_maxpayload[sspd],
(u16)(1 << (max_rec + 1)));
guid = get_unaligned(&arp1394->s_uniq_id);
node = eth1394_find_node_guid(&priv->ip_node_list,
be64_to_cpu(guid));
if (!node)
return 0;
node_info =
(struct eth1394_node_info *)node->ud->device.driver_data;
/* Update our speed/payload/fifo_offset table */
node_info->maxpayload = maxpayload;
node_info->sspd = sspd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -