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

📄 airo.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* Question : is ASSOCIATED the only status			 * that is valid ? We want to catch handover			 * and reassociations as valid status			 * Jean II */			if(newStatus == ASSOCIATED) {				if (apriv->scan_timestamp) {					/* Send an empty event to user space.					 * We don't send the received data on					 * the event because it would require					 * us to do complex transcoding, and					 * we want to minimise the work done in					 * the irq handler. Use a request to					 * extract the data - Jean II */					wrqu.data.length = 0;					wrqu.data.flags = 0;					wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);					apriv->scan_timestamp = 0;				}				airo_send_event(dev);			} else {				memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);				wrqu.ap_addr.sa_family = ARPHRD_ETHER;				/* Send event to user space */				wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);			}#endif /* WIRELESS_EXT > 13 */		}		/* Check to see if there is something to receive */		if ( status & EV_RX  ) {			struct sk_buff *skb = NULL;			u16 fc, len, hdrlen = 0;#pragma pack(1)			struct {				u16 status, len;				u8 rssi[2];				u8 rate;				u8 freq;				u16 tmp[4];			} hdr;#pragma pack()			u16 gap;			u16 tmpbuf[4];			u16 *buffer;			fid = IN4500( apriv, RXFID );			/* Get the packet length */			if (apriv->flags & FLAG_802_11) {				bap_setup (apriv, fid, 4, BAP0);				bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0);				/* Bad CRC. Ignore packet */				if (le16_to_cpu(hdr.status) & 2)					hdr.len = 0;				if (apriv->wifidev == NULL)					hdr.len = 0;			} else {				bap_setup (apriv, fid, 0x36, BAP0);				bap_read (apriv, (u16*)&hdr.len, 2, BAP0);			}			len = le16_to_cpu(hdr.len);			if (len > 2312) {				printk( KERN_ERR "airo: Bad size %d\n", len );				len = 0;			}			if (len) {				if (apriv->flags & FLAG_802_11) {					bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0);					fc = le16_to_cpu(fc);					switch (fc & 0xc) {						case 4:							if ((fc & 0xe0) == 0xc0)								hdrlen = 10;							else								hdrlen = 16;							break;						case 8:							if ((fc&0x300)==0x300){								hdrlen = 30;								break;							}						default:							hdrlen = 24;					}				} else					hdrlen = ETH_ALEN * 2;				skb = dev_alloc_skb( len + hdrlen + 2 );				if ( !skb ) {					apriv->stats.rx_dropped++;					len = 0;				}			}			if (len) {				buffer = (u16*)skb_put (skb, len + hdrlen);				if (apriv->flags & FLAG_802_11) {					buffer[0] = fc;					bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);					if (hdrlen == 24)						bap_read (apriv, tmpbuf, 6, BAP0);					bap_read (apriv, &gap, sizeof(gap), BAP0);					gap = le16_to_cpu(gap);					if (gap) {						if (gap <= 8)							bap_read (apriv, tmpbuf, gap, BAP0);						else							printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n");					}					bap_read (apriv, buffer + hdrlen/2, len, BAP0);				} else {					MICBuffer micbuf;					bap_read (apriv, buffer, ETH_ALEN*2, BAP0);					if (apriv->micstats.enabled) {						bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);						if (ntohs(micbuf.typelen) > 0x05DC)							bap_setup (apriv, fid, 0x44, BAP0);						else {							len -= sizeof(micbuf);							if (len < 48)								len = 48;							skb_trim (skb, len + hdrlen);						}					}					bap_read(apriv,buffer+ETH_ALEN,len,BAP0);#ifdef MICSUPPORT					if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {						dev_kfree_skb_irq (skb);						len = 0;					}#endif				}			}			if (len) {#ifdef WIRELESS_SPY				if (apriv->spy_number > 0) {					int i;					char *sa;					sa = (char*)buffer + ((apriv->flags & FLAG_802_11) ? 10 : 6);					for (i=0; i<apriv->spy_number; i++)						if (!memcmp(sa,apriv->spy_address[i],ETH_ALEN))						{							if (!(apriv->flags & FLAG_802_11)) {								bap_setup (apriv, fid, 8, BAP0);								bap_read (apriv, (u16*)hdr.rssi, 2, BAP0);							}							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  */				OUT4500( apriv, EVACK, EV_RX);				if (apriv->flags & FLAG_802_11) {					skb->mac.raw = skb->data;					skb->pkt_type = PACKET_OTHERHOST;					skb->dev = apriv->wifidev;					skb->protocol = htons(ETH_P_802_2);				} else {					skb->dev = dev;					skb->protocol = eth_type_trans(skb,dev);				}				skb->dev->last_rx = jiffies;				skb->ip_summed = CHECKSUM_NONE;				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)					get_tx_error(apriv, index);			}			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 & ~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 ) {	int rc;        Cmd cmd;	/* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions	 * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"	 * Note : we could try to use !netif_running(dev) in enable_MAC()	 * instead of this flag, but I don't trust it *within* the	 * open/close functions, and testing both flags together is	 * "cheaper" - Jean II */	if (ai->flags & (FLAG_RADIO_OFF|FLAG_RADIO_DOWN)) return SUCCESS;	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = MAC_ENABLE;	if (test_bit(FLAG_LOCKED, &ai->flags) != 0)		return issuecommand(ai, &cmd, rsp);	if (down_interruptible(&ai->sem))		return -ERESTARTSYS;	rc = issuecommand(ai, &cmd, rsp);	up(&ai->sem);	return rc;}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	if (test_bit(FLAG_LOCKED, &ai->flags) != 0) {		issuecommand(ai, &cmd, &rsp);		return;	}	if (down_interruptible(&ai->sem))		return;	issuecommand(ai, &cmd, &rsp);	up(&ai->sem);}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){	Cmd cmd;	Resp rsp;	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 (down_interruptible(&ai->sem))		return ERROR;	if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {		up(&ai->sem);		return ERROR;	}	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = MAC_DISABLE; // disable in case already enabled	if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {		up(&ai->sem);		return ERROR;	}	// Let's figure out if we need to use the AUX port	cmd.cmd = CMD_ENABLEAUX;	if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {		up(&ai->sem);		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");	}	up(&ai->sem);	if (ai->config.len == 0) {		tdsRssiRid rssi_rid;		CapabilityRid cap_rid;		// general configuration (read/modify/write)		status = readConfigRid(ai);		if ( status != SUCCESS ) return ERROR;		status = readCapabilityRid(ai, &cap_rid);		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 {			if (ai->rssi) {				kfree(ai->rssi);				ai->rssi = NULL;			}			if (cap_rid.softCap & 8)				ai->config.rmode |= RXMODE_NORMALIZED_RSSI;			else				printk(KERN_WARNING "airo: unknown received signal level scale\n");		}		ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;#ifdef MICSUPPORT		if ((cap_rid.len==sizeof(cap_rid)) && (cap_rid.extSoftCap&1)) {			ai->config.opmode |= MODE_MIC;			ai->flags |= FLAG_MIC_CAPABLE;			micsetup(ai);		}#endif		/* Save off the MAC */		for( i = 0; i < ETH_ALEN; i++ ) {			mac[i] = ai->config.macAddr[i];		}		/* Check to see if there are any insmod configured		   rates to add */		if ( rates ) {			int i = 0;			if ( rates[0] ) memset(ai->config.rates,0,sizeof(ai->config.rates));			for( i = 0; i < 8 && rates[i]; i++ ) {				ai->config.rates[i] = rates[i];			}		}		if ( basic_rate > 0 ) {			int i;			for( i = 0; i < 8; i++ ) {				if ( ai->config.rates[i] == basic_rate ||				     !ai->config.rates ) {					ai->config.rates[i] = basic_rate | 0x80;					break;				}			}		}		ai->need_commit = 1;	}	/* Setup the SSIDs if present */	if ( ssids[0] ) {		int i;		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);		}	}	status = writeConfigRid(ai);	if ( status != SUCCESS ) return ERROR;	/* Set up the SSID list */	status = writeSsidRid(ai, &mySsid);	if ( status != SUCCESS ) return ERROR;	status = enable_MAC(ai, &rsp);	if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {		printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 );		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 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {        // Im really paranoid about letting it run forever!	int max_tries = 600000;	if (sendcommand(ai, pCmd) == (u16)ERROR)		return ERROR;	while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {		if (!in_interrupt() && (max_tries & 255) == 0)			schedule();	}	if ( max_tries == -1 ) {		printk( KERN_ERR			"airo: Max tries exceeded waiting for command\n" );                return ERROR;	}	completecommand(ai, pRsp);	return SUCCESS;}static u16 sendcommand(struct airo_info *ai, Cmd *pCmd) {        // Im 

⌨️ 快捷键说明

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