7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Use is subject to license terms.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * All rights reserved.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
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 *
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 *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Driver for the Atheros Wireless LAN controller.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
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.)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | GLD thread
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * V
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 * | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * V |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +----------------------------------+ |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * |[2] | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | Net80211 Callback functions | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | registered by LLD | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +----------------------------------+ |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * V v
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +-----------------------------------------------------------+
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * |[3] |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | LLD Internal functions |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | |
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * +-----------------------------------------------------------+
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * ^
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * | Software interrupt thread
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * |
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
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 *
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 *
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 *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * All the transmit buffers are contained in asc_txbuf which are
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * protected by asc_txbuflock.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Each receive buffers are contained in asc_rxbuf which are protected
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * by asc_rxbuflock.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *
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 *
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
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/param.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/types.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/signal.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stream.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/termio.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/errno.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/file.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/cmn_err.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stropts.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strsubr.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strtty.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/kbio.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/cred.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/stat.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/consdev.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/kmem.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/modctl.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/ddi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/sunddi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/pci.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/errno.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_provider.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/dlpi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/ethernet.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/list.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/byteorder.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/strsun.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <sys/policy.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/common.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/nd.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/mi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include <inet/wifi_ioctl.h>
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#include <sys/mac_wifi.h>
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_hal.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_impl.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_aux.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#include "ath_rate.h"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc#define ATH_MAX_RSSI 63 /* max rssi */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
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
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * PIO access attributes for registers
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic ddi_device_acc_attr_t ath_reg_accattr = {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc DDI_DEVICE_ATTR_V0,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc DDI_STRUCTURE_LE_ACC,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc DDI_STRICTORDER_ACC
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc};
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * DMA access attributes for descriptors: NOT to be byte swapped.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic ddi_device_acc_attr_t ath_desc_accattr = {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc DDI_DEVICE_ATTR_V0,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc DDI_STRUCTURE_LE_ACC,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc DDI_STRICTORDER_ACC
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc};
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * DMA attributes for rx/tx buffers
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxcstatic ddi_dma_attr_t ath_dma_attr = {
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc DMA_ATTR_V0, /* version number */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* low address */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xffffffffU, /* high address */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0x3ffffU, /* counter register max */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 1, /* alignment */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xFFF, /* burst sizes */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 1, /* minimum transfer size */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0x3ffffU, /* max transfer size */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xffffffffU, /* address register max */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 1, /* no scatter-gather */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 1, /* granularity of device */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* DMA flags */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc};
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc
3caf11144eab1a56717f986d44ae7f40ee8b28fcxcstatic ddi_dma_attr_t ath_desc_dma_attr = {
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc DMA_ATTR_V0, /* version number */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* low address */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xffffffffU, /* high address */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xffffffffU, /* counter register max */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0x1000, /* alignment */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xFFF, /* burst sizes */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 1, /* minimum transfer size */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xffffffffU, /* max transfer size */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0xffffffffU, /* address register max */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 1, /* no scatter-gather */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 1, /* granularity of device */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc 0, /* DMA flags */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc};
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic kmutex_t ath_loglock;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void *ath_soft_state_p = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_dwelltime = 150; /* scan interval, ms */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_stat(void *, uint_t, uint64_t *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_start(void *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void ath_m_stop(void *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_promisc(void *, boolean_t);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_multicst(void *, boolean_t, const uint8_t *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int ath_m_unicst(void *, const uint8_t *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic mblk_t *ath_m_tx(void *, mblk_t *);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void ath_m_ioctl(void *, queue_t *, mblk_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,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t, void *);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void ath_m_propinfo(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic mac_callbacks_t ath_m_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_stat,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_start,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_stop,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_promisc,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_multicst,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_unicst,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_m_ioctl,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan NULL, /* mc_getcapab */
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan NULL,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan NULL,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ath_m_setprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ath_m_getprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ath_m_propinfo
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc};
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcuint32_t ath_dbg_flags = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Exception/warning cases not leading to panic.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_problem(const int8_t *fmt, ...)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_list args;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&ath_loglock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_start(args, fmt);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc vcmn_err(CE_WARN, fmt, args);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_end(args);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&ath_loglock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Normal log information independent of debug.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_log(const int8_t *fmt, ...)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_list args;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&ath_loglock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_start(args, fmt);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc vcmn_err(CE_CONT, fmt, args);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_end(args);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&ath_loglock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_dbg(uint32_t dbg_flags, const int8_t *fmt, ...)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_list args;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (dbg_flags & ath_dbg_flags) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&ath_loglock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_start(args, fmt);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc vcmn_err(CE_CONT, fmt, args);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc va_end(args);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&ath_loglock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcvoid
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_setup_desc(ath_t *asc, struct ath_buf *bf)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_desc *ds;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds = bf->bf_desc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_link = bf->bf_daddr;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_data = bf->bf_dma.cookie.dmac_address;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETUPRXDESC(asc->asc_ah, ds,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf->bf_dma.alength, /* buffer size */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (asc->asc_rxlink != NULL)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *asc->asc_rxlink = bf->bf_daddr;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rxlink = &ds->ds_link;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate an area of memory and a DMA handle for accessing it
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
3caf11144eab1a56717f986d44ae7f40ee8b28fcxcath_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, size_t memsize,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc ddi_device_acc_attr_t *attr_p, uint_t alloc_flags,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc uint_t bind_flags, dma_area_t *dma_p)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int err;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate handle
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc err = ddi_dma_alloc_handle(devinfo, dma_attr,
1f156c6a7686102f9a1057cb9294c57041f3da68xc DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_SUCCESS)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_FAILURE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Allocate memory
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc &dma_p->alength, &dma_p->acc_hdl);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_SUCCESS)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_FAILURE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Bind the two together
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
1f156c6a7686102f9a1057cb9294c57041f3da68xc dma_p->mem_va, dma_p->alength, bind_flags,
1f156c6a7686102f9a1057cb9294c57041f3da68xc DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_DMA_MAPPED)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_FAILURE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dma_p->nslots = ~0U;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dma_p->size = ~0U;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dma_p->token = ~0U;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dma_p->offset = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_SUCCESS);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Free one allocated area of DMAable memory
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_free_dma_mem(dma_area_t *dma_p)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (dma_p->dma_hdl != NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (dma_p->acc_hdl != NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_dma_mem_free(&dma_p->acc_hdl);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dma_p->acc_hdl = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_dma_free_handle(&dma_p->dma_hdl);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dma_p->ncookies = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dma_p->dma_hdl = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China/*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Initialize tx/rx buffer list. Allocate DMA memory for
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * each buffer.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
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)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int i, err;
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
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
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 (err);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China *pbf = bf;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China *pds = ds;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China}
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China/*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Destroy tx/rx buffer list. Free DMA memory.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinastatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_buflist_cleanup(list_t *buflist)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China{
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_buf *bf;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (!buflist)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
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 }
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 }
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 }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China list_destroy(buflist);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China}
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinastatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_desc_free(ath_t *asc)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China{
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
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
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 China}
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinastatic int
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_desc_alloc(dev_info_t *devinfo, ath_t *asc)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China{
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China int err;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc size_t size;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_desc *ds;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_buf *bf;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc size = sizeof (struct ath_desc) * (ATH_TXBUF + ATH_RXBUF);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc err = ath_alloc_dma_mem(devinfo, &ath_desc_dma_attr, size,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc &ath_desc_accattr, DDI_DMA_CONSISTENT,
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &asc->asc_desc_dma);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* virtual address of the first descriptor */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_desc = (struct ath_desc *)asc->asc_desc_dma.mem_va;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds = asc->asc_desc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_INIT, "ath: ath_desc_alloc(): DMA map: "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "%p (%d) -> %p\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_desc, asc->asc_desc_dma.alength,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_desc_dma.cookie.dmac_address));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
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 asc->asc_vbufptr = bf;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* DMA buffer size for each TX/RX packet */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_dmabuf_size = roundup(1000 + sizeof (struct ieee80211_frame) +
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc IEEE80211_MTU + IEEE80211_CRC_LEN +
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc IEEE80211_WEP_CRCLEN), asc->asc_cachelsz);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
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 return (err);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
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 (err);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China return (DDI_SUCCESS);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_printrxbuf(struct ath_buf *bf, int32_t done)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_desc *ds = bf->bf_desc;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China const struct ath_rx_status *rs = &bf->bf_status.ds_rxstat;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RECV, "ath: R (%p %p) %08x %08x %08x "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "%08x %08x %08x %c\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds, bf->bf_daddr,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_link, ds->ds_data,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_ctl0, ds->ds_ctl1,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_hw[0], ds->ds_hw[1],
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_rx_handler(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_buf *bf;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_desc *ds;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_rx_status *rs;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mblk_t *rx_mp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t len, loop = 1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint8_t phyerr;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_STATUS status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_NODE_STATS hal_node_stats;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_node *in;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc do {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_head(&asc->asc_rxbuf_list);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bf == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_RECV, "ath: ath_rx_handler(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "no buffer\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ASSERT(bf->bf_dma.cookie.dmac_address != NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds = bf->bf_desc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ds->ds_link == bf->bf_daddr) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Never process the self-linked entry at the end,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * this may be met at heavy load.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China rs = &bf->bf_status.ds_rxstat;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc status = ATH_HAL_RXPROCDESC(ah, ds,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf->bf_daddr,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ATH_PA2DESC(asc, ds->ds_link), rs);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status == HAL_EINPROGRESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_remove(&asc->asc_rxbuf_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status != 0) {
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_CRC)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rx_crcerr++;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_FIFO)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rx_fifoerr++;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_DECRYPT)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rx_badcrypt++;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (rs->rs_status & HAL_RXERR_PHY) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rx_phyerr++;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China phyerr = rs->rs_phyerr & 0x1f;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rx_phy[phyerr]++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto rx_next;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China len = rs->rs_datalen;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* less than sizeof(struct ieee80211_frame) */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (len < 20) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rx_tooshort++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto rx_next;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if ((rx_mp = allocb(asc->asc_dmabuf_size, BPRI_MED)) == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_problem("ath: ath_rx_handler(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "allocing mblk buffer failed.\n");
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORCPU);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bcopy(bf->bf_dma.mem_va, rx_mp->b_rptr, len);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rx_mp->b_wptr += len;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc wh = (struct ieee80211_frame *)rx_mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc IEEE80211_FC0_TYPE_CTL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Ignore control frame received in promisc mode.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc freemsg(rx_mp);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto rx_next;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Remove the CRC at the end of IEEE80211 frame */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rx_mp->b_wptr -= IEEE80211_CRC_LEN;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#ifdef DEBUG
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_printrxbuf(bf, status == HAL_OK);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#endif /* DEBUG */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
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 */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ieee80211_find_rxnode(ic, wh);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Send frame up for processing.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ieee80211_input(ic, rx_mp, in,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China rs->rs_rssi, rs->rs_tstamp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_free_node(in);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcrx_next:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_insert_tail(&asc->asc_rxbuf_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_setup_desc(asc, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } while (loop);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* rx signal state monitoring */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_RXMONITOR(ah, &hal_node_stats, &asc->asc_curchan);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_printtxbuf(struct ath_buf *bf, int done)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_desc *ds = bf->bf_desc;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_SEND, "ath: T(%p %p) %08x %08x %08x %08x %08x"
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc " %08x %08x %08x %c\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds, bf->bf_daddr,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_link, ds->ds_data,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_ctl0, ds->ds_ctl1,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China !done ? ' ' : (ts->ts_status == 0) ? '*' : '!'));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
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.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int32_t
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_tx_start(ath_t *asc, struct ieee80211_node *in, struct ath_buf *bf,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *mp)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ieee80211_frame *wh;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint32_t subtype, flags, ctsduration;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t keyix, iswep, hdrlen, pktlen, mblen, mbslen, try0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint8_t rix, cix, txrate, ctsrate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_desc *ds;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_txq *txq;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_PKT_TYPE atype;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc const HAL_RATE_TABLE *rt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_BOOL shortPreamble;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_node *an;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc caddr_t dest;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * CRC are added by H/W, not encaped by driver,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * but we must count it in pkt length.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pktlen = IEEE80211_CRC_LEN;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc keyix = HAL_TXKEYIX_INVALID;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc hdrlen = sizeof (struct ieee80211_frame);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (iswep != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc const struct ieee80211_cipher *cip;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_key *k;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc k = ieee80211_crypto_encap(ic, mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (k == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_AUX, "crypto_encap failed\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
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 * debugging/diagnostics.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (EIO);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc cip = k->wk_cipher;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
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 */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc hdrlen += cip->ic_header;
a399b7655a1d835aa8606c2b29e4e777baac8635zf pktlen += cip->ic_trailer;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((k->wk_flags & IEEE80211_KEY_SWMIC) == 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc pktlen += cip->ic_miclen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc keyix = k->wk_keyix;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* packet header may have moved, reset our local pointer */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc dest = bf->bf_dma.mem_va;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc for (; mp != NULL; mp = mp->b_cont) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblen = MBLKL(mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bcopy(mp->b_rptr, dest, mblen);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc dest += mblen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
22eb7cb54d8a6bcf6fe2674cb4b1f0cf2d85cfb6gd mbslen = (uintptr_t)dest - (uintptr_t)bf->bf_dma.mem_va;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc pktlen += mbslen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf->bf_in = in;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* setup descriptors */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds = bf->bf_desc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt = asc->asc_currates;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(rt != NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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 */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc shortPreamble = AH_TRUE;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_shortpre++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc shortPreamble = AH_FALSE;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an = ATH_NODE(in);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate Atheros packet type from IEEE80211 packet header
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * and setup for rate calculations.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case IEEE80211_FC0_TYPE_MGT:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (subtype == IEEE80211_FC0_SUBTYPE_BEACON)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc atype = HAL_PKT_TYPE_BEACON;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc atype = HAL_PKT_TYPE_PROBE_RESP;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc atype = HAL_PKT_TYPE_ATIM;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc atype = HAL_PKT_TYPE_NORMAL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rix = 0; /* lowest rate */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc try0 = ATH_TXMAXTRY;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (shortPreamble)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txrate = an->an_tx_mgtratesp;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txrate = an->an_tx_mgtrate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* force all ctl frames to highest queue */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq = asc->asc_ac2q[WME_AC_VO];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case IEEE80211_FC0_TYPE_CTL:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc atype = HAL_PKT_TYPE_PSPOLL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rix = 0; /* lowest rate */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc try0 = ATH_TXMAXTRY;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (shortPreamble)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txrate = an->an_tx_mgtratesp;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txrate = an->an_tx_mgtrate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* force all ctl frames to highest queue */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq = asc->asc_ac2q[WME_AC_VO];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc case IEEE80211_FC0_TYPE_DATA:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc atype = HAL_PKT_TYPE_NORMAL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rix = an->an_tx_rix0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc try0 = an->an_tx_try0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (shortPreamble)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txrate = an->an_tx_rate0sp;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txrate = an->an_tx_rate0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Always use background queue */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq = asc->asc_ac2q[WME_AC_BK];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc default:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Unknown 802.11 frame */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_invalid++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate miscellaneous flags.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc flags = HAL_TXDESC_CLRDMASK;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc flags |= HAL_TXDESC_NOACK; /* no ack on broad/multicast */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_noack++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else if (pktlen > ic->ic_rtsthreshold) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc flags |= HAL_TXDESC_RTSENA; /* RTS based on frame length */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_rts++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate duration. This logically belongs in the 802.11
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * layer but it lacks sufficient information to calculate it.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if ((flags & HAL_TXDESC_NOACK) == 0 &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc IEEE80211_FC0_TYPE_CTL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint16_t dur;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc dur = ath_hal_computetxtime(ah, rt, IEEE80211_ACK_SIZE,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rix, shortPreamble);
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *(uint16_t *)wh->i_dur = LE_16(dur);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Calculate RTS/CTS rate and duration if needed.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsduration = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc cix = rt->info[rix].controlRate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsrate = rt->info[cix].rateCode;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (shortPreamble)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsrate |= rt->info[cix].shortPreamble;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (flags & HAL_TXDESC_RTSENA) { /* SIFS + CTS */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsduration += ath_hal_computetxtime(ah,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* SIFS + data */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsduration += ath_hal_computetxtime(ah,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt, pktlen, rix, shortPreamble);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if ((flags & HAL_TXDESC_NOACK) == 0) { /* SIFS + ACK */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsduration += ath_hal_computetxtime(ah,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsrate = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (++txq->axq_intrcnt >= ATH_TXINTR_PERIOD) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc flags |= HAL_TXDESC_INTREQ;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_intrcnt = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Formulate first tx descriptor with tx controls.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETUPTXDESC(ah, ds,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pktlen, /* packet length */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc hdrlen, /* header length */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc atype, /* Atheros packet type */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc MIN(in->in_txpower, 60), /* txpower */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txrate, try0, /* series 0 rate/tries */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc keyix, /* key cache index */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc an->an_tx_antenna, /* antenna mode */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc flags, /* flags */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsrate, /* rts/cts rate */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ctsduration); /* rts/cts duration */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bf->bf_flags = flags;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
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,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate2sp, an->an_tx_rate3sp,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc txq->axq_qnum, rix, shortPreamble, *(uint16_t *)wh->i_dur));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (try0 != ATH_TXMAXTRY)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETUPXTXDESC(ah, ds,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate1sp, 2, /* series 1 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate2sp, 2, /* series 2 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_rate3sp, 2); /* series 3 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_link = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds->ds_data = bf->bf_dma.cookie.dmac_address;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_FILLTXDESC(ah, ds,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mbslen, /* segment length */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc AH_TRUE, /* first segment */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc AH_TRUE, /* last segment */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds); /* first descriptor */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_insert_tail(&txq->axq_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (txq->axq_link == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_PUTTXBUF(ah, txq->axq_qnum, bf->bf_daddr);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc *txq->axq_link = bf->bf_daddr;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_link = &ds->ds_link;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_TXSTART(ah, txq->axq_qnum);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_tx_frags++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_tx_bytes += pktlen;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc/*
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_xmit(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)ic;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_node *in = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_buf *bf = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_frame *wh;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int error = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(mp->b_next == NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxc if (!ATH_IS_RUNNING(asc)) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc if ((type & IEEE80211_FC0_TYPE_MASK) !=
f11a3086bc0b6b242d387296efedd61d43316e8dxc IEEE80211_FC0_TYPE_DATA) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc freemsg(mp);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (ENXIO);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Grab a TX buffer */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&asc->asc_txbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_head(&asc->asc_txbuf_list);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bf != NULL)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_remove(&asc->asc_txbuf_list, bf);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (list_empty(&asc->asc_txbuf_list)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_SEND, "ath: ath_mgmt_send(): "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "stop queue\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_stats.ast_tx_qstop++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_txbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bf == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_SEND, "ath: ath_mgmt_send(): discard, "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "no xmit buf\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_tx_nobuf++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((type & IEEE80211_FC0_TYPE_MASK) ==
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_FC0_TYPE_DATA) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_stats.ast_tx_nobuf++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_enter(&asc->asc_resched_lock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_resched_needed = B_TRUE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_exit(&asc->asc_resched_lock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_stats.ast_tx_nobufmgt++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc freemsg(mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOMEM);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wh = (struct ieee80211_frame *)mp->b_rptr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Locate node */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ieee80211_find_txnode(ic, wh->i_addr1);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in == NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc error = EIO;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto bad;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in->in_inact = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (type & IEEE80211_FC0_TYPE_MASK) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case IEEE80211_FC0_TYPE_DATA:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ieee80211_encap(ic, mp, in);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* fill time stamp */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint64_t tsf;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc uint32_t *tstamp;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tsf = ATH_HAL_GETTSF64(ah);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* adjust 100us delay to xmit */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tsf += 100;
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tstamp = (uint32_t *)&wh[1];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tstamp[0] = LE_32(tsf & 0xffffffff);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tstamp[1] = LE_32(tsf >> 32);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_stats.ast_tx_mgmt++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc error = ath_tx_start(asc, in, bf, mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (error != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcbad:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_stats.is_tx_failed++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (bf != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_enter(&asc->asc_txbuflock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc list_insert_tail(&asc->asc_txbuf_list, bf);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_exit(&asc->asc_txbuflock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (in != NULL)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_free_node(in);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc error == 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc freemsg(mp);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (error);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic mblk_t *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_tx(void *arg, mblk_t *mp)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mblk_t *next;
a399b7655a1d835aa8606c2b29e4e777baac8635zf int error = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
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.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state != IEEE80211_S_RUN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_SEND, "ath: ath_m_tx(): "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "discard, state %u\n", ic->ic_state));
cd5560ef29d7a0451b9a7ab81863515641f482b6xh asc->asc_stats.ast_tx_discard++;
9ee221cae3d2394b6c2f558a1b5629187861ea42xc freemsgchain(mp);
9ee221cae3d2394b6c2f558a1b5629187861ea42xc return (NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc while (mp != NULL) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc next = mp->b_next;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp->b_next = NULL;
a399b7655a1d835aa8606c2b29e4e777baac8635zf error = ath_xmit(ic, mp, IEEE80211_FC0_TYPE_DATA);
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (error != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp->b_next = next;
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (error == ENOMEM) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf break;
a399b7655a1d835aa8606c2b29e4e777baac8635zf } else {
a399b7655a1d835aa8606c2b29e4e777baac8635zf freemsgchain(mp); /* CR6501759 issues */
a399b7655a1d835aa8606c2b29e4e777baac8635zf return (NULL);
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mp = next;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_tx_processq(ath_t *asc, struct ath_txq *txq)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_buf *bf;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_desc *ds;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ieee80211_node *in;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int32_t sr, lr, nacked = 0;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China struct ath_tx_status *ts;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_STATUS status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_node *an;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (;;) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_head(&txq->axq_list);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bf == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq->axq_link = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ds = bf->bf_desc; /* last decriptor */
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#ifdef DEBUG
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_printtxbuf(bf, status == HAL_OK);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc#endif
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status == HAL_EINPROGRESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_remove(&txq->axq_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc in = bf->bf_in;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (in != NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an = ATH_NODE(in);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Successful transmition */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_status == 0) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_ok++;
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)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_altrate++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_rssidelta =
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;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_err++;
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)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_fifoerr++;
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++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an->an_tx_antenna = 0; /* invalidate */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China sr = ts->ts_shortretry;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China lr = ts->ts_longretry;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_shortretry += sr;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_tx_longretry += lr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Hand the descriptor to the rate control algorithm.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (bf->bf_flags & HAL_TXDESC_NOACK) == 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * If frame was ack'd update the last rx time
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * used to workaround phantom bmiss interrupts.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (ts->ts_status == 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc nacked++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc an->an_tx_ok++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc an->an_tx_err++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc an->an_tx_retr += sr + lr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf->bf_in = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&asc->asc_txbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc list_insert_tail(&asc->asc_txbuf_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&asc->asc_txbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Reschedule stalled outbound packets
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_enter(&asc->asc_resched_lock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (asc->asc_resched_needed) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_resched_needed = B_FALSE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_tx_update(ic->ic_mach);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_exit(&asc->asc_resched_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (nacked);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_tx_handler(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int i;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Process each active queue.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ATH_TXQ_SETUP(asc, i)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ath_tx_processq(asc, &asc->asc_txq[i]);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic struct ieee80211_node *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_node_alloc(ieee80211com_t *ic)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_node *an;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)ic;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc an = kmem_zalloc(sizeof (struct ath_node), KM_SLEEP);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_update(asc, &an->an_node, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (&an->an_node);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_node_free(struct ieee80211_node *in)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = in->in_ic;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)ic;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_buf *bf;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_txq *txq;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t i;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ATH_TXQ_SETUP(asc, i)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc txq = &asc->asc_txq[i];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_enter(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_head(&txq->axq_list);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc while (bf != NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (bf->bf_in == in) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf->bf_in = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bf = list_next(&txq->axq_list, bf);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_exit(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_node_cleanup(in);
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (in->in_wpa_ie != NULL)
a399b7655a1d835aa8606c2b29e4e777baac8635zf ieee80211_free(in->in_wpa_ie);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc kmem_free(in, sizeof (struct ath_node));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_next_scan(void *arg)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = arg;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)ic;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_scan_timer = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state == IEEE80211_S_SCAN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_scan_timer = timeout(ath_next_scan, (void *)asc,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc drv_usectohz(ath_dwelltime * 1000));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_next_scan(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_stop_scantimer(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc timeout_id_t tmp_id = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc while ((asc->asc_scan_timer != 0) && (tmp_id != asc->asc_scan_timer)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc tmp_id = asc->asc_scan_timer;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) untimeout(tmp_id);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_scan_timer = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int32_t
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)ic;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ieee80211_node *in;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t i, error;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint8_t *bssid;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint32_t rfilt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc enum ieee80211_state ostate;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc static const HAL_LED_STATE leds[] = {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_LED_INIT, /* IEEE80211_S_INIT */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_LED_SCAN, /* IEEE80211_S_SCAN */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_LED_AUTH, /* IEEE80211_S_AUTH */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_LED_ASSOC, /* IEEE80211_S_ASSOC */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_LED_RUN, /* IEEE80211_S_RUN */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc };
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ATH_IS_RUNNING(asc))
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ostate = ic->ic_state;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (nstate != IEEE80211_S_SCAN)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_stop_scantimer(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETLEDSTATE(ah, leds[nstate]); /* set LED */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (nstate == IEEE80211_S_INIT) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /*
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China * Disable interrupts.
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_INTRSET(ah, asc->asc_imask &~ HAL_INT_GLOBAL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto done;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc in = ic->ic_bss;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc error = ath_chan_set(asc, ic->ic_curchan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (error != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (nstate != IEEE80211_S_SCAN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_reset_chan(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto bad;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rfilt = ath_calcrxfilter(asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (nstate == IEEE80211_S_SCAN)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc bssid = ic->ic_macaddr;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc bssid = in->in_bssid;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETRXFILTER(ah, rfilt);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (nstate == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETASSOCID(ah, bssid, in->in_associd);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETASSOCID(ah, bssid, 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_flags & IEEE80211_F_PRIVACY) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < IEEE80211_WEP_NKID; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ATH_HAL_KEYISVALID(ah, i))
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_KEYSETMAC(ah, i, bssid);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if ((nstate == IEEE80211_S_RUN) &&
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (ostate != IEEE80211_S_RUN)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Configure the beacon and sleep timers. */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_beacon_config(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, asc->asc_imask);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Reset the rate control state.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_ctl_reset(asc, nstate);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcdone:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Invoke the parent method to complete the work.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc error = asc->asc_newstate(ic, nstate, arg);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Finally, start any timers.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (nstate == IEEE80211_S_RUN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_start_watchdog(ic, 1);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else if ((nstate == IEEE80211_S_SCAN) && (ostate != nstate)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* start ap/neighbor scan timer */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ASSERT(asc->asc_scan_timer == 0);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_scan_timer = timeout(ath_next_scan, (void *)asc,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc drv_usectohz(ath_dwelltime * 1000));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcbad:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (error);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Periodically recalibrate the PHY to account
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * for temperature/environment changes.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_calibrate(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc HAL_BOOL iqcaldone;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_per_cal++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ATH_HAL_GETRFGAIN(ah) == HAL_RFGAIN_NEED_CHANGE) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Rfgain is out of bounds, reset the chip
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * to load new gain values.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_HAL, "ath: ath_calibrate(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Need change RFgain\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_per_rfgain++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ath_reset(&asc->asc_isc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ATH_HAL_CALIBRATE(ah, &asc->asc_curchan, &iqcaldone)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_HAL, "ath: ath_calibrate(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "calibration of channel %u failed\n",
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_curchan.channel));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_per_calfail++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_watchdog(void *arg)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = &asc->asc_isc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int ntimer = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_watchdog_timer = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ATH_IS_RUNNING(asc)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state == IEEE80211_S_RUN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* periodic recalibration */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_calibrate(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Start the background rate control thread if we
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * are not configured to use a fixed xmit rate.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_stats.ast_rate_calls ++;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_opmode == IEEE80211_M_STA)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_rate_ctl(ic, ic->ic_bss);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_iterate_nodes(&ic->ic_sta,
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_rate_ctl, asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ntimer = 1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_watchdog(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ntimer != 0)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_start_watchdog(ic, ntimer);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinastatic void
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing Chinaath_tx_proc(void *arg)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China{
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_t *asc = arg;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ath_tx_handler(asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China}
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic uint_t
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_intr(caddr_t arg)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = (ath_t *)arg;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_INT status;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ATH_IS_RUNNING(asc)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * The hardware is not ready/present, don't touch anything.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Note this can happen early on if the IRQ is shared.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (DDI_INTR_UNCLAIMED);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (!ATH_HAL_INTRPEND(ah)) { /* shared irq, not for us */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_INTR_UNCLAIMED);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_GETISR(ah, &status);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc status &= asc->asc_imask;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status & HAL_INT_FATAL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_hardware++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto reset;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else if (status & HAL_INT_RXORN) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rxorn++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto reset;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status & HAL_INT_RXEOL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_rxeol++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rxlink = NULL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status & HAL_INT_TXURN) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_stats.ast_txurn++;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_UPDATETXTRIGLEVEL(ah, AH_TRUE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status & HAL_INT_RX) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rx_pend = 1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_trigger_softintr(asc->asc_softint_id);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status & HAL_INT_TX) {
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");
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status & HAL_INT_SWBA) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* This will occur only in Host-AP or Ad-Hoc mode */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_INTR_CLAIMED);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status & HAL_INT_BMISS) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ic->ic_state == IEEE80211_S_RUN) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ieee80211_new_state(ic,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc IEEE80211_S_ASSOC, -1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_INTR_CLAIMED);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcreset:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ath_reset(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_INTR_CLAIMED);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic uint_t
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_softint_handler(caddr_t data)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
ff3124eff995e6cd8ebd8c6543648e0670920034ff /* LINTED E_BAD_PTR_CAST_ALIGN */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_t *asc = (ath_t *)data;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Check if the soft interrupt is triggered by another
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * driver at the same level.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (asc->asc_rx_pend) { /* Soft interrupt for this driver */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rx_pend = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_rx_handler(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_INTR_CLAIMED);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_INTR_UNCLAIMED);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc/*
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.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_stop_locked(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK_ASSERT(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc if (!asc->asc_isrunning)
f11a3086bc0b6b242d387296efedd61d43316e8dxc return;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
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 *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Note that some of this work is not possible if the
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * hardware is gone (invalid).
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_stop_watchdog(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_draintxq(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc if (!asc->asc_invalid) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_stoprecv(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_PHYDISABLE(ah);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc } else {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rxlink = NULL;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc asc->asc_isrunning = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_stop(void *arg)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_stop_locked(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_SETPOWER(ah, HAL_PM_AWAKE);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_invalid = 1;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxcstatic int
f11a3086bc0b6b242d387296efedd61d43316e8dxcath_start_locked(ath_t *asc)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_STATUS status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_LOCK_ASSERT(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_curchan.channel = ic->ic_curchan->ich_freq;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_curchan.channelFlags = ath_chan2flags(ic, ic->ic_curchan);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (!ATH_HAL_RESET(ah, (HAL_OPMODE)ic->ic_opmode,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc &asc->asc_curchan, AH_FALSE, &status)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_HAL, "ath: ath_m_start(): "
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "reset hardware failed: '%s' (HAL status %u)\n",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc ath_get_hal_status_desc(status), status));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOTACTIVE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ath_startrecv(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Enable interrupts.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_imask = HAL_INT_RX | HAL_INT_TX
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc | HAL_INT_RXEOL | HAL_INT_RXORN
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc | HAL_INT_FATAL | HAL_INT_GLOBAL;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, asc->asc_imask);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_chan_change(asc, ic->ic_curchan);
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc asc->asc_isrunning = 1;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (0);
f11a3086bc0b6b242d387296efedd61d43316e8dxc}
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxcint
f11a3086bc0b6b242d387296efedd61d43316e8dxcath_m_start(void *arg)
f11a3086bc0b6b242d387296efedd61d43316e8dxc{
f11a3086bc0b6b242d387296efedd61d43316e8dxc ath_t *asc = arg;
f11a3086bc0b6b242d387296efedd61d43316e8dxc int err;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_LOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc /*
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Stop anything previously setup. This is safe
f11a3086bc0b6b242d387296efedd61d43316e8dxc * whether this is the first time through or not.
f11a3086bc0b6b242d387296efedd61d43316e8dxc */
f11a3086bc0b6b242d387296efedd61d43316e8dxc ath_stop_locked(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc if ((err = ath_start_locked(asc)) != 0) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_UNLOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (err);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_invalid = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcstatic int
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_unicst(void *arg, const uint8_t *macaddr)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_GLD, "ath: ath_gld_saddr(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc macaddr[0], macaddr[1], macaddr[2],
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc macaddr[3], macaddr[4], macaddr[5]));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(asc->asc_isc.ic_macaddr, macaddr);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_SETMAC(ah, asc->asc_isc.ic_macaddr);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ath_reset(&asc->asc_isc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_promisc(void *arg, boolean_t on)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah = asc->asc_ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint32_t rfilt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rfilt = ATH_HAL_GETRXFILTER(ah);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (on)
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc rfilt |= HAL_RX_FILTER_PROM;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc else
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc rfilt &= ~HAL_RX_FILTER_PROM;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc asc->asc_promisc = on;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_SETRXFILTER(ah, rfilt);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ath_hal *ah = asc->asc_ah;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc uint32_t val, index, bit;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint8_t pos;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc uint32_t *mfilt = asc->asc_mcast_hash;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* calculate XOR of eight 6bit values */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc val = ATH_LE_READ_4(mca + 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc val = ATH_LE_READ_4(mca + 3);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pos &= 0x3f;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc index = pos / 32;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc bit = 1 << (pos % 32);
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc if (add) { /* enable multicast */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc asc->asc_mcast_refs[pos]++;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc mfilt[index] |= bit;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc } else { /* disable multicast */
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc if (--asc->asc_mcast_refs[pos] == 0)
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc mfilt[index] &= ~bit;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_SETMCASTFILTER(ah, mfilt[0], mfilt[1]);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan/*
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan * callback functions for /get/set properties
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan */
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanath_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan uint_t wldp_length, const void *wldp_buf)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan{
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ath_t *asc = arg;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan int err;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan err = ieee80211_setprop(&asc->asc_isc, pr_name, wldp_pr_num,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan wldp_length, wldp_buf);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ATH_LOCK(asc);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (err == ENETRESET) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan if (ATH_IS_RUNNING(asc)) {
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ATH_UNLOCK(asc);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan (void) ath_m_start(asc);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan (void) ieee80211_new_state(&asc->asc_isc,
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan IEEE80211_S_SCAN, -1);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ATH_LOCK(asc);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan }
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan err = 0;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan }
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ATH_UNLOCK(asc);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return (err);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstatic int
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanath_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t wldp_length, void *wldp_buf)
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan{
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan ath_t *asc = arg;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan int err = 0;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan err = ieee80211_getprop(&asc->asc_isc, pr_name, wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer wldp_length, wldp_buf);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan return (err);
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan}
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerath_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t mph)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ath_t *asc = arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ieee80211_propinfo(&asc->asc_isc, pr_name, wldp_pr_num, mph);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic void
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int32_t err;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc err = ieee80211_ioctl(&asc->asc_isc, wq, mp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (err == ENETRESET) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ATH_IS_RUNNING(asc)) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ath_m_start(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ieee80211_new_state(&asc->asc_isc,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_S_SCAN, -1);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcath_m_stat(void *arg, uint_t stat, uint64_t *val)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_t *asc = arg;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic = (ieee80211com_t *)asc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_node *in = ic->ic_bss;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc struct ieee80211_rateset *rs = &in->in_rates;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_LOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc switch (stat) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case MAC_STAT_IFSPEED:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) / 2 *
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc 1000000ull;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case MAC_STAT_NOXMTBUF:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = asc->asc_stats.ast_tx_nobuf +
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_stats.ast_tx_nobufmgt;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case MAC_STAT_IERRORS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = asc->asc_stats.ast_rx_tooshort;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case MAC_STAT_RBYTES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = ic->ic_stats.is_rx_bytes;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case MAC_STAT_IPACKETS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = ic->ic_stats.is_rx_frags;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case MAC_STAT_OBYTES:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = ic->ic_stats.is_tx_bytes;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case MAC_STAT_OPACKETS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = ic->ic_stats.is_tx_frags;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
cd5560ef29d7a0451b9a7ab81863515641f482b6xh case MAC_STAT_OERRORS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_TX_FAILED:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = asc->asc_stats.ast_tx_fifoerr +
cd5560ef29d7a0451b9a7ab81863515641f482b6xh asc->asc_stats.ast_tx_xretries +
cd5560ef29d7a0451b9a7ab81863515641f482b6xh asc->asc_stats.ast_tx_discard;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_TX_RETRANS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = asc->asc_stats.ast_tx_xretries;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_FCS_ERRORS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = asc->asc_stats.ast_rx_crcerr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_WEP_ERRORS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc *val = asc->asc_stats.ast_rx_badcrypt;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc break;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_TX_FRAGS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_MCAST_TX:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_RTS_SUCCESS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_RTS_FAILURE:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_ACK_FAILURE:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_RX_FRAGS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_MCAST_RX:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc case WIFI_STAT_RX_DUPS:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ieee80211_stat(ic, stat, val));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc default:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (ENOTSUP);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_UNLOCK(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc return (0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxcstatic int
f11a3086bc0b6b242d387296efedd61d43316e8dxcath_pci_setup(ath_t *asc)
f11a3086bc0b6b242d387296efedd61d43316e8dxc{
f11a3086bc0b6b242d387296efedd61d43316e8dxc uint16_t command;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc /*
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Enable memory mapping and bus mastering
f11a3086bc0b6b242d387296efedd61d43316e8dxc */
f11a3086bc0b6b242d387296efedd61d43316e8dxc ASSERT(asc != NULL);
f11a3086bc0b6b242d387296efedd61d43316e8dxc command = pci_config_get16(asc->asc_cfg_handle, PCI_CONF_COMM);
f11a3086bc0b6b242d387296efedd61d43316e8dxc command |= PCI_COMM_MAE | PCI_COMM_ME;
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 if ((command & PCI_COMM_MAE) == 0) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc ath_problem("ath: ath_pci_setup(): "
f11a3086bc0b6b242d387296efedd61d43316e8dxc "failed to enable memory mapping\n");
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (EIO);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc if ((command & PCI_COMM_ME) == 0) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc ath_problem("ath: ath_pci_setup(): "
f11a3086bc0b6b242d387296efedd61d43316e8dxc "failed to enable bus mastering\n");
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (EIO);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_DEBUG((ATH_DBG_INIT, "ath: ath_pci_setup(): "
f11a3086bc0b6b242d387296efedd61d43316e8dxc "set command reg to 0x%x \n", command));
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (0);
f11a3086bc0b6b242d387296efedd61d43316e8dxc}
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxcstatic int
f11a3086bc0b6b242d387296efedd61d43316e8dxcath_resume(dev_info_t *devinfo)
f11a3086bc0b6b242d387296efedd61d43316e8dxc{
f11a3086bc0b6b242d387296efedd61d43316e8dxc ath_t *asc;
f11a3086bc0b6b242d387296efedd61d43316e8dxc int ret = DDI_SUCCESS;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
f11a3086bc0b6b242d387296efedd61d43316e8dxc if (asc == NULL) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_DEBUG((ATH_DBG_SUSPEND, "ath: ath_resume(): "
f11a3086bc0b6b242d387296efedd61d43316e8dxc "failed to get soft state\n"));
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (DDI_FAILURE);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_LOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc /*
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Set up config space command register(s). Refuse
f11a3086bc0b6b242d387296efedd61d43316e8dxc * to resume on failure.
f11a3086bc0b6b242d387296efedd61d43316e8dxc */
f11a3086bc0b6b242d387296efedd61d43316e8dxc if (ath_pci_setup(asc) != 0) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_DEBUG((ATH_DBG_SUSPEND, "ath: ath_resume(): "
f11a3086bc0b6b242d387296efedd61d43316e8dxc "ath_pci_setup() failed\n"));
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_UNLOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (DDI_FAILURE);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc if (!asc->asc_invalid)
f11a3086bc0b6b242d387296efedd61d43316e8dxc ret = ath_start_locked(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_UNLOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (ret);
f11a3086bc0b6b242d387296efedd61d43316e8dxc}
f11a3086bc0b6b242d387296efedd61d43316e8dxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_t *asc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211com_t *ic;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_hal *ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint8_t csz;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc HAL_STATUS status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc caddr_t regs;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc uint32_t i, val;
f11a3086bc0b6b242d387296efedd61d43316e8dxc uint16_t vendor_id, device_id;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc const char *athname;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t ath_countrycode = CTRY_DEFAULT; /* country code */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int32_t err, ath_regdomain = 0; /* regulatory domain */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc char strbuf[32];
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc int instance;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wifi_data_t wd = { 0 };
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_register_t *macp;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxc switch (cmd) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc case DDI_ATTACH:
f11a3086bc0b6b242d387296efedd61d43316e8dxc break;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc case DDI_RESUME:
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (ath_resume(devinfo));
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc default:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_FAILURE);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc instance = ddi_get_instance(devinfo);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ddi_soft_state_zalloc(ath_soft_state_p, instance) != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Unable to alloc softstate\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_FAILURE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic = (ieee80211com_t *)asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_dev = devinfo;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_init(&asc->asc_genlock, NULL, MUTEX_DRIVER, NULL);
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
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = pci_config_setup(devinfo, &asc->asc_cfg_handle);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "pci_config_setup() failed"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxc if (ath_pci_setup(asc) != 0)
f11a3086bc0b6b242d387296efedd61d43316e8dxc goto attach_fail1;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
1f156c6a7686102f9a1057cb9294c57041f3da68xc /*
1f156c6a7686102f9a1057cb9294c57041f3da68xc * Cache line size is used to size and align various
1f156c6a7686102f9a1057cb9294c57041f3da68xc * structures used to communicate with the hardware.
1f156c6a7686102f9a1057cb9294c57041f3da68xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc csz = pci_config_get8(asc->asc_cfg_handle, PCI_CONF_CACHE_LINESZ);
1f156c6a7686102f9a1057cb9294c57041f3da68xc if (csz == 0) {
1f156c6a7686102f9a1057cb9294c57041f3da68xc /*
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 */
1f156c6a7686102f9a1057cb9294c57041f3da68xc csz = ATH_DEF_CACHE_BYTES / sizeof (uint32_t);
1f156c6a7686102f9a1057cb9294c57041f3da68xc pci_config_put8(asc->asc_cfg_handle, PCI_CONF_CACHE_LINESZ,
1f156c6a7686102f9a1057cb9294c57041f3da68xc csz);
1f156c6a7686102f9a1057cb9294c57041f3da68xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_cachelsz = csz << 2;
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
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc athname = ath_hal_probe(vendor_id, device_id);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): athname: %s\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc athname ? athname : "Atheros ???"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pci_config_put8(asc->asc_cfg_handle, PCI_CONF_LATENCY_TIMER, 0xa8);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc val = pci_config_get32(asc->asc_cfg_handle, 0x40);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if ((val & 0x0000ff00) != 0)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pci_config_put32(asc->asc_cfg_handle, 0x40, val & 0xffff00ff);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ddi_regs_map_setup(devinfo, 1,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc &regs, 0, 0, &ath_reg_accattr, &asc->asc_io_handle);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "regs map1 = %x err=%d\n", regs, err));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "ddi_regs_map_setup() failed"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah = ath_hal_attach(device_id, asc, 0, regs, &status);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ah == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc "unable to attach hw: '%s' (HAL status %u)\n",
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc ath_get_hal_status_desc(status), status));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail2;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
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 ATH_HAL_INTRSET(ah, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_ah = ah;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ah->ah_abi != HAL_ABI_VERSION) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL ABI mismatch detected (0x%x != 0x%x)\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_abi, HAL_ABI_VERSION));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail3;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL ABI version 0x%x\n", ah->ah_abi));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL mac version %d.%d, phy version %d.%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_macVersion, ah->ah_macRev,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ah->ah_analog5GhzRev)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL 5ghz radio version %d.%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_analog5GhzRev >> 4,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_analog5GhzRev & 0xf));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ah->ah_analog2GhzRev)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "HAL 2ghz radio version %d.%d\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_analog2GhzRev >> 4,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_analog2GhzRev & 0xf));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_mrretry = ATH_HAL_SETUPXTXDESC(ah, NULL, 0, 0, 0, 0, 0, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "multi rate retry support=%x\n",
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_mrretry));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Get the hardware key cache size.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf asc->asc_keymax = ATH_HAL_KEYCACHESIZE(ah);
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (asc->asc_keymax > sizeof (asc->asc_keymap) * NBBY) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_ATTACH, "ath_attach:"
a399b7655a1d835aa8606c2b29e4e777baac8635zf " Warning, using only %u entries in %u key cache\n",
a399b7655a1d835aa8606c2b29e4e777baac8635zf sizeof (asc->asc_keymap) * NBBY, asc->asc_keymax));
a399b7655a1d835aa8606c2b29e4e777baac8635zf asc->asc_keymax = sizeof (asc->asc_keymap) * NBBY;
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf /*
a399b7655a1d835aa8606c2b29e4e777baac8635zf * Reset the key cache since some parts do not
a399b7655a1d835aa8606c2b29e4e777baac8635zf * reset the contents on initial power up.
a399b7655a1d835aa8606c2b29e4e777baac8635zf */
a399b7655a1d835aa8606c2b29e4e777baac8635zf for (i = 0; i < asc->asc_keymax; i++)
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_HAL_KEYRESET(ah, i);
a399b7655a1d835aa8606c2b29e4e777baac8635zf
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_GETREGDOMAIN(ah, (uint32_t *)&ath_regdomain);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_GETCOUNTRYCODE(ah, &ath_countrycode);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
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 */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_have11g = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* enable outdoor use, enable extended channels */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ath_getchannels(asc, ath_countrycode, AH_FALSE, AH_TRUE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != 0)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail3;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /*
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc * Setup rate tables for all potential media types.
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_setup(asc, IEEE80211_MODE_11A);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_setup(asc, IEEE80211_MODE_11B);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_rate_setup(asc, IEEE80211_MODE_11G);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_rate_setup(asc, IEEE80211_MODE_TURBO_A);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Setup here so ath_rate_update is happy */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_setcurmode(asc, IEEE80211_MODE_11A);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ath_desc_alloc(devinfo, asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "failed to allocate descriptors: %d\n", err));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail3;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
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;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Setup transmit queues in the HAL */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ath_txq_setup(asc))
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail4;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_HAL_GETMAC(ah, ic->ic_macaddr);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Initialize pointers to device specific functions which
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * will be used by the generic layer.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* 11g support is identified when we fetch the channel set */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (asc->asc_have11g)
c1500db945971ce16b2509a64fc04cd590779a2ezf ic->ic_caps |= IEEE80211_C_SHPREAMBLE |
c1500db945971ce16b2509a64fc04cd590779a2ezf IEEE80211_C_SHSLOT; /* short slot time */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Query the hal to figure out h/w crypto support.
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_WEP))
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_caps |= IEEE80211_C_WEP;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_AES_OCB))
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_caps |= IEEE80211_C_AES;
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_AES_CCM)) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_ATTACH, "Atheros support H/W CCMP\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_caps |= IEEE80211_C_AES_CCM;
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_CKIP))
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_caps |= IEEE80211_C_CKIP;
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_TKIP)) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_ATTACH, "Atheros support H/W TKIP\n"));
a399b7655a1d835aa8606c2b29e4e777baac8635zf ic->ic_caps |= IEEE80211_C_TKIP;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
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 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf if (ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_MIC)) {
a399b7655a1d835aa8606c2b29e4e777baac8635zf ATH_DEBUG((ATH_DBG_ATTACH, "Support H/W TKIP MIC\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_caps |= IEEE80211_C_TKIPMIC;
a399b7655a1d835aa8606c2b29e4e777baac8635zf }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /*
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 */
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_splitmic = 1;
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
a399b7655a1d835aa8606c2b29e4e777baac8635zf ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */
a399b7655a1d835aa8606c2b29e4e777baac8635zf
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_hasclrkey = ATH_HAL_CIPHERSUPPORTED(ah, HAL_CIPHER_CLR);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China /*
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 */
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);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China }
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_phytype = IEEE80211_T_OFDM;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_opmode = IEEE80211_M_STA;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_state = IEEE80211_S_INIT;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_maxrssi = ATH_MAX_RSSI;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_set_shortslot = ath_set_shortslot;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_xmit = ath_xmit;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_attach(ic);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
a399b7655a1d835aa8606c2b29e4e777baac8635zf /* different instance has different WPA door */
a399b7655a1d835aa8606c2b29e4e777baac8635zf (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
1f156c6a7686102f9a1057cb9294c57041f3da68xc ddi_driver_name(devinfo),
1f156c6a7686102f9a1057cb9294c57041f3da68xc ddi_get_instance(devinfo));
a399b7655a1d835aa8606c2b29e4e777baac8635zf
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /* Override 80211 default routines */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_reset = ath_reset;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc asc->asc_newstate = ic->ic_newstate;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_newstate = ath_newstate;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_watchdog = ath_watchdog;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_node_alloc = ath_node_alloc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_node_free = ath_node_free;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_crypto.cs_key_alloc = ath_key_alloc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_crypto.cs_key_delete = ath_key_delete;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ic->ic_crypto.cs_key_set = ath_key_set;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_media_init(ic);
d28940508b8826beeaea79e67482a225b86f3778zf /*
d28940508b8826beeaea79e67482a225b86f3778zf * initialize default tx key
d28940508b8826beeaea79e67482a225b86f3778zf */
d28940508b8826beeaea79e67482a225b86f3778zf ic->ic_def_txkey = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_rx_pend = 0;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(ah, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW,
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc &asc->asc_softint_id, NULL, 0, ath_softint_handler, (caddr_t)asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "ddi_add_softintr() failed\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail5;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ddi_get_iblock_cookie(devinfo, 0, &asc->asc_iblock)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Can not get iblock cookie for INT\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail6;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (ddi_add_intr(devinfo, 0, NULL, NULL, ath_intr,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (caddr_t)asc) != DDI_SUCCESS) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Can not set intr for ATH driver\n"));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail6;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Provide initial settings for the WiFi plugin; whenever this
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * information changes, we need to call mac_plugindata_update()
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wd.wd_opmode = ic->ic_opmode;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc wd.wd_secalloc = WIFI_SEC_NONE;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "MAC version mismatch\n"));
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc goto attach_fail7;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc }
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_driver = asc;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_dip = devinfo;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_src_addr = ic->ic_macaddr;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_callbacks = &ath_m_callbacks;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_min_sdu = 0;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_max_sdu = IEEE80211_MTU;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_pdata = &wd;
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc macp->m_pdata_size = sizeof (wd);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc err = mac_register(macp, &ic->ic_mach);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_free(macp);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc if (err != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_DEBUG((ATH_DBG_ATTACH, "ath: ath_attach(): "
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc "mac_register err %x\n", err));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc goto attach_fail7;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* Create minor node of type DDI_NT_NET_WIFI */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ATH_NODENAME, instance);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc instance + 1, DDI_NT_NET_WIFI, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (err != DDI_SUCCESS)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_DEBUG((ATH_DBG_ATTACH, "WARN: ath: ath_attach(): "
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc "Create minor node failed - %d\n", err));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_invalid = 1;
f11a3086bc0b6b242d387296efedd61d43316e8dxc asc->asc_isrunning = 0;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc asc->asc_promisc = B_FALSE;
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc bzero(asc->asc_mcast_refs, sizeof (asc->asc_mcast_refs));
3caf11144eab1a56717f986d44ae7f40ee8b28fcxc bzero(asc->asc_mcast_hash, sizeof (asc->asc_mcast_hash));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_SUCCESS);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail7:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_remove_intr(devinfo, 0, asc->asc_iblock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail6:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_remove_softintr(asc->asc_softint_id);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail5:
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc (void) ieee80211_detach(ic);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail4:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_desc_free(asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China if (asc->asc_tq)
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ddi_taskq_destroy(asc->asc_tq);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail3:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ah->ah_detach(asc->asc_ah);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail2:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_regs_map_free(&asc->asc_io_handle);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail1:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pci_config_teardown(&asc->asc_cfg_handle);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcattach_fail0:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_invalid = 1;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&asc->asc_txbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (ATH_TXQ_SETUP(asc, i)) {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc struct ath_txq *txq = &asc->asc_txq[i];
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&txq->axq_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&asc->asc_genlock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_destroy(&asc->asc_resched_lock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ddi_soft_state_free(ath_soft_state_p, instance);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_FAILURE);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxc/*
f11a3086bc0b6b242d387296efedd61d43316e8dxc * Suspend transmit/receive for powerdown
f11a3086bc0b6b242d387296efedd61d43316e8dxc */
f11a3086bc0b6b242d387296efedd61d43316e8dxcstatic int
f11a3086bc0b6b242d387296efedd61d43316e8dxcath_suspend(ath_t *asc)
f11a3086bc0b6b242d387296efedd61d43316e8dxc{
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_LOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc ath_stop_locked(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_UNLOCK(asc);
f11a3086bc0b6b242d387296efedd61d43316e8dxc ATH_DEBUG((ATH_DBG_SUSPEND, "ath: suspended.\n"));
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (DDI_SUCCESS);
f11a3086bc0b6b242d387296efedd61d43316e8dxc}
f11a3086bc0b6b242d387296efedd61d43316e8dxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic int32_t
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcath_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_t *asc;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ASSERT(asc != NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
f11a3086bc0b6b242d387296efedd61d43316e8dxc switch (cmd) {
f11a3086bc0b6b242d387296efedd61d43316e8dxc case DDI_DETACH:
f11a3086bc0b6b242d387296efedd61d43316e8dxc break;
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc case DDI_SUSPEND:
f11a3086bc0b6b242d387296efedd61d43316e8dxc return (ath_suspend(asc));
f11a3086bc0b6b242d387296efedd61d43316e8dxc
f11a3086bc0b6b242d387296efedd61d43316e8dxc default:
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_FAILURE);
f11a3086bc0b6b242d387296efedd61d43316e8dxc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China if (mac_disable(asc->asc_isc.ic_mach) != 0)
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_stop_scantimer(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* disable interrupts */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ATH_HAL_INTRSET(asc->asc_ah, 0);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * Unregister from the MAC layer subsystem
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China (void) mac_unregister(asc->asc_isc.ic_mach);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* free intterrupt resources */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_remove_intr(devinfo, 0, asc->asc_iblock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_remove_softintr(asc->asc_softint_id);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc /*
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
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc * it last
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc */
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ieee80211_detach(&asc->asc_isc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ath_desc_free(asc);
129d67acdc2d029d3d6cff4022c0c26c81c76f89lin wang - Sun Microsystems - Beijing China ddi_taskq_destroy(asc->asc_tq);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_txq_cleanup(asc);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc asc->asc_ah->ah_detach(asc->asc_ah);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* free io handle */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_regs_map_free(&asc->asc_io_handle);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc pci_config_teardown(&asc->asc_cfg_handle);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc /* destroy locks */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&asc->asc_rxbuflock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&asc->asc_genlock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mutex_destroy(&asc->asc_resched_lock);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_remove_minor_node(devinfo, NULL);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc ddi_soft_state_free(ath_soft_state_p, ddi_get_instance(devinfo));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (DDI_SUCCESS);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev/*
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * quiesce(9E) entry point.
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev *
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 * blocked.
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev *
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 */
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyevstatic int32_t
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyevath_quiesce(dev_info_t *devinfo)
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev{
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ath_t *asc;
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev struct ath_hal *ah;
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev int i;
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev asc = ddi_get_soft_state(ath_soft_state_p, ddi_get_instance(devinfo));
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev if (asc == NULL || (ah = asc->asc_ah) == NULL)
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev return (DDI_FAILURE);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev /*
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Disable interrupts
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev */
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ATH_HAL_INTRSET(ah, 0);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev /*
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Disable TX HW
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev */
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev for (i = 0; i < HAL_NUM_TX_QUEUES; i++) {
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev if (ATH_TXQ_SETUP(asc, i)) {
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ATH_HAL_STOPTXDMA(ah, asc->asc_txq[i].axq_qnum);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev }
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev }
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev /*
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Disable RX HW
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev */
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ATH_HAL_STOPPCURECV(ah);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ATH_HAL_SETRXFILTER(ah, 0);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ATH_HAL_STOPDMARECV(ah);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev drv_usecwait(3000);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev /*
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev * Power down HW
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev */
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev ATH_HAL_PHYDISABLE(ah);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev return (DDI_SUCCESS);
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev}
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxcDDI_DEFINE_STREAM_OPS(ath_dev_ops, nulldev, nulldev, ath_attach, ath_detach,
b9ee76db3dd20a04fb00f5d885ffb58006c581bfKonstantin Ananyev nodev, NULL, D_MP, NULL, ath_quiesce);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic struct modldrv ath_modldrv = {
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 &ath_dev_ops /* driver specific ops */
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc};
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcstatic struct modlinkage modlinkage = {
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc MODREV_1, (void *)&ath_modldrv, NULL
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc};
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcint
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc_info(struct modinfo *modinfop)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (mod_info(&modlinkage, modinfop));
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcint
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc_init(void)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc status = ddi_soft_state_init(&ath_soft_state_p, sizeof (ath_t), 1);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status != 0)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (status);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_init(&ath_loglock, NULL, MUTEX_DRIVER, NULL);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_halfix_init();
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_init_ops(&ath_dev_ops, "ath");
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc status = mod_install(&modlinkage);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status != 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_fini_ops(&ath_dev_ops);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_halfix_finit();
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&ath_loglock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ddi_soft_state_fini(&ath_soft_state_p);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (status);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xcint
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc_fini(void)
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc{
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc int status;
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc status = mod_remove(&modlinkage);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc if (status == 0) {
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc mac_fini_ops(&ath_dev_ops);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ath_halfix_finit();
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc mutex_destroy(&ath_loglock);
0ba2cbe97e0678a691742f98d2532caed0a2c4aaxc ddi_soft_state_fini(&ath_soft_state_p);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc }
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc return (status);
7a1306a70fee0e017a445bde1dcfd1997f691cf4xc}