📄 airo.c
字号:
static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) { int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock); 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 lock) { int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock); 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; Resp rsp; if (test_bit(FLAG_FLASHING, &info->flags)) return -EIO; /* Make sure the card is configured. * Wireless Extensions may postpone config changes until the card * is open (to pipeline changes and speed-up card setup). If * those changes are not yet commited, do it now - Jean II */ if (test_bit (FLAG_COMMIT, &info->flags)) { disable_MAC(info, 1); writeConfigRid(info, 1); } if (info->wifidev != dev) { /* Power on the MAC controller (which may have been disabled) */ clear_bit(FLAG_RADIO_DOWN, &info->flags); enable_interrupts(info); } enable_MAC(info, &rsp, 1); netif_start_queue(dev); return 0;}static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) { int npacks, pending; unsigned long flags; struct airo_info *ai = dev->priv; if (!skb) { printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__); return 0; } npacks = skb_queue_len (&ai->txq); if (npacks >= MAXTXQ - 1) { netif_stop_queue (dev); if (npacks > MAXTXQ) { ai->stats.tx_fifo_errors++; return 1; } skb_queue_tail (&ai->txq, skb); return 0; } spin_lock_irqsave(&ai->aux_lock, flags); skb_queue_tail (&ai->txq, skb); pending = test_bit(FLAG_PENDING_XMIT, &ai->flags); spin_unlock_irqrestore(&ai->aux_lock,flags); netif_wake_queue (dev); if (pending == 0) { set_bit(FLAG_PENDING_XMIT, &ai->flags); mpi_send_packet (dev); } return 0;}/* * @mpi_send_packet * * Attempt to transmit a packet. Can be called from interrupt * or transmit . return number of packets we tried to send */static int mpi_send_packet (struct net_device *dev){ struct sk_buff *skb; unsigned char *buffer; s16 len, *payloadLen; struct airo_info *ai = dev->priv; u8 *sendbuf; /* get a packet to send */ if ((skb = skb_dequeue(&ai->txq)) == 0) { printk (KERN_ERR "airo: %s: Dequeue'd zero in send_packet()\n", __FUNCTION__); return 0; } /* check min length*/ len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; buffer = skb->data; ai->txfids[0].tx_desc.offset = 0; ai->txfids[0].tx_desc.valid = 1; ai->txfids[0].tx_desc.eoc = 1; ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr);/* * Magic, the cards firmware needs a length count (2 bytes) in the host buffer * right after TXFID_HDR.The TXFID_HDR contains the status short so payloadlen * is immediatly after it. ------------------------------------------------ * |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA| * ------------------------------------------------ */ memcpy((char *)ai->txfids[0].virtual_host_addr, (char *)&wifictlhdr8023, sizeof(wifictlhdr8023)); payloadLen = (s16 *)(ai->txfids[0].virtual_host_addr + sizeof(wifictlhdr8023)); sendbuf = ai->txfids[0].virtual_host_addr + sizeof(wifictlhdr8023) + 2 ; /* * Firmware automaticly puts 802 header on so * we don't need to account for it in the length */#ifdef MICSUPPORT if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && (ntohs(((u16 *)buffer)[6]) != 0x888E)) { MICBuffer pMic; if (encapsulate(ai, (etherHead *)buffer, &pMic, len - sizeof(etherHead)) != SUCCESS) return ERROR; *payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic)); ai->txfids[0].tx_desc.len += sizeof(pMic); /* copy data into airo dma buffer */ memcpy (sendbuf, buffer, sizeof(etherHead)); buffer += sizeof(etherHead); sendbuf += sizeof(etherHead); memcpy (sendbuf, &pMic, sizeof(pMic)); sendbuf += sizeof(pMic); memcpy (sendbuf, buffer, len - sizeof(etherHead)); } else#endif { *payloadLen = cpu_to_le16(len - sizeof(etherHead)); dev->trans_start = jiffies; /* copy data into airo dma buffer */ memcpy(sendbuf, buffer, len); } memcpy_toio(ai->txfids[0].card_ram_off, &ai->txfids[0].tx_desc, sizeof(TxFid)); OUT4500(ai, EVACK, 8); dev_kfree_skb_any(skb); return 1;}static void get_tx_error(struct airo_info *ai, s32 fid){ u16 status; if (fid < 0) status = ((WifiCtlHdr *)ai->txfids[0].virtual_host_addr)->ctlhdr.status; else { if (bap_setup(ai, ai->fids[fid] & 0xffff, 4, BAP0) != SUCCESS) return; bap_read(ai, &status, 2, BAP0); } if (le16_to_cpu(status) & 2) /* Too many retries */ ai->stats.tx_aborted_errors++; if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */ ai->stats.tx_heartbeat_errors++; if (le16_to_cpu(status) & 8) /* Aid fail */ { } if (le16_to_cpu(status) & 0x10) /* MAC disabled */ ai->stats.tx_carrier_errors++; if (le16_to_cpu(status) & 0x20) /* Association lost */ { } /* We produce a TXDROP event only for retry or lifetime * exceeded, because that's the only status that really mean * that this particular node went away. * Other errors means that *we* screwed up. - Jean II */ if ((le16_to_cpu(status) & 2) || (le16_to_cpu(status) & 4)) { union iwreq_data wrqu; char junk[0x18]; /* Faster to skip over useless data than to do * another bap_setup(). We are at offset 0x6 and * need to go to 0x18 and read 6 bytes - Jean II */ bap_read(ai, (u16 *) junk, 0x18, BAP0); /* Copy 802.11 dest address. * We use the 802.11 header because the frame may * not be 802.3 or may be mangled... * In Ad-Hoc mode, it will be the node address. * In managed mode, it will be most likely the AP addr * User space will figure out how to convert it to * whatever it needs (IP address or else). * - Jean II */ memcpy(wrqu.addr.sa_data, junk + 0x12, ETH_ALEN); wrqu.addr.sa_family = ARPHRD_ETHER; /* Send event to user space */ wireless_send_event(ai->dev, IWEVTXDROP, &wrqu, NULL); }}static void airo_end_xmit(struct net_device *dev) { u16 status; int i; struct airo_info *priv = dev->priv; struct sk_buff *skb = priv->xmit.skb; int fid = priv->xmit.fid; u32 *fids = priv->fids; clear_bit(JOB_XMIT, &priv->flags); clear_bit(FLAG_PENDING_XMIT, &priv->flags); status = transmit_802_3_packet (priv, fids[fid], skb->data); up(&priv->sem); i = 0; if ( status == SUCCESS ) { dev->trans_start = jiffies; for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++); } else { priv->fids[fid] &= 0xffff; priv->stats.tx_window_errors++; } if (i < MAX_FIDS / 2) netif_wake_queue(dev); dev_kfree_skb(skb);}static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) { s16 len; int i, j; struct airo_info *priv = dev->priv; u32 *fids = priv->fids; if ( skb == NULL ) { printk( KERN_ERR "airo: skb == NULL!!!\n" ); return 0; } /* Find a vacant FID */ for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ ); for( j = i + 1; j < MAX_FIDS / 2 && (fids[j] & 0xffff0000); j++ ); if ( j >= MAX_FIDS / 2 ) { netif_stop_queue(dev); if (i == MAX_FIDS / 2) { priv->stats.tx_fifo_errors++; return 1; } } /* check min length*/ len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* Mark fid as used & save length for later */ fids[i] |= (len << 16); priv->xmit.skb = skb; priv->xmit.fid = i; if (down_trylock(&priv->sem) != 0) { set_bit(FLAG_PENDING_XMIT, &priv->flags); netif_stop_queue(dev); set_bit(JOB_XMIT, &priv->flags); wake_up_interruptible(&priv->thr_wait); } else airo_end_xmit(dev); return 0;}static void airo_end_xmit11(struct net_device *dev) { u16 status; int i; struct airo_info *priv = dev->priv; struct sk_buff *skb = priv->xmit11.skb; int fid = priv->xmit11.fid; u32 *fids = priv->fids; clear_bit(JOB_XMIT11, &priv->flags); clear_bit(FLAG_PENDING_XMIT11, &priv->flags); status = transmit_802_11_packet (priv, fids[fid], skb->data); up(&priv->sem); i = MAX_FIDS / 2; if ( status == SUCCESS ) { dev->trans_start = jiffies; for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++); } else { priv->fids[fid] &= 0xffff; priv->stats.tx_window_errors++; } if (i < MAX_FIDS) netif_wake_queue(dev); dev_kfree_skb(skb);}static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) { s16 len; int i, j; struct airo_info *priv = dev->priv; u32 *fids = priv->fids; if (test_bit(FLAG_MPI, &priv->flags)) { /* Not implemented yet for MPI350 */ netif_stop_queue(dev); return -ENETDOWN; } if ( skb == NULL ) { printk( KERN_ERR "airo: skb == NULL!!!\n" ); return 0; } /* Find a vacant FID */ for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ ); for( j = i + 1; j < MAX_FIDS && (fids[j] & 0xffff0000); j++ ); if ( j >= MAX_FIDS ) { netif_stop_queue(dev); if (i == MAX_FIDS) { priv->stats.tx_fifo_errors++; return 1; } } /* check min length*/ len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* Mark fid as used & save length for later */ fids[i] |= (len << 16); priv->xmit11.skb = skb; priv->xmit11.fid = i; if (down_trylock(&priv->sem) != 0) { set_bit(FLAG_PENDING_XMIT11, &priv->flags); netif_stop_queue(dev); set_bit(JOB_XMIT11, &priv->flags); wake_up_interruptible(&priv->thr_wait); } else airo_end_xmit11(dev); return 0;}static void airo_read_stats(struct airo_info *ai) { StatsRid stats_rid; u32 *vals = stats_rid.vals; clear_bit(JOB_STATS, &ai->flags); if (ai->power.event) { up(&ai->sem); return; } readStatsRid(ai, &stats_rid, RID_STATS, 0); up(&ai->sem); ai->stats.rx_packets = vals[43] + vals[44] + vals[45]; ai->stats.tx_packets = vals[39] + vals[40] + vals[41]; ai->stats.rx_bytes = vals[92]; ai->stats.tx_bytes = vals[91]; ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4]; ai->stats.tx_errors = vals[42] + ai->stats.tx_fifo_errors; ai->stats.multicast = vals[43]; ai->stats.collisions = vals[89]; /* detailed rx_errors: */ ai->stats.rx_length_errors = vals[3]; ai->stats.rx_crc_errors = vals[4]; ai->stats.rx_frame_errors = vals[2]; ai->stats.rx_fifo_errors = vals[0];}static struct net_device_stats *airo_get_stats(struct net_device *dev){ struct airo_info *local = dev->priv; if (!test_bit(JOB_STATS, &local->flags)) { /* Get stats out of the card if available */ if (down_trylock(&local->sem) != 0) { set_bit(JOB_STATS, &local->flags); wake_up_interruptible(&local->thr_wait); } else airo_read_stats(local); } return &local->stats;}static void airo_set_promisc(struct airo_info *ai) { Cmd cmd; Resp rsp; memset(&cmd, 0, sizeof(cmd)); cmd.cmd=CMD_SETMODE; clear_bit(JOB_PROMISC, &ai->flags); cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; issuecommand(ai, &cmd, &rsp); up(&ai->sem);}static void airo_set_multicast_list(struct net_device *dev) { struct airo_info *ai = dev->priv; if ((dev->flags ^ ai->flags) & IFF_PROMISC) { change_bit(FLAG_PROMISC, &ai->flags); if (down_trylock(&ai->sem) != 0) { set_bit(JOB_PROMISC, &ai->flags); wake_up_interruptible(&ai->thr_wait); } else airo_set_promisc(ai); } 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 = dev->priv; struct sockaddr *addr = p; Resp rsp; readConfigRid(ai, 1); memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len); set_bit (FLAG_COMMIT, &ai->flags); disable_MAC(ai, 1); writeConfigRid (ai, 1); enable_MAC(ai, &rsp, 1); memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len); if (ai->wifidev) memcpy (ai->wifidev->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 = dev->priv; netif_stop_queue(dev); if (ai->wifidev != dev) {#ifdef POWER_ON_DOWN /* Shut power to the card. The idea is that the user can save * power when he doesn't need the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -