ath_main.c revision c1500db945971ce16b2509a64fc04cd590779a2e
cd5560ef29d7a0451b9a7ab81863515641f482b6xh * Copyright 2007 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#pragma ident "%Z%%M% %I% %E% SMI"
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.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Describes the chip's DMA engine
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc 0 /* dma_attr_flags */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_start(void *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void ath_m_stop(void *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_multicst(void *, boolean_t, const uint8_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
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate handle
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate memory
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Bind the two together
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Free one allocated area of DMAable memory
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ath_alloc_dma_mem(devinfo, size, &ath_desc_accattr,
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) +
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* create RX buffer list and allocate DMA memory */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_create(&asc->asc_rxbuf_list, sizeof (struct ath_buf),
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* alloc DMA memory */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* create TX buffer list and allocate DMA memory */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_create(&asc->asc_txbuf_list, sizeof (struct ath_buf),
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* alloc DMA memory */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Free TX DMA buffer */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Free RX DMA uffer */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Free descriptor DMA buffer */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RECV, "ath: R (%p %p) %08x %08x %08x "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "%08x %08x %08x %c\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!'));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "no buffer\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Never process the self-linked entry at the end,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * this may be met at heavy load.
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.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } while (loop);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* rx signal state monitoring */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_RXMONITOR(ah, &hal_node_stats, &asc->asc_curchan);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_SEND, "ath: T(%p %p) %08x %08x %08x %08x %08x"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc " %08x %08x %08x %c\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc !done ? ' ' : (ds->ds_txstat.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.
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Formulate first tx descriptor with tx controls.
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 */
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);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (;;) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Successful transmition */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Hand the descriptor to the rate control algorithm.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * If frame was ack'd update the last rx time
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * used to workaround phantom bmiss interrupts.
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);
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 if (nstate == IEEE80211_S_RUN && (ostate != IEEE80211_S_RUN)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "ic_flags=0x%08x iv=%d"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc " bssid=%s capinfo=0x%04x chan=%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "ath_new_state: error log event\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "ath_new_state(): error log event\n"));
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.
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* This will occur only in Host-AP or Ad-Hoc mode */
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 * Stop anything previously setup. This is safe
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * whether this is the first time through or not.
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);
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.
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 /* disable multicast */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* enable multicast */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* calculate XOR of eight 6bit values */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (stat) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2 *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc 1000000ull;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc const char *athname;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t ath_countrycode = CTRY_DEFAULT; /* country code */
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"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc csz = pci_config_get8(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 * Enable response to memory space accesses,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * and enabe bus master.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pci_config_put16(asc->asc_cfg_handle, PCI_CONF_COMM, command);
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"));
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.
a399b7655a1d835aa8606c2b29e4e777baac8635zf for (i = 0; i < IEEE80211_WEP_NKID; i++) {
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 */
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.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_hasclrkey = ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_CLR);
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 */
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* disable interrupts */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Unregister from the MAC layer subsystem
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
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* free io handle */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* destroy locks */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_soft_state_free(ath_soft_state_p, ddi_get_instance(devinfo));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcDDI_DEFINE_STREAM_OPS(ath_dev_ops, nulldev, nulldev, ath_attach, ath_detach,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc &mod_driverops, /* Type of module. This one is a driver */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc status = ddi_soft_state_init(&ath_soft_state_p, sizeof (ath_t), 1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status != 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status == 0) {