xref: /freebsd/sys/dev/iwn/if_iwnreg.h (revision 39beb93c)
1 /*	$FreeBSD$	*/
2 /*	$OpenBSD: if_iwnreg.h,v 1.9 2007/11/27 20:59:40 damien Exp $	*/
3 
4 /*-
5  * Copyright (c) 2007
6  *	Damien Bergamini <damien.bergamini@free.fr>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #define	EDCA_NUM_AC  4
22 
23 #define IWN_TX_RING_COUNT	256
24 #define IWN_RX_RING_COUNT	64
25 
26 #define IWN_NTXQUEUES		16
27 #define IWN_NTXCHAINS		2
28 
29 /*
30  * Rings must be aligned on a 256-byte boundary.
31  */
32 #define IWN_RING_DMA_ALIGN	256
33 
34 /* maximum scatter/gather */
35 #define IWN_MAX_SCATTER	20
36 
37 /* Rx buffers must be large enough to hold a full 4K A-MPDU */
38 #define IWN_RBUF_SIZE	(4 * 1024)
39 
40 /*
41  * Control and status registers.
42  */
43 #define IWN_HWCONFIG		0x000
44 #define IWN_INTR_MIT		0x004
45 #define IWN_INTR		0x008
46 #define IWN_MASK		0x00c
47 #define IWN_INTR_STATUS		0x010
48 #define IWN_RESET		0x020
49 #define IWN_GPIO_CTL		0x024
50 #define IWN_EEPROM_CTL		0x02c
51 #define IWN_UCODE_CLR		0x05c
52 #define IWN_CHICKEN		0x100
53 #define IWN_QUEUE_OFFSET(qid)	(0x380 + (qid) * 8)
54 #define IWN_MEM_WADDR		0x410
55 #define IWN_MEM_WDATA		0x418
56 #define IWN_WRITE_MEM_ADDR  	0x444
57 #define IWN_READ_MEM_ADDR   	0x448
58 #define IWN_WRITE_MEM_DATA  	0x44c
59 #define IWN_READ_MEM_DATA   	0x450
60 #define IWN_TX_WIDX		0x460
61 
62 #define IWN_KW_BASE		0x197c
63 #define IWN_TX_BASE(qid)	(0x19d0 + (qid) * 4)
64 #define IWN_RW_WIDX_PTR		0x1bc0
65 #define IWN_RX_BASE		0x1bc4
66 #define IWN_RX_WIDX		0x1bc8
67 #define IWN_RX_CONFIG		0x1c00
68 #define IWN_RX_STATUS		0x1c44
69 #define IWN_TX_CONFIG(qid)	(0x1d00 + (qid) * 32)
70 #define IWN_TX_STATUS		0x1eb0
71 
72 #define IWN_SRAM_BASE		0xa02c00
73 #define IWN_TX_ACTIVE		(IWN_SRAM_BASE + 0x01c)
74 #define IWN_QUEUE_RIDX(qid)	(IWN_SRAM_BASE + 0x064 + (qid) * 4)
75 #define IWN_SELECT_QCHAIN	(IWN_SRAM_BASE + 0x0d0)
76 #define IWN_QUEUE_INTR_MASK	(IWN_SRAM_BASE + 0x0e4)
77 #define IWN_TXQ_STATUS(qid)	(IWN_SRAM_BASE + 0x104 + (qid) * 4)
78 
79 /*
80  * NIC internal memory offsets.
81  */
82 #define IWN_CLOCK_CTL		0x3000
83 #define IWN_MEM_CLOCK2		0x3008
84 #define IWN_MEM_POWER		0x300c
85 #define IWN_MEM_PCIDEV		0x3010
86 #define IWN_MEM_UCODE_CTL	0x3400
87 #define IWN_MEM_UCODE_SRC	0x3404
88 #define IWN_MEM_UCODE_DST	0x3408
89 #define IWN_MEM_UCODE_SIZE	0x340c
90 #define IWN_MEM_TEXT_BASE	0x3490
91 #define IWN_MEM_TEXT_SIZE	0x3494
92 #define IWN_MEM_DATA_BASE	0x3498
93 #define IWN_MEM_DATA_SIZE	0x349c
94 #define IWN_MEM_UCODE_BASE	0x3800
95 
96 
97 /* possible flags for register IWN_HWCONFIG */
98 #define IWN_HW_EEPROM_LOCKED	(1 << 21)
99 
100 /* possible flags for registers IWN_READ_MEM_ADDR/IWN_WRITE_MEM_ADDR */
101 #define IWN_MEM_4	((sizeof (uint32_t) - 1) << 24)
102 
103 /* possible values for IWN_MEM_UCODE_DST */
104 #define IWN_FW_TEXT	0x00000000
105 
106 /* possible flags for register IWN_RESET */
107 #define IWN_NEVO_RESET		(1 << 0)
108 #define IWN_SW_RESET		(1 << 7)
109 #define IWN_MASTER_DISABLED	(1 << 8)
110 #define IWN_STOP_MASTER		(1 << 9)
111 
112 /* possible flags for register IWN_GPIO_CTL */
113 #define IWN_GPIO_CLOCK		(1 << 0)
114 #define IWN_GPIO_INIT		(1 << 2)
115 #define IWN_GPIO_MAC		(1 << 3)
116 #define IWN_GPIO_SLEEP		(1 << 4)
117 #define IWN_GPIO_PWR_STATUS	0x07000000
118 #define IWN_GPIO_PWR_SLEEP	(4 << 24)
119 #define IWN_GPIO_RF_ENABLED	(1 << 27)
120 
121 /* possible flags for register IWN_CHICKEN */
122 #define IWN_CHICKEN_DISLOS	(1 << 29)
123 
124 /* possible flags for register IWN_UCODE_CLR */
125 #define IWN_RADIO_OFF		(1 << 1)
126 #define IWN_DISABLE_CMD		(1 << 2)
127 #define IWN_CTEMP_STOP_RF	(1 << 3)
128 
129 /* possible flags for IWN_RX_STATUS */
130 #define	IWN_RX_IDLE	(1 << 24)
131 
132 /* possible flags for register IWN_UC_CTL */
133 #define IWN_UC_ENABLE	(1 << 30)
134 #define IWN_UC_RUN	(1 << 31)
135 
136 /* possible flags for register IWN_INTR */
137 #define IWN_ALIVE_INTR	(1 <<  0)
138 #define IWN_WAKEUP_INTR	(1 <<  1)
139 #define IWN_SW_RX_INTR	(1 <<  3)
140 #define IWN_CT_REACHED	(1 <<  6)
141 #define IWN_RF_TOGGLED	(1 <<  7)
142 #define IWN_SW_ERROR	(1 << 25)
143 #define IWN_TX_INTR	(1 << 27)
144 #define IWN_HW_ERROR	(1 << 29)
145 #define IWN_RX_INTR	(1 << 31)
146 
147 #define	IWN_INTR_BITS	"\20\1ALIVE\2WAKEUP\3SW_RX\6CT_REACHED\7RF_TOGGLED" \
148 	"\32SW_ERROR\34TX_INTR\36HW_ERROR\40RX_INTR"
149 
150 #define IWN_INTR_MASK							\
151 	(IWN_SW_ERROR | IWN_HW_ERROR | IWN_TX_INTR | IWN_RX_INTR |	\
152 	 IWN_ALIVE_INTR | IWN_WAKEUP_INTR | IWN_SW_RX_INTR |		\
153 	 IWN_CT_REACHED | IWN_RF_TOGGLED)
154 
155 /* possible flags for register IWN_INTR_STATUS */
156 #define IWN_STATUS_TXQ(x)	(1 << (x))
157 #define IWN_STATUS_RXQ(x)	(1 << ((x) + 16))
158 #define IWN_STATUS_PRI		(1 << 30)
159 /* shortcuts for the above */
160 #define IWN_TX_STATUS_INTR						\
161 	(IWN_STATUS_TXQ(0) | IWN_STATUS_TXQ(1) | IWN_STATUS_TXQ(6))
162 #define IWN_RX_STATUS_INTR						\
163 	(IWN_STATUS_RXQ(0) | IWN_STATUS_RXQ(1) | IWN_STATUS_RXQ(2) |	\
164 	 IWN_STATUS_PRI)
165 
166 /* possible flags for register IWN_TX_STATUS */
167 #define IWN_TX_IDLE(qid)	(1 << ((qid) + 24) | 1 << ((qid) + 16))
168 
169 /* possible flags/masks for register IWN_EEPROM_CTL */
170 #define IWN_EEPROM_READY	(1 << 0)
171 #define IWN_EEPROM_MSK		(1 << 1)
172 
173 /* possible flags for register IWN_TXQ_STATUS */
174 #define IWN_TXQ_STATUS_ACTIVE	0x0007fc01
175 
176 /* possible flags for register IWN_MEM_POWER */
177 #define IWN_POWER_RESET	(1 << 26)
178 
179 /* possible flags for register IWN_MEM_TEXT_SIZE */
180 #define IWN_FW_UPDATED	(1 << 31)
181 
182 /* possible flags for device-specific PCI register 0xe8 */
183 #define IWN_DIS_NOSNOOP	(1 << 11)
184 
185 /* possible flags for device-specific PCI register 0xf0 */
186 #define IWN_ENA_L1	(1 << 1)
187 
188 
189 #define IWN_TX_WINDOW	64
190 struct iwn_shared {
191 	uint16_t	len[IWN_NTXQUEUES][512];	/* 16KB total */
192 	uint16_t	closed_count;
193 	uint16_t	closed_rx_count;
194 	uint16_t	finished_count;
195 	uint16_t	finished_rx_count;
196 	uint32_t	reserved[2];
197 } __packed;
198 
199 struct iwn_tx_desc {
200 	uint32_t	flags;
201 	struct {
202 		uint32_t	w1;
203 		uint32_t	w2;
204 		uint32_t	w3;
205 	} __packed	segs[IWN_MAX_SCATTER / 2];
206 	/* pad to 128 bytes */
207 	uint32_t	reserved;
208 } __packed;
209 
210 #define IWN_SET_DESC_NSEGS(d, x)					\
211 	(d)->flags = htole32(((x) & 0x1f) << 24)
212 
213 /* set a segment physical address and length in a Tx descriptor */
214 #define IWN_SET_DESC_SEG(d, n, addr, size) do {				\
215 	if ((n) & 1) {							\
216 		(d)->segs[(n) / 2].w2 |=				\
217 		    htole32(((addr) & 0xffff) << 16);			\
218 		(d)->segs[(n) / 2].w3 =					\
219 		    htole32((((addr) >> 16) & 0xffff) | (size) << 20);	\
220 	} else {							\
221 		(d)->segs[(n) / 2].w1 = htole32(addr);			\
222 		(d)->segs[(n) / 2].w2 = htole32((size) << 4);		\
223 	}								\
224 } while (0)
225 
226 struct iwn_rx_desc {
227 	uint32_t	len;
228 	uint8_t		type;
229 #define IWN_UC_READY		  1
230 #define IWN_ADD_NODE_DONE	 24
231 #define IWN_TX_DONE		 28
232 #define IWN_START_SCAN		130
233 #define IWN_STOP_SCAN		132
234 #define IWN_RX_STATISTICS	156
235 #define IWN_BEACON_STATISTICS	157
236 #define IWN_STATE_CHANGED	161
237 #define IWN_BEACON_MISSED	162
238 #define IWN_AMPDU_RX_START	192
239 #define IWN_AMPDU_RX_DONE	193
240 #define IWN_RX_DONE		195
241 
242 	uint8_t		flags;
243 	uint8_t		idx;
244 	uint8_t		qid;
245 } __packed;
246 
247 /* possible Rx status flags */
248 #define IWN_RX_NO_CRC_ERR	(1 << 0)
249 #define IWN_RX_NO_OVFL_ERR	(1 << 1)
250 /* shortcut for the above */
251 #define IWN_RX_NOERROR	(IWN_RX_NO_CRC_ERR | IWN_RX_NO_OVFL_ERR)
252 
253 struct iwn_tx_cmd {
254 	uint8_t	code;
255 #define IWN_CMD_CONFIGURE		0x10	/* REPLY_RXON */
256 #define IWN_CMD_ASSOCIATE		0x11	/* REPLY_RXON_ASSOC */
257 #define IWN_CMD_EDCA_PARAMS		0x13	/* REPLY_QOS_PARAM */
258 #define IWN_CMD_TSF			0x14	/* REPLY_RXON_TIMING */
259 #define IWN_CMD_ADD_NODE		0x18	/* REPLY_ADD_STA */
260 #define IWN_CMD_TX_DATA			0x1c	/* REPLY_TX */
261 #define IWN_CMD_TX_LINK_QUALITY		0x4e	/* REPLY_TX_LINK_QUALITY_CMD */
262 #define IWN_CMD_SET_LED			0x48	/* REPLY_LEDS_CMD */
263 #define IWN_CMD_SET_POWER_MODE		0x77	/* POWER_TABLE_CMD */
264 #define IWN_CMD_SCAN			0x80	/* REPLY_SCAN_CMD */
265 #define IWN_CMD_TXPOWER			0x97	/* REPLY_TX_PWR_TABLE_CMD */
266 #define IWN_CMD_BLUETOOTH		0x9b	/* REPLY_BT_CONFIG */
267 #define IWN_CMD_GET_STATISTICS		0x9c	/* REPLY_STATISTICS_CMD */
268 #define IWN_CMD_SET_CRITICAL_TEMP	0xa4	/* REPLY_CT_KILL_CONFIG_CMD */
269 #define IWN_SENSITIVITY			0xa8	/* SENSITIVITY_CMD */
270 #define IWN_PHY_CALIB			0xb0	/* REPLY_PHY_CALIBRATION_CMD */
271 	uint8_t	flags;
272 	uint8_t	idx;
273 	uint8_t	qid;
274 	uint8_t	data[136];
275 } __packed;
276 
277 /* structure for command IWN_CMD_CONFIGURE (aka RXON) */
278 struct iwn_config {
279 	uint8_t		myaddr[IEEE80211_ADDR_LEN];
280 	uint16_t	reserved1;
281 	uint8_t		bssid[IEEE80211_ADDR_LEN];
282 	uint16_t	reserved2;
283 	uint8_t		wlap[IEEE80211_ADDR_LEN];
284 	uint16_t	reserved3;
285 	uint8_t		mode;
286 #define IWN_MODE_HOSTAP		1
287 #define IWN_MODE_STA		3
288 #define IWN_MODE_IBSS		4
289 #define IWN_MODE_MONITOR	6
290 	uint8_t		unused4;	/* air propagation */
291 	uint16_t	rxchain;
292 #define	IWN_RXCHAIN_VALID	0x000e	/* which antennae are valid */
293 #define IWN_RXCHAIN_VALID_S	1
294 #define	IWN_RXCHAIN_FORCE	0x0070
295 #define	IWN_RXCHAIN_FORCE_S	4
296 #define	IWN_RXCHAIN_FORCE_MIMO	0x0380
297 #define	IWN_RXCHAIN_FORCE_MIMO_S	7
298 #define	IWN_RXCHAIN_CNT		0x0c00
299 #define	IWN_RXCHAIN_CNT_S	10
300 #define	IWN_RXCHAIN_MIMO_CNT	0x3000
301 #define	IWN_RXCHAIN_MIMO_CNT_S	12
302 #define IWN_RXCHAIN_MIMO_FORCE	0x4000
303 #define IWN_RXCHAIN_MIMO_FORCE_S	14
304 	uint8_t		ofdm_mask;	/* basic rates */
305 	uint8_t		cck_mask;	/* basic rates */
306 	uint16_t	associd;
307 	uint32_t	flags;
308 #define	IWN_CONFIG_24GHZ	0x00000001	/* band */
309 #define	IWN_CONFIG_CCK		0x00000002	/* modulation */
310 #define	IWN_CONFIG_AUTO		0x00000004	/* 2.4-only auto-detect */
311 #define	IWN_CONFIG_HTPROT	0x00000008	/* xmit with HT protection */
312 #define	IWN_CONFIG_SHSLOT	0x00000010	/* short slot time */
313 #define	IWN_CONFIG_SHPREAMBLE	0x00000020	/* short premable */
314 #define	IWN_CONFIG_NODIVERSITY	0x00000080	/* disable antenna diversity */
315 #define	IWN_CONFIG_ANTENNA_A	0x00000100
316 #define	IWN_CONFIG_ANTENNA_B	0x00000200
317 #define	IWN_CONFIG_RADAR	0x00001000	/* enable radar detect */
318 #define	IWN_CONFIG_NARROW	0x00002000	/* MKK narrow band select */
319 #define	IWN_CONFIG_TSF		0x00008000
320 #define	IWN_CONFIG_HT		0x06400000
321 #define	IWN_CONFIG_HT20		0x02000000
322 #define	IWN_CONFIG_HT40U	0x04000000
323 #define	IWN_CONFIG_HT40D	0x04400000
324 	uint32_t	filter;
325 #define IWN_FILTER_PROMISC	(1 << 0)	/* pass all data frames */
326 #define IWN_FILTER_CTL		(1 << 1)	/* pass ctl+mgt frames */
327 #define IWN_FILTER_MULTICAST	(1 << 2)	/* pass multi-cast frames */
328 #define IWN_FILTER_NODECRYPT	(1 << 3)	/* pass unicast undecrypted */
329 #define IWN_FILTER_BSS		(1 << 5)	/* station is associated */
330 #define IWN_FILTER_ALLBEACONS	(1 << 6)	/* pass overlapping bss beacons
331 						   (must be associated) */
332 	uint16_t	chan;		/* IEEE channel # of control/primary */
333 	uint8_t		ht_single_mask;	/* single-stream basic rates */
334 	uint8_t		ht_dual_mask;	/* dual-stream basic rates */
335 } __packed;
336 
337 /* structure for command IWN_CMD_ASSOCIATE */
338 struct iwn_assoc {
339 	uint32_t	flags;
340 	uint32_t	filter;
341 	uint8_t		ofdm_mask;
342 	uint8_t		cck_mask;
343 	uint16_t	reserved;
344 } __packed;
345 
346 /* structure for command IWN_CMD_EDCA_PARAMS */
347 struct iwn_edca_params {
348 	uint32_t	flags;
349 #define IWN_EDCA_UPDATE	(1 << 0)
350 #define IWN_EDCA_TXOP	(1 << 4)
351 
352 	struct {
353 		uint16_t	cwmin;
354 		uint16_t	cwmax;
355 		uint8_t		aifsn;
356 		uint8_t		reserved;
357 		uint16_t	txoplimit;
358 	} __packed	ac[EDCA_NUM_AC];
359 } __packed;
360 
361 /* structure for command IWN_CMD_TSF */
362 struct iwn_cmd_tsf {
363 	uint64_t	tstamp;
364 	uint16_t	bintval;
365 	uint16_t	atim;
366 	uint32_t	binitval;
367 	uint16_t	lintval;
368 	uint16_t	reserved;
369 } __packed;
370 
371 /* structure for command IWN_CMD_ADD_NODE */
372 struct iwn_node_info {
373 	uint8_t		control;
374 #define IWN_NODE_UPDATE		(1 << 0)
375 	uint8_t		reserved1[3];
376 	uint8_t		macaddr[IEEE80211_ADDR_LEN];
377 	uint16_t	reserved2;
378 	uint8_t		id;
379 #define IWN_ID_BSS		 0
380 #define IWN_ID_BROADCAST	31
381 	uint8_t		flags;
382 #define IWN_FLAG_SET_KEY	(1 << 0)
383 	uint16_t	reserved3;
384 	uint16_t	security;
385 	uint8_t		tsc2;	/* TKIP TSC2 */
386 	uint8_t		reserved4;
387 	uint16_t	ttak[5];
388 	uint16_t	reserved5;
389 	uint8_t		key[IEEE80211_KEYBUF_SIZE];
390 	uint32_t	htflags;
391 #define IWN_MAXRXAMPDU_S	19
392 #define IWN_MPDUDENSITY_S	23
393 	uint32_t	mask;
394 	uint16_t	tid;
395 	uint8_t		rate;		/* legacy rate/MCS */
396 #define	IWN_RATE_MCS	0x08		/* or'd to indicate MCS */
397 	uint8_t		rflags;
398 #define	IWN_RFLAG_HT	(1 << 0)	/* use HT modulation */
399 #define IWN_RFLAG_CCK	(1 << 1)	/* use CCK modulation */
400 #define	IWN_RFLAG_HT40	(1 << 3)	/* use dual-stream */
401 #define	IWN_RFLAG_SGI	(1 << 5)	/* use short GI */
402 #define IWN_RFLAG_ANT_A	(1 << 6)	/* start on antenna port A */
403 #define IWN_RFLAG_ANT_B	(1 << 7)	/* start on antenna port B */
404 	uint8_t		add_imm;
405 	uint8_t		del_imm;
406 	uint16_t	add_imm_start;
407 	uint32_t	reserved6;
408 } __packed;
409 
410 /* structure for command IWN_CMD_TX_DATA */
411 struct iwn_cmd_data {
412 	uint16_t	len;
413 	uint16_t	lnext;
414 	uint32_t	flags;
415 #define IWN_TX_NEED_RTS		(1 <<  1)
416 #define IWN_TX_NEED_CTS		(1 <<  2)
417 #define IWN_TX_NEED_ACK		(1 <<  3)
418 #define IWN_TX_USE_NODE_RATE	(1 <<  4)
419 #define IWN_TX_FULL_TXOP	(1 <<  7)
420 #define IWN_TX_BT_DISABLE	(1 << 12)	/* bluetooth coexistence */
421 #define IWN_TX_AUTO_SEQ		(1 << 13)
422 #define IWN_TX_INSERT_TSTAMP	(1 << 16)
423 #define IWN_TX_NEED_PADDING	(1 << 20)
424 
425 	uint8_t		ntries;
426 	uint8_t		bluetooth;
427 	uint16_t	reserved1;
428 	uint8_t		rate;
429 	uint8_t		rflags;
430 	uint16_t	xrflags;
431 	uint8_t		id;
432 	uint8_t		security;
433 #define IWN_CIPHER_WEP40	1
434 #define IWN_CIPHER_CCMP		2
435 #define IWN_CIPHER_TKIP		3
436 #define IWN_CIPHER_WEP104	9
437 
438 	uint8_t		ridx;
439 	uint8_t		reserved2;
440 	uint8_t		key[IEEE80211_KEYBUF_SIZE];
441 	uint16_t	fnext;
442 	uint16_t	reserved3;
443 	uint32_t	lifetime;
444 #define IWN_LIFETIME_INFINITE	0xffffffff
445 
446 	uint32_t	loaddr;
447 	uint8_t		hiaddr;
448 	uint8_t		rts_ntries;
449 	uint8_t		data_ntries;
450 	uint8_t		tid;
451 	uint16_t	timeout;
452 	uint16_t	txop;
453 } __packed;
454 
455 /* structure for command IWN_CMD_TX_LINK_QUALITY */
456 #define IWN_MAX_TX_RETRIES	16
457 struct iwn_cmd_link_quality {
458 	uint8_t		id;
459 	uint8_t		reserved1;
460 	uint16_t	ctl;
461 	uint8_t		flags;
462 	uint8_t		mimo;		/* MIMO delimiter */
463 	uint8_t		ssmask;		/* single stream antenna mask */
464 	uint8_t		dsmask;		/* dual stream antenna mask */
465 	uint8_t		ridx[EDCA_NUM_AC];/* starting rate index */
466 	uint16_t	ampdu_limit;	/* tx aggregation time limit */
467 	uint8_t		ampdu_disable;
468 	uint8_t		ampdu_max;	/* frame count limit */
469 	uint32_t	reserved2;
470 	struct {
471 		uint8_t		rate;
472 #define IWN_RATE_CCK1	 0
473 #define IWN_RATE_CCK11	 3
474 #define IWN_RATE_OFDM6	 4
475 #define IWN_RATE_OFDM54	11
476 		uint8_t		rflags;
477 		uint16_t	xrflags;
478 	} table[IWN_MAX_TX_RETRIES];
479 	uint32_t	reserved3;
480 } __packed;
481 
482 /* structure for command IWN_CMD_SET_LED */
483 struct iwn_cmd_led {
484 	uint32_t	unit;	/* multiplier (in usecs) */
485 	uint8_t		which;
486 #define IWN_LED_ACTIVITY	1
487 #define IWN_LED_LINK		2
488 
489 	uint8_t		off;
490 	uint8_t		on;
491 	uint8_t		reserved;
492 } __packed;
493 
494 /* structure for command IWN_CMD_SET_POWER_MODE */
495 struct iwn_power {
496 	uint16_t	flags;
497 #define IWN_POWER_CAM	0	/* constantly awake mode */
498 
499 	uint8_t		alive;
500 	uint8_t		debug;
501 	uint32_t	rx_timeout;
502 	uint32_t	tx_timeout;
503 	uint32_t	sleep[5];
504 	uint32_t	beacons;
505 } __packed;
506 
507 /* structures for command IWN_CMD_SCAN */
508 struct iwn_scan_essid {
509 	uint8_t	id;
510 	uint8_t	len;
511 	uint8_t	data[IEEE80211_NWID_LEN];
512 } __packed;
513 
514 struct iwn_scan_hdr {
515 	uint16_t	len;
516 	uint8_t		reserved1;
517 	uint8_t		nchan;
518 	uint16_t	quiet;
519 	uint16_t	plcp_threshold;
520 	uint16_t	crc_threshold;
521 	uint16_t	rxchain;
522 	uint32_t	max_svc;	/* background scans */
523 	uint32_t	pause_svc;	/* background scans */
524 	uint32_t	flags;
525 	uint32_t	filter;
526 
527 	/* followed by a struct iwn_cmd_data */
528 	/* followed by an array of 4x struct iwn_scan_essid */
529 	/* followed by probe request body */
530 	/* followed by nchan x struct iwn_scan_chan */
531 } __packed;
532 
533 struct iwn_scan_chan {
534 	uint8_t		flags;
535 #define IWN_CHAN_ACTIVE	(1 << 0)
536 #define IWN_CHAN_DIRECT	(1 << 1)
537 
538 	uint8_t		chan;
539 	uint8_t		rf_gain;
540 	uint8_t		dsp_gain;
541 	uint16_t	active;		/* msecs */
542 	uint16_t	passive;	/* msecs */
543 } __packed;
544 
545 /* structure for command IWN_CMD_TXPOWER */
546 #define IWN_RIDX_MAX	32
547 struct iwn_cmd_txpower {
548 	uint8_t	band;
549 	uint8_t	reserved1;
550 	uint8_t	chan;
551 	uint8_t	reserved2;
552 	struct {
553 		uint8_t	rf_gain[IWN_NTXCHAINS];
554 		uint8_t	dsp_gain[IWN_NTXCHAINS];
555 	}	power[IWN_RIDX_MAX + 1];
556 } __packed;
557 
558 /* structure for command IWN_CMD_BLUETOOTH */
559 struct iwn_bluetooth {
560 	uint8_t		flags;
561 	uint8_t		lead;
562 	uint8_t		kill;
563 	uint8_t		reserved;
564 	uint32_t	ack;
565 	uint32_t	cts;
566 } __packed;
567 
568 /* structure for command IWN_CMD_SET_CRITICAL_TEMP */
569 struct iwn_critical_temp {
570 	uint32_t	reserved;
571 	uint32_t	tempM;
572 	uint32_t	tempR;
573 /* degK <-> degC conversion macros */
574 #define IWN_CTOK(c)	((c) + 273)
575 #define IWN_KTOC(k)	((k) - 273)
576 #define IWN_CTOMUK(c)	(((c) * 1000000) + 273150000)
577 } __packed;
578 
579 /* structure for command IWN_SENSITIVITY */
580 struct iwn_sensitivity_cmd {
581 	uint16_t	which;
582 #define IWN_SENSITIVITY_DEFAULTTBL	0
583 #define IWN_SENSITIVITY_WORKTBL		1
584 
585 	uint16_t	energy_cck;
586 	uint16_t	energy_ofdm;
587 	uint16_t	corr_ofdm_x1;
588 	uint16_t	corr_ofdm_mrc_x1;
589 	uint16_t	corr_cck_mrc_x4;
590 	uint16_t	corr_ofdm_x4;
591 	uint16_t	corr_ofdm_mrc_x4;
592 	uint16_t	corr_barker;
593 	uint16_t	corr_barker_mrc;
594 	uint16_t	corr_cck_x4;
595 	uint16_t	energy_ofdm_th;
596 } __packed;
597 
598 /* structure for command IWN_PHY_CALIB */
599 struct iwn_phy_calib_cmd {
600 	uint8_t		code;
601 #define IWN_SET_DIFF_GAIN	7
602 
603 	uint8_t		flags;
604 	uint16_t	reserved1;
605 	int8_t		gain[3];
606 #define IWN_GAIN_SET	(1 << 2)
607 
608 	uint8_t		reserved2;
609 } __packed;
610 
611 
612 /* structure for IWN_UC_READY notification */
613 #define IWN_NATTEN_GROUPS	5
614 struct iwn_ucode_info {
615 	uint8_t		minor;
616 	uint8_t		major;
617 	uint16_t	reserved1;
618 	uint8_t		revision[8];
619 	uint8_t		type;
620 	uint8_t		subtype;
621 #define IWN_UCODE_RUNTIME	0
622 #define IWN_UCODE_INIT		9
623 
624 	uint16_t	reserved2;
625 	uint32_t	logptr;
626 	uint32_t	errorptr;
627 	uint32_t	tstamp;
628 	uint32_t	valid;
629 
630 	/* the following fields are for UCODE_INIT only */
631 	int32_t		volt;
632 	struct {
633 		int32_t	chan20MHz;
634 		int32_t	chan40MHz;
635 	} __packed	temp[4];
636 	int32_t		atten[IWN_NATTEN_GROUPS][IWN_NTXCHAINS];
637 } __packed;
638 
639 /* structure for IWN_TX_DONE notification */
640 struct iwn_tx_stat {
641 	uint8_t		nframes;
642 	uint8_t		nkill;
643 	uint8_t		nrts;
644 	uint8_t		ntries;
645 	uint8_t		rate;
646 	uint8_t		rflags;
647 	uint16_t	xrflags;
648 	uint16_t	duration;
649 	uint16_t	reserved;
650 	uint32_t	power[2];
651 	uint32_t	status;
652 #define	IWN_TX_SUCCESS			0x00
653 #define	IWN_TX_FAIL			0x80	/* all failures have 0x80 set */
654 #define	IWN_TX_FAIL_SHORT_LIMIT		0x82	/* too many RTS retries */
655 #define	IWN_TX_FAIL_LONG_LIMIT		0x83	/* too many retries */
656 #define	IWN_TX_FAIL_FIFO_UNDERRRUN	0x84	/* tx fifo not kept running */
657 #define	IWN_TX_FAIL_DEST_IN_PS		0x88	/* sta found in power save */
658 #define	IWN_TX_FAIL_TX_LOCKED		0x90	/* waiting to see traffic */
659 } __packed;
660 
661 /* structure for IWN_BEACON_MISSED notification */
662 struct iwn_beacon_missed {
663 	uint32_t	consecutive;
664 	uint32_t	total;
665 	uint32_t	expected;
666 	uint32_t	received;
667 } __packed;
668 
669 /* structure for IWN_AMPDU_RX_DONE notification */
670 struct iwn_rx_ampdu {
671 	uint16_t	len;
672 	uint16_t	reserved;
673 } __packed;
674 
675 /* structure for IWN_RX_DONE and IWN_AMPDU_RX_START notifications */
676 struct iwn_rx_stat {
677 	uint8_t		phy_len;
678 	uint8_t		cfg_phy_len;
679 #define IWN_STAT_MAXLEN	20
680 
681 	uint8_t		id;
682 	uint8_t		reserved1;
683 	uint64_t	tstamp;
684 	uint32_t	beacon;
685 	uint16_t	flags;
686 	uint16_t	chan;
687 	uint16_t	antenna;
688 	uint16_t	agc;
689 	uint8_t		rssi[6];
690 #define IWN_RSSI_TO_DBM	44
691 
692 	uint8_t		reserved2[22];
693 	uint8_t		rate;
694 	uint8_t		rflags;
695 	uint16_t	xrflags;
696 	uint16_t	len;
697 	uint16_t	reserve3;
698 } __packed;
699 
700 /* structure for IWN_START_SCAN notification */
701 struct iwn_start_scan {
702 	uint64_t	tstamp;
703 	uint32_t	tbeacon;
704 	uint8_t		chan;
705 	uint8_t		band;
706 	uint16_t	reserved;
707 	uint32_t	status;
708 } __packed;
709 
710 /* structure for IWN_STOP_SCAN notification */
711 struct iwn_stop_scan {
712 	uint8_t		nchan;
713 	uint8_t		status;
714 	uint8_t		reserved;
715 	uint8_t		chan;
716 	uint64_t	tsf;
717 } __packed;
718 
719 /* structure for IWN_{RX,BEACON}_STATISTICS notification */
720 struct iwn_rx_phy_stats {
721 	uint32_t	ina;
722 	uint32_t	fina;
723 	uint32_t	bad_plcp;
724 	uint32_t	bad_crc32;
725 	uint32_t	overrun;
726 	uint32_t	eoverrun;
727 	uint32_t	good_crc32;
728 	uint32_t	fa;
729 	uint32_t	bad_fina_sync;
730 	uint32_t	sfd_timeout;
731 	uint32_t	fina_timeout;
732 	uint32_t	no_rts_ack;
733 	uint32_t	rxe_limit;
734 	uint32_t	ack;
735 	uint32_t	cts;
736 	uint32_t	ba_resp;
737 	uint32_t	dsp_kill;
738 	uint32_t	bad_mh;
739 	uint32_t	rssi_sum;
740 	uint32_t	reserved;
741 } __packed;
742 
743 struct iwn_rx_general_stats {
744 	uint32_t	bad_cts;
745 	uint32_t	bad_ack;
746 	uint32_t	not_bss;
747 	uint32_t	filtered;
748 	uint32_t	bad_chan;
749 	uint32_t	beacons;
750 	uint32_t	missed_beacons;
751 	uint32_t	adc_saturated;	/* time in 0.8us */
752 	uint32_t	ina_searched;	/* time in 0.8us */
753 	uint32_t	noise[3];
754 	uint32_t	flags;
755 	uint32_t	load;
756 	uint32_t	fa;
757 	uint32_t	rssi[3];
758 	uint32_t	energy[3];
759 } __packed;
760 
761 struct iwn_rx_ht_phy_stats {
762 	uint32_t	bad_plcp;
763 	uint32_t	overrun;
764 	uint32_t	eoverrun;
765 	uint32_t	good_crc32;
766 	uint32_t	bad_crc32;
767 	uint32_t	bad_mh;
768 	uint32_t	good_ampdu_crc32;
769 	uint32_t	ampdu;
770 	uint32_t	fragment;
771 	uint32_t	reserved;
772 } __packed;
773 
774 struct iwn_rx_stats {
775 	struct iwn_rx_phy_stats		ofdm;
776 	struct iwn_rx_phy_stats		cck;
777 	struct iwn_rx_general_stats	general;
778 	struct iwn_rx_ht_phy_stats	ht;
779 } __packed;
780 
781 struct iwn_tx_stats {
782 	uint32_t	preamble;
783 	uint32_t	rx_detected;
784 	uint32_t	bt_defer;
785 	uint32_t	bt_kill;
786 	uint32_t	short_len;
787 	uint32_t	cts_timeout;
788 	uint32_t	ack_timeout;
789 	uint32_t	exp_ack;
790 	uint32_t	ack;
791 	uint32_t	msdu;
792 	uint32_t	busrt_err1;
793 	uint32_t	burst_err2;
794 	uint32_t	cts_collision;
795 	uint32_t	ack_collision;
796 	uint32_t	ba_timeout;
797 	uint32_t	ba_resched;
798 	uint32_t	query_ampdu;
799 	uint32_t	query;
800 	uint32_t	query_ampdu_frag;
801 	uint32_t	query_mismatch;
802 	uint32_t	not_ready;
803 	uint32_t	underrun;
804 	uint32_t	bt_ht_kill;
805 	uint32_t	rx_ba_resp;
806 	uint32_t	reserved[2];
807 } __packed;
808 
809 struct iwn_general_stats {
810 	uint32_t	temp;
811 	uint32_t	temp_m;
812 	uint32_t	burst_check;
813 	uint32_t	burst;
814 	uint32_t	reserved1[4];
815 	uint32_t	sleep;
816 	uint32_t	slot_out;
817 	uint32_t	slot_idle;
818 	uint32_t	ttl_tstamp;
819 	uint32_t	tx_ant_a;
820 	uint32_t	tx_ant_b;
821 	uint32_t	exec;
822 	uint32_t	probe;
823 	uint32_t	reserved2[2];
824 	uint32_t	rx_enabled;
825 	uint32_t	reserved3[3];
826 } __packed;
827 
828 struct iwn_stats {
829 	uint32_t			flags;
830 	struct iwn_rx_stats		rx;
831 	struct iwn_tx_stats		tx;
832 	struct iwn_general_stats	general;
833 } __packed;
834 
835 
836 /* firmware image header */
837 struct iwn_firmware_hdr {
838 	uint32_t	version;
839 	uint32_t	main_textsz;
840 	uint32_t	main_datasz;
841 	uint32_t	init_textsz;
842 	uint32_t	init_datasz;
843 	uint32_t	boot_textsz;
844 } __packed;
845 
846 #define IWN_FW_MAIN_TEXT_MAXSZ	(96 * 1024)
847 #define IWN_FW_MAIN_DATA_MAXSZ	(40 * 1024)
848 #define IWN_FW_INIT_TEXT_MAXSZ	(96 * 1024)
849 #define IWN_FW_INIT_DATA_MAXSZ	(40 * 1024)
850 #define IWN_FW_BOOT_TEXT_MAXSZ	1024
851 
852 
853 /*
854  * Offsets into EEPROM.
855  */
856 #define IWN_EEPROM_MAC		0x015
857 #define IWN_EEPROM_DOMAIN	0x060
858 #define IWN_EEPROM_BAND1	0x063
859 #define IWN_EEPROM_BAND2	0x072
860 #define IWN_EEPROM_BAND3	0x080
861 #define IWN_EEPROM_BAND4	0x08d
862 #define IWN_EEPROM_BAND5	0x099
863 #define IWN_EEPROM_BAND6	0x0a0
864 #define IWN_EEPROM_BAND7	0x0a8
865 #define IWN_EEPROM_MAXPOW	0x0e8
866 #define IWN_EEPROM_VOLTAGE	0x0e9
867 #define IWN_EEPROM_BANDS	0x0ea
868 
869 struct iwn_eeprom_chan {
870 	uint8_t	flags;
871 #define IWN_EEPROM_CHAN_VALID	(1 << 0)
872 #define IWN_EEPROM_CHAN_IBSS	(1 << 1)	/* adhoc permitted */
873 /* NB: bit 2 is reserved */
874 #define IWN_EEPROM_CHAN_ACTIVE	(1 << 3)	/* active/passive scan */
875 #define IWN_EEPROM_CHAN_RADAR	(1 << 4)	/* DFS required */
876 #define IWN_EEPROM_CHAN_WIDE	(1 << 5)	/* HT40 */
877 #define IWN_EEPROM_CHAN_NARROW	(1 << 6)	/* HT20 */
878 
879 	int8_t	maxpwr;
880 } __packed;
881 
882 #define IWN_NSAMPLES	3
883 struct iwn_eeprom_chan_samples {
884 	uint8_t	num;
885 	struct {
886 		uint8_t temp;
887 		uint8_t	gain;
888 		uint8_t	power;
889 		int8_t	pa_det;
890 	}	samples[IWN_NTXCHAINS][IWN_NSAMPLES];
891 } __packed;
892 
893 #define IWN_NBANDS	8
894 struct iwn_eeprom_band {
895 	uint8_t	lo;	/* low channel number */
896 	uint8_t	hi;	/* high channel number */
897 	struct	iwn_eeprom_chan_samples chans[2];
898 } __packed;
899 
900 #define IWN_MAX_PWR_INDEX	107
901 
902 /*
903  * RF Tx gain values from highest to lowest power (values obtained from
904  * the reference driver.)
905  */
906 static const uint8_t iwn_rf_gain_2ghz[IWN_MAX_PWR_INDEX + 1] = {
907 	0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c,
908 	0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39, 0x39, 0x38,
909 	0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x35, 0x35, 0x35,
910 	0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x31, 0x31,
911 	0x31, 0x30, 0x30, 0x30, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x04,
912 	0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
913 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
914 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
915 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
917 };
918 
919 static const uint8_t iwn_rf_gain_5ghz[IWN_MAX_PWR_INDEX + 1] = {
920 	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x3e, 0x3d, 0x3d, 0x3d,
921 	0x3c, 0x3c, 0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39,
922 	0x39, 0x38, 0x38, 0x38, 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x35,
923 	0x35, 0x35, 0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32,
924 	0x31, 0x31, 0x31, 0x30, 0x30, 0x30, 0x25, 0x25, 0x25, 0x24, 0x24,
925 	0x24, 0x23, 0x23, 0x23, 0x22, 0x18, 0x18, 0x17, 0x17, 0x17, 0x16,
926 	0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13,
927 	0x12, 0x08, 0x08, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x05, 0x05,
928 	0x05, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01,
929 	0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
930 };
931 
932 /*
933  * DSP pre-DAC gain values from highest to lowest power (values obtained
934  * from the reference driver.)
935  */
936 static const uint8_t iwn_dsp_gain_2ghz[IWN_MAX_PWR_INDEX + 1] = {
937 	0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,
938 	0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,
939 	0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,
940 	0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,
941 	0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,
942 	0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,
943 	0x6e, 0x68, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a,
944 	0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f,
945 	0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44,
946 	0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b
947 };
948 
949 static const uint8_t iwn_dsp_gain_5ghz[IWN_MAX_PWR_INDEX + 1] = {
950 	0x7b, 0x75, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,
951 	0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,
952 	0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,
953 	0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,
954 	0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,
955 	0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,
956 	0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62,
957 	0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68,
958 	0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e, 0x68, 0x62, 0x6e,
959 	0x68, 0x62, 0x6e, 0x68, 0x62, 0x5d, 0x58, 0x53, 0x4e
960 };
961 
962 #define IWN_READ(sc, reg)						\
963 	bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
964 
965 #define IWN_WRITE(sc, reg, val)						\
966 	bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
967 
968 #define IWN_WRITE_REGION_4(sc, offset, datap, count)			\
969 	bus_space_write_region_4((sc)->sc_st, (sc)->sc_sh, (offset),	\
970 	    (datap), (count))
971