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

📄 fastvnet_cs.c

📁 Atmel公司的USB无线局域网卡11 mbps Linux设备驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
}/********************************************************************* PCMCIA ATTACH / DETACH********************************************************************/static dev_link_t *vnet_attach (void){	dev_link_t *link;	struct net_device *dev;	struct net_local *local;	int rc;	client_reg_t client_reg;	IF_VERY_LOUD(DbgPrint("-> vnet_attach()\n");)	// Flush stale links	for (link=dev_list; link; link=link->next)		if (link->state & DEV_STALE_LINK)			vnet_detach(link);	// Initialize the dev_link_t structure	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);	memset(link, 0, sizeof(struct dev_link_t));	link->release.function = &vnet_release;	link->release.data = (u_long) link;	link->conf.Vcc = 33;	link->conf.IntType = INT_MEMORY_AND_IO;	// Allocate space for netdevice (private data of link)	dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);	memset(dev, 0, sizeof(struct net_device));	link->priv = dev;	// Allocate space for netdevice priv (private data of netdevice)	local = kmalloc(sizeof(struct net_local), GFP_KERNEL);	memset(local, 0, sizeof(struct net_local));	dev->priv = local;	// Initialize specific data	local->link = link;	local->dev = dev;	spin_lock_init(&local->slock);	 /* Set the mgmt timer */	init_timer(&local->Adapter.MgmtTimer);	local->Adapter.MgmtTimer.function = MgmtTimer;  	local->Adapter.MgmtTimer.data = (unsigned long) dev;	// Standard setup for generic data	ether_setup(dev);	// kernel callbacks	dev->open = vnet_open;	dev->stop = vnet_close;	dev->hard_start_xmit = vnet_tx;	dev->get_stats = vnet_get_stats;#ifdef WIRELESS_EXT	dev->do_ioctl = vnet_ioctl;	dev->get_wireless_stats = vnet_get_wireless_stats;#endif	// Other netdevice data	init_dev_name(dev, local->node);	dev->mtu = mtu;		netif_stop_queue(dev);	// Register with CardServices	link->next = dev_list;	dev_list = link;	client_reg.dev_info = &dev_info;	client_reg.Attributes = INFO_IO_CLIENT;	client_reg.EventMask =	CS_EVENT_REGISTRATION_COMPLETE |							CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |							CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |							CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;	client_reg.event_handler = &vnet_event;	client_reg.Version = 0x0210;	client_reg.event_callback_args.client_data = link;	rc = CardServices(RegisterClient, &link->handle, &client_reg);	if (rc)	{		cs_error(link->handle, RegisterClient, rc);		vnet_detach(link);		return NULL;	}	IF_VERY_LOUD(DbgPrint("<- vnet_attach()\n");)	return link;}static void vnet_detach (dev_link_t *link){	dev_link_t **linkp;	IF_VERY_LOUD(DbgPrint("-> vnet_detach(0x%p)\n", link);)	// Locate device structure 	for (linkp=&dev_list; *linkp; linkp=&(*linkp)->next) 		if (*linkp == link) 			break; 	if (!*linkp) 	{ 		IF_DEBUG_ERRORS(DbgPrint("%s: Attempt to detach non-existing PCMCIA client!\n", dev_info);) 		return; 	} 	// If the device is currently configured and active, we won't	// actually delete it yet. Instead, it is marked so that when the	// release() function is called, that will trigger a proper	// detach()	del_timer(&link->release);	if (link->state & DEV_CONFIG)	{		IF_LOUD(DbgPrint("%s: vnet_detach: detach postponed, %s still locked\n", dev_info, link->dev->dev_name);)		vnet_release((u_long)link);		if (link->state & DEV_STALE_CONFIG)		{			link->state |= DEV_STALE_LINK;			return;		}	}	// Break the line with CardServices	if (link->handle)		CardServices(DeregisterClient, link->handle);	// Unlink device structure, free pieces	*linkp = link->next;	if (link->priv)	{		struct net_device *dev = (struct net_device *) link->priv;		if (link->dev)		{			unregister_netdev(dev);			IF_LOUD(DbgPrint("%s: Netdevice unregistered\n", dev_info);)		}		if (dev->priv)			kfree(dev->priv);		kfree(link->priv);	}	kfree(link);	IF_VERY_LOUD(DbgPrint("<- vnet_detach()\n");)}/******************************************************************** * PCMCIA EVENT HANDLER********************************************************************/static int vnet_event (event_t event, int priority, event_callback_args_t *args){	dev_link_t 		*link = (dev_link_t *) args->client_data;	struct net_device *dev = (struct net_device *) link->priv;	struct net_local 	*local = (struct net_local *) dev->priv;	PVNet_ADAPTER 	Adapter = &local->Adapter;	IF_LOUD(DbgPrint("-> vnet_event(%s, %d, 0x%p)\n",		((event==CS_EVENT_REGISTRATION_COMPLETE) ? "registration complete" :		((event==CS_EVENT_CARD_INSERTION) ? "card insertion" :		((event==CS_EVENT_CARD_REMOVAL) ? "card removal" :		((event==CS_EVENT_RESET_PHYSICAL) ? "physical physical" :		((event==CS_EVENT_CARD_RESET) ? "card reset" :		((event==CS_EVENT_PM_SUSPEND) ? "pm suspend" :		((event==CS_EVENT_PM_RESUME) ? "pm resume" :		"unknown"))))))), priority, args);)	switch (event)	{		case CS_EVENT_CARD_INSERTION:			link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;			if (!vnet_config(link))				dev->irq = 0;						Adapter->IsUp = TRUE;				InitAdapter(&local->Adapter);			SetParameters(&local->Adapter);			if (!InitAndStartCard(&local->Adapter))				return -1;			memcpy(dev->dev_addr, Adapter->StationAddress, 6);			break;		case CS_EVENT_CARD_REMOVAL:			del_timer(&Adapter->MgmtTimer);			link->state &= ~DEV_PRESENT;			Adapter->IsUp = FALSE;					if (link->state & DEV_CONFIG)			{				netif_stop_queue(dev);				netif_device_detach(dev);				mod_timer(&link->release, jiffies + HZ/20);			}			break;		case CS_EVENT_PM_SUSPEND:			link->state |= DEV_SUSPEND;		case CS_EVENT_RESET_PHYSICAL:			Adapter->IsUp = FALSE;			if (link->state & DEV_CONFIG)			{				if (link->open)				{					netif_stop_queue(dev);					netif_device_detach(dev);				}				CardServices(ReleaseConfiguration, link->handle);			}			break;		case CS_EVENT_PM_RESUME:			link->state &= ~DEV_SUSPEND;			// Fall through		case CS_EVENT_CARD_RESET:			if (link->state & DEV_CONFIG)			{				CardServices(RequestConfiguration, link->handle, &link->conf);				if (link->open)				{					netif_device_attach(dev);					netif_start_queue(dev);				}			}			break;	}	IF_VERY_LOUD(DbgPrint("<- vnet_event()\n");)	return 0;}/******************************************************************** * MODULE INSERTION / REMOVAL********************************************************************/extern int init_module (void){	servinfo_t serv;	IF_VERY_LOUD(DbgPrint("-> init_module()\n");)	IF_LOUD(DbgPrint("%s: ATMEL 11Mbps Wireless PCMCIA LAN driver version %s\n", dev_info, version);)	// Check CardServices release	CardServices(GetCardServicesInfo, &serv);	if (serv.Revision < CS_RELEASE_CODE)	{		      	printk("%s: CardServices release does not match!\n", dev_info); 		return -1; 	}	// Register PCMCIA driver	register_pcmcia_driver(&dev_info, &vnet_attach, &vnet_detach);	IF_VERY_LOUD(DbgPrint("<- init_module()\n");)	return 0;}extern void cleanup_module (void){	IF_VERY_LOUD(DbgPrint("-> cleanup_module()\n");)	// Unregister PCMCIA driver	unregister_pcmcia_driver(&dev_info);	// Remove leftover devices	if (dev_list)	{		IF_VERY_LOUD(DbgPrint("%s: Removing leftover devices!\n", dev_info);)	}	while (dev_list)	{		if (dev_list->state & DEV_CONFIG)			vnet_release((u_long)dev_list);		vnet_detach(dev_list);	}	IF_LOUD(DbgPrint("%s: Driver unloaded\n", dev_info);)	IF_VERY_LOUD(DbgPrint("<- cleanup_module()\n");)}/******************************************************************** * NET OPEN / CLOSE********************************************************************/static int vnet_open (struct net_device *dev){	struct net_local *local = (struct net_local *) dev->priv;	struct dev_link_t *link = local->link;	IF_VERY_LOUD(DbgPrint("-> vnet_open(%s)\n", dev->name);)	netif_device_attach(dev);	netif_start_queue(dev);	local->interrupt = 0;	link->open++;	MOD_INC_USE_COUNT;	IF_VERY_LOUD(DbgPrint("<- vnet_open(%s)\n", dev->name);)	return 0;}static int vnet_close (struct net_device *dev){	struct net_local *local = (struct net_local *) dev->priv;	struct dev_link_t *link = local->link;	// If the device isn't open, then nothing to do	if (!link->open)	{		IF_VERY_LOUD(DbgPrint("<> vnet_close(%s)\n", dev->name);)		return 0;	}		IF_VERY_LOUD(DbgPrint("-> vnet_close(%s)\n", dev->name);)	// Close the device	link->open--;	MOD_DEC_USE_COUNT;	// Check if card is still present	if (netif_running(dev))	{		netif_stop_queue(dev);		netif_device_detach(dev);	}	else		if (link->state & DEV_STALE_CONFIG)			mod_timer(&link->release, jiffies + HZ/20);	IF_VERY_LOUD(DbgPrint("<- vnet_close(%s)\n", dev->name);)	return -EINVAL;}/******************************************************************** * NET Statistics ********************************************************************/struct net_device_stats *vnet_get_stats (struct net_device *dev){	struct net_local *local = (struct net_local *)dev->priv;	PVNet_ADAPTER Adapter = &local->Adapter;	IF_VERY_LOUD(DbgPrint("<> vnet_get_stats(%s)\n", dev->name);)	local->stats.tx_packets=Adapter->Stats.TxDataPacketsOk;	return(&((struct net_local *) dev->priv)->stats);}/*******************************************************************Management Timer*******************************************************************/VOIDMgmtTimer(u_long a){	struct net_device 	*dev ;	struct net_local    *local;  	PVNet_ADAPTER		Adapter;  	dev = (struct net_device *) a;	local = (struct net_local *)dev->priv;	Adapter = &local->Adapter;	if(!Adapter->IsUp || !(local->link->state & DEV_PRESENT))	{		IF_LOUD(DbgPrint("** MgmtTimer reject ***\n");)		return;	}		MgmtTimeOutCallBack(Adapter);}/******************************************************************** * NET TX / RX ********************************************************************/int vnet_tx (struct sk_buff *skb, struct net_device *dev){	struct net_local *local = (struct net_local *)dev->priv;	ULONG TotalBytes=0;	USHORT StartOfTxBuffer=0;	unsigned long flags;	ULONG Status;	int len;	UCHAR *p;	PVNet_ADAPTER Adapter = &local->Adapter;	IF_VERY_LOUD(DbgPrint("-> vnet_tx(%s)\n", dev->name);)	if(Adapter->StationState != STATION_STATE_READY || !(local->link->state & DEV_PRESENT))		return 0;	#if (KERNEL_VERSION_CODE < KERNEL_VERSION(2,3,42))	if (netif_queue_stopped(dev))	{		IF_VERY_LOUD(DbgPrint("%s: vnet_tx(%s) called while busy!\n", dev_info, dev->name);)		if ((jiffies - dev->trans_start) < TX_TIMEOUT)			return 1;		if (!netif_running(dev))		{			IF_LOUD(DbgPrint("%s: %s Tx on stopped device!\n", dev_info, dev->name);)			return 1;		}	}#endif	skb_tx_check(dev, skb);#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,79))	skb->arp = 1;#endif	// Disable interrupts	spin_lock_irqsave(&local->slock, flags);	// Prepare packet	p = skb->data;	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;	TotalBytes = len;		if ( TxResourcesAvailable(Adapter, TotalBytes+18, &StartOfTxBuffer) == FALSE)	{		Adapter->Stats.RxLost++;		netif_stop_queue(dev);		spin_unlock_irqrestore(&local->slock, flags);		return 1;	}	TxEthernetPacket(Adapter,skb->data, len, &TotalBytes, StartOfTxBuffer, TRUE);	TxUpdateDescriptor(Adapter, TotalBytes, StartOfTxBuffer, TRUE);	// Send packet	// Remember time transmission and count tx bytes	dev->trans_start = jiffies;	add_tx_bytes(&local->stats, len);	// Re-enable interrupts	spin_unlock_irqrestore(&local->slock, flags);	DEV_KFREE_SKB(skb);

⌨️ 快捷键说明

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