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

📄 airo.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
	} tx_done:	spin_unlock_irqrestore(&priv->bap1_lock, flags);	KFREE_SKB( skb, FREE_WRITE );	return 0;}static struct net_device_stats *airo_get_stats(struct net_device *dev) {	return &(((struct airo_info*)dev->priv)->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;	Resp rsp;	  	ai->flags &= ~FLAG_PROMISC;	if (dev->flags&IFF_PROMISC) {		ai->flags |= FLAG_PROMISC;	} else if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {		/* Turn on multicast.  (Should be already setup...) */	}	disable_MAC(ai);	enable_MAC(ai, &rsp);}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;	ai->open--;	netif_stop_queue(dev);        netif_mark_down(dev);	if ( !ai->open ) {		disable_interrupts( ai );	}	MOD_DEC_USE_COUNT;	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;	takedown_proc_entry( dev, ai );	if (ai->registered) {		unregister_netdev( dev );		ai->registered = 0;	}	disable_interrupts(ai);	free_irq( dev->irq, dev );	if (freeres) {		/* PCMCIA frees this stuff, so only for PCI and ISA */	        release_region( dev->base_addr, 64 );        }	del_airo_dev( dev );	kfree( dev );	if (auto_wep) del_timer(&(ai)->timer);}static void add_airo_dev( struct net_device *dev ); struct net_device *init_airo_card( unsigned short irq, int port ){	struct net_device *dev;	struct airo_info *ai;	int i;		/* Create the network device object. */        dev = init_etherdev(0, sizeof(*ai));        if (!dev) {            printk(KERN_ERR "airo:  Couldn't init_etherdev\n");            return NULL;        }	ai = (struct airo_info *)dev->priv;	ai->registered = 1;        ai->dev = dev;	ai->bap0_lock = SPIN_LOCK_UNLOCKED;	ai->bap1_lock = SPIN_LOCK_UNLOCKED;	ai->aux_lock = SPIN_LOCK_UNLOCKED;	ai->cmd_lock = SPIN_LOCK_UNLOCKED;	add_airo_dev( dev ); 		/* 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->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;	netif_stop_queue(dev);	dev->irq = irq;	dev->base_addr = port;		if ( request_irq( dev->irq, airo_interrupt, 			  SA_SHIRQ | SA_INTERRUPT, dev->name, dev ) ) {		printk(KERN_ERR "airo: register interrupt %d failed\n", irq );	}	request_region( dev->base_addr, 64, dev->name );		memset( &((struct airo_info*)dev->priv)->config, 0,		sizeof(((struct airo_info*)dev->priv)->config));		if ( setup_card( ai, dev->dev_addr, 			 &((struct airo_info*)dev->priv)->config) 	     != SUCCESS ) {		printk( KERN_ERR "airo: MAC could not be enabled\n" );	} 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, 2000 );	}		setup_proc_entry( dev, (struct airo_info*)dev->priv );	netif_start_queue(dev);	return dev;}int reset_airo_card( struct net_device *dev ) {	int i;	struct airo_info *ai = (struct airo_info*)dev->priv;	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++ ) {			((struct airo_info*)dev->priv)->fids[i] =				transmit_allocate( ai, 2000 );		}	}	enable_interrupts( ai );	netif_start_queue(dev);	return 0;}static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {	struct net_device *dev = (struct net_device *)dev_id;	u16 len;	u16 status;	u16 fid;	struct airo_info *apriv = (struct airo_info *)dev->priv;	u16 savedInterrupts;		if (!netif_device_present(dev))		return;		status = IN4500( apriv, EVSTAT );	if ( !status ) return;		if ( status & EV_AWAKE ) {		OUT4500( apriv, EVACK, EV_AWAKE );		OUT4500( apriv, EVACK, EV_AWAKE );	}		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);		/* 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 recieve */	if ( status & EV_RX  ) {		struct sk_buff *skb;		int flags;		fid = IN4500( apriv, RXFID );		/* Get the packet length */	        spin_lock_irqsave(&apriv->bap0_lock, flags);		bap_setup( apriv, fid, 0x36, BAP0 );		bap_read( apriv, &len, sizeof(len), BAP0 );		len = le16_to_cpu(len);                /* The length only counts the payload		   not the hw addresses */		len += 12; 		if ( len < 12 || len > 2048 ) {#if LINUX_VERSION_CODE > 0x20127			apriv->stats.rx_length_errors++;#endif			apriv->stats.rx_errors++;			printk( KERN_ERR 				"airo: Bad size %d\n", len );		} else {			skb = dev_alloc_skb( len + 2 );			if ( !skb ) {				apriv->stats.rx_dropped++;			} else {				char *buffer;				buffer = skb_put( skb, len );		                bap_setup( apriv, fid, 0x36+sizeof(len), BAP0 );				bap_read( apriv, (u16*)buffer, len, BAP0 );#ifdef WIRELESS_SPY				if (apriv->spy_number > 0) {#if (LINUX_VERSION_CODE >= KERNEL_VERSION(1,3,0))					char *srcaddr = skb->mac.raw + 6;#else					char *srcaddr = skb->data + MAX_ADDR_SIZE;#endif					u8 rssi[2];					int i;					for (i=0; i<apriv->spy_number; i++)						if (!memcmp(srcaddr, apriv->spy_address[i], 6))						{							/* Get the rssi signal strength */							bap_setup( apriv, fid, 0x08, BAP0 );							bap_read( apriv, (u16 *)&rssi, sizeof(rssi), BAP0 );							apriv->spy_stat[i].qual = rssi[0];							apriv->spy_stat[i].level = rssi[1];							apriv->spy_stat[i].noise = 0;							apriv->spy_stat[i].updated = 3;							break;						}				}#endif /* WIRELESS_SPY  */				dev->last_rx = jiffies;				apriv->stats.rx_packets++;#if LINUX_VERSION_CODE > 0x20127				apriv->stats.rx_bytes += len;#endif				skb->dev = dev;				skb->ip_summed = CHECKSUM_NONE;				skb->protocol = eth_type_trans( skb, dev );				netif_rx( skb );			}		}		spin_unlock_irqrestore(&apriv->bap0_lock, flags);	}	/* Check to see if a packet has been transmitted */	if (  status & ( EV_TX|EV_TXEXC ) ) {		int i;		int len = 0;		int full = 1;		int index = -1;				fid = IN4500(apriv, TXCOMPLFID);				for( i = 0; i < MAX_FIDS; i++ ) {			if (!(apriv->fids[i] & 0xffff0000)) full = 0;			if ( ( apriv->fids[i] & 0xffff ) == fid ) {				len = apriv->fids[i] >> 16;				index = i;				/* Set up to be used again */				apriv->fids[i] &= 0xffff; 			}		}		if (full) netif_wake_queue(dev);		if (index==-1) {			printk( KERN_ERR				"airo: Unallocated FID was used to xmit\n" );		}		if ( status & EV_TX ) {			apriv->stats.tx_packets++;#if LINUX_VERSION_CODE > 0x20127			if(index!=-1)				apriv->stats.tx_bytes += len;#endif		} else {			apriv->stats.tx_errors++;		}	}	if ( status & ~STATUS_INTS ) 		printk( KERN_WARNING 			"airo: Got weird status %x\n", 			status & ~STATUS_INTS );	OUT4500( apriv, EVACK, status & STATUS_INTS );	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;	int status;        if (ai->flags&FLAG_RADIO_OFF) return SUCCESS;	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = MAC_ENABLE;	status = issuecommand(ai, &cmd, rsp);	if (status == SUCCESS && ai->flags&FLAG_PROMISC) {		Resp rsp;		memset(&cmd, 0, sizeof(cmd));		cmd.cmd=CMD_SETMODE;		cmd.parm1=PROMISC;		issuecommand(ai, &cmd, &rsp);	}	return status;}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	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 ) );	/* The NOP is the first step in getting the card going */	cmd.cmd = NOP;	cmd.parm0 = cmd.parm1 = cmd.parm2 = 0;	if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {		return ERROR;	}	memset(&cmd, 0, sizeof(cmd));	cmd.cmd = MAC_DISABLE; // disable in case already enabled	if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {		return ERROR;	}		// Let's figure out if we need to use the AUX port	cmd.cmd = CMD_ENABLEAUX;	if (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 {		// general configuration (read/modify/write)		status = readConfigRid(ai, &cfg);		if ( status != SUCCESS ) return ERROR;		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++ ) {

⌨️ 快捷键说明

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