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

📄 airo.c

📁 Linux下的PCMCIA接口的无线网卡驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
			                bap_setup (apriv, fid, 0x38, BAP0);					bap_read (apriv, buffer,len + hdrlen,BAP0);				}				OUT4500( apriv, EVACK, EV_RX);#ifdef WIRELESS_SPY				if (apriv->spy_number > 0) {					int i;					char *sa;					sa = (char*)buffer + ((dev->type == ARPHRD_IEEE80211) ? 10 : 6);					for (i=0; i<apriv->spy_number; i++)						if (!memcmp(sa,apriv->spy_address[i],6))						{							apriv->spy_stat[i].qual = hdr.rssi[0];							if (apriv->rssi)								apriv->spy_stat[i].level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;							else								apriv->spy_stat[i].level = (hdr.rssi[1] + 321) / 2;							apriv->spy_stat[i].noise = 0;							apriv->spy_stat[i].updated = 3;							break;						}				}#endif /* WIRELESS_SPY  */				dev->last_rx = jiffies;				skb->dev = dev;				skb->ip_summed = CHECKSUM_NONE;				if (dev->type == ARPHRD_IEEE80211) {					skb->mac.raw = skb->data;					skb_pull (skb, hdrlen);					skb->pkt_type = PACKET_OTHERHOST;					skb->protocol = htons(ETH_P_802_2);				} else					skb->protocol = eth_type_trans(skb,dev);				netif_rx( skb );			} else				OUT4500( apriv, EVACK, EV_RX);		}		/* Check to see if a packet has been transmitted */		if (  status & ( EV_TX|EV_TXEXC ) ) {			int i;			int len = 0;			int index = -1;			fid = IN4500(apriv, TXCOMPLFID);			for( i = 0; i < MAX_FIDS; i++ ) {				if ( ( apriv->fids[i] & 0xffff ) == fid ) {					len = apriv->fids[i] >> 16;					index = i;					/* Set up to be used again */					apriv->fids[i] &= 0xffff;				}			}			if (index != -1) netif_wake_queue(dev);			if ((status & EV_TXEXC) &&				(bap_setup(apriv, fid, 4, BAP1) == SUCCESS)) {				u16 status;				bap_read(apriv, &status, 2, BAP1);				if (le16_to_cpu(status) & 2)					apriv->stats.tx_aborted_errors++;				if (le16_to_cpu(status) & 4)					apriv->stats.tx_heartbeat_errors++;				if (le16_to_cpu(status) & 0x10)					apriv->stats.tx_carrier_errors++;			}			OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));			if (index==-1) {				printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" );			}		}		if ( status & ~STATUS_INTS )			OUT4500( apriv, EVACK, status & ~STATUS_INTS);		if ( status & ~STATUS_INTS & ~IGNORE_INTS )			printk( KERN_WARNING "airo: Got weird status %x\n",				status & ~STATUS_INTS & ~IGNORE_INTS );	}	if (savedInterrupts)		OUT4500( apriv, EVINTEN, savedInterrupts );	/* done.. */	return;}/* *  Routines to talk to the card *//* *  This was originally written for the 4500, hence the name *  NOTE:  If use with 8bit mode and SMP bad things will happen! *         Why would some one do 8 bit IO in an SMP machine?!? */static void OUT4500( struct airo_info *ai, u16 reg, u16 val ) {	if ( !do8bitIO )		outw( val, ai->dev->base_addr + reg );	else {		outb( val & 0xff, ai->dev->base_addr + reg );		outb( val >> 8, ai->dev->base_addr + reg + 1 );	}}static u16 IN4500( struct airo_info *ai, u16 reg ) {	unsigned short rc;	if ( !do8bitIO )		rc = inw( ai->dev->base_addr + reg );	else {		rc = inb( ai->dev->base_addr + reg );		rc += ((int)inb( ai->dev->base_addr + reg + 1 )) << 8;	}	return rc;}static int enable_MAC( struct airo_info *ai, Resp *rsp ) {        Cmd cmd;        if (ai->flags&FLAG_RADIO_OFF) return SUCCESS;	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = MAC_ENABLE;	return lock_issuecommand(ai, &cmd, rsp);}static void disable_MAC( struct airo_info *ai ) {        Cmd cmd;	Resp rsp;	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = MAC_DISABLE; // disable in case already enabled	lock_issuecommand(ai, &cmd, &rsp);}static void enable_interrupts( struct airo_info *ai ) {	/* Reset the status register */	u16 status = IN4500( ai, EVSTAT );	OUT4500( ai, EVACK, status );	/* Enable the interrupts */	OUT4500( ai, EVINTEN, STATUS_INTS );	/* Note there is a race condition between the last two lines that	   I dont know how to get rid of right now... */}static void disable_interrupts( struct airo_info *ai ) {	OUT4500( ai, EVINTEN, 0 );}static u16 setup_card(struct airo_info *ai, u8 *mac,		      ConfigRid *config){	Cmd cmd;	Resp rsp;	ConfigRid cfg;	int status;	int i;	SsidRid mySsid;	u16 lastindex;	WepKeyRid wkr;	int rc;	memset( &mySsid, 0, sizeof( mySsid ) );	if (ai->flash) {		kfree (ai->flash);		ai->flash = NULL;	}	/* The NOP is the first step in getting the card going */	cmd.cmd = NOP;	cmd.parm0 = cmd.parm1 = cmd.parm2 = 0;	if ( lock_issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {		return ERROR;	}	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = MAC_DISABLE; // disable in case already enabled	if ( lock_issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {		return ERROR;	}	// Let's figure out if we need to use the AUX port	cmd.cmd = CMD_ENABLEAUX;	if (lock_issuecommand(ai, &cmd, &rsp) != SUCCESS) {		printk(KERN_ERR "airo: Error checking for AUX port\n");		return ERROR;	}	if (!aux_bap || rsp.status & 0xff00) {		ai->bap_read = fast_bap_read;		printk(KERN_DEBUG "airo: Doing fast bap_reads\n");	} else {		ai->bap_read = aux_bap_read;		printk(KERN_DEBUG "airo: Doing AUX bap_reads\n");	}	if ( config->len ) {		cfg = *config;	} else {		tdsRssiRid rssi_rid;		// general configuration (read/modify/write)		status = readConfigRid(ai, &cfg);		if ( status != SUCCESS ) return ERROR;		status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid));		if ( status == SUCCESS ) {			if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)				memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);		}		else {			CapabilityRid cap_rid;			if (ai->rssi) {				kfree(ai->rssi);				ai->rssi = NULL;			}			status = readCapabilityRid(ai, &cap_rid);			if ((status == SUCCESS) && (cap_rid.softCap & 8))				cfg.rmode |= RXMODE_NORMALIZED_RSSI;			else				printk(KERN_WARNING "airo: unknown received signal level scale\n");		}		cfg.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;		/* Save off the MAC */		for( i = 0; i < 6; i++ ) {			mac[i] = cfg.macAddr[i];		}		/* Check to see if there are any insmod configured		   rates to add */		if ( rates ) {			int i = 0;			if ( rates[0] ) memset(cfg.rates,0,sizeof(cfg.rates));			for( i = 0; i < 8 && rates[i]; i++ ) {				cfg.rates[i] = rates[i];			}		}		if ( basic_rate > 0 ) {			int i;			for( i = 0; i < 8; i++ ) {				if ( cfg.rates[i] == basic_rate ||				     !cfg.rates ) {					cfg.rates[i] = basic_rate | 0x80;					break;				}			}		}		cfg.authType = ai->authtype;		*config = cfg;	}	/* Setup the SSIDs if present */	if ( ssids[0] ) {		int i = 0;		for( i = 0; i < 3 && ssids[i]; i++ ) {			mySsid.ssids[i].len = strlen(ssids[i]);			if ( mySsid.ssids[i].len > 32 )				mySsid.ssids[i].len = 32;			memcpy(mySsid.ssids[i].ssid, ssids[i],			       mySsid.ssids[i].len);			mySsid.ssids[i].len = mySsid.ssids[i].len;		}	}	status = writeConfigRid(ai, &cfg);	if ( status != SUCCESS ) return ERROR;	/* Set up the SSID list */	status = writeSsidRid(ai, &mySsid);	if ( status != SUCCESS ) return ERROR;	/* Grab the initial wep key, we gotta save it for auto_wep */	rc = readWepKeyRid(ai, &wkr, 1);	if (rc == SUCCESS) do {		lastindex = wkr.kindex;		if (wkr.kindex == 0xffff) {			ai->defindex = wkr.mac[0];		}		rc = readWepKeyRid(ai, &wkr, 0);	} while(lastindex != wkr.kindex);	if (auto_wep && !timer_pending(&ai->timer)) {		ai->timer.expires = RUN_AT(HZ*3);		add_timer(&ai->timer);	}	return SUCCESS;}static u16 lock_issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {	int rc;	long flags;	spin_lock_irqsave(&ai->main_lock, flags);	rc = issuecommand(ai, pCmd, pRsp);	spin_unlock_irqrestore(&ai->main_lock, flags);	return rc;}static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {        // Im really paranoid about letting it run forever!	int max_tries = 600000;	OUT4500(ai, PARAM0, pCmd->parm0);	OUT4500(ai, PARAM1, pCmd->parm1);	OUT4500(ai, PARAM2, pCmd->parm2);	OUT4500(ai, COMMAND, pCmd->cmd);	while ( max_tries-- &&		(IN4500(ai, EVSTAT) & EV_CMD) == 0) {		if ( IN4500(ai, COMMAND) == pCmd->cmd) {			// PC4500 didn't notice command, try again			OUT4500(ai, COMMAND, pCmd->cmd);		}	}	if ( max_tries == -1 ) {		printk( KERN_ERR			"airo: Max tries exceeded when issueing command\n" );                return ERROR;	}	// command completed	pRsp->status = IN4500(ai, STATUS);	pRsp->rsp0 = IN4500(ai, RESP0);	pRsp->rsp1 = IN4500(ai, RESP1);	pRsp->rsp2 = IN4500(ai, RESP2);	// clear stuck command busy if necessary	if (IN4500(ai, COMMAND) & COMMAND_BUSY) {		OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);	}	// acknowledge processing the status/response	OUT4500(ai, EVACK, EV_CMD);	return SUCCESS;}/* Sets up the bap to start exchange data.  whichbap should * be one of the BAP0 or BAP1 defines.  Locks should be held before * calling! */static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ){	int timeout = 50;	int max_tries = 3;	OUT4500(ai, SELECT0+whichbap, rid);	OUT4500(ai, OFFSET0+whichbap, offset);	while (1) {		int status = IN4500(ai, OFFSET0+whichbap);		if (status & BAP_BUSY) {                        /* This isn't really a timeout, but its kinda			   close */			if (timeout--) {				continue;			}		} else if ( status & BAP_ERR ) {			/* invalid rid or offset */			printk( KERN_ERR "airo: BAP error %x %d\n",				status, whichbap );			return ERROR;		} else if (status & BAP_DONE) { // success			return SUCCESS;		}		if ( !(max_tries--) ) {			printk( KERN_ERR				"airo: BAP setup error too many retries\n" );			return ERROR;		}		// -- PC4500 missed it, try again		OUT4500(ai, SELECT0+whichbap, rid);		OUT4500(ai, OFFSET0+whichbap, offset);		timeout = 50;	}}/* should only be called by aux_bap_read.  This aux function and the   following use concepts not documented in the developers guide.  I   got them from a patch given to my by Aironet */static u16 aux_setup(struct airo_info *ai, u16 page,		     u16 offset, u16 *len){	u16 next;	OUT4500(ai, AUXPAGE, page);	OUT4500(ai, AUXOFF, 0);	next = IN4500(ai, AUXDATA);	*len = IN4500(ai, AUXDATA)&0xff;	if (offset != 4) OUT4500(ai, AUXOFF, offset);	return next;}/* requires call to bap_setup() first */static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst,			int bytelen, int whichbap){	u16 len;	u16 page;	u16 offset;	u16 next;	int words;	int i;	long flags;	spin_lock_irqsave(&ai->aux_lock, flags);	page = IN4500(ai, SWS0+whichbap);	offset = IN4500(ai, SWS2+whichbap);	next = aux_setup(ai, page, offset, &len);	words = (bytelen+1)>>1;	for (i=0; i<words;) {		int count;		count = (len>>1) < (words-i) ? (len>>1) : (words-i);		if ( !do8bitIO )			insw( ai->dev->base_addr+DATA0+whichbap,			      pu16Dst+i,count );		else			insb( ai->dev->base_addr+DATA0+whichbap,			      pu16Dst+i, count << 1 );		i += count;		if (i<words) {			next = aux_setup(ai, next, 4, &len);		}	}	spin_unlock_irqrestore(&ai->aux_lock, flags);	return SUCCESS;}/* requires call to bap_setup() first */static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst,			 int bytelen, int whichbap){	bytelen = (bytelen + 1) & (~1); // round up to even value	if ( !do8bitIO )		insw( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen>>1 );	else		insb( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen );	return SUCCESS;}/* requires call to bap_setup() first */static int bap_write(struct airo_info *ai, const u16 *pu16Src,		     int bytelen, int whichbap){	bytelen = (bytelen + 1) & (~1); // round up to even value	if ( !do8bitIO )		outsw( ai->dev->base_addr+DATA0+whichbap,		       pu16Src, bytelen>>1 );	else		outsb( ai->dev->base_addr+DATA0+whichbap, pu16Src, bytelen );	return SUCCESS;}static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd){	Cmd cmd; /* for issuing commands */	Resp rsp; /* response from commands */	u16 status;	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = accmd;	cmd.parm0 = rid;	status = issuecommand(ai, &cmd, &rsp);	if (status != 0) return status;	if ( (rsp.status & 0x7F00) != 0) {		return (accmd << 8) + (rsp.rsp0 & 0xFF);	}	return 0;}/*  Note, that we are using BAP1 which is also used by transmit, so *  we must get a lock. */static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len){	u16 status;        long flags;        int rc = SUCCESS;

⌨️ 快捷键说明

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