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

📄 arlan-main.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  Copyright (C) 1997 Cullen Jennings *  Copyright (C) 1998 Elmer Joandiu, elmer@ylenurme.ee *  GNU General Public License applies * This module provides support for the Arlan 655 card made by Aironet */#include <linux/config.h>#include "arlan.h"#if BITS_PER_LONG != 32#  error FIXME: this driver requires a 32-bit platform#endifstatic const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee  Oct'98, http://www.ylenurme.ee/~elmer/655/";struct net_device *arlan_device[MAX_ARLANS];static int SID = SIDUNKNOWN;static int radioNodeId = radioNodeIdUNKNOWN;static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};int arlan_debug = debugUNKNOWN;static int spreadingCode = spreadingCodeUNKNOWN;static int channelNumber = channelNumberUNKNOWN;static int channelSet = channelSetUNKNOWN;static int systemId = systemIdUNKNOWN;static int registrationMode = registrationModeUNKNOWN;static int keyStart;static int tx_delay_ms;static int retries = 5;static int tx_queue_len = 1;static int arlan_EEPROM_bad;#ifdef ARLAN_DEBUGGINGstatic int arlan_entry_debug;static int arlan_exit_debug;static int testMemory = testMemoryUNKNOWN;static int irq = irqUNKNOWN;static int txScrambled = 1;static int mdebug;#endifMODULE_PARM(irq, "i");MODULE_PARM(mem, "i");MODULE_PARM(arlan_debug, "i");MODULE_PARM(testMemory, "i");MODULE_PARM(spreadingCode, "i");MODULE_PARM(channelNumber, "i");MODULE_PARM(channelSet, "i");MODULE_PARM(systemId, "i");MODULE_PARM(registrationMode, "i");MODULE_PARM(radioNodeId, "i");MODULE_PARM(SID, "i");MODULE_PARM(txScrambled, "i");MODULE_PARM(keyStart, "i");MODULE_PARM(mdebug, "i");MODULE_PARM(tx_delay_ms, "i");MODULE_PARM(retries, "i");MODULE_PARM(async, "i");MODULE_PARM(tx_queue_len, "i");MODULE_PARM(arlan_entry_debug, "i");MODULE_PARM(arlan_exit_debug, "i");MODULE_PARM(arlan_entry_and_exit_debug, "i");MODULE_PARM(arlan_EEPROM_bad, "i");MODULE_PARM_DESC(irq, "(unused)");MODULE_PARM_DESC(mem, "Arlan memory address for single device probing");MODULE_PARM_DESC(arlan_debug, "Arlan debug enable (0-1)");MODULE_PARM_DESC(testMemory, "(unused)");MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)");MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions");#ifdef ARLAN_ENTRY_EXIT_DEBUGGINGMODULE_PARM_DESC(arlan_entry_debug, "Arlan driver function entry debugging");MODULE_PARM_DESC(arlan_exit_debug, "Arlan driver function exit debugging");MODULE_PARM_DESC(arlan_entry_and_exit_debug, "Arlan driver function entry and exit debugging");#elseMODULE_PARM_DESC(arlan_entry_debug, "(ignored)");MODULE_PARM_DESC(arlan_exit_debug, "(ignored)");MODULE_PARM_DESC(arlan_entry_and_exit_debug, "(ignored)");#endifstruct arlan_conf_stru arlan_conf[MAX_ARLANS];static int arlans_found;static  int 	arlan_open(struct net_device *dev);static  int 	arlan_tx(struct sk_buff *skb, struct net_device *dev);static  irqreturn_t arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);static  int 	arlan_close(struct net_device *dev);static  struct net_device_stats *		arlan_statistics		(struct net_device *dev);static  void 	arlan_set_multicast		(struct net_device *dev);static  int 	arlan_hw_tx			(struct net_device* dev, char *buf, int length );static  int	arlan_hw_config			(struct net_device * dev);static  void 	arlan_tx_done_interrupt		(struct net_device * dev, int status);static  void	arlan_rx_interrupt		(struct net_device * dev, u_char rxStatus, u_short, u_short);static  void	arlan_process_interrupt		(struct net_device * dev);static	void	arlan_tx_timeout		(struct net_device *dev);static inline long us2ticks(int us){	return us * (1000000 / HZ);}#ifdef ARLAN_ENTRY_EXIT_DEBUGGING#define ARLAN_DEBUG_ENTRY(name) \	{\	struct timeval timev;\	do_gettimeofday(&timev);\		if (arlan_entry_debug || arlan_entry_and_exit_debug)\			printk("--->>>" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec));\	}#define ARLAN_DEBUG_EXIT(name) \	{\	struct timeval timev;\	do_gettimeofday(&timev);\		if (arlan_exit_debug || arlan_entry_and_exit_debug)\			printk("<<<---" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec) );\	}#else#define ARLAN_DEBUG_ENTRY(name)#define ARLAN_DEBUG_EXIT(name)#endif#define arlan_interrupt_ack(dev)\        clearClearInterrupt(dev);\        setClearInterrupt(dev);static inline int arlan_drop_tx(struct net_device *dev){	struct arlan_private *priv = dev->priv;	priv->stats.tx_errors++;	if (priv->Conf->tx_delay_ms)	{		priv->tx_done_delayed = jiffies + priv->Conf->tx_delay_ms * HZ / 1000 + 1;	}	else	{		priv->waiting_command_mask &= ~ARLAN_COMMAND_TX;		TXHEAD(dev).offset = 0;		TXTAIL(dev).offset = 0;		priv->txLast = 0;		priv->bad = 0;		if (!priv->under_reset && !priv->under_config)			netif_wake_queue (dev);	}	return 1;}int arlan_command(struct net_device *dev, int command_p){	struct arlan_private *priv = dev->priv;	volatile struct arlan_shmem *arlan = priv->card;	struct arlan_conf_stru *conf = priv->Conf;	int udelayed = 0;	int i = 0;	unsigned long flags;	ARLAN_DEBUG_ENTRY("arlan_command");	if (priv->card_polling_interval)		priv->card_polling_interval = 1;	if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)		printk(KERN_DEBUG "arlan_command, %lx commandByte %x waiting %lx incoming %x \n",		jiffies, READSHMB(arlan->commandByte),		       priv->waiting_command_mask, command_p);	priv->waiting_command_mask |= command_p;	if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)		if (time_after(jiffies, priv->lastReset + 5 * HZ))			priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET;	if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ACK)	{		arlan_interrupt_ack(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ACK;	}	if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ENABLE)	{		setInterruptEnable(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ENABLE;	}	/* Card access serializing lock */	spin_lock_irqsave(&priv->lock, flags);	/* Check cards status and waiting */	if (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW))	{		while (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW))		{			if (READSHMB(arlan->resetFlag) ||				READSHMB(arlan->commandByte))	/* || 								   (readControlRegister(dev) & ARLAN_ACCESS))								 */				udelay(40);			else				priv->waiting_command_mask &= ~(ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW);			udelayed++;			if (priv->waiting_command_mask & ARLAN_COMMAND_LONG_WAIT_NOW)			{				if (udelayed * 40 > 1000000)				{					printk(KERN_ERR "%s long wait too long \n", dev->name);					priv->waiting_command_mask |= ARLAN_COMMAND_RESET;					break;				}			}			else if (priv->waiting_command_mask & ARLAN_COMMAND_WAIT_NOW)			{				if (udelayed * 40 > 1000)				{					printk(KERN_ERR "%s short wait too long \n", dev->name);					goto bad_end;				}			}		}	}	else	{		i = 0;		while ((READSHMB(arlan->resetFlag) ||			READSHMB(arlan->commandByte)) &&			conf->pre_Command_Wait > (i++) * 10)			udelay(10);		if ((READSHMB(arlan->resetFlag) ||			READSHMB(arlan->commandByte)) &&			!(priv->waiting_command_mask & ARLAN_COMMAND_RESET))		{			goto card_busy_end;		}	}	if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)		priv->under_reset = 1;	if (priv->waiting_command_mask & ARLAN_COMMAND_CONF)		priv->under_config = 1;	/* Issuing command */	arlan_lock_card_access(dev);	if (priv->waiting_command_mask & ARLAN_COMMAND_POWERUP)	{	//     if (readControlRegister(dev) & (ARLAN_ACCESS && ARLAN_POWER))		setPowerOn(dev);		arlan_interrupt_lancpu(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERUP;		priv->waiting_command_mask |= ARLAN_COMMAND_RESET;		priv->card_polling_interval = HZ / 10;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_ACTIVATE)	{		WRITESHMB(arlan->commandByte, ARLAN_COM_ACTIVATE);		arlan_interrupt_lancpu(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_ACTIVATE;		priv->card_polling_interval = HZ / 10;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_RX_ABORT)	{		if (priv->rx_command_given)		{			WRITESHMB(arlan->commandByte, ARLAN_COM_RX_ABORT);			arlan_interrupt_lancpu(dev);			priv->rx_command_given = 0;		}		priv->waiting_command_mask &= ~ARLAN_COMMAND_RX_ABORT;		priv->card_polling_interval = 1;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_TX_ABORT)	{		if (priv->tx_command_given)		{			WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ABORT);			arlan_interrupt_lancpu(dev);			priv->tx_command_given = 0;		}		priv->waiting_command_mask &= ~ARLAN_COMMAND_TX_ABORT;		priv->card_polling_interval = 1;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)	{		priv->under_reset=1;		netif_stop_queue (dev);		arlan_drop_tx(dev);		if (priv->tx_command_given || priv->rx_command_given)		{			printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);		}		netif_stop_queue (dev);		if (arlan_debug & ARLAN_DEBUG_RESET)			printk(KERN_ERR "%s: Doing chip reset\n", dev->name);		priv->lastReset = jiffies;		WRITESHM(arlan->commandByte, 0, u_char);		/* hold card in reset state */		setHardwareReset(dev);		/* set reset flag and then release reset */		WRITESHM(arlan->resetFlag, 0xff, u_char);		clearChannelAttention(dev);		clearHardwareReset(dev);		priv->card_polling_interval = HZ / 4;		priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET;		priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK;//		priv->waiting_command_mask |= ARLAN_COMMAND_INT_RENABLE; //		priv->waiting_command_mask |= ARLAN_COMMAND_RX;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RACK)	{		clearHardwareReset(dev);		clearClearInterrupt(dev);		setClearInterrupt(dev);		setInterruptEnable(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RACK;		priv->waiting_command_mask |= ARLAN_COMMAND_CONF;		priv->under_config = 1;		priv->under_reset = 0;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RENABLE)	{		setInterruptEnable(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RENABLE;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF)	{		if (priv->tx_command_given || priv->rx_command_given)		{			printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);		}		arlan_drop_tx(dev);		setInterruptEnable(dev);		arlan_hw_config(dev);		arlan_interrupt_lancpu(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF;		priv->card_polling_interval = HZ / 10;//		priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK;   //		priv->waiting_command_mask |= ARLAN_COMMAND_INT_ENABLE; 		priv->waiting_command_mask |= ARLAN_COMMAND_CONF_WAIT;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF_WAIT)	{		if (READSHMB(arlan->configuredStatusFlag) != 0 &&			READSHMB(arlan->diagnosticInfo) == 0xff)		{			priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT;			priv->waiting_command_mask |= ARLAN_COMMAND_RX;			priv->waiting_command_mask |= ARLAN_COMMAND_TBUSY_CLEAR;			priv->card_polling_interval = HZ / 10;			priv->tx_command_given = 0;			priv->under_config = 0;		}		else		{			priv->card_polling_interval = 1;			if (arlan_debug & ARLAN_DEBUG_TIMING)				printk(KERN_ERR "configure delayed \n");		}	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_RX)	{		if (!registrationBad(dev))		{			setInterruptEnable(dev);			memset_io((void *) arlan->commandParameter, 0, 0xf);			WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE);			WRITESHMB(arlan->commandParameter[0], conf->rxParameter);			arlan_interrupt_lancpu(dev);			priv->rx_command_given = 0; // mnjah, bad			priv->waiting_command_mask &= ~ARLAN_COMMAND_RX;			priv->card_polling_interval = 1;		}		else			priv->card_polling_interval = 2;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_TBUSY_CLEAR)	{		if ( !registrationBad(dev) &&		     (netif_queue_stopped(dev) || !netif_running(dev)) )			{				priv->waiting_command_mask &= ~ARLAN_COMMAND_TBUSY_CLEAR;				netif_wake_queue (dev);			}	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_TX)	{		if (!test_and_set_bit(0, (void *) &priv->tx_command_given))		{			if (time_after(jiffies, 				       priv->tx_last_sent + us2ticks(conf->rx_tweak1))			    || time_before(jiffies,					   priv->last_rx_int_ack_time + us2ticks(conf->rx_tweak2)))			{				setInterruptEnable(dev);				memset_io((void *) arlan->commandParameter, 0, 0xf);				WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ENABLE | ARLAN_COM_INT);				memcpy_toio((void *) arlan->commandParameter, &TXLAST(dev), 14);//				for ( i=1 ; i < 15 ; i++) printk("%02x:",READSHMB(arlan->commandParameter[i]));				priv->tx_last_sent = jiffies;				arlan_interrupt_lancpu(dev);				priv->tx_command_given = 1;				priv->waiting_command_mask &= ~ARLAN_COMMAND_TX;				priv->card_polling_interval = 1;			}			else			{				priv->tx_command_given = 0;				priv->card_polling_interval = 1;			}		} 		else if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)			printk(KERN_ERR "tx command when tx chain locked \n");	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOPINT)	{		{			WRITESHMB(arlan->commandByte, ARLAN_COM_NOP | ARLAN_COM_INT);		}		arlan_interrupt_lancpu(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOPINT;		priv->card_polling_interval = HZ / 3;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOP)	{		WRITESHMB(arlan->commandByte, ARLAN_COM_NOP);		arlan_interrupt_lancpu(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOP;		priv->card_polling_interval = HZ / 3;	}	else if (priv->waiting_command_mask & ARLAN_COMMAND_SLOW_POLL)	{		WRITESHMB(arlan->commandByte, ARLAN_COM_GOTO_SLOW_POLL);		arlan_interrupt_lancpu(dev);		priv->waiting_command_mask &= ~ARLAN_COMMAND_SLOW_POLL;		priv->card_polling_interval = HZ / 3;	} 	else if (priv->waiting_command_mask & ARLAN_COMMAND_POWERDOWN)	{		setPowerOff(dev);		if (arlan_debug & ARLAN_DEBUG_CARD_STATE)			printk(KERN_WARNING "%s: Arlan Going Standby\n", dev->name);		priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERDOWN;		priv->card_polling_interval = 3 * HZ;	}	arlan_unlock_card_access(dev);	for (i = 0; READSHMB(arlan->commandByte) && i < 20; i++)		udelay(10);	if (READSHMB(arlan->commandByte))		if (arlan_debug & ARLAN_DEBUG_CARD_STATE)			printk(KERN_ERR "card busy leaving command %lx\n", priv->waiting_command_mask);	spin_unlock_irqrestore(&priv->lock, flags);	ARLAN_DEBUG_EXIT("arlan_command");	priv->last_command_buff_free_time = jiffies;	return 0;card_busy_end:	if (time_after(jiffies, priv->last_command_buff_free_time + HZ))		priv->waiting_command_mask |= ARLAN_COMMAND_CLEAN_AND_RESET;	if (arlan_debug & ARLAN_DEBUG_CARD_STATE)		printk(KERN_ERR "%s arlan_command card busy end \n", dev->name);	spin_unlock_irqrestore(&priv->lock, flags);	ARLAN_DEBUG_EXIT("arlan_command");	return 1;bad_end:	printk(KERN_ERR "%s arlan_command bad end \n", dev->name);

⌨️ 快捷键说明

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