summaryrefslogtreecommitdiff
path: root/sys/dev/ic/athnvar.h
blob: db6bdf443043169fe97bcc1fdc686aa60598eb60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
/*	$OpenBSD: athnvar.h,v 1.42 2021/04/15 18:25:43 stsp Exp $	*/

/*-
 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifdef notyet
#define ATHN_BT_COEXISTENCE	1
#endif

#ifdef ATHN_DEBUG
#define DPRINTF(x)	do { if (athn_debug > 0) printf x; } while (0)
#define DPRINTFN(n, x)	do { if (athn_debug >= (n)) printf x; } while (0)
extern int athn_debug;
#else
#define DPRINTF(x)
#define DPRINTFN(n, x)
#endif

#define LE_READ_4(p)	((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24)
#define LE_READ_2(p)	((p)[0] | (p)[1] << 8)

#define ATHN_RXBUFSZ	3872
#define ATHN_TXBUFSZ	4096

#define ATHN_NRXBUFS	64
#define ATHN_NTXBUFS	64	/* Shared between all Tx queues. */

struct athn_rx_radiotap_header {
	struct ieee80211_radiotap_header wr_ihdr;
	uint64_t	wr_tsft;
	uint8_t		wr_flags;
	uint8_t		wr_rate;
	uint16_t	wr_chan_freq;
	uint16_t	wr_chan_flags;
	int8_t		wr_dbm_antsignal;
	uint8_t		wr_antenna;
} __packed;

#define ATHN_RX_RADIOTAP_PRESENT						\
	(1 << IEEE80211_RADIOTAP_TSFT |					\
	 1 << IEEE80211_RADIOTAP_FLAGS |				\
	 1 << IEEE80211_RADIOTAP_RATE |					\
	 1 << IEEE80211_RADIOTAP_CHANNEL |				\
	 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL |			\
	 1 << IEEE80211_RADIOTAP_ANTENNA)

struct athn_tx_radiotap_header {
	struct ieee80211_radiotap_header wt_ihdr;
	uint8_t		wt_flags;
	uint8_t		wt_rate;
	uint16_t	wt_chan_freq;
	uint16_t	wt_chan_flags;
} __packed;

#define ATHN_TX_RADIOTAP_PRESENT						\
	(1 << IEEE80211_RADIOTAP_FLAGS |				\
	 1 << IEEE80211_RADIOTAP_RATE |					\
	 1 << IEEE80211_RADIOTAP_CHANNEL)

struct athn_tx_buf {
	SIMPLEQ_ENTRY(athn_tx_buf)	bf_list;

	void				*bf_descs;
	bus_dmamap_t			bf_map;
	bus_addr_t			bf_daddr;

	struct mbuf			*bf_m;
	struct ieee80211_node		*bf_ni;
	int				bf_txmcs;
	int				bf_txflags;
#define ATHN_TXFLAG_PAPRD	(1 << 0)
#define ATHN_TXFLAG_CAB		(1 << 1) 
};

struct athn_txq {
	SIMPLEQ_HEAD(, athn_tx_buf)	head;
	void				*lastds;
	struct athn_tx_buf		*wait;
	int				queued;
};

struct athn_rx_buf {
	SIMPLEQ_ENTRY(athn_rx_buf)	bf_list;

	void				*bf_desc;
	bus_dmamap_t			bf_map;

	struct mbuf			*bf_m;
	bus_addr_t			bf_daddr;
};

struct athn_rxq {
	struct athn_rx_buf		*bf;

	void				*descs;
	void				*lastds;
	bus_dmamap_t			map;
	bus_dma_segment_t		seg;
	int				count;

	SIMPLEQ_HEAD(, athn_rx_buf)	head;
};

/* Software rate indexes. */
#define ATHN_RIDX_CCK1	0
#define ATHN_RIDX_CCK2	1
#define ATHN_RIDX_OFDM6	4
#define ATHN_RIDX_MCS0	12
#define ATHN_RIDX_MCS8	(ATHN_RIDX_MCS0 + 8)
#define ATHN_RIDX_MCS15	27
#define ATHN_RIDX_MAX	27
#define ATHN_MCS_MAX	15
#define ATHN_NUM_MCS	(ATHN_MCS_MAX + 1)
#define ATHN_IS_HT_RIDX(ridx)	((ridx) >= ATHN_RIDX_MCS0)
#define ATHN_IS_MIMO_RIDX(ridx)	((ridx) >= ATHN_RIDX_MCS8)

static const struct athn_rate {
	uint16_t	rate;		/* Rate in 500Kbps unit. */
	uint8_t		hwrate;		/* HW representation. */
	uint8_t		rspridx;	/* Control Response Frame rate index. */
	enum	ieee80211_phytype phy;
} athn_rates[] = {
	{    2, 0x1b, 0, IEEE80211_T_DS },
	{    4, 0x1a, 1, IEEE80211_T_DS },
	{   11, 0x19, 1, IEEE80211_T_DS },
	{   22, 0x18, 1, IEEE80211_T_DS },
	{   12, 0x0b, 4, IEEE80211_T_OFDM },
	{   18, 0x0f, 4, IEEE80211_T_OFDM },
	{   24, 0x0a, 6, IEEE80211_T_OFDM },
	{   36, 0x0e, 6, IEEE80211_T_OFDM },
	{   48, 0x09, 8, IEEE80211_T_OFDM },
	{   72, 0x0d, 8, IEEE80211_T_OFDM },
	{   96, 0x08, 8, IEEE80211_T_OFDM },
	{  108, 0x0c, 8, IEEE80211_T_OFDM },
	{   13, 0x80, 4, IEEE80211_T_OFDM },
	{   26, 0x81, 6, IEEE80211_T_OFDM },
	{   39, 0x82, 6, IEEE80211_T_OFDM },
	{   52, 0x83, 8, IEEE80211_T_OFDM },
	{   78, 0x84, 8, IEEE80211_T_OFDM },
	{  104, 0x85, 8, IEEE80211_T_OFDM },
	{  117, 0x86, 8, IEEE80211_T_OFDM },
	{  130, 0x87, 8, IEEE80211_T_OFDM },
	{   26, 0x88, 4, IEEE80211_T_OFDM },
	{   52, 0x89, 6, IEEE80211_T_OFDM },
	{   78, 0x8a, 8, IEEE80211_T_OFDM },
	{  104, 0x8b, 8, IEEE80211_T_OFDM },
	{  156, 0x8c, 8, IEEE80211_T_OFDM },
	{  208, 0x8d, 8, IEEE80211_T_OFDM },
	{  234, 0x8e, 8, IEEE80211_T_OFDM },
	{  260, 0x8f, 8, IEEE80211_T_OFDM }
};

struct athn_series {
	uint16_t	dur;
	uint8_t		hwrate;
};

struct athn_pier {
	uint8_t		fbin;
	const uint8_t	*pwr[AR_PD_GAINS_IN_MASK];
	const uint8_t	*vpd[AR_PD_GAINS_IN_MASK];
};

/*
 * Structures used to store initialization values.
 */
struct athn_ini {
	int		nregs;
	const uint16_t	*regs;
	const uint32_t	*vals_5g20;
	const uint32_t	*vals_5g40;
	const uint32_t	*vals_2g40;
	const uint32_t	*vals_2g20;
	int		ncmregs;
	const uint16_t	*cmregs;
	const uint32_t	*cmvals;
	int		nfastregs;
	const uint16_t	*fastregs;
	const uint32_t	*fastvals_5g20;
	const uint32_t	*fastvals_5g40;
};

struct athn_gain {
	int		nregs;
	const uint16_t	*regs;
	const uint32_t	*vals_5g;
	const uint32_t	*vals_2g;
};

struct athn_addac {
	int		nvals;
	const uint32_t	*vals;
};

struct athn_serdes {
	int		nvals;
	const uint32_t	*regs;
	const uint32_t	*vals;
};

/* Rx queue software indexes. */
#define ATHN_QID_LP		0
#define ATHN_QID_HP		1

/* Tx queue software indexes. */
#define ATHN_QID_AC_BE		0
#define ATHN_QID_PSPOLL		1
#define ATHN_QID_AC_BK		2
#define ATHN_QID_AC_VI		3
#define ATHN_QID_AC_VO		4
#define ATHN_QID_UAPSD		5
#define ATHN_QID_CAB		6
#define ATHN_QID_BEACON		7
#define ATHN_QID_COUNT		8

/* Map Access Category to Tx queue Id. */
static const uint8_t athn_ac2qid[EDCA_NUM_AC] = {
	ATHN_QID_AC_BE,	/* EDCA_AC_BE */
	ATHN_QID_AC_BK,	/* EDCA_AC_BK */
	ATHN_QID_AC_VI,	/* EDCA_AC_VI */
	ATHN_QID_AC_VO	/* EDCA_AC_VO */
};

static const uint8_t athn_5ghz_chans[] = {
	/* UNII 1. */
	36, 40, 44, 48,
	/* UNII 2. */
	52, 56, 60, 64,
	/* Middle band. */
	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
	/* UNII 3. */
	149, 153, 157, 161, 165
};

/* Number of data bits per OFDM symbol for MCS[0-15]. */
/* See tables 20-29, 20-30, 20-33, 20-34. */
static const uint16_t ar_mcs_ndbps[][2] = {
	/* 20MHz  40MHz */
	{     26,    54 },	/* MCS0 */
	{     52,   108 },	/* MCS1 */
	{     78,   162 },	/* MCS2 */
	{    104,   216 },	/* MCS3 */
	{    156,   324 },	/* MCS4 */
	{    208,   432 },	/* MCS5 */
	{    234,   486 },	/* MCS6 */
	{    260,   540 },	/* MCS7 */
	{     26,   108 },	/* MCS8 */
	{     52,   216 },	/* MCS9 */
	{     78,   324 },	/* MCS10 */
	{    104,   432 },	/* MCS11 */
	{    156,   648 },	/* MCS12 */
	{    208,   864 },	/* MCS13 */
	{    234,   972 },	/* MCS14 */
	{    260,  1080 }	/* MCS15 */
};

#define ATHN_POWER_OFDM6	0
#define ATHN_POWER_OFDM9	1
#define ATHN_POWER_OFDM12	2
#define ATHN_POWER_OFDM18	3
#define ATHN_POWER_OFDM24	4
#define ATHN_POWER_OFDM36	5
#define ATHN_POWER_OFDM48	6
#define ATHN_POWER_OFDM54	7
#define ATHN_POWER_CCK1_LP	8
#define ATHN_POWER_CCK2_LP	9
#define ATHN_POWER_CCK2_SP	10
#define ATHN_POWER_CCK55_LP	11
#define ATHN_POWER_CCK55_SP	12
#define ATHN_POWER_CCK11_LP	13
#define ATHN_POWER_CCK11_SP	14
#define ATHN_POWER_XR		15
#define ATHN_POWER_HT20(mcs)	(16 + (mcs))
#define ATHN_POWER_HT40(mcs)	(40 + (mcs))
#define ATHN_POWER_CCK_DUP	64
#define ATHN_POWER_OFDM_DUP	65
#define ATHN_POWER_CCK_EXT	66
#define ATHN_POWER_OFDM_EXT	67
#define ATHN_POWER_COUNT	68

#define ATHN_NUM_LEGACY_RATES	IEEE80211_RATE_MAXSIZE
#define ATHN_NUM_RATES		(ATHN_NUM_LEGACY_RATES + ATHN_NUM_MCS)
struct athn_node {
	struct ieee80211_node		ni;
	struct ieee80211_amrr_node	amn;
	struct ieee80211_ra_node	rn;
	uint8_t				ridx[ATHN_NUM_RATES];
	uint8_t				fallback[ATHN_NUM_RATES];
	uint8_t				sta_index;
};

