Home | History | Annotate | Download | only in wpi
      1  4128   hx147065 /*
      2  8796  Pengcheng  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
      3  4128   hx147065  * Use is subject to license terms.
      4  4128   hx147065  */
      5  4128   hx147065 
      6  4128   hx147065 /*
      7  4128   hx147065  * Copyright (c) 2006
      8  4128   hx147065  *	Damien Bergamini <damien.bergamini (at) free.fr>
      9  4128   hx147065  *
     10  4128   hx147065  * Permission to use, copy, modify, and distribute this software for any
     11  4128   hx147065  * purpose with or without fee is hereby granted, provided that the above
     12  4128   hx147065  * copyright notice and this permission notice appear in all copies.
     13  4128   hx147065  *
     14  4128   hx147065  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     15  4128   hx147065  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     16  4128   hx147065  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     17  4128   hx147065  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     18  4128   hx147065  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     19  4128   hx147065  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     20  4128   hx147065  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     21  4128   hx147065  */
     22  4128   hx147065 
     23  4128   hx147065 /*
     24  4128   hx147065  * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
     25  4128   hx147065  */
     26  4128   hx147065 
     27  4128   hx147065 #include <sys/types.h>
     28  4128   hx147065 #include <sys/byteorder.h>
     29  4128   hx147065 #include <sys/conf.h>
     30  4128   hx147065 #include <sys/cmn_err.h>
     31  4128   hx147065 #include <sys/stat.h>
     32  4128   hx147065 #include <sys/ddi.h>
     33  4128   hx147065 #include <sys/sunddi.h>
     34  4128   hx147065 #include <sys/strsubr.h>
     35  4128   hx147065 #include <sys/ethernet.h>
     36  4128   hx147065 #include <inet/common.h>
     37  4128   hx147065 #include <inet/nd.h>
     38  4128   hx147065 #include <inet/mi.h>
     39  4128   hx147065 #include <sys/note.h>
     40  4128   hx147065 #include <sys/stream.h>
     41  4128   hx147065 #include <sys/strsun.h>
     42  4128   hx147065 #include <sys/modctl.h>
     43  4128   hx147065 #include <sys/devops.h>
     44  4128   hx147065 #include <sys/dlpi.h>
     45  8275       Eric #include <sys/mac_provider.h>
     46  4128   hx147065 #include <sys/mac_wifi.h>
     47  4128   hx147065 #include <sys/net80211.h>
     48  4128   hx147065 #include <sys/net80211_proto.h>
     49  4128   hx147065 #include <sys/varargs.h>
     50  4128   hx147065 #include <sys/policy.h>
     51  4128   hx147065 #include <sys/pci.h>
     52  4128   hx147065 
     53  4128   hx147065 #include "wpireg.h"
     54  4128   hx147065 #include "wpivar.h"
     55  4128   hx147065 #include <inet/wifi_ioctl.h>
     56  4128   hx147065 
     57  4128   hx147065 #ifdef DEBUG
     58  4128   hx147065 #define	WPI_DEBUG_80211		(1 << 0)
     59  4128   hx147065 #define	WPI_DEBUG_CMD		(1 << 1)
     60  4128   hx147065 #define	WPI_DEBUG_DMA		(1 << 2)
     61  4128   hx147065 #define	WPI_DEBUG_EEPROM	(1 << 3)
     62  4128   hx147065 #define	WPI_DEBUG_FW		(1 << 4)
     63  4128   hx147065 #define	WPI_DEBUG_HW		(1 << 5)
     64  4128   hx147065 #define	WPI_DEBUG_INTR		(1 << 6)
     65  4128   hx147065 #define	WPI_DEBUG_MRR		(1 << 7)
     66  4128   hx147065 #define	WPI_DEBUG_PIO		(1 << 8)
     67  4128   hx147065 #define	WPI_DEBUG_RX		(1 << 9)
     68  4128   hx147065 #define	WPI_DEBUG_SCAN		(1 << 10)
     69  4128   hx147065 #define	WPI_DEBUG_TX		(1 << 11)
     70  4128   hx147065 #define	WPI_DEBUG_RATECTL	(1 << 12)
     71  4128   hx147065 #define	WPI_DEBUG_RADIO		(1 << 13)
     72  6062   hx147065 #define	WPI_DEBUG_RESUME	(1 << 14)
     73  4128   hx147065 uint32_t wpi_dbg_flags = 0;
     74  4128   hx147065 #define	WPI_DBG(x) \
     75  4128   hx147065 	wpi_dbg x
     76  4128   hx147065 #else
     77  4128   hx147065 #define	WPI_DBG(x)
     78  4128   hx147065 #endif
     79  4128   hx147065 
     80  4128   hx147065 static void	*wpi_soft_state_p = NULL;
     81  4128   hx147065 static uint8_t wpi_fw_bin [] = {
     82  4128   hx147065 #include "fw-wpi/ipw3945.ucode.hex"
     83  4128   hx147065 };
     84  4128   hx147065 
     85  4128   hx147065 /* DMA attributes for a shared page */
     86  4128   hx147065 static ddi_dma_attr_t sh_dma_attr = {
     87  4128   hx147065 	DMA_ATTR_V0,	/* version of this structure */
     88  4128   hx147065 	0,		/* lowest usable address */
     89  4128   hx147065 	0xffffffffU,	/* highest usable address */
     90  4128   hx147065 	0xffffffffU,	/* maximum DMAable byte count */
     91  4128   hx147065 	0x1000,		/* alignment in bytes */
     92  4128   hx147065 	0x1000,		/* burst sizes (any?) */
     93  4128   hx147065 	1,		/* minimum transfer */
     94  4128   hx147065 	0xffffffffU,	/* maximum transfer */
     95  4128   hx147065 	0xffffffffU,	/* maximum segment length */
     96  4128   hx147065 	1,		/* maximum number of segments */
     97  4128   hx147065 	1,		/* granularity */
     98  4128   hx147065 	0,		/* flags (reserved) */
     99  4128   hx147065 };
    100  4128   hx147065 
    101  4128   hx147065 /* DMA attributes for a ring descriptor */
    102  4128   hx147065 static ddi_dma_attr_t ring_desc_dma_attr = {
    103  4128   hx147065 	DMA_ATTR_V0,	/* version of this structure */
    104  4128   hx147065 	0,		/* lowest usable address */
    105  4128   hx147065 	0xffffffffU,	/* highest usable address */
    106  4128   hx147065 	0xffffffffU,	/* maximum DMAable byte count */
    107  4128   hx147065 	0x4000,		/* alignment in bytes */
    108  4128   hx147065 	0x100,		/* burst sizes (any?) */
    109  4128   hx147065 	1,		/* minimum transfer */
    110  4128   hx147065 	0xffffffffU,	/* maximum transfer */
    111  4128   hx147065 	0xffffffffU,	/* maximum segment length */
    112  4128   hx147065 	1,		/* maximum number of segments */
    113  4128   hx147065 	1,		/* granularity */
    114  4128   hx147065 	0,		/* flags (reserved) */
    115  4128   hx147065 };
    116  4128   hx147065 
    117  4128   hx147065 
    118  4128   hx147065 /* DMA attributes for a tx cmd */
    119  4128   hx147065 static ddi_dma_attr_t tx_cmd_dma_attr = {
    120  4128   hx147065 	DMA_ATTR_V0,	/* version of this structure */
    121  4128   hx147065 	0,		/* lowest usable address */
    122  4128   hx147065 	0xffffffffU,	/* highest usable address */
    123  4128   hx147065 	0xffffffffU,	/* maximum DMAable byte count */
    124  4128   hx147065 	4,		/* alignment in bytes */
    125  4128   hx147065 	0x100,		/* burst sizes (any?) */
    126  4128   hx147065 	1,		/* minimum transfer */
    127  4128   hx147065 	0xffffffffU,	/* maximum transfer */
    128  4128   hx147065 	0xffffffffU,	/* maximum segment length */
    129  4128   hx147065 	1,		/* maximum number of segments */
    130  4128   hx147065 	1,		/* granularity */
    131  4128   hx147065 	0,		/* flags (reserved) */
    132  4128   hx147065 };
    133  4128   hx147065 
    134  4128   hx147065 /* DMA attributes for a rx buffer */
    135  4128   hx147065 static ddi_dma_attr_t rx_buffer_dma_attr = {
    136  4128   hx147065 	DMA_ATTR_V0,	/* version of this structure */
    137  4128   hx147065 	0,		/* lowest usable address */
    138  4128   hx147065 	0xffffffffU,	/* highest usable address */
    139  4128   hx147065 	0xffffffffU,	/* maximum DMAable byte count */
    140  4128   hx147065 	1,		/* alignment in bytes */
    141  4128   hx147065 	0x100,		/* burst sizes (any?) */
    142  4128   hx147065 	1,		/* minimum transfer */
    143  4128   hx147065 	0xffffffffU,	/* maximum transfer */
    144  4128   hx147065 	0xffffffffU,	/* maximum segment length */
    145  4128   hx147065 	1,		/* maximum number of segments */
    146  4128   hx147065 	1,		/* granularity */
    147  4128   hx147065 	0,		/* flags (reserved) */
    148  4128   hx147065 };
    149  4128   hx147065 
    150  4128   hx147065 /*
    151  4128   hx147065  * DMA attributes for a tx buffer.
    152  4128   hx147065  * the maximum number of segments is 4 for the hardware.
    153  4128   hx147065  * now all the wifi drivers put the whole frame in a single
    154  4128   hx147065  * descriptor, so we define the maximum  number of segments 4,
    155  4128   hx147065  * just the same as the rx_buffer. we consider leverage the HW
    156  4128   hx147065  * ability in the future, that is why we don't define rx and tx
    157  4128   hx147065  * buffer_dma_attr as the same.
    158  4128   hx147065  */
    159  4128   hx147065 static ddi_dma_attr_t tx_buffer_dma_attr = {
    160  4128   hx147065 	DMA_ATTR_V0,	/* version of this structure */
    161  4128   hx147065 	0,		/* lowest usable address */
    162  4128   hx147065 	0xffffffffU,	/* highest usable address */
    163  4128   hx147065 	0xffffffffU,	/* maximum DMAable byte count */
    164  4128   hx147065 	1,		/* alignment in bytes */
    165  4128   hx147065 	0x100,		/* burst sizes (any?) */
    166  4128   hx147065 	1,		/* minimum transfer */
    167  4128   hx147065 	0xffffffffU,	/* maximum transfer */
    168  4128   hx147065 	0xffffffffU,	/* maximum segment length */
    169  4128   hx147065 	1,		/* maximum number of segments */
    170  4128   hx147065 	1,		/* granularity */
    171  4128   hx147065 	0,		/* flags (reserved) */
    172  4128   hx147065 };
    173  4128   hx147065 
    174  4128   hx147065 /* DMA attributes for a load firmware */
    175  4128   hx147065 static ddi_dma_attr_t fw_buffer_dma_attr = {
    176  4128   hx147065 	DMA_ATTR_V0,	/* version of this structure */
    177  4128   hx147065 	0,		/* lowest usable address */
    178  4128   hx147065 	0xffffffffU,	/* highest usable address */
    179  4128   hx147065 	0x7fffffff,	/* maximum DMAable byte count */
    180  4128   hx147065 	4,		/* alignment in bytes */
    181  4128   hx147065 	0x100,		/* burst sizes (any?) */
    182  4128   hx147065 	1,		/* minimum transfer */
    183  4128   hx147065 	0xffffffffU,	/* maximum transfer */
    184  4128   hx147065 	0xffffffffU,	/* maximum segment length */
    185  4128   hx147065 	4,		/* maximum number of segments */
    186  4128   hx147065 	1,		/* granularity */
    187  4128   hx147065 	0,		/* flags (reserved) */
    188  4128   hx147065 };
    189  4128   hx147065 
    190  4128   hx147065 /* regs access attributes */
    191  4128   hx147065 static ddi_device_acc_attr_t wpi_reg_accattr = {
    192  4128   hx147065 	DDI_DEVICE_ATTR_V0,
    193  4128   hx147065 	DDI_STRUCTURE_LE_ACC,
    194  4128   hx147065 	DDI_STRICTORDER_ACC,
    195  4128   hx147065 	DDI_DEFAULT_ACC
    196  4128   hx147065 };
    197  4128   hx147065 
    198  4128   hx147065 /* DMA access attributes */
    199  4128   hx147065 static ddi_device_acc_attr_t wpi_dma_accattr = {
    200  4128   hx147065 	DDI_DEVICE_ATTR_V0,
    201  4128   hx147065 	DDI_NEVERSWAP_ACC,
    202  4128   hx147065 	DDI_STRICTORDER_ACC,
    203  4128   hx147065 	DDI_DEFAULT_ACC
    204  4128   hx147065 };
    205  4128   hx147065 
    206  4128   hx147065 static int	wpi_ring_init(wpi_sc_t *);
    207  4128   hx147065 static void	wpi_ring_free(wpi_sc_t *);
    208  4128   hx147065 static int	wpi_alloc_shared(wpi_sc_t *);
    209  4128   hx147065 static void	wpi_free_shared(wpi_sc_t *);
    210  4128   hx147065 static int	wpi_alloc_fw_dma(wpi_sc_t *);
    211  4128   hx147065 static void	wpi_free_fw_dma(wpi_sc_t *);
    212  4128   hx147065 static int	wpi_alloc_rx_ring(wpi_sc_t *);
    213  4128   hx147065 static void	wpi_reset_rx_ring(wpi_sc_t *);
    214  4128   hx147065 static void	wpi_free_rx_ring(wpi_sc_t *);
    215  4128   hx147065 static int	wpi_alloc_tx_ring(wpi_sc_t *, wpi_tx_ring_t *, int, int);
    216  4128   hx147065 static void	wpi_reset_tx_ring(wpi_sc_t *, wpi_tx_ring_t *);
    217  4128   hx147065 static void	wpi_free_tx_ring(wpi_sc_t *, wpi_tx_ring_t *);
    218  4128   hx147065 
    219  4128   hx147065 static ieee80211_node_t *wpi_node_alloc(ieee80211com_t *);
    220  4128   hx147065 static void	wpi_node_free(ieee80211_node_t *);
    221  4128   hx147065 static int	wpi_newstate(ieee80211com_t *, enum ieee80211_state, int);
    222  5296   zf162725 static int	wpi_key_set(ieee80211com_t *, const struct ieee80211_key *,
    223  5296   zf162725     const uint8_t mac[IEEE80211_ADDR_LEN]);
    224  4128   hx147065 static void	wpi_mem_lock(wpi_sc_t *);
    225  4128   hx147065 static void	wpi_mem_unlock(wpi_sc_t *);
    226  4128   hx147065 static uint32_t	wpi_mem_read(wpi_sc_t *, uint16_t);
    227  4128   hx147065 static void	wpi_mem_write(wpi_sc_t *, uint16_t, uint32_t);
    228  4128   hx147065 static void	wpi_mem_write_region_4(wpi_sc_t *, uint16_t,
    229  4128   hx147065 		    const uint32_t *, int);
    230  4128   hx147065 static uint16_t	wpi_read_prom_word(wpi_sc_t *, uint32_t);
    231  4128   hx147065 static int	wpi_load_microcode(wpi_sc_t *);
    232  4128   hx147065 static int	wpi_load_firmware(wpi_sc_t *, uint32_t);
    233  4128   hx147065 static void	wpi_rx_intr(wpi_sc_t *, wpi_rx_desc_t *,
    234  4128   hx147065 		    wpi_rx_data_t *);
    235  4128   hx147065 static void	wpi_tx_intr(wpi_sc_t *, wpi_rx_desc_t *,
    236  4128   hx147065 		    wpi_rx_data_t *);
    237  4128   hx147065 static void	wpi_cmd_intr(wpi_sc_t *, wpi_rx_desc_t *);
    238  4128   hx147065 static uint_t	wpi_intr(caddr_t);
    239  4128   hx147065 static uint_t	wpi_notif_softintr(caddr_t);
    240  4128   hx147065 static uint8_t	wpi_plcp_signal(int);
    241  4128   hx147065 static void	wpi_read_eeprom(wpi_sc_t *);
    242  4128   hx147065 static int	wpi_cmd(wpi_sc_t *, int, const void *, int, int);
    243  4128   hx147065 static int	wpi_mrr_setup(wpi_sc_t *);
    244  4128   hx147065 static void	wpi_set_led(wpi_sc_t *, uint8_t, uint8_t, uint8_t);
    245  4128   hx147065 static int	wpi_auth(wpi_sc_t *);
    246  4128   hx147065 static int	wpi_scan(wpi_sc_t *);
    247  4128   hx147065 static int	wpi_config(wpi_sc_t *);
    248  4128   hx147065 static void	wpi_stop_master(wpi_sc_t *);
    249  4128   hx147065 static int	wpi_power_up(wpi_sc_t *);
    250  4128   hx147065 static int	wpi_reset(wpi_sc_t *);
    251  4128   hx147065 static void	wpi_hw_config(wpi_sc_t *);
    252  4128   hx147065 static int	wpi_init(wpi_sc_t *);
    253  4128   hx147065 static void	wpi_stop(wpi_sc_t *);
    254  8165        Fei static int	wpi_quiesce(dev_info_t *dip);
    255  4128   hx147065 static void	wpi_amrr_init(wpi_amrr_t *);
    256  4128   hx147065 static void	wpi_amrr_timeout(wpi_sc_t *);
    257  4128   hx147065 static void	wpi_amrr_ratectl(void *, ieee80211_node_t *);
    258  4128   hx147065 
    259  4128   hx147065 static int wpi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
    260  4128   hx147065 static int wpi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
    261  4128   hx147065 
    262  4128   hx147065 /*
    263  4128   hx147065  * GLD specific operations
    264  4128   hx147065  */
    265  4128   hx147065 static int	wpi_m_stat(void *arg, uint_t stat, uint64_t *val);
    266  4128   hx147065 static int	wpi_m_start(void *arg);
    267  4128   hx147065 static void	wpi_m_stop(void *arg);
    268  4128   hx147065 static int	wpi_m_unicst(void *arg, const uint8_t *macaddr);
    269  4128   hx147065 static int	wpi_m_multicst(void *arg, boolean_t add, const uint8_t *m);
    270  4128   hx147065 static int	wpi_m_promisc(void *arg, boolean_t on);
    271  4128   hx147065 static mblk_t  *wpi_m_tx(void *arg, mblk_t *mp);
    272  4128   hx147065 static void	wpi_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
    273  7663    Sowmini static int	wpi_m_setprop(void *arg, const char *pr_name,
    274  7663    Sowmini     mac_prop_id_t wldp_pr_num, uint_t wldp_length, const void *wldp_buf);
    275  7663    Sowmini static int	wpi_m_getprop(void *arg, const char *pr_name,
    276  7663    Sowmini     mac_prop_id_t wldp_pr_num, uint_t pr_flags, uint_t wldp_lenth,
    277  8118  Vasumathi     void *wldp_buf, uint_t *);
    278  4128   hx147065 static void	wpi_destroy_locks(wpi_sc_t *sc);
    279  4128   hx147065 static int	wpi_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type);
    280  4128   hx147065 static void	wpi_thread(wpi_sc_t *sc);
    281  8902  Pengcheng static int	wpi_fast_recover(wpi_sc_t *sc);
    282  4128   hx147065 
    283  4128   hx147065 /*
    284  4128   hx147065  * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
    285  4128   hx147065  */
    286  4128   hx147065 static const struct ieee80211_rateset wpi_rateset_11b =
    287  4128   hx147065 	{ 4, { 2, 4, 11, 22 } };
    288  4128   hx147065 
    289  4128   hx147065 static const struct ieee80211_rateset wpi_rateset_11g =
    290  4128   hx147065 	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
    291  4128   hx147065 
    292  4128   hx147065 static const uint8_t wpi_ridx_to_signal[] = {
    293  4128   hx147065 	/* OFDM: IEEE Std 802.11a-1999, pp. 14 Table 80 */
    294  4128   hx147065 	/* R1-R4 (ral/ural is R4-R1) */
    295  4128   hx147065 	0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3,
    296  4128   hx147065 	/* CCK: device-dependent */
    297  4128   hx147065 	10, 20, 55, 110
    298  4128   hx147065 };
    299  4128   hx147065 
    300  4128   hx147065 /*
    301  4128   hx147065  * For mfthread only
    302  4128   hx147065  */
    303  4128   hx147065 extern pri_t minclsyspri;
    304  4128   hx147065 
    305  4128   hx147065 /*
    306  4128   hx147065  * Module Loading Data & Entry Points
    307  4128   hx147065  */
    308  4128   hx147065 DDI_DEFINE_STREAM_OPS(wpi_devops, nulldev, nulldev, wpi_attach,
    309  8165        Fei     wpi_detach, nodev, NULL, D_MP, NULL, wpi_quiesce);
    310  4128   hx147065 
    311  4128   hx147065 static struct modldrv wpi_modldrv = {
    312  4128   hx147065 	&mod_driverops,
    313  4128   hx147065 	"Intel(R) PRO/Wireless 3945ABG driver",
    314  4128   hx147065 	&wpi_devops
    315  4128   hx147065 };
    316  4128   hx147065 
    317  4128   hx147065 static struct modlinkage wpi_modlinkage = {
    318  4128   hx147065 	MODREV_1,
    319  4128   hx147065 	&wpi_modldrv,
    320  4128   hx147065 	NULL
    321  4128   hx147065 };
    322  4128   hx147065 
    323  4128   hx147065 int
    324  4128   hx147065 _init(void)
    325  4128   hx147065 {
    326  4128   hx147065 	int	status;
    327  4128   hx147065 
    328  4128   hx147065 	status = ddi_soft_state_init(&wpi_soft_state_p,
    329  4128   hx147065 	    sizeof (wpi_sc_t), 1);
    330  4128   hx147065 	if (status != DDI_SUCCESS)
    331  4128   hx147065 		return (status);
    332  4128   hx147065 
    333  4128   hx147065 	mac_init_ops(&wpi_devops, "wpi");
    334  4128   hx147065 	status = mod_install(&wpi_modlinkage);
    335  4128   hx147065 	if (status != DDI_SUCCESS) {
    336  4128   hx147065 		mac_fini_ops(&wpi_devops);
    337  4128   hx147065 		ddi_soft_state_fini(&wpi_soft_state_p);
    338  4128   hx147065 	}
    339  4128   hx147065 
    340  4128   hx147065 	return (status);
    341  4128   hx147065 }
    342  4128   hx147065 
    343  4128   hx147065 int
    344  4128   hx147065 _fini(void)
    345  4128   hx147065 {
    346  4128   hx147065 	int status;
    347  4128   hx147065 
    348  4128   hx147065 	status = mod_remove(&wpi_modlinkage);
    349  4128   hx147065 	if (status == DDI_SUCCESS) {
    350  4128   hx147065 		mac_fini_ops(&wpi_devops);
    351  4128   hx147065 		ddi_soft_state_fini(&wpi_soft_state_p);
    352  4128   hx147065 	}
    353  4128   hx147065 
    354  4128   hx147065 	return (status);
    355  4128   hx147065 }
    356  4128   hx147065 
    357  4128   hx147065 int
    358  4128   hx147065 _info(struct modinfo *mip)
    359  4128   hx147065 {
    360  4128   hx147065 	return (mod_info(&wpi_modlinkage, mip));
    361  4128   hx147065 }
    362  4128   hx147065 
    363  4128   hx147065 /*
    364  4128   hx147065  * Mac Call Back entries
    365  4128   hx147065  */
    366  4128   hx147065 mac_callbacks_t	wpi_m_callbacks = {
    367  7663    Sowmini 	MC_IOCTL | MC_SETPROP | MC_GETPROP,
    368  4128   hx147065 	wpi_m_stat,
    369  4128   hx147065 	wpi_m_start,
    370  4128   hx147065 	wpi_m_stop,
    371  4128   hx147065 	wpi_m_promisc,
    372  4128   hx147065 	wpi_m_multicst,
    373  4128   hx147065 	wpi_m_unicst,
    374  4128   hx147065 	wpi_m_tx,
    375  7663    Sowmini 	wpi_m_ioctl,
    376  7663    Sowmini 	NULL,
    377  7663    Sowmini 	NULL,
    378  7663    Sowmini 	NULL,
    379  7663    Sowmini 	wpi_m_setprop,
    380  7663    Sowmini 	wpi_m_getprop
    381  4128   hx147065 };
    382  4128   hx147065 
    383  4128   hx147065 #ifdef DEBUG
    384  4128   hx147065 void
    385  4128   hx147065 wpi_dbg(uint32_t flags, const char *fmt, ...)
    386  4128   hx147065 {
    387  4128   hx147065 	va_list	ap;
    388  4128   hx147065 
    389  4128   hx147065 	if (flags & wpi_dbg_flags) {
    390  4128   hx147065 		va_start(ap, fmt);
    391  4128   hx147065 		vcmn_err(CE_NOTE, fmt, ap);
    392  4128   hx147065 		va_end(ap);
    393  4128   hx147065 	}
    394  4128   hx147065 }
    395  4128   hx147065 #endif
    396  4128   hx147065 /*
    397  4128   hx147065  * device operations
    398  4128   hx147065  */
    399  4128   hx147065 int
    400  4128   hx147065 wpi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
    401  4128   hx147065 {
    402  4128   hx147065 	wpi_sc_t		*sc;
    403  4128   hx147065 	ddi_acc_handle_t	cfg_handle;
    404  4128   hx147065 	caddr_t			cfg_base;
    405  4128   hx147065 	ieee80211com_t	*ic;
    406  4128   hx147065 	int			instance, err, i;
    407  4128   hx147065 	char			strbuf[32];
    408  4128   hx147065 	wifi_data_t		wd = { 0 };
    409  4128   hx147065 	mac_register_t		*macp;
    410  4128   hx147065 
    411  6062   hx147065 	switch (cmd) {
    412  6062   hx147065 	case DDI_ATTACH:
    413  6062   hx147065 		break;
    414  6062   hx147065 	case DDI_RESUME:
    415  6062   hx147065 		sc = ddi_get_soft_state(wpi_soft_state_p,
    416  6062   hx147065 		    ddi_get_instance(dip));
    417  6062   hx147065 		ASSERT(sc != NULL);
    418  8796  Pengcheng 
    419  8796  Pengcheng 		mutex_enter(&sc->sc_glock);
    420  8796  Pengcheng 		sc->sc_flags &= ~WPI_F_SUSPEND;
    421  8796  Pengcheng 		mutex_exit(&sc->sc_glock);
    422  8796  Pengcheng 
    423  8349  Pengcheng 		if (sc->sc_flags & WPI_F_RUNNING)
    424  8349  Pengcheng 			(void) wpi_init(sc);
    425  8349  Pengcheng 
    426  6062   hx147065 		mutex_enter(&sc->sc_glock);
    427  8349  Pengcheng 		sc->sc_flags |= WPI_F_LAZY_RESUME;
    428  6062   hx147065 		mutex_exit(&sc->sc_glock);
    429  8349  Pengcheng 
    430  6062   hx147065 		WPI_DBG((WPI_DEBUG_RESUME, "wpi: resume \n"));
    431  6062   hx147065 		return (DDI_SUCCESS);
    432  6062   hx147065 	default:
    433  4128   hx147065 		err = DDI_FAILURE;
    434  4128   hx147065 		goto attach_fail1;
    435  4128   hx147065 	}
    436  4128   hx147065 
    437  4128   hx147065 	instance = ddi_get_instance(dip);
    438  4128   hx147065 	err = ddi_soft_state_zalloc(wpi_soft_state_p, instance);
    439  4128   hx147065 	if (err != DDI_SUCCESS) {
    440  4128   hx147065 		cmn_err(CE_WARN,
    441  4128   hx147065 		    "wpi_attach(): failed to allocate soft state\n");
    442  4128   hx147065 		goto attach_fail1;
    443  4128   hx147065 	}
    444  4128   hx147065 	sc = ddi_get_soft_state(wpi_soft_state_p, instance);
    445  4128   hx147065 	sc->sc_dip = dip;
    446  4128   hx147065 
    447  4128   hx147065 	err = ddi_regs_map_setup(dip, 0, &cfg_base, 0, 0,
    448  4128   hx147065 	    &wpi_reg_accattr, &cfg_handle);
    449  4128   hx147065 	if (err != DDI_SUCCESS) {
    450  4128   hx147065 		cmn_err(CE_WARN,
    451  4128   hx147065 		    "wpi_attach(): failed to map config spaces regs\n");
    452  4128   hx147065 		goto attach_fail2;
    453  4128   hx147065 	}
    454  4128   hx147065 	sc->sc_rev = ddi_get8(cfg_handle,
    455  4128   hx147065 	    (uint8_t *)(cfg_base + PCI_CONF_REVID));
    456  4128   hx147065 	ddi_put8(cfg_handle, (uint8_t *)(cfg_base + 0x41), 0);
    457  4128   hx147065 	sc->sc_clsz = ddi_get16(cfg_handle,
    458  4128   hx147065 	    (uint16_t *)(cfg_base + PCI_CONF_CACHE_LINESZ));
    459  4128   hx147065 	ddi_regs_map_free(&cfg_handle);
    460  4128   hx147065 	if (!sc->sc_clsz)
    461  4128   hx147065 		sc->sc_clsz = 16;
    462  4128   hx147065 	sc->sc_clsz = (sc->sc_clsz << 2);
    463  4128   hx147065 	sc->sc_dmabuf_sz = roundup(0x1000 + sizeof (struct ieee80211_frame) +
    464  4128   hx147065 	    IEEE80211_MTU + IEEE80211_CRC_LEN +
    465  4128   hx147065 	    (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
    466  4128   hx147065 	    IEEE80211_WEP_CRCLEN), sc->sc_clsz);
    467  4128   hx147065 	/*
    468  4128   hx147065 	 * Map operating registers
    469  4128   hx147065 	 */
    470  4128   hx147065 	err = ddi_regs_map_setup(dip, 1, &sc->sc_base,
    471  4128   hx147065 	    0, 0, &wpi_reg_accattr, &sc->sc_handle);
    472  4128   hx147065 	if (err != DDI_SUCCESS) {
    473  4128   hx147065 		cmn_err(CE_WARN,
    474  4128   hx147065 		    "wpi_attach(): failed to map device regs\n");
    475  4128   hx147065 		goto attach_fail2;
    476  4128   hx147065 	}
    477  4128   hx147065 
    478  4128   hx147065 	/*
    479  4128   hx147065 	 * Allocate shared page.
    480  4128   hx147065 	 */
    481  4128   hx147065 	err = wpi_alloc_shared(sc);
    482  4128   hx147065 	if (err != DDI_SUCCESS) {
    483  4128   hx147065 		cmn_err(CE_WARN, "failed to allocate shared page\n");
    484  4128   hx147065 		goto attach_fail3;
    485  4128   hx147065 	}
    486  4128   hx147065 
    487  4128   hx147065 	/*
    488  4128   hx147065 	 * Get the hw conf, including MAC address, then init all rings.
    489  4128   hx147065 	 */
    490  4128   hx147065 	wpi_read_eeprom(sc);
    491  4128   hx147065 	err = wpi_ring_init(sc);
    492  4128   hx147065 	if (err != DDI_SUCCESS) {
    493  4128   hx147065 		cmn_err(CE_WARN, "wpi_attach(): "
    494  4128   hx147065 		    "failed to allocate and initialize ring\n");
    495  4128   hx147065 		goto attach_fail4;
    496  4128   hx147065 	}
    497  4128   hx147065 
    498  4128   hx147065 	sc->sc_hdr = (const wpi_firmware_hdr_t *)wpi_fw_bin;
    499  4128   hx147065 
    500  4128   hx147065 	/* firmware image layout: |HDR|<--TEXT-->|<--DATA-->|<--BOOT-->| */
    501  4128   hx147065 	sc->sc_text = (const char *)(sc->sc_hdr + 1);
    502  4128   hx147065 	sc->sc_data = sc->sc_text + LE_32(sc->sc_hdr->textsz);
    503  4128   hx147065 	sc->sc_boot = sc->sc_data + LE_32(sc->sc_hdr->datasz);
    504  4128   hx147065 	err = wpi_alloc_fw_dma(sc);
    505  4128   hx147065 	if (err != DDI_SUCCESS) {
    506  4128   hx147065 		cmn_err(CE_WARN, "wpi_attach(): "
    507  4128   hx147065 		    "failed to allocate firmware dma\n");
    508  4128   hx147065 		goto attach_fail5;
    509  4128   hx147065 	}
    510  4128   hx147065 
    511  4128   hx147065 	/*
    512  4128   hx147065 	 * Initialize mutexs and condvars
    513  4128   hx147065 	 */
    514  4128   hx147065 	err = ddi_get_iblock_cookie(dip, 0, &sc->sc_iblk);
    515  4128   hx147065 	if (err != DDI_SUCCESS) {
    516  4128   hx147065 		cmn_err(CE_WARN,
    517  4128   hx147065 		    "wpi_attach(): failed to do ddi_get_iblock_cookie()\n");
    518  4128   hx147065 		goto attach_fail6;
    519  4128   hx147065 	}
    520  4128   hx147065 	mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER, sc->sc_iblk);
    521  4128   hx147065 	mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER, sc->sc_iblk);
    522  4128   hx147065 	cv_init(&sc->sc_fw_cv, NULL, CV_DRIVER, NULL);
    523  4128   hx147065 	cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL);
    524  7865  Pengcheng 
    525  4128   hx147065 	/*
    526  4128   hx147065 	 * initialize the mfthread
    527  4128   hx147065 	 */
    528  4128   hx147065 	mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER,
    529  4128   hx147065 	    (void *) sc->sc_iblk);
    530  4128   hx147065 	cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL);
    531  4128   hx147065 	sc->sc_mf_thread = NULL;
    532  4128   hx147065 	sc->sc_mf_thread_switch = 0;
    533  4128   hx147065 	/*
    534  4128   hx147065 	 * Initialize the wifi part, which will be used by
    535  4128   hx147065 	 * generic layer
    536  4128   hx147065 	 */
    537  4128   hx147065 	ic = &sc->sc_ic;
    538  4128   hx147065 	ic->ic_phytype  = IEEE80211_T_OFDM;
    539  4128   hx147065 	ic->ic_opmode   = IEEE80211_M_STA; /* default to BSS mode */
    540  4128   hx147065 	ic->ic_state    = IEEE80211_S_INIT;
    541  4128   hx147065 	ic->ic_maxrssi  = 70; /* experimental number */
    542  4128   hx147065 	ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT |
    543  4499   hx147065 	    IEEE80211_C_PMGT | IEEE80211_C_SHSLOT;
    544  5296   zf162725 
    545  5296   zf162725 	/*
    546  5296   zf162725 	 * use software WEP and TKIP, hardware CCMP;
    547  5296   zf162725 	 */
    548  5296   zf162725 	ic->ic_caps |= IEEE80211_C_AES_CCM;
    549  5296   zf162725 	ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */
    550  4128   hx147065 
    551  4128   hx147065 	/* set supported .11b and .11g rates */
    552  4128   hx147065 	ic->ic_sup_rates[IEEE80211_MODE_11B] = wpi_rateset_11b;
    553  4128   hx147065 	ic->ic_sup_rates[IEEE80211_MODE_11G] = wpi_rateset_11g;
    554  4128   hx147065 
    555  4128   hx147065 	/* set supported .11b and .11g channels (1 through 14) */
    556  4128   hx147065 	for (i = 1; i <= 14; i++) {
    557  4128   hx147065 		ic->ic_sup_channels[i].ich_freq =
    558  4128   hx147065 		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
    559  4128   hx147065 		ic->ic_sup_channels[i].ich_flags =
    560  4128   hx147065 		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
    561  7865  Pengcheng 		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ |
    562  7865  Pengcheng 		    IEEE80211_CHAN_PASSIVE;
    563  4128   hx147065 	}
    564  4128   hx147065 	ic->ic_ibss_chan = &ic->ic_sup_channels[0];
    565  4128   hx147065 	ic->ic_xmit = wpi_send;
    566  4128   hx147065 	/*
    567  4128   hx147065 	 * init Wifi layer
    568  4128   hx147065 	 */
    569  4128   hx147065 	ieee80211_attach(ic);
    570  4128   hx147065 
    571  5296   zf162725 	/* register WPA door */
    572  5296   zf162725 	ieee80211_register_door(ic, ddi_driver_name(dip),
    573  5296   zf162725 	    ddi_get_instance(dip));
    574  5296   zf162725 
    575  4128   hx147065 	/*
    576  4128   hx147065 	 * Override 80211 default routines
    577  4128   hx147065 	 */
    578  4128   hx147065 	sc->sc_newstate = ic->ic_newstate;
    579  4128   hx147065 	ic->ic_newstate = wpi_newstate;
    580  4128   hx147065 	ic->ic_node_alloc = wpi_node_alloc;
    581  4128   hx147065 	ic->ic_node_free = wpi_node_free;
    582  5296   zf162725 	ic->ic_crypto.cs_key_set = wpi_key_set;
    583  4128   hx147065 	ieee80211_media_init(ic);
    584  4128   hx147065 	/*
    585  4128   hx147065 	 * initialize default tx key
    586  4128   hx147065 	 */
    587  4128   hx147065 	ic->ic_def_txkey = 0;
    588  4128   hx147065 
    589  4128   hx147065 	err = ddi_add_softintr(dip, DDI_SOFTINT_LOW,
    590  4128   hx147065 	    &sc->sc_notif_softint_id, &sc->sc_iblk, NULL, wpi_notif_softintr,
    591  4128   hx147065 	    (caddr_t)sc);
    592  4128   hx147065 	if (err != DDI_SUCCESS) {
    593  4128   hx147065 		cmn_err(CE_WARN,
    594  4128   hx147065 		    "wpi_attach(): failed to do ddi_add_softintr()\n");
    595  4128   hx147065 		goto attach_fail7;
    596  4128   hx147065 	}
    597  4128   hx147065 
    598  4128   hx147065 	/*
    599  4128   hx147065 	 * Add the interrupt handler
    600  4128   hx147065 	 */
    601  4128   hx147065 	err = ddi_add_intr(dip, 0, &sc->sc_iblk, NULL,
    602  4128   hx147065 	    wpi_intr, (caddr_t)sc);
    603  4128   hx147065 	if (err != DDI_SUCCESS) {
    604  4128   hx147065 		cmn_err(CE_WARN,
    605  4128   hx147065 		    "wpi_attach(): failed to do ddi_add_intr()\n");
    606  4128   hx147065 		goto attach_fail8;
    607  4128   hx147065 	}
    608  4128   hx147065 
    609  4128   hx147065 	/*
    610  4128   hx147065 	 * Initialize pointer to device specific functions
    611  4128   hx147065 	 */
    612  4128   hx147065 	wd.wd_secalloc = WIFI_SEC_NONE;
    613  4128   hx147065 	wd.wd_opmode = ic->ic_opmode;
    614  4128   hx147065 	IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
    615  4128   hx147065 
    616  4128   hx147065 	macp = mac_alloc(MAC_VERSION);
    617  4128   hx147065 	if (err != DDI_SUCCESS) {
    618  4128   hx147065 		cmn_err(CE_WARN,
    619  4128   hx147065 		    "wpi_attach(): failed to do mac_alloc()\n");
    620  4128   hx147065 		goto attach_fail9;
    621  4128   hx147065 	}
    622  4128   hx147065 
    623  4128   hx147065 	macp->m_type_ident	= MAC_PLUGIN_IDENT_WIFI;
    624  4128   hx147065 	macp->m_driver		= sc;
    625  4128   hx147065 	macp->m_dip		= dip;
    626  4128   hx147065 	macp->m_src_addr	= ic->ic_macaddr;
    627  4128   hx147065 	macp->m_callbacks	= &wpi_m_callbacks;
    628  4128   hx147065 	macp->m_min_sdu		= 0;
    629  4128   hx147065 	macp->m_max_sdu		= IEEE80211_MTU;
    630  4128   hx147065 	macp->m_pdata		= &wd;
    631  4128   hx147065 	macp->m_pdata_size	= sizeof (wd);
    632  4128   hx147065 
    633  4128   hx147065 	/*
    634  4128   hx147065 	 * Register the macp to mac
    635  4128   hx147065 	 */
    636  4128   hx147065 	err = mac_register(macp, &ic->ic_mach);
    637  4128   hx147065 	mac_free(macp);
    638  4128   hx147065 	if (err != DDI_SUCCESS) {
    639  4128   hx147065 		cmn_err(CE_WARN,
    640  4128   hx147065 		    "wpi_attach(): failed to do mac_register()\n");
    641  4128   hx147065 		goto attach_fail9;
    642  4128   hx147065 	}
    643  4128   hx147065 
    644  4128   hx147065 	/*
    645  4128   hx147065 	 * Create minor node of type DDI_NT_NET_WIFI
    646  4128   hx147065 	 */
    647  4128   hx147065 	(void) snprintf(strbuf, sizeof (strbuf), "wpi%d", instance);
    648  4128   hx147065 	err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
    649  4128   hx147065 	    instance + 1, DDI_NT_NET_WIFI, 0);
    650  4128   hx147065 	if (err != DDI_SUCCESS)
    651  4128   hx147065 		cmn_err(CE_WARN,
    652  4128   hx147065 		    "wpi_attach(): failed to do ddi_create_minor_node()\n");
    653  4128   hx147065 
    654  4128   hx147065 	/*
    655  4128   hx147065 	 * Notify link is down now
    656  4128   hx147065 	 */
    657  4128   hx147065 	mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
    658  4128   hx147065 
    659  4128   hx147065 	/*
    660  4128   hx147065 	 * create the mf thread to handle the link status,
    661  4128   hx147065 	 * recovery fatal error, etc.
    662  4128   hx147065 	 */
    663  4128   hx147065 
    664  4128   hx147065 	sc->sc_mf_thread_switch = 1;
    665  4128   hx147065 	if (sc->sc_mf_thread == NULL)
    666  4128   hx147065 		sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
    667  4128   hx147065 		    wpi_thread, sc, 0, &p0, TS_RUN, minclsyspri);
    668  4128   hx147065 
    669  4128   hx147065 	sc->sc_flags |= WPI_F_ATTACHED;
    670  4128   hx147065 
    671  4128   hx147065 	return (DDI_SUCCESS);
    672  4128   hx147065 attach_fail9:
    673  4128   hx147065 	ddi_remove_intr(dip, 0, sc->sc_iblk);
    674  4128   hx147065 attach_fail8:
    675  4128   hx147065 	ddi_remove_softintr(sc->sc_notif_softint_id);
    676  4128   hx147065 	sc->sc_notif_softint_id = NULL;
    677  4128   hx147065 attach_fail7:
    678  4128   hx147065 	ieee80211_detach(ic);
    679  4128   hx147065 	wpi_destroy_locks(sc);
    680  4128   hx147065 attach_fail6:
    681  4128   hx147065 	wpi_free_fw_dma(sc);
    682  4128   hx147065 attach_fail5:
    683  4128   hx147065 	wpi_ring_free(sc);
    684  4128   hx147065 attach_fail4:
    685  4128   hx147065 	wpi_free_shared(sc);
    686  4128   hx147065 attach_fail3:
    687  4128   hx147065 	ddi_regs_map_free(&sc->sc_handle);
    688  4128   hx147065 attach_fail2:
    689  4128   hx147065 	ddi_soft_state_free(wpi_soft_state_p, instance);
    690  4128   hx147065 attach_fail1:
    691  4128   hx147065 	return (err);
    692  4128   hx147065 }
    693  4128   hx147065 
    694  4128   hx147065 int
    695  4128   hx147065 wpi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    696  4128   hx147065 {
    697  4128   hx147065 	wpi_sc_t	*sc;
    698  4128   hx147065 	int err;
    699  4128   hx147065 
    700  4128   hx147065 	sc = ddi_get_soft_state(wpi_soft_state_p, ddi_get_instance(dip));
    701  4128   hx147065 	ASSERT(sc != NULL);
    702  4128   hx147065 
    703  6062   hx147065 	switch (cmd) {
    704  6062   hx147065 	case DDI_DETACH:
    705  6062   hx147065 		break;
    706  6062   hx147065 	case DDI_SUSPEND:
    707  8349  Pengcheng 		mutex_enter(&sc->sc_glock);
    708  8349  Pengcheng 		sc->sc_flags |= WPI_F_SUSPEND;
    709  8349  Pengcheng 		mutex_exit(&sc->sc_glock);
    710  8349  Pengcheng 
    711  6062   hx147065 		if (sc->sc_flags & WPI_F_RUNNING) {
    712  6062   hx147065 			wpi_stop(sc);
    713  6062   hx147065 		}
    714  8349  Pengcheng 
    715  6062   hx147065 		WPI_DBG((WPI_DEBUG_RESUME, "wpi: suspend \n"));
    716  6062   hx147065 		return (DDI_SUCCESS);
    717  6062   hx147065 	default:
    718  4128   hx147065 		return (DDI_FAILURE);
    719  6062   hx147065 	}
    720  4128   hx147065 	if (!(sc->sc_flags & WPI_F_ATTACHED))
    721  4128   hx147065 		return (DDI_FAILURE);
    722  4128   hx147065 
    723  7507    Xinghua 	err = mac_disable(sc->sc_ic.ic_mach);
    724  7507    Xinghua 	if (err != DDI_SUCCESS)
    725  7507    Xinghua 		return (err);
    726  7507    Xinghua 
    727  4128   hx147065 	/*
    728  4128   hx147065 	 * Destroy the mf_thread
    729  4128   hx147065 	 */
    730  4128   hx147065 	mutex_enter(&sc->sc_mt_lock);
    731  4128   hx147065 	sc->sc_mf_thread_switch = 0;
    732  4128   hx147065 	while (sc->sc_mf_thread != NULL) {
    733  4128   hx147065 		if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0)
    734  4128   hx147065 			break;
    735  4128   hx147065 	}
    736  4128   hx147065 	mutex_exit(&sc->sc_mt_lock);
    737  4128   hx147065 
    738  4128   hx147065 	wpi_stop(sc);
    739  4128   hx147065 
    740  4128   hx147065 	/*
    741  4128   hx147065 	 * Unregiste from the MAC layer subsystem
    742  4128   hx147065 	 */
    743  7507    Xinghua 	(void) mac_unregister(sc->sc_ic.ic_mach);
    744  4128   hx147065 
    745  4128   hx147065 	mutex_enter(&sc->sc_glock);
    746  4128   hx147065 	wpi_free_fw_dma(sc);
    747  4128   hx147065 	wpi_ring_free(sc);
    748  4128   hx147065 	wpi_free_shared(sc);
    749  4128   hx147065 	mutex_exit(&sc->sc_glock);
    750  4128   hx147065 
    751  4128   hx147065 	ddi_remove_intr(dip, 0, sc->sc_iblk);
    752  4128   hx147065 	ddi_remove_softintr(sc->sc_notif_softint_id);
    753  4128   hx147065 	sc->sc_notif_softint_id = NULL;
    754  4128   hx147065 
    755  4128   hx147065 	/*
    756  4128   hx147065 	 * detach ieee80211
    757  4128   hx147065 	 */
    758  4128   hx147065 	ieee80211_detach(&sc->sc_ic);
    759  4128   hx147065 
    760  4128   hx147065 	wpi_destroy_locks(sc);
    761  4128   hx147065 
    762  4128   hx147065 	ddi_regs_map_free(&sc->sc_handle);
    763  4128   hx147065 	ddi_remove_minor_node(dip, NULL);
    764  4128   hx147065 	ddi_soft_state_free(wpi_soft_state_p, ddi_get_instance(dip));
    765  4128   hx147065 
    766  4128   hx147065 	return (DDI_SUCCESS);
    767  4128   hx147065 }
    768  4128   hx147065 
    769  4128   hx147065 static void
    770  4128   hx147065 wpi_destroy_locks(wpi_sc_t *sc)
    771  4128   hx147065 {
    772  4128   hx147065 	cv_destroy(&sc->sc_mt_cv);
    773  4128   hx147065 	mutex_destroy(&sc->sc_mt_lock);
    774  4128   hx147065 	cv_destroy(&sc->sc_cmd_cv);
    775  4128   hx147065 	cv_destroy(&sc->sc_fw_cv);
    776  4128   hx147065 	mutex_destroy(&sc->sc_tx_lock);
    777  4128   hx147065 	mutex_destroy(&sc->sc_glock);
    778  4128   hx147065 }
    779  4128   hx147065 
    780  4128   hx147065 /*
    781  4128   hx147065  * Allocate an area of memory and a DMA handle for accessing it
    782  4128   hx147065  */
    783  4128   hx147065 static int
    784  4128   hx147065 wpi_alloc_dma_mem(wpi_sc_t *sc, size_t memsize, ddi_dma_attr_t *dma_attr_p,
    785  4128   hx147065 	ddi_device_acc_attr_t *acc_attr_p, uint_t dma_flags, wpi_dma_t *dma_p)
    786  4128   hx147065 {
    787  4128   hx147065 	caddr_t vaddr;
    788  4128   hx147065 	int err;
    789  4128   hx147065 
    790  4128   hx147065 	/*
    791  4128   hx147065 	 * Allocate handle
    792  4128   hx147065 	 */
    793  4128   hx147065 	err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p,
    794  4499   hx147065 	    DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
    795  4128   hx147065 	if (err != DDI_SUCCESS) {
    796  4128   hx147065 		dma_p->dma_hdl = NULL;
    797  4128   hx147065 		return (DDI_FAILURE);
    798  4128   hx147065 	}
    799  4128   hx147065 
    800  4128   hx147065 	/*
    801  4128   hx147065 	 * Allocate memory
    802  4128   hx147065 	 */
    803  4128   hx147065 	err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
    804  4128   hx147065 	    dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
    805  4128   hx147065 	    DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
    806  4128   hx147065 	if (err != DDI_SUCCESS) {
    807  4128   hx147065 		ddi_dma_free_handle(&dma_p->dma_hdl);
    808  4128   hx147065 		dma_p->dma_hdl = NULL;
    809  4128   hx147065 		dma_p->acc_hdl = NULL;
    810  4128   hx147065 		return (DDI_FAILURE);
    811  4128   hx147065 	}
    812  4128   hx147065 
    813  4128   hx147065 	/*
    814  4128   hx147065 	 * Bind the two together
    815  4128   hx147065 	 */
    816  4128   hx147065 	dma_p->mem_va = vaddr;
    817  4128   hx147065 	err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
    818  4128   hx147065 	    vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
    819  4128   hx147065 	    &dma_p->cookie, &dma_p->ncookies);
    820  4128   hx147065 	if (err != DDI_DMA_MAPPED) {
    821  4128   hx147065 		ddi_dma_mem_free(&dma_p->acc_hdl);
    822  4128   hx147065 		ddi_dma_free_handle(&dma_p->dma_hdl);
    823  4128   hx147065 		dma_p->acc_hdl = NULL;
    824  4128   hx147065 		dma_p->dma_hdl = NULL;
    825  4128   hx147065 		return (DDI_FAILURE);
    826  4128   hx147065 	}
    827  4128   hx147065 
    828  4128   hx147065 	dma_p->nslots = ~0U;
    829  4128   hx147065 	dma_p->size = ~0U;
    830  4128   hx147065 	dma_p->token = ~0U;
    831  4128   hx147065 	dma_p->offset = 0;
    832  4128   hx147065 	return (DDI_SUCCESS);
    833  4128   hx147065 }
    834  4128   hx147065 
    835  4128   hx147065 /*
    836  4128   hx147065  * Free one allocated area of DMAable memory
    837  4128   hx147065  */
    838  4128   hx147065 static void
    839  4128   hx147065 wpi_free_dma_mem(wpi_dma_t *dma_p)
    840  4128   hx147065 {
    841  4128   hx147065 	if (dma_p->dma_hdl != NULL) {
    842  4128   hx147065 		if (dma_p->ncookies) {
    843  4128   hx147065 			(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
    844  4128   hx147065 			dma_p->ncookies = 0;
    845  4128   hx147065 		}
    846  4128   hx147065 		ddi_dma_free_handle(&dma_p->dma_hdl);
    847  4128   hx147065 		dma_p->dma_hdl = NULL;
    848  4128   hx147065 	}
    849  4128   hx147065 
    850  4128   hx147065 	if (dma_p->acc_hdl != NULL) {
    851  4128   hx147065 		ddi_dma_mem_free(&dma_p->acc_hdl);
    852  4128   hx147065 		dma_p->acc_hdl = NULL;
    853  4128   hx147065 	}
    854  4128   hx147065 }
    855  4128   hx147065 
    856  4128   hx147065 /*
    857  4128   hx147065  * Allocate an area of dma memory for firmware load.
    858  4128   hx147065  * Idealy, this allocation should be a one time action, that is,
    859  4128   hx147065  * the memory will be freed after the firmware is uploaded to the
    860  4128   hx147065  * card. but since a recovery mechanism for the fatal firmware need
    861  4128   hx147065  * reload the firmware, and re-allocate dma at run time may be failed,
    862  4128   hx147065  * so we allocate it at attach and keep it in the whole lifecycle of
    863  4128   hx147065  * the driver.
    864  4128   hx147065  */
    865  4128   hx147065 static int
    866  4128   hx147065 wpi_alloc_fw_dma(wpi_sc_t *sc)
    867  4128   hx147065 {
    868  4128   hx147065 	int i, err = DDI_SUCCESS;
    869  4128   hx147065 	wpi_dma_t *dma_p;
    870  4128   hx147065 
    871  4128   hx147065 	err = wpi_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz),
    872  4128   hx147065 	    &fw_buffer_dma_attr, &wpi_dma_accattr,
    873  4128   hx147065 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
    874  4128   hx147065 	    &sc->sc_dma_fw_text);
    875  4128   hx147065 	dma_p = &sc->sc_dma_fw_text;
    876  4128   hx147065 	WPI_DBG((WPI_DEBUG_DMA, "ncookies:%d addr1:%x size1:%x\n",
    877  4128   hx147065 	    dma_p->ncookies, dma_p->cookie.dmac_address,
    878  4128   hx147065 	    dma_p->cookie.dmac_size));
    879  4128   hx147065 	if (err != DDI_SUCCESS) {
    880  4128   hx147065 		cmn_err(CE_WARN, "wpi_alloc_fw_dma(): failed to alloc"
    881  4128   hx147065 		    "text dma memory");
    882  4128   hx147065 		goto fail;
    883  4128   hx147065 	}
    884  4128   hx147065 	for (i = 0; i < dma_p->ncookies; i++) {
    885  4128   hx147065 		sc->sc_fw_text_cookie[i] = dma_p->cookie;
    886  4128   hx147065 		ddi_dma_nextcookie(dma_p->dma_hdl, &dma_p->cookie);
    887  4128   hx147065 	}
    888  4128   hx147065 	err = wpi_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
    889  4128   hx147065 	    &fw_buffer_dma_attr, &wpi_dma_accattr,
    890  4128   hx147065 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
    891  4128   hx147065 	    &sc->sc_dma_fw_data);
    892  4128   hx147065 	dma_p = &sc->sc_dma_fw_data;
    893  4128   hx147065 	WPI_DBG((WPI_DEBUG_DMA, "ncookies:%d addr1:%x size1:%x\n",
    894  4128   hx147065 	    dma_p->ncookies, dma_p->cookie.dmac_address,
    895  4128   hx147065 	    dma_p->cookie.dmac_size));
    896  4128   hx147065 	if (err != DDI_SUCCESS) {
    897  4128   hx147065 		cmn_err(CE_WARN, "wpi_alloc_fw_dma(): failed to alloc"
    898  4128   hx147065 		    "data dma memory");
    899  4128   hx147065 		goto fail;
    900  4128   hx147065 	}
    901  4128   hx147065 	for (i = 0; i < dma_p->ncookies; i++) {
    902  4128   hx147065 		sc->sc_fw_data_cookie[i] = dma_p->cookie;
    903  4128   hx147065 		ddi_dma_nextcookie(dma_p->dma_hdl, &dma_p->cookie);
    904  4128   hx147065 	}
    905  4128   hx147065 fail:
    906  4128   hx147065 	return (err);
    907  4128   hx147065 }
    908  4128   hx147065 
    909  4128   hx147065 static void
    910  4128   hx147065 wpi_free_fw_dma(wpi_sc_t *sc)
    911  4128   hx147065 {
    912  4128   hx147065 	wpi_free_dma_mem(&sc->sc_dma_fw_text);
    913  4128   hx147065 	wpi_free_dma_mem(&sc->sc_dma_fw_data);
    914  4128   hx147065 }
    915  4128   hx147065 
    916  4128   hx147065 /*
    917  4128   hx147065  * Allocate a shared page between host and NIC.
    918  4128   hx147065  */
    919  4128   hx147065 static int
    920  4128   hx147065 wpi_alloc_shared(wpi_sc_t *sc)
    921  4128   hx147065 {
    922  4128   hx147065 	int err = DDI_SUCCESS;
    923  4128   hx147065 
    924  4128   hx147065 	/* must be aligned on a 4K-page boundary */
    925  4128   hx147065 	err = wpi_alloc_dma_mem(sc, sizeof (wpi_shared_t),
    926  4128   hx147065 	    &sh_dma_attr, &wpi_dma_accattr,
    927  4128   hx147065 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
    928  4128   hx147065 	    &sc->sc_dma_sh);
    929  4128   hx147065 	if (err != DDI_SUCCESS)
    930  4128   hx147065 		goto fail;
    931  4128   hx147065 	sc->sc_shared = (wpi_shared_t *)sc->sc_dma_sh.mem_va;
    932  4128   hx147065 	return (err);
    933  4128   hx147065 
    934  4128   hx147065 fail:
    935  4128   hx147065 	wpi_free_shared(sc);
    936  4128   hx147065 	return (err);
    937  4128   hx147065 }
    938  4128   hx147065 
    939  4128   hx147065 static void
    940  4128   hx147065 wpi_free_shared(wpi_sc_t *sc)
    941  4128   hx147065 {
    942  4128   hx147065 	wpi_free_dma_mem(&sc->sc_dma_sh);
    943  4128   hx147065 }
    944  4128   hx147065 
    945  4128   hx147065 static int
    946  4128   hx147065 wpi_alloc_rx_ring(wpi_sc_t *sc)
    947  4128   hx147065 {
    948  4128   hx147065 	wpi_rx_ring_t *ring;
    949  4128   hx147065 	wpi_rx_data_t *data;
    950  4128   hx147065 	int i, err = DDI_SUCCESS;
    951  4128   hx147065 
    952  4128   hx147065 	ring = &sc->sc_rxq;
    953  4128   hx147065 	ring->cur = 0;
    954  4128   hx147065 
    955  4128   hx147065 	err = wpi_alloc_dma_mem(sc, WPI_RX_RING_COUNT * sizeof (uint32_t),
    956  4128   hx147065 	    &ring_desc_dma_attr, &wpi_dma_accattr,
    957  4128   hx147065 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
    958  4128   hx147065 	    &ring->dma_desc);
    959  4128   hx147065 	if (err != DDI_SUCCESS) {
    960  4128   hx147065 		WPI_DBG((WPI_DEBUG_DMA, "dma alloc rx ring desc failed\n"));
    961  4128   hx147065 		goto fail;
    962  4128   hx147065 	}
    963  4128   hx147065 	ring->desc = (uint32_t *)ring->dma_desc.mem_va;
    964  4128   hx147065 
    965  4128   hx147065 	/*
    966  4128   hx147065 	 * Allocate Rx buffers.
    967  4128   hx147065 	 */
    968  4128   hx147065 	for (i = 0; i < WPI_RX_RING_COUNT; i++) {
    969  4128   hx147065 		data = &ring->data[i];
    970  4128   hx147065 		err = wpi_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
    971  4128   hx147065 		    &rx_buffer_dma_attr, &wpi_dma_accattr,
    972  4128   hx147065 		    DDI_DMA_READ | DDI_DMA_STREAMING,
    973  4128   hx147065 		    &data->dma_data);
    974  4128   hx147065 		if (err != DDI_SUCCESS) {
    975  4128   hx147065 			WPI_DBG((WPI_DEBUG_DMA, "dma alloc rx ring buf[%d] "
    976  4128   hx147065 			    "failed\n", i));
    977  4128   hx147065 			goto fail;
    978  4128   hx147065 		}
    979  4128   hx147065 
    980  4128   hx147065 		ring->desc[i] = LE_32(data->dma_data.cookie.dmac_address);
    981  4128   hx147065 	}
    982  4128   hx147065 
    983  4128   hx147065 	WPI_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
    984  4128   hx147065 
    985  4128   hx147065 	return (err);
    986  4128   hx147065 
    987  4128   hx147065 fail:
    988  4128   hx147065 	wpi_free_rx_ring(sc);
    989  4128   hx147065 	return (err);
    990  4128   hx147065 }
    991  4128   hx147065 
    992  4128   hx147065 static void
    993  4128   hx147065 wpi_reset_rx_ring(wpi_sc_t *sc)
    994  4128   hx147065 {
    995  4128   hx147065 	int ntries;
    996  4128   hx147065 
    997  4128   hx147065 	wpi_mem_lock(sc);
    998  4128   hx147065 
    999  4128   hx147065 	WPI_WRITE(sc, WPI_RX_CONFIG, 0);
   1000  4128   hx147065 	for (ntries = 0; ntries < 2000; ntries++) {
   1001  4128   hx147065 		if (WPI_READ(sc, WPI_RX_STATUS) & WPI_RX_IDLE)
   1002  4128   hx147065 			break;
   1003  4128   hx147065 		DELAY(1000);
   1004  4128   hx147065 	}
   1005  4128   hx147065 	if (ntries == 2000)
   1006  4128   hx147065 		WPI_DBG((WPI_DEBUG_DMA, "timeout resetting Rx ring\n"));
   1007  7865  Pengcheng 
   1008  4128   hx147065 	wpi_mem_unlock(sc);
   1009  4128   hx147065 
   1010  4128   hx147065 	sc->sc_rxq.cur = 0;
   1011  4128   hx147065 }
   1012  4128   hx147065 
   1013  4128   hx147065 static void
   1014  4128   hx147065 wpi_free_rx_ring(wpi_sc_t *sc)
   1015  4128   hx147065 {
   1016  4128   hx147065 	int i;
   1017  4128   hx147065 
   1018  4128   hx147065 	for (i = 0; i < WPI_RX_RING_COUNT; i++) {
   1019  4128   hx147065 		if (sc->sc_rxq.data[i].dma_data.dma_hdl)
   1020  4128   hx147065 			WPI_DMA_SYNC(sc->sc_rxq.data[i].dma_data,
   1021  4128   hx147065 			    DDI_DMA_SYNC_FORCPU);
   1022  4128   hx147065 		wpi_free_dma_mem(&sc->sc_rxq.data[i].dma_data);
   1023  4128   hx147065 	}
   1024  4128   hx147065 
   1025  4128   hx147065 	if (sc->sc_rxq.dma_desc.dma_hdl)
   1026  4128   hx147065 		WPI_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV);
   1027  4128   hx147065 	wpi_free_dma_mem(&sc->sc_rxq.dma_desc);
   1028  4128   hx147065 }
   1029  4128   hx147065 
   1030  4128   hx147065 static int
   1031  4128   hx147065 wpi_alloc_tx_ring(wpi_sc_t *sc, wpi_tx_ring_t *ring, int count, int qid)
   1032  4128   hx147065 {
   1033  4128   hx147065 	wpi_tx_data_t *data;
   1034  4128   hx147065 	wpi_tx_desc_t *desc_h;
   1035  4128   hx147065 	uint32_t paddr_desc_h;
   1036  4128   hx147065 	wpi_tx_cmd_t *cmd_h;
   1037  4128   hx147065 	uint32_t paddr_cmd_h;
   1038  4128   hx147065 	int i, err = DDI_SUCCESS;
   1039  4128   hx147065 
   1040  4128   hx147065 	ring->qid = qid;
   1041  4128   hx147065 	ring->count = count;
   1042  4128   hx147065 	ring->queued = 0;
   1043  4128   hx147065 	ring->cur = 0;
   1044  4128   hx147065 
   1045  4128   hx147065 	err = wpi_alloc_dma_mem(sc, count * sizeof (wpi_tx_desc_t),
   1046  4128   hx147065 	    &ring_desc_dma_attr, &wpi_dma_accattr,
   1047  4128   hx147065 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
   1048  4128   hx147065 	    &ring->dma_desc);
   1049  4128   hx147065 	if (err != DDI_SUCCESS) {
   1050  4128   hx147065 		WPI_DBG((WPI_DEBUG_DMA, "dma alloc tx ring desc[%d] failed\n",
   1051  4128   hx147065 		    qid));
   1052  4128   hx147065 		goto fail;
   1053  4128   hx147065 	}
   1054  4128   hx147065 
   1055  4128   hx147065 	/* update shared page with ring's base address */
   1056  4128   hx147065 	sc->sc_shared->txbase[qid] = ring->dma_desc.cookie.dmac_address;
   1057  4128   hx147065 
   1058  4128   hx147065 	desc_h = (wpi_tx_desc_t *)ring->dma_desc.mem_va;
   1059  4128   hx147065 	paddr_desc_h = ring->dma_desc.cookie.dmac_address;
   1060  4128   hx147065 
   1061  4128   hx147065 	err = wpi_alloc_dma_mem(sc, count * sizeof (wpi_tx_cmd_t),
   1062  4128   hx147065 	    &tx_cmd_dma_attr, &wpi_dma_accattr,
   1063  4128   hx147065 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
   1064  4128   hx147065 	    &ring->dma_cmd);
   1065  4128   hx147065 	if (err != DDI_SUCCESS) {
   1066  4128   hx147065 		WPI_DBG((WPI_DEBUG_DMA, "dma alloc tx ring cmd[%d] failed\n",
   1067  4128   hx147065 		    qid));
   1068  4128   hx147065 		goto fail;
   1069  4128   hx147065 	}
   1070  4128   hx147065 
   1071  4128   hx147065 	cmd_h = (wpi_tx_cmd_t *)ring->dma_cmd.mem_va;
   1072  4128   hx147065 	paddr_cmd_h = ring->dma_cmd.cookie.dmac_address;
   1073  4128   hx147065 
   1074  4128   hx147065 	/*
   1075  4128   hx147065 	 * Allocate Tx buffers.
   1076  4128   hx147065 	 */
   1077  4128   hx147065 	ring->data = kmem_zalloc(sizeof (wpi_tx_data_t) * count, KM_NOSLEEP);
   1078  4128   hx147065 	if (ring->data == NULL) {
   1079  4128   hx147065 		WPI_DBG((WPI_DEBUG_DMA, "could not allocate tx data slots\n"));
   1080  4128   hx147065 		goto fail;
   1081  4128   hx147065 	}
   1082  4128   hx147065 
   1083  4128   hx147065 	for (i = 0; i < count; i++) {
   1084  4128   hx147065 		data = &ring->data[i];
   1085  4128   hx147065 		err = wpi_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
   1086  4128   hx147065 		    &tx_buffer_dma_attr, &wpi_dma_accattr,
   1087  4128   hx147065 		    DDI_DMA_WRITE | DDI_DMA_STREAMING,
   1088  4128   hx147065 		    &data->dma_data);
   1089  4128   hx147065 		if (err != DDI_SUCCESS) {
   1090  4128   hx147065 			WPI_DBG((WPI_DEBUG_DMA, "dma alloc tx ring buf[%d] "
   1091  4128   hx147065 			    "failed\n", i));
   1092  4128   hx147065 			goto fail;
   1093  4128   hx147065 		}
   1094  4128   hx147065 
   1095  4128   hx147065 		data->desc = desc_h + i;
   1096  4128   hx147065 		data->paddr_desc = paddr_desc_h +
   1097  6990    gd78059 		    ((uintptr_t)data->desc - (uintptr_t)desc_h);
   1098  4128   hx147065 		data->cmd = cmd_h + i;
   1099  4128   hx147065 		data->paddr_cmd = paddr_cmd_h +
   1100  6990    gd78059 		    ((uintptr_t)data->cmd - (uintptr_t)cmd_h);
   1101  4128   hx147065 	}
   1102  4128   hx147065 
   1103  4128   hx147065 	return (err);
   1104  4128   hx147065 
   1105  4128   hx147065 fail:
   1106  4128   hx147065 	wpi_free_tx_ring(sc, ring);
   1107  4128   hx147065 	return (err);
   1108  4128   hx147065 }
   1109  4128   hx147065 
   1110  4128   hx147065 static void
   1111  4128   hx147065 wpi_reset_tx_ring(wpi_sc_t *sc, wpi_tx_ring_t *ring)
   1112  4128   hx147065 {
   1113  4128   hx147065 	wpi_tx_data_t *data;
   1114  4128   hx147065 	int i, ntries;
   1115  4128   hx147065 
   1116  4128   hx147065 	wpi_mem_lock(sc);
   1117  4128   hx147065 
   1118  4128   hx147065 	WPI_WRITE(sc, WPI_TX_CONFIG(ring->qid), 0);
   1119  4128   hx147065 	for (ntries = 0; ntries < 100; ntries++) {
   1120  4128   hx147065 		if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(ring->qid))
   1121  4128   hx147065 			break;
   1122  4128   hx147065 		DELAY(10);
   1123  4128   hx147065 	}
   1124  4128   hx147065 #ifdef DEBUG
   1125  4128   hx147065 	if (ntries == 100 && wpi_dbg_flags > 0) {
   1126  4128   hx147065 		WPI_DBG((WPI_DEBUG_DMA, "timeout resetting Tx ring %d\n",
   1127  4128   hx147065 		    ring->qid));
   1128  4128   hx147065 	}
   1129  4128   hx147065 #endif
   1130  4128   hx147065 	wpi_mem_unlock(sc);
   1131  4128   hx147065 
   1132  8165        Fei 	if (!(sc->sc_flags & WPI_F_QUIESCED)) {
   1133  8165        Fei 		for (i = 0; i < ring->count; i++) {
   1134  8165        Fei 			data = &ring->data[i];
   1135  8165        Fei 			WPI_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
   1136  8165        Fei 		}
   1137  4128   hx147065 	}
   1138  4128   hx147065 
   1139  4128   hx147065 	ring->queued = 0;
   1140  4128   hx147065 	ring->cur = 0;
   1141  4128   hx147065 }
   1142  4128   hx147065 
   1143  4128   hx147065 /*ARGSUSED*/
   1144  4128   hx147065 static void
   1145  4128   hx147065 wpi_free_tx_ring(wpi_sc_t *sc, wpi_tx_ring_t *ring)
   1146  4128   hx147065 {
   1147  4128   hx147065 	int i;
   1148  4128   hx147065 
   1149  4128   hx147065 	if (ring->dma_desc.dma_hdl != NULL)
   1150  4128   hx147065 		WPI_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
   1151  4128   hx147065 	wpi_free_dma_mem(&ring->dma_desc);
   1152  4128   hx147065 
   1153  4128   hx147065 	if (ring->dma_cmd.dma_hdl != NULL)
   1154  4128   hx147065 		WPI_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV);
   1155  4128   hx147065 	wpi_free_dma_mem(&ring->dma_cmd);
   1156  4128   hx147065 
   1157  4128   hx147065 	if (ring->data != NULL) {
   1158  4128   hx147065 		for (i = 0; i < ring->count; i++) {
   1159  4128   hx147065 			if (ring->data[i].dma_data.dma_hdl)
   1160  4128   hx147065 				WPI_DMA_SYNC(ring->data[i].dma_data,
   1161  4128   hx147065 				    DDI_DMA_SYNC_FORDEV);
   1162  4128   hx147065 			wpi_free_dma_mem(&ring->data[i].dma_data);
   1163  4128   hx147065 		}
   1164  4128   hx147065 		kmem_free(ring->data, ring->count * sizeof (wpi_tx_data_t));
   1165  7865  Pengcheng 		ring->data = NULL;
   1166  4128   hx147065 	}
   1167  4128   hx147065 }
   1168  4128   hx147065 
   1169  4128   hx147065 static int
   1170  4128   hx147065 wpi_ring_init(wpi_sc_t *sc)
   1171  4128   hx147065 {
   1172  4128   hx147065 	int i, err = DDI_SUCCESS;
   1173  4128   hx147065 
   1174  4128   hx147065 	for (i = 0; i < 4; i++) {
   1175  4128   hx147065 		err = wpi_alloc_tx_ring(sc, &sc->sc_txq[i], WPI_TX_RING_COUNT,
   1176  4128   hx147065 		    i);
   1177  4128   hx147065 		if (err != DDI_SUCCESS)
   1178  4128   hx147065 			goto fail;
   1179  4128   hx147065 	}
   1180  4128   hx147065 	err = wpi_alloc_tx_ring(sc, &sc->sc_cmdq, WPI_CMD_RING_COUNT, 4);
   1181  4128   hx147065 	if (err != DDI_SUCCESS)
   1182  4128   hx147065 		goto fail;
   1183  4128   hx147065 	err = wpi_alloc_tx_ring(sc, &sc->sc_svcq, WPI_SVC_RING_COUNT, 5);
   1184  4128   hx147065 	if (err != DDI_SUCCESS)
   1185  4128   hx147065 		goto fail;
   1186  4128   hx147065 	err = wpi_alloc_rx_ring(sc);
   1187  4128   hx147065 	if (err != DDI_SUCCESS)
   1188  4128   hx147065 		goto fail;
   1189  4128   hx147065 	return (err);
   1190  4128   hx147065 
   1191  4128   hx147065 fail:
   1192  4128   hx147065 	return (err);
   1193  4128   hx147065 }
   1194  4128   hx147065 
   1195  4128   hx147065 static void
   1196  4128   hx147065 wpi_ring_free(wpi_sc_t *sc)
   1197  4128   hx147065 {
   1198  4128   hx147065 	int i = 4;
   1199  4128   hx147065 
   1200  4128   hx147065 	wpi_free_rx_ring(sc);
   1201  4128   hx147065 	wpi_free_tx_ring(sc, &sc->sc_svcq);
   1202  4128   hx147065 	wpi_free_tx_ring(sc, &sc->sc_cmdq);
   1203  4128   hx147065 	while (--i >= 0) {
   1204  4128   hx147065 		wpi_free_tx_ring(sc, &sc->sc_txq[i]);
   1205  4128   hx147065 	}
   1206  4128   hx147065 }
   1207  4128   hx147065 
   1208  4128   hx147065 /* ARGSUSED */
   1209  4128   hx147065 static ieee80211_node_t *
   1210  4128   hx147065 wpi_node_alloc(ieee80211com_t *ic)
   1211  4128   hx147065 {
   1212  4128   hx147065 	wpi_amrr_t *amrr;
   1213  4128   hx147065 
   1214  4128   hx147065 	amrr = kmem_zalloc(sizeof (wpi_amrr_t), KM_SLEEP);
   1215  4128   hx147065 	if (amrr != NULL)
   1216  4128   hx147065 		wpi_amrr_init(amrr);
   1217  4128   hx147065 	return (&amrr->in);
   1218  4128   hx147065 }
   1219  4128   hx147065 
   1220  4128   hx147065 static void
   1221  4128   hx147065 wpi_node_free(ieee80211_node_t *in)
   1222  4128   hx147065 {
   1223  4128   hx147065 	ieee80211com_t *ic = in->in_ic;
   1224  4128   hx147065 
   1225  4128   hx147065 	ic->ic_node_cleanup(in);
   1226  5296   zf162725 	if (in->in_wpa_ie != NULL)
   1227  5296   zf162725 		ieee80211_free(in->in_wpa_ie);
   1228  4128   hx147065 	kmem_free(in, sizeof (wpi_amrr_t));
   1229  4128   hx147065 }
   1230  4128   hx147065 
   1231  4128   hx147065 /*ARGSUSED*/
   1232  4128   hx147065 static int
   1233  4128   hx147065 wpi_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
   1234  4128   hx147065 {
   1235  4128   hx147065 	wpi_sc_t *sc = (wpi_sc_t *)ic;
   1236  4128   hx147065 	ieee80211_node_t *in = ic->ic_bss;
   1237  5453   hx147065 	enum ieee80211_state ostate;
   1238  4128   hx147065 	int i, err = WPI_SUCCESS;
   1239  4128   hx147065 
   1240  4128   hx147065 	mutex_enter(&sc->sc_glock);
   1241  7865  Pengcheng 	ostate = ic->ic_state;
   1242  4128   hx147065 	switch (nstate) {
   1243  4128   hx147065 	case IEEE80211_S_SCAN:
   1244  5453   hx147065 		switch (ostate) {
   1245  5453   hx147065 		case IEEE80211_S_INIT:
   1246  7865  Pengcheng 		{
   1247  7865  Pengcheng 			wpi_node_t node;
   1248  7865  Pengcheng 
   1249  7865  Pengcheng 			sc->sc_flags |= WPI_F_SCANNING;
   1250  7865  Pengcheng 			sc->sc_scan_next = 0;
   1251  7865  Pengcheng 
   1252  5453   hx147065 			/* make the link LED blink while we're scanning */
   1253  5453   hx147065 			wpi_set_led(sc, WPI_LED_LINK, 20, 2);
   1254  4128   hx147065 
   1255  7865  Pengcheng 			/*
   1256  7865  Pengcheng 			 * clear association to receive beacons from all
   1257  7865  Pengcheng 			 * BSS'es
   1258  7865  Pengcheng 			 */
   1259  7865  Pengcheng 			sc->sc_config.state = 0;
   1260  7865  Pengcheng 			sc->sc_config.filter &= ~LE_32(WPI_FILTER_BSS);
   1261  7865  Pengcheng 
   1262  7865  Pengcheng 			WPI_DBG((WPI_DEBUG_80211, "config chan %d flags %x "
   1263  7865  Pengcheng 			    "filter %x\n",
   1264  7865  Pengcheng 			    sc->sc_config.chan, sc->sc_config.flags,
   1265  7865  Pengcheng 			    sc->sc_config.filter));
   1266  7865  Pengcheng 
   1267  7865  Pengcheng 			err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
   1268  7865  Pengcheng 			    sizeof (wpi_config_t), 1);
   1269  7865  Pengcheng 			if (err != WPI_SUCCESS) {
   1270  7865  Pengcheng 				cmn_err(CE_WARN,
   1271  7865  Pengcheng 				    "could not clear association\n");
   1272  7865  Pengcheng 				sc->sc_flags &= ~WPI_F_SCANNING;
   1273  7865  Pengcheng 				mutex_exit(&sc->sc_glock);
   1274  7865  Pengcheng 				return (err);
   1275  7865  Pengcheng 			}
   1276  7865  Pengcheng 
   1277  7865  Pengcheng 			/* add broadcast node to send probe request */
   1278  7865  Pengcheng 			(void) memset(&node, 0, sizeof (node));
   1279  7865  Pengcheng 			(void) memset(&node.bssid, 0xff, IEEE80211_ADDR_LEN);
   1280  7865  Pengcheng 			node.id = WPI_ID_BROADCAST;
   1281  7865  Pengcheng 
   1282  7865  Pengcheng 			err = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node,
   1283  7865  Pengcheng 			    sizeof (node), 1);
   1284  7865  Pengcheng 			if (err != WPI_SUCCESS) {
   1285  7865  Pengcheng 				cmn_err(CE_WARN,
   1286  7865  Pengcheng 				    "could not add broadcast node\n");
   1287  7865  Pengcheng 				sc->sc_flags &= ~WPI_F_SCANNING;
   1288  5453   hx147065 				mutex_exit(&sc->sc_glock);
   1289  5453   hx147065 				return (err);
   1290  5453   hx147065 			}
   1291  5453   hx147065 			break;
   1292  4128   hx147065 		}
   1293  7865  Pengcheng 		case IEEE80211_S_SCAN:
   1294  7865  Pengcheng 			mutex_exit(&sc->sc_glock);
   1295  7865  Pengcheng 			/* step to next channel before actual FW scan */
   1296  7865  Pengcheng 			err = sc->sc_newstate(ic, nstate, arg);
   1297  7865  Pengcheng 			mutex_enter(&sc->sc_glock);
   1298  7865  Pengcheng 			if ((err != 0) || ((err = wpi_scan(sc)) != 0)) {
   1299  7865  Pengcheng 				cmn_err(CE_WARN,
   1300  7865  Pengcheng 				    "could not initiate scan\n");
   1301  7865  Pengcheng 				sc->sc_flags &= ~WPI_F_SCANNING;
   1302  7865  Pengcheng 				ieee80211_cancel_scan(ic);
   1303  7865  Pengcheng 			}
   1304  7865  Pengcheng 			mutex_exit(&sc->sc_glock);
   1305  7865  Pengcheng 			return (err);
   1306  7865  Pengcheng 		default:
   1307  7865  Pengcheng 			break;
   1308  7865  Pengcheng 		}
   1309  4128   hx147065 		sc->sc_clk = 0;
   1310  7865  Pengcheng 		break;
   1311  4128   hx147065 
   1312  4128   hx147065 	case IEEE80211_S_AUTH:
   1313  7865  Pengcheng 		if (ostate == IEEE80211_S_SCAN) {
   1314  7865  Pengcheng 			sc->sc_flags &= ~WPI_F_SCANNING;
   1315  7865  Pengcheng 		}
   1316  7865  Pengcheng 
   1317  4128   hx147065 		/* reset state to handle reassociations correctly */
   1318  4128   hx147065 		sc->sc_config.state = 0;
   1319  4128   hx147065 		sc->sc_config.filter &= ~LE_32(WPI_FILTER_BSS);
   1320  4128   hx147065 
   1321  4128   hx147065 		if ((err = wpi_auth(sc)) != 0) {
   1322  4128   hx147065 			WPI_DBG((WPI_DEBUG_80211,
   1323  4128   hx147065 			    "could not send authentication request\n"));
   1324  4128   hx147065 			mutex_exit(&sc->sc_glock);
   1325  4128   hx147065 			return (err);
   1326  4128   hx147065 		}
   1327  4128   hx147065 		break;
   1328  4128   hx147065 
   1329  4128   hx147065 	case IEEE80211_S_RUN:
   1330  7865  Pengcheng 		if (ostate == IEEE80211_S_SCAN) {
   1331  7865  Pengcheng 			sc->sc_flags &= ~WPI_F_SCANNING;
   1332  7865  Pengcheng 		}
   1333  7865  Pengcheng 
   1334  4128   hx147065 		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
   1335  4128   hx147065 			/* link LED blinks while monitoring */
   1336  4128   hx147065 			wpi_set_led(sc, WPI_LED_LINK, 5, 5);
   1337  4128   hx147065 			break;
   1338  4128   hx147065 		}
   1339  4128   hx147065 
   1340  4128   hx147065 		if (ic->ic_opmode != IEEE80211_M_STA) {
   1341  4128   hx147065 			(void) wpi_auth(sc);
   1342  4128   hx147065 			/* need setup beacon here */
   1343  4128   hx147065 		}
   1344  4128   hx147065 		WPI_DBG((WPI_DEBUG_80211, "wpi: associated."));
   1345  4128   hx147065 
   1346  4128   hx147065 		/* update adapter's configuration */
   1347  4128   hx147065 		sc->sc_config.state = LE_16(WPI_CONFIG_ASSOCIATED);
   1348  4128   hx147065 		/* short preamble/slot time are negotiated when associating */
   1349  4128   hx147065 		sc->sc_config.flags &= ~LE_32(WPI_CONFIG_SHPREAMBLE |
   1350  4128   hx147065 		    WPI_CONFIG_SHSLOT);
   1351  4128   hx147065 		if (ic->ic_flags & IEEE80211_F_SHSLOT)
   1352  4128   hx147065 			sc->sc_config.flags |= LE_32(WPI_CONFIG_SHSLOT);
   1353  4128   hx147065 		if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
   1354  4128   hx147065 			sc->sc_config.flags |= LE_32(WPI_CONFIG_SHPREAMBLE);
   1355  4128   hx147065 		sc->sc_config.filter |= LE_32(WPI_FILTER_BSS);
   1356  4128   hx147065 		if (ic->ic_opmode != IEEE80211_M_STA)
   1357  4128   hx147065 			sc->sc_config.filter |= LE_32(WPI_FILTER_BEACON);
   1358  4128   hx147065 
   1359  4128   hx147065 		WPI_DBG((WPI_DEBUG_80211, "config chan %d flags %x\n",
   1360  4128   hx147065 		    sc->sc_config.chan, sc->sc_config.flags));
   1361  4128   hx147065 		err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
   1362  4128   hx147065 		    sizeof (wpi_config_t), 1);
   1363  4128   hx147065 		if (err != WPI_SUCCESS) {
   1364  4128   hx147065 			WPI_DBG((WPI_DEBUG_80211,
   1365  4128   hx147065 			    "could not update configuration\n"));
   1366  4128   hx147065 			mutex_exit(&sc->sc_glock);
   1367  4128   hx147065 			return (err);
   1368  4128   hx147065 		}
   1369  4128   hx147065 
   1370  4128   hx147065 		/* start automatic rate control */
   1371  4128   hx147065 		mutex_enter(&sc->sc_mt_lock);
   1372  4128   hx147065 		if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
   1373  4128   hx147065 			sc->sc_flags |= WPI_F_RATE_AUTO_CTL;
   1374  4128   hx147065 			/* set rate to some reasonable initial value */
   1375  4499   hx147065 			i = in->in_rates.ir_nrates - 1;
   1376  4499   hx147065 			while (i > 0 && IEEE80211_RATE(i) > 72)
   1377  4499   hx147065 				i--;
   1378  4128   hx147065 			in->in_txrate = i;
   1379  4128   hx147065 		} else {
   1380  4128   hx147065 			sc->sc_flags &= ~WPI_F_RATE_AUTO_CTL;
   1381  4128   hx147065 		}
   1382  4128   hx147065 		mutex_exit(&sc->sc_mt_lock);
   1383  4128   hx147065 
   1384  4128   hx147065 		/* link LED always on while associated */
   1385  4128   hx147065 		wpi_set_led(sc, WPI_LED_LINK, 0, 1);
   1386  4128   hx147065 		break;
   1387  4128   hx147065 
   1388  4128   hx147065 	case IEEE80211_S_INIT:
   1389  7865  Pengcheng 		sc->sc_flags &= ~WPI_F_SCANNING;
   1390  7865  Pengcheng 		break;
   1391  7865  Pengcheng 
   1392  4128   hx147065 	case IEEE80211_S_ASSOC:
   1393  7865  Pengcheng 		sc->sc_flags &= ~WPI_F_SCANNING;
   1394  4128   hx147065 		break;
   1395  4128   hx147065 	}
   1396  4128   hx147065 
   1397  4128   hx147065 	mutex_exit(&sc->sc_glock);
   1398  4128   hx147065 	return (sc->sc_newstate(ic, nstate, arg));
   1399  5296   zf162725 }
   1400  5296   zf162725 
   1401  5296   zf162725 /*ARGSUSED*/
   1402  5296   zf162725 static int wpi_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
   1403  5296   zf162725     const uint8_t mac[IEEE80211_ADDR_LEN])
   1404  5296   zf162725 {
   1405  5296   zf162725 	wpi_sc_t *sc = (wpi_sc_t *)ic;
   1406  5296   zf162725 	wpi_node_t node;
   1407  5296   zf162725 	int err;
   1408  5296   zf162725 
   1409  5296   zf162725 	switch (k->wk_cipher->ic_cipher) {
   1410  5296   zf162725 	case IEEE80211_CIPHER_WEP:
   1411  5296   zf162725 	case IEEE80211_CIPHER_TKIP:
   1412  5296   zf162725 		return (1); /* sofeware do it. */
   1413  5296   zf162725 	case IEEE80211_CIPHER_AES_CCM:
   1414  5296   zf162725 		break;
   1415  5296   zf162725 	default:
   1416  5296   zf162725 		return (0);
   1417  5296   zf162725 	}
   1418  5296   zf162725 	sc->sc_config.filter &= ~(WPI_FILTER_NODECRYPTUNI |
   1419  5296   zf162725 	    WPI_FILTER_NODECRYPTMUL);
   1420  5296   zf162725 
   1421  5296   zf162725 	mutex_enter(&sc->sc_glock);
   1422  5296   zf162725 
   1423  5296   zf162725 	/* update ap/multicast node */
   1424  5296   zf162725 	(void) memset(&node, 0, sizeof (node));
   1425  5296   zf162725 	if (IEEE80211_IS_MULTICAST(mac)) {
   1426  5296   zf162725 		(void) memset(node.bssid, 0xff, 6);
   1427  5296   zf162725 		node.id = WPI_ID_BROADCAST;
   1428  5296   zf162725 	} else {
   1429  5296   zf162725 		IEEE80211_ADDR_COPY(node.bssid, ic->ic_bss->in_bssid);
   1430  5296   zf162725 		node.id = WPI_ID_BSS;
   1431  5296   zf162725 	}
   1432  5296   zf162725 	if (k->wk_flags & IEEE80211_KEY_XMIT) {
   1433  5296   zf162725 		node.key_flags = 0;
   1434  5296   zf162725 		node.keyp = k->wk_keyix;
   1435  5296   zf162725 	} else {
   1436  5296   zf162725 		node.key_flags = (1 << 14);
   1437  5296   zf162725 		node.keyp = k->wk_keyix + 4;
   1438  5296   zf162725 	}
   1439  5296   zf162725 	(void) memcpy(node.key, k->wk_key, k->wk_keylen);
   1440  5296   zf162725 	node.key_flags |= (2 | (1 << 3) | (k->wk_keyix << 8));
   1441  5296   zf162725 	node.sta_mask = 1;
   1442  5296   zf162725 	node.control = 1;
   1443  5296   zf162725 	err = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof (node), 1);
   1444  5296   zf162725 	if (err != WPI_SUCCESS) {
   1445  5296   zf162725 		cmn_err(CE_WARN, "wpi_key_set():"
   1446  5296   zf162725 		    "failed to update ap node\n");
   1447  5296   zf162725 		mutex_exit(&sc->sc_glock);
   1448  5296   zf162725 		return (0);
   1449  5296   zf162725 	}
   1450  5296   zf162725 	mutex_exit(&sc->sc_glock);
   1451  5296   zf162725 	return (1);
   1452  4128   hx147065 }
   1453  4128   hx147065 
   1454  4128   hx147065 /*
   1455  4128   hx147065  * Grab exclusive access to NIC memory.
   1456  4128   hx147065  */
   1457  4128   hx147065 static void
   1458  4128   hx147065 wpi_mem_lock(wpi_sc_t *sc)
   1459  4128   hx147065 {
   1460  4128   hx147065 	uint32_t tmp;
   1461  4128   hx147065 	int ntries;
   1462  4128   hx147065 
   1463  4128   hx147065 	tmp = WPI_READ(sc, WPI_GPIO_CTL);
   1464  4128   hx147065 	WPI_WRITE(sc, WPI_GPIO_CTL, tmp | WPI_GPIO_MAC);
   1465  4128   hx147065 
   1466  4128   hx147065 	/* spin until we actually get the lock */
   1467  4128   hx147065 	for (ntries = 0; ntries < 1000; ntries++) {
   1468  4128   hx147065 		if ((WPI_READ(sc, WPI_GPIO_CTL) &
   1469  4128   hx147065 		    (WPI_GPIO_CLOCK | WPI_GPIO_SLEEP)) == WPI_GPIO_CLOCK)
   1470  4128   hx147065 			break;
   1471  4128   hx147065 		DELAY(10);
   1472  4128   hx147065 	}
   1473  4128   hx147065 	if (ntries == 1000)
   1474  4128   hx147065 		WPI_DBG((WPI_DEBUG_PIO, "could not lock memory\n"));
   1475  4128   hx147065 }
   1476  4128   hx147065 
   1477  4128   hx147065 /*
   1478  4128   hx147065  * Release lock on NIC memory.
   1479  4128   hx147065  */
   1480  4128   hx147065 static void
   1481  4128   hx147065 wpi_mem_unlock(wpi_sc_t *sc)
   1482  4128   hx147065 {
   1483  4128   hx147065 	uint32_t tmp = WPI_READ(sc, WPI_GPIO_CTL);
   1484  4128   hx147065 	WPI_WRITE(sc, WPI_GPIO_CTL, tmp & ~WPI_GPIO_MAC);
   1485  4128   hx147065 }
   1486  4128   hx147065 
   1487  4128   hx147065 static uint32_t
   1488  4128   hx147065 wpi_mem_read(wpi_sc_t *sc, uint16_t addr)
   1489  4128   hx147065 {
   1490  4128   hx147065 	WPI_WRITE(sc, WPI_READ_MEM_ADDR, WPI_MEM_4 | addr);
   1491  4128   hx147065 	return (WPI_READ(sc, WPI_READ_MEM_DATA));
   1492  4128   hx147065 }
   1493  4128   hx147065 
   1494  4128   hx147065 static void
   1495  4128   hx147065 wpi_mem_write(wpi_sc_t *sc, uint16_t addr, uint32_t data)
   1496  4128   hx147065 {
   1497  4128   hx147065 	WPI_WRITE(sc, WPI_WRITE_MEM_ADDR, WPI_MEM_4 | addr);
   1498  4128   hx147065 	WPI_WRITE(sc, WPI_WRITE_MEM_DATA, data);
   1499  4128   hx147065 }
   1500  4128   hx147065 
   1501  4128   hx147065 static void
   1502  4128   hx147065 wpi_mem_write_region_4(wpi_sc_t *sc, uint16_t addr,
   1503  4128   hx147065     const uint32_t *data, int wlen)
   1504  4128   hx147065 {
   1505  4128   hx147065 	for (; wlen > 0; wlen--, data++, addr += 4)
   1506  4128   hx147065 		wpi_mem_write(sc, addr, *data);
   1507  4128   hx147065 }
   1508  4128   hx147065 
   1509  4128   hx147065 /*
   1510  4128   hx147065  * Read 16 bits from the EEPROM.  We access EEPROM through the MAC instead of
   1511  4128   hx147065  * using the traditional bit-bang method.
   1512  4128   hx147065  */
   1513  4128   hx147065 static uint16_t
   1514  4128   hx147065 wpi_read_prom_word(wpi_sc_t *sc, uint32_t addr)
   1515  4128   hx147065 {
   1516  4128   hx147065 	uint32_t val;
   1517  4128   hx147065 	int ntries;
   1518  4128   hx147065 
   1519  4128   hx147065 	WPI_WRITE(sc, WPI_EEPROM_CTL, addr << 2);
   1520  4128   hx147065 
   1521  4128   hx147065 	wpi_mem_lock(sc);
   1522  4128   hx147065 	for (ntries = 0; ntries < 10; ntries++) {
   1523  4128   hx147065 		if ((val = WPI_READ(sc, WPI_EEPROM_CTL)) & WPI_EEPROM_READY)
   1524  4128   hx147065 			break;
   1525  4128   hx147065 		DELAY(10);
   1526  4128   hx147065 	}
   1527  4128   hx147065 	wpi_mem_unlock(sc);
   1528  4128   hx147065 
   1529  4128   hx147065 	if (ntries == 10) {
   1530  4128   hx147065 		WPI_DBG((WPI_DEBUG_PIO, "could not read EEPROM\n"));
   1531  4128   hx147065 		return (0xdead);
   1532  4128   hx147065 	}
   1533  4128   hx147065 	return (val >> 16);
   1534  4128   hx147065 }
   1535  4128   hx147065 
   1536  4128   hx147065 /*
   1537  4128   hx147065  * The firmware boot code is small and is intended to be copied directly into
   1538  4128   hx147065  * the NIC internal memory.
   1539  4128   hx147065  */
   1540  4128   hx147065 static int
   1541  4128   hx147065 wpi_load_microcode(wpi_sc_t *sc)
   1542  4128   hx147065 {
   1543  4128   hx147065 	const char *ucode;
   1544  4128   hx147065 	int size;
   1545  4128   hx147065 
   1546  4128   hx147065 	ucode = sc->sc_boot;
   1547  4128   hx147065 	size = LE_32(sc->sc_hdr->bootsz);
   1548  4128   hx147065 	/* check that microcode size is a multiple of 4 */
   1549  4128   hx147065 	if (size & 3)
   1550  4128   hx147065 		return (EINVAL);
   1551  4128   hx147065 
   1552  4128   hx147065 	size /= sizeof (uint32_t);
   1553  4128   hx147065 
   1554  4128   hx147065 	wpi_mem_lock(sc);
   1555  4128   hx147065 
   1556  4128   hx147065 	/* copy microcode image into NIC memory */
   1557  4128   hx147065 	wpi_mem_write_region_4(sc, WPI_MEM_UCODE_BASE, (const uint32_t *)ucode,
   1558  4128   hx147065 	    size);
   1559  4128   hx147065 
   1560  4128   hx147065 	wpi_mem_write(sc, WPI_MEM_UCODE_SRC, 0);
   1561  4128   hx147065 	wpi_mem_write(sc, WPI_MEM_UCODE_DST, WPI_FW_TEXT);
   1562  4128   hx147065 	wpi_mem_write(sc, WPI_MEM_UCODE_SIZE, size);
   1563  4128   hx147065 
   1564  4128   hx147065 	/* run microcode */
   1565  4128   hx147065 	wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_RUN);
   1566  4128   hx147065 
   1567  4128   hx147065 	wpi_mem_unlock(sc);
   1568  4128   hx147065 
   1569  4128   hx147065 	return (WPI_SUCCESS);
   1570  4128   hx147065 }
   1571  4128   hx147065 
   1572  4128   hx147065 /*
   1573  4128   hx147065  * The firmware text and data segments are transferred to the NIC using DMA.
   1574  4128   hx147065  * The driver just copies the firmware into DMA-safe memory and tells the NIC
   1575  4128   hx147065  * where to find it.  Once the NIC has copied the firmware into its internal
   1576  4128   hx147065  * memory, we can free our local copy in the driver.
   1577  4128   hx147065  */
   1578  4128   hx147065 static int
   1579  4128   hx147065 wpi_load_firmware(wpi_sc_t *sc, uint32_t target)
   1580  4128   hx147065 {
   1581  4128   hx147065 	const char *fw;
   1582  4128   hx147065 	int size;
   1583  4128   hx147065 	wpi_dma_t *dma_p;
   1584  4128   hx147065 	ddi_dma_cookie_t *cookie;
   1585  4128   hx147065 	wpi_tx_desc_t desc;
   1586  4128   hx147065 	int i, ntries, err = WPI_SUCCESS;
   1587  4128   hx147065 
   1588  4128   hx147065 	/* only text and data here */
   1589  4128   hx147065 	if (target == WPI_FW_TEXT) {
   1590  4128   hx147065 		fw = sc->sc_text;
   1591  4128   hx147065 		size = LE_32(sc->sc_hdr->textsz);
   1592  4128   hx147065 		dma_p = &sc->sc_dma_fw_text;
   1593  4128   hx147065 		cookie = sc->sc_fw_text_cookie;
   1594  4128   hx147065 	} else {
   1595  4128   hx147065 		fw = sc->sc_data;
   1596  4128   hx147065 		size = LE_32(sc->sc_hdr->datasz);
   1597  4128   hx147065 		dma_p = &sc->sc_dma_fw_data;
   1598  4128   hx147065 		cookie = sc->sc_fw_data_cookie;
   1599  4128   hx147065 	}
   1600  4128   hx147065 
   1601  4128   hx147065 	/* copy firmware image to DMA-safe memory */
   1602  4128   hx147065 	(void) memcpy(dma_p->mem_va, fw, size);
   1603  4128   hx147065 
   1604  4128   hx147065 	/* make sure the adapter will get up-to-date values */
   1605  4128   hx147065 	(void) ddi_dma_sync(dma_p->dma_hdl, 0, size, DDI_DMA_SYNC_FORDEV);
   1606  4128   hx147065 
   1607  4128   hx147065 	(void) memset(&desc, 0, sizeof (desc));
   1608  4128   hx147065 	desc.flags = LE_32(WPI_PAD32(size) << 28 | dma_p->ncookies << 24);
   1609  4128   hx147065 	for (i = 0; i < dma_p->ncookies; i++) {
   1610  4128   hx147065 		WPI_DBG((WPI_DEBUG_DMA, "cookie%d addr:%x size:%x\n",
   1611  4128   hx147065 		    i, cookie[i].dmac_address, cookie[i].dmac_size));
   1612  4128   hx147065 		desc.segs[i].addr = cookie[i].dmac_address;
   1613  4128   hx147065 		desc.segs[i].len = (uint32_t)cookie[i].dmac_size;
   1614  4128   hx147065 	}
   1615  4128   hx147065 
   1616  4128   hx147065 	wpi_mem_lock(sc);
   1617  4128   hx147065 
   1618  4128   hx147065 	/* tell adapter where to copy image in its internal memory */
   1619  4128   hx147065 	WPI_WRITE(sc, WPI_FW_TARGET, target);
   1620  4128   hx147065 
   1621  4128   hx147065 	WPI_WRITE(sc, WPI_TX_CONFIG(6), 0);
   1622  4128   hx147065 
   1623  4128   hx147065 	/* copy firmware descriptor into NIC memory */
   1624  4128   hx147065 	WPI_WRITE_REGION_4(sc, WPI_TX_DESC(6), (uint32_t *)&desc,
   1625  4128   hx147065 	    sizeof desc / sizeof (uint32_t));
   1626  4128   hx147065 
   1627  4128   hx147065 	WPI_WRITE(sc, WPI_TX_CREDIT(6), 0xfffff);
   1628  4128   hx147065 	WPI_WRITE(sc, WPI_TX_STATE(6), 0x4001);
   1629  4128   hx147065 	WPI_WRITE(sc, WPI_TX_CONFIG(6), 0x80000001);
   1630  4128   hx147065 
   1631  4128   hx147065 	/* wait while the adapter is busy copying the firmware */
   1632  4128   hx147065 	for (ntries = 0; ntries < 100; ntries++) {
   1633  4128   hx147065 		if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(6))
   1634  4128   hx147065 			break;
   1635  4128   hx147065 		DELAY(1000);
   1636  4128   hx147065 	}
   1637  4128   hx147065 	if (ntries == 100) {
   1638  4128   hx147065 		WPI_DBG((WPI_DEBUG_FW, "timeout transferring firmware\n"));
   1639  4128   hx147065 		err = ETIMEDOUT;
   1640  4128   hx147065 	}
   1641  4128   hx147065 
   1642  4128   hx147065 	WPI_WRITE(sc, WPI_TX_CREDIT(6), 0);
   1643  4128   hx147065 
   1644  4128   hx147065 	wpi_mem_unlock(sc);
   1645  4128   hx147065 
   1646  4128   hx147065 	return (err);
   1647  4128   hx147065 }
   1648  4128   hx147065 
   1649  4128   hx147065 /*ARGSUSED*/
   1650  4128   hx147065 static void
   1651  4128   hx147065 wpi_rx_intr(wpi_sc_t *sc, wpi_rx_desc_t *desc, wpi_rx_data_t *data)
   1652  4128   hx147065 {
   1653  4128   hx147065 	ieee80211com_t *ic = &sc->sc_ic;
   1654  4128   hx147065 	wpi_rx_ring_t *ring = &sc->sc_rxq;
   1655  4128   hx147065 	wpi_rx_stat_t *stat;
   1656  4128   hx147065 	wpi_rx_head_t *head;
   1657  4128   hx147065 	wpi_rx_tail_t *tail;
   1658  4128   hx147065 	ieee80211_node_t *in;
   1659  4128   hx147065 	struct ieee80211_frame *wh;
   1660  4128   hx147065 	mblk_t *mp;
   1661  4128   hx147065 	uint16_t len;
   1662  4128   hx147065 
   1663  4128   hx147065 	stat = (wpi_rx_stat_t *)(desc + 1);
   1664  4128   hx147065 
   1665  4128   hx147065 	if (stat->len > WPI_STAT_MAXLEN) {
   1666  4128   hx147065 		WPI_DBG((WPI_DEBUG_RX, "invalid rx statistic header\n"));
   1667  4128   hx147065 		return;
   1668  4128   hx147065 	}
   1669  4128   hx147065 
   1670  4128   hx147065 	head = (wpi_rx_head_t *)((caddr_t)(stat + 1) + stat->len);
   1671  4128   hx147065 	tail = (wpi_rx_tail_t *)((caddr_t)(head + 1) + LE_16(head->len));
   1672  4128   hx147065 
   1673  4128   hx147065 	len = LE_16(head->len);
   1674  4128   hx147065 
   1675  4128   hx147065 	WPI_DBG((WPI_DEBUG_RX, "rx intr: idx=%d len=%d stat len=%d rssi=%d "
   1676  4128   hx147065 	    "rate=%x chan=%d tstamp=%llu", ring->cur, LE_32(desc->len),
   1677  4128   hx147065 	    len, (int8_t)stat->rssi, head->rate, head->chan,
   1678  4128   hx147065 	    LE_64(tail->tstamp)));
   1679  4128   hx147065 
   1680  4128   hx147065 	if ((len < 20) || (len > sc->sc_dmabuf_sz)) {
   1681  4128   hx147065 		sc->sc_rx_err++;
   1682  4128   hx147065 		return;
   1683  4128   hx147065 	}
   1684  4128   hx147065 
   1685  4128   hx147065 	/*
   1686  4128   hx147065 	 * Discard Rx frames with bad CRC early
   1687  4128   hx147065 	 */
   1688  4128   hx147065 	if ((LE_32(tail->flags) & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
   1689  4128   hx147065 		WPI_DBG((WPI_DEBUG_RX, "rx tail flags error %x\n",
   1690  4128   hx147065 		    LE_32(tail->flags)));
   1691  4128   hx147065 		sc->sc_rx_err++;
   1692  4128   hx147065 		return;
   1693  4128   hx147065 	}
   1694  4128   hx147065 
   1695  4128   hx147065 	/* update Rx descriptor */
   1696  4128   hx147065 	/* ring->desc[ring->cur] = LE_32(data->dma_data.cookie.dmac_address); */
   1697  4128   hx147065 
   1698  4128   hx147065 #ifdef WPI_BPF
   1699  4128   hx147065 #ifndef WPI_CURRENT
   1700  4128   hx147065 	if (sc->sc_drvbpf != NULL) {
   1701  4128   hx147065 #else
   1702  4128   hx147065 	if (bpf_peers_present(sc->sc_drvbpf)) {
   1703  4128   hx147065 #endif
   1704  4128   hx147065 		struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;
   1705  4128   hx147065 
   1706  4128   hx147065 		tap->wr_flags = 0;
   1707  4128   hx147065 		tap->wr_rate = head->rate;
   1708  4128   hx147065 		tap->wr_chan_freq =
   1709  4128   hx147065 		    LE_16(ic->ic_channels[head->chan].ic_freq);
   1710  4128   hx147065 		tap->wr_chan_flags =
   1711  4128   hx147065 		    LE_16(ic->ic_channels[head->chan].ic_flags);
   1712  4128   hx147065 		tap->wr_dbm_antsignal = (int8_t)(stat->rssi - WPI_RSSI_OFFSET);
   1713  4128   hx147065 		tap->wr_dbm_antnoise = (int8_t)LE_16(stat->noise);
   1714  4128   hx147065 		tap->wr_tsft = tail->tstamp;
   1715  4128   hx147065 		tap->wr_antenna = (LE_16(head->flags) >> 4) & 0xf;
   1716  4128   hx147065 		switch (head->rate) {
   1717  4128   hx147065 		/* CCK rates */
   1718  4128   hx147065 		case  10: tap->wr_rate =   2; break;
   1719  4128   hx147065 		case  20: tap->wr_rate =   4; break;
   1720  4128   hx147065 		case  55: tap->wr_rate =  11; break;
   1721  4128   hx147065 		case 110: tap->wr_rate =  22; break;
   1722  4128   hx147065 		/* OFDM rates */
   1723  4128   hx147065 		case 0xd: tap->wr_rate =  12; break;
   1724  4128   hx147065 		case 0xf: tap->wr_rate =  18; break;
   1725  4128   hx147065 		case 0x5: tap->wr_rate =  24; break;
   1726  4128   hx147065 		case 0x7: tap->wr_rate =  36; break;
   1727  4128   hx147065 		case 0x9: tap->wr_rate =  48; break;
   1728  4128   hx147065 		case 0xb: tap->wr_rate =  72; break;
   1729  4128   hx147065 		case 0x1: tap->wr_rate =  96; break;
   1730  4128   hx147065 		case 0x3: tap->wr_rate = 108; break;
   1731  4128   hx147065 		/* unknown rate: should not happen */
   1732  4128   hx147065 		default:  tap->wr_rate =   0;
   1733  4128   hx147065 		}
   1734  4128   hx147065 		if (LE_16(head->flags) & 0x4)
   1735  4128   hx147065 			tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
   1736  4128   hx147065 
   1737  4128   hx147065 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
   1738  4128   hx147065 	}
   1739  4128   hx147065 #endif
   1740  4128   hx147065 	/* grab a reference to the source node */
   1741  4128   hx147065 	wh = (struct ieee80211_frame *)(head + 1);
   1742  4128   hx147065 
   1743  4128   hx147065 #ifdef DEBUG
   1744  4128   hx147065 	if (wpi_dbg_flags & WPI_DEBUG_RX)
   1745  4128   hx147065 		ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0);
   1746  4128   hx147065 #endif
   1747  4128   hx147065 
   1748  4128   hx147065 	in = ieee80211_find_rxnode(ic, wh);
   1749  4128   hx147065 	mp = allocb(len, BPRI_MED);
   1750  4128   hx147065 	if (mp) {
   1751  4128   hx147065 		(void) memcpy(mp->b_wptr, wh, len);
   1752  4128   hx147065 		mp->b_wptr += len;
   1753  4128   hx147065 
   1754  4128   hx147065 		/* send the frame to the 802.11 layer */
   1755  4128   hx147065 		(void) ieee80211_input(ic, mp, in, stat->rssi, 0);
   1756  4128   hx147065 	} else {
   1757  4128   hx147065 		sc->sc_rx_nobuf++;
   1758  4128   hx147065 		WPI_DBG((WPI_DEBUG_RX,
   1759  4128   hx147065 		    "wpi_rx_intr(): alloc rx buf failed\n"));
   1760  4128   hx147065 	}
   1761  4128   hx147065 	/* release node reference */
   1762  4128   hx147065 	ieee80211_free_node(in);
   1763  4128   hx147065 }
   1764  4128   hx147065 
   1765  4128   hx147065 /*ARGSUSED*/
   1766  4128   hx147065 static void
   1767  4128   hx147065 wpi_tx_intr(wpi_sc_t *sc, wpi_rx_desc_t *desc, wpi_rx_data_t *data)
   1768  4128   hx147065 {
   1769  4128   hx147065 	ieee80211com_t *ic = &sc->sc_ic;
   1770  4128   hx147065 	wpi_tx_ring_t *ring = &sc->sc_txq[desc->qid & 0x3];
   1771  4128   hx147065 	/* wpi_tx_data_t *txdata = &ring->data[desc->idx]; */
   1772  4128   hx147065 	wpi_tx_stat_t *stat = (wpi_tx_stat_t *)(desc + 1);
   1773  4128   hx147065 	wpi_amrr_t *amrr = (wpi_amrr_t *)ic->ic_bss;
   1774  4128   hx147065 
   1775  4128   hx147065 	WPI_DBG((WPI_DEBUG_TX, "tx done: qid=%d idx=%d retries=%d nkill=%d "
   1776  4128   hx147065 	    "rate=%x duration=%d status=%x\n",
   1777  4128   hx147065 	    desc->qid, desc->idx, stat->ntries, stat->nkill, stat->rate,
   1778  4128   hx147065 	    LE_32(stat->duration), LE_32(stat->status)));
   1779  4128   hx147065 
   1780  4128   hx147065 	amrr->txcnt++;
   1781  4128   hx147065 	WPI_DBG((WPI_DEBUG_RATECTL, "tx: %d cnt\n", amrr->txcnt));
   1782  4128   hx147065 	if (stat->ntries > 0) {
   1783  4128   hx147065 		amrr->retrycnt++;
   1784  4128   hx147065 		sc->sc_tx_retries++;
   1785  4128   hx147065 		WPI_DBG((WPI_DEBUG_RATECTL, "tx: %d retries\n",
   1786  4128   hx147065 		    amrr->retrycnt));
   1787  4128   hx147065 	}
   1788  4128   hx147065 
   1789  4128   hx147065 	sc->sc_tx_timer = 0;
   1790  4128   hx147065 
   1791  4128   hx147065 	mutex_enter(&sc->sc_tx_lock);
   1792  4128   hx147065 	ring->queued--;
   1793  4128   hx147065 	if (ring->queued < 0)
   1794  4128   hx147065 		ring->queued = 0;
   1795  4128   hx147065 	if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count << 3))) {
   1796  4128   hx147065 		sc->sc_need_reschedule = 0;
   1797  4128   hx147065 		mutex_exit(&sc->sc_tx_lock);
   1798  4128   hx147065 		mac_tx_update(ic->ic_mach);
   1799  4128   hx147065 		mutex_enter(&sc->sc_tx_lock);
   1800  4128   hx147065 	}
   1801  4128   hx147065 	mutex_exit(&sc->sc_tx_lock);
   1802  4128   hx147065 }
   1803  4128   hx147065 
   1804  4128   hx147065 static void
   1805  4128   hx147065 wpi_cmd_intr(wpi_sc_t *sc, wpi_rx_desc_t *desc)
   1806  4128   hx147065 {
   1807  4128   hx147065 	if ((desc->qid & 7) != 4) {
   1808  4128   hx147065 		return;	/* not a command ack */
   1809  4128   hx147065 	}
   1810  4128   hx147065 	mutex_enter(&sc->sc_glock);
   1811  4128   hx147065 	sc->sc_flags |= WPI_F_CMD_DONE;
   1812  4128   hx147065 	cv_signal(&sc->sc_cmd_cv);
   1813  4128   hx147065 	mutex_exit(&sc->sc_glock);
   1814  4128   hx147065 }
   1815  4128   hx147065 
   1816  4128   hx147065 static uint_t
   1817  4128   hx147065 wpi_notif_softintr(caddr_t arg)
   1818  4128   hx147065 {
   1819  4128   hx147065 	wpi_sc_t *sc = (wpi_sc_t *)arg;
   1820  4128   hx147065 	wpi_rx_desc_t *desc;
   1821  4128   hx147065 	wpi_rx_data_t *data;
   1822  4128   hx147065 	uint32_t hw;
   1823  4128   hx147065 
   1824  4128   hx147065 	mutex_enter(&sc->sc_glock);
   1825  4128   hx147065 	if (sc->sc_notif_softint_pending != 1) {
   1826  4128   hx147065 		mutex_exit(&sc->sc_glock);
   1827  4128   hx147065 		return (DDI_INTR_UNCLAIMED);
   1828  4128   hx147065 	}
   1829  4128   hx147065 	mutex_exit(&sc->sc_glock);
   1830  4128   hx147065 
   1831  4128   hx147065 	hw = LE_32(sc->sc_shared->next);
   1832  4128   hx147065 
   1833  4128   hx147065 	while (sc->sc_rxq.cur != hw) {
   1834  4128   hx147065 		data = &sc->sc_rxq.data[sc->sc_rxq.cur];
   1835  4128   hx147065 		desc = (wpi_rx_desc_t *)data->dma_data.mem_va;
   1836  4128   hx147065 
   1837  4128   hx147065 		WPI_DBG((WPI_DEBUG_INTR, "rx notification hw = %d cur = %d "
   1838  4128   hx147065 		    "qid=%x idx=%d flags=%x type=%d len=%d\n",
   1839  4128   hx147065 		    hw, sc->sc_rxq.cur, desc->qid, desc->idx, desc->flags,
   1840  4128   hx147065 		    desc->type, LE_32(desc->len)));
   1841  4128   hx147065 
   1842  4128   hx147065 		if (!(desc->qid & 0x80))	/* reply to a command */
   1843  4128   hx147065 			wpi_cmd_intr(sc, desc);
   1844  4128   hx147065 
   1845  4128   hx147065 		switch (desc->type) {
   1846  4128   hx147065 		case WPI_RX_DONE:
   1847  4128   hx147065 			/* a 802.11 frame was received */
   1848  4128   hx147065 			wpi_rx_intr(sc, desc, data);
   1849  4128   hx147065 			break;
   1850  4128   hx147065 
   1851  4128   hx147065 		case WPI_TX_DONE:
   1852  4128   hx147065 			/* a 802.11 frame has been transmitted */
   1853  4128   hx147065 			wpi_tx_intr(sc, desc, data);
   1854  4128   hx147065 			break;
   1855  4128   hx147065 
   1856  4128   hx147065 		case WPI_UC_READY:
   1857  4128   hx147065 		{
   1858  4128   hx147065 			wpi_ucode_info_t *uc =
   1859  4128   hx147065 			    (wpi_ucode_info_t *)(desc + 1);
   1860  4128   hx147065 
   1861  4128   hx147065 			/* the microcontroller is ready */
   1862  4128   hx147065 			WPI_DBG((WPI_DEBUG_FW,
   1863  4128   hx147065 			    "microcode alive notification version %x "
   1864  4128   hx147065 			    "alive %x\n", LE_32(uc->version),
   1865  4128   hx147065 			    LE_32(uc->valid)));
   1866  4128   hx147065 
   1867  4128   hx147065 			if (LE_32(uc->valid) != 1) {
   1868  4128   hx147065 				WPI_DBG((WPI_DEBUG_FW,
   1869  4128   hx147065 				    "microcontroller initialization failed\n"));
   1870  4128   hx147065 			}
   1871  4128   hx147065 			break;
   1872  4128   hx147065 		}
   1873  4128   hx147065 		case WPI_STATE_CHANGED:
   1874  4128   hx147065 		{
   1875  4128   hx147065 			uint32_t *status = (uint32_t *)(desc + 1);
   1876  4128   hx147065 
   1877  4128   hx147065 			/* enabled/disabled notification */
   1878  4128   hx147065 			WPI_DBG((WPI_DEBUG_RADIO, "state changed to %x\n",
   1879  4128   hx147065 			    LE_32(*status)));
   1880  4128   hx147065 
   1881  4128   hx147065 			if (LE_32(*status) & 1) {
   1882  6062   hx147065 				/*
   1883  6062   hx147065 				 * the radio button has to be pushed(OFF). It
   1884  6062   hx147065 				 * is considered as a hw error, the
   1885  6062   hx147065 				 * wpi_thread() tries to recover it after the
   1886  6062   hx147065 				 * button is pushed again(ON)
   1887  6062   hx147065 				 */
   1888  4128   hx147065 				cmn_err(CE_NOTE,
   1889  4128   hx147065 				    "wpi: Radio transmitter is off\n");
   1890  6062   hx147065 				sc->sc_ostate = sc->sc_ic.ic_state;
   1891  6062   hx147065 				ieee80211_new_state(&sc->sc_ic,
   1892  6062   hx147065 				    IEEE80211_S_INIT, -1);
   1893  6062   hx147065 				sc->sc_flags |=
   1894  6062   hx147065 				    (WPI_F_HW_ERR_RECOVER | WPI_F_RADIO_OFF);
   1895  4128   hx147065 			}
   1896  4128   hx147065 			break;
   1897  4128   hx147065 		}
   1898  4128   hx147065 		case WPI_START_SCAN:
   1899  4128   hx147065 		{
   1900  4128   hx147065 			wpi_start_scan_t *scan =
   1901  4128   hx147065 			    (wpi_start_scan_t *)(desc + 1);
   1902  4128   hx147065 
   1903  4128   hx147065 			WPI_DBG((WPI_DEBUG_SCAN,
   1904  4128   hx147065 			    "scanning channel %d status %x\n",
   1905  4128   hx147065 			    scan->chan, LE_32(scan->status)));
   1906  4128   hx147065 
   1907  4128   hx147065 			break;
   1908  4128   hx147065 		}
   1909  4128   hx147065 		case WPI_STOP_SCAN:
   1910  7865  Pengcheng 		{
   1911  7865  Pengcheng 			wpi_stop_scan_t *scan =
   1912  7865  Pengcheng 			    (wpi_stop_scan_t *)(desc + 1);
   1913  7865  Pengcheng 
   1914  7865  Pengcheng 			WPI_DBG((WPI_DEBUG_SCAN,
   1915  7865  Pengcheng 			    "completed channel %d (burst of %d) status %02x\n",
   1916  7865  Pengcheng 			    scan->chan, scan->nchan, scan->status));
   1917  7865  Pengcheng 
   1918  7865  Pengcheng 			sc->sc_scan_pending = 0;
   1919  7865  Pengcheng 			sc->sc_scan_next++;
   1920  7865  Pengcheng 			break;
   1921  7865  Pengcheng 		}
   1922  7865  Pengcheng 		default:
   1923  4128   hx147065 			break;
   1924  4128   hx147065 		}
   1925  4128   hx147065 
   1926  4128   hx147065 		sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % WPI_RX_RING_COUNT;
   1927  4128   hx147065 	}
   1928  4128   hx147065 
   1929  4128   hx147065 	/* tell the firmware what we have processed */
   1930  4128   hx147065 	hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
   1931  4128   hx147065 	WPI_WRITE(sc, WPI_RX_WIDX, hw & (~7));
   1932  4128   hx147065 	mutex_enter(&sc->sc_glock);
   1933  4128   hx147065 	sc->sc_notif_softint_pending = 0;
   1934  4128   hx147065 	mutex_exit(&sc->sc_glock);
   1935  4128   hx147065 
   1936  4128   hx147065 	return (DDI_INTR_CLAIMED);
   1937  4128   hx147065 }
   1938  4128   hx147065 
   1939  4128   hx147065 static uint_t
   1940  4128   hx147065 wpi_intr(caddr_t arg)
   1941  4128   hx147065 {
   1942  4128   hx147065 	wpi_sc_t *sc = (wpi_sc_t *)arg;
   1943  5453   hx147065 	uint32_t r, rfh;
   1944  4128   hx147065 
   1945  4128   hx147065 	mutex_enter(&sc->sc_glock);
   1946  6062   hx147065 	if (sc->sc_flags & WPI_F_SUSPEND) {
   1947  6062   hx147065 		mutex_exit(&sc->sc_glock);
   1948  6062   hx147065 		return (DDI_INTR_UNCLAIMED);
   1949  6062   hx147065 	}
   1950  6062   hx147065 
   1951  4128   hx147065 	r = WPI_READ(sc, WPI_INTR);
   1952  4128   hx147065 	if (r == 0 || r == 0xffffffff) {
   1953  4128   hx147065 		mutex_exit(&sc->sc_glock);
   1954  4128   hx147065 		return (DDI_INTR_UNCLAIMED);
   1955  4128   hx147065 	}
   1956  4128   hx147065 
   1957  4128   hx147065 	WPI_DBG((WPI_DEBUG_INTR, "interrupt reg %x\n", r));
   1958  4128   hx147065 
   1959  5453   hx147065 	rfh = WPI_READ(sc, WPI_INTR_STATUS);
   1960  4128   hx147065 	/* disable interrupts */
   1961  4128   hx147065 	WPI_WRITE(sc, WPI_MASK, 0);
   1962  4128   hx147065 	/* ack interrupts */
   1963  4128   hx147065 	WPI_WRITE(sc, WPI_INTR, r);
   1964  5453   hx147065 	WPI_WRITE(sc, WPI_INTR_STATUS, rfh);
   1965  4128   hx147065 
   1966  4128   hx147065 	if (sc->sc_notif_softint_id == NULL) {
   1967  4128   hx147065 		mutex_exit(&sc->sc_glock);
   1968  4128   hx147065 		return (DDI_INTR_CLAIMED);
   1969  4128   hx147065 	}
   1970  4128   hx147065 
   1971  4128   hx147065 	if (r & (WPI_SW_ERROR | WPI_HW_ERROR)) {
   1972  4128   hx147065 		WPI_DBG((WPI_DEBUG_FW, "fatal firmware error\n"));
   1973  4128   hx147065 		mutex_exit(&sc->sc_glock);
   1974  4128   hx147065 		wpi_stop(sc);
   1975  7865  Pengcheng 		if (!(sc->sc_flags & WPI_F_HW_ERR_RECOVER)) {
   1976  7865  Pengcheng 			sc->sc_ostate = sc->sc_ic.ic_state;
   1977  7865  Pengcheng 		}
   1978  8902  Pengcheng 
   1979  8902  Pengcheng 		/* not capable of fast recovery */
   1980  8902  Pengcheng 		if (!WPI_CHK_FAST_RECOVER(sc))
   1981  8902  Pengcheng 			ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
   1982  8902  Pengcheng 
   1983  4128   hx147065 		sc->sc_flags |= WPI_F_HW_ERR_RECOVER;
   1984  4128   hx147065 		return (DDI_INTR_CLAIMED);
   1985  4128   hx147065 	}
   1986  4128   hx147065 
   1987  5453   hx147065 	if ((r & (WPI_RX_INTR | WPI_RX_SWINT)) ||
   1988  5453   hx147065 	    (rfh & 0x40070000)) {
   1989  4128   hx147065 		sc->sc_notif_softint_pending = 1;
   1990  4128   hx147065 		ddi_trigger_softintr(sc->sc_notif_softint_id);
   1991  4128   hx147065 	}
   1992  4128   hx147065 
   1993  4128   hx147065 	if (r & WPI_ALIVE_INTR)	{ /* firmware initialized */
   1994  4128   hx147065 		sc->sc_flags |= WPI_F_FW_INIT;
   1995  4128   hx147065 		cv_signal(&sc->sc_fw_cv);
   1996  4128   hx147065 	}
   1997  4128   hx147065 
   1998  4128   hx147065 	/* re-enable interrupts */
   1999  4128   hx147065 	WPI_WRITE(sc, WPI_MASK, WPI_INTR_MASK);
   2000  4128   hx147065 	mutex_exit(&sc->sc_glock);
   2001  4128   hx147065 
   2002  4128   hx147065 	return (DDI_INTR_CLAIMED);
   2003  4128   hx147065 }
   2004  4128   hx147065 
   2005  4128   hx147065 static uint8_t
   2006  4128   hx147065 wpi_plcp_signal(int rate)
   2007  4128   hx147065 {
   2008  4128   hx147065 	switch (rate) {
   2009  4128   hx147065 	/* CCK rates (returned values are device-dependent) */
   2010  4128   hx147065 	case 2:		return (10);
   2011  4128   hx147065 	case 4:		return (20);
   2012  4128   hx147065 	case 11:	return (55);
   2013  4128   hx147065 	case 22:	return (110);
   2014  4128   hx147065 
   2015  4128   hx147065 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
   2016  4128   hx147065 	/* R1-R4 (ral/ural is R4-R1) */
   2017  4128   hx147065 	case 12:	return (0xd);
   2018  4128   hx147065 	case 18:	return (0xf);
   2019  4128   hx147065 	case 24:	return (0x5);
   2020  4128   hx147065 	case 36:	return (0x7);
   2021  4128   hx147065 	case 48:	return (0x9);
   2022  4128   hx147065 	case 72:	return (0xb);
   2023  4128   hx147065 	case 96:	return (0x1);
   2024  4128   hx147065 	case 108:	return (0x3);
   2025  4128   hx147065 
   2026  4128   hx147065 	/* unsupported rates (should not get there) */
   2027  4128   hx147065 	default:	return (0);
   2028  4128   hx147065 	}
   2029  4128   hx147065 }
   2030  4128   hx147065 
   2031  4128   hx147065 static mblk_t *
   2032  4128   hx147065 wpi_m_tx(void *arg, mblk_t *mp)
   2033  4128   hx147065 {
   2034  4128   hx147065 	wpi_sc_t	*sc = (wpi_sc_t *)arg;
   2035  4128   hx147065 	ieee80211com_t	*ic = &sc->sc_ic;
   2036  4128   hx147065 	mblk_t			*next;
   2037  4128   hx147065 
   2038  6062   hx147065 	if (sc->sc_flags & WPI_F_SUSPEND) {
   2039  6062   hx147065 		freemsgchain(mp);
   2040  6062   hx147065 		return (NULL);
   2041  6062   hx147065 	}
   2042  6062   hx147065 
   2043  4128   hx147065 	if (ic->ic_state != IEEE80211_S_RUN) {
   2044  4128   hx147065 		freemsgchain(mp);
   2045  4128   hx147065 		return (NULL);
   2046  8902  Pengcheng 	}
   2047  8902  Pengcheng 
   2048  8902  Pengcheng 	if ((sc->sc_flags & WPI_F_HW_ERR_RECOVER) &&
   2049  8902  Pengcheng 	    WPI_CHK_FAST_RECOVER(sc)) {
   2050  8902  Pengcheng 		WPI_DBG((WPI_DEBUG_FW, "wpi_m_tx(): hold queue\n"));
   2051  8902  Pengcheng 		return (mp);
   2052  4128   hx147065 	}
   2053  4128   hx147065 
   2054  4128   hx147065 	while (mp != NULL) {
   2055  4128   hx147065 		next = mp->b_next;
   2056  4128   hx147065 		mp->b_next = NULL;
   2057  4128   hx147065 		if (wpi_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) {
   2058  4128   hx147065 			mp->b_next = next;
   2059  4128   hx147065 			break;
   2060  4128   hx147065 		}
   2061  4128   hx147065 		mp = next;
   2062  4128   hx147065 	}
   2063  4128   hx147065 	return (mp);
   2064  4128   hx147065 }
   2065  4128   hx147065 
   2066  4128   hx147065 /* ARGSUSED */
   2067  4128   hx147065 static int
   2068  4128   hx147065 wpi_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
   2069  4128   hx147065 {
   2070  4128   hx147065 	wpi_sc_t *sc = (wpi_sc_t *)ic;
   2071  4128   hx147065 	wpi_tx_ring_t *ring;
   2072  4128   hx147065 	wpi_tx_desc_t *desc;
   2073  4128   hx147065 	wpi_tx_data_t *data;
   2074  4128   hx147065 	wpi_tx_cmd_t *cmd;
   2075  4128   hx147065 	wpi_cmd_data_t *tx;
   2076  4128   hx147065 	ieee80211_node_t *in;
   2077  4128   hx147065 	struct ieee80211_frame *wh;
   2078  4128   hx147065 	struct ieee80211_key *k;
   2079  4128   hx147065 	mblk_t *m, *m0;
   2080  4128   hx147065 	int rate, hdrlen, len, mblen, off, err = WPI_SUCCESS;
   2081  4128   hx147065 
   2082  4128   hx147065 	ring = ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) ?
   2083  4128   hx147065 	    (&sc->sc_txq[0]) : (&sc->sc_txq[1]);
   2084  4128   hx147065 	data = &ring->data[ring->cur];
   2085  4128   hx147065 	desc = data->desc;
   2086  4128   hx147065 	cmd = data->cmd;
   2087  4128   hx147065 	bzero(desc, sizeof (*desc));
   2088  4128   hx147065 	bzero(cmd, sizeof (*cmd));
   2089  4128   hx147065 
   2090  4128   hx147065 	mutex_enter(&sc->sc_tx_lock);
   2091  6062   hx147065 	if (sc->sc_flags & WPI_F_SUSPEND) {
   2092  6062   hx147065 		mutex_exit(&sc->sc_tx_lock);
   2093  6062   hx147065 		if ((type & IEEE80211_FC0_TYPE_MASK) !=
   2094  6062   hx147065 		    IEEE80211_FC0_TYPE_DATA) {
   2095  6062   hx147065 			freemsg(mp);
   2096  6062   hx147065 		}
   2097  6629   zf162725 		err = ENXIO;
   2098  6062   hx147065 		goto exit;
   2099  6062   hx147065 	}
   2100  6062   hx147065 
   2101  4128   hx147065 	if (ring->queued > ring->count - 64) {
   2102  4128   hx147065 		WPI_DBG((WPI_DEBUG_TX, "wpi_send(): no txbuf\n"));
   2103  4128   hx147065 		sc->sc_need_reschedule = 1;
   2104  4128   hx147065 		mutex_exit(&sc->sc_tx_lock);
   2105  4128   hx147065 		if ((type & IEEE80211_FC0_TYPE_MASK) !=
   2106  4128   hx147065 		    IEEE80211_FC0_TYPE_DATA) {
   2107  4128   hx147065 			freemsg(mp);
   2108  4128   hx147065 		}
   2109  4128   hx147065 		sc->sc_tx_nobuf++;
   2110  6629   zf162725 		err = ENOMEM;
   2111  4128   hx147065 		goto exit;
   2112  4128   hx147065 	}
   2113  4128   hx147065 	mutex_exit(&sc->sc_tx_lock);
   2114  4128   hx147065 
   2115  4128   hx147065 	hdrlen = sizeof (struct ieee80211_frame);
   2116  4128   hx147065 
   2117  4128   hx147065 	m = allocb(msgdsize(mp) + 32, BPRI_MED);
   2118  4128   hx147065 	if (m == NULL) { /* can not alloc buf, drop this package */
   2119  4128   hx147065 		cmn_err(CE_WARN,
   2120  4128   hx147065 		    "wpi_send(): failed to allocate msgbuf\n");
   2121  4128   hx147065 		freemsg(mp);
   2122  4128   hx147065 		err = WPI_SUCCESS;
   2123  4128   hx147065 		goto exit;
   2124  4128   hx147065 	}
   2125  4128   hx147065 	for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
   2126  4128   hx147065 		mblen = MBLKL(m0);
   2127  4128   hx147065 		(void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
   2128  4128   hx147065 		off += mblen;
   2129  4128   hx147065 	}
   2130  4128   hx147065 	m->b_wptr += off;
   2131  4128   hx147065 	freemsg(mp);
   2132  4128   hx147065 
   2133  4128   hx147065 	wh = (struct ieee80211_frame *)m->b_rptr;
   2134  4128   hx147065 
   2135  4128   hx147065 	in = ieee80211_find_txnode(ic, wh->i_addr1);
   2136  4128   hx147065 	if (in == NULL) {
   2137  4128   hx147065 		cmn_err(CE_WARN, "wpi_send(): failed to find tx node\n");
   2138  4128   hx147065 		freemsg(m);
   2139  4128   hx147065 		sc->sc_tx_err++;
   2140  4128   hx147065 		err = WPI_SUCCESS;
   2141  4128   hx147065 		goto exit;
   2142  4128   hx147065 	}
   2143  5296   zf162725 
   2144  5296   zf162725 	(void) ieee80211_encap(ic, m, in);
   2145  5296   zf162725 
   2146  5296   zf162725 	cmd->code = WPI_CMD_TX_DATA;
   2147  5296   zf162725 	cmd->flags = 0;
   2148  5296   zf162725 	cmd->qid = ring->qid;
   2149  5296   zf162725 	cmd->idx = ring->cur;
   2150  5296   zf162725 
   2151  5296   zf162725 	tx = (wpi_cmd_data_t *)cmd->data;
   2152  5296   zf162725 	tx->flags = 0;
   2153  5296   zf162725 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
   2154  5296   zf162725 		tx->flags |= LE_32(WPI_TX_NEED_ACK);
   2155  5296   zf162725 	} else {
   2156  5296   zf162725 		tx->flags &= ~(LE_32(WPI_TX_NEED_ACK));
   2157  5296   zf162725 	}
   2158  5296   zf162725 
   2159  4128   hx147065 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
   2160  4128   hx147065 		k = ieee80211_crypto_encap(ic, m);
   2161  4128   hx147065 		if (k == NULL) {
   2162  4128   hx147065 			freemsg(m);
   2163  4128   hx147065 			sc->sc_tx_err++;
   2164  4128   hx147065 			err = WPI_SUCCESS;
   2165  4128   hx147065 			goto exit;
   2166  5296   zf162725 		}
   2167  5296   zf162725 
   2168  5296   zf162725 		if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
   2169  5296   zf162725 			tx->security = 2; /* for CCMP */
   2170  5296   zf162725 			tx->flags |= LE_32(WPI_TX_NEED_ACK);
   2171  5296   zf162725 			(void) memcpy(&tx->key, k->wk_key, k->wk_keylen);
   2172  4128   hx147065 		}
   2173  4128   hx147065 
   2174  4128   hx147065 		/* packet header may have moved, reset our local pointer */
   2175  4128   hx147065 		wh = (struct ieee80211_frame *)m->b_rptr;
   2176  4128   hx147065 	}
   2177  4128   hx147065 
   2178  4128   hx147065 	len = msgdsize(m);
   2179  4128   hx147065 
   2180  4128   hx147065 #ifdef DEBUG
   2181  4128   hx147065 	if (wpi_dbg_flags & WPI_DEBUG_TX)
   2182  4128   hx147065 		ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0);
   2183  4128   hx147065 #endif
   2184  4128   hx147065 
   2185  4128   hx147065 	/* pickup a rate */
   2186  4128   hx147065 	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
   2187  4128   hx147065 	    IEEE80211_FC0_TYPE_MGT) {
   2188  4128   hx147065 		/* mgmt frames are sent at the lowest available bit-rate */
   2189  4499   hx147065 		rate = 2;
   2190  4128   hx147065 	} else {
   2191  4128   hx147065 		if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
   2192  4128   hx147065 			rate = ic->ic_fixed_rate;
   2193  4128   hx147065 		} else
   2194  4128   hx147065 			rate = in->in_rates.ir_rates[in->in_txrate];
   2195  4128   hx147065 	}
   2196  4128   hx147065 	rate &= IEEE80211_RATE_VAL;
   2197  4128   hx147065 	WPI_DBG((WPI_DEBUG_RATECTL, "tx rate[%d of %d] = %x",
   2198  4128   hx147065 	    in->in_txrate, in->in_rates.ir_nrates, rate));
   2199  4128   hx147065 #ifdef WPI_BPF
   2200  4128   hx147065 #ifndef WPI_CURRENT
   2201  4128   hx147065 	if (sc->sc_drvbpf != NULL) {
   2202  4128   hx147065 #else
   2203  4128   hx147065 	if (bpf_peers_present(sc->sc_drvbpf)) {
   2204  4128   hx147065 #endif
   2205  4128   hx147065 		struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
   2206  4128   hx147065 
   2207  4128   hx147065 		tap->wt_flags = 0;
   2208  4128   hx147065 		tap->wt_chan_freq = LE_16(ic->ic_curchan->ic_freq);
   2209  4128   hx147065 		tap->wt_chan_flags = LE_16(ic->ic_curchan->ic_flags);
   2210  4128   hx147065 		tap->wt_rate = rate;
   2211  4128   hx147065 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
   2212  4128   hx147065 			tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
   2213  4128   hx147065 
   2214  4128   hx147065 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
   2215  4128   hx147065 	}
   2216  4128   hx147065 #endif
   2217  4128   hx147065 
   2218  4128   hx147065 	tx->flags |= (LE_32(WPI_TX_AUTO_SEQ));
   2219  4128   hx147065 	tx->flags |= LE_32(WPI_TX_BT_DISABLE | WPI_TX_CALIBRATION);
   2220  4128   hx147065 
   2221  4128   hx147065 	/* retrieve destination node's id */
   2222  4128   hx147065 	tx->id = IEEE80211_IS_MULTICAST(wh->i_addr1) ? WPI_ID_BROADCAST :
   2223  4128   hx147065 	    WPI_ID_BSS;
   2224  4128   hx147065 
   2225  4128   hx147065 	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
   2226  4128   hx147065 	    IEEE80211_FC0_TYPE_MGT) {
   2227  4128   hx147065 		/* tell h/w to set timestamp in probe responses */
   2228  4128   hx147065 		if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
   2229  4128   hx147065 		    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
   2230  4128   hx147065 			tx->flags |= LE_32(WPI_TX_INSERT_TSTAMP);
   2231  4128   hx147065 
   2232  4128   hx147065 		if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
   2233  4128   hx147065 		    IEEE80211_FC0_SUBTYPE_ASSOC_REQ) ||
   2234  4128   hx147065 		    ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
   2235  4128   hx147065 		    IEEE80211_FC0_SUBTYPE_REASSOC_REQ))
   2236  4128   hx147065 			tx->timeout = 3;
   2237  4128   hx147065 		else
   2238  4128   hx147065 			tx->timeout = 2;
   2239  4128   hx147065 	} else
   2240  4128   hx147065 		tx->timeout = 0;
   2241  4128   hx147065 
   2242  4128   hx147065 	tx->rate = wpi_plcp_signal(rate);
   2243  4128   hx147065 
   2244  4128   hx147065 	/* be very persistant at sending frames out */
   2245  4128   hx147065 	tx->rts_ntries = 7;
   2246  4128   hx147065 	tx->data_ntries = 15;
   2247  4128   hx147065 
   2248  4128   hx147065 	tx->cck_mask  = 0x0f;
   2249  4128   hx147065 	tx->ofdm_mask = 0xff;
   2250  4128   hx147065 	tx->lifetime  = LE_32(0xffffffff);
   2251  4128   hx147065 
   2252  4128   hx147065 	tx->len = LE_16(len);
   2253  4128   hx147065 
   2254  4128   hx147065 	/* save and trim IEEE802.11 header */
   2255  4128   hx147065 	(void) memcpy(tx + 1, m->b_rptr, hdrlen);
   2256  4128   hx147065 	m->b_rptr += hdrlen;
   2257  4128   hx147065 	(void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen);
   2258  4128   hx147065 
   2259  4128   hx147065 	WPI_DBG((WPI_DEBUG_TX, "sending data: qid=%d idx=%d len=%d", ring->qid,
   2260  4128   hx147065 	    ring->cur, len));
   2261  4128   hx147065 
   2262  4128   hx147065 	/* first scatter/gather segment is used by the tx data command */
   2263  4128   hx147065 	desc->flags = LE_32(WPI_PAD32(len) << 28 | (2) << 24);
   2264  4128   hx147065 	desc->segs[0].addr = LE_32(data->paddr_cmd);
   2265  4128   hx147065 	desc->segs[0].len  = LE_32(
   2266  4128   hx147065 	    roundup(4 + sizeof (wpi_cmd_data_t) + hdrlen, 4));
   2267  4128   hx147065 	desc->segs[1].addr = LE_32(data->dma_data.cookie.dmac_address);
   2268  4128   hx147065 	desc->segs[1].len  = LE_32(len - hdrlen);
   2269  4128   hx147065 
   2270  4128   hx147065 	WPI_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
   2271  4128   hx147065 	WPI_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
   2272  4128   hx147065 
   2273  4128   hx147065 	mutex_enter(&sc->sc_tx_lock);
   2274  4128   hx147065 	ring->queued++;
   2275  4128   hx147065 	mutex_exit(&sc->sc_tx_lock);
   2276  4128   hx147065 
   2277  4128   hx147065 	/* kick ring */
   2278  4128   hx147065 	ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT;
   2279  4128   hx147065 	WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
   2280  4128   hx147065 	freemsg(m);
   2281  4128   hx147065 	/* release node reference */
   2282  4128   hx147065 	ieee80211_free_node(in);
   2283  4128   hx147065 
   2284  4128   hx147065 	ic->ic_stats.is_tx_bytes += len;
   2285  4128   hx147065 	ic->ic_stats.is_tx_frags++;
   2286  4128   hx147065 
   2287  4128   hx147065 	if (sc->sc_tx_timer == 0)
   2288  4128   hx147065 		sc->sc_tx_timer = 5;
   2289  4128   hx147065 exit:
   2290  4128   hx147065 	return (err);
   2291  4128   hx147065 }
   2292  4128   hx147065 
   2293  4128   hx147065 static void
   2294  4128   hx147065 wpi_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
   2295  4128   hx147065 {
   2296  4128   hx147065 	wpi_sc_t	*sc  = (wpi_sc_t *)arg;
   2297  4128   hx147065 	ieee80211com_t	*ic = &sc->sc_ic;
   2298  4128   hx147065 	int		err;
   2299  4128   hx147065 
   2300  4128   hx147065 	err = ieee80211_ioctl(ic, wq, mp);
   2301  4128   hx147065 	if (err == ENETRESET) {
   2302  6199   hx147065 		/*
   2303  6199   hx147065 		 * This is special for the hidden AP connection.
   2304  6199   hx147065 		 * In any case, we should make sure only one 'scan'
   2305  6199   hx147065 		 * in the driver for a 'connect' CLI command. So
   2306  6199   hx147065 		 * when connecting to a hidden AP, the scan is just
   2307  6199   hx147065 		 * sent out to the air when we know the desired
   2308  6199   hx147065 		 * essid of the AP we want to connect.
   2309  6199   hx147065 		 */
   2310  6199   hx147065 		if (ic->ic_des_esslen) {
   2311  7865  Pengcheng 			if (sc->sc_flags & WPI_F_RUNNING) {
   2312  7865  Pengcheng 				wpi_m_stop(sc);
   2313  7865  Pengcheng 				(void) wpi_m_start(sc);
   2314  7865  Pengcheng 				(void) ieee80211_new_state(ic,
   2315  7865  Pengcheng 				    IEEE80211_S_SCAN, -1);
   2316  7865  Pengcheng 			}
   2317  6199   hx147065 		}
   2318  4128   hx147065 	}
   2319  4128   hx147065 }
   2320  4128   hx147065 
   2321  7663    Sowmini /*
   2322  7663    Sowmini  * Callback functions for get/set properties
   2323  7663    Sowmini  */
   2324  8118  Vasumathi /* ARGSUSED */
   2325  7663    Sowmini static int
   2326  7663    Sowmini wpi_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_name,
   2327  8118  Vasumathi     uint_t pr_flags, uint_t wldp_length, void *wldp_buf, uint_t *perm)
   2328  7663    Sowmini {
   2329  7663    Sowmini 	int		err = 0;
   2330  7663    Sowmini 	wpi_sc_t	*sc = (wpi_sc_t *)arg;
   2331  7663    Sowmini 
   2332  7663    Sowmini 	err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_name,
   2333  8118  Vasumathi 	    pr_flags, wldp_length, wldp_buf, perm);
   2334  7663    Sowmini 
   2335  7663    Sowmini 	return (err);
   2336  7663    Sowmini }
   2337  7663    Sowmini static int
   2338  7663    Sowmini wpi_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_name,
   2339  7663    Sowmini     uint_t wldp_length, const void *wldp_buf)
   2340  7663    Sowmini {
   2341  7663    Sowmini 	int		err;
   2342  7663    Sowmini 	wpi_sc_t	*sc = (wpi_sc_t *)arg;
   2343  7663    Sowmini 	ieee80211com_t  *ic = &sc->sc_ic;
   2344  7663    Sowmini 
   2345  7663    Sowmini 	err = ieee80211_setprop(ic, pr_name, wldp_pr_name,
   2346  7663    Sowmini 	    wldp_length, wldp_buf);
   2347  7663    Sowmini 
   2348  7663    Sowmini 	if (err == ENETRESET) {
   2349  7663    Sowmini 		if (ic->ic_des_esslen) {
   2350  7865  Pengcheng 			if (sc->sc_flags & WPI_F_RUNNING) {
   2351  7865  Pengcheng 				wpi_m_stop(sc);
   2352  7865  Pengcheng 				(void) wpi_m_start(sc);
   2353  7865  Pengcheng 				(void) ieee80211_new_state(ic,
   2354  7865  Pengcheng 				    IEEE80211_S_SCAN, -1);
   2355  7865  Pengcheng 			}
   2356  7663    Sowmini 		}
   2357  7663    Sowmini 
   2358  7663    Sowmini 		err = 0;
   2359  7663    Sowmini 	}
   2360  7663    Sowmini 
   2361  7663    Sowmini 	return (err);
   2362  7663    Sowmini }
   2363  7663    Sowmini 
   2364  4128   hx147065 /*ARGSUSED*/
   2365  4128   hx147065 static int
   2366  4128   hx147065 wpi_m_stat(void *arg, uint_t stat, uint64_t *val)
   2367  4128   hx147065 {
   2368  4128   hx147065 	wpi_sc_t	*sc  = (wpi_sc_t *)arg;
   2369  4128   hx147065 	ieee80211com_t	*ic = &sc->sc_ic;
   2370  7865  Pengcheng 	ieee80211_node_t *in;
   2371  4128   hx147065 
   2372  4128   hx147065 	mutex_enter(&sc->sc_glock);
   2373  4128   hx147065 	switch (stat) {
   2374  4128   hx147065 	case MAC_STAT_IFSPEED:
   2375  7865  Pengcheng 		in = ic->ic_bss;
   2376  4128   hx147065 		*val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
   2377  7865  Pengcheng 		    IEEE80211_RATE(in->in_txrate) :
   2378  7865  Pengcheng 		    ic->ic_fixed_rate) / 2 * 1000000;
   2379  4128   hx147065 		break;
   2380  4128   hx147065 	case MAC_STAT_NOXMTBUF:
   2381  4128   hx147065 		*val = sc->sc_tx_nobuf;
   2382  4128   hx147065 		break;
   2383  4128   hx147065 	case MAC_STAT_NORCVBUF:
   2384  4128   hx147065 		*val = sc->sc_rx_nobuf;
   2385  4128   hx147065 		break;
   2386  4128   hx147065 	case MAC_STAT_IERRORS:
   2387  4128   hx147065 		*val = sc->sc_rx_err;
   2388  4128   hx147065 		break;
   2389  4128   hx147065 	case MAC_STAT_RBYTES:
   2390  4128   hx147065 		*val = ic->ic_stats.is_rx_bytes;
   2391  4128   hx147065 		break;
   2392  4128   hx147065 	case MAC_STAT_IPACKETS:
   2393  4128   hx147065 		*val = ic->ic_stats.is_rx_frags;
   2394  4128   hx147065 		break;
   2395  4128   hx147065 	case MAC_STAT_OBYTES:
   2396  4128   hx147065 		*val = ic->ic_stats.is_tx_bytes;
   2397  4128   hx147065 		break;
   2398  4128   hx147065 	case MAC_STAT_OPACKETS:
   2399  4128   hx147065 		*val = ic->ic_stats.is_tx_frags;
   2400  4128   hx147065 		break;
   2401  4128   hx147065 	case MAC_STAT_OERRORS:
   2402  4128   hx147065 	case WIFI_STAT_TX_FAILED:
   2403  4128   hx147065 		*val = sc->sc_tx_err;
   2404  4128   hx147065 		break;
   2405  4128   hx147065 	case WIFI_STAT_TX_RETRANS:
   2406  4128   hx147065 		*val = sc->sc_tx_retries;
   2407  4128   hx147065 		break;
   2408  4128   hx147065 	case WIFI_STAT_FCS_ERRORS:
   2409  4128   hx147065 	case WIFI_STAT_WEP_ERRORS:
   2410  4128   hx147065 	case WIFI_STAT_TX_FRAGS:
   2411  4128   hx147065 	case WIFI_STAT_MCAST_TX:
   2412  4128   hx147065 	case WIFI_STAT_RTS_SUCCESS:
   2413  4128   hx147065 	case WIFI_STAT_RTS_FAILURE:
   2414  4128   hx147065 	case WIFI_STAT_ACK_FAILURE:
   2415  4128   hx147065 	case WIFI_STAT_RX_FRAGS:
   2416  4128   hx147065 	case WIFI_STAT_MCAST_RX:
   2417  4128   hx147065 	case WIFI_STAT_RX_DUPS:
   2418  4128   hx147065 		mutex_exit(&sc->sc_glock);
   2419  4128   hx147065 		return (ieee80211_stat(ic, stat, val));
   2420  4128   hx147065 	default:
   2421  4128   hx147065 		mutex_exit(&sc->sc_glock);
   2422  4128   hx147065 		return (ENOTSUP);
   2423  4128   hx147065 	}
   2424  4128   hx147065 	mutex_exit(&sc->sc_glock);
   2425  4128   hx147065 
   2426  4128   hx147065 	return (WPI_SUCCESS);
   2427  4128   hx147065 
   2428  4128   hx147065 }
   2429  4128   hx147065 
   2430  4128   hx147065 static int
   2431  4128   hx147065 wpi_m_start(void *arg)
   2432  4128   hx147065 {
   2433  4128   hx147065 	wpi_sc_t *sc = (wpi_sc_t *)arg;
   2434  4128   hx147065 	ieee80211com_t	*ic = &sc->sc_ic;
   2435  4128   hx147065 	int err;
   2436  4128   hx147065 
   2437  4128   hx147065 	err = wpi_init(sc);
   2438  4128   hx147065 	if (err != WPI_SUCCESS) {
   2439  4128   hx147065 		wpi_stop(sc);
   2440  4128   hx147065 		DELAY(1000000);
   2441  4128   hx147065 		err = wpi_init(sc);
   2442  4128   hx147065 	}
   2443  6062   hx147065 
   2444  6062   hx147065 	if (err) {
   2445  6062   hx147065 		/*
   2446  6062   hx147065 		 * The hw init err(eg. RF is OFF). Return Success to make
   2447  6062   hx147065 		 * the 'plumb' succeed. The wpi_thread() tries to re-init
   2448  6062   hx147065 		 * background.
   2449  6062   hx147065 		 */
   2450  6062   hx147065 		mutex_enter(&sc->sc_glock);
   2451  6062   hx147065 		sc->sc_flags |= WPI_F_HW_ERR_RECOVER;
   2452  6062   hx147065 		mutex_exit(&sc->sc_glock);
   2453  6062   hx147065 		return (WPI_SUCCESS);
   2454  6062   hx147065 	}
   2455  4128   hx147065 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
   2456  6062   hx147065 	mutex_enter(&sc->sc_glock);
   2457  6062   hx147065 	sc->sc_flags |= WPI_F_RUNNING;
   2458  6062   hx147065 	mutex_exit(&sc->sc_glock);
   2459  4128   hx147065 
   2460  6062   hx147065 	return (WPI_SUCCESS);
   2461  4128   hx147065 }
   2462  4128   hx147065 
   2463  4128   hx147065 static void
   2464  4128   hx147065 wpi_m_stop(void *arg)
   2465  4128   hx147065 {
   2466  4128   hx147065 	wpi_sc_t *sc = (wpi_sc_t *)arg;
   2467  4128   hx147065 	ieee80211com_t	*ic = &sc->sc_ic;
   2468  4128   hx147065 
   2469  4128   hx147065 	wpi_stop(sc);
   2470  4128   hx147065 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
   2471  4128   hx147065 	mutex_enter(&sc->sc_mt_lock);
   2472  4128   hx147065 	sc->sc_flags &= ~WPI_F_HW_ERR_RECOVER;
   2473  4128   hx147065 	sc->sc_flags &= ~WPI_F_RATE_AUTO_CTL;
   2474  4128   hx147065 	mutex_exit(&sc->sc_mt_lock);
   2475  6062   hx147065 	mutex_enter(&sc->sc_glock);
   2476  6062   hx147065 	sc->sc_flags &= ~WPI_F_RUNNING;
   2477  6062   hx147065 	mutex_exit(&sc->sc_glock);
   2478  4128   hx147065 }
   2479  4128   hx147065 
   2480  4128   hx147065 /*ARGSUSED*/
   2481  4128   hx147065 static int
   2482  4128   hx147065 wpi_m_unicst(void *arg, const uint8_t *macaddr)
   2483  4128   hx147065 {
   2484  4128   hx147065 	wpi_sc_t *sc = (wpi_sc_t *)arg;
   2485  4128   hx147065 	ieee80211com_t	*ic = &sc->sc_ic;
   2486  4128   hx147065 	int err;
   2487  4128   hx147065 
   2488  4128   hx147065 	if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) {
   2489  4128   hx147065 		IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
   2490  4128   hx147065 		mutex_enter(&sc->sc_glock);
   2491  4128   hx147065 		err = wpi_config(sc);
   2492  4128   hx147065 		mutex_exit(&sc->sc_glock);
   2493  4128   hx147065 		if (err != WPI_SUCCESS) {
   2494  4128   hx147065 			cmn_err(CE_WARN,
   2495  4128   hx147065 			    "wpi_m_unicst(): "
   2496  4128   hx147065 			    "failed to configure device\n");
   2497  4128   hx147065 			goto fail;
   2498  4128   hx147065 		}
   2499  4128   hx147065 	}
   2500  4128   hx147065 	return (WPI_SUCCESS);
   2501  4128   hx147065 fail:
   2502  4128   hx147065 	return (err);
   2503  4128   hx147065 }
   2504  4128   hx147065 
   2505  4128   hx147065 /*ARGSUSED*/
   2506  4128   hx147065 static int
   2507  4128   hx147065 wpi_m_multicst(void *arg, boolean_t add, const uint8_t *m)
   2508  4128   hx147065 {
   2509  4128   hx147065 	return (WPI_SUCCESS);
   2510  4128   hx147065 }
   2511  4128   hx147065 
   2512  4128   hx147065 /*ARGSUSED*/
   2513  4128   hx147065 static int
   2514  4128   hx147065 wpi_m_promisc(void *arg, boolean_t on)
   2515  4128   hx147065 {
   2516  4128   hx147065 	return (WPI_SUCCESS);
   2517  4128   hx147065 }
   2518  4128   hx147065 
   2519  4128   hx147065 static void
   2520  4128   hx147065 wpi_thread(wpi_sc_t *sc)
   2521  4128   hx147065 {
   2522  4128   hx147065 	ieee80211com_t	*ic = &sc->sc_ic;
   2523  4128   hx147065 	clock_t clk;
   2524  4128   hx147065 	int times = 0, err, n = 0, timeout = 0;
   2525  6062   hx147065 	uint32_t tmp;
   2526  4128   hx147065 
   2527  4128   hx147065 	mutex_enter(&sc->sc_mt_lock);
   2528  4128   hx147065 	while (sc->sc_mf_thread_switch) {
   2529  6062   hx147065 		tmp = WPI_READ(sc, WPI_GPIO_CTL);
   2530  6062   hx147065 		if (tmp & WPI_GPIO_HW_RF_KILL) {
   2531  6062   hx147065 			sc->sc_flags &= ~WPI_F_RADIO_OFF;
   2532  6062   hx147065 		} else {
   2533  6062   hx147065 			sc->sc_flags |= WPI_F_RADIO_OFF;
   2534  6062   hx147065 		}
   2535  6062   hx147065 		/*
   2536  6062   hx147065 		 * If in SUSPEND or the RF is OFF, do nothing
   2537  6062   hx147065 		 */
   2538  6062   hx147065 		if ((sc->sc_flags & WPI_F_SUSPEND) ||
   2539  6062   hx147065 		    (sc->sc_flags & WPI_F_RADIO_OFF)) {
   2540  6062   hx147065 			mutex_exit(&sc->sc_mt_lock);
   2541  6062   hx147065 			delay(drv_usectohz(100000));
   2542  6062   hx147065 			mutex_enter(&sc->sc_mt_lock);
   2543  6062   hx147065 			continue;
   2544  6062   hx147065 		}
   2545  6062   hx147065 
   2546  4128   hx147065 		/*
   2547  4128   hx147065 		 * recovery fatal error
   2548  4128   hx147065 		 */
   2549  4128   hx147065 		if (ic->ic_mach &&
   2550  4128   hx147065 		    (sc->sc_flags & WPI_F_HW_ERR_RECOVER)) {
   2551  4128   hx147065 
   2552  4128   hx147065 			WPI_DBG((WPI_DEBUG_FW,
   2553  4128   hx147065 			    "wpi_thread(): "
   2554  4128   hx147065 			    "try to recover fatal hw error: %d\n", times++));
   2555  4128   hx147065 
   2556  4128   hx147065 			wpi_stop(sc);
   2557  7865  Pengcheng 
   2558  8902  Pengcheng 			if (WPI_CHK_FAST_RECOVER(sc)) {
   2559  8902  Pengcheng 				/* save runtime configuration */
   2560  8902  Pengcheng 				bcopy(&sc->sc_config, &sc->sc_config_save,
   2561  8902  Pengcheng 				    sizeof (sc->sc_config));
   2562  8902  Pengcheng 			} else {
   2563  8902  Pengcheng 				mutex_exit(&sc->sc_mt_lock);
   2564  8902  Pengcheng 				ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
   2565  8902  Pengcheng 				delay(drv_usectohz(2000000));
   2566  8902  Pengcheng 				mutex_enter(&sc->sc_mt_lock);
   2567  8902  Pengcheng 			}
   2568  4128   hx147065 
   2569  4128   hx147065 			err = wpi_init(sc);
   2570  4128   hx147065 			if (err != WPI_SUCCESS) {
   2571  4128   hx147065 				n++;
   2572  4128   hx147065 				if (n < 3)
   2573  4128   hx147065 					continue;
   2574  4128   hx147065 			}
   2575  4128   hx147065 			n = 0;
   2576  6062   hx147065 			if (!err)
   2577  6062   hx147065 				sc->sc_flags |= WPI_F_RUNNING;
   2578  8902  Pengcheng 
   2579  8902  Pengcheng 			if (!WPI_CHK_FAST_RECOVER(sc) ||
   2580  8902  Pengcheng 			    wpi_fast_recover(sc) != WPI_SUCCESS) {
   2581  8902  Pengcheng 				sc->sc_flags &= ~WPI_F_HW_ERR_RECOVER;
   2582  8902  Pengcheng 
   2583  8902  Pengcheng 				mutex_exit(&sc->sc_mt_lock);
   2584  8902  Pengcheng 				delay(drv_usectohz(2000000));
   2585  8902  Pengcheng 				if (sc->sc_ostate != IEEE80211_S_INIT)
   2586  8902  Pengcheng 					ieee80211_new_state(ic,
   2587  8902  Pengcheng 					    IEEE80211_S_SCAN, 0);
   2588  8902  Pengcheng 				mutex_enter(&sc->sc_mt_lock);
   2589  8902  Pengcheng 			}
   2590  7865  Pengcheng 		}
   2591  7865  Pengcheng 
   2592  8349  Pengcheng 		if (ic->ic_mach && (sc->sc_flags & WPI_F_LAZY_RESUME)) {
   2593  8349  Pengcheng 			WPI_DBG((WPI_DEBUG_RESUME,
   2594  8349  Pengcheng 			    "wpi_thread(): "
   2595  8349  Pengcheng 			    "lazy resume\n"));
   2596  8349  Pengcheng 			sc->sc_flags &= ~WPI_F_LAZY_RESUME;
   2597  8349  Pengcheng 			mutex_exit(&sc->sc_mt_lock);
   2598  8349  Pengcheng 			/*
   2599  8349  Pengcheng 			 * NB: under WPA mode, this call hangs (door problem?)
   2600  8349  Pengcheng 			 * when called in wpi_attach() and wpi_detach() while
   2601  8349  Pengcheng 			 * system is in the procedure of CPR. To be safe, let
   2602  8349  Pengcheng 			 * the thread do this.
   2603  8349  Pengcheng 			 */
   2604  8349  Pengcheng 			ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
   2605  8349  Pengcheng 			mutex_enter(&sc->sc_mt_lock);
   2606  8349  Pengcheng 		}
   2607  8349  Pengcheng 
   2608  7865  Pengcheng 		/*
   2609  7865  Pengcheng 		 * scan next channel
   2610  7865  Pengcheng 		 */
   2611  7865  Pengcheng 		if (ic->ic_mach &&
   2612  7865  Pengcheng 		    (sc->sc_flags & WPI_F_SCANNING) && sc->sc_scan_next) {
   2613  7865  Pengcheng 
   2614  7865  Pengcheng 			WPI_DBG((WPI_DEBUG_SCAN,
   2615  7865  Pengcheng 			    "wpi_thread(): "
   2616  7865  Pengcheng 			    "wait for probe response\n"));
   2617  7865  Pengcheng 
   2618  7865  Pengcheng 			sc->sc_scan_next--;
   2619  7865  Pengcheng 			mutex_exit(&sc->sc_mt_lock);
   2620  7865  Pengcheng 			delay(drv_usectohz(200000));
   2621  8349  Pengcheng 			if (sc->sc_flags & WPI_F_SCANNING)
   2622  8349  Pengcheng 				ieee80211_next_scan(ic);
   2623  4128   hx147065 			mutex_enter(&sc->sc_mt_lock);
   2624  4128   hx147065 		}
   2625  4128   hx147065 
   2626  4128   hx147065 		/*
   2627  4128   hx147065 		 * rate ctl
   2628  4128   hx147065 		 */
   2629  4128   hx147065 		if (ic->ic_mach &&
   2630  4128   hx147065 		    (sc->sc_flags & WPI_F_RATE_AUTO_CTL)) {
   2631  4128   hx147065 			clk = ddi_get_lbolt();
   2632  4128   hx147065 			if (clk > sc->sc_clk + drv_usectohz(500000)) {
   2633  4128   hx147065 				wpi_amrr_timeout(sc);
   2634  4128   hx147065 			}
   2635  4128   hx147065 		}
   2636  4128   hx147065 		mutex_exit(&sc->sc_mt_lock);
   2637  4128   hx147065 		delay(drv_usectohz(100000));
   2638  4128   hx147065 		mutex_enter(&sc->sc_mt_lock);
   2639  4128   hx147065 		if (sc->sc_tx_timer) {
   2640  4128   hx147065 			timeout++;
   2641  4128   hx147065 			if (timeout == 10) {
   2642  4128   hx147065 				sc->sc_tx_timer--;
   2643  4128   hx147065 				if (sc->sc_tx_timer == 0) {
   2644  4128   hx147065 					sc->sc_flags |= WPI_F_HW_ERR_RECOVER;
   2645  4128   hx147065 					sc->sc_ostate = IEEE80211_S_RUN;
   2646  7865  Pengcheng 					WPI_DBG((WPI_DEBUG_FW,
   2647  7865  Pengcheng 					    "wpi_thread(): send fail\n"));
   2648  4128   hx147065 				}
   2649  4128   hx147065 				timeout = 0;
   2650  4128   hx147065 			}
   2651  4128   hx147065 		}
   2652  4128   hx147065 	}
   2653  4128   hx147065 	sc->sc_mf_thread = NULL;
   2654  4128   hx147065 	cv_signal(&sc->sc_mt_cv);
   2655  4128   hx147065 	mutex_exit(&sc->sc_mt_lock);
   2656  4128   hx147065 }
   2657  4128   hx147065 
   2658  4128   hx147065 /*
   2659  4128   hx147065  * Extract various information from EEPROM.
   2660  4128   hx147065  */
   2661  4128   hx147065 static void
   2662  4128   hx147065 wpi_read_eeprom(wpi_sc_t *sc)
   2663  4128   hx147065 {
   2664  4128   hx147065 	ieee80211com_t *ic = &sc->sc_ic;
   2665  4128   hx147065 	uint16_t val;
   2666  4128   hx147065 	int i;
   2667  4128   hx147065 
   2668  4128   hx147065 	/* read MAC address */
   2669  4128   hx147065 	val = wpi_read_prom_word(sc, WPI_EEPROM_MAC + 0);
   2670  4128   hx147065 	ic->ic_macaddr[0] = val & 0xff;
   2671  4128   hx147065 	ic->ic_macaddr[1] = val >> 8;
   2672  4128   hx147065 	val = wpi_read_prom_word(sc, WPI_EEPROM_MAC + 1);
   2673  4128   hx147065 	ic->ic_macaddr[2] = val & 0xff;
   2674  4128   hx147065 	ic->ic_macaddr[3] = val >> 8;
   2675  4128   hx147065 	val = wpi_read_prom_word(sc, WPI_EEPROM_MAC + 2);
   2676  4128   hx147065 	ic->ic_macaddr[4] = val & 0xff;
   2677  4128   hx147065 	ic->ic_macaddr[5] = val >> 8;
   2678  4128   hx147065 
   2679  4128   hx147065 	WPI_DBG((WPI_DEBUG_EEPROM,
   2680  4128   hx147065 	    "mac:%2x:%2x:%2x:%2x:%2x:%2x\n",
   2681  4128   hx147065 	    ic->ic_macaddr[0], ic->ic_macaddr[1],
   2682  4128   hx147065 	    ic->ic_macaddr[2], ic->ic_macaddr[3],
   2683  4128   hx147065 	    ic->ic_macaddr[4], ic->ic_macaddr[5]));
   2684  4128   hx147065 	/* read power settings for 2.4GHz channels */
   2685  4128   hx147065 	for (i = 0; i < 14; i++) {
   2686  4128   hx147065 		sc->sc_pwr1[i] = wpi_read_prom_word(sc, WPI_EEPROM_PWR1 + i);
   2687  4128   hx147065 		sc->sc_pwr2[i] = wpi_read_prom_word(sc, WPI_EEPROM_PWR2 + i);
   2688  4128   hx147065 		WPI_DBG((WPI_DEBUG_EEPROM,
   2689  4128   hx147065 		    "channel %d pwr1 0x%04x pwr2 0x%04x\n", i + 1,
   2690  4128   hx147065 		    sc->sc_pwr1[i], sc->sc_pwr2[i]));
   2691  4128   hx147065 	}
   2692  4128   hx147065 }
   2693  4128   hx147065 
   2694  4128   hx147065 /*
   2695  4128   hx147065  * Send a command to the firmware.
   2696  4128   hx147065  */
   2697  4128   hx147065 static int
   2698  4128   hx147065 wpi_cmd(wpi_sc_t *sc, int code, const void *buf, int size, int async)
   2699  4128   hx147065 {
   2700  4128   hx147065 	wpi_tx_ring_t *ring = &sc->sc_cmdq;
   2701  4128   hx147065 	wpi_tx_desc_t *desc;
   2702  4128   hx147065 	wpi_tx_cmd_t *cmd;
   2703  4128   hx147065 
   2704  4128   hx147065 	ASSERT(size <= sizeof (cmd->data));
   2705  4128   hx147065 	ASSERT(mutex_owned(&sc->sc_glock));
   2706  4128   hx147065 
   2707  4128   hx147065 	WPI_DBG((WPI_DEBUG_CMD, "wpi_cmd() # code[%d]", code));
   2708  4128   hx147065 	desc = ring->data[ring->cur].desc;
   2709  4128   hx147065 	cmd = ring->data[ring->cur].cmd;
   2710  4128   hx147065 
   2711  4128   hx147065 	cmd->code = (uint8_t)code;
   2712  4128   hx147065 	cmd->flags = 0;
   2713  4128   hx147065 	cmd->qid = ring->qid;
   2714  4128   hx147065 	cmd->idx = ring->cur;
   2715  4128   hx147065 	(void) memcpy(cmd->data, buf, size);
   2716  4128   hx147065 
   2717  4128   hx147065 	desc->flags = LE_32(WPI_PAD32(size) << 28 | 1 << 24);
   2718  4128   hx147065 	desc->segs[0].addr = ring->data[ring->cur].paddr_cmd;
   2719  4128   hx147065 	desc->segs[0].len  = 4 + size;
   2720  4128   hx147065 
   2721  4128   hx147065 	/* kick cmd ring */
   2722  4128   hx147065 	ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
   2723  4128   hx147065 	WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
   2724  4128   hx147065 
   2725  4128   hx147065 	if (async)
   2726  4128   hx147065 		return (WPI_SUCCESS);
   2727  4128   hx147065 	else {
   2728  4128   hx147065 		clock_t clk;
   2729  4128   hx147065 		sc->sc_flags &= ~WPI_F_CMD_DONE;
   2730  4128   hx147065 		clk = ddi_get_lbolt() + drv_usectohz(2000000);
   2731  4128   hx147065 		while (!(sc->sc_flags & WPI_F_CMD_DONE)) {
   2732  4128   hx147065 			if (cv_timedwait(&sc->sc_cmd_cv, &sc->sc_glock, clk)
   2733  4128   hx147065 			    < 0)
   2734  4128   hx147065 				break;
   2735  4128   hx147065 		}
   2736  4128   hx147065 		if (sc->sc_flags & WPI_F_CMD_DONE)
   2737  4128   hx147065 			return (WPI_SUCCESS);
   2738  4128   hx147065 		else
   2739  4128   hx147065 			return (WPI_FAIL);
   2740  4128   hx147065 	}
   2741  4128   hx147065 }
   2742  4128   hx147065 
   2743  4128   hx147065 /*
   2744  4128   hx147065  * Configure h/w multi-rate retries.
   2745  4128   hx147065  */
   2746  4128   hx147065 static int
   2747  4128   hx147065 wpi_mrr_setup(wpi_sc_t *sc)
   2748  4128   hx147065 {
   2749  4128   hx147065 	wpi_mrr_setup_t mrr;
   2750  4128   hx147065 	int i, err;
   2751  4128   hx147065 
   2752  4128   hx147065 	/* CCK rates (not used with 802.11a) */
   2753  4128   hx147065 	for (i = WPI_CCK1; i <= WPI_CCK11; i++) {
   2754  4128   hx147065 		mrr.rates[i].flags = 0;
   2755  4128   hx147065 		mrr.rates[i].signal = wpi_ridx_to_signal[i];
   2756  4128   hx147065 		/* fallback to the immediate lower CCK rate (if any) */
   2757  4128   hx147065 		mrr.rates[i].next = (i == WPI_CCK1) ? WPI_CCK1 : i - 1;
   2758  4128   hx147065 		/* try one time at this rate before falling back to "next" */
   2759  4128   hx147065 		mrr.rates[i].ntries = 1;
   2760  4128   hx147065 	}
   2761  4128   hx147065 
   2762  4128   hx147065 	/* OFDM rates (not used with 802.11b) */
   2763  4128   hx147065 	for (i = WPI_OFDM6; i <= WPI_OFDM54; i++) {
   2764  4128   hx147065 		mrr.rates[i].flags = 0;
   2765  4128   hx147065 		mrr.rates[i].signal = wpi_ridx_to_signal[i];
   2766  4128   hx147065 		/* fallback to the immediate lower OFDM rate (if any) */
   2767  4128   hx147065 		mrr.rates[i].next = (i == WPI_OFDM6) ? WPI_OFDM6 : i - 1;
   2768  4128   hx147065 		/* try one time at this rate before falling back to "next" */
   2769  4128   hx147065 		mrr.rates[i].ntries = 1;
   2770  4128   hx147065 	}
   2771  4128   hx147065 
   2772  4128   hx147065 	/* setup MRR for control frames */
   2773  4128   hx147065 	mrr.which = LE_32(WPI_MRR_CTL);
   2774  4128   hx147065 	err = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof (mrr), 1);
   2775  4128   hx147065 	if (err != WPI_SUCCESS) {
   2776  4128   hx147065 		WPI_DBG((WPI_DEBUG_MRR,
   2777  4128   hx147065 		    "could not setup MRR for control frames\n"));
   2778  4128   hx147065 		return (err);
   2779  4128   hx147065 	}
   2780  4128   hx147065 
   2781  4128   hx147065 	/* setup MRR for data frames */
   2782  4128   hx147065 	mrr.which = LE_32(WPI_MRR_DATA);
   2783  4128   hx147065 	err = wpi_cmd(sc, WPI_CMD_MRR_SETUP, &mrr, sizeof (mrr), 1);
   2784  4128   hx147065 	if (err != WPI_SUCCESS) {
   2785  4128   hx147065 		WPI_DBG((WPI_DEBUG_MRR,
   2786  4128   hx147065 		    "could not setup MRR for data frames\n"));
   2787  4128   hx147065 		return (err);
   2788  4128   hx147065 	}
   2789  4128   hx147065 
   2790  4128   hx147065 	return (WPI_SUCCESS);
   2791  4128   hx147065 }
   2792  4128   hx147065 
   2793  4128   hx147065 static void
   2794  4128   hx147065 wpi_set_led(wpi_sc_t *sc, uint8_t which, uint8_t off, uint8_t on)
   2795  4128   hx147065 {
   2796  4128   hx147065 	wpi_cmd_led_t led;
   2797  4128   hx147065 
   2798  4128   hx147065 	led.which = which;
   2799  4128   hx147065 	led.unit = LE_32(100000);	/* on/off in unit of 100ms */
   2800  4128   hx147065 	led.off = off;
   2801  4128   hx147065 	led.on = on;
   2802  4128   hx147065 
   2803  4128   hx147065 	(void) wpi_cmd(sc, WPI_CMD_SET_LED, &led, sizeof (led), 1);
   2804  4128   hx147065 }
   2805  4128   hx147065 
   2806  4128   hx147065 static int
   2807  4128   hx147065 wpi_auth(wpi_sc_t *sc)
   2808  4128   hx147065 {
   2809  4128   hx147065 	ieee80211com_t *ic = &sc->sc_ic;
   2810  4128   hx147065 	ieee80211_node_t *in = ic->ic_bss;
   2811  4128   hx147065 	wpi_node_t node;
   2812  4128   hx147065 	int err;
   2813  4128   hx147065 
   2814  4128   hx147065 	/* update adapter's configuration */
   2815  4128   hx147065 	IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
   2816  4128   hx147065 	sc->sc_config.chan = ieee80211_chan2ieee(ic, in->in_chan);
   2817  4128   hx147065 	if (ic->ic_curmode == IEEE80211_MODE_11B) {
   2818  4128   hx147065 		sc->sc_config.cck_mask  = 0x03;
   2819  4128   hx147065 		sc->sc_config.ofdm_mask = 0;
   2820  4128   hx147065 	} else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
   2821  4128   hx147065 	    (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
   2822  4128   hx147065 		sc->sc_config.cck_mask  = 0;
   2823  4128   hx147065 		sc->sc_config.ofdm_mask = 0x15;
   2824  4128   hx147065 	} else {	/* assume 802.11b/g */
   2825  4128   hx147065 		sc->sc_config.cck_mask  = 0x0f;
   2826  5453   hx147065 		sc->sc_config.ofdm_mask = 0xff;
   2827  4128   hx147065 	}
   2828  4128   hx147065 
   2829  4128   hx147065 	WPI_DBG((WPI_DEBUG_80211, "config chan %d flags %x cck %x ofdm %x"
   2830  4128   hx147065 	    " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n",
   2831  4128   hx147065 	    sc->sc_config.chan, sc->sc_config.flags,
   2832  4128   hx147065 	    sc->sc_config.cck_mask, sc->sc_config.ofdm_mask,
   2833  4128   hx147065 	    sc->sc_config.bssid[0], sc->sc_config.bssid[1],
   2834  4128   hx147065 	    sc->sc_config.bssid[2], sc->sc_config.bssid[3],
   2835  4128   hx147065 	    sc->sc_config.bssid[4], sc->sc_config.bssid[5]));
   2836  4128   hx147065 	err = wpi_cmd(sc, WPI_CMD_CONFIGURE, &sc->sc_config,
   2837  4128   hx147065 	    sizeof (wpi_config_t), 1);
   2838  4128   hx147065 	if (err != WPI_SUCCESS) {
   2839  4128   hx147065 		cmn_err(CE_WARN, "wpi_auth(): failed to configurate chan%d\n",
   2840  4128   hx147065 		    sc->sc_config.chan);
   2841  4128   hx147065 		return (err);
   2842  4128   hx147065 	}
   2843  4128   hx147065 
   2844  4128   hx147065 	/* add default node */
   2845  4128   hx147065 	(void) memset(&node, 0, sizeof (node));
   2846  4128   hx147065 	IEEE80211_ADDR_COPY(node.bssid, in->in_bssid);
   2847  4128   hx147065 	node.id = WPI_ID_BSS;
   2848  4128   hx147065 	node.rate = wpi_plcp_signal(2);
   2849  4128   hx147065 	err = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof (node), 1);
   2850  4128   hx147065 	if (err != WPI_SUCCESS) {
   2851  4128   hx147065 		cmn_err(CE_WARN, "wpi_auth(): failed to add BSS node\n");
   2852  4128   hx147065 		return (err);
   2853  4128   hx147065 	}
   2854  4128   hx147065 
   2855  4128   hx147065 	err = wpi_mrr_setup(sc);
   2856  4128   hx147065 	if (err != WPI_SUCCESS) {
   2857  4128   hx147065 		cmn_err(CE_WARN, "wpi_auth(): failed to setup MRR\n");
   2858  4128   hx147065 		return (err);
   2859  4128   hx147065 	}
   2860  4128   hx147065 
   2861  4128   hx147065 	return (WPI_SUCCESS);
   2862  4128   hx147065 }
   2863  4128   hx147065 
   2864  4128   hx147065 /*
   2865  4128   hx147065  * Send a scan request to the firmware.
   2866  4128   hx147065  */
   2867  4128   hx147065 static int
   2868  4128   hx147065 wpi_scan(wpi_sc_t *sc)
   2869  4128   hx147065 {
   2870  4128   hx147065 	ieee80211com_t *ic = &sc->sc_ic;
   2871  4128   hx147065 	wpi_tx_ring_t *ring = &sc->sc_cmdq;
   2872  4128   hx147065 	wpi_tx_desc_t *desc;
   2873  4128   hx147065 	wpi_tx_data_t *data;
   2874  4128   hx147065 	wpi_tx_cmd_t *cmd;
   2875  4128   hx147065 	wpi_scan_hdr_t *hdr;
   2876  4128   hx147065 	wpi_scan_chan_t *chan;
   2877  4128   hx147065 	struct ieee80211_frame *wh;
   2878  4128   hx147065 	ieee80211_node_t *in = ic->ic_bss;
   2879  7865  Pengcheng 	uint8_t essid[IEEE80211_NWID_LEN+1];
   2880  4128   hx147065 	struct ieee80211_rateset *rs;
   2881  4128   hx147065 	enum ieee80211_phymode mode;
   2882  4128   hx147065 	uint8_t *frm;
   2883  4128   hx147065 	int i, pktlen, nrates;
   2884  7865  Pengcheng 
   2885  7865  Pengcheng 	/* previous scan not completed */
   2886  7865  Pengcheng 	if (sc->sc_scan_pending) {
   2887  7865  Pengcheng 		WPI_DBG((WPI_DEBUG_SCAN, "previous scan not completed\n"));
   2888  7865  Pengcheng 		return (WPI_SUCCESS);
   2889  7865  Pengcheng 	}
   2890  4128   hx147065 
   2891  4128   hx147065 	data = &ring->data[ring->cur];
   2892  4128   hx147065 	desc = data->desc;
   2893  4128   hx147065 	cmd = (wpi_tx_cmd_t *)data->dma_data.mem_va;
   2894  4128   hx147065 
   2895  4128   hx147065 	cmd->code = WPI_CMD_SCAN;
   2896  4128   hx147065 	cmd->flags = 0;
   2897  4128   hx147065 	cmd->qid = ring->qid;
   2898  4128   hx147065 	cmd->idx = ring->cur;
   2899  4128   hx147065 
   2900  4128   hx147065 	hdr = (wpi_scan_hdr_t *)cmd->data;
   2901  4128   hx147065 	(void) memset(hdr, 0, sizeof (wpi_scan_hdr_t));
   2902  4128   hx147065 	hdr->first = 1;
   2903  7865  Pengcheng 	hdr->nchan = 1;
   2904  4128   hx147065 	hdr->len = hdr->nchan * sizeof (wpi_scan_chan_t);
   2905  7865  Pengcheng 	hdr->quiet = LE_16(50);
   2906  4128   hx147065 	hdr->threshold = LE_16(1);
   2907  4128   hx147065 	hdr->filter = LE_32(5);
   2908  4128   hx147065 	hdr->rate = wpi_plcp_signal(2);
   2909  4128   hx147065 	hdr->id = WPI_ID_BROADCAST;
   2910  4128   hx147065 	hdr->mask = LE_32(0xffffffff);
   2911  4128   hx147065 	hdr->esslen = ic->ic_des_esslen;
   2912  7865  Pengcheng 
   2913  7865  Pengcheng 	if (ic->ic_des_esslen) {
   2914  7865  Pengcheng 		bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen);
   2915  7865  Pengcheng 		essid[ic->ic_des_esslen] = '\0';
   2916  7865  Pengcheng 		WPI_DBG((WPI_DEBUG_SCAN, "directed scan %s\n", essid));
   2917  7865  Pengcheng 
   2918  4128   hx147065 		bcopy(ic->ic_des_essid, hdr->essid, ic->ic_des_esslen);
   2919  7865  Pengcheng 	} else {
   2920  4128   hx147065 		bzero(hdr->essid, sizeof (hdr->essid));
   2921  7865  Pengcheng 	}
   2922  7865  Pengcheng 
   2923  4128   hx147065 	/*
   2924  4128   hx147065 	 * Build a probe request frame.  Most of the following code is a
   2925  4128   hx147065 	 * copy & paste of what is done in net80211.  Unfortunately, the
   2926  4128   hx147065 	 * functions to add IEs are static and thus can't be reused here.
   2927  4128   hx147065 	 */
   2928  4128   hx147065 	wh = (struct ieee80211_frame *)(hdr + 1);
   2929  4128   hx147065 	wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
   2930  4128   hx147065 	    IEEE80211_FC0_SUBTYPE_PROBE_REQ;
   2931  4128   hx147065 	wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
   2932  4128   hx147065 	(void) memset(wh->i_addr1, 0xff, 6);
   2933  4128   hx147065 	IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr);
   2934  4128   hx147065 	(void) memset(wh->i_addr3, 0xff, 6);
   2935  4128   hx147065 	*(uint16_t *)&wh->i_dur[0] = 0;	/* filled by h/w */
   2936  4128   hx147065 	*(uint16_t *)&wh->i_seq[0] = 0;	/* filled by h/w */
   2937  4128   hx147065 
   2938  4128   hx147065 	frm = (uint8_t *)(wh + 1);
   2939  4128   hx147065 
   2940  4128   hx147065 	/* add essid IE */
   2941  7865  Pengcheng 	if (in->in_esslen) {
   2942  7865  Pengcheng 		bcopy(in->in_essid, essid, in->in_esslen);
   2943  7865  Pengcheng 		essid[in->in_esslen] = '\0';
   2944  7865  Pengcheng 		WPI_DBG((WPI_DEBUG_SCAN, "probe with ESSID %s\n",
   2945  7865  Pengcheng 		    essid));
   2946  7865  Pengcheng 	}
   2947  4128   hx147065 	*frm++ = IEEE80211_ELEMID_SSID;
   2948  4128   hx147065 	*frm++ = in->in_esslen;
   2949  4128   hx147065 	(void) memcpy(frm, in->