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