xref: /titanic_52/usr/src/uts/common/io/ath/ath_main.c (revision b26a64ae582e72d0b4c710cd8eba9c4afd4a9fdd)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer,
15  * without modification.
16  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
17  * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
18  * redistribution must be conditioned upon including a substantially
19  * similar Disclaimer requirement for further binary redistribution.
20  * 3. Neither the names of the above-listed copyright holders nor the names
21  * of any contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * NO WARRANTY
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
28  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
29  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
30  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
33  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35  * THE POSSIBILITY OF SUCH DAMAGES.
36  *
37  */
38 
39 #pragma ident	"%Z%%M%	%I%	%E% SMI"
40 
41 /*
42  * Driver for the Atheros Wireless LAN controller.
43  *
44  * The Atheros driver calls into net80211 module for IEEE80211 protocol
45  * management functionalities. The driver includes a LLD(Low Level Driver)
46  * part to implement H/W related operations.
47  * The following is the high level structure of ath driver.
48  * (The arrows between modules indicate function call direction.)
49  *
50  *
51  *                                                  |
52  *                                                  | GLD thread
53  *                                                  V
54  *         ==================  =========================================
55  *         |                |  |[1]                                    |
56  *         |                |  |  GLDv3 Callback functions registered  |
57  *         |   Net80211     |  =========================       by      |
58  *         |    module      |          |               |     driver    |
59  *         |                |          V               |               |
60  *         |                |========================  |               |
61  *         |   Functions exported by net80211       |  |               |
62  *         |                                        |  |               |
63  *         ==========================================  =================
64  *                         |                                  |
65  *                         V                                  |
66  *         +----------------------------------+               |
67  *         |[2]                               |               |
68  *         |    Net80211 Callback functions   |               |
69  *         |      registered by LLD           |               |
70  *         +----------------------------------+               |
71  *                         |                                  |
72  *                         V                                  v
73  *         +-----------------------------------------------------------+
74  *         |[3]                                                        |
75  *         |                LLD Internal functions                     |
76  *         |                                                           |
77  *         +-----------------------------------------------------------+
78  *                                    ^
79  *                                    | Software interrupt thread
80  *                                    |
81  *
82  * The short description of each module is as below:
83  *      Module 1: GLD callback functions, which are intercepting the calls from
84  *                GLD to LLD.
85  *      Module 2: Net80211 callback functions registered by LLD, which
86  *                calls into LLD for H/W related functions needed by net80211.
87  *      Module 3: LLD Internal functions, which are responsible for allocing
88  *                descriptor/buffer, handling interrupt and other H/W
89  *                operations.
90  *
91  * All functions are running in 3 types of thread:
92  * 1. GLD callbacks threads, such as ioctl, intr, etc.
93  * 2. Clock interruptt thread which is responsible for scan, rate control and
94  *    calibration.
95  * 3. Software Interrupt thread originated in LLD.
96  *
97  * The lock strategy is as below:
98  * There have 4 queues for tx, each queue has one asc_txqlock[i] to
99  *      prevent conflicts access to queue resource from different thread.
100  *
101  * All the transmit buffers are contained in asc_txbuf which are
102  *      protected by asc_txbuflock.
103  *
104  * Each receive buffers are contained in asc_rxbuf which are protected
105  *      by asc_rxbuflock.
106  *
107  * In ath struct, asc_genlock is a general lock, protecting most other
108  *      operational data in ath_softc struct and HAL accesses.
109  *      It is acquired by the interupt handler and most "mode-ctrl" routines.
110  *
111  * Any of the locks can be acquired singly, but where multiple
112  * locks are acquired, they *must* be in the order:
113  *    asc_genlock >> asc_txqlock[i] >> asc_txbuflock >> asc_rxbuflock
114  */
115 
116 #include <sys/param.h>
117 #include <sys/types.h>
118 #include <sys/signal.h>
119 #include <sys/stream.h>
120 #include <sys/termio.h>
121 #include <sys/errno.h>
122 #include <sys/file.h>
123 #include <sys/cmn_err.h>
124 #include <sys/stropts.h>
125 #include <sys/strsubr.h>
126 #include <sys/strtty.h>
127 #include <sys/kbio.h>
128 #include <sys/cred.h>
129 #include <sys/stat.h>
130 #include <sys/consdev.h>
131 #include <sys/kmem.h>
132 #include <sys/modctl.h>
133 #include <sys/ddi.h>
134 #include <sys/sunddi.h>
135 #include <sys/pci.h>
136 #include <sys/errno.h>
137 #include <sys/mac.h>
138 #include <sys/dlpi.h>
139 #include <sys/ethernet.h>
140 #include <sys/list.h>
141 #include <sys/byteorder.h>
142 #include <sys/strsun.h>
143 #include <sys/policy.h>
144 #include <inet/common.h>
145 #include <inet/nd.h>
146 #include <inet/mi.h>
147 #include <inet/wifi_ioctl.h>
148 #include <sys/mac_wifi.h>
149 #include "ath_hal.h"
150 #include "ath_impl.h"
151 #include "ath_aux.h"
152 #include "ath_rate.h"
153 
154 #define	ATH_MAX_RSSI	63	/* max rssi */
155 
156 extern void ath_halfix_init(void);
157 extern void ath_halfix_finit(void);
158 extern int32_t ath_getset(ath_t *asc, mblk_t *mp, uint32_t cmd);
159 
160 /*
161  * PIO access attributes for registers
162  */
163 static ddi_device_acc_attr_t ath_reg_accattr = {
164 	DDI_DEVICE_ATTR_V0,
165 	DDI_STRUCTURE_LE_ACC,
166 	DDI_STRICTORDER_ACC
167 };
168 
169 /*
170  * DMA access attributes for descriptors: NOT to be byte swapped.
171  */
172 static ddi_device_acc_attr_t ath_desc_accattr = {
173 	DDI_DEVICE_ATTR_V0,
174 	DDI_STRUCTURE_LE_ACC,
175 	DDI_STRICTORDER_ACC
176 };
177 
178 /*
179  * Describes the chip's DMA engine
180  */
181 static ddi_dma_attr_t ath_dma_attr = {
182 	DMA_ATTR_V0,		/* version number */
183 	0,			/* low address */
184 	0xffffffffU,		/* high address */
185 	0x3ffffU,		/* counter register max */
186 	1,			/* alignment */
187 	0xFFF,			/* burst sizes */
188 	1,			/* minimum transfer size */
189 	0x3ffffU,		/* max transfer size */
190 	0xffffffffU,		/* address register max */
191 	1,			/* no scatter-gather */
192 	1,			/* granularity of device */
193 	0,			/* DMA flags */
194 };
195 
196 static ddi_dma_attr_t ath_desc_dma_attr = {
197 	DMA_ATTR_V0,		/* version number */
198 	0,			/* low address */
199 	0xffffffffU,		/* high address */
200 	0xffffffffU,		/* counter register max */
201 	0x1000,			/* alignment */
202 	0xFFF,			/* burst sizes */
203 	1,			/* minimum transfer size */
204 	0xffffffffU,		/* max transfer size */
205 	0xffffffffU,		/* address register max */
206 	1,			/* no scatter-gather */
207 	1,			/* granularity of device */
208 	0,			/* DMA flags */
209 };
210 
211 static kmutex_t ath_loglock;
212 static void *ath_soft_state_p = NULL;
213 static int ath_dwelltime = 150;		/* scan interval, ms */
214 
215 static int	ath_m_stat(void *,  uint_t, uint64_t *);
216 static int	ath_m_start(void *);
217 static void	ath_m_stop(void *);
218 static int	ath_m_promisc(void *, boolean_t);
219 static int	ath_m_multicst(void *, boolean_t, const uint8_t *);
220 static int	ath_m_unicst(void *, const uint8_t *);
221 static mblk_t	*ath_m_tx(void *, mblk_t *);
222 static void	ath_m_ioctl(void *, queue_t *, mblk_t *);
223 static mac_callbacks_t ath_m_callbacks = {
224 	MC_IOCTL,
225 	ath_m_stat,
226 	ath_m_start,
227 	ath_m_stop,
228 	ath_m_promisc,
229 	ath_m_multicst,
230 	ath_m_unicst,
231 	ath_m_tx,
232 	NULL,		/* mc_resources; */
233 	ath_m_ioctl,
234 	NULL		/* mc_getcapab */
235 };
236 
237 /*
238  * Available debug flags:
239  * ATH_DBG_INIT, ATH_DBG_GLD, ATH_DBG_HAL, ATH_DBG_INT, ATH_DBG_ATTACH,
240  * ATH_DBG_DETACH, ATH_DBG_AUX, ATH_DBG_WIFICFG, ATH_DBG_OSDEP
241  */
242 uint32_t ath_dbg_flags = 0;
243 
244 /*
245  * Exception/warning cases not leading to panic.
246  */
247 void
248 ath_problem(const int8_t *fmt, ...)
249 {
250 	va_list args;
251 
252 	mutex_enter(&ath_loglock);
253 
254 	va_start(args, fmt);
255 	vcmn_err(CE_WARN, fmt, args);
256 	va_end(args);
257 
258 	mutex_exit(&ath_loglock);
259 }
260 
261 /*
262  * Normal log information independent of debug.
263  */
264 void
265 ath_log(const int8_t *fmt, ...)
266 {
267 	va_list args;
268 
269 	mutex_enter(&ath_loglock);
270 
271 	va_start(args, fmt);
272 	vcmn_err(CE_CONT, fmt, args);
273 	va_end(args);
274 
275 	mutex_exit(&ath_loglock);
276 }
277 
278 void
279 ath_dbg(uint32_t dbg_flags, const int8_t *fmt, ...)
280 {
281 	va_list args;
282 
283 	if (dbg_flags & ath_dbg_flags) {
284 		mutex_enter(&ath_loglock);
285 		va_start(args, fmt);
286 		vcmn_err(CE_CONT, fmt, args);
287 		va_end(args);
288 		mutex_exit(&ath_loglock);
289 	}
290 }
291 
292 void
293 ath_setup_desc(ath_t *asc, struct ath_buf *bf)
294 {
295 	struct ath_desc *ds;
296 
297 	ds = bf->bf_desc;
298 	ds->ds_link = bf->bf_daddr;
299 	ds->ds_data = bf->bf_dma.cookie.dmac_address;
300 	ds->ds_vdata = bf->bf_dma.mem_va;
301 	ATH_HAL_SETUPRXDESC(asc->asc_ah, ds,
302 	    bf->bf_dma.alength,		/* buffer size */
303 	    0);
304 
305 	if (asc->asc_rxlink != NULL)
306 		*asc->asc_rxlink = bf->bf_daddr;
307 	asc->asc_rxlink = &ds->ds_link;
308 }
309 
310 
311 /*
312  * Allocate an area of memory and a DMA handle for accessing it
313  */
314 static int
315 ath_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, size_t memsize,
316     ddi_device_acc_attr_t *attr_p, uint_t alloc_flags,
317     uint_t bind_flags, dma_area_t *dma_p)
318 {
319 	int err;
320 
321 	/*
322 	 * Allocate handle
323 	 */
324 	err = ddi_dma_alloc_handle(devinfo, dma_attr,
325 	    DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
326 	if (err != DDI_SUCCESS)
327 		return (DDI_FAILURE);
328 
329 	/*
330 	 * Allocate memory
331 	 */
332 	err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
333 	    alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va,
334 	    &dma_p->alength, &dma_p->acc_hdl);
335 	if (err != DDI_SUCCESS)
336 		return (DDI_FAILURE);
337 
338 	/*
339 	 * Bind the two together
340 	 */
341 	err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
342 	    dma_p->mem_va, dma_p->alength, bind_flags,
343 	    DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies);
344 	if (err != DDI_DMA_MAPPED)
345 		return (DDI_FAILURE);
346 
347 	dma_p->nslots = ~0U;
348 	dma_p->size = ~0U;
349 	dma_p->token = ~0U;
350 	dma_p->offset = 0;
351 	return (DDI_SUCCESS);
352 }
353 
354 /*
355  * Free one allocated area of DMAable memory
356  */
357 static void
358 ath_free_dma_mem(dma_area_t *dma_p)
359 {
360 	if (dma_p->dma_hdl != NULL) {
361 		(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
362 		if (dma_p->acc_hdl != NULL) {
363 			ddi_dma_mem_free(&dma_p->acc_hdl);
364 			dma_p->acc_hdl = NULL;
365 		}
366 		ddi_dma_free_handle(&dma_p->dma_hdl);
367 		dma_p->ncookies = 0;
368 		dma_p->dma_hdl = NULL;
369 	}
370 }
371 
372 
373 static int
374 ath_desc_alloc(dev_info_t *devinfo, ath_t *asc)
375 {
376 	int i, err;
377 	size_t size;
378 	struct ath_desc *ds;
379 	struct ath_buf *bf;
380 
381 	size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF);
382 
383 	err = ath_alloc_dma_mem(devinfo, &ath_desc_dma_attr, size,
384 	    &ath_desc_accattr, DDI_DMA_CONSISTENT,
385 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &asc->asc_desc_dma);
386 
387 	/* virtual address of the first descriptor */
388 	asc->asc_desc = (struct ath_desc *)asc->asc_desc_dma.mem_va;
389 
390 	ds = asc->asc_desc;
391 	ATH_DEBUG((ATH_DBG_INIT, "ath: ath_desc_alloc(): DMA map: "
392 	    "%p (%d) -> %p\n",
393 	    asc->asc_desc, asc->asc_desc_dma.alength,
394 	    asc->asc_desc_dma.cookie.dmac_address));
395 
396 	/* allocate data structures to describe TX/RX DMA buffers */
397 	asc->asc_vbuflen = sizeof (struct ath_buf) * (ATH_TXBUF + ATH_RXBUF);
398 	bf = (struct ath_buf *)kmem_zalloc(asc->asc_vbuflen, KM_SLEEP);
399 	asc->asc_vbufptr = bf;
400 
401 	/* DMA buffer size for each TX/RX packet */
402 	asc->asc_dmabuf_size = roundup(1000 + sizeof (struct ieee80211_frame) +
403 	    IEEE80211_MTU + IEEE80211_CRC_LEN +
404 	    (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
405 	    IEEE80211_WEP_CRCLEN), asc->asc_cachelsz);
406 
407 	/* create RX buffer list and allocate DMA memory */
408 	list_create(&asc->asc_rxbuf_list, sizeof (struct ath_buf),
409 	    offsetof(struct ath_buf, bf_node));
410 	for (i = 0; i < ATH_RXBUF; i++, bf++, ds++) {
411 		bf->bf_desc = ds;
412 		bf->bf_daddr = asc->asc_desc_dma.cookie.dmac_address +
413 		    ((caddr_t)ds - (caddr_t)asc->asc_desc);
414 		list_insert_tail(&asc->asc_rxbuf_list, bf);
415 
416 		/* alloc DMA memory */
417 		err = ath_alloc_dma_mem(devinfo, &ath_dma_attr,
418 		    asc->asc_dmabuf_size, &ath_desc_accattr,
419 		    DDI_DMA_STREAMING, DDI_DMA_READ | DDI_DMA_STREAMING,
420 		    &bf->bf_dma);
421 		if (err != DDI_SUCCESS)
422 			return (err);
423 	}
424 
425 	/* create TX buffer list and allocate DMA memory */
426 	list_create(&asc->asc_txbuf_list, sizeof (struct ath_buf),
427 	    offsetof(struct ath_buf, bf_node));
428 	for (i = 0; i < ATH_TXBUF; i++, bf++, ds++) {
429 		bf->bf_desc = ds;
430 		bf->bf_daddr = asc->asc_desc_dma.cookie.dmac_address +
431 		    ((caddr_t)ds - (caddr_t)asc->asc_desc);
432 		list_insert_tail(&asc->asc_txbuf_list, bf);
433 
434 		/* alloc DMA memory */
435 		err = ath_alloc_dma_mem(devinfo, &ath_dma_attr,
436 		    asc->asc_dmabuf_size, &ath_desc_accattr,
437 		    DDI_DMA_STREAMING, DDI_DMA_STREAMING, &bf->bf_dma);
438 		if (err != DDI_SUCCESS)
439 			return (err);
440 	}
441 
442 	return (DDI_SUCCESS);
443 }
444 
445 static void
446 ath_desc_free(ath_t *asc)
447 {
448 	struct ath_buf *bf;
449 
450 	/* Free TX DMA buffer */
451 	bf = list_head(&asc->asc_txbuf_list);
452 	while (bf != NULL) {
453 		ath_free_dma_mem(&bf->bf_dma);
454 		list_remove(&asc->asc_txbuf_list, bf);
455 		bf = list_head(&asc->asc_txbuf_list);
456 	}
457 	list_destroy(&asc->asc_txbuf_list);
458 
459 	/* Free RX DMA uffer */
460 	bf = list_head(&asc->asc_rxbuf_list);
461 	while (bf != NULL) {
462 		ath_free_dma_mem(&bf->bf_dma);
463 		list_remove(&asc->asc_rxbuf_list, bf);
464 		bf = list_head(&asc->asc_rxbuf_list);
465 	}
466 	list_destroy(&asc->asc_rxbuf_list);
467 
468 	/* Free descriptor DMA buffer */
469 	ath_free_dma_mem(&asc->asc_desc_dma);
470 
471 	kmem_free((void *)asc->asc_vbufptr, asc->asc_vbuflen);
472 	asc->asc_vbufptr = NULL;
473 }
474 
475 static void
476 ath_printrxbuf(struct ath_buf *bf, int32_t done)
477 {
478 	struct ath_desc *ds = bf->bf_desc;
479 
480 	ATH_DEBUG((ATH_DBG_RECV, "ath: R (%p %p) %08x %08x %08x "
481 	    "%08x %08x %08x %c\n",
482 	    ds, bf->bf_daddr,
483 	    ds->ds_link, ds->ds_data,
484 	    ds->ds_ctl0, ds->ds_ctl1,
485 	    ds->ds_hw[0], ds->ds_hw[1],
486 	    !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!'));
487 }
488 
489 static void
490 ath_rx_handler(ath_t *asc)
491 {
492 	ieee80211com_t *ic = (ieee80211com_t *)asc;
493 	struct ath_buf *bf;
494 	struct ath_hal *ah = asc->asc_ah;
495 	struct ath_desc *ds;
496 	mblk_t *rx_mp;
497 	struct ieee80211_frame *wh;
498 	int32_t len, loop = 1;
499 	uint8_t phyerr;
500 	HAL_STATUS status;
501 	HAL_NODE_STATS hal_node_stats;
502 	struct ieee80211_node *in;
503 
504 	do {
505 		mutex_enter(&asc->asc_rxbuflock);
506 		bf = list_head(&asc->asc_rxbuf_list);
507 		if (bf == NULL) {
508 			ATH_DEBUG((ATH_DBG_RECV, "ath: ath_rx_handler(): "
509 			    "no buffer\n"));
510 			mutex_exit(&asc->asc_rxbuflock);
511 			break;
512 		}
513 		ASSERT(bf->bf_dma.cookie.dmac_address != NULL);
514 		ds = bf->bf_desc;
515 		if (ds->ds_link == bf->bf_daddr) {
516 			/*
517 			 * Never process the self-linked entry at the end,
518 			 * this may be met at heavy load.
519 			 */
520 			mutex_exit(&asc->asc_rxbuflock);
521 			break;
522 		}
523 
524 		status = ATH_HAL_RXPROCDESC(ah, ds,
525 		    bf->bf_daddr,
526 		    ATH_PA2DESC(asc, ds->ds_link));
527 		if (status == HAL_EINPROGRESS) {
528 			mutex_exit(&asc->asc_rxbuflock);
529 			break;
530 		}
531 		list_remove(&asc->asc_rxbuf_list, bf);
532 		mutex_exit(&asc->asc_rxbuflock);
533 
534 		if (ds->ds_rxstat.rs_status != 0) {
535 			if (ds->ds_rxstat.rs_status & HAL_RXERR_CRC)
536 				asc->asc_stats.ast_rx_crcerr++;
537 			if (ds->ds_rxstat.rs_status & HAL_RXERR_FIFO)
538 				asc->asc_stats.ast_rx_fifoerr++;
539 			if (ds->ds_rxstat.rs_status & HAL_RXERR_DECRYPT)
540 				asc->asc_stats.ast_rx_badcrypt++;
541 			if (ds->ds_rxstat.rs_status & HAL_RXERR_PHY) {
542 				asc->asc_stats.ast_rx_phyerr++;
543 				phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
544 				asc->asc_stats.ast_rx_phy[phyerr]++;
545 			}
546 			goto rx_next;
547 		}
548 		len = ds->ds_rxstat.rs_datalen;
549 
550 		/* less than sizeof(struct ieee80211_frame) */
551 		if (len < 20) {
552 			asc->asc_stats.ast_rx_tooshort++;
553 			goto rx_next;
554 		}
555 
556 		if ((rx_mp = allocb(asc->asc_dmabuf_size, BPRI_MED)) == NULL) {
557 			ath_problem("ath: ath_rx_handler(): "
558 			    "allocing mblk buffer failed.\n");
559 			return;
560 		}
561 
562 		ATH_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORCPU);
563 		bcopy(bf->bf_dma.mem_va, rx_mp->b_rptr, len);
564 
565 		rx_mp->b_wptr += len;
566 		wh = (struct ieee80211_frame *)rx_mp->b_rptr;
567 		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
568 		    IEEE80211_FC0_TYPE_CTL) {
569 			/*
570 			 * Ignore control frame received in promisc mode.
571 			 */
572 			freemsg(rx_mp);
573 			goto rx_next;
574 		}
575 		/* Remove the CRC at the end of IEEE80211 frame */
576 		rx_mp->b_wptr -= IEEE80211_CRC_LEN;
577 #ifdef DEBUG
578 		ath_printrxbuf(bf, status == HAL_OK);
579 #endif /* DEBUG */
580 		/*
581 		 * Locate the node for sender, track state, and then
582 		 * pass the (referenced) node up to the 802.11 layer
583 		 * for its use.
584 		 */
585 		in = ieee80211_find_rxnode(ic, wh);
586 
587 		/*
588 		 * Send frame up for processing.
589 		 */
590 		(void) ieee80211_input(ic, rx_mp, in,
591 		    ds->ds_rxstat.rs_rssi,
592 		    ds->ds_rxstat.rs_tstamp);
593 
594 		ieee80211_free_node(in);
595 
596 rx_next:
597 		mutex_enter(&asc->asc_rxbuflock);
598 		list_insert_tail(&asc->asc_rxbuf_list, bf);
599 		mutex_exit(&asc->asc_rxbuflock);
600 		ath_setup_desc(asc, bf);
601 	} while (loop);
602 
603 	/* rx signal state monitoring */
604 	ATH_HAL_RXMONITOR(ah, &hal_node_stats, &asc->asc_curchan);
605 }
606 
607 static void
608 ath_printtxbuf(struct ath_buf *bf, int done)
609 {
610 	struct ath_desc *ds = bf->bf_desc;
611 
612 	ATH_DEBUG((ATH_DBG_SEND, "ath: T(%p %p) %08x %08x %08x %08x %08x"
613 	    " %08x %08x %08x %c\n",
614 	    ds, bf->bf_daddr,
615 	    ds->ds_link, ds->ds_data,
616 	    ds->ds_ctl0, ds->ds_ctl1,
617 	    ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
618 	    !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!'));
619 }
620 
621 /*
622  * The input parameter mp has following assumption:
623  * For data packets, GLDv3 mac_wifi plugin allocates and fills the
624  * ieee80211 header. For management packets, net80211 allocates and
625  * fills the ieee80211 header. In both cases, enough spaces in the
626  * header are left for encryption option.
627  */
628 static int32_t
629 ath_tx_start(ath_t *asc, struct ieee80211_node *in, struct ath_buf *bf,
630     mblk_t *mp)
631 {
632 	ieee80211com_t *ic = (ieee80211com_t *)asc;
633 	struct ieee80211_frame *wh;
634 	struct ath_hal *ah = asc->asc_ah;
635 	uint32_t subtype, flags, ctsduration;
636 	int32_t keyix, iswep, hdrlen, pktlen, mblen, mbslen, try0;
637 	uint8_t rix, cix, txrate, ctsrate;
638 	struct ath_desc *ds;
639 	struct ath_txq *txq;
640 	HAL_PKT_TYPE atype;
641 	const HAL_RATE_TABLE *rt;
642 	HAL_BOOL shortPreamble;
643 	struct ath_node *an;
644 	caddr_t dest;
645 
646 	/*
647 	 * CRC are added by H/W, not encaped by driver,
648 	 * but we must count it in pkt length.
649 	 */
650 	pktlen = IEEE80211_CRC_LEN;
651 
652 	wh = (struct ieee80211_frame *)mp->b_rptr;
653 	iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
654 	keyix = HAL_TXKEYIX_INVALID;
655 	hdrlen = sizeof (struct ieee80211_frame);
656 	if (iswep != 0) {
657 		const struct ieee80211_cipher *cip;
658 		struct ieee80211_key *k;
659 
660 		/*
661 		 * Construct the 802.11 header+trailer for an encrypted
662 		 * frame. The only reason this can fail is because of an
663 		 * unknown or unsupported cipher/key type.
664 		 */
665 		k = ieee80211_crypto_encap(ic, mp);
666 		if (k == NULL) {
667 			ATH_DEBUG((ATH_DBG_AUX, "crypto_encap failed\n"));
668 			/*
669 			 * This can happen when the key is yanked after the
670 			 * frame was queued.  Just discard the frame; the
671 			 * 802.11 layer counts failures and provides
672 			 * debugging/diagnostics.
673 			 */
674 			return (EIO);
675 		}
676 		cip = k->wk_cipher;
677 		/*
678 		 * Adjust the packet + header lengths for the crypto
679 		 * additions and calculate the h/w key index.  When
680 		 * a s/w mic is done the frame will have had any mic
681 		 * added to it prior to entry so m0->m_pkthdr.len above will
682 		 * account for it. Otherwise we need to add it to the
683 		 * packet length.
684 		 */
685 		hdrlen += cip->ic_header;
686 		pktlen += cip->ic_trailer;
687 		if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0)
688 			pktlen += cip->ic_miclen;
689 		keyix = k->wk_keyix;
690 
691 		/* packet header may have moved, reset our local pointer */
692 		wh = (struct ieee80211_frame *)mp->b_rptr;
693 	}
694 
695 	dest = bf->bf_dma.mem_va;
696 	for (; mp != NULL; mp = mp->b_cont) {
697 		mblen = MBLKL(mp);
698 		bcopy(mp->b_rptr, dest, mblen);
699 		dest += mblen;
700 	}
701 	mbslen = dest - bf->bf_dma.mem_va;
702 	pktlen += mbslen;
703 
704 	bf->bf_in = in;
705 
706 	/* setup descriptors */
707 	ds = bf->bf_desc;
708 	rt = asc->asc_currates;
709 	ASSERT(rt != NULL);
710 
711 	/*
712 	 * The 802.11 layer marks whether or not we should
713 	 * use short preamble based on the current mode and
714 	 * negotiated parameters.
715 	 */
716 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
717 	    (in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
718 		shortPreamble = AH_TRUE;
719 		asc->asc_stats.ast_tx_shortpre++;
720 	} else {
721 		shortPreamble = AH_FALSE;
722 	}
723 
724 	an = ATH_NODE(in);
725 
726 	/*
727 	 * Calculate Atheros packet type from IEEE80211 packet header
728 	 * and setup for rate calculations.
729 	 */
730 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
731 	case IEEE80211_FC0_TYPE_MGT:
732 		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
733 		if (subtype == IEEE80211_FC0_SUBTYPE_BEACON)
734 			atype = HAL_PKT_TYPE_BEACON;
735 		else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
736 			atype = HAL_PKT_TYPE_PROBE_RESP;
737 		else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM)
738 			atype = HAL_PKT_TYPE_ATIM;
739 		else
740 			atype = HAL_PKT_TYPE_NORMAL;
741 		rix = 0;	/* lowest rate */
742 		try0 = ATH_TXMAXTRY;
743 		if (shortPreamble)
744 			txrate = an->an_tx_mgtratesp;
745 		else
746 			txrate = an->an_tx_mgtrate;
747 		/* force all ctl frames to highest queue */
748 		txq = asc->asc_ac2q[WME_AC_VO];
749 		break;
750 	case IEEE80211_FC0_TYPE_CTL:
751 		atype = HAL_PKT_TYPE_PSPOLL;
752 		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
753 		rix = 0;	/* lowest rate */
754 		try0 = ATH_TXMAXTRY;
755 		if (shortPreamble)
756 			txrate = an->an_tx_mgtratesp;
757 		else
758 			txrate = an->an_tx_mgtrate;
759 		/* force all ctl frames to highest queue */
760 		txq = asc->asc_ac2q[WME_AC_VO];
761 		break;
762 	case IEEE80211_FC0_TYPE_DATA:
763 		atype = HAL_PKT_TYPE_NORMAL;
764 		rix = an->an_tx_rix0;
765 		try0 = an->an_tx_try0;
766 		if (shortPreamble)
767 			txrate = an->an_tx_rate0sp;
768 		else
769 			txrate = an->an_tx_rate0;
770 		/* Always use background queue */
771 		txq = asc->asc_ac2q[WME_AC_BK];
772 		break;
773 	default:
774 		/* Unknown 802.11 frame */
775 		asc->asc_stats.ast_tx_invalid++;
776 		return (1);
777 	}
778 	/*
779 	 * Calculate miscellaneous flags.
780 	 */
781 	flags = HAL_TXDESC_CLRDMASK;
782 	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
783 		flags |= HAL_TXDESC_NOACK;	/* no ack on broad/multicast */
784 		asc->asc_stats.ast_tx_noack++;
785 	} else if (pktlen > ic->ic_rtsthreshold) {
786 		flags |= HAL_TXDESC_RTSENA;	/* RTS based on frame length */
787 		asc->asc_stats.ast_tx_rts++;
788 	}
789 
790 	/*
791 	 * Calculate duration.  This logically belongs in the 802.11
792 	 * layer but it lacks sufficient information to calculate it.
793 	 */
794 	if ((flags & HAL_TXDESC_NOACK) == 0 &&
795 	    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
796 	    IEEE80211_FC0_TYPE_CTL) {
797 		uint16_t dur;
798 		dur = ath_hal_computetxtime(ah, rt, IEEE80211_ACK_SIZE,
799 		    rix, shortPreamble);
800 		*(uint16_t *)wh->i_dur = LE_16(dur);
801 	}
802 
803 	/*
804 	 * Calculate RTS/CTS rate and duration if needed.
805 	 */
806 	ctsduration = 0;
807 	if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
808 		/*
809 		 * CTS transmit rate is derived from the transmit rate
810 		 * by looking in the h/w rate table.  We must also factor
811 		 * in whether or not a short preamble is to be used.
812 		 */
813 		cix = rt->info[rix].controlRate;
814 		ctsrate = rt->info[cix].rateCode;
815 		if (shortPreamble)
816 			ctsrate |= rt->info[cix].shortPreamble;
817 		/*
818 		 * Compute the transmit duration based on the size
819 		 * of an ACK frame.  We call into the HAL to do the
820 		 * computation since it depends on the characteristics
821 		 * of the actual PHY being used.
822 		 */
823 		if (flags & HAL_TXDESC_RTSENA) {	/* SIFS + CTS */
824 			ctsduration += ath_hal_computetxtime(ah,
825 			    rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
826 		}
827 		/* SIFS + data */
828 		ctsduration += ath_hal_computetxtime(ah,
829 		    rt, pktlen, rix, shortPreamble);
830 		if ((flags & HAL_TXDESC_NOACK) == 0) {	/* SIFS + ACK */
831 			ctsduration += ath_hal_computetxtime(ah,
832 			    rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
833 		}
834 	} else
835 		ctsrate = 0;
836 
837 	if (++txq->axq_intrcnt >= ATH_TXINTR_PERIOD) {
838 		flags |= HAL_TXDESC_INTREQ;
839 		txq->axq_intrcnt = 0;
840 	}
841 
842 	/*
843 	 * Formulate first tx descriptor with tx controls.
844 	 */
845 	ATH_HAL_SETUPTXDESC(ah, ds,
846 	    pktlen,			/* packet length */
847 	    hdrlen,			/* header length */
848 	    atype,			/* Atheros packet type */
849 	    MIN(in->in_txpower, 60),	/* txpower */
850 	    txrate, try0,		/* series 0 rate/tries */
851 	    keyix,			/* key cache index */
852 	    an->an_tx_antenna,		/* antenna mode */
853 	    flags,			/* flags */
854 	    ctsrate,			/* rts/cts rate */
855 	    ctsduration);		/* rts/cts duration */
856 	bf->bf_flags = flags;
857 
858 	ATH_DEBUG((ATH_DBG_SEND, "ath: ath_xmit(): to %s totlen=%d "
859 	    "an->an_tx_rate1sp=%d tx_rate2sp=%d tx_rate3sp=%d "
860 	    "qnum=%d rix=%d sht=%d dur = %d\n",
861 	    ieee80211_macaddr_sprintf(wh->i_addr1), mbslen, an->an_tx_rate1sp,
862 	    an->an_tx_rate2sp, an->an_tx_rate3sp,
863 	    txq->axq_qnum, rix, shortPreamble, *(uint16_t *)wh->i_dur));
864 
865 	/*
866 	 * Setup the multi-rate retry state only when we're
867 	 * going to use it.  This assumes ath_hal_setuptxdesc
868 	 * initializes the descriptors (so we don't have to)
869 	 * when the hardware supports multi-rate retry and
870 	 * we don't use it.
871 	 */
872 	if (try0 != ATH_TXMAXTRY)
873 		ATH_HAL_SETUPXTXDESC(ah, ds,
874 		    an->an_tx_rate1sp, 2,	/* series 1 */
875 		    an->an_tx_rate2sp, 2,	/* series 2 */
876 		    an->an_tx_rate3sp, 2);	/* series 3 */
877 
878 	ds->ds_link = 0;
879 	ds->ds_data = bf->bf_dma.cookie.dmac_address;
880 	ATH_HAL_FILLTXDESC(ah, ds,
881 	    mbslen,		/* segment length */
882 	    AH_TRUE,		/* first segment */
883 	    AH_TRUE,		/* last segment */
884 	    ds);		/* first descriptor */
885 
886 	ATH_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV);
887 
888 	mutex_enter(&txq->axq_lock);
889 	list_insert_tail(&txq->axq_list, bf);
890 	if (txq->axq_link == NULL) {
891 		ATH_HAL_PUTTXBUF(ah, txq->axq_qnum, bf->bf_daddr);
892 	} else {
893 		*txq->axq_link = bf->bf_daddr;
894 	}
895 	txq->axq_link = &ds->ds_link;
896 	mutex_exit(&txq->axq_lock);
897 
898 	ATH_HAL_TXSTART(ah, txq->axq_qnum);
899 
900 	ic->ic_stats.is_tx_frags++;
901 	ic->ic_stats.is_tx_bytes += pktlen;
902 
903 	return (0);
904 }
905 
906 /*
907  * Transmit a management frame.  On failure we reclaim the skbuff.
908  * Note that management frames come directly from the 802.11 layer
909  * and do not honor the send queue flow control.  Need to investigate
910  * using priority queueing so management frames can bypass data.
911  */
912 static int
913 ath_xmit(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
914 {
915 	ath_t *asc = (ath_t *)ic;
916 	struct ath_hal *ah = asc->asc_ah;
917 	struct ieee80211_node *in = NULL;
918 	struct ath_buf *bf = NULL;
919 	struct ieee80211_frame *wh;
920 	int error = 0;
921 
922 	ASSERT(mp->b_next == NULL);
923 
924 	/* Grab a TX buffer */
925 	mutex_enter(&asc->asc_txbuflock);
926 	bf = list_head(&asc->asc_txbuf_list);
927 	if (bf != NULL)
928 		list_remove(&asc->asc_txbuf_list, bf);
929 	if (list_empty(&asc->asc_txbuf_list)) {
930 		ATH_DEBUG((ATH_DBG_SEND, "ath: ath_mgmt_send(): "
931 		    "stop queue\n"));
932 		asc->asc_stats.ast_tx_qstop++;
933 	}
934 	mutex_exit(&asc->asc_txbuflock);
935 	if (bf == NULL) {
936 		ATH_DEBUG((ATH_DBG_SEND, "ath: ath_mgmt_send(): discard, "
937 		    "no xmit buf\n"));
938 		ic->ic_stats.is_tx_nobuf++;
939 		if ((type & IEEE80211_FC0_TYPE_MASK) ==
940 		    IEEE80211_FC0_TYPE_DATA) {
941 			asc->asc_stats.ast_tx_nobuf++;
942 			mutex_enter(&asc->asc_resched_lock);
943 			asc->asc_resched_needed = B_TRUE;
944 			mutex_exit(&asc->asc_resched_lock);
945 		} else {
946 			asc->asc_stats.ast_tx_nobufmgt++;
947 			freemsg(mp);
948 		}
949 		return (ENOMEM);
950 	}
951 
952 	wh = (struct ieee80211_frame *)mp->b_rptr;
953 
954 	/* Locate node */
955 	in = ieee80211_find_txnode(ic,  wh->i_addr1);
956 	if (in == NULL) {
957 		error = EIO;
958 		goto bad;
959 	}
960 
961 	in->in_inact = 0;
962 	switch (type & IEEE80211_FC0_TYPE_MASK) {
963 	case IEEE80211_FC0_TYPE_DATA:
964 		(void) ieee80211_encap(ic, mp, in);
965 		break;
966 	default:
967 		if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
968 		    IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
969 			/* fill time stamp */
970 			uint64_t tsf;
971 			uint32_t *tstamp;
972 
973 			tsf = ATH_HAL_GETTSF64(ah);
974 			/* adjust 100us delay to xmit */
975 			tsf += 100;
976 			tstamp = (uint32_t *)&wh[1];
977 			tstamp[0] = LE_32(tsf & 0xffffffff);
978 			tstamp[1] = LE_32(tsf >> 32);
979 		}
980 		asc->asc_stats.ast_tx_mgmt++;
981 		break;
982 	}
983 
984 	error = ath_tx_start(asc, in, bf, mp);
985 	if (error != 0) {
986 bad:
987 		ic->ic_stats.is_tx_failed++;
988 		if (bf != NULL) {
989 			mutex_enter(&asc->asc_txbuflock);
990 			list_insert_tail(&asc->asc_txbuf_list, bf);
991 			mutex_exit(&asc->asc_txbuflock);
992 		}
993 	}
994 	if (in != NULL)
995 		ieee80211_free_node(in);
996 	if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
997 	    error == 0) {
998 		freemsg(mp);
999 	}
1000 
1001 	return (error);
1002 }
1003 
1004 static mblk_t *
1005 ath_m_tx(void *arg, mblk_t *mp)
1006 {
1007 	ath_t *asc = arg;
1008 	ieee80211com_t *ic = (ieee80211com_t *)asc;
1009 	mblk_t *next;
1010 	int error = 0;
1011 
1012 	/*
1013 	 * No data frames go out unless we're associated; this
1014 	 * should not happen as the 802.11 layer does not enable
1015 	 * the xmit queue until we enter the RUN state.
1016 	 */
1017 	if (ic->ic_state != IEEE80211_S_RUN) {
1018 		ATH_DEBUG((ATH_DBG_SEND, "ath: ath_m_tx(): "
1019 		    "discard, state %u\n", ic->ic_state));
1020 		asc->asc_stats.ast_tx_discard++;
1021 		freemsgchain(mp);
1022 		return (NULL);
1023 	}
1024 
1025 	while (mp != NULL) {
1026 		next = mp->b_next;
1027 		mp->b_next = NULL;
1028 		error = ath_xmit(ic, mp, IEEE80211_FC0_TYPE_DATA);
1029 		if (error != 0) {
1030 			mp->b_next = next;
1031 			if (error == ENOMEM) {
1032 				break;
1033 			} else {
1034 				freemsgchain(mp);	/* CR6501759 issues */
1035 				return (NULL);
1036 			}
1037 		}
1038 		mp = next;
1039 	}
1040 
1041 	return (mp);
1042 
1043 }
1044 
1045 static int
1046 ath_tx_processq(ath_t *asc, struct ath_txq *txq)
1047 {
1048 	ieee80211com_t *ic = (ieee80211com_t *)asc;
1049 	struct ath_hal *ah = asc->asc_ah;
1050 	struct ath_buf *bf;
1051 	struct ath_desc *ds;
1052 	struct ieee80211_node *in;
1053 	int32_t sr, lr, nacked = 0;
1054 	HAL_STATUS status;
1055 	struct ath_node *an;
1056 
1057 	for (;;) {
1058 		mutex_enter(&txq->axq_lock);
1059 		bf = list_head(&txq->axq_list);
1060 		if (bf == NULL) {
1061 			txq->axq_link = NULL;
1062 			mutex_exit(&txq->axq_lock);
1063 			break;
1064 		}
1065 		ds = bf->bf_desc;	/* last decriptor */
1066 		status = ATH_HAL_TXPROCDESC(ah, ds);
1067 #ifdef DEBUG
1068 		ath_printtxbuf(bf, status == HAL_OK);
1069 #endif
1070 		if (status == HAL_EINPROGRESS) {
1071 			mutex_exit(&txq->axq_lock);
1072 			break;
1073 		}
1074 		list_remove(&txq->axq_list, bf);
1075 		mutex_exit(&txq->axq_lock);
1076 		in = bf->bf_in;
1077 		if (in != NULL) {
1078 			an = ATH_NODE(in);
1079 			/* Successful transmition */
1080 			if (ds->ds_txstat.ts_status == 0) {
1081 				an->an_tx_ok++;
1082 				an->an_tx_antenna =
1083 				    ds->ds_txstat.ts_antenna;
1084 				if (ds->ds_txstat.ts_rate &
1085 				    HAL_TXSTAT_ALTRATE)
1086 					asc->asc_stats.ast_tx_altrate++;
1087 				asc->asc_stats.ast_tx_rssidelta =
1088 				    ds->ds_txstat.ts_rssi -
1089 				    asc->asc_stats.ast_tx_rssi;
1090 				asc->asc_stats.ast_tx_rssi =
1091 				    ds->ds_txstat.ts_rssi;
1092 			} else {
1093 				an->an_tx_err++;
1094 				if (ds->ds_txstat.ts_status &
1095 				    HAL_TXERR_XRETRY)
1096 					asc->asc_stats.
1097 					    ast_tx_xretries++;
1098 				if (ds->ds_txstat.ts_status &
1099 				    HAL_TXERR_FIFO)
1100 					asc->asc_stats.ast_tx_fifoerr++;
1101 				if (ds->ds_txstat.ts_status &
1102 				    HAL_TXERR_FILT)
1103 					asc->asc_stats.
1104 					    ast_tx_filtered++;
1105 				an->an_tx_antenna = 0;	/* invalidate */
1106 			}
1107 			sr = ds->ds_txstat.ts_shortretry;
1108 			lr = ds->ds_txstat.ts_longretry;
1109 			asc->asc_stats.ast_tx_shortretry += sr;
1110 			asc->asc_stats.ast_tx_longretry += lr;
1111 			/*
1112 			 * Hand the descriptor to the rate control algorithm.
1113 			 */
1114 			if ((ds->ds_txstat.ts_status & HAL_TXERR_FILT) == 0 &&
1115 			    (bf->bf_flags & HAL_TXDESC_NOACK) == 0) {
1116 				/*
1117 				 * If frame was ack'd update the last rx time
1118 				 * used to workaround phantom bmiss interrupts.
1119 				 */
1120 				if (ds->ds_txstat.ts_status == 0) {
1121 					nacked++;
1122 					an->an_tx_ok++;
1123 				} else {
1124 					an->an_tx_err++;
1125 				}
1126 				an->an_tx_retr += sr + lr;
1127 			}
1128 		}
1129 		bf->bf_in = NULL;
1130 		mutex_enter(&asc->asc_txbuflock);
1131 		list_insert_tail(&asc->asc_txbuf_list, bf);
1132 		mutex_exit(&asc->asc_txbuflock);
1133 		/*
1134 		 * Reschedule stalled outbound packets
1135 		 */
1136 		mutex_enter(&asc->asc_resched_lock);
1137 		if (asc->asc_resched_needed) {
1138 			asc->asc_resched_needed = B_FALSE;
1139 			mac_tx_update(ic->ic_mach);
1140 		}
1141 		mutex_exit(&asc->asc_resched_lock);
1142 	}
1143 	return (nacked);
1144 }
1145 
1146 
1147 static void
1148 ath_tx_handler(ath_t *asc)
1149 {
1150 	int i;
1151 
1152 	/*
1153 	 * Process each active queue.
1154 	 */
1155 	for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
1156 		if (ATH_TXQ_SETUP(asc, i)) {
1157 			(void) ath_tx_processq(asc, &asc->asc_txq[i]);
1158 		}
1159 	}
1160 }
1161 
1162 static struct ieee80211_node *
1163 ath_node_alloc(ieee80211com_t *ic)
1164 {
1165 	struct ath_node *an;
1166 	ath_t *asc = (ath_t *)ic;
1167 
1168 	an = kmem_zalloc(sizeof (struct ath_node), KM_SLEEP);
1169 	ath_rate_update(asc, &an->an_node, 0);
1170 	return (&an->an_node);
1171 }
1172 
1173 static void
1174 ath_node_free(struct ieee80211_node *in)
1175 {
1176 	ieee80211com_t *ic = in->in_ic;
1177 	ath_t *asc = (ath_t *)ic;
1178 	struct ath_buf *bf;
1179 	struct ath_txq *txq;
1180 	int32_t i;
1181 
1182 	for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
1183 		if (ATH_TXQ_SETUP(asc, i)) {
1184 			txq = &asc->asc_txq[i];
1185 			mutex_enter(&txq->axq_lock);
1186 			bf = list_head(&txq->axq_list);
1187 			while (bf != NULL) {
1188 				if (bf->bf_in == in) {
1189 					bf->bf_in = NULL;
1190 				}
1191 				bf = list_next(&txq->axq_list, bf);
1192 			}
1193 			mutex_exit(&txq->axq_lock);
1194 		}
1195 	}
1196 	ic->ic_node_cleanup(in);
1197 	if (in->in_wpa_ie != NULL)
1198 		ieee80211_free(in->in_wpa_ie);
1199 	kmem_free(in, sizeof (struct ath_node));
1200 }
1201 
1202 static void
1203 ath_next_scan(void *arg)
1204 {
1205 	ieee80211com_t *ic = arg;
1206 	ath_t *asc = (ath_t *)ic;
1207 
1208 	asc->asc_scan_timer = 0;
1209 	if (ic->ic_state == IEEE80211_S_SCAN) {
1210 		asc->asc_scan_timer = timeout(ath_next_scan, (void *)asc,
1211 		    drv_usectohz(ath_dwelltime * 1000));
1212 		ieee80211_next_scan(ic);
1213 	}
1214 }
1215 
1216 static void
1217 ath_stop_scantimer(ath_t *asc)
1218 {
1219 	timeout_id_t tmp_id = 0;
1220 
1221 	while ((asc->asc_scan_timer != 0) && (tmp_id != asc->asc_scan_timer)) {
1222 		tmp_id = asc->asc_scan_timer;
1223 		(void) untimeout(tmp_id);
1224 	}
1225 	asc->asc_scan_timer = 0;
1226 }
1227 
1228 static int32_t
1229 ath_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
1230 {
1231 	ath_t *asc = (ath_t *)ic;
1232 	struct ath_hal *ah = asc->asc_ah;
1233 	struct ieee80211_node *in;
1234 	int32_t i, error;
1235 	uint8_t *bssid;
1236 	uint32_t rfilt;
1237 	enum ieee80211_state ostate;
1238 
1239 	static const HAL_LED_STATE leds[] = {
1240 	    HAL_LED_INIT,	/* IEEE80211_S_INIT */
1241 	    HAL_LED_SCAN,	/* IEEE80211_S_SCAN */
1242 	    HAL_LED_AUTH,	/* IEEE80211_S_AUTH */
1243 	    HAL_LED_ASSOC, 	/* IEEE80211_S_ASSOC */
1244 	    HAL_LED_RUN, 	/* IEEE80211_S_RUN */
1245 	};
1246 	if (!ATH_IS_RUNNING(asc))
1247 		return (0);
1248 
1249 	ostate = ic->ic_state;
1250 	if (nstate != IEEE80211_S_SCAN)
1251 		ath_stop_scantimer(asc);
1252 
1253 	ATH_LOCK(asc);
1254 	ATH_HAL_SETLEDSTATE(ah, leds[nstate]);	/* set LED */
1255 
1256 	if (nstate == IEEE80211_S_INIT) {
1257 		asc->asc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
1258 		ATH_HAL_INTRSET(ah, asc->asc_imask &~ HAL_INT_GLOBAL);
1259 		ATH_UNLOCK(asc);
1260 		goto done;
1261 	}
1262 	in = ic->ic_bss;
1263 	error = ath_chan_set(asc, ic->ic_curchan);
1264 	if (error != 0) {
1265 		if (nstate != IEEE80211_S_SCAN) {
1266 			ATH_UNLOCK(asc);
1267 			ieee80211_reset_chan(ic);
1268 			goto bad;
1269 		}
1270 	}
1271 
1272 	rfilt = ath_calcrxfilter(asc);
1273 	if (nstate == IEEE80211_S_SCAN)
1274 		bssid = ic->ic_macaddr;
1275 	else
1276 		bssid = in->in_bssid;
1277 	ATH_HAL_SETRXFILTER(ah, rfilt);
1278 
1279 	if (nstate == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS)
1280 		ATH_HAL_SETASSOCID(ah, bssid, in->in_associd);
1281 	else
1282 		ATH_HAL_SETASSOCID(ah, bssid, 0);
1283 	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
1284 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1285 			if (ATH_HAL_KEYISVALID(ah, i))
1286 				ATH_HAL_KEYSETMAC(ah, i, bssid);
1287 		}
1288 	}
1289 
1290 	if ((nstate == IEEE80211_S_RUN) &&
1291 	    (ostate != IEEE80211_S_RUN)) {
1292 		/* Configure the beacon and sleep timers. */
1293 		ath_beacon_config(asc);
1294 	} else {
1295 		asc->asc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
1296 		ATH_HAL_INTRSET(ah, asc->asc_imask);
1297 	}
1298 	/*
1299 	 * Reset the rate control state.
1300 	 */
1301 	ath_rate_ctl_reset(asc, nstate);
1302 
1303 	if (nstate == IEEE80211_S_RUN && (ostate != IEEE80211_S_RUN)) {
1304 		nvlist_t *attr_list = NULL;
1305 		sysevent_id_t eid;
1306 		int32_t err = 0;
1307 		char *str_name = "ATH";
1308 		char str_value[256] = {0};
1309 
1310 		ATH_DEBUG((ATH_DBG_80211, "ath: ath new state(RUN): "
1311 		    "ic_flags=0x%08x iv=%d"
1312 		    " bssid=%s capinfo=0x%04x chan=%d\n",
1313 		    ic->ic_flags,
1314 		    in->in_intval,
1315 		    ieee80211_macaddr_sprintf(in->in_bssid),
1316 		    in->in_capinfo,
1317 		    ieee80211_chan2ieee(ic, in->in_chan)));
1318 
1319 		(void) sprintf(str_value, "%s%s%d", "-i ",
1320 		    ddi_driver_name(asc->asc_dev),
1321 		    ddi_get_instance(asc->asc_dev));
1322 		if (nvlist_alloc(&attr_list,
1323 		    NV_UNIQUE_NAME_TYPE, KM_SLEEP) == 0) {
1324 			err = nvlist_add_string(attr_list,
1325 			    str_name, str_value);
1326 			if (err != DDI_SUCCESS)
1327 				ATH_DEBUG((ATH_DBG_80211, "ath: "
1328 				    "ath_new_state: error log event\n"));
1329 			err = ddi_log_sysevent(asc->asc_dev,
1330 			    DDI_VENDOR_SUNW, "class",
1331 			    "subclass", attr_list,
1332 			    &eid, DDI_NOSLEEP);
1333 			if (err != DDI_SUCCESS)
1334 				ATH_DEBUG((ATH_DBG_80211, "ath: "
1335 				    "ath_new_state(): error log event\n"));
1336 			nvlist_free(attr_list);
1337 		}
1338 	}
1339 
1340 	ATH_UNLOCK(asc);
1341 done:
1342 	/*
1343 	 * Invoke the parent method to complete the work.
1344 	 */
1345 	error = asc->asc_newstate(ic, nstate, arg);
1346 	/*
1347 	 * Finally, start any timers.
1348 	 */
1349 	if (nstate == IEEE80211_S_RUN) {
1350 		ieee80211_start_watchdog(ic, 1);
1351 	} else if ((nstate == IEEE80211_S_SCAN) && (ostate != nstate)) {
1352 		/* start ap/neighbor scan timer */
1353 		ASSERT(asc->asc_scan_timer == 0);
1354 		asc->asc_scan_timer = timeout(ath_next_scan, (void *)asc,
1355 		    drv_usectohz(ath_dwelltime * 1000));
1356 	}
1357 bad:
1358 	return (error);
1359 }
1360 
1361 /*
1362  * Periodically recalibrate the PHY to account
1363  * for temperature/environment changes.
1364  */
1365 static void
1366 ath_calibrate(ath_t *asc)
1367 {
1368 	struct ath_hal *ah = asc->asc_ah;
1369 	HAL_BOOL iqcaldone;
1370 
1371 	asc->asc_stats.ast_per_cal++;
1372 
1373 	if (ATH_HAL_GETRFGAIN(ah) == HAL_RFGAIN_NEED_CHANGE) {
1374 		/*
1375 		 * Rfgain is out of bounds, reset the chip
1376 		 * to load new gain values.
1377 		 */
1378 		ATH_DEBUG((ATH_DBG_HAL, "ath: ath_calibrate(): "
1379 		    "Need change RFgain\n"));
1380 		asc->asc_stats.ast_per_rfgain++;
1381 		(void) ath_reset(&asc->asc_isc);
1382 	}
1383 	if (!ATH_HAL_CALIBRATE(ah, &asc->asc_curchan, &iqcaldone)) {
1384 		ATH_DEBUG((ATH_DBG_HAL, "ath: ath_calibrate(): "
1385 		    "calibration of channel %u failed\n",
1386 		    asc->asc_curchan.channel));
1387 		asc->asc_stats.ast_per_calfail++;
1388 	}
1389 }
1390 
1391 static void
1392 ath_watchdog(void *arg)
1393 {
1394 	ath_t *asc = arg;
1395 	ieee80211com_t *ic = &asc->asc_isc;
1396 	int ntimer = 0;
1397 
1398 	ATH_LOCK(asc);
1399 	ic->ic_watchdog_timer = 0;
1400 	if (!ATH_IS_RUNNING(asc)) {
1401 		ATH_UNLOCK(asc);
1402 		return;
1403 	}
1404 
1405 	if (ic->ic_state == IEEE80211_S_RUN) {
1406 		/* periodic recalibration */
1407 		ath_calibrate(asc);
1408 
1409 		/*
1410 		 * Start the background rate control thread if we
1411 		 * are not configured to use a fixed xmit rate.
1412 		 */
1413 		if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
1414 			asc->asc_stats.ast_rate_calls ++;
1415 			if (ic->ic_opmode == IEEE80211_M_STA)
1416 				ath_rate_ctl(ic, ic->ic_bss);
1417 			else
1418 				ieee80211_iterate_nodes(&ic->ic_sta,
1419 				    ath_rate_cb, asc);
1420 		}
1421 
1422 		ntimer = 1;
1423 	}
1424 	ATH_UNLOCK(asc);
1425 
1426 	ieee80211_watchdog(ic);
1427 	if (ntimer != 0)
1428 		ieee80211_start_watchdog(ic, ntimer);
1429 }
1430 
1431 static uint_t
1432 ath_intr(caddr_t arg)
1433 {
1434 	ath_t *asc = (ath_t *)arg;
1435 	struct ath_hal *ah = asc->asc_ah;
1436 	HAL_INT status;
1437 	ieee80211com_t *ic = (ieee80211com_t *)asc;
1438 
1439 	ATH_LOCK(asc);
1440 
1441 	if (!ATH_IS_RUNNING(asc)) {
1442 		/*
1443 		 * The hardware is not ready/present, don't touch anything.
1444 		 * Note this can happen early on if the IRQ is shared.
1445 		 */
1446 		ATH_UNLOCK(asc);
1447 		return (DDI_INTR_UNCLAIMED);
1448 	}
1449 
1450 	if (!ATH_HAL_INTRPEND(ah)) {	/* shared irq, not for us */
1451 		ATH_UNLOCK(asc);
1452 		return (DDI_INTR_UNCLAIMED);
1453 	}
1454 
1455 	ATH_HAL_GETISR(ah, &status);
1456 	status &= asc->asc_imask;
1457 	if (status & HAL_INT_FATAL) {
1458 		asc->asc_stats.ast_hardware++;
1459 		goto reset;
1460 	} else if (status & HAL_INT_RXORN) {
1461 		asc->asc_stats.ast_rxorn++;
1462 		goto reset;
1463 	} else {
1464 		if (status & HAL_INT_RXEOL) {
1465 			asc->asc_stats.ast_rxeol++;
1466 			asc->asc_rxlink = NULL;
1467 		}
1468 		if (status & HAL_INT_TXURN) {
1469 			asc->asc_stats.ast_txurn++;
1470 			ATH_HAL_UPDATETXTRIGLEVEL(ah, AH_TRUE);
1471 		}
1472 
1473 		if (status & HAL_INT_RX) {
1474 			asc->asc_rx_pend = 1;
1475 			ddi_trigger_softintr(asc->asc_softint_id);
1476 		}
1477 		if (status & HAL_INT_TX) {
1478 			ath_tx_handler(asc);
1479 		}
1480 		ATH_UNLOCK(asc);
1481 
1482 		if (status & HAL_INT_SWBA) {
1483 			/* This will occur only in Host-AP or Ad-Hoc mode */
1484 			return (DDI_INTR_CLAIMED);
1485 		}
1486 		if (status & HAL_INT_BMISS) {
1487 			if (ic->ic_state == IEEE80211_S_RUN) {
1488 				(void) ieee80211_new_state(ic,
1489 				    IEEE80211_S_ASSOC, -1);
1490 			}
1491 		}
1492 	}
1493 
1494 	return (DDI_INTR_CLAIMED);
1495 reset:
1496 	(void) ath_reset(ic);
1497 	ATH_UNLOCK(asc);
1498 	return (DDI_INTR_CLAIMED);
1499 }
1500 
1501 static uint_t
1502 ath_softint_handler(caddr_t data)
1503 {
1504 	ath_t *asc = (ath_t *)data;
1505 
1506 	/*
1507 	 * Check if the soft interrupt is triggered by another
1508 	 * driver at the same level.
1509 	 */
1510 	ATH_LOCK(asc);
1511 	if (asc->asc_rx_pend) { /* Soft interrupt for this driver */
1512 		asc->asc_rx_pend = 0;
1513 		ATH_UNLOCK(asc);
1514 		ath_rx_handler(asc);
1515 		return (DDI_INTR_CLAIMED);
1516 	}
1517 	ATH_UNLOCK(asc);
1518 	return (DDI_INTR_UNCLAIMED);
1519 }
1520 
1521 /*
1522  * following are gld callback routine
1523  * ath_gld_send, ath_gld_ioctl, ath_gld_gstat
1524  * are listed in other corresponding sections.
1525  * reset the hardware w/o losing operational state.  this is
1526  * basically a more efficient way of doing ath_gld_stop, ath_gld_start,
1527  * followed by state transitions to the current 802.11
1528  * operational state.  used to recover from errors rx overrun
1529  * and to reset the hardware when rf gain settings must be reset.
1530  */
1531 
1532 static void
1533 ath_stop_locked(ath_t *asc)
1534 {
1535 	ieee80211com_t *ic = (ieee80211com_t *)asc;
1536 	struct ath_hal *ah = asc->asc_ah;
1537 
1538 	ATH_LOCK_ASSERT(asc);
1539 	/*
1540 	 * Shutdown the hardware and driver:
1541 	 *    reset 802.11 state machine
1542 	 *    turn off timers
1543 	 *    disable interrupts
1544 	 *    turn off the radio
1545 	 *    clear transmit machinery
1546 	 *    clear receive machinery
1547 	 *    drain and release tx queues
1548 	 *    reclaim beacon resources
1549 	 *    power down hardware
1550 	 *
1551 	 * Note that some of this work is not possible if the
1552 	 * hardware is gone (invalid).
1553 	 */
1554 	ATH_UNLOCK(asc);
1555 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1556 	ieee80211_stop_watchdog(ic);
1557 	ATH_LOCK(asc);
1558 	ATH_HAL_INTRSET(ah, 0);
1559 	ath_draintxq(asc);
1560 	if (ATH_IS_RUNNING(asc)) {
1561 		ath_stoprecv(asc);
1562 		ATH_HAL_PHYDISABLE(ah);
1563 	} else {
1564 		asc->asc_rxlink = NULL;
1565 	}
1566 }
1567 
1568 static void
1569 ath_m_stop(void *arg)
1570 {
1571 	ath_t *asc = arg;
1572 	struct ath_hal *ah = asc->asc_ah;
1573 
1574 	ATH_LOCK(asc);
1575 	ath_stop_locked(asc);
1576 	ATH_HAL_SETPOWER(ah, HAL_PM_AWAKE);
1577 	asc->asc_invalid = 1;
1578 	ATH_UNLOCK(asc);
1579 }
1580 
1581 int
1582 ath_m_start(void *arg)
1583 {
1584 	ath_t *asc = arg;
1585 	ieee80211com_t *ic = (ieee80211com_t *)asc;
1586 	struct ath_hal *ah = asc->asc_ah;
1587 	HAL_STATUS status;
1588 
1589 	ATH_LOCK(asc);
1590 	/*
1591 	 * Stop anything previously setup.  This is safe
1592 	 * whether this is the first time through or not.
1593 	 */
1594 	ath_stop_locked(asc);
1595 
1596 	/*
1597 	 * The basic interface to setting the hardware in a good
1598 	 * state is ``reset''.  On return the hardware is known to
1599 	 * be powered up and with interrupts disabled.  This must
1600 	 * be followed by initialization of the appropriate bits
1601 	 * and then setup of the interrupt mask.
1602 	 */
1603 	asc->asc_curchan.channel = ic->ic_curchan->ich_freq;
1604 	asc->asc_curchan.channelFlags = ath_chan2flags(ic, ic->ic_curchan);
1605 	if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode,
1606 	    &asc->asc_curchan, AH_FALSE, &status)) {
1607 		ATH_DEBUG((ATH_DBG_HAL, "ath: ath_m_start(): "
1608 		    "reset hardware failed: '%s' (HAL status %u)\n",
1609 		    ath_get_hal_status_desc(status), status));
1610 		ATH_UNLOCK(asc);
1611 		return (ENOTACTIVE);
1612 	}
1613 
1614 	(void) ath_startrecv(asc);
1615 
1616 	/*
1617 	 * Enable interrupts.
1618 	 */
1619 	asc->asc_imask = HAL_INT_RX | HAL_INT_TX
1620 	    | HAL_INT_RXEOL | HAL_INT_RXORN
1621 	    | HAL_INT_FATAL | HAL_INT_GLOBAL;
1622 	ATH_HAL_INTRSET(ah, asc->asc_imask);
1623 
1624 	ic->ic_state = IEEE80211_S_INIT;
1625 
1626 	/*
1627 	 * The hardware should be ready to go now so it's safe
1628 	 * to kick the 802.11 state machine as it's likely to
1629 	 * immediately call back to us to send mgmt frames.
1630 	 */
1631 	ath_chan_change(asc, ic->ic_curchan);
1632 	asc->asc_invalid = 0;
1633 	ATH_UNLOCK(asc);
1634 	return (0);
1635 }
1636 
1637 
1638 static int
1639 ath_m_unicst(void *arg, const uint8_t *macaddr)
1640 {
1641 	ath_t *asc = arg;
1642 	struct ath_hal *ah = asc->asc_ah;
1643 
1644 	ATH_DEBUG((ATH_DBG_GLD, "ath: ath_gld_saddr(): "
1645 	    "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
1646 	    macaddr[0], macaddr[1], macaddr[2],
1647 	    macaddr[3], macaddr[4], macaddr[5]));
1648 
1649 	ATH_LOCK(asc);
1650 	IEEE80211_ADDR_COPY(asc->asc_isc.ic_macaddr, macaddr);
1651 	ATH_HAL_SETMAC(ah, asc->asc_isc.ic_macaddr);
1652 
1653 	(void) ath_reset(&asc->asc_isc);
1654 	ATH_UNLOCK(asc);
1655 	return (0);
1656 }
1657 
1658 static int
1659 ath_m_promisc(void *arg, boolean_t on)
1660 {
1661 	ath_t *asc = arg;
1662 	struct ath_hal *ah = asc->asc_ah;
1663 	uint32_t rfilt;
1664 
1665 	ATH_LOCK(asc);
1666 	rfilt = ATH_HAL_GETRXFILTER(ah);
1667 	if (on)
1668 		rfilt |= HAL_RX_FILTER_PROM;
1669 	else
1670 		rfilt &= ~HAL_RX_FILTER_PROM;
1671 	asc->asc_promisc = on;
1672 	ATH_HAL_SETRXFILTER(ah, rfilt);
1673 	ATH_UNLOCK(asc);
1674 
1675 	return (0);
1676 }
1677 
1678 static int
1679 ath_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
1680 {
1681 	ath_t *asc = arg;
1682 	struct ath_hal *ah = asc->asc_ah;
1683 	uint32_t val, index, bit;
1684 	uint8_t pos;
1685 	uint32_t *mfilt = asc->asc_mcast_hash;
1686 
1687 	ATH_LOCK(asc);
1688 	/* calculate XOR of eight 6bit values */
1689 	val = ATH_LE_READ_4(mca + 0);
1690 	pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
1691 	val = ATH_LE_READ_4(mca + 3);
1692 	pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
1693 	pos &= 0x3f;
1694 	index = pos / 32;
1695 	bit = 1 << (pos % 32);
1696 
1697 	if (add) {	/* enable multicast */
1698 		asc->asc_mcast_refs[pos]++;
1699 		mfilt[index] |= bit;
1700 	} else {	/* disable multicast */
1701 		if (--asc->asc_mcast_refs[pos] == 0)
1702 			mfilt[index] &= ~bit;
1703 	}
1704 	ATH_HAL_SETMCASTFILTER(ah, mfilt[0], mfilt[1]);
1705 
1706 	ATH_UNLOCK(asc);
1707 	return (0);
1708 }
1709 
1710 static void
1711 ath_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1712 {
1713 	ath_t *asc = arg;
1714 	int32_t err;
1715 
1716 	err = ieee80211_ioctl(&asc->asc_isc, wq, mp);
1717 	ATH_LOCK(asc);
1718 	if (err == ENETRESET) {
1719 		if (ATH_IS_RUNNING(asc)) {
1720 			ATH_UNLOCK(asc);
1721 			(void) ath_m_start(asc);
1722 			(void) ieee80211_new_state(&asc->asc_isc,
1723 			    IEEE80211_S_SCAN, -1);
1724 			ATH_LOCK(asc);
1725 		}
1726 	}
1727 	ATH_UNLOCK(asc);
1728 }
1729 
1730 static int
1731 ath_m_stat(void *arg, uint_t stat, uint64_t *val)
1732 {
1733 	ath_t *asc = arg;
1734 	ieee80211com_t *ic = (ieee80211com_t *)asc;
1735 	struct ieee80211_node *in = ic->ic_bss;
1736 	struct ieee80211_rateset *rs = &in->in_rates;
1737 
1738 	ATH_LOCK(asc);
1739 	switch (stat) {
1740 	case MAC_STAT_IFSPEED:
1741 		*val = (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2 *
1742 		    1000000ull;
1743 		break;
1744 	case MAC_STAT_NOXMTBUF:
1745 		*val = asc->asc_stats.ast_tx_nobuf +
1746 		    asc->asc_stats.ast_tx_nobufmgt;
1747 		break;
1748 	case MAC_STAT_IERRORS:
1749 		*val = asc->asc_stats.ast_rx_tooshort;
1750 		break;
1751 	case MAC_STAT_RBYTES:
1752 		*val = ic->ic_stats.is_rx_bytes;
1753 		break;
1754 	case MAC_STAT_IPACKETS:
1755 		*val = ic->ic_stats.is_rx_frags;
1756 		break;
1757 	case MAC_STAT_OBYTES:
1758 		*val = ic->ic_stats.is_tx_bytes;
1759 		break;
1760 	case MAC_STAT_OPACKETS:
1761 		*val = ic->ic_stats.is_tx_frags;
1762 		break;
1763 	case MAC_STAT_OERRORS:
1764 	case WIFI_STAT_TX_FAILED:
1765 		*val = asc->asc_stats.ast_tx_fifoerr +
1766 		    asc->asc_stats.ast_tx_xretries +
1767 		    asc->asc_stats.ast_tx_discard;
1768 		break;
1769 	case WIFI_STAT_TX_RETRANS:
1770 		*val = asc->asc_stats.ast_tx_xretries;
1771 		break;
1772 	case WIFI_STAT_FCS_ERRORS:
1773 		*val = asc->asc_stats.ast_rx_crcerr;
1774 		break;
1775 	case WIFI_STAT_WEP_ERRORS:
1776 		*val = asc->asc_stats.ast_rx_badcrypt;
1777 		break;
1778 	case WIFI_STAT_TX_FRAGS:
1779 	case WIFI_STAT_MCAST_TX:
1780 	case WIFI_STAT_RTS_SUCCESS:
1781 	case WIFI_STAT_RTS_FAILURE:
1782 	case WIFI_STAT_ACK_FAILURE:
1783 	case WIFI_STAT_RX_FRAGS:
1784 	case WIFI_STAT_MCAST_RX:
1785 	case WIFI_STAT_RX_DUPS:
1786 		ATH_UNLOCK(asc);
1787 		return (ieee80211_stat(ic, stat, val));
1788 	default:
1789 		ATH_UNLOCK(asc);
1790 		return (ENOTSUP);
1791 	}
1792 	ATH_UNLOCK(asc);
1793 
1794 	return (0);
1795 }
1796 
1797 static int
1798 ath_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
1799 {
1800 	ath_t *asc;
1801 	ieee80211com_t *ic;
1802 	struct ath_hal *ah;
1803 	uint8_t csz;
1804 	HAL_STATUS status;
1805 	caddr_t regs;
1806 	uint32_t i, val;
1807 	uint16_t vendor_id, device_id, command;
1808 	const char *athname;
1809 	int32_t ath_countrycode = CTRY_DEFAULT;	/* country code */
1810 	int32_t err, ath_regdomain = 0; /* regulatory domain */
1811 	char strbuf[32];
1812 	int instance;
1813 	wifi_data_t wd = { 0 };
1814 	mac_register_t *macp;
1815 
1816 	if (cmd != DDI_ATTACH)
1817 		return (DDI_FAILURE);
1818 
1819 	instance = ddi_get_instance(devinfo);
1820 	if (ddi_soft_state_zalloc(ath_soft_state_p, instance) != DDI_SUCCESS) {
1821 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1822 		    "Unable to alloc softstate\n"));
1823 		return (DDI_FAILURE);
1824 	}
1825 
1826 	asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
1827 	ic = (ieee80211com_t *)asc;
1828 	asc->asc_dev = devinfo;
1829 
1830 	mutex_init(&asc->asc_genlock, NULL, MUTEX_DRIVER, NULL);
1831 	mutex_init(&asc->asc_txbuflock, NULL, MUTEX_DRIVER, NULL);
1832 	mutex_init(&asc->asc_rxbuflock, NULL, MUTEX_DRIVER, NULL);
1833 	mutex_init(&asc->asc_resched_lock, NULL, MUTEX_DRIVER, NULL);
1834 
1835 	err = pci_config_setup(devinfo, &asc->asc_cfg_handle);
1836 	if (err != DDI_SUCCESS) {
1837 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1838 		    "pci_config_setup() failed"));
1839 		goto attach_fail0;
1840 	}
1841 
1842 	/*
1843 	 * Cache line size is used to size and align various
1844 	 * structures used to communicate with the hardware.
1845 	 */
1846 	csz = pci_config_get8(asc->asc_cfg_handle, PCI_CONF_CACHE_LINESZ);
1847 	if (csz == 0) {
1848 		/*
1849 		 * We must have this setup properly for rx buffer
1850 		 * DMA to work so force a reasonable value here if it
1851 		 * comes up zero.
1852 		 */
1853 		csz = ATH_DEF_CACHE_BYTES / sizeof (uint32_t);
1854 		pci_config_put8(asc->asc_cfg_handle, PCI_CONF_CACHE_LINESZ,
1855 		    csz);
1856 	}
1857 	asc->asc_cachelsz = csz << 2;
1858 	vendor_id = pci_config_get16(asc->asc_cfg_handle, PCI_CONF_VENID);
1859 	device_id = pci_config_get16(asc->asc_cfg_handle, PCI_CONF_DEVID);
1860 	ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): vendor 0x%x, "
1861 	    "device id 0x%x, cache size %d\n", vendor_id, device_id, csz));
1862 
1863 	athname = ath_hal_probe(vendor_id, device_id);
1864 	ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): athname: %s\n",
1865 	    athname ? athname : "Atheros ???"));
1866 
1867 	/*
1868 	 * Enable response to memory space accesses,
1869 	 * and enabe bus master.
1870 	 */
1871 	command = PCI_COMM_MAE | PCI_COMM_ME;
1872 	pci_config_put16(asc->asc_cfg_handle, PCI_CONF_COMM, command);
1873 	ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1874 	    "set command reg to 0x%x \n", command));
1875 
1876 	pci_config_put8(asc->asc_cfg_handle, PCI_CONF_LATENCY_TIMER, 0xa8);
1877 	val = pci_config_get32(asc->asc_cfg_handle, 0x40);
1878 	if ((val & 0x0000ff00) != 0)
1879 		pci_config_put32(asc->asc_cfg_handle, 0x40, val & 0xffff00ff);
1880 
1881 	err = ddi_regs_map_setup(devinfo, 1,
1882 	    &regs, 0, 0, &ath_reg_accattr, &asc->asc_io_handle);
1883 	ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1884 	    "regs map1 = %x err=%d\n", regs, err));
1885 	if (err != DDI_SUCCESS) {
1886 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1887 		    "ddi_regs_map_setup() failed"));
1888 		goto attach_fail1;
1889 	}
1890 
1891 	ah = ath_hal_attach(device_id, asc, 0, regs, &status);
1892 	if (ah == NULL) {
1893 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1894 		    "unable to attach hw: '%s' (HAL status %u)\n",
1895 		    ath_get_hal_status_desc(status), status));
1896 		goto attach_fail2;
1897 	}
1898 	ATH_HAL_INTRSET(ah, 0);
1899 	asc->asc_ah = ah;
1900 
1901 	if (ah->ah_abi != HAL_ABI_VERSION) {
1902 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1903 		    "HAL ABI mismatch detected (0x%x != 0x%x)\n",
1904 		    ah->ah_abi, HAL_ABI_VERSION));
1905 		goto attach_fail3;
1906 	}
1907 
1908 	ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1909 	    "HAL ABI version 0x%x\n", ah->ah_abi));
1910 	ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1911 	    "HAL mac version %d.%d, phy version %d.%d\n",
1912 	    ah->ah_macVersion, ah->ah_macRev,
1913 	    ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf));
1914 	if (ah->ah_analog5GhzRev)
1915 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1916 		    "HAL 5ghz radio version %d.%d\n",
1917 		    ah->ah_analog5GhzRev >> 4,
1918 		    ah->ah_analog5GhzRev & 0xf));
1919 	if (ah->ah_analog2GhzRev)
1920 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1921 		    "HAL 2ghz radio version %d.%d\n",
1922 		    ah->ah_analog2GhzRev >> 4,
1923 		    ah->ah_analog2GhzRev & 0xf));
1924 
1925 	/*
1926 	 * Check if the MAC has multi-rate retry support.
1927 	 * We do this by trying to setup a fake extended
1928 	 * descriptor.  MAC's that don't have support will
1929 	 * return false w/o doing anything.  MAC's that do
1930 	 * support it will return true w/o doing anything.
1931 	 */
1932 	asc->asc_mrretry = ATH_HAL_SETUPXTXDESC(ah, NULL, 0, 0, 0, 0, 0, 0);
1933 	ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1934 	    "multi rate retry support=%x\n",
1935 	    asc->asc_mrretry));
1936 
1937 	/*
1938 	 * Get the hardware key cache size.
1939 	 */
1940 	asc->asc_keymax = ATH_HAL_KEYCACHESIZE(ah);
1941 	if (asc->asc_keymax > sizeof (asc->asc_keymap) * NBBY) {
1942 		ATH_DEBUG((ATH_DBG_ATTACH, "ath_attach:"
1943 		    " Warning, using only %u entries in %u key cache\n",
1944 		    sizeof (asc->asc_keymap) * NBBY, asc->asc_keymax));
1945 		asc->asc_keymax = sizeof (asc->asc_keymap) * NBBY;
1946 	}
1947 	/*
1948 	 * Reset the key cache since some parts do not
1949 	 * reset the contents on initial power up.
1950 	 */
1951 	for (i = 0; i < asc->asc_keymax; i++)
1952 		ATH_HAL_KEYRESET(ah, i);
1953 
1954 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1955 		setbit(asc->asc_keymap, i);
1956 		setbit(asc->asc_keymap, i+32);
1957 		setbit(asc->asc_keymap, i+64);
1958 		setbit(asc->asc_keymap, i+32+64);
1959 	}
1960 
1961 	ATH_HAL_GETREGDOMAIN(ah, (uint32_t *)&ath_regdomain);
1962 	ATH_HAL_GETCOUNTRYCODE(ah, &ath_countrycode);
1963 	/*
1964 	 * Collect the channel list using the default country
1965 	 * code and including outdoor channels.  The 802.11 layer
1966 	 * is resposible for filtering this list to a set of
1967 	 * channels that it considers ok to use.
1968 	 */
1969 	asc->asc_have11g = 0;
1970 
1971 	/* enable outdoor use, enable extended channels */
1972 	err = ath_getchannels(asc, ath_countrycode, AH_FALSE, AH_TRUE);
1973 	if (err != 0)
1974 		goto attach_fail3;
1975 
1976 	/*
1977 	 * Setup rate tables for all potential media types.
1978 	 */
1979 	ath_rate_setup(asc, IEEE80211_MODE_11A);
1980 	ath_rate_setup(asc, IEEE80211_MODE_11B);
1981 	ath_rate_setup(asc, IEEE80211_MODE_11G);
1982 	ath_rate_setup(asc, IEEE80211_MODE_TURBO_A);
1983 
1984 	/* Setup here so ath_rate_update is happy */
1985 	ath_setcurmode(asc, IEEE80211_MODE_11A);
1986 
1987 	err = ath_desc_alloc(devinfo, asc);
1988 	if (err != DDI_SUCCESS) {
1989 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
1990 		    "failed to allocate descriptors: %d\n", err));
1991 		goto attach_fail3;
1992 	}
1993 
1994 	/* Setup transmit queues in the HAL */
1995 	if (ath_txq_setup(asc))
1996 		goto attach_fail4;
1997 
1998 	ATH_HAL_GETMAC(ah, ic->ic_macaddr);
1999 
2000 	/*
2001 	 * Initialize pointers to device specific functions which
2002 	 * will be used by the generic layer.
2003 	 */
2004 	/* 11g support is identified when we fetch the channel set */
2005 	if (asc->asc_have11g)
2006 		ic->ic_caps |= IEEE80211_C_SHPREAMBLE |
2007 		    IEEE80211_C_SHSLOT;		/* short slot time */
2008 	/*
2009 	 * Query the hal to figure out h/w crypto support.
2010 	 */
2011 	if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_WEP))
2012 		ic->ic_caps |= IEEE80211_C_WEP;
2013 	if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_AES_OCB))
2014 		ic->ic_caps |= IEEE80211_C_AES;
2015 	if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_AES_CCM)) {
2016 		ATH_DEBUG((ATH_DBG_ATTACH, "Atheros support H/W CCMP\n"));
2017 		ic->ic_caps |= IEEE80211_C_AES_CCM;
2018 	}
2019 	if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_CKIP))
2020 		ic->ic_caps |= IEEE80211_C_CKIP;
2021 	if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_TKIP)) {
2022 		ATH_DEBUG((ATH_DBG_ATTACH, "Atheros support H/W TKIP\n"));
2023 		ic->ic_caps |= IEEE80211_C_TKIP;
2024 		/*
2025 		 * Check if h/w does the MIC and/or whether the
2026 		 * separate key cache entries are required to
2027 		 * handle both tx+rx MIC keys.
2028 		 */
2029 		if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_MIC)) {
2030 			ATH_DEBUG((ATH_DBG_ATTACH, "Support H/W TKIP MIC\n"));
2031 			ic->ic_caps |= IEEE80211_C_TKIPMIC;
2032 		}
2033 		if (ATH_HAL_TKIPSPLIT(ah))
2034 			asc->asc_splitmic = 1;
2035 	}
2036 	ic->ic_caps |= IEEE80211_C_WPA;	/* Support WPA/WPA2 */
2037 
2038 	asc->asc_hasclrkey = ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_CLR);
2039 	ic->ic_phytype = IEEE80211_T_OFDM;
2040 	ic->ic_opmode = IEEE80211_M_STA;
2041 	ic->ic_state = IEEE80211_S_INIT;
2042 	ic->ic_maxrssi = ATH_MAX_RSSI;
2043 	ic->ic_set_shortslot = ath_set_shortslot;
2044 	ic->ic_xmit = ath_xmit;
2045 	ieee80211_attach(ic);
2046 
2047 	/* different instance has different WPA door */
2048 	(void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
2049 	    ddi_driver_name(devinfo),
2050 	    ddi_get_instance(devinfo));
2051 
2052 	/* Override 80211 default routines */
2053 	ic->ic_reset = ath_reset;
2054 	asc->asc_newstate = ic->ic_newstate;
2055 	ic->ic_newstate = ath_newstate;
2056 	ic->ic_watchdog = ath_watchdog;
2057 	ic->ic_node_alloc = ath_node_alloc;
2058 	ic->ic_node_free = ath_node_free;
2059 	ic->ic_crypto.cs_key_alloc = ath_key_alloc;
2060 	ic->ic_crypto.cs_key_delete = ath_key_delete;
2061 	ic->ic_crypto.cs_key_set = ath_key_set;
2062 	ieee80211_media_init(ic);
2063 	/*
2064 	 * initialize default tx key
2065 	 */
2066 	ic->ic_def_txkey = 0;
2067 
2068 	asc->asc_rx_pend = 0;
2069 	ATH_HAL_INTRSET(ah, 0);
2070 	err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW,
2071 	    &asc->asc_softint_id, NULL, 0, ath_softint_handler, (caddr_t)asc);
2072 	if (err != DDI_SUCCESS) {
2073 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
2074 		    "ddi_add_softintr() failed\n"));
2075 		goto attach_fail5;
2076 	}
2077 
2078 	if (ddi_get_iblock_cookie(devinfo, 0, &asc->asc_iblock)
2079 	    != DDI_SUCCESS) {
2080 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
2081 		    "Can not get iblock cookie for INT\n"));
2082 		goto attach_fail6;
2083 	}
2084 
2085 	if (ddi_add_intr(devinfo, 0, NULL, NULL, ath_intr,
2086 	    (caddr_t)asc) != DDI_SUCCESS) {
2087 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
2088 		    "Can not set intr for ATH driver\n"));
2089 		goto attach_fail6;
2090 	}
2091 
2092 	/*
2093 	 * Provide initial settings for the WiFi plugin; whenever this
2094 	 * information changes, we need to call mac_plugindata_update()
2095 	 */
2096 	wd.wd_opmode = ic->ic_opmode;
2097 	wd.wd_secalloc = WIFI_SEC_NONE;
2098 	IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
2099 
2100 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
2101 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
2102 		    "MAC version mismatch\n"));
2103 		goto attach_fail7;
2104 	}
2105 
2106 	macp->m_type_ident	= MAC_PLUGIN_IDENT_WIFI;
2107 	macp->m_driver		= asc;
2108 	macp->m_dip		= devinfo;
2109 	macp->m_src_addr	= ic->ic_macaddr;
2110 	macp->m_callbacks	= &ath_m_callbacks;
2111 	macp->m_min_sdu		= 0;
2112 	macp->m_max_sdu		= IEEE80211_MTU;
2113 	macp->m_pdata		= &wd;
2114 	macp->m_pdata_size	= sizeof (wd);
2115 
2116 	err = mac_register(macp, &ic->ic_mach);
2117 	mac_free(macp);
2118 	if (err != 0) {
2119 		ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
2120 		    "mac_register err %x\n", err));
2121 		goto attach_fail7;
2122 	}
2123 
2124 	/* Create minor node of type DDI_NT_NET_WIFI */
2125 	(void) snprintf(strbuf, sizeof (strbuf), "%s%d",
2126 	    ATH_NODENAME, instance);
2127 	err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
2128 	    instance + 1, DDI_NT_NET_WIFI, 0);
2129 	if (err != DDI_SUCCESS)
2130 		ATH_DEBUG((ATH_DBG_ATTACH, "WARN: ath: ath_attach(): "
2131 		    "Create minor node failed - %d\n", err));
2132 
2133 	mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
2134 	asc->asc_invalid = 1;
2135 	asc->asc_promisc = B_FALSE;
2136 	bzero(asc->asc_mcast_refs, sizeof (asc->asc_mcast_refs));
2137 	bzero(asc->asc_mcast_hash, sizeof (asc->asc_mcast_hash));
2138 	return (DDI_SUCCESS);
2139 attach_fail7:
2140 	ddi_remove_intr(devinfo, 0, asc->asc_iblock);
2141 attach_fail6:
2142 	ddi_remove_softintr(asc->asc_softint_id);
2143 attach_fail5:
2144 	(void) ieee80211_detach(ic);
2145 attach_fail4:
2146 	ath_desc_free(asc);
2147 attach_fail3:
2148 	ah->ah_detach(asc->asc_ah);
2149 attach_fail2:
2150 	ddi_regs_map_free(&asc->asc_io_handle);
2151 attach_fail1:
2152 	pci_config_teardown(&asc->asc_cfg_handle);
2153 attach_fail0:
2154 	asc->asc_invalid = 1;
2155 	mutex_destroy(&asc->asc_txbuflock);
2156 	for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
2157 		if (ATH_TXQ_SETUP(asc, i)) {
2158 			struct ath_txq *txq = &asc->asc_txq[i];
2159 			mutex_destroy(&txq->axq_lock);
2160 		}
2161 	}
2162 	mutex_destroy(&asc->asc_rxbuflock);
2163 	mutex_destroy(&asc->asc_genlock);
2164 	mutex_destroy(&asc->asc_resched_lock);
2165 	ddi_soft_state_free(ath_soft_state_p, instance);
2166 
2167 	return (DDI_FAILURE);
2168 }
2169 
2170 static int32_t
2171 ath_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
2172 {
2173 	ath_t *asc;
2174 
2175 	asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
2176 	ASSERT(asc != NULL);
2177 
2178 	if (cmd != DDI_DETACH)
2179 		return (DDI_FAILURE);
2180 
2181 	ath_stop_scantimer(asc);
2182 
2183 	/* disable interrupts */
2184 	ATH_HAL_INTRSET(asc->asc_ah, 0);
2185 
2186 	/*
2187 	 * Unregister from the MAC layer subsystem
2188 	 */
2189 	if (mac_unregister(asc->asc_isc.ic_mach) != 0)
2190 		return (DDI_FAILURE);
2191 
2192 	/* free intterrupt resources */
2193 	ddi_remove_intr(devinfo, 0, asc->asc_iblock);
2194 	ddi_remove_softintr(asc->asc_softint_id);
2195 
2196 	/*
2197 	 * NB: the order of these is important:
2198 	 * o call the 802.11 layer before detaching the hal to
2199 	 *   insure callbacks into the driver to delete global
2200 	 *   key cache entries can be handled
2201 	 * o reclaim the tx queue data structures after calling
2202 	 *   the 802.11 layer as we'll get called back to reclaim
2203 	 *   node state and potentially want to use them
2204 	 * o to cleanup the tx queues the hal is called, so detach
2205 	 *   it last
2206 	 */
2207 	ieee80211_detach(&asc->asc_isc);
2208 	ath_desc_free(asc);
2209 	ath_txq_cleanup(asc);
2210 	asc->asc_ah->ah_detach(asc->asc_ah);
2211 
2212 	/* free io handle */
2213 	ddi_regs_map_free(&asc->asc_io_handle);
2214 	pci_config_teardown(&asc->asc_cfg_handle);
2215 
2216 	/* destroy locks */
2217 	mutex_destroy(&asc->asc_rxbuflock);
2218 	mutex_destroy(&asc->asc_genlock);
2219 	mutex_destroy(&asc->asc_resched_lock);
2220 
2221 	ddi_remove_minor_node(devinfo, NULL);
2222 	ddi_soft_state_free(ath_soft_state_p, ddi_get_instance(devinfo));
2223 
2224 	return (DDI_SUCCESS);
2225 }
2226 
2227 DDI_DEFINE_STREAM_OPS(ath_dev_ops, nulldev, nulldev, ath_attach, ath_detach,
2228     nodev, NULL, D_MP, NULL);
2229 
2230 static struct modldrv ath_modldrv = {
2231 	&mod_driverops,		/* Type of module.  This one is a driver */
2232 	"ath driver 1.3.1/HAL 0.9.17.2",	/* short description */
2233 	&ath_dev_ops		/* driver specific ops */
2234 };
2235 
2236 static struct modlinkage modlinkage = {
2237 	MODREV_1, (void *)&ath_modldrv, NULL
2238 };
2239 
2240 
2241 int
2242 _info(struct modinfo *modinfop)
2243 {
2244 	return (mod_info(&modlinkage, modinfop));
2245 }
2246 
2247 int
2248 _init(void)
2249 {
2250 	int status;
2251 
2252 	status = ddi_soft_state_init(&ath_soft_state_p, sizeof (ath_t), 1);
2253 	if (status != 0)
2254 		return (status);
2255 
2256 	mutex_init(&ath_loglock, NULL, MUTEX_DRIVER, NULL);
2257 	ath_halfix_init();
2258 	mac_init_ops(&ath_dev_ops, "ath");
2259 	status = mod_install(&modlinkage);
2260 	if (status != 0) {
2261 		mac_fini_ops(&ath_dev_ops);
2262 		ath_halfix_finit();
2263 		mutex_destroy(&ath_loglock);
2264 		ddi_soft_state_fini(&ath_soft_state_p);
2265 	}
2266 
2267 	return (status);
2268 }
2269 
2270 int
2271 _fini(void)
2272 {
2273 	int status;
2274 
2275 	status = mod_remove(&modlinkage);
2276 	if (status == 0) {
2277 		mac_fini_ops(&ath_dev_ops);
2278 		ath_halfix_finit();
2279 		mutex_destroy(&ath_loglock);
2280 		ddi_soft_state_fini(&ath_soft_state_p);
2281 	}
2282 	return (status);
2283 }
2284