📄 orinoco.c
字号:
printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick); /* Get allowed channels */ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST, &priv->channel_mask); if (err) { printk(KERN_ERR "%s: failed to read channel list!\n", dev->name); goto out; } /* Get initial AP density */ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, &priv->ap_density); if (err) { printk(KERN_ERR "%s: failed to read AP density!\n", dev->name); goto out; } /* Get initial RTS threshold */ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, &priv->rts_thresh); if (err) { printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name); goto out; } /* Get initial fragmentation settings */ if (priv->has_mwo) err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFMWOROBUST_AGERE, &priv->mwo_robust); else err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, &priv->frag_thresh); if (err) { printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name); goto out; } /* Power management setup */ if (priv->has_pm) { priv->pm_on = 0; priv->pm_mcast = 1; err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFMAXSLEEPDURATION, &priv->pm_period); if (err) { printk(KERN_ERR "%s: failed to read power management period!\n", dev->name); goto out; } err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMHOLDOVERDURATION, &priv->pm_timeout); if (err) { printk(KERN_ERR "%s: failed to read power management timeout!\n", dev->name); goto out; } } /* Preamble setup */ if (priv->has_preamble) { err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPREAMBLE_SYMBOL, &priv->preamble); if (err) goto out; } /* Set up the default configuration */ priv->iw_mode = IW_MODE_INFRA; /* By default use IEEE/IBSS ad-hoc mode if we have it */ priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss); set_port_type(priv); priv->promiscuous = 0; priv->wep_on = 0; priv->tx_key = 0; printk(KERN_DEBUG "%s: ready\n", dev->name); out: orinoco_unlock(priv); TRACE_EXIT("orinoco"); return err;}struct net_device_stats *orinoco_get_stats(struct net_device *dev){ struct orinoco_private *priv = (struct orinoco_private *)dev->priv; return &priv->stats;}struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev){ struct orinoco_private *priv = (struct orinoco_private *)dev->priv; hermes_t *hw = &priv->hw; struct iw_statistics *wstats = &priv->wstats; int err = 0; if (! netif_device_present(dev)) return NULL; /* FIXME: We may be able to do better than this */ orinoco_lock(priv); if (priv->iw_mode == IW_MODE_ADHOC) { memset(&wstats->qual, 0, sizeof(wstats->qual)); /* If a spy address is defined, we report stats of the * first spy address - Jean II */ if (SPY_NUMBER(priv)) { wstats->qual.qual = priv->spy_stat[0].qual; wstats->qual.level = priv->spy_stat[0].level; wstats->qual.noise = priv->spy_stat[0].noise; wstats->qual.updated = priv->spy_stat[0].updated; } } else { orinoco_commsqual_t cq; err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_COMMSQUALITY, &cq); DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name, cq.qual, cq.signal, cq.noise); wstats->qual.qual = (int)le16_to_cpu(cq.qual); wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; wstats->qual.updated = 7; } /* We can't really wait for the tallies inquiry command to * complete, so we just use the previous results and trigger * a new tallies inquiry command for next time - Jean II */ /* FIXME: Hmm.. seems a bit ugly, I wonder if there's a way to do better - dgibson */ err = hermes_inquire(hw, HERMES_INQ_TALLIES); orinoco_unlock(priv); if (err) return NULL; return wstats;}static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, int level, int noise){ struct orinoco_private *priv = (struct orinoco_private *)dev->priv; int i; /* Gather wireless spy statistics: for each packet, compare the * source address with out list, and if match, get the stats... */ for (i = 0; i < priv->spy_number; i++) if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) { priv->spy_stat[i].level = level - 0x95; priv->spy_stat[i].noise = noise - 0x95; priv->spy_stat[i].qual = level - noise; priv->spy_stat[i].updated = 7; }}voidorinoco_stat_gather( struct net_device *dev, struct sk_buff *skb, struct orinoco_rxframe_hdr *hdr){ struct orinoco_private *priv = (struct orinoco_private *)dev->priv; /* Using spy support with lots of Rx packets, like in an * infrastructure (AP), will really slow down everything, because * the MAC address must be compared to each entry of the spy list. * If the user really asks for it (set some address in the * spy list), we do it, but he will pay the price. * Note that to get here, you need both WIRELESS_SPY * compiled in AND some addresses in the list !!! */ /* Note : gcc will optimise the whole section away if * WIRELESS_SPY is not defined... - Jean II */ if (SPY_NUMBER(priv)) { orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN, hdr->desc.signal, hdr->desc.silence); }}intorinoco_xmit(struct sk_buff *skb, struct net_device *dev){ struct orinoco_private *priv = (struct orinoco_private *)dev->priv; struct net_device_stats *stats = &priv->stats; hermes_t *hw = &priv->hw; int err = 0; u16 txfid = priv->txfid; char *p; struct ethhdr *eh; int len, data_len, data_off; struct orinoco_txframe_hdr hdr; hermes_response_t resp; if (! netif_running(dev)) { printk(KERN_ERR "%s: Tx on stopped device!\n", dev->name); return 1; } if (netif_queue_stopped(dev)) { printk(KERN_ERR "%s: Tx while transmitter busy!\n", dev->name); return 1; } orinoco_lock(priv); /* Length of the packet body */ /* FIXME: what if the skb is smaller than this? */ len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN); eh = (struct ethhdr *)skb->data; /* Build the IEEE 802.11 header */ memset(&hdr, 0, sizeof(hdr)); memcpy(hdr.p80211.addr1, eh->h_dest, ETH_ALEN); memcpy(hdr.p80211.addr2, eh->h_source, ETH_ALEN); hdr.p80211.frame_ctl = IEEE802_11_FTYPE_DATA; /* Request an interrupt on Tx failures, but not sucesses (we use the buffer reclaim allocation event instead */ hdr.desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_EX | HERMES_TXCTRL_TX_OK); /* Encapsulate Ethernet-II frames */ if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */ data_len = len; data_off = sizeof(hdr); p = skb->data + ETH_HLEN; /* 802.11 header */ hdr.p80211.data_len = cpu_to_le16(data_len + ENCAPS_OVERHEAD); /* 802.3 header */ memcpy(hdr.p8023.h_dest, eh->h_dest, ETH_ALEN); memcpy(hdr.p8023.h_source, eh->h_source, ETH_ALEN); hdr.p8023.h_proto = htons(data_len + ENCAPS_OVERHEAD); /* 802.2 header */ memcpy(&hdr.p8022, &encaps_hdr, sizeof(encaps_hdr)); hdr.ethertype = eh->h_proto; err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), txfid, 0); if (err) { printk(KERN_ERR "%s: Error %d writing packet header to BAP\n", dev->name, err); stats->tx_errors++; goto fail; } } else { /* IEEE 802.3 frame */ data_len = len + ETH_HLEN; data_off = P8023_OFFSET; p = skb->data; /* 802.11 header */ hdr.p80211.data_len = cpu_to_le16(len); err = hermes_bap_pwrite(hw, USER_BAP, &hdr, P8023_OFFSET, txfid, 0); if (err) { printk(KERN_ERR "%s: Error %d writing packet header to BAP\n", dev->name, err); stats->tx_errors++; goto fail; } } /* Round up for odd length packets */ err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off); if (err) { printk(KERN_ERR "%s: Error %d writing packet header to BAP\n", dev->name, err); stats->tx_errors++; goto fail; } /* Finally, we actually initiate the send */ err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, &resp); if (err) { printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err); stats->tx_errors++; goto fail; } atomic_inc(&priv->queue_length); dev->trans_start = jiffies; stats->tx_bytes += data_off + data_len; netif_stop_queue(dev); orinoco_unlock(priv); dev_kfree_skb(skb); return 0; fail: orinoco_unlock(priv); return err;}voidorinoco_tx_timeout(struct net_device *dev){ struct orinoco_private *priv = (struct orinoco_private *)dev->priv; struct net_device_stats *stats = &priv->stats; int err = 0; printk(KERN_WARNING "%s: Tx timeout! Resetting card.\n", dev->name); stats->tx_errors++; err = orinoco_reset(priv); if (err) printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n", dev->name, err); else { dev->trans_start = jiffies; netif_wake_queue(dev); }}static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq){ struct orinoco_private *priv = dev->priv; int err = 0; int mode; struct iw_range range; int numrates; int i, k; TRACE_ENTER(dev->name); err = verify_area(VERIFY_WRITE, rrq->pointer, sizeof(range)); if (err) return err; rrq->length = sizeof(range); orinoco_lock(priv); mode = priv->iw_mode; orinoco_unlock(priv); memset(&range, 0, sizeof(range)); /* Much of this shamelessly taken from wvlan_cs.c. No idea * what it all means -dgibson */#if WIRELESS_EXT > 10 range.we_version_compiled = WIRELESS_EXT; range.we_version_source = 11;#endif /* WIRELESS_EXT > 10 */ range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ /* Set available channels/frequencies */ range.num_channels = NUM_CHANNELS; k = 0; for (i = 0; i < NUM_CHANNELS; i++) { if (priv->channel_mask & (1 << i)) { range.freq[k].i = i + 1; range.freq[k].m = channel_frequency[i] * 100000; range.freq[k].e = 1; k++; } if (k >= IW_MAX_FREQUENCIES) break; } range.num_frequency = k; range.sensitivity = 3; if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ /* Quality stats meaningless in ad-hoc mode */ range.max_qual.qual = 0; range.max_qual.level = 0; range.max_qual.noise = 0;#if WIRELESS_EXT > 11 range.avg_qual.qual = 0; range.avg_qual.level = 0; range.avg_qual.noise = 0;#endif /* WIRELESS_EXT > 11 */ } else { range.max_qual.qual = 0x8b - 0x2f; range.max_qual.level = 0x2f - 0x95 - 1; range.max_qual.noise = 0x2f - 0x95 - 1;#if WIRELESS_EXT > 11 /* Need to get better values */ range.avg_qual.qual = 0x24; range.avg_qual.level = 0xC2; range.avg_qual.noise = 0x9E;#endif /* WIRELESS_EXT > 11 */ } err = orinoco_hw_get_bitratelist(priv, &numrates, range.bitrate, IW_MAX_BITRATES); if (err) return err; range.num_bitrates = numrates; /* Set an indication of the max TCP throughput in bit/s that we can * expect using this interface. May be use for QoS stuff... * Jean II */ if(numrates > 2) range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ else range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ range.min_rts = 0; range.max_rts = 2347;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -