📄 airo.c
字号:
u16 _reserved1a[1]; /*---------- Power save operation ----------*/ u16 powerSaveMode;#define POWERSAVE_CAM 0#define POWERSAVE_PSP 1#define POWERSAVE_PSPCAM 2 u16 sleepForDtims; u16 listenInterval; u16 fastListenInterval; u16 listenDecay; u16 fastListenDelay; u16 _reserved2[2]; /*---------- Ap/Ibss config items ----------*/ u16 beaconPeriod; u16 atimDuration; u16 hopPeriod; u16 channelSet; u16 channel; u16 dtimPeriod; u16 bridgeDistance; u16 radioID; /*---------- Radio configuration ----------*/ u16 radioType;#define RADIOTYPE_DEFAULT 0#define RADIOTYPE_802_11 1#define RADIOTYPE_LEGACY 2 u8 rxDiversity; u8 txDiversity; u16 txPower;#define TXPOWER_DEFAULT 0 u16 rssiThreshold;#define RSSI_DEFAULT 0 u16 modulation; u16 shortPreamble; u16 homeProduct; u16 radioSpecific; /*---------- Aironet Extensions ----------*/ u8 nodeName[16]; u16 arlThreshold; u16 arlDecay; u16 arlDelay; u16 _reserved4[1]; /*---------- Aironet Extensions ----------*/ u16 magicAction;#define MAGIC_ACTION_STSCHG 1#define MACIC_ACTION_RESUME 2#define MAGIC_IGNORE_MCAST (1<<8)#define MAGIC_IGNORE_BCAST (1<<9)#define MAGIC_SWITCH_TO_PSP (0<<10)#define MAGIC_STAY_IN_CAM (1<<10) u16 magicControl; u16 autoWake;} ConfigRid;typedef struct { u16 len; u8 mac[6]; u16 mode; u16 errorCode; u16 sigQuality; u16 SSIDlen; char SSID[32]; char apName[16]; char bssid[4][6]; u16 beaconPeriod; u16 dimPeriod; u16 atimDuration; u16 hopPeriod; u16 channelSet; u16 channel; u16 hopsToBackbone; u16 apTotalLoad; u16 generatedLoad; u16 accumulatedArl; u16 signalQuality; u16 currentXmitRate; u16 apDevExtensions; u16 normalizedSignalStrength; u16 _reserved[10];} StatusRid;typedef struct { u16 len; u16 spacer; u32 vals[100];} StatsRid; typedef struct { u16 len; u8 ap[4][6];} APListRid;typedef struct { u16 len; char oui[3]; u16 prodNum; char manName[32]; char prodName[16]; char prodVer[8]; char factoryAddr[6]; char aironetAddr[6]; u16 radioType; u16 country; char callid[6]; char supportedRates[8]; char rxDiversity; char txDiversity; u16 txPowerLevels[8]; u16 hardVer; u16 hardCap; u16 tempRange; u16 softVer; u16 softSubVer; u16 interfaceVer; u16 softCap; u16 bootBlockVer; u16 requiredHard;} CapabilityRid;#define TXCTL_TXOK (1<<1) /* report if tx is ok */#define TXCTL_TXEX (1<<2) /* report if tx fails */#define TXCTL_802_3 (0<<3) /* 802.3 packet */#define TXCTL_802_11 (1<<3) /* 802.11 mac packet */#define TXCTL_ETHERNET (0<<4) /* payload has ethertype */#define TXCTL_LLC (1<<4) /* payload is llc */#define TXCTL_RELEASE (0<<5) /* release after completion */#define TXCTL_NORELEASE (1<<5) /* on completion returns to host */#define BUSY_FID 0x10000#ifdef CISCO_EXT#define AIROMAGIC 0xa55a#define AIROIOCTL SIOCDEVPRIVATE#define AIROIDIFC AIROIOCTL + 1/* Ioctl constants to be used in airo_ioctl.command */#define AIROGCAP 0 // Capability rid#define AIROGCFG 1 // USED A LOT #define AIROGSLIST 2 // System ID list #define AIROGVLIST 3 // List of specified AP's#define AIROGDRVNAM 4 // NOTUSED#define AIROGEHTENC 5 // NOTUSED#define AIROGWEPKTMP 6#define AIROGWEPKNV 7#define AIROGSTAT 8#define AIROGSTATSC32 9#define AIROGSTATSD32 10/* Leave gap of 40 commands after AIROGSTATSD32 for future */#define AIROPCAP AIROGSTATSD32 + 40#define AIROPVLIST AIROPCAP + 1#define AIROPSLIST AIROPVLIST + 1#define AIROPCFG AIROPSLIST + 1#define AIROPSIDS AIROPCFG + 1#define AIROPAPLIST AIROPSIDS + 1#define AIROPMACON AIROPAPLIST + 1 /* Enable mac */#define AIROPMACOFF AIROPMACON + 1 /* Disable mac */#define AIROPSTCLR AIROPMACOFF + 1#define AIROPWEPKEY AIROPSTCLR + 1#define AIROPWEPKEYNV AIROPWEPKEY + 1#define AIROPLEAPPWD AIROPWEPKEYNV + 1#define AIROPLEAPUSR AIROPLEAPPWD + 1/* Flash codes */#define AIROFLSHRST AIROPWEPKEYNV + 40#define AIROFLSHGCHR AIROFLSHRST + 1#define AIROFLSHSTFL AIROFLSHGCHR + 1#define AIROFLSHPCHR AIROFLSHSTFL + 1#define AIROFLPUTBUF AIROFLSHPCHR + 1#define AIRORESTART AIROFLPUTBUF + 1#define FLASHSIZE 32768typedef struct aironet_ioctl { unsigned short command; // What to do unsigned short len; // Len of data unsigned char *data; // d-data} aironet_ioctl;#endif /* CISCO_EXT */#ifdef WIRELESS_EXT// Frequency list (map channels to frequencies)const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 };// A few details needed for WEP (Wireless Equivalent Privacy)#define MAX_KEY_SIZE 13 // 128 (?) bits#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP#define MAX_KEYS 4 // 4 different keystypedef struct wep_key_t { u16 len; u8 key[16]; /* 40-bit and 104-bit keys */} wep_key_t;#endif /* WIRELESS_EXT */static char *version ="airo.c 1.8 2001/03/27 (Benjamin Reed et al)";struct airo_info;static int get_dec_u16( char *buffer, int *start, int limit );static void OUT4500( struct airo_info *, u16 register, u16 value );static unsigned short IN4500( struct airo_info *, u16 register );static u16 setup_card(struct airo_info*, u8 *mac, ConfigRid *);static void enable_interrupts(struct airo_info*);static void disable_interrupts(struct airo_info*);static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap);static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap);static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen, int whichbap);static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len);static int PC4500_writerid(struct airo_info*, u16 rid, const void *pBuf, int len);static int do_writerid( struct airo_info*, u16 rid, const void *rid_data, int len );static u16 transmit_allocate(struct airo_info*, int lenPayload);static int transmit_802_3_packet(struct airo_info*, u16 TxFid, char *pPacket, int len);static void airo_interrupt( int irq, void* dev_id, struct pt_regs *regs);static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);#ifdef WIRELESS_EXTstruct iw_statistics *airo_get_wireless_stats (struct net_device *dev);#endif /* WIRELESS_EXT */#ifdef CISCO_EXTstatic int readrids(struct net_device *dev, aironet_ioctl *comp);static int writerids(struct net_device *dev, aironet_ioctl *comp);int flashcard(struct net_device *dev, aironet_ioctl *comp);#endif /* CISCO_EXT */struct airo_info { struct net_device_stats stats; int open;#if (LINUX_VERSION_CODE < 0x020363) char name[8];#endif struct net_device *dev; /* Note, we can have MAX_FIDS outstanding. FIDs are 16-bits, so we use the high bit to mark wether it is in use. */#define MAX_FIDS 6 int fids[MAX_FIDS]; int registered; ConfigRid config; u16 authtype; // Used with auto_wep char keyindex; // Used with auto wep char defindex; // Used with auto wep struct timer_list timer;#if (LINUX_VERSION_CODE < 0x20311) struct proc_dir_entry proc_entry; struct proc_dir_entry proc_statsdelta_entry; struct proc_dir_entry proc_stats_entry; struct proc_dir_entry proc_status_entry; struct proc_dir_entry proc_config_entry; struct proc_dir_entry proc_SSID_entry; struct proc_dir_entry proc_APList_entry; struct proc_dir_entry proc_wepkey_entry;#else struct proc_dir_entry *proc_entry;#endif struct airo_info *next; spinlock_t bap0_lock; spinlock_t bap1_lock; spinlock_t aux_lock; spinlock_t cmd_lock; int flags;#define FLAG_PROMISC 0x01#define FLAG_RADIO_OFF 0x02 int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap);#ifdef WIRELESS_EXT int need_commit; // Need to set config struct iw_statistics wstats; // wireless stats#endif /* WIRELESS_EXT */#ifdef WIRELESS_SPY int spy_number; u_char spy_address[IW_MAX_SPY][6]; struct iw_quality spy_stat[IW_MAX_SPY];#endif /* WIRELESS_SPY */};static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, int whichbap) { return ai->bap_read(ai, pu16Dst, bytelen, whichbap);}static int setup_proc_entry( struct net_device *dev, struct airo_info *apriv );static int takedown_proc_entry( struct net_device *dev, struct airo_info *apriv );static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp) { int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, wkr, sizeof(*wkr)); wkr->len = le16_to_cpu(wkr->len); wkr->kindex = le16_to_cpu(wkr->kindex); wkr->klen = le16_to_cpu(wkr->klen); return rc;}/* In the writeXXXRid routines we copy the rids so that we don't screwup * the originals when we endian them... */static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm) { int rc; WepKeyRid wkr = *pwkr; wkr.len = cpu_to_le16(wkr.len); wkr.kindex = cpu_to_le16(wkr.kindex); wkr.klen = cpu_to_le16(wkr.klen); rc = do_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr)); if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc); if (perm) { rc = do_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr)); if (rc!=SUCCESS) { printk(KERN_ERR "airo: WEP_PERM set %x\n", rc); } } return rc;}static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) { int i; int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr)); ssidr->len = le16_to_cpu(ssidr->len); for(i = 0; i < 3; i++) { ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len); } return rc;}static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr) { int rc; int i; SsidRid ssidr = *pssidr; ssidr.len = cpu_to_le16(ssidr.len); for(i = 0; i < 3; i++) { ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len); } rc = do_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr)); return rc;}static int readConfigRid(struct airo_info*ai, ConfigRid *cfgr) { int rc = PC4500_readrid(ai, RID_ACTUALCONFIG, cfgr, sizeof(*cfgr)); u16 *s; for(s = &cfgr->len; s <= &cfgr->rtsThres; s++) *s = le16_to_cpu(*s); for(s = &cfgr->shortRetryLimit; s <= &cfgr->radioType; s++) *s = le16_to_cpu(*s); for(s = &cfgr->txPower; s <= &cfgr->radioSpecific; s++) *s = le16_to_cpu(*s); for(s = &cfgr->arlThreshold; s <= &cfgr->autoWake; s++) *s = le16_to_cpu(*s); return rc;}static int writeConfigRid(struct airo_info*ai, ConfigRid *pcfgr) { u16 *s; ConfigRid cfgr = *pcfgr; for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s); for(s = &cfgr.shortRetryLimit; s <= &cfgr.radioType; s++) *s = cpu_to_le16(*s); for(s = &cfgr.txPower; s <= &cfgr.radioSpecific; s++) *s = cpu_to_le16(*s); for(s = &cfgr.arlThreshold; s <= &cfgr.autoWake; s++) *s = cpu_to_le16(*s); return do_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr));}static int readStatusRid(struct airo_info*ai, StatusRid *statr) { int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr)); 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; MOD_INC_USE_COUNT; if ( info->open == 0 ) { enable_interrupts(info); } info->open++; netif_start_queue(dev); netif_mark_up(dev); return 0;}static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { s16 len; s16 retval = 0; u16 status; u32 flags; s8 *buffer; int i; 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->bap1_lock, flags); for( i = 0; i < MAX_FIDS; i++ ) { if ( !( fids[i] & 0xffff0000 ) ) break; } if ( i == MAX_FIDS ) { netif_stop_queue(dev); retval = -EBUSY; goto tx_done; } len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/ buffer = skb->data; 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 { ((struct airo_info*)dev->priv)->stats.tx_errors++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -