1 /* 2 * Misc utility routines for WL and Apps 3 * This header file housing the define and function prototype use by 4 * both the wl driver, tools & Apps. 5 * 6 * Portions of this code are copyright (c) 2021 Cypress Semiconductor Corporation 7 * 8 * Copyright (C) 1999-2017, Broadcom Corporation 9 * 10 * Unless you and Broadcom execute a separate written software license 11 * agreement governing use of this software, this software is licensed to you 12 * under the terms of the GNU General Public License version 2 (the "GPL"), 13 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 14 * following added to such license: 15 * 16 * As a special exception, the copyright holders of this software give you 17 * permission to link this software with independent modules, and to copy and 18 * distribute the resulting executable under terms of your choice, provided that 19 * you also meet, for each linked independent module, the terms and conditions of 20 * the license of that module. An independent module is a module which is not 21 * derived from this software. The special exception does not apply to any 22 * modifications of the software. 23 * 24 * Notwithstanding the above, under no circumstances may you combine this 25 * software in any way with any other Broadcom software provided under a license 26 * other than the GPL, without Broadcom's express prior written consent. 27 * 28 * 29 * <<Broadcom-WL-IPTag/Open:>> 30 * 31 * $Id: bcmwifi_channels.h 695288 2017-04-19 17:20:39Z $ 32 */ 33 34 #ifndef _bcmwifi_channels_h_ 35 #define _bcmwifi_channels_h_ 36 37 /* A chanspec holds the channel number, band, bandwidth and primary 20MHz sideband */ 38 typedef uint16 chanspec_t; 39 typedef uint16 chanspec_band_t; 40 typedef uint16 chanspec_bw_t; 41 typedef uint16 chanspec_subband_t; 42 43 /* channel defines */ 44 #define CH_80MHZ_APART 16 45 #define CH_40MHZ_APART 8 46 #define CH_20MHZ_APART 4 47 #define CH_10MHZ_APART 2 48 #define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */ 49 50 #define CH_MIN_2G_CHANNEL 1u /* Min channel in 2G band */ 51 #define CH_MAX_2G_CHANNEL 14u /* Max channel in 2G band */ 52 #define CH_MIN_2G_40M_CHANNEL 3u /* Min 40MHz center channel in 2G band */ 53 #define CH_MAX_2G_40M_CHANNEL 11u /* Max 40MHz center channel in 2G band */ 54 55 /* maximum # channels the s/w supports */ 56 #define MAXCHANNEL 224 /* max # supported channels. The max channel no is above, 57 * this is that + 1 rounded up to a multiple of NBBY (8). 58 * DO NOT MAKE it > 255: channels are uint8's all over 59 */ 60 #define MAXCHANNEL_NUM (MAXCHANNEL - 1) /* max channel number */ 61 62 #define INVCHANNEL 255 /* error value for a bad channel */ 63 64 /* channel bitvec */ 65 typedef struct { 66 uint8 vec[MAXCHANNEL/8]; /* bitvec of channels */ 67 } chanvec_t; 68 69 /* make sure channel num is within valid range */ 70 #define CH_NUM_VALID_RANGE(ch_num) ((ch_num) > 0 && (ch_num) <= MAXCHANNEL_NUM) 71 72 #define CHSPEC_CTLOVLP(sp1, sp2, sep) \ 73 (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep)) 74 75 /* All builds use the new 11ac ratespec/chanspec */ 76 #undef D11AC_IOTYPES 77 #define D11AC_IOTYPES 78 79 #define WL_CHANSPEC_CHAN_MASK 0x00ff 80 #define WL_CHANSPEC_CHAN_SHIFT 0 81 #define WL_CHANSPEC_CHAN1_MASK 0x000f 82 #define WL_CHANSPEC_CHAN1_SHIFT 0 83 #define WL_CHANSPEC_CHAN2_MASK 0x00f0 84 #define WL_CHANSPEC_CHAN2_SHIFT 4 85 86 #define WL_CHANSPEC_CTL_SB_MASK 0x0700 87 #define WL_CHANSPEC_CTL_SB_SHIFT 8 88 #define WL_CHANSPEC_CTL_SB_LLL 0x0000 89 #define WL_CHANSPEC_CTL_SB_LLU 0x0100 90 #define WL_CHANSPEC_CTL_SB_LUL 0x0200 91 #define WL_CHANSPEC_CTL_SB_LUU 0x0300 92 #define WL_CHANSPEC_CTL_SB_ULL 0x0400 93 #define WL_CHANSPEC_CTL_SB_ULU 0x0500 94 #define WL_CHANSPEC_CTL_SB_UUL 0x0600 95 #define WL_CHANSPEC_CTL_SB_UUU 0x0700 96 #define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL 97 #define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU 98 #define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL 99 #define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU 100 #define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL 101 #define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU 102 #define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL 103 #define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU 104 #define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL 105 106 #define WL_CHANSPEC_BW_MASK 0x3800u 107 #define WL_CHANSPEC_BW_SHIFT 11u 108 #define WL_CHANSPEC_BW_5 0x0000u 109 #define WL_CHANSPEC_BW_10 0x0800u 110 #define WL_CHANSPEC_BW_20 0x1000u 111 #define WL_CHANSPEC_BW_40 0x1800u 112 #define WL_CHANSPEC_BW_80 0x2000u 113 #define WL_CHANSPEC_BW_160 0x2800u 114 #define WL_CHANSPEC_BW_8080 0x3000u 115 116 #define WL_CHANSPEC_BAND_MASK 0xc000u 117 #define WL_CHANSPEC_BAND_SHIFT 14u 118 #define WL_CHANSPEC_BAND_2G 0x0000u 119 #define WL_CHANSPEC_BAND_3G 0x4000u 120 #define WL_CHANSPEC_BAND_4G 0x8000u 121 #define WL_CHANSPEC_BAND_5G 0xc000u 122 #define INVCHANSPEC 255u 123 #define MAX_CHANSPEC 0xFFFFu 124 125 #define WL_CHANNEL_BAND(ch) (((ch) <= CH_MAX_2G_CHANNEL) ? \ 126 WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) 127 128 /* channel defines */ 129 #define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ 130 ((channel) - CH_10MHZ_APART) : 0) 131 #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ 132 ((channel) + CH_10MHZ_APART) : 0) 133 134 /* pass a 80MHz channel number (uint8) to get respective LL, UU, LU, UL */ 135 #define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) 136 #define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ 137 ((channel) + 3 * CH_10MHZ_APART) : 0) 138 #define LU_20_SB(channel) LOWER_20_SB(channel) 139 #define UL_20_SB(channel) UPPER_20_SB(channel) 140 141 #define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART) 142 #define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART) 143 #define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) 144 #define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ 145 (((channel) <= CH_MAX_2G_CHANNEL) ? \ 146 WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) 147 #define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ 148 ((channel) + CH_20MHZ_APART) : 0) 149 #define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 150 ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ 151 ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ 152 WL_CHANSPEC_BAND_5G)) 153 #define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 154 ((channel) | (ctlsb) | \ 155 WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G) 156 #define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 157 ((channel) | (ctlsb) | \ 158 WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G) 159 160 /* simple MACROs to get different fields of chanspec */ 161 #ifdef WL11AC_80P80 162 #define CHSPEC_CHANNEL(chspec) wf_chspec_channel(chspec) 163 #else 164 #define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) 165 #endif // endif 166 #define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT 167 #define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT 168 #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) 169 #define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) 170 #define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) 171 172 #ifdef WL11N_20MHZONLY 173 #define CHSPEC_IS20(chspec) 1 174 #define CHSPEC_IS20_2G(chspec) ((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \ 175 CHSPEC_IS2G(chspec)) 176 #ifndef CHSPEC_IS40 177 #define CHSPEC_IS40(chspec) 0 178 #endif // endif 179 #ifndef CHSPEC_IS80 180 #define CHSPEC_IS80(chspec) 0 181 #endif // endif 182 #ifndef CHSPEC_IS160 183 #define CHSPEC_IS160(chspec) 0 184 #endif // endif 185 #ifndef CHSPEC_IS8080 186 #define CHSPEC_IS8080(chspec) 0 187 #endif // endif 188 189 /* see FOREACH_20_SB in !WL11N_20MHZONLY section */ 190 #define FOREACH_20_SB(chspec, channel) \ 191 for (channel = CHSPEC_CHANNEL(chspec); channel; channel = 0) 192 193 /* see GET_ALL_SB in !WL11N_20MHZONLY section */ 194 #define GET_ALL_SB(chspec, psb) do { \ 195 psb[0] = CHSPEC_CHANNEL(chspec); \ 196 } while (0) 197 198 #else /* !WL11N_20MHZONLY */ 199 200 #define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) 201 #define CHSPEC_IS20_5G(chspec) ((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \ 202 CHSPEC_IS5G(chspec)) 203 #ifndef CHSPEC_IS40 204 #define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) 205 #endif // endif 206 #ifndef CHSPEC_IS80 207 #define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) 208 #endif // endif 209 #ifndef CHSPEC_IS160 210 #define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) 211 #endif // endif 212 #ifndef CHSPEC_IS8080 213 #define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) 214 #endif // endif 215 216 /* pass a center channel and get channel offset from it by 10MHz */ 217 #define CH_OFF_10MHZ_MULTIPLES(channel, offset) ((uint8) (((offset) < 0) ? \ 218 (((channel) > (WL_CHANSPEC_CHAN_MASK & ((uint16)((-(offset)) * CH_10MHZ_APART)))) ?\ 219 ((channel) + (offset) * CH_10MHZ_APART) : 0) : \ 220 (((channel) < (uint16)(MAXCHANNEL - (offset) * CH_10MHZ_APART)) ? \ 221 ((channel) + (offset) * CH_10MHZ_APART) : 0))) 222 223 #if defined(WL11AC_80P80) || defined(WL11AC_160) 224 /* pass a 160MHz center channel to get 20MHz subband channel numbers */ 225 #define LLL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -7) 226 #define LLU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -5) 227 #define LUL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -3) 228 #define LUU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -1) 229 #define ULL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 1) 230 #define ULU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 3) 231 #define UUL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 5) 232 #define UUU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 7) 233 234 /* given an 80p80 channel, return the lower 80MHz sideband */ 235 #define LOWER_80_SB(chspec) (wf_chspec_primary80_channel(chspec) < \ 236 wf_chspec_secondary80_channel(chspec) ? \ 237 wf_chspec_primary80_channel(chspec) : wf_chspec_secondary80_channel(chspec)) 238 239 /* given an 80p80 channel, return the upper 80MHz sideband */ 240 #define UPPER_80_SB(chspec) (wf_chspec_primary80_channel(chspec) > \ 241 wf_chspec_secondary80_channel(chspec) ? \ 242 wf_chspec_primary80_channel(chspec) : wf_chspec_secondary80_channel(chspec)) 243 244 /* pass an 80P80 chanspec (not channel) to get 20MHz subnand channel numbers */ 245 #define LLL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), -3) 246 #define LLU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), -1) 247 #define LUL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), 1) 248 #define LUU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), 3) 249 #define ULL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), -3) 250 #define ULU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), -1) 251 #define UUL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), 1) 252 #define UUU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), 3) 253 254 /* get lowest 20MHz sideband of a given chspec 255 * (works with 20, 40, 80, 160, 80p80) 256 */ 257 #define CH_FIRST_20_SB(chspec) ((uint8) (\ 258 CHSPEC_IS160(chspec) ? LLL_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\ 259 CHSPEC_IS8080(chspec) ? LLL_20_SB_8080(chspec) : (\ 260 CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 261 CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 262 CHSPEC_CHANNEL(chspec)))))) 263 264 /* get upper most 20MHz sideband of a given chspec 265 * (works with 20, 40, 80, 160, 80p80) 266 */ 267 #define CH_LAST_20_SB(chspec) ((uint8) (\ 268 CHSPEC_IS160(chspec) ? UUU_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\ 269 CHSPEC_IS8080(chspec) ? UUU_20_SB_8080(chspec) : (\ 270 CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 271 CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 272 CHSPEC_CHANNEL(chspec)))))) 273 274 /* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband 275 * (works with 80p80 only) 276 * resolves to 0 if called with upper most channel 277 */ 278 #define CH_NEXT_20_SB_IN_8080(chspec, channel) ((uint8) (\ 279 ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ 280 ((channel) == LUU_20_SB_8080(chspec) ? ULL_20_SB_8080(chspec) : \ 281 (channel) + CH_20MHZ_APART)))) 282 283 /* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband 284 * (works with 20, 40, 80, 160, 80p80) 285 * resolves to 0 if called with upper most channel 286 */ 287 #define CH_NEXT_20_SB(chspec, channel) ((uint8) (\ 288 (CHSPEC_IS8080(chspec) ? CH_NEXT_20_SB_IN_8080((chspec), (channel)) : \ 289 ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ 290 ((channel) + CH_20MHZ_APART))))) 291 292 #else /* WL11AC_80P80, WL11AC_160 */ 293 294 #define LLL_20_SB_160(channel) 0 295 #define LLU_20_SB_160(channel) 0 296 #define LUL_20_SB_160(channel) 0 297 #define LUU_20_SB_160(channel) 0 298 #define ULL_20_SB_160(channel) 0 299 #define ULU_20_SB_160(channel) 0 300 #define UUL_20_SB_160(channel) 0 301 #define UUU_20_SB_160(channel) 0 302 303 #define LOWER_80_SB(chspec) 0 304 305 #define UPPER_80_SB(chspec) 0 306 307 #define LLL_20_SB_8080(chspec) 0 308 #define LLU_20_SB_8080(chspec) 0 309 #define LUL_20_SB_8080(chspec) 0 310 #define LUU_20_SB_8080(chspec) 0 311 #define ULL_20_SB_8080(chspec) 0 312 #define ULU_20_SB_8080(chspec) 0 313 #define UUL_20_SB_8080(chspec) 0 314 #define UUU_20_SB_8080(chspec) 0 315 316 /* get lowest 20MHz sideband of a given chspec 317 * (works with 20, 40, 80) 318 */ 319 #define CH_FIRST_20_SB(chspec) ((uint8) (\ 320 CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 321 CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 322 CHSPEC_CHANNEL(chspec)))) 323 /* get upper most 20MHz sideband of a given chspec 324 * (works with 20, 40, 80, 160, 80p80) 325 */ 326 #define CH_LAST_20_SB(chspec) ((uint8) (\ 327 CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 328 CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 329 CHSPEC_CHANNEL(chspec)))) 330 331 /* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband 332 * (works with 20, 40, 80, 160, 80p80) 333 * resolves to 0 if called with upper most channel 334 */ 335 #define CH_NEXT_20_SB(chspec, channel) ((uint8) (\ 336 ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ 337 ((channel) + CH_20MHZ_APART)))) 338 339 #endif /* WL11AC_80P80, WL11AC_160 */ 340 341 /* Iterator for 20MHz side bands of a chanspec: (chanspec_t chspec, uint8 channel) 342 * 'chspec' chanspec_t of interest (used in loop, better to pass a resolved value than a macro) 343 * 'channel' must be a variable (not an expression). 344 */ 345 #define FOREACH_20_SB(chspec, channel) \ 346 for (channel = CH_FIRST_20_SB(chspec); channel; \ 347 channel = CH_NEXT_20_SB((chspec), channel)) 348 349 /* Uses iterator to populate array with all side bands involved (sorted lower to upper). 350 * 'chspec' chanspec_t of interest 351 * 'psb' pointer to uint8 array of enough size to hold all side bands for the given chspec 352 */ 353 #define GET_ALL_SB(chspec, psb) do { \ 354 uint8 channel, idx = 0; \ 355 chanspec_t chspec_local = chspec; \ 356 FOREACH_20_SB(chspec_local, channel) \ 357 (psb)[idx++] = channel; \ 358 } while (0) 359 360 /* given a chanspec of any bw, tests if primary20 SB is in lower 20, 40, 80 respectively */ 361 #define IS_CTL_IN_L20(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_U) /* CTL SB is in low 20 of any 40 */ 362 #define IS_CTL_IN_L40(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_UL) /* in low 40 of any 80 */ 363 #define IS_CTL_IN_L80(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_ULL) /* in low 80 of 80p80/160 */ 364 365 #endif /* !WL11N_20MHZONLY */ 366 367 /* ULB introduced macros. Remove once ULB is cleaned from phy code */ 368 #define CHSPEC_IS2P5(chspec) 0 369 #define CHSPEC_IS5(chspec) 0 370 #define CHSPEC_IS10(chspec) 0 371 #define CHSPEC_ISLE20(chspec) (CHSPEC_IS20(chspec)) 372 #define CHSPEC_BW_LE20(chspec) (CHSPEC_IS20(chspec)) 373 374 #define BW_LE40(bw) ((bw) == WL_CHANSPEC_BW_20 || ((bw) == WL_CHANSPEC_BW_40)) 375 #define BW_LE80(bw) (BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80)) 376 #define BW_LE160(bw) (BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160)) 377 378 #define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) 379 #define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) 380 #define CHSPEC_SB_UPPER(chspec) \ 381 ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ 382 (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) 383 #define CHSPEC_SB_LOWER(chspec) \ 384 ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ 385 (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) 386 #define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) 387 388 /** 389 * Number of chars needed for wf_chspec_ntoa() destination character buffer. 390 */ 391 #define CHANSPEC_STR_LEN 20 392 393 /* 394 * This function returns TRUE if both the chanspec can co-exist in PHY. 395 * Addition to primary20 channel, the function checks for side band for 2g 40 channels 396 */ 397 extern bool wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2); 398 399 #define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\ 400 CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080) 401 402 /* BW inequality comparisons, LE (<=), GE (>=), LT (<), GT (>), comparisons can be made 403 * as simple numeric comparisons, with the exception that 160 is the same BW as 80+80, 404 * but have different numeric values; (WL_CHANSPEC_BW_160 < WL_CHANSPEC_BW_8080). 405 * 406 * The LT/LE/GT/GE macros check first checks whether both chspec bandwidth and bw are 160 wide. 407 * If both chspec bandwidth and bw is not 160 wide, then the comparison is made. 408 */ 409 #define CHSPEC_BW_GE(chspec, bw) \ 410 ((CHSPEC_IS_BW_160_WIDE(chspec) &&\ 411 ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\ 412 (CHSPEC_BW(chspec) >= (bw))) 413 414 #define CHSPEC_BW_LE(chspec, bw) \ 415 ((CHSPEC_IS_BW_160_WIDE(chspec) &&\ 416 ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\ 417 (CHSPEC_BW(chspec) <= (bw))) 418 419 #define CHSPEC_BW_GT(chspec, bw) \ 420 (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\ 421 ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\ 422 (CHSPEC_BW(chspec) > (bw))) 423 424 #define CHSPEC_BW_LT(chspec, bw) \ 425 (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\ 426 ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\ 427 (CHSPEC_BW(chspec) < (bw))) 428 429 /* Legacy Chanspec defines 430 * These are the defines for the previous format of the chanspec_t 431 */ 432 #define WL_LCHANSPEC_CHAN_MASK 0x00ff 433 #define WL_LCHANSPEC_CHAN_SHIFT 0 434 435 #define WL_LCHANSPEC_CTL_SB_MASK 0x0300 436 #define WL_LCHANSPEC_CTL_SB_SHIFT 8 437 #define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 438 #define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 439 #define WL_LCHANSPEC_CTL_SB_NONE 0x0300 440 441 #define WL_LCHANSPEC_BW_MASK 0x0C00 442 #define WL_LCHANSPEC_BW_SHIFT 10 443 #define WL_LCHANSPEC_BW_10 0x0400 444 #define WL_LCHANSPEC_BW_20 0x0800 445 #define WL_LCHANSPEC_BW_40 0x0C00 446 447 #define WL_LCHANSPEC_BAND_MASK 0xf000 448 #define WL_LCHANSPEC_BAND_SHIFT 12 449 #define WL_LCHANSPEC_BAND_5G 0x1000 450 #define WL_LCHANSPEC_BAND_2G 0x2000 451 452 #define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) 453 #define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) 454 #define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) 455 #define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) 456 #define LCHSPEC_IS10(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10) 457 #define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) 458 #define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) 459 #define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) 460 #define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) 461 462 #define LCHSPEC_SB_UPPER(chspec) \ 463 ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \ 464 (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)) 465 #define LCHSPEC_SB_LOWER(chspec) \ 466 ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \ 467 (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)) 468 469 #define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) 470 471 #define CH20MHZ_LCHSPEC(channel) \ 472 (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \ 473 WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ 474 WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G)) 475 476 #define GET_ALL_EXT wf_get_all_ext 477 478 /* 479 * WF_CHAN_FACTOR_* constants are used to calculate channel frequency 480 * given a channel number. 481 * chan_freq = chan_factor * 500Mhz + chan_number * 5 482 */ 483 484 /** 485 * Channel Factor for the starting frequence of 2.4 GHz channels. 486 * The value corresponds to 2407 MHz. 487 */ 488 #define WF_CHAN_FACTOR_2_4_G 4814 /* 2.4 GHz band, 2407 MHz */ 489 490 /** 491 * Channel Factor for the starting frequence of 5 GHz channels. 492 * The value corresponds to 5000 MHz. 493 */ 494 #define WF_CHAN_FACTOR_5_G 10000 /* 5 GHz band, 5000 MHz */ 495 496 /** 497 * Channel Factor for the starting frequence of 4.9 GHz channels. 498 * The value corresponds to 4000 MHz. 499 */ 500 #define WF_CHAN_FACTOR_4_G 8000 /* 4.9 GHz band for Japan */ 501 502 #define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ 503 504 /** 505 * No of sub-band vlaue of the specified Mhz chanspec 506 */ 507 #define WF_NUM_SIDEBANDS_40MHZ 2 508 #define WF_NUM_SIDEBANDS_80MHZ 4 509 #define WF_NUM_SIDEBANDS_8080MHZ 4 510 #define WF_NUM_SIDEBANDS_160MHZ 8 511 512 /** 513 * Return the chanspec bandwidth in MHz 514 * Bandwidth of 160 MHz will be returned for 80+80MHz chanspecs. 515 * 516 * @param chspec chanspec_t 517 * 518 * @return bandwidth of chspec in MHz units 519 */ 520 extern uint wf_bw_chspec_to_mhz(chanspec_t chspec); 521 522 /** 523 * Convert chanspec to ascii string 524 * 525 * @param chspec chanspec format 526 * @param buf ascii string of chanspec 527 * 528 * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes 529 * Original chanspec in case of error 530 * 531 * @see CHANSPEC_STR_LEN 532 */ 533 extern char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf); 534 535 /** 536 * Convert chanspec to ascii string 537 * 538 * @param chspec chanspec format 539 * @param buf ascii string of chanspec 540 * 541 * @return pointer to buf with room for at least CHANSPEC_STR_LEN bytes 542 * NULL in case of error 543 * 544 * @see CHANSPEC_STR_LEN 545 */ 546 extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); 547 548 /** 549 * Convert ascii string to chanspec 550 * 551 * @param a pointer to input string 552 * 553 * @return >= 0 if successful or 0 otherwise 554 */ 555 extern chanspec_t wf_chspec_aton(const char *a); 556 557 /** 558 * Convert ascii string to chanspec 559 * 560 * @param a pointer to chanspec input string 561 * @param default_bw default bandwidth to use if not specified in chanspec input string 562 * 563 * @return >= 0 if successful or 0 otherwise 564 */ 565 extern chanspec_t wf_chspec_aton_ex(const char *a, const uint default_bw); 566 567 /** 568 * Verify the chanspec fields are valid. 569 * 570 * Verify the chanspec is using a legal set field values, i.e. that the chanspec 571 * specified a band, bw, primary_sb, and channel and that the combination could be 572 * legal given some set of circumstances. 573 * 574 * @param chanspec input chanspec to verify 575 * 576 * @return TRUE if the chanspec is malformed, FALSE if it looks good. 577 */ 578 extern bool wf_chspec_malformed(chanspec_t chanspec); 579 580 /** 581 * Verify the chanspec specifies a valid channel according to 802.11. 582 * 583 * @param chanspec input chanspec to verify 584 * 585 * @return TRUE if the chanspec is a valid 802.11 channel 586 */ 587 extern bool wf_chspec_valid(chanspec_t chanspec); 588 589 /** 590 * Return the primary 20MHz channel. 591 * 592 * This function returns the channel number of the primary 20MHz channel. For 593 * 20MHz channels this is just the channel number. For 40MHz or wider channels 594 * it is the primary 20MHz channel specified by the chanspec. 595 * 596 * @param chspec input chanspec 597 * 598 * @return Returns the channel number of the primary 20MHz channel 599 */ 600 extern uint8 wf_chspec_primary20_chan(chanspec_t chspec); 601 602 /* alias for old function name */ 603 #define wf_chspec_ctlchan(c) wf_chspec_primary20_chan(c) 604 605 /** 606 * Return the bandwidth string. 607 * 608 * This function returns the bandwidth string for the passed chanspec. 609 * 610 * @param chspec input chanspec 611 * 612 * @return Returns the bandwidth string: 613 * "5", "10", "20", "40", "80", "160", "80+80" 614 */ 615 extern const char *wf_chspec_to_bw_str(chanspec_t chspec); 616 617 /** 618 * Create a 20MHz chanspec for the given band. 619 */ 620 chanspec_t wf_create_20MHz_chspec(uint channel, chanspec_band_t band); 621 622 /** 623 * Return the primary 20MHz chanspec. 624 * 625 * This function returns the chanspec of the primary 20MHz channel. For 20MHz 626 * channels this is just the chanspec. For 40MHz or wider channels it is the 627 * chanspec of the primary 20MHZ channel specified by the chanspec. 628 * 629 * @param chspec input chanspec 630 * 631 * @return Returns the chanspec of the primary 20MHz channel 632 */ 633 extern chanspec_t wf_chspec_primary20_chspec(chanspec_t chspec); 634 635 /* alias for old function name */ 636 #define wf_chspec_ctlchspec(c) wf_chspec_primary20_chspec(c) 637 638 /** 639 * Return the primary 40MHz chanspec. 640 * 641 * This function returns the chanspec for the primary 40MHz of an 80MHz or wider channel. 642 * The primary 20MHz channel of the returned 40MHz chanspec is the same as the primary 20MHz 643 * channel of the input chanspec. 644 */ 645 extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec); 646 647 /* 648 * Return the channel number for a given frequency and base frequency. 649 * The returned channel number is relative to the given base frequency. 650 * If the given base frequency is zero, a base frequency of 5 GHz is assumed for 651 * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz. 652 * 653 * Frequency is specified in MHz. 654 * The base frequency is specified as (start_factor * 500 kHz). 655 * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for 656 * 2.4 GHz and 5 GHz bands. 657 * 658 * The returned channel will be in the range [1, 14] in the 2.4 GHz band 659 * and [0, 200] otherwise. 660 * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the 661 * frequency is not a 2.4 GHz channel, or if the frequency is not and even 662 * multiple of 5 MHz from the base frequency to the base plus 1 GHz. 663 * 664 * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3 665 * 666 * @param freq frequency in MHz 667 * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz 668 * 669 * @return Returns a channel number 670 * 671 * @see WF_CHAN_FACTOR_2_4_G 672 * @see WF_CHAN_FACTOR_5_G 673 */ 674 extern int wf_mhz2channel(uint freq, uint start_factor); 675 676 /** 677 * Return the center frequency in MHz of the given channel and base frequency. 678 * 679 * Return the center frequency in MHz of the given channel and base frequency. 680 * The channel number is interpreted relative to the given base frequency. 681 * 682 * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise. 683 * The base frequency is specified as (start_factor * 500 kHz). 684 * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for 685 * 2.4 GHz and 5 GHz bands. 686 * The channel range of [1, 14] is only checked for a start_factor of 687 * WF_CHAN_FACTOR_2_4_G (4814). 688 * Odd start_factors produce channels on .5 MHz boundaries, in which case 689 * the answer is rounded down to an integral MHz. 690 * -1 is returned for an out of range channel. 691 * 692 * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3 693 * 694 * @param channel input channel number 695 * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz 696 * 697 * @return Returns a frequency in MHz 698 * 699 * @see WF_CHAN_FACTOR_2_4_G 700 * @see WF_CHAN_FACTOR_5_G 701 */ 702 extern int wf_channel2mhz(uint channel, uint start_factor); 703 704 /** 705 * Returns the chanspec 80Mhz channel corresponding to the following input 706 * parameters 707 * 708 * primary_channel - primary 20Mhz channel 709 * center_channel - center frequecny of the 80Mhz channel 710 * 711 * The center_channel can be one of {42, 58, 106, 122, 138, 155} 712 * 713 * returns INVCHANSPEC in case of error 714 */ 715 extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel); 716 717 /** 718 * Convert ctl chan and bw to chanspec 719 * 720 * @param ctl_ch channel 721 * @param bw bandwidth 722 * 723 * @return > 0 if successful or 0 otherwise 724 * 725 */ 726 extern uint16 wf_channel2chspec(uint ctl_ch, uint bw); 727 728 extern uint wf_channel2freq(uint channel); 729 extern uint wf_freq2channel(uint freq); 730 731 /* 732 * Returns the 80+80 MHz chanspec corresponding to the following input parameters 733 * 734 * primary_20mhz - Primary 20 MHz channel 735 * chan0_80MHz - center channel number of one frequency segment 736 * chan1_80MHz - center channel number of the other frequency segment 737 * 738 * Parameters chan0_80MHz and chan1_80MHz are channel numbers in {42, 58, 106, 122, 138, 155}. 739 * The primary channel must be contained in one of the 80MHz channels. This routine 740 * will determine which frequency segment is the primary 80 MHz segment. 741 * 742 * Returns INVCHANSPEC in case of error. 743 * 744 * Refer to 802.11-2016 section 22.3.14 "Channelization". 745 */ 746 extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz, 747 uint8 chan0_80Mhz, uint8 chan1_80Mhz); 748 749 /** 750 * Returns the center channel of the primary 80 MHz sub-band of the provided chanspec 751 * 752 * @param chspec input chanspec 753 * 754 * @return center channel number of the primary 80MHz sub-band of the input. 755 * Will return the center channel of an input 80MHz chspec. 756 * Will return INVCHANNEL if the chspec is malformed or less than 80MHz bw. 757 */ 758 extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec); 759 760 /** 761 * Returns the center channel of the secondary 80 MHz sub-band of the provided chanspec 762 * 763 * @param chspec input chanspec 764 * 765 * @return center channel number of the secondary 80MHz sub-band of the input. 766 * Will return INVCHANNEL if the chspec is malformed or bw is not greater than 80MHz. 767 */ 768 extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec); 769 770 /** 771 * Returns the chanspec for the primary 80MHz sub-band of an 160MHz or 80+80 channel 772 * 773 * @param chspec input chanspec 774 * 775 * @return An 80MHz chanspec describing the primary 80MHz sub-band of the input. 776 * Will return an input 80MHz chspec as is. 777 * Will return INVCHANSPEC if the chspec is malformed or less than 80MHz bw. 778 */ 779 extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec); 780 781 /** 782 * Returns the chanspec for the secondary 80MHz sub-band of an 160MHz or 80+80 channel 783 * The sideband in the chanspec is always set to WL_CHANSPEC_CTL_SB_LL since this sub-band 784 * does not contain the primary 20MHz channel. 785 * 786 * @param chspec input chanspec 787 * 788 * @return An 80MHz chanspec describing the secondary 80MHz sub-band of the input. 789 * Will return INVCHANSPEC if the chspec is malformed or bw is not greater than 80MHz. 790 */ 791 extern chanspec_t wf_chspec_secondary80_chspec(chanspec_t chspec); 792 793 /* 794 * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels 795 * 796 * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1 797 */ 798 extern void wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch); 799 800 #ifdef WL11AC_80P80 801 /* 802 * This function returns the centre chanel for the given chanspec. 803 * In case of 80+80 chanspec it returns the primary 80 Mhz centre channel 804 */ 805 extern uint8 wf_chspec_channel(chanspec_t chspec); 806 #endif // endif 807 extern chanspec_t wf_channel_create_chspec_frm_opclass(uint8 opclass, uint8 channel); 808 extern int wf_channel_create_opclass_frm_chspec(chanspec_t chspec); 809 810 /* Populates array with all 20MHz side bands of a given chanspec_t in the following order: 811 * primary20, ext20, two ext40s, four ext80s. 812 * 'chspec' is the chanspec of interest 813 * 'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec 814 * 815 * Works with 20, 40, 80, 80p80 and 160MHz chspec 816 */ 817 818 extern void wf_get_all_ext(chanspec_t chspec, uint8 *chan_ptr); 819 820 /* 821 * Given two chanspecs, returns true if they overlap. 822 * (Overlap: At least one 20MHz subband is common between the two chanspecs provided) 823 */ 824 extern bool wf_chspec_overlap(chanspec_t chspec0, chanspec_t chspec1); 825 826 extern uint8 channel_bw_to_width(chanspec_t chspec); 827 #endif /* _bcmwifi_channels_h_ */ 828