📄 airo.c
字号:
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 + -