ath_main.c revision 129d67acdc2d029d3d6cff4022c0c26c81c76f89
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Use is subject to license terms.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Redistribution and use in source and binary forms, with or without
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * modification, are permitted provided that the following conditions
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * are met:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 1. Redistributions of source code must retain the above copyright
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * notice, this list of conditions and the following disclaimer,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * without modification.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 2. Redistributions in binary form must reproduce at minimum a disclaimer
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * redistribution must be conditioned upon including a substantially
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * similar Disclaimer requirement for further binary redistribution.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 3. Neither the names of the above-listed copyright holders nor the names
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * of any contributors may be used to endorse or promote products derived
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * from this software without specific prior written permission.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * NO WARRANTY
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * THE POSSIBILITY OF SUCH DAMAGES.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Driver for the Atheros Wireless LAN controller.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * The Atheros driver calls into net80211 module for IEEE80211 protocol
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * management functionalities. The driver includes a LLD(Low Level Driver)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * part to implement H/W related operations.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The following is the high level structure of ath driver.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * (The arrows between modules indicate function call direction.)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | GLD thread
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * ================== =========================================
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | | |[1] |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | | | GLDv3 Callback functions registered |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | Net80211 | ========================= by |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | module | | | driver |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | | V | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | |======================== | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | Functions exported by net80211 | | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * ========================================== =================
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +----------------------------------+ |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * |[2] | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | Net80211 Callback functions | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | registered by LLD | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +----------------------------------+ |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +-----------------------------------------------------------+
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | LLD Internal functions |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +-----------------------------------------------------------+
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | Software interrupt thread
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The short description of each module is as below:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Module 1: GLD callback functions, which are intercepting the calls from
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * GLD to LLD.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Module 2: Net80211 callback functions registered by LLD, which
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * calls into LLD for H/W related functions needed by net80211.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Module 3: LLD Internal functions, which are responsible for allocing
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * descriptor/buffer, handling interrupt and other H/W
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * operations.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * All functions are running in 3 types of thread:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 1. GLD callbacks threads, such as ioctl, intr, etc.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * 2. Clock interruptt thread which is responsible for scan, rate control and
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * calibration.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * 3. Software Interrupt thread originated in LLD.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The lock strategy is as below:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * There have 4 queues for tx, each queue has one asc_txqlock[i] to
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * prevent conflicts access to queue resource from different thread.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * All the transmit buffers are contained in asc_txbuf which are
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * protected by asc_txbuflock.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Each receive buffers are contained in asc_rxbuf which are protected
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * by asc_rxbuflock.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * In ath struct, asc_genlock is a general lock, protecting most other
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * operational data in ath_softc struct and HAL accesses.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * It is acquired by the interupt handler and most "mode-ctrl" routines.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Any of the locks can be acquired singly, but where multiple
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * locks are acquired, they *must* be in the order:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * asc_genlock >> asc_txqlock[i] >> asc_txbuflock >> asc_rxbuflock
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcextern void ath_halfix_init(void);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcextern void ath_halfix_finit(void);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcextern int32_t ath_getset(ath_t *asc, mblk_t *mp, uint32_t cmd);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * PIO access attributes for registers
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * DMA access attributes for descriptors: NOT to be byte swapped.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * DMA attributes for rx/tx buffers
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* low address */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* DMA flags */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* low address */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* DMA flags */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_start(void *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void ath_m_stop(void *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_multicst(void *, boolean_t, const uint8_t *);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int ath_m_setprop(void *, const char *, mac_prop_id_t,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan uint_t, const void *);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int ath_m_getprop(void *, const char *, mac_prop_id_t,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Available debug flags:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ATH_DBG_INIT, ATH_DBG_GLD, ATH_DBG_HAL, ATH_DBG_INT, ATH_DBG_ATTACH,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ATH_DBG_DETACH, ATH_DBG_AUX, ATH_DBG_WIFICFG, ATH_DBG_OSDEP
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Exception/warning cases not leading to panic.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Normal log information independent of debug.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate an area of memory and a DMA handle for accessing it
3caf11144eab1a56717f986d44ae7f40ee8b28fcxcath_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, size_t memsize,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate handle
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate memory
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Bind the two together
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Free one allocated area of DMAable memory
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Initialize tx/rx buffer list. Allocate DMA memory for
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_buflist_setup(dev_info_t *devinfo, ath_t *asc, list_t *bflist,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_buf **pbf, struct ath_desc **pds, int nbuf, uint_t dmabflags)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_buf *bf = *pbf;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_desc *ds = *pds;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China list_create(bflist, sizeof (struct ath_buf),
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China offsetof(struct ath_buf, bf_node));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China for (i = 0; i < nbuf; i++, bf++, ds++) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China bf->bf_desc = ds;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China bf->bf_daddr = asc->asc_desc_dma.cookie.dmac_address +
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ((uintptr_t)ds - (uintptr_t)asc->asc_desc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China list_insert_tail(bflist, bf);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* alloc DMA memory */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China err = ath_alloc_dma_mem(devinfo, &ath_dma_attr,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc->asc_dmabuf_size, &ath_desc_accattr, DDI_DMA_STREAMING,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China dmabflags, &bf->bf_dma);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Destroy tx/rx buffer list. Free DMA memory.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_buflist_cleanup(list_t *buflist)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_buf *bf;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China bf = list_head(buflist);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China while (bf != NULL) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (bf->bf_m != NULL) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China freemsg(bf->bf_m);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China bf->bf_m = NULL;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* Free DMA buffer */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_free_dma_mem(&bf->bf_dma);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (bf->bf_in != NULL) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ieee80211_free_node(bf->bf_in);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China bf->bf_in = NULL;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China list_remove(buflist, bf);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China bf = list_head(buflist);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China list_destroy(buflist);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_desc_free(ath_t *asc)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_buflist_cleanup(&asc->asc_txbuf_list);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_buflist_cleanup(&asc->asc_rxbuf_list);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* Free descriptor DMA buffer */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_free_dma_mem(&asc->asc_desc_dma);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China kmem_free((void *)asc->asc_vbufptr, asc->asc_vbuflen);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc->asc_vbufptr = NULL;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_desc_alloc(dev_info_t *devinfo, ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF);
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc err = ath_alloc_dma_mem(devinfo, &ath_desc_dma_attr, size,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* virtual address of the first descriptor */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_desc = (struct ath_desc *)asc->asc_desc_dma.mem_va;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_INIT, "ath: ath_desc_alloc(): DMA map: "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "%p (%d) -> %p\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* allocate data structures to describe TX/RX DMA buffers */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_vbuflen = sizeof (struct ath_buf) * (ATH_TXBUF + ATH_RXBUF);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = (struct ath_buf *)kmem_zalloc(asc->asc_vbuflen, KM_SLEEP);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* DMA buffer size for each TX/RX packet */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_dmabuf_size = roundup(1000 + sizeof (struct ieee80211_frame) +
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* create RX buffer list */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China err = ath_buflist_setup(devinfo, asc, &asc->asc_rxbuf_list, &bf, &ds,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ATH_RXBUF, DDI_DMA_READ | DDI_DMA_STREAMING);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_desc_free(asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /* create TX buffer list */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China err = ath_buflist_setup(devinfo, asc, &asc->asc_txbuf_list, &bf, &ds,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ATH_TXBUF, DDI_DMA_STREAMING);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_desc_free(asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China const struct ath_rx_status *rs = &bf->bf_status.ds_rxstat;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RECV, "ath: R (%p %p) %08x %08x %08x "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "%08x %08x %08x %c\n",
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_rx_status *rs;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "no buffer\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Never process the self-linked entry at the end,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * this may be met at heavy load.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China rs = &bf->bf_status.ds_rxstat;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ATH_PA2DESC(asc, ds->ds_link), rs);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status != 0) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_CRC)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_FIFO)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_DECRYPT)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_PHY) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China phyerr = rs->rs_phyerr & 0x1f;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China len = rs->rs_datalen;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* less than sizeof(struct ieee80211_frame) */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if ((rx_mp = allocb(asc->asc_dmabuf_size, BPRI_MED)) == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "allocing mblk buffer failed.\n");
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Ignore control frame received in promisc mode.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Remove the CRC at the end of IEEE80211 frame */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#endif /* DEBUG */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Locate the node for sender, track state, and then
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * pass the (referenced) node up to the 802.11 layer
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * for its use.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Send frame up for processing.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China rs->rs_rssi, rs->rs_tstamp);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } while (loop);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* rx signal state monitoring */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_RXMONITOR(ah, &hal_node_stats, &asc->asc_curchan);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_SEND, "ath: T(%p %p) %08x %08x %08x %08x %08x"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc " %08x %08x %08x %c\n",
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China !done ? ' ' : (ts->ts_status == 0) ? '*' : '!'));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The input parameter mp has following assumption:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * For data packets, GLDv3 mac_wifi plugin allocates and fills the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * ieee80211 header. For management packets, net80211 allocates and
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * fills the ieee80211 header. In both cases, enough spaces in the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * header are left for encryption option.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_tx_start(ath_t *asc, struct ieee80211_node *in, struct ath_buf *bf,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t keyix, iswep, hdrlen, pktlen, mblen, mbslen, try0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * CRC are added by H/W, not encaped by driver,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * but we must count it in pkt length.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (iswep != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Construct the 802.11 header+trailer for an encrypted
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * frame. The only reason this can fail is because of an
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * unknown or unsupported cipher/key type.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (k == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * This can happen when the key is yanked after the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * frame was queued. Just discard the frame; the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * 802.11 layer counts failures and provides
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Adjust the packet + header lengths for the crypto
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * additions and calculate the h/w key index. When
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * a s/w mic is done the frame will have had any mic
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * added to it prior to entry so m0->m_pkthdr.len above will
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * account for it. Otherwise we need to add it to the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * packet length.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* packet header may have moved, reset our local pointer */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* setup descriptors */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The 802.11 layer marks whether or not we should
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * use short preamble based on the current mode and
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * negotiated parameters.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate Atheros packet type from IEEE80211 packet header
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * and setup for rate calculations.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* force all ctl frames to highest queue */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* force all ctl frames to highest queue */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Always use background queue */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Unknown 802.11 frame */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate miscellaneous flags.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate duration. This logically belongs in the 802.11
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * layer but it lacks sufficient information to calculate it.
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate RTS/CTS rate and duration if needed.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * CTS transmit rate is derived from the transmit rate
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * by looking in the h/w rate table. We must also factor
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * in whether or not a short preamble is to be used.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Compute the transmit duration based on the size
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * of an ACK frame. We call into the HAL to do the
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * computation since it depends on the characteristics
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * of the actual PHY being used.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* SIFS + data */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if ((flags & HAL_TXDESC_NOACK) == 0) { /* SIFS + ACK */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Formulate first tx descriptor with tx controls.
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_SEND, "ath: ath_xmit(): to %s totlen=%d "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "an->an_tx_rate1sp=%d tx_rate2sp=%d tx_rate3sp=%d "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "qnum=%d rix=%d sht=%d dur = %d\n",
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_macaddr_sprintf(wh->i_addr1), mbslen, an->an_tx_rate1sp,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc txq->axq_qnum, rix, shortPreamble, *(uint16_t *)wh->i_dur));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Setup the multi-rate retry state only when we're
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * going to use it. This assumes ath_hal_setuptxdesc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * initializes the descriptors (so we don't have to)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * when the hardware supports multi-rate retry and
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * we don't use it.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Transmit a management frame. On failure we reclaim the skbuff.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Note that management frames come directly from the 802.11 layer
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * and do not honor the send queue flow control. Need to investigate
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * using priority queueing so management frames can bypass data.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Grab a TX buffer */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "stop queue\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_SEND, "ath: ath_mgmt_send(): discard, "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "no xmit buf\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Locate node */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* fill time stamp */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* adjust 100us delay to xmit */
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (error != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * No data frames go out unless we're associated; this
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * should not happen as the 802.11 layer does not enable
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * the xmit queue until we enter the RUN state.
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (error != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (mp);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_tx_status *ts;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (;;) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ts = &bf->bf_status.ds_txstat;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China status = ATH_HAL_TXPROCDESC(ah, ds, ts);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Successful transmition */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_status == 0) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China an->an_tx_antenna = ts->ts_antenna;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_rate & HAL_TXSTAT_ALTRATE)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ts->ts_rssi - asc->asc_stats.ast_tx_rssi;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc->asc_stats.ast_tx_rssi = ts->ts_rssi;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_status & HAL_TXERR_XRETRY)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc->asc_stats.ast_tx_xretries++;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_status & HAL_TXERR_FIFO)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_status & HAL_TXERR_FILT)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc->asc_stats.ast_tx_filtered++;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China sr = ts->ts_shortretry;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China lr = ts->ts_longretry;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Hand the descriptor to the rate control algorithm.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * If frame was ack'd update the last rx time
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * used to workaround phantom bmiss interrupts.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_status == 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Reschedule stalled outbound packets
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Process each active queue.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic struct ieee80211_node *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_scan_timer = timeout(ath_next_scan, (void *)asc,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc while ((asc->asc_scan_timer != 0) && (tmp_id != asc->asc_scan_timer)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Disable interrupts.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (error != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (nstate == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < IEEE80211_WEP_NKID; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Configure the beacon and sleep timers. */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Reset the rate control state.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Invoke the parent method to complete the work.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Finally, start any timers.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else if ((nstate == IEEE80211_S_SCAN) && (ostate != nstate)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* start ap/neighbor scan timer */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_scan_timer = timeout(ath_next_scan, (void *)asc,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Periodically recalibrate the PHY to account
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * for temperature/environment changes.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Rfgain is out of bounds, reset the chip
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * to load new gain values.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Need change RFgain\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ATH_HAL_CALIBRATE(ah, &asc->asc_curchan, &iqcaldone)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "calibration of channel %u failed\n",
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* periodic recalibration */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Start the background rate control thread if we
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * are not configured to use a fixed xmit rate.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_rate_ctl, asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_tx_proc(void *arg)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_t *asc = arg;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_tx_handler(asc);
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * The hardware is not ready/present, don't touch anything.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Note this can happen early on if the IRQ is shared.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (!ATH_HAL_INTRPEND(ah)) { /* shared irq, not for us */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ddi_taskq_dispatch(asc->asc_tq, ath_tx_proc,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China asc, DDI_NOSLEEP) != DDI_SUCCESS) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_problem("ath: ath_intr(): "
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China "No memory available for tx taskq\n");
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* This will occur only in Host-AP or Ad-Hoc mode */
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Check if the soft interrupt is triggered by another
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * driver at the same level.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (asc->asc_rx_pend) { /* Soft interrupt for this driver */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * following are gld callback routine
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * ath_gld_send, ath_gld_ioctl, ath_gld_gstat
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * are listed in other corresponding sections.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * reset the hardware w/o losing operational state. this is
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * basically a more efficient way of doing ath_gld_stop, ath_gld_start,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * followed by state transitions to the current 802.11
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * operational state. used to recover from errors rx overrun
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * and to reset the hardware when rf gain settings must be reset.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Shutdown the hardware and driver:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * reset 802.11 state machine
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * turn off timers
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * disable interrupts
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * turn off the radio
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * clear transmit machinery
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * clear receive machinery
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * drain and release tx queues
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * reclaim beacon resources
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * power down hardware
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Note that some of this work is not possible if the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * hardware is gone (invalid).
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The basic interface to setting the hardware in a good
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * state is ``reset''. On return the hardware is known to
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * be powered up and with interrupts disabled. This must
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * be followed by initialization of the appropriate bits
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * and then setup of the interrupt mask.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_curchan.channelFlags = ath_chan2flags(ic, ic->ic_curchan);
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "reset hardware failed: '%s' (HAL status %u)\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Enable interrupts.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * The hardware should be ready to go now so it's safe
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * to kick the 802.11 state machine as it's likely to
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * immediately call back to us to send mgmt frames.
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (0);
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Stop anything previously setup. This is safe
f11a3086bc0b6b242d387296efedd61d43316e8dxc * whether this is the first time through or not.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* calculate XOR of eight 6bit values */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc } else { /* disable multicast */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan * callback functions for /get/set properties
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanath_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan err = ieee80211_setprop(&asc->asc_isc, pr_name, wldp_pr_num,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanath_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan uint_t pr_flags, uint_t wldp_length, void *wldp_buf)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan err = ieee80211_getprop(&asc->asc_isc, pr_name, wldp_pr_num,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (stat) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2 *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc 1000000ull;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Enable memory mapping and bus mastering
f11a3086bc0b6b242d387296efedd61d43316e8dxc command = pci_config_get16(asc->asc_cfg_handle, PCI_CONF_COMM);
f11a3086bc0b6b242d387296efedd61d43316e8dxc pci_config_put16(asc->asc_cfg_handle, PCI_CONF_COMM, command);
f11a3086bc0b6b242d387296efedd61d43316e8dxc command = pci_config_get16(asc->asc_cfg_handle, PCI_CONF_COMM);
f11a3086bc0b6b242d387296efedd61d43316e8dxc "failed to enable memory mapping\n");
f11a3086bc0b6b242d387296efedd61d43316e8dxc "failed to enable bus mastering\n");
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (0);
f11a3086bc0b6b242d387296efedd61d43316e8dxc asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
f11a3086bc0b6b242d387296efedd61d43316e8dxc "failed to get soft state\n"));
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Set up config space command register(s). Refuse
f11a3086bc0b6b242d387296efedd61d43316e8dxc * to resume on failure.
f11a3086bc0b6b242d387296efedd61d43316e8dxc "ath_pci_setup() failed\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc const char *athname;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t ath_countrycode = CTRY_DEFAULT; /* country code */
f11a3086bc0b6b242d387296efedd61d43316e8dxc switch (cmd) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ddi_soft_state_zalloc(ath_soft_state_p, instance) != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Unable to alloc softstate\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_init(&asc->asc_txbuflock, NULL, MUTEX_DRIVER, NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_init(&asc->asc_rxbuflock, NULL, MUTEX_DRIVER, NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_init(&asc->asc_resched_lock, NULL, MUTEX_DRIVER, NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "pci_config_setup() failed"));
1f156c6a7686102f9a1057cb9294c57041f3da68xc * Cache line size is used to size and align various
1f156c6a7686102f9a1057cb9294c57041f3da68xc * structures used to communicate with the hardware.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc csz = pci_config_get8(asc->asc_cfg_handle, PCI_CONF_CACHE_LINESZ);
1f156c6a7686102f9a1057cb9294c57041f3da68xc if (csz == 0) {
1f156c6a7686102f9a1057cb9294c57041f3da68xc * We must have this setup properly for rx buffer
1f156c6a7686102f9a1057cb9294c57041f3da68xc * DMA to work so force a reasonable value here if it
1f156c6a7686102f9a1057cb9294c57041f3da68xc * comes up zero.
1f156c6a7686102f9a1057cb9294c57041f3da68xc pci_config_put8(asc->asc_cfg_handle, PCI_CONF_CACHE_LINESZ,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc vendor_id = pci_config_get16(asc->asc_cfg_handle, PCI_CONF_VENID);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc device_id = pci_config_get16(asc->asc_cfg_handle, PCI_CONF_DEVID);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): vendor 0x%x, "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "device id 0x%x, cache size %d\n", vendor_id, device_id, csz));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): athname: %s\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pci_config_put8(asc->asc_cfg_handle, PCI_CONF_LATENCY_TIMER, 0xa8);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pci_config_put32(asc->asc_cfg_handle, 0x40, val & 0xffff00ff);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "ddi_regs_map_setup() failed"));
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "unable to attach hw: '%s' (HAL status %u)\n",
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ATH_DEBUG((ATH_DBG_ATTACH, "mac %d.%d phy %d.%d",
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ah->ah_macVersion, ah->ah_macRev,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL ABI mismatch detected (0x%x != 0x%x)\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL mac version %d.%d, phy version %d.%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL 5ghz radio version %d.%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL 2ghz radio version %d.%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Check if the MAC has multi-rate retry support.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * We do this by trying to setup a fake extended
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * descriptor. MAC's that don't have support will
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * return false w/o doing anything. MAC's that do
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * support it will return true w/o doing anything.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_mrretry = ATH_HAL_SETUPXTXDESC(ah, NULL, 0, 0, 0, 0, 0, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "multi rate retry support=%x\n",
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Get the hardware key cache size.
a399b7655a1d835aa8606c2b29e4e777baac8635zf " Warning, using only %u entries in %u key cache\n",
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Reset the key cache since some parts do not
a399b7655a1d835aa8606c2b29e4e777baac8635zf * reset the contents on initial power up.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Collect the channel list using the default country
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * code and including outdoor channels. The 802.11 layer
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * is resposible for filtering this list to a set of
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * channels that it considers ok to use.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* enable outdoor use, enable extended channels */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ath_getchannels(asc, ath_countrycode, AH_FALSE, AH_TRUE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Setup rate tables for all potential media types.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Setup here so ath_rate_update is happy */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if ((asc->asc_tq = ddi_taskq_create(devinfo, "ath_taskq", 1,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China TASKQ_DEFAULTPRI, 0)) == NULL) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China goto attach_fail4;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Setup transmit queues in the HAL */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Initialize pointers to device specific functions which
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * will be used by the generic layer.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* 11g support is identified when we fetch the channel set */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Query the hal to figure out h/w crypto support.
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_ATTACH, "Atheros support H/W CCMP\n"));
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_ATTACH, "Atheros support H/W TKIP\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Check if h/w does the MIC and/or whether the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * separate key cache entries are required to
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * handle both tx+rx MIC keys.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * If the h/w supports storing tx+rx MIC keys
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * in one cache slot automatically enable use.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ATH_HAL_HASTKIPSPLIT(ah) ||
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China !ATH_HAL_SETTKIPSPLIT(ah, AH_FALSE)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_hasclrkey = ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_CLR);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Mark key cache slots associated with global keys
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * as in use. If we knew TKIP was not to be used we
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * could leave the +32, +64, and +32+64 slots free.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China for (i = 0; i < IEEE80211_WEP_NKID; i++) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China setbit(asc->asc_keymap, i);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China setbit(asc->asc_keymap, i+64);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (asc->asc_splitmic) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China setbit(asc->asc_keymap, i+32);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China setbit(asc->asc_keymap, i+32+64);
a399b7655a1d835aa8606c2b29e4e777baac8635zf /* different instance has different WPA door */
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Override 80211 default routines */
d28940508b8826beeaea79e67482a225b86f3778zf * initialize default tx key
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc &asc->asc_softint_id, NULL, 0, ath_softint_handler, (caddr_t)asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "ddi_add_softintr() failed\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Can not get iblock cookie for INT\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Can not set intr for ATH driver\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Provide initial settings for the WiFi plugin; whenever this
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * information changes, we need to call mac_plugindata_update()
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "MAC version mismatch\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (err != 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Create minor node of type DDI_NT_NET_WIFI */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc bzero(asc->asc_mcast_refs, sizeof (asc->asc_mcast_refs));
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc bzero(asc->asc_mcast_hash, sizeof (asc->asc_mcast_hash));
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (asc->asc_tq)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ddi_taskq_destroy(asc->asc_tq);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Suspend transmit/receive for powerdown
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
f11a3086bc0b6b242d387296efedd61d43316e8dxc switch (cmd) {
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China if (mac_disable(asc->asc_isc.ic_mach) != 0)
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* disable interrupts */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Unregister from the MAC layer subsystem
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China (void) mac_unregister(asc->asc_isc.ic_mach);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* free intterrupt resources */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * NB: the order of these is important:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * o call the 802.11 layer before detaching the hal to
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * insure callbacks into the driver to delete global
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * key cache entries can be handled
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * o reclaim the tx queue data structures after calling
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * the 802.11 layer as we'll get called back to reclaim
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * node state and potentially want to use them
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * o to cleanup the tx queues the hal is called, so detach
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ddi_taskq_destroy(asc->asc_tq);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* free io handle */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* destroy locks */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_soft_state_free(ath_soft_state_p, ddi_get_instance(devinfo));
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * quiesce(9E) entry point.
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * This function is called when the system is single-threaded at high
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * PIL with preemption disabled. Therefore, this function must not be
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * DDI_FAILURE indicates an error condition and should almost never happen.
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev if (asc == NULL || (ah = asc->asc_ah) == NULL)
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Disable interrupts
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Disable TX HW
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ATH_HAL_STOPTXDMA(ah, asc->asc_txq[i].axq_qnum);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Disable RX HW
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Power down HW
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcDDI_DEFINE_STREAM_OPS(ath_dev_ops, nulldev, nulldev, ath_attach, ath_detach,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc &mod_driverops, /* Type of module. This one is a driver */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China "ath driver 1.4/HAL 0.10.5.6", /* short description */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc status = ddi_soft_state_init(&ath_soft_state_p, sizeof (ath_t), 1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status != 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status == 0) {