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

📄 airo.c

📁 Linux下的PCMCIA接口的无线网卡驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	u16 *s;	statr->len = le16_to_cpu(statr->len);	for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s);	for(s = &statr->beaconPeriod; s <= &statr->_reserved[9]; s++)		*s = le16_to_cpu(*s);	return rc;}static int readAPListRid(struct airo_info*ai, APListRid *aplr) {	int rc =  PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr));	aplr->len = le16_to_cpu(aplr->len);	return rc;}static int writeAPListRid(struct airo_info*ai, APListRid *aplr) {	int rc;	aplr->len = cpu_to_le16(aplr->len);	rc = do_writerid(ai, RID_APLIST, aplr, sizeof(*aplr));	return rc;}static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr) {	int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr));	u16 *s;	capr->len = le16_to_cpu(capr->len);	capr->prodNum = le16_to_cpu(capr->prodNum);	capr->radioType = le16_to_cpu(capr->radioType);	capr->country = le16_to_cpu(capr->country);	for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++)		*s = le16_to_cpu(*s);	return rc;}static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid) {	int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr));	u32 *i;	sr->len = le16_to_cpu(sr->len);	for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i);	return rc;}static int airo_open(struct net_device *dev) {	struct airo_info *info = dev->priv;	enable_interrupts(info);	netif_start_queue(dev);	return 0;}static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {	s16 len;	u16 status;	u32 flags;	int i,j;	struct airo_info *priv = (struct airo_info*)dev->priv;	u32 *fids = priv->fids;	if ( skb == NULL ) {		printk( KERN_ERR "airo:  skb == NULL!!!\n" );		return 0;	}	/* Find a vacant FID */	spin_lock_irqsave(&priv->main_lock, flags);	for( j = 0, i = -1; j < MAX_FIDS; j++ ) {		if ( !( fids[j] & 0xffff0000 ) ) {			if ( i == -1 ) i = j;			else break;		}	}	if ( j == MAX_FIDS ) netif_stop_queue(dev);	if ( i == -1 ) {		priv->stats.tx_fifo_errors++;		goto tx_done;	}	len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/	status = transmit_802_3_packet( priv, fids[i], skb->data, len );	if ( status == SUCCESS ) {                /* Mark fid as used & save length for later */		fids[i] |= (len << 16);		dev->trans_start = jiffies;	} else {		priv->stats.tx_window_errors++;	} tx_done:	spin_unlock_irqrestore(&priv->main_lock, flags);	dev_kfree_skb(skb);	return 0;}struct net_device_stats *airo_get_stats(struct net_device *dev){	struct airo_info *local = (struct airo_info*) dev->priv;	StatsRid stats_rid;	u32 *vals = stats_rid.vals;	/* Get stats out of the card */	readStatsRid(local, &stats_rid, RID_STATS);	local->stats.rx_packets = vals[43] + vals[44] + vals[45];	local->stats.tx_packets = vals[39] + vals[40] + vals[41];	local->stats.rx_bytes = vals[92];	local->stats.tx_bytes = vals[91];	local->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4];	local->stats.tx_errors = vals[42] + local->stats.tx_fifo_errors;	local->stats.multicast = vals[43];	local->stats.collisions = vals[89];	/* detailed rx_errors: */	local->stats.rx_length_errors = vals[3];	local->stats.rx_crc_errors = vals[4];	local->stats.rx_frame_errors = vals[2];	local->stats.rx_fifo_errors = vals[0];	return (&local->stats);}static int enable_MAC( struct airo_info *ai, Resp *rsp );static void disable_MAC(struct airo_info *ai);static void airo_set_multicast_list(struct net_device *dev) {	struct airo_info *ai = (struct airo_info*)dev->priv;	Cmd cmd;	Resp rsp;	/* For some reason this command takes a lot of time (~20 ms) and it's	 * run in an interrupt handler, so we'd better be sure we needed it	 * before executing it.	 */	if ((dev->flags ^ ai->flags) & IFF_PROMISC) {		memset(&cmd, 0, sizeof(cmd));		cmd.cmd=CMD_SETMODE;		cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;		lock_issuecommand(ai, &cmd, &rsp);		ai->flags^=IFF_PROMISC;	}	if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {		/* Turn on multicast.  (Should be already setup...) */	}}static int airo_set_mac_address(struct net_device *dev, void *p){	struct airo_info *ai = (struct airo_info*)dev->priv;	struct sockaddr *addr = p;	ConfigRid cfg;	readConfigRid (ai, &cfg);	memcpy (cfg.macAddr, addr->sa_data, dev->addr_len);	writeConfigRid (ai, &cfg);	memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);	return 0;}static int airo_change_mtu(struct net_device *dev, int new_mtu){	if ((new_mtu < 68) || (new_mtu > 2400))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static int airo_close(struct net_device *dev) {	struct airo_info *ai = (struct airo_info*)dev->priv;	netif_stop_queue(dev);	disable_interrupts( ai );	return 0;}static void del_airo_dev( struct net_device *dev );void stop_airo_card( struct net_device *dev, int freeres ){	struct airo_info *ai = (struct airo_info*)dev->priv;	if (ai->flash)		kfree(ai->flash);	if (ai->rssi)		kfree(ai->rssi);	takedown_proc_entry( dev, ai );	if (ai->registered) {		unregister_netdev( dev );		ai->registered = 0;	}	disable_interrupts(ai);	free_irq( dev->irq, dev );	if (auto_wep) del_timer_sync(&ai->timer);	if (freeres) {		/* PCMCIA frees this stuff, so only for PCI and ISA */	        release_region( dev->base_addr, 64 );        }	del_airo_dev( dev );	kfree( dev );}static int add_airo_dev( struct net_device *dev );struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia ){	struct net_device *dev;	struct airo_info *ai;	int i, rc;	/* Create the network device object. */        dev = alloc_etherdev(sizeof(*ai));        if (!dev) {		printk(KERN_ERR "airo:  Couldn't alloc_etherdev\n");		return NULL;        }	if (dev_alloc_name(dev, dev->name) < 0) {		printk(KERN_ERR "airo:  Couldn't get name!\n");		goto err_out_free;	}	ai = dev->priv;	ai->registered = 0;        ai->dev = dev;	ai->aux_lock = SPIN_LOCK_UNLOCKED;	ai->main_lock = SPIN_LOCK_UNLOCKED;	ai->header_parse = dev->hard_header_parse;	rc = add_airo_dev( dev );	if (rc)		goto err_out_free;	/* The Airo-specific entries in the device structure. */	dev->hard_start_xmit = &airo_start_xmit;	dev->get_stats = &airo_get_stats;	dev->set_multicast_list = &airo_set_multicast_list;	dev->set_mac_address = &airo_set_mac_address;	dev->do_ioctl = &airo_ioctl;#ifdef WIRELESS_EXT	dev->get_wireless_stats = airo_get_wireless_stats;#endif /* WIRELESS_EXT */	dev->change_mtu = &airo_change_mtu;	dev->open = &airo_open;	dev->stop = &airo_close;	dev->irq = irq;	dev->base_addr = port;	rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev );	if (rc) {		printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc );		goto err_out_unlink;	}	if (!is_pcmcia) {		if (!request_region( dev->base_addr, 64, dev->name )) {			rc = -EBUSY;			goto err_out_irq;		}	}	if ( setup_card( ai, dev->dev_addr, &ai->config) != SUCCESS ) {		printk( KERN_ERR "airo: MAC could not be enabled\n" );		rc = -EIO;		goto err_out_res;	}	rc = register_netdev(dev);	if (rc)		goto err_out_res;	ai->registered = 1;	printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",		dev->name,		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );	/* Allocate the transmit buffers */	for( i = 0; i < MAX_FIDS; i++ )		ai->fids[i] = transmit_allocate( ai, 2312 );	setup_proc_entry( dev, dev->priv ); /* XXX check for failure */	netif_start_queue(dev);	SET_MODULE_OWNER(dev);	return dev;err_out_res:	if (!is_pcmcia)	        release_region( dev->base_addr, 64 );err_out_irq:	free_irq(dev->irq, dev);err_out_unlink:	del_airo_dev(dev);err_out_free:	kfree(dev);	return NULL;}int waitbusy (struct airo_info *ai) {	int delay = 0;	while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) & (delay < 10000)) {		udelay (10);		if (++delay % 20)			OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);	}	return delay < 10000;}int reset_airo_card( struct net_device *dev ) {	int i;	struct airo_info *ai = (struct airo_info*)dev->priv;	disable_MAC(ai);	waitbusy (ai);	OUT4500(ai,COMMAND,CMD_SOFTRESET);	set_current_state (TASK_UNINTERRUPTIBLE);	schedule_timeout (HZ/5);	waitbusy (ai);	set_current_state (TASK_UNINTERRUPTIBLE);	schedule_timeout (HZ/5);	if ( setup_card(ai, dev->dev_addr, &(ai)->config) != SUCCESS ) {		printk( KERN_ERR "airo: MAC could not be enabled\n" );		return -1;	} else {		printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",			dev->name,			dev->dev_addr[0],			dev->dev_addr[1],			dev->dev_addr[2],			dev->dev_addr[3],			dev->dev_addr[4],			dev->dev_addr[5]			);		/* Allocate the transmit buffers */		for( i = 0; i < MAX_FIDS; i++ )			ai->fids[i] = transmit_allocate( ai, 2312 );	}	enable_interrupts( ai );	netif_wake_queue(dev);	return 0;}int wll_header_parse(struct sk_buff *skb, unsigned char *haddr){	memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);	return ETH_ALEN;}static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {	struct net_device *dev = (struct net_device *)dev_id;	u16 status;	u16 fid;	struct airo_info *apriv = (struct airo_info *)dev->priv;	u16 savedInterrupts = 0;	if (!netif_device_present(dev))		return;	for (;;) {		status = IN4500( apriv, EVSTAT );		if ( !status || status == 0xffff ) break;		if ( status & EV_AWAKE ) {			OUT4500( apriv, EVACK, EV_AWAKE );			OUT4500( apriv, EVACK, EV_AWAKE );		}		if (!savedInterrupts) {			savedInterrupts = IN4500( apriv, EVINTEN );			OUT4500( apriv, EVINTEN, 0 );		}		if ( status & EV_LINK ) {			/* The link status has changed, if you want to put a			   monitor hook in, do it here.  (Remember that			   interrupts are still disabled!)			*/			u16 newStatus = IN4500(apriv, LINKSTAT);			OUT4500( apriv, EVACK, EV_LINK);			/* Here is what newStatus means: */#define NOBEACON 0x8000 /* Loss of sync - missed beacons */#define MAXRETRIES 0x8001 /* Loss of sync - max retries */#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/#define FORCELOSS 0x8003 /* Loss of sync - host request */#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */#define DISASS 0x8200 /* Disassociation (low byte is reason code) */#define ASSFAIL 0x8400 /* Association failure (low byte is reason			  code) */#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason			   code) */#define ASSOCIATED 0x0400 /* Assocatied */#define RC_RESERVED 0 /* Reserved return code */#define RC_NOREASON 1 /* Unspecified reason */#define RC_AUTHINV 2 /* Previous authentication invalid */#define RC_DEAUTH 3 /* Deauthenticated because sending station is		       leaving */#define RC_NOACT 4 /* Disassociated due to inactivity */#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle			all currently associated stations */#define RC_BADCLASS2 6 /* Class 2 frame received from			  non-Authenticated station */#define RC_BADCLASS3 7 /* Class 3 frame received from			  non-Associated station */#define RC_STATLEAVE 8 /* Disassociated because sending station is			  leaving BSS */#define RC_NOAUTH 9 /* Station requesting (Re)Association is not		       Authenticated with the responding station */			if (newStatus != ASSOCIATED) {				if (auto_wep && !timer_pending(&apriv->timer)) {					apriv->timer.expires = RUN_AT(HZ*3);		      			add_timer(&apriv->timer);				}			}		}		/* Check to see if there is something to receive */		if ( status & EV_RX  ) {			struct sk_buff *skb = NULL;			u16 fc, len, hdrlen = 0;			struct {				u16 status, len;				u8 rssi[2];			} hdr;			fid = IN4500( apriv, RXFID );			/* Get the packet length */			if (dev->type == ARPHRD_IEEE80211) {				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;			} else {				bap_setup (apriv, fid, 6, BAP0);				bap_read (apriv, (u16*)&hdr.len, 4, BAP0);			}			len = le16_to_cpu(hdr.len);			if (len > 2312) {				printk( KERN_ERR "airo: Bad size %d\n", len );				len = 0;			}			if (len) {				if (dev->type == ARPHRD_IEEE80211) {					bap_setup (apriv, fid, 0x14, BAP0);					bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0);					if ((le16_to_cpu(fc) & 0x300) == 0x300)						hdrlen = 30;					else						hdrlen = 24;				} else					hdrlen = 12;				skb = dev_alloc_skb( len + hdrlen + 2 );				if ( !skb ) {					apriv->stats.rx_dropped++;					len = 0;				}			}			if (len) {				u16 *buffer;				buffer = (u16*)skb_put (skb, len + hdrlen);				if (dev->type == ARPHRD_IEEE80211) {					u16 gap, tmpbuf[4];					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 && gap <= 8)						bap_read (apriv, tmpbuf, gap, BAP0);					bap_read (apriv, buffer + hdrlen/2, len, BAP0);				} else {

⌨️ 快捷键说明

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