📄 wlc_rate.c
字号:
/* * Common [OS-independent] rate management * 802.11 Networking Adapter Device Driver. * * Copyright 2005-2006, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id$ */#include <wlc_cfg.h>#include <typedefs.h>#include <osl.h>#include <bcmutils.h>#include <sbutils.h>#include <bcmendian.h>#include <wlioctl.h>#include <proto/802.11.h>#include <sbhndpio.h>#include <sbhnddma.h>#include <hnddma.h>#include <d11.h>#include <wlc_rate.h>#include <wl_dbg.h>#include <wlc_pub.h>/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */const uint8 rate_info[WLC_MAXRATE + 1] = { /* 0 1 2 3 4 5 6 7 8 9 *//* 0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,/* 10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,/* 20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,/* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,/* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c};/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams * Number of spatial streams: always 1 * other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard */typedef struct ofdm_phycfg { uint32 rate_ofdm; /* ofdm mac rate */ uint8 tx_phy_ctl3; /* phy ctl byte 3, code rate, modulation type, # of streams */} ofdm_phycfg_t;#define OFDM_PHYCFG_TABLE_SIZE 8 /* Number of ofdm_rate_cfg entries in the table */static const ofdm_phycfg_t ofdm_phycfg_table[OFDM_PHYCFG_TABLE_SIZE] = { {WLC_RATE_6M, 0x00}, /* OFDM 6Mbps, code rate 1/2, BPSK, 1 spatial stream */ {WLC_RATE_9M, 0x02}, /* OFDM 9Mbps, code rate 3/4, BPSK, 1 spatial stream */ {WLC_RATE_12M, 0x08}, /* OFDM 12Mbps, code rate 1/2, QPSK, 1 spatial stream */ {WLC_RATE_18M, 0x0A}, /* OFDM 18Mbps, code rate 3/4, QPSK, 1 spatial stream */ {WLC_RATE_24M, 0x10}, /* OFDM 24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */ {WLC_RATE_36M, 0x12}, /* OFDM 36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */ {WLC_RATE_48M, 0x19}, /* OFDM 48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */ {WLC_RATE_54M, 0x1A}, /* OFDM 54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */};static const rateset_t cck_ofdm_rates_s = { 12, { /* 1b, 2b, 5.5b, 6, 9, 11b, 12, 18, 24, 36, 48, 54 Mbps */ 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};const rateset_t * cck_ofdm_rates = &cck_ofdm_rates_s;static const rateset_t gphy_legacy_rates_s = { 4, { /* 1b, 2b, 5.5b, 11b Mbps */ 0x82, 0x84, 0x8b, 0x96 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};const rateset_t * gphy_legacy_rates = &gphy_legacy_rates_s;static const rateset_t ofdm_rates_s = { 8, { /* 6b, 9, 12b, 18, 24b, 36, 48, 54 Mbps */ 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};const rateset_t * ofdm_rates = &ofdm_rates_s;static const rateset_t cck_rates_s = { 4, { /* 1b, 2b, 5.5, 11 Mbps */ 0x82, 0x84, 0x0b, 0x16 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};const rateset_t * cck_rates = &cck_rates_s;/* set of rates in supported rates elt when splitting rates between it and the Extended Rates elt */static const rateset_t wlc_lrs_rates_s = { 8, { /* 1, 2, 5.5, 11, 18, 24, 36, 54 Mbps */ 0x02, 0x04, 0x0b, 0x16, 0x24, 0x30, 0x48, 0x6c }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};const rateset_t * wlc_lrs_rates = &wlc_lrs_rates_s;/* Rateset including only 1 and 2 Mbps, without basic rate annotation. * This is used for a wlc_sort_rates param when limiting a rateset for */static const rateset_t rate_limit_1_2_s = { 2, { /* 1, 2 Mbps */ 0x02, 0x04 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};const rateset_t * rate_limit_1_2 = &rate_limit_1_2_s;/* sanitize and sort a rateset, preserving the basic bit(s) */voidwlc_sort_rates(rateset_t *rs, const rateset_t *hw_rs){ uint8 rateset[WLC_MAXRATE+1]; uint8 r; uint count; uint i; bzero(rateset, sizeof(rateset)); count = rs->count; for (i = 0; i < count; i++) { /* mask off "basic rate" bit, WLC_RATE_FLAG */ r = (int)rs->rates[i] & RATE_MASK; if ((r > WLC_MAXRATE) || (rate_info[r] == 0)) { WL_INFORM(("wlc_sort_rates: bad rate in rate set 0x%x\n", r)); continue; } rateset[r] = rs->rates[i]; /* preserve basic bit! */ } /* fill out the rates in order, looking at only supported rates */ count = 0; for (i = 0; i < hw_rs->count; i++) { r = hw_rs->rates[i] & RATE_MASK; ASSERT(r <= WLC_MAXRATE); if (rateset[r]) rs->rates[count++] = rateset[r]; } rs->count = count;}bool wlc_valid_rateset(struct rateset *rs, struct rateset *hwrs){ uint origcount; uint i; origcount = rs->count; wlc_sort_rates(rs, hwrs); /* if bad or duplicate rates */ if (rs->count != origcount) return (FALSE); /* error if no basic rates */ for (i = 0; i < rs->count; i++) { if (rs->rates[i] & WLC_RATE_FLAG) break; } if (i == rs->count) return (FALSE); return (TRUE);}intwlc_compute_rate(d11rxhdr_t *rxh, void *plcp){ int phy_type; int rate = 0; phy_type = ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT); if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM)) rate = OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *)plcp)->rlpt[0]); else rate = CCK_PHY2MAC_RATE(((cck_phy_hdr_t *)plcp)->signal); return rate;}/* copy rateset src to dst as-is (no masking or sorting) */void wlc_rateset_copy(const struct rateset *src, struct rateset *dst){ bcopy(src, dst, sizeof(struct rateset));}/* * Copy and selectively filter one rateset to another. * 'basic_only' means only copy basic rates. * 'cck_only' means only copy cck (11b) rates. * 'xmask' is the copy mask (typically 0x7f or 0xff). */voidwlc_rateset_filter(struct rateset *src, struct rateset *dst, bool basic_only, bool cck_only, uint xmask){ uint i; uint r; uint count; count = 0; for (i = 0; i < src->count; i++) { r = src->rates[i]; if (basic_only && !(r & WLC_RATE_FLAG)) continue; if (cck_only && IS_OFDM((r & RATE_MASK))) continue; dst->rates[count++] = r & xmask; } dst->count = count;}int16wlc_rate_ofdm_phyctl(uint rate){ uint i; for (i = 0; i < OFDM_PHYCFG_TABLE_SIZE; i++) if (rate == ofdm_phycfg_table[i].rate_ofdm) return ofdm_phycfg_table[i].tx_phy_ctl3; return -1;}char*wlc_dumprateset(char *name, struct rateset *rateset, char *buf){ uint r, i; bool b; buf += sprintf(buf, "%s [ ", name ? name : ""); for (i = 0; i < rateset->count; i++) { r = rateset->rates[i] & RATE_MASK; b = rateset->rates[i] & WLC_RATE_FLAG; buf += sprintf(buf, "%d%s%s ", (r / 2), (r % 2) ? ".5" : "", b ? "(b)" : ""); } buf += sprintf(buf, "]"); return (buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -