1c533a883Shx147065 /* 2*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3c533a883Shx147065 * Use is subject to license terms. 4c533a883Shx147065 */ 5c533a883Shx147065 6c533a883Shx147065 /* 7c533a883Shx147065 * Copyright (c) 2007, Intel Corporation 8c533a883Shx147065 * All rights reserved. 9c533a883Shx147065 */ 10c533a883Shx147065 11c533a883Shx147065 /* 12c533a883Shx147065 * Copyright (c) 2006 13c533a883Shx147065 * Copyright (c) 2007 14c533a883Shx147065 * Damien Bergamini <damien.bergamini@free.fr> 15c533a883Shx147065 * 16c533a883Shx147065 * Permission to use, copy, modify, and distribute this software for any 17c533a883Shx147065 * purpose with or without fee is hereby granted, provided that the above 18c533a883Shx147065 * copyright notice and this permission notice appear in all copies. 19c533a883Shx147065 * 20c533a883Shx147065 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 21c533a883Shx147065 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 22c533a883Shx147065 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 23c533a883Shx147065 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 24c533a883Shx147065 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 25c533a883Shx147065 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 26c533a883Shx147065 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27c533a883Shx147065 */ 28c533a883Shx147065 29c533a883Shx147065 /* 30c533a883Shx147065 * Driver for Intel PRO/Wireless 4965AGN(kedron) 802.11 network adapters. 31c533a883Shx147065 */ 32c533a883Shx147065 33c533a883Shx147065 #include <sys/types.h> 34c533a883Shx147065 #include <sys/byteorder.h> 35c533a883Shx147065 #include <sys/conf.h> 36c533a883Shx147065 #include <sys/cmn_err.h> 37c533a883Shx147065 #include <sys/stat.h> 38c533a883Shx147065 #include <sys/ddi.h> 39c533a883Shx147065 #include <sys/sunddi.h> 40c533a883Shx147065 #include <sys/strsubr.h> 41c533a883Shx147065 #include <sys/ethernet.h> 42c533a883Shx147065 #include <inet/common.h> 43c533a883Shx147065 #include <inet/nd.h> 44c533a883Shx147065 #include <inet/mi.h> 45c533a883Shx147065 #include <sys/note.h> 46c533a883Shx147065 #include <sys/stream.h> 47c533a883Shx147065 #include <sys/strsun.h> 48c533a883Shx147065 #include <sys/modctl.h> 49c533a883Shx147065 #include <sys/devops.h> 50c533a883Shx147065 #include <sys/dlpi.h> 51da14cebeSEric Cheng #include <sys/mac_provider.h> 52c533a883Shx147065 #include <sys/mac_wifi.h> 53c533a883Shx147065 #include <sys/net80211.h> 54c533a883Shx147065 #include <sys/net80211_proto.h> 55c533a883Shx147065 #include <sys/varargs.h> 56c533a883Shx147065 #include <sys/policy.h> 57c533a883Shx147065 #include <sys/pci.h> 58c533a883Shx147065 59cdc64593Sxinghua wen - Sun Microsystems - Beijing China #include "iwk_calibration.h" 60c533a883Shx147065 #include "iwk_hw.h" 61c533a883Shx147065 #include "iwk_eeprom.h" 62c533a883Shx147065 #include "iwk2_var.h" 63c533a883Shx147065 #include <inet/wifi_ioctl.h> 64c533a883Shx147065 65c533a883Shx147065 #ifdef DEBUG 66c533a883Shx147065 #define IWK_DEBUG_80211 (1 << 0) 67c533a883Shx147065 #define IWK_DEBUG_CMD (1 << 1) 68c533a883Shx147065 #define IWK_DEBUG_DMA (1 << 2) 69c533a883Shx147065 #define IWK_DEBUG_EEPROM (1 << 3) 70c533a883Shx147065 #define IWK_DEBUG_FW (1 << 4) 71c533a883Shx147065 #define IWK_DEBUG_HW (1 << 5) 72c533a883Shx147065 #define IWK_DEBUG_INTR (1 << 6) 73c533a883Shx147065 #define IWK_DEBUG_MRR (1 << 7) 74c533a883Shx147065 #define IWK_DEBUG_PIO (1 << 8) 75c533a883Shx147065 #define IWK_DEBUG_RX (1 << 9) 76c533a883Shx147065 #define IWK_DEBUG_SCAN (1 << 10) 77c533a883Shx147065 #define IWK_DEBUG_TX (1 << 11) 78c533a883Shx147065 #define IWK_DEBUG_RATECTL (1 << 12) 79c533a883Shx147065 #define IWK_DEBUG_RADIO (1 << 13) 8043439c96Shx147065 #define IWK_DEBUG_RESUME (1 << 14) 81cdc64593Sxinghua wen - Sun Microsystems - Beijing China #define IWK_DEBUG_CALIBRATION (1 << 15) 82c533a883Shx147065 uint32_t iwk_dbg_flags = 0; 83c533a883Shx147065 #define IWK_DBG(x) \ 84c533a883Shx147065 iwk_dbg x 85c533a883Shx147065 #else 86c533a883Shx147065 #define IWK_DBG(x) 87c533a883Shx147065 #endif 88c533a883Shx147065 89c533a883Shx147065 static void *iwk_soft_state_p = NULL; 90c533a883Shx147065 static uint8_t iwk_fw_bin [] = { 91c533a883Shx147065 #include "fw-iw/iw4965.ucode.hex" 92c533a883Shx147065 }; 93c533a883Shx147065 94c533a883Shx147065 /* DMA attributes for a shared page */ 95c533a883Shx147065 static ddi_dma_attr_t sh_dma_attr = { 96c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */ 97c533a883Shx147065 0, /* lowest usable address */ 98c533a883Shx147065 0xffffffffU, /* highest usable address */ 99c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */ 100c533a883Shx147065 0x1000, /* alignment in bytes */ 101c533a883Shx147065 0x1000, /* burst sizes (any?) */ 102c533a883Shx147065 1, /* minimum transfer */ 103c533a883Shx147065 0xffffffffU, /* maximum transfer */ 104c533a883Shx147065 0xffffffffU, /* maximum segment length */ 105c533a883Shx147065 1, /* maximum number of segments */ 106c533a883Shx147065 1, /* granularity */ 107c533a883Shx147065 0, /* flags (reserved) */ 108c533a883Shx147065 }; 109c533a883Shx147065 110c533a883Shx147065 /* DMA attributes for a keep warm DRAM descriptor */ 111c533a883Shx147065 static ddi_dma_attr_t kw_dma_attr = { 112c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */ 113c533a883Shx147065 0, /* lowest usable address */ 114c533a883Shx147065 0xffffffffU, /* highest usable address */ 115c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */ 116c533a883Shx147065 0x1000, /* alignment in bytes */ 117c533a883Shx147065 0x1000, /* burst sizes (any?) */ 118c533a883Shx147065 1, /* minimum transfer */ 119c533a883Shx147065 0xffffffffU, /* maximum transfer */ 120c533a883Shx147065 0xffffffffU, /* maximum segment length */ 121c533a883Shx147065 1, /* maximum number of segments */ 122c533a883Shx147065 1, /* granularity */ 123c533a883Shx147065 0, /* flags (reserved) */ 124c533a883Shx147065 }; 125c533a883Shx147065 126c533a883Shx147065 /* DMA attributes for a ring descriptor */ 127c533a883Shx147065 static ddi_dma_attr_t ring_desc_dma_attr = { 128c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */ 129c533a883Shx147065 0, /* lowest usable address */ 130c533a883Shx147065 0xffffffffU, /* highest usable address */ 131c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */ 132c533a883Shx147065 0x100, /* alignment in bytes */ 133c533a883Shx147065 0x100, /* burst sizes (any?) */ 134c533a883Shx147065 1, /* minimum transfer */ 135c533a883Shx147065 0xffffffffU, /* maximum transfer */ 136c533a883Shx147065 0xffffffffU, /* maximum segment length */ 137c533a883Shx147065 1, /* maximum number of segments */ 138c533a883Shx147065 1, /* granularity */ 139c533a883Shx147065 0, /* flags (reserved) */ 140c533a883Shx147065 }; 141c533a883Shx147065 142c533a883Shx147065 /* DMA attributes for a cmd */ 143c533a883Shx147065 static ddi_dma_attr_t cmd_dma_attr = { 144c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */ 145c533a883Shx147065 0, /* lowest usable address */ 146c533a883Shx147065 0xffffffffU, /* highest usable address */ 147c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */ 148c533a883Shx147065 4, /* alignment in bytes */ 149c533a883Shx147065 0x100, /* burst sizes (any?) */ 150c533a883Shx147065 1, /* minimum transfer */ 151c533a883Shx147065 0xffffffffU, /* maximum transfer */ 152c533a883Shx147065 0xffffffffU, /* maximum segment length */ 153c533a883Shx147065 1, /* maximum number of segments */ 154c533a883Shx147065 1, /* granularity */ 155c533a883Shx147065 0, /* flags (reserved) */ 156c533a883Shx147065 }; 157c533a883Shx147065 158c533a883Shx147065 /* DMA attributes for a rx buffer */ 159c533a883Shx147065 static ddi_dma_attr_t rx_buffer_dma_attr = { 160c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */ 161c533a883Shx147065 0, /* lowest usable address */ 162c533a883Shx147065 0xffffffffU, /* highest usable address */ 163c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */ 164c533a883Shx147065 0x100, /* alignment in bytes */ 165c533a883Shx147065 0x100, /* burst sizes (any?) */ 166c533a883Shx147065 1, /* minimum transfer */ 167c533a883Shx147065 0xffffffffU, /* maximum transfer */ 168c533a883Shx147065 0xffffffffU, /* maximum segment length */ 169c533a883Shx147065 1, /* maximum number of segments */ 170c533a883Shx147065 1, /* granularity */ 171c533a883Shx147065 0, /* flags (reserved) */ 172c533a883Shx147065 }; 173c533a883Shx147065 174c533a883Shx147065 /* 175c533a883Shx147065 * DMA attributes for a tx buffer. 176c533a883Shx147065 * the maximum number of segments is 4 for the hardware. 177c533a883Shx147065 * now all the wifi drivers put the whole frame in a single 178c533a883Shx147065 * descriptor, so we define the maximum number of segments 1, 179c533a883Shx147065 * just the same as the rx_buffer. we consider leverage the HW 180c533a883Shx147065 * ability in the future, that is why we don't define rx and tx 181c533a883Shx147065 * buffer_dma_attr as the same. 182c533a883Shx147065 */ 183c533a883Shx147065 static ddi_dma_attr_t tx_buffer_dma_attr = { 184c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */ 185c533a883Shx147065 0, /* lowest usable address */ 186c533a883Shx147065 0xffffffffU, /* highest usable address */ 187c533a883Shx147065 0xffffffffU, /* maximum DMAable byte count */ 188c533a883Shx147065 4, /* alignment in bytes */ 189c533a883Shx147065 0x100, /* burst sizes (any?) */ 190c533a883Shx147065 1, /* minimum transfer */ 191c533a883Shx147065 0xffffffffU, /* maximum transfer */ 192c533a883Shx147065 0xffffffffU, /* maximum segment length */ 193c533a883Shx147065 1, /* maximum number of segments */ 194c533a883Shx147065 1, /* granularity */ 195c533a883Shx147065 0, /* flags (reserved) */ 196c533a883Shx147065 }; 197c533a883Shx147065 198c533a883Shx147065 /* DMA attributes for text and data part in the firmware */ 199c533a883Shx147065 static ddi_dma_attr_t fw_dma_attr = { 200c533a883Shx147065 DMA_ATTR_V0, /* version of this structure */ 201c533a883Shx147065 0, /* lowest usable address */ 202c533a883Shx147065 0xffffffffU, /* highest usable address */ 203c533a883Shx147065 0x7fffffff, /* maximum DMAable byte count */ 204c533a883Shx147065 0x10, /* alignment in bytes */ 205c533a883Shx147065 0x100, /* burst sizes (any?) */ 206c533a883Shx147065 1, /* minimum transfer */ 207c533a883Shx147065 0xffffffffU, /* maximum transfer */ 208c533a883Shx147065 0xffffffffU, /* maximum segment length */ 209c533a883Shx147065 1, /* maximum number of segments */ 210c533a883Shx147065 1, /* granularity */ 211c533a883Shx147065 0, /* flags (reserved) */ 212c533a883Shx147065 }; 213c533a883Shx147065 214c533a883Shx147065 215c533a883Shx147065 /* regs access attributes */ 216c533a883Shx147065 static ddi_device_acc_attr_t iwk_reg_accattr = { 217c533a883Shx147065 DDI_DEVICE_ATTR_V0, 218c533a883Shx147065 DDI_STRUCTURE_LE_ACC, 219c533a883Shx147065 DDI_STRICTORDER_ACC, 220c533a883Shx147065 DDI_DEFAULT_ACC 221c533a883Shx147065 }; 222c533a883Shx147065 223b510adaeSfei feng - Sun Microsystems - Beijing China /* DMA access attributes for Descriptor */ 224b510adaeSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t iwk_dma_descattr = { 225b510adaeSfei feng - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0, 226b510adaeSfei feng - Sun Microsystems - Beijing China DDI_STRUCTURE_LE_ACC, 227b510adaeSfei feng - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC, 228b510adaeSfei feng - Sun Microsystems - Beijing China DDI_DEFAULT_ACC 229b510adaeSfei feng - Sun Microsystems - Beijing China }; 230b510adaeSfei feng - Sun Microsystems - Beijing China 231c533a883Shx147065 /* DMA access attributes */ 232c533a883Shx147065 static ddi_device_acc_attr_t iwk_dma_accattr = { 233c533a883Shx147065 DDI_DEVICE_ATTR_V0, 234c533a883Shx147065 DDI_NEVERSWAP_ACC, 235c533a883Shx147065 DDI_STRICTORDER_ACC, 236c533a883Shx147065 DDI_DEFAULT_ACC 237c533a883Shx147065 }; 238c533a883Shx147065 239c533a883Shx147065 static int iwk_ring_init(iwk_sc_t *); 240c533a883Shx147065 static void iwk_ring_free(iwk_sc_t *); 241c533a883Shx147065 static int iwk_alloc_shared(iwk_sc_t *); 242c533a883Shx147065 static void iwk_free_shared(iwk_sc_t *); 243c533a883Shx147065 static int iwk_alloc_kw(iwk_sc_t *); 244c533a883Shx147065 static void iwk_free_kw(iwk_sc_t *); 245c533a883Shx147065 static int iwk_alloc_fw_dma(iwk_sc_t *); 246c533a883Shx147065 static void iwk_free_fw_dma(iwk_sc_t *); 247c533a883Shx147065 static int iwk_alloc_rx_ring(iwk_sc_t *); 248c533a883Shx147065 static void iwk_reset_rx_ring(iwk_sc_t *); 249c533a883Shx147065 static void iwk_free_rx_ring(iwk_sc_t *); 250c533a883Shx147065 static int iwk_alloc_tx_ring(iwk_sc_t *, iwk_tx_ring_t *, 251c533a883Shx147065 int, int); 252c533a883Shx147065 static void iwk_reset_tx_ring(iwk_sc_t *, iwk_tx_ring_t *); 253c533a883Shx147065 static void iwk_free_tx_ring(iwk_sc_t *, iwk_tx_ring_t *); 254c533a883Shx147065 25543439c96Shx147065 static ieee80211_node_t *iwk_node_alloc(ieee80211com_t *); 25643439c96Shx147065 static void iwk_node_free(ieee80211_node_t *); 257c533a883Shx147065 static int iwk_newstate(ieee80211com_t *, enum ieee80211_state, int); 258c533a883Shx147065 static int iwk_key_set(ieee80211com_t *, const struct ieee80211_key *, 259c533a883Shx147065 const uint8_t mac[IEEE80211_ADDR_LEN]); 260c533a883Shx147065 static void iwk_mac_access_enter(iwk_sc_t *); 261c533a883Shx147065 static void iwk_mac_access_exit(iwk_sc_t *); 262c533a883Shx147065 static uint32_t iwk_reg_read(iwk_sc_t *, uint32_t); 263c533a883Shx147065 static void iwk_reg_write(iwk_sc_t *, uint32_t, uint32_t); 264c533a883Shx147065 static void iwk_reg_write_region_4(iwk_sc_t *, uint32_t, 265c533a883Shx147065 uint32_t *, int); 266c533a883Shx147065 static int iwk_load_firmware(iwk_sc_t *); 267c533a883Shx147065 static void iwk_rx_intr(iwk_sc_t *, iwk_rx_desc_t *, 268c533a883Shx147065 iwk_rx_data_t *); 269c533a883Shx147065 static void iwk_tx_intr(iwk_sc_t *, iwk_rx_desc_t *, 270c533a883Shx147065 iwk_rx_data_t *); 271c533a883Shx147065 static void iwk_cmd_intr(iwk_sc_t *, iwk_rx_desc_t *); 272cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint_t iwk_intr(caddr_t, caddr_t); 273c533a883Shx147065 static int iwk_eep_load(iwk_sc_t *sc); 274c533a883Shx147065 static void iwk_get_mac_from_eep(iwk_sc_t *sc); 275c533a883Shx147065 static int iwk_eep_sem_down(iwk_sc_t *sc); 276c533a883Shx147065 static void iwk_eep_sem_up(iwk_sc_t *sc); 277cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint_t iwk_rx_softintr(caddr_t, caddr_t); 278c533a883Shx147065 static uint8_t iwk_rate_to_plcp(int); 279c533a883Shx147065 static int iwk_cmd(iwk_sc_t *, int, const void *, int, int); 280c533a883Shx147065 static void iwk_set_led(iwk_sc_t *, uint8_t, uint8_t, uint8_t); 281c533a883Shx147065 static int iwk_hw_set_before_auth(iwk_sc_t *); 282c533a883Shx147065 static int iwk_scan(iwk_sc_t *); 283c533a883Shx147065 static int iwk_config(iwk_sc_t *); 284c533a883Shx147065 static void iwk_stop_master(iwk_sc_t *); 285c533a883Shx147065 static int iwk_power_up(iwk_sc_t *); 286c533a883Shx147065 static int iwk_preinit(iwk_sc_t *); 287c533a883Shx147065 static int iwk_init(iwk_sc_t *); 288c533a883Shx147065 static void iwk_stop(iwk_sc_t *); 28943439c96Shx147065 static void iwk_amrr_init(iwk_amrr_t *); 29043439c96Shx147065 static void iwk_amrr_timeout(iwk_sc_t *); 29143439c96Shx147065 static void iwk_amrr_ratectl(void *, ieee80211_node_t *); 292cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_curr_tempera(iwk_sc_t *sc); 293cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_tx_power_calibration(iwk_sc_t *sc); 294cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_24G_band(iwk_sc_t *sc); 295cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_fat_channel(iwk_sc_t *sc); 296cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_grp(uint16_t channel); 297cdc64593Sxinghua wen - Sun Microsystems - Beijing China static struct iwk_eep_channel *iwk_get_eep_channel(iwk_sc_t *sc, 298cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel, 299cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_24G, int is_fat, int is_hi_chan); 300cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_band_number(iwk_sc_t *sc, uint16_t channel); 301cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_division(int32_t num, int32_t denom, int32_t *res); 302cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_interpolate_value(int32_t x, int32_t x1, int32_t y1, 303cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t x2, int32_t y2); 304cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_channel_interpolate(iwk_sc_t *sc, uint16_t channel, 305cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_channel_info *chan_info); 306cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_voltage_compensation(int32_t eep_voltage, 307cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t curr_voltage); 308cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_min_power_index(int32_t rate_pow_idx, int32_t is_24G); 309cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_table_cmd_init(iwk_sc_t *sc, 310cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_tx_power_db *tp_db); 311cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_statistics_notify(iwk_sc_t *sc, iwk_rx_desc_t *desc); 312cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_is_associated(iwk_sc_t *sc); 313cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff_init(iwk_sc_t *sc); 314cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff(iwk_sc_t *sc); 315cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens_init(iwk_sc_t *sc); 316cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens(iwk_sc_t *sc); 317cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_cck_sens(iwk_sc_t *sc, uint32_t actual_rx_time); 318cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time); 31919d332feSfei feng - Sun Microsystems - Beijing China static void iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp, 32019d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_node *in, int subtype, int rssi, uint32_t rstamp); 321cdc64593Sxinghua wen - Sun Microsystems - Beijing China 322cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_event_log(iwk_sc_t *); 323cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_error_log(iwk_sc_t *); 324c533a883Shx147065 325c533a883Shx147065 static int iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 326c533a883Shx147065 static int iwk_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 327d2a61391Spengcheng chen - Sun Microsystems - Beijing China static int iwk_quiesce(dev_info_t *dip); 328c533a883Shx147065 329c533a883Shx147065 /* 330c533a883Shx147065 * GLD specific operations 331c533a883Shx147065 */ 332c533a883Shx147065 static int iwk_m_stat(void *arg, uint_t stat, uint64_t *val); 333c533a883Shx147065 static int iwk_m_start(void *arg); 334c533a883Shx147065 static void iwk_m_stop(void *arg); 335c533a883Shx147065 static int iwk_m_unicst(void *arg, const uint8_t *macaddr); 336c533a883Shx147065 static int iwk_m_multicst(void *arg, boolean_t add, const uint8_t *m); 337c533a883Shx147065 static int iwk_m_promisc(void *arg, boolean_t on); 338c533a883Shx147065 static mblk_t *iwk_m_tx(void *arg, mblk_t *mp); 339c533a883Shx147065 static void iwk_m_ioctl(void *arg, queue_t *wq, mblk_t *mp); 340bcb5c89dSSowmini Varadhan static int iwk_m_setprop(void *arg, const char *pr_name, 341bcb5c89dSSowmini Varadhan mac_prop_id_t wldp_pr_name, uint_t wldp_length, const void *wldp_buf); 342bcb5c89dSSowmini Varadhan static int iwk_m_getprop(void *arg, const char *pr_name, 343*0dc2366fSVenugopal Iyer mac_prop_id_t wldp_pr_name, uint_t wldp_length, void *wldp_buf); 344*0dc2366fSVenugopal Iyer static void iwk_m_propinfo(void *arg, const char *pr_name, 345*0dc2366fSVenugopal Iyer mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph); 346c533a883Shx147065 static void iwk_destroy_locks(iwk_sc_t *sc); 347c533a883Shx147065 static int iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type); 348c533a883Shx147065 static void iwk_thread(iwk_sc_t *sc); 349f3c4902cSpengcheng chen - Sun Microsystems - Beijing China static void iwk_watchdog(void *arg); 35019d332feSfei feng - Sun Microsystems - Beijing China static int iwk_run_state_config_ibss(ieee80211com_t *ic); 35119d332feSfei feng - Sun Microsystems - Beijing China static int iwk_run_state_config_sta(ieee80211com_t *ic); 3526f12def4Spengcheng chen - Sun Microsystems - Beijing China static int iwk_fast_recover(iwk_sc_t *sc); 35319d332feSfei feng - Sun Microsystems - Beijing China static int iwk_start_tx_beacon(ieee80211com_t *ic); 35419d332feSfei feng - Sun Microsystems - Beijing China static int iwk_clean_add_node_ibss(struct ieee80211com *ic, 35519d332feSfei feng - Sun Microsystems - Beijing China uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2); 356c533a883Shx147065 357c533a883Shx147065 /* 358c533a883Shx147065 * Supported rates for 802.11b/g modes (in 500Kbps unit). 359c533a883Shx147065 * 11a and 11n support will be added later. 360c533a883Shx147065 */ 361c533a883Shx147065 static const struct ieee80211_rateset iwk_rateset_11b = 362c533a883Shx147065 { 4, { 2, 4, 11, 22 } }; 363c533a883Shx147065 364c533a883Shx147065 static const struct ieee80211_rateset iwk_rateset_11g = 365c533a883Shx147065 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 366c533a883Shx147065 367c533a883Shx147065 /* 368c533a883Shx147065 * For mfthread only 369c533a883Shx147065 */ 370c533a883Shx147065 extern pri_t minclsyspri; 371c533a883Shx147065 372c533a883Shx147065 #define DRV_NAME_4965 "iwk" 373c533a883Shx147065 374c533a883Shx147065 /* 375c533a883Shx147065 * Module Loading Data & Entry Points 376c533a883Shx147065 */ 377c533a883Shx147065 DDI_DEFINE_STREAM_OPS(iwk_devops, nulldev, nulldev, iwk_attach, 378d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_detach, nodev, NULL, D_MP, NULL, iwk_quiesce); 379c533a883Shx147065 380c533a883Shx147065 static struct modldrv iwk_modldrv = { 381c533a883Shx147065 &mod_driverops, 382c533a883Shx147065 "Intel(R) 4965AGN driver(N)", 383c533a883Shx147065 &iwk_devops 384c533a883Shx147065 }; 385c533a883Shx147065 386c533a883Shx147065 static struct modlinkage iwk_modlinkage = { 387c533a883Shx147065 MODREV_1, 388c533a883Shx147065 &iwk_modldrv, 389c533a883Shx147065 NULL 390c533a883Shx147065 }; 391c533a883Shx147065 392c533a883Shx147065 int 393c533a883Shx147065 _init(void) 394c533a883Shx147065 { 395c533a883Shx147065 int status; 396c533a883Shx147065 397c533a883Shx147065 status = ddi_soft_state_init(&iwk_soft_state_p, 398c533a883Shx147065 sizeof (iwk_sc_t), 1); 399c533a883Shx147065 if (status != DDI_SUCCESS) 400c533a883Shx147065 return (status); 401c533a883Shx147065 402c533a883Shx147065 mac_init_ops(&iwk_devops, DRV_NAME_4965); 403c533a883Shx147065 status = mod_install(&iwk_modlinkage); 404c533a883Shx147065 if (status != DDI_SUCCESS) { 405c533a883Shx147065 mac_fini_ops(&iwk_devops); 406c533a883Shx147065 ddi_soft_state_fini(&iwk_soft_state_p); 407c533a883Shx147065 } 408c533a883Shx147065 409c533a883Shx147065 return (status); 410c533a883Shx147065 } 411c533a883Shx147065 412c533a883Shx147065 int 413c533a883Shx147065 _fini(void) 414c533a883Shx147065 { 415c533a883Shx147065 int status; 416c533a883Shx147065 417c533a883Shx147065 status = mod_remove(&iwk_modlinkage); 418c533a883Shx147065 if (status == DDI_SUCCESS) { 419c533a883Shx147065 mac_fini_ops(&iwk_devops); 420c533a883Shx147065 ddi_soft_state_fini(&iwk_soft_state_p); 421c533a883Shx147065 } 422c533a883Shx147065 423c533a883Shx147065 return (status); 424c533a883Shx147065 } 425c533a883Shx147065 426c533a883Shx147065 int 427c533a883Shx147065 _info(struct modinfo *mip) 428c533a883Shx147065 { 429c533a883Shx147065 return (mod_info(&iwk_modlinkage, mip)); 430c533a883Shx147065 } 431c533a883Shx147065 432c533a883Shx147065 /* 433c533a883Shx147065 * Mac Call Back entries 434c533a883Shx147065 */ 435c533a883Shx147065 mac_callbacks_t iwk_m_callbacks = { 436*0dc2366fSVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 437c533a883Shx147065 iwk_m_stat, 438c533a883Shx147065 iwk_m_start, 439c533a883Shx147065 iwk_m_stop, 440c533a883Shx147065 iwk_m_promisc, 441c533a883Shx147065 iwk_m_multicst, 442c533a883Shx147065 iwk_m_unicst, 443c533a883Shx147065 iwk_m_tx, 444*0dc2366fSVenugopal Iyer NULL, 445bcb5c89dSSowmini Varadhan iwk_m_ioctl, 446bcb5c89dSSowmini Varadhan NULL, 447bcb5c89dSSowmini Varadhan NULL, 448bcb5c89dSSowmini Varadhan NULL, 449bcb5c89dSSowmini Varadhan iwk_m_setprop, 450*0dc2366fSVenugopal Iyer iwk_m_getprop, 451*0dc2366fSVenugopal Iyer iwk_m_propinfo 452c533a883Shx147065 }; 453c533a883Shx147065 454c533a883Shx147065 #ifdef DEBUG 455c533a883Shx147065 void 456c533a883Shx147065 iwk_dbg(uint32_t flags, const char *fmt, ...) 457c533a883Shx147065 { 458c533a883Shx147065 va_list ap; 459c533a883Shx147065 460c533a883Shx147065 if (flags & iwk_dbg_flags) { 461c533a883Shx147065 va_start(ap, fmt); 462c533a883Shx147065 vcmn_err(CE_NOTE, fmt, ap); 463c533a883Shx147065 va_end(ap); 464c533a883Shx147065 } 465c533a883Shx147065 } 466c533a883Shx147065 #endif 467c533a883Shx147065 468c533a883Shx147065 /* 469c533a883Shx147065 * device operations 470c533a883Shx147065 */ 471c533a883Shx147065 int 472c533a883Shx147065 iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 473c533a883Shx147065 { 474c533a883Shx147065 iwk_sc_t *sc; 475c533a883Shx147065 ieee80211com_t *ic; 476c533a883Shx147065 int instance, err, i; 477c533a883Shx147065 char strbuf[32]; 478c533a883Shx147065 wifi_data_t wd = { 0 }; 479c533a883Shx147065 mac_register_t *macp; 480c533a883Shx147065 481cdc64593Sxinghua wen - Sun Microsystems - Beijing China int intr_type; 482cdc64593Sxinghua wen - Sun Microsystems - Beijing China int intr_count; 483cdc64593Sxinghua wen - Sun Microsystems - Beijing China int intr_actual; 484cdc64593Sxinghua wen - Sun Microsystems - Beijing China 485d62cb7ffShx147065 switch (cmd) { 486d62cb7ffShx147065 case DDI_ATTACH: 487d62cb7ffShx147065 break; 488d62cb7ffShx147065 case DDI_RESUME: 489d62cb7ffShx147065 sc = ddi_get_soft_state(iwk_soft_state_p, 490d62cb7ffShx147065 ddi_get_instance(dip)); 491d62cb7ffShx147065 ASSERT(sc != NULL); 49209539a3cSpengcheng chen - Sun Microsystems - Beijing China 49309539a3cSpengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 49409539a3cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SUSPEND; 49509539a3cSpengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 49609539a3cSpengcheng chen - Sun Microsystems - Beijing China 497d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING) 498d40f4da4Spengcheng chen - Sun Microsystems - Beijing China (void) iwk_init(sc); 499d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 500d62cb7ffShx147065 mutex_enter(&sc->sc_glock); 501d40f4da4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_LAZY_RESUME; 502d62cb7ffShx147065 mutex_exit(&sc->sc_glock); 503d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 504d62cb7ffShx147065 IWK_DBG((IWK_DEBUG_RESUME, "iwk: resume\n")); 505d62cb7ffShx147065 return (DDI_SUCCESS); 506d62cb7ffShx147065 default: 507c533a883Shx147065 err = DDI_FAILURE; 508c533a883Shx147065 goto attach_fail1; 509c533a883Shx147065 } 510c533a883Shx147065 511c533a883Shx147065 instance = ddi_get_instance(dip); 512c533a883Shx147065 err = ddi_soft_state_zalloc(iwk_soft_state_p, instance); 513c533a883Shx147065 if (err != DDI_SUCCESS) { 514c533a883Shx147065 cmn_err(CE_WARN, 515c533a883Shx147065 "iwk_attach(): failed to allocate soft state\n"); 516c533a883Shx147065 goto attach_fail1; 517c533a883Shx147065 } 518c533a883Shx147065 sc = ddi_get_soft_state(iwk_soft_state_p, instance); 519c533a883Shx147065 sc->sc_dip = dip; 520c533a883Shx147065 521c533a883Shx147065 err = ddi_regs_map_setup(dip, 0, &sc->sc_cfg_base, 0, 0, 522c533a883Shx147065 &iwk_reg_accattr, &sc->sc_cfg_handle); 523c533a883Shx147065 if (err != DDI_SUCCESS) { 524c533a883Shx147065 cmn_err(CE_WARN, 525c533a883Shx147065 "iwk_attach(): failed to map config spaces regs\n"); 526c533a883Shx147065 goto attach_fail2; 527c533a883Shx147065 } 528c533a883Shx147065 sc->sc_rev = ddi_get8(sc->sc_cfg_handle, 529c533a883Shx147065 (uint8_t *)(sc->sc_cfg_base + PCI_CONF_REVID)); 530c533a883Shx147065 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0x41), 0); 531c533a883Shx147065 sc->sc_clsz = ddi_get16(sc->sc_cfg_handle, 532c533a883Shx147065 (uint16_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ)); 533c533a883Shx147065 if (!sc->sc_clsz) 534c533a883Shx147065 sc->sc_clsz = 16; 535c533a883Shx147065 sc->sc_clsz = (sc->sc_clsz << 2); 536c533a883Shx147065 sc->sc_dmabuf_sz = roundup(0x1000 + sizeof (struct ieee80211_frame) + 537c533a883Shx147065 IEEE80211_MTU + IEEE80211_CRC_LEN + 538c533a883Shx147065 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 539c533a883Shx147065 IEEE80211_WEP_CRCLEN), sc->sc_clsz); 540c533a883Shx147065 /* 541c533a883Shx147065 * Map operating registers 542c533a883Shx147065 */ 543c533a883Shx147065 err = ddi_regs_map_setup(dip, 1, &sc->sc_base, 544c533a883Shx147065 0, 0, &iwk_reg_accattr, &sc->sc_handle); 545c533a883Shx147065 if (err != DDI_SUCCESS) { 546c533a883Shx147065 cmn_err(CE_WARN, 547c533a883Shx147065 "iwk_attach(): failed to map device regs\n"); 548c533a883Shx147065 goto attach_fail2a; 549c533a883Shx147065 } 550c533a883Shx147065 551cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_get_supported_types(dip, &intr_type); 552cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) { 553cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 554cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Fixed type interrupt is not supported\n"); 555cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_a; 556c533a883Shx147065 } 557cdc64593Sxinghua wen - Sun Microsystems - Beijing China 558cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &intr_count); 559cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((err != DDI_SUCCESS) || (intr_count != 1)) { 560cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 561cdc64593Sxinghua wen - Sun Microsystems - Beijing China "No fixed interrupts\n"); 562cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_a; 563cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 564cdc64593Sxinghua wen - Sun Microsystems - Beijing China 565cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP); 566cdc64593Sxinghua wen - Sun Microsystems - Beijing China 567cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_alloc(dip, sc->sc_intr_htable, DDI_INTR_TYPE_FIXED, 0, 568cdc64593Sxinghua wen - Sun Microsystems - Beijing China intr_count, &intr_actual, 0); 569cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((err != DDI_SUCCESS) || (intr_actual != 1)) { 570cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 571cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_alloc() failed 0x%x\n", err); 572cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_b; 573cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 574cdc64593Sxinghua wen - Sun Microsystems - Beijing China 575cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri); 576cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 577cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 578cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_get_pri() failed 0x%x\n", err); 579cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_c; 580cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 581cdc64593Sxinghua wen - Sun Microsystems - Beijing China 582cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER, 583cdc64593Sxinghua wen - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri)); 584cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER, 585cdc64593Sxinghua wen - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri)); 586cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER, 587cdc64593Sxinghua wen - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri)); 58819d332feSfei feng - Sun Microsystems - Beijing China mutex_init(&sc->sc_ibss.node_tb_lock, NULL, MUTEX_DRIVER, 58919d332feSfei feng - Sun Microsystems - Beijing China DDI_INTR_PRI(sc->sc_intr_pri)); 590cdc64593Sxinghua wen - Sun Microsystems - Beijing China 591c533a883Shx147065 cv_init(&sc->sc_fw_cv, NULL, CV_DRIVER, NULL); 592c533a883Shx147065 cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL); 593c533a883Shx147065 cv_init(&sc->sc_tx_cv, "tx-ring", CV_DRIVER, NULL); 594c533a883Shx147065 /* 595c533a883Shx147065 * initialize the mfthread 596c533a883Shx147065 */ 597c533a883Shx147065 cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL); 598c533a883Shx147065 sc->sc_mf_thread = NULL; 599c533a883Shx147065 sc->sc_mf_thread_switch = 0; 600c533a883Shx147065 601c533a883Shx147065 /* 602c533a883Shx147065 * Allocate shared page. 603c533a883Shx147065 */ 604c533a883Shx147065 err = iwk_alloc_shared(sc); 605c533a883Shx147065 if (err != DDI_SUCCESS) { 606cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 607cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to allocate shared page\n"); 608c533a883Shx147065 goto attach_fail3; 609c533a883Shx147065 } 610c533a883Shx147065 611c533a883Shx147065 /* 612c533a883Shx147065 * Allocate keep warm page. 613c533a883Shx147065 */ 614c533a883Shx147065 err = iwk_alloc_kw(sc); 615c533a883Shx147065 if (err != DDI_SUCCESS) { 616cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 617cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to allocate keep warm page\n"); 618c533a883Shx147065 goto attach_fail3a; 619c533a883Shx147065 } 620c533a883Shx147065 621c533a883Shx147065 /* 622c533a883Shx147065 * Do some necessary hardware initializations. 623c533a883Shx147065 */ 624c533a883Shx147065 err = iwk_preinit(sc); 625c533a883Shx147065 if (err != DDI_SUCCESS) { 626cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 627cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to init hardware\n"); 628c533a883Shx147065 goto attach_fail4; 629c533a883Shx147065 } 630c533a883Shx147065 631c533a883Shx147065 /* initialize EEPROM */ 632c533a883Shx147065 err = iwk_eep_load(sc); /* get hardware configurations from eeprom */ 633c533a883Shx147065 if (err != 0) { 634c533a883Shx147065 cmn_err(CE_WARN, "iwk_attach(): failed to load eeprom\n"); 635c533a883Shx147065 goto attach_fail4; 636c533a883Shx147065 } 637c533a883Shx147065 638b510adaeSfei feng - Sun Microsystems - Beijing China if (LE_16(sc->sc_eep_map.calib_version) < EEP_TX_POWER_VERSION_NEW) { 639c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "older EEPROM detected\n"); 640c533a883Shx147065 goto attach_fail4; 641c533a883Shx147065 } 642c533a883Shx147065 643c533a883Shx147065 iwk_get_mac_from_eep(sc); 644c533a883Shx147065 645c533a883Shx147065 err = iwk_ring_init(sc); 646c533a883Shx147065 if (err != DDI_SUCCESS) { 647c533a883Shx147065 cmn_err(CE_WARN, "iwk_attach(): " 648c533a883Shx147065 "failed to allocate and initialize ring\n"); 649c533a883Shx147065 goto attach_fail4; 650c533a883Shx147065 } 651c533a883Shx147065 652c533a883Shx147065 sc->sc_hdr = (iwk_firmware_hdr_t *)iwk_fw_bin; 653c533a883Shx147065 654c533a883Shx147065 err = iwk_alloc_fw_dma(sc); 655c533a883Shx147065 if (err != DDI_SUCCESS) { 656c533a883Shx147065 cmn_err(CE_WARN, "iwk_attach(): " 657c533a883Shx147065 "failed to allocate firmware dma\n"); 658c533a883Shx147065 goto attach_fail5; 659c533a883Shx147065 } 660c533a883Shx147065 661c533a883Shx147065 /* 662c533a883Shx147065 * Initialize the wifi part, which will be used by 663c533a883Shx147065 * generic layer 664c533a883Shx147065 */ 665c533a883Shx147065 ic = &sc->sc_ic; 666c533a883Shx147065 ic->ic_phytype = IEEE80211_T_OFDM; 667c533a883Shx147065 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 668c533a883Shx147065 ic->ic_state = IEEE80211_S_INIT; 669c533a883Shx147065 ic->ic_maxrssi = 100; /* experimental number */ 670c533a883Shx147065 ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT | 671c533a883Shx147065 IEEE80211_C_PMGT | IEEE80211_C_SHSLOT; 672c533a883Shx147065 /* 673c533a883Shx147065 * use software WEP and TKIP, hardware CCMP; 674c533a883Shx147065 */ 675c533a883Shx147065 ic->ic_caps |= IEEE80211_C_AES_CCM; 676c533a883Shx147065 /* 677c533a883Shx147065 * Support WPA/WPA2 678c533a883Shx147065 */ 679c533a883Shx147065 ic->ic_caps |= IEEE80211_C_WPA; 68019d332feSfei feng - Sun Microsystems - Beijing China /* 68119d332feSfei feng - Sun Microsystems - Beijing China * support Adhoc mode 68219d332feSfei feng - Sun Microsystems - Beijing China */ 68319d332feSfei feng - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_IBSS; 684cdc64593Sxinghua wen - Sun Microsystems - Beijing China 685c533a883Shx147065 /* set supported .11b and .11g rates */ 686c533a883Shx147065 ic->ic_sup_rates[IEEE80211_MODE_11B] = iwk_rateset_11b; 687c533a883Shx147065 ic->ic_sup_rates[IEEE80211_MODE_11G] = iwk_rateset_11g; 688c533a883Shx147065 689c50ced99Spengcheng chen - Sun Microsystems - Beijing China /* set supported .11b and .11g channels (1 through 11) */ 690c50ced99Spengcheng chen - Sun Microsystems - Beijing China for (i = 1; i <= 11; i++) { 691c533a883Shx147065 ic->ic_sup_channels[i].ich_freq = 692c533a883Shx147065 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 693c533a883Shx147065 ic->ic_sup_channels[i].ich_flags = 694c533a883Shx147065 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 695c50ced99Spengcheng chen - Sun Microsystems - Beijing China IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ | 696c50ced99Spengcheng chen - Sun Microsystems - Beijing China IEEE80211_CHAN_PASSIVE; 697c533a883Shx147065 } 69819d332feSfei feng - Sun Microsystems - Beijing China ic->ic_ibss_chan = &ic->ic_sup_channels[0]; 699cdc64593Sxinghua wen - Sun Microsystems - Beijing China 700c533a883Shx147065 ic->ic_xmit = iwk_send; 701c533a883Shx147065 /* 702c533a883Shx147065 * init Wifi layer 703c533a883Shx147065 */ 704c533a883Shx147065 ieee80211_attach(ic); 705c533a883Shx147065 706c533a883Shx147065 /* 707c533a883Shx147065 * different instance has different WPA door 708c533a883Shx147065 */ 709c533a883Shx147065 (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR, 710c533a883Shx147065 ddi_driver_name(dip), 711c533a883Shx147065 ddi_get_instance(dip)); 712c533a883Shx147065 713c533a883Shx147065 /* 714c533a883Shx147065 * Override 80211 default routines 715c533a883Shx147065 */ 716c533a883Shx147065 sc->sc_newstate = ic->ic_newstate; 717c533a883Shx147065 ic->ic_newstate = iwk_newstate; 718f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ic->ic_watchdog = iwk_watchdog; 719cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_recv_mgmt = ic->ic_recv_mgmt; 72019d332feSfei feng - Sun Microsystems - Beijing China ic->ic_recv_mgmt = iwk_recv_mgmt; 72143439c96Shx147065 ic->ic_node_alloc = iwk_node_alloc; 72243439c96Shx147065 ic->ic_node_free = iwk_node_free; 723c533a883Shx147065 ic->ic_crypto.cs_key_set = iwk_key_set; 724c533a883Shx147065 ieee80211_media_init(ic); 725c533a883Shx147065 /* 726c533a883Shx147065 * initialize default tx key 727c533a883Shx147065 */ 728c533a883Shx147065 ic->ic_def_txkey = 0; 729cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_add_softint(dip, &sc->sc_soft_hdl, DDI_INTR_SOFTPRI_MAX, 730cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_rx_softintr, (caddr_t)sc); 731c533a883Shx147065 if (err != DDI_SUCCESS) { 732cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 733cdc64593Sxinghua wen - Sun Microsystems - Beijing China "add soft interrupt failed\n"); 734c533a883Shx147065 goto attach_fail7; 735c533a883Shx147065 } 736c533a883Shx147065 737c533a883Shx147065 /* 738c533a883Shx147065 * Add the interrupt handler 739c533a883Shx147065 */ 740cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_add_handler(sc->sc_intr_htable[0], iwk_intr, 741cdc64593Sxinghua wen - Sun Microsystems - Beijing China (caddr_t)sc, NULL); 742c533a883Shx147065 if (err != DDI_SUCCESS) { 743cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 744cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_add_handle() failed\n"); 745c533a883Shx147065 goto attach_fail8; 746c533a883Shx147065 } 747c533a883Shx147065 748cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = ddi_intr_enable(sc->sc_intr_htable[0]); 749cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 750cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_attach(): " 751cdc64593Sxinghua wen - Sun Microsystems - Beijing China "ddi_intr_enable() failed\n"); 752cdc64593Sxinghua wen - Sun Microsystems - Beijing China goto attach_fail_intr_d; 753cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 754cdc64593Sxinghua wen - Sun Microsystems - Beijing China 755c533a883Shx147065 /* 756c533a883Shx147065 * Initialize pointer to device specific functions 757c533a883Shx147065 */ 758c533a883Shx147065 wd.wd_secalloc = WIFI_SEC_NONE; 759c533a883Shx147065 wd.wd_opmode = ic->ic_opmode; 760c533a883Shx147065 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr); 761c533a883Shx147065 762c533a883Shx147065 macp = mac_alloc(MAC_VERSION); 76319d332feSfei feng - Sun Microsystems - Beijing China if (macp == NULL) { 764c533a883Shx147065 cmn_err(CE_WARN, 765c533a883Shx147065 "iwk_attach(): failed to do mac_alloc()\n"); 766c533a883Shx147065 goto attach_fail9; 767c533a883Shx147065 } 768c533a883Shx147065 769c533a883Shx147065 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 770c533a883Shx147065 macp->m_driver = sc; 771c533a883Shx147065 macp->m_dip = dip; 772c533a883Shx147065 macp->m_src_addr = ic->ic_macaddr; 773c533a883Shx147065 macp->m_callbacks = &iwk_m_callbacks; 774c533a883Shx147065 macp->m_min_sdu = 0; 775c533a883Shx147065 macp->m_max_sdu = IEEE80211_MTU; 776c533a883Shx147065 macp->m_pdata = &wd; 777c533a883Shx147065 macp->m_pdata_size = sizeof (wd); 778c533a883Shx147065 779c533a883Shx147065 /* 780c533a883Shx147065 * Register the macp to mac 781c533a883Shx147065 */ 782c533a883Shx147065 err = mac_register(macp, &ic->ic_mach); 783c533a883Shx147065 mac_free(macp); 784c533a883Shx147065 if (err != DDI_SUCCESS) { 785c533a883Shx147065 cmn_err(CE_WARN, 786c533a883Shx147065 "iwk_attach(): failed to do mac_register()\n"); 787c533a883Shx147065 goto attach_fail9; 788c533a883Shx147065 } 789c533a883Shx147065 790c533a883Shx147065 /* 791c533a883Shx147065 * Create minor node of type DDI_NT_NET_WIFI 792c533a883Shx147065 */ 793c533a883Shx147065 (void) snprintf(strbuf, sizeof (strbuf), DRV_NAME_4965"%d", instance); 794c533a883Shx147065 err = ddi_create_minor_node(dip, strbuf, S_IFCHR, 795c533a883Shx147065 instance + 1, DDI_NT_NET_WIFI, 0); 796c533a883Shx147065 if (err != DDI_SUCCESS) 797c533a883Shx147065 cmn_err(CE_WARN, 798c533a883Shx147065 "iwk_attach(): failed to do ddi_create_minor_node()\n"); 799c533a883Shx147065 800c533a883Shx147065 /* 801c533a883Shx147065 * Notify link is down now 802c533a883Shx147065 */ 803c533a883Shx147065 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 804c533a883Shx147065 805c533a883Shx147065 /* 806c533a883Shx147065 * create the mf thread to handle the link status, 807c533a883Shx147065 * recovery fatal error, etc. 808c533a883Shx147065 */ 809c533a883Shx147065 sc->sc_mf_thread_switch = 1; 810c533a883Shx147065 if (sc->sc_mf_thread == NULL) 811c533a883Shx147065 sc->sc_mf_thread = thread_create((caddr_t)NULL, 0, 812c533a883Shx147065 iwk_thread, sc, 0, &p0, TS_RUN, minclsyspri); 813c533a883Shx147065 814c533a883Shx147065 sc->sc_flags |= IWK_F_ATTACHED; 815c533a883Shx147065 816c533a883Shx147065 return (DDI_SUCCESS); 817c533a883Shx147065 attach_fail9: 818cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_disable(sc->sc_intr_htable[0]); 819cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_d: 820cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]); 821cdc64593Sxinghua wen - Sun Microsystems - Beijing China 822c533a883Shx147065 attach_fail8: 823cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_softint(sc->sc_soft_hdl); 824cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_soft_hdl = NULL; 825c533a883Shx147065 attach_fail7: 826c533a883Shx147065 ieee80211_detach(ic); 827c533a883Shx147065 attach_fail6: 828c533a883Shx147065 iwk_free_fw_dma(sc); 829c533a883Shx147065 attach_fail5: 830c533a883Shx147065 iwk_ring_free(sc); 831c533a883Shx147065 attach_fail4: 832c533a883Shx147065 iwk_free_kw(sc); 833c533a883Shx147065 attach_fail3a: 834c533a883Shx147065 iwk_free_shared(sc); 835c533a883Shx147065 attach_fail3: 836c533a883Shx147065 iwk_destroy_locks(sc); 837cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_c: 838cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_free(sc->sc_intr_htable[0]); 839cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_b: 840cdc64593Sxinghua wen - Sun Microsystems - Beijing China kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t)); 841cdc64593Sxinghua wen - Sun Microsystems - Beijing China attach_fail_intr_a: 842c533a883Shx147065 ddi_regs_map_free(&sc->sc_handle); 843c533a883Shx147065 attach_fail2a: 844c533a883Shx147065 ddi_regs_map_free(&sc->sc_cfg_handle); 845c533a883Shx147065 attach_fail2: 846c533a883Shx147065 ddi_soft_state_free(iwk_soft_state_p, instance); 847c533a883Shx147065 attach_fail1: 848c533a883Shx147065 return (err); 849c533a883Shx147065 } 850c533a883Shx147065 851c533a883Shx147065 int 852c533a883Shx147065 iwk_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 853c533a883Shx147065 { 854c533a883Shx147065 iwk_sc_t *sc; 855c533a883Shx147065 int err; 856c533a883Shx147065 857c533a883Shx147065 sc = ddi_get_soft_state(iwk_soft_state_p, ddi_get_instance(dip)); 858c533a883Shx147065 ASSERT(sc != NULL); 859c533a883Shx147065 860d62cb7ffShx147065 switch (cmd) { 861d62cb7ffShx147065 case DDI_DETACH: 862d62cb7ffShx147065 break; 863d62cb7ffShx147065 case DDI_SUSPEND: 864d62cb7ffShx147065 mutex_enter(&sc->sc_glock); 865d62cb7ffShx147065 sc->sc_flags |= IWK_F_SUSPEND; 866d62cb7ffShx147065 mutex_exit(&sc->sc_glock); 867d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING) { 868d40f4da4Spengcheng chen - Sun Microsystems - Beijing China iwk_stop(sc); 869d40f4da4Spengcheng chen - Sun Microsystems - Beijing China } 870d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 871d62cb7ffShx147065 IWK_DBG((IWK_DEBUG_RESUME, "iwk: suspend\n")); 872d62cb7ffShx147065 return (DDI_SUCCESS); 873d62cb7ffShx147065 default: 874c533a883Shx147065 return (DDI_FAILURE); 875d62cb7ffShx147065 } 87643439c96Shx147065 877c533a883Shx147065 if (!(sc->sc_flags & IWK_F_ATTACHED)) 878c533a883Shx147065 return (DDI_FAILURE); 879c533a883Shx147065 880cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = mac_disable(sc->sc_ic.ic_mach); 881cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) 882cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err); 883cdc64593Sxinghua wen - Sun Microsystems - Beijing China 884c533a883Shx147065 /* 885c533a883Shx147065 * Destroy the mf_thread 886c533a883Shx147065 */ 887c533a883Shx147065 mutex_enter(&sc->sc_mt_lock); 888c533a883Shx147065 sc->sc_mf_thread_switch = 0; 889c533a883Shx147065 while (sc->sc_mf_thread != NULL) { 890c533a883Shx147065 if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0) 891c533a883Shx147065 break; 892c533a883Shx147065 } 893c533a883Shx147065 mutex_exit(&sc->sc_mt_lock); 894c533a883Shx147065 895c533a883Shx147065 iwk_stop(sc); 896c533a883Shx147065 DELAY(500000); 897c533a883Shx147065 898c533a883Shx147065 /* 899c533a883Shx147065 * Unregiste from the MAC layer subsystem 900c533a883Shx147065 */ 901cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) mac_unregister(sc->sc_ic.ic_mach); 902c533a883Shx147065 903c533a883Shx147065 mutex_enter(&sc->sc_glock); 904c533a883Shx147065 iwk_free_fw_dma(sc); 905c533a883Shx147065 iwk_ring_free(sc); 906c533a883Shx147065 iwk_free_kw(sc); 907c533a883Shx147065 iwk_free_shared(sc); 908c533a883Shx147065 mutex_exit(&sc->sc_glock); 909c533a883Shx147065 910cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_disable(sc->sc_intr_htable[0]); 911cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]); 912cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_free(sc->sc_intr_htable[0]); 913cdc64593Sxinghua wen - Sun Microsystems - Beijing China kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t)); 914cdc64593Sxinghua wen - Sun Microsystems - Beijing China 915cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_remove_softint(sc->sc_soft_hdl); 916cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_soft_hdl = NULL; 917c533a883Shx147065 918c533a883Shx147065 /* 919c533a883Shx147065 * detach ieee80211 920c533a883Shx147065 */ 921c533a883Shx147065 ieee80211_detach(&sc->sc_ic); 922c533a883Shx147065 923c533a883Shx147065 iwk_destroy_locks(sc); 924c533a883Shx147065 925c533a883Shx147065 ddi_regs_map_free(&sc->sc_handle); 926c533a883Shx147065 ddi_regs_map_free(&sc->sc_cfg_handle); 927c533a883Shx147065 ddi_remove_minor_node(dip, NULL); 928c533a883Shx147065 ddi_soft_state_free(iwk_soft_state_p, ddi_get_instance(dip)); 929c533a883Shx147065 930c533a883Shx147065 return (DDI_SUCCESS); 931c533a883Shx147065 } 932c533a883Shx147065 933d2a61391Spengcheng chen - Sun Microsystems - Beijing China /* 934d2a61391Spengcheng chen - Sun Microsystems - Beijing China * quiesce(9E) entry point. 935d2a61391Spengcheng chen - Sun Microsystems - Beijing China * 936d2a61391Spengcheng chen - Sun Microsystems - Beijing China * This function is called when the system is single-threaded at high 937d2a61391Spengcheng chen - Sun Microsystems - Beijing China * PIL with preemption disabled. Therefore, this function must not be 938d2a61391Spengcheng chen - Sun Microsystems - Beijing China * blocked. 939d2a61391Spengcheng chen - Sun Microsystems - Beijing China * 940d2a61391Spengcheng chen - Sun Microsystems - Beijing China * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 941d2a61391Spengcheng chen - Sun Microsystems - Beijing China * DDI_FAILURE indicates an error condition and should almost never happen. 942d2a61391Spengcheng chen - Sun Microsystems - Beijing China */ 943d2a61391Spengcheng chen - Sun Microsystems - Beijing China int 944d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_quiesce(dev_info_t *dip) 945d2a61391Spengcheng chen - Sun Microsystems - Beijing China { 946d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_sc_t *sc; 947d2a61391Spengcheng chen - Sun Microsystems - Beijing China 948d2a61391Spengcheng chen - Sun Microsystems - Beijing China sc = ddi_get_soft_state(iwk_soft_state_p, ddi_get_instance(dip)); 949d2a61391Spengcheng chen - Sun Microsystems - Beijing China ASSERT(sc != NULL); 950d2a61391Spengcheng chen - Sun Microsystems - Beijing China 951d2a61391Spengcheng chen - Sun Microsystems - Beijing China /* no message prints and no lock accquisition */ 952d2a61391Spengcheng chen - Sun Microsystems - Beijing China #ifdef DEBUG 953d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_dbg_flags = 0; 954d2a61391Spengcheng chen - Sun Microsystems - Beijing China #endif 955d2a61391Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_QUIESCED; 956d2a61391Spengcheng chen - Sun Microsystems - Beijing China 957d2a61391Spengcheng chen - Sun Microsystems - Beijing China iwk_stop(sc); 958d2a61391Spengcheng chen - Sun Microsystems - Beijing China 959d2a61391Spengcheng chen - Sun Microsystems - Beijing China return (DDI_SUCCESS); 960d2a61391Spengcheng chen - Sun Microsystems - Beijing China } 961d2a61391Spengcheng chen - Sun Microsystems - Beijing China 962c533a883Shx147065 static void 963c533a883Shx147065 iwk_destroy_locks(iwk_sc_t *sc) 964c533a883Shx147065 { 965c533a883Shx147065 cv_destroy(&sc->sc_mt_cv); 966c533a883Shx147065 mutex_destroy(&sc->sc_mt_lock); 967c533a883Shx147065 cv_destroy(&sc->sc_tx_cv); 968c533a883Shx147065 cv_destroy(&sc->sc_cmd_cv); 969c533a883Shx147065 cv_destroy(&sc->sc_fw_cv); 970c533a883Shx147065 mutex_destroy(&sc->sc_tx_lock); 971c533a883Shx147065 mutex_destroy(&sc->sc_glock); 972c533a883Shx147065 } 973c533a883Shx147065 974c533a883Shx147065 /* 975c533a883Shx147065 * Allocate an area of memory and a DMA handle for accessing it 976c533a883Shx147065 */ 977c533a883Shx147065 static int 978c533a883Shx147065 iwk_alloc_dma_mem(iwk_sc_t *sc, size_t memsize, 979c533a883Shx147065 ddi_dma_attr_t *dma_attr_p, ddi_device_acc_attr_t *acc_attr_p, 980c533a883Shx147065 uint_t dma_flags, iwk_dma_t *dma_p) 981c533a883Shx147065 { 982c533a883Shx147065 caddr_t vaddr; 983c533a883Shx147065 int err; 984c533a883Shx147065 985c533a883Shx147065 /* 986c533a883Shx147065 * Allocate handle 987c533a883Shx147065 */ 988c533a883Shx147065 err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p, 989c533a883Shx147065 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 990c533a883Shx147065 if (err != DDI_SUCCESS) { 991c533a883Shx147065 dma_p->dma_hdl = NULL; 992c533a883Shx147065 return (DDI_FAILURE); 993c533a883Shx147065 } 994c533a883Shx147065 995c533a883Shx147065 /* 996c533a883Shx147065 * Allocate memory 997c533a883Shx147065 */ 998c533a883Shx147065 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p, 999c533a883Shx147065 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 1000c533a883Shx147065 DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl); 1001c533a883Shx147065 if (err != DDI_SUCCESS) { 1002c533a883Shx147065 ddi_dma_free_handle(&dma_p->dma_hdl); 1003c533a883Shx147065 dma_p->dma_hdl = NULL; 1004c533a883Shx147065 dma_p->acc_hdl = NULL; 1005c533a883Shx147065 return (DDI_FAILURE); 1006c533a883Shx147065 } 1007c533a883Shx147065 1008c533a883Shx147065 /* 1009c533a883Shx147065 * Bind the two together 1010c533a883Shx147065 */ 1011c533a883Shx147065 dma_p->mem_va = vaddr; 1012c533a883Shx147065 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 1013c533a883Shx147065 vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL, 1014c533a883Shx147065 &dma_p->cookie, &dma_p->ncookies); 1015c533a883Shx147065 if (err != DDI_DMA_MAPPED) { 1016c533a883Shx147065 ddi_dma_mem_free(&dma_p->acc_hdl); 1017c533a883Shx147065 ddi_dma_free_handle(&dma_p->dma_hdl); 1018c533a883Shx147065 dma_p->acc_hdl = NULL; 1019c533a883Shx147065 dma_p->dma_hdl = NULL; 1020c533a883Shx147065 return (DDI_FAILURE); 1021c533a883Shx147065 } 1022c533a883Shx147065 1023c533a883Shx147065 dma_p->nslots = ~0U; 1024c533a883Shx147065 dma_p->size = ~0U; 1025c533a883Shx147065 dma_p->token = ~0U; 1026c533a883Shx147065 dma_p->offset = 0; 1027c533a883Shx147065 return (DDI_SUCCESS); 1028c533a883Shx147065 } 1029c533a883Shx147065 1030c533a883Shx147065 /* 1031c533a883Shx147065 * Free one allocated area of DMAable memory 1032c533a883Shx147065 */ 1033c533a883Shx147065 static void 1034c533a883Shx147065 iwk_free_dma_mem(iwk_dma_t *dma_p) 1035c533a883Shx147065 { 1036c533a883Shx147065 if (dma_p->dma_hdl != NULL) { 1037c533a883Shx147065 if (dma_p->ncookies) { 1038c533a883Shx147065 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 1039c533a883Shx147065 dma_p->ncookies = 0; 1040c533a883Shx147065 } 1041c533a883Shx147065 ddi_dma_free_handle(&dma_p->dma_hdl); 1042c533a883Shx147065 dma_p->dma_hdl = NULL; 1043c533a883Shx147065 } 1044c533a883Shx147065 1045c533a883Shx147065 if (dma_p->acc_hdl != NULL) { 1046c533a883Shx147065 ddi_dma_mem_free(&dma_p->acc_hdl); 1047c533a883Shx147065 dma_p->acc_hdl = NULL; 1048c533a883Shx147065 } 1049c533a883Shx147065 } 1050c533a883Shx147065 1051c533a883Shx147065 /* 1052c533a883Shx147065 * 1053c533a883Shx147065 */ 1054c533a883Shx147065 static int 1055c533a883Shx147065 iwk_alloc_fw_dma(iwk_sc_t *sc) 1056c533a883Shx147065 { 1057c533a883Shx147065 int err = DDI_SUCCESS; 1058c533a883Shx147065 iwk_dma_t *dma_p; 1059c533a883Shx147065 char *t; 1060c533a883Shx147065 1061c533a883Shx147065 /* 1062c533a883Shx147065 * firmware image layout: 1063c533a883Shx147065 * |HDR|<-TEXT->|<-DATA->|<-INIT_TEXT->|<-INIT_DATA->|<-BOOT->| 1064c533a883Shx147065 */ 1065c533a883Shx147065 t = (char *)(sc->sc_hdr + 1); 1066c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz), 1067c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr, 1068c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1069c533a883Shx147065 &sc->sc_dma_fw_text); 1070c533a883Shx147065 dma_p = &sc->sc_dma_fw_text; 1071c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "text[ncookies:%d addr:%lx size:%lx]\n", 1072c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1073c533a883Shx147065 dma_p->cookie.dmac_size)); 1074c533a883Shx147065 if (err != DDI_SUCCESS) { 1075c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc" 1076c533a883Shx147065 " text dma memory"); 1077c533a883Shx147065 goto fail; 1078c533a883Shx147065 } 1079c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->textsz)); 1080c533a883Shx147065 1081c533a883Shx147065 t += LE_32(sc->sc_hdr->textsz); 1082c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz), 1083c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr, 1084c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1085c533a883Shx147065 &sc->sc_dma_fw_data); 1086c533a883Shx147065 dma_p = &sc->sc_dma_fw_data; 1087c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "data[ncookies:%d addr:%lx size:%lx]\n", 1088c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1089c533a883Shx147065 dma_p->cookie.dmac_size)); 1090c533a883Shx147065 if (err != DDI_SUCCESS) { 1091c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc" 1092c533a883Shx147065 " data dma memory"); 1093c533a883Shx147065 goto fail; 1094c533a883Shx147065 } 1095c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz)); 1096c533a883Shx147065 1097c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz), 1098c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr, 1099c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1100c533a883Shx147065 &sc->sc_dma_fw_data_bak); 1101c533a883Shx147065 dma_p = &sc->sc_dma_fw_data_bak; 1102c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "data_bak[ncookies:%d addr:%lx " 1103c533a883Shx147065 "size:%lx]\n", 1104c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1105c533a883Shx147065 dma_p->cookie.dmac_size)); 1106c533a883Shx147065 if (err != DDI_SUCCESS) { 1107c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc" 1108c533a883Shx147065 " data bakeup dma memory"); 1109c533a883Shx147065 goto fail; 1110c533a883Shx147065 } 1111c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz)); 1112c533a883Shx147065 1113c533a883Shx147065 t += LE_32(sc->sc_hdr->datasz); 1114c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_textsz), 1115c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr, 1116c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1117c533a883Shx147065 &sc->sc_dma_fw_init_text); 1118c533a883Shx147065 dma_p = &sc->sc_dma_fw_init_text; 1119c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "init_text[ncookies:%d addr:%lx " 1120c533a883Shx147065 "size:%lx]\n", 1121c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1122c533a883Shx147065 dma_p->cookie.dmac_size)); 1123c533a883Shx147065 if (err != DDI_SUCCESS) { 1124c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc" 1125c533a883Shx147065 "init text dma memory"); 1126c533a883Shx147065 goto fail; 1127c533a883Shx147065 } 1128c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_textsz)); 1129c533a883Shx147065 1130c533a883Shx147065 t += LE_32(sc->sc_hdr->init_textsz); 1131c533a883Shx147065 err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_datasz), 1132c533a883Shx147065 &fw_dma_attr, &iwk_dma_accattr, 1133c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1134c533a883Shx147065 &sc->sc_dma_fw_init_data); 1135c533a883Shx147065 dma_p = &sc->sc_dma_fw_init_data; 1136c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "init_data[ncookies:%d addr:%lx " 1137c533a883Shx147065 "size:%lx]\n", 1138c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1139c533a883Shx147065 dma_p->cookie.dmac_size)); 1140c533a883Shx147065 if (err != DDI_SUCCESS) { 1141c533a883Shx147065 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc" 1142c533a883Shx147065 "init data dma memory"); 1143c533a883Shx147065 goto fail; 1144c533a883Shx147065 } 1145c533a883Shx147065 (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_datasz)); 1146c533a883Shx147065 1147c533a883Shx147065 sc->sc_boot = t + LE_32(sc->sc_hdr->init_datasz); 1148c533a883Shx147065 fail: 1149c533a883Shx147065 return (err); 1150c533a883Shx147065 } 1151c533a883Shx147065 1152c533a883Shx147065 static void 1153c533a883Shx147065 iwk_free_fw_dma(iwk_sc_t *sc) 1154c533a883Shx147065 { 1155c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_text); 1156c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_data); 1157c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_data_bak); 1158c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_init_text); 1159c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_fw_init_data); 1160c533a883Shx147065 } 1161c533a883Shx147065 1162c533a883Shx147065 /* 1163c533a883Shx147065 * Allocate a shared page between host and NIC. 1164c533a883Shx147065 */ 1165c533a883Shx147065 static int 1166c533a883Shx147065 iwk_alloc_shared(iwk_sc_t *sc) 1167c533a883Shx147065 { 1168c533a883Shx147065 iwk_dma_t *dma_p; 1169c533a883Shx147065 int err = DDI_SUCCESS; 1170c533a883Shx147065 1171c533a883Shx147065 /* must be aligned on a 4K-page boundary */ 1172c533a883Shx147065 err = iwk_alloc_dma_mem(sc, sizeof (iwk_shared_t), 1173b510adaeSfei feng - Sun Microsystems - Beijing China &sh_dma_attr, &iwk_dma_descattr, 1174c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1175c533a883Shx147065 &sc->sc_dma_sh); 1176c533a883Shx147065 if (err != DDI_SUCCESS) 1177c533a883Shx147065 goto fail; 1178c533a883Shx147065 sc->sc_shared = (iwk_shared_t *)sc->sc_dma_sh.mem_va; 1179c533a883Shx147065 1180c533a883Shx147065 dma_p = &sc->sc_dma_sh; 1181c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "sh[ncookies:%d addr:%lx size:%lx]\n", 1182c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1183c533a883Shx147065 dma_p->cookie.dmac_size)); 1184c533a883Shx147065 1185c533a883Shx147065 return (err); 1186c533a883Shx147065 fail: 1187c533a883Shx147065 iwk_free_shared(sc); 1188c533a883Shx147065 return (err); 1189c533a883Shx147065 } 1190c533a883Shx147065 1191c533a883Shx147065 static void 1192c533a883Shx147065 iwk_free_shared(iwk_sc_t *sc) 1193c533a883Shx147065 { 1194c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_sh); 1195c533a883Shx147065 } 1196c533a883Shx147065 1197c533a883Shx147065 /* 1198c533a883Shx147065 * Allocate a keep warm page. 1199c533a883Shx147065 */ 1200c533a883Shx147065 static int 1201c533a883Shx147065 iwk_alloc_kw(iwk_sc_t *sc) 1202c533a883Shx147065 { 1203c533a883Shx147065 iwk_dma_t *dma_p; 1204c533a883Shx147065 int err = DDI_SUCCESS; 1205c533a883Shx147065 1206c533a883Shx147065 /* must be aligned on a 4K-page boundary */ 1207c533a883Shx147065 err = iwk_alloc_dma_mem(sc, IWK_KW_SIZE, 1208c533a883Shx147065 &kw_dma_attr, &iwk_dma_accattr, 1209c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1210c533a883Shx147065 &sc->sc_dma_kw); 1211c533a883Shx147065 if (err != DDI_SUCCESS) 1212c533a883Shx147065 goto fail; 1213c533a883Shx147065 1214c533a883Shx147065 dma_p = &sc->sc_dma_kw; 1215c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "kw[ncookies:%d addr:%lx size:%lx]\n", 1216c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1217c533a883Shx147065 dma_p->cookie.dmac_size)); 1218c533a883Shx147065 1219c533a883Shx147065 return (err); 1220c533a883Shx147065 fail: 1221c533a883Shx147065 iwk_free_kw(sc); 1222c533a883Shx147065 return (err); 1223c533a883Shx147065 } 1224c533a883Shx147065 1225c533a883Shx147065 static void 1226c533a883Shx147065 iwk_free_kw(iwk_sc_t *sc) 1227c533a883Shx147065 { 1228c533a883Shx147065 iwk_free_dma_mem(&sc->sc_dma_kw); 1229c533a883Shx147065 } 1230c533a883Shx147065 1231c533a883Shx147065 static int 1232c533a883Shx147065 iwk_alloc_rx_ring(iwk_sc_t *sc) 1233c533a883Shx147065 { 1234c533a883Shx147065 iwk_rx_ring_t *ring; 1235c533a883Shx147065 iwk_rx_data_t *data; 1236c533a883Shx147065 iwk_dma_t *dma_p; 1237c533a883Shx147065 int i, err = DDI_SUCCESS; 1238c533a883Shx147065 1239c533a883Shx147065 ring = &sc->sc_rxq; 1240c533a883Shx147065 ring->cur = 0; 1241c533a883Shx147065 1242c533a883Shx147065 err = iwk_alloc_dma_mem(sc, RX_QUEUE_SIZE * sizeof (uint32_t), 1243b510adaeSfei feng - Sun Microsystems - Beijing China &ring_desc_dma_attr, &iwk_dma_descattr, 1244c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1245c533a883Shx147065 &ring->dma_desc); 1246c533a883Shx147065 if (err != DDI_SUCCESS) { 1247c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc rx ring desc failed\n"); 1248c533a883Shx147065 goto fail; 1249c533a883Shx147065 } 1250c533a883Shx147065 ring->desc = (uint32_t *)ring->dma_desc.mem_va; 1251c533a883Shx147065 dma_p = &ring->dma_desc; 1252c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "rx bd[ncookies:%d addr:%lx size:%lx]\n", 1253c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1254c533a883Shx147065 dma_p->cookie.dmac_size)); 1255c533a883Shx147065 1256c533a883Shx147065 /* 1257c533a883Shx147065 * Allocate Rx buffers. 1258c533a883Shx147065 */ 1259c533a883Shx147065 for (i = 0; i < RX_QUEUE_SIZE; i++) { 1260c533a883Shx147065 data = &ring->data[i]; 1261c533a883Shx147065 err = iwk_alloc_dma_mem(sc, sc->sc_dmabuf_sz, 1262c533a883Shx147065 &rx_buffer_dma_attr, &iwk_dma_accattr, 1263c533a883Shx147065 DDI_DMA_READ | DDI_DMA_STREAMING, 1264c533a883Shx147065 &data->dma_data); 1265c533a883Shx147065 if (err != DDI_SUCCESS) { 1266c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc rx ring buf[%d] " 1267c50ced99Spengcheng chen - Sun Microsystems - Beijing China "failed\n", i); 1268c533a883Shx147065 goto fail; 1269c533a883Shx147065 } 1270c533a883Shx147065 /* 1271c533a883Shx147065 * the physical address bit [8-36] are used, 1272c533a883Shx147065 * instead of bit [0-31] in 3945. 1273c533a883Shx147065 */ 1274b510adaeSfei feng - Sun Microsystems - Beijing China ring->desc[i] = (uint32_t) 1275b510adaeSfei feng - Sun Microsystems - Beijing China (data->dma_data.cookie.dmac_address >> 8); 1276c533a883Shx147065 } 1277c533a883Shx147065 dma_p = &ring->data[0].dma_data; 1278c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "rx buffer[0][ncookies:%d addr:%lx " 1279c533a883Shx147065 "size:%lx]\n", 1280c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1281c533a883Shx147065 dma_p->cookie.dmac_size)); 1282c533a883Shx147065 1283c533a883Shx147065 IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 1284c533a883Shx147065 1285c533a883Shx147065 return (err); 1286c533a883Shx147065 1287c533a883Shx147065 fail: 1288c533a883Shx147065 iwk_free_rx_ring(sc); 1289c533a883Shx147065 return (err); 1290c533a883Shx147065 } 1291c533a883Shx147065 1292c533a883Shx147065 static void 1293c533a883Shx147065 iwk_reset_rx_ring(iwk_sc_t *sc) 1294c533a883Shx147065 { 1295c533a883Shx147065 int n; 1296c533a883Shx147065 1297c533a883Shx147065 iwk_mac_access_enter(sc); 1298c533a883Shx147065 IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 1299c533a883Shx147065 for (n = 0; n < 2000; n++) { 1300c533a883Shx147065 if (IWK_READ(sc, FH_MEM_RSSR_RX_STATUS_REG) & (1 << 24)) 1301c533a883Shx147065 break; 1302c533a883Shx147065 DELAY(1000); 1303c533a883Shx147065 } 1304d2a61391Spengcheng chen - Sun Microsystems - Beijing China 1305c533a883Shx147065 if (n == 2000) 1306c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "timeout resetting Rx ring\n")); 1307d2a61391Spengcheng chen - Sun Microsystems - Beijing China 1308c533a883Shx147065 iwk_mac_access_exit(sc); 1309c533a883Shx147065 1310c533a883Shx147065 sc->sc_rxq.cur = 0; 1311c533a883Shx147065 } 1312c533a883Shx147065 1313c533a883Shx147065 static void 1314c533a883Shx147065 iwk_free_rx_ring(iwk_sc_t *sc) 1315c533a883Shx147065 { 1316c533a883Shx147065 int i; 1317c533a883Shx147065 1318c533a883Shx147065 for (i = 0; i < RX_QUEUE_SIZE; i++) { 1319c533a883Shx147065 if (sc->sc_rxq.data[i].dma_data.dma_hdl) 1320c533a883Shx147065 IWK_DMA_SYNC(sc->sc_rxq.data[i].dma_data, 1321c533a883Shx147065 DDI_DMA_SYNC_FORCPU); 1322c533a883Shx147065 iwk_free_dma_mem(&sc->sc_rxq.data[i].dma_data); 1323c533a883Shx147065 } 1324c533a883Shx147065 1325c533a883Shx147065 if (sc->sc_rxq.dma_desc.dma_hdl) 1326c533a883Shx147065 IWK_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV); 1327c533a883Shx147065 iwk_free_dma_mem(&sc->sc_rxq.dma_desc); 1328c533a883Shx147065 } 1329c533a883Shx147065 1330c533a883Shx147065 static int 1331c533a883Shx147065 iwk_alloc_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring, 1332c533a883Shx147065 int slots, int qid) 1333c533a883Shx147065 { 1334c533a883Shx147065 iwk_tx_data_t *data; 1335c533a883Shx147065 iwk_tx_desc_t *desc_h; 1336c533a883Shx147065 uint32_t paddr_desc_h; 1337c533a883Shx147065 iwk_cmd_t *cmd_h; 1338c533a883Shx147065 uint32_t paddr_cmd_h; 1339c533a883Shx147065 iwk_dma_t *dma_p; 1340c533a883Shx147065 int i, err = DDI_SUCCESS; 1341c533a883Shx147065 1342c533a883Shx147065 ring->qid = qid; 1343c533a883Shx147065 ring->count = TFD_QUEUE_SIZE_MAX; 1344c533a883Shx147065 ring->window = slots; 1345c533a883Shx147065 ring->queued = 0; 1346c533a883Shx147065 ring->cur = 0; 1347c533a883Shx147065 1348c533a883Shx147065 err = iwk_alloc_dma_mem(sc, 1349c533a883Shx147065 TFD_QUEUE_SIZE_MAX * sizeof (iwk_tx_desc_t), 1350b510adaeSfei feng - Sun Microsystems - Beijing China &ring_desc_dma_attr, &iwk_dma_descattr, 1351c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1352c533a883Shx147065 &ring->dma_desc); 1353c533a883Shx147065 if (err != DDI_SUCCESS) { 1354c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc tx ring desc[%d] " 1355c50ced99Spengcheng chen - Sun Microsystems - Beijing China "failed\n", qid); 1356c533a883Shx147065 goto fail; 1357c533a883Shx147065 } 1358c533a883Shx147065 dma_p = &ring->dma_desc; 1359c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "tx bd[ncookies:%d addr:%lx size:%lx]\n", 1360c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1361c533a883Shx147065 dma_p->cookie.dmac_size)); 1362c533a883Shx147065 1363c533a883Shx147065 desc_h = (iwk_tx_desc_t *)ring->dma_desc.mem_va; 1364c533a883Shx147065 paddr_desc_h = ring->dma_desc.cookie.dmac_address; 1365c533a883Shx147065 1366c533a883Shx147065 err = iwk_alloc_dma_mem(sc, 1367c533a883Shx147065 TFD_QUEUE_SIZE_MAX * sizeof (iwk_cmd_t), 1368c533a883Shx147065 &cmd_dma_attr, &iwk_dma_accattr, 1369c533a883Shx147065 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1370c533a883Shx147065 &ring->dma_cmd); 1371c533a883Shx147065 if (err != DDI_SUCCESS) { 1372c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc tx ring cmd[%d] " 1373c50ced99Spengcheng chen - Sun Microsystems - Beijing China "failed\n", qid); 1374c533a883Shx147065 goto fail; 1375c533a883Shx147065 } 1376c533a883Shx147065 dma_p = &ring->dma_cmd; 1377c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "tx cmd[ncookies:%d addr:%lx size:%lx]\n", 1378c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1379c533a883Shx147065 dma_p->cookie.dmac_size)); 1380c533a883Shx147065 1381c533a883Shx147065 cmd_h = (iwk_cmd_t *)ring->dma_cmd.mem_va; 1382c533a883Shx147065 paddr_cmd_h = ring->dma_cmd.cookie.dmac_address; 1383c533a883Shx147065 1384c533a883Shx147065 /* 1385c533a883Shx147065 * Allocate Tx buffers. 1386c533a883Shx147065 */ 1387c533a883Shx147065 ring->data = kmem_zalloc(sizeof (iwk_tx_data_t) * TFD_QUEUE_SIZE_MAX, 1388c533a883Shx147065 KM_NOSLEEP); 1389c533a883Shx147065 if (ring->data == NULL) { 1390c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not allocate tx data slots\n"); 1391c533a883Shx147065 goto fail; 1392c533a883Shx147065 } 1393c533a883Shx147065 1394c533a883Shx147065 for (i = 0; i < TFD_QUEUE_SIZE_MAX; i++) { 1395c533a883Shx147065 data = &ring->data[i]; 1396c533a883Shx147065 err = iwk_alloc_dma_mem(sc, sc->sc_dmabuf_sz, 1397c533a883Shx147065 &tx_buffer_dma_attr, &iwk_dma_accattr, 1398c533a883Shx147065 DDI_DMA_WRITE | DDI_DMA_STREAMING, 1399c533a883Shx147065 &data->dma_data); 1400c533a883Shx147065 if (err != DDI_SUCCESS) { 1401c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "dma alloc tx ring " 1402c50ced99Spengcheng chen - Sun Microsystems - Beijing China "buf[%d] failed\n", i); 1403c533a883Shx147065 goto fail; 1404c533a883Shx147065 } 1405c533a883Shx147065 1406c533a883Shx147065 data->desc = desc_h + i; 1407c533a883Shx147065 data->paddr_desc = paddr_desc_h + 1408ff3124efSff224033 _PTRDIFF(data->desc, desc_h); 1409c533a883Shx147065 data->cmd = cmd_h + i; /* (i % slots); */ 1410cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* ((i % slots) * sizeof (iwk_cmd_t)); */ 1411c533a883Shx147065 data->paddr_cmd = paddr_cmd_h + 1412ff3124efSff224033 _PTRDIFF(data->cmd, cmd_h); 1413c533a883Shx147065 } 1414c533a883Shx147065 dma_p = &ring->data[0].dma_data; 1415c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "tx buffer[0][ncookies:%d addr:%lx " 1416c533a883Shx147065 "size:%lx]\n", 1417c533a883Shx147065 dma_p->ncookies, dma_p->cookie.dmac_address, 1418c533a883Shx147065 dma_p->cookie.dmac_size)); 1419c533a883Shx147065 1420c533a883Shx147065 return (err); 1421c533a883Shx147065 1422c533a883Shx147065 fail: 1423c533a883Shx147065 if (ring->data) 1424c533a883Shx147065 kmem_free(ring->data, 1425c533a883Shx147065 sizeof (iwk_tx_data_t) * TFD_QUEUE_SIZE_MAX); 1426c533a883Shx147065 iwk_free_tx_ring(sc, ring); 1427c533a883Shx147065 return (err); 1428c533a883Shx147065 } 1429c533a883Shx147065 1430c533a883Shx147065 static void 1431c533a883Shx147065 iwk_reset_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring) 1432c533a883Shx147065 { 1433c533a883Shx147065 iwk_tx_data_t *data; 1434c533a883Shx147065 int i, n; 1435c533a883Shx147065 1436c533a883Shx147065 iwk_mac_access_enter(sc); 1437c533a883Shx147065 1438c533a883Shx147065 IWK_WRITE(sc, IWK_FH_TCSR_CHNL_TX_CONFIG_REG(ring->qid), 0); 1439c533a883Shx147065 for (n = 0; n < 200; n++) { 1440c533a883Shx147065 if (IWK_READ(sc, IWK_FH_TSSR_TX_STATUS_REG) & 1441c533a883Shx147065 IWK_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ring->qid)) 1442c533a883Shx147065 break; 1443c533a883Shx147065 DELAY(10); 1444c533a883Shx147065 } 1445c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (n == 200) { 1446c533a883Shx147065 IWK_DBG((IWK_DEBUG_DMA, "timeout reset tx ring %d\n", 1447c533a883Shx147065 ring->qid)); 1448c533a883Shx147065 } 1449c533a883Shx147065 iwk_mac_access_exit(sc); 1450c533a883Shx147065 1451c533a883Shx147065 for (i = 0; i < ring->count; i++) { 1452c533a883Shx147065 data = &ring->data[i]; 1453c533a883Shx147065 IWK_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV); 1454c533a883Shx147065 } 1455c533a883Shx147065 1456c533a883Shx147065 ring->queued = 0; 1457c533a883Shx147065 ring->cur = 0; 1458c533a883Shx147065 } 1459c533a883Shx147065 1460c533a883Shx147065 /*ARGSUSED*/ 1461c533a883Shx147065 static void 1462c533a883Shx147065 iwk_free_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring) 1463c533a883Shx147065 { 1464c533a883Shx147065 int i; 1465c533a883Shx147065 1466c533a883Shx147065 if (ring->dma_desc.dma_hdl != NULL) 1467c533a883Shx147065 IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 1468c533a883Shx147065 iwk_free_dma_mem(&ring->dma_desc); 1469c533a883Shx147065 1470c533a883Shx147065 if (ring->dma_cmd.dma_hdl != NULL) 1471c533a883Shx147065 IWK_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV); 1472c533a883Shx147065 iwk_free_dma_mem(&ring->dma_cmd); 1473c533a883Shx147065 1474c533a883Shx147065 if (ring->data != NULL) { 1475c533a883Shx147065 for (i = 0; i < ring->count; i++) { 1476c533a883Shx147065 if (ring->data[i].dma_data.dma_hdl) 1477c533a883Shx147065 IWK_DMA_SYNC(ring->data[i].dma_data, 1478c533a883Shx147065 DDI_DMA_SYNC_FORDEV); 1479c533a883Shx147065 iwk_free_dma_mem(&ring->data[i].dma_data); 1480c533a883Shx147065 } 1481c533a883Shx147065 kmem_free(ring->data, ring->count * sizeof (iwk_tx_data_t)); 1482c533a883Shx147065 } 1483c533a883Shx147065 } 1484c533a883Shx147065 1485c533a883Shx147065 static int 1486c533a883Shx147065 iwk_ring_init(iwk_sc_t *sc) 1487c533a883Shx147065 { 1488c533a883Shx147065 int i, err = DDI_SUCCESS; 1489c533a883Shx147065 1490c533a883Shx147065 for (i = 0; i < IWK_NUM_QUEUES; i++) { 1491c533a883Shx147065 if (i == IWK_CMD_QUEUE_NUM) 1492c533a883Shx147065 continue; 1493c533a883Shx147065 err = iwk_alloc_tx_ring(sc, &sc->sc_txq[i], TFD_TX_CMD_SLOTS, 1494c533a883Shx147065 i); 1495c533a883Shx147065 if (err != DDI_SUCCESS) 1496c533a883Shx147065 goto fail; 1497c533a883Shx147065 } 1498c533a883Shx147065 err = iwk_alloc_tx_ring(sc, &sc->sc_txq[IWK_CMD_QUEUE_NUM], 1499c533a883Shx147065 TFD_CMD_SLOTS, IWK_CMD_QUEUE_NUM); 1500c533a883Shx147065 if (err != DDI_SUCCESS) 1501c533a883Shx147065 goto fail; 1502c533a883Shx147065 err = iwk_alloc_rx_ring(sc); 1503c533a883Shx147065 if (err != DDI_SUCCESS) 1504c533a883Shx147065 goto fail; 1505c533a883Shx147065 return (err); 1506c533a883Shx147065 1507c533a883Shx147065 fail: 1508c533a883Shx147065 return (err); 1509c533a883Shx147065 } 1510c533a883Shx147065 1511c533a883Shx147065 static void 1512c533a883Shx147065 iwk_ring_free(iwk_sc_t *sc) 1513c533a883Shx147065 { 1514c533a883Shx147065 int i = IWK_NUM_QUEUES; 1515c533a883Shx147065 1516c533a883Shx147065 iwk_free_rx_ring(sc); 1517c533a883Shx147065 while (--i >= 0) { 1518c533a883Shx147065 iwk_free_tx_ring(sc, &sc->sc_txq[i]); 1519c533a883Shx147065 } 1520c533a883Shx147065 } 1521c533a883Shx147065 1522c533a883Shx147065 /* ARGSUSED */ 152343439c96Shx147065 static ieee80211_node_t * 152443439c96Shx147065 iwk_node_alloc(ieee80211com_t *ic) 152543439c96Shx147065 { 152643439c96Shx147065 iwk_amrr_t *amrr; 152743439c96Shx147065 152843439c96Shx147065 amrr = kmem_zalloc(sizeof (iwk_amrr_t), KM_SLEEP); 152943439c96Shx147065 if (amrr != NULL) 153043439c96Shx147065 iwk_amrr_init(amrr); 153143439c96Shx147065 return (&amrr->in); 153243439c96Shx147065 } 153343439c96Shx147065 153443439c96Shx147065 static void 153543439c96Shx147065 iwk_node_free(ieee80211_node_t *in) 153643439c96Shx147065 { 153743439c96Shx147065 ieee80211com_t *ic = in->in_ic; 153843439c96Shx147065 153943439c96Shx147065 ic->ic_node_cleanup(in); 154043439c96Shx147065 if (in->in_wpa_ie != NULL) 154143439c96Shx147065 ieee80211_free(in->in_wpa_ie); 154243439c96Shx147065 kmem_free(in, sizeof (iwk_amrr_t)); 154343439c96Shx147065 } 154443439c96Shx147065 154543439c96Shx147065 /*ARGSUSED*/ 1546c533a883Shx147065 static int 1547c533a883Shx147065 iwk_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg) 1548c533a883Shx147065 { 1549c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)ic; 155043439c96Shx147065 ieee80211_node_t *in = ic->ic_bss; 1551c533a883Shx147065 enum ieee80211_state ostate = ic->ic_state; 1552c533a883Shx147065 int i, err = IWK_SUCCESS; 1553c533a883Shx147065 1554c533a883Shx147065 mutex_enter(&sc->sc_glock); 1555c533a883Shx147065 switch (nstate) { 1556c533a883Shx147065 case IEEE80211_S_SCAN: 1557c50ced99Spengcheng chen - Sun Microsystems - Beijing China switch (ostate) { 1558c50ced99Spengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_INIT: 1559c50ced99Spengcheng chen - Sun Microsystems - Beijing China { 1560c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_add_sta_t node; 1561c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1562c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_SCANNING; 1563f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending = 0; 1564c533a883Shx147065 iwk_set_led(sc, 2, 10, 2); 1565c533a883Shx147065 1566c50ced99Spengcheng chen - Sun Microsystems - Beijing China /* 1567c50ced99Spengcheng chen - Sun Microsystems - Beijing China * clear association to receive beacons from 1568c50ced99Spengcheng chen - Sun Microsystems - Beijing China * all BSS'es 1569c50ced99Spengcheng chen - Sun Microsystems - Beijing China */ 1570c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.assoc_id = 0; 1571c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.filter_flags &= 1572c50ced99Spengcheng chen - Sun Microsystems - Beijing China ~LE_32(RXON_FILTER_ASSOC_MSK); 1573c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1574c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "config chan %d " 1575c50ced99Spengcheng chen - Sun Microsystems - Beijing China "flags %x filter_flags %x\n", sc->sc_config.chan, 1576c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.flags, sc->sc_config.filter_flags)); 1577c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1578c50ced99Spengcheng chen - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config, 1579c50ced99Spengcheng chen - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1); 1580c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 1581c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, 1582c50ced99Spengcheng chen - Sun Microsystems - Beijing China "could not clear association\n"); 1583c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 1584c533a883Shx147065 mutex_exit(&sc->sc_glock); 1585c533a883Shx147065 return (err); 1586c533a883Shx147065 } 1587c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1588c50ced99Spengcheng chen - Sun Microsystems - Beijing China /* add broadcast node to send probe request */ 1589c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) memset(&node, 0, sizeof (node)); 1590c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) memset(&node.bssid, 0xff, IEEE80211_ADDR_LEN); 1591c50ced99Spengcheng chen - Sun Microsystems - Beijing China node.id = IWK_BROADCAST_ID; 1592c50ced99Spengcheng chen - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA, &node, 1593c50ced99Spengcheng chen - Sun Microsystems - Beijing China sizeof (node), 1); 1594c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 1595c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not add " 1596c50ced99Spengcheng chen - Sun Microsystems - Beijing China "broadcast node\n"); 1597c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 1598c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 1599c50ced99Spengcheng chen - Sun Microsystems - Beijing China return (err); 1600c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 1601c50ced99Spengcheng chen - Sun Microsystems - Beijing China break; 1602c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 1603f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 1604f3c4902cSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_AUTH: 1605f3c4902cSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_ASSOC: 1606f3c4902cSpengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_RUN: 1607f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_SCANNING; 1608f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending = 0; 1609f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 1610f3c4902cSpengcheng chen - Sun Microsystems - Beijing China iwk_set_led(sc, 2, 10, 2); 1611f3c4902cSpengcheng chen - Sun Microsystems - Beijing China /* FALLTHRU */ 1612c50ced99Spengcheng chen - Sun Microsystems - Beijing China case IEEE80211_S_SCAN: 1613c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 1614c50ced99Spengcheng chen - Sun Microsystems - Beijing China /* step to next channel before actual FW scan */ 1615c50ced99Spengcheng chen - Sun Microsystems - Beijing China err = sc->sc_newstate(ic, nstate, arg); 1616c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 1617c50ced99Spengcheng chen - Sun Microsystems - Beijing China if ((err != 0) || ((err = iwk_scan(sc)) != 0)) { 1618c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, 1619c50ced99Spengcheng chen - Sun Microsystems - Beijing China "could not initiate scan\n"); 1620c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 1621c50ced99Spengcheng chen - Sun Microsystems - Beijing China ieee80211_cancel_scan(ic); 1622c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 1623c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 1624c50ced99Spengcheng chen - Sun Microsystems - Beijing China return (err); 1625c50ced99Spengcheng chen - Sun Microsystems - Beijing China default: 1626c50ced99Spengcheng chen - Sun Microsystems - Beijing China break; 1627c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1628c533a883Shx147065 } 162943439c96Shx147065 sc->sc_clk = 0; 1630c50ced99Spengcheng chen - Sun Microsystems - Beijing China break; 1631c533a883Shx147065 1632c533a883Shx147065 case IEEE80211_S_AUTH: 1633c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) { 1634c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 1635c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 1636c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1637c533a883Shx147065 /* reset state to handle reassociations correctly */ 1638c533a883Shx147065 sc->sc_config.assoc_id = 0; 1639c533a883Shx147065 sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK); 1640c533a883Shx147065 1641c533a883Shx147065 /* 1642c533a883Shx147065 * before sending authentication and association request frame, 1643c533a883Shx147065 * we need do something in the hardware, such as setting the 1644c533a883Shx147065 * channel same to the target AP... 1645c533a883Shx147065 */ 1646c533a883Shx147065 if ((err = iwk_hw_set_before_auth(sc)) != 0) { 1647c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "could not setup firmware for " 1648c50ced99Spengcheng chen - Sun Microsystems - Beijing China "authentication\n"); 1649c533a883Shx147065 mutex_exit(&sc->sc_glock); 1650c533a883Shx147065 return (err); 1651c533a883Shx147065 } 1652c533a883Shx147065 break; 1653c533a883Shx147065 1654c533a883Shx147065 case IEEE80211_S_RUN: 1655c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) { 1656c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 1657c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 1658c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1659c533a883Shx147065 if (ic->ic_opmode == IEEE80211_M_MONITOR) { 1660c533a883Shx147065 /* let LED blink when monitoring */ 1661c533a883Shx147065 iwk_set_led(sc, 2, 10, 10); 1662c533a883Shx147065 break; 1663c533a883Shx147065 } 1664c533a883Shx147065 IWK_DBG((IWK_DEBUG_80211, "iwk: associated.")); 1665c533a883Shx147065 166619d332feSfei feng - Sun Microsystems - Beijing China /* IBSS mode */ 166719d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS) { 166819d332feSfei feng - Sun Microsystems - Beijing China /* 166919d332feSfei feng - Sun Microsystems - Beijing China * clean all nodes in ibss node table 167019d332feSfei feng - Sun Microsystems - Beijing China * in order to be consistent with hardware 167119d332feSfei feng - Sun Microsystems - Beijing China */ 167219d332feSfei feng - Sun Microsystems - Beijing China err = iwk_run_state_config_ibss(ic); 167319d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 167419d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): " 167519d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration " 167619d332feSfei feng - Sun Microsystems - Beijing China "in IBSS mode\n"); 167719d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 167819d332feSfei feng - Sun Microsystems - Beijing China return (err); 167919d332feSfei feng - Sun Microsystems - Beijing China } 168019d332feSfei feng - Sun Microsystems - Beijing China } 168119d332feSfei feng - Sun Microsystems - Beijing China 1682cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* none IBSS mode */ 1683cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (ic->ic_opmode != IEEE80211_M_IBSS) { 1684c533a883Shx147065 /* update adapter's configuration */ 168519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_run_state_config_sta(ic); 1686c533a883Shx147065 if (err != IWK_SUCCESS) { 168719d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): " 168819d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration " 168919d332feSfei feng - Sun Microsystems - Beijing China "in none IBSS mode\n"); 1690c533a883Shx147065 mutex_exit(&sc->sc_glock); 1691c533a883Shx147065 return (err); 1692c533a883Shx147065 } 1693cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 1694cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1695cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */ 1696cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc); 1697c533a883Shx147065 1698c533a883Shx147065 /* 1699cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Tx power calibration to determine 1700cdc64593Sxinghua wen - Sun Microsystems - Beijing China * the gains of DSP and radio 1701c533a883Shx147065 */ 1702cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc); 1703cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) { 1704cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): " 1705cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to set tx power table\n"); 170619d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 1707c533a883Shx147065 return (err); 1708c533a883Shx147065 } 1709c533a883Shx147065 171019d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS) { 171119d332feSfei feng - Sun Microsystems - Beijing China 171219d332feSfei feng - Sun Microsystems - Beijing China /* 171319d332feSfei feng - Sun Microsystems - Beijing China * allocate and transmit beacon frames 171419d332feSfei feng - Sun Microsystems - Beijing China */ 171519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_start_tx_beacon(ic); 171619d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 171719d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): " 171819d332feSfei feng - Sun Microsystems - Beijing China "can't transmit beacon frames\n"); 171919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 172019d332feSfei feng - Sun Microsystems - Beijing China return (err); 172119d332feSfei feng - Sun Microsystems - Beijing China } 172219d332feSfei feng - Sun Microsystems - Beijing China } 172319d332feSfei feng - Sun Microsystems - Beijing China 172443439c96Shx147065 /* start automatic rate control */ 172543439c96Shx147065 mutex_enter(&sc->sc_mt_lock); 172643439c96Shx147065 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 172743439c96Shx147065 sc->sc_flags |= IWK_F_RATE_AUTO_CTL; 172843439c96Shx147065 /* set rate to some reasonable initial value */ 172943439c96Shx147065 i = in->in_rates.ir_nrates - 1; 173043439c96Shx147065 while (i > 0 && IEEE80211_RATE(i) > 72) 173143439c96Shx147065 i--; 173243439c96Shx147065 in->in_txrate = i; 173343439c96Shx147065 } else { 173443439c96Shx147065 sc->sc_flags &= ~IWK_F_RATE_AUTO_CTL; 173543439c96Shx147065 } 173643439c96Shx147065 mutex_exit(&sc->sc_mt_lock); 173743439c96Shx147065 1738c533a883Shx147065 /* set LED on after associated */ 1739c533a883Shx147065 iwk_set_led(sc, 2, 0, 1); 1740c533a883Shx147065 break; 1741c533a883Shx147065 1742c533a883Shx147065 case IEEE80211_S_INIT: 1743c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) { 1744c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 1745c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 1746c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1747c533a883Shx147065 /* set LED off after init */ 1748c533a883Shx147065 iwk_set_led(sc, 2, 1, 0); 1749c533a883Shx147065 break; 1750c533a883Shx147065 case IEEE80211_S_ASSOC: 1751c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_SCAN) { 1752c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 1753c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 1754c50ced99Spengcheng chen - Sun Microsystems - Beijing China 1755c533a883Shx147065 break; 1756c533a883Shx147065 } 1757c533a883Shx147065 1758c533a883Shx147065 mutex_exit(&sc->sc_glock); 1759cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1760cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = sc->sc_newstate(ic, nstate, arg); 1761cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1762cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (nstate == IEEE80211_S_RUN) { 1763cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1764cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 1765cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1766cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 1767cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make initialization for Receiver 1768cdc64593Sxinghua wen - Sun Microsystems - Beijing China * sensitivity calibration 1769cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 1770cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_rx_sens_init(sc); 1771cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) { 1772cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): " 1773cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to init RX sensitivity\n"); 1774c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 1775cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err); 1776cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 1777cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1778cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make initialization for Receiver gain balance */ 1779cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_rxgain_diff_init(sc); 1780cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) { 1781cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_newstate(): " 1782cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to init phy calibration\n"); 1783c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 1784cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err); 1785cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 1786cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1787cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 1788cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1789cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 1790cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1791cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (err); 1792c533a883Shx147065 } 1793c533a883Shx147065 1794f3c4902cSpengcheng chen - Sun Microsystems - Beijing China static void 1795f3c4902cSpengcheng chen - Sun Microsystems - Beijing China iwk_watchdog(void *arg) 1796f3c4902cSpengcheng chen - Sun Microsystems - Beijing China { 1797f3c4902cSpengcheng chen - Sun Microsystems - Beijing China iwk_sc_t *sc = arg; 1798f3c4902cSpengcheng chen - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 1799f3c4902cSpengcheng chen - Sun Microsystems - Beijing China #ifdef DEBUG 1800f3c4902cSpengcheng chen - Sun Microsystems - Beijing China timeout_id_t timeout_id = ic->ic_watchdog_timer; 1801f3c4902cSpengcheng chen - Sun Microsystems - Beijing China #endif 1802f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 1803f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic); 1804f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 1805f3c4902cSpengcheng chen - Sun Microsystems - Beijing China if ((ic->ic_state != IEEE80211_S_AUTH) && 1806f3c4902cSpengcheng chen - Sun Microsystems - Beijing China (ic->ic_state != IEEE80211_S_ASSOC)) 1807f3c4902cSpengcheng chen - Sun Microsystems - Beijing China return; 1808f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 1809f3c4902cSpengcheng chen - Sun Microsystems - Beijing China if (ic->ic_bss->in_fails > 0) { 1810f3c4902cSpengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "watchdog (0x%x) reset: " 1811f3c4902cSpengcheng chen - Sun Microsystems - Beijing China "node (0x%x)\n", timeout_id, &ic->ic_bss)); 1812f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 1813f3c4902cSpengcheng chen - Sun Microsystems - Beijing China } else { 1814f3c4902cSpengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "watchdog (0x%x) timeout: " 1815f3c4902cSpengcheng chen - Sun Microsystems - Beijing China "node (0x%x), retry (%d)\n", 1816f3c4902cSpengcheng chen - Sun Microsystems - Beijing China timeout_id, &ic->ic_bss, ic->ic_bss->in_fails + 1)); 1817f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_watchdog(ic); 1818f3c4902cSpengcheng chen - Sun Microsystems - Beijing China } 1819f3c4902cSpengcheng chen - Sun Microsystems - Beijing China } 1820f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 1821c533a883Shx147065 /*ARGSUSED*/ 1822c533a883Shx147065 static int iwk_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 1823c533a883Shx147065 const uint8_t mac[IEEE80211_ADDR_LEN]) 1824c533a883Shx147065 { 1825c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)ic; 1826c533a883Shx147065 iwk_add_sta_t node; 1827c533a883Shx147065 int err; 182819d332feSfei feng - Sun Microsystems - Beijing China uint8_t index1; 1829c533a883Shx147065 1830c533a883Shx147065 switch (k->wk_cipher->ic_cipher) { 1831c533a883Shx147065 case IEEE80211_CIPHER_WEP: 1832c533a883Shx147065 case IEEE80211_CIPHER_TKIP: 1833c533a883Shx147065 return (1); /* sofeware do it. */ 1834c533a883Shx147065 case IEEE80211_CIPHER_AES_CCM: 1835c533a883Shx147065 break; 1836c533a883Shx147065 default: 1837c533a883Shx147065 return (0); 1838c533a883Shx147065 } 1839b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_DIS_DECRYPT_MSK | 1840cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK); 1841c533a883Shx147065 1842c533a883Shx147065 mutex_enter(&sc->sc_glock); 1843c533a883Shx147065 1844c533a883Shx147065 /* update ap/multicast node */ 1845c533a883Shx147065 (void) memset(&node, 0, sizeof (node)); 1846c533a883Shx147065 if (IEEE80211_IS_MULTICAST(mac)) { 1847c533a883Shx147065 (void) memset(node.bssid, 0xff, 6); 1848c533a883Shx147065 node.id = IWK_BROADCAST_ID; 184919d332feSfei feng - Sun Microsystems - Beijing China } else if (ic->ic_opmode == IEEE80211_M_IBSS) { 185019d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 185119d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock); 185219d332feSfei feng - Sun Microsystems - Beijing China 185319d332feSfei feng - Sun Microsystems - Beijing China /* 185419d332feSfei feng - Sun Microsystems - Beijing China * search for node in ibss node table 185519d332feSfei feng - Sun Microsystems - Beijing China */ 185619d332feSfei feng - Sun Microsystems - Beijing China for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT; 185719d332feSfei feng - Sun Microsystems - Beijing China index1++) { 185819d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_node_tb[index1].used && 185919d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_EQ(sc->sc_ibss. 186019d332feSfei feng - Sun Microsystems - Beijing China ibss_node_tb[index1].node.bssid, 186119d332feSfei feng - Sun Microsystems - Beijing China mac)) { 186219d332feSfei feng - Sun Microsystems - Beijing China break; 186319d332feSfei feng - Sun Microsystems - Beijing China } 186419d332feSfei feng - Sun Microsystems - Beijing China } 186519d332feSfei feng - Sun Microsystems - Beijing China if (index1 >= IWK_BROADCAST_ID) { 186619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_key_set(): " 186719d332feSfei feng - Sun Microsystems - Beijing China "have no this node in hardware node table\n"); 186819d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock); 186919d332feSfei feng - Sun Microsystems - Beijing China return (0); 187019d332feSfei feng - Sun Microsystems - Beijing China } else { 187119d332feSfei feng - Sun Microsystems - Beijing China /* 187219d332feSfei feng - Sun Microsystems - Beijing China * configure key for given node in hardware 187319d332feSfei feng - Sun Microsystems - Beijing China */ 187419d332feSfei feng - Sun Microsystems - Beijing China if (k->wk_flags & IEEE80211_KEY_XMIT) { 187519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1]. 187619d332feSfei feng - Sun Microsystems - Beijing China node.key_flags = 0; 187719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1]. 187819d332feSfei feng - Sun Microsystems - Beijing China node.keyp = k->wk_keyix; 187919d332feSfei feng - Sun Microsystems - Beijing China } else { 188019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1]. 188119d332feSfei feng - Sun Microsystems - Beijing China node.key_flags = (1 << 14); 188219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1]. 188319d332feSfei feng - Sun Microsystems - Beijing China node.keyp = k->wk_keyix + 4; 188419d332feSfei feng - Sun Microsystems - Beijing China } 188519d332feSfei feng - Sun Microsystems - Beijing China 188619d332feSfei feng - Sun Microsystems - Beijing China (void) memcpy(sc->sc_ibss.ibss_node_tb[index1].node.key, 188719d332feSfei feng - Sun Microsystems - Beijing China k->wk_key, k->wk_keylen); 188819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.key_flags |= 188919d332feSfei feng - Sun Microsystems - Beijing China (STA_KEY_FLG_CCMP | (1 << 3) | (k->wk_keyix << 8)); 1890b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.key_flags = 1891b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(sc->sc_ibss.ibss_node_tb[index1]. 1892b510adaeSfei feng - Sun Microsystems - Beijing China node.key_flags); 189319d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.sta_mask = 189419d332feSfei feng - Sun Microsystems - Beijing China STA_MODIFY_KEY_MASK; 189519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[index1].node.control = 1; 189619d332feSfei feng - Sun Microsystems - Beijing China 189719d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 189819d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA, 189919d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_node_tb[index1].node, 190019d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t), 1); 190119d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 190219d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_key_set(): " 190319d332feSfei feng - Sun Microsystems - Beijing China "failed to update IBSS node in hardware\n"); 190419d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 190519d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock); 190619d332feSfei feng - Sun Microsystems - Beijing China return (0); 190719d332feSfei feng - Sun Microsystems - Beijing China } 190819d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 190919d332feSfei feng - Sun Microsystems - Beijing China } 191019d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock); 191119d332feSfei feng - Sun Microsystems - Beijing China return (1); 1912c533a883Shx147065 } else { 1913c533a883Shx147065 IEEE80211_ADDR_COPY(node.bssid, ic->ic_bss->in_bssid); 1914c533a883Shx147065 node.id = IWK_AP_ID; 1915c533a883Shx147065 } 1916c533a883Shx147065 if (k->wk_flags & IEEE80211_KEY_XMIT) { 1917c533a883Shx147065 node.key_flags = 0; 1918c533a883Shx147065 node.keyp = k->wk_keyix; 1919c533a883Shx147065 } else { 1920c533a883Shx147065 node.key_flags = (1 << 14); 1921c533a883Shx147065 node.keyp = k->wk_keyix + 4; 1922c533a883Shx147065 } 1923c533a883Shx147065 (void) memcpy(node.key, k->wk_key, k->wk_keylen); 1924c533a883Shx147065 node.key_flags |= (STA_KEY_FLG_CCMP | (1 << 3) | (k->wk_keyix << 8)); 1925b510adaeSfei feng - Sun Microsystems - Beijing China node.key_flags = LE_16(node.key_flags); 1926c533a883Shx147065 node.sta_mask = STA_MODIFY_KEY_MASK; 1927c533a883Shx147065 node.control = 1; 1928c533a883Shx147065 err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1); 1929c533a883Shx147065 if (err != IWK_SUCCESS) { 1930c533a883Shx147065 cmn_err(CE_WARN, "iwk_key_set():" 1931c533a883Shx147065 "failed to update ap node\n"); 1932c533a883Shx147065 mutex_exit(&sc->sc_glock); 1933c533a883Shx147065 return (0); 1934c533a883Shx147065 } 1935c533a883Shx147065 mutex_exit(&sc->sc_glock); 1936c533a883Shx147065 return (1); 1937c533a883Shx147065 } 1938c533a883Shx147065 1939c533a883Shx147065 /* 1940c533a883Shx147065 * exclusive access to mac begin. 1941c533a883Shx147065 */ 1942c533a883Shx147065 static void 1943c533a883Shx147065 iwk_mac_access_enter(iwk_sc_t *sc) 1944c533a883Shx147065 { 1945c533a883Shx147065 uint32_t tmp; 1946c533a883Shx147065 int n; 1947c533a883Shx147065 1948c533a883Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL); 1949c533a883Shx147065 IWK_WRITE(sc, CSR_GP_CNTRL, 1950c533a883Shx147065 tmp | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1951c533a883Shx147065 1952c533a883Shx147065 /* wait until we succeed */ 1953c533a883Shx147065 for (n = 0; n < 1000; n++) { 1954c533a883Shx147065 if ((IWK_READ(sc, CSR_GP_CNTRL) & 1955c533a883Shx147065 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | 1956c533a883Shx147065 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP)) == 1957c533a883Shx147065 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN) 1958c533a883Shx147065 break; 1959c533a883Shx147065 DELAY(10); 1960c533a883Shx147065 } 1961c533a883Shx147065 if (n == 1000) 1962c533a883Shx147065 IWK_DBG((IWK_DEBUG_PIO, "could not lock memory\n")); 1963c533a883Shx147065 } 1964c533a883Shx147065 1965c533a883Shx147065 /* 1966c533a883Shx147065 * exclusive access to mac end. 1967c533a883Shx147065 */ 1968c533a883Shx147065 static void 1969c533a883Shx147065 iwk_mac_access_exit(iwk_sc_t *sc) 1970c533a883Shx147065 { 1971c533a883Shx147065 uint32_t tmp = IWK_READ(sc, CSR_GP_CNTRL); 1972c533a883Shx147065 IWK_WRITE(sc, CSR_GP_CNTRL, 1973c533a883Shx147065 tmp & ~CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1974c533a883Shx147065 } 1975c533a883Shx147065 1976cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint32_t 1977cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mem_read(iwk_sc_t *sc, uint32_t addr) 1978cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 1979cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_WRITE(sc, HBUS_TARG_MEM_RADDR, addr); 1980cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_READ(sc, HBUS_TARG_MEM_RDAT)); 1981cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 1982c533a883Shx147065 1983c533a883Shx147065 static void 1984c533a883Shx147065 iwk_mem_write(iwk_sc_t *sc, uint32_t addr, uint32_t data) 1985c533a883Shx147065 { 1986c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_MEM_WADDR, addr); 1987c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_MEM_WDAT, data); 1988c533a883Shx147065 } 1989c533a883Shx147065 1990c533a883Shx147065 static uint32_t 1991c533a883Shx147065 iwk_reg_read(iwk_sc_t *sc, uint32_t addr) 1992c533a883Shx147065 { 1993c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_PRPH_RADDR, addr | (3 << 24)); 1994c533a883Shx147065 return (IWK_READ(sc, HBUS_TARG_PRPH_RDAT)); 1995c533a883Shx147065 } 1996c533a883Shx147065 1997c533a883Shx147065 static void 1998c533a883Shx147065 iwk_reg_write(iwk_sc_t *sc, uint32_t addr, uint32_t data) 1999c533a883Shx147065 { 2000c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_PRPH_WADDR, addr | (3 << 24)); 2001c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_PRPH_WDAT, data); 2002c533a883Shx147065 } 2003c533a883Shx147065 2004c533a883Shx147065 static void 2005c533a883Shx147065 iwk_reg_write_region_4(iwk_sc_t *sc, uint32_t addr, 2006c533a883Shx147065 uint32_t *data, int wlen) 2007c533a883Shx147065 { 2008c533a883Shx147065 for (; wlen > 0; wlen--, data++, addr += 4) 2009b510adaeSfei feng - Sun Microsystems - Beijing China iwk_reg_write(sc, addr, LE_32(*data)); 2010c533a883Shx147065 } 2011c533a883Shx147065 2012c533a883Shx147065 2013c533a883Shx147065 /* 2014c533a883Shx147065 * ucode load/initialization steps: 2015c533a883Shx147065 * 1) load Bootstrap State Machine (BSM) with "bootstrap" uCode image. 2016c533a883Shx147065 * BSM contains a small memory that *always* stays powered up, so it can 2017c533a883Shx147065 * retain the bootstrap program even when the card is in a power-saving 2018c533a883Shx147065 * power-down state. The BSM loads the small program into ARC processor's 2019c533a883Shx147065 * instruction memory when triggered by power-up. 2020c533a883Shx147065 * 2) load Initialize image via bootstrap program. 2021c533a883Shx147065 * The Initialize image sets up regulatory and calibration data for the 2022c533a883Shx147065 * Runtime/Protocol uCode. This sends a REPLY_ALIVE notification when completed. 2023c533a883Shx147065 * The 4965 reply contains calibration data for temperature, voltage and tx gain 2024c533a883Shx147065 * correction. 2025c533a883Shx147065 */ 2026c533a883Shx147065 static int 2027c533a883Shx147065 iwk_load_firmware(iwk_sc_t *sc) 2028c533a883Shx147065 { 2029c533a883Shx147065 uint32_t *boot_fw = (uint32_t *)sc->sc_boot; 2030b510adaeSfei feng - Sun Microsystems - Beijing China uint32_t size = LE_32(sc->sc_hdr->bootsz); 2031c533a883Shx147065 int n, err = IWK_SUCCESS; 2032c533a883Shx147065 2033c533a883Shx147065 /* 2034c533a883Shx147065 * The physical address bit [4-35] of the initialize uCode. 2035c533a883Shx147065 * In the initialize alive notify interrupt the physical address of 2036c533a883Shx147065 * the runtime ucode will be set for loading. 2037c533a883Shx147065 */ 2038c533a883Shx147065 iwk_mac_access_enter(sc); 2039c533a883Shx147065 2040c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_PTR_REG, 2041c533a883Shx147065 sc->sc_dma_fw_init_text.cookie.dmac_address >> 4); 2042c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_PTR_REG, 2043c533a883Shx147065 sc->sc_dma_fw_init_data.cookie.dmac_address >> 4); 2044c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_BYTECOUNT_REG, 2045c533a883Shx147065 sc->sc_dma_fw_init_text.cookie.dmac_size); 2046c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_BYTECOUNT_REG, 2047c533a883Shx147065 sc->sc_dma_fw_init_data.cookie.dmac_size); 2048c533a883Shx147065 2049c533a883Shx147065 /* load bootstrap code into BSM memory */ 2050c533a883Shx147065 iwk_reg_write_region_4(sc, BSM_SRAM_LOWER_BOUND, boot_fw, 2051c533a883Shx147065 size / sizeof (uint32_t)); 2052c533a883Shx147065 2053c533a883Shx147065 iwk_reg_write(sc, BSM_WR_MEM_SRC_REG, 0); 2054c533a883Shx147065 iwk_reg_write(sc, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND); 2055c533a883Shx147065 iwk_reg_write(sc, BSM_WR_DWCOUNT_REG, size / sizeof (uint32_t)); 2056c533a883Shx147065 2057c533a883Shx147065 /* 2058c533a883Shx147065 * prepare to load initialize uCode 2059c533a883Shx147065 */ 2060c533a883Shx147065 iwk_reg_write(sc, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); 2061c533a883Shx147065 2062c533a883Shx147065 /* wait while the adapter is busy loading the firmware */ 2063c533a883Shx147065 for (n = 0; n < 1000; n++) { 2064c533a883Shx147065 if (!(iwk_reg_read(sc, BSM_WR_CTRL_REG) & 2065c533a883Shx147065 BSM_WR_CTRL_REG_BIT_START)) 2066c533a883Shx147065 break; 2067c533a883Shx147065 DELAY(10); 2068c533a883Shx147065 } 2069c533a883Shx147065 if (n == 1000) { 2070c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "timeout transferring firmware\n"); 2071c533a883Shx147065 err = ETIMEDOUT; 2072c533a883Shx147065 return (err); 2073c533a883Shx147065 } 2074c533a883Shx147065 2075c533a883Shx147065 /* for future power-save mode use */ 2076c533a883Shx147065 iwk_reg_write(sc, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); 2077c533a883Shx147065 2078c533a883Shx147065 iwk_mac_access_exit(sc); 2079c533a883Shx147065 2080c533a883Shx147065 return (err); 2081c533a883Shx147065 } 2082c533a883Shx147065 2083c533a883Shx147065 /*ARGSUSED*/ 2084c533a883Shx147065 static void 2085c533a883Shx147065 iwk_rx_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc, iwk_rx_data_t *data) 2086c533a883Shx147065 { 2087c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 2088c533a883Shx147065 iwk_rx_ring_t *ring = &sc->sc_rxq; 2089c533a883Shx147065 iwk_rx_phy_res_t *stat; 2090c533a883Shx147065 ieee80211_node_t *in; 2091c533a883Shx147065 uint32_t *tail; 2092c533a883Shx147065 struct ieee80211_frame *wh; 2093c533a883Shx147065 mblk_t *mp; 2094c533a883Shx147065 uint16_t len, rssi, mrssi, agc; 2095c533a883Shx147065 int16_t t; 2096c533a883Shx147065 uint32_t ants, i; 2097c533a883Shx147065 struct iwk_rx_non_cfg_phy *phyinfo; 2098b510adaeSfei feng - Sun Microsystems - Beijing China uint32_t crc; 2099c533a883Shx147065 2100c533a883Shx147065 /* assuming not 11n here. cope with 11n in phase-II */ 2101c533a883Shx147065 stat = (iwk_rx_phy_res_t *)(desc + 1); 2102c533a883Shx147065 if (stat->cfg_phy_cnt > 20) { 2103c533a883Shx147065 return; 2104c533a883Shx147065 } 2105c533a883Shx147065 2106b510adaeSfei feng - Sun Microsystems - Beijing China for (i = 0; i < RX_RES_PHY_CNT; i++) 2107b510adaeSfei feng - Sun Microsystems - Beijing China stat->non_cfg_phy[i] = LE_16(stat->non_cfg_phy[i]); 2108b510adaeSfei feng - Sun Microsystems - Beijing China 2109c533a883Shx147065 phyinfo = (struct iwk_rx_non_cfg_phy *)stat->non_cfg_phy; 2110c533a883Shx147065 agc = (phyinfo->agc_info & IWK_AGC_DB_MASK) >> IWK_AGC_DB_POS; 2111c533a883Shx147065 mrssi = 0; 2112b510adaeSfei feng - Sun Microsystems - Beijing China ants = (LE_16(stat->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) >> 2113cdc64593Sxinghua wen - Sun Microsystems - Beijing China RX_PHY_FLAGS_ANTENNAE_OFFSET; 2114c533a883Shx147065 for (i = 0; i < 3; i++) { 2115c533a883Shx147065 if (ants & (1 << i)) 2116c533a883Shx147065 mrssi = MAX(mrssi, phyinfo->rssi_info[i << 1]); 2117c533a883Shx147065 } 2118c533a883Shx147065 t = mrssi - agc - 44; /* t is the dBM value */ 2119c533a883Shx147065 /* 2120c533a883Shx147065 * convert dBm to percentage ??? 2121c533a883Shx147065 */ 2122cdc64593Sxinghua wen - Sun Microsystems - Beijing China rssi = (100 * 75 * 75 - (-20 - t) * (15 * 75 + 62 * (-20 - t))) / 2123cdc64593Sxinghua wen - Sun Microsystems - Beijing China (75 * 75); 2124c533a883Shx147065 if (rssi > 100) 2125c533a883Shx147065 rssi = 100; 2126c533a883Shx147065 if (rssi < 1) 2127c533a883Shx147065 rssi = 1; 2128b510adaeSfei feng - Sun Microsystems - Beijing China len = LE_16(stat->byte_count); 2129b510adaeSfei feng - Sun Microsystems - Beijing China tail = (uint32_t *)((caddr_t)(stat + 1) + stat->cfg_phy_cnt + len); 2130b510adaeSfei feng - Sun Microsystems - Beijing China bcopy(tail, &crc, 4); 2131c533a883Shx147065 2132c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx intr: idx=%d phy_len=%x len=%d " 2133c533a883Shx147065 "rate=%x chan=%d tstamp=%x non_cfg_phy_count=%x " 2134c533a883Shx147065 "cfg_phy_count=%x tail=%x", ring->cur, sizeof (*stat), 2135b510adaeSfei feng - Sun Microsystems - Beijing China len, stat->rate.r.s.rate, LE_16(stat->channel), 2136c533a883Shx147065 LE_32(stat->timestampl), stat->non_cfg_phy_cnt, 2137b510adaeSfei feng - Sun Microsystems - Beijing China stat->cfg_phy_cnt, LE_32(crc))); 2138c533a883Shx147065 2139c533a883Shx147065 if ((len < 16) || (len > sc->sc_dmabuf_sz)) { 2140c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx frame oversize\n")); 2141c533a883Shx147065 return; 2142c533a883Shx147065 } 2143c533a883Shx147065 2144c533a883Shx147065 /* 2145c533a883Shx147065 * discard Rx frames with bad CRC 2146c533a883Shx147065 */ 2147b510adaeSfei feng - Sun Microsystems - Beijing China if ((LE_32(crc) & 2148c533a883Shx147065 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) != 2149c533a883Shx147065 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) { 2150c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx crc error tail: %x\n", 2151b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(crc))); 2152c533a883Shx147065 sc->sc_rx_err++; 2153c533a883Shx147065 return; 2154c533a883Shx147065 } 2155c533a883Shx147065 2156c533a883Shx147065 wh = (struct ieee80211_frame *) 2157c533a883Shx147065 ((uint8_t *)(stat + 1)+ stat->cfg_phy_cnt); 2158c533a883Shx147065 if (*(uint8_t *)wh == IEEE80211_FC0_SUBTYPE_ASSOC_RESP) { 2159c533a883Shx147065 sc->sc_assoc_id = *((uint16_t *)(wh + 1) + 2); 2160c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, "rx : association id = %x\n", 2161c533a883Shx147065 sc->sc_assoc_id)); 2162c533a883Shx147065 } 2163c533a883Shx147065 #ifdef DEBUG 2164c533a883Shx147065 if (iwk_dbg_flags & IWK_DEBUG_RX) 2165c533a883Shx147065 ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0); 2166c533a883Shx147065 #endif 2167c533a883Shx147065 in = ieee80211_find_rxnode(ic, wh); 2168c533a883Shx147065 mp = allocb(len, BPRI_MED); 2169c533a883Shx147065 if (mp) { 2170c533a883Shx147065 (void) memcpy(mp->b_wptr, wh, len); 2171c533a883Shx147065 mp->b_wptr += len; 2172c533a883Shx147065 2173c533a883Shx147065 /* send the frame to the 802.11 layer */ 2174c533a883Shx147065 (void) ieee80211_input(ic, mp, in, rssi, 0); 2175c533a883Shx147065 } else { 2176c533a883Shx147065 sc->sc_rx_nobuf++; 2177c533a883Shx147065 IWK_DBG((IWK_DEBUG_RX, 2178c533a883Shx147065 "iwk_rx_intr(): alloc rx buf failed\n")); 2179c533a883Shx147065 } 2180c533a883Shx147065 /* release node reference */ 2181c533a883Shx147065 ieee80211_free_node(in); 2182c533a883Shx147065 } 2183c533a883Shx147065 2184c533a883Shx147065 /*ARGSUSED*/ 2185c533a883Shx147065 static void 2186c533a883Shx147065 iwk_tx_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc, iwk_rx_data_t *data) 2187c533a883Shx147065 { 2188c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 2189c533a883Shx147065 iwk_tx_ring_t *ring = &sc->sc_txq[desc->hdr.qid & 0x3]; 2190c533a883Shx147065 iwk_tx_stat_t *stat = (iwk_tx_stat_t *)(desc + 1); 219143439c96Shx147065 iwk_amrr_t *amrr = (iwk_amrr_t *)ic->ic_bss; 2192c533a883Shx147065 2193c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx done: qid=%d idx=%d" 2194c533a883Shx147065 " retries=%d frame_count=%x nkill=%d " 2195c533a883Shx147065 "rate=%x duration=%d status=%x\n", 2196c533a883Shx147065 desc->hdr.qid, desc->hdr.idx, stat->ntries, stat->frame_count, 2197c533a883Shx147065 stat->bt_kill_count, stat->rate.r.s.rate, 2198b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(stat->duration), LE_32(stat->status))); 2199c533a883Shx147065 220043439c96Shx147065 amrr->txcnt++; 220143439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL, "tx: %d cnt\n", amrr->txcnt)); 2202c533a883Shx147065 if (stat->ntries > 0) { 220343439c96Shx147065 amrr->retrycnt++; 2204c533a883Shx147065 sc->sc_tx_retries++; 2205c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx: %d retries\n", 2206c533a883Shx147065 sc->sc_tx_retries)); 2207c533a883Shx147065 } 2208c533a883Shx147065 2209c533a883Shx147065 sc->sc_tx_timer = 0; 2210c533a883Shx147065 2211c533a883Shx147065 mutex_enter(&sc->sc_tx_lock); 2212c533a883Shx147065 ring->queued--; 2213c533a883Shx147065 if (ring->queued < 0) 2214c533a883Shx147065 ring->queued = 0; 2215c533a883Shx147065 if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count << 3))) { 2216c533a883Shx147065 sc->sc_need_reschedule = 0; 2217c533a883Shx147065 mutex_exit(&sc->sc_tx_lock); 2218c533a883Shx147065 mac_tx_update(ic->ic_mach); 2219c533a883Shx147065 mutex_enter(&sc->sc_tx_lock); 2220c533a883Shx147065 } 2221c533a883Shx147065 mutex_exit(&sc->sc_tx_lock); 2222c533a883Shx147065 } 2223c533a883Shx147065 2224c533a883Shx147065 static void 2225c533a883Shx147065 iwk_cmd_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc) 2226c533a883Shx147065 { 2227c533a883Shx147065 if ((desc->hdr.qid & 7) != 4) { 2228c533a883Shx147065 return; 2229c533a883Shx147065 } 2230c533a883Shx147065 mutex_enter(&sc->sc_glock); 2231c533a883Shx147065 sc->sc_flags |= IWK_F_CMD_DONE; 2232c533a883Shx147065 cv_signal(&sc->sc_cmd_cv); 2233c533a883Shx147065 mutex_exit(&sc->sc_glock); 2234c533a883Shx147065 IWK_DBG((IWK_DEBUG_CMD, "rx cmd: " 2235c533a883Shx147065 "qid=%x idx=%d flags=%x type=0x%x\n", 2236c533a883Shx147065 desc->hdr.qid, desc->hdr.idx, desc->hdr.flags, 2237c533a883Shx147065 desc->hdr.type)); 2238c533a883Shx147065 } 2239c533a883Shx147065 2240c533a883Shx147065 static void 2241c533a883Shx147065 iwk_ucode_alive(iwk_sc_t *sc, iwk_rx_desc_t *desc) 2242c533a883Shx147065 { 2243c533a883Shx147065 uint32_t base, i; 2244c533a883Shx147065 struct iwk_alive_resp *ar = 2245c533a883Shx147065 (struct iwk_alive_resp *)(desc + 1); 2246c533a883Shx147065 2247c533a883Shx147065 /* the microcontroller is ready */ 2248c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, 2249c533a883Shx147065 "microcode alive notification minor: %x major: %x type:" 2250c533a883Shx147065 " %x subtype: %x\n", 2251c533a883Shx147065 ar->ucode_minor, ar->ucode_minor, ar->ver_type, ar->ver_subtype)); 2252c533a883Shx147065 2253c533a883Shx147065 if (LE_32(ar->is_valid) != UCODE_VALID_OK) { 2254c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, 2255c533a883Shx147065 "microcontroller initialization failed\n")); 2256c533a883Shx147065 } 2257c533a883Shx147065 if (ar->ver_subtype == INITIALIZE_SUBTYPE) { 2258c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, 2259c533a883Shx147065 "initialization alive received.\n")); 2260c533a883Shx147065 (void) memcpy(&sc->sc_card_alive_init, ar, 2261c533a883Shx147065 sizeof (struct iwk_init_alive_resp)); 2262c533a883Shx147065 /* XXX get temperature */ 2263c533a883Shx147065 iwk_mac_access_enter(sc); 2264c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_PTR_REG, 2265c533a883Shx147065 sc->sc_dma_fw_text.cookie.dmac_address >> 4); 2266c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_PTR_REG, 2267c533a883Shx147065 sc->sc_dma_fw_data_bak.cookie.dmac_address >> 4); 2268c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_DATA_BYTECOUNT_REG, 2269c533a883Shx147065 sc->sc_dma_fw_data.cookie.dmac_size); 2270c533a883Shx147065 iwk_reg_write(sc, BSM_DRAM_INST_BYTECOUNT_REG, 2271c533a883Shx147065 sc->sc_dma_fw_text.cookie.dmac_size | 0x80000000); 2272c533a883Shx147065 iwk_mac_access_exit(sc); 2273c533a883Shx147065 } else { 2274c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, "runtime alive received.\n")); 2275c533a883Shx147065 (void) memcpy(&sc->sc_card_alive_run, ar, 2276c533a883Shx147065 sizeof (struct iwk_alive_resp)); 2277c533a883Shx147065 2278c533a883Shx147065 /* 2279c533a883Shx147065 * Init SCD related registers to make Tx work. XXX 2280c533a883Shx147065 */ 2281c533a883Shx147065 iwk_mac_access_enter(sc); 2282c533a883Shx147065 2283c533a883Shx147065 /* read sram address of data base */ 2284c533a883Shx147065 sc->sc_scd_base = iwk_reg_read(sc, SCD_SRAM_BASE_ADDR); 2285c533a883Shx147065 2286c533a883Shx147065 /* clear and init SCD_CONTEXT_DATA_OFFSET area. 128 bytes */ 2287c533a883Shx147065 for (base = sc->sc_scd_base + SCD_CONTEXT_DATA_OFFSET, i = 0; 2288c533a883Shx147065 i < 128; i += 4) 2289c533a883Shx147065 iwk_mem_write(sc, base + i, 0); 2290c533a883Shx147065 2291c533a883Shx147065 /* clear and init SCD_TX_STTS_BITMAP_OFFSET area. 256 bytes */ 2292c533a883Shx147065 for (base = sc->sc_scd_base + SCD_TX_STTS_BITMAP_OFFSET; 2293c533a883Shx147065 i < 256; i += 4) 2294c533a883Shx147065 iwk_mem_write(sc, base + i, 0); 2295c533a883Shx147065 2296c533a883Shx147065 /* clear and init SCD_TRANSLATE_TBL_OFFSET area. 32 bytes */ 2297c533a883Shx147065 for (base = sc->sc_scd_base + SCD_TRANSLATE_TBL_OFFSET; 2298c533a883Shx147065 i < sizeof (uint16_t) * IWK_NUM_QUEUES; i += 4) 2299c533a883Shx147065 iwk_mem_write(sc, base + i, 0); 2300c533a883Shx147065 2301c533a883Shx147065 iwk_reg_write(sc, SCD_DRAM_BASE_ADDR, 2302c533a883Shx147065 sc->sc_dma_sh.cookie.dmac_address >> 10); 2303c533a883Shx147065 iwk_reg_write(sc, SCD_QUEUECHAIN_SEL, 0); 2304c533a883Shx147065 2305c533a883Shx147065 /* initiate the tx queues */ 2306c533a883Shx147065 for (i = 0; i < IWK_NUM_QUEUES; i++) { 2307c533a883Shx147065 iwk_reg_write(sc, SCD_QUEUE_RDPTR(i), 0); 2308c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, (i << 8)); 2309c533a883Shx147065 iwk_mem_write(sc, sc->sc_scd_base + 2310c533a883Shx147065 SCD_CONTEXT_QUEUE_OFFSET(i), 2311c533a883Shx147065 (SCD_WIN_SIZE & 0x7f)); 2312c533a883Shx147065 iwk_mem_write(sc, sc->sc_scd_base + 2313c533a883Shx147065 SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof (uint32_t), 2314c533a883Shx147065 (SCD_FRAME_LIMIT & 0x7f) << 16); 2315c533a883Shx147065 } 2316c533a883Shx147065 /* interrupt enable on each queue0-7 */ 2317c533a883Shx147065 iwk_reg_write(sc, SCD_INTERRUPT_MASK, 2318c533a883Shx147065 (1 << IWK_NUM_QUEUES) - 1); 2319c533a883Shx147065 /* enable each channel 0-7 */ 2320c533a883Shx147065 iwk_reg_write(sc, SCD_TXFACT, 2321c533a883Shx147065 SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); 2322c533a883Shx147065 /* 2323c533a883Shx147065 * queue 0-7 maps to FIFO 0-7 and 2324c533a883Shx147065 * all queues work under FIFO mode (none-scheduler-ack) 2325c533a883Shx147065 */ 2326c533a883Shx147065 for (i = 0; i < 7; i++) { 2327c533a883Shx147065 iwk_reg_write(sc, 2328c533a883Shx147065 SCD_QUEUE_STATUS_BITS(i), 2329c533a883Shx147065 (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| 2330c533a883Shx147065 (i << SCD_QUEUE_STTS_REG_POS_TXF)| 2331c533a883Shx147065 SCD_QUEUE_STTS_REG_MSK); 2332c533a883Shx147065 } 2333c533a883Shx147065 iwk_mac_access_exit(sc); 2334c533a883Shx147065 2335c533a883Shx147065 sc->sc_flags |= IWK_F_FW_INIT; 2336c533a883Shx147065 cv_signal(&sc->sc_fw_cv); 2337c533a883Shx147065 } 2338c533a883Shx147065 2339c533a883Shx147065 } 2340c533a883Shx147065 2341c533a883Shx147065 static uint_t 2342cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* LINTED: argument unused in function: unused */ 2343cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_rx_softintr(caddr_t arg, caddr_t unused) 2344c533a883Shx147065 { 2345c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 2346c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 2347c533a883Shx147065 iwk_rx_desc_t *desc; 2348c533a883Shx147065 iwk_rx_data_t *data; 2349c533a883Shx147065 uint32_t index; 2350c533a883Shx147065 2351c533a883Shx147065 mutex_enter(&sc->sc_glock); 2352c533a883Shx147065 if (sc->sc_rx_softint_pending != 1) { 2353c533a883Shx147065 mutex_exit(&sc->sc_glock); 2354c533a883Shx147065 return (DDI_INTR_UNCLAIMED); 2355c533a883Shx147065 } 2356c533a883Shx147065 /* disable interrupts */ 2357c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, 0); 2358c533a883Shx147065 mutex_exit(&sc->sc_glock); 2359c533a883Shx147065 2360c533a883Shx147065 /* 2361c533a883Shx147065 * firmware has moved the index of the rx queue, driver get it, 2362c533a883Shx147065 * and deal with it. 2363c533a883Shx147065 */ 2364b510adaeSfei feng - Sun Microsystems - Beijing China index = sc->sc_shared->val0 & 0xfff; 2365c533a883Shx147065 2366c533a883Shx147065 while (sc->sc_rxq.cur != index) { 2367c533a883Shx147065 data = &sc->sc_rxq.data[sc->sc_rxq.cur]; 2368c533a883Shx147065 desc = (iwk_rx_desc_t *)data->dma_data.mem_va; 2369c533a883Shx147065 2370c533a883Shx147065 IWK_DBG((IWK_DEBUG_INTR, "rx notification index = %d" 2371c533a883Shx147065 " cur = %d qid=%x idx=%d flags=%x type=%x len=%d\n", 2372c533a883Shx147065 index, sc->sc_rxq.cur, desc->hdr.qid, desc->hdr.idx, 2373c533a883Shx147065 desc->hdr.flags, desc->hdr.type, LE_32(desc->len))); 2374c533a883Shx147065 2375c533a883Shx147065 /* a command other than a tx need to be replied */ 2376c533a883Shx147065 if (!(desc->hdr.qid & 0x80) && 2377c533a883Shx147065 (desc->hdr.type != REPLY_RX_PHY_CMD) && 2378cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != REPLY_TX) && 2379cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != REPLY_TX_PWR_TABLE_CMD) && 2380cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != REPLY_PHY_CALIBRATION_CMD) && 2381cdc64593Sxinghua wen - Sun Microsystems - Beijing China (desc->hdr.type != SENSITIVITY_CMD)) 2382c533a883Shx147065 iwk_cmd_intr(sc, desc); 2383c533a883Shx147065 2384c533a883Shx147065 switch (desc->hdr.type) { 2385c533a883Shx147065 case REPLY_4965_RX: 2386c533a883Shx147065 iwk_rx_intr(sc, desc, data); 2387c533a883Shx147065 break; 2388c533a883Shx147065 2389c533a883Shx147065 case REPLY_TX: 2390c533a883Shx147065 iwk_tx_intr(sc, desc, data); 2391c533a883Shx147065 break; 2392c533a883Shx147065 2393c533a883Shx147065 case REPLY_ALIVE: 2394c533a883Shx147065 iwk_ucode_alive(sc, desc); 2395c533a883Shx147065 break; 2396c533a883Shx147065 2397c533a883Shx147065 case CARD_STATE_NOTIFICATION: 2398c533a883Shx147065 { 2399c533a883Shx147065 uint32_t *status = (uint32_t *)(desc + 1); 2400c533a883Shx147065 2401c533a883Shx147065 IWK_DBG((IWK_DEBUG_RADIO, "state changed to %x\n", 2402c533a883Shx147065 LE_32(*status))); 2403c533a883Shx147065 2404c533a883Shx147065 if (LE_32(*status) & 1) { 240543439c96Shx147065 /* 240643439c96Shx147065 * the radio button has to be pushed(OFF). It 240743439c96Shx147065 * is considered as a hw error, the 240843439c96Shx147065 * iwk_thread() tries to recover it after the 240943439c96Shx147065 * button is pushed again(ON) 241043439c96Shx147065 */ 2411c533a883Shx147065 cmn_err(CE_NOTE, 2412cdc64593Sxinghua wen - Sun Microsystems - Beijing China "iwk_rx_softintr(): " 2413cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Radio transmitter is off\n"); 241443439c96Shx147065 sc->sc_ostate = sc->sc_ic.ic_state; 241543439c96Shx147065 ieee80211_new_state(&sc->sc_ic, 241643439c96Shx147065 IEEE80211_S_INIT, -1); 241743439c96Shx147065 sc->sc_flags |= 241843439c96Shx147065 (IWK_F_HW_ERR_RECOVER | IWK_F_RADIO_OFF); 2419c533a883Shx147065 } 2420c533a883Shx147065 break; 2421c533a883Shx147065 } 2422c533a883Shx147065 case SCAN_START_NOTIFICATION: 2423c533a883Shx147065 { 2424c533a883Shx147065 iwk_start_scan_t *scan = 2425c533a883Shx147065 (iwk_start_scan_t *)(desc + 1); 2426c533a883Shx147065 2427c533a883Shx147065 IWK_DBG((IWK_DEBUG_SCAN, 2428c533a883Shx147065 "scanning channel %d status %x\n", 2429c533a883Shx147065 scan->chan, LE_32(scan->status))); 2430c533a883Shx147065 2431c533a883Shx147065 ic->ic_curchan = &ic->ic_sup_channels[scan->chan]; 2432c533a883Shx147065 break; 2433c533a883Shx147065 } 2434c533a883Shx147065 case SCAN_COMPLETE_NOTIFICATION: 2435cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 2436c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_stop_scan_t *scan = 2437c50ced99Spengcheng chen - Sun Microsystems - Beijing China (iwk_stop_scan_t *)(desc + 1); 2438c50ced99Spengcheng chen - Sun Microsystems - Beijing China 2439c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN, 2440c50ced99Spengcheng chen - Sun Microsystems - Beijing China "completed channel %d (burst of %d) status %02x\n", 2441c50ced99Spengcheng chen - Sun Microsystems - Beijing China scan->chan, scan->nchan, scan->status)); 2442c50ced99Spengcheng chen - Sun Microsystems - Beijing China 2443c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending++; 2444c50ced99Spengcheng chen - Sun Microsystems - Beijing China break; 2445c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 2446c50ced99Spengcheng chen - Sun Microsystems - Beijing China case STATISTICS_NOTIFICATION: 2447cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* handle statistics notification */ 2448cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_statistics_notify(sc, desc); 2449cdc64593Sxinghua wen - Sun Microsystems - Beijing China break; 2450cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 2451cdc64593Sxinghua wen - Sun Microsystems - Beijing China 2452c533a883Shx147065 sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % RX_QUEUE_SIZE; 2453c533a883Shx147065 } 2454c533a883Shx147065 2455c533a883Shx147065 /* 2456c533a883Shx147065 * driver dealt with what reveived in rx queue and tell the information 2457c533a883Shx147065 * to the firmware. 2458c533a883Shx147065 */ 2459c533a883Shx147065 index = (index == 0) ? RX_QUEUE_SIZE - 1 : index - 1; 2460c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, index & (~7)); 2461c533a883Shx147065 2462c533a883Shx147065 mutex_enter(&sc->sc_glock); 2463c533a883Shx147065 /* re-enable interrupts */ 2464c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 2465c533a883Shx147065 sc->sc_rx_softint_pending = 0; 2466c533a883Shx147065 mutex_exit(&sc->sc_glock); 2467c533a883Shx147065 2468c533a883Shx147065 return (DDI_INTR_CLAIMED); 2469c533a883Shx147065 } 2470c533a883Shx147065 2471c533a883Shx147065 static uint_t 2472cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* LINTED: argument unused in function: unused */ 2473cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_intr(caddr_t arg, caddr_t unused) 2474c533a883Shx147065 { 2475c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 2476c533a883Shx147065 uint32_t r, rfh; 2477c533a883Shx147065 2478c533a883Shx147065 mutex_enter(&sc->sc_glock); 2479d62cb7ffShx147065 2480d62cb7ffShx147065 if (sc->sc_flags & IWK_F_SUSPEND) { 2481d62cb7ffShx147065 mutex_exit(&sc->sc_glock); 2482d62cb7ffShx147065 return (DDI_INTR_UNCLAIMED); 2483d62cb7ffShx147065 } 2484d62cb7ffShx147065 2485c533a883Shx147065 r = IWK_READ(sc, CSR_INT); 2486c533a883Shx147065 if (r == 0 || r == 0xffffffff) { 2487c533a883Shx147065 mutex_exit(&sc->sc_glock); 2488c533a883Shx147065 return (DDI_INTR_UNCLAIMED); 2489c533a883Shx147065 } 2490c533a883Shx147065 2491c533a883Shx147065 IWK_DBG((IWK_DEBUG_INTR, "interrupt reg %x\n", r)); 2492c533a883Shx147065 2493c533a883Shx147065 rfh = IWK_READ(sc, CSR_FH_INT_STATUS); 2494c533a883Shx147065 IWK_DBG((IWK_DEBUG_INTR, "FH interrupt reg %x\n", rfh)); 2495c533a883Shx147065 /* disable interrupts */ 2496c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, 0); 2497c533a883Shx147065 /* ack interrupts */ 2498c533a883Shx147065 IWK_WRITE(sc, CSR_INT, r); 2499c533a883Shx147065 IWK_WRITE(sc, CSR_FH_INT_STATUS, rfh); 2500c533a883Shx147065 2501cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_soft_hdl == NULL) { 2502c533a883Shx147065 mutex_exit(&sc->sc_glock); 2503c533a883Shx147065 return (DDI_INTR_CLAIMED); 2504c533a883Shx147065 } 2505c533a883Shx147065 if (r & (BIT_INT_SWERROR | BIT_INT_ERR)) { 2506c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "fatal firmware error\n"); 2507c533a883Shx147065 mutex_exit(&sc->sc_glock); 2508cdc64593Sxinghua wen - Sun Microsystems - Beijing China #ifdef DEBUG 2509cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* dump event and error logs to dmesg */ 2510cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_write_error_log(sc); 2511cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_write_event_log(sc); 2512cdc64593Sxinghua wen - Sun Microsystems - Beijing China #endif /* DEBUG */ 2513c533a883Shx147065 iwk_stop(sc); 2514c533a883Shx147065 sc->sc_ostate = sc->sc_ic.ic_state; 25156f12def4Spengcheng chen - Sun Microsystems - Beijing China 25166f12def4Spengcheng chen - Sun Microsystems - Beijing China /* not capable of fast recovery */ 25176f12def4Spengcheng chen - Sun Microsystems - Beijing China if (!IWK_CHK_FAST_RECOVER(sc)) 2518c533a883Shx147065 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 25196f12def4Spengcheng chen - Sun Microsystems - Beijing China 2520c533a883Shx147065 sc->sc_flags |= IWK_F_HW_ERR_RECOVER; 2521c533a883Shx147065 return (DDI_INTR_CLAIMED); 2522c533a883Shx147065 } 2523c533a883Shx147065 2524c533a883Shx147065 if (r & BIT_INT_RF_KILL) { 2525b510adaeSfei feng - Sun Microsystems - Beijing China uint32_t tmp = IWK_READ(sc, CSR_GP_CNTRL); 2526b510adaeSfei feng - Sun Microsystems - Beijing China if (tmp & (1 << 27)) 2527b510adaeSfei feng - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "RF switch: radio on\n"); 2528c533a883Shx147065 } 2529c533a883Shx147065 2530c533a883Shx147065 if ((r & (BIT_INT_FH_RX | BIT_INT_SW_RX)) || 2531c533a883Shx147065 (rfh & FH_INT_RX_MASK)) { 2532c533a883Shx147065 sc->sc_rx_softint_pending = 1; 2533cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) ddi_intr_trigger_softint(sc->sc_soft_hdl, NULL); 2534c533a883Shx147065 } 2535c533a883Shx147065 2536c533a883Shx147065 if (r & BIT_INT_ALIVE) { 2537c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, "firmware initialized.\n")); 2538c533a883Shx147065 } 2539c533a883Shx147065 2540c533a883Shx147065 /* re-enable interrupts */ 2541c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 2542c533a883Shx147065 mutex_exit(&sc->sc_glock); 2543c533a883Shx147065 2544c533a883Shx147065 return (DDI_INTR_CLAIMED); 2545c533a883Shx147065 } 2546c533a883Shx147065 2547c533a883Shx147065 static uint8_t 2548c533a883Shx147065 iwk_rate_to_plcp(int rate) 2549c533a883Shx147065 { 2550c533a883Shx147065 uint8_t ret; 2551c533a883Shx147065 2552c533a883Shx147065 switch (rate) { 2553c533a883Shx147065 /* CCK rates */ 2554c533a883Shx147065 case 2: 2555c533a883Shx147065 ret = 0xa; 2556c533a883Shx147065 break; 2557c533a883Shx147065 case 4: 2558c533a883Shx147065 ret = 0x14; 2559c533a883Shx147065 break; 2560c533a883Shx147065 case 11: 2561c533a883Shx147065 ret = 0x37; 2562c533a883Shx147065 break; 2563c533a883Shx147065 case 22: 2564c533a883Shx147065 ret = 0x6e; 2565c533a883Shx147065 break; 2566c533a883Shx147065 /* OFDM rates */ 2567c533a883Shx147065 case 12: 2568c533a883Shx147065 ret = 0xd; 2569c533a883Shx147065 break; 2570c533a883Shx147065 case 18: 2571c533a883Shx147065 ret = 0xf; 2572c533a883Shx147065 break; 2573c533a883Shx147065 case 24: 2574c533a883Shx147065 ret = 0x5; 2575c533a883Shx147065 break; 2576c533a883Shx147065 case 36: 2577c533a883Shx147065 ret = 0x7; 2578c533a883Shx147065 break; 2579c533a883Shx147065 case 48: 2580c533a883Shx147065 ret = 0x9; 2581c533a883Shx147065 break; 2582c533a883Shx147065 case 72: 2583c533a883Shx147065 ret = 0xb; 2584c533a883Shx147065 break; 2585c533a883Shx147065 case 96: 2586c533a883Shx147065 ret = 0x1; 2587c533a883Shx147065 break; 2588c533a883Shx147065 case 108: 2589c533a883Shx147065 ret = 0x3; 2590c533a883Shx147065 break; 2591c533a883Shx147065 default: 2592c533a883Shx147065 ret = 0; 2593c533a883Shx147065 break; 2594c533a883Shx147065 } 2595c533a883Shx147065 return (ret); 2596c533a883Shx147065 } 2597c533a883Shx147065 2598c533a883Shx147065 static mblk_t * 2599c533a883Shx147065 iwk_m_tx(void *arg, mblk_t *mp) 2600c533a883Shx147065 { 2601c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 2602c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 2603c533a883Shx147065 mblk_t *next; 2604c533a883Shx147065 2605d62cb7ffShx147065 if (sc->sc_flags & IWK_F_SUSPEND) { 2606d62cb7ffShx147065 freemsgchain(mp); 2607d62cb7ffShx147065 return (NULL); 2608d62cb7ffShx147065 } 2609d62cb7ffShx147065 2610c533a883Shx147065 if (ic->ic_state != IEEE80211_S_RUN) { 2611c533a883Shx147065 freemsgchain(mp); 2612c533a883Shx147065 return (NULL); 2613c533a883Shx147065 } 2614c533a883Shx147065 26156f12def4Spengcheng chen - Sun Microsystems - Beijing China if ((sc->sc_flags & IWK_F_HW_ERR_RECOVER) && 26166f12def4Spengcheng chen - Sun Microsystems - Beijing China IWK_CHK_FAST_RECOVER(sc)) { 26176f12def4Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_FW, "iwk_m_tx(): hold queue\n")); 26186f12def4Spengcheng chen - Sun Microsystems - Beijing China return (mp); 26196f12def4Spengcheng chen - Sun Microsystems - Beijing China } 26206f12def4Spengcheng chen - Sun Microsystems - Beijing China 2621c533a883Shx147065 while (mp != NULL) { 2622c533a883Shx147065 next = mp->b_next; 2623c533a883Shx147065 mp->b_next = NULL; 2624c533a883Shx147065 if (iwk_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) { 2625c533a883Shx147065 mp->b_next = next; 2626c533a883Shx147065 break; 2627c533a883Shx147065 } 2628c533a883Shx147065 mp = next; 2629c533a883Shx147065 } 2630c533a883Shx147065 return (mp); 2631c533a883Shx147065 } 2632c533a883Shx147065 2633c533a883Shx147065 /* ARGSUSED */ 2634c533a883Shx147065 static int 2635c533a883Shx147065 iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 2636c533a883Shx147065 { 2637c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)ic; 2638c533a883Shx147065 iwk_tx_ring_t *ring; 2639c533a883Shx147065 iwk_tx_desc_t *desc; 2640c533a883Shx147065 iwk_tx_data_t *data; 2641c533a883Shx147065 iwk_cmd_t *cmd; 2642c533a883Shx147065 iwk_tx_cmd_t *tx; 2643c533a883Shx147065 ieee80211_node_t *in; 2644c533a883Shx147065 struct ieee80211_frame *wh; 2645c533a883Shx147065 struct ieee80211_key *k = NULL; 2646c533a883Shx147065 mblk_t *m, *m0; 2647c533a883Shx147065 int rate, hdrlen, len, len0, mblen, off, err = IWK_SUCCESS; 2648c533a883Shx147065 uint16_t masks = 0; 264919d332feSfei feng - Sun Microsystems - Beijing China uint8_t index, index1, index2; 2650c533a883Shx147065 2651c533a883Shx147065 ring = &sc->sc_txq[0]; 2652c533a883Shx147065 data = &ring->data[ring->cur]; 2653c533a883Shx147065 desc = data->desc; 2654c533a883Shx147065 cmd = data->cmd; 2655c533a883Shx147065 bzero(desc, sizeof (*desc)); 2656c533a883Shx147065 bzero(cmd, sizeof (*cmd)); 2657c533a883Shx147065 2658c533a883Shx147065 mutex_enter(&sc->sc_tx_lock); 2659d62cb7ffShx147065 if (sc->sc_flags & IWK_F_SUSPEND) { 2660d62cb7ffShx147065 mutex_exit(&sc->sc_tx_lock); 2661d62cb7ffShx147065 if ((type & IEEE80211_FC0_TYPE_MASK) != 2662d62cb7ffShx147065 IEEE80211_FC0_TYPE_DATA) { 2663d62cb7ffShx147065 freemsg(mp); 2664d62cb7ffShx147065 } 2665d62cb7ffShx147065 err = IWK_FAIL; 2666d62cb7ffShx147065 goto exit; 2667d62cb7ffShx147065 } 2668d62cb7ffShx147065 2669c533a883Shx147065 if (ring->queued > ring->count - 64) { 2670c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "iwk_send(): no txbuf\n")); 2671c533a883Shx147065 sc->sc_need_reschedule = 1; 2672c533a883Shx147065 mutex_exit(&sc->sc_tx_lock); 2673c533a883Shx147065 if ((type & IEEE80211_FC0_TYPE_MASK) != 2674c533a883Shx147065 IEEE80211_FC0_TYPE_DATA) { 2675c533a883Shx147065 freemsg(mp); 2676c533a883Shx147065 } 2677c533a883Shx147065 sc->sc_tx_nobuf++; 2678c533a883Shx147065 err = IWK_FAIL; 2679c533a883Shx147065 goto exit; 2680c533a883Shx147065 } 2681c533a883Shx147065 mutex_exit(&sc->sc_tx_lock); 2682c533a883Shx147065 2683c533a883Shx147065 hdrlen = sizeof (struct ieee80211_frame); 2684c533a883Shx147065 2685c533a883Shx147065 m = allocb(msgdsize(mp) + 32, BPRI_MED); 2686c533a883Shx147065 if (m == NULL) { /* can not alloc buf, drop this package */ 2687c533a883Shx147065 cmn_err(CE_WARN, 2688c533a883Shx147065 "iwk_send(): failed to allocate msgbuf\n"); 2689c533a883Shx147065 freemsg(mp); 2690c533a883Shx147065 err = IWK_SUCCESS; 2691c533a883Shx147065 goto exit; 2692c533a883Shx147065 } 2693c533a883Shx147065 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 2694c533a883Shx147065 mblen = MBLKL(m0); 2695c533a883Shx147065 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen); 2696c533a883Shx147065 off += mblen; 2697c533a883Shx147065 } 2698c533a883Shx147065 m->b_wptr += off; 2699c533a883Shx147065 freemsg(mp); 2700c533a883Shx147065 2701c533a883Shx147065 wh = (struct ieee80211_frame *)m->b_rptr; 2702c533a883Shx147065 270319d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS && 270419d332feSfei feng - Sun Microsystems - Beijing China (!(IEEE80211_IS_MULTICAST(wh->i_addr1)))) { 270519d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 270619d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock); 270719d332feSfei feng - Sun Microsystems - Beijing China 270819d332feSfei feng - Sun Microsystems - Beijing China /* 270919d332feSfei feng - Sun Microsystems - Beijing China * search for node in ibss node table 271019d332feSfei feng - Sun Microsystems - Beijing China */ 271119d332feSfei feng - Sun Microsystems - Beijing China for (index1 = IWK_STA_ID; 271219d332feSfei feng - Sun Microsystems - Beijing China index1 < IWK_STATION_COUNT; index1++) { 271319d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_node_tb[index1].used && 271419d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_EQ(sc->sc_ibss. 271519d332feSfei feng - Sun Microsystems - Beijing China ibss_node_tb[index1].node.bssid, 271619d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr1)) { 271719d332feSfei feng - Sun Microsystems - Beijing China break; 271819d332feSfei feng - Sun Microsystems - Beijing China } 271919d332feSfei feng - Sun Microsystems - Beijing China } 272019d332feSfei feng - Sun Microsystems - Beijing China 272119d332feSfei feng - Sun Microsystems - Beijing China /* 272219d332feSfei feng - Sun Microsystems - Beijing China * if don't find in ibss node table 272319d332feSfei feng - Sun Microsystems - Beijing China */ 272419d332feSfei feng - Sun Microsystems - Beijing China if (index1 >= IWK_BROADCAST_ID) { 272519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_clean_add_node_ibss(ic, 272619d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr1, &index2); 272719d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 272819d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_send(): " 272919d332feSfei feng - Sun Microsystems - Beijing China "failed to clean all nodes " 273019d332feSfei feng - Sun Microsystems - Beijing China "and add one node\n"); 273119d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock); 273219d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 273319d332feSfei feng - Sun Microsystems - Beijing China freemsg(m); 273419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_tx_err++; 273519d332feSfei feng - Sun Microsystems - Beijing China err = IWK_SUCCESS; 273619d332feSfei feng - Sun Microsystems - Beijing China goto exit; 273719d332feSfei feng - Sun Microsystems - Beijing China } 273819d332feSfei feng - Sun Microsystems - Beijing China index = index2; 273919d332feSfei feng - Sun Microsystems - Beijing China } else { 274019d332feSfei feng - Sun Microsystems - Beijing China index = index1; 274119d332feSfei feng - Sun Microsystems - Beijing China } 274219d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock); 274319d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 274419d332feSfei feng - Sun Microsystems - Beijing China } 274519d332feSfei feng - Sun Microsystems - Beijing China 2746c533a883Shx147065 in = ieee80211_find_txnode(ic, wh->i_addr1); 2747c533a883Shx147065 if (in == NULL) { 2748c533a883Shx147065 cmn_err(CE_WARN, "iwk_send(): failed to find tx node\n"); 2749c533a883Shx147065 freemsg(m); 2750c533a883Shx147065 sc->sc_tx_err++; 2751c533a883Shx147065 err = IWK_SUCCESS; 2752c533a883Shx147065 goto exit; 2753c533a883Shx147065 } 2754c533a883Shx147065 (void) ieee80211_encap(ic, m, in); 2755c533a883Shx147065 2756c533a883Shx147065 cmd->hdr.type = REPLY_TX; 2757c533a883Shx147065 cmd->hdr.flags = 0; 2758c533a883Shx147065 cmd->hdr.qid = ring->qid; 2759c533a883Shx147065 cmd->hdr.idx = ring->cur; 2760c533a883Shx147065 2761c533a883Shx147065 tx = (iwk_tx_cmd_t *)cmd->data; 2762c533a883Shx147065 tx->tx_flags = 0; 2763c533a883Shx147065 2764c533a883Shx147065 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2765c533a883Shx147065 tx->tx_flags &= ~(LE_32(TX_CMD_FLG_ACK_MSK)); 2766c533a883Shx147065 } else { 2767c533a883Shx147065 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK); 2768c533a883Shx147065 } 2769c533a883Shx147065 2770c533a883Shx147065 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2771c533a883Shx147065 k = ieee80211_crypto_encap(ic, m); 2772c533a883Shx147065 if (k == NULL) { 2773c533a883Shx147065 freemsg(m); 2774c533a883Shx147065 sc->sc_tx_err++; 2775c533a883Shx147065 err = IWK_SUCCESS; 2776c533a883Shx147065 goto exit; 2777c533a883Shx147065 } 2778c533a883Shx147065 2779c533a883Shx147065 if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) { 2780c533a883Shx147065 tx->sec_ctl = 2; /* for CCMP */ 2781c533a883Shx147065 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK); 2782c533a883Shx147065 (void) memcpy(&tx->key, k->wk_key, k->wk_keylen); 2783c533a883Shx147065 } 2784c533a883Shx147065 2785c533a883Shx147065 /* packet header may have moved, reset our local pointer */ 2786c533a883Shx147065 wh = (struct ieee80211_frame *)m->b_rptr; 2787c533a883Shx147065 } 2788c533a883Shx147065 2789c533a883Shx147065 len = msgdsize(m); 2790c533a883Shx147065 2791c533a883Shx147065 #ifdef DEBUG 2792c533a883Shx147065 if (iwk_dbg_flags & IWK_DEBUG_TX) 2793c533a883Shx147065 ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0); 2794c533a883Shx147065 #endif 2795c533a883Shx147065 2796c533a883Shx147065 /* pickup a rate */ 2797c533a883Shx147065 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2798c533a883Shx147065 IEEE80211_FC0_TYPE_MGT) { 2799c533a883Shx147065 /* mgmt frames are sent at 1M */ 2800c533a883Shx147065 rate = in->in_rates.ir_rates[0]; 2801c533a883Shx147065 } else { 2802c533a883Shx147065 /* 280343439c96Shx147065 * do it here for the software way rate control. 280443439c96Shx147065 * later for rate scaling in hardware. 2805c533a883Shx147065 * maybe like the following, for management frame: 2806c533a883Shx147065 * tx->initial_rate_index = LINK_QUAL_MAX_RETRY_NUM - 1; 2807c533a883Shx147065 * for data frame: 2808c533a883Shx147065 * tx->tx_flags |= (LE_32(TX_CMD_FLG_STA_RATE_MSK)); 2809c533a883Shx147065 * rate = in->in_rates.ir_rates[in->in_txrate]; 2810c533a883Shx147065 * tx->initial_rate_index = 1; 2811c533a883Shx147065 * 2812c533a883Shx147065 * now the txrate is determined in tx cmd flags, set to the 2813c533a883Shx147065 * max value 54M for 11g and 11M for 11b. 2814c533a883Shx147065 */ 2815c533a883Shx147065 2816c533a883Shx147065 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 2817c533a883Shx147065 rate = ic->ic_fixed_rate; 2818c533a883Shx147065 } else { 2819c533a883Shx147065 rate = in->in_rates.ir_rates[in->in_txrate]; 2820c533a883Shx147065 } 2821c533a883Shx147065 } 2822c533a883Shx147065 rate &= IEEE80211_RATE_VAL; 2823c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx rate[%d of %d] = %x", 2824c533a883Shx147065 in->in_txrate, in->in_rates.ir_nrates, rate)); 2825c533a883Shx147065 2826c533a883Shx147065 tx->tx_flags |= (LE_32(TX_CMD_FLG_SEQ_CTL_MSK)); 2827c533a883Shx147065 2828c533a883Shx147065 len0 = roundup(4 + sizeof (iwk_tx_cmd_t) + hdrlen, 4); 2829c533a883Shx147065 if (len0 != (4 + sizeof (iwk_tx_cmd_t) + hdrlen)) 2830b510adaeSfei feng - Sun Microsystems - Beijing China tx->tx_flags |= LE_32(TX_CMD_FLG_MH_PAD_MSK); 2831c533a883Shx147065 2832c533a883Shx147065 /* retrieve destination node's id */ 2833c533a883Shx147065 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2834c533a883Shx147065 tx->sta_id = IWK_BROADCAST_ID; 2835c533a883Shx147065 } else { 283619d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS) 283719d332feSfei feng - Sun Microsystems - Beijing China tx->sta_id = index; 283819d332feSfei feng - Sun Microsystems - Beijing China else 2839c533a883Shx147065 tx->sta_id = IWK_AP_ID; 2840c533a883Shx147065 } 2841c533a883Shx147065 2842c533a883Shx147065 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2843c533a883Shx147065 IEEE80211_FC0_TYPE_MGT) { 2844c533a883Shx147065 /* tell h/w to set timestamp in probe responses */ 2845c533a883Shx147065 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 2846c533a883Shx147065 IEEE80211_FC0_SUBTYPE_PROBE_RESP) 2847c533a883Shx147065 tx->tx_flags |= LE_32(TX_CMD_FLG_TSF_MSK); 2848c533a883Shx147065 2849c533a883Shx147065 if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 2850c533a883Shx147065 IEEE80211_FC0_SUBTYPE_ASSOC_REQ) || 2851c533a883Shx147065 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 2852c533a883Shx147065 IEEE80211_FC0_SUBTYPE_REASSOC_REQ)) 2853b510adaeSfei feng - Sun Microsystems - Beijing China tx->timeout.pm_frame_timeout = LE_16(3); 2854c533a883Shx147065 else 2855b510adaeSfei feng - Sun Microsystems - Beijing China tx->timeout.pm_frame_timeout = LE_16(2); 2856c533a883Shx147065 } else 2857c533a883Shx147065 tx->timeout.pm_frame_timeout = 0; 2858c533a883Shx147065 if (rate == 2 || rate == 4 || rate == 11 || rate == 22) 2859c533a883Shx147065 masks |= RATE_MCS_CCK_MSK; 2860c533a883Shx147065 2861c533a883Shx147065 masks |= RATE_MCS_ANT_B_MSK; 2862b510adaeSfei feng - Sun Microsystems - Beijing China tx->rate.r.rate_n_flags = LE_32(iwk_rate_to_plcp(rate) | masks); 2863c533a883Shx147065 2864c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "tx flag = %x", 2865b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(tx->tx_flags))); 2866c533a883Shx147065 2867c533a883Shx147065 tx->rts_retry_limit = 60; 2868c533a883Shx147065 tx->data_retry_limit = 15; 2869c533a883Shx147065 2870c533a883Shx147065 tx->stop_time.life_time = LE_32(0xffffffff); 2871c533a883Shx147065 2872c533a883Shx147065 tx->len = LE_16(len); 2873c533a883Shx147065 2874c533a883Shx147065 tx->dram_lsb_ptr = 2875b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(data->paddr_cmd + 4 + offsetof(iwk_tx_cmd_t, scratch)); 2876c533a883Shx147065 tx->dram_msb_ptr = 0; 2877c533a883Shx147065 tx->driver_txop = 0; 2878c533a883Shx147065 tx->next_frame_len = 0; 2879c533a883Shx147065 2880c533a883Shx147065 (void) memcpy(tx + 1, m->b_rptr, hdrlen); 2881c533a883Shx147065 m->b_rptr += hdrlen; 2882c533a883Shx147065 (void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen); 2883c533a883Shx147065 2884c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "sending data: qid=%d idx=%d len=%d", 2885c533a883Shx147065 ring->qid, ring->cur, len)); 2886c533a883Shx147065 2887c533a883Shx147065 /* 2888c533a883Shx147065 * first segment includes the tx cmd plus the 802.11 header, 2889c533a883Shx147065 * the second includes the remaining of the 802.11 frame. 2890c533a883Shx147065 */ 2891b510adaeSfei feng - Sun Microsystems - Beijing China desc->val0 = 2 << 24; 2892b510adaeSfei feng - Sun Microsystems - Beijing China desc->pa[0].tb1_addr = data->paddr_cmd; 2893c533a883Shx147065 desc->pa[0].val1 = ((len0 << 4) & 0xfff0) | 2894c533a883Shx147065 ((data->dma_data.cookie.dmac_address & 0xffff) << 16); 2895c533a883Shx147065 desc->pa[0].val2 = 2896c533a883Shx147065 ((data->dma_data.cookie.dmac_address & 0xffff0000) >> 16) | 2897c533a883Shx147065 ((len - hdrlen) << 20); 2898c533a883Shx147065 IWK_DBG((IWK_DEBUG_TX, "phy addr1 = 0x%x phy addr2 = 0x%x " 2899c533a883Shx147065 "len1 = 0x%x, len2 = 0x%x val1 = 0x%x val2 = 0x%x", 2900c533a883Shx147065 data->paddr_cmd, data->dma_data.cookie.dmac_address, 2901b510adaeSfei feng - Sun Microsystems - Beijing China len0, len - hdrlen, LE_32(desc->pa[0].val1), 2902b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(desc->pa[0].val2))); 2903c533a883Shx147065 2904c533a883Shx147065 mutex_enter(&sc->sc_tx_lock); 2905c533a883Shx147065 ring->queued++; 2906c533a883Shx147065 mutex_exit(&sc->sc_tx_lock); 2907c533a883Shx147065 2908c533a883Shx147065 /* kick ring */ 2909cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 2910cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[ring->cur].val = 8 + len; 2911c533a883Shx147065 if (ring->cur < IWK_MAX_WIN_SIZE) { 2912c533a883Shx147065 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 2913c533a883Shx147065 tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8 + len; 2914c533a883Shx147065 } 2915c533a883Shx147065 2916c533a883Shx147065 IWK_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV); 2917c533a883Shx147065 IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 2918c533a883Shx147065 2919c533a883Shx147065 ring->cur = (ring->cur + 1) % ring->count; 2920c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 2921c533a883Shx147065 freemsg(m); 2922c533a883Shx147065 /* release node reference */ 2923c533a883Shx147065 ieee80211_free_node(in); 2924c533a883Shx147065 2925c533a883Shx147065 ic->ic_stats.is_tx_bytes += len; 2926c533a883Shx147065 ic->ic_stats.is_tx_frags++; 2927c533a883Shx147065 2928c533a883Shx147065 if (sc->sc_tx_timer == 0) 29296f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_tx_timer = 4; 29306f12def4Spengcheng chen - Sun Microsystems - Beijing China 2931c533a883Shx147065 exit: 2932c533a883Shx147065 return (err); 2933c533a883Shx147065 } 2934c533a883Shx147065 2935c533a883Shx147065 static void 2936c533a883Shx147065 iwk_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 2937c533a883Shx147065 { 2938c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 2939c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 294019d332feSfei feng - Sun Microsystems - Beijing China 294119d332feSfei feng - Sun Microsystems - Beijing China enum ieee80211_opmode oldmod; 294219d332feSfei feng - Sun Microsystems - Beijing China iwk_tx_power_table_cmd_t txpower; 294319d332feSfei feng - Sun Microsystems - Beijing China iwk_add_sta_t node; 294419d332feSfei feng - Sun Microsystems - Beijing China iwk_link_quality_cmd_t link_quality; 294519d332feSfei feng - Sun Microsystems - Beijing China uint16_t masks = 0; 294619d332feSfei feng - Sun Microsystems - Beijing China int i, err, err1; 294719d332feSfei feng - Sun Microsystems - Beijing China 294819d332feSfei feng - Sun Microsystems - Beijing China oldmod = ic->ic_opmode; 2949c533a883Shx147065 2950c533a883Shx147065 err = ieee80211_ioctl(ic, wq, mp); 2951cdc64593Sxinghua wen - Sun Microsystems - Beijing China 295219d332feSfei feng - Sun Microsystems - Beijing China /* 295319d332feSfei feng - Sun Microsystems - Beijing China * return to STA mode 295419d332feSfei feng - Sun Microsystems - Beijing China */ 295519d332feSfei feng - Sun Microsystems - Beijing China if ((0 == err || ENETRESET == err) && (oldmod != ic->ic_opmode) && 295619d332feSfei feng - Sun Microsystems - Beijing China (ic->ic_opmode == IEEE80211_M_STA)) { 295719d332feSfei feng - Sun Microsystems - Beijing China /* configure rxon */ 295819d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&sc->sc_config, 0, sizeof (iwk_rxon_cmd_t)); 295919d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr); 296019d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr); 2961b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan = 2962b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan)); 2963b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags = LE_32(RXON_FLG_TSF2HOST_MSK | 296419d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_AUTO_DETECT_MSK | 296519d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_BAND_24G_MSK); 2966b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &= LE_32(~RXON_FLG_CCK_MSK); 296719d332feSfei feng - Sun Microsystems - Beijing China switch (ic->ic_opmode) { 296819d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_STA: 296919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_ESS; 297019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |= 297119d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 297219d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK | 297319d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK); 297419d332feSfei feng - Sun Microsystems - Beijing China break; 297519d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_IBSS: 297619d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_AHDEMO: 297719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS; 2978b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= 2979b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 298019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags = 298119d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 298219d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK | 298319d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK); 298419d332feSfei feng - Sun Microsystems - Beijing China break; 298519d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_HOSTAP: 298619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_AP; 298719d332feSfei feng - Sun Microsystems - Beijing China break; 298819d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_MONITOR: 298919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER; 299019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |= 299119d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 299219d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_CTL2HOST_MSK | 299319d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_PROMISC_MSK); 299419d332feSfei feng - Sun Microsystems - Beijing China break; 299519d332feSfei feng - Sun Microsystems - Beijing China } 299619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0x0f; 299719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0xff; 299819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff; 299919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff; 300019d332feSfei feng - Sun Microsystems - Beijing China /* set antenna */ 300119d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 3002b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK | 3003b510adaeSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_VALID_POS) | 300419d332feSfei feng - Sun Microsystems - Beijing China (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) | 300519d332feSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 300619d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_RXON, &sc->sc_config, 300719d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1); 300819d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) { 300919d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): " 301019d332feSfei feng - Sun Microsystems - Beijing China "failed to set configure command" 301119d332feSfei feng - Sun Microsystems - Beijing China " please run (ifconfig unplumb and" 301219d332feSfei feng - Sun Microsystems - Beijing China " ifconfig plumb)\n"); 301319d332feSfei feng - Sun Microsystems - Beijing China } 301419d332feSfei feng - Sun Microsystems - Beijing China /* 301519d332feSfei feng - Sun Microsystems - Beijing China * set Tx power for 2.4GHz channels 301619d332feSfei feng - Sun Microsystems - Beijing China * (need further investigation. fix tx power at present) 301719d332feSfei feng - Sun Microsystems - Beijing China */ 301819d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&txpower, 0, sizeof (txpower)); 301919d332feSfei feng - Sun Microsystems - Beijing China txpower.band = 1; /* for 2.4G */ 302019d332feSfei feng - Sun Microsystems - Beijing China txpower.channel = sc->sc_config.chan; 302119d332feSfei feng - Sun Microsystems - Beijing China txpower.channel_normal_width = 0; 302219d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < POWER_TABLE_NUM_HT_OFDM_ENTRIES; i++) { 302319d332feSfei feng - Sun Microsystems - Beijing China txpower.tx_power.ht_ofdm_power[i]. 3024b510adaeSfei feng - Sun Microsystems - Beijing China s.ramon_tx_gain = LE_16(0x3f3f); 302519d332feSfei feng - Sun Microsystems - Beijing China txpower.tx_power.ht_ofdm_power[i]. 3026b510adaeSfei feng - Sun Microsystems - Beijing China s.dsp_predis_atten = LE_16(110 | (110 << 8)); 302719d332feSfei feng - Sun Microsystems - Beijing China } 3028b510adaeSfei feng - Sun Microsystems - Beijing China txpower.tx_power.legacy_cck_power.s. 3029b510adaeSfei feng - Sun Microsystems - Beijing China ramon_tx_gain = LE_16(0x3f3f); 3030b510adaeSfei feng - Sun Microsystems - Beijing China txpower.tx_power.legacy_cck_power.s. 3031b510adaeSfei feng - Sun Microsystems - Beijing China dsp_predis_atten = LE_16(110 | (110 << 8)); 303219d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &txpower, 303319d332feSfei feng - Sun Microsystems - Beijing China sizeof (txpower), 1); 303419d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) { 303519d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): failed to set txpower" 303619d332feSfei feng - Sun Microsystems - Beijing China " please run (ifconfig unplumb " 303719d332feSfei feng - Sun Microsystems - Beijing China "and ifconfig plumb)\n"); 303819d332feSfei feng - Sun Microsystems - Beijing China } 303919d332feSfei feng - Sun Microsystems - Beijing China /* add broadcast node so that we can send broadcast frame */ 304019d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&node, 0, sizeof (node)); 304119d332feSfei feng - Sun Microsystems - Beijing China (void) memset(node.bssid, 0xff, 6); 304219d332feSfei feng - Sun Microsystems - Beijing China node.id = IWK_BROADCAST_ID; 304319d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1); 304419d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) { 304519d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): " 304619d332feSfei feng - Sun Microsystems - Beijing China "failed to add broadcast node\n"); 304719d332feSfei feng - Sun Microsystems - Beijing China } 304819d332feSfei feng - Sun Microsystems - Beijing China 304919d332feSfei feng - Sun Microsystems - Beijing China /* TX_LINK_QUALITY cmd */ 305019d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&link_quality, 0, sizeof (link_quality)); 305119d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 305219d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_CCK_MSK; 305319d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_ANT_B_MSK; 305419d332feSfei feng - Sun Microsystems - Beijing China masks &= ~RATE_MCS_ANT_A_MSK; 305519d332feSfei feng - Sun Microsystems - Beijing China link_quality.rate_n_flags[i] = 3056b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(2) | masks); 305719d332feSfei feng - Sun Microsystems - Beijing China } 305819d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.single_stream_ant_msk = 2; 305919d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.dual_stream_ant_msk = 3; 306019d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_dis_start_th = 3; 306119d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_time_limit = LE_16(4000); 306219d332feSfei feng - Sun Microsystems - Beijing China link_quality.sta_id = IWK_BROADCAST_ID; 306319d332feSfei feng - Sun Microsystems - Beijing China err1 = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality, 306419d332feSfei feng - Sun Microsystems - Beijing China sizeof (link_quality), 1); 306519d332feSfei feng - Sun Microsystems - Beijing China if (err1 != IWK_SUCCESS) { 306619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_m_ioctl(): " 306719d332feSfei feng - Sun Microsystems - Beijing China "failed to config link quality table\n"); 306819d332feSfei feng - Sun Microsystems - Beijing China } 306919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 307019d332feSfei feng - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 307119d332feSfei feng - Sun Microsystems - Beijing China } 307219d332feSfei feng - Sun Microsystems - Beijing China 3073c533a883Shx147065 if (err == ENETRESET) { 307443439c96Shx147065 /* 307543439c96Shx147065 * This is special for the hidden AP connection. 307643439c96Shx147065 * In any case, we should make sure only one 'scan' 307743439c96Shx147065 * in the driver for a 'connect' CLI command. So 307843439c96Shx147065 * when connecting to a hidden AP, the scan is just 307943439c96Shx147065 * sent out to the air when we know the desired 308043439c96Shx147065 * essid of the AP we want to connect. 308143439c96Shx147065 */ 308243439c96Shx147065 if (ic->ic_des_esslen) { 3083c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING) { 3084c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_m_stop(sc); 3085c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) iwk_m_start(sc); 3086c533a883Shx147065 (void) ieee80211_new_state(ic, 3087c533a883Shx147065 IEEE80211_S_SCAN, -1); 3088c533a883Shx147065 } 3089c533a883Shx147065 } 309043439c96Shx147065 } 3091c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 3092c533a883Shx147065 3093bcb5c89dSSowmini Varadhan /* 3094bcb5c89dSSowmini Varadhan * callback functions for set/get properties 3095bcb5c89dSSowmini Varadhan */ 3096*0dc2366fSVenugopal Iyer 3097bcb5c89dSSowmini Varadhan static int 3098bcb5c89dSSowmini Varadhan iwk_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 3099*0dc2366fSVenugopal Iyer uint_t wldp_length, void *wldp_buf) 3100bcb5c89dSSowmini Varadhan { 3101bcb5c89dSSowmini Varadhan int err = 0; 3102bcb5c89dSSowmini Varadhan iwk_sc_t *sc = (iwk_sc_t *)arg; 3103bcb5c89dSSowmini Varadhan 3104bcb5c89dSSowmini Varadhan err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num, 3105*0dc2366fSVenugopal Iyer wldp_length, wldp_buf); 3106bcb5c89dSSowmini Varadhan 3107bcb5c89dSSowmini Varadhan return (err); 3108bcb5c89dSSowmini Varadhan } 3109*0dc2366fSVenugopal Iyer 3110bcb5c89dSSowmini Varadhan static int 3111bcb5c89dSSowmini Varadhan iwk_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 3112bcb5c89dSSowmini Varadhan uint_t wldp_length, const void *wldp_buf) 3113bcb5c89dSSowmini Varadhan { 3114bcb5c89dSSowmini Varadhan int err; 3115bcb5c89dSSowmini Varadhan iwk_sc_t *sc = (iwk_sc_t *)arg; 3116bcb5c89dSSowmini Varadhan ieee80211com_t *ic = &sc->sc_ic; 3117bcb5c89dSSowmini Varadhan 3118bcb5c89dSSowmini Varadhan err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length, 3119bcb5c89dSSowmini Varadhan wldp_buf); 3120bcb5c89dSSowmini Varadhan 3121bcb5c89dSSowmini Varadhan if (err == ENETRESET) { 3122bcb5c89dSSowmini Varadhan if (ic->ic_des_esslen) { 3123c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_RUNNING) { 3124c50ced99Spengcheng chen - Sun Microsystems - Beijing China iwk_m_stop(sc); 3125c50ced99Spengcheng chen - Sun Microsystems - Beijing China (void) iwk_m_start(sc); 3126bcb5c89dSSowmini Varadhan (void) ieee80211_new_state(ic, 3127bcb5c89dSSowmini Varadhan IEEE80211_S_SCAN, -1); 3128bcb5c89dSSowmini Varadhan } 3129c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 3130bcb5c89dSSowmini Varadhan err = 0; 3131bcb5c89dSSowmini Varadhan } 3132bcb5c89dSSowmini Varadhan 3133bcb5c89dSSowmini Varadhan return (err); 3134bcb5c89dSSowmini Varadhan } 3135bcb5c89dSSowmini Varadhan 3136*0dc2366fSVenugopal Iyer static void 3137*0dc2366fSVenugopal Iyer iwk_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 3138*0dc2366fSVenugopal Iyer mac_prop_info_handle_t mph) 3139*0dc2366fSVenugopal Iyer { 3140*0dc2366fSVenugopal Iyer iwk_sc_t *sc = (iwk_sc_t *)arg; 3141*0dc2366fSVenugopal Iyer ieee80211com_t *ic = &sc->sc_ic; 3142*0dc2366fSVenugopal Iyer 3143*0dc2366fSVenugopal Iyer ieee80211_propinfo(ic, pr_name, wldp_pr_num, mph); 3144*0dc2366fSVenugopal Iyer } 3145*0dc2366fSVenugopal Iyer 3146c533a883Shx147065 /*ARGSUSED*/ 3147c533a883Shx147065 static int 3148c533a883Shx147065 iwk_m_stat(void *arg, uint_t stat, uint64_t *val) 3149c533a883Shx147065 { 3150c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 3151c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 3152503bf41cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_node_t *in; 3153c533a883Shx147065 3154c533a883Shx147065 mutex_enter(&sc->sc_glock); 3155c533a883Shx147065 switch (stat) { 3156c533a883Shx147065 case MAC_STAT_IFSPEED: 3157503bf41cSpengcheng chen - Sun Microsystems - Beijing China in = ic->ic_bss; 3158c533a883Shx147065 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 3159503bf41cSpengcheng chen - Sun Microsystems - Beijing China IEEE80211_RATE(in->in_txrate) : 3160503bf41cSpengcheng chen - Sun Microsystems - Beijing China ic->ic_fixed_rate) / 2 * 1000000; 3161c533a883Shx147065 break; 3162c533a883Shx147065 case MAC_STAT_NOXMTBUF: 3163c533a883Shx147065 *val = sc->sc_tx_nobuf; 3164c533a883Shx147065 break; 3165c533a883Shx147065 case MAC_STAT_NORCVBUF: 3166c533a883Shx147065 *val = sc->sc_rx_nobuf; 3167c533a883Shx147065 break; 3168c533a883Shx147065 case MAC_STAT_IERRORS: 3169c533a883Shx147065 *val = sc->sc_rx_err; 3170c533a883Shx147065 break; 3171c533a883Shx147065 case MAC_STAT_RBYTES: 3172c533a883Shx147065 *val = ic->ic_stats.is_rx_bytes; 3173c533a883Shx147065 break; 3174c533a883Shx147065 case MAC_STAT_IPACKETS: 3175c533a883Shx147065 *val = ic->ic_stats.is_rx_frags; 3176c533a883Shx147065 break; 3177c533a883Shx147065 case MAC_STAT_OBYTES: 3178c533a883Shx147065 *val = ic->ic_stats.is_tx_bytes; 3179c533a883Shx147065 break; 3180c533a883Shx147065 case MAC_STAT_OPACKETS: 3181c533a883Shx147065 *val = ic->ic_stats.is_tx_frags; 3182c533a883Shx147065 break; 3183c533a883Shx147065 case MAC_STAT_OERRORS: 3184c533a883Shx147065 case WIFI_STAT_TX_FAILED: 3185c533a883Shx147065 *val = sc->sc_tx_err; 3186c533a883Shx147065 break; 3187c533a883Shx147065 case WIFI_STAT_TX_RETRANS: 3188c533a883Shx147065 *val = sc->sc_tx_retries; 3189c533a883Shx147065 break; 3190c533a883Shx147065 case WIFI_STAT_FCS_ERRORS: 3191c533a883Shx147065 case WIFI_STAT_WEP_ERRORS: 3192c533a883Shx147065 case WIFI_STAT_TX_FRAGS: 3193c533a883Shx147065 case WIFI_STAT_MCAST_TX: 3194c533a883Shx147065 case WIFI_STAT_RTS_SUCCESS: 3195c533a883Shx147065 case WIFI_STAT_RTS_FAILURE: 3196c533a883Shx147065 case WIFI_STAT_ACK_FAILURE: 3197c533a883Shx147065 case WIFI_STAT_RX_FRAGS: 3198c533a883Shx147065 case WIFI_STAT_MCAST_RX: 3199c533a883Shx147065 case WIFI_STAT_RX_DUPS: 3200c533a883Shx147065 mutex_exit(&sc->sc_glock); 3201c533a883Shx147065 return (ieee80211_stat(ic, stat, val)); 3202c533a883Shx147065 default: 3203c533a883Shx147065 mutex_exit(&sc->sc_glock); 3204c533a883Shx147065 return (ENOTSUP); 3205c533a883Shx147065 } 3206c533a883Shx147065 mutex_exit(&sc->sc_glock); 3207c533a883Shx147065 3208c533a883Shx147065 return (IWK_SUCCESS); 3209c533a883Shx147065 3210c533a883Shx147065 } 3211c533a883Shx147065 3212c533a883Shx147065 static int 3213c533a883Shx147065 iwk_m_start(void *arg) 3214c533a883Shx147065 { 3215c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 3216c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 3217c533a883Shx147065 int err; 3218c533a883Shx147065 3219c533a883Shx147065 err = iwk_init(sc); 3220c533a883Shx147065 3221c533a883Shx147065 if (err != IWK_SUCCESS) { 322243439c96Shx147065 /* 322343439c96Shx147065 * The hw init err(eg. RF is OFF). Return Success to make 322443439c96Shx147065 * the 'plumb' succeed. The iwk_thread() tries to re-init 322543439c96Shx147065 * background. 322643439c96Shx147065 */ 322743439c96Shx147065 mutex_enter(&sc->sc_glock); 322843439c96Shx147065 sc->sc_flags |= IWK_F_HW_ERR_RECOVER; 322943439c96Shx147065 mutex_exit(&sc->sc_glock); 323043439c96Shx147065 return (IWK_SUCCESS); 3231c533a883Shx147065 } 323243439c96Shx147065 3233c533a883Shx147065 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3234c533a883Shx147065 323543439c96Shx147065 mutex_enter(&sc->sc_glock); 323643439c96Shx147065 sc->sc_flags |= IWK_F_RUNNING; 323743439c96Shx147065 mutex_exit(&sc->sc_glock); 323843439c96Shx147065 323943439c96Shx147065 return (IWK_SUCCESS); 3240c533a883Shx147065 } 3241c533a883Shx147065 3242c533a883Shx147065 static void 3243c533a883Shx147065 iwk_m_stop(void *arg) 3244c533a883Shx147065 { 3245c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 3246c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 3247c533a883Shx147065 3248c533a883Shx147065 iwk_stop(sc); 3249c533a883Shx147065 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3250f3c4902cSpengcheng chen - Sun Microsystems - Beijing China ieee80211_stop_watchdog(ic); 3251c533a883Shx147065 mutex_enter(&sc->sc_mt_lock); 3252c533a883Shx147065 sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER; 325343439c96Shx147065 sc->sc_flags &= ~IWK_F_RATE_AUTO_CTL; 3254c533a883Shx147065 mutex_exit(&sc->sc_mt_lock); 325543439c96Shx147065 mutex_enter(&sc->sc_glock); 325643439c96Shx147065 sc->sc_flags &= ~IWK_F_RUNNING; 325743439c96Shx147065 mutex_exit(&sc->sc_glock); 3258c533a883Shx147065 } 3259c533a883Shx147065 3260c533a883Shx147065 /*ARGSUSED*/ 3261c533a883Shx147065 static int 3262c533a883Shx147065 iwk_m_unicst(void *arg, const uint8_t *macaddr) 3263c533a883Shx147065 { 3264c533a883Shx147065 iwk_sc_t *sc = (iwk_sc_t *)arg; 3265c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 3266c533a883Shx147065 int err; 3267c533a883Shx147065 3268c533a883Shx147065 if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) { 3269c533a883Shx147065 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr); 3270c533a883Shx147065 mutex_enter(&sc->sc_glock); 3271c533a883Shx147065 err = iwk_config(sc); 3272c533a883Shx147065 mutex_exit(&sc->sc_glock); 3273c533a883Shx147065 if (err != IWK_SUCCESS) { 3274c533a883Shx147065 cmn_err(CE_WARN, 3275c533a883Shx147065 "iwk_m_unicst(): " 3276c533a883Shx147065 "failed to configure device\n"); 3277c533a883Shx147065 goto fail; 3278c533a883Shx147065 } 3279c533a883Shx147065 } 3280c533a883Shx147065 return (IWK_SUCCESS); 3281c533a883Shx147065 fail: 3282c533a883Shx147065 return (err); 3283c533a883Shx147065 } 3284c533a883Shx147065 3285c533a883Shx147065 /*ARGSUSED*/ 3286c533a883Shx147065 static int 3287c533a883Shx147065 iwk_m_multicst(void *arg, boolean_t add, const uint8_t *m) 3288c533a883Shx147065 { 3289c533a883Shx147065 return (IWK_SUCCESS); 3290c533a883Shx147065 } 3291c533a883Shx147065 3292c533a883Shx147065 /*ARGSUSED*/ 3293c533a883Shx147065 static int 3294c533a883Shx147065 iwk_m_promisc(void *arg, boolean_t on) 3295c533a883Shx147065 { 3296c533a883Shx147065 return (IWK_SUCCESS); 3297c533a883Shx147065 } 3298c533a883Shx147065 3299c533a883Shx147065 static void 3300c533a883Shx147065 iwk_thread(iwk_sc_t *sc) 3301c533a883Shx147065 { 3302c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 330343439c96Shx147065 clock_t clk; 3304c533a883Shx147065 int times = 0, err, n = 0, timeout = 0; 330543439c96Shx147065 uint32_t tmp; 3306c533a883Shx147065 3307c533a883Shx147065 mutex_enter(&sc->sc_mt_lock); 3308c533a883Shx147065 while (sc->sc_mf_thread_switch) { 330943439c96Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL); 331043439c96Shx147065 if (tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) { 331143439c96Shx147065 sc->sc_flags &= ~IWK_F_RADIO_OFF; 331243439c96Shx147065 } else { 331343439c96Shx147065 sc->sc_flags |= IWK_F_RADIO_OFF; 331443439c96Shx147065 } 331543439c96Shx147065 /* 3316d62cb7ffShx147065 * If in SUSPEND or the RF is OFF, do nothing 331743439c96Shx147065 */ 3318d62cb7ffShx147065 if ((sc->sc_flags & IWK_F_SUSPEND) || 3319d62cb7ffShx147065 (sc->sc_flags & IWK_F_RADIO_OFF)) { 332043439c96Shx147065 mutex_exit(&sc->sc_mt_lock); 332143439c96Shx147065 delay(drv_usectohz(100000)); 332243439c96Shx147065 mutex_enter(&sc->sc_mt_lock); 332343439c96Shx147065 continue; 332443439c96Shx147065 } 332543439c96Shx147065 3326c533a883Shx147065 /* 3327c533a883Shx147065 * recovery fatal error 3328c533a883Shx147065 */ 3329c533a883Shx147065 if (ic->ic_mach && 3330c533a883Shx147065 (sc->sc_flags & IWK_F_HW_ERR_RECOVER)) { 3331c533a883Shx147065 3332c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, 3333c533a883Shx147065 "iwk_thread(): " 3334c533a883Shx147065 "try to recover fatal hw error: %d\n", times++)); 3335c533a883Shx147065 3336c533a883Shx147065 iwk_stop(sc); 3337c533a883Shx147065 33386f12def4Spengcheng chen - Sun Microsystems - Beijing China if (IWK_CHK_FAST_RECOVER(sc)) { 33396f12def4Spengcheng chen - Sun Microsystems - Beijing China /* save runtime configuration */ 33406f12def4Spengcheng chen - Sun Microsystems - Beijing China bcopy(&sc->sc_config, &sc->sc_config_save, 33416f12def4Spengcheng chen - Sun Microsystems - Beijing China sizeof (sc->sc_config)); 33426f12def4Spengcheng chen - Sun Microsystems - Beijing China } else { 3343c533a883Shx147065 mutex_exit(&sc->sc_mt_lock); 3344c50ced99Spengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3345c533a883Shx147065 delay(drv_usectohz(2000000 + n*500000)); 3346c533a883Shx147065 mutex_enter(&sc->sc_mt_lock); 33476f12def4Spengcheng chen - Sun Microsystems - Beijing China } 3348c50ced99Spengcheng chen - Sun Microsystems - Beijing China 3349c533a883Shx147065 err = iwk_init(sc); 3350c533a883Shx147065 if (err != IWK_SUCCESS) { 3351c533a883Shx147065 n++; 3352c533a883Shx147065 if (n < 20) 3353c533a883Shx147065 continue; 3354c533a883Shx147065 } 3355c533a883Shx147065 n = 0; 335643439c96Shx147065 if (!err) 335743439c96Shx147065 sc->sc_flags |= IWK_F_RUNNING; 33586f12def4Spengcheng chen - Sun Microsystems - Beijing China 33596f12def4Spengcheng chen - Sun Microsystems - Beijing China if (!IWK_CHK_FAST_RECOVER(sc) || 33606f12def4Spengcheng chen - Sun Microsystems - Beijing China iwk_fast_recover(sc) != IWK_SUCCESS) { 3361c533a883Shx147065 sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER; 33626f12def4Spengcheng chen - Sun Microsystems - Beijing China 3363c533a883Shx147065 mutex_exit(&sc->sc_mt_lock); 3364c533a883Shx147065 delay(drv_usectohz(2000000)); 3365c533a883Shx147065 if (sc->sc_ostate != IEEE80211_S_INIT) 33666f12def4Spengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(ic, 33676f12def4Spengcheng chen - Sun Microsystems - Beijing China IEEE80211_S_SCAN, 0); 3368c533a883Shx147065 mutex_enter(&sc->sc_mt_lock); 3369c533a883Shx147065 } 33706f12def4Spengcheng chen - Sun Microsystems - Beijing China } 3371c533a883Shx147065 3372d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_mach && (sc->sc_flags & IWK_F_LAZY_RESUME)) { 3373d40f4da4Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_RESUME, 33746f12def4Spengcheng chen - Sun Microsystems - Beijing China "iwk_thread(): lazy resume\n")); 33756f12def4Spengcheng chen - Sun Microsystems - Beijing China 3376d40f4da4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_LAZY_RESUME; 3377d40f4da4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_mt_lock); 3378d40f4da4Spengcheng chen - Sun Microsystems - Beijing China /* 3379d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * NB: under WPA mode, this call hangs (door problem?) 3380d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * when called in iwk_attach() and iwk_detach() while 3381d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * system is in the procedure of CPR. To be safe, let 3382d40f4da4Spengcheng chen - Sun Microsystems - Beijing China * the thread do this. 3383d40f4da4Spengcheng chen - Sun Microsystems - Beijing China */ 3384d40f4da4Spengcheng chen - Sun Microsystems - Beijing China ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 3385d40f4da4Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_mt_lock); 3386d40f4da4Spengcheng chen - Sun Microsystems - Beijing China } 3387d40f4da4Spengcheng chen - Sun Microsystems - Beijing China 3388c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_mach && 3389c50ced99Spengcheng chen - Sun Microsystems - Beijing China (sc->sc_flags & IWK_F_SCANNING) && sc->sc_scan_pending) { 3390c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN, 3391c50ced99Spengcheng chen - Sun Microsystems - Beijing China "iwk_thread(): " 3392c50ced99Spengcheng chen - Sun Microsystems - Beijing China "wait for probe response\n")); 3393c50ced99Spengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending--; 3394c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_mt_lock); 3395c50ced99Spengcheng chen - Sun Microsystems - Beijing China delay(drv_usectohz(200000)); 3396d40f4da4Spengcheng chen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_SCANNING) 3397c50ced99Spengcheng chen - Sun Microsystems - Beijing China ieee80211_next_scan(ic); 3398c50ced99Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_mt_lock); 3399c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 3400c50ced99Spengcheng chen - Sun Microsystems - Beijing China 340143439c96Shx147065 /* 340243439c96Shx147065 * rate ctl 340343439c96Shx147065 */ 340443439c96Shx147065 if (ic->ic_mach && 340543439c96Shx147065 (sc->sc_flags & IWK_F_RATE_AUTO_CTL)) { 340643439c96Shx147065 clk = ddi_get_lbolt(); 340743439c96Shx147065 if (clk > sc->sc_clk + drv_usectohz(500000)) { 340843439c96Shx147065 iwk_amrr_timeout(sc); 340943439c96Shx147065 } 341043439c96Shx147065 } 341143439c96Shx147065 3412216e0daaSQuaker Fang if ((ic->ic_state == IEEE80211_S_RUN) && 3413216e0daaSQuaker Fang (ic->ic_beaconmiss++ > 50)) { /* 5 seconds */ 3414216e0daaSQuaker Fang cmn_err(CE_WARN, "iwk: beacon missed for 5 seconds\n"); 3415216e0daaSQuaker Fang (void) ieee80211_new_state(ic, 3416216e0daaSQuaker Fang IEEE80211_S_INIT, -1); 3417216e0daaSQuaker Fang } 3418216e0daaSQuaker Fang 3419c533a883Shx147065 mutex_exit(&sc->sc_mt_lock); 3420c533a883Shx147065 delay(drv_usectohz(100000)); 3421c533a883Shx147065 mutex_enter(&sc->sc_mt_lock); 3422c533a883Shx147065 3423c533a883Shx147065 if (sc->sc_tx_timer) { 3424c533a883Shx147065 timeout++; 3425c533a883Shx147065 if (timeout == 10) { 3426c533a883Shx147065 sc->sc_tx_timer--; 3427c533a883Shx147065 if (sc->sc_tx_timer == 0) { 3428c533a883Shx147065 sc->sc_flags |= IWK_F_HW_ERR_RECOVER; 3429c533a883Shx147065 sc->sc_ostate = IEEE80211_S_RUN; 3430c533a883Shx147065 IWK_DBG((IWK_DEBUG_FW, 3431c533a883Shx147065 "iwk_thread(): try to recover from" 3432c533a883Shx147065 " 'send fail\n")); 3433c533a883Shx147065 } 3434c533a883Shx147065 timeout = 0; 3435c533a883Shx147065 } 3436c533a883Shx147065 } 3437c533a883Shx147065 3438c533a883Shx147065 } 3439c533a883Shx147065 sc->sc_mf_thread = NULL; 3440c533a883Shx147065 cv_signal(&sc->sc_mt_cv); 3441c533a883Shx147065 mutex_exit(&sc->sc_mt_lock); 3442c533a883Shx147065 } 3443c533a883Shx147065 3444c533a883Shx147065 3445c533a883Shx147065 /* 3446c533a883Shx147065 * Send a command to the firmware. 3447c533a883Shx147065 */ 3448c533a883Shx147065 static int 3449c533a883Shx147065 iwk_cmd(iwk_sc_t *sc, int code, const void *buf, int size, int async) 3450c533a883Shx147065 { 3451c533a883Shx147065 iwk_tx_ring_t *ring = &sc->sc_txq[IWK_CMD_QUEUE_NUM]; 3452c533a883Shx147065 iwk_tx_desc_t *desc; 3453c533a883Shx147065 iwk_cmd_t *cmd; 3454cdc64593Sxinghua wen - Sun Microsystems - Beijing China clock_t clk; 3455c533a883Shx147065 3456c533a883Shx147065 ASSERT(size <= sizeof (cmd->data)); 3457c533a883Shx147065 ASSERT(mutex_owned(&sc->sc_glock)); 3458c533a883Shx147065 3459c533a883Shx147065 IWK_DBG((IWK_DEBUG_CMD, "iwk_cmd() code[%d]", code)); 3460c533a883Shx147065 desc = ring->data[ring->cur].desc; 3461c533a883Shx147065 cmd = ring->data[ring->cur].cmd; 3462c533a883Shx147065 3463c533a883Shx147065 cmd->hdr.type = (uint8_t)code; 3464c533a883Shx147065 cmd->hdr.flags = 0; 3465c533a883Shx147065 cmd->hdr.qid = ring->qid; 3466c533a883Shx147065 cmd->hdr.idx = ring->cur; 3467c533a883Shx147065 (void) memcpy(cmd->data, buf, size); 3468c533a883Shx147065 (void) memset(desc, 0, sizeof (*desc)); 3469c533a883Shx147065 3470b510adaeSfei feng - Sun Microsystems - Beijing China desc->val0 = 1 << 24; 3471c533a883Shx147065 desc->pa[0].tb1_addr = 3472c533a883Shx147065 (uint32_t)(ring->data[ring->cur].paddr_cmd & 0xffffffff); 3473c533a883Shx147065 desc->pa[0].val1 = ((4 + size) << 4) & 0xfff0; 3474c533a883Shx147065 3475c533a883Shx147065 /* kick cmd ring XXX */ 3476cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3477cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[ring->cur].val = 8; 3478c533a883Shx147065 if (ring->cur < IWK_MAX_WIN_SIZE) { 3479cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3480cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8; 3481c533a883Shx147065 } 3482c533a883Shx147065 ring->cur = (ring->cur + 1) % ring->count; 3483c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3484c533a883Shx147065 3485c533a883Shx147065 if (async) 3486c533a883Shx147065 return (IWK_SUCCESS); 3487c533a883Shx147065 else { 3488c533a883Shx147065 sc->sc_flags &= ~IWK_F_CMD_DONE; 3489c533a883Shx147065 clk = ddi_get_lbolt() + drv_usectohz(2000000); 3490c533a883Shx147065 while (!(sc->sc_flags & IWK_F_CMD_DONE)) { 3491cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (cv_timedwait(&sc->sc_cmd_cv, &sc->sc_glock, clk) < 3492cdc64593Sxinghua wen - Sun Microsystems - Beijing China 0) 3493c533a883Shx147065 break; 3494c533a883Shx147065 } 3495c533a883Shx147065 if (sc->sc_flags & IWK_F_CMD_DONE) 3496c533a883Shx147065 return (IWK_SUCCESS); 3497c533a883Shx147065 else 3498c533a883Shx147065 return (IWK_FAIL); 3499c533a883Shx147065 } 3500c533a883Shx147065 } 3501c533a883Shx147065 3502c533a883Shx147065 static void 3503c533a883Shx147065 iwk_set_led(iwk_sc_t *sc, uint8_t id, uint8_t off, uint8_t on) 3504c533a883Shx147065 { 3505c533a883Shx147065 iwk_led_cmd_t led; 3506c533a883Shx147065 3507c533a883Shx147065 led.interval = LE_32(100000); /* unit: 100ms */ 3508c533a883Shx147065 led.id = id; 3509c533a883Shx147065 led.off = off; 3510c533a883Shx147065 led.on = on; 3511c533a883Shx147065 3512c533a883Shx147065 (void) iwk_cmd(sc, REPLY_LEDS_CMD, &led, sizeof (led), 1); 3513c533a883Shx147065 } 3514c533a883Shx147065 3515c533a883Shx147065 static int 3516c533a883Shx147065 iwk_hw_set_before_auth(iwk_sc_t *sc) 3517c533a883Shx147065 { 3518c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 3519c533a883Shx147065 ieee80211_node_t *in = ic->ic_bss; 3520c533a883Shx147065 iwk_add_sta_t node; 3521c533a883Shx147065 iwk_link_quality_cmd_t link_quality; 3522c533a883Shx147065 struct ieee80211_rateset rs; 3523c533a883Shx147065 uint16_t masks = 0, rate; 3524c533a883Shx147065 int i, err; 3525c533a883Shx147065 3526f3c4902cSpengcheng chen - Sun Microsystems - Beijing China if (in->in_chan == IEEE80211_CHAN_ANYC) { 3527f3c4902cSpengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_hw_set_before_auth():" 3528f3c4902cSpengcheng chen - Sun Microsystems - Beijing China "channel (%d) isn't in proper range\n", 3529b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(ieee80211_chan2ieee(ic, in->in_chan))); 3530f3c4902cSpengcheng chen - Sun Microsystems - Beijing China return (IWK_FAIL); 3531f3c4902cSpengcheng chen - Sun Microsystems - Beijing China } 3532f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 3533c533a883Shx147065 /* update adapter's configuration according the info of target AP */ 3534c533a883Shx147065 IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid); 3535b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, in->in_chan)); 3536c533a883Shx147065 if (ic->ic_curmode == IEEE80211_MODE_11B) { 3537c533a883Shx147065 sc->sc_config.cck_basic_rates = 0x03; 3538c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0; 3539c533a883Shx147065 } else if ((in->in_chan != IEEE80211_CHAN_ANYC) && 3540c533a883Shx147065 (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) { 3541c533a883Shx147065 sc->sc_config.cck_basic_rates = 0; 3542c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0x15; 3543c533a883Shx147065 } else { /* assume 802.11b/g */ 3544c533a883Shx147065 sc->sc_config.cck_basic_rates = 0x0f; 3545c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0xff; 3546c533a883Shx147065 } 3547c533a883Shx147065 3548c533a883Shx147065 sc->sc_config.flags &= ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK | 3549c533a883Shx147065 RXON_FLG_SHORT_SLOT_MSK); 3550c533a883Shx147065 3551c533a883Shx147065 if (ic->ic_flags & IEEE80211_F_SHSLOT) 3552c533a883Shx147065 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_SLOT_MSK); 3553c533a883Shx147065 else 3554c533a883Shx147065 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_SLOT_MSK); 3555c533a883Shx147065 3556c533a883Shx147065 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 3557c533a883Shx147065 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 3558c533a883Shx147065 else 3559c533a883Shx147065 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_PREAMBLE_MSK); 3560c533a883Shx147065 3561c533a883Shx147065 IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x " 3562c533a883Shx147065 "filter_flags %x cck %x ofdm %x" 3563c533a883Shx147065 " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n", 3564b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(sc->sc_config.chan), LE_32(sc->sc_config.flags), 3565b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(sc->sc_config.filter_flags), 3566c533a883Shx147065 sc->sc_config.cck_basic_rates, sc->sc_config.ofdm_basic_rates, 3567c533a883Shx147065 sc->sc_config.bssid[0], sc->sc_config.bssid[1], 3568c533a883Shx147065 sc->sc_config.bssid[2], sc->sc_config.bssid[3], 3569c533a883Shx147065 sc->sc_config.bssid[4], sc->sc_config.bssid[5])); 3570c533a883Shx147065 err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config, 3571c533a883Shx147065 sizeof (iwk_rxon_cmd_t), 1); 3572c533a883Shx147065 if (err != IWK_SUCCESS) { 3573c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth():" 3574c533a883Shx147065 " failed to config chan%d\n", 3575c533a883Shx147065 sc->sc_config.chan); 3576c533a883Shx147065 return (err); 3577c533a883Shx147065 } 3578c533a883Shx147065 3579cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */ 3580cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc); 3581cdc64593Sxinghua wen - Sun Microsystems - Beijing China 3582cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Tx power calibration to determine the gains of DSP and radio */ 3583cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc); 3584cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) { 3585c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth():" 3586cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to set tx power table\n"); 3587c533a883Shx147065 return (err); 3588c533a883Shx147065 } 3589c533a883Shx147065 3590c533a883Shx147065 /* add default AP node */ 3591c533a883Shx147065 (void) memset(&node, 0, sizeof (node)); 3592c533a883Shx147065 IEEE80211_ADDR_COPY(node.bssid, in->in_bssid); 3593c533a883Shx147065 node.id = IWK_AP_ID; 3594c533a883Shx147065 err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1); 3595c533a883Shx147065 if (err != IWK_SUCCESS) { 3596c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth(): " 3597c533a883Shx147065 "failed to add BSS node\n"); 3598c533a883Shx147065 return (err); 3599c533a883Shx147065 } 3600c533a883Shx147065 360119d332feSfei feng - Sun Microsystems - Beijing China /* TX_LINK_QUALITY cmd */ 3602c533a883Shx147065 (void) memset(&link_quality, 0, sizeof (link_quality)); 3603c533a883Shx147065 rs = ic->ic_sup_rates[ieee80211_chan2mode(ic, ic->ic_curchan)]; 3604c533a883Shx147065 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 3605c533a883Shx147065 if (i < rs.ir_nrates) 3606c533a883Shx147065 rate = rs.ir_rates[rs.ir_nrates - i]; 3607c533a883Shx147065 else 3608c533a883Shx147065 rate = 2; 3609c533a883Shx147065 if (rate == 2 || rate == 4 || rate == 11 || rate == 22) 3610c533a883Shx147065 masks |= RATE_MCS_CCK_MSK; 3611c533a883Shx147065 masks |= RATE_MCS_ANT_B_MSK; 3612c533a883Shx147065 masks &= ~RATE_MCS_ANT_A_MSK; 3613c533a883Shx147065 link_quality.rate_n_flags[i] = 3614b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(rate) | masks); 3615c533a883Shx147065 } 3616c533a883Shx147065 3617c533a883Shx147065 link_quality.general_params.single_stream_ant_msk = 2; 3618c533a883Shx147065 link_quality.general_params.dual_stream_ant_msk = 3; 3619c533a883Shx147065 link_quality.agg_params.agg_dis_start_th = 3; 3620c533a883Shx147065 link_quality.agg_params.agg_time_limit = LE_16(4000); 3621c533a883Shx147065 link_quality.sta_id = IWK_AP_ID; 3622c533a883Shx147065 err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality, 3623c533a883Shx147065 sizeof (link_quality), 1); 3624c533a883Shx147065 if (err != IWK_SUCCESS) { 3625c533a883Shx147065 cmn_err(CE_WARN, "iwk_hw_set_before_auth(): " 3626c533a883Shx147065 "failed to config link quality table\n"); 3627c533a883Shx147065 return (err); 3628c533a883Shx147065 } 3629c533a883Shx147065 3630c533a883Shx147065 return (IWK_SUCCESS); 3631c533a883Shx147065 } 3632c533a883Shx147065 3633c533a883Shx147065 /* 3634c533a883Shx147065 * Send a scan request(assembly scan cmd) to the firmware. 3635c533a883Shx147065 */ 3636c533a883Shx147065 static int 3637c533a883Shx147065 iwk_scan(iwk_sc_t *sc) 3638c533a883Shx147065 { 3639c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 3640c533a883Shx147065 iwk_tx_ring_t *ring = &sc->sc_txq[IWK_CMD_QUEUE_NUM]; 3641c533a883Shx147065 iwk_tx_desc_t *desc; 3642c533a883Shx147065 iwk_tx_data_t *data; 3643c533a883Shx147065 iwk_cmd_t *cmd; 3644c533a883Shx147065 iwk_scan_hdr_t *hdr; 3645c533a883Shx147065 iwk_scan_chan_t *chan; 3646c533a883Shx147065 struct ieee80211_frame *wh; 3647c533a883Shx147065 ieee80211_node_t *in = ic->ic_bss; 3648c50ced99Spengcheng chen - Sun Microsystems - Beijing China uint8_t essid[IEEE80211_NWID_LEN+1]; 3649c533a883Shx147065 struct ieee80211_rateset *rs; 3650c533a883Shx147065 enum ieee80211_phymode mode; 3651c533a883Shx147065 uint8_t *frm; 3652c533a883Shx147065 int i, pktlen, nrates; 3653c533a883Shx147065 3654c533a883Shx147065 data = &ring->data[ring->cur]; 3655c533a883Shx147065 desc = data->desc; 3656c533a883Shx147065 cmd = (iwk_cmd_t *)data->dma_data.mem_va; 3657c533a883Shx147065 3658c533a883Shx147065 cmd->hdr.type = REPLY_SCAN_CMD; 3659c533a883Shx147065 cmd->hdr.flags = 0; 3660c533a883Shx147065 cmd->hdr.qid = ring->qid; 3661c533a883Shx147065 cmd->hdr.idx = ring->cur | 0x40; 3662c533a883Shx147065 3663c533a883Shx147065 hdr = (iwk_scan_hdr_t *)cmd->data; 3664c533a883Shx147065 (void) memset(hdr, 0, sizeof (iwk_scan_hdr_t)); 3665c50ced99Spengcheng chen - Sun Microsystems - Beijing China hdr->nchan = 1; 3666c50ced99Spengcheng chen - Sun Microsystems - Beijing China hdr->quiet_time = LE_16(50); 3667c533a883Shx147065 hdr->quiet_plcp_th = LE_16(1); 3668c533a883Shx147065 3669b510adaeSfei feng - Sun Microsystems - Beijing China hdr->flags = LE_32(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK); 3670b510adaeSfei feng - Sun Microsystems - Beijing China hdr->rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK | 3671b510adaeSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_VALID_POS) | 3672c533a883Shx147065 (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) | 3673c533a883Shx147065 (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 3674c533a883Shx147065 3675b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.tx_flags = LE_32(TX_CMD_FLG_SEQ_CTL_MSK); 3676c533a883Shx147065 hdr->tx_cmd.sta_id = IWK_BROADCAST_ID; 3677b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.stop_time.life_time = LE_32(0xffffffff); 3678b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.tx_flags |= LE_32(0x200); 3679b510adaeSfei feng - Sun Microsystems - Beijing China hdr->tx_cmd.rate.r.rate_n_flags = LE_32(iwk_rate_to_plcp(2)); 3680c533a883Shx147065 hdr->tx_cmd.rate.r.rate_n_flags |= 3681b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK); 3682c533a883Shx147065 hdr->direct_scan[0].len = ic->ic_des_esslen; 3683c533a883Shx147065 hdr->direct_scan[0].id = IEEE80211_ELEMID_SSID; 3684c533a883Shx147065 3685c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_des_esslen) { 3686c50ced99Spengcheng chen - Sun Microsystems - Beijing China bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen); 3687c50ced99Spengcheng chen - Sun Microsystems - Beijing China essid[ic->ic_des_esslen] = '\0'; 3688c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN, "directed scan %s\n", essid)); 3689c50ced99Spengcheng chen - Sun Microsystems - Beijing China 3690c533a883Shx147065 bcopy(ic->ic_des_essid, hdr->direct_scan[0].ssid, 3691c533a883Shx147065 ic->ic_des_esslen); 3692c50ced99Spengcheng chen - Sun Microsystems - Beijing China } else { 3693c533a883Shx147065 bzero(hdr->direct_scan[0].ssid, 3694c533a883Shx147065 sizeof (hdr->direct_scan[0].ssid)); 3695c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 3696c533a883Shx147065 /* 3697c533a883Shx147065 * a probe request frame is required after the REPLY_SCAN_CMD 3698c533a883Shx147065 */ 3699c533a883Shx147065 wh = (struct ieee80211_frame *)(hdr + 1); 3700c533a883Shx147065 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 3701c533a883Shx147065 IEEE80211_FC0_SUBTYPE_PROBE_REQ; 3702c533a883Shx147065 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 3703c533a883Shx147065 (void) memset(wh->i_addr1, 0xff, 6); 3704c533a883Shx147065 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr); 3705c533a883Shx147065 (void) memset(wh->i_addr3, 0xff, 6); 3706c533a883Shx147065 *(uint16_t *)&wh->i_dur[0] = 0; 3707c533a883Shx147065 *(uint16_t *)&wh->i_seq[0] = 0; 3708c533a883Shx147065 3709c533a883Shx147065 frm = (uint8_t *)(wh + 1); 3710c533a883Shx147065 3711c533a883Shx147065 /* essid IE */ 3712c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (in->in_esslen) { 3713c50ced99Spengcheng chen - Sun Microsystems - Beijing China bcopy(in->in_essid, essid, in->in_esslen); 3714c50ced99Spengcheng chen - Sun Microsystems - Beijing China essid[in->in_esslen] = '\0'; 3715c50ced99Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_SCAN, "probe with ESSID %s\n", 3716c50ced99Spengcheng chen - Sun Microsystems - Beijing China essid)); 3717c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 3718c533a883Shx147065 *frm++ = IEEE80211_ELEMID_SSID; 3719c533a883Shx147065 *frm++ = in->in_esslen; 3720c533a883Shx147065 (void) memcpy(frm, in->in_essid, in->in_esslen); 3721c533a883Shx147065 frm += in->in_esslen; 3722c533a883Shx147065 3723c533a883Shx147065 mode = ieee80211_chan2mode(ic, ic->ic_curchan); 3724c533a883Shx147065 rs = &ic->ic_sup_rates[mode]; 3725c533a883Shx147065 3726c533a883Shx147065 /* supported rates IE */ 3727c533a883Shx147065 *frm++ = IEEE80211_ELEMID_RATES; 3728c533a883Shx147065 nrates = rs->ir_nrates; 3729c533a883Shx147065 if (nrates > IEEE80211_RATE_SIZE) 3730c533a883Shx147065 nrates = IEEE80211_RATE_SIZE; 3731c533a883Shx147065 *frm++ = (uint8_t)nrates; 3732c533a883Shx147065 (void) memcpy(frm, rs->ir_rates, nrates); 3733c533a883Shx147065 frm += nrates; 3734c533a883Shx147065 3735c533a883Shx147065 /* supported xrates IE */ 3736c533a883Shx147065 if (rs->ir_nrates > IEEE80211_RATE_SIZE) { 3737c533a883Shx147065 nrates = rs->ir_nrates - IEEE80211_RATE_SIZE; 3738c533a883Shx147065 *frm++ = IEEE80211_ELEMID_XRATES; 3739c533a883Shx147065 *frm++ = (uint8_t)nrates; 3740c533a883Shx147065 (void) memcpy(frm, rs->ir_rates + IEEE80211_RATE_SIZE, nrates); 3741c533a883Shx147065 frm += nrates; 3742c533a883Shx147065 } 3743c533a883Shx147065 3744c533a883Shx147065 /* optionnal IE (usually for wpa) */ 3745c533a883Shx147065 if (ic->ic_opt_ie != NULL) { 3746c533a883Shx147065 (void) memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len); 3747c533a883Shx147065 frm += ic->ic_opt_ie_len; 3748c533a883Shx147065 } 3749c533a883Shx147065 3750c533a883Shx147065 /* setup length of probe request */ 3751ff3124efSff224033 hdr->tx_cmd.len = LE_16(_PTRDIFF(frm, wh)); 3752b510adaeSfei feng - Sun Microsystems - Beijing China hdr->len = LE_16(hdr->nchan * sizeof (iwk_scan_chan_t) + 3753b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(hdr->tx_cmd.len) + sizeof (iwk_scan_hdr_t)); 3754c533a883Shx147065 3755c533a883Shx147065 /* 3756c533a883Shx147065 * the attribute of the scan channels are required after the probe 3757c533a883Shx147065 * request frame. 3758c533a883Shx147065 */ 3759c533a883Shx147065 chan = (iwk_scan_chan_t *)frm; 3760c533a883Shx147065 for (i = 1; i <= hdr->nchan; i++, chan++) { 3761c50ced99Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_des_esslen) { 3762c533a883Shx147065 chan->type = 3; 3763c50ced99Spengcheng chen - Sun Microsystems - Beijing China } else { 3764c50ced99Spengcheng chen - Sun Microsystems - Beijing China chan->type = 1; 3765c50ced99Spengcheng chen - Sun Microsystems - Beijing China } 3766c50ced99Spengcheng chen - Sun Microsystems - Beijing China 3767c50ced99Spengcheng chen - Sun Microsystems - Beijing China chan->chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 3768c533a883Shx147065 chan->tpc.tx_gain = 0x3f; 3769c533a883Shx147065 chan->tpc.dsp_atten = 110; 3770c50ced99Spengcheng chen - Sun Microsystems - Beijing China chan->active_dwell = LE_16(50); 3771c533a883Shx147065 chan->passive_dwell = LE_16(120); 3772c533a883Shx147065 3773c533a883Shx147065 frm += sizeof (iwk_scan_chan_t); 3774c533a883Shx147065 } 3775c533a883Shx147065 3776ff3124efSff224033 pktlen = _PTRDIFF(frm, cmd); 3777c533a883Shx147065 3778c533a883Shx147065 (void) memset(desc, 0, sizeof (*desc)); 3779b510adaeSfei feng - Sun Microsystems - Beijing China desc->val0 = 1 << 24; 3780c533a883Shx147065 desc->pa[0].tb1_addr = 3781c533a883Shx147065 (uint32_t)(data->dma_data.cookie.dmac_address & 0xffffffff); 3782c533a883Shx147065 desc->pa[0].val1 = (pktlen << 4) & 0xfff0; 3783c533a883Shx147065 3784c533a883Shx147065 /* 3785c533a883Shx147065 * maybe for cmd, filling the byte cnt table is not necessary. 3786c533a883Shx147065 * anyway, we fill it here. 3787c533a883Shx147065 */ 3788cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3789cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[ring->cur].val = 8; 3790c533a883Shx147065 if (ring->cur < IWK_MAX_WIN_SIZE) { 3791cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3792cdc64593Sxinghua wen - Sun Microsystems - Beijing China tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8; 3793c533a883Shx147065 } 379443439c96Shx147065 3795c533a883Shx147065 /* kick cmd ring */ 3796c533a883Shx147065 ring->cur = (ring->cur + 1) % ring->count; 3797c533a883Shx147065 IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3798c533a883Shx147065 3799c533a883Shx147065 return (IWK_SUCCESS); 3800c533a883Shx147065 } 3801c533a883Shx147065 3802c533a883Shx147065 static int 3803c533a883Shx147065 iwk_config(iwk_sc_t *sc) 3804c533a883Shx147065 { 3805c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 3806c533a883Shx147065 iwk_powertable_cmd_t powertable; 3807c533a883Shx147065 iwk_bt_cmd_t bt; 3808c533a883Shx147065 iwk_add_sta_t node; 3809c533a883Shx147065 iwk_link_quality_cmd_t link_quality; 3810c533a883Shx147065 int i, err; 3811c533a883Shx147065 uint16_t masks = 0; 3812c533a883Shx147065 3813c533a883Shx147065 /* 3814c533a883Shx147065 * set power mode. Disable power management at present, do it later 3815c533a883Shx147065 */ 3816c533a883Shx147065 (void) memset(&powertable, 0, sizeof (powertable)); 3817c533a883Shx147065 powertable.flags = LE_16(0x8); 3818c533a883Shx147065 err = iwk_cmd(sc, POWER_TABLE_CMD, &powertable, 3819c533a883Shx147065 sizeof (powertable), 0); 3820c533a883Shx147065 if (err != IWK_SUCCESS) { 3821c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): failed to set power mode\n"); 3822c533a883Shx147065 return (err); 3823c533a883Shx147065 } 3824c533a883Shx147065 3825c533a883Shx147065 /* configure bt coexistence */ 3826c533a883Shx147065 (void) memset(&bt, 0, sizeof (bt)); 3827c533a883Shx147065 bt.flags = 3; 3828c533a883Shx147065 bt.lead_time = 0xaa; 3829c533a883Shx147065 bt.max_kill = 1; 3830c533a883Shx147065 err = iwk_cmd(sc, REPLY_BT_CONFIG, &bt, 3831c533a883Shx147065 sizeof (bt), 0); 3832c533a883Shx147065 if (err != IWK_SUCCESS) { 3833c533a883Shx147065 cmn_err(CE_WARN, 3834c533a883Shx147065 "iwk_config(): " 3835c533a883Shx147065 "failed to configurate bt coexistence\n"); 3836c533a883Shx147065 return (err); 3837c533a883Shx147065 } 3838c533a883Shx147065 3839c533a883Shx147065 /* configure rxon */ 3840c533a883Shx147065 (void) memset(&sc->sc_config, 0, sizeof (iwk_rxon_cmd_t)); 3841c533a883Shx147065 IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr); 3842c533a883Shx147065 IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr); 3843b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan)); 3844b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags = LE_32(RXON_FLG_TSF2HOST_MSK | 3845cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_BAND_24G_MSK); 3846b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &= LE_32(~RXON_FLG_CCK_MSK); 3847c533a883Shx147065 switch (ic->ic_opmode) { 3848c533a883Shx147065 case IEEE80211_M_STA: 3849c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_ESS; 3850c533a883Shx147065 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 3851c533a883Shx147065 RXON_FILTER_DIS_DECRYPT_MSK | 3852c533a883Shx147065 RXON_FILTER_DIS_GRP_DECRYPT_MSK); 3853c533a883Shx147065 break; 385419d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_M_IBSS: 3855c533a883Shx147065 case IEEE80211_M_AHDEMO: 3856c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS; 3857b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 3858cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_config.filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 3859cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK | 3860cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK); 3861c533a883Shx147065 break; 3862c533a883Shx147065 case IEEE80211_M_HOSTAP: 3863c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_AP; 3864c533a883Shx147065 break; 3865c533a883Shx147065 case IEEE80211_M_MONITOR: 3866c533a883Shx147065 sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER; 3867c533a883Shx147065 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 3868c533a883Shx147065 RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK); 3869c533a883Shx147065 break; 3870c533a883Shx147065 } 3871c533a883Shx147065 sc->sc_config.cck_basic_rates = 0x0f; 3872c533a883Shx147065 sc->sc_config.ofdm_basic_rates = 0xff; 3873c533a883Shx147065 3874c533a883Shx147065 sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff; 3875c533a883Shx147065 sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff; 3876c533a883Shx147065 3877c533a883Shx147065 /* set antenna */ 3878c533a883Shx147065 3879b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK | 3880b510adaeSfei feng - Sun Microsystems - Beijing China (0x7 << RXON_RX_CHAIN_VALID_POS) | 3881c533a883Shx147065 (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) | 3882c533a883Shx147065 (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 3883c533a883Shx147065 3884c533a883Shx147065 err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config, 3885c533a883Shx147065 sizeof (iwk_rxon_cmd_t), 0); 3886c533a883Shx147065 if (err != IWK_SUCCESS) { 3887c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): " 3888c533a883Shx147065 "failed to set configure command\n"); 3889c533a883Shx147065 return (err); 3890c533a883Shx147065 } 3891cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */ 3892cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc); 3893c533a883Shx147065 3894cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Tx power calibration to determine the gains of DSP and radio */ 3895cdc64593Sxinghua wen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc); 3896cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (err) { 3897cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_config(): " 3898cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to set tx power table\n"); 3899c533a883Shx147065 return (err); 3900c533a883Shx147065 } 3901c533a883Shx147065 3902c533a883Shx147065 /* add broadcast node so that we can send broadcast frame */ 3903c533a883Shx147065 (void) memset(&node, 0, sizeof (node)); 3904c533a883Shx147065 (void) memset(node.bssid, 0xff, 6); 3905c533a883Shx147065 node.id = IWK_BROADCAST_ID; 3906c533a883Shx147065 err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 0); 3907c533a883Shx147065 if (err != IWK_SUCCESS) { 3908c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): " 3909c533a883Shx147065 "failed to add broadcast node\n"); 3910c533a883Shx147065 return (err); 3911c533a883Shx147065 } 3912c533a883Shx147065 3913c533a883Shx147065 /* TX_LINK_QUALITY cmd ? */ 3914c533a883Shx147065 (void) memset(&link_quality, 0, sizeof (link_quality)); 3915c533a883Shx147065 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 3916c533a883Shx147065 masks |= RATE_MCS_CCK_MSK; 3917c533a883Shx147065 masks |= RATE_MCS_ANT_B_MSK; 3918c533a883Shx147065 masks &= ~RATE_MCS_ANT_A_MSK; 3919b510adaeSfei feng - Sun Microsystems - Beijing China link_quality.rate_n_flags[i] = 3920b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(2) | masks); 3921c533a883Shx147065 } 3922c533a883Shx147065 3923c533a883Shx147065 link_quality.general_params.single_stream_ant_msk = 2; 3924c533a883Shx147065 link_quality.general_params.dual_stream_ant_msk = 3; 3925c533a883Shx147065 link_quality.agg_params.agg_dis_start_th = 3; 3926c533a883Shx147065 link_quality.agg_params.agg_time_limit = LE_16(4000); 3927c533a883Shx147065 link_quality.sta_id = IWK_BROADCAST_ID; 3928c533a883Shx147065 err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality, 3929c533a883Shx147065 sizeof (link_quality), 0); 3930c533a883Shx147065 if (err != IWK_SUCCESS) { 3931c533a883Shx147065 cmn_err(CE_WARN, "iwk_config(): " 3932c533a883Shx147065 "failed to config link quality table\n"); 3933c533a883Shx147065 return (err); 3934c533a883Shx147065 } 3935c533a883Shx147065 3936c533a883Shx147065 return (IWK_SUCCESS); 3937c533a883Shx147065 } 3938c533a883Shx147065 3939c533a883Shx147065 static void 3940c533a883Shx147065 iwk_stop_master(iwk_sc_t *sc) 3941c533a883Shx147065 { 3942c533a883Shx147065 uint32_t tmp; 3943c533a883Shx147065 int n; 3944c533a883Shx147065 3945c533a883Shx147065 tmp = IWK_READ(sc, CSR_RESET); 3946c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_STOP_MASTER); 3947c533a883Shx147065 3948c533a883Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL); 3949c533a883Shx147065 if ((tmp & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE) == 3950c533a883Shx147065 CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE) 3951c533a883Shx147065 return; 3952c533a883Shx147065 3953c533a883Shx147065 for (n = 0; n < 2000; n++) { 3954c533a883Shx147065 if (IWK_READ(sc, CSR_RESET) & 3955c533a883Shx147065 CSR_RESET_REG_FLAG_MASTER_DISABLED) 3956c533a883Shx147065 break; 3957c533a883Shx147065 DELAY(1000); 3958c533a883Shx147065 } 3959c533a883Shx147065 if (n == 2000) 3960c533a883Shx147065 IWK_DBG((IWK_DEBUG_HW, 3961c533a883Shx147065 "timeout waiting for master stop\n")); 3962c533a883Shx147065 } 3963c533a883Shx147065 3964c533a883Shx147065 static int 3965c533a883Shx147065 iwk_power_up(iwk_sc_t *sc) 3966c533a883Shx147065 { 3967c533a883Shx147065 uint32_t tmp; 3968c533a883Shx147065 3969c533a883Shx147065 iwk_mac_access_enter(sc); 3970c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL); 3971c533a883Shx147065 tmp &= ~APMG_PS_CTRL_REG_MSK_POWER_SRC; 3972c533a883Shx147065 tmp |= APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN; 3973c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp); 3974c533a883Shx147065 iwk_mac_access_exit(sc); 3975c533a883Shx147065 3976c533a883Shx147065 DELAY(5000); 3977c533a883Shx147065 return (IWK_SUCCESS); 3978c533a883Shx147065 } 3979c533a883Shx147065 3980c533a883Shx147065 static int 3981c533a883Shx147065 iwk_preinit(iwk_sc_t *sc) 3982c533a883Shx147065 { 3983c533a883Shx147065 uint32_t tmp; 3984c533a883Shx147065 int n; 3985c533a883Shx147065 uint8_t vlink; 3986c533a883Shx147065 3987c533a883Shx147065 /* clear any pending interrupts */ 3988c533a883Shx147065 IWK_WRITE(sc, CSR_INT, 0xffffffff); 3989c533a883Shx147065 3990c533a883Shx147065 tmp = IWK_READ(sc, CSR_GIO_CHICKEN_BITS); 3991c533a883Shx147065 IWK_WRITE(sc, CSR_GIO_CHICKEN_BITS, 3992c533a883Shx147065 tmp | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); 3993c533a883Shx147065 3994c533a883Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL); 3995c533a883Shx147065 IWK_WRITE(sc, CSR_GP_CNTRL, tmp | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 3996c533a883Shx147065 3997c533a883Shx147065 /* wait for clock ready */ 3998c533a883Shx147065 for (n = 0; n < 1000; n++) { 3999c533a883Shx147065 if (IWK_READ(sc, CSR_GP_CNTRL) & 4000c533a883Shx147065 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) 4001c533a883Shx147065 break; 4002c533a883Shx147065 DELAY(10); 4003c533a883Shx147065 } 4004c533a883Shx147065 if (n == 1000) { 4005c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, 4006c50ced99Spengcheng chen - Sun Microsystems - Beijing China "iwk_preinit(): timeout waiting for clock ready\n"); 4007c533a883Shx147065 return (ETIMEDOUT); 4008c533a883Shx147065 } 4009c533a883Shx147065 iwk_mac_access_enter(sc); 4010c533a883Shx147065 tmp = iwk_reg_read(sc, APMG_CLK_CTRL_REG); 4011c533a883Shx147065 iwk_reg_write(sc, APMG_CLK_CTRL_REG, tmp | 4012c533a883Shx147065 APMG_CLK_REG_VAL_DMA_CLK_RQT | APMG_CLK_REG_VAL_BSM_CLK_RQT); 4013c533a883Shx147065 4014c533a883Shx147065 DELAY(20); 4015c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PCIDEV_STT); 4016c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PCIDEV_STT, tmp | 4017c533a883Shx147065 APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE); 4018c533a883Shx147065 iwk_mac_access_exit(sc); 4019c533a883Shx147065 4020c533a883Shx147065 IWK_WRITE(sc, CSR_INT_COALESCING, 512 / 32); /* ??? */ 4021c533a883Shx147065 4022c533a883Shx147065 (void) iwk_power_up(sc); 4023c533a883Shx147065 4024c533a883Shx147065 if ((sc->sc_rev & 0x80) == 0x80 && (sc->sc_rev & 0x7f) < 8) { 4025c533a883Shx147065 tmp = ddi_get32(sc->sc_cfg_handle, 4026c533a883Shx147065 (uint32_t *)(sc->sc_cfg_base + 0xe8)); 4027c533a883Shx147065 ddi_put32(sc->sc_cfg_handle, 4028c533a883Shx147065 (uint32_t *)(sc->sc_cfg_base + 0xe8), 4029c533a883Shx147065 tmp & ~(1 << 11)); 4030c533a883Shx147065 } 4031c533a883Shx147065 4032c533a883Shx147065 4033c533a883Shx147065 vlink = ddi_get8(sc->sc_cfg_handle, 4034c533a883Shx147065 (uint8_t *)(sc->sc_cfg_base + 0xf0)); 4035c533a883Shx147065 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0xf0), 4036c533a883Shx147065 vlink & ~2); 4037c533a883Shx147065 4038c533a883Shx147065 tmp = IWK_READ(sc, CSR_SW_VER); 4039c533a883Shx147065 tmp |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | 4040cdc64593Sxinghua wen - Sun Microsystems - Beijing China CSR_HW_IF_CONFIG_REG_BIT_MAC_SI | 4041cdc64593Sxinghua wen - Sun Microsystems - Beijing China CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R; 4042c533a883Shx147065 IWK_WRITE(sc, CSR_SW_VER, tmp); 4043c533a883Shx147065 4044c533a883Shx147065 /* make sure power supply on each part of the hardware */ 4045c533a883Shx147065 iwk_mac_access_enter(sc); 4046c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL); 4047c533a883Shx147065 tmp |= APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ; 4048c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4049c533a883Shx147065 DELAY(5); 4050c533a883Shx147065 tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL); 4051c533a883Shx147065 tmp &= ~APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ; 4052c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4053c533a883Shx147065 iwk_mac_access_exit(sc); 4054c533a883Shx147065 return (IWK_SUCCESS); 4055c533a883Shx147065 } 4056c533a883Shx147065 4057c533a883Shx147065 /* 4058c533a883Shx147065 * set up semphore flag to own EEPROM 4059c533a883Shx147065 */ 4060c533a883Shx147065 static int iwk_eep_sem_down(iwk_sc_t *sc) 4061c533a883Shx147065 { 4062c533a883Shx147065 int count1, count2; 4063c533a883Shx147065 uint32_t tmp; 4064c533a883Shx147065 4065c533a883Shx147065 for (count1 = 0; count1 < 1000; count1++) { 4066c533a883Shx147065 tmp = IWK_READ(sc, CSR_HW_IF_CONFIG_REG); 4067c533a883Shx147065 IWK_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4068c533a883Shx147065 tmp | CSR_HW_IF_CONFIG_REG_EEP_SEM); 4069c533a883Shx147065 4070c533a883Shx147065 for (count2 = 0; count2 < 2; count2++) { 4071c533a883Shx147065 if (IWK_READ(sc, CSR_HW_IF_CONFIG_REG) & 4072c533a883Shx147065 CSR_HW_IF_CONFIG_REG_EEP_SEM) 4073c533a883Shx147065 return (IWK_SUCCESS); 4074c533a883Shx147065 DELAY(10000); 4075c533a883Shx147065 } 4076c533a883Shx147065 } 4077c533a883Shx147065 return (IWK_FAIL); 4078c533a883Shx147065 } 4079c533a883Shx147065 4080c533a883Shx147065 /* 4081c533a883Shx147065 * reset semphore flag to release EEPROM 4082c533a883Shx147065 */ 4083c533a883Shx147065 static void iwk_eep_sem_up(iwk_sc_t *sc) 4084c533a883Shx147065 { 4085c533a883Shx147065 uint32_t tmp; 4086c533a883Shx147065 4087c533a883Shx147065 tmp = IWK_READ(sc, CSR_HW_IF_CONFIG_REG); 4088c533a883Shx147065 IWK_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4089c533a883Shx147065 tmp & (~CSR_HW_IF_CONFIG_REG_EEP_SEM)); 4090c533a883Shx147065 } 4091c533a883Shx147065 4092c533a883Shx147065 /* 4093c533a883Shx147065 * This function load all infomation in eeprom into iwk_eep 4094c533a883Shx147065 * structure in iwk_sc_t structure 4095c533a883Shx147065 */ 4096c533a883Shx147065 static int iwk_eep_load(iwk_sc_t *sc) 4097c533a883Shx147065 { 4098c533a883Shx147065 int i, rr; 4099c533a883Shx147065 uint32_t rv, tmp, eep_gp; 4100c533a883Shx147065 uint16_t addr, eep_sz = sizeof (sc->sc_eep_map); 4101c533a883Shx147065 uint16_t *eep_p = (uint16_t *)&sc->sc_eep_map; 4102c533a883Shx147065 4103c533a883Shx147065 /* read eeprom gp register in CSR */ 4104c533a883Shx147065 eep_gp = IWK_READ(sc, CSR_EEPROM_GP); 4105c533a883Shx147065 if ((eep_gp & CSR_EEPROM_GP_VALID_MSK) == 4106c533a883Shx147065 CSR_EEPROM_GP_BAD_SIGNATURE) { 4107c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "EEPROM not found\n"); 4108c533a883Shx147065 return (IWK_FAIL); 4109c533a883Shx147065 } 4110c533a883Shx147065 4111c533a883Shx147065 rr = iwk_eep_sem_down(sc); 4112c533a883Shx147065 if (rr != 0) { 4113c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "failed to own EEPROM\n"); 4114c533a883Shx147065 return (IWK_FAIL); 4115c533a883Shx147065 } 4116c533a883Shx147065 4117c533a883Shx147065 for (addr = 0; addr < eep_sz; addr += 2) { 4118c533a883Shx147065 IWK_WRITE(sc, CSR_EEPROM_REG, addr<<1); 4119c533a883Shx147065 tmp = IWK_READ(sc, CSR_EEPROM_REG); 4120c533a883Shx147065 IWK_WRITE(sc, CSR_EEPROM_REG, tmp & ~(0x2)); 4121c533a883Shx147065 4122c533a883Shx147065 for (i = 0; i < 10; i++) { 4123c533a883Shx147065 rv = IWK_READ(sc, CSR_EEPROM_REG); 4124c533a883Shx147065 if (rv & 1) 4125c533a883Shx147065 break; 4126c533a883Shx147065 DELAY(10); 4127c533a883Shx147065 } 4128c533a883Shx147065 4129c533a883Shx147065 if (!(rv & 1)) { 4130c50ced99Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "time out when read EEPROM\n"); 4131c533a883Shx147065 iwk_eep_sem_up(sc); 4132c533a883Shx147065 return (IWK_FAIL); 4133c533a883Shx147065 } 4134c533a883Shx147065 4135b510adaeSfei feng - Sun Microsystems - Beijing China eep_p[addr/2] = LE_16(rv >> 16); 4136c533a883Shx147065 } 4137c533a883Shx147065 4138c533a883Shx147065 iwk_eep_sem_up(sc); 4139c533a883Shx147065 return (IWK_SUCCESS); 4140c533a883Shx147065 } 4141c533a883Shx147065 4142c533a883Shx147065 /* 4143c533a883Shx147065 * init mac address in ieee80211com_t struct 4144c533a883Shx147065 */ 4145c533a883Shx147065 static void iwk_get_mac_from_eep(iwk_sc_t *sc) 4146c533a883Shx147065 { 4147c533a883Shx147065 ieee80211com_t *ic = &sc->sc_ic; 4148c533a883Shx147065 struct iwk_eep *ep = &sc->sc_eep_map; 4149c533a883Shx147065 4150c533a883Shx147065 IEEE80211_ADDR_COPY(ic->ic_macaddr, ep->mac_address); 4151c533a883Shx147065 4152c533a883Shx147065 IWK_DBG((IWK_DEBUG_EEPROM, "mac:%2x:%2x:%2x:%2x:%2x:%2x\n", 4153c533a883Shx147065 ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2], 4154c533a883Shx147065 ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5])); 4155c533a883Shx147065 } 4156c533a883Shx147065 4157c533a883Shx147065 static int 4158c533a883Shx147065 iwk_init(iwk_sc_t *sc) 4159c533a883Shx147065 { 4160c533a883Shx147065 int qid, n, err; 4161c533a883Shx147065 clock_t clk; 416243439c96Shx147065 uint32_t tmp; 4163c533a883Shx147065 4164c533a883Shx147065 mutex_enter(&sc->sc_glock); 4165c533a883Shx147065 sc->sc_flags &= ~IWK_F_FW_INIT; 4166c533a883Shx147065 4167c533a883Shx147065 (void) iwk_preinit(sc); 4168c533a883Shx147065 416943439c96Shx147065 tmp = IWK_READ(sc, CSR_GP_CNTRL); 417043439c96Shx147065 if (!(tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) { 4171b510adaeSfei feng - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "iwk_init(): Radio transmitter is off\n"); 417243439c96Shx147065 goto fail1; 417343439c96Shx147065 } 417443439c96Shx147065 4175c533a883Shx147065 /* init Rx ring */ 4176c533a883Shx147065 iwk_mac_access_enter(sc); 4177c533a883Shx147065 IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 4178c533a883Shx147065 4179c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); 4180c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_BASE_REG, 4181c533a883Shx147065 sc->sc_rxq.dma_desc.cookie.dmac_address >> 8); 4182c533a883Shx147065 4183c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_STTS_WPTR_REG, 4184c533a883Shx147065 ((uint32_t)(sc->sc_dma_sh.cookie.dmac_address + 4185c533a883Shx147065 offsetof(struct iwk_shared, val0)) >> 4)); 4186c533a883Shx147065 4187c533a883Shx147065 IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 4188c533a883Shx147065 FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | 4189c533a883Shx147065 FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | 4190c533a883Shx147065 IWK_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K | 4191c533a883Shx147065 (RX_QUEUE_SIZE_LOG << 4192c533a883Shx147065 FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); 4193c533a883Shx147065 iwk_mac_access_exit(sc); 4194c533a883Shx147065 IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 4195c533a883Shx147065 (RX_QUEUE_SIZE - 1) & ~0x7); 4196c533a883Shx147065 4197c533a883Shx147065 /* init Tx rings */ 4198c533a883Shx147065 iwk_mac_access_enter(sc); 4199c533a883Shx147065 iwk_reg_write(sc, SCD_TXFACT, 0); 4200c533a883Shx147065 4201d62cb7ffShx147065 /* keep warm page */ 4202c533a883Shx147065 iwk_reg_write(sc, IWK_FH_KW_MEM_ADDR_REG, 4203c533a883Shx147065 sc->sc_dma_kw.cookie.dmac_address >> 4); 4204c533a883Shx147065 4205c533a883Shx147065 for (qid = 0; qid < IWK_NUM_QUEUES; qid++) { 4206c533a883Shx147065 IWK_WRITE(sc, FH_MEM_CBBC_QUEUE(qid), 4207c533a883Shx147065 sc->sc_txq[qid].dma_desc.cookie.dmac_address >> 8); 4208c533a883Shx147065 IWK_WRITE(sc, IWK_FH_TCSR_CHNL_TX_CONFIG_REG(qid), 4209c533a883Shx147065 IWK_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | 4210c533a883Shx147065 IWK_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL); 4211c533a883Shx147065 } 4212c533a883Shx147065 iwk_mac_access_exit(sc); 4213c533a883Shx147065 4214c533a883Shx147065 /* clear "radio off" and "disable command" bits */ 4215c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 4216c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, 4217c533a883Shx147065 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); 4218c533a883Shx147065 4219c533a883Shx147065 /* clear any pending interrupts */ 4220c533a883Shx147065 IWK_WRITE(sc, CSR_INT, 0xffffffff); 4221c533a883Shx147065 4222c533a883Shx147065 /* enable interrupts */ 4223c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 4224c533a883Shx147065 4225c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 4226c533a883Shx147065 IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 4227c533a883Shx147065 4228c533a883Shx147065 /* 4229c533a883Shx147065 * backup ucode data part for future use. 4230c533a883Shx147065 */ 4231c533a883Shx147065 (void) memcpy(sc->sc_dma_fw_data_bak.mem_va, 4232c533a883Shx147065 sc->sc_dma_fw_data.mem_va, 4233c533a883Shx147065 sc->sc_dma_fw_data.alength); 4234c533a883Shx147065 4235c533a883Shx147065 for (n = 0; n < 2; n++) { 4236c533a883Shx147065 /* load firmware init segment into NIC */ 4237c533a883Shx147065 err = iwk_load_firmware(sc); 4238c533a883Shx147065 if (err != IWK_SUCCESS) { 4239c533a883Shx147065 cmn_err(CE_WARN, "iwk_init(): " 4240c533a883Shx147065 "failed to setup boot firmware\n"); 4241c533a883Shx147065 continue; 4242c533a883Shx147065 } 4243c533a883Shx147065 4244c533a883Shx147065 /* now press "execute" start running */ 4245c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, 0); 4246c533a883Shx147065 break; 4247c533a883Shx147065 } 4248c533a883Shx147065 if (n == 2) { 4249cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_init(): failed to load firmware\n"); 4250c533a883Shx147065 goto fail1; 4251c533a883Shx147065 } 4252c533a883Shx147065 /* ..and wait at most one second for adapter to initialize */ 4253c533a883Shx147065 clk = ddi_get_lbolt() + drv_usectohz(2000000); 4254c533a883Shx147065 while (!(sc->sc_flags & IWK_F_FW_INIT)) { 4255c533a883Shx147065 if (cv_timedwait(&sc->sc_fw_cv, &sc->sc_glock, clk) < 0) 4256c533a883Shx147065 break; 4257c533a883Shx147065 } 4258c533a883Shx147065 if (!(sc->sc_flags & IWK_F_FW_INIT)) { 4259c533a883Shx147065 cmn_err(CE_WARN, 4260c533a883Shx147065 "iwk_init(): timeout waiting for firmware init\n"); 4261c533a883Shx147065 goto fail1; 4262c533a883Shx147065 } 4263c533a883Shx147065 4264c533a883Shx147065 /* 4265c533a883Shx147065 * at this point, the firmware is loaded OK, then config the hardware 4266c533a883Shx147065 * with the ucode API, including rxon, txpower, etc. 4267c533a883Shx147065 */ 4268c533a883Shx147065 err = iwk_config(sc); 4269c533a883Shx147065 if (err) { 4270c533a883Shx147065 cmn_err(CE_WARN, "iwk_init(): failed to configure device\n"); 4271c533a883Shx147065 goto fail1; 4272c533a883Shx147065 } 4273c533a883Shx147065 4274c533a883Shx147065 /* at this point, hardware may receive beacons :) */ 4275c533a883Shx147065 mutex_exit(&sc->sc_glock); 4276c533a883Shx147065 return (IWK_SUCCESS); 4277c533a883Shx147065 4278c533a883Shx147065 fail1: 4279c533a883Shx147065 err = IWK_FAIL; 4280c533a883Shx147065 mutex_exit(&sc->sc_glock); 4281c533a883Shx147065 return (err); 4282c533a883Shx147065 } 4283c533a883Shx147065 4284c533a883Shx147065 static void 4285c533a883Shx147065 iwk_stop(iwk_sc_t *sc) 4286c533a883Shx147065 { 4287c533a883Shx147065 uint32_t tmp; 4288c533a883Shx147065 int i; 4289c533a883Shx147065 4290d2a61391Spengcheng chen - Sun Microsystems - Beijing China if (!(sc->sc_flags & IWK_F_QUIESCED)) 4291c533a883Shx147065 mutex_enter(&sc->sc_glock); 4292c533a883Shx147065 4293c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); 4294c533a883Shx147065 /* disable interrupts */ 4295c533a883Shx147065 IWK_WRITE(sc, CSR_INT_MASK, 0); 4296c533a883Shx147065 IWK_WRITE(sc, CSR_INT, CSR_INI_SET_MASK); 4297c533a883Shx147065 IWK_WRITE(sc, CSR_FH_INT_STATUS, 0xffffffff); 4298c533a883Shx147065 4299c533a883Shx147065 /* reset all Tx rings */ 4300c533a883Shx147065 for (i = 0; i < IWK_NUM_QUEUES; i++) 4301c533a883Shx147065 iwk_reset_tx_ring(sc, &sc->sc_txq[i]); 4302c533a883Shx147065 4303c533a883Shx147065 /* reset Rx ring */ 4304c533a883Shx147065 iwk_reset_rx_ring(sc); 4305c533a883Shx147065 4306c533a883Shx147065 iwk_mac_access_enter(sc); 4307c533a883Shx147065 iwk_reg_write(sc, ALM_APMG_CLK_DIS, APMG_CLK_REG_VAL_DMA_CLK_RQT); 4308c533a883Shx147065 iwk_mac_access_exit(sc); 4309c533a883Shx147065 4310c533a883Shx147065 DELAY(5); 4311c533a883Shx147065 4312c533a883Shx147065 iwk_stop_master(sc); 4313c533a883Shx147065 4314c533a883Shx147065 sc->sc_tx_timer = 0; 4315f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_SCANNING; 4316f3c4902cSpengcheng chen - Sun Microsystems - Beijing China sc->sc_scan_pending = 0; 4317f3c4902cSpengcheng chen - Sun Microsystems - Beijing China 4318c533a883Shx147065 tmp = IWK_READ(sc, CSR_RESET); 4319c533a883Shx147065 IWK_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_SW_RESET); 4320d2a61391Spengcheng chen - Sun Microsystems - Beijing China 4321d2a61391Spengcheng chen - Sun Microsystems - Beijing China if (!(sc->sc_flags & IWK_F_QUIESCED)) 4322c533a883Shx147065 mutex_exit(&sc->sc_glock); 4323c533a883Shx147065 } 432443439c96Shx147065 432543439c96Shx147065 /* 432643439c96Shx147065 * Naive implementation of the Adaptive Multi Rate Retry algorithm: 432743439c96Shx147065 * "IEEE 802.11 Rate Adaptation: A Practical Approach" 432843439c96Shx147065 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti 432943439c96Shx147065 * INRIA Sophia - Projet Planete 433043439c96Shx147065 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html 433143439c96Shx147065 */ 433243439c96Shx147065 #define is_success(amrr) \ 433343439c96Shx147065 ((amrr)->retrycnt < (amrr)->txcnt / 10) 433443439c96Shx147065 #define is_failure(amrr) \ 433543439c96Shx147065 ((amrr)->retrycnt > (amrr)->txcnt / 3) 433643439c96Shx147065 #define is_enough(amrr) \ 433743439c96Shx147065 ((amrr)->txcnt > 100) 433843439c96Shx147065 #define is_min_rate(in) \ 433943439c96Shx147065 ((in)->in_txrate == 0) 434043439c96Shx147065 #define is_max_rate(in) \ 434143439c96Shx147065 ((in)->in_txrate == (in)->in_rates.ir_nrates - 1) 434243439c96Shx147065 #define increase_rate(in) \ 434343439c96Shx147065 ((in)->in_txrate++) 434443439c96Shx147065 #define decrease_rate(in) \ 434543439c96Shx147065 ((in)->in_txrate--) 434643439c96Shx147065 #define reset_cnt(amrr) \ 434743439c96Shx147065 { (amrr)->txcnt = (amrr)->retrycnt = 0; } 434843439c96Shx147065 434943439c96Shx147065 #define IWK_AMRR_MIN_SUCCESS_THRESHOLD 1 435043439c96Shx147065 #define IWK_AMRR_MAX_SUCCESS_THRESHOLD 15 435143439c96Shx147065 435243439c96Shx147065 static void 435343439c96Shx147065 iwk_amrr_init(iwk_amrr_t *amrr) 435443439c96Shx147065 { 435543439c96Shx147065 amrr->success = 0; 435643439c96Shx147065 amrr->recovery = 0; 435743439c96Shx147065 amrr->txcnt = amrr->retrycnt = 0; 435843439c96Shx147065 amrr->success_threshold = IWK_AMRR_MIN_SUCCESS_THRESHOLD; 435943439c96Shx147065 } 436043439c96Shx147065 436143439c96Shx147065 static void 436243439c96Shx147065 iwk_amrr_timeout(iwk_sc_t *sc) 436343439c96Shx147065 { 436443439c96Shx147065 ieee80211com_t *ic = &sc->sc_ic; 436543439c96Shx147065 436643439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL, "iwk_amrr_timeout() enter\n")); 436743439c96Shx147065 if (ic->ic_opmode == IEEE80211_M_STA) 436843439c96Shx147065 iwk_amrr_ratectl(NULL, ic->ic_bss); 436943439c96Shx147065 else 437043439c96Shx147065 ieee80211_iterate_nodes(&ic->ic_sta, iwk_amrr_ratectl, NULL); 437143439c96Shx147065 sc->sc_clk = ddi_get_lbolt(); 437243439c96Shx147065 } 437343439c96Shx147065 437443439c96Shx147065 /* ARGSUSED */ 437543439c96Shx147065 static void 437643439c96Shx147065 iwk_amrr_ratectl(void *arg, ieee80211_node_t *in) 437743439c96Shx147065 { 437843439c96Shx147065 iwk_amrr_t *amrr = (iwk_amrr_t *)in; 437943439c96Shx147065 int need_change = 0; 438043439c96Shx147065 438143439c96Shx147065 if (is_success(amrr) && is_enough(amrr)) { 438243439c96Shx147065 amrr->success++; 438343439c96Shx147065 if (amrr->success >= amrr->success_threshold && 438443439c96Shx147065 !is_max_rate(in)) { 438543439c96Shx147065 amrr->recovery = 1; 438643439c96Shx147065 amrr->success = 0; 438743439c96Shx147065 increase_rate(in); 438843439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL, 438943439c96Shx147065 "AMRR increasing rate %d (txcnt=%d retrycnt=%d)\n", 439043439c96Shx147065 in->in_txrate, amrr->txcnt, amrr->retrycnt)); 439143439c96Shx147065 need_change = 1; 439243439c96Shx147065 } else { 439343439c96Shx147065 amrr->recovery = 0; 439443439c96Shx147065 } 439543439c96Shx147065 } else if (is_failure(amrr)) { 439643439c96Shx147065 amrr->success = 0; 439743439c96Shx147065 if (!is_min_rate(in)) { 439843439c96Shx147065 if (amrr->recovery) { 439943439c96Shx147065 amrr->success_threshold++; 440043439c96Shx147065 if (amrr->success_threshold > 440143439c96Shx147065 IWK_AMRR_MAX_SUCCESS_THRESHOLD) 440243439c96Shx147065 amrr->success_threshold = 440343439c96Shx147065 IWK_AMRR_MAX_SUCCESS_THRESHOLD; 440443439c96Shx147065 } else { 440543439c96Shx147065 amrr->success_threshold = 440643439c96Shx147065 IWK_AMRR_MIN_SUCCESS_THRESHOLD; 440743439c96Shx147065 } 440843439c96Shx147065 decrease_rate(in); 440943439c96Shx147065 IWK_DBG((IWK_DEBUG_RATECTL, 441043439c96Shx147065 "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)\n", 441143439c96Shx147065 in->in_txrate, amrr->txcnt, amrr->retrycnt)); 441243439c96Shx147065 need_change = 1; 441343439c96Shx147065 } 441443439c96Shx147065 amrr->recovery = 0; /* paper is incorrect */ 441543439c96Shx147065 } 441643439c96Shx147065 441743439c96Shx147065 if (is_enough(amrr) || need_change) 441843439c96Shx147065 reset_cnt(amrr); 441943439c96Shx147065 } 4420cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4421cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4422cdc64593Sxinghua wen - Sun Microsystems - Beijing China * calculate 4965 chipset's kelvin temperature according to 4423cdc64593Sxinghua wen - Sun Microsystems - Beijing China * the data of init alive and satistics notification. 4424cdc64593Sxinghua wen - Sun Microsystems - Beijing China * The details is described in iwk_calibration.h file 4425cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4426cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_curr_tempera(iwk_sc_t *sc) 4427cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4428cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t tempera; 4429cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t r1, r2, r3; 4430cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t r4_u; 4431cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t r4_s; 4432cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4433cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_is_fat_channel(sc)) { 4434b510adaeSfei feng - Sun Microsystems - Beijing China r1 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r1[1]); 4435b510adaeSfei feng - Sun Microsystems - Beijing China r2 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r2[1]); 4436b510adaeSfei feng - Sun Microsystems - Beijing China r3 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r3[1]); 4437b510adaeSfei feng - Sun Microsystems - Beijing China r4_u = LE_32(sc->sc_card_alive_init.therm_r4[1]); 4438cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4439b510adaeSfei feng - Sun Microsystems - Beijing China r1 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r1[0]); 4440b510adaeSfei feng - Sun Microsystems - Beijing China r2 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r2[0]); 4441b510adaeSfei feng - Sun Microsystems - Beijing China r3 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r3[0]); 4442b510adaeSfei feng - Sun Microsystems - Beijing China r4_u = LE_32(sc->sc_card_alive_init.therm_r4[0]); 4443cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4444cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4445cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_STATISTICS) { 4446b510adaeSfei feng - Sun Microsystems - Beijing China r4_s = (int32_t)(LE_32(sc->sc_statistics.general.temperature) << 4447cdc64593Sxinghua wen - Sun Microsystems - Beijing China (31-23)) >> (31-23); 4448cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4449cdc64593Sxinghua wen - Sun Microsystems - Beijing China r4_s = (int32_t)(r4_u << (31-23)) >> (31-23); 4450cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4451cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4452cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION, "temperature R[1-4]: %d %d %d %d\n", 4453cdc64593Sxinghua wen - Sun Microsystems - Beijing China r1, r2, r3, r4_s)); 4454cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4455cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (r3 == r1) { 4456cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_curr_tempera(): " 4457cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to calculate temperature" 4458cdc64593Sxinghua wen - Sun Microsystems - Beijing China "because r3 = r1\n"); 4459cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 4460cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4461cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4462cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera = TEMPERATURE_CALIB_A_VAL * (r4_s - r2); 4463cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera /= (r3 - r1); 4464cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera = (tempera*97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET; 4465cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4466cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION, "calculated temperature: %dK, %dC\n", 4467cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera, KELVIN_TO_CELSIUS(tempera))); 4468cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4469cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (tempera); 4470cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4471cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4472cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Determine whether 4965 is using 2.4 GHz band */ 4473cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_24G_band(iwk_sc_t *sc) 4474cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4475b510adaeSfei feng - Sun Microsystems - Beijing China return (LE_32(sc->sc_config.flags) & RXON_FLG_BAND_24G_MSK); 4476cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4477cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4478cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Determine whether 4965 is using fat channel */ 4479cdc64593Sxinghua wen - Sun Microsystems - Beijing China static inline int iwk_is_fat_channel(iwk_sc_t *sc) 4480cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4481b510adaeSfei feng - Sun Microsystems - Beijing China return ((LE_32(sc->sc_config.flags) & 4482b510adaeSfei feng - Sun Microsystems - Beijing China RXON_FLG_CHANNEL_MODE_PURE_40_MSK) || 4483b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(sc->sc_config.flags) & RXON_FLG_CHANNEL_MODE_MIXED_MSK)); 4484cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4485cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4486cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4487cdc64593Sxinghua wen - Sun Microsystems - Beijing China * In MIMO mode, determine which group 4965's current channel belong to. 4488cdc64593Sxinghua wen - Sun Microsystems - Beijing China * For more infomation about "channel group", 4489cdc64593Sxinghua wen - Sun Microsystems - Beijing China * please refer to iwk_calibration.h file 4490cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4491cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_grp(uint16_t channel) 4492cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4493cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR5_FCH && 4494cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR5_LCH) { 4495cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_5); 4496cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4497cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4498cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR1_FCH && 4499cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR1_LCH) { 4500cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_1); 4501cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4502cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4503cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR2_FCH && 4504cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR2_LCH) { 4505cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_2); 4506cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4507cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4508cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR3_FCH && 4509cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR3_LCH) { 4510cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_3); 4511cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4512cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4513cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (channel >= CALIB_IWK_TX_ATTEN_GR4_FCH && 4514cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel <= CALIB_IWK_TX_ATTEN_GR4_LCH) { 4515cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (CALIB_CH_GROUP_4); 4516cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4517cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4518cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_grp(): " 4519cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't find txpower group for channel %d.\n", channel); 4520cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4521cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 4522cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4523cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4524cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 2.4 GHz */ 4525cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_1[14] = { 4526cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 4527cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4528cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4529cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5.2 GHz bands */ 4530cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_2[13] = { 4531cdc64593Sxinghua wen - Sun Microsystems - Beijing China 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 4532cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4533cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4534cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_3[12] = { 4535cdc64593Sxinghua wen - Sun Microsystems - Beijing China 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 4536cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4537cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4538cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_4[11] = { 4539cdc64593Sxinghua wen - Sun Microsystems - Beijing China 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 4540cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4541cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4542cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_5[6] = { 4543cdc64593Sxinghua wen - Sun Microsystems - Beijing China 145, 149, 153, 157, 161, 165 4544cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4545cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4546cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_6[7] = { 4547cdc64593Sxinghua wen - Sun Microsystems - Beijing China 1, 2, 3, 4, 5, 6, 7 4548cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4549cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4550cdc64593Sxinghua wen - Sun Microsystems - Beijing China static uint16_t iwk_eep_band_7[11] = { 4551cdc64593Sxinghua wen - Sun Microsystems - Beijing China 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 4552cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4553cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4554cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Get regulatory data from eeprom for a given channel */ 4555cdc64593Sxinghua wen - Sun Microsystems - Beijing China static struct iwk_eep_channel *iwk_get_eep_channel(iwk_sc_t *sc, 4556cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel, 4557cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_24G, int is_fat, int is_hi_chan) 4558cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4559cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t i; 4560cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t chan; 4561cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4562cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_fat) { /* 11n mode */ 4563cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4564cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_hi_chan) { 4565cdc64593Sxinghua wen - Sun Microsystems - Beijing China chan = channel - 4; 4566cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4567cdc64593Sxinghua wen - Sun Microsystems - Beijing China chan = channel; 4568cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4569cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4570cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 7; i++) { 4571cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_6[i] == chan) { 4572cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_24_channels[i]); 4573cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4574cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4575cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 11; i++) { 4576cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_7[i] == chan) { 4577cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_52_channels[i]); 4578cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4579cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4580cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (is_24G) { /* 2.4 GHz band */ 4581cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 14; i++) { 4582cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_1[i] == channel) { 4583cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_1_channels[i]); 4584cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4585cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4586cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { /* 5 GHz band */ 4587cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 13; i++) { 4588cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_2[i] == channel) { 4589cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_2_channels[i]); 4590cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4591cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4592cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 12; i++) { 4593cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_3[i] == channel) { 4594cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_3_channels[i]); 4595cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4596cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4597cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 11; i++) { 4598cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_4[i] == channel) { 4599cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_4_channels[i]); 4600cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4601cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4602cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 6; i++) { 4603cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_eep_band_5[i] == channel) { 4604cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (&sc->sc_eep_map.band_5_channels[i]); 4605cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4606cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4607cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4608cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4609cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (NULL); 4610cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4611cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4612cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4613cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Determine which subband a given channel belongs 4614cdc64593Sxinghua wen - Sun Microsystems - Beijing China * to in 2.4 GHz or 5 GHz band 4615cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4616cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_band_number(iwk_sc_t *sc, uint16_t channel) 4617cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4618cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t b_n = -1; 4619cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4620cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (b_n = 0; b_n < EEP_TX_POWER_BANDS; b_n++) { 4621cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (0 == sc->sc_eep_map.calib_info.band_info_tbl[b_n].ch_from) { 4622cdc64593Sxinghua wen - Sun Microsystems - Beijing China continue; 4623cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4624cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4625cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((channel >= 4626cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint16_t)sc->sc_eep_map.calib_info. 4627cdc64593Sxinghua wen - Sun Microsystems - Beijing China band_info_tbl[b_n].ch_from) && 4628cdc64593Sxinghua wen - Sun Microsystems - Beijing China (channel <= 4629cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint16_t)sc->sc_eep_map.calib_info. 4630cdc64593Sxinghua wen - Sun Microsystems - Beijing China band_info_tbl[b_n].ch_to)) { 4631cdc64593Sxinghua wen - Sun Microsystems - Beijing China break; 4632cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4633cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4634cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4635cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (b_n); 4636cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4637cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4638cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make a special division for interpolation operation */ 4639cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_division(int32_t num, int32_t denom, int32_t *res) 4640cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4641cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t sign = 1; 4642cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4643cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (num < 0) { 4644cdc64593Sxinghua wen - Sun Microsystems - Beijing China sign = -sign; 4645cdc64593Sxinghua wen - Sun Microsystems - Beijing China num = -num; 4646cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4647cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4648cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (denom < 0) { 4649cdc64593Sxinghua wen - Sun Microsystems - Beijing China sign = -sign; 4650cdc64593Sxinghua wen - Sun Microsystems - Beijing China denom = -denom; 4651cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4652cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4653cdc64593Sxinghua wen - Sun Microsystems - Beijing China *res = ((num*2 + denom) / (denom*2)) * sign; 4654cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4655cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 4656cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4657cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4658cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make interpolation operation */ 4659cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_interpolate_value(int32_t x, int32_t x1, int32_t y1, 4660cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t x2, int32_t y2) 4661cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4662cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t val; 4663cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4664cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (x2 == x1) { 4665cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (y1); 4666cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4667cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_division((x2-x)*(y1-y2), (x2-x1), &val); 4668cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (val + y2); 4669cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4670cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4671cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4672cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Get interpolation measurement data of a given channel for all chains. */ 4673cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_channel_interpolate(iwk_sc_t *sc, uint16_t channel, 4674cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_channel_info *chan_info) 4675cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4676cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t ban_n; 4677cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t ch1_n, ch2_n; 4678cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t c, m; 4679cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_measure *m1_p, *m2_p, *m_p; 4680cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4681cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine subband number */ 4682cdc64593Sxinghua wen - Sun Microsystems - Beijing China ban_n = iwk_band_number(sc, channel); 4683cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (ban_n >= EEP_TX_POWER_BANDS) { 4684cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 4685cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4686cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4687cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n = 4688cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint32_t)sc->sc_eep_map.calib_info.band_info_tbl[ban_n].ch1.ch_num; 4689cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n = 4690cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint32_t)sc->sc_eep_map.calib_info.band_info_tbl[ban_n].ch2.ch_num; 4691cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4692cdc64593Sxinghua wen - Sun Microsystems - Beijing China chan_info->ch_num = (uint8_t)channel; /* given channel number */ 4693cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4694cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4695cdc64593Sxinghua wen - Sun Microsystems - Beijing China * go through all chains on chipset 4696cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4697cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (c = 0; c < EEP_TX_POWER_TX_CHAINS; c++) { 4698cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4699cdc64593Sxinghua wen - Sun Microsystems - Beijing China * go through all factory measurements 4700cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4701cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (m = 0; m < EEP_TX_POWER_MEASUREMENTS; m++) { 4702cdc64593Sxinghua wen - Sun Microsystems - Beijing China m1_p = 4703cdc64593Sxinghua wen - Sun Microsystems - Beijing China &(sc->sc_eep_map.calib_info. 4704cdc64593Sxinghua wen - Sun Microsystems - Beijing China band_info_tbl[ban_n].ch1.measure[c][m]); 4705cdc64593Sxinghua wen - Sun Microsystems - Beijing China m2_p = 4706cdc64593Sxinghua wen - Sun Microsystems - Beijing China &(sc->sc_eep_map.calib_info.band_info_tbl[ban_n]. 4707cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2.measure[c][m]); 4708cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p = &(chan_info->measure[c][m]); 4709cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4710cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4711cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make interpolation to get actual 4712cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Tx power for given channel 4713cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4714cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->actual_pow = iwk_interpolate_value(channel, 4715cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n, m1_p->actual_pow, 4716cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->actual_pow); 4717cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4718cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make interpolation to get index into gain table */ 4719cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->gain_idx = iwk_interpolate_value(channel, 4720cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n, m1_p->gain_idx, 4721cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->gain_idx); 4722cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4723cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make interpolation to get chipset temperature */ 4724cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->temperature = iwk_interpolate_value(channel, 4725cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch1_n, m1_p->temperature, 4726cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->temperature); 4727cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4728cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4729cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make interpolation to get power 4730cdc64593Sxinghua wen - Sun Microsystems - Beijing China * amp detector level 4731cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4732cdc64593Sxinghua wen - Sun Microsystems - Beijing China m_p->pa_det = iwk_interpolate_value(channel, ch1_n, 4733cdc64593Sxinghua wen - Sun Microsystems - Beijing China m1_p->pa_det, 4734cdc64593Sxinghua wen - Sun Microsystems - Beijing China ch2_n, m2_p->pa_det); 4735cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4736cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4737cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4738cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 4739cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4740cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4741cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4742cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Calculate voltage compensation for Tx power. For more infomation, 4743cdc64593Sxinghua wen - Sun Microsystems - Beijing China * please refer to iwk_calibration.h file 4744cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4745cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_voltage_compensation(int32_t eep_voltage, 4746cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t curr_voltage) 4747cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4748cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t vol_comp = 0; 4749cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4750cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((TX_POWER_IWK_ILLEGAL_VOLTAGE == eep_voltage) || 4751cdc64593Sxinghua wen - Sun Microsystems - Beijing China (TX_POWER_IWK_ILLEGAL_VOLTAGE == curr_voltage)) { 4752cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (vol_comp); 4753cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4754cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4755cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_division(curr_voltage-eep_voltage, 4756cdc64593Sxinghua wen - Sun Microsystems - Beijing China TX_POWER_IWK_VOLTAGE_CODES_PER_03V, &vol_comp); 4757cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4758cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (curr_voltage > eep_voltage) { 4759cdc64593Sxinghua wen - Sun Microsystems - Beijing China vol_comp *= 2; 4760cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4761cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((vol_comp < -2) || (vol_comp > 2)) { 4762cdc64593Sxinghua wen - Sun Microsystems - Beijing China vol_comp = 0; 4763cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4764cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4765cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (vol_comp); 4766cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4767cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4768cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4769cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Thermal compensation values for txpower for various frequency ranges ... 4770cdc64593Sxinghua wen - Sun Microsystems - Beijing China * ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust 4771cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4772cdc64593Sxinghua wen - Sun Microsystems - Beijing China static struct iwk_txpower_tempera_comp { 4773cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_a; 4774cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_a_denom; 4775cdc64593Sxinghua wen - Sun Microsystems - Beijing China } txpower_tempera_comp_table[CALIB_CH_GROUP_MAX] = { 4776cdc64593Sxinghua wen - Sun Microsystems - Beijing China {9, 2}, /* group 0 5.2, ch 34-43 */ 4777cdc64593Sxinghua wen - Sun Microsystems - Beijing China {4, 1}, /* group 1 5.2, ch 44-70 */ 4778cdc64593Sxinghua wen - Sun Microsystems - Beijing China {4, 1}, /* group 2 5.2, ch 71-124 */ 4779cdc64593Sxinghua wen - Sun Microsystems - Beijing China {4, 1}, /* group 3 5.2, ch 125-200 */ 4780cdc64593Sxinghua wen - Sun Microsystems - Beijing China {3, 1} /* group 4 2.4, ch all */ 4781cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4782cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4783cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4784cdc64593Sxinghua wen - Sun Microsystems - Beijing China * bit-rate-dependent table to prevent Tx distortion, in half-dB units, 4785cdc64593Sxinghua wen - Sun Microsystems - Beijing China * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. 4786cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4787cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t back_off_table[] = { 4788cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */ 4789cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */ 4790cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */ 4791cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */ 4792cdc64593Sxinghua wen - Sun Microsystems - Beijing China 10 /* CCK */ 4793cdc64593Sxinghua wen - Sun Microsystems - Beijing China }; 4794cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4795cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine minimum Tx power index in gain table */ 4796cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int32_t iwk_min_power_index(int32_t rate_pow_idx, int32_t is_24G) 4797cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4798cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((!is_24G) && ((rate_pow_idx & 7) <= 4)) { 4799cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (MIN_TX_GAIN_INDEX_52GHZ_EXT); 4800cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4801cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4802cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (MIN_TX_GAIN_INDEX); 4803cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4804cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4805cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4806cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Determine DSP and radio gain according to temperature and other factors. 4807cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This function is the majority of Tx power calibration 4808cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4809cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_txpower_table_cmd_init(iwk_sc_t *sc, 4810cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_tx_power_db *tp_db) 4811cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 4812cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_24G, is_fat, is_high_chan, is_mimo; 4813cdc64593Sxinghua wen - Sun Microsystems - Beijing China int c, r; 4814cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t target_power; 4815cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t tx_grp = CALIB_CH_GROUP_MAX; 4816cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel; 4817cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint8_t saturation_power; 4818cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t regu_power; 4819cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t curr_regu_power; 4820cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_channel *eep_chan_p; 4821cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_channel_info eep_chan_calib; 4822cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t eep_voltage, init_voltage; 4823cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t voltage_compensation; 4824cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t temperature; 4825cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_num; 4826cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t degrees_per_05db_denom; 4827cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_eep_calib_measure *measure_p; 4828cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t interpo_temp; 4829cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t power_limit; 4830cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t atten_value; 4831cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t tempera_comp[2]; 4832cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t interpo_gain_idx[2]; 4833cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t interpo_actual_pow[2]; 4834cdc64593Sxinghua wen - Sun Microsystems - Beijing China union iwk_tx_power_dual_stream txpower_gains; 4835cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t txpower_gains_idx; 4836cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4837b510adaeSfei feng - Sun Microsystems - Beijing China channel = LE_16(sc->sc_config.chan); 4838cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4839cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 2.4 GHz or 5 GHz band */ 4840cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_24G = iwk_is_24G_band(sc); 4841cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4842cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* fat channel or not */ 4843cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_fat = iwk_is_fat_channel(sc); 4844cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4845cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4846cdc64593Sxinghua wen - Sun Microsystems - Beijing China * using low half channel number or high half channel number 4847cdc64593Sxinghua wen - Sun Microsystems - Beijing China * identify fat channel 4848cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4849b510adaeSfei feng - Sun Microsystems - Beijing China if (is_fat && (LE_32(sc->sc_config.flags) & 4850cdc64593Sxinghua wen - Sun Microsystems - Beijing China RXON_FLG_CONTROL_CHANNEL_LOC_HIGH_MSK)) { 4851cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_high_chan = 1; 4852cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4853cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4854cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((channel > 0) && (channel < 200)) { 4855cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* get regulatory channel data from eeprom */ 4856cdc64593Sxinghua wen - Sun Microsystems - Beijing China eep_chan_p = iwk_get_eep_channel(sc, channel, is_24G, 4857cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_fat, is_high_chan); 4858cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (NULL == eep_chan_p) { 4859cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, 4860cdc64593Sxinghua wen - Sun Microsystems - Beijing China "iwk_txpower_table_cmd_init(): " 4861cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't get channel infomation\n"); 4862cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 4863cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4864cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4865cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): " 4866cdc64593Sxinghua wen - Sun Microsystems - Beijing China "channel(%d) isn't in proper range\n", 4867cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel); 4868cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 4869cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4870cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4871cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* initial value of Tx power */ 4872cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_user_txpower = (int32_t)eep_chan_p->max_power_avg; 4873cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_user_txpower < IWK_TX_POWER_TARGET_POWER_MIN) { 4874cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): " 4875cdc64593Sxinghua wen - Sun Microsystems - Beijing China "user TX power is too weak\n"); 4876cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 4877cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (sc->sc_user_txpower > IWK_TX_POWER_TARGET_POWER_MAX) { 4878cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): " 4879cdc64593Sxinghua wen - Sun Microsystems - Beijing China "user TX power is too strong\n"); 4880cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 4881cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4882cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4883cdc64593Sxinghua wen - Sun Microsystems - Beijing China target_power = 2 * sc->sc_user_txpower; 4884cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4885cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine which group current channel belongs to */ 4886cdc64593Sxinghua wen - Sun Microsystems - Beijing China tx_grp = iwk_txpower_grp(channel); 4887cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (tx_grp < 0) { 4888cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (tx_grp); 4889cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4890cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4891cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4892cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_fat) { 4893cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_high_chan) { 4894cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel -= 2; 4895cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4896cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel += 2; 4897cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4898cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4899cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4900cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine saturation power */ 4901cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_24G) { 4902cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power = 4903cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_eep_map.calib_info.saturation_power24; 4904cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4905cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power = 4906cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_eep_map.calib_info.saturation_power52; 4907cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4908cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4909cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (saturation_power < IWK_TX_POWER_SATURATION_MIN || 4910cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power > IWK_TX_POWER_SATURATION_MAX) { 4911cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_24G) { 4912cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power = IWK_TX_POWER_DEFAULT_SATURATION_24; 4913cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4914cdc64593Sxinghua wen - Sun Microsystems - Beijing China saturation_power = IWK_TX_POWER_DEFAULT_SATURATION_52; 4915cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4916cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4917cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4918cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine regulatory power */ 4919cdc64593Sxinghua wen - Sun Microsystems - Beijing China regu_power = (int32_t)eep_chan_p->max_power_avg * 2; 4920cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((regu_power < IWK_TX_POWER_REGULATORY_MIN) || 4921cdc64593Sxinghua wen - Sun Microsystems - Beijing China (regu_power > IWK_TX_POWER_REGULATORY_MAX)) { 4922cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_24G) { 4923cdc64593Sxinghua wen - Sun Microsystems - Beijing China regu_power = IWK_TX_POWER_DEFAULT_REGULATORY_24; 4924cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4925cdc64593Sxinghua wen - Sun Microsystems - Beijing China regu_power = IWK_TX_POWER_DEFAULT_REGULATORY_52; 4926cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4927cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4928cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4929cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4930cdc64593Sxinghua wen - Sun Microsystems - Beijing China * get measurement data for current channel 4931cdc64593Sxinghua wen - Sun Microsystems - Beijing China * suach as temperature,index to gain table,actual Tx power 4932cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4933cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_channel_interpolate(sc, channel, &eep_chan_calib); 4934cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4935b510adaeSfei feng - Sun Microsystems - Beijing China eep_voltage = (int32_t)LE_16(sc->sc_eep_map.calib_info.voltage); 4936b510adaeSfei feng - Sun Microsystems - Beijing China init_voltage = (int32_t)LE_32(sc->sc_card_alive_init.voltage); 4937cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4938cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calculate voltage compensation to Tx power */ 4939cdc64593Sxinghua wen - Sun Microsystems - Beijing China voltage_compensation = 4940cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_voltage_compensation(eep_voltage, init_voltage); 4941cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4942cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_tempera >= IWK_TX_POWER_TEMPERATURE_MIN) { 4943cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = sc->sc_tempera; 4944cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4945cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = IWK_TX_POWER_TEMPERATURE_MIN; 4946cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4947cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_tempera <= IWK_TX_POWER_TEMPERATURE_MAX) { 4948cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = sc->sc_tempera; 4949cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4950cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = IWK_TX_POWER_TEMPERATURE_MAX; 4951cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4952cdc64593Sxinghua wen - Sun Microsystems - Beijing China temperature = KELVIN_TO_CELSIUS(temperature); 4953cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4954cdc64593Sxinghua wen - Sun Microsystems - Beijing China degrees_per_05db_num = 4955cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_tempera_comp_table[tx_grp].degrees_per_05db_a; 4956cdc64593Sxinghua wen - Sun Microsystems - Beijing China degrees_per_05db_denom = 4957cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_tempera_comp_table[tx_grp].degrees_per_05db_a_denom; 4958cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4959cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (c = 0; c < 2; c++) { /* go through all chains */ 4960cdc64593Sxinghua wen - Sun Microsystems - Beijing China measure_p = &eep_chan_calib.measure[c][1]; 4961cdc64593Sxinghua wen - Sun Microsystems - Beijing China interpo_temp = measure_p->temperature; 4962cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4963cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine temperature compensation to Tx power */ 4964cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_division( 4965cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temperature-interpo_temp)*degrees_per_05db_denom, 4966cdc64593Sxinghua wen - Sun Microsystems - Beijing China degrees_per_05db_num, &tempera_comp[c]); 4967cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4968cdc64593Sxinghua wen - Sun Microsystems - Beijing China interpo_gain_idx[c] = measure_p->gain_idx; 4969cdc64593Sxinghua wen - Sun Microsystems - Beijing China interpo_actual_pow[c] = measure_p->actual_pow; 4970cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4971cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4972cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 4973cdc64593Sxinghua wen - Sun Microsystems - Beijing China * go through all rate entries in Tx power table 4974cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 4975cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (r = 0; r < POWER_TABLE_NUM_ENTRIES; r++) { 4976cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (r & 0x8) { 4977cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* need to lower regulatory power for MIMO mode */ 4978cdc64593Sxinghua wen - Sun Microsystems - Beijing China curr_regu_power = regu_power - 4979cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_TX_POWER_MIMO_REGULATORY_COMPENSATION; 4980cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_mimo = 1; 4981cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 4982cdc64593Sxinghua wen - Sun Microsystems - Beijing China curr_regu_power = regu_power; 4983cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_mimo = 0; 4984cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4985cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4986cdc64593Sxinghua wen - Sun Microsystems - Beijing China power_limit = saturation_power - back_off_table[r]; 4987cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (power_limit > curr_regu_power) { 4988cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* final Tx power limit */ 4989cdc64593Sxinghua wen - Sun Microsystems - Beijing China power_limit = curr_regu_power; 4990cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4991cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4992cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (target_power > power_limit) { 4993cdc64593Sxinghua wen - Sun Microsystems - Beijing China target_power = power_limit; /* final target Tx power */ 4994cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 4995cdc64593Sxinghua wen - Sun Microsystems - Beijing China 4996cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (c = 0; c < 2; c++) { /* go through all Tx chains */ 4997cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (is_mimo) { 4998cdc64593Sxinghua wen - Sun Microsystems - Beijing China atten_value = 4999b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(sc->sc_card_alive_init. 5000b510adaeSfei feng - Sun Microsystems - Beijing China tx_atten[tx_grp][c]); 5001cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5002cdc64593Sxinghua wen - Sun Microsystems - Beijing China atten_value = 0; 5003cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5004cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5005cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5006cdc64593Sxinghua wen - Sun Microsystems - Beijing China * calculate index in gain table 5007cdc64593Sxinghua wen - Sun Microsystems - Beijing China * this step is very important 5008cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5009cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx = interpo_gain_idx[c] - 5010cdc64593Sxinghua wen - Sun Microsystems - Beijing China (target_power - interpo_actual_pow[c]) - 5011cdc64593Sxinghua wen - Sun Microsystems - Beijing China tempera_comp[c] - voltage_compensation + 5012cdc64593Sxinghua wen - Sun Microsystems - Beijing China atten_value; 5013cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5014cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (txpower_gains_idx < 5015cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_min_power_index(r, is_24G)) { 5016cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx = 5017cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_min_power_index(r, is_24G); 5018cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5019cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5020cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!is_24G) { 5021cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5022cdc64593Sxinghua wen - Sun Microsystems - Beijing China * support negative index for 5 GHz 5023cdc64593Sxinghua wen - Sun Microsystems - Beijing China * band 5024cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5025cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx += 9; 5026cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5027cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5028cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (POWER_TABLE_CCK_ENTRY == r) { 5029cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* for CCK mode, make necessary attenuaton */ 5030cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx += 5031cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_TX_POWER_CCK_COMPENSATION_C_STEP; 5032cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5033cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5034cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (txpower_gains_idx > 107) { 5035cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx = 107; 5036cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (txpower_gains_idx < 0) { 5037cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains_idx = 0; 5038cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5039cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5040cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* search DSP and radio gains in gain table */ 5041cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains.s.radio_tx_gain[c] = 5042cdc64593Sxinghua wen - Sun Microsystems - Beijing China gains_table[is_24G][txpower_gains_idx].radio; 5043cdc64593Sxinghua wen - Sun Microsystems - Beijing China txpower_gains.s.dsp_predis_atten[c] = 5044cdc64593Sxinghua wen - Sun Microsystems - Beijing China gains_table[is_24G][txpower_gains_idx].dsp; 5045cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5046cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION, 5047cdc64593Sxinghua wen - Sun Microsystems - Beijing China "rate_index: %d, " 5048cdc64593Sxinghua wen - Sun Microsystems - Beijing China "gain_index %d, c: %d,is_mimo: %d\n", 5049cdc64593Sxinghua wen - Sun Microsystems - Beijing China r, txpower_gains_idx, c, is_mimo)); 5050cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5051cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5052cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* initialize Tx power table */ 5053cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (r < POWER_TABLE_NUM_HT_OFDM_ENTRIES) { 5054b510adaeSfei feng - Sun Microsystems - Beijing China tp_db->ht_ofdm_power[r].dw = LE_32(txpower_gains.dw); 5055cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5056b510adaeSfei feng - Sun Microsystems - Beijing China tp_db->legacy_cck_power.dw = LE_32(txpower_gains.dw); 5057cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5058cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5059cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5060cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5061cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5062cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5063cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5064cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Tx power calibration to adjust Tx power. 5065cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This is completed by sending out Tx power table command. 5066cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5067cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_tx_power_calibration(iwk_sc_t *sc) 5068cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5069cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_tx_power_table_cmd_t cmd; 5070cdc64593Sxinghua wen - Sun Microsystems - Beijing China int rv; 5071cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5072cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (sc->sc_flags & IWK_F_SCANNING) { 5073cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5074cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5075cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5076cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* necessary initialization to Tx power table command */ 5077cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.band = (uint8_t)iwk_is_24G_band(sc); 5078cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.channel = sc->sc_config.chan; 5079cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.channel_normal_width = 0; 5080cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5081cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* initialize Tx power table */ 5082cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_txpower_table_cmd_init(sc, &cmd.tx_power); 5083cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5084cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_NOTE, "rv= %d\n", rv); 5085cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5086cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5087cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5088cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* send out Tx power table command */ 5089cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &cmd, sizeof (cmd), 1); 5090cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5091cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5092cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5093cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5094cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record current temperature */ 5095cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_last_tempera = sc->sc_tempera; 5096cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5097cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5098cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5099cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5100cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* This function is the handler of statistics notification from uCode */ 5101cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_statistics_notify(iwk_sc_t *sc, iwk_rx_desc_t *desc) 5102cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5103cdc64593Sxinghua wen - Sun Microsystems - Beijing China int is_diff; 5104cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_notif_statistics *statistics_p = 5105cdc64593Sxinghua wen - Sun Microsystems - Beijing China (struct iwk_notif_statistics *)(desc + 1); 5106cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5107cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 5108cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5109cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_diff = (sc->sc_statistics.general.temperature != 5110cdc64593Sxinghua wen - Sun Microsystems - Beijing China statistics_p->general.temperature) || 5111b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(sc->sc_statistics.flag) & 5112b510adaeSfei feng - Sun Microsystems - Beijing China STATISTICS_REPLY_FLG_FAT_MODE_MSK) != 5113b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(statistics_p->flag) & STATISTICS_REPLY_FLG_FAT_MODE_MSK); 5114cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5115cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* update statistics data */ 5116cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memcpy(&sc->sc_statistics, statistics_p, 5117cdc64593Sxinghua wen - Sun Microsystems - Beijing China sizeof (struct iwk_notif_statistics)); 5118cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5119cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_flags |= IWK_F_STATISTICS; 5120cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5121cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(sc->sc_flags & IWK_F_SCANNING)) { 5122cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Receiver gain balance calibration */ 5123cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_rxgain_diff(sc); 5124cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5125cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Receiver sensitivity calibration */ 5126cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_rx_sens(sc); 5127cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5128cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5129cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5130cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!is_diff) { 5131cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 5132cdc64593Sxinghua wen - Sun Microsystems - Beijing China return; 5133cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5134cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5135cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calibration current temperature of 4965 chipset */ 5136cdc64593Sxinghua wen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc); 5137cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5138cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* distinct temperature change will trigger Tx power calibration */ 5139cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (((sc->sc_tempera - sc->sc_last_tempera) >= 3) || 5140cdc64593Sxinghua wen - Sun Microsystems - Beijing China ((sc->sc_last_tempera - sc->sc_tempera) >= 3)) { 5141cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Tx power calibration */ 5142cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) iwk_tx_power_calibration(sc); 5143cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5144cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5145cdc64593Sxinghua wen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 5146cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5147cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5148cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Determine this station is in associated state or not */ 5149cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_is_associated(iwk_sc_t *sc) 5150cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5151b510adaeSfei feng - Sun Microsystems - Beijing China return (LE_32(sc->sc_config.filter_flags) & RXON_FILTER_ASSOC_MSK); 5152cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5153cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5154cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make necessary preparation for Receiver gain balance calibration */ 5155cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff_init(iwk_sc_t *sc) 5156cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5157cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i, rv; 5158cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_calibration_cmd cmd; 5159cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_gain_diff *gain_diff_p; 5160cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5161cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p = &sc->sc_rxgain_diff; 5162cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5163cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(gain_diff_p, 0, sizeof (struct iwk_rx_gain_diff)); 5164cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (struct iwk_calibration_cmd)); 5165cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5166cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) { 5167cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] = CHAIN_GAIN_DIFF_INIT_VAL; 5168cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5169cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5170cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (iwk_is_associated(sc)) { 5171cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD; 5172cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_a = 0; 5173cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_b = 0; 5174cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_c = 0; 5175cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5176cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* assume the gains of every Rx chains is balanceable */ 5177cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, REPLY_PHY_CALIBRATION_CMD, &cmd, 5178cdc64593Sxinghua wen - Sun Microsystems - Beijing China sizeof (cmd), 1); 5179cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5180cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5181cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5182cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5183cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->state = IWK_GAIN_DIFF_ACCUMULATE; 5184cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5185cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5186cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5187cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5188cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5189cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5190cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Receiver gain balance to balance Rx gain between Rx chains 5191cdc64593Sxinghua wen - Sun Microsystems - Beijing China * and determine which chain is disconnected 5192cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5193cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rxgain_diff(iwk_sc_t *sc) 5194cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5195cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i, is_24G, rv; 5196cdc64593Sxinghua wen - Sun Microsystems - Beijing China int max_beacon_chain_n; 5197cdc64593Sxinghua wen - Sun Microsystems - Beijing China int min_noise_chain_n; 5198cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t channel_n; 5199cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t beacon_diff; 5200cdc64593Sxinghua wen - Sun Microsystems - Beijing China int32_t noise_diff; 5201cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t noise_chain_a, noise_chain_b, noise_chain_c; 5202cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t beacon_chain_a, beacon_chain_b, beacon_chain_c; 5203cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_calibration_cmd cmd; 5204cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t beacon_aver[RX_CHAINS_NUM] = {0xFFFFFFFF}; 5205cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t noise_aver[RX_CHAINS_NUM] = {0xFFFFFFFF}; 5206cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct statistics_rx_non_phy *rx_general_p = 5207cdc64593Sxinghua wen - Sun Microsystems - Beijing China &sc->sc_statistics.rx.general; 5208cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_gain_diff *gain_diff_p = &sc->sc_rxgain_diff; 5209cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5210cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (INTERFERENCE_DATA_AVAILABLE != 5211b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(rx_general_p->interference_data_flag)) { 5212cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5213cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5214cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5215cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (IWK_GAIN_DIFF_ACCUMULATE != gain_diff_p->state) { 5216cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5217cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5218cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5219cdc64593Sxinghua wen - Sun Microsystems - Beijing China is_24G = iwk_is_24G_band(sc); 5220cdc64593Sxinghua wen - Sun Microsystems - Beijing China channel_n = sc->sc_config.chan; /* channel number */ 5221cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5222b510adaeSfei feng - Sun Microsystems - Beijing China if ((channel_n != (LE_32(sc->sc_statistics.flag) >> 16)) || 5223cdc64593Sxinghua wen - Sun Microsystems - Beijing China ((STATISTICS_REPLY_FLG_BAND_24G_MSK == 5224b510adaeSfei feng - Sun Microsystems - Beijing China (LE_32(sc->sc_statistics.flag) & 5225b510adaeSfei feng - Sun Microsystems - Beijing China STATISTICS_REPLY_FLG_BAND_24G_MSK)) && 5226cdc64593Sxinghua wen - Sun Microsystems - Beijing China !is_24G)) { 5227cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5228cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5229cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5230cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Rx chain's noise strength from statistics notification */ 5231b510adaeSfei feng - Sun Microsystems - Beijing China noise_chain_a = LE_32(rx_general_p->beacon_silence_rssi_a) & 0xFF; 5232b510adaeSfei feng - Sun Microsystems - Beijing China noise_chain_b = LE_32(rx_general_p->beacon_silence_rssi_b) & 0xFF; 5233b510adaeSfei feng - Sun Microsystems - Beijing China noise_chain_c = LE_32(rx_general_p->beacon_silence_rssi_c) & 0xFF; 5234cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5235cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Rx chain's beacon strength from statistics notification */ 5236b510adaeSfei feng - Sun Microsystems - Beijing China beacon_chain_a = LE_32(rx_general_p->beacon_rssi_a) & 0xFF; 5237b510adaeSfei feng - Sun Microsystems - Beijing China beacon_chain_b = LE_32(rx_general_p->beacon_rssi_b) & 0xFF; 5238b510adaeSfei feng - Sun Microsystems - Beijing China beacon_chain_c = LE_32(rx_general_p->beacon_rssi_c) & 0xFF; 5239cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5240cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_count++; 5241cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5242cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate chain's noise strength */ 5243cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_a += noise_chain_a; 5244cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_b += noise_chain_b; 5245cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_c += noise_chain_c; 5246cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5247cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate chain's beacon strength */ 5248cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_a += beacon_chain_a; 5249cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_b += beacon_chain_b; 5250cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_c += beacon_chain_c; 5251cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5252cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (BEACON_NUM_20 == gain_diff_p->beacon_count) { 5253cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calculate average beacon strength */ 5254cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[0] = (gain_diff_p->beacon_stren_a) / BEACON_NUM_20; 5255cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[1] = (gain_diff_p->beacon_stren_b) / BEACON_NUM_20; 5256cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[2] = (gain_diff_p->beacon_stren_c) / BEACON_NUM_20; 5257cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5258cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* calculate average noise strength */ 5259cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[0] = (gain_diff_p->noise_stren_a) / BEACON_NUM_20; 5260cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[1] = (gain_diff_p->noise_stren_b) / BEACON_NUM_20; 5261cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[2] = (gain_diff_p->noise_stren_b) / BEACON_NUM_20; 5262cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5263cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum beacon strength among 3 chains */ 5264cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((beacon_aver[0] >= beacon_aver[1]) && 5265cdc64593Sxinghua wen - Sun Microsystems - Beijing China (beacon_aver[0] >= beacon_aver[2])) { 5266cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_chain_n = 0; 5267cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains = 1 << 0; 5268cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (beacon_aver[1] >= beacon_aver[2]) { 5269cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_chain_n = 1; 5270cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains = 1 << 1; 5271cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5272cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_chain_n = 2; 5273cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains = 1 << 2; 5274cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5275cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5276cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine which chain is disconnected */ 5277cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) { 5278cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (i != max_beacon_chain_n) { 5279cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_diff = beacon_aver[max_beacon_chain_n] - 5280cdc64593Sxinghua wen - Sun Microsystems - Beijing China beacon_aver[i]; 5281cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (beacon_diff > MAX_ALLOWED_DIFF) { 5282cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[i] = 1; 5283cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5284cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains |= 5285cdc64593Sxinghua wen - Sun Microsystems - Beijing China (1 << i); 5286cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5287cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5288cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5289cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5290cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5291cdc64593Sxinghua wen - Sun Microsystems - Beijing China * if chain A and B are both disconnected, 5292cdc64593Sxinghua wen - Sun Microsystems - Beijing China * assume the stronger in beacon strength is connected 5293cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5294cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (gain_diff_p->disconnect_chain[0] && 5295cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[1]) { 5296cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (beacon_aver[0] >= beacon_aver[1]) { 5297cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[0] = 0; 5298cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains |= (1 << 0); 5299cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5300cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->disconnect_chain[1] = 0; 5301cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->connected_chains |= (1 << 1); 5302cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5303cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5304cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5305cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine minimum noise strength among 3 chains */ 5306cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[0]) { 5307cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = 0; 5308cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5309cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) { 5310cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[i] && 5311cdc64593Sxinghua wen - Sun Microsystems - Beijing China (noise_aver[i] <= 5312cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[min_noise_chain_n])) { 5313cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = i; 5314cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5315cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5316cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5317cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5318cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = 1; 5319cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5320cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) { 5321cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[i] && 5322cdc64593Sxinghua wen - Sun Microsystems - Beijing China (noise_aver[i] <= 5323cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[min_noise_chain_n])) { 5324cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_noise_chain_n = i; 5325cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5326cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5327cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5328cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5329cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[min_noise_chain_n] = 0; 5330cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5331cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine gain difference between chains */ 5332cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < RX_CHAINS_NUM; i++) { 5333cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->disconnect_chain[i] && 5334cdc64593Sxinghua wen - Sun Microsystems - Beijing China (CHAIN_GAIN_DIFF_INIT_VAL == 5335cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i])) { 5336cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5337cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_diff = noise_aver[i] - 5338cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_aver[min_noise_chain_n]; 5339cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] = 5340cdc64593Sxinghua wen - Sun Microsystems - Beijing China (uint8_t)((noise_diff * 10) / 15); 5341cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5342cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (gain_diff_p->gain_diff_chain[i] > 3) { 5343cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] = 3; 5344cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5345cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5346cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] |= (1 << 2); 5347cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5348cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_chain[i] = 0; 5349cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5350cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5351cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5352cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!gain_diff_p->gain_diff_send) { 5353cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->gain_diff_send = 1; 5354cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5355cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (cmd)); 5356cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5357cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD; 5358cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_a = gain_diff_p->gain_diff_chain[0]; 5359cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_b = gain_diff_p->gain_diff_chain[1]; 5360cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.diff_gain_c = gain_diff_p->gain_diff_chain[2]; 5361cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5362cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5363cdc64593Sxinghua wen - Sun Microsystems - Beijing China * send out PHY calibration command to 5364cdc64593Sxinghua wen - Sun Microsystems - Beijing China * adjust every chain's Rx gain 5365cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5366cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, REPLY_PHY_CALIBRATION_CMD, 5367cdc64593Sxinghua wen - Sun Microsystems - Beijing China &cmd, sizeof (cmd), 1); 5368cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5369cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5370cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5371cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5372cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->state = IWK_GAIN_DIFF_CALIBRATED; 5373cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5374cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5375cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_a = 0; 5376cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_b = 0; 5377cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->beacon_stren_c = 0; 5378cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5379cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_a = 0; 5380cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_b = 0; 5381cdc64593Sxinghua wen - Sun Microsystems - Beijing China gain_diff_p->noise_stren_c = 0; 5382cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5383cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5384cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5385cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5386cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5387cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Make necessary preparation for Receiver sensitivity calibration */ 5388cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens_init(iwk_sc_t *sc) 5389cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5390cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i, rv; 5391cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity_cmd cmd; 5392cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens; 5393cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5394cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(&cmd, 0, sizeof (struct iwk_rx_sensitivity_cmd)); 5395cdc64593Sxinghua wen - Sun Microsystems - Beijing China (void) memset(rx_sens_p, 0, sizeof (struct iwk_rx_sensitivity)); 5396cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5397cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4 = 90; 5398cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4 = 170; 5399cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1 = 105; 5400cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1 = 220; 5401cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5402cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 125; 5403cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 = 200; 5404cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck = 100; 5405cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5406cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CALIB_ALLOW_MSK); 5407cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_OFDM_UPDATE_MSK); 5408cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK); 5409cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5410cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_ofdm = 0; 5411cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_ofdm = 0; 5412cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_cck = 0; 5413cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_cck = 0; 5414cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5415cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_TOO_MANY_FALSE_ALARM; 5416cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_prev_state = IWK_TOO_MANY_FALSE_ALARM; 5417cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num = 0; 5418cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_idx = 0; 5419cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5420cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 10; i++) { 5421cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_min[i] = 0; 5422cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5423cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5424cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_idx = 0; 5425cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_ref = 0; 5426cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5427cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 20; i++) { 5428cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_max[i] = 0; 5429cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5430cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5431cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_diff = 0; 5432cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num = 0; 5433cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5434b510adaeSfei feng - Sun Microsystems - Beijing China cmd.control = LE_16(IWK_SENSITIVITY_CONTROL_WORK_TABLE); 5435cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5436cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_IDX] = 5437b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_ofdm_x4); 5438cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] = 5439b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_mrc_ofdm_x4); 5440cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_IDX] = 5441b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_ofdm_x1); 5442cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] = 5443b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_mrc_ofdm_x1); 5444cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5445cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_IDX] = 5446b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_cck_x4); 5447cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] = 5448b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->auto_corr_mrc_cck_x4); 5449b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_CCK_DET_IDX] = 5450b510adaeSfei feng - Sun Microsystems - Beijing China LE_16(rx_sens_p->min_energy_det_cck); 5451cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5452b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_OFDM_DET_IDX] = LE_16(100); 5453b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_IDX] = LE_16(190); 5454b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_MRC_IDX] = LE_16(390); 5455b510adaeSfei feng - Sun Microsystems - Beijing China cmd.table[PTAM_ENERGY_TH_IDX] = LE_16(62); 5456cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5457cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* at first, set up Rx to maximum sensitivity */ 5458cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, SENSITIVITY_CMD, &cmd, sizeof (cmd), 1); 5459cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5460cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens_init(): " 5461cdc64593Sxinghua wen - Sun Microsystems - Beijing China "in the process of initialization, " 5462cdc64593Sxinghua wen - Sun Microsystems - Beijing China "failed to send rx sensitivity command\n"); 5463cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5464cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5465cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5466cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_CALIB_ALLOW_MSK; 5467cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5468cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5469cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5470cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5471cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5472cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Receiver sensitivity calibration to adjust every chain's Rx sensitivity. 5473cdc64593Sxinghua wen - Sun Microsystems - Beijing China * for more infomation, please refer to iwk_calibration.h file 5474cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5475cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_rx_sens(iwk_sc_t *sc) 5476cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5477cdc64593Sxinghua wen - Sun Microsystems - Beijing China int rv; 5478cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t actual_rx_time; 5479cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct statistics_rx_non_phy *rx_general_p = 5480cdc64593Sxinghua wen - Sun Microsystems - Beijing China &sc->sc_statistics.rx.general; 5481cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens; 5482cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity_cmd cmd; 5483cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5484cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(rx_sens_p->flags & IWK_SENSITIVITY_CALIB_ALLOW_MSK)) { 5485cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens(): " 5486cdc64593Sxinghua wen - Sun Microsystems - Beijing China "sensitivity initialization has not finished.\n"); 5487cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 5488cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5489cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5490cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (INTERFERENCE_DATA_AVAILABLE != 5491b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(rx_general_p->interference_data_flag)) { 5492cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens(): " 5493cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't make rx sensitivity calibration," 5494cdc64593Sxinghua wen - Sun Microsystems - Beijing China "because of invalid statistics\n"); 5495cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 5496cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5497cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5498b510adaeSfei feng - Sun Microsystems - Beijing China actual_rx_time = LE_32(rx_general_p->channel_load); 5499cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!actual_rx_time) { 5500d2a61391Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_CALIBRATION, "iwk_rx_sens(): " 5501cdc64593Sxinghua wen - Sun Microsystems - Beijing China "can't make rx sensitivity calibration," 5502d2a61391Spengcheng chen - Sun Microsystems - Beijing China "because has not enough rx time\n")); 5503cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 5504cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5505cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5506cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Rx sensitivity calibration for OFDM mode */ 5507cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_ofdm_sens(sc, actual_rx_time); 5508cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5509cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5510cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5511cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5512cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* make Rx sensitivity calibration for CCK mode */ 5513cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cck_sens(sc, actual_rx_time); 5514cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5515cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5516cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5517cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5518cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5519cdc64593Sxinghua wen - Sun Microsystems - Beijing China * if the sum of false alarm had not changed, nothing will be done 5520cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5521cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((!(rx_sens_p->flags & IWK_SENSITIVITY_OFDM_UPDATE_MSK)) && 5522cdc64593Sxinghua wen - Sun Microsystems - Beijing China (!(rx_sens_p->flags & IWK_SENSITIVITY_CCK_UPDATE_MSK))) { 5523cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5524cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5525cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5526cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.control = IWK_SENSITIVITY_CONTROL_WORK_TABLE; 5527cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5528cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_IDX] = 5529cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4; 5530cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] = 5531cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4; 5532cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_IDX] = 5533cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1; 5534cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] = 5535cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1; 5536cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5537cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_IDX] = 5538cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4; 5539cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] = 5540cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4; 5541cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_CCK_DET_IDX] = 5542cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck; 5543cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5544cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[MIN_ENERGY_OFDM_DET_IDX] = 100; 5545cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_IDX] = 190; 5546cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[BARKER_CORR_TH_ADD_MIN_MRC_IDX] = 390; 5547cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmd.table[PTAM_ENERGY_TH_IDX] = 62; 5548cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5549cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5550cdc64593Sxinghua wen - Sun Microsystems - Beijing China * send sensitivity command to complete actual sensitivity calibration 5551cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5552cdc64593Sxinghua wen - Sun Microsystems - Beijing China rv = iwk_cmd(sc, SENSITIVITY_CMD, &cmd, sizeof (cmd), 1); 5553cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rv) { 5554cdc64593Sxinghua wen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_rx_sens(): " 5555cdc64593Sxinghua wen - Sun Microsystems - Beijing China "fail to send rx sensitivity command\n"); 5556cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (rv); 5557cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5558cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5559cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5560cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5561cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5562cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5563cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5564cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Rx sensitivity calibration for CCK mode. 5565cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This is preparing parameters for Sensitivity command 5566cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5567cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_cck_sens(iwk_sc_t *sc, uint32_t actual_rx_time) 5568cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5569cdc64593Sxinghua wen - Sun Microsystems - Beijing China int i; 5570cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint8_t noise_a, noise_b, noise_c; 5571cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint8_t max_noise_abc, max_noise_20; 5572cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t beacon_a, beacon_b, beacon_c; 5573cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t min_beacon_abc, max_beacon_10; 5574cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t cck_fa, cck_bp; 5575cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t cck_sum_fa_bp; 5576cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t temp; 5577cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct statistics_rx_non_phy *rx_general_p = 5578cdc64593Sxinghua wen - Sun Microsystems - Beijing China &sc->sc_statistics.rx.general; 5579cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens; 5580cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5581b510adaeSfei feng - Sun Microsystems - Beijing China cck_fa = LE_32(sc->sc_statistics.rx.cck.false_alarm_cnt); 5582b510adaeSfei feng - Sun Microsystems - Beijing China cck_bp = LE_32(sc->sc_statistics.rx.cck.plcp_err); 5583cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5584cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate false alarm */ 5585cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_false_alarm_cnt_cck > cck_fa) { 5586cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_false_alarm_cnt_cck; 5587cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_cck = cck_fa; 5588cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_fa += (0xFFFFFFFF - temp); 5589cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5590cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_fa -= rx_sens_p->last_false_alarm_cnt_cck; 5591cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_cck += cck_fa; 5592cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5593cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5594cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate bad plcp */ 5595cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_bad_plcp_cnt_cck > cck_bp) { 5596cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_bad_plcp_cnt_cck; 5597cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_cck = cck_bp; 5598cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_bp += (0xFFFFFFFF - temp); 5599cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5600cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_bp -= rx_sens_p->last_bad_plcp_cnt_cck; 5601cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_cck += cck_bp; 5602cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5603cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5604cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5605cdc64593Sxinghua wen - Sun Microsystems - Beijing China * calculate relative value 5606cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5607cdc64593Sxinghua wen - Sun Microsystems - Beijing China cck_sum_fa_bp = (cck_fa + cck_bp) * 200 * 1024; 5608cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_diff = 0; 5609cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5610cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_a = 5611b510adaeSfei feng - Sun Microsystems - Beijing China (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_a) & 0xFF00) >> 5612b510adaeSfei feng - Sun Microsystems - Beijing China 8); 5613cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_b = 5614b510adaeSfei feng - Sun Microsystems - Beijing China (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_b) & 0xFF00) >> 5615b510adaeSfei feng - Sun Microsystems - Beijing China 8); 5616cdc64593Sxinghua wen - Sun Microsystems - Beijing China noise_c = 5617b510adaeSfei feng - Sun Microsystems - Beijing China (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_c) & 0xFF00) >> 5618b510adaeSfei feng - Sun Microsystems - Beijing China 8); 5619cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5620b510adaeSfei feng - Sun Microsystems - Beijing China beacon_a = LE_32(rx_general_p->beacon_energy_a); 5621b510adaeSfei feng - Sun Microsystems - Beijing China beacon_b = LE_32(rx_general_p->beacon_energy_b); 5622b510adaeSfei feng - Sun Microsystems - Beijing China beacon_c = LE_32(rx_general_p->beacon_energy_c); 5623cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5624cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum noise among 3 chains */ 5625cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((noise_a >= noise_b) && (noise_a >= noise_c)) { 5626cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_abc = noise_a; 5627cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (noise_b >= noise_c) { 5628cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_abc = noise_b; 5629cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5630cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_abc = noise_c; 5631cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5632cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5633cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record maximum noise among 3 chains */ 5634cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_max[rx_sens_p->cck_noise_idx] = max_noise_abc; 5635cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_idx++; 5636cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_noise_idx >= 20) { 5637cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_idx = 0; 5638cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5639cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5640cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum noise among 20 max noise */ 5641cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_20 = rx_sens_p->cck_noise_max[0]; 5642cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 20; i++) { 5643cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_noise_max[i] >= max_noise_20) { 5644cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_noise_20 = rx_sens_p->cck_noise_max[i]; 5645cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5646cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5647cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5648cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine minimum beacon among 3 chains */ 5649cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((beacon_a <= beacon_b) && (beacon_a <= beacon_c)) { 5650cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_beacon_abc = beacon_a; 5651cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (beacon_b <= beacon_c) { 5652cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_beacon_abc = beacon_b; 5653cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5654cdc64593Sxinghua wen - Sun Microsystems - Beijing China min_beacon_abc = beacon_c; 5655cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5656cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5657cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record miminum beacon among 3 chains */ 5658cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_min[rx_sens_p->cck_beacon_idx] = min_beacon_abc; 5659cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_idx++; 5660cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_beacon_idx >= 10) { 5661cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_beacon_idx = 0; 5662cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5663cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5664cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* determine maximum beacon among 10 miminum beacon among 3 chains */ 5665cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_10 = rx_sens_p->cck_beacon_min[0]; 5666cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < 10; i++) { 5667cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->cck_beacon_min[i] >= max_beacon_10) { 5668cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_10 = rx_sens_p->cck_beacon_min[i]; 5669cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5670cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5671cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5672cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* add a little margin */ 5673cdc64593Sxinghua wen - Sun Microsystems - Beijing China max_beacon_10 += 6; 5674cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5675cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* record the count of having no false alarms */ 5676cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (cck_sum_fa_bp < (5 * actual_rx_time)) { 5677cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num++; 5678cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5679cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_no_false_alarm_num = 0; 5680cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5681cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5682cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5683cdc64593Sxinghua wen - Sun Microsystems - Beijing China * adjust parameters in sensitivity command 5684cdc64593Sxinghua wen - Sun Microsystems - Beijing China * according to different status. 5685cdc64593Sxinghua wen - Sun Microsystems - Beijing China * for more infomation, please refer to iwk_calibration.h file 5686cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5687cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (cck_sum_fa_bp > (50 * actual_rx_time)) { 5688cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_TOO_MANY_FALSE_ALARM; 5689cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5690cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->auto_corr_cck_x4 > 160) { 5691cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_ref = max_noise_20; 5692cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5693cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->min_energy_det_cck > 2) { 5694cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck -= 2; 5695cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5696cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5697cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5698cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->auto_corr_cck_x4 < 160) { 5699cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 160 + 1; 5700cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5701cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_cck_x4 + 3) < 200) { 5702cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 += 3; 5703cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5704cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 200; 5705cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5706cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5707cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5708cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_mrc_cck_x4 + 3) < 400) { 5709cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 += 3; 5710cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5711cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 = 400; 5712cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5713cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5714cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_CCK_UPDATE_MSK; 5715cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5716cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (cck_sum_fa_bp < (5 * actual_rx_time)) { 5717cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_TOO_FEW_FALSE_ALARM; 5718cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5719cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_diff = (int32_t)rx_sens_p->cck_noise_ref - 5720cdc64593Sxinghua wen - Sun Microsystems - Beijing China (int32_t)max_noise_20; 5721cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5722cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->cck_prev_state != IWK_TOO_MANY_FALSE_ALARM) && 5723cdc64593Sxinghua wen - Sun Microsystems - Beijing China ((rx_sens_p->cck_noise_diff > 2) || 5724cdc64593Sxinghua wen - Sun Microsystems - Beijing China (rx_sens_p->cck_no_false_alarm_num > 100))) { 5725cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->min_energy_det_cck + 2) < 97) { 5726cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck += 2; 5727cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5728cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck = 97; 5729cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5730cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5731cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_cck_x4 - 3) > 125) { 5732cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 -= 3; 5733cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5734cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_cck_x4 = 125; 5735cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5736cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5737cdc64593Sxinghua wen - Sun Microsystems - Beijing China if ((rx_sens_p->auto_corr_mrc_cck_x4 -3) > 200) { 5738cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 -= 3; 5739cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5740cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_cck_x4 = 200; 5741cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5742cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5743cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_CCK_UPDATE_MSK; 5744cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5745cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK); 5746cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5747cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5748cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_curr_state = IWK_GOOD_RANGE_FALSE_ALARM; 5749cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5750cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_noise_ref = max_noise_20; 5751cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5752cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (IWK_TOO_MANY_FALSE_ALARM == rx_sens_p->cck_prev_state) { 5753cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck -= 8; 5754cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5755cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5756cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK); 5757cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5758cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5759cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->min_energy_det_cck < max_beacon_10) { 5760cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->min_energy_det_cck = (uint16_t)max_beacon_10; 5761cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5762cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5763cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->cck_prev_state = rx_sens_p->cck_curr_state; 5764cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5765cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5766cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5767cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5768cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5769cdc64593Sxinghua wen - Sun Microsystems - Beijing China * make Rx sensitivity calibration for OFDM mode. 5770cdc64593Sxinghua wen - Sun Microsystems - Beijing China * This is preparing parameters for Sensitivity command 5771cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5772cdc64593Sxinghua wen - Sun Microsystems - Beijing China static int iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time) 5773cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5774cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t temp; 5775cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint16_t temp1; 5776cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t ofdm_fa, ofdm_bp; 5777cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t ofdm_sum_fa_bp; 5778cdc64593Sxinghua wen - Sun Microsystems - Beijing China struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens; 5779cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5780b510adaeSfei feng - Sun Microsystems - Beijing China ofdm_fa = LE_32(sc->sc_statistics.rx.ofdm.false_alarm_cnt); 5781b510adaeSfei feng - Sun Microsystems - Beijing China ofdm_bp = LE_32(sc->sc_statistics.rx.ofdm.plcp_err); 5782cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5783cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate false alarm */ 5784cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_false_alarm_cnt_ofdm > ofdm_fa) { 5785cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_false_alarm_cnt_ofdm; 5786cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_ofdm = ofdm_fa; 5787cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_fa += (0xFFFFFFFF - temp); 5788cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5789cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_fa -= rx_sens_p->last_false_alarm_cnt_ofdm; 5790cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_false_alarm_cnt_ofdm += ofdm_fa; 5791cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5792cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5793cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* accumulate bad plcp */ 5794cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (rx_sens_p->last_bad_plcp_cnt_ofdm > ofdm_bp) { 5795cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp = rx_sens_p->last_bad_plcp_cnt_ofdm; 5796cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_ofdm = ofdm_bp; 5797cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_bp += (0xFFFFFFFF - temp); 5798cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5799cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_bp -= rx_sens_p->last_bad_plcp_cnt_ofdm; 5800cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->last_bad_plcp_cnt_ofdm += ofdm_bp; 5801cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5802cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5803cdc64593Sxinghua wen - Sun Microsystems - Beijing China ofdm_sum_fa_bp = (ofdm_fa + ofdm_bp) * 200 * 1024; /* relative value */ 5804cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5805cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5806cdc64593Sxinghua wen - Sun Microsystems - Beijing China * adjust parameter in sensitivity command according to different status 5807cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5808cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (ofdm_sum_fa_bp > (50 * actual_rx_time)) { 5809cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x4 + 1; 5810cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4 = (temp1 <= 120) ? temp1 : 120; 5811cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5812cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x4 + 1; 5813cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4 = 5814cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 <= 210) ? temp1 : 210; 5815cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5816cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x1 + 1; 5817cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1 = (temp1 <= 140) ? temp1 : 140; 5818cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5819cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x1 + 1; 5820cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1 = 5821cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 <= 270) ? temp1 : 270; 5822cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5823cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_OFDM_UPDATE_MSK; 5824cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5825cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else if (ofdm_sum_fa_bp < (5 * actual_rx_time)) { 5826cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x4 - 1; 5827cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x4 = (temp1 >= 85) ? temp1 : 85; 5828cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5829cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x4 - 1; 5830cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x4 = 5831cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 >= 170) ? temp1 : 170; 5832cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5833cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_ofdm_x1 - 1; 5834cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_ofdm_x1 = (temp1 >= 105) ? temp1 : 105; 5835cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5836cdc64593Sxinghua wen - Sun Microsystems - Beijing China temp1 = rx_sens_p->auto_corr_mrc_ofdm_x1 - 1; 5837cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->auto_corr_mrc_ofdm_x1 = 5838cdc64593Sxinghua wen - Sun Microsystems - Beijing China (temp1 >= 220) ? temp1 : 220; 5839cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5840cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags |= IWK_SENSITIVITY_OFDM_UPDATE_MSK; 5841cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5842cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5843cdc64593Sxinghua wen - Sun Microsystems - Beijing China rx_sens_p->flags &= (~IWK_SENSITIVITY_OFDM_UPDATE_MSK); 5844cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5845cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5846cdc64593Sxinghua wen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 5847cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5848cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5849cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 585019d332feSfei feng - Sun Microsystems - Beijing China * additional process to management frames 585119d332feSfei feng - Sun Microsystems - Beijing China */ 585219d332feSfei feng - Sun Microsystems - Beijing China static void iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp, 585319d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_node *in, 585419d332feSfei feng - Sun Microsystems - Beijing China int subtype, int rssi, uint32_t rstamp) 585519d332feSfei feng - Sun Microsystems - Beijing China { 585619d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic; 585719d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_frame *wh; 585819d332feSfei feng - Sun Microsystems - Beijing China uint8_t index1, index2; 585919d332feSfei feng - Sun Microsystems - Beijing China int err; 586019d332feSfei feng - Sun Microsystems - Beijing China 586119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_recv_mgmt(ic, mp, in, subtype, rssi, rstamp); 586219d332feSfei feng - Sun Microsystems - Beijing China 586319d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 586419d332feSfei feng - Sun Microsystems - Beijing China switch (subtype) { 586519d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_FC0_SUBTYPE_BEACON: 586619d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_beacon.syncbeacon && in == ic->ic_bss && 586719d332feSfei feng - Sun Microsystems - Beijing China ic->ic_state == IEEE80211_S_RUN) { 586819d332feSfei feng - Sun Microsystems - Beijing China if (ieee80211_beacon_update(ic, in, 586919d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.iwk_boff, 587019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.mp, 0)) { 587119d332feSfei feng - Sun Microsystems - Beijing China bcopy(sc->sc_ibss.ibss_beacon.mp->b_rptr, 587219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd. 587319d332feSfei feng - Sun Microsystems - Beijing China bcon_frame, 587419d332feSfei feng - Sun Microsystems - Beijing China MBLKL(sc->sc_ibss.ibss_beacon.mp)); 587519d332feSfei feng - Sun Microsystems - Beijing China } 587619d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_BEACON, 587719d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.beacon_cmd, 587819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd_len, 1); 587919d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 588019d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_recv_mgmt(): " 588119d332feSfei feng - Sun Microsystems - Beijing China "failed to TX beacon.\n"); 588219d332feSfei feng - Sun Microsystems - Beijing China } 588319d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.syncbeacon = 0; 588419d332feSfei feng - Sun Microsystems - Beijing China } 588519d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_IBSS && 588619d332feSfei feng - Sun Microsystems - Beijing China ic->ic_state == IEEE80211_S_RUN) { 588719d332feSfei feng - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)mp->b_rptr; 588819d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock); 588919d332feSfei feng - Sun Microsystems - Beijing China /* 589019d332feSfei feng - Sun Microsystems - Beijing China * search for node in ibss node table 589119d332feSfei feng - Sun Microsystems - Beijing China */ 589219d332feSfei feng - Sun Microsystems - Beijing China for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT; 589319d332feSfei feng - Sun Microsystems - Beijing China index1++) { 589419d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_node_tb[index1].used && 589519d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_EQ(sc->sc_ibss. 589619d332feSfei feng - Sun Microsystems - Beijing China ibss_node_tb[index1].node.bssid, 589719d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr2)) { 589819d332feSfei feng - Sun Microsystems - Beijing China break; 589919d332feSfei feng - Sun Microsystems - Beijing China } 590019d332feSfei feng - Sun Microsystems - Beijing China } 590119d332feSfei feng - Sun Microsystems - Beijing China /* 590219d332feSfei feng - Sun Microsystems - Beijing China * if don't find in ibss node table 590319d332feSfei feng - Sun Microsystems - Beijing China */ 590419d332feSfei feng - Sun Microsystems - Beijing China if (index1 >= IWK_BROADCAST_ID) { 590519d332feSfei feng - Sun Microsystems - Beijing China err = iwk_clean_add_node_ibss(ic, 590619d332feSfei feng - Sun Microsystems - Beijing China wh->i_addr2, &index2); 590719d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 590819d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_recv_mgmt(): " 590919d332feSfei feng - Sun Microsystems - Beijing China "failed to clean all nodes " 591019d332feSfei feng - Sun Microsystems - Beijing China "and add one node\n"); 591119d332feSfei feng - Sun Microsystems - Beijing China } 591219d332feSfei feng - Sun Microsystems - Beijing China } 591319d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock); 591419d332feSfei feng - Sun Microsystems - Beijing China } 591519d332feSfei feng - Sun Microsystems - Beijing China break; 591619d332feSfei feng - Sun Microsystems - Beijing China case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 591719d332feSfei feng - Sun Microsystems - Beijing China break; 591819d332feSfei feng - Sun Microsystems - Beijing China } 591919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 592019d332feSfei feng - Sun Microsystems - Beijing China } 592119d332feSfei feng - Sun Microsystems - Beijing China 592219d332feSfei feng - Sun Microsystems - Beijing China /* 5923cdc64593Sxinghua wen - Sun Microsystems - Beijing China * 1) log_event_table_ptr indicates base of the event log. This traces 5924cdc64593Sxinghua wen - Sun Microsystems - Beijing China * a 256-entry history of uCode execution within a circular buffer. 5925cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Its header format is: 5926cdc64593Sxinghua wen - Sun Microsystems - Beijing China * 5927cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t log_size; log capacity (in number of entries) 5928cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t type; (1) timestamp with each entry, (0) no timestamp 5929cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t wraps; # times uCode has wrapped to top of circular buffer 5930cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t write_index; next circular buffer entry that uCode would fill 5931cdc64593Sxinghua wen - Sun Microsystems - Beijing China * 5932cdc64593Sxinghua wen - Sun Microsystems - Beijing China * The header is followed by the circular buffer of log entries. Entries 5933cdc64593Sxinghua wen - Sun Microsystems - Beijing China * with timestamps have the following format: 5934cdc64593Sxinghua wen - Sun Microsystems - Beijing China * 5935cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t event_id; range 0 - 1500 5936cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t timestamp; low 32 bits of TSF (of network, if associated) 5937cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t data; event_id-specific data value 5938cdc64593Sxinghua wen - Sun Microsystems - Beijing China * 5939cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Entries without timestamps contain only event_id and data. 5940cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5941cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5942cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 5943cdc64593Sxinghua wen - Sun Microsystems - Beijing China * iwk_write_event_log - Write event log to dmesg 5944cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 5945cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_event_log(iwk_sc_t *sc) 5946cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 5947cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t log_event_table_ptr; /* Start address of event table */ 5948cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t startptr; /* Start address of log data */ 5949cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t logptr; /* address of log data entry */ 5950cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t i, n, num_events; 5951cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t event_id, data1, data2; /* log data */ 5952cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5953cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t log_size; /* log capacity (in number of entries) */ 5954cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t type; /* (1)timestamp with each entry,(0) no timestamp */ 5955cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t wraps; /* # times uCode has wrapped to */ 5956cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* the top of circular buffer */ 5957cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t idx; /* index of entry to be filled in next */ 5958cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5959b510adaeSfei feng - Sun Microsystems - Beijing China log_event_table_ptr = LE_32(sc->sc_card_alive_run.log_event_table_ptr); 5960cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(log_event_table_ptr)) { 5961cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "NULL event table pointer\n")); 5962cdc64593Sxinghua wen - Sun Microsystems - Beijing China return; 5963cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5964cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5965cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_enter(sc); 5966cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5967cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* Read log header */ 5968cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_size = iwk_mem_read(sc, log_event_table_ptr); 5969cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_event_table_ptr += sizeof (uint32_t); /* addr of "type" */ 5970cdc64593Sxinghua wen - Sun Microsystems - Beijing China type = iwk_mem_read(sc, log_event_table_ptr); 5971cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_event_table_ptr += sizeof (uint32_t); /* addr of "wraps" */ 5972cdc64593Sxinghua wen - Sun Microsystems - Beijing China wraps = iwk_mem_read(sc, log_event_table_ptr); 5973cdc64593Sxinghua wen - Sun Microsystems - Beijing China log_event_table_ptr += sizeof (uint32_t); /* addr of "idx" */ 5974cdc64593Sxinghua wen - Sun Microsystems - Beijing China idx = iwk_mem_read(sc, log_event_table_ptr); 5975cdc64593Sxinghua wen - Sun Microsystems - Beijing China startptr = log_event_table_ptr + 5976cdc64593Sxinghua wen - Sun Microsystems - Beijing China sizeof (uint32_t); /* addr of start of log data */ 5977cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!log_size & !wraps) { 5978cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "Empty log\n")); 5979cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc); 5980cdc64593Sxinghua wen - Sun Microsystems - Beijing China return; 5981cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5982cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5983cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!wraps) { 5984cdc64593Sxinghua wen - Sun Microsystems - Beijing China num_events = idx; 5985cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr = startptr; 5986cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { 5987cdc64593Sxinghua wen - Sun Microsystems - Beijing China num_events = log_size - idx; 5988cdc64593Sxinghua wen - Sun Microsystems - Beijing China n = type ? 2 : 3; 5989cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr = startptr + (idx * n * sizeof (uint32_t)); 5990cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 5991cdc64593Sxinghua wen - Sun Microsystems - Beijing China 5992cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < num_events; i++) { 5993cdc64593Sxinghua wen - Sun Microsystems - Beijing China event_id = iwk_mem_read(sc, logptr); 5994cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t); 5995cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1 = iwk_mem_read(sc, logptr); 5996cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t); 5997cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (type == 0) { /* no timestamp */ 5998cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "Event ID=%d, Data=%x0x", 5999cdc64593Sxinghua wen - Sun Microsystems - Beijing China event_id, data1)); 6000cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { /* timestamp */ 6001cdc64593Sxinghua wen - Sun Microsystems - Beijing China data2 = iwk_mem_read(sc, logptr); 6002cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, 6003cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Time=%d, Event ID=%d, Data=0x%x\n", 6004cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1, event_id, data2)); 6005cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t); 6006cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6007cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6008cdc64593Sxinghua wen - Sun Microsystems - Beijing China 6009cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 6010cdc64593Sxinghua wen - Sun Microsystems - Beijing China * Print the wrapped around entries, if any 6011cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 6012cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (wraps) { 6013cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr = startptr; 6014cdc64593Sxinghua wen - Sun Microsystems - Beijing China for (i = 0; i < idx; i++) { 6015cdc64593Sxinghua wen - Sun Microsystems - Beijing China event_id = iwk_mem_read(sc, logptr); 6016cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t); 6017cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1 = iwk_mem_read(sc, logptr); 6018cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t); 6019cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (type == 0) { /* no timestamp */ 6020cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, 6021cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Event ID=%d, Data=%x0x", event_id, data1)); 6022cdc64593Sxinghua wen - Sun Microsystems - Beijing China } else { /* timestamp */ 6023cdc64593Sxinghua wen - Sun Microsystems - Beijing China data2 = iwk_mem_read(sc, logptr); 6024cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, 6025cdc64593Sxinghua wen - Sun Microsystems - Beijing China "Time = %d, Event ID=%d, Data=0x%x\n", 6026cdc64593Sxinghua wen - Sun Microsystems - Beijing China data1, event_id, data2)); 6027cdc64593Sxinghua wen - Sun Microsystems - Beijing China logptr += sizeof (uint32_t); 6028cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6029cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6030cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6031cdc64593Sxinghua wen - Sun Microsystems - Beijing China 6032cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc); 6033cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6034cdc64593Sxinghua wen - Sun Microsystems - Beijing China 6035cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 6036cdc64593Sxinghua wen - Sun Microsystems - Beijing China * error_event_table_ptr indicates base of the error log. This contains 6037cdc64593Sxinghua wen - Sun Microsystems - Beijing China * information about any uCode error that occurs. For 4965, the format is: 6038cdc64593Sxinghua wen - Sun Microsystems - Beijing China * 6039cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t valid; (nonzero) valid, (0) log is empty 6040cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t error_id; type of error 6041cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t pc; program counter 6042cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t blink1; branch link 6043cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t blink2; branch link 6044cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t ilink1; interrupt link 6045cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t ilink2; interrupt link 6046cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t data1; error-specific data 6047cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t data2; error-specific data 6048cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t line; source code line of error 6049cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t bcon_time; beacon timer 6050cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t tsf_low; network timestamp function timer 6051cdc64593Sxinghua wen - Sun Microsystems - Beijing China * uint32_t tsf_hi; network timestamp function timer 6052cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 6053cdc64593Sxinghua wen - Sun Microsystems - Beijing China /* 6054cdc64593Sxinghua wen - Sun Microsystems - Beijing China * iwk_write_error_log - Write error log to dmesg 6055cdc64593Sxinghua wen - Sun Microsystems - Beijing China */ 6056cdc64593Sxinghua wen - Sun Microsystems - Beijing China static void iwk_write_error_log(iwk_sc_t *sc) 6057cdc64593Sxinghua wen - Sun Microsystems - Beijing China { 6058cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t err_ptr; /* Start address of error log */ 6059cdc64593Sxinghua wen - Sun Microsystems - Beijing China uint32_t valid; /* is error log valid */ 6060cdc64593Sxinghua wen - Sun Microsystems - Beijing China 6061b510adaeSfei feng - Sun Microsystems - Beijing China err_ptr = LE_32(sc->sc_card_alive_run.error_event_table_ptr); 6062cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(err_ptr)) { 6063cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "NULL error table pointer\n")); 6064cdc64593Sxinghua wen - Sun Microsystems - Beijing China return; 6065cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6066cdc64593Sxinghua wen - Sun Microsystems - Beijing China 6067cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_enter(sc); 6068cdc64593Sxinghua wen - Sun Microsystems - Beijing China 6069cdc64593Sxinghua wen - Sun Microsystems - Beijing China valid = iwk_mem_read(sc, err_ptr); 6070cdc64593Sxinghua wen - Sun Microsystems - Beijing China if (!(valid)) { 6071cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "Error data not valid\n")); 6072cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc); 6073cdc64593Sxinghua wen - Sun Microsystems - Beijing China return; 6074cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 6075cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6076cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "err=%d ", iwk_mem_read(sc, err_ptr))); 6077cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6078cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "pc=0x%X ", iwk_mem_read(sc, err_ptr))); 6079cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6080cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, 6081cdc64593Sxinghua wen - Sun Microsystems - Beijing China "branch link1=0x%X ", iwk_mem_read(sc, err_ptr))); 6082cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6083cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, 6084cdc64593Sxinghua wen - Sun Microsystems - Beijing China "branch link2=0x%X ", iwk_mem_read(sc, err_ptr))); 6085cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6086cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, 6087cdc64593Sxinghua wen - Sun Microsystems - Beijing China "interrupt link1=0x%X ", iwk_mem_read(sc, err_ptr))); 6088cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6089cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, 6090cdc64593Sxinghua wen - Sun Microsystems - Beijing China "interrupt link2=0x%X ", iwk_mem_read(sc, err_ptr))); 6091cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6092cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "data1=0x%X ", iwk_mem_read(sc, err_ptr))); 6093cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6094cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "data2=0x%X ", iwk_mem_read(sc, err_ptr))); 6095cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6096cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "line=%d ", iwk_mem_read(sc, err_ptr))); 6097cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6098cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "bcon_time=%d ", iwk_mem_read(sc, err_ptr))); 6099cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6100cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "tsf_low=%d ", iwk_mem_read(sc, err_ptr))); 6101cdc64593Sxinghua wen - Sun Microsystems - Beijing China err_ptr += sizeof (uint32_t); 6102cdc64593Sxinghua wen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_EEPROM, "tsf_hi=%d\n", iwk_mem_read(sc, err_ptr))); 6103cdc64593Sxinghua wen - Sun Microsystems - Beijing China 6104cdc64593Sxinghua wen - Sun Microsystems - Beijing China iwk_mac_access_exit(sc); 6105cdc64593Sxinghua wen - Sun Microsystems - Beijing China } 610619d332feSfei feng - Sun Microsystems - Beijing China 610719d332feSfei feng - Sun Microsystems - Beijing China static int 610819d332feSfei feng - Sun Microsystems - Beijing China iwk_run_state_config_ibss(ieee80211com_t *ic) 610919d332feSfei feng - Sun Microsystems - Beijing China { 611019d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic; 611119d332feSfei feng - Sun Microsystems - Beijing China ieee80211_node_t *in = ic->ic_bss; 611219d332feSfei feng - Sun Microsystems - Beijing China int i, err = IWK_SUCCESS; 611319d332feSfei feng - Sun Microsystems - Beijing China 611419d332feSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_ibss.node_tb_lock); 611519d332feSfei feng - Sun Microsystems - Beijing China 611619d332feSfei feng - Sun Microsystems - Beijing China /* 611719d332feSfei feng - Sun Microsystems - Beijing China * clean all nodes in ibss node table assure be 611819d332feSfei feng - Sun Microsystems - Beijing China * consistent with hardware 611919d332feSfei feng - Sun Microsystems - Beijing China */ 612019d332feSfei feng - Sun Microsystems - Beijing China for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) { 612119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[i].used = 0; 612219d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&sc->sc_ibss.ibss_node_tb[i].node, 612319d332feSfei feng - Sun Microsystems - Beijing China 0, 612419d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t)); 612519d332feSfei feng - Sun Microsystems - Beijing China } 612619d332feSfei feng - Sun Microsystems - Beijing China 612719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number = 0; 612819d332feSfei feng - Sun Microsystems - Beijing China 612919d332feSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_ibss.node_tb_lock); 613019d332feSfei feng - Sun Microsystems - Beijing China 613119d332feSfei feng - Sun Microsystems - Beijing China /* 613219d332feSfei feng - Sun Microsystems - Beijing China * configure RX and TX 613319d332feSfei feng - Sun Microsystems - Beijing China */ 613419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS; 613519d332feSfei feng - Sun Microsystems - Beijing China 6136b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 613719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags = 613819d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 613919d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_DECRYPT_MSK | 614019d332feSfei feng - Sun Microsystems - Beijing China RXON_FILTER_DIS_GRP_DECRYPT_MSK); 614119d332feSfei feng - Sun Microsystems - Beijing China 614219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.assoc_id = 0; 614319d332feSfei feng - Sun Microsystems - Beijing China 614419d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid); 6145b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, 6146b510adaeSfei feng - Sun Microsystems - Beijing China in->in_chan)); 614719d332feSfei feng - Sun Microsystems - Beijing China 614819d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_curmode == IEEE80211_MODE_11B) { 614919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0x03; 615019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0; 615119d332feSfei feng - Sun Microsystems - Beijing China } else if ((in->in_chan != IEEE80211_CHAN_ANYC) && 615219d332feSfei feng - Sun Microsystems - Beijing China (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) { 615319d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0; 615419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0x15; 615519d332feSfei feng - Sun Microsystems - Beijing China 615619d332feSfei feng - Sun Microsystems - Beijing China } else { 615719d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.cck_basic_rates = 0x0f; 615819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.ofdm_basic_rates = 0xff; 615919d332feSfei feng - Sun Microsystems - Beijing China } 616019d332feSfei feng - Sun Microsystems - Beijing China 616119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &= 616219d332feSfei feng - Sun Microsystems - Beijing China ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK | 616319d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_SHORT_SLOT_MSK); 616419d332feSfei feng - Sun Microsystems - Beijing China 616519d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHSLOT) { 616619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= 616719d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_SLOT_MSK); 616819d332feSfei feng - Sun Microsystems - Beijing China } 616919d332feSfei feng - Sun Microsystems - Beijing China 617019d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) { 617119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= 617219d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 617319d332feSfei feng - Sun Microsystems - Beijing China } 617419d332feSfei feng - Sun Microsystems - Beijing China 617519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |= 617619d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ASSOC_MSK); 617719d332feSfei feng - Sun Microsystems - Beijing China 617819d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config, 617919d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1); 618019d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 618119d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_run_state_config_ibss(): " 618219d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration.\n"); 618319d332feSfei feng - Sun Microsystems - Beijing China return (err); 618419d332feSfei feng - Sun Microsystems - Beijing China } 618519d332feSfei feng - Sun Microsystems - Beijing China 618619d332feSfei feng - Sun Microsystems - Beijing China return (err); 618719d332feSfei feng - Sun Microsystems - Beijing China 618819d332feSfei feng - Sun Microsystems - Beijing China } 618919d332feSfei feng - Sun Microsystems - Beijing China 619019d332feSfei feng - Sun Microsystems - Beijing China static int 619119d332feSfei feng - Sun Microsystems - Beijing China iwk_run_state_config_sta(ieee80211com_t *ic) 619219d332feSfei feng - Sun Microsystems - Beijing China { 619319d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic; 619419d332feSfei feng - Sun Microsystems - Beijing China ieee80211_node_t *in = ic->ic_bss; 619519d332feSfei feng - Sun Microsystems - Beijing China int err = IWK_SUCCESS; 619619d332feSfei feng - Sun Microsystems - Beijing China 619719d332feSfei feng - Sun Microsystems - Beijing China /* update adapter's configuration */ 619819d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_assoc_id != in->in_associd) { 619919d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_run_state_config_sta(): " 620019d332feSfei feng - Sun Microsystems - Beijing China "associate ID mismatch: expected %d, " 620119d332feSfei feng - Sun Microsystems - Beijing China "got %d\n", 620219d332feSfei feng - Sun Microsystems - Beijing China in->in_associd, sc->sc_assoc_id); 620319d332feSfei feng - Sun Microsystems - Beijing China } 6204b510adaeSfei feng - Sun Microsystems - Beijing China sc->sc_config.assoc_id = LE_16(in->in_associd & 0x3fff); 620519d332feSfei feng - Sun Microsystems - Beijing China 620619d332feSfei feng - Sun Microsystems - Beijing China /* 620719d332feSfei feng - Sun Microsystems - Beijing China * short preamble/slot time are 620819d332feSfei feng - Sun Microsystems - Beijing China * negotiated when associating 620919d332feSfei feng - Sun Microsystems - Beijing China */ 621019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags &= 621119d332feSfei feng - Sun Microsystems - Beijing China ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK | 621219d332feSfei feng - Sun Microsystems - Beijing China RXON_FLG_SHORT_SLOT_MSK); 621319d332feSfei feng - Sun Microsystems - Beijing China 621419d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHSLOT) 621519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= 621619d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_SLOT_MSK); 621719d332feSfei feng - Sun Microsystems - Beijing China 621819d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 621919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.flags |= 622019d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 622119d332feSfei feng - Sun Microsystems - Beijing China 622219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |= 622319d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_ASSOC_MSK); 622419d332feSfei feng - Sun Microsystems - Beijing China 622519d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode != IEEE80211_M_STA) 622619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags |= 622719d332feSfei feng - Sun Microsystems - Beijing China LE_32(RXON_FILTER_BCON_AWARE_MSK); 622819d332feSfei feng - Sun Microsystems - Beijing China 622919d332feSfei feng - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x" 623019d332feSfei feng - Sun Microsystems - Beijing China " filter_flags %x\n", 623119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.chan, sc->sc_config.flags, 623219d332feSfei feng - Sun Microsystems - Beijing China sc->sc_config.filter_flags)); 623319d332feSfei feng - Sun Microsystems - Beijing China 623419d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config, 623519d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_rxon_cmd_t), 1); 623619d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 623719d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_run_state_config_sta(): " 623819d332feSfei feng - Sun Microsystems - Beijing China "failed to update configuration\n"); 623919d332feSfei feng - Sun Microsystems - Beijing China return (err); 624019d332feSfei feng - Sun Microsystems - Beijing China } 624119d332feSfei feng - Sun Microsystems - Beijing China 624219d332feSfei feng - Sun Microsystems - Beijing China return (err); 624319d332feSfei feng - Sun Microsystems - Beijing China } 624419d332feSfei feng - Sun Microsystems - Beijing China 624519d332feSfei feng - Sun Microsystems - Beijing China static int 62466f12def4Spengcheng chen - Sun Microsystems - Beijing China iwk_fast_recover(iwk_sc_t *sc) 62476f12def4Spengcheng chen - Sun Microsystems - Beijing China { 62486f12def4Spengcheng chen - Sun Microsystems - Beijing China ieee80211com_t *ic = &sc->sc_ic; 62496f12def4Spengcheng chen - Sun Microsystems - Beijing China int err; 62506f12def4Spengcheng chen - Sun Microsystems - Beijing China 62516f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_enter(&sc->sc_glock); 62526f12def4Spengcheng chen - Sun Microsystems - Beijing China 62536f12def4Spengcheng chen - Sun Microsystems - Beijing China /* restore runtime configuration */ 62546f12def4Spengcheng chen - Sun Microsystems - Beijing China bcopy(&sc->sc_config_save, &sc->sc_config, 62556f12def4Spengcheng chen - Sun Microsystems - Beijing China sizeof (sc->sc_config)); 62566f12def4Spengcheng chen - Sun Microsystems - Beijing China 62576f12def4Spengcheng chen - Sun Microsystems - Beijing China /* reset state to handle reassociations correctly */ 62586f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.assoc_id = 0; 62596f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_config.filter_flags &= 62606f12def4Spengcheng chen - Sun Microsystems - Beijing China ~LE_32(RXON_FILTER_ASSOC_MSK); 62616f12def4Spengcheng chen - Sun Microsystems - Beijing China 62626f12def4Spengcheng chen - Sun Microsystems - Beijing China if ((err = iwk_hw_set_before_auth(sc)) != 0) { 62636f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): " 62646f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to setup authentication\n"); 62656f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 62666f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err); 62676f12def4Spengcheng chen - Sun Microsystems - Beijing China } 62686f12def4Spengcheng chen - Sun Microsystems - Beijing China 62696f12def4Spengcheng chen - Sun Microsystems - Beijing China bcopy(&sc->sc_config_save, &sc->sc_config, 62706f12def4Spengcheng chen - Sun Microsystems - Beijing China sizeof (sc->sc_config)); 62716f12def4Spengcheng chen - Sun Microsystems - Beijing China 62726f12def4Spengcheng chen - Sun Microsystems - Beijing China /* update adapter's configuration */ 62736f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_run_state_config_sta(ic); 62746f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 62756f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): " 62766f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to setup association\n"); 62776f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 62786f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err); 62796f12def4Spengcheng chen - Sun Microsystems - Beijing China } 62806f12def4Spengcheng chen - Sun Microsystems - Beijing China 62816f12def4Spengcheng chen - Sun Microsystems - Beijing China /* obtain current temperature of chipset */ 62826f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_tempera = iwk_curr_tempera(sc); 62836f12def4Spengcheng chen - Sun Microsystems - Beijing China 62846f12def4Spengcheng chen - Sun Microsystems - Beijing China /* 62856f12def4Spengcheng chen - Sun Microsystems - Beijing China * make Tx power calibration to determine 62866f12def4Spengcheng chen - Sun Microsystems - Beijing China * the gains of DSP and radio 62876f12def4Spengcheng chen - Sun Microsystems - Beijing China */ 62886f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_tx_power_calibration(sc); 62896f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err) { 62906f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): " 62916f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to set tx power table\n"); 62926f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 62936f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err); 62946f12def4Spengcheng chen - Sun Microsystems - Beijing China } 62956f12def4Spengcheng chen - Sun Microsystems - Beijing China 62966f12def4Spengcheng chen - Sun Microsystems - Beijing China /* 62976f12def4Spengcheng chen - Sun Microsystems - Beijing China * make initialization for Receiver 62986f12def4Spengcheng chen - Sun Microsystems - Beijing China * sensitivity calibration 62996f12def4Spengcheng chen - Sun Microsystems - Beijing China */ 63006f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_rx_sens_init(sc); 63016f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err) { 63026f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): " 63036f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to init RX sensitivity\n"); 63046f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 63056f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err); 63066f12def4Spengcheng chen - Sun Microsystems - Beijing China } 63076f12def4Spengcheng chen - Sun Microsystems - Beijing China 63086f12def4Spengcheng chen - Sun Microsystems - Beijing China /* make initialization for Receiver gain balance */ 63096f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_rxgain_diff_init(sc); 63106f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err) { 63116f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): " 63126f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to init phy calibration\n"); 63136f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 63146f12def4Spengcheng chen - Sun Microsystems - Beijing China return (err); 63156f12def4Spengcheng chen - Sun Microsystems - Beijing China 63166f12def4Spengcheng chen - Sun Microsystems - Beijing China } 63176f12def4Spengcheng chen - Sun Microsystems - Beijing China /* set LED on */ 63186f12def4Spengcheng chen - Sun Microsystems - Beijing China iwk_set_led(sc, 2, 0, 1); 63196f12def4Spengcheng chen - Sun Microsystems - Beijing China 63206f12def4Spengcheng chen - Sun Microsystems - Beijing China mutex_exit(&sc->sc_glock); 63216f12def4Spengcheng chen - Sun Microsystems - Beijing China 63226f12def4Spengcheng chen - Sun Microsystems - Beijing China /* update keys */ 63236f12def4Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_PRIVACY) { 63246f12def4Spengcheng chen - Sun Microsystems - Beijing China for (int i = 0; i < IEEE80211_KEY_MAX; i++) { 63256f12def4Spengcheng chen - Sun Microsystems - Beijing China if (ic->ic_nw_keys[i].wk_keyix == IEEE80211_KEYIX_NONE) 63266f12def4Spengcheng chen - Sun Microsystems - Beijing China continue; 63276f12def4Spengcheng chen - Sun Microsystems - Beijing China err = iwk_key_set(ic, &ic->ic_nw_keys[i], 63286f12def4Spengcheng chen - Sun Microsystems - Beijing China ic->ic_bss->in_macaddr); 63296f12def4Spengcheng chen - Sun Microsystems - Beijing China /* failure */ 63306f12def4Spengcheng chen - Sun Microsystems - Beijing China if (err == 0) { 63316f12def4Spengcheng chen - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_fast_recover(): " 63326f12def4Spengcheng chen - Sun Microsystems - Beijing China "failed to setup hardware keys\n"); 63336f12def4Spengcheng chen - Sun Microsystems - Beijing China return (IWK_FAIL); 63346f12def4Spengcheng chen - Sun Microsystems - Beijing China } 63356f12def4Spengcheng chen - Sun Microsystems - Beijing China } 63366f12def4Spengcheng chen - Sun Microsystems - Beijing China } 63376f12def4Spengcheng chen - Sun Microsystems - Beijing China 63386f12def4Spengcheng chen - Sun Microsystems - Beijing China sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER; 63396f12def4Spengcheng chen - Sun Microsystems - Beijing China 63406f12def4Spengcheng chen - Sun Microsystems - Beijing China /* start queue */ 63416f12def4Spengcheng chen - Sun Microsystems - Beijing China IWK_DBG((IWK_DEBUG_FW, "iwk_fast_recover(): resume xmit\n")); 63426f12def4Spengcheng chen - Sun Microsystems - Beijing China mac_tx_update(ic->ic_mach); 63436f12def4Spengcheng chen - Sun Microsystems - Beijing China 63446f12def4Spengcheng chen - Sun Microsystems - Beijing China 63456f12def4Spengcheng chen - Sun Microsystems - Beijing China return (IWK_SUCCESS); 63466f12def4Spengcheng chen - Sun Microsystems - Beijing China } 63476f12def4Spengcheng chen - Sun Microsystems - Beijing China 63486f12def4Spengcheng chen - Sun Microsystems - Beijing China static int 634919d332feSfei feng - Sun Microsystems - Beijing China iwk_start_tx_beacon(ieee80211com_t *ic) 635019d332feSfei feng - Sun Microsystems - Beijing China { 635119d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic; 635219d332feSfei feng - Sun Microsystems - Beijing China ieee80211_node_t *in = ic->ic_bss; 635319d332feSfei feng - Sun Microsystems - Beijing China int err = IWK_SUCCESS; 635419d332feSfei feng - Sun Microsystems - Beijing China iwk_tx_beacon_cmd_t *tx_beacon_p; 635519d332feSfei feng - Sun Microsystems - Beijing China uint16_t masks = 0; 635619d332feSfei feng - Sun Microsystems - Beijing China mblk_t *mp; 635719d332feSfei feng - Sun Microsystems - Beijing China int rate; 635819d332feSfei feng - Sun Microsystems - Beijing China 635919d332feSfei feng - Sun Microsystems - Beijing China /* 636019d332feSfei feng - Sun Microsystems - Beijing China * allocate and transmit beacon frames 636119d332feSfei feng - Sun Microsystems - Beijing China */ 636219d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p = &sc->sc_ibss.ibss_beacon.beacon_cmd; 636319d332feSfei feng - Sun Microsystems - Beijing China 636419d332feSfei feng - Sun Microsystems - Beijing China (void) memset(tx_beacon_p, 0, 636519d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_tx_beacon_cmd_t)); 636619d332feSfei feng - Sun Microsystems - Beijing China rate = 0; 636719d332feSfei feng - Sun Microsystems - Beijing China masks = 0; 636819d332feSfei feng - Sun Microsystems - Beijing China 636919d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.sta_id = IWK_BROADCAST_ID; 637019d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.stop_time.life_time = 637119d332feSfei feng - Sun Microsystems - Beijing China LE_32(0xffffffff); 637219d332feSfei feng - Sun Microsystems - Beijing China 637319d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_beacon.mp != NULL) { 637419d332feSfei feng - Sun Microsystems - Beijing China freemsg(sc->sc_ibss.ibss_beacon.mp); 637519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.mp = NULL; 637619d332feSfei feng - Sun Microsystems - Beijing China } 637719d332feSfei feng - Sun Microsystems - Beijing China 637819d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.mp = 637919d332feSfei feng - Sun Microsystems - Beijing China ieee80211_beacon_alloc(ic, in, 638019d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.iwk_boff); 638119d332feSfei feng - Sun Microsystems - Beijing China if (sc->sc_ibss.ibss_beacon.mp == NULL) { 638219d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_start_tx_beacon(): " 638319d332feSfei feng - Sun Microsystems - Beijing China "failed to get beacon frame.\n"); 638419d332feSfei feng - Sun Microsystems - Beijing China return (IWK_FAIL); 638519d332feSfei feng - Sun Microsystems - Beijing China } 638619d332feSfei feng - Sun Microsystems - Beijing China 638719d332feSfei feng - Sun Microsystems - Beijing China mp = sc->sc_ibss.ibss_beacon.mp; 638819d332feSfei feng - Sun Microsystems - Beijing China 638919d332feSfei feng - Sun Microsystems - Beijing China ASSERT(mp->b_cont == NULL); 639019d332feSfei feng - Sun Microsystems - Beijing China 639119d332feSfei feng - Sun Microsystems - Beijing China bcopy(mp->b_rptr, tx_beacon_p->bcon_frame, MBLKL(mp)); 639219d332feSfei feng - Sun Microsystems - Beijing China 6393b510adaeSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.len = LE_16((uint16_t)(MBLKL(mp))); 639419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd_len = 639519d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_tx_cmd_t) + 6396b510adaeSfei feng - Sun Microsystems - Beijing China 4 + LE_16(tx_beacon_p->config.len); 639719d332feSfei feng - Sun Microsystems - Beijing China 639819d332feSfei feng - Sun Microsystems - Beijing China /* 639919d332feSfei feng - Sun Microsystems - Beijing China * beacons are sent at 1M 640019d332feSfei feng - Sun Microsystems - Beijing China */ 640119d332feSfei feng - Sun Microsystems - Beijing China rate = in->in_rates.ir_rates[0]; 640219d332feSfei feng - Sun Microsystems - Beijing China rate &= IEEE80211_RATE_VAL; 640319d332feSfei feng - Sun Microsystems - Beijing China 640419d332feSfei feng - Sun Microsystems - Beijing China if (2 == rate || 4 == rate || 11 == rate || 640519d332feSfei feng - Sun Microsystems - Beijing China 22 == rate) { 640619d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_CCK_MSK; 640719d332feSfei feng - Sun Microsystems - Beijing China } 640819d332feSfei feng - Sun Microsystems - Beijing China 640919d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_ANT_B_MSK; 641019d332feSfei feng - Sun Microsystems - Beijing China 641119d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.rate.r.rate_n_flags = 6412b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(rate) | masks); 641319d332feSfei feng - Sun Microsystems - Beijing China 641419d332feSfei feng - Sun Microsystems - Beijing China 641519d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->config.tx_flags = 6416b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK); 641719d332feSfei feng - Sun Microsystems - Beijing China 641819d332feSfei feng - Sun Microsystems - Beijing China if (ic->ic_bss->in_tstamp.tsf != 0) { 641919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.syncbeacon = 1; 642019d332feSfei feng - Sun Microsystems - Beijing China } else { 642119d332feSfei feng - Sun Microsystems - Beijing China if (ieee80211_beacon_update(ic, in, 642219d332feSfei feng - Sun Microsystems - Beijing China &sc->sc_ibss.ibss_beacon.iwk_boff, 642319d332feSfei feng - Sun Microsystems - Beijing China mp, 0)) { 642419d332feSfei feng - Sun Microsystems - Beijing China bcopy(mp->b_rptr, 642519d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p->bcon_frame, 642619d332feSfei feng - Sun Microsystems - Beijing China MBLKL(mp)); 642719d332feSfei feng - Sun Microsystems - Beijing China } 642819d332feSfei feng - Sun Microsystems - Beijing China 642919d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_BEACON, 643019d332feSfei feng - Sun Microsystems - Beijing China tx_beacon_p, 643119d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.beacon_cmd_len, 643219d332feSfei feng - Sun Microsystems - Beijing China 1); 643319d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 643419d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_start_tx_beacon(): " 643519d332feSfei feng - Sun Microsystems - Beijing China "failed to TX beacon.\n"); 643619d332feSfei feng - Sun Microsystems - Beijing China return (err); 643719d332feSfei feng - Sun Microsystems - Beijing China } 643819d332feSfei feng - Sun Microsystems - Beijing China 643919d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_beacon.syncbeacon = 0; 644019d332feSfei feng - Sun Microsystems - Beijing China } 644119d332feSfei feng - Sun Microsystems - Beijing China 644219d332feSfei feng - Sun Microsystems - Beijing China return (err); 644319d332feSfei feng - Sun Microsystems - Beijing China } 644419d332feSfei feng - Sun Microsystems - Beijing China 644519d332feSfei feng - Sun Microsystems - Beijing China static int 644619d332feSfei feng - Sun Microsystems - Beijing China iwk_clean_add_node_ibss(struct ieee80211com *ic, 644719d332feSfei feng - Sun Microsystems - Beijing China uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2) 644819d332feSfei feng - Sun Microsystems - Beijing China { 644919d332feSfei feng - Sun Microsystems - Beijing China iwk_sc_t *sc = (iwk_sc_t *)ic; 645019d332feSfei feng - Sun Microsystems - Beijing China uint8_t index; 645119d332feSfei feng - Sun Microsystems - Beijing China iwk_add_sta_t bc_node; 645219d332feSfei feng - Sun Microsystems - Beijing China iwk_link_quality_cmd_t bc_link_quality; 645319d332feSfei feng - Sun Microsystems - Beijing China iwk_link_quality_cmd_t link_quality; 645419d332feSfei feng - Sun Microsystems - Beijing China uint16_t bc_masks = 0; 645519d332feSfei feng - Sun Microsystems - Beijing China uint16_t masks = 0; 645619d332feSfei feng - Sun Microsystems - Beijing China int i, rate; 645719d332feSfei feng - Sun Microsystems - Beijing China struct ieee80211_rateset rs; 645819d332feSfei feng - Sun Microsystems - Beijing China iwk_ibss_node_t *ibss_node_p; 645919d332feSfei feng - Sun Microsystems - Beijing China int err = IWK_SUCCESS; 646019d332feSfei feng - Sun Microsystems - Beijing China 646119d332feSfei feng - Sun Microsystems - Beijing China /* 646219d332feSfei feng - Sun Microsystems - Beijing China * find a location that is not 646319d332feSfei feng - Sun Microsystems - Beijing China * used in ibss node table 646419d332feSfei feng - Sun Microsystems - Beijing China */ 646519d332feSfei feng - Sun Microsystems - Beijing China for (index = IWK_STA_ID; 646619d332feSfei feng - Sun Microsystems - Beijing China index < IWK_STATION_COUNT; index++) { 646719d332feSfei feng - Sun Microsystems - Beijing China if (!sc->sc_ibss.ibss_node_tb[index].used) { 646819d332feSfei feng - Sun Microsystems - Beijing China break; 646919d332feSfei feng - Sun Microsystems - Beijing China } 647019d332feSfei feng - Sun Microsystems - Beijing China } 647119d332feSfei feng - Sun Microsystems - Beijing China 647219d332feSfei feng - Sun Microsystems - Beijing China /* 647319d332feSfei feng - Sun Microsystems - Beijing China * if have too many nodes in hardware, clean up 647419d332feSfei feng - Sun Microsystems - Beijing China */ 647519d332feSfei feng - Sun Microsystems - Beijing China if (index < IWK_BROADCAST_ID && 647619d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number >= 25) { 647719d332feSfei feng - Sun Microsystems - Beijing China if (iwk_cmd(sc, REPLY_REMOVE_ALL_STA, 647819d332feSfei feng - Sun Microsystems - Beijing China NULL, 0, 1) != IWK_SUCCESS) { 647919d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): " 648019d332feSfei feng - Sun Microsystems - Beijing China "failed to remove all nodes in hardware\n"); 648119d332feSfei feng - Sun Microsystems - Beijing China return (IWK_FAIL); 648219d332feSfei feng - Sun Microsystems - Beijing China } 648319d332feSfei feng - Sun Microsystems - Beijing China 648419d332feSfei feng - Sun Microsystems - Beijing China for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) { 648519d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.ibss_node_tb[i].used = 0; 648619d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&sc->sc_ibss.ibss_node_tb[i].node, 648719d332feSfei feng - Sun Microsystems - Beijing China 0, sizeof (iwk_add_sta_t)); 648819d332feSfei feng - Sun Microsystems - Beijing China } 648919d332feSfei feng - Sun Microsystems - Beijing China 649019d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number = 0; 649119d332feSfei feng - Sun Microsystems - Beijing China 649219d332feSfei feng - Sun Microsystems - Beijing China /* 649319d332feSfei feng - Sun Microsystems - Beijing China * add broadcast node so that we 649419d332feSfei feng - Sun Microsystems - Beijing China * can send broadcast frame 649519d332feSfei feng - Sun Microsystems - Beijing China */ 649619d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&bc_node, 0, sizeof (bc_node)); 649719d332feSfei feng - Sun Microsystems - Beijing China (void) memset(bc_node.bssid, 0xff, 6); 649819d332feSfei feng - Sun Microsystems - Beijing China bc_node.id = IWK_BROADCAST_ID; 649919d332feSfei feng - Sun Microsystems - Beijing China 650019d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA, &bc_node, sizeof (bc_node), 1); 650119d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 650219d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): " 650319d332feSfei feng - Sun Microsystems - Beijing China "failed to add broadcast node\n"); 650419d332feSfei feng - Sun Microsystems - Beijing China return (err); 650519d332feSfei feng - Sun Microsystems - Beijing China } 650619d332feSfei feng - Sun Microsystems - Beijing China 650719d332feSfei feng - Sun Microsystems - Beijing China /* TX_LINK_QUALITY cmd */ 650819d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&bc_link_quality, 0, sizeof (bc_link_quality)); 650919d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 651019d332feSfei feng - Sun Microsystems - Beijing China bc_masks |= RATE_MCS_CCK_MSK; 651119d332feSfei feng - Sun Microsystems - Beijing China bc_masks |= RATE_MCS_ANT_B_MSK; 651219d332feSfei feng - Sun Microsystems - Beijing China bc_masks &= ~RATE_MCS_ANT_A_MSK; 651319d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.rate_n_flags[i] = 6514b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(2) | bc_masks); 651519d332feSfei feng - Sun Microsystems - Beijing China } 651619d332feSfei feng - Sun Microsystems - Beijing China 651719d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.general_params.single_stream_ant_msk = 2; 651819d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.general_params.dual_stream_ant_msk = 3; 651919d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.agg_params.agg_dis_start_th = 3; 652019d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.agg_params.agg_time_limit = LE_16(4000); 652119d332feSfei feng - Sun Microsystems - Beijing China bc_link_quality.sta_id = IWK_BROADCAST_ID; 652219d332feSfei feng - Sun Microsystems - Beijing China 652319d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, 652419d332feSfei feng - Sun Microsystems - Beijing China &bc_link_quality, sizeof (bc_link_quality), 1); 652519d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 652619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): " 652719d332feSfei feng - Sun Microsystems - Beijing China "failed to config link quality table\n"); 652819d332feSfei feng - Sun Microsystems - Beijing China return (err); 652919d332feSfei feng - Sun Microsystems - Beijing China } 653019d332feSfei feng - Sun Microsystems - Beijing China } 653119d332feSfei feng - Sun Microsystems - Beijing China 653219d332feSfei feng - Sun Microsystems - Beijing China if (index >= IWK_BROADCAST_ID) { 653319d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): " 653419d332feSfei feng - Sun Microsystems - Beijing China "the count of node in hardware is too much\n"); 653519d332feSfei feng - Sun Microsystems - Beijing China return (IWK_FAIL); 653619d332feSfei feng - Sun Microsystems - Beijing China } 653719d332feSfei feng - Sun Microsystems - Beijing China 653819d332feSfei feng - Sun Microsystems - Beijing China /* 653919d332feSfei feng - Sun Microsystems - Beijing China * add a node into hardware 654019d332feSfei feng - Sun Microsystems - Beijing China */ 654119d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p = &sc->sc_ibss.ibss_node_tb[index]; 654219d332feSfei feng - Sun Microsystems - Beijing China 654319d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->used = 1; 654419d332feSfei feng - Sun Microsystems - Beijing China 654519d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&ibss_node_p->node, 0, 654619d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t)); 654719d332feSfei feng - Sun Microsystems - Beijing China 654819d332feSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(ibss_node_p->node.bssid, addr); 654919d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->node.id = index; 655019d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->node.control = 0; 655119d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->node.flags = 0; 655219d332feSfei feng - Sun Microsystems - Beijing China 655319d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_ADD_STA, &ibss_node_p->node, 655419d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t), 1); 655519d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 655619d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): " 655719d332feSfei feng - Sun Microsystems - Beijing China "failed to add IBSS node\n"); 655819d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->used = 0; 655919d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&ibss_node_p->node, 0, 656019d332feSfei feng - Sun Microsystems - Beijing China sizeof (iwk_add_sta_t)); 656119d332feSfei feng - Sun Microsystems - Beijing China return (err); 656219d332feSfei feng - Sun Microsystems - Beijing China } 656319d332feSfei feng - Sun Microsystems - Beijing China 656419d332feSfei feng - Sun Microsystems - Beijing China sc->sc_ibss.node_number++; 656519d332feSfei feng - Sun Microsystems - Beijing China 656619d332feSfei feng - Sun Microsystems - Beijing China (void) memset(&link_quality, 0, sizeof (link_quality)); 656719d332feSfei feng - Sun Microsystems - Beijing China 656819d332feSfei feng - Sun Microsystems - Beijing China rs = ic->ic_sup_rates[ieee80211_chan2mode(ic, 656919d332feSfei feng - Sun Microsystems - Beijing China ic->ic_curchan)]; 657019d332feSfei feng - Sun Microsystems - Beijing China 657119d332feSfei feng - Sun Microsystems - Beijing China for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 657219d332feSfei feng - Sun Microsystems - Beijing China if (i < rs.ir_nrates) { 657319d332feSfei feng - Sun Microsystems - Beijing China rate = rs. 657419d332feSfei feng - Sun Microsystems - Beijing China ir_rates[rs.ir_nrates - i]; 657519d332feSfei feng - Sun Microsystems - Beijing China } else { 657619d332feSfei feng - Sun Microsystems - Beijing China rate = 2; 657719d332feSfei feng - Sun Microsystems - Beijing China } 657819d332feSfei feng - Sun Microsystems - Beijing China 657919d332feSfei feng - Sun Microsystems - Beijing China if (2 == rate || 4 == rate || 658019d332feSfei feng - Sun Microsystems - Beijing China 11 == rate || 22 == rate) { 658119d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_CCK_MSK; 658219d332feSfei feng - Sun Microsystems - Beijing China } 658319d332feSfei feng - Sun Microsystems - Beijing China 658419d332feSfei feng - Sun Microsystems - Beijing China masks |= RATE_MCS_ANT_B_MSK; 658519d332feSfei feng - Sun Microsystems - Beijing China masks &= ~RATE_MCS_ANT_A_MSK; 658619d332feSfei feng - Sun Microsystems - Beijing China 658719d332feSfei feng - Sun Microsystems - Beijing China link_quality.rate_n_flags[i] = 6588b510adaeSfei feng - Sun Microsystems - Beijing China LE_32(iwk_rate_to_plcp(rate) | masks); 658919d332feSfei feng - Sun Microsystems - Beijing China } 659019d332feSfei feng - Sun Microsystems - Beijing China 659119d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.single_stream_ant_msk = 2; 659219d332feSfei feng - Sun Microsystems - Beijing China link_quality.general_params.dual_stream_ant_msk = 3; 659319d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_dis_start_th = 3; 659419d332feSfei feng - Sun Microsystems - Beijing China link_quality.agg_params.agg_time_limit = LE_16(4000); 659519d332feSfei feng - Sun Microsystems - Beijing China link_quality.sta_id = ibss_node_p->node.id; 659619d332feSfei feng - Sun Microsystems - Beijing China 659719d332feSfei feng - Sun Microsystems - Beijing China err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, 659819d332feSfei feng - Sun Microsystems - Beijing China &link_quality, sizeof (link_quality), 1); 659919d332feSfei feng - Sun Microsystems - Beijing China if (err != IWK_SUCCESS) { 660019d332feSfei feng - Sun Microsystems - Beijing China cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): " 660119d332feSfei feng - Sun Microsystems - Beijing China "failed to set up TX link quality\n"); 660219d332feSfei feng - Sun Microsystems - Beijing China ibss_node_p->used = 0; 660319d332feSfei feng - Sun Microsystems - Beijing China (void) memset(ibss_node_p->node.bssid, 0, 6); 660419d332feSfei feng - Sun Microsystems - Beijing China return (err); 660519d332feSfei feng - Sun Microsystems - Beijing China } 660619d332feSfei feng - Sun Microsystems - Beijing China 660719d332feSfei feng - Sun Microsystems - Beijing China *index2 = index; 660819d332feSfei feng - Sun Microsystems - Beijing China 660919d332feSfei feng - Sun Microsystems - Beijing China return (err); 661019d332feSfei feng - Sun Microsystems - Beijing China } 6611