eth1394.c
来自「linux 内核源代码」· C语言 代码 · 共 1,753 行 · 第 1/4 页
C
1,753 行
node = eth1394_find_node(&priv->ip_node_list, ud); if (node) 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 const struct header_ops ether1394_header_ops = { .create = ether1394_header, .rebuild = ether1394_rebuild_header, .cache = ether1394_header_cache, .cache_update = ether1394_header_cache_update, .parse = ether1394_header_parse,};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->header_ops = ðer1394_header_ops; 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_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, const void *daddr, const 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(const struct sk_buff *skb, unsigned char *haddr){ memcpy(haddr, skb->dev->dev_addr, ETH1394_ALEN); return ETH1394_ALEN;}static int ether1394_header_cache(const 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, const struct net_device *dev, const 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 =
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?