/*
 * Adaptive noise immunity state.
 */
#define ATHN_ANI_PERIOD		100
#define ATHN_ANI_RSSI_THR_HIGH	40
#define ATHN_ANI_RSSI_THR_LOW	7
struct athn_ani {
	uint8_t		noise_immunity_level;
	uint8_t		spur_immunity_level;
	uint8_t		firstep_level;
	uint8_t		ofdm_weak_signal;
	uint8_t		cck_weak_signal;

	uint32_t	listen_time;

	uint32_t	ofdm_trig_high;
	uint32_t	ofdm_trig_low;

	int32_t		cck_trig_high;
	int32_t		cck_trig_low;

	uint32_t	ofdm_phy_err_base;
	uint32_t	cck_phy_err_base;
	uint32_t	ofdm_phy_err_count;
	uint32_t	cck_phy_err_count;

	uint32_t	cyccnt;
	uint32_t	txfcnt;
	uint32_t	rxfcnt;
};

struct athn_iq_cal {
	uint32_t	pwr_meas_i;
	uint32_t	pwr_meas_q;
	int32_t		iq_corr_meas;
};

struct athn_adc_cal {
	uint32_t	pwr_meas_odd_i;
	uint32_t	pwr_meas_even_i;
	uint32_t	pwr_meas_odd_q;
	uint32_t	pwr_meas_even_q;
};

struct athn_calib {
	int			nsamples;
	struct athn_iq_cal	iq[AR_MAX_CHAINS];
	struct athn_adc_cal	adc_gain[AR_MAX_CHAINS];
	struct athn_adc_cal	adc_dc_offset[AR_MAX_CHAINS];
};

#define ATHN_NF_CAL_HIST_MAX	5

struct athn_softc;

struct athn_ops {
	/* Bus callbacks. */
	uint32_t	(*read)(struct athn_softc *, uint32_t);
	void		(*write)(struct athn_softc *, uint32_t, uint32_t);
	void		(*write_barrier)(struct athn_softc *);

	void	(*setup)(struct athn_softc *);
	void	(*set_txpower)(struct athn_softc *, struct ieee80211_channel *,
		    struct ieee80211_channel *);
	void	(*spur_mitigate)(struct athn_softc *,
		    struct ieee80211_channel *, struct ieee80211_channel *);
	const struct ar_spur_chan *
		(*get_spur_chans)(struct athn_softc *, int);
	void	(*init_from_rom)(struct athn_softc *,
		    struct ieee80211_channel *, struct ieee80211_channel *);
	int	(*set_synth)(struct athn_softc *, struct ieee80211_channel *,
		    struct ieee80211_channel *);
	int	(*read_rom_data)(struct athn_softc *, uint32_t, void *, int);
	const uint8_t *
		(*get_rom_template)(struct athn_softc *, uint8_t);
	void	(*swap_rom)(struct athn_softc *);
	void	(*olpc_init)(struct athn_softc *);
	void	(*olpc_temp_compensation)(struct athn_softc *);
	/* GPIO callbacks. */
	int	(*gpio_read)(struct athn_softc *, int);
	void	(*gpio_write)(struct athn_softc *, int, int);
	void	(*gpio_config_input)(struct athn_softc *, int);
	void	(*gpio_config_output)(struct athn_softc *, int, int);
	void	(*rfsilent_init)(struct athn_softc *);
	/* DMA callbacks. */
	int	(*dma_alloc)(struct athn_softc *);
	void	(*dma_free)(struct athn_softc *);
	void	(*rx_enable)(struct athn_softc *);
	int	(*intr)(struct athn_softc *);
	int	(*tx)(struct athn_softc *, struct mbuf *,
		    struct ieee80211_node *, int);
	/* PHY callbacks. */
	void	(*set_rf_mode)(struct athn_softc *,
		    struct ieee80211_channel *);
	int	(*rf_bus_request)(struct athn_softc *);
	void	(*rf_bus_release)(struct athn_softc *);
	void	(*set_phy)(struct athn_softc *, struct ieee80211_channel *,
		    struct ieee80211_channel *);
	void	(*set_delta_slope)(struct athn_softc *,
		    struct ieee80211_channel *, struct ieee80211_channel *);
	void	(*enable_antenna_diversity)(struct athn_softc *);
	void	(*init_baseband)(struct athn_softc *);
	void	(*disable_phy)(struct athn_softc *);
	void	(*set_rxchains)(struct athn_softc *);
	void	(*noisefloor_calib)(struct athn_softc *);
	void	(*init_noisefloor_calib)(struct athn_softc *);
	int	(*get_noisefloor)(struct athn_softc *);
	void	(*apply_noisefloor)(struct athn_softc *);
	void	(*do_calib)(struct athn_softc *);
	void	(*next_calib)(struct athn_softc *);
	void	(*hw_init)(struct athn_softc *, struct ieee80211_channel *,
		    struct ieee80211_channel *);
	void	(*get_paprd_masks)(struct athn_softc *sc,
		    struct ieee80211_channel *, uint32_t *, uint32_t *);
	/* ANI callbacks. */
	void	(*set_noise_immunity_level)(struct athn_softc *, int);
	void	(*enable_ofdm_weak_signal)(struct athn_softc *);
	void	(*disable_ofdm_weak_signal)(struct athn_softc *);
	void	(*set_cck_weak_signal)(struct athn_softc *, int);
	void	(*set_firstep_level)(struct athn_softc *, int);
	void	(*set_spur_immunity_level)(struct athn_softc *, int);
};

