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

📄 aironet4500_core.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	 Aironet 4500/4800 driver core * *		Elmer Joandi, Januar 1999 *		Copyright: 	GPL *	 * *	Revision 0.1 ,started  30.12.1998 * * */ /* CHANGELOG: 	march 99, stable version 2.0 	august 99, stable version 2.2 	november 99, integration with 2.3	17.12.99: finally, got SMP near-correct. 		timing issues remain- on SMP box its 15% slower on tcp		10.03.00 looks like softnet take us back to normal on SMP */#include <linux/module.h>#include <linux/init.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/ioport.h>#include <asm/io.h>#include <asm/bitops.h>#include <asm/system.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <linux/time.h>#include <linux/sched.h>#include <linux/delay.h>#include "aironet4500.h"#include <linux/ip.h>int bap_sleep = 10 ;int bap_sleep_after_setup = 1;int sleep_before_command  = 1;int bap_sleep_before_write= 1;int sleep_in_command	  = 1;int both_bap_lock;		/* activated at awc_init in this */int bap_setup_spinlock;		/* file if numcpu >1 */EXPORT_SYMBOL(bap_sleep);EXPORT_SYMBOL(bap_sleep_after_setup);EXPORT_SYMBOL(sleep_before_command);EXPORT_SYMBOL(bap_sleep_before_write);EXPORT_SYMBOL(sleep_in_command);EXPORT_SYMBOL(both_bap_lock);EXPORT_SYMBOL(bap_setup_spinlock);struct awc_strings awc_status_error_codes[]=awc_reply_error_strings;struct awc_strings awc_command_names[]=awc_command_name_strings;struct awc_strings awc_link_status_names[]=awc_link_status_strings;struct awc_strings awc_rid_names[]=aironet4500_RID_Select_strings;struct awc_strings awc_link_failure_reason_names[]=IEEE_802_11_LINK_STATUS_FAILURE_REASON_STRINGS;const char *  awc_print_string( struct awc_strings* strings, int code){		struct awc_strings * str = strings;	int i = 0;	while (str[i].string != NULL){		if (str[i].par == (code & str[i].mask )){			return str[i].string;		};		i++;	};	return "UNKNOWN";};int awc_dump_registers(struct net_device * dev){#ifdef AWC_DEBUG	int i;#endif	int status= inw(dev->base_addr +4*2);		int r1= inw(dev->base_addr +5*2);		int r2= inw(dev->base_addr +6*2);		int r3= inw(dev->base_addr +7*2);		printk(KERN_ERR "Command %s , result: %s, at memblk %x(RID %s) , offset %x \n",		awc_print_string(awc_command_names,status), 		awc_print_string(awc_status_error_codes,r1),		r2, awc_print_string(awc_rid_names,r2),		r3);#ifdef AWC_DEBUG	printk(KERN_ERR "%s aironet register dump ",dev->name );  	                        	for (i=0; i < 32; i++){		printk("%4x ", inw(dev->base_addr + i*2 ) );		if ( (i+1)%8 == 0){			printk("\n");			printk(KERN_ERR "%02x",(i+1)*2);		}	};	printk(KERN_ERR " \n");#endif	return 0;                       };          /******************************		COMMAND 	******************/inline int	awc_command_busy_clear_wait(struct net_device * dev){//	long long jiff = jiffies;        u16  active_interrupts;        int  cnt= 0;          	AWC_ENTRY_EXIT_DEBUG(" entry awc_command_busy_clear_wait ");  		     	while (awc_command_busy(dev->base_addr)){		if (cnt > 1000 ){			printk(KERN_ERR "awc command busy too long, clearing\n");			awc_dump_registers(dev);			awc_event_ack_ClrStckCmdBsy(dev->base_addr);			break;		};		if (((struct awc_private*) dev->priv)->ejected)			return -1;		cnt++;		udelay(10);	}		cnt = 0;	while (awc_command_busy(dev->base_addr)){		//if (jiffies - jiff > (HZ/3)){		if (cnt > 30000 ){			printk(KERN_CRIT "awc command busy WAY too long, clearing\n");			awc_dump_registers(dev);			awc_event_ack_ClrStckCmdBsy(dev->base_addr); 			active_interrupts = awc_event_status(dev->base_addr);			awc_event_ack(dev->base_addr, active_interrupts);			                                			AWC_ENTRY_EXIT_DEBUG("BAD exit\n ");			return -1 ;					};		if (((struct awc_private*) dev->priv)->ejected)			return -1;		cnt++;		udelay(10);	}		AWC_ENTRY_EXIT_DEBUG(" exit\n ");	     	return 0;	  };inline unsigned short awc_issue_command_and_block(struct awc_command * cmd){	int ticks;                    long long jiff;     u16	enabled_interrupts;     int cnt = 0;//     unsigned long flags;          jiff = jiffies;             AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_and_block ");                    AWC_LOCK_COMMAND_ISSUING(cmd->priv);     if (awc_command_busy_clear_wait(cmd->dev)) 		goto final;     if (cmd->priv->sleeping_bap) udelay(sleep_before_command);               	     awc4500wout(cmd->port,cmd->command,cmd->par0,cmd->par1,cmd->par2);//     awc_dump_registers(cmd->dev);     if (cmd->priv->sleeping_bap) udelay(sleep_in_command);          enabled_interrupts = awc_ints_enabled(cmd->dev->base_addr);     awc_ints_enable(cmd->dev->base_addr, enabled_interrupts & ~0x10);      if(cmd->priv->enabled_interrupts & 0x10)      	cmd->priv->enabled_interrupts &= ~0x10;	     while ( awc_command_read(cmd->port) == cmd->command) {       	  udelay(1);          awc_command_write(cmd->port, cmd->command);          //if ((jiffies - jiff) > 2){	  if (cnt > 2000 ){          	printk(" long wait with commmand reg busy in blocking command \n");          	awc_dump_registers(cmd->dev);         	goto final;          };          if (cmd->priv->ejected)		goto final;	  cnt++;  	  udelay(10);     };     AWC_ENTRY_EXIT_DEBUG(" issued " );      ticks = 0;     while ( awc_event_status_Cmd(cmd->port) == 0) {	  ticks++;          if (ticks > 100000){		printk(" long wait with commmand reg busy \n");          	awc_dump_registers(cmd->dev);          		goto final;          };	  if (ticks > 500){	       DEBUG(1, " long wait after issue 10mks * %d ", ticks );          	//printk(" long wait with command reg busy about ticks\n");	  	// sti();          }          if (cmd->priv->ejected)		goto final;	  udelay(10);     }                 if (cmd->priv->sleeping_bap) udelay(sleep_in_command);          awc_read_response(cmd);     AWC_ENTRY_EXIT_DEBUG(" resp read \n");      if (awc_command_busy(cmd->port))      	awc_event_ack_ClrStckCmdBsy(cmd->port);     awc_event_ack_Cmd(cmd->port);    if (cmd->priv->sleeping_bap) udelay(sleep_in_command);           if (cmd->status & 0xff00){     	printk(KERN_ERR " bad response to command %s, parameter %x \n",awc_print_string(awc_command_names, cmd->command),cmd->par0);     	awc_dump_registers(cmd->dev);  	goto final;   	      }	     AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);     AWC_ENTRY_EXIT_DEBUG(" exit \n");     udelay(1);     return 0;final:      AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);     AWC_ENTRY_EXIT_DEBUG("  BAD exit \n");     return -1; ;};inline unsigned short awc_issue_command(struct awc_command * cmd){//     long long jiff = jiffies;          //     unsigned short enabled_ints;                    int cnt = 0;//	int i=0;       AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command");          if (!cmd){     	printk(KERN_CRIT "cmd == NULL in awc_issue_command\n");     	return -1;          }     if (!cmd->dev){     	printk(KERN_CRIT "cmd->dev == NULL in awc_issue_command\n");     	return -1;          }     AWC_LOCK_COMMAND_ISSUING(cmd->priv);	     if(awc_command_busy_clear_wait(cmd->dev))		goto final;               	      if(!cmd->priv->enabled_interrupts & 0x10){      	cmd->priv->enabled_interrupts |= 0x10;     	awc_ints_enable(cmd->port, cmd->priv->enabled_interrupts );      }     cmd->priv->async_command_start = jiffies;     cmd->priv->command_semaphore_on++;     awc4500wout(cmd->port,cmd->command,cmd->par0,cmd->par1,cmd->par2);          while ( awc_command_read(cmd->port) == cmd->command) {                 awc_command_write(cmd->port, cmd->command);          //if ((jiffies - jiff) > 2){          if (cnt > 2000) {  		printk(" long wait with commmand reg busy in async command \n");          	awc_dump_registers(cmd->dev);         	goto final;          };          if (cmd->priv->ejected)		goto final;	   cnt++;	  udelay(10);     };          cmd->priv->cmd = *cmd;               AWC_ENTRY_EXIT_DEBUG(" exit \n");      return 0; final:     AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);     AWC_ENTRY_EXIT_DEBUG("  BAD exit \n");	   return -1; ;};inline unsigned short awc_issue_command_no_ack(struct net_device * dev,			u16 com, u16 par1, u16 par2, u16 par3){     struct awc_private * priv = (struct awc_private *)dev->priv;     int cnt = 0;     long long jiff;     jiff = jiffies;               AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_no_ack ");                         AWC_LOCK_COMMAND_ISSUING(priv);	     if (awc_command_busy_clear_wait(dev)) {		printk("aironet4x00 no_ack command (reset) with stuck card \n");     }     awc4500wout(dev->base_addr,com, par1, par2,par3);     udelay(10);          while ( awc_event_status_Cmd(dev->base_addr) == 0) {          if (awc_command_read(dev->base_addr) == com) {                               awc_command_write(dev->base_addr, com);          }          //if ((jiffies - jiff) > 2){          if (cnt > 2000) {  		printk(" long wait with commmand reg busy in noack command %d par %d %d %d\n",com,par1,par2,par3);          	awc_dump_registers(dev);          		goto final;          };          if (priv->ejected)		goto final;	  udelay(10);	  cnt++;     }                      if (awc_command_busy(dev->base_addr))      	awc_event_ack_ClrStckCmdBsy(dev->base_addr);     AWC_UNLOCK_COMMAND_ISSUING(priv);     AWC_ENTRY_EXIT_DEBUG(" exit \n");  return 0;final:      AWC_UNLOCK_COMMAND_ISSUING(priv);     AWC_ENTRY_EXIT_DEBUG("  BAD exit \n");	   return -1; ;};/******************************** 	BAP	*************************/// inline // too long for inlineint awc_bap_setup(struct awc_command * cmd) {	int status;	long long jiff;	unsigned long flags;		int cleared = 0;	int cycles = 0;	     AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_setup ");     	     if ( cmd->priv->sleeping_bap)	udelay(bap_sleep);		if (cmd->priv->ejected)		return -1;               if (!cmd->bap || !(cmd->lock_state & (AWC_BAP_SEMALOCKED |AWC_BAP_LOCKED)))     	DEBUG(1,"no bap or bap not locked cmd %d !!", cmd->command);	if (bap_setup_spinlock)		my_spin_lock_irqsave(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  	  status = AWC_IN(cmd->bap->offset);	  	  if (status & ~0x2000 ){	  	WAIT61x3;	  	status = AWC_IN(cmd->bap->offset);	  }	  if (status & ~0x2000 ){                WAIT61x3;	        AWC_IN(cmd->dev->base_addr + 0x26);                AWC_OUT(cmd->dev->base_addr + 0x26, 0);    	  	WAIT61x3;	  	udelay(60);	  	#ifdef AWC_DEBUG	  		printk("b");	  	#endif	  	status = AWC_IN(cmd->bap->offset);	  }	  	  if (status & 0xC000){	  	printk(KERN_ERR "bap entered with err or busy bit set %x \n",status);		if (cmd->bap->lock != 1) 			printk(KERN_ERR "bap lock bad same time %x\n",cmd->bap->lock);	  	awc_dump_registers(cmd->dev);	  	//	AWC_OUT(cmd->bap->offset, 0x800);	  }	  save_flags(flags);	  cli();	              AWC_OUT(cmd->bap->select, cmd->rid);	  WAIT61x3;          AWC_OUT(cmd->bap->offset, cmd->offset);           restore_flags(flags);	  WAIT61x3;                              jiff = jiffies;          while (1) {              cycles++;              status = AWC_IN(cmd->bap->offset);              if ( cmd->priv->sleeping_bap)              		udelay(bap_sleep);              if (cmd->priv->ejected)			goto ejected_unlock;

⌨️ 快捷键说明

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