xref: /freebsd/sys/dev/bwn/if_bwnvar.h (revision da5069e1f7daaef1e7157876d6044de6f3a08ce2)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer,
12  *    without modification.
13  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
15  *    redistribution must be conditioned upon including a substantially
16  *    similar Disclaimer requirement for further binary redistribution.
17  *
18  * NO WARRANTY
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
22  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
24  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29  * THE POSSIBILITY OF SUCH DAMAGES.
30  *
31  * $FreeBSD$
32  */
33 
34 #ifndef _IF_BWNVAR_H
35 #define	_IF_BWNVAR_H
36 
37 #include <dev/bhnd/bhnd.h>
38 
39 struct bwn_softc;
40 struct bwn_mac;
41 
42 #define	N(a)			(sizeof(a) / sizeof(a[0]))
43 #define	BWN_ALIGN			0x1000
44 #define	BWN_RETRY_SHORT			7
45 #define	BWN_RETRY_LONG			4
46 #define	BWN_STAID_MAX			64
47 #define	BWN_TXPWR_IGNORE_TIME		(1 << 0)
48 #define	BWN_TXPWR_IGNORE_TSSI		(1 << 1)
49 #define	BWN_HAS_TXMAG(phy)						\
50 	(((phy)->rev >= 2) && ((phy)->rf_ver == 0x2050) &&		\
51 	 ((phy)->rf_rev == 8))
52 #define	BWN_HAS_LOOPBACK(phy)						\
53 	(((phy)->rev > 1) || ((phy)->gmode))
54 #define	BWN_TXERROR_MAX			1000
55 #define	BWN_GETTIME(v)	do {						\
56 	struct timespec ts;						\
57 	nanouptime(&ts);						\
58 	(v) = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;			\
59 } while (0)
60 #define	BWN_ISOLDFMT(mac)		((mac)->mac_fw.rev <= 351)
61 #define	BWN_TSSI2DBM(num, den)						\
62 	((int32_t)((num < 0) ? num / den : (num + den / 2) / den))
63 #define	BWN_HDRSIZE(mac)	bwn_tx_hdrsize(mac)
64 #define	BWN_MAXTXHDRSIZE	(112 + (sizeof(struct bwn_plcp6)))
65 
66 #define	BWN_PIO_COOKIE(tq, tp)						\
67 	((uint16_t)((((uint16_t)tq->tq_index + 1) << 12) | tp->tp_index))
68 #define	BWN_DMA_COOKIE(dr, slot)					\
69 	((uint16_t)(((uint16_t)dr->dr_index + 1) << 12) | (uint16_t)slot)
70 #define	BWN_READ_2(mac, o)						\
71 	(bus_read_2((mac)->mac_sc->sc_mem_res, (o)))
72 #define	BWN_READ_4(mac, o)						\
73 	(bus_read_4((mac)->mac_sc->sc_mem_res, (o)))
74 #define	BWN_WRITE_2(mac, o, v)						\
75 	(bus_write_2((mac)->mac_sc->sc_mem_res, (o), (v)))
76 #define	BWN_WRITE_2_F(mac, o, v) do { \
77 	(BWN_WRITE_2(mac, o, v)); \
78 	BWN_READ_2(mac, o); \
79 } while(0)
80 #define	BWN_WRITE_SETMASK2(mac, offset, mask, set)			\
81 	BWN_WRITE_2(mac, offset, (BWN_READ_2(mac, offset) & mask) | set)
82 #define	BWN_WRITE_4(mac, o, v)						\
83 	(bus_write_4((mac)->mac_sc->sc_mem_res, (o), (v)))
84 #define	BWN_WRITE_SETMASK4(mac, offset, mask, set)			\
85 	BWN_WRITE_4(mac, offset, (BWN_READ_4(mac, offset) & mask) | set)
86 #define	BWN_PIO_TXQOFFSET(mac)						\
87 	((bhnd_get_hwrev(mac->mac_sc->sc_dev) >= 11) ? 0x18 : 0)
88 #define	BWN_PIO_RXQOFFSET(mac)						\
89 	((bhnd_get_hwrev(mac->mac_sc->sc_dev) >= 11) ? 0x38 : 8)
90 #define	BWN_SEC_NEWAPI(mac)		(mac->mac_fw.rev >= 351)
91 #define	BWN_SEC_KEY2FW(mac, idx)					\
92 	(BWN_SEC_NEWAPI(mac) ? idx : ((idx >= 4) ? idx - 4 : idx))
93 #define	BWN_RF_READ(mac, r)		(mac->mac_phy.rf_read(mac, r))
94 #define	BWN_RF_WRITE(mac, r, v)		(mac->mac_phy.rf_write(mac, r, v))
95 #define	BWN_RF_MASK(mac, o, m)						\
96 	BWN_RF_WRITE(mac, o, BWN_RF_READ(mac, o) & m)
97 #define	BWN_RF_SETMASK(mac, offset, mask, set)				\
98 	BWN_RF_WRITE(mac, offset, (BWN_RF_READ(mac, offset) & mask) | set)
99 #define	BWN_RF_SET(mac, offset, set)					\
100 	BWN_RF_WRITE(mac, offset, BWN_RF_READ(mac, offset) | set)
101 #define	BWN_PHY_READ(mac, r)		(mac->mac_phy.phy_read(mac, r))
102 #define	BWN_PHY_WRITE(mac, r, v)					\
103 	(mac->mac_phy.phy_write(mac, r, v))
104 #define	BWN_PHY_SET(mac, offset, set)	do {				\
105 	if (mac->mac_phy.phy_maskset != NULL) {				\
106 		KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED ||	\
107 		    mac->mac_suspended > 0,				\
108 		    ("dont access PHY or RF registers after turning on MAC")); \
109 		mac->mac_phy.phy_maskset(mac, offset, 0xffff, set);	\
110 	} else								\
111 		BWN_PHY_WRITE(mac, offset,				\
112 		    BWN_PHY_READ(mac, offset) | (set));			\
113 } while (0)
114 #define	BWN_PHY_SETMASK(mac, offset, mask, set)	do {			\
115 	if (mac->mac_phy.phy_maskset != NULL) {				\
116 		KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED ||	\
117 		    mac->mac_suspended > 0,				\
118 		    ("dont access PHY or RF registers after turning on MAC")); \
119 		mac->mac_phy.phy_maskset(mac, offset, mask, set);	\
120 	} else								\
121 		BWN_PHY_WRITE(mac, offset,				\
122 		    (BWN_PHY_READ(mac, offset) & (mask)) | (set));	\
123 } while (0)
124 #define	BWN_PHY_MASK(mac, offset, mask)	do {				\
125 	if (mac->mac_phy.phy_maskset != NULL) {				\
126 		KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED ||	\
127 		    mac->mac_suspended > 0,				\
128 		    ("dont access PHY or RF registers after turning on MAC")); \
129 		mac->mac_phy.phy_maskset(mac, offset, mask, 0);		\
130 	} else								\
131 		BWN_PHY_WRITE(mac, offset,				\
132 		    BWN_PHY_READ(mac, offset) & mask);			\
133 } while (0)
134 #define	BWN_PHY_COPY(mac, dst, src)	do {				\
135 	KASSERT(mac->mac_status < BWN_MAC_STATUS_INITED ||		\
136 	    mac->mac_suspended > 0,					\
137 	    ("dont access PHY or RF registers after turning on MAC"));	\
138 	BWN_PHY_WRITE(mac, dst, BWN_PHY_READ(mac, src));		\
139 } while (0)
140 #define BWN_LO_CALIB_EXPIRE		(1000 * (30 - 2))
141 #define BWN_LO_PWRVEC_EXPIRE		(1000 * (30 - 2))
142 #define BWN_LO_TXCTL_EXPIRE		(1000 * (180 - 4))
143 #define BWN_LPD(L, P, D)		(((L) << 2) | ((P) << 1) | ((D) << 0))
144 #define BWN_BITREV4(tmp)		(BWN_BITREV8(tmp) >> 4)
145 #define	BWN_BITREV8(byte)		(bwn_bitrev_table[byte])
146 #define	BWN_BBATTCMP(a, b)		((a)->att == (b)->att)
147 #define	BWN_RFATTCMP(a, b)						\
148 	(((a)->att == (b)->att) && ((a)->padmix == (b)->padmix))
149 #define	BWN_PIO_WRITE_2(mac, tq, offset, value)				\
150 	BWN_WRITE_2(mac, (tq)->tq_base + offset, value)
151 #define	BWN_PIO_READ_4(mac, tq, offset)					\
152 	BWN_READ_4(mac, tq->tq_base + offset)
153 #define	BWN_ISCCKRATE(rate)						\
154 	(rate == BWN_CCK_RATE_1MB || rate == BWN_CCK_RATE_2MB ||	\
155 	 rate == BWN_CCK_RATE_5MB || rate == BWN_CCK_RATE_11MB)
156 #define	BWN_ISOFDMRATE(rate)		(!BWN_ISCCKRATE(rate))
157 #define	BWN_BARRIER(mac, offset, length, flags)			\
158 	bus_barrier((mac)->mac_sc->sc_mem_res, (offset), (length), (flags))
159 #define	BWN_DMA_READ(dr, offset)				\
160 	(BWN_READ_4(dr->dr_mac, dr->dr_base + offset))
161 #define	BWN_DMA_WRITE(dr, offset, value)			\
162 	(BWN_WRITE_4(dr->dr_mac, dr->dr_base + offset, value))
163 
164 
165 typedef enum {
166 	BWN_PHY_BAND_2G = 0,
167 	BWN_PHY_BAND_5G_LO = 1,
168 	BWN_PHY_BAND_5G_MI = 2,
169 	BWN_PHY_BAND_5G_HI = 3
170 } bwn_phy_band_t;
171 
172 typedef enum {
173 	BWN_BAND_2G,
174 	BWN_BAND_5G,
175 } bwn_band_t;
176 
177 typedef enum {
178 	BWN_CHAN_TYPE_20,
179 	BWN_CHAN_TYPE_20_HT,
180 	BWN_CHAN_TYPE_40_HT_U,
181 	BWN_CHAN_TYPE_40_HT_D,
182 } bwn_chan_type_t;
183 
184 struct bwn_rate {
185 	uint16_t			rateid;
186 	uint32_t			flags;
187 };
188 
189 #define	BWN_ANT0			0
190 #define	BWN_ANT1			1
191 #define	BWN_ANTAUTO0			2
192 #define	BWN_ANTAUTO1			3
193 #define	BWN_ANT2			4
194 #define	BWN_ANT3			8
195 #define	BWN_ANTAUTO			BWN_ANTAUTO0
196 #define	BWN_ANT_DEFAULT			BWN_ANTAUTO
197 #define	BWN_TX_SLOTS_PER_FRAME		2
198 
199 struct bwn_channel {
200 	unsigned			freq;
201 	unsigned			ieee;
202 	unsigned			maxTxPow;
203 };
204 
205 struct bwn_channelinfo {
206 	struct bwn_channel		channels[IEEE80211_CHAN_MAX];
207 	unsigned			nchannels;
208 };
209 
210 struct bwn_bbatt {
211 	uint8_t				att;
212 };
213 
214 struct bwn_bbatt_list {
215 	const struct bwn_bbatt		*array;
216 	uint8_t				len;
217 	uint8_t				min;
218 	uint8_t				max;
219 };
220 
221 struct bwn_rfatt {
222 	uint8_t				att;
223 	int				padmix;
224 };
225 
226 struct bwn_rfatt_list {
227 	const struct bwn_rfatt		*array;
228 	uint8_t				len;
229 	uint8_t				min;
230 	uint8_t				max;
231 };
232 
233 #define	BWN_DC_LT_SIZE			32
234 
235 struct bwn_loctl {
236 	int8_t				i;
237 	int8_t				q;
238 };
239 
240 typedef enum {
241 	BWN_TXPWR_RES_NEED_ADJUST,
242 	BWN_TXPWR_RES_DONE,
243 } bwn_txpwr_result_t;
244 
245 struct bwn_lo_calib {
246 	struct bwn_bbatt		bbatt;
247 	struct bwn_rfatt		rfatt;
248 	struct bwn_loctl		ctl;
249 	unsigned long			calib_time;
250 	TAILQ_ENTRY(bwn_lo_calib)	list;
251 };
252 
253 struct bwn_rxhdr4 {
254 	uint16_t			frame_len;
255 	uint8_t				pad1[2];
256 	uint16_t			phy_status0;
257 	union {
258 		struct {
259 			uint8_t		rssi;
260 			uint8_t		sig_qual;
261 		} __packed abg;
262 		struct {
263 			int8_t		power0;
264 			int8_t		power1;
265 		} __packed n;
266 	} __packed phy;
267 	union {
268 		struct {
269 			int8_t		power2;
270 			uint8_t		pad;
271 		} __packed n;
272 		struct {
273 			uint8_t		pad;
274 			int8_t		ht_power0;
275 		} __packed ht;
276 		uint16_t		phy_status2;
277 	} __packed ps2;
278 	union {
279 		struct {
280 			uint16_t	phy_status3;
281 		} __packed lp;
282 		struct {
283 			int8_t		phy_ht_power1;
284 			int8_t		phy_ht_power2;
285 		} __packed ht;
286 	} __packed ps3;
287 	union {
288 		struct {
289 			uint32_t	mac_status;
290 			uint16_t	mac_time;
291 			uint16_t	channel;
292 		} __packed r351;
293 		struct {
294 			uint16_t	phy_status4;
295 			uint16_t	phy_status5;
296 			uint32_t	mac_status;
297 			uint16_t	mac_time;
298 			uint16_t	channel;
299 		} __packed r598;
300 	} __packed ps4;
301 } __packed;
302 
303 struct bwn_txstatus {
304 	uint16_t			cookie;
305 	uint16_t			seq;
306 	uint8_t				phy_stat;
307 	uint8_t				framecnt;
308 	uint8_t				rtscnt;
309 	uint8_t				sreason;
310 	uint8_t				pm;
311 	uint8_t				im;
312 	uint8_t				ampdu;
313 	uint8_t				ack;
314 };
315 
316 #define	BWN_TXCTL_PA3DB			0x40
317 #define	BWN_TXCTL_PA2DB			0x20
318 #define	BWN_TXCTL_TXMIX			0x10
319 
320 struct bwn_txpwr_loctl {
321 	struct bwn_rfatt_list		rfatt;
322 	struct bwn_bbatt_list		bbatt;
323 	uint16_t			dc_lt[BWN_DC_LT_SIZE];
324 	TAILQ_HEAD(, bwn_lo_calib)	calib_list;
325 	unsigned long			pwr_vec_read_time;
326 	unsigned long			txctl_measured_time;
327 	uint8_t				tx_bias;
328 	uint8_t				tx_magn;
329 	uint64_t			power_vector;
330 };
331 
332 #define	BWN_OFDMTAB_DIR_UNKNOWN		0
333 #define	BWN_OFDMTAB_DIR_READ		1
334 #define	BWN_OFDMTAB_DIR_WRITE		2
335 
336 struct bwn_phy_g {
337 	unsigned			pg_flags;
338 #define	BWN_PHY_G_FLAG_TSSITABLE_ALLOC	(1 << 0)
339 #define	BWN_PHY_G_FLAG_RADIOCTX_VALID	(1 << 1)
340 	int				pg_aci_enable;
341 	int				pg_aci_wlan_automatic;
342 	int				pg_aci_hw_rssi;
343 	int				pg_rf_on;
344 	uint16_t			pg_radioctx_over;
345 	uint16_t			pg_radioctx_overval;
346 	uint16_t			pg_minlowsig[2];
347 	uint16_t			pg_minlowsigpos[2];
348 	uint16_t			pg_pa0maxpwr;
349 	int8_t				*pg_tssi2dbm;
350 	int				pg_idletssi;
351 	int				pg_curtssi;
352 	uint8_t				pg_avgtssi;
353 	struct bwn_bbatt		pg_bbatt;
354 	struct bwn_rfatt		pg_rfatt;
355 	uint8_t				pg_txctl;
356 	int				pg_bbatt_delta;
357 	int				pg_rfatt_delta;
358 
359 	struct bwn_txpwr_loctl		pg_loctl;
360 	int16_t				pg_max_lb_gain;
361 	int16_t				pg_trsw_rx_gain;
362 	int16_t				pg_lna_lod_gain;
363 	int16_t				pg_lna_gain;
364 	int16_t				pg_pga_gain;
365 	int				pg_immode;
366 #define	BWN_INTERFSTACK_SIZE	26
367 	uint32_t			pg_interfstack[BWN_INTERFSTACK_SIZE];
368 
369 	int16_t				pg_nrssi[2];
370 	int32_t				pg_nrssi_slope;
371 	int8_t				pg_nrssi_lt[64];
372 
373 	uint16_t			pg_lofcal;
374 
375 	uint16_t			pg_initval;
376 	uint16_t			pg_ofdmtab_addr;
377 	unsigned			pg_ofdmtab_dir;
378 };
379 
380 #define	BWN_IMMODE_NONE			0
381 #define	BWN_IMMODE_NONWLAN		1
382 #define	BWN_IMMODE_MANUAL		2
383 #define	BWN_IMMODE_AUTO			3
384 
385 #define	BWN_PHYLP_TXPCTL_UNKNOWN	0
386 #define	BWN_PHYLP_TXPCTL_OFF		1
387 #define	BWN_PHYLP_TXPCTL_ON_SW		2
388 #define	BWN_PHYLP_TXPCTL_ON_HW		3
389 
390 struct bwn_phy_lp {
391 	uint8_t				plp_chan;
392 	uint8_t				plp_chanfullcal;
393 	int32_t				plp_antenna;
394 	uint8_t				plp_txpctlmode;
395 	uint8_t				plp_txisoband_h;
396 	uint8_t				plp_txisoband_m;
397 	uint8_t				plp_txisoband_l;
398 	uint8_t				plp_rxpwroffset;
399 	int8_t				plp_txpwridx;
400 	uint16_t			plp_tssiidx;
401 	uint16_t			plp_tssinpt;
402 	uint8_t				plp_rssivf;
403 	uint8_t				plp_rssivc;
404 	uint8_t				plp_rssigs;
405 	uint8_t				plp_rccap;
406 	uint8_t				plp_bxarch;
407 	uint8_t				plp_crsusr_off;
408 	uint8_t				plp_crssys_off;
409 	uint32_t			plp_div;
410 	int32_t				plp_tonefreq;
411 	uint16_t			plp_digfilt[9];
412 };
413 
414 /* for LP */
415 struct bwn_txgain {
416 	uint16_t			tg_gm;
417 	uint16_t			tg_pga;
418 	uint16_t			tg_pad;
419 	uint16_t			tg_dac;
420 };
421 
422 struct bwn_rxcompco {
423 	uint8_t				rc_chan;
424 	int8_t				rc_c1;
425 	int8_t				rc_c0;
426 };
427 
428 struct bwn_phy_lp_iq_est {
429 	uint32_t			ie_iqprod;
430 	uint32_t			ie_ipwr;
431 	uint32_t			ie_qpwr;
432 };
433 
434 struct bwn_txgain_entry {
435 	uint8_t				te_gm;
436 	uint8_t				te_pga;
437 	uint8_t				te_pad;
438 	uint8_t				te_dac;
439 	uint8_t				te_bbmult;
440 };
441 
442 /* only for LP PHY */
443 struct bwn_stxtable {
444 	uint16_t			st_phyoffset;
445 	uint16_t			st_physhift;
446 	uint16_t			st_rfaddr;
447 	uint16_t			st_rfshift;
448 	uint16_t			st_mask;
449 };
450 
451 struct bwn_b206x_chan {
452 	uint8_t				bc_chan;
453 	uint16_t			bc_freq;
454 	const uint8_t			*bc_data;
455 };
456 
457 struct bwn_b206x_rfinit_entry {
458 	uint16_t			br_offset;
459 	uint16_t			br_valuea;
460 	uint16_t			br_valueg;
461 	uint8_t				br_flags;
462 };
463 
464 struct bwn_phy_n;
465 
466 struct bwn_phy {
467 	uint8_t				type;
468 	uint8_t				rev;
469 	uint8_t				analog;
470 
471 	int				supports_2ghz;
472 	int				supports_5ghz;
473 
474 	int				gmode;
475 	struct bwn_phy_g		phy_g;
476 	struct bwn_phy_lp		phy_lp;
477 
478 	/*
479 	 * I'd like the newer PHY code to not hide in the top-level
480 	 * structs..
481 	 */
482 	struct bwn_phy_n		*phy_n;
483 
484 	uint16_t			rf_manuf;
485 	uint16_t			rf_ver;
486 	uint8_t				rf_rev;
487 	int				rf_on;
488 	int				phy_do_full_init;
489 
490 	int				txpower;
491 	int				hwpctl;
492 	unsigned long			nexttime;
493 	unsigned int			chan;
494 	int				txerrors;
495 
496 	int				(*attach)(struct bwn_mac *);
497 	void				(*detach)(struct bwn_mac *);
498 	int				(*prepare_hw)(struct bwn_mac *);
499 	void				(*init_pre)(struct bwn_mac *);
500 	int				(*init)(struct bwn_mac *);
501 	void				(*exit)(struct bwn_mac *);
502 	uint16_t			(*phy_read)(struct bwn_mac *, uint16_t);
503 	void				(*phy_write)(struct bwn_mac *, uint16_t,
504 					    uint16_t);
505 	void				(*phy_maskset)(struct bwn_mac *,
506 					    uint16_t, uint16_t, uint16_t);
507 	uint16_t			(*rf_read)(struct bwn_mac *, uint16_t);
508 	void				(*rf_write)(struct bwn_mac *, uint16_t,
509 					    uint16_t);
510 	int				(*use_hwpctl)(struct bwn_mac *);
511 	void				(*rf_onoff)(struct bwn_mac *, int);
512 	void				(*switch_analog)(struct bwn_mac *, int);
513 	int				(*switch_channel)(struct bwn_mac *,
514 					    unsigned int);
515 	uint32_t			(*get_default_chan)(struct bwn_mac *);
516 	void				(*set_antenna)(struct bwn_mac *, int);
517 	int				(*set_im)(struct bwn_mac *, int);
518 	bwn_txpwr_result_t		(*recalc_txpwr)(struct bwn_mac *, int);
519 	void				(*set_txpwr)(struct bwn_mac *);
520 	void				(*task_15s)(struct bwn_mac *);
521 	void				(*task_60s)(struct bwn_mac *);
522 };
523 
524 struct bwn_chan_band {
525 	uint32_t			flags;
526 	uint8_t				nchan;
527 #define	BWN_MAX_CHAN_PER_BAND		14
528 	uint8_t				chan[BWN_MAX_CHAN_PER_BAND];
529 };
530 
531 #define	BWN_NR_WMEPARAMS		16
532 enum {
533 	BWN_WMEPARAM_TXOP = 0,
534 	BWN_WMEPARAM_CWMIN,
535 	BWN_WMEPARAM_CWMAX,
536 	BWN_WMEPARAM_CWCUR,
537 	BWN_WMEPARAM_AIFS,
538 	BWN_WMEPARAM_BSLOTS,
539 	BWN_WMEPARAM_REGGAP,
540 	BWN_WMEPARAM_STATUS,
541 };
542 
543 #define	BWN_WME_PARAMS(queue)	\
544 	(BWN_SHARED_EDCFQ + (BWN_NR_WMEPARAMS * sizeof(uint16_t) * (queue)))
545 #define	BWN_WME_BACKGROUND	BWN_WME_PARAMS(0)
546 #define	BWN_WME_BESTEFFORT	BWN_WME_PARAMS(1)
547 #define	BWN_WME_VIDEO		BWN_WME_PARAMS(2)
548 #define	BWN_WME_VOICE		BWN_WME_PARAMS(3)
549 
550 /*
551  * Radio capture format.
552  */
553 #define	BWN_RX_RADIOTAP_PRESENT (		\
554 	(1 << IEEE80211_RADIOTAP_TSFT)		| \
555 	(1 << IEEE80211_RADIOTAP_FLAGS)		| \
556 	(1 << IEEE80211_RADIOTAP_RATE)		| \
557 	(1 << IEEE80211_RADIOTAP_CHANNEL)	| \
558 	(1 << IEEE80211_RADIOTAP_ANTENNA)	| \
559 	(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)	| \
560 	(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)	| \
561 	0)
562 
563 struct bwn_rx_radiotap_header {
564 	struct ieee80211_radiotap_header wr_ihdr;
565 	uint64_t			wr_tsf;
566 	u_int8_t			wr_flags;
567 	u_int8_t			wr_rate;
568 	u_int16_t			wr_chan_freq;
569 	u_int16_t			wr_chan_flags;
570 	int8_t				wr_antsignal;
571 	int8_t				wr_antnoise;
572 	u_int8_t			wr_antenna;
573 } __packed __aligned(8);
574 
575 #define	BWN_TX_RADIOTAP_PRESENT (		\
576 	(1 << IEEE80211_RADIOTAP_FLAGS)		| \
577 	(1 << IEEE80211_RADIOTAP_RATE)		| \
578 	(1 << IEEE80211_RADIOTAP_CHANNEL)	| \
579 	(1 << IEEE80211_RADIOTAP_DBM_TX_POWER)	| \
580 	(1 << IEEE80211_RADIOTAP_ANTENNA)	| \
581 	0)
582 
583 struct bwn_tx_radiotap_header {
584 	struct ieee80211_radiotap_header wt_ihdr;
585 	u_int8_t			wt_flags;
586 	u_int8_t			wt_rate;
587 	u_int16_t			wt_chan_freq;
588 	u_int16_t			wt_chan_flags;
589 	u_int8_t			wt_txpower;
590 	u_int8_t			wt_antenna;
591 } __packed;
592 
593 struct bwn_stats {
594 	int32_t				rtsfail;
595 	int32_t				rts;
596 	int32_t				link_noise;
597 };
598 
599 /* Noise Calculation (Link Quality) */
600 struct bwn_noise {
601 	uint8_t				noi_running;
602 	uint8_t				noi_nsamples;
603 	int8_t				noi_samples[8][4];
604 };
605 
606 struct bwn_dmadesc_meta {
607 	bus_dmamap_t			mt_dmap;
608 	bus_addr_t			mt_paddr;
609 	struct mbuf			*mt_m;
610 	struct ieee80211_node		*mt_ni;
611 	uint8_t				mt_txtype;
612 #define	BWN_DMADESC_METATYPE_HEADER	0
613 #define	BWN_DMADESC_METATYPE_BODY	1
614 	uint8_t				mt_islast;
615 };
616 
617 #define	BWN_DMAINTR_FATALMASK	\
618 	((1 << 10) | (1 << 11) | (1 << 12) | (1 << 14) | (1 << 15))
619 #define	BWN_DMAINTR_NONFATALMASK	(1 << 13)
620 #define	BWN_DMAINTR_RX_DONE		(1 << 16)
621 
622 #define	BWN_DMA32_DCTL_BYTECNT		0x00001fff
623 #define	BWN_DMA32_DCTL_ADDREXT_MASK	0x00030000
624 #define	BWN_DMA32_DCTL_ADDREXT_SHIFT	16
625 #define	BWN_DMA32_DCTL_DTABLEEND	0x10000000
626 #define	BWN_DMA32_DCTL_IRQ		0x20000000
627 #define	BWN_DMA32_DCTL_FRAMEEND		0x40000000
628 #define	BWN_DMA32_DCTL_FRAMESTART	0x80000000
629 struct bwn_dmadesc32 {
630 	uint32_t			control;
631 	uint32_t			address;
632 } __packed;
633 
634 #define	BWN_DMA64_DCTL0_DTABLEEND	0x10000000
635 #define	BWN_DMA64_DCTL0_IRQ		0x20000000
636 #define	BWN_DMA64_DCTL0_FRAMEEND	0x40000000
637 #define	BWN_DMA64_DCTL0_FRAMESTART	0x80000000
638 #define	BWN_DMA64_DCTL1_BYTECNT		0x00001fff
639 #define	BWN_DMA64_DCTL1_ADDREXT_MASK	0x00030000
640 #define	BWN_DMA64_DCTL1_ADDREXT_SHIFT	16
641 struct bwn_dmadesc64 {
642 	uint32_t			control0;
643 	uint32_t			control1;
644 	uint32_t			address_low;
645 	uint32_t			address_high;
646 } __packed;
647 
648 struct bwn_dmadesc_generic {
649 	union {
650 		struct bwn_dmadesc32 dma32;
651 		struct bwn_dmadesc64 dma64;
652 	} __packed dma;
653 } __packed;
654 
655 struct bwn_dma_ring;
656 
657 struct bwn_dma_ring {
658 	struct bwn_mac			*dr_mac;
659 	const struct bwn_dma_ops	*dr_ops;
660 	struct bwn_dmadesc_meta		*dr_meta;
661 	void				*dr_txhdr_cache;
662 	bus_dma_tag_t			dr_ring_dtag;
663 	bus_dma_tag_t			dr_txring_dtag;
664 	bus_dmamap_t			dr_spare_dmap; /* only for RX */
665 	bus_dmamap_t			dr_ring_dmap;
666 	bus_addr_t			dr_txring_paddr;
667 	void				*dr_ring_descbase;
668 	bus_addr_t			dr_ring_dmabase;
669 	int				dr_numslots;
670 	int				dr_usedslot;
671 	int				dr_curslot;
672 	uint32_t			dr_frameoffset;
673 	uint16_t			dr_rx_bufsize;
674 	uint16_t			dr_base;
675 	int				dr_index;
676 	uint8_t				dr_tx;
677 	uint8_t				dr_stop;
678 	int				dr_type;
679 
680 	void				(*getdesc)(struct bwn_dma_ring *,
681 					    int, struct bwn_dmadesc_generic **,
682 					    struct bwn_dmadesc_meta **);
683 	void				(*setdesc)(struct bwn_dma_ring *,
684 					    struct bwn_dmadesc_generic *,
685 					    bus_addr_t, uint16_t, int, int,
686 					    int);
687 	void				(*start_transfer)(struct bwn_dma_ring *,
688 					    int);
689 	void				(*suspend)(struct bwn_dma_ring *);
690 	void				(*resume)(struct bwn_dma_ring *);
691 	int				(*get_curslot)(struct bwn_dma_ring *);
692 	void				(*set_curslot)(struct bwn_dma_ring *,
693 					    int);
694 };
695 
696 struct bwn_dma {
697 	bus_dma_tag_t			parent_dtag;
698 	bus_dma_tag_t			rxbuf_dtag;
699 	bus_dma_tag_t			txbuf_dtag;
700 	struct bhnd_dma_translation	translation;
701 	u_int				addrext_shift;
702 
703 	struct bwn_dma_ring		*wme[5];
704 	struct bwn_dma_ring		*mcast;
705 	struct bwn_dma_ring		*rx;
706 	uint64_t			lastseq;	/* XXX FIXME */
707 };
708 
709 struct bwn_pio_rxqueue {
710 	struct bwn_mac			*prq_mac;
711 	uint16_t			prq_base;
712 	uint8_t				prq_rev;
713 };
714 
715 struct bwn_pio_txqueue;
716 struct bwn_pio_txpkt {
717 	struct bwn_pio_txqueue		*tp_queue;
718 	struct ieee80211_node		*tp_ni;
719 	struct mbuf			*tp_m;
720 	uint8_t				tp_index;
721 	TAILQ_ENTRY(bwn_pio_txpkt)	tp_list;
722 };
723 
724 #define	BWN_PIO_MAX_TXPACKETS		32
725 struct bwn_pio_txqueue {
726 	uint16_t			tq_base;
727 	uint16_t			tq_size;
728 	uint16_t			tq_used;
729 	uint16_t			tq_free;
730 	uint8_t				tq_index;
731 	struct bwn_pio_txpkt		tq_pkts[BWN_PIO_MAX_TXPACKETS];
732 	TAILQ_HEAD(, bwn_pio_txpkt)	tq_pktlist;
733 };
734 
735 struct bwn_pio {
736 	struct bwn_pio_txqueue		wme[5];
737 	struct bwn_pio_txqueue		mcast;
738 	struct bwn_pio_rxqueue		rx;
739 };
740 
741 struct bwn_plcp4 {
742 	union {
743 		uint32_t		data;
744 		uint8_t			raw[4];
745 	} __packed o;
746 } __packed;
747 
748 struct bwn_plcp6 {
749 	union {
750 		uint32_t		data;
751 		uint8_t			raw[6];
752 	} __packed o;
753 } __packed;
754 
755 struct bwn_txhdr {
756 	uint32_t			macctl;
757 	uint8_t				macfc[2];
758 	uint16_t			tx_festime;
759 	uint16_t			phyctl;
760 	uint16_t			phyctl_1;
761 	uint16_t			phyctl_1fb;
762 	uint16_t			phyctl_1rts;
763 	uint16_t			phyctl_1rtsfb;
764 	uint8_t				phyrate;
765 	uint8_t				phyrate_rts;
766 	uint8_t				eftypes;	/* extra frame types */
767 	uint8_t				chan;
768 	uint8_t				iv[16];
769 	uint8_t				addr1[IEEE80211_ADDR_LEN];
770 	uint16_t			tx_festime_fb;
771 	struct bwn_plcp6		rts_plcp_fb;
772 	uint16_t			rts_dur_fb;
773 	struct bwn_plcp6		plcp_fb;
774 	uint16_t			dur_fb;
775 	uint16_t			mimo_modelen;
776 	uint16_t			mimo_ratelen_fb;
777 	uint32_t			timeout;
778 
779 	union {
780 		/* format <= r351 */
781 		struct {
782 			uint8_t		pad0[2];
783 			uint16_t	cookie;
784 			uint16_t	tx_status;
785 			struct bwn_plcp6	rts_plcp;
786 			uint8_t		rts_frame[16];
787 			uint8_t		pad1[2];
788 			struct bwn_plcp6	plcp;
789 		} __packed r351;
790 		/* format > r410 < r598 */
791 		struct {
792 			uint16_t	mimo_antenna;
793 			uint16_t	preload_size;
794 			uint8_t		pad0[2];
795 			uint16_t	cookie;
796 			uint16_t	tx_status;
797 			struct bwn_plcp6	rts_plcp;
798 			uint8_t		rts_frame[16];
799 			uint8_t		pad1[2];
800 			struct bwn_plcp6	plcp;
801 		} __packed r410;
802 		struct {
803 			uint16_t	mimo_antenna;
804 			uint16_t	preload_size;
805 			uint8_t		pad0[2];
806 			uint16_t	cookie;
807 			uint16_t	tx_status;
808 			uint16_t	max_n_mpdus;
809 			uint16_t	max_a_bytes_mrt;
810 			uint16_t	max_a_bytes_fbr;
811 			uint16_t	min_m_bytes;
812 			struct bwn_plcp6	rts_plcp;
813 			uint8_t		rts_frame[16];
814 			uint8_t		pad1[2];
815 			struct bwn_plcp6	plcp;
816 		} __packed r598;
817 	} __packed body;
818 } __packed;
819 
820 #define	BWN_FWTYPE_UCODE		'u'
821 #define	BWN_FWTYPE_PCM			'p'
822 #define	BWN_FWTYPE_IV			'i'
823 struct bwn_fwhdr {
824 	uint8_t				type;
825 	uint8_t				ver;
826 	uint8_t				pad[2];
827 	uint32_t			size;
828 } __packed;
829 
830 #define	BWN_FWINITVALS_OFFSET_MASK	0x7fff
831 #define	BWN_FWINITVALS_32BIT		0x8000
832 struct bwn_fwinitvals {
833 	uint16_t			offset_size;
834 	union {
835 		uint16_t		d16;
836 		uint32_t		d32;
837 	} __packed data;
838 } __packed;
839 
840 enum bwn_fw_hdr_format {
841 	BWN_FW_HDR_598,
842 	BWN_FW_HDR_410,
843 	BWN_FW_HDR_351,
844 };
845 
846 enum bwn_fwtype {
847 	BWN_FWTYPE_DEFAULT,
848 	BWN_FWTYPE_OPENSOURCE,
849 	BWN_NR_FWTYPES,
850 };
851 
852 struct bwn_fwfile {
853 	const char			*filename;
854 	const struct firmware		*fw;
855 	enum bwn_fwtype			type;
856 };
857 
858 struct bwn_key {
859 	void				*keyconf;
860 	uint8_t				algorithm;
861 };
862 
863 struct bwn_fw {
864 	struct bwn_fwfile		ucode;
865 	struct bwn_fwfile		pcm;
866 	struct bwn_fwfile		initvals;
867 	struct bwn_fwfile		initvals_band;
868 	enum bwn_fw_hdr_format		fw_hdr_format;
869 
870 	uint16_t			rev;
871 	uint16_t			patch;
872 	uint8_t				opensource;
873 	uint8_t				no_pcmfile;
874 };
875 
876 struct bwn_lo_g_sm {
877 	int				curstate;
878 	int				nmeasure;
879 	int				multipler;
880 	uint16_t			feedth;
881 	struct bwn_loctl		loctl;
882 };
883 
884 struct bwn_lo_g_value {
885 	uint8_t				old_channel;
886 	uint16_t			phy_lomask;
887 	uint16_t			phy_extg;
888 	uint16_t			phy_dacctl_hwpctl;
889 	uint16_t			phy_dacctl;
890 	uint16_t			phy_hpwr_tssictl;
891 	uint16_t			phy_analogover;
892 	uint16_t			phy_analogoverval;
893 	uint16_t			phy_rfover;
894 	uint16_t			phy_rfoverval;
895 	uint16_t			phy_classctl;
896 	uint16_t			phy_crs0;
897 	uint16_t			phy_pgactl;
898 	uint16_t			phy_syncctl;
899 	uint16_t			phy_cck0;
900 	uint16_t			phy_cck1;
901 	uint16_t			phy_cck2;
902 	uint16_t			phy_cck3;
903 	uint16_t			phy_cck4;
904 	uint16_t			reg0;
905 	uint16_t			reg1;
906 	uint16_t			rf0;
907 	uint16_t			rf1;
908 	uint16_t			rf2;
909 };
910 
911 #define	BWN_LED_MAX			4
912 
913 #define	BWN_LED_EVENT_NONE		-1
914 #define	BWN_LED_EVENT_POLL		0
915 #define	BWN_LED_EVENT_TX		1
916 #define	BWN_LED_EVENT_RX		2
917 #define	BWN_LED_SLOWDOWN(dur)		(dur) = (((dur) * 3) / 2)
918 
919 struct bwn_led {
920 	uint8_t				led_flags;	/* BWN_LED_F_ */
921 	uint8_t				led_act;	/* BWN_LED_ACT_ */
922 	uint8_t				led_mask;
923 };
924 
925 #define	BWN_LED_F_ACTLOW		0x1
926 #define	BWN_LED_F_BLINK			0x2
927 #define	BWN_LED_F_POLLABLE		0x4
928 #define	BWN_LED_F_SLOW			0x8
929 
930 struct bwn_mac {
931 	struct bwn_softc		*mac_sc;
932 	unsigned			mac_status;
933 #define	BWN_MAC_STATUS_UNINIT		0
934 #define	BWN_MAC_STATUS_INITED		1
935 #define	BWN_MAC_STATUS_STARTED		2
936 	unsigned			mac_flags;
937 	/* use "Bad Frames Preemption" */
938 #define	BWN_MAC_FLAG_BADFRAME_PREEMP	(1 << 0)
939 #define	BWN_MAC_FLAG_DFQVALID		(1 << 1)
940 #define	BWN_MAC_FLAG_RADIO_ON		(1 << 2)
941 #define	BWN_MAC_FLAG_DMA		(1 << 3)
942 #define	BWN_MAC_FLAG_WME		(1 << 4)
943 #define	BWN_MAC_FLAG_HWCRYPTO		(1 << 5)
944 
945 	struct resource			*mac_res_irq;
946 	int				 mac_rid_irq;
947 	void				*mac_intrhand;
948 
949 	struct bwn_noise		mac_noise;
950 	struct bwn_phy			mac_phy;
951 	struct bwn_stats		mac_stats;
952 	uint32_t			mac_reason_intr;
953 	uint32_t			mac_reason[6];
954 	uint32_t			mac_intr_mask;
955 	int				mac_suspended;
956 
957 	struct bwn_fw			mac_fw;
958 
959 	int				mac_dmatype;
960 	union {
961 		struct bwn_dma		dma;
962 		struct bwn_pio		pio;
963 	} mac_method;
964 
965 	uint16_t			mac_ktp;	/* Key table pointer */
966 	uint8_t				mac_max_nr_keys;
967 	struct bwn_key			mac_key[58];
968 
969 	unsigned int			mac_task_state;
970 	struct task			mac_intrtask;
971 	struct task			mac_hwreset;
972 	struct task			mac_txpower;
973 
974 	TAILQ_ENTRY(bwn_mac)	mac_list;
975 };
976 
977 static inline int
978 bwn_tx_hdrsize(struct bwn_mac *mac)
979 {
980 	switch (mac->mac_fw.fw_hdr_format) {
981 	case BWN_FW_HDR_598:
982 		return (112 + (sizeof(struct bwn_plcp6)));
983 	case BWN_FW_HDR_410:
984 		return (104 + (sizeof(struct bwn_plcp6)));
985 	case BWN_FW_HDR_351:
986 		return (100 + (sizeof(struct bwn_plcp6)));
987 	default:
988 		printf("%s: unknown header format (%d)\n", __func__,
989 		    mac->mac_fw.fw_hdr_format);
990 		return (112 + (sizeof(struct bwn_plcp6)));
991 	}
992 }
993 
994 /*
995  * Driver-specific vap state.
996  */
997 struct bwn_vap {
998 	struct ieee80211vap		bv_vap;	/* base class */
999 	int				(*bv_newstate)(struct ieee80211vap *,
1000 					    enum ieee80211_state, int);
1001 };
1002 #define	BWN_VAP(vap)			((struct bwn_vap *)(vap))
1003 #define	BWN_VAP_CONST(vap)		((const struct mwl_vap *)(vap))
1004 
1005 enum bwn_quirk {
1006 	/**
1007 	 * The ucode PCI slowclock workaround is required on this device.
1008 	 * @see BWN_HF_PCI_SLOWCLOCK_WORKAROUND.
1009 	 */
1010 	BWN_QUIRK_UCODE_SLOWCLOCK_WAR	= (1<<0),
1011 
1012 	/**
1013 	 * DMA is unsupported on this device; PIO should be used instead.
1014 	 */
1015 	BWN_QUIRK_NODMA			= (1<<1),
1016 };
1017 
1018 struct bwn_softc {
1019 	device_t			sc_dev;
1020 	struct bhnd_board_info		sc_board_info;
1021 	struct bhnd_chipid		sc_cid;
1022 	uint32_t			sc_quirks;	/**< @see bwn_quirk */
1023 	struct resource			*sc_mem_res;
1024 	int				sc_mem_rid;
1025 
1026 	device_t			sc_chipc;	/**< ChipCommon device */
1027 	device_t			sc_gpio;	/**< GPIO device */
1028 	device_t			sc_pmu;		/**< PMU device, or NULL if unsupported */
1029 
1030 	struct mtx			sc_mtx;
1031 	struct ieee80211com		sc_ic;
1032 	struct mbufq			sc_snd;
1033 	unsigned			sc_flags;
1034 #define	BWN_FLAG_ATTACHED		(1 << 0)
1035 #define	BWN_FLAG_INVALID		(1 << 1)
1036 #define	BWN_FLAG_NEED_BEACON_TP		(1 << 2)
1037 #define	BWN_FLAG_RUNNING		(1 << 3)
1038 	unsigned			sc_debug;
1039 
1040 	struct bwn_mac		*sc_curmac;
1041 	TAILQ_HEAD(, bwn_mac)	sc_maclist;
1042 
1043 	uint8_t				sc_bssid[IEEE80211_ADDR_LEN];
1044 	unsigned int			sc_filters;
1045 	uint8_t				sc_beacons[2];
1046 	uint8_t				sc_rf_enabled;
1047 
1048 	struct wmeParams		sc_wmeParams[4];
1049 
1050 	struct callout			sc_rfswitch_ch;	/* for laptop */
1051 	struct callout			sc_task_ch;
1052 	struct callout			sc_watchdog_ch;
1053 	int				sc_watchdog_timer;
1054 	struct taskqueue		*sc_tq;	/* private task queue */
1055 	int				(*sc_newstate)(struct ieee80211com *,
1056 					    enum ieee80211_state, int);
1057 	void				(*sc_node_cleanup)(
1058 					    struct ieee80211_node *);
1059 
1060 	int				sc_rx_rate;
1061 	int				sc_tx_rate;
1062 
1063 	int				sc_led_blinking;
1064 	int				sc_led_ticks;
1065 	struct bwn_led			*sc_blink_led;
1066 	struct callout			sc_led_blink_ch;
1067 	int				sc_led_blink_offdur;
1068 	struct bwn_led			sc_leds[BWN_LED_MAX];
1069 	int				sc_led_idle;
1070 	int				sc_led_blink;
1071 
1072 	uint8_t				sc_ant2g;	/**< available 2GHz antennas */
1073 	uint8_t				sc_ant5g;	/**< available 5GHz antennas */
1074 
1075 	struct bwn_tx_radiotap_header	sc_tx_th;
1076 	struct bwn_rx_radiotap_header	sc_rx_th;
1077 };
1078 
1079 #define	BWN_LOCK_INIT(sc) \
1080 	mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->sc_dev), \
1081 	    MTX_NETWORK_LOCK, MTX_DEF)
1082 #define	BWN_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->sc_mtx)
1083 #define	BWN_LOCK(sc)		mtx_lock(&(sc)->sc_mtx)
1084 #define	BWN_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
1085 #define	BWN_ASSERT_LOCKED(sc)	mtx_assert(&(sc)->sc_mtx, MA_OWNED)
1086 
1087 static inline bwn_band_t
1088 bwn_channel_band(struct bwn_mac *mac, struct ieee80211_channel *c)
1089 {
1090 	if (IEEE80211_IS_CHAN_5GHZ(c))
1091 		return BWN_BAND_5G;
1092 	/* XXX check 2g, log error if not 2g or 5g? */
1093 	return BWN_BAND_2G;
1094 }
1095 
1096 static inline bwn_band_t
1097 bwn_current_band(struct bwn_mac *mac)
1098 {
1099 	struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1100 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
1101 		return BWN_BAND_5G;
1102 	/* XXX check 2g, log error if not 2g or 5g? */
1103 	return BWN_BAND_2G;
1104 }
1105 
1106 static inline bool
1107 bwn_is_40mhz(struct bwn_mac *mac)
1108 {
1109 	struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1110 
1111 	return !! (IEEE80211_IS_CHAN_HT40(ic->ic_curchan));
1112 }
1113 
1114 static inline int
1115 bwn_get_centre_freq(struct bwn_mac *mac)
1116 {
1117 
1118 	struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1119 	/* XXX TODO: calculate correctly for HT40 mode */
1120 	return ic->ic_curchan->ic_freq;
1121 }
1122 
1123 static inline int
1124 bwn_get_chan_centre_freq(struct bwn_mac *mac, struct ieee80211_channel *chan)
1125 {
1126 
1127 	/* XXX TODO: calculate correctly for HT40 mode */
1128 	return chan->ic_freq;
1129 }
1130 
1131 static inline int
1132 bwn_get_chan(struct bwn_mac *mac)
1133 {
1134 
1135 	struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1136 	/* XXX TODO: calculate correctly for HT40 mode */
1137 	return ic->ic_curchan->ic_ieee;
1138 }
1139 
1140 static inline struct ieee80211_channel *
1141 bwn_get_channel(struct bwn_mac *mac)
1142 {
1143 
1144 	struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1145 	return ic->ic_curchan;
1146 }
1147 
1148 static inline bool
1149 bwn_is_chan_passive(struct bwn_mac *mac)
1150 {
1151 
1152 	struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1153 	return !! IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan);
1154 }
1155 
1156 static inline bwn_chan_type_t
1157 bwn_get_chan_type(struct bwn_mac *mac, struct ieee80211_channel *c)
1158 {
1159 	struct ieee80211com *ic = &mac->mac_sc->sc_ic;
1160 	if (c == NULL)
1161 		c = ic->ic_curchan;
1162 	if (IEEE80211_IS_CHAN_HT40U(c))
1163 		return BWN_CHAN_TYPE_40_HT_U;
1164 	else if (IEEE80211_IS_CHAN_HT40D(c))
1165 		return BWN_CHAN_TYPE_40_HT_D;
1166 	else if (IEEE80211_IS_CHAN_HT20(c))
1167 		return BWN_CHAN_TYPE_20_HT;
1168 	else
1169 		return BWN_CHAN_TYPE_20;
1170 }
1171 
1172 static inline int
1173 bwn_get_chan_power(struct bwn_mac *mac, struct ieee80211_channel *c)
1174 {
1175 
1176 	/* return in dbm */
1177 	return c->ic_maxpower / 2;
1178 }
1179 
1180 #endif	/* !_IF_BWNVAR_H */
1181