1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Misc utility routines for WL and Apps 3*4882a593Smuzhiyun * This header file housing the define and function prototype use by 4*4882a593Smuzhiyun * both the wl driver, tools & Apps. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Copyright (C) 2020, Broadcom. 7*4882a593Smuzhiyun * 8*4882a593Smuzhiyun * Unless you and Broadcom execute a separate written software license 9*4882a593Smuzhiyun * agreement governing use of this software, this software is licensed to you 10*4882a593Smuzhiyun * under the terms of the GNU General Public License version 2 (the "GPL"), 11*4882a593Smuzhiyun * available at http://www.broadcom.com/licenses/GPLv2.php, with the 12*4882a593Smuzhiyun * following added to such license: 13*4882a593Smuzhiyun * 14*4882a593Smuzhiyun * As a special exception, the copyright holders of this software give you 15*4882a593Smuzhiyun * permission to link this software with independent modules, and to copy and 16*4882a593Smuzhiyun * distribute the resulting executable under terms of your choice, provided that 17*4882a593Smuzhiyun * you also meet, for each linked independent module, the terms and conditions of 18*4882a593Smuzhiyun * the license of that module. An independent module is a module which is not 19*4882a593Smuzhiyun * derived from this software. The special exception does not apply to any 20*4882a593Smuzhiyun * modifications of the software. 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * 23*4882a593Smuzhiyun * <<Broadcom-WL-IPTag/Dual:>> 24*4882a593Smuzhiyun */ 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun #ifndef _bcmwifi_channels_h_ 27*4882a593Smuzhiyun #define _bcmwifi_channels_h_ 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun /* A chanspec holds the channel number, band, bandwidth and primary 20MHz sub-band */ 30*4882a593Smuzhiyun typedef uint16 chanspec_t; 31*4882a593Smuzhiyun typedef uint16 chanspec_band_t; 32*4882a593Smuzhiyun typedef uint16 chanspec_bw_t; 33*4882a593Smuzhiyun typedef uint16 chanspec_subband_t; 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun /* channel defines */ 36*4882a593Smuzhiyun #define CH_80MHZ_APART 16u 37*4882a593Smuzhiyun #define CH_40MHZ_APART 8u 38*4882a593Smuzhiyun #define CH_20MHZ_APART 4u 39*4882a593Smuzhiyun #define CH_10MHZ_APART 2u 40*4882a593Smuzhiyun #define CH_5MHZ_APART 1u /* 2G band channels are 5 Mhz apart */ 41*4882a593Smuzhiyun #define CH_160MHZ_APART (32u * CH_5MHZ_APART) /* 32 5Mhz-spaces */ 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun #define CH_MIN_2G_CHANNEL 1u /* Min channel in 2G band */ 44*4882a593Smuzhiyun #define CH_MAX_2G_CHANNEL 14u /* Max channel in 2G band */ 45*4882a593Smuzhiyun #define CH_MIN_2G_40M_CHANNEL 3u /* Min 40MHz center channel in 2G band */ 46*4882a593Smuzhiyun #define CH_MAX_2G_40M_CHANNEL 11u /* Max 40MHz center channel in 2G band */ 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun #define CH_MIN_6G_CHANNEL 1u /* Min 20MHz channel in 6G band */ 49*4882a593Smuzhiyun #define CH_MAX_6G_CHANNEL 253u /* Max 20MHz channel in 6G band */ 50*4882a593Smuzhiyun #define CH_MIN_6G_40M_CHANNEL 3u /* Min 40MHz center channel in 6G band */ 51*4882a593Smuzhiyun #define CH_MAX_6G_40M_CHANNEL 227u /* Max 40MHz center channel in 6G band */ 52*4882a593Smuzhiyun #define CH_MIN_6G_80M_CHANNEL 7u /* Min 80MHz center channel in 6G band */ 53*4882a593Smuzhiyun #define CH_MAX_6G_80M_CHANNEL 215u /* Max 80MHz center channel in 6G band */ 54*4882a593Smuzhiyun #define CH_MIN_6G_160M_CHANNEL 15u /* Min 160MHz center channel in 6G band */ 55*4882a593Smuzhiyun #define CH_MAX_6G_160M_CHANNEL 207u /* Max 160MHz center channel in 6G band */ 56*4882a593Smuzhiyun #define CH_MIN_6G_240M_CHANNEL 23u /* Min 240MHz center channel in 6G band */ 57*4882a593Smuzhiyun #define CH_MAX_6G_240M_CHANNEL 167u /* Max 240MHz center channel in 6G band */ 58*4882a593Smuzhiyun #define CH_MIN_6G_320M_CHANNEL 31u /* Min 320MHz center channel in 6G band */ 59*4882a593Smuzhiyun #define CH_MAX_6G_320M_CHANNEL 199u /* Max 320MHz center channel in 6G band */ 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun /* maximum # channels the s/w supports */ 62*4882a593Smuzhiyun #define MAXCHANNEL 254u /* max # supported channels. 63*4882a593Smuzhiyun * DO NOT MAKE > 255: channels are uint8's all over 64*4882a593Smuzhiyun */ 65*4882a593Smuzhiyun #define MAXCHANNEL_NUM (MAXCHANNEL - 1) /* max channel number */ 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun #define INVCHANNEL 255u /* error value for a bad channel */ 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun /* length of channel vector bitmap is the MAXCHANNEL we want to handle rounded up to a byte */ 70*4882a593Smuzhiyun /* The actual CHANVEC_LEN fix is leading to high static memory impact 71*4882a593Smuzhiyun * in all projects wherein the previous CHANVEC_LEN definition is used. 72*4882a593Smuzhiyun * 73*4882a593Smuzhiyun * Retaining the previous definition under MAXCHNL_ROM_COMPAT flag. 74*4882a593Smuzhiyun * All those chip porgrams where memory impact is observed need to define the same. 75*4882a593Smuzhiyun */ 76*4882a593Smuzhiyun #ifdef MAXCHNL_ROM_COMPAT 77*4882a593Smuzhiyun #define CHANVEC_LEN (MAXCHANNEL + (8 - 1) / 8) 78*4882a593Smuzhiyun #else 79*4882a593Smuzhiyun #define CHANVEC_LEN ((MAXCHANNEL + (8 - 1)) / 8) 80*4882a593Smuzhiyun #endif 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun /* channel bitvec */ 83*4882a593Smuzhiyun typedef struct { 84*4882a593Smuzhiyun uint8 vec[CHANVEC_LEN]; /* bitvec of channels */ 85*4882a593Smuzhiyun } chanvec_t; 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun /* make sure channel num is within valid range */ 88*4882a593Smuzhiyun #define CH_NUM_VALID_RANGE(ch_num) ((ch_num) > 0 && (ch_num) <= MAXCHANNEL_NUM) 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun #define CHSPEC_CTLOVLP(sp1, sp2, sep) \ 91*4882a593Smuzhiyun ((uint)ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (uint)(sep)) 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun /* All builds use the new 11ac ratespec/chanspec */ 94*4882a593Smuzhiyun #undef D11AC_IOTYPES 95*4882a593Smuzhiyun #define D11AC_IOTYPES 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun /* For contiguous channel bandwidth other than 240MHz/320Mhz */ 98*4882a593Smuzhiyun #define WL_CHANSPEC_CHAN_MASK 0x00ffu 99*4882a593Smuzhiyun #define WL_CHANSPEC_CHAN_SHIFT 0u 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun /* For contiguous channel bandwidth >= 240MHz */ 102*4882a593Smuzhiyun #define WL_CHANSPEC_GE240_CHAN_MASK 0x0003u 103*4882a593Smuzhiyun #define WL_CHANSPEC_GE240_CHAN_SHIFT 0u 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun /* For discontiguous channel bandwidth */ 106*4882a593Smuzhiyun #define WL_CHANSPEC_CHAN0_MASK 0x000fu 107*4882a593Smuzhiyun #define WL_CHANSPEC_CHAN0_SHIFT 0u 108*4882a593Smuzhiyun #define WL_CHANSPEC_CHAN1_MASK 0x00f0u 109*4882a593Smuzhiyun #define WL_CHANSPEC_CHAN1_SHIFT 4u 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun /* Non-320/Non-240 Mhz channel sideband indication */ 112*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_MASK 0x0700u 113*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_SHIFT 8u 114*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_LLL 0x0000u 115*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_LLU 0x0100u 116*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_LUL 0x0200u 117*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_LUU 0x0300u 118*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_ULL 0x0400u 119*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_ULU 0x0500u 120*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_UUL 0x0600u 121*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_UUU 0x0700u 122*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_LL WL_CHANSPEC_CTL_SB_LLL 123*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_LU WL_CHANSPEC_CTL_SB_LLU 124*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_UL WL_CHANSPEC_CTL_SB_LUL 125*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_UU WL_CHANSPEC_CTL_SB_LUU 126*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_L WL_CHANSPEC_CTL_SB_LLL 127*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_U WL_CHANSPEC_CTL_SB_LLU 128*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_LOWER WL_CHANSPEC_CTL_SB_LLL 129*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_UPPER WL_CHANSPEC_CTL_SB_LLU 130*4882a593Smuzhiyun #define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun /* channel sideband indication for frequency >= 240MHz */ 133*4882a593Smuzhiyun #define WL_CHANSPEC_GE240_SB_MASK 0x0780u 134*4882a593Smuzhiyun #define WL_CHANSPEC_GE240_SB_SHIFT 7u 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun /* Bandwidth field */ 137*4882a593Smuzhiyun #define WL_CHANSPEC_BW_MASK 0x3800u 138*4882a593Smuzhiyun #define WL_CHANSPEC_BW_SHIFT 11u 139*4882a593Smuzhiyun #define WL_CHANSPEC_BW_320 0x0000u 140*4882a593Smuzhiyun #define WL_CHANSPEC_BW_160160 0x0800u 141*4882a593Smuzhiyun #define WL_CHANSPEC_BW_20 0x1000u 142*4882a593Smuzhiyun #define WL_CHANSPEC_BW_40 0x1800u 143*4882a593Smuzhiyun #define WL_CHANSPEC_BW_80 0x2000u 144*4882a593Smuzhiyun #define WL_CHANSPEC_BW_160 0x2800u 145*4882a593Smuzhiyun #define WL_CHANSPEC_BW_8080 0x3000u 146*4882a593Smuzhiyun #define WL_CHANSPEC_BW_240 0x3800u 147*4882a593Smuzhiyun 148*4882a593Smuzhiyun /* Band field */ 149*4882a593Smuzhiyun #define WL_CHANSPEC_BAND_MASK 0xc000u 150*4882a593Smuzhiyun #define WL_CHANSPEC_BAND_SHIFT 14u 151*4882a593Smuzhiyun #define WL_CHANSPEC_BAND_2G 0x0000u 152*4882a593Smuzhiyun #define WL_CHANSPEC_BAND_6G 0x4000u 153*4882a593Smuzhiyun #define WL_CHANSPEC_BAND_4G 0x8000u 154*4882a593Smuzhiyun #define WL_CHANSPEC_BAND_5G 0xc000u 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun #define INVCHANSPEC 255u 157*4882a593Smuzhiyun #define MAX_CHANSPEC 0xFFFFu 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun #define WL_CHSPEC_BW(chspec) ((chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT) 160*4882a593Smuzhiyun #define MAX_BW_NUM (uint8)(((WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT)) 161*4882a593Smuzhiyun 162*4882a593Smuzhiyun #define WL_CHANNEL_BAND(ch) (((uint)(ch) <= CH_MAX_2G_CHANNEL) ? \ 163*4882a593Smuzhiyun WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun /* channel defines */ 166*4882a593Smuzhiyun #define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? \ 167*4882a593Smuzhiyun ((channel) - CH_10MHZ_APART) : 0) 168*4882a593Smuzhiyun #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ 169*4882a593Smuzhiyun ((channel) + CH_10MHZ_APART) : 0) 170*4882a593Smuzhiyun 171*4882a593Smuzhiyun /* pass a 80MHz channel number (uint8) to get respective LL, UU, LU, UL */ 172*4882a593Smuzhiyun #define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) 173*4882a593Smuzhiyun #define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ 174*4882a593Smuzhiyun ((channel) + 3 * CH_10MHZ_APART) : 0) 175*4882a593Smuzhiyun #define LU_20_SB(channel) LOWER_20_SB(channel) 176*4882a593Smuzhiyun #define UL_20_SB(channel) UPPER_20_SB(channel) 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun #define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART) 179*4882a593Smuzhiyun #define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART) 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun #ifndef CHSPEC_WLCBANDUNIT 182*4882a593Smuzhiyun #define CHSPEC_WLCBANDUNIT(chspec) \ 183*4882a593Smuzhiyun ((CHSPEC_IS5G(chspec) || CHSPEC_IS6G(chspec)) ? BAND_5G_INDEX : BAND_2G_INDEX) 184*4882a593Smuzhiyun #endif 185*4882a593Smuzhiyun #define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ 186*4882a593Smuzhiyun WL_CHANNEL_BAND(channel)) 187*4882a593Smuzhiyun #define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ 188*4882a593Smuzhiyun ((channel) + CH_20MHZ_APART) : 0) 189*4882a593Smuzhiyun #define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 190*4882a593Smuzhiyun ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ 191*4882a593Smuzhiyun WL_CHANNEL_BAND(channel)) 192*4882a593Smuzhiyun #define CH80MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 193*4882a593Smuzhiyun ((channel) | (ctlsb) | \ 194*4882a593Smuzhiyun WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G) 195*4882a593Smuzhiyun #define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ 196*4882a593Smuzhiyun ((channel) | (ctlsb) | \ 197*4882a593Smuzhiyun WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G) 198*4882a593Smuzhiyun 199*4882a593Smuzhiyun /* simple MACROs to get different fields of chanspec */ 200*4882a593Smuzhiyun #define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) 201*4882a593Smuzhiyun #define CHSPEC_CHAN0(chspec) (((chspec) & WL_CHANSPEC_CHAN0_MASK) >> WL_CHANSPEC_CHAN0_SHIFT) 202*4882a593Smuzhiyun #define CHSPEC_CHAN1(chspec) (((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT) 203*4882a593Smuzhiyun #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) 204*4882a593Smuzhiyun #define CHSPEC_CTL_SB(chspec) ((chspec) & WL_CHANSPEC_CTL_SB_MASK) 205*4882a593Smuzhiyun #define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) 206*4882a593Smuzhiyun #define CHSPEC_GE240_CHAN(chspec) (((chspec) & WL_CHANSPEC_GE240_CHAN_MASK) >> \ 207*4882a593Smuzhiyun WL_CHANSPEC_GE240_CHAN_SHIFT) 208*4882a593Smuzhiyun #define CHSPEC_GE240_SB(chspec) ((chspec) & WL_CHANSPEC_GE240_SB_MASK) 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun #define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) 211*4882a593Smuzhiyun #define CHSPEC_IS20_5G(chspec) ((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \ 212*4882a593Smuzhiyun CHSPEC_IS5G(chspec)) 213*4882a593Smuzhiyun #ifndef CHSPEC_IS40 214*4882a593Smuzhiyun #define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) 215*4882a593Smuzhiyun #endif 216*4882a593Smuzhiyun #ifndef CHSPEC_IS80 217*4882a593Smuzhiyun #define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) 218*4882a593Smuzhiyun #endif 219*4882a593Smuzhiyun #ifndef CHSPEC_IS160 220*4882a593Smuzhiyun #define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) 221*4882a593Smuzhiyun #endif 222*4882a593Smuzhiyun #define CHSPEC_IS8080(chspec) (FALSE) 223*4882a593Smuzhiyun #ifndef CHSPEC_IS320 224*4882a593Smuzhiyun #ifdef WL11BE 225*4882a593Smuzhiyun #define CHSPEC_IS320(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_320) 226*4882a593Smuzhiyun #else 227*4882a593Smuzhiyun #define CHSPEC_IS320(chspec) (FALSE) 228*4882a593Smuzhiyun #endif 229*4882a593Smuzhiyun #endif /* CHSPEC_IS320 */ 230*4882a593Smuzhiyun #ifndef CHSPEC_IS240 231*4882a593Smuzhiyun #ifdef WL11BE 232*4882a593Smuzhiyun #define CHSPEC_IS240(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_240) 233*4882a593Smuzhiyun #else 234*4882a593Smuzhiyun #define CHSPEC_IS240(chspec) (FALSE) 235*4882a593Smuzhiyun #endif 236*4882a593Smuzhiyun #endif /* CHSPEC_IS240 */ 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun /* pass a center channel and get channel offset from it by 10MHz */ 239*4882a593Smuzhiyun #define CH_OFF_10MHZ_MULTIPLES(channel, offset) \ 240*4882a593Smuzhiyun ((uint8) (((offset) < 0) ? \ 241*4882a593Smuzhiyun (((channel) > (WL_CHANSPEC_CHAN_MASK & ((uint16)((-(offset)) * CH_10MHZ_APART)))) ? \ 242*4882a593Smuzhiyun ((channel) + (offset) * CH_10MHZ_APART) : 0) : \ 243*4882a593Smuzhiyun ((((uint16)(channel) + (uint16)(offset) * CH_10MHZ_APART) < (uint16)MAXCHANNEL) ? \ 244*4882a593Smuzhiyun ((channel) + (offset) * CH_10MHZ_APART) : 0))) 245*4882a593Smuzhiyun 246*4882a593Smuzhiyun uint wf_chspec_first_20_sb(chanspec_t chspec); 247*4882a593Smuzhiyun 248*4882a593Smuzhiyun #if defined(WL_BW160MHZ) 249*4882a593Smuzhiyun /* pass a 160MHz center channel to get 20MHz subband channel numbers */ 250*4882a593Smuzhiyun #define LLL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -7) 251*4882a593Smuzhiyun #define LLU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -5) 252*4882a593Smuzhiyun #define LUL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -3) 253*4882a593Smuzhiyun #define LUU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -1) 254*4882a593Smuzhiyun #define ULL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 1) 255*4882a593Smuzhiyun #define ULU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 3) 256*4882a593Smuzhiyun #define UUL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 5) 257*4882a593Smuzhiyun #define UUU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 7) 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun /* get lowest 20MHz sideband of a given chspec 260*4882a593Smuzhiyun * (works with 20, 40, 80, 160) 261*4882a593Smuzhiyun */ 262*4882a593Smuzhiyun #define CH_FIRST_20_SB(chspec) ((uint8) (\ 263*4882a593Smuzhiyun CHSPEC_IS160(chspec) ? LLL_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\ 264*4882a593Smuzhiyun CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 265*4882a593Smuzhiyun CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 266*4882a593Smuzhiyun CHSPEC_CHANNEL(chspec))))) 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun /* get upper most 20MHz sideband of a given chspec 269*4882a593Smuzhiyun * (works with 20, 40, 80, 160) 270*4882a593Smuzhiyun */ 271*4882a593Smuzhiyun #define CH_LAST_20_SB(chspec) ((uint8) (\ 272*4882a593Smuzhiyun CHSPEC_IS160(chspec) ? UUU_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\ 273*4882a593Smuzhiyun CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 274*4882a593Smuzhiyun CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 275*4882a593Smuzhiyun CHSPEC_CHANNEL(chspec))))) 276*4882a593Smuzhiyun 277*4882a593Smuzhiyun /* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband 278*4882a593Smuzhiyun * (works with 20, 40, 80, 160) 279*4882a593Smuzhiyun * resolves to 0 if called with upper most channel 280*4882a593Smuzhiyun */ 281*4882a593Smuzhiyun #define CH_NEXT_20_SB(chspec, channel) ((uint8) (\ 282*4882a593Smuzhiyun ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ 283*4882a593Smuzhiyun ((channel) + CH_20MHZ_APART)))) 284*4882a593Smuzhiyun 285*4882a593Smuzhiyun #else /* WL_BW160MHZ */ 286*4882a593Smuzhiyun 287*4882a593Smuzhiyun #define LLL_20_SB_160(channel) 0 288*4882a593Smuzhiyun #define LLU_20_SB_160(channel) 0 289*4882a593Smuzhiyun #define LUL_20_SB_160(channel) 0 290*4882a593Smuzhiyun #define LUU_20_SB_160(channel) 0 291*4882a593Smuzhiyun #define ULL_20_SB_160(channel) 0 292*4882a593Smuzhiyun #define ULU_20_SB_160(channel) 0 293*4882a593Smuzhiyun #define UUL_20_SB_160(channel) 0 294*4882a593Smuzhiyun #define UUU_20_SB_160(channel) 0 295*4882a593Smuzhiyun 296*4882a593Smuzhiyun /* get lowest 20MHz sideband of a given chspec 297*4882a593Smuzhiyun * (works with 20, 40, 80) 298*4882a593Smuzhiyun */ 299*4882a593Smuzhiyun #define CH_FIRST_20_SB(chspec) ((uint8) (\ 300*4882a593Smuzhiyun CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 301*4882a593Smuzhiyun CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 302*4882a593Smuzhiyun CHSPEC_CHANNEL(chspec)))) 303*4882a593Smuzhiyun /* get upper most 20MHz sideband of a given chspec 304*4882a593Smuzhiyun * (works with 20, 40, 80, 160) 305*4882a593Smuzhiyun */ 306*4882a593Smuzhiyun #define CH_LAST_20_SB(chspec) ((uint8) (\ 307*4882a593Smuzhiyun CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\ 308*4882a593Smuzhiyun CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \ 309*4882a593Smuzhiyun CHSPEC_CHANNEL(chspec)))) 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun /* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband 312*4882a593Smuzhiyun * (works with 20, 40, 80, 160) 313*4882a593Smuzhiyun * resolves to 0 if called with upper most channel 314*4882a593Smuzhiyun */ 315*4882a593Smuzhiyun #define CH_NEXT_20_SB(chspec, channel) ((uint8) (\ 316*4882a593Smuzhiyun ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ 317*4882a593Smuzhiyun ((channel) + CH_20MHZ_APART)))) 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun #endif /* WL_BW160MHZ */ 320*4882a593Smuzhiyun 321*4882a593Smuzhiyun /* Iterator for 20MHz side bands of a chanspec: (chanspec_t chspec, uint8 channel) 322*4882a593Smuzhiyun * 'chspec' chanspec_t of interest (used in loop, better to pass a resolved value than a macro) 323*4882a593Smuzhiyun * 'channel' must be a variable (not an expression). 324*4882a593Smuzhiyun */ 325*4882a593Smuzhiyun #define FOREACH_20_SB(chspec, channel) \ 326*4882a593Smuzhiyun for (channel = (uint8)wf_chspec_first_20_sb(chspec); channel; \ 327*4882a593Smuzhiyun channel = CH_NEXT_20_SB((chspec), channel)) 328*4882a593Smuzhiyun 329*4882a593Smuzhiyun /* Uses iterator to populate array with all side bands involved (sorted lower to upper). 330*4882a593Smuzhiyun * 'chspec' chanspec_t of interest 331*4882a593Smuzhiyun * 'psb' pointer to uint8 array of enough size to hold all side bands for the given chspec 332*4882a593Smuzhiyun */ 333*4882a593Smuzhiyun #define GET_ALL_SB(chspec, psb) do { \ 334*4882a593Smuzhiyun uint8 channel, idx = 0; \ 335*4882a593Smuzhiyun chanspec_t chspec_local = chspec; \ 336*4882a593Smuzhiyun FOREACH_20_SB(chspec_local, channel) \ 337*4882a593Smuzhiyun (psb)[idx++] = channel; \ 338*4882a593Smuzhiyun } while (0) 339*4882a593Smuzhiyun 340*4882a593Smuzhiyun /* given a chanspec of any bw, tests if primary20 SB is in lower 20, 40, 80 respectively */ 341*4882a593Smuzhiyun #define IS_CTL_IN_L20(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_U) /* CTL SB is in low 20 of any 40 */ 342*4882a593Smuzhiyun #define IS_CTL_IN_L40(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_UL) /* in low 40 of any 80 */ 343*4882a593Smuzhiyun #define IS_CTL_IN_L80(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_ULL) /* in low 80 of 160 */ 344*4882a593Smuzhiyun 345*4882a593Smuzhiyun #define BW_LE40(bw) ((bw) == WL_CHANSPEC_BW_20 || ((bw) == WL_CHANSPEC_BW_40)) 346*4882a593Smuzhiyun #define BW_LE80(bw) (BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80)) 347*4882a593Smuzhiyun #define BW_LE160(bw) (BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160)) 348*4882a593Smuzhiyun 349*4882a593Smuzhiyun #define CHSPEC_IS6G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_6G) 350*4882a593Smuzhiyun #define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) 351*4882a593Smuzhiyun #define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) 352*4882a593Smuzhiyun #define CHSPEC_SB_UPPER(chspec) \ 353*4882a593Smuzhiyun ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \ 354*4882a593Smuzhiyun (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) 355*4882a593Smuzhiyun #define CHSPEC_SB_LOWER(chspec) \ 356*4882a593Smuzhiyun ((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \ 357*4882a593Smuzhiyun (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)) 358*4882a593Smuzhiyun 359*4882a593Smuzhiyun #ifdef WL_6G_BAND 360*4882a593Smuzhiyun #define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS2G(chspec) ? WLC_BAND_2G : CHSPEC_IS5G(chspec) ? \ 361*4882a593Smuzhiyun WLC_BAND_5G : WLC_BAND_6G) 362*4882a593Smuzhiyun #else 363*4882a593Smuzhiyun #define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS2G(chspec) ? WLC_BAND_2G : WLC_BAND_5G) 364*4882a593Smuzhiyun #endif 365*4882a593Smuzhiyun 366*4882a593Smuzhiyun #define CHSPEC_BW_CHANGED(prev_chspec, curr_chspec) \ 367*4882a593Smuzhiyun (((prev_chspec) & WL_CHANSPEC_BW_MASK) != ((curr_chspec) & WL_CHANSPEC_BW_MASK)) 368*4882a593Smuzhiyun 369*4882a593Smuzhiyun #if (defined(WL_BAND6G) && !defined(WL_BAND6G_DISABLED)) 370*4882a593Smuzhiyun #define CHSPEC_IS_5G_6G(chspec) (CHSPEC_IS5G(chspec) || CHSPEC_IS6G(chspec)) 371*4882a593Smuzhiyun #define CHSPEC_IS20_5G_6G(chspec) ((((chspec) & \ 372*4882a593Smuzhiyun WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \ 373*4882a593Smuzhiyun (CHSPEC_IS5G(chspec) || CHSPEC_IS6G(chspec))) 374*4882a593Smuzhiyun #else 375*4882a593Smuzhiyun #define CHSPEC_IS_5G_6G(chspec) (CHSPEC_IS5G(chspec)) 376*4882a593Smuzhiyun #define CHSPEC_IS20_5G_6G(chspec) (CHSPEC_IS20_5G(chspec)) 377*4882a593Smuzhiyun #endif 378*4882a593Smuzhiyun 379*4882a593Smuzhiyun /** 380*4882a593Smuzhiyun * Number of chars needed for wf_chspec_ntoa() destination character buffer. 381*4882a593Smuzhiyun */ 382*4882a593Smuzhiyun #ifdef WL11BE 383*4882a593Smuzhiyun #define CHANSPEC_STR_LEN 22 384*4882a593Smuzhiyun #else 385*4882a593Smuzhiyun #define CHANSPEC_STR_LEN 20 386*4882a593Smuzhiyun #endif 387*4882a593Smuzhiyun 388*4882a593Smuzhiyun /* 389*4882a593Smuzhiyun * This function returns TRUE if both the chanspec can co-exist in PHY. 390*4882a593Smuzhiyun * Addition to primary20 channel, the function checks for side band for 2g 40 channels 391*4882a593Smuzhiyun */ 392*4882a593Smuzhiyun extern bool wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2); 393*4882a593Smuzhiyun 394*4882a593Smuzhiyun #define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\ 395*4882a593Smuzhiyun CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080) 396*4882a593Smuzhiyun 397*4882a593Smuzhiyun /* BW inequality comparisons, GE (>=), GT (>) */ 398*4882a593Smuzhiyun 399*4882a593Smuzhiyun #define CHSPEC_BW_GE(chspec, bw) (CHSPEC_BW(chspec) >= (bw)) 400*4882a593Smuzhiyun 401*4882a593Smuzhiyun #define CHSPEC_BW_GT(chspec, bw) (CHSPEC_BW(chspec) > (bw)) 402*4882a593Smuzhiyun 403*4882a593Smuzhiyun /* Legacy Chanspec defines 404*4882a593Smuzhiyun * These are the defines for the previous format of the chanspec_t 405*4882a593Smuzhiyun */ 406*4882a593Smuzhiyun #define WL_LCHANSPEC_CHAN_MASK 0x00ff 407*4882a593Smuzhiyun #define WL_LCHANSPEC_CHAN_SHIFT 0 408*4882a593Smuzhiyun 409*4882a593Smuzhiyun #define WL_LCHANSPEC_CTL_SB_MASK 0x0300 410*4882a593Smuzhiyun #define WL_LCHANSPEC_CTL_SB_SHIFT 8 411*4882a593Smuzhiyun #define WL_LCHANSPEC_CTL_SB_LOWER 0x0100 412*4882a593Smuzhiyun #define WL_LCHANSPEC_CTL_SB_UPPER 0x0200 413*4882a593Smuzhiyun #define WL_LCHANSPEC_CTL_SB_NONE 0x0300 414*4882a593Smuzhiyun 415*4882a593Smuzhiyun #define WL_LCHANSPEC_BW_MASK 0x0C00 416*4882a593Smuzhiyun #define WL_LCHANSPEC_BW_SHIFT 10 417*4882a593Smuzhiyun #define WL_LCHANSPEC_BW_10 0x0400 418*4882a593Smuzhiyun #define WL_LCHANSPEC_BW_20 0x0800 419*4882a593Smuzhiyun #define WL_LCHANSPEC_BW_40 0x0C00 420*4882a593Smuzhiyun 421*4882a593Smuzhiyun #define WL_LCHANSPEC_BAND_MASK 0xf000 422*4882a593Smuzhiyun #define WL_LCHANSPEC_BAND_SHIFT 12 423*4882a593Smuzhiyun #define WL_LCHANSPEC_BAND_5G 0x1000 424*4882a593Smuzhiyun #define WL_LCHANSPEC_BAND_2G 0x2000 425*4882a593Smuzhiyun 426*4882a593Smuzhiyun #define LCHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK)) 427*4882a593Smuzhiyun #define LCHSPEC_BAND(chspec) ((chspec) & WL_LCHANSPEC_BAND_MASK) 428*4882a593Smuzhiyun #define LCHSPEC_CTL_SB(chspec) ((chspec) & WL_LCHANSPEC_CTL_SB_MASK) 429*4882a593Smuzhiyun #define LCHSPEC_BW(chspec) ((chspec) & WL_LCHANSPEC_BW_MASK) 430*4882a593Smuzhiyun #define LCHSPEC_IS20(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20) 431*4882a593Smuzhiyun #define LCHSPEC_IS40(chspec) (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40) 432*4882a593Smuzhiyun #define LCHSPEC_IS5G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G) 433*4882a593Smuzhiyun #define LCHSPEC_IS2G(chspec) (((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G) 434*4882a593Smuzhiyun 435*4882a593Smuzhiyun #define LCHSPEC_SB_UPPER(chspec) \ 436*4882a593Smuzhiyun ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \ 437*4882a593Smuzhiyun (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)) 438*4882a593Smuzhiyun #define LCHSPEC_SB_LOWER(chspec) \ 439*4882a593Smuzhiyun ((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \ 440*4882a593Smuzhiyun (((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)) 441*4882a593Smuzhiyun 442*4882a593Smuzhiyun #define LCHSPEC_CREATE(chan, band, bw, sb) ((uint16)((chan) | (sb) | (bw) | (band))) 443*4882a593Smuzhiyun 444*4882a593Smuzhiyun #define CH20MHZ_LCHSPEC(channel) \ 445*4882a593Smuzhiyun (chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \ 446*4882a593Smuzhiyun WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ 447*4882a593Smuzhiyun WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G)) 448*4882a593Smuzhiyun 449*4882a593Smuzhiyun #define GET_ALL_EXT wf_get_all_ext 450*4882a593Smuzhiyun 451*4882a593Smuzhiyun /* 452*4882a593Smuzhiyun * WF_CHAN_FACTOR_* constants are used to calculate channel frequency 453*4882a593Smuzhiyun * given a channel number. 454*4882a593Smuzhiyun * chan_freq = chan_factor * 500Mhz + chan_number * 5 455*4882a593Smuzhiyun */ 456*4882a593Smuzhiyun 457*4882a593Smuzhiyun /** 458*4882a593Smuzhiyun * Channel Factor for the starting frequence of 2.4 GHz channels. 459*4882a593Smuzhiyun * The value corresponds to 2407 MHz. 460*4882a593Smuzhiyun */ 461*4882a593Smuzhiyun #define WF_CHAN_FACTOR_2_4_G 4814u /* 2.4 GHz band, 2407 MHz */ 462*4882a593Smuzhiyun 463*4882a593Smuzhiyun /** 464*4882a593Smuzhiyun * Channel Factor for the starting frequence of 4.9 GHz channels. 465*4882a593Smuzhiyun * The value corresponds to 4000 MHz. 466*4882a593Smuzhiyun */ 467*4882a593Smuzhiyun #define WF_CHAN_FACTOR_4_G 8000u /* 4.9 GHz band for Japan */ 468*4882a593Smuzhiyun 469*4882a593Smuzhiyun /** 470*4882a593Smuzhiyun * Channel Factor for the starting frequence of 5 GHz channels. 471*4882a593Smuzhiyun * The value corresponds to 5000 MHz. 472*4882a593Smuzhiyun */ 473*4882a593Smuzhiyun #define WF_CHAN_FACTOR_5_G 10000u /* 5 GHz band, 5000 MHz */ 474*4882a593Smuzhiyun 475*4882a593Smuzhiyun /** 476*4882a593Smuzhiyun * Channel Factor for the starting frequence of 6 GHz channels. 477*4882a593Smuzhiyun * The value corresponds to 5940 MHz. 478*4882a593Smuzhiyun */ 479*4882a593Smuzhiyun #define WF_CHAN_FACTOR_6_G 11900u /* 6 GHz band, 5950 MHz */ 480*4882a593Smuzhiyun 481*4882a593Smuzhiyun #define WLC_2G_25MHZ_OFFSET 5 /* 2.4GHz band channel offset */ 482*4882a593Smuzhiyun 483*4882a593Smuzhiyun /** 484*4882a593Smuzhiyun * No of sub-band value of the specified Mhz chanspec 485*4882a593Smuzhiyun */ 486*4882a593Smuzhiyun #define WF_NUM_SIDEBANDS_40MHZ 2u 487*4882a593Smuzhiyun #define WF_NUM_SIDEBANDS_80MHZ 4u 488*4882a593Smuzhiyun #define WF_NUM_SIDEBANDS_160MHZ 8u 489*4882a593Smuzhiyun 490*4882a593Smuzhiyun /** 491*4882a593Smuzhiyun * Return the chanspec bandwidth in MHz 492*4882a593Smuzhiyun */ 493*4882a593Smuzhiyun uint wf_bw_chspec_to_mhz(chanspec_t chspec); 494*4882a593Smuzhiyun 495*4882a593Smuzhiyun /** 496*4882a593Smuzhiyun * Return the bandwidth string for a given chanspec 497*4882a593Smuzhiyun */ 498*4882a593Smuzhiyun const char *wf_chspec_to_bw_str(chanspec_t chspec); 499*4882a593Smuzhiyun 500*4882a593Smuzhiyun /** 501*4882a593Smuzhiyun * Convert chanspec to ascii string, or formats hex of an invalid chanspec. 502*4882a593Smuzhiyun */ 503*4882a593Smuzhiyun char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf); 504*4882a593Smuzhiyun 505*4882a593Smuzhiyun /** 506*4882a593Smuzhiyun * Convert chanspec to ascii string, or returns NULL on error. 507*4882a593Smuzhiyun */ 508*4882a593Smuzhiyun char * wf_chspec_ntoa(chanspec_t chspec, char *buf); 509*4882a593Smuzhiyun 510*4882a593Smuzhiyun /** 511*4882a593Smuzhiyun * Convert ascii string to chanspec 512*4882a593Smuzhiyun */ 513*4882a593Smuzhiyun chanspec_t wf_chspec_aton(const char *a); 514*4882a593Smuzhiyun 515*4882a593Smuzhiyun /** 516*4882a593Smuzhiyun * Verify the chanspec fields are valid for a chanspec_t 517*4882a593Smuzhiyun */ 518*4882a593Smuzhiyun bool wf_chspec_malformed(chanspec_t chanspec); 519*4882a593Smuzhiyun 520*4882a593Smuzhiyun /** 521*4882a593Smuzhiyun * Verify the chanspec specifies a valid channel according to 802.11. 522*4882a593Smuzhiyun */ 523*4882a593Smuzhiyun bool wf_chspec_valid(chanspec_t chanspec); 524*4882a593Smuzhiyun 525*4882a593Smuzhiyun /** 526*4882a593Smuzhiyun * Verify that the channel is a valid 20MHz channel according to 802.11. 527*4882a593Smuzhiyun */ 528*4882a593Smuzhiyun bool wf_valid_20MHz_chan(uint channel, chanspec_band_t band); 529*4882a593Smuzhiyun 530*4882a593Smuzhiyun /** 531*4882a593Smuzhiyun * Verify that the center channel is a valid 40MHz center channel according to 802.11. 532*4882a593Smuzhiyun */ 533*4882a593Smuzhiyun bool wf_valid_40MHz_center_chan(uint center_channel, chanspec_band_t band); 534*4882a593Smuzhiyun 535*4882a593Smuzhiyun /** 536*4882a593Smuzhiyun * Verify that the center channel is a valid 80MHz center channel according to 802.11. 537*4882a593Smuzhiyun */ 538*4882a593Smuzhiyun bool wf_valid_80MHz_center_chan(uint center_channel, chanspec_band_t band); 539*4882a593Smuzhiyun 540*4882a593Smuzhiyun /** 541*4882a593Smuzhiyun * Verify that the center channel is a valid 160MHz center channel according to 802.11. 542*4882a593Smuzhiyun */ 543*4882a593Smuzhiyun bool wf_valid_160MHz_center_chan(uint center_channel, chanspec_band_t band); 544*4882a593Smuzhiyun 545*4882a593Smuzhiyun /** 546*4882a593Smuzhiyun * Verify that the center channel is a valid 240MHz center channel according to 802.11. 547*4882a593Smuzhiyun */ 548*4882a593Smuzhiyun bool wf_valid_240MHz_center_chan(uint center_channel, chanspec_band_t band); 549*4882a593Smuzhiyun 550*4882a593Smuzhiyun /** 551*4882a593Smuzhiyun * Verify that the center channel is a valid 320MHz center channel according to 802.11. 552*4882a593Smuzhiyun */ 553*4882a593Smuzhiyun bool wf_valid_320MHz_center_chan(uint center_channel, chanspec_band_t band); 554*4882a593Smuzhiyun 555*4882a593Smuzhiyun /** 556*4882a593Smuzhiyun * Create a 20MHz chanspec for the given band. 557*4882a593Smuzhiyun */ 558*4882a593Smuzhiyun chanspec_t wf_create_20MHz_chspec(uint channel, chanspec_band_t band); 559*4882a593Smuzhiyun 560*4882a593Smuzhiyun /** 561*4882a593Smuzhiyun * Returns the chanspec for a 40MHz channel given the primary 20MHz channel number, 562*4882a593Smuzhiyun * the center channel number, and the band. 563*4882a593Smuzhiyun */ 564*4882a593Smuzhiyun chanspec_t wf_create_40MHz_chspec(uint primary_channel, uint center_channel, 565*4882a593Smuzhiyun chanspec_band_t band); 566*4882a593Smuzhiyun 567*4882a593Smuzhiyun /** 568*4882a593Smuzhiyun * Returns the chanspec for a 40MHz channel given the primary 20MHz channel number, 569*4882a593Smuzhiyun * the sub-band for the primary 20MHz channel, and the band. 570*4882a593Smuzhiyun */ 571*4882a593Smuzhiyun chanspec_t wf_create_40MHz_chspec_primary_sb(uint primary_channel, 572*4882a593Smuzhiyun chanspec_subband_t primary_subband, 573*4882a593Smuzhiyun chanspec_band_t band); 574*4882a593Smuzhiyun /** 575*4882a593Smuzhiyun * Returns the chanspec for an 80MHz channel given the primary 20MHz channel number, 576*4882a593Smuzhiyun * the center channel number, and the band. 577*4882a593Smuzhiyun */ 578*4882a593Smuzhiyun chanspec_t wf_create_80MHz_chspec(uint primary_channel, uint center_channel, 579*4882a593Smuzhiyun chanspec_band_t band); 580*4882a593Smuzhiyun 581*4882a593Smuzhiyun /** 582*4882a593Smuzhiyun * Returns the chanspec for an 160MHz channel given the primary 20MHz channel number, 583*4882a593Smuzhiyun * the center channel number, and the band. 584*4882a593Smuzhiyun */ 585*4882a593Smuzhiyun chanspec_t wf_create_160MHz_chspec(uint primary_channel, uint center_channel, 586*4882a593Smuzhiyun chanspec_band_t band); 587*4882a593Smuzhiyun 588*4882a593Smuzhiyun /** 589*4882a593Smuzhiyun * Returns the chanspec for an 240MHz channel given the primary 20MHz channel number, 590*4882a593Smuzhiyun * the center channel number, and the band. 591*4882a593Smuzhiyun */ 592*4882a593Smuzhiyun chanspec_t wf_create_240MHz_chspec(uint primary_channel, uint center_channel, 593*4882a593Smuzhiyun chanspec_band_t band); 594*4882a593Smuzhiyun 595*4882a593Smuzhiyun /** 596*4882a593Smuzhiyun * Returns the chanspec for an 320MHz channel given the primary 20MHz channel number, 597*4882a593Smuzhiyun * the center channel number, and the band. 598*4882a593Smuzhiyun */ 599*4882a593Smuzhiyun chanspec_t wf_create_320MHz_chspec(uint primary_channel, uint center_channel, 600*4882a593Smuzhiyun chanspec_band_t band); 601*4882a593Smuzhiyun 602*4882a593Smuzhiyun /** 603*4882a593Smuzhiyun * Returns the chanspec for an 80+80MHz channel given the primary 20MHz channel number, 604*4882a593Smuzhiyun * the center channel numbers for each frequency segment, and the band. 605*4882a593Smuzhiyun */ 606*4882a593Smuzhiyun chanspec_t wf_create_8080MHz_chspec(uint primary_channel, uint chan0, uint chan1, 607*4882a593Smuzhiyun chanspec_band_t band); 608*4882a593Smuzhiyun 609*4882a593Smuzhiyun /** 610*4882a593Smuzhiyun * Returns the chanspec for an 160+160MHz channel given the primary 20MHz channel number, 611*4882a593Smuzhiyun * the center channel numbers for each frequency segment, and the band. 612*4882a593Smuzhiyun */ 613*4882a593Smuzhiyun chanspec_t wf_create_160160MHz_chspec(uint primary_channel, uint chan0, uint chan1, 614*4882a593Smuzhiyun chanspec_band_t band); 615*4882a593Smuzhiyun /** 616*4882a593Smuzhiyun * Returns the chanspec given the primary 20MHz channel number, 617*4882a593Smuzhiyun * the center channel number, channel width, and the band. 618*4882a593Smuzhiyun * 619*4882a593Smuzhiyun * The channel width must be 20, 40, 80, or 160 MHz. 620*4882a593Smuzhiyun */ 621*4882a593Smuzhiyun chanspec_t wf_create_chspec(uint primary_channel, uint center_channel, 622*4882a593Smuzhiyun chanspec_bw_t bw, chanspec_band_t band); 623*4882a593Smuzhiyun 624*4882a593Smuzhiyun /** 625*4882a593Smuzhiyun * Returns the chanspec given the primary 20MHz channel number, 626*4882a593Smuzhiyun * channel width, and the band. 627*4882a593Smuzhiyun */ 628*4882a593Smuzhiyun chanspec_t wf_create_chspec_from_primary(uint primary_channel, chanspec_bw_t bw, 629*4882a593Smuzhiyun chanspec_band_t band); 630*4882a593Smuzhiyun 631*4882a593Smuzhiyun /** 632*4882a593Smuzhiyun * Returns the chanspec given the index of primary 20MHz channel within whole 633*4882a593Smuzhiyun * channel, the center channel number, channel width, and the band. 634*4882a593Smuzhiyun * 635*4882a593Smuzhiyun * The channel width must be 20, 40, 80, or 160 MHz. 636*4882a593Smuzhiyun */ 637*4882a593Smuzhiyun chanspec_t wf_create_chspec_sb(uint sb, uint center_channel, chanspec_bw_t bw, 638*4882a593Smuzhiyun chanspec_band_t band); 639*4882a593Smuzhiyun 640*4882a593Smuzhiyun /** 641*4882a593Smuzhiyun * Returns the chanspec for an 160+160MHz channel given the index of primary 20MHz 642*4882a593Smuzhiyun * channel within whole channel pair (0-3 if within chan0, 4-7 if within chan1), 643*4882a593Smuzhiyun * the center channel numbers for each frequency segment, and the band. 644*4882a593Smuzhiyun */ 645*4882a593Smuzhiyun chanspec_t wf_create_160160MHz_chspec_sb(uint sb, uint chan0, uint chan1, 646*4882a593Smuzhiyun chanspec_band_t band); 647*4882a593Smuzhiyun 648*4882a593Smuzhiyun /** 649*4882a593Smuzhiyun * Return the primary 20MHz channel. 650*4882a593Smuzhiyun */ 651*4882a593Smuzhiyun uint8 wf_chspec_primary20_chan(chanspec_t chspec); 652*4882a593Smuzhiyun 653*4882a593Smuzhiyun /* alias for old function name */ 654*4882a593Smuzhiyun #define wf_chspec_ctlchan(c) wf_chspec_primary20_chan(c) 655*4882a593Smuzhiyun 656*4882a593Smuzhiyun /** 657*4882a593Smuzhiyun * Return the primary 20MHz chanspec of a given chanspec 658*4882a593Smuzhiyun */ 659*4882a593Smuzhiyun chanspec_t wf_chspec_primary20_chspec(chanspec_t chspec); 660*4882a593Smuzhiyun 661*4882a593Smuzhiyun /* alias for old function name */ 662*4882a593Smuzhiyun #define wf_chspec_ctlchspec(c) wf_chspec_primary20_chspec(c) 663*4882a593Smuzhiyun 664*4882a593Smuzhiyun /** 665*4882a593Smuzhiyun * Return the primary 40MHz chanspec for a 40MHz or wider channel 666*4882a593Smuzhiyun */ 667*4882a593Smuzhiyun chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec); 668*4882a593Smuzhiyun 669*4882a593Smuzhiyun /** 670*4882a593Smuzhiyun * Return the channel number for a given frequency and base frequency 671*4882a593Smuzhiyun */ 672*4882a593Smuzhiyun int wf_mhz2channel(uint freq, uint start_factor); 673*4882a593Smuzhiyun 674*4882a593Smuzhiyun /** 675*4882a593Smuzhiyun * Return the center frequency in MHz of the given channel and base frequency. 676*4882a593Smuzhiyun */ 677*4882a593Smuzhiyun int wf_channel2mhz(uint channel, uint start_factor); 678*4882a593Smuzhiyun 679*4882a593Smuzhiyun /** 680*4882a593Smuzhiyun * Returns the chanspec 80Mhz channel corresponding to the following input 681*4882a593Smuzhiyun * parameters 682*4882a593Smuzhiyun * 683*4882a593Smuzhiyun * primary_channel - primary 20Mhz channel 684*4882a593Smuzhiyun * center_channel - center frequecny of the 80Mhz channel 685*4882a593Smuzhiyun * 686*4882a593Smuzhiyun * The center_channel can be one of {42, 58, 106, 122, 138, 155} 687*4882a593Smuzhiyun * 688*4882a593Smuzhiyun * returns INVCHANSPEC in case of error 689*4882a593Smuzhiyun */ 690*4882a593Smuzhiyun extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel); 691*4882a593Smuzhiyun 692*4882a593Smuzhiyun /** 693*4882a593Smuzhiyun * Convert ctl chan and bw to chanspec 694*4882a593Smuzhiyun * 695*4882a593Smuzhiyun * @param ctl_ch channel 696*4882a593Smuzhiyun * @param bw bandwidth 697*4882a593Smuzhiyun * 698*4882a593Smuzhiyun * @return > 0 if successful or 0 otherwise 699*4882a593Smuzhiyun * 700*4882a593Smuzhiyun */ 701*4882a593Smuzhiyun extern uint16 wf_channel2chspec(uint ctl_ch, uint bw); 702*4882a593Smuzhiyun 703*4882a593Smuzhiyun /* 704*4882a593Smuzhiyun * Returns the 80+80 MHz chanspec corresponding to the following input parameters 705*4882a593Smuzhiyun * 706*4882a593Smuzhiyun * primary_20mhz - Primary 20 MHz channel 707*4882a593Smuzhiyun * chan0_80MHz - center channel number of one frequency segment 708*4882a593Smuzhiyun * chan1_80MHz - center channel number of the other frequency segment 709*4882a593Smuzhiyun * 710*4882a593Smuzhiyun * Parameters chan0_80MHz and chan1_80MHz are channel numbers in {42, 58, 106, 122, 138, 155}. 711*4882a593Smuzhiyun * The primary channel must be contained in one of the 80MHz channels. This routine 712*4882a593Smuzhiyun * will determine which frequency segment is the primary 80 MHz segment. 713*4882a593Smuzhiyun * 714*4882a593Smuzhiyun * Returns INVCHANSPEC in case of error. 715*4882a593Smuzhiyun * 716*4882a593Smuzhiyun * Refer to 802.11-2016 section 22.3.14 "Channelization". 717*4882a593Smuzhiyun */ 718*4882a593Smuzhiyun extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz, 719*4882a593Smuzhiyun uint8 chan0_80Mhz, uint8 chan1_80Mhz); 720*4882a593Smuzhiyun 721*4882a593Smuzhiyun /** 722*4882a593Smuzhiyun * Returns the center channel of the primary 80 MHz sub-band of the provided chanspec 723*4882a593Smuzhiyun * 724*4882a593Smuzhiyun * @param chspec input chanspec 725*4882a593Smuzhiyun * 726*4882a593Smuzhiyun * @return center channel number of the primary 80MHz sub-band of the input. 727*4882a593Smuzhiyun * Will return the center channel of an input 80MHz chspec. 728*4882a593Smuzhiyun * Will return INVCHANNEL if the chspec is malformed or less than 80MHz bw. 729*4882a593Smuzhiyun */ 730*4882a593Smuzhiyun extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec); 731*4882a593Smuzhiyun 732*4882a593Smuzhiyun /** 733*4882a593Smuzhiyun * Returns the center channel of the secondary 80 MHz sub-band of the provided chanspec 734*4882a593Smuzhiyun * 735*4882a593Smuzhiyun * @param chspec input chanspec 736*4882a593Smuzhiyun * 737*4882a593Smuzhiyun * @return center channel number of the secondary 80MHz sub-band of the input. 738*4882a593Smuzhiyun * Will return INVCHANNEL if the chspec is malformed or bw is not greater than 80MHz. 739*4882a593Smuzhiyun */ 740*4882a593Smuzhiyun extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec); 741*4882a593Smuzhiyun 742*4882a593Smuzhiyun /** 743*4882a593Smuzhiyun * Returns the chanspec for the primary 80MHz sub-band of an 160MHz or 80+80 channel 744*4882a593Smuzhiyun * 745*4882a593Smuzhiyun * @param chspec input chanspec 746*4882a593Smuzhiyun * 747*4882a593Smuzhiyun * @return An 80MHz chanspec describing the primary 80MHz sub-band of the input. 748*4882a593Smuzhiyun * Will return an input 80MHz chspec as is. 749*4882a593Smuzhiyun * Will return INVCHANSPEC if the chspec is malformed or less than 80MHz bw. 750*4882a593Smuzhiyun */ 751*4882a593Smuzhiyun extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec); 752*4882a593Smuzhiyun 753*4882a593Smuzhiyun /** 754*4882a593Smuzhiyun * Returns the chanspec for the secondary 80MHz sub-band of an 160MHz or 80+80 channel 755*4882a593Smuzhiyun * The sideband in the chanspec is always set to WL_CHANSPEC_CTL_SB_LL since this sub-band 756*4882a593Smuzhiyun * does not contain the primary 20MHz channel. 757*4882a593Smuzhiyun * 758*4882a593Smuzhiyun * @param chspec input chanspec 759*4882a593Smuzhiyun * 760*4882a593Smuzhiyun * @return An 80MHz chanspec describing the secondary 80MHz sub-band of the input. 761*4882a593Smuzhiyun * Will return INVCHANSPEC if the chspec is malformed or bw is not greater than 80MHz. 762*4882a593Smuzhiyun */ 763*4882a593Smuzhiyun extern chanspec_t wf_chspec_secondary80_chspec(chanspec_t chspec); 764*4882a593Smuzhiyun 765*4882a593Smuzhiyun /** 766*4882a593Smuzhiyun * Returns the center channel of the primary 160MHz sub-band of the provided chanspec 767*4882a593Smuzhiyun * 768*4882a593Smuzhiyun * @param chspec input chanspec 769*4882a593Smuzhiyun * 770*4882a593Smuzhiyun * @return center channel number of the primary 160MHz sub-band of the input. 771*4882a593Smuzhiyun * Will return the center channel of an input 160MHz chspec. 772*4882a593Smuzhiyun * Will return INVCHANNEL if the chspec is malformed or less than 160MHz bw. 773*4882a593Smuzhiyun */ 774*4882a593Smuzhiyun extern uint8 wf_chspec_primary160_channel(chanspec_t chanspec); 775*4882a593Smuzhiyun 776*4882a593Smuzhiyun /** 777*4882a593Smuzhiyun * Returns the chanspec for the primary 160MHz sub-band of an 320MHz channel 778*4882a593Smuzhiyun * 779*4882a593Smuzhiyun * @param chspec input chanspec 780*4882a593Smuzhiyun * 781*4882a593Smuzhiyun * @return An 160MHz chanspec describing the primary 160MHz sub-band of the input. 782*4882a593Smuzhiyun * Will return an input 160MHz chspec as is. 783*4882a593Smuzhiyun * Will return INVCHANSPEC if the chspec is malformed or less than 160MHz bw. 784*4882a593Smuzhiyun */ 785*4882a593Smuzhiyun extern chanspec_t wf_chspec_primary160_chspec(chanspec_t chspec); 786*4882a593Smuzhiyun 787*4882a593Smuzhiyun /* 788*4882a593Smuzhiyun * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels 789*4882a593Smuzhiyun * 790*4882a593Smuzhiyun * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1 791*4882a593Smuzhiyun */ 792*4882a593Smuzhiyun extern void wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch); 793*4882a593Smuzhiyun 794*4882a593Smuzhiyun /* wf_chanspec_iter_... iterator API is deprecated. Use wlc_clm_chanspec_iter_... API instead */ 795*4882a593Smuzhiyun 796*4882a593Smuzhiyun struct wf_iter_range { 797*4882a593Smuzhiyun uint8 start; 798*4882a593Smuzhiyun uint8 end; 799*4882a593Smuzhiyun }; 800*4882a593Smuzhiyun 801*4882a593Smuzhiyun /* Internal structure for wf_chanspec_iter_* functions. 802*4882a593Smuzhiyun * Do not directly access the members. Only use the related 803*4882a593Smuzhiyun * functions to query and manipulate the structure. 804*4882a593Smuzhiyun */ 805*4882a593Smuzhiyun typedef struct chanspec_iter { 806*4882a593Smuzhiyun uint8 state; 807*4882a593Smuzhiyun chanspec_t chanspec; 808*4882a593Smuzhiyun chanspec_band_t band; 809*4882a593Smuzhiyun chanspec_bw_t bw; 810*4882a593Smuzhiyun struct wf_iter_range range; 811*4882a593Smuzhiyun union { 812*4882a593Smuzhiyun uint8 range_id; 813*4882a593Smuzhiyun struct { 814*4882a593Smuzhiyun uint8 ch0; 815*4882a593Smuzhiyun uint8 ch1; 816*4882a593Smuzhiyun }; 817*4882a593Smuzhiyun }; 818*4882a593Smuzhiyun } wf_chanspec_iter_t; 819*4882a593Smuzhiyun 820*4882a593Smuzhiyun /** 821*4882a593Smuzhiyun * Initialize a chanspec iteration structure. 822*4882a593Smuzhiyun * The parameters define the set of chanspecs to generate in the iteration. 823*4882a593Smuzhiyun * After initialization wf_chanspec_iter_current() will return the first chanspec 824*4882a593Smuzhiyun * in the set. A call to wf_chanspec_iter_next() will advance the interation 825*4882a593Smuzhiyun * to the next chanspec in the set. 826*4882a593Smuzhiyun * 827*4882a593Smuzhiyun * Example use: 828*4882a593Smuzhiyun * wf_chanspec_iter_t iter; 829*4882a593Smuzhiyun * chanspec_t chanspec; 830*4882a593Smuzhiyun * 831*4882a593Smuzhiyun * wf_chanspec_iter_init(&iter, band, bw); 832*4882a593Smuzhiyun * 833*4882a593Smuzhiyun * while (wf_chanspec_iter_next(&iter, &chanspec)) { 834*4882a593Smuzhiyun * ... do some work ... 835*4882a593Smuzhiyun * } 836*4882a593Smuzhiyun * 837*4882a593Smuzhiyun * @param iter pointer to a wf_chanspec_iter_t structure to initialize 838*4882a593Smuzhiyun * @param band chanspec_band_t value specifying the band of interest 839*4882a593Smuzhiyun * @param bw chanspec_bw_t value specifying the bandwidth of interest, 840*4882a593Smuzhiyun * or INVCHANSPEC to specify all bandwidths 841*4882a593Smuzhiyun * 842*4882a593Smuzhiyun * @return a success value, FALSE on error, or TRUE if OK 843*4882a593Smuzhiyun */ 844*4882a593Smuzhiyun bool wf_chanspec_iter_init(wf_chanspec_iter_t *iter, chanspec_band_t band, chanspec_bw_t bw); 845*4882a593Smuzhiyun 846*4882a593Smuzhiyun /** 847*4882a593Smuzhiyun * Advance the iteration to the next chanspec in the set. 848*4882a593Smuzhiyun * 849*4882a593Smuzhiyun * @param iter pointer to a wf_chanspec_iter_t structure 850*4882a593Smuzhiyun * @param chspec pointer to storage for the next chanspec. Return value will be INVCHANSPEC 851*4882a593Smuzhiyun * if the iteration ended. Pass in NULL if return value is not desired. 852*4882a593Smuzhiyun * 853*4882a593Smuzhiyun * @return a success value, TRUE if there was another chanspec in the iteration, FALSE if not 854*4882a593Smuzhiyun */ 855*4882a593Smuzhiyun bool wf_chanspec_iter_next(wf_chanspec_iter_t *iter, chanspec_t *chspec); 856*4882a593Smuzhiyun 857*4882a593Smuzhiyun /** 858*4882a593Smuzhiyun * Return the current chanspec of the iteration. 859*4882a593Smuzhiyun * 860*4882a593Smuzhiyun * @param iter pointer to a wf_chanspec_iter_t structure 861*4882a593Smuzhiyun * 862*4882a593Smuzhiyun * @return the current chanspec_t 863*4882a593Smuzhiyun */ 864*4882a593Smuzhiyun chanspec_t wf_chanspec_iter_current(wf_chanspec_iter_t *iter); 865*4882a593Smuzhiyun 866*4882a593Smuzhiyun /* Populates array with all 20MHz side bands of a given chanspec_t in the following order: 867*4882a593Smuzhiyun * primary20, ext20, two ext40s, four ext80s. 868*4882a593Smuzhiyun * 'chspec' is the chanspec of interest 869*4882a593Smuzhiyun * 'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec 870*4882a593Smuzhiyun * 871*4882a593Smuzhiyun * Works with 20, 40, 80 and 160MHz chspec 872*4882a593Smuzhiyun */ 873*4882a593Smuzhiyun 874*4882a593Smuzhiyun extern void wf_get_all_ext(chanspec_t chspec, uint8 *chan_ptr); 875*4882a593Smuzhiyun 876*4882a593Smuzhiyun /* 877*4882a593Smuzhiyun * Given two chanspecs, returns true if they overlap. 878*4882a593Smuzhiyun * (Overlap: At least one 20MHz subband is common between the two chanspecs provided) 879*4882a593Smuzhiyun */ 880*4882a593Smuzhiyun extern bool wf_chspec_overlap(chanspec_t chspec0, chanspec_t chspec1); 881*4882a593Smuzhiyun 882*4882a593Smuzhiyun extern uint8 channel_bw_to_width(chanspec_t chspec); 883*4882a593Smuzhiyun 884*4882a593Smuzhiyun uint8 wf_chspec_320_id2cch(chanspec_t chanspec); 885*4882a593Smuzhiyun 886*4882a593Smuzhiyun uint8 wf_chspec_240_id2cch(chanspec_t chanspec); 887*4882a593Smuzhiyun 888*4882a593Smuzhiyun #endif /* _bcmwifi_channels_h_ */ 889