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

📄 eth1394.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 4 页
字号:
		INIT_LIST_HEAD(&node_info->pdg.list);		node_info->pdg.sz = 0;		ud->device.driver_data = node_info;		node->ud = ud;		priv = netdev_priv(hi->dev);		list_add_tail(&node->list, &priv->ip_node_list);	}	return 0;}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		= ETH1394_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]));	u16 maxpayload = 1 << (host->csr.max_rec + 1);	int max_speed = IEEE1394_SPEED_MAX;	spin_lock_irqsave (&priv->lock, flags);	memset(priv->ud_list, 0, sizeof(struct node_entry*) * ALL_NODES);	priv->bc_maxpayload = 512;	/* Determine speed limit */	for (i = 0; i < host->node_count; i++)		if (max_speed > host->speed[i])			max_speed = host->speed[i];	priv->bc_sspd = max_speed;	/* We'll use our maxpayload as the default mtu */	if (set_mtu) {		dev->mtu = min(ETH1394_DATA_LEN,			       (int)(maxpayload -				     (sizeof(union eth1394_hdr) +				      ETHER1394_GASP_OVERHEAD)));		/* 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);}/* This function is called right before register_netdev */static void 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;	SET_ETHTOOL_OPS(dev, &ethtool_ops);	/* 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);}/* * 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 (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394))		return;	fifo_addr = hpsb_allocate_and_register_addrspace(			&eth1394_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)		goto out;	/* We should really have our own alloc_hpsbdev() function in	 * net_init.c instead of calling the one for ethernet then hijacking	 * it for ourselves.  That way we'd be a real networking device. */	dev = alloc_etherdev(sizeof (struct eth1394_priv));	if (dev == NULL) {		ETH1394_PRINT_G (KERN_ERR, "Out of memory trying to allocate "				 "etherdevice for IEEE 1394 device %s-%d\n",				 host->driver->name, host->id);		goto out;        }	SET_MODULE_OWNER(dev);#if 0	/* FIXME - Is this the correct parent device anyway? */	SET_NETDEV_DEV(dev, &host->device);#endif	priv = netdev_priv(dev);	INIT_LIST_HEAD(&priv->ip_node_list);	spin_lock_init(&priv->lock);	priv->host = host;	priv->local_fifo = fifo_addr;	hi = hpsb_create_hostinfo(&eth1394_highlevel, host, sizeof(*hi));	if (hi == NULL) {		ETH1394_PRINT_G (KERN_ERR, "Out of memory trying to create "				 "hostinfo for IEEE 1394 device %s-%d\n",				 host->driver->name, host->id);		goto out;        }	ether1394_init_dev(dev);	if (register_netdev (dev)) {		ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n");		goto out;	}	ETH1394_PRINT (KERN_INFO, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (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;	priv->iso = hpsb_iso_recv_init(host,				       ETHER1394_ISO_BUF_SIZE,				       ETHER1394_GASP_BUFFERS,				       priv->broadcast_channel,				       HPSB_ISO_DMA_PACKET_PER_BUFFER,				       1, ether1394_iso);	if (priv->iso == NULL) {		ETH1394_PRINT(KERN_ERR, dev->name,			      "Could not allocate isochronous receive context "			      "for the broadcast channel\n");		priv->bc_state = ETHER1394_BC_ERROR;	} else {		if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0)			priv->bc_state = ETHER1394_BC_STOPPED;		else			priv->bc_state = ETHER1394_BC_RUNNING;	}	return;out:	if (dev != NULL)		free_netdev(dev);	if (hi)		hpsb_destroy_hostinfo(&eth1394_highlevel, host);	return;}/* Remove a card from our list */static void ether1394_remove_host (struct hpsb_host *host){	struct eth1394_host_info *hi;	hi = hpsb_get_hostinfo(&eth1394_highlevel, host);	if (hi != NULL) {		struct eth1394_priv *priv = netdev_priv(hi->dev);		hpsb_unregister_addrspace(&eth1394_highlevel, host,					  priv->local_fifo);		if (priv->iso != NULL)			hpsb_iso_shutdown(priv->iso);		if (hi->dev) {			unregister_netdev (hi->dev);			free_netdev(hi->dev);		}	}	return;}/* A reset has just arisen */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(&eth1394_highlevel, host);	/* This can happen for hosts that we don't use */	if (hi == NULL)		return;	dev = hi->dev;	priv = (struct eth1394_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 = (struct eth1394_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;	struct net_device *dev = skb->dev;	switch (eth->h_proto) {#ifdef CONFIG_INET	case __constant_htons(ETH_P_IP): 		return arp_find((unsigned char*)&eth->h_dest, skb);#endif	default:		ETH1394_PRINT(KERN_DEBUG, dev->name,			      "unable to resolve type %04x addresses.\n",			      ntohs(eth->h_proto));		break;	}	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 eth1394hdr *eth = (struct eth1394hdr*)(((u8*)hh->hh_data) +						      (16 - ETH1394_HLEN));	struct net_device *dev = neigh->dev;	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);}static int ether1394_mac_addr(struct net_device *dev, void *p){	if (netif_running(dev))		return -EBUSY;	/* Not going to allow setting the MAC address, we really need to use	 * the real one supplied by the hardware */	 return -EINVAL; }/****************************************** * Datagram reception code ******************************************//* Copied from net/ethernet/eth.c */static inline u16 ether1394_type_trans(struct sk_buff *skb,				       struct net_device *dev){	struct eth1394hdr *eth;	unsigned char *rawp;	skb->mac.raw = skb->data;	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 inline 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;

⌨️ 快捷键说明

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