struct athn_softc {
	struct device			sc_dev;
	struct ieee80211com		sc_ic;

	int				(*sc_enable)(struct athn_softc *);
	void				(*sc_disable)(struct athn_softc *);
	void				(*sc_power)(struct athn_softc *, int);
	void				(*sc_disable_aspm)(struct athn_softc *);
	void				(*sc_enable_extsynch)(
					    struct athn_softc *);

	int				(*sc_newstate)(struct ieee80211com *,
					    enum ieee80211_state, int);

	bus_dma_tag_t			sc_dmat;

	struct timeout			scan_to;
	struct timeout			calib_to;
	struct ieee80211_amrr		amrr;

	u_int				flags;
#define ATHN_FLAG_PCIE			(1 << 0)
#define ATHN_FLAG_USB			(1 << 1)
#define ATHN_FLAG_OLPC			(1 << 2)
#define ATHN_FLAG_PAPRD			(1 << 3)
#define ATHN_FLAG_FAST_PLL_CLOCK	(1 << 4)
#define ATHN_FLAG_RFSILENT		(1 << 5)
#define ATHN_FLAG_RFSILENT_REVERSED	(1 << 6)
#define ATHN_FLAG_BTCOEX2WIRE		(1 << 7)
#define ATHN_FLAG_BTCOEX3WIRE		(1 << 8)
/* Shortcut. */
#define ATHN_FLAG_BTCOEX	(ATHN_FLAG_BTCOEX2WIRE | ATHN_FLAG_BTCOEX3WIRE)
#define ATHN_FLAG_11A			(1 << 9)
#define ATHN_FLAG_11G			(1 << 10)
#define ATHN_FLAG_11N			(1 << 11)
#define ATHN_FLAG_AN_TOP2_FIXUP		(1 << 12)
#define ATHN_FLAG_NON_ENTERPRISE	(1 << 13)
#define ATHN_FLAG_3TREDUCE_CHAIN	(1 << 14)

	uint8_t				ngpiopins;
	int				led_pin;
	int				rfsilent_pin;
	int				led_state;
	uint32_t			isync;
	uint32_t			imask;

	uint16_t			mac_ver;
	uint8_t				mac_rev;
	uint8_t				rf_rev;
	uint16_t			eep_rev;

