1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Misc utility routines for WL and Apps
4  * This header file housing the define and function prototype use by
5  * both the wl driver, tools & Apps.
6  *
7  * Copyright (C) 1999-2017, Broadcom Corporation
8  *
9  *      Unless you and Broadcom execute a separate written software license
10  * agreement governing use of this software, this software is licensed to you
11  * under the terms of the GNU General Public License version 2 (the "GPL"),
12  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
13  * following added to such license:
14  *
15  *      As a special exception, the copyright holders of this software give you
16  * permission to link this software with independent modules, and to copy and
17  * distribute the resulting executable under terms of your choice, provided that
18  * you also meet, for each linked independent module, the terms and conditions of
19  * the license of that module.  An independent module is a module which is not
20  * derived from this software.  The special exception does not apply to any
21  * modifications of the software.
22  *
23  *      Notwithstanding the above, under no circumstances may you combine this
24  * software in any way with any other Broadcom software provided under a license
25  * other than the GPL, without Broadcom's express prior written consent.
26  *
27  *
28  * <<Broadcom-WL-IPTag/Open:>>
29  *
30  * $Id: bcmwifi_channels.h 612483 2016-01-14 03:44:27Z $
31  */
32 
33 #ifndef	_bcmwifi_channels_h_
34 #define	_bcmwifi_channels_h_
35 
36 
37 /* A chanspec holds the channel number, band, bandwidth and control sideband */
38 typedef uint16 chanspec_t;
39 
40 /* channel defines */
41 #define CH_UPPER_SB			0x01
42 #define CH_LOWER_SB			0x02
43 #define CH_EWA_VALID			0x04
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 #define CH_MAX_2G_CHANNEL		14	/* Max channel in 2G band */
50 
51 /* maximum # channels the s/w supports */
52 #define MAXCHANNEL		224	/* max # supported channels. The max channel no is above,
53 					 * this is that + 1 rounded up to a multiple of NBBY (8).
54 					 * DO NOT MAKE it > 255: channels are uint8's all over
55 					 */
56 #define MAXCHANNEL_NUM	(MAXCHANNEL - 1)	/* max channel number */
57 
58 /* channel bitvec */
59 typedef struct {
60 	uint8   vec[MAXCHANNEL/8];   /* bitvec of channels */
61 } chanvec_t;
62 
63 /* make sure channel num is within valid range */
64 #define CH_NUM_VALID_RANGE(ch_num) ((ch_num) > 0 && (ch_num) <= MAXCHANNEL_NUM)
65 
66 #define CHSPEC_CTLOVLP(sp1, sp2, sep)	\
67 	(ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep))
68 
69 /* All builds use the new 11ac ratespec/chanspec */
70 #undef  D11AC_IOTYPES
71 #define D11AC_IOTYPES
72 
73 #define WL_CHANSPEC_CHAN_MASK		0x00ff
74 #define WL_CHANSPEC_CHAN_SHIFT		0
75 #define WL_CHANSPEC_CHAN1_MASK		0x000f
76 #define WL_CHANSPEC_CHAN1_SHIFT		0
77 #define WL_CHANSPEC_CHAN2_MASK		0x00f0
78 #define WL_CHANSPEC_CHAN2_SHIFT		4
79 
80 #define WL_CHANSPEC_CTL_SB_MASK		0x0700
81 #define WL_CHANSPEC_CTL_SB_SHIFT	8
82 #define WL_CHANSPEC_CTL_SB_LLL		0x0000
83 #define WL_CHANSPEC_CTL_SB_LLU		0x0100
84 #define WL_CHANSPEC_CTL_SB_LUL		0x0200
85 #define WL_CHANSPEC_CTL_SB_LUU		0x0300
86 #define WL_CHANSPEC_CTL_SB_ULL		0x0400
87 #define WL_CHANSPEC_CTL_SB_ULU		0x0500
88 #define WL_CHANSPEC_CTL_SB_UUL		0x0600
89 #define WL_CHANSPEC_CTL_SB_UUU		0x0700
90 #define WL_CHANSPEC_CTL_SB_LL		WL_CHANSPEC_CTL_SB_LLL
91 #define WL_CHANSPEC_CTL_SB_LU		WL_CHANSPEC_CTL_SB_LLU
92 #define WL_CHANSPEC_CTL_SB_UL		WL_CHANSPEC_CTL_SB_LUL
93 #define WL_CHANSPEC_CTL_SB_UU		WL_CHANSPEC_CTL_SB_LUU
94 #define WL_CHANSPEC_CTL_SB_L		WL_CHANSPEC_CTL_SB_LLL
95 #define WL_CHANSPEC_CTL_SB_U		WL_CHANSPEC_CTL_SB_LLU
96 #define WL_CHANSPEC_CTL_SB_LOWER	WL_CHANSPEC_CTL_SB_LLL
97 #define WL_CHANSPEC_CTL_SB_UPPER	WL_CHANSPEC_CTL_SB_LLU
98 #define WL_CHANSPEC_CTL_SB_NONE		WL_CHANSPEC_CTL_SB_LLL
99 
100 #define WL_CHANSPEC_BW_MASK		0x3800
101 #define WL_CHANSPEC_BW_SHIFT		11
102 #define WL_CHANSPEC_BW_5		0x0000
103 #define WL_CHANSPEC_BW_10		0x0800
104 #define WL_CHANSPEC_BW_20		0x1000
105 #define WL_CHANSPEC_BW_40		0x1800
106 #define WL_CHANSPEC_BW_80		0x2000
107 #define WL_CHANSPEC_BW_160		0x2800
108 #define WL_CHANSPEC_BW_8080		0x3000
109 #define WL_CHANSPEC_BW_2P5		0x3800
110 
111 #define WL_CHANSPEC_BAND_MASK		0xc000
112 #define WL_CHANSPEC_BAND_SHIFT		14
113 #define WL_CHANSPEC_BAND_2G		0x0000
114 #define WL_CHANSPEC_BAND_3G		0x4000
115 #define WL_CHANSPEC_BAND_4G		0x8000
116 #define WL_CHANSPEC_BAND_5G		0xc000
117 #define INVCHANSPEC			255
118 #define MAX_CHANSPEC				0xFFFF
119 
120 #define WL_CHANNEL_BAND(ch) (((ch) <= CH_MAX_2G_CHANNEL) ? \
121 	WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)
122 
123 /* channel defines */
124 #define LOWER_20_SB(channel)		(((channel) > CH_10MHZ_APART) ? \
125 					((channel) - CH_10MHZ_APART) : 0)
126 #define UPPER_20_SB(channel)		(((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \
127 					((channel) + CH_10MHZ_APART) : 0)
128 
129 #define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0)
130 #define UU_20_SB(channel) 	(((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \
131 				((channel) + 3 * CH_10MHZ_APART) : 0)
132 #define LU_20_SB(channel) LOWER_20_SB(channel)
133 #define UL_20_SB(channel) UPPER_20_SB(channel)
134 
135 #define LOWER_40_SB(channel)		((channel) - CH_20MHZ_APART)
136 #define UPPER_40_SB(channel)		((channel) + CH_20MHZ_APART)
137 #define CHSPEC_WLCBANDUNIT(chspec)	(CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX)
138 #define CH20MHZ_CHSPEC(channel)		(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \
139 					(((channel) <= CH_MAX_2G_CHANNEL) ? \
140 					WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
141 #define CH2P5MHZ_CHSPEC(channel)	(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_2P5 | \
142 						(((channel) <= CH_MAX_2G_CHANNEL) ? \
143 						WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
144 #define CH5MHZ_CHSPEC(channel)		(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_5 | \
145 						(((channel) <= CH_MAX_2G_CHANNEL) ? \
146 						WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
147 #define CH10MHZ_CHSPEC(channel)		(chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_10 | \
148 						(((channel) <= CH_MAX_2G_CHANNEL) ? \
149 						WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
150 #define NEXT_20MHZ_CHAN(channel)	(((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \
151 					((channel) + CH_20MHZ_APART) : 0)
152 #define CH40MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
153 					((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \
154 					((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
155 					WL_CHANSPEC_BAND_5G))
156 #define CH80MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
157 					((channel) | (ctlsb) | \
158 					 WL_CHANSPEC_BW_80 | WL_CHANSPEC_BAND_5G)
159 #define CH160MHZ_CHSPEC(channel, ctlsb)	(chanspec_t) \
160 					((channel) | (ctlsb) | \
161 					 WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G)
162 #define CHBW_CHSPEC(bw, channel)	(chanspec_t)((chanspec_t)(channel) | (bw) | \
163 							(((channel) <= CH_MAX_2G_CHANNEL) ? \
164 							WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G))
165 
166 /* simple MACROs to get different fields of chanspec */
167 #ifdef WL11AC_80P80
168 #define CHSPEC_CHANNEL(chspec)	wf_chspec_channel(chspec)
169 #else
170 #define CHSPEC_CHANNEL(chspec)	((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK))
171 #endif
172 #define CHSPEC_CHAN1(chspec)	((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT
173 #define CHSPEC_CHAN2(chspec)	((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT
174 #define CHSPEC_BAND(chspec)		((chspec) & WL_CHANSPEC_BAND_MASK)
175 #define CHSPEC_CTL_SB(chspec)	((chspec) & WL_CHANSPEC_CTL_SB_MASK)
176 #define CHSPEC_BW(chspec)		((chspec) & WL_CHANSPEC_BW_MASK)
177 
178 #ifdef WL11N_20MHZONLY
179 #ifdef WL11ULB
180 #define CHSPEC_IS2P5(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5)
181 #define CHSPEC_IS5(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5)
182 #define CHSPEC_IS10(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
183 #else
184 #define CHSPEC_IS2P5(chspec)	0
185 #define CHSPEC_IS5(chspec)	0
186 #define CHSPEC_IS10(chspec)	0
187 #endif
188 #define CHSPEC_IS20(chspec)	1
189 #define CHSPEC_IS20_2G(chspec)	((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \
190 								CHSPEC_IS2G(chspec))
191 #ifndef CHSPEC_IS40
192 #define CHSPEC_IS40(chspec)	0
193 #endif
194 #ifndef CHSPEC_IS80
195 #define CHSPEC_IS80(chspec)	0
196 #endif
197 #ifndef CHSPEC_IS160
198 #define CHSPEC_IS160(chspec)	0
199 #endif
200 #ifndef CHSPEC_IS8080
201 #define CHSPEC_IS8080(chspec)	0
202 #endif
203 #define BW_LE20(bw)		TRUE
204 #define CHSPEC_ISLE20(chspec)	TRUE
205 #else /* !WL11N_20MHZONLY */
206 
207 #define CHSPEC_IS2P5(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5)
208 #define CHSPEC_IS5(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5)
209 #define CHSPEC_IS10(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
210 #define CHSPEC_IS20(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
211 #define CHSPEC_IS20_5G(chspec)	((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \
212 								CHSPEC_IS5G(chspec))
213 #ifndef CHSPEC_IS40
214 #define CHSPEC_IS40(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
215 #endif
216 #ifndef CHSPEC_IS80
217 #define CHSPEC_IS80(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80)
218 #endif
219 #ifndef CHSPEC_IS160
220 #define CHSPEC_IS160(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160)
221 #endif
222 #ifndef CHSPEC_IS8080
223 #define CHSPEC_IS8080(chspec)	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080)
224 #endif
225 
226 #ifdef WL11ULB
227 #define BW_LT20(bw)		(((bw) == WL_CHANSPEC_BW_2P5) || \
228 				((bw) == WL_CHANSPEC_BW_5) || \
229 				((bw) == WL_CHANSPEC_BW_10))
230 #define CHSPEC_BW_LT20(chspec)	(BW_LT20(CHSPEC_BW(chspec)))
231 /* This MACRO is strictly to avoid abandons in existing code with ULB feature and is in no way
232  * optimial to use. Should be replaced with CHSPEC_BW_LE() instead
233  */
234 #define BW_LE20(bw)		(((bw) == WL_CHANSPEC_BW_2P5) || \
235 				((bw) == WL_CHANSPEC_BW_5) || \
236 				((bw) == WL_CHANSPEC_BW_10) || \
237 				((bw) == WL_CHANSPEC_BW_20))
238 #define CHSPEC_ISLE20(chspec)	(BW_LE20(CHSPEC_BW(chspec)))
239 
240 #else /* WL11ULB */
241 #define BW_LE20(bw)		((bw) == WL_CHANSPEC_BW_20)
242 #define CHSPEC_ISLE20(chspec)	(CHSPEC_IS20(chspec))
243 #endif /* WL11ULB */
244 #endif /* !WL11N_20MHZONLY */
245 
246 #define BW_LE40(bw)		(BW_LE20(bw) || ((bw) == WL_CHANSPEC_BW_40))
247 #define BW_LE80(bw)		(BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80))
248 #define BW_LE160(bw)		(BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160))
249 #define CHSPEC_BW_LE20(chspec)	(BW_LE20(CHSPEC_BW(chspec)))
250 #define CHSPEC_IS5G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
251 #define CHSPEC_IS2G(chspec)	(((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
252 #define CHSPEC_SB_UPPER(chspec)	\
253 	((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) && \
254 	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
255 #define CHSPEC_SB_LOWER(chspec)	\
256 	((((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) && \
257 	(((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40))
258 #define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G)
259 
260 /**
261  * Number of chars needed for wf_chspec_ntoa() destination character buffer.
262  */
263 #define CHANSPEC_STR_LEN    20
264 
265 
266 #define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\
267 	CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080)
268 
269 /* BW inequality comparisons, LE (<=), GE (>=), LT (<), GT (>), comparisons can be made
270 * as simple numeric comparisons, with the exception that 160 is the same BW as 80+80,
271 * but have different numeric values; (WL_CHANSPEC_BW_160 < WL_CHANSPEC_BW_8080).
272 *
273 * The LT/LE/GT/GE macros check first checks whether both chspec bandwidth and bw are 160 wide.
274 * If both chspec bandwidth and bw is not 160 wide, then the comparison is made.
275 */
276 #ifdef WL11ULB
277 #define CHSPEC_BW_GE(chspec, bw) \
278 	(((CHSPEC_IS_BW_160_WIDE(chspec) &&\
279 	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
280 	(CHSPEC_BW(chspec) >= (bw))) && \
281 	(!(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
282 #else /* WL11ULB */
283 #define CHSPEC_BW_GE(chspec, bw) \
284 		((CHSPEC_IS_BW_160_WIDE(chspec) &&\
285 		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
286 		(CHSPEC_BW(chspec) >= (bw)))
287 #endif /* WL11ULB */
288 
289 #ifdef WL11ULB
290 #define CHSPEC_BW_LE(chspec, bw) \
291 	(((CHSPEC_IS_BW_160_WIDE(chspec) &&\
292 	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
293 	(CHSPEC_BW(chspec) <= (bw))) || \
294 	(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5))
295 #else /* WL11ULB */
296 #define CHSPEC_BW_LE(chspec, bw) \
297 		((CHSPEC_IS_BW_160_WIDE(chspec) &&\
298 		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\
299 		(CHSPEC_BW(chspec) <= (bw)))
300 #endif /* WL11ULB */
301 
302 #ifdef WL11ULB
303 #define CHSPEC_BW_GT(chspec, bw) \
304 	((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
305 	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
306 	(CHSPEC_BW(chspec) > (bw))) && \
307 	(CHSPEC_BW(chspec) != WL_CHANSPEC_BW_2P5))
308 #else /* WL11ULB */
309 #define CHSPEC_BW_GT(chspec, bw) \
310 		(!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
311 		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
312 		(CHSPEC_BW(chspec) > (bw)))
313 #endif /* WL11ULB */
314 
315 #ifdef WL11ULB
316 #define CHSPEC_BW_LT(chspec, bw) \
317 	((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
318 	((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
319 	(CHSPEC_BW(chspec) < (bw))) || \
320 	((CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5)))
321 #else /* WL11ULB */
322 #define CHSPEC_BW_LT(chspec, bw) \
323 		(!(CHSPEC_IS_BW_160_WIDE(chspec) &&\
324 		((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\
325 		(CHSPEC_BW(chspec) < (bw)))
326 #endif /* WL11ULB */
327 
328 /* Legacy Chanspec defines
329  * These are the defines for the previous format of the chanspec_t
330  */
331 #define WL_LCHANSPEC_CHAN_MASK		0x00ff
332 #define WL_LCHANSPEC_CHAN_SHIFT		     0
333 
334 #define WL_LCHANSPEC_CTL_SB_MASK	0x0300
335 #define WL_LCHANSPEC_CTL_SB_SHIFT	     8
336 #define WL_LCHANSPEC_CTL_SB_LOWER	0x0100
337 #define WL_LCHANSPEC_CTL_SB_UPPER	0x0200
338 #define WL_LCHANSPEC_CTL_SB_NONE	0x0300
339 
340 #define WL_LCHANSPEC_BW_MASK		0x0C00
341 #define WL_LCHANSPEC_BW_SHIFT		    10
342 #define WL_LCHANSPEC_BW_10		0x0400
343 #define WL_LCHANSPEC_BW_20		0x0800
344 #define WL_LCHANSPEC_BW_40		0x0C00
345 
346 #define WL_LCHANSPEC_BAND_MASK		0xf000
347 #define WL_LCHANSPEC_BAND_SHIFT		    12
348 #define WL_LCHANSPEC_BAND_5G		0x1000
349 #define WL_LCHANSPEC_BAND_2G		0x2000
350 
351 #define LCHSPEC_CHANNEL(chspec)	((uint8)((chspec) & WL_LCHANSPEC_CHAN_MASK))
352 #define LCHSPEC_BAND(chspec)	((chspec) & WL_LCHANSPEC_BAND_MASK)
353 #define LCHSPEC_CTL_SB(chspec)	((chspec) & WL_LCHANSPEC_CTL_SB_MASK)
354 #define LCHSPEC_BW(chspec)	((chspec) & WL_LCHANSPEC_BW_MASK)
355 #define LCHSPEC_IS10(chspec)	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_10)
356 #define LCHSPEC_IS20(chspec)	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_20)
357 #define LCHSPEC_IS40(chspec)	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40)
358 #define LCHSPEC_IS5G(chspec)	(((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_5G)
359 #define LCHSPEC_IS2G(chspec)	(((chspec) & WL_LCHANSPEC_BAND_MASK) == WL_LCHANSPEC_BAND_2G)
360 
361 #define LCHSPEC_SB_UPPER(chspec)	\
362 	((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_UPPER) && \
363 	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
364 #define LCHSPEC_SB_LOWER(chspec)	\
365 	((((chspec) & WL_LCHANSPEC_CTL_SB_MASK) == WL_LCHANSPEC_CTL_SB_LOWER) && \
366 	(((chspec) & WL_LCHANSPEC_BW_MASK) == WL_LCHANSPEC_BW_40))
367 
368 #define LCHSPEC_CREATE(chan, band, bw, sb)  ((uint16)((chan) | (sb) | (bw) | (band)))
369 
370 #define CH20MHZ_LCHSPEC(channel) \
371 	(chanspec_t)((chanspec_t)(channel) | WL_LCHANSPEC_BW_20 | \
372 	WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \
373 	WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G))
374 
375 /*
376  * WF_CHAN_FACTOR_* constants are used to calculate channel frequency
377  * given a channel number.
378  * chan_freq = chan_factor * 500Mhz + chan_number * 5
379  */
380 
381 /**
382  * Channel Factor for the starting frequence of 2.4 GHz channels.
383  * The value corresponds to 2407 MHz.
384  */
385 #define WF_CHAN_FACTOR_2_4_G		4814	/* 2.4 GHz band, 2407 MHz */
386 
387 /**
388  * Channel Factor for the starting frequence of 5 GHz channels.
389  * The value corresponds to 5000 MHz.
390  */
391 #define WF_CHAN_FACTOR_5_G		10000	/* 5   GHz band, 5000 MHz */
392 
393 /**
394  * Channel Factor for the starting frequence of 4.9 GHz channels.
395  * The value corresponds to 4000 MHz.
396  */
397 #define WF_CHAN_FACTOR_4_G		8000	/* 4.9 GHz band for Japan */
398 
399 #define WLC_2G_25MHZ_OFFSET		5	/* 2.4GHz band channel offset */
400 
401 /**
402  *  No of sub-band vlaue of the specified Mhz chanspec
403  */
404 #define WF_NUM_SIDEBANDS_40MHZ   2
405 #define WF_NUM_SIDEBANDS_80MHZ   4
406 #define WF_NUM_SIDEBANDS_8080MHZ 4
407 #define WF_NUM_SIDEBANDS_160MHZ  8
408 
409 /**
410  * Convert chanspec to ascii string
411  *
412  * @param	chspec		chanspec format
413  * @param	buf		ascii string of chanspec
414  *
415  * @return	pointer to buf with room for at least CHANSPEC_STR_LEN bytes
416  *		Original chanspec in case of error
417  *
418  * @see		CHANSPEC_STR_LEN
419  */
420 extern char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf);
421 
422 /**
423  * Convert chanspec to ascii string
424  *
425  * @param	chspec		chanspec format
426  * @param	buf		ascii string of chanspec
427  *
428  * @return	pointer to buf with room for at least CHANSPEC_STR_LEN bytes
429  *		NULL in case of error
430  *
431  * @see		CHANSPEC_STR_LEN
432  */
433 extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf);
434 
435 /**
436  * Convert ascii string to chanspec
437  *
438  * @param	a     pointer to input string
439  *
440  * @return	>= 0 if successful or 0 otherwise
441  */
442 extern chanspec_t wf_chspec_aton(const char *a);
443 
444 /**
445  * Verify the chanspec fields are valid.
446  *
447  * Verify the chanspec is using a legal set field values, i.e. that the chanspec
448  * specified a band, bw, ctl_sb and channel and that the combination could be
449  * legal given some set of circumstances.
450  *
451  * @param	chanspec   input chanspec to verify
452  *
453  * @return TRUE if the chanspec is malformed, FALSE if it looks good.
454  */
455 extern bool wf_chspec_malformed(chanspec_t chanspec);
456 
457 /**
458  * Verify the chanspec specifies a valid channel according to 802.11.
459  *
460  * @param	chanspec   input chanspec to verify
461  *
462  * @return TRUE if the chanspec is a valid 802.11 channel
463  */
464 extern bool wf_chspec_valid(chanspec_t chanspec);
465 
466 /**
467  * Return the primary (control) channel.
468  *
469  * This function returns the channel number of the primary 20MHz channel. For
470  * 20MHz channels this is just the channel number. For 40MHz or wider channels
471  * it is the primary 20MHz channel specified by the chanspec.
472  *
473  * @param	chspec    input chanspec
474  *
475  * @return Returns the channel number of the primary 20MHz channel
476  */
477 extern uint8 wf_chspec_ctlchan(chanspec_t chspec);
478 
479 /*
480  * Return the bandwidth string.
481  *
482  * This function returns the bandwidth string for the passed chanspec.
483  *
484  * @param	chspec    input chanspec
485  *
486  * @return Returns the bandwidth string
487  */
488 extern const char *wf_chspec_to_bw_str(chanspec_t chspec);
489 
490 /**
491  * Return the primary (control) chanspec.
492  *
493  * This function returns the chanspec of the primary 20MHz channel. For 20MHz
494  * channels this is just the chanspec. For 40MHz or wider channels it is the
495  * chanspec of the primary 20MHZ channel specified by the chanspec.
496  *
497  * @param	chspec    input chanspec
498  *
499  * @return Returns the chanspec of the primary 20MHz channel
500  */
501 extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
502 
503 /**
504  * Return a channel number corresponding to a frequency.
505  *
506  * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
507  * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
508  * as the primary 20MHz channel.
509  */
510 extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec);
511 
512 /*
513  * Return the channel number for a given frequency and base frequency.
514  * The returned channel number is relative to the given base frequency.
515  * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
516  * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
517  *
518  * Frequency is specified in MHz.
519  * The base frequency is specified as (start_factor * 500 kHz).
520  * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
521  * 2.4 GHz and 5 GHz bands.
522  *
523  * The returned channel will be in the range [1, 14] in the 2.4 GHz band
524  * and [0, 200] otherwise.
525  * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
526  * frequency is not a 2.4 GHz channel, or if the frequency is not and even
527  * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
528  *
529  * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
530  *
531  * @param	freq          frequency in MHz
532  * @param	start_factor  base frequency in 500 kHz units, e.g. 10000 for 5 GHz
533  *
534  * @return Returns a channel number
535  *
536  * @see  WF_CHAN_FACTOR_2_4_G
537  * @see  WF_CHAN_FACTOR_5_G
538  */
539 extern int wf_mhz2channel(uint freq, uint start_factor);
540 
541 /**
542  * Return the center frequency in MHz of the given channel and base frequency.
543  *
544  * Return the center frequency in MHz of the given channel and base frequency.
545  * The channel number is interpreted relative to the given base frequency.
546  *
547  * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
548  * The base frequency is specified as (start_factor * 500 kHz).
549  * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
550  * 2.4 GHz and 5 GHz bands.
551  * The channel range of [1, 14] is only checked for a start_factor of
552  * WF_CHAN_FACTOR_2_4_G (4814).
553  * Odd start_factors produce channels on .5 MHz boundaries, in which case
554  * the answer is rounded down to an integral MHz.
555  * -1 is returned for an out of range channel.
556  *
557  * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
558  *
559  * @param	channel       input channel number
560  * @param	start_factor  base frequency in 500 kHz units, e.g. 10000 for 5 GHz
561  *
562  * @return Returns a frequency in MHz
563  *
564  * @see  WF_CHAN_FACTOR_2_4_G
565  * @see  WF_CHAN_FACTOR_5_G
566  */
567 extern int wf_channel2mhz(uint channel, uint start_factor);
568 
569 /**
570  * Returns the chanspec 80Mhz channel corresponding to the following input
571  * parameters
572  *
573  *	primary_channel - primary 20Mhz channel
574  *	center_channel   - center frequecny of the 80Mhz channel
575  *
576  * The center_channel can be one of {42, 58, 106, 122, 138, 155}
577  *
578  * returns INVCHANSPEC in case of error
579  */
580 extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel);
581 
582 /**
583  * Convert ctl chan and bw to chanspec
584  *
585  * @param	ctl_ch		channel
586  * @param	bw	        bandwidth
587  *
588  * @return	> 0 if successful or 0 otherwise
589  *
590  */
591 extern uint16 wf_channel2chspec(uint ctl_ch, uint bw);
592 
593 extern uint wf_channel2freq(uint channel);
594 extern uint wf_freq2channel(uint freq);
595 
596 /*
597  * Returns the 80+80 MHz chanspec corresponding to the following input parameters
598  *
599  *    primary_20mhz - Primary 20 MHz channel
600  *    chan0_80MHz - center channel number of one frequency segment
601  *    chan1_80MHz - center channel number of the other frequency segment
602  *
603  * Parameters chan0_80MHz and chan1_80MHz are channel numbers in {42, 58, 106, 122, 138, 155}.
604  * The primary channel must be contained in one of the 80MHz channels. This routine
605  * will determine which frequency segment is the primary 80 MHz segment.
606  *
607  * Returns INVCHANSPEC in case of error.
608  *
609  * Refer to IEEE802.11ac section 22.3.14 "Channelization".
610  */
611 extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz,
612 	uint8 chan0_80Mhz, uint8 chan1_80Mhz);
613 
614 /*
615  * Returns the primary 80 Mhz channel for the provided chanspec
616  *
617  *    chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
618  *
619  *  returns -1 in case the provided channel is 20/40 Mhz chanspec
620  */
621 extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec);
622 
623 /*
624  * Returns the secondary 80 Mhz channel for the provided chanspec
625  *
626  *    chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
627  *
628  *  returns -1 in case the provided channel is 20/40 Mhz chanspec
629  */
630 extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec);
631 
632 /*
633  * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
634  */
635 extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec);
636 
637 #ifdef WL11AC_80P80
638 /*
639  * This function returns the centre chanel for the given chanspec.
640  * In case of 80+80 chanspec it returns the primary 80 Mhz centre channel
641  */
642 extern uint8 wf_chspec_channel(chanspec_t chspec);
643 #endif
644 extern chanspec_t wf_channel_create_chspec_frm_opclass(uint8 opclass, uint8 channel);
645 extern int wf_channel_create_opclass_frm_chspec(chanspec_t chspec);
646 #endif	/* _bcmwifi_channels_h_ */
647