for (i = 0; i < ARRAY_SIZE(b43_tx_legacy_rate_phy_ctl); i++) {
e = &(b43_tx_legacy_rate_phy_ctl[i]); if (e->bitrate == bitrate) return e;
}
B43_WARN_ON(1); return NULL;
}
/* Extract the bitrate index out of a CCK PLCP header. */ staticint b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
{ switch (plcp->raw[0]) { case 0x0A: return 0; case 0x14: return 1; case 0x37: return 2; case 0x6E: return 3;
} return -1;
}
/* Extract the bitrate index out of an OFDM PLCP header. */ staticint b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
{ /* For 2 GHz band first OFDM rate is at index 4, see main.c */ int base = ghz5 ? 0 : 4;
switch (plcp->raw[0] & 0xF) { case 0xB: return base + 0; case 0xF: return base + 1; case 0xA: return base + 2; case 0xE: return base + 3; case 0x9: return base + 4; case 0xD: return base + 5; case 0x8: return base + 6; case 0xC: return base + 7;
} return -1;
}
u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
{ switch (bitrate) { case B43_CCK_RATE_1MB: return 0x0A; case B43_CCK_RATE_2MB: return 0x14; case B43_CCK_RATE_5MB: return 0x37; case B43_CCK_RATE_11MB: return 0x6E;
}
B43_WARN_ON(1); return 0;
}
u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate)
{ switch (bitrate) { case B43_OFDM_RATE_6MB: return 0xB; case B43_OFDM_RATE_9MB: return 0xF; case B43_OFDM_RATE_12MB: return 0xA; case B43_OFDM_RATE_18MB: return 0xE; case B43_OFDM_RATE_24MB: return 0x9; case B43_OFDM_RATE_36MB: return 0xD; case B43_OFDM_RATE_48MB: return 0x8; case B43_OFDM_RATE_54MB: return 0xC;
}
B43_WARN_ON(1); return 0;
}
if (0) { /* FIXME: MIMO */
} elseif (b43_is_cck_rate(bitrate) && phy->type != B43_PHYTYPE_LP) {
control = bw;
} else {
control = bw;
e = b43_tx_legacy_rate_phy_ctl_ent(bitrate); if (e) {
control |= e->coding_rate;
control |= e->modulation;
}
control |= B43_TXH_PHY1_MODE_SISO;
}
return control;
}
static u8 b43_calc_fallback_rate(u8 bitrate, int gmode)
{ switch (bitrate) { case B43_CCK_RATE_1MB: return B43_CCK_RATE_1MB; case B43_CCK_RATE_2MB: return B43_CCK_RATE_1MB; case B43_CCK_RATE_5MB: return B43_CCK_RATE_2MB; case B43_CCK_RATE_11MB: return B43_CCK_RATE_5MB; /* * Don't just fallback to CCK; it may be in 5GHz operation * and falling back to CCK won't work out very well.
*/ case B43_OFDM_RATE_6MB: if (gmode) return B43_CCK_RATE_5MB; else return B43_OFDM_RATE_6MB; case B43_OFDM_RATE_9MB: return B43_OFDM_RATE_6MB; case B43_OFDM_RATE_12MB: return B43_OFDM_RATE_9MB; case B43_OFDM_RATE_18MB: return B43_OFDM_RATE_12MB; case B43_OFDM_RATE_24MB: return B43_OFDM_RATE_18MB; case B43_OFDM_RATE_36MB: return B43_OFDM_RATE_24MB; case B43_OFDM_RATE_48MB: return B43_OFDM_RATE_36MB; case B43_OFDM_RATE_54MB: return B43_OFDM_RATE_48MB;
}
B43_WARN_ON(1); return 0;
}
/* Calculate duration for fallback rate */ if ((rate_fb == rate) ||
(wlhdr->duration_id & cpu_to_le16(0x8000)) ||
(wlhdr->duration_id == cpu_to_le16(0))) { /* If the fallback rate equals the normal rate or the * dur_id field contains an AID, CFP magic or 0,
* use the original dur_id field. */
txhdr->dur_fb = wlhdr->duration_id;
} else {
txhdr->dur_fb = ieee80211_generic_frame_duration(
dev->wl->hw, info->control.vif, info->band,
fragment_len, fbrate);
}
plcp_fragment_len = fragment_len + FCS_LEN; if (use_encryption) {
u8 key_idx = info->control.hw_key->hw_key_idx; struct b43_key *key; int wlhdr_len;
size_t iv_len;
if (unlikely(!key->keyconf)) { /* This key is invalid. This might only happen * in a short timeframe after machine resume before * we were able to reconfigure keys. * Drop this packet completely. Do not transmit it
* unencrypted to avoid leaking information. */ return -ENOKEY;
}
key_idx = b43_kidx_to_fw(dev, key_idx);
mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
B43_TXH_MAC_KEYIDX;
mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
B43_TXH_MAC_KEYALG;
wlhdr_len = ieee80211_hdrlen(fctl); if (key->algorithm == B43_SEC_ALGO_TKIP) {
u16 phase1key[5]; int i; /* we give the phase1key and iv16 here, the key is stored in * shm. With that the hardware can do phase 2 and encryption.
*/
ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key); /* phase1key is in host endian. Copy to little-endian txhdr->iv. */ for (i = 0; i < 5; i++) {
txhdr->iv[i * 2 + 0] = phase1key[i];
txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
} /* iv16 */
memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
} else {
iv_len = min_t(size_t, info->control.hw_key->iv_len,
ARRAY_SIZE(txhdr->iv));
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
}
} switch (dev->fw.hdr_format) { case B43_FW_HDR_598:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),
plcp_fragment_len, rate); break; case B43_FW_HDR_351:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp),
plcp_fragment_len, rate); break; case B43_FW_HDR_410:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),
plcp_fragment_len, rate); break;
}
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
plcp_fragment_len, rate_fb);
/* Extra Frame Types */ if (rate_fb_ofdm)
extra_ft |= B43_TXH_EFT_FB_OFDM; else
extra_ft |= B43_TXH_EFT_FB_CCK;
/* Set channel radio code. Note that the micrcode ORs 0x100 to * this value before comparing it to the value in SHM, if this * is a 5Ghz packet.
*/
txhdr->chan_radio_code = phy->channel;
/* PHY TX Control word */ if (rate_ofdm)
phy_ctl |= B43_TXH_PHY_ENC_OFDM; else
phy_ctl |= B43_TXH_PHY_ENC_CCK; if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
rates = info->control.rates; /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
mac_ctl |= B43_TXH_MAC_ACK; /* use hardware sequence counter as the non-TID counter */ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
mac_ctl |= B43_TXH_MAC_HWSEQ; if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
mac_ctl |= B43_TXH_MAC_STMSDU; if (!phy->gmode)
mac_ctl |= B43_TXH_MAC_5GHZ;
/* Overwrite rates[0].count to make the retry calculation * in the tx status easier. need the actual retry limit to * detect whether the fallback rate was used.
*/ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
mac_ctl |= B43_TXH_MAC_LONGFRAME;
} else {
rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
}
/* Generate the RTS or CTS-to-self frame */ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsignedint len; struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; int rts_rate_ofdm, rts_rate_fb_ofdm; struct b43_plcp_hdr6 *plcp; struct ieee80211_rate *rts_cts_rate;
/* Get metadata about the frame from the header. */
phystat0 = le16_to_cpu(rxhdr->phy_status0);
phystat3 = le16_to_cpu(rxhdr->phy_status3); switch (dev->fw.hdr_format) { case B43_FW_HDR_598:
macstat = le32_to_cpu(rxhdr->format_598.mac_status);
mactime = le16_to_cpu(rxhdr->format_598.mac_time);
chanstat = le16_to_cpu(rxhdr->format_598.channel); break; case B43_FW_HDR_410: case B43_FW_HDR_351:
macstat = le32_to_cpu(rxhdr->format_351.mac_status);
mactime = le16_to_cpu(rxhdr->format_351.mac_time);
chanstat = le16_to_cpu(rxhdr->format_351.channel); break;
}
if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
dev->wl->ieee_stats.dot11FCSErrorCount++;
status.flag |= RX_FLAG_FAILED_FCS_CRC;
} if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV)))
status.flag |= RX_FLAG_FAILED_PLCP_CRC; if (phystat0 & B43_RX_PHYST0_SHORTPRMBL)
status.enc_flags |= RX_ENC_FLAG_SHORTPRE; if (macstat & B43_RX_MAC_DECERR) { /* Decryption with the given key failed. * Drop the packet. We also won't be able to decrypt it with
* the key in software. */ goto drop;
}
if (macstat & B43_RX_MAC_DEC) { unsignedint keyidx; int wlhdr_len;
keyidx = ((macstat & B43_RX_MAC_KEYIDX)
>> B43_RX_MAC_KEYIDX_SHIFT); /* We must adjust the key index here. We want the "physical" * key index, but the ucode passed it slightly different.
*/
keyidx = b43_kidx_to_raw(dev, keyidx);
B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
/* Link quality statistics */ switch (chanstat & B43_RX_CHAN_PHYTYPE) { case B43_PHYTYPE_HT: /* TODO: is max the right choice? */
status.signal = max_t(__s8,
max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
rxhdr->phy_ht_power2); break; case B43_PHYTYPE_N: /* Broadcom has code for min and avg, but always uses max */ if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
status.signal = max(rxhdr->power1, rxhdr->power2); else
status.signal = max(rxhdr->power0, rxhdr->power1); break; case B43_PHYTYPE_B: case B43_PHYTYPE_G: case B43_PHYTYPE_LP:
status.signal = b43_rssi_postprocess(dev, rxhdr->jssi,
(phystat0 & B43_RX_PHYST0_OFDM),
(phystat0 & B43_RX_PHYST0_GAINCTL),
(phystat3 & B43_RX_PHYST3_TRSTATE)); break;
}
if (phystat0 & B43_RX_PHYST0_OFDM)
rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
!!(chanstat & B43_RX_CHAN_5GHZ)); else
rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); if (unlikely(rate_idx == -1)) { /* PLCP seems to be corrupted.
* Drop the frame, if we are not interested in corrupted frames. */ if (!(dev->wl->filter_flags & FIF_PLCPFAIL)) goto drop;
}
status.rate_idx = rate_idx;
status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
/* * All frames on monitor interfaces and beacons always need a full * 64-bit timestamp. Monitor interfaces need it for diagnostic * purposes and beacons for IBSS merging. * This code assumes we get to process the packet within 16 bits * of timestamp, i.e. about 65 milliseconds after the PHY received * the first symbol.
*/ if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
u16 low_mactime_now;
chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; switch (chanstat & B43_RX_CHAN_PHYTYPE) { case B43_PHYTYPE_G:
status.band = NL80211_BAND_2GHZ; /* Somewhere between 478.104 and 508.1084 firmware for G-PHY * has been modified to be compatible with N-PHY and others.
*/ if (dev->fw.rev >= 508)
status.freq = ieee80211_channel_to_frequency(chanid, status.band); else
status.freq = chanid + 2400; break; case B43_PHYTYPE_N: case B43_PHYTYPE_LP: case B43_PHYTYPE_HT: /* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */ if (chanstat & B43_RX_CHAN_5GHZ)
status.band = NL80211_BAND_5GHZ; else
status.band = NL80211_BAND_2GHZ;
status.freq =
ieee80211_channel_to_frequency(chanid, status.band); break; default:
B43_WARN_ON(1); goto drop;
}
if (status->intermediate) return; if (status->for_ampdu) return; if (!status->acked)
dev->wl->ieee_stats.dot11ACKFailureCount++; if (status->rts_count) { if (status->rts_count == 0xF) //FIXME
dev->wl->ieee_stats.dot11RTSFailureCount++; else
dev->wl->ieee_stats.dot11RTSSuccessCount++;
}
if (b43_using_pio_transfers(dev))
b43_pio_handle_txstatus(dev, status); else
b43_dma_handle_txstatus(dev, status);
b43_phy_txpower_check(dev, 0);
}
/* Fill out the mac80211 TXstatus report based on the b43-specific * txstatus report data. This returns a boolean whether the frame was
* successfully transmitted. */ bool b43_fill_txstatus_report(struct b43_wldev *dev, struct ieee80211_tx_info *report, conststruct b43_txstatus *status)
{ bool frame_success = true; int retry_limit;
/* preserve the confiured retry limit before clearing the status * The xmit function has overwritten the rc's value with the actual
* retry limit done by the hardware */
retry_limit = report->status.rates[0].count;
ieee80211_tx_info_clear_status(report);
if (status->acked) { /* The frame was ACKed. */
report->flags |= IEEE80211_TX_STAT_ACK;
} else { /* The frame was not ACKed... */ if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { /* ...but we expected an ACK. */
frame_success = false;
}
} if (status->frame_count == 0) { /* The frame was not transmitted at all. */
report->status.rates[0].count = 0;
} elseif (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { /* * If the short retries (RTS, not data frame) have exceeded * the limit, the hw will not have tried the selected rate, * but will have used the fallback rate instead. * Don't let the rate control count attempts for the selected * rate in this case, otherwise the statistics will be off.
*/
report->status.rates[0].count = 0;
report->status.rates[1].count = status->frame_count;
} else { if (status->frame_count > retry_limit) {
report->status.rates[0].count = retry_limit;
report->status.rates[1].count = status->frame_count -
retry_limit;
/* Stop any TX operation on the device (suspend the hardware queues) */ void b43_tx_suspend(struct b43_wldev *dev)
{ if (b43_using_pio_transfers(dev))
b43_pio_tx_suspend(dev); else
b43_dma_tx_suspend(dev);
}
/* Resume any TX operation on the device (resume the hardware queues) */ void b43_tx_resume(struct b43_wldev *dev)
{ if (b43_using_pio_transfers(dev))
b43_pio_tx_resume(dev); else
b43_dma_tx_resume(dev);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.