	uint8_t				txchainmask;
	uint8_t				rxchainmask;
	uint8_t				ntxchains;
	uint8_t				nrxchains;

	uint8_t				sup_calib_mask;
	uint8_t				cur_calib_mask;
#define ATHN_CAL_IQ		(1 << 0)
#define ATHN_CAL_ADC_GAIN	(1 << 1)
#define ATHN_CAL_ADC_DC		(1 << 2)
#define ATHN_CAL_TEMP		(1 << 3)

	struct ieee80211_channel	*curchan;
	struct ieee80211_channel	*curchanext;

	/* Open Loop Power Control. */
	int8_t				tx_gain_tbl[AR9280_TX_GAIN_TABLE_SIZE];
	int8_t				pdadc;
	int8_t				tcomp;
	int				olpc_ticks;
	int				iqcal_ticks;

	/* PA predistortion. */
	uint16_t			gain1[AR_MAX_CHAINS];
	uint32_t			txgain[AR9003_TX_GAIN_TABLE_SIZE];
	int16_t				pa_in[AR_MAX_CHAINS]
					     [AR9003_PAPRD_MEM_TAB_SIZE];
	int16_t				angle[AR_MAX_CHAINS]
					     [AR9003_PAPRD_MEM_TAB_SIZE];
	int32_t				trainpow;
	uint8_t				paprd_curchain;

	uint32_t			rwbuf[64];

	int				kc_entries;

	void				*eep;
	const void			*eep_def;
	uint32_t			eep_base;
	uint32_t			eep_size;

	struct athn_rxq			rxq[2];
	struct athn_txq			txq[31];

	void				*descs;
	bus_dmamap_t			map;
	bus_dma_segment_t		seg;
	SIMPLEQ_HEAD(, athn_tx_buf)	txbufs;
	struct athn_tx_buf		*bcnbuf;
	struct athn_tx_buf		txpool[ATHN_NTXBUFS];

	bus_dmamap_t			txsmap;
	bus_dma_segment_t		txsseg;
	void				*txsring;
	int				txscur;

	int				sc_if_flags;
	int				sc_tx_timer;

	const struct athn_ini		*ini;
	const struct athn_gain		*rx_gain;
	const struct athn_gain		*tx_gain;
	const struct athn_addac		*addac;
	const struct athn_serdes	*serdes;
	uint32_t			workaround;
	uint32_t			obs_off;
	uint32_t			gpio_input_en_off;

	struct athn_ops			ops;

	int				fixed_ridx;

	int16_t				cca_min_2g;
	int16_t				cca_max_2g;
	int16_t				cca_min_5g;
	int16_t				cca_max_5g;
	struct {
		int16_t	nf[AR_MAX_CHAINS];
		int16_t	nf_ext[AR_MAX_CHAINS];
	}				nf_hist[ATHN_NF_CAL_HIST_MAX];
	int				nf_hist_cur;
	int				nf_hist_nvalid;
	int16_t				nf_priv[AR_MAX_CHAINS];
	int16_t				nf_ext_priv[AR_MAX_CHAINS];
	int				nf_calib_pending;
	int				nf_calib_ticks;
	int				pa_calib_ticks;

	struct athn_calib		calib;
	struct athn_ani			ani;

#if NBPFILTER > 0
	caddr_t				sc_drvbpf;

	union {
		struct athn_rx_radiotap_header th;
		uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
	} sc_rxtapu;
#define sc_rxtap			sc_rxtapu.th
	int				sc_rxtap_len;

	union {
		struct athn_tx_radiotap_header th;
		uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
	} sc_txtapu;
#define sc_txtap			sc_txtapu.th
	int				sc_txtap_len;
#endif
};

extern int	athn_attach(struct athn_softc *);
extern void	athn_detach(struct athn_softc *);
extern void	athn_suspend(struct athn_softc *);
extern void	athn_wakeup(struct athn_softc *);
extern int	athn_intr(void *);