xref: /freebsd/sys/contrib/dev/broadcom/brcm80211/brcmsmac/rate.h (revision b4c3e9b5b09c829b4135aff738bd2893ed052377)
1*b4c3e9b5SBjoern A. Zeeb /*
2*b4c3e9b5SBjoern A. Zeeb  * Copyright (c) 2010 Broadcom Corporation
3*b4c3e9b5SBjoern A. Zeeb  *
4*b4c3e9b5SBjoern A. Zeeb  * Permission to use, copy, modify, and/or distribute this software for any
5*b4c3e9b5SBjoern A. Zeeb  * purpose with or without fee is hereby granted, provided that the above
6*b4c3e9b5SBjoern A. Zeeb  * copyright notice and this permission notice appear in all copies.
7*b4c3e9b5SBjoern A. Zeeb  *
8*b4c3e9b5SBjoern A. Zeeb  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*b4c3e9b5SBjoern A. Zeeb  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*b4c3e9b5SBjoern A. Zeeb  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11*b4c3e9b5SBjoern A. Zeeb  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*b4c3e9b5SBjoern A. Zeeb  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13*b4c3e9b5SBjoern A. Zeeb  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14*b4c3e9b5SBjoern A. Zeeb  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15*b4c3e9b5SBjoern A. Zeeb  */
16*b4c3e9b5SBjoern A. Zeeb 
17*b4c3e9b5SBjoern A. Zeeb #ifndef _BRCM_RATE_H_
18*b4c3e9b5SBjoern A. Zeeb #define _BRCM_RATE_H_
19*b4c3e9b5SBjoern A. Zeeb 
20*b4c3e9b5SBjoern A. Zeeb #include "types.h"
21*b4c3e9b5SBjoern A. Zeeb #include "d11.h"
22*b4c3e9b5SBjoern A. Zeeb #include "phy_hal.h"
23*b4c3e9b5SBjoern A. Zeeb 
24*b4c3e9b5SBjoern A. Zeeb extern const u8 rate_info[];
25*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_c_rateset cck_ofdm_mimo_rates;
26*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_c_rateset ofdm_mimo_rates;
27*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_c_rateset cck_ofdm_rates;
28*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_c_rateset ofdm_rates;
29*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_c_rateset cck_rates;
30*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_c_rateset gphy_legacy_rates;
31*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_c_rateset rate_limit_1_2;
32*b4c3e9b5SBjoern A. Zeeb 
33*b4c3e9b5SBjoern A. Zeeb struct brcms_mcs_info {
34*b4c3e9b5SBjoern A. Zeeb 	/* phy rate in kbps [20Mhz] */
35*b4c3e9b5SBjoern A. Zeeb 	u32 phy_rate_20;
36*b4c3e9b5SBjoern A. Zeeb 	/* phy rate in kbps [40Mhz] */
37*b4c3e9b5SBjoern A. Zeeb 	u32 phy_rate_40;
38*b4c3e9b5SBjoern A. Zeeb 	/* phy rate in kbps [20Mhz] with SGI */
39*b4c3e9b5SBjoern A. Zeeb 	u32 phy_rate_20_sgi;
40*b4c3e9b5SBjoern A. Zeeb 	/* phy rate in kbps [40Mhz] with SGI */
41*b4c3e9b5SBjoern A. Zeeb 	u32 phy_rate_40_sgi;
42*b4c3e9b5SBjoern A. Zeeb 	/* phy ctl byte 3, code rate, modulation type, # of streams */
43*b4c3e9b5SBjoern A. Zeeb 	u8 tx_phy_ctl3;
44*b4c3e9b5SBjoern A. Zeeb 	/* matching legacy ofdm rate in 500bkps */
45*b4c3e9b5SBjoern A. Zeeb 	u8 leg_ofdm;
46*b4c3e9b5SBjoern A. Zeeb };
47*b4c3e9b5SBjoern A. Zeeb 
48*b4c3e9b5SBjoern A. Zeeb #define BRCMS_MAXMCS	32	/* max valid mcs index */
49*b4c3e9b5SBjoern A. Zeeb #define MCS_TABLE_SIZE	33	/* Number of mcs entries in the table */
50*b4c3e9b5SBjoern A. Zeeb extern const struct brcms_mcs_info mcs_table[];
51*b4c3e9b5SBjoern A. Zeeb 
52*b4c3e9b5SBjoern A. Zeeb #define MCS_TXS_MASK	0xc0	/* num tx streams - 1 bit mask */
53*b4c3e9b5SBjoern A. Zeeb #define MCS_TXS_SHIFT	6	/* num tx streams - 1 bit shift */
54*b4c3e9b5SBjoern A. Zeeb 
55*b4c3e9b5SBjoern A. Zeeb /* returns num tx streams - 1 */
mcs_2_txstreams(u8 mcs)56*b4c3e9b5SBjoern A. Zeeb static inline u8 mcs_2_txstreams(u8 mcs)
57*b4c3e9b5SBjoern A. Zeeb {
58*b4c3e9b5SBjoern A. Zeeb 	return (mcs_table[mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT;
59*b4c3e9b5SBjoern A. Zeeb }
60*b4c3e9b5SBjoern A. Zeeb 
mcs_2_rate(u8 mcs,bool is40,bool sgi)61*b4c3e9b5SBjoern A. Zeeb static inline uint mcs_2_rate(u8 mcs, bool is40, bool sgi)
62*b4c3e9b5SBjoern A. Zeeb {
63*b4c3e9b5SBjoern A. Zeeb 	if (sgi) {
64*b4c3e9b5SBjoern A. Zeeb 		if (is40)
65*b4c3e9b5SBjoern A. Zeeb 			return mcs_table[mcs].phy_rate_40_sgi;
66*b4c3e9b5SBjoern A. Zeeb 		return mcs_table[mcs].phy_rate_20_sgi;
67*b4c3e9b5SBjoern A. Zeeb 	}
68*b4c3e9b5SBjoern A. Zeeb 	if (is40)
69*b4c3e9b5SBjoern A. Zeeb 		return mcs_table[mcs].phy_rate_40;
70*b4c3e9b5SBjoern A. Zeeb 
71*b4c3e9b5SBjoern A. Zeeb 	return mcs_table[mcs].phy_rate_20;
72*b4c3e9b5SBjoern A. Zeeb }
73*b4c3e9b5SBjoern A. Zeeb 
74*b4c3e9b5SBjoern A. Zeeb /* Macro to use the rate_info table */
75*b4c3e9b5SBjoern A. Zeeb #define	BRCMS_RATE_MASK_FULL 0xff /* Rate value mask with basic rate flag */
76*b4c3e9b5SBjoern A. Zeeb 
77*b4c3e9b5SBjoern A. Zeeb /*
78*b4c3e9b5SBjoern A. Zeeb  * rate spec : holds rate and mode specific information required to generate a
79*b4c3e9b5SBjoern A. Zeeb  * tx frame. Legacy CCK and OFDM information is held in the same manner as was
80*b4c3e9b5SBjoern A. Zeeb  * done in the past (in the lower byte) the upper 3 bytes primarily hold MIMO
81*b4c3e9b5SBjoern A. Zeeb  * specific information
82*b4c3e9b5SBjoern A. Zeeb  */
83*b4c3e9b5SBjoern A. Zeeb 
84*b4c3e9b5SBjoern A. Zeeb /* rate spec bit fields */
85*b4c3e9b5SBjoern A. Zeeb 
86*b4c3e9b5SBjoern A. Zeeb /* Either 500Kbps units or MIMO MCS idx */
87*b4c3e9b5SBjoern A. Zeeb #define RSPEC_RATE_MASK		0x0000007F
88*b4c3e9b5SBjoern A. Zeeb /* mimo MCS is stored in RSPEC_RATE_MASK */
89*b4c3e9b5SBjoern A. Zeeb #define RSPEC_MIMORATE		0x08000000
90*b4c3e9b5SBjoern A. Zeeb /* mimo bw mask */
91*b4c3e9b5SBjoern A. Zeeb #define RSPEC_BW_MASK		0x00000700
92*b4c3e9b5SBjoern A. Zeeb /* mimo bw shift */
93*b4c3e9b5SBjoern A. Zeeb #define RSPEC_BW_SHIFT		8
94*b4c3e9b5SBjoern A. Zeeb /* mimo Space/Time/Frequency mode mask */
95*b4c3e9b5SBjoern A. Zeeb #define RSPEC_STF_MASK		0x00003800
96*b4c3e9b5SBjoern A. Zeeb /* mimo Space/Time/Frequency mode shift */
97*b4c3e9b5SBjoern A. Zeeb #define RSPEC_STF_SHIFT		11
98*b4c3e9b5SBjoern A. Zeeb /* mimo coding type mask */
99*b4c3e9b5SBjoern A. Zeeb #define RSPEC_CT_MASK		0x0000C000
100*b4c3e9b5SBjoern A. Zeeb /* mimo coding type shift */
101*b4c3e9b5SBjoern A. Zeeb #define RSPEC_CT_SHIFT		14
102*b4c3e9b5SBjoern A. Zeeb /* mimo num STC streams per PLCP defn. */
103*b4c3e9b5SBjoern A. Zeeb #define RSPEC_STC_MASK		0x00300000
104*b4c3e9b5SBjoern A. Zeeb /* mimo num STC streams per PLCP defn. */
105*b4c3e9b5SBjoern A. Zeeb #define RSPEC_STC_SHIFT		20
106*b4c3e9b5SBjoern A. Zeeb /* mimo bit indicates adv coding in use */
107*b4c3e9b5SBjoern A. Zeeb #define RSPEC_LDPC_CODING	0x00400000
108*b4c3e9b5SBjoern A. Zeeb /* mimo bit indicates short GI in use */
109*b4c3e9b5SBjoern A. Zeeb #define RSPEC_SHORT_GI		0x00800000
110*b4c3e9b5SBjoern A. Zeeb /* bit indicates override both rate & mode */
111*b4c3e9b5SBjoern A. Zeeb #define RSPEC_OVERRIDE		0x80000000
112*b4c3e9b5SBjoern A. Zeeb /* bit indicates override rate only */
113*b4c3e9b5SBjoern A. Zeeb #define RSPEC_OVERRIDE_MCS_ONLY 0x40000000
114*b4c3e9b5SBjoern A. Zeeb 
rspec_active(u32 rspec)115*b4c3e9b5SBjoern A. Zeeb static inline bool rspec_active(u32 rspec)
116*b4c3e9b5SBjoern A. Zeeb {
117*b4c3e9b5SBjoern A. Zeeb 	return rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE);
118*b4c3e9b5SBjoern A. Zeeb }
119*b4c3e9b5SBjoern A. Zeeb 
rspec_phytxbyte2(u32 rspec)120*b4c3e9b5SBjoern A. Zeeb static inline u8 rspec_phytxbyte2(u32 rspec)
121*b4c3e9b5SBjoern A. Zeeb {
122*b4c3e9b5SBjoern A. Zeeb 	return (rspec & 0xff00) >> 8;
123*b4c3e9b5SBjoern A. Zeeb }
124*b4c3e9b5SBjoern A. Zeeb 
rspec_get_bw(u32 rspec)125*b4c3e9b5SBjoern A. Zeeb static inline u32 rspec_get_bw(u32 rspec)
126*b4c3e9b5SBjoern A. Zeeb {
127*b4c3e9b5SBjoern A. Zeeb 	return (rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT;
128*b4c3e9b5SBjoern A. Zeeb }
129*b4c3e9b5SBjoern A. Zeeb 
rspec_issgi(u32 rspec)130*b4c3e9b5SBjoern A. Zeeb static inline bool rspec_issgi(u32 rspec)
131*b4c3e9b5SBjoern A. Zeeb {
132*b4c3e9b5SBjoern A. Zeeb 	return (rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI;
133*b4c3e9b5SBjoern A. Zeeb }
134*b4c3e9b5SBjoern A. Zeeb 
rspec_is40mhz(u32 rspec)135*b4c3e9b5SBjoern A. Zeeb static inline bool rspec_is40mhz(u32 rspec)
136*b4c3e9b5SBjoern A. Zeeb {
137*b4c3e9b5SBjoern A. Zeeb 	u32 bw = rspec_get_bw(rspec);
138*b4c3e9b5SBjoern A. Zeeb 
139*b4c3e9b5SBjoern A. Zeeb 	return bw == PHY_TXC1_BW_40MHZ || bw == PHY_TXC1_BW_40MHZ_DUP;
140*b4c3e9b5SBjoern A. Zeeb }
141*b4c3e9b5SBjoern A. Zeeb 
rspec2rate(u32 rspec)142*b4c3e9b5SBjoern A. Zeeb static inline uint rspec2rate(u32 rspec)
143*b4c3e9b5SBjoern A. Zeeb {
144*b4c3e9b5SBjoern A. Zeeb 	if (rspec & RSPEC_MIMORATE)
145*b4c3e9b5SBjoern A. Zeeb 		return mcs_2_rate(rspec & RSPEC_RATE_MASK, rspec_is40mhz(rspec),
146*b4c3e9b5SBjoern A. Zeeb 				  rspec_issgi(rspec));
147*b4c3e9b5SBjoern A. Zeeb 	return rspec & RSPEC_RATE_MASK;
148*b4c3e9b5SBjoern A. Zeeb }
149*b4c3e9b5SBjoern A. Zeeb 
rspec_mimoplcp3(u32 rspec)150*b4c3e9b5SBjoern A. Zeeb static inline u8 rspec_mimoplcp3(u32 rspec)
151*b4c3e9b5SBjoern A. Zeeb {
152*b4c3e9b5SBjoern A. Zeeb 	return (rspec & 0xf00000) >> 16;
153*b4c3e9b5SBjoern A. Zeeb }
154*b4c3e9b5SBjoern A. Zeeb 
plcp3_issgi(u8 plcp)155*b4c3e9b5SBjoern A. Zeeb static inline bool plcp3_issgi(u8 plcp)
156*b4c3e9b5SBjoern A. Zeeb {
157*b4c3e9b5SBjoern A. Zeeb 	return (plcp & (RSPEC_SHORT_GI >> 16)) != 0;
158*b4c3e9b5SBjoern A. Zeeb }
159*b4c3e9b5SBjoern A. Zeeb 
rspec_stc(u32 rspec)160*b4c3e9b5SBjoern A. Zeeb static inline uint rspec_stc(u32 rspec)
161*b4c3e9b5SBjoern A. Zeeb {
162*b4c3e9b5SBjoern A. Zeeb 	return (rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT;
163*b4c3e9b5SBjoern A. Zeeb }
164*b4c3e9b5SBjoern A. Zeeb 
rspec_stf(u32 rspec)165*b4c3e9b5SBjoern A. Zeeb static inline uint rspec_stf(u32 rspec)
166*b4c3e9b5SBjoern A. Zeeb {
167*b4c3e9b5SBjoern A. Zeeb 	return (rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT;
168*b4c3e9b5SBjoern A. Zeeb }
169*b4c3e9b5SBjoern A. Zeeb 
is_mcs_rate(u32 ratespec)170*b4c3e9b5SBjoern A. Zeeb static inline bool is_mcs_rate(u32 ratespec)
171*b4c3e9b5SBjoern A. Zeeb {
172*b4c3e9b5SBjoern A. Zeeb 	return (ratespec & RSPEC_MIMORATE) != 0;
173*b4c3e9b5SBjoern A. Zeeb }
174*b4c3e9b5SBjoern A. Zeeb 
is_ofdm_rate(u32 ratespec)175*b4c3e9b5SBjoern A. Zeeb static inline bool is_ofdm_rate(u32 ratespec)
176*b4c3e9b5SBjoern A. Zeeb {
177*b4c3e9b5SBjoern A. Zeeb 	return !is_mcs_rate(ratespec) &&
178*b4c3e9b5SBjoern A. Zeeb 	       (rate_info[ratespec & RSPEC_RATE_MASK] & BRCMS_RATE_FLAG);
179*b4c3e9b5SBjoern A. Zeeb }
180*b4c3e9b5SBjoern A. Zeeb 
is_cck_rate(u32 ratespec)181*b4c3e9b5SBjoern A. Zeeb static inline bool is_cck_rate(u32 ratespec)
182*b4c3e9b5SBjoern A. Zeeb {
183*b4c3e9b5SBjoern A. Zeeb 	u32 rate = (ratespec & BRCMS_RATE_MASK);
184*b4c3e9b5SBjoern A. Zeeb 
185*b4c3e9b5SBjoern A. Zeeb 	return !is_mcs_rate(ratespec) && (
186*b4c3e9b5SBjoern A. Zeeb 			rate == BRCM_RATE_1M || rate == BRCM_RATE_2M ||
187*b4c3e9b5SBjoern A. Zeeb 			rate == BRCM_RATE_5M5 || rate == BRCM_RATE_11M);
188*b4c3e9b5SBjoern A. Zeeb }
189*b4c3e9b5SBjoern A. Zeeb 
is_single_stream(u8 mcs)190*b4c3e9b5SBjoern A. Zeeb static inline bool is_single_stream(u8 mcs)
191*b4c3e9b5SBjoern A. Zeeb {
192*b4c3e9b5SBjoern A. Zeeb 	return mcs <= HIGHEST_SINGLE_STREAM_MCS || mcs == 32;
193*b4c3e9b5SBjoern A. Zeeb }
194*b4c3e9b5SBjoern A. Zeeb 
cck_rspec(u8 cck)195*b4c3e9b5SBjoern A. Zeeb static inline u8 cck_rspec(u8 cck)
196*b4c3e9b5SBjoern A. Zeeb {
197*b4c3e9b5SBjoern A. Zeeb 	return cck & RSPEC_RATE_MASK;
198*b4c3e9b5SBjoern A. Zeeb }
199*b4c3e9b5SBjoern A. Zeeb 
200*b4c3e9b5SBjoern A. Zeeb /* Convert encoded rate value in plcp header to numerical rates in 500 KHz
201*b4c3e9b5SBjoern A. Zeeb  * increments */
ofdm_phy2mac_rate(u8 rlpt)202*b4c3e9b5SBjoern A. Zeeb static inline u8 ofdm_phy2mac_rate(u8 rlpt)
203*b4c3e9b5SBjoern A. Zeeb {
204*b4c3e9b5SBjoern A. Zeeb 	return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7];
205*b4c3e9b5SBjoern A. Zeeb }
206*b4c3e9b5SBjoern A. Zeeb 
cck_phy2mac_rate(u8 signal)207*b4c3e9b5SBjoern A. Zeeb static inline u8 cck_phy2mac_rate(u8 signal)
208*b4c3e9b5SBjoern A. Zeeb {
209*b4c3e9b5SBjoern A. Zeeb 	return signal/5;
210*b4c3e9b5SBjoern A. Zeeb }
211*b4c3e9b5SBjoern A. Zeeb 
212*b4c3e9b5SBjoern A. Zeeb /* Rates specified in brcms_c_rateset_filter() */
213*b4c3e9b5SBjoern A. Zeeb #define BRCMS_RATES_CCK_OFDM	0
214*b4c3e9b5SBjoern A. Zeeb #define BRCMS_RATES_CCK		1
215*b4c3e9b5SBjoern A. Zeeb #define BRCMS_RATES_OFDM		2
216*b4c3e9b5SBjoern A. Zeeb 
217*b4c3e9b5SBjoern A. Zeeb /* sanitize, and sort a rateset with the basic bit(s) preserved, validate
218*b4c3e9b5SBjoern A. Zeeb  * rateset */
219*b4c3e9b5SBjoern A. Zeeb bool brcms_c_rate_hwrs_filter_sort_validate(struct brcms_c_rateset *rs,
220*b4c3e9b5SBjoern A. Zeeb 					    const struct brcms_c_rateset *hw_rs,
221*b4c3e9b5SBjoern A. Zeeb 					    bool check_brate, u8 txstreams);
222*b4c3e9b5SBjoern A. Zeeb /* copy rateset src to dst as-is (no masking or sorting) */
223*b4c3e9b5SBjoern A. Zeeb void brcms_c_rateset_copy(const struct brcms_c_rateset *src,
224*b4c3e9b5SBjoern A. Zeeb 			  struct brcms_c_rateset *dst);
225*b4c3e9b5SBjoern A. Zeeb 
226*b4c3e9b5SBjoern A. Zeeb /* would be nice to have these documented ... */
227*b4c3e9b5SBjoern A. Zeeb u32 brcms_c_compute_rspec(struct d11rxhdr *rxh, u8 *plcp);
228*b4c3e9b5SBjoern A. Zeeb 
229*b4c3e9b5SBjoern A. Zeeb void brcms_c_rateset_filter(struct brcms_c_rateset *src,
230*b4c3e9b5SBjoern A. Zeeb 			    struct brcms_c_rateset *dst, bool basic_only,
231*b4c3e9b5SBjoern A. Zeeb 			    u8 rates, uint xmask, bool mcsallow);
232*b4c3e9b5SBjoern A. Zeeb 
233*b4c3e9b5SBjoern A. Zeeb void brcms_c_rateset_default(struct brcms_c_rateset *rs_tgt,
234*b4c3e9b5SBjoern A. Zeeb 			     const struct brcms_c_rateset *rs_hw, uint phy_type,
235*b4c3e9b5SBjoern A. Zeeb 			     int bandtype, bool cck_only, uint rate_mask,
236*b4c3e9b5SBjoern A. Zeeb 			     bool mcsallow, u8 bw, u8 txstreams);
237*b4c3e9b5SBjoern A. Zeeb 
238*b4c3e9b5SBjoern A. Zeeb s16 brcms_c_rate_legacy_phyctl(uint rate);
239*b4c3e9b5SBjoern A. Zeeb 
240*b4c3e9b5SBjoern A. Zeeb void brcms_c_rateset_mcs_upd(struct brcms_c_rateset *rs, u8 txstreams);
241*b4c3e9b5SBjoern A. Zeeb void brcms_c_rateset_mcs_clear(struct brcms_c_rateset *rateset);
242*b4c3e9b5SBjoern A. Zeeb void brcms_c_rateset_mcs_build(struct brcms_c_rateset *rateset, u8 txstreams);
243*b4c3e9b5SBjoern A. Zeeb void brcms_c_rateset_bw_mcs_filter(struct brcms_c_rateset *rateset, u8 bw);
244*b4c3e9b5SBjoern A. Zeeb 
245*b4c3e9b5SBjoern A. Zeeb #endif				/* _BRCM_RATE_H_ */
246