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