📄 orinoco.c
字号:
if (err) { printk(KERN_ERR "%s: failed to read station name!n", dev->name); goto out; } if ( nickbuf.len ) len = MIN(IW_ESSID_MAX_SIZE, le16_to_cpu(nickbuf.len)); else len = MIN(IW_ESSID_MAX_SIZE, 2 * reclen); memcpy(priv->nick, &nickbuf.val, len); priv->nick[len] = '\0'; printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick); /* Get allowed channels */ err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNEL_LIST, &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_CNF_SYSTEM_SCALE, &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_CNF_RTS_THRESH, &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_CNF_MWO_ROBUST, &priv->mwo_robust); else err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNF_FRAG_THRESH, &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_CNF_PM_PERIOD, &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_CNF_PM_HOLDOVER, &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_CNF_SYMBOL_PREAMBLE, &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->allmulti = 0; priv->wep_on = 0; priv->tx_key = 0; printk(KERN_DEBUG "%s: ready\n", dev->name); out: dldwd_unlock(priv); TRACE_EXIT("dldwd"); return err;}struct net_device_stats *dldwd_get_stats(struct net_device *dev){ dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv; return &priv->stats;}struct iw_statistics *dldwd_get_wireless_stats(struct net_device *dev){ dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv; hermes_t *hw = &priv->hw; struct iw_statistics *wstats = &priv->wstats; int err = 0; hermes_commsqual_t cq; if (!priv->hw_ready) return NULL; dldwd_lock(priv); if (priv->iw_mode == IW_MODE_ADHOC) { memset(&wstats->qual, 0, sizeof(wstats->qual));#ifdef WIRELESS_SPY /* If a spy address is defined, we report stats of the * first spy address - Jean II */ if (priv->spy_number > 0) { 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; }#endif /* WIRELESS_SPY */ } else { err = hermes_read_commsqual(hw, USER_BAP, &cq); DEBUG(3, "%s: Global stats = %X-%X-%X\n", dev->name, cq.qual, cq.signal, cq.noise); /* Why are we using MIN/MAX ? We don't really care * if the value goes above max, because we export the * raw dBm values anyway. The normalisation should be done * in user space - Jean II */ wstats->qual.qual = MAX(MIN(cq.qual, 0x8b-0x2f), 0); wstats->qual.level = MAX(MIN(cq.signal, 0x8a), 0x2f) - 0x95; wstats->qual.noise = MAX(MIN(cq.noise, 0x8a), 0x2f) - 0x95; wstats->qual.updated = 7; } dldwd_unlock(priv); if (err) return NULL; return wstats;}#ifdef WIRELESS_SPYstatic inline void dldwd_spy_gather(struct net_device *dev, u_char *mac, hermes_commsqual_t *cq){ dldwd_priv_t *priv = (dldwd_priv_t *)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].qual = MAX(MIN(cq->qual, 0x8b-0x2f), 0); priv->spy_stat[i].level = MAX(MIN(cq->signal, 0x8a), 0x2f) - 0x95; priv->spy_stat[i].noise = MAX(MIN(cq->noise, 0x8a), 0x2f) - 0x95; priv->spy_stat[i].updated = 7; }}#endif /* WIRELESS_SPY */voiddldwd_stat_gather( struct net_device *dev, struct sk_buff *skb, struct dldwd_frame_hdr *hdr){ dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv; hermes_commsqual_t cq; /* 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 !!! */#ifdef WIRELESS_EXT /* Note : gcc will optimise the whole section away if * WIRELESS_SPY is not defined... - Jean II */ if (#ifdef WIRELESS_SPY (priv->spy_number > 0) ||#endif 0 ) { u_char *stats = (u_char *) &(hdr->desc.q_info); /* This code may look strange. Everywhere we are using 16 bit * ints except here. I've verified that these are are the * correct values. Please check on PPC - Jean II */ cq.signal = stats[1]; /* High order byte */ cq.noise = stats[0]; /* Low order byte */ cq.qual = stats[0] - stats[1]; /* Better than nothing */ DEBUG(3, "%s: Packet stats = %X-%X-%X\n", dev->name, cq.qual, cq.signal, cq.noise);#ifdef WIRELESS_SPY dldwd_spy_gather(dev, skb->mac.raw + ETH_ALEN, &cq); #endif }#endif /* WIRELESS_EXT */}intdldwd_xmit(struct sk_buff *skb, struct net_device *dev){ dldwd_priv_t *priv = (dldwd_priv_t *)dev->priv; struct net_device_stats *stats = &priv->stats; hermes_t *hw = &priv->hw; int err = 0; uint16_t txfid = priv->txfid; char *p; struct ethhdr *eh; int len, data_len, data_off; struct dldwd_frame_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; } dldwd_lock(priv); /* Length of the packet body */ len = MAX(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 = DLDWD_FTYPE_DATA; /* 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 data 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; } dev->trans_start = jiffies; stats->tx_bytes += data_off + data_len; netif_stop_queue(dev); dldwd_unlock(priv); dev_kfree_skb(skb); return 0; fail: dldwd_unlock(priv); return err;}voiddldwd_tx_timeout(struct net_device *dev){ dldwd_priv_t *priv = (dldwd_priv_t *)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 = dldwd_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 dldwd_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq){ dldwd_priv_t *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); dldwd_lock(priv); mode = priv->iw_mode; dldwd_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; } else { range.max_qual.qual = 0x8b - 0x2f; range.max_qual.level = 0x2f - 0x95 - 1; range.max_qual.noise = 0x2f - 0x95 - 1; } err = dldwd_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; range.min_frag = 256; range.max_frag = 2346; dldwd_lock(priv); if (priv->has_wep) { range.max_encoding_tokens = MAX_KEYS; range.encoding_size[0] = SMALL_KEY_SIZE; range.num_encoding_sizes = 1; if (priv->has_big_wep) { range.encoding_size[1] = LARGE_KEY_SIZE; range.num_encoding_sizes = 2; } } else { range.num_encoding_sizes = 0; range.max_encoding_tokens = 0; } dldwd_unlock(priv); range.min_pmp = 0; range.max_pmp = 65535000; range.min_pmt = 0; range.max_pmt = 65535 * 1000; /* ??? */ range.pmp_flags = IW_POWER_PERIOD; range.pmt_flags = IW_POWER_TIMEOUT; range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R; range.num_txpower = 1; range.txpower[0] = 15; /* 15dBm */ range.txpower_capa = IW_TXPOW_DBM;#if WIRELESS_EXT > 10 range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; range.retry_flags = IW_RETRY_LIMIT; range.r_time_flags = IW_RETRY_LIFETIME; range.min_retry = 0; range.max_retry = 65535; /* ??? */ range.min_r_time = 0; range.max_r_time = 65535 * 1000; /* ??? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -