📄 cb20_cb.c
字号:
remove_proc_entry("SSID",v_info->device); remove_proc_entry("Status",v_info->device); remove_proc_entry(dev->name,cb20_entry);#else proc_unregister(&cb20_entry,v_info->proc_ssid_entry.low_ino); proc_unregister(&cb20_entry,status_entry.low_ino); proc_unregister(&proc_root,cb20_entry.low_ino);#endif return 0;}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++ ) { put_user( priv->rbuffer[i+pos], buffer+i ); } *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++ ) { get_user( priv->wbuffer[i+pos], buffer + i ); } if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos; *offset += i; return i;}static int proc_close( struct inode *inode, struct file *file ) { struct proc_data *data = (struct proc_data *)file->private_data; if ( data->on_close != NULL ) data->on_close( inode, file ); MOD_DEC_USE_COUNT; if ( data->rbuffer ) kfree( data->rbuffer ); if ( data->wbuffer ) kfree( data->wbuffer ); kfree( data ); return 0;}static void proc_ssid_on_close( struct inode *inode, struct file *file ) { struct proc_data *data = (struct proc_data *)file->private_data; struct proc_dir_entry *dp = inode->u.generic_ip; struct net_device *dev = dp->data; struct cb20_info *vi = (struct cb20_info*)dev->priv; PC3500_SID_LIST *SSID_rid; char ssidp[200]; int i; int offset = 0; SSID_rid = (PC3500_SID_LIST *)ssidp; if ( !data->writelen ) return; memset( SSID_rid, 0, sizeof( SSID_rid ) ); for( i = 0; i < 3; i++ ) { int j; for( j = 0; j+offset < data->writelen && j < 32 && data->wbuffer[offset+j] != '\n'; j++ ) { SSID_rid->aSsid[i].Ssid[j] = data->wbuffer[offset+j]; } if ( j == 0 ) break; SSID_rid->aSsid[i].SsidLen = cpu_to_le16(j); offset += j; while( data->wbuffer[offset] != '\n' && offset < data->writelen ) offset++; offset++; } SSID_rid->u16RidLen = sizeof(PC3500_SID_LIST) * i; vwriterid(vi, RID_SSID, (unsigned char *)SSID_rid,sizeof(PC3500_SID_LIST) * i);}static int proc_ssid_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 cb20_info *vi = (struct cb20_info*)dev->priv; int i; char *ptr,blargbuf[1023]; PC3500_SID_LIST *SSID_rid; SSID_rid = (PC3500_SID_LIST *)blargbuf; MOD_INC_USE_COUNT; dp = (struct proc_dir_entry *) inode->u.generic_ip; file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL); memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; data->rbuffer = kmalloc( 104, GFP_KERNEL ); data->writelen = 0; data->maxwritelen = 33*3; data->wbuffer = kmalloc( 33*3, GFP_KERNEL ); memset( data->wbuffer, 0, 33*3 ); data->on_close = proc_ssid_on_close; vreadrid(vi,RID_SSLIST,(unsigned char *)SSID_rid, sizeof(SSID_rid)); ptr = data->rbuffer; for( i = 0; i < 3; i++ ) { int j; if ( !SSID_rid->aSsid[i].SsidLen ) break; for( j = 0; j < 32 && j < le16_to_cpu(SSID_rid->aSsid[i].SsidLen) && SSID_rid->aSsid[i].Ssid[j]; j++ ) { *ptr++ = SSID_rid->aSsid[i].Ssid[j]; } *ptr++ = '\n'; } *ptr = '\0'; data->readlen = strlen( data->rbuffer ); return 0;}/* * Status open Changed 10/4/02 for proper display of * channel. */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 cb20_info *vi = (struct cb20_info *)dev->priv; STCAPS cap_rid; StatRid status_rid; MOD_INC_USE_COUNT; dp = (struct proc_dir_entry *) inode->u.generic_ip; file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL); memset(file->private_data, 0, sizeof(struct proc_data)); data = (struct proc_data *)file->private_data; data->rbuffer = kmalloc( 2048, GFP_KERNEL ); vreadrid(vi,RID_STATUS,(unsigned char *)&status_rid, sizeof(status_rid)); vreadrid(vi,RID_CAPABILITIES,(unsigned char *)&cap_rid, sizeof(cap_rid)); sprintf( data->rbuffer, "Mode: %x\n" "Signal Strength: %d\n" "Signal Quality: %d\n" "SSID: %-.*s\n" "AP: %-.16s\n" "Channel: %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)le16_to_cpu(status_rid.mode), (int)le16_to_cpu(status_rid.normalizedSignalStrength), (int)le16_to_cpu(status_rid.signalQuality), (int)status_rid.SSIDlen, status_rid.SSID, status_rid.apName, (int)le16_to_cpu(status_rid.frq.u16DsChannel), (int)le16_to_cpu(status_rid.currentXmitRate)/2, version, cap_rid.au8ProductName, cap_rid.au8ManufacturerName, cap_rid.au8ProductVersion, le16_to_cpu(cap_rid.u16RadioType), le16_to_cpu(cap_rid.u16RegDomain), le16_to_cpu(cap_rid.u16HardwareVersion), (int)le16_to_cpu(cap_rid.u16SoftwareVersion), (int)le16_to_cpu(cap_rid.u16SoftwareSubVersion), (int)le16_to_cpu(cap_rid.u16BootBlockVersion) ); data->readlen = strlen( data->rbuffer ); return 0;}/* * @vreadrid * Return 0 on sucess or other on failure . Uses the len value of all rids * in the first 2 bytes . */static int vreadrid(struct cb20_info *v_info,unsigned short rid,unsigned char *ridp, int len){ Cmd cmd; Resp rsp; int status; unsigned short *ridlen; CARD_RID_DESC *cardDes; cardDes = (CARD_RID_DESC *)v_info->ConfigDesc.CardRamOff; memset(&rsp,0,sizeof(rsp)); memset(&cmd,0,sizeof(cmd)); v_info->ConfigDesc.RIDDesc.valid = 0; v_info->ConfigDesc.RIDDesc.length = 1024; v_info->ConfigDesc.RIDDesc.RID = rid; cmd.cmd = CMD_X500_AccessRIDRead; cmd.parm0 = rid; memcpy((char *)v_info->ConfigDesc.CardRamOff, (char *)&v_info->ConfigDesc.RIDDesc,sizeof(CARD_RID_DESC)); cardDes->valid=1; status = cb20command(v_info,&cmd,&rsp); /* If status error return qualifier */ if((rsp.status & 0x7f00) !=0 ) return rsp.rsp0; /* return error qualifier */ if(!status){ ridlen = VADDR(unsigned short,v_info->ConfigDesc); *ridlen = (*ridlen > len) ? len : *ridlen; memcpy((char *)ridp,(char *)v_info->ConfigDesc.VirtualHostAddress,*ridlen); } return status;}/* * @writerid * */static int vwriterid(struct cb20_info *v_info,unsigned short rid,unsigned char *ridp,int len){ Cmd cmd; Resp rsp; ConfigRid *cfg; int status; int irqstate; u16 *ridlen,rlen; CARD_RID_DESC *carddesc = (CARD_RID_DESC*)v_info->ConfigDesc.CardRamOff; memset(&rsp,0,sizeof(rsp)); memset(&cmd,0,sizeof(cmd)); irqstate = cb20in(v_info,V_EVINTEN); cb20out(v_info,V_EVINTEN,0); mac_disable(v_info ); /* * Check for addhoc change in cfg. MIC needs * to know about it. */ if(rid == RID_CONFIG){ cfg = (ConfigRid *)ridp; if((cfg->opmode & 1)==0) v_info->flags |= ADHOC; else v_info->flags &= ~(ADHOC); } v_info->ConfigDesc.RIDDesc.valid = 1; v_info->ConfigDesc.RIDDesc.length = len; v_info->ConfigDesc.RIDDesc.RID = 0; cmd.cmd = CMD_X500_AccessRIDWrite; cmd.parm0 = rid; rlen = sizeof(CARD_RID_DESC); memcpy((char *)v_info->ConfigDesc.CardRamOff, (char *)&v_info->ConfigDesc.RIDDesc,sizeof(CARD_RID_DESC)); ridlen = (u16 *)ridp; if(*ridlen < 4 || *ridlen > 2047 ){ printk(KERN_ERR "RIDLEN in vwrite = %x\n",*ridlen); return -1; } memcpy((char *)v_info->ConfigDesc.VirtualHostAddress,(char *)ridp,*ridlen); carddesc->valid = 1; if(((status = cb20command(v_info,&cmd,&rsp)) & 0xff00) !=0){ printk(KERN_ERR "Write rid Error %d\n",status); printk(KERN_ERR "Cmd = %x\n",cmd.cmd); } mac_enable(v_info,&rsp); cb20out(v_info,V_EVINTEN,irqstate); /* If status error return qualifier */ if((rsp.status & 0x7f00)!=0) return rsp.rsp0; return status;}/* In/out word * @cb20out */ unsigned short cb20in(struct cb20_info *vp,u16 reg){ unsigned short ret; ret = inw(vp->iobase+reg); return ret;}void cb20out(struct cb20_info *vp,u16 reg,u16 val){ outw(val,vp->iobase+reg);}/* @command */static u16 cb20command(struct cb20_info *ai, Cmd *pCmd, Resp *pRsp) { int flags; int max_tries =600000; int rc = SUCCESS; int i,ik=0; if(ai->flags & NOCARD ) return -NODEV; /* Ejected */ spin_lock_irqsave(&ai->cmd_lock, flags); // wait for no busy for(i=0;i!=600000;i++){ if (cb20in(ai, V_COMMAND) & COMMAND_BUSY) { mdelay(10); } else break; } if(i==600000){#ifdef DEBUG_CMD printk(KERN_ERR "Was busy too long \n");#endif rc = ERROR; goto trynclear; } cb20out(ai, V_PARAM0, pCmd->parm0); cb20out(ai, V_PARAM1, pCmd->parm1); cb20out(ai, V_PARAM2, pCmd->parm2); cb20out(ai, V_COMMAND, pCmd->cmd); /* * Check for reset command . Takes a while and does * not return EV_CMD status. Caller must delay ~1s . * after calling. */ if(pCmd->cmd == CMD_X500_ResetCard ) goto done; while ( max_tries-- && (cb20in(ai, V_EVSTAT) & EV_CMD)== 0) { if ( (ik = cb20in(ai, V_COMMAND)) == pCmd->cmd) { // didn't notice command, try again cb20out(ai, V_COMMAND, pCmd->cmd); } } trynclear: if ( max_tries == -1 ) { printk( KERN_ERR "CB20: Max tries exceeded when issueing command\n" ); printk( KERN_ERR "CB20: Command was %x\n",pCmd->cmd ); rc = ERROR;#ifdef DEBUG_CMD printk(KERN_ERR "Hung command reg = %x\n",cb20in(ai,V_COMMAND));#endif cb20_kick(ai); if ( !cb20_clear(ai)){#ifdef DEBUG_CMD printk(KERN_ERR "Command register cleared!\n");#endif goto done; } else{ printk(KERN_ERR "Could not clear command register\n"); goto done; } } // command completed pRsp->status = cb20in(ai, V_STATUS); pRsp->rsp0 = cb20in(ai, V_RESP0); pRsp->rsp1 = cb20in(ai, V_RESP1); pRsp->rsp2 = cb20in(ai, V_RESP2); // clear stuck command busy if necessary if (cb20in(ai, V_COMMAND) & COMMAND_BUSY) { cb20out(ai, V_EVACK, EV_CLEARCOMMANDBUSY); } // acknowledge processing the status/response cb20out(ai, V_EVACK, EV_CMD); done: if((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_X500_ResetCard ){ printk(KERN_ERR "cb20command cmd = %x\n",pCmd->cmd); printk(KERN_ERR "cb20command status = %x\n",pRsp->status); printk(KERN_ERR "cb20command Rsp0 = %x\n",pRsp->rsp0); printk(KERN_ERR "cb20command Rsp1 = %x\n",pRsp->rsp1); printk(KERN_ERR "cb20command Rsp2 = %x\n",pRsp->rsp2); } spin_unlock_irqrestore(&ai->cmd_lock, flags); return rc;}static void cb20_kick(struct cb20_info *v_info){#ifdef DEBUG_CMD printk(KERN_ERR "Cb20 kick!!\n");#endif cb20out(v_info,V_COMMAND,0x10); mdelay(20);}/* * Try to clear stuck command busy bit return * 0 if cleared NZ if not */static int cb20_clear(struct cb20_info *v_info){ u32 ccmd,maxtries = 10000; if (cb20in(v_info, V_COMMAND) & COMMAND_BUSY) { cb20out(v_info, V_EVACK, EV_CMD); } else {#ifdef DEBUG_CMD printk(KERN_ERR "Busy not set in cb20 clear !!\n");#endif return 0; /* Busybit not set */ } while ( maxtries-- && ((cb20in(v_info, V_EVSTAT)) & EV_CMD)== 0) { mdelay(10); if ( (ccmd = cb20in(v_info, V_COMMAND)) & COMMAND_BUSY ) { cb20out(v_info, V_EVACK, EV_CMD); } } if(maxtries > 0 ){#if DEBUG_CMD printk(KERN_ERR "Acknowledge command in clear!!\n");#endif cb20out(v_info, V_EVACK, EV_CMD); return 0; } else printk(KERN_ERR "Could not clear command busy !\n"); return 1;}/******************************************************************* * @init_cb20_card the descriptors etc start ball rolling. * ******************************************************************* */static struct net_device *init_cb20_card(struct pci_dev *vencard){ TXFID_HDR txFidHdr = {{0, 0, 0, 0, 0x20, 0, 0, 0}}; struct net_device *vdev; int i,status; struct cb20_info *v_info; unsigned char *busaddroff,*vpackoff; unsigned char *pciaddroff; Cmd cmd; Resp rsp; if(!vencard){ printk(KERN_ERR "No cb20 found!\n"); return 0; } vdev = 0; vdev = init_etherdev(0,sizeof(struct cb20_info)); if(!vdev){ printk( KERN_INFO "CB20: etherdev alloc FAILED\n"); return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -