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