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

📄 airo.c

📁 Linux下的PCMCIA接口的无线网卡驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	spin_lock_irqsave(&ai->main_lock, flags);	if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != SUCCESS) {                rc = status;                goto done;        }	if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {		rc = ERROR;                goto done;        }	// read the rid length field	bap_read(ai, pBuf, 2, BAP1);	// length for remaining part of rid	len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2;	if ( len <= 2 ) {		printk( KERN_ERR			"airo: Rid %x has a length of %d which is too short\n",			(int)rid,			(int)len );		rc = ERROR;                goto done;	}	// read remainder of the rid	rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1); done:	spin_unlock_irqrestore(&ai->main_lock, flags);	return rc;}/*  Note, that we are using BAP1 which is also used by transmit, so *  make sure this isnt called when a transmit is happening */static int PC4500_writerid(struct airo_info *ai, u16 rid,			   const void *pBuf, int len){	u16 status;        long flags;	int rc = SUCCESS;	spin_lock_irqsave(&ai->main_lock, flags);	// --- first access so that we can write the rid data	if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != 0) {                rc = status;                goto done;        }	// --- now write the rid data	if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {                rc = ERROR;                goto done;        }	bap_write(ai, pBuf, len, BAP1);	// ---now commit the rid data	rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS); done:	spin_unlock_irqrestore(&ai->main_lock, flags);        return rc;}/* Allocates a FID to be used for transmitting packets.  We only use   one for now. */static u16 transmit_allocate(struct airo_info *ai, int lenPayload){	Cmd cmd;	Resp rsp;	u16 txFid;	u16 txControl;        long flags;	cmd.cmd = CMD_ALLOCATETX;	cmd.parm0 = lenPayload;	if (lock_issuecommand(ai, &cmd, &rsp) != SUCCESS) return 0;	if ( (rsp.status & 0xFF00) != 0) return 0;	/* wait for the allocate event/indication	 * It makes me kind of nervous that this can just sit here and spin,	 * but in practice it only loops like four times. */	while ( (IN4500(ai, EVSTAT) & EV_ALLOC) == 0) ;	// get the allocated fid and acknowledge	txFid = IN4500(ai, TXALLOCFID);	OUT4500(ai, EVACK, EV_ALLOC);	/*  The CARD is pretty cool since it converts the ethernet packet	 *  into 802.11.  Also note that we don't release the FID since we	 *  will be using the same one over and over again. */	/*  We only have to setup the control once since we are not	 *  releasing the fid. */	txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_3		| TXCTL_ETHERNET | TXCTL_NORELEASE);	spin_lock_irqsave(&ai->main_lock, flags);	if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS) {		spin_unlock_irqrestore(&ai->main_lock, flags);		return ERROR;	}	bap_write(ai, &txControl, sizeof(txControl), BAP1);	spin_unlock_irqrestore(&ai->main_lock, flags);	return txFid;}/* In general BAP1 is dedicated to transmiting packets.  However,   since we need a BAP when accessing RIDs, we also use BAP1 for that.   Make sure the BAP1 spinlock is held when this is called. */static int transmit_802_3_packet(struct airo_info *ai, u16 txFid,				 char *pPacket, int len){	u16 payloadLen;	Cmd cmd;	Resp rsp;	if (len < 12) {		printk( KERN_WARNING "Short packet %d\n", len );		return ERROR;	}	// packet is destination[6], source[6], payload[len-12]	// write the payload length and dst/src/payload	if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;	/* The hardware addresses aren't counted as part of the payload, so	 * we have to subtract the 12 bytes for the addresses off */	payloadLen = cpu_to_le16(len-12);	bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);	bap_write(ai, (const u16*)pPacket, len, BAP1);	// issue the transmit command	memset( &cmd, 0, sizeof( cmd ) );	cmd.cmd = CMD_TRANSMIT;	cmd.parm0 = txFid;	if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;	if ( (rsp.status & 0xFF00) != 0) return ERROR;	return SUCCESS;}/* *  This is the proc_fs routines.  It is a bit messier than I would *  like!  Feel free to clean it up! */static ssize_t proc_read( struct file *file,			  char *buffer,			  size_t len,			  loff_t *offset);static ssize_t proc_write( struct file *file,			   const char *buffer,			   size_t len,			   loff_t *offset );static int proc_close( struct inode *inode, struct file *file );static int proc_stats_open( struct inode *inode, struct file *file );static int proc_statsdelta_open( struct inode *inode, struct file *file );static int proc_status_open( struct inode *inode, struct file *file );static int proc_SSID_open( struct inode *inode, struct file *file );static int proc_APList_open( struct inode *inode, struct file *file );static int proc_BSSList_open( struct inode *inode, struct file *file );static int proc_config_open( struct inode *inode, struct file *file );static int proc_wepkey_open( struct inode *inode, struct file *file );static struct file_operations proc_statsdelta_ops = {	read:           proc_read,	open:           proc_statsdelta_open,	release:        proc_close};static struct file_operations proc_stats_ops = {	read:           proc_read,	open:           proc_stats_open,	release:        proc_close};static struct file_operations proc_status_ops = {	read:            proc_read,	open:            proc_status_open,	release:         proc_close};static struct file_operations proc_SSID_ops = {	read:          proc_read,	write:         proc_write,	open:          proc_SSID_open,	release:       proc_close};static struct file_operations proc_BSSList_ops = {	read:          proc_read,	write:         proc_write,	open:          proc_BSSList_open,	release:       proc_close};static struct file_operations proc_APList_ops = {	read:          proc_read,	write:         proc_write,	open:          proc_APList_open,	release:       proc_close};static struct file_operations proc_config_ops = {	read:          proc_read,	write:         proc_write,	open:          proc_config_open,	release:       proc_close};static struct file_operations proc_wepkey_ops = {	read:          proc_read,	write:         proc_write,	open:          proc_wepkey_open,	release:       proc_close};static struct proc_dir_entry *airo_entry = 0;struct proc_data {	int release_buffer;	int readlen;	char *rbuffer;	int writelen;	int maxwritelen;	char *wbuffer;	void (*on_close) (struct inode *, struct file *);};#ifndef SETPROC_OPS#define SETPROC_OPS(entry, ops) (entry)->proc_fops = &(ops)#endifstatic int setup_proc_entry( struct net_device *dev,			     struct airo_info *apriv ) {	struct proc_dir_entry *entry;	/* First setup the device directory */	apriv->proc_entry = create_proc_entry(dev->name,					      S_IFDIR|airo_perm,					      airo_entry);        apriv->proc_entry->uid = proc_uid;        apriv->proc_entry->gid = proc_gid;	/* Setup the StatsDelta */	entry = create_proc_entry("StatsDelta",				  S_IFREG | (S_IRUGO&proc_perm),				  apriv->proc_entry);        entry->uid = proc_uid;        entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_statsdelta_ops);	/* Setup the Stats */	entry = create_proc_entry("Stats",				  S_IFREG | (S_IRUGO&proc_perm),				  apriv->proc_entry);        entry->uid = proc_uid;        entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_stats_ops);	/* Setup the Status */	entry = create_proc_entry("Status",				  S_IFREG | (S_IRUGO&proc_perm),				  apriv->proc_entry);        entry->uid = proc_uid;        entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_status_ops);	/* Setup the Config */	entry = create_proc_entry("Config",				  S_IFREG | proc_perm,				  apriv->proc_entry);        entry->uid = proc_uid;        entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_config_ops);	/* Setup the SSID */	entry = create_proc_entry("SSID",				  S_IFREG | proc_perm,				  apriv->proc_entry);        entry->uid = proc_uid;        entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_SSID_ops);	/* Setup the APList */	entry = create_proc_entry("APList",				  S_IFREG | proc_perm,				  apriv->proc_entry);        entry->uid = proc_uid;        entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_APList_ops);	/* Setup the BSSList */	entry = create_proc_entry("BSSList",				  S_IFREG | proc_perm,				  apriv->proc_entry);	entry->uid = proc_uid;	entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_BSSList_ops);	/* Setup the WepKey */	entry = create_proc_entry("WepKey",				  S_IFREG | proc_perm,				  apriv->proc_entry);        entry->uid = proc_uid;        entry->gid = proc_gid;	entry->data = dev;	SETPROC_OPS(entry, proc_wepkey_ops);	return 0;}static int takedown_proc_entry( struct net_device *dev,				struct airo_info *apriv ) {	if ( !apriv->proc_entry->namelen ) return 0;	remove_proc_entry("Stats",apriv->proc_entry);	remove_proc_entry("StatsDelta",apriv->proc_entry);	remove_proc_entry("Status",apriv->proc_entry);	remove_proc_entry("Config",apriv->proc_entry);	remove_proc_entry("SSID",apriv->proc_entry);	remove_proc_entry("APList",apriv->proc_entry);	remove_proc_entry("BSSList",apriv->proc_entry);	remove_proc_entry("WepKey",apriv->proc_entry);	remove_proc_entry(dev->name,airo_entry);	return 0;}/* *  What we want from the proc_fs is to be able to efficiently read *  and write the configuration.  To do this, we want to read the *  configuration when the file is opened and write it when the file is *  closed.  So basically we allocate a read buffer at open and fill it *  with data, and allocate a write buffer and read it at close. *//* *  The read routine is generic, it relies on the preallocated rbuffer *  to supply the data. */static ssize_t proc_read( struct file *file,			  char *buffer,			  size_t len,			  loff_t *offset ){	int i;	int pos;	struct proc_data *priv = (struct proc_data*)file->private_data;	if( !priv->rbuffer ) return -EINVAL;	pos = *offset;	for( i = 0; i+pos < priv->readlen && i < len; i++ ) {		if (put_user( priv->rbuffer[i+pos], buffer+i ))			return -EFAULT;	}	*offset += i;	return i;}/* *  The write routine is generic, it fills in a preallocated rbuffer *  to supply the data. */static ssize_t proc_write( struct file *file,			   const char *buffer,			   size_t len,			   loff_t *offset ){	int i;	int pos;	struct proc_data *priv = (struct proc_data*)file->private_data;	if ( !priv->wbuffer ) {		return -EINVAL;	}	pos = *offset;	for( i = 0; i + pos <  priv->maxwritelen &&		     i < len; i++ ) {		if (get_user( priv->wbuffer[i+pos], buffer + i ))			return -EFAULT;	}	if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos;	*offset += i;	return i;}static int proc_status_open( struct inode *inode, struct file *file ) {	struct proc_data *data;	struct proc_dir_entry *dp = inode->u.generic_ip;	struct net_device *dev = dp->data;	struct airo_info *apriv = (struct airo_info *)dev->priv;	CapabilityRid cap_rid;	StatusRid status_rid;	int i;	MOD_INC_USE_COUNT;	dp = inode->u.generic_ip;	if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)		return -ENOMEM;	memset(file->private_data, 0, sizeof(struct proc_data));	data = (struct proc_data *)file->private_data;	if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {		kfree (file->private_data);		return -ENOMEM;	}	readStatusRid(apriv, &status_rid);	readCapabilityRid(apriv, &cap_rid);        i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n",                    status_rid.mode & 1 ? "CFG ": "",                    status_rid.mode & 2 ? "ACT ": "",                    status_rid.mode & 0x10 ? "SYN ": "",                    status_rid.mode & 0x20 ? "LNK ": "",                    status_rid.mode & 0x40 ? "LEAP ": "",                    status_rid.mode & 0x80 ? "PRIV ": "",                    status_rid.mode & 0x100 ? "KEY ": "",                    status_rid.mode & 0x200 ? "WEP ": "",                    status_rid.mode & 0x8000 ? "ERR ": "");	sprintf( data->rbuffer+i, "Mode: %x\n"		 "Signal Strength: %d\n"		 "Signal Quality: %d\n"		 "SSID: %-.*s\n"		 "AP: %-.16s\n"		 "Freq: %d\n"		 "BitRate: %dmbs\n"		 "Driver Version: %s\n"		 "Device: %s\nManufacturer: %s\nFirmware Version: %s\n"		 "Radio type: %x\nCountry: %x\nHardware Version: %x\n"		 "Software Version: %x\nSoftware Subversion: %x\n"		 "Boot block version: %x\n",		 (int)status_rid.mode,		 (int)status_rid.normalizedSignalStrength,		 (int)status_rid.signalQuality,		 (int)status_rid.SSIDlen,		 status_rid.SSID,		 status_rid.apName,		 (int)status_rid.channel,		 (int)status_rid.currentXmitRate/2,		 version,		 cap_rid.prodName,		 cap_rid.manName,		 cap_rid.prodVer,		 cap_rid.radioType,		 cap_rid.country,		 cap_rid.hardVer,		 (int)cap_rid.softVer,		 (int)cap_rid.softSubVer,		 (int)cap_rid.bootBlockVer );	data->readlen = strlen( data->rbuffer );	return 0;}static int proc_stats_rid_open(struct inode*, struct file*, u16);static int proc_statsdelta_open( struct inode *inode,				 struct file *file ) {	if (file->f_mode&FMODE_WRITE) {		return proc_stats_rid_open(inode, file, RID_STATSDELTACLEAR);	}	return proc_stats_rid_open(inode, file, RID_STATSDELTA);}static int proc_stats_open( struct inode *inode, struct file *file ) {	return proc_stats_rid_open(inode, file, RID_STATS);}static int proc_stats_rid_open( struct inode *inode,				struct file *file,				u16 rid ) {	struct proc_data *data;	struct proc_dir_entry *dp = inode->u.generic_ip;	struct net_device *dev = dp->data;	struct airo_info *ap

⌨️ 快捷键说明

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