1 /*
   2  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * Copyright (c) 2007, Intel Corporation
   8  * All rights reserved.
   9  */
  10 
  11 /*
  12  * Copyright (c) 2006
  13  * Copyright (c) 2007
  14  *      Damien Bergamini <damien.bergamini@free.fr>
  15  *
  16  * Permission to use, copy, modify, and distribute this software for any
  17  * purpose with or without fee is hereby granted, provided that the above
  18  * copyright notice and this permission notice appear in all copies.
  19  *
  20  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  21  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  22  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  23  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  24  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  25  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  26  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27  */
  28 
  29 /*
  30  * Driver for Intel PRO/Wireless 4965AGN(kedron) 802.11 network adapters.
  31  */
  32 
  33 #include <sys/types.h>
  34 #include <sys/byteorder.h>
  35 #include <sys/conf.h>
  36 #include <sys/cmn_err.h>
  37 #include <sys/stat.h>
  38 #include <sys/ddi.h>
  39 #include <sys/sunddi.h>
  40 #include <sys/strsubr.h>
  41 #include <sys/ethernet.h>
  42 #include <inet/common.h>
  43 #include <inet/nd.h>
  44 #include <inet/mi.h>
  45 #include <sys/note.h>
  46 #include <sys/stream.h>
  47 #include <sys/strsun.h>
  48 #include <sys/modctl.h>
  49 #include <sys/devops.h>
  50 #include <sys/dlpi.h>
  51 #include <sys/mac_provider.h>
  52 #include <sys/mac_wifi.h>
  53 #include <sys/net80211.h>
  54 #include <sys/net80211_proto.h>
  55 #include <sys/varargs.h>
  56 #include <sys/policy.h>
  57 #include <sys/pci.h>
  58 
  59 #include "iwk_calibration.h"
  60 #include "iwk_hw.h"
  61 #include "iwk_eeprom.h"
  62 #include "iwk2_var.h"
  63 #include <inet/wifi_ioctl.h>
  64 
  65 #ifdef DEBUG
  66 #define IWK_DEBUG_80211         (1 << 0)
  67 #define IWK_DEBUG_CMD           (1 << 1)
  68 #define IWK_DEBUG_DMA           (1 << 2)
  69 #define IWK_DEBUG_EEPROM        (1 << 3)
  70 #define IWK_DEBUG_FW            (1 << 4)
  71 #define IWK_DEBUG_HW            (1 << 5)
  72 #define IWK_DEBUG_INTR          (1 << 6)
  73 #define IWK_DEBUG_MRR           (1 << 7)
  74 #define IWK_DEBUG_PIO           (1 << 8)
  75 #define IWK_DEBUG_RX            (1 << 9)
  76 #define IWK_DEBUG_SCAN          (1 << 10)
  77 #define IWK_DEBUG_TX            (1 << 11)
  78 #define IWK_DEBUG_RATECTL       (1 << 12)
  79 #define IWK_DEBUG_RADIO         (1 << 13)
  80 #define IWK_DEBUG_RESUME        (1 << 14)
  81 #define IWK_DEBUG_CALIBRATION   (1 << 15)
  82 uint32_t iwk_dbg_flags = 0;
  83 #define IWK_DBG(x) \
  84         iwk_dbg x
  85 #else
  86 #define IWK_DBG(x)
  87 #endif
  88 
  89 static void     *iwk_soft_state_p = NULL;
  90 static uint8_t iwk_fw_bin [] = {
  91 #include "fw-iw/iw4965.ucode.hex"
  92 };
  93 
  94 /* DMA attributes for a shared page */
  95 static ddi_dma_attr_t sh_dma_attr = {
  96         DMA_ATTR_V0,    /* version of this structure */
  97         0,              /* lowest usable address */
  98         0xffffffffU,    /* highest usable address */
  99         0xffffffffU,    /* maximum DMAable byte count */
 100         0x1000,         /* alignment in bytes */
 101         0x1000,         /* burst sizes (any?) */
 102         1,              /* minimum transfer */
 103         0xffffffffU,    /* maximum transfer */
 104         0xffffffffU,    /* maximum segment length */
 105         1,              /* maximum number of segments */
 106         1,              /* granularity */
 107         0,              /* flags (reserved) */
 108 };
 109 
 110 /* DMA attributes for a keep warm DRAM descriptor */
 111 static ddi_dma_attr_t kw_dma_attr = {
 112         DMA_ATTR_V0,    /* version of this structure */
 113         0,              /* lowest usable address */
 114         0xffffffffU,    /* highest usable address */
 115         0xffffffffU,    /* maximum DMAable byte count */
 116         0x1000,         /* alignment in bytes */
 117         0x1000,         /* burst sizes (any?) */
 118         1,              /* minimum transfer */
 119         0xffffffffU,    /* maximum transfer */
 120         0xffffffffU,    /* maximum segment length */
 121         1,              /* maximum number of segments */
 122         1,              /* granularity */
 123         0,              /* flags (reserved) */
 124 };
 125 
 126 /* DMA attributes for a ring descriptor */
 127 static ddi_dma_attr_t ring_desc_dma_attr = {
 128         DMA_ATTR_V0,    /* version of this structure */
 129         0,              /* lowest usable address */
 130         0xffffffffU,    /* highest usable address */
 131         0xffffffffU,    /* maximum DMAable byte count */
 132         0x100,          /* alignment in bytes */
 133         0x100,          /* burst sizes (any?) */
 134         1,              /* minimum transfer */
 135         0xffffffffU,    /* maximum transfer */
 136         0xffffffffU,    /* maximum segment length */
 137         1,              /* maximum number of segments */
 138         1,              /* granularity */
 139         0,              /* flags (reserved) */
 140 };
 141 
 142 /* DMA attributes for a cmd */
 143 static ddi_dma_attr_t cmd_dma_attr = {
 144         DMA_ATTR_V0,    /* version of this structure */
 145         0,              /* lowest usable address */
 146         0xffffffffU,    /* highest usable address */
 147         0xffffffffU,    /* maximum DMAable byte count */
 148         4,              /* alignment in bytes */
 149         0x100,          /* burst sizes (any?) */
 150         1,              /* minimum transfer */
 151         0xffffffffU,    /* maximum transfer */
 152         0xffffffffU,    /* maximum segment length */
 153         1,              /* maximum number of segments */
 154         1,              /* granularity */
 155         0,              /* flags (reserved) */
 156 };
 157 
 158 /* DMA attributes for a rx buffer */
 159 static ddi_dma_attr_t rx_buffer_dma_attr = {
 160         DMA_ATTR_V0,    /* version of this structure */
 161         0,              /* lowest usable address */
 162         0xffffffffU,    /* highest usable address */
 163         0xffffffffU,    /* maximum DMAable byte count */
 164         0x100,          /* alignment in bytes */
 165         0x100,          /* burst sizes (any?) */
 166         1,              /* minimum transfer */
 167         0xffffffffU,    /* maximum transfer */
 168         0xffffffffU,    /* maximum segment length */
 169         1,              /* maximum number of segments */
 170         1,              /* granularity */
 171         0,              /* flags (reserved) */
 172 };
 173 
 174 /*
 175  * DMA attributes for a tx buffer.
 176  * the maximum number of segments is 4 for the hardware.
 177  * now all the wifi drivers put the whole frame in a single
 178  * descriptor, so we define the maximum  number of segments 1,
 179  * just the same as the rx_buffer. we consider leverage the HW
 180  * ability in the future, that is why we don't define rx and tx
 181  * buffer_dma_attr as the same.
 182  */
 183 static ddi_dma_attr_t tx_buffer_dma_attr = {
 184         DMA_ATTR_V0,    /* version of this structure */
 185         0,              /* lowest usable address */
 186         0xffffffffU,    /* highest usable address */
 187         0xffffffffU,    /* maximum DMAable byte count */
 188         4,              /* alignment in bytes */
 189         0x100,          /* burst sizes (any?) */
 190         1,              /* minimum transfer */
 191         0xffffffffU,    /* maximum transfer */
 192         0xffffffffU,    /* maximum segment length */
 193         1,              /* maximum number of segments */
 194         1,              /* granularity */
 195         0,              /* flags (reserved) */
 196 };
 197 
 198 /* DMA attributes for text and data part in the firmware */
 199 static ddi_dma_attr_t fw_dma_attr = {
 200         DMA_ATTR_V0,    /* version of this structure */
 201         0,              /* lowest usable address */
 202         0xffffffffU,    /* highest usable address */
 203         0x7fffffff,     /* maximum DMAable byte count */
 204         0x10,           /* alignment in bytes */
 205         0x100,          /* burst sizes (any?) */
 206         1,              /* minimum transfer */
 207         0xffffffffU,    /* maximum transfer */
 208         0xffffffffU,    /* maximum segment length */
 209         1,              /* maximum number of segments */
 210         1,              /* granularity */
 211         0,              /* flags (reserved) */
 212 };
 213 
 214 
 215 /* regs access attributes */
 216 static ddi_device_acc_attr_t iwk_reg_accattr = {
 217         DDI_DEVICE_ATTR_V0,
 218         DDI_STRUCTURE_LE_ACC,
 219         DDI_STRICTORDER_ACC,
 220         DDI_DEFAULT_ACC
 221 };
 222 
 223 /* DMA access attributes for Descriptor */
 224 static ddi_device_acc_attr_t iwk_dma_descattr = {
 225         DDI_DEVICE_ATTR_V0,
 226         DDI_STRUCTURE_LE_ACC,
 227         DDI_STRICTORDER_ACC,
 228         DDI_DEFAULT_ACC
 229 };
 230 
 231 /* DMA access attributes */
 232 static ddi_device_acc_attr_t iwk_dma_accattr = {
 233         DDI_DEVICE_ATTR_V0,
 234         DDI_NEVERSWAP_ACC,
 235         DDI_STRICTORDER_ACC,
 236         DDI_DEFAULT_ACC
 237 };
 238 
 239 static int      iwk_ring_init(iwk_sc_t *);
 240 static void     iwk_ring_free(iwk_sc_t *);
 241 static int      iwk_alloc_shared(iwk_sc_t *);
 242 static void     iwk_free_shared(iwk_sc_t *);
 243 static int      iwk_alloc_kw(iwk_sc_t *);
 244 static void     iwk_free_kw(iwk_sc_t *);
 245 static int      iwk_alloc_fw_dma(iwk_sc_t *);
 246 static void     iwk_free_fw_dma(iwk_sc_t *);
 247 static int      iwk_alloc_rx_ring(iwk_sc_t *);
 248 static void     iwk_reset_rx_ring(iwk_sc_t *);
 249 static void     iwk_free_rx_ring(iwk_sc_t *);
 250 static int      iwk_alloc_tx_ring(iwk_sc_t *, iwk_tx_ring_t *,
 251     int, int);
 252 static void     iwk_reset_tx_ring(iwk_sc_t *, iwk_tx_ring_t *);
 253 static void     iwk_free_tx_ring(iwk_sc_t *, iwk_tx_ring_t *);
 254 
 255 static ieee80211_node_t *iwk_node_alloc(ieee80211com_t *);
 256 static void     iwk_node_free(ieee80211_node_t *);
 257 static int      iwk_newstate(ieee80211com_t *, enum ieee80211_state, int);
 258 static int      iwk_key_set(ieee80211com_t *, const struct ieee80211_key *,
 259     const uint8_t mac[IEEE80211_ADDR_LEN]);
 260 static void     iwk_mac_access_enter(iwk_sc_t *);
 261 static void     iwk_mac_access_exit(iwk_sc_t *);
 262 static uint32_t iwk_reg_read(iwk_sc_t *, uint32_t);
 263 static void     iwk_reg_write(iwk_sc_t *, uint32_t, uint32_t);
 264 static void     iwk_reg_write_region_4(iwk_sc_t *, uint32_t,
 265                     uint32_t *, int);
 266 static int      iwk_load_firmware(iwk_sc_t *);
 267 static void     iwk_rx_intr(iwk_sc_t *, iwk_rx_desc_t *,
 268                     iwk_rx_data_t *);
 269 static void     iwk_tx_intr(iwk_sc_t *, iwk_rx_desc_t *,
 270                     iwk_rx_data_t *);
 271 static void     iwk_cmd_intr(iwk_sc_t *, iwk_rx_desc_t *);
 272 static uint_t   iwk_intr(caddr_t, caddr_t);
 273 static int      iwk_eep_load(iwk_sc_t *sc);
 274 static void     iwk_get_mac_from_eep(iwk_sc_t *sc);
 275 static int      iwk_eep_sem_down(iwk_sc_t *sc);
 276 static void     iwk_eep_sem_up(iwk_sc_t *sc);
 277 static uint_t   iwk_rx_softintr(caddr_t, caddr_t);
 278 static uint8_t  iwk_rate_to_plcp(int);
 279 static int      iwk_cmd(iwk_sc_t *, int, const void *, int, int);
 280 static void     iwk_set_led(iwk_sc_t *, uint8_t, uint8_t, uint8_t);
 281 static int      iwk_hw_set_before_auth(iwk_sc_t *);
 282 static int      iwk_scan(iwk_sc_t *);
 283 static int      iwk_config(iwk_sc_t *);
 284 static void     iwk_stop_master(iwk_sc_t *);
 285 static int      iwk_power_up(iwk_sc_t *);
 286 static int      iwk_preinit(iwk_sc_t *);
 287 static int      iwk_init(iwk_sc_t *);
 288 static void     iwk_stop(iwk_sc_t *);
 289 static void     iwk_amrr_init(iwk_amrr_t *);
 290 static void     iwk_amrr_timeout(iwk_sc_t *);
 291 static void     iwk_amrr_ratectl(void *, ieee80211_node_t *);
 292 static int32_t  iwk_curr_tempera(iwk_sc_t *sc);
 293 static int      iwk_tx_power_calibration(iwk_sc_t *sc);
 294 static inline int       iwk_is_24G_band(iwk_sc_t *sc);
 295 static inline int       iwk_is_fat_channel(iwk_sc_t *sc);
 296 static int      iwk_txpower_grp(uint16_t channel);
 297 static struct   iwk_eep_channel *iwk_get_eep_channel(iwk_sc_t *sc,
 298     uint16_t channel,
 299     int is_24G, int is_fat, int is_hi_chan);
 300 static int32_t  iwk_band_number(iwk_sc_t *sc, uint16_t channel);
 301 static int      iwk_division(int32_t num, int32_t denom, int32_t *res);
 302 static int32_t  iwk_interpolate_value(int32_t x, int32_t x1, int32_t y1,
 303     int32_t x2, int32_t y2);
 304 static int      iwk_channel_interpolate(iwk_sc_t *sc, uint16_t channel,
 305     struct iwk_eep_calib_channel_info *chan_info);
 306 static int32_t  iwk_voltage_compensation(int32_t eep_voltage,
 307     int32_t curr_voltage);
 308 static int32_t  iwk_min_power_index(int32_t rate_pow_idx, int32_t is_24G);
 309 static int      iwk_txpower_table_cmd_init(iwk_sc_t *sc,
 310     struct iwk_tx_power_db *tp_db);
 311 static void     iwk_statistics_notify(iwk_sc_t *sc, iwk_rx_desc_t *desc);
 312 static int      iwk_is_associated(iwk_sc_t *sc);
 313 static int      iwk_rxgain_diff_init(iwk_sc_t *sc);
 314 static int      iwk_rxgain_diff(iwk_sc_t *sc);
 315 static int      iwk_rx_sens_init(iwk_sc_t *sc);
 316 static int      iwk_rx_sens(iwk_sc_t *sc);
 317 static int      iwk_cck_sens(iwk_sc_t *sc, uint32_t actual_rx_time);
 318 static int      iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time);
 319 static void     iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp,
 320     struct ieee80211_node *in, int subtype, int rssi, uint32_t rstamp);
 321 
 322 static void     iwk_write_event_log(iwk_sc_t *);
 323 static void     iwk_write_error_log(iwk_sc_t *);
 324 
 325 static int      iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 326 static int      iwk_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
 327 static int      iwk_quiesce(dev_info_t *dip);
 328 
 329 /*
 330  * GLD specific operations
 331  */
 332 static int      iwk_m_stat(void *arg, uint_t stat, uint64_t *val);
 333 static int      iwk_m_start(void *arg);
 334 static void     iwk_m_stop(void *arg);
 335 static int      iwk_m_unicst(void *arg, const uint8_t *macaddr);
 336 static int      iwk_m_multicst(void *arg, boolean_t add, const uint8_t *m);
 337 static int      iwk_m_promisc(void *arg, boolean_t on);
 338 static mblk_t   *iwk_m_tx(void *arg, mblk_t *mp);
 339 static void     iwk_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
 340 static int      iwk_m_setprop(void *arg, const char *pr_name,
 341         mac_prop_id_t wldp_pr_name, uint_t wldp_length, const void *wldp_buf);
 342 static int      iwk_m_getprop(void *arg, const char *pr_name,
 343         mac_prop_id_t wldp_pr_name, uint_t wldp_length, void *wldp_buf);
 344 static void     iwk_m_propinfo(void *arg, const char *pr_name,
 345     mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
 346 static void     iwk_destroy_locks(iwk_sc_t *sc);
 347 static int      iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type);
 348 static void     iwk_thread(iwk_sc_t *sc);
 349 static void     iwk_watchdog(void *arg);
 350 static int      iwk_run_state_config_ibss(ieee80211com_t *ic);
 351 static int      iwk_run_state_config_sta(ieee80211com_t *ic);
 352 static int      iwk_fast_recover(iwk_sc_t *sc);
 353 static int      iwk_start_tx_beacon(ieee80211com_t *ic);
 354 static int      iwk_clean_add_node_ibss(struct ieee80211com *ic,
 355     uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2);
 356 
 357 /*
 358  * Supported rates for 802.11b/g modes (in 500Kbps unit).
 359  * 11a and 11n support will be added later.
 360  */
 361 static const struct ieee80211_rateset iwk_rateset_11b =
 362         { 4, { 2, 4, 11, 22 } };
 363 
 364 static const struct ieee80211_rateset iwk_rateset_11g =
 365         { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
 366 
 367 /*
 368  * For mfthread only
 369  */
 370 extern pri_t minclsyspri;
 371 
 372 #define DRV_NAME_4965   "iwk"
 373 
 374 /*
 375  * Module Loading Data & Entry Points
 376  */
 377 DDI_DEFINE_STREAM_OPS(iwk_devops, nulldev, nulldev, iwk_attach,
 378     iwk_detach, nodev, NULL, D_MP, NULL, iwk_quiesce);
 379 
 380 static struct modldrv iwk_modldrv = {
 381         &mod_driverops,
 382         "Intel(R) 4965AGN driver(N)",
 383         &iwk_devops
 384 };
 385 
 386 static struct modlinkage iwk_modlinkage = {
 387         MODREV_1,
 388         { &iwk_modldrv, NULL }
 389 };
 390 
 391 int
 392 _init(void)
 393 {
 394         int     status;
 395 
 396         status = ddi_soft_state_init(&iwk_soft_state_p,
 397             sizeof (iwk_sc_t), 1);
 398         if (status != DDI_SUCCESS)
 399                 return (status);
 400 
 401         mac_init_ops(&iwk_devops, DRV_NAME_4965);
 402         status = mod_install(&iwk_modlinkage);
 403         if (status != DDI_SUCCESS) {
 404                 mac_fini_ops(&iwk_devops);
 405                 ddi_soft_state_fini(&iwk_soft_state_p);
 406         }
 407 
 408         return (status);
 409 }
 410 
 411 int
 412 _fini(void)
 413 {
 414         int status;
 415 
 416         status = mod_remove(&iwk_modlinkage);
 417         if (status == DDI_SUCCESS) {
 418                 mac_fini_ops(&iwk_devops);
 419                 ddi_soft_state_fini(&iwk_soft_state_p);
 420         }
 421 
 422         return (status);
 423 }
 424 
 425 int
 426 _info(struct modinfo *mip)
 427 {
 428         return (mod_info(&iwk_modlinkage, mip));
 429 }
 430 
 431 /*
 432  * Mac Call Back entries
 433  */
 434 mac_callbacks_t iwk_m_callbacks = {
 435         MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
 436         iwk_m_stat,
 437         iwk_m_start,
 438         iwk_m_stop,
 439         iwk_m_promisc,
 440         iwk_m_multicst,
 441         iwk_m_unicst,
 442         iwk_m_tx,
 443         NULL,
 444         iwk_m_ioctl,
 445         NULL,
 446         NULL,
 447         NULL,
 448         iwk_m_setprop,
 449         iwk_m_getprop,
 450         iwk_m_propinfo
 451 };
 452 
 453 #ifdef DEBUG
 454 void
 455 iwk_dbg(uint32_t flags, const char *fmt, ...)
 456 {
 457         va_list ap;
 458 
 459         if (flags & iwk_dbg_flags) {
 460                 va_start(ap, fmt);
 461                 vcmn_err(CE_NOTE, fmt, ap);
 462                 va_end(ap);
 463         }
 464 }
 465 #endif
 466 
 467 /*
 468  * device operations
 469  */
 470 int
 471 iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 472 {
 473         iwk_sc_t                *sc;
 474         ieee80211com_t  *ic;
 475         int                     instance, err, i;
 476         char                    strbuf[32];
 477         wifi_data_t             wd = { 0 };
 478         mac_register_t          *macp;
 479 
 480         int                     intr_type;
 481         int                     intr_count;
 482         int                     intr_actual;
 483 
 484         switch (cmd) {
 485         case DDI_ATTACH:
 486                 break;
 487         case DDI_RESUME:
 488                 sc = ddi_get_soft_state(iwk_soft_state_p,
 489                     ddi_get_instance(dip));
 490                 ASSERT(sc != NULL);
 491 
 492                 mutex_enter(&sc->sc_glock);
 493                 sc->sc_flags &= ~IWK_F_SUSPEND;
 494                 mutex_exit(&sc->sc_glock);
 495 
 496                 if (sc->sc_flags & IWK_F_RUNNING)
 497                         (void) iwk_init(sc);
 498 
 499                 mutex_enter(&sc->sc_glock);
 500                 sc->sc_flags |= IWK_F_LAZY_RESUME;
 501                 mutex_exit(&sc->sc_glock);
 502 
 503                 IWK_DBG((IWK_DEBUG_RESUME, "iwk: resume\n"));
 504                 return (DDI_SUCCESS);
 505         default:
 506                 err = DDI_FAILURE;
 507                 goto attach_fail1;
 508         }
 509 
 510         instance = ddi_get_instance(dip);
 511         err = ddi_soft_state_zalloc(iwk_soft_state_p, instance);
 512         if (err != DDI_SUCCESS) {
 513                 cmn_err(CE_WARN,
 514                     "iwk_attach(): failed to allocate soft state\n");
 515                 goto attach_fail1;
 516         }
 517         sc = ddi_get_soft_state(iwk_soft_state_p, instance);
 518         sc->sc_dip = dip;
 519 
 520         err = ddi_regs_map_setup(dip, 0, &sc->sc_cfg_base, 0, 0,
 521             &iwk_reg_accattr, &sc->sc_cfg_handle);
 522         if (err != DDI_SUCCESS) {
 523                 cmn_err(CE_WARN,
 524                     "iwk_attach(): failed to map config spaces regs\n");
 525                 goto attach_fail2;
 526         }
 527         sc->sc_rev = ddi_get8(sc->sc_cfg_handle,
 528             (uint8_t *)(sc->sc_cfg_base + PCI_CONF_REVID));
 529         ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0x41), 0);
 530         sc->sc_clsz = ddi_get16(sc->sc_cfg_handle,
 531             (uint16_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
 532         if (!sc->sc_clsz)
 533                 sc->sc_clsz = 16;
 534         sc->sc_clsz = (sc->sc_clsz << 2);
 535         sc->sc_dmabuf_sz = roundup(0x1000 + sizeof (struct ieee80211_frame) +
 536             IEEE80211_MTU + IEEE80211_CRC_LEN +
 537             (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
 538             IEEE80211_WEP_CRCLEN), sc->sc_clsz);
 539         /*
 540          * Map operating registers
 541          */
 542         err = ddi_regs_map_setup(dip, 1, &sc->sc_base,
 543             0, 0, &iwk_reg_accattr, &sc->sc_handle);
 544         if (err != DDI_SUCCESS) {
 545                 cmn_err(CE_WARN,
 546                     "iwk_attach(): failed to map device regs\n");
 547                 goto attach_fail2a;
 548         }
 549 
 550         err = ddi_intr_get_supported_types(dip, &intr_type);
 551         if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) {
 552                 cmn_err(CE_WARN, "iwk_attach(): "
 553                     "Fixed type interrupt is not supported\n");
 554                 goto attach_fail_intr_a;
 555         }
 556 
 557         err = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &intr_count);
 558         if ((err != DDI_SUCCESS) || (intr_count != 1)) {
 559                 cmn_err(CE_WARN, "iwk_attach(): "
 560                     "No fixed interrupts\n");
 561                 goto attach_fail_intr_a;
 562         }
 563 
 564         sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
 565 
 566         err = ddi_intr_alloc(dip, sc->sc_intr_htable, DDI_INTR_TYPE_FIXED, 0,
 567             intr_count, &intr_actual, 0);
 568         if ((err != DDI_SUCCESS) || (intr_actual != 1)) {
 569                 cmn_err(CE_WARN, "iwk_attach(): "
 570                     "ddi_intr_alloc() failed 0x%x\n", err);
 571                 goto attach_fail_intr_b;
 572         }
 573 
 574         err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri);
 575         if (err != DDI_SUCCESS) {
 576                 cmn_err(CE_WARN, "iwk_attach(): "
 577                     "ddi_intr_get_pri() failed 0x%x\n", err);
 578                 goto attach_fail_intr_c;
 579         }
 580 
 581         mutex_init(&sc->sc_glock, NULL, MUTEX_DRIVER,
 582             DDI_INTR_PRI(sc->sc_intr_pri));
 583         mutex_init(&sc->sc_tx_lock, NULL, MUTEX_DRIVER,
 584             DDI_INTR_PRI(sc->sc_intr_pri));
 585         mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER,
 586             DDI_INTR_PRI(sc->sc_intr_pri));
 587         mutex_init(&sc->sc_ibss.node_tb_lock, NULL, MUTEX_DRIVER,
 588             DDI_INTR_PRI(sc->sc_intr_pri));
 589 
 590         cv_init(&sc->sc_fw_cv, NULL, CV_DRIVER, NULL);
 591         cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL);
 592         cv_init(&sc->sc_tx_cv, "tx-ring", CV_DRIVER, NULL);
 593         /*
 594          * initialize the mfthread
 595          */
 596         cv_init(&sc->sc_mt_cv, NULL, CV_DRIVER, NULL);
 597         sc->sc_mf_thread = NULL;
 598         sc->sc_mf_thread_switch = 0;
 599 
 600         /*
 601          * Allocate shared page.
 602          */
 603         err = iwk_alloc_shared(sc);
 604         if (err != DDI_SUCCESS) {
 605                 cmn_err(CE_WARN, "iwk_attach(): "
 606                     "failed to allocate shared page\n");
 607                 goto attach_fail3;
 608         }
 609 
 610         /*
 611          * Allocate keep warm page.
 612          */
 613         err = iwk_alloc_kw(sc);
 614         if (err != DDI_SUCCESS) {
 615                 cmn_err(CE_WARN, "iwk_attach(): "
 616                     "failed to allocate keep warm page\n");
 617                 goto attach_fail3a;
 618         }
 619 
 620         /*
 621          * Do some necessary hardware initializations.
 622          */
 623         err = iwk_preinit(sc);
 624         if (err != DDI_SUCCESS) {
 625                 cmn_err(CE_WARN, "iwk_attach(): "
 626                     "failed to init hardware\n");
 627                 goto attach_fail4;
 628         }
 629 
 630         /* initialize EEPROM */
 631         err = iwk_eep_load(sc);  /* get hardware configurations from eeprom */
 632         if (err != 0) {
 633                 cmn_err(CE_WARN, "iwk_attach(): failed to load eeprom\n");
 634                 goto attach_fail4;
 635         }
 636 
 637         if (LE_16(sc->sc_eep_map.calib_version) < EEP_TX_POWER_VERSION_NEW) {
 638                 cmn_err(CE_WARN, "older EEPROM detected\n");
 639                 goto attach_fail4;
 640         }
 641 
 642         iwk_get_mac_from_eep(sc);
 643 
 644         err = iwk_ring_init(sc);
 645         if (err != DDI_SUCCESS) {
 646                 cmn_err(CE_WARN, "iwk_attach(): "
 647                     "failed to allocate and initialize ring\n");
 648                 goto attach_fail4;
 649         }
 650 
 651         sc->sc_hdr = (iwk_firmware_hdr_t *)iwk_fw_bin;
 652 
 653         err = iwk_alloc_fw_dma(sc);
 654         if (err != DDI_SUCCESS) {
 655                 cmn_err(CE_WARN, "iwk_attach(): "
 656                     "failed to allocate firmware dma\n");
 657                 goto attach_fail5;
 658         }
 659 
 660         /*
 661          * Initialize the wifi part, which will be used by
 662          * generic layer
 663          */
 664         ic = &sc->sc_ic;
 665         ic->ic_phytype  = IEEE80211_T_OFDM;
 666         ic->ic_opmode   = IEEE80211_M_STA; /* default to BSS mode */
 667         ic->ic_state    = IEEE80211_S_INIT;
 668         ic->ic_maxrssi  = 100; /* experimental number */
 669         ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT |
 670             IEEE80211_C_PMGT | IEEE80211_C_SHSLOT;
 671         /*
 672          * use software WEP and TKIP, hardware CCMP;
 673          */
 674         ic->ic_caps |= IEEE80211_C_AES_CCM;
 675         /*
 676          * Support WPA/WPA2
 677          */
 678         ic->ic_caps |= IEEE80211_C_WPA;
 679         /*
 680          * support Adhoc mode
 681          */
 682         ic->ic_caps |= IEEE80211_C_IBSS;
 683 
 684         /* set supported .11b and .11g rates */
 685         ic->ic_sup_rates[IEEE80211_MODE_11B] = iwk_rateset_11b;
 686         ic->ic_sup_rates[IEEE80211_MODE_11G] = iwk_rateset_11g;
 687 
 688         /* set supported .11b and .11g channels (1 through 11) */
 689         for (i = 1; i <= 11; i++) {
 690                 ic->ic_sup_channels[i].ich_freq =
 691                     ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
 692                 ic->ic_sup_channels[i].ich_flags =
 693                     IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
 694                     IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ |
 695                     IEEE80211_CHAN_PASSIVE;
 696         }
 697         ic->ic_ibss_chan = &ic->ic_sup_channels[0];
 698 
 699         ic->ic_xmit = iwk_send;
 700         /*
 701          * init Wifi layer
 702          */
 703         ieee80211_attach(ic);
 704 
 705         /*
 706          * different instance has different WPA door
 707          */
 708         (void) snprintf(ic->ic_wpadoor, MAX_IEEE80211STR, "%s_%s%d", WPA_DOOR,
 709             ddi_driver_name(dip),
 710             ddi_get_instance(dip));
 711 
 712         /*
 713          * Override 80211 default routines
 714          */
 715         sc->sc_newstate = ic->ic_newstate;
 716         ic->ic_newstate = iwk_newstate;
 717         ic->ic_watchdog = iwk_watchdog;
 718         sc->sc_recv_mgmt = ic->ic_recv_mgmt;
 719         ic->ic_recv_mgmt = iwk_recv_mgmt;
 720         ic->ic_node_alloc = iwk_node_alloc;
 721         ic->ic_node_free = iwk_node_free;
 722         ic->ic_crypto.cs_key_set = iwk_key_set;
 723         ieee80211_media_init(ic);
 724         /*
 725          * initialize default tx key
 726          */
 727         ic->ic_def_txkey = 0;
 728         err = ddi_intr_add_softint(dip, &sc->sc_soft_hdl, DDI_INTR_SOFTPRI_MAX,
 729             iwk_rx_softintr, (caddr_t)sc);
 730         if (err != DDI_SUCCESS) {
 731                 cmn_err(CE_WARN, "iwk_attach(): "
 732                     "add soft interrupt failed\n");
 733                 goto attach_fail7;
 734         }
 735 
 736         /*
 737          * Add the interrupt handler
 738          */
 739         err = ddi_intr_add_handler(sc->sc_intr_htable[0], iwk_intr,
 740             (caddr_t)sc, NULL);
 741         if (err != DDI_SUCCESS) {
 742                 cmn_err(CE_WARN, "iwk_attach(): "
 743                     "ddi_intr_add_handle() failed\n");
 744                 goto attach_fail8;
 745         }
 746 
 747         err = ddi_intr_enable(sc->sc_intr_htable[0]);
 748         if (err != DDI_SUCCESS) {
 749                 cmn_err(CE_WARN, "iwk_attach(): "
 750                     "ddi_intr_enable() failed\n");
 751                 goto attach_fail_intr_d;
 752         }
 753 
 754         /*
 755          * Initialize pointer to device specific functions
 756          */
 757         wd.wd_secalloc = WIFI_SEC_NONE;
 758         wd.wd_opmode = ic->ic_opmode;
 759         IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
 760 
 761         macp = mac_alloc(MAC_VERSION);
 762         if (macp == NULL) {
 763                 cmn_err(CE_WARN,
 764                     "iwk_attach(): failed to do mac_alloc()\n");
 765                 goto attach_fail9;
 766         }
 767 
 768         macp->m_type_ident   = MAC_PLUGIN_IDENT_WIFI;
 769         macp->m_driver               = sc;
 770         macp->m_dip          = dip;
 771         macp->m_src_addr     = ic->ic_macaddr;
 772         macp->m_callbacks    = &iwk_m_callbacks;
 773         macp->m_min_sdu              = 0;
 774         macp->m_max_sdu              = IEEE80211_MTU;
 775         macp->m_pdata                = &wd;
 776         macp->m_pdata_size   = sizeof (wd);
 777 
 778         /*
 779          * Register the macp to mac
 780          */
 781         err = mac_register(macp, &ic->ic_mach);
 782         mac_free(macp);
 783         if (err != DDI_SUCCESS) {
 784                 cmn_err(CE_WARN,
 785                     "iwk_attach(): failed to do mac_register()\n");
 786                 goto attach_fail9;
 787         }
 788 
 789         /*
 790          * Create minor node of type DDI_NT_NET_WIFI
 791          */
 792         (void) snprintf(strbuf, sizeof (strbuf), DRV_NAME_4965"%d", instance);
 793         err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
 794             instance + 1, DDI_NT_NET_WIFI, 0);
 795         if (err != DDI_SUCCESS)
 796                 cmn_err(CE_WARN,
 797                     "iwk_attach(): failed to do ddi_create_minor_node()\n");
 798 
 799         /*
 800          * Notify link is down now
 801          */
 802         mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
 803 
 804         /*
 805          * create the mf thread to handle the link status,
 806          * recovery fatal error, etc.
 807          */
 808         sc->sc_mf_thread_switch = 1;
 809         if (sc->sc_mf_thread == NULL)
 810                 sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
 811                     iwk_thread, sc, 0, &p0, TS_RUN, minclsyspri);
 812 
 813         sc->sc_flags |= IWK_F_ATTACHED;
 814 
 815         return (DDI_SUCCESS);
 816 attach_fail9:
 817         (void) ddi_intr_disable(sc->sc_intr_htable[0]);
 818 attach_fail_intr_d:
 819         (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
 820 
 821 attach_fail8:
 822         (void) ddi_intr_remove_softint(sc->sc_soft_hdl);
 823         sc->sc_soft_hdl = NULL;
 824 attach_fail7:
 825         ieee80211_detach(ic);
 826 attach_fail6:
 827         iwk_free_fw_dma(sc);
 828 attach_fail5:
 829         iwk_ring_free(sc);
 830 attach_fail4:
 831         iwk_free_kw(sc);
 832 attach_fail3a:
 833         iwk_free_shared(sc);
 834 attach_fail3:
 835         iwk_destroy_locks(sc);
 836 attach_fail_intr_c:
 837         (void) ddi_intr_free(sc->sc_intr_htable[0]);
 838 attach_fail_intr_b:
 839         kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
 840 attach_fail_intr_a:
 841         ddi_regs_map_free(&sc->sc_handle);
 842 attach_fail2a:
 843         ddi_regs_map_free(&sc->sc_cfg_handle);
 844 attach_fail2:
 845         ddi_soft_state_free(iwk_soft_state_p, instance);
 846 attach_fail1:
 847         return (err);
 848 }
 849 
 850 int
 851 iwk_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 852 {
 853         iwk_sc_t        *sc;
 854         int err;
 855 
 856         sc = ddi_get_soft_state(iwk_soft_state_p, ddi_get_instance(dip));
 857         ASSERT(sc != NULL);
 858 
 859         switch (cmd) {
 860         case DDI_DETACH:
 861                 break;
 862         case DDI_SUSPEND:
 863                 mutex_enter(&sc->sc_glock);
 864                 sc->sc_flags |= IWK_F_SUSPEND;
 865                 mutex_exit(&sc->sc_glock);
 866                 if (sc->sc_flags & IWK_F_RUNNING) {
 867                         iwk_stop(sc);
 868                 }
 869 
 870                 IWK_DBG((IWK_DEBUG_RESUME, "iwk: suspend\n"));
 871                 return (DDI_SUCCESS);
 872         default:
 873                 return (DDI_FAILURE);
 874         }
 875 
 876         if (!(sc->sc_flags & IWK_F_ATTACHED))
 877                 return (DDI_FAILURE);
 878 
 879         err = mac_disable(sc->sc_ic.ic_mach);
 880         if (err != DDI_SUCCESS)
 881                 return (err);
 882 
 883         /*
 884          * Destroy the mf_thread
 885          */
 886         mutex_enter(&sc->sc_mt_lock);
 887         sc->sc_mf_thread_switch = 0;
 888         while (sc->sc_mf_thread != NULL) {
 889                 if (cv_wait_sig(&sc->sc_mt_cv, &sc->sc_mt_lock) == 0)
 890                         break;
 891         }
 892         mutex_exit(&sc->sc_mt_lock);
 893 
 894         iwk_stop(sc);
 895         DELAY(500000);
 896 
 897         /*
 898          * Unregiste from the MAC layer subsystem
 899          */
 900         (void) mac_unregister(sc->sc_ic.ic_mach);
 901 
 902         mutex_enter(&sc->sc_glock);
 903         iwk_free_fw_dma(sc);
 904         iwk_ring_free(sc);
 905         iwk_free_kw(sc);
 906         iwk_free_shared(sc);
 907         mutex_exit(&sc->sc_glock);
 908 
 909         (void) ddi_intr_disable(sc->sc_intr_htable[0]);
 910         (void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
 911         (void) ddi_intr_free(sc->sc_intr_htable[0]);
 912         kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
 913 
 914         (void) ddi_intr_remove_softint(sc->sc_soft_hdl);
 915         sc->sc_soft_hdl = NULL;
 916 
 917         /*
 918          * detach ieee80211
 919          */
 920         ieee80211_detach(&sc->sc_ic);
 921 
 922         iwk_destroy_locks(sc);
 923 
 924         ddi_regs_map_free(&sc->sc_handle);
 925         ddi_regs_map_free(&sc->sc_cfg_handle);
 926         ddi_remove_minor_node(dip, NULL);
 927         ddi_soft_state_free(iwk_soft_state_p, ddi_get_instance(dip));
 928 
 929         return (DDI_SUCCESS);
 930 }
 931 
 932 /*
 933  * quiesce(9E) entry point.
 934  *
 935  * This function is called when the system is single-threaded at high
 936  * PIL with preemption disabled. Therefore, this function must not be
 937  * blocked.
 938  *
 939  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
 940  * DDI_FAILURE indicates an error condition and should almost never happen.
 941  */
 942 int
 943 iwk_quiesce(dev_info_t *dip)
 944 {
 945         iwk_sc_t        *sc;
 946 
 947         sc = ddi_get_soft_state(iwk_soft_state_p, ddi_get_instance(dip));
 948         ASSERT(sc != NULL);
 949 
 950         /* no message prints and no lock accquisition */
 951 #ifdef DEBUG
 952         iwk_dbg_flags = 0;
 953 #endif
 954         sc->sc_flags |= IWK_F_QUIESCED;
 955 
 956         iwk_stop(sc);
 957 
 958         return (DDI_SUCCESS);
 959 }
 960 
 961 static void
 962 iwk_destroy_locks(iwk_sc_t *sc)
 963 {
 964         cv_destroy(&sc->sc_mt_cv);
 965         mutex_destroy(&sc->sc_mt_lock);
 966         cv_destroy(&sc->sc_tx_cv);
 967         cv_destroy(&sc->sc_cmd_cv);
 968         cv_destroy(&sc->sc_fw_cv);
 969         mutex_destroy(&sc->sc_tx_lock);
 970         mutex_destroy(&sc->sc_glock);
 971 }
 972 
 973 /*
 974  * Allocate an area of memory and a DMA handle for accessing it
 975  */
 976 static int
 977 iwk_alloc_dma_mem(iwk_sc_t *sc, size_t memsize,
 978     ddi_dma_attr_t *dma_attr_p, ddi_device_acc_attr_t *acc_attr_p,
 979     uint_t dma_flags, iwk_dma_t *dma_p)
 980 {
 981         caddr_t vaddr;
 982         int err;
 983 
 984         /*
 985          * Allocate handle
 986          */
 987         err = ddi_dma_alloc_handle(sc->sc_dip, dma_attr_p,
 988             DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
 989         if (err != DDI_SUCCESS) {
 990                 dma_p->dma_hdl = NULL;
 991                 return (DDI_FAILURE);
 992         }
 993 
 994         /*
 995          * Allocate memory
 996          */
 997         err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, acc_attr_p,
 998             dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING),
 999             DDI_DMA_SLEEP, NULL, &vaddr, &dma_p->alength, &dma_p->acc_hdl);
1000         if (err != DDI_SUCCESS) {
1001                 ddi_dma_free_handle(&dma_p->dma_hdl);
1002                 dma_p->dma_hdl = NULL;
1003                 dma_p->acc_hdl = NULL;
1004                 return (DDI_FAILURE);
1005         }
1006 
1007         /*
1008          * Bind the two together
1009          */
1010         dma_p->mem_va = vaddr;
1011         err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
1012             vaddr, dma_p->alength, dma_flags, DDI_DMA_SLEEP, NULL,
1013             &dma_p->cookie, &dma_p->ncookies);
1014         if (err != DDI_DMA_MAPPED) {
1015                 ddi_dma_mem_free(&dma_p->acc_hdl);
1016                 ddi_dma_free_handle(&dma_p->dma_hdl);
1017                 dma_p->acc_hdl = NULL;
1018                 dma_p->dma_hdl = NULL;
1019                 return (DDI_FAILURE);
1020         }
1021 
1022         dma_p->nslots = ~0U;
1023         dma_p->size = ~0U;
1024         dma_p->token = ~0U;
1025         dma_p->offset = 0;
1026         return (DDI_SUCCESS);
1027 }
1028 
1029 /*
1030  * Free one allocated area of DMAable memory
1031  */
1032 static void
1033 iwk_free_dma_mem(iwk_dma_t *dma_p)
1034 {
1035         if (dma_p->dma_hdl != NULL) {
1036                 if (dma_p->ncookies) {
1037                         (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
1038                         dma_p->ncookies = 0;
1039                 }
1040                 ddi_dma_free_handle(&dma_p->dma_hdl);
1041                 dma_p->dma_hdl = NULL;
1042         }
1043 
1044         if (dma_p->acc_hdl != NULL) {
1045                 ddi_dma_mem_free(&dma_p->acc_hdl);
1046                 dma_p->acc_hdl = NULL;
1047         }
1048 }
1049 
1050 /*
1051  *
1052  */
1053 static int
1054 iwk_alloc_fw_dma(iwk_sc_t *sc)
1055 {
1056         int err = DDI_SUCCESS;
1057         iwk_dma_t *dma_p;
1058         char *t;
1059 
1060         /*
1061          * firmware image layout:
1062          * |HDR|<-TEXT->|<-DATA->|<-INIT_TEXT->|<-INIT_DATA->|<-BOOT->|
1063          */
1064         t = (char *)(sc->sc_hdr + 1);
1065         err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->textsz),
1066             &fw_dma_attr, &iwk_dma_accattr,
1067             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1068             &sc->sc_dma_fw_text);
1069         dma_p = &sc->sc_dma_fw_text;
1070         IWK_DBG((IWK_DEBUG_DMA, "text[ncookies:%d addr:%lx size:%lx]\n",
1071             dma_p->ncookies, dma_p->cookie.dmac_address,
1072             dma_p->cookie.dmac_size));
1073         if (err != DDI_SUCCESS) {
1074                 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1075                     " text dma memory");
1076                 goto fail;
1077         }
1078         (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->textsz));
1079 
1080         t += LE_32(sc->sc_hdr->textsz);
1081         err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1082             &fw_dma_attr, &iwk_dma_accattr,
1083             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1084             &sc->sc_dma_fw_data);
1085         dma_p = &sc->sc_dma_fw_data;
1086         IWK_DBG((IWK_DEBUG_DMA, "data[ncookies:%d addr:%lx size:%lx]\n",
1087             dma_p->ncookies, dma_p->cookie.dmac_address,
1088             dma_p->cookie.dmac_size));
1089         if (err != DDI_SUCCESS) {
1090                 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1091                     " data dma memory");
1092                 goto fail;
1093         }
1094         (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz));
1095 
1096         err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->datasz),
1097             &fw_dma_attr, &iwk_dma_accattr,
1098             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1099             &sc->sc_dma_fw_data_bak);
1100         dma_p = &sc->sc_dma_fw_data_bak;
1101         IWK_DBG((IWK_DEBUG_DMA, "data_bak[ncookies:%d addr:%lx "
1102             "size:%lx]\n",
1103             dma_p->ncookies, dma_p->cookie.dmac_address,
1104             dma_p->cookie.dmac_size));
1105         if (err != DDI_SUCCESS) {
1106                 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1107                     " data bakeup dma memory");
1108                 goto fail;
1109         }
1110         (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->datasz));
1111 
1112         t += LE_32(sc->sc_hdr->datasz);
1113         err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_textsz),
1114             &fw_dma_attr, &iwk_dma_accattr,
1115             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1116             &sc->sc_dma_fw_init_text);
1117         dma_p = &sc->sc_dma_fw_init_text;
1118         IWK_DBG((IWK_DEBUG_DMA, "init_text[ncookies:%d addr:%lx "
1119             "size:%lx]\n",
1120             dma_p->ncookies, dma_p->cookie.dmac_address,
1121             dma_p->cookie.dmac_size));
1122         if (err != DDI_SUCCESS) {
1123                 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1124                     "init text dma memory");
1125                 goto fail;
1126         }
1127         (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_textsz));
1128 
1129         t += LE_32(sc->sc_hdr->init_textsz);
1130         err = iwk_alloc_dma_mem(sc, LE_32(sc->sc_hdr->init_datasz),
1131             &fw_dma_attr, &iwk_dma_accattr,
1132             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1133             &sc->sc_dma_fw_init_data);
1134         dma_p = &sc->sc_dma_fw_init_data;
1135         IWK_DBG((IWK_DEBUG_DMA, "init_data[ncookies:%d addr:%lx "
1136             "size:%lx]\n",
1137             dma_p->ncookies, dma_p->cookie.dmac_address,
1138             dma_p->cookie.dmac_size));
1139         if (err != DDI_SUCCESS) {
1140                 cmn_err(CE_WARN, "iwk_alloc_fw_dma(): failed to alloc"
1141                     "init data dma memory");
1142                 goto fail;
1143         }
1144         (void) memcpy(dma_p->mem_va, t, LE_32(sc->sc_hdr->init_datasz));
1145 
1146         sc->sc_boot = t + LE_32(sc->sc_hdr->init_datasz);
1147 fail:
1148         return (err);
1149 }
1150 
1151 static void
1152 iwk_free_fw_dma(iwk_sc_t *sc)
1153 {
1154         iwk_free_dma_mem(&sc->sc_dma_fw_text);
1155         iwk_free_dma_mem(&sc->sc_dma_fw_data);
1156         iwk_free_dma_mem(&sc->sc_dma_fw_data_bak);
1157         iwk_free_dma_mem(&sc->sc_dma_fw_init_text);
1158         iwk_free_dma_mem(&sc->sc_dma_fw_init_data);
1159 }
1160 
1161 /*
1162  * Allocate a shared page between host and NIC.
1163  */
1164 static int
1165 iwk_alloc_shared(iwk_sc_t *sc)
1166 {
1167         iwk_dma_t *dma_p;
1168         int err = DDI_SUCCESS;
1169 
1170         /* must be aligned on a 4K-page boundary */
1171         err = iwk_alloc_dma_mem(sc, sizeof (iwk_shared_t),
1172             &sh_dma_attr, &iwk_dma_descattr,
1173             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1174             &sc->sc_dma_sh);
1175         if (err != DDI_SUCCESS)
1176                 goto fail;
1177         sc->sc_shared = (iwk_shared_t *)sc->sc_dma_sh.mem_va;
1178 
1179         dma_p = &sc->sc_dma_sh;
1180         IWK_DBG((IWK_DEBUG_DMA, "sh[ncookies:%d addr:%lx size:%lx]\n",
1181             dma_p->ncookies, dma_p->cookie.dmac_address,
1182             dma_p->cookie.dmac_size));
1183 
1184         return (err);
1185 fail:
1186         iwk_free_shared(sc);
1187         return (err);
1188 }
1189 
1190 static void
1191 iwk_free_shared(iwk_sc_t *sc)
1192 {
1193         iwk_free_dma_mem(&sc->sc_dma_sh);
1194 }
1195 
1196 /*
1197  * Allocate a keep warm page.
1198  */
1199 static int
1200 iwk_alloc_kw(iwk_sc_t *sc)
1201 {
1202         iwk_dma_t *dma_p;
1203         int err = DDI_SUCCESS;
1204 
1205         /* must be aligned on a 4K-page boundary */
1206         err = iwk_alloc_dma_mem(sc, IWK_KW_SIZE,
1207             &kw_dma_attr, &iwk_dma_accattr,
1208             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1209             &sc->sc_dma_kw);
1210         if (err != DDI_SUCCESS)
1211                 goto fail;
1212 
1213         dma_p = &sc->sc_dma_kw;
1214         IWK_DBG((IWK_DEBUG_DMA, "kw[ncookies:%d addr:%lx size:%lx]\n",
1215             dma_p->ncookies, dma_p->cookie.dmac_address,
1216             dma_p->cookie.dmac_size));
1217 
1218         return (err);
1219 fail:
1220         iwk_free_kw(sc);
1221         return (err);
1222 }
1223 
1224 static void
1225 iwk_free_kw(iwk_sc_t *sc)
1226 {
1227         iwk_free_dma_mem(&sc->sc_dma_kw);
1228 }
1229 
1230 static int
1231 iwk_alloc_rx_ring(iwk_sc_t *sc)
1232 {
1233         iwk_rx_ring_t *ring;
1234         iwk_rx_data_t *data;
1235         iwk_dma_t *dma_p;
1236         int i, err = DDI_SUCCESS;
1237 
1238         ring = &sc->sc_rxq;
1239         ring->cur = 0;
1240 
1241         err = iwk_alloc_dma_mem(sc, RX_QUEUE_SIZE * sizeof (uint32_t),
1242             &ring_desc_dma_attr, &iwk_dma_descattr,
1243             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1244             &ring->dma_desc);
1245         if (err != DDI_SUCCESS) {
1246                 cmn_err(CE_WARN, "dma alloc rx ring desc failed\n");
1247                 goto fail;
1248         }
1249         ring->desc = (uint32_t *)ring->dma_desc.mem_va;
1250         dma_p = &ring->dma_desc;
1251         IWK_DBG((IWK_DEBUG_DMA, "rx bd[ncookies:%d addr:%lx size:%lx]\n",
1252             dma_p->ncookies, dma_p->cookie.dmac_address,
1253             dma_p->cookie.dmac_size));
1254 
1255         /*
1256          * Allocate Rx buffers.
1257          */
1258         for (i = 0; i < RX_QUEUE_SIZE; i++) {
1259                 data = &ring->data[i];
1260                 err = iwk_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1261                     &rx_buffer_dma_attr, &iwk_dma_accattr,
1262                     DDI_DMA_READ | DDI_DMA_STREAMING,
1263                     &data->dma_data);
1264                 if (err != DDI_SUCCESS) {
1265                         cmn_err(CE_WARN, "dma alloc rx ring buf[%d] "
1266                             "failed\n", i);
1267                         goto fail;
1268                 }
1269                 /*
1270                  * the physical address bit [8-36] are used,
1271                  * instead of bit [0-31] in 3945.
1272                  */
1273                 ring->desc[i] = (uint32_t)
1274                     (data->dma_data.cookie.dmac_address >> 8);
1275         }
1276         dma_p = &ring->data[0].dma_data;
1277         IWK_DBG((IWK_DEBUG_DMA, "rx buffer[0][ncookies:%d addr:%lx "
1278             "size:%lx]\n",
1279             dma_p->ncookies, dma_p->cookie.dmac_address,
1280             dma_p->cookie.dmac_size));
1281 
1282         IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1283 
1284         return (err);
1285 
1286 fail:
1287         iwk_free_rx_ring(sc);
1288         return (err);
1289 }
1290 
1291 static void
1292 iwk_reset_rx_ring(iwk_sc_t *sc)
1293 {
1294         int n;
1295 
1296         iwk_mac_access_enter(sc);
1297         IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
1298         for (n = 0; n < 2000; n++) {
1299                 if (IWK_READ(sc, FH_MEM_RSSR_RX_STATUS_REG) & (1 << 24))
1300                         break;
1301                 DELAY(1000);
1302         }
1303 
1304         if (n == 2000)
1305                 IWK_DBG((IWK_DEBUG_DMA, "timeout resetting Rx ring\n"));
1306 
1307         iwk_mac_access_exit(sc);
1308 
1309         sc->sc_rxq.cur = 0;
1310 }
1311 
1312 static void
1313 iwk_free_rx_ring(iwk_sc_t *sc)
1314 {
1315         int i;
1316 
1317         for (i = 0; i < RX_QUEUE_SIZE; i++) {
1318                 if (sc->sc_rxq.data[i].dma_data.dma_hdl)
1319                         IWK_DMA_SYNC(sc->sc_rxq.data[i].dma_data,
1320                             DDI_DMA_SYNC_FORCPU);
1321                 iwk_free_dma_mem(&sc->sc_rxq.data[i].dma_data);
1322         }
1323 
1324         if (sc->sc_rxq.dma_desc.dma_hdl)
1325                 IWK_DMA_SYNC(sc->sc_rxq.dma_desc, DDI_DMA_SYNC_FORDEV);
1326         iwk_free_dma_mem(&sc->sc_rxq.dma_desc);
1327 }
1328 
1329 static int
1330 iwk_alloc_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring,
1331     int slots, int qid)
1332 {
1333         iwk_tx_data_t *data;
1334         iwk_tx_desc_t *desc_h;
1335         uint32_t paddr_desc_h;
1336         iwk_cmd_t *cmd_h;
1337         uint32_t paddr_cmd_h;
1338         iwk_dma_t *dma_p;
1339         int i, err = DDI_SUCCESS;
1340 
1341         ring->qid = qid;
1342         ring->count = TFD_QUEUE_SIZE_MAX;
1343         ring->window = slots;
1344         ring->queued = 0;
1345         ring->cur = 0;
1346 
1347         err = iwk_alloc_dma_mem(sc,
1348             TFD_QUEUE_SIZE_MAX * sizeof (iwk_tx_desc_t),
1349             &ring_desc_dma_attr, &iwk_dma_descattr,
1350             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1351             &ring->dma_desc);
1352         if (err != DDI_SUCCESS) {
1353                 cmn_err(CE_WARN, "dma alloc tx ring desc[%d] "
1354                     "failed\n", qid);
1355                 goto fail;
1356         }
1357         dma_p = &ring->dma_desc;
1358         IWK_DBG((IWK_DEBUG_DMA, "tx bd[ncookies:%d addr:%lx size:%lx]\n",
1359             dma_p->ncookies, dma_p->cookie.dmac_address,
1360             dma_p->cookie.dmac_size));
1361 
1362         desc_h = (iwk_tx_desc_t *)ring->dma_desc.mem_va;
1363         paddr_desc_h = ring->dma_desc.cookie.dmac_address;
1364 
1365         err = iwk_alloc_dma_mem(sc,
1366             TFD_QUEUE_SIZE_MAX * sizeof (iwk_cmd_t),
1367             &cmd_dma_attr, &iwk_dma_accattr,
1368             DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1369             &ring->dma_cmd);
1370         if (err != DDI_SUCCESS) {
1371                 cmn_err(CE_WARN, "dma alloc tx ring cmd[%d] "
1372                     "failed\n", qid);
1373                 goto fail;
1374         }
1375         dma_p = &ring->dma_cmd;
1376         IWK_DBG((IWK_DEBUG_DMA, "tx cmd[ncookies:%d addr:%lx size:%lx]\n",
1377             dma_p->ncookies, dma_p->cookie.dmac_address,
1378             dma_p->cookie.dmac_size));
1379 
1380         cmd_h = (iwk_cmd_t *)ring->dma_cmd.mem_va;
1381         paddr_cmd_h = ring->dma_cmd.cookie.dmac_address;
1382 
1383         /*
1384          * Allocate Tx buffers.
1385          */
1386         ring->data = kmem_zalloc(sizeof (iwk_tx_data_t) * TFD_QUEUE_SIZE_MAX,
1387             KM_NOSLEEP);
1388         if (ring->data == NULL) {
1389                 cmn_err(CE_WARN, "could not allocate tx data slots\n");
1390                 goto fail;
1391         }
1392 
1393         for (i = 0; i < TFD_QUEUE_SIZE_MAX; i++) {
1394                 data = &ring->data[i];
1395                 err = iwk_alloc_dma_mem(sc, sc->sc_dmabuf_sz,
1396                     &tx_buffer_dma_attr, &iwk_dma_accattr,
1397                     DDI_DMA_WRITE | DDI_DMA_STREAMING,
1398                     &data->dma_data);
1399                 if (err != DDI_SUCCESS) {
1400                         cmn_err(CE_WARN, "dma alloc tx ring "
1401                             "buf[%d] failed\n", i);
1402                         goto fail;
1403                 }
1404 
1405                 data->desc = desc_h + i;
1406                 data->paddr_desc = paddr_desc_h +
1407                     _PTRDIFF(data->desc, desc_h);
1408                 data->cmd = cmd_h +  i; /* (i % slots); */
1409                 /* ((i % slots) * sizeof (iwk_cmd_t)); */
1410                 data->paddr_cmd = paddr_cmd_h +
1411                     _PTRDIFF(data->cmd, cmd_h);
1412         }
1413         dma_p = &ring->data[0].dma_data;
1414         IWK_DBG((IWK_DEBUG_DMA, "tx buffer[0][ncookies:%d addr:%lx "
1415             "size:%lx]\n",
1416             dma_p->ncookies, dma_p->cookie.dmac_address,
1417             dma_p->cookie.dmac_size));
1418 
1419         return (err);
1420 
1421 fail:
1422         if (ring->data)
1423                 kmem_free(ring->data,
1424                     sizeof (iwk_tx_data_t) * TFD_QUEUE_SIZE_MAX);
1425         iwk_free_tx_ring(sc, ring);
1426         return (err);
1427 }
1428 
1429 static void
1430 iwk_reset_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring)
1431 {
1432         iwk_tx_data_t *data;
1433         int i, n;
1434 
1435         iwk_mac_access_enter(sc);
1436 
1437         IWK_WRITE(sc, IWK_FH_TCSR_CHNL_TX_CONFIG_REG(ring->qid), 0);
1438         for (n = 0; n < 200; n++) {
1439                 if (IWK_READ(sc, IWK_FH_TSSR_TX_STATUS_REG) &
1440                     IWK_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ring->qid))
1441                         break;
1442                 DELAY(10);
1443         }
1444         if (n == 200) {
1445                 IWK_DBG((IWK_DEBUG_DMA, "timeout reset tx ring %d\n",
1446                     ring->qid));
1447         }
1448         iwk_mac_access_exit(sc);
1449 
1450         for (i = 0; i < ring->count; i++) {
1451                 data = &ring->data[i];
1452                 IWK_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
1453         }
1454 
1455         ring->queued = 0;
1456         ring->cur = 0;
1457 }
1458 
1459 /*ARGSUSED*/
1460 static void
1461 iwk_free_tx_ring(iwk_sc_t *sc, iwk_tx_ring_t *ring)
1462 {
1463         int i;
1464 
1465         if (ring->dma_desc.dma_hdl != NULL)
1466                 IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
1467         iwk_free_dma_mem(&ring->dma_desc);
1468 
1469         if (ring->dma_cmd.dma_hdl != NULL)
1470                 IWK_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV);
1471         iwk_free_dma_mem(&ring->dma_cmd);
1472 
1473         if (ring->data != NULL) {
1474                 for (i = 0; i < ring->count; i++) {
1475                         if (ring->data[i].dma_data.dma_hdl)
1476                                 IWK_DMA_SYNC(ring->data[i].dma_data,
1477                                     DDI_DMA_SYNC_FORDEV);
1478                         iwk_free_dma_mem(&ring->data[i].dma_data);
1479                 }
1480                 kmem_free(ring->data, ring->count * sizeof (iwk_tx_data_t));
1481         }
1482 }
1483 
1484 static int
1485 iwk_ring_init(iwk_sc_t *sc)
1486 {
1487         int i, err = DDI_SUCCESS;
1488 
1489         for (i = 0; i < IWK_NUM_QUEUES; i++) {
1490                 if (i == IWK_CMD_QUEUE_NUM)
1491                         continue;
1492                 err = iwk_alloc_tx_ring(sc, &sc->sc_txq[i], TFD_TX_CMD_SLOTS,
1493                     i);
1494                 if (err != DDI_SUCCESS)
1495                         goto fail;
1496         }
1497         err = iwk_alloc_tx_ring(sc, &sc->sc_txq[IWK_CMD_QUEUE_NUM],
1498             TFD_CMD_SLOTS, IWK_CMD_QUEUE_NUM);
1499         if (err != DDI_SUCCESS)
1500                 goto fail;
1501         err = iwk_alloc_rx_ring(sc);
1502         if (err != DDI_SUCCESS)
1503                 goto fail;
1504         return (err);
1505 
1506 fail:
1507         return (err);
1508 }
1509 
1510 static void
1511 iwk_ring_free(iwk_sc_t *sc)
1512 {
1513         int i = IWK_NUM_QUEUES;
1514 
1515         iwk_free_rx_ring(sc);
1516         while (--i >= 0) {
1517                 iwk_free_tx_ring(sc, &sc->sc_txq[i]);
1518         }
1519 }
1520 
1521 /* ARGSUSED */
1522 static ieee80211_node_t *
1523 iwk_node_alloc(ieee80211com_t *ic)
1524 {
1525         iwk_amrr_t *amrr;
1526 
1527         amrr = kmem_zalloc(sizeof (iwk_amrr_t), KM_SLEEP);
1528         if (amrr != NULL)
1529                 iwk_amrr_init(amrr);
1530         return (&amrr->in);
1531 }
1532 
1533 static void
1534 iwk_node_free(ieee80211_node_t *in)
1535 {
1536         ieee80211com_t *ic = in->in_ic;
1537 
1538         ic->ic_node_cleanup(in);
1539         if (in->in_wpa_ie != NULL)
1540                 ieee80211_free(in->in_wpa_ie);
1541         kmem_free(in, sizeof (iwk_amrr_t));
1542 }
1543 
1544 /*ARGSUSED*/
1545 static int
1546 iwk_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
1547 {
1548         iwk_sc_t *sc = (iwk_sc_t *)ic;
1549         ieee80211_node_t *in = ic->ic_bss;
1550         enum ieee80211_state ostate = ic->ic_state;
1551         int i, err = IWK_SUCCESS;
1552 
1553         mutex_enter(&sc->sc_glock);
1554         switch (nstate) {
1555         case IEEE80211_S_SCAN:
1556                 switch (ostate) {
1557                 case IEEE80211_S_INIT:
1558                 {
1559                         iwk_add_sta_t node;
1560 
1561                         sc->sc_flags |= IWK_F_SCANNING;
1562                         sc->sc_scan_pending = 0;
1563                         iwk_set_led(sc, 2, 10, 2);
1564 
1565                         /*
1566                          * clear association to receive beacons from
1567                          * all BSS'es
1568                          */
1569                         sc->sc_config.assoc_id = 0;
1570                         sc->sc_config.filter_flags &=
1571                             ~LE_32(RXON_FILTER_ASSOC_MSK);
1572 
1573                         IWK_DBG((IWK_DEBUG_80211, "config chan %d "
1574                             "flags %x filter_flags %x\n", sc->sc_config.chan,
1575                             sc->sc_config.flags, sc->sc_config.filter_flags));
1576 
1577                         err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
1578                             sizeof (iwk_rxon_cmd_t), 1);
1579                         if (err != IWK_SUCCESS) {
1580                                 cmn_err(CE_WARN,
1581                                     "could not clear association\n");
1582                                 sc->sc_flags &= ~IWK_F_SCANNING;
1583                                 mutex_exit(&sc->sc_glock);
1584                                 return (err);
1585                         }
1586 
1587                         /* add broadcast node to send probe request */
1588                         (void) memset(&node, 0, sizeof (node));
1589                         (void) memset(&node.bssid, 0xff, IEEE80211_ADDR_LEN);
1590                         node.id = IWK_BROADCAST_ID;
1591                         err = iwk_cmd(sc, REPLY_ADD_STA, &node,
1592                             sizeof (node), 1);
1593                         if (err != IWK_SUCCESS) {
1594                                 cmn_err(CE_WARN, "could not add "
1595                                     "broadcast node\n");
1596                                 sc->sc_flags &= ~IWK_F_SCANNING;
1597                                 mutex_exit(&sc->sc_glock);
1598                                 return (err);
1599                         }
1600                         break;
1601                 }
1602 
1603                 case IEEE80211_S_AUTH:
1604                 case IEEE80211_S_ASSOC:
1605                 case IEEE80211_S_RUN:
1606                         sc->sc_flags |= IWK_F_SCANNING;
1607                         sc->sc_scan_pending = 0;
1608 
1609                         iwk_set_led(sc, 2, 10, 2);
1610                         /* FALLTHRU */
1611                 case IEEE80211_S_SCAN:
1612                         mutex_exit(&sc->sc_glock);
1613                         /* step to next channel before actual FW scan */
1614                         err = sc->sc_newstate(ic, nstate, arg);
1615                         mutex_enter(&sc->sc_glock);
1616                         if ((err != 0) || ((err = iwk_scan(sc)) != 0)) {
1617                                 cmn_err(CE_WARN,
1618                                     "could not initiate scan\n");
1619                                 sc->sc_flags &= ~IWK_F_SCANNING;
1620                                 ieee80211_cancel_scan(ic);
1621                         }
1622                         mutex_exit(&sc->sc_glock);
1623                         return (err);
1624                 default:
1625                         break;
1626 
1627                 }
1628                 sc->sc_clk = 0;
1629                 break;
1630 
1631         case IEEE80211_S_AUTH:
1632                 if (ostate == IEEE80211_S_SCAN) {
1633                         sc->sc_flags &= ~IWK_F_SCANNING;
1634                 }
1635 
1636                 /* reset state to handle reassociations correctly */
1637                 sc->sc_config.assoc_id = 0;
1638                 sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK);
1639 
1640                 /*
1641                  * before sending authentication and association request frame,
1642                  * we need do something in the hardware, such as setting the
1643                  * channel same to the target AP...
1644                  */
1645                 if ((err = iwk_hw_set_before_auth(sc)) != 0) {
1646                         cmn_err(CE_WARN, "could not setup firmware for "
1647                             "authentication\n");
1648                         mutex_exit(&sc->sc_glock);
1649                         return (err);
1650                 }
1651                 break;
1652 
1653         case IEEE80211_S_RUN:
1654                 if (ostate == IEEE80211_S_SCAN) {
1655                         sc->sc_flags &= ~IWK_F_SCANNING;
1656                 }
1657 
1658                 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
1659                         /* let LED blink when monitoring */
1660                         iwk_set_led(sc, 2, 10, 10);
1661                         break;
1662                 }
1663                 IWK_DBG((IWK_DEBUG_80211, "iwk: associated."));
1664 
1665                 /* IBSS mode */
1666                 if (ic->ic_opmode == IEEE80211_M_IBSS) {
1667                         /*
1668                          * clean all nodes in ibss node table
1669                          * in order to be consistent with hardware
1670                          */
1671                         err = iwk_run_state_config_ibss(ic);
1672                         if (err != IWK_SUCCESS) {
1673                                 cmn_err(CE_WARN, "iwk_newstate(): "
1674                                     "failed to update configuration "
1675                                     "in IBSS mode\n");
1676                                 mutex_exit(&sc->sc_glock);
1677                                 return (err);
1678                         }
1679                 }
1680 
1681                 /* none IBSS mode */
1682                 if (ic->ic_opmode != IEEE80211_M_IBSS) {
1683                         /* update adapter's configuration */
1684                         err = iwk_run_state_config_sta(ic);
1685                         if (err != IWK_SUCCESS) {
1686                                 cmn_err(CE_WARN, "iwk_newstate(): "
1687                                     "failed to update configuration "
1688                                     "in none IBSS mode\n");
1689                                 mutex_exit(&sc->sc_glock);
1690                                 return (err);
1691                         }
1692                 }
1693 
1694                 /* obtain current temperature of chipset */
1695                 sc->sc_tempera = iwk_curr_tempera(sc);
1696 
1697                 /*
1698                  * make Tx power calibration to determine
1699                  * the gains of DSP and radio
1700                  */
1701                 err = iwk_tx_power_calibration(sc);
1702                 if (err) {
1703                         cmn_err(CE_WARN, "iwk_newstate(): "
1704                             "failed to set tx power table\n");
1705                         mutex_exit(&sc->sc_glock);
1706                         return (err);
1707                 }
1708 
1709                 if (ic->ic_opmode == IEEE80211_M_IBSS) {
1710 
1711                         /*
1712                          * allocate and transmit beacon frames
1713                          */
1714                         err = iwk_start_tx_beacon(ic);
1715                         if (err != IWK_SUCCESS) {
1716                                 cmn_err(CE_WARN, "iwk_newstate(): "
1717                                     "can't transmit beacon frames\n");
1718                                 mutex_exit(&sc->sc_glock);
1719                                 return (err);
1720                         }
1721                 }
1722 
1723                 /* start automatic rate control */
1724                 mutex_enter(&sc->sc_mt_lock);
1725                 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
1726                         sc->sc_flags |= IWK_F_RATE_AUTO_CTL;
1727                         /* set rate to some reasonable initial value */
1728                         i = in->in_rates.ir_nrates - 1;
1729                         while (i > 0 && IEEE80211_RATE(i) > 72)
1730                                 i--;
1731                         in->in_txrate = i;
1732                 } else {
1733                         sc->sc_flags &= ~IWK_F_RATE_AUTO_CTL;
1734                 }
1735                 mutex_exit(&sc->sc_mt_lock);
1736 
1737                 /* set LED on after associated */
1738                 iwk_set_led(sc, 2, 0, 1);
1739                 break;
1740 
1741         case IEEE80211_S_INIT:
1742                 if (ostate == IEEE80211_S_SCAN) {
1743                         sc->sc_flags &= ~IWK_F_SCANNING;
1744                 }
1745 
1746                 /* set LED off after init */
1747                 iwk_set_led(sc, 2, 1, 0);
1748                 break;
1749         case IEEE80211_S_ASSOC:
1750                 if (ostate == IEEE80211_S_SCAN) {
1751                         sc->sc_flags &= ~IWK_F_SCANNING;
1752                 }
1753 
1754                 break;
1755         }
1756 
1757         mutex_exit(&sc->sc_glock);
1758 
1759         err = sc->sc_newstate(ic, nstate, arg);
1760 
1761         if (nstate == IEEE80211_S_RUN) {
1762 
1763                 mutex_enter(&sc->sc_glock);
1764 
1765                 /*
1766                  * make initialization for Receiver
1767                  * sensitivity calibration
1768                  */
1769                 err = iwk_rx_sens_init(sc);
1770                 if (err) {
1771                         cmn_err(CE_WARN, "iwk_newstate(): "
1772                             "failed to init RX sensitivity\n");
1773                         mutex_exit(&sc->sc_glock);
1774                         return (err);
1775                 }
1776 
1777                 /* make initialization for Receiver gain balance */
1778                 err = iwk_rxgain_diff_init(sc);
1779                 if (err) {
1780                         cmn_err(CE_WARN, "iwk_newstate(): "
1781                             "failed to init phy calibration\n");
1782                         mutex_exit(&sc->sc_glock);
1783                         return (err);
1784                 }
1785 
1786                 mutex_exit(&sc->sc_glock);
1787 
1788         }
1789 
1790         return (err);
1791 }
1792 
1793 static void
1794 iwk_watchdog(void *arg)
1795 {
1796         iwk_sc_t *sc = arg;
1797         struct ieee80211com *ic = &sc->sc_ic;
1798 #ifdef DEBUG
1799         timeout_id_t timeout_id = ic->ic_watchdog_timer;
1800 #endif
1801 
1802         ieee80211_stop_watchdog(ic);
1803 
1804         if ((ic->ic_state != IEEE80211_S_AUTH) &&
1805             (ic->ic_state != IEEE80211_S_ASSOC))
1806                 return;
1807 
1808         if (ic->ic_bss->in_fails > 0) {
1809                 IWK_DBG((IWK_DEBUG_80211, "watchdog (0x%x) reset: "
1810                     "node (0x%x)\n", timeout_id, &ic->ic_bss));
1811                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
1812         } else {
1813                 IWK_DBG((IWK_DEBUG_80211, "watchdog (0x%x) timeout: "
1814                     "node (0x%x), retry (%d)\n",
1815                     timeout_id, &ic->ic_bss, ic->ic_bss->in_fails + 1));
1816                 ieee80211_watchdog(ic);
1817         }
1818 }
1819 
1820 /*ARGSUSED*/
1821 static int iwk_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
1822     const uint8_t mac[IEEE80211_ADDR_LEN])
1823 {
1824         iwk_sc_t *sc = (iwk_sc_t *)ic;
1825         iwk_add_sta_t node;
1826         int err;
1827         uint8_t index1;
1828 
1829         switch (k->wk_cipher->ic_cipher) {
1830         case IEEE80211_CIPHER_WEP:
1831         case IEEE80211_CIPHER_TKIP:
1832                 return (1); /* sofeware do it. */
1833         case IEEE80211_CIPHER_AES_CCM:
1834                 break;
1835         default:
1836                 return (0);
1837         }
1838         sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_DIS_DECRYPT_MSK |
1839             RXON_FILTER_DIS_GRP_DECRYPT_MSK);
1840 
1841         mutex_enter(&sc->sc_glock);
1842 
1843         /* update ap/multicast node */
1844         (void) memset(&node, 0, sizeof (node));
1845         if (IEEE80211_IS_MULTICAST(mac)) {
1846                 (void) memset(node.bssid, 0xff, 6);
1847                 node.id = IWK_BROADCAST_ID;
1848         } else if (ic->ic_opmode == IEEE80211_M_IBSS) {
1849                 mutex_exit(&sc->sc_glock);
1850                 mutex_enter(&sc->sc_ibss.node_tb_lock);
1851 
1852                 /*
1853                  * search for node in ibss node table
1854                  */
1855                 for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT;
1856                     index1++) {
1857                         if (sc->sc_ibss.ibss_node_tb[index1].used &&
1858                             IEEE80211_ADDR_EQ(sc->sc_ibss.
1859                             ibss_node_tb[index1].node.bssid,
1860                             mac)) {
1861                                 break;
1862                         }
1863                 }
1864                 if (index1 >= IWK_BROADCAST_ID) {
1865                         cmn_err(CE_WARN, "iwk_key_set(): "
1866                             "have no this node in hardware node table\n");
1867                         mutex_exit(&sc->sc_ibss.node_tb_lock);
1868                         return (0);
1869                 } else {
1870                         /*
1871                          * configure key for given node in hardware
1872                          */
1873                         if (k->wk_flags & IEEE80211_KEY_XMIT) {
1874                                 sc->sc_ibss.ibss_node_tb[index1].
1875                                     node.key_flags = 0;
1876                                 sc->sc_ibss.ibss_node_tb[index1].
1877                                     node.keyp = k->wk_keyix;
1878                         } else {
1879                                 sc->sc_ibss.ibss_node_tb[index1].
1880                                     node.key_flags = (1 << 14);
1881                                 sc->sc_ibss.ibss_node_tb[index1].
1882                                     node.keyp = k->wk_keyix + 4;
1883                         }
1884 
1885                         (void) memcpy(sc->sc_ibss.ibss_node_tb[index1].node.key,
1886                             k->wk_key, k->wk_keylen);
1887                         sc->sc_ibss.ibss_node_tb[index1].node.key_flags |=
1888                             (STA_KEY_FLG_CCMP | (1 << 3) | (k->wk_keyix << 8));
1889                         sc->sc_ibss.ibss_node_tb[index1].node.key_flags =
1890                             LE_16(sc->sc_ibss.ibss_node_tb[index1].
1891                             node.key_flags);
1892                         sc->sc_ibss.ibss_node_tb[index1].node.sta_mask =
1893                             STA_MODIFY_KEY_MASK;
1894                         sc->sc_ibss.ibss_node_tb[index1].node.control = 1;
1895 
1896                         mutex_enter(&sc->sc_glock);
1897                         err = iwk_cmd(sc, REPLY_ADD_STA,
1898                             &sc->sc_ibss.ibss_node_tb[index1].node,
1899                             sizeof (iwk_add_sta_t), 1);
1900                         if (err != IWK_SUCCESS) {
1901                                 cmn_err(CE_WARN, "iwk_key_set(): "
1902                                     "failed to update IBSS node in hardware\n");
1903                                 mutex_exit(&sc->sc_glock);
1904                                 mutex_exit(&sc->sc_ibss.node_tb_lock);
1905                                 return (0);
1906                         }
1907                         mutex_exit(&sc->sc_glock);
1908                 }
1909                 mutex_exit(&sc->sc_ibss.node_tb_lock);
1910                 return (1);
1911         } else {
1912                 IEEE80211_ADDR_COPY(node.bssid, ic->ic_bss->in_bssid);
1913                 node.id = IWK_AP_ID;
1914         }
1915         if (k->wk_flags & IEEE80211_KEY_XMIT) {
1916                 node.key_flags = 0;
1917                 node.keyp = k->wk_keyix;
1918         } else {
1919                 node.key_flags = (1 << 14);
1920                 node.keyp = k->wk_keyix + 4;
1921         }
1922         (void) memcpy(node.key, k->wk_key, k->wk_keylen);
1923         node.key_flags |= (STA_KEY_FLG_CCMP | (1 << 3) | (k->wk_keyix << 8));
1924         node.key_flags = LE_16(node.key_flags);
1925         node.sta_mask = STA_MODIFY_KEY_MASK;
1926         node.control = 1;
1927         err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
1928         if (err != IWK_SUCCESS) {
1929                 cmn_err(CE_WARN, "iwk_key_set():"
1930                     "failed to update ap node\n");
1931                 mutex_exit(&sc->sc_glock);
1932                 return (0);
1933         }
1934         mutex_exit(&sc->sc_glock);
1935         return (1);
1936 }
1937 
1938 /*
1939  * exclusive access to mac begin.
1940  */
1941 static void
1942 iwk_mac_access_enter(iwk_sc_t *sc)
1943 {
1944         uint32_t tmp;
1945         int n;
1946 
1947         tmp = IWK_READ(sc, CSR_GP_CNTRL);
1948         IWK_WRITE(sc, CSR_GP_CNTRL,
1949             tmp | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1950 
1951         /* wait until we succeed */
1952         for (n = 0; n < 1000; n++) {
1953                 if ((IWK_READ(sc, CSR_GP_CNTRL) &
1954                     (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
1955                     CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP)) ==
1956                     CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN)
1957                         break;
1958                 DELAY(10);
1959         }
1960         if (n == 1000)
1961                 IWK_DBG((IWK_DEBUG_PIO, "could not lock memory\n"));
1962 }
1963 
1964 /*
1965  * exclusive access to mac end.
1966  */
1967 static void
1968 iwk_mac_access_exit(iwk_sc_t *sc)
1969 {
1970         uint32_t tmp = IWK_READ(sc, CSR_GP_CNTRL);
1971         IWK_WRITE(sc, CSR_GP_CNTRL,
1972             tmp & ~CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1973 }
1974 
1975 static uint32_t
1976 iwk_mem_read(iwk_sc_t *sc, uint32_t addr)
1977 {
1978         IWK_WRITE(sc, HBUS_TARG_MEM_RADDR, addr);
1979         return (IWK_READ(sc, HBUS_TARG_MEM_RDAT));
1980 }
1981 
1982 static void
1983 iwk_mem_write(iwk_sc_t *sc, uint32_t addr, uint32_t data)
1984 {
1985         IWK_WRITE(sc, HBUS_TARG_MEM_WADDR, addr);
1986         IWK_WRITE(sc, HBUS_TARG_MEM_WDAT, data);
1987 }
1988 
1989 static uint32_t
1990 iwk_reg_read(iwk_sc_t *sc, uint32_t addr)
1991 {
1992         IWK_WRITE(sc, HBUS_TARG_PRPH_RADDR, addr | (3 << 24));
1993         return (IWK_READ(sc, HBUS_TARG_PRPH_RDAT));
1994 }
1995 
1996 static void
1997 iwk_reg_write(iwk_sc_t *sc, uint32_t addr, uint32_t data)
1998 {
1999         IWK_WRITE(sc, HBUS_TARG_PRPH_WADDR, addr | (3 << 24));
2000         IWK_WRITE(sc, HBUS_TARG_PRPH_WDAT, data);
2001 }
2002 
2003 static void
2004 iwk_reg_write_region_4(iwk_sc_t *sc, uint32_t addr,
2005     uint32_t *data, int wlen)
2006 {
2007         for (; wlen > 0; wlen--, data++, addr += 4)
2008                 iwk_reg_write(sc, addr, LE_32(*data));
2009 }
2010 
2011 
2012 /*
2013  * ucode load/initialization steps:
2014  * 1)  load Bootstrap State Machine (BSM) with "bootstrap" uCode image.
2015  * BSM contains a small memory that *always* stays powered up, so it can
2016  * retain the bootstrap program even when the card is in a power-saving
2017  * power-down state.  The BSM loads the small program into ARC processor's
2018  * instruction memory when triggered by power-up.
2019  * 2)  load Initialize image via bootstrap program.
2020  * The Initialize image sets up regulatory and calibration data for the
2021  * Runtime/Protocol uCode. This sends a REPLY_ALIVE notification when completed.
2022  * The 4965 reply contains calibration data for temperature, voltage and tx gain
2023  * correction.
2024  */
2025 static int
2026 iwk_load_firmware(iwk_sc_t *sc)
2027 {
2028         uint32_t *boot_fw = (uint32_t *)sc->sc_boot;
2029         uint32_t size = LE_32(sc->sc_hdr->bootsz);
2030         int n, err = IWK_SUCCESS;
2031 
2032         /*
2033          * The physical address bit [4-35] of the initialize uCode.
2034          * In the initialize alive notify interrupt the physical address of
2035          * the runtime ucode will be set for loading.
2036          */
2037         iwk_mac_access_enter(sc);
2038 
2039         iwk_reg_write(sc, BSM_DRAM_INST_PTR_REG,
2040             sc->sc_dma_fw_init_text.cookie.dmac_address >> 4);
2041         iwk_reg_write(sc, BSM_DRAM_DATA_PTR_REG,
2042             sc->sc_dma_fw_init_data.cookie.dmac_address >> 4);
2043         iwk_reg_write(sc, BSM_DRAM_INST_BYTECOUNT_REG,
2044             sc->sc_dma_fw_init_text.cookie.dmac_size);
2045         iwk_reg_write(sc, BSM_DRAM_DATA_BYTECOUNT_REG,
2046             sc->sc_dma_fw_init_data.cookie.dmac_size);
2047 
2048         /* load bootstrap code into BSM memory */
2049         iwk_reg_write_region_4(sc, BSM_SRAM_LOWER_BOUND, boot_fw,
2050             size / sizeof (uint32_t));
2051 
2052         iwk_reg_write(sc, BSM_WR_MEM_SRC_REG, 0);
2053         iwk_reg_write(sc, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
2054         iwk_reg_write(sc, BSM_WR_DWCOUNT_REG, size / sizeof (uint32_t));
2055 
2056         /*
2057          * prepare to load initialize uCode
2058          */
2059         iwk_reg_write(sc, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
2060 
2061         /* wait while the adapter is busy loading the firmware */
2062         for (n = 0; n < 1000; n++) {
2063                 if (!(iwk_reg_read(sc, BSM_WR_CTRL_REG) &
2064                     BSM_WR_CTRL_REG_BIT_START))
2065                         break;
2066                 DELAY(10);
2067         }
2068         if (n == 1000) {
2069                 cmn_err(CE_WARN, "timeout transferring firmware\n");
2070                 err = ETIMEDOUT;
2071                 return (err);
2072         }
2073 
2074         /* for future power-save mode use */
2075         iwk_reg_write(sc, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
2076 
2077         iwk_mac_access_exit(sc);
2078 
2079         return (err);
2080 }
2081 
2082 /*ARGSUSED*/
2083 static void
2084 iwk_rx_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc, iwk_rx_data_t *data)
2085 {
2086         ieee80211com_t *ic = &sc->sc_ic;
2087         iwk_rx_ring_t *ring = &sc->sc_rxq;
2088         iwk_rx_phy_res_t *stat;
2089         ieee80211_node_t *in;
2090         uint32_t *tail;
2091         struct ieee80211_frame *wh;
2092         mblk_t *mp;
2093         uint16_t len, rssi, mrssi, agc;
2094         int16_t t;
2095         uint32_t ants, i;
2096         struct iwk_rx_non_cfg_phy *phyinfo;
2097         uint32_t crc;
2098 
2099         /* assuming not 11n here. cope with 11n in phase-II */
2100         stat = (iwk_rx_phy_res_t *)(desc + 1);
2101         if (stat->cfg_phy_cnt > 20) {
2102                 return;
2103         }
2104 
2105         for (i = 0; i < RX_RES_PHY_CNT; i++)
2106                 stat->non_cfg_phy[i] = LE_16(stat->non_cfg_phy[i]);
2107 
2108         phyinfo = (struct iwk_rx_non_cfg_phy *)stat->non_cfg_phy;
2109         agc = (phyinfo->agc_info & IWK_AGC_DB_MASK) >> IWK_AGC_DB_POS;
2110         mrssi = 0;
2111         ants = (LE_16(stat->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) >>
2112             RX_PHY_FLAGS_ANTENNAE_OFFSET;
2113         for (i = 0; i < 3; i++) {
2114                 if (ants & (1 << i))
2115                         mrssi = MAX(mrssi, phyinfo->rssi_info[i << 1]);
2116         }
2117         t = mrssi - agc - 44; /* t is the dBM value */
2118         /*
2119          * convert dBm to percentage ???
2120          */
2121         rssi = (100 * 75 * 75 - (-20 - t) * (15 * 75 + 62 * (-20 - t))) /
2122             (75 * 75);
2123         if (rssi > 100)
2124                 rssi = 100;
2125         if (rssi < 1)
2126                 rssi = 1;
2127         len = LE_16(stat->byte_count);
2128         tail = (uint32_t *)((caddr_t)(stat + 1) + stat->cfg_phy_cnt + len);
2129         bcopy(tail, &crc, 4);
2130 
2131         IWK_DBG((IWK_DEBUG_RX, "rx intr: idx=%d phy_len=%x len=%d "
2132             "rate=%x chan=%d tstamp=%x non_cfg_phy_count=%x "
2133             "cfg_phy_count=%x tail=%x", ring->cur, sizeof (*stat),
2134             len, stat->rate.r.s.rate, LE_16(stat->channel),
2135             LE_32(stat->timestampl), stat->non_cfg_phy_cnt,
2136             stat->cfg_phy_cnt, LE_32(crc)));
2137 
2138         if ((len < 16) || (len > sc->sc_dmabuf_sz)) {
2139                 IWK_DBG((IWK_DEBUG_RX, "rx frame oversize\n"));
2140                 return;
2141         }
2142 
2143         /*
2144          * discard Rx frames with bad CRC
2145          */
2146         if ((LE_32(crc) &
2147             (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) !=
2148             (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) {
2149                 IWK_DBG((IWK_DEBUG_RX, "rx crc error tail: %x\n",
2150                     LE_32(crc)));
2151                 sc->sc_rx_err++;
2152                 return;
2153         }
2154 
2155         wh = (struct ieee80211_frame *)
2156             ((uint8_t *)(stat + 1)+ stat->cfg_phy_cnt);
2157         if (*(uint8_t *)wh == IEEE80211_FC0_SUBTYPE_ASSOC_RESP) {
2158                 sc->sc_assoc_id = *((uint16_t *)(wh + 1) + 2);
2159                 IWK_DBG((IWK_DEBUG_RX, "rx : association id = %x\n",
2160                     sc->sc_assoc_id));
2161         }
2162 #ifdef DEBUG
2163         if (iwk_dbg_flags & IWK_DEBUG_RX)
2164                 ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0);
2165 #endif
2166         in = ieee80211_find_rxnode(ic, wh);
2167         mp = allocb(len, BPRI_MED);
2168         if (mp) {
2169                 (void) memcpy(mp->b_wptr, wh, len);
2170                 mp->b_wptr += len;
2171 
2172                 /* send the frame to the 802.11 layer */
2173                 (void) ieee80211_input(ic, mp, in, rssi, 0);
2174         } else {
2175                 sc->sc_rx_nobuf++;
2176                 IWK_DBG((IWK_DEBUG_RX,
2177                     "iwk_rx_intr(): alloc rx buf failed\n"));
2178         }
2179         /* release node reference */
2180         ieee80211_free_node(in);
2181 }
2182 
2183 /*ARGSUSED*/
2184 static void
2185 iwk_tx_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc, iwk_rx_data_t *data)
2186 {
2187         ieee80211com_t *ic = &sc->sc_ic;
2188         iwk_tx_ring_t *ring = &sc->sc_txq[desc->hdr.qid & 0x3];
2189         iwk_tx_stat_t *stat = (iwk_tx_stat_t *)(desc + 1);
2190         iwk_amrr_t *amrr = (iwk_amrr_t *)ic->ic_bss;
2191 
2192         IWK_DBG((IWK_DEBUG_TX, "tx done: qid=%d idx=%d"
2193             " retries=%d frame_count=%x nkill=%d "
2194             "rate=%x duration=%d status=%x\n",
2195             desc->hdr.qid, desc->hdr.idx, stat->ntries, stat->frame_count,
2196             stat->bt_kill_count, stat->rate.r.s.rate,
2197             LE_16(stat->duration), LE_32(stat->status)));
2198 
2199         amrr->txcnt++;
2200         IWK_DBG((IWK_DEBUG_RATECTL, "tx: %d cnt\n", amrr->txcnt));
2201         if (stat->ntries > 0) {
2202                 amrr->retrycnt++;
2203                 sc->sc_tx_retries++;
2204                 IWK_DBG((IWK_DEBUG_TX, "tx: %d retries\n",
2205                     sc->sc_tx_retries));
2206         }
2207 
2208         sc->sc_tx_timer = 0;
2209 
2210         mutex_enter(&sc->sc_tx_lock);
2211         ring->queued--;
2212         if (ring->queued < 0)
2213                 ring->queued = 0;
2214         if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count << 3))) {
2215                 sc->sc_need_reschedule = 0;
2216                 mutex_exit(&sc->sc_tx_lock);
2217                 mac_tx_update(ic->ic_mach);
2218                 mutex_enter(&sc->sc_tx_lock);
2219         }
2220         mutex_exit(&sc->sc_tx_lock);
2221 }
2222 
2223 static void
2224 iwk_cmd_intr(iwk_sc_t *sc, iwk_rx_desc_t *desc)
2225 {
2226         if ((desc->hdr.qid & 7) != 4) {
2227                 return;
2228         }
2229         mutex_enter(&sc->sc_glock);
2230         sc->sc_flags |= IWK_F_CMD_DONE;
2231         cv_signal(&sc->sc_cmd_cv);
2232         mutex_exit(&sc->sc_glock);
2233         IWK_DBG((IWK_DEBUG_CMD, "rx cmd: "
2234             "qid=%x idx=%d flags=%x type=0x%x\n",
2235             desc->hdr.qid, desc->hdr.idx, desc->hdr.flags,
2236             desc->hdr.type));
2237 }
2238 
2239 static void
2240 iwk_ucode_alive(iwk_sc_t *sc, iwk_rx_desc_t *desc)
2241 {
2242         uint32_t base, i;
2243         struct iwk_alive_resp *ar =
2244             (struct iwk_alive_resp *)(desc + 1);
2245 
2246         /* the microcontroller is ready */
2247         IWK_DBG((IWK_DEBUG_FW,
2248             "microcode alive notification minor: %x major: %x type:"
2249             " %x subtype: %x\n",
2250             ar->ucode_minor, ar->ucode_minor, ar->ver_type, ar->ver_subtype));
2251 
2252         if (LE_32(ar->is_valid) != UCODE_VALID_OK) {
2253                 IWK_DBG((IWK_DEBUG_FW,
2254                     "microcontroller initialization failed\n"));
2255         }
2256         if (ar->ver_subtype == INITIALIZE_SUBTYPE) {
2257                 IWK_DBG((IWK_DEBUG_FW,
2258                     "initialization alive received.\n"));
2259                 (void) memcpy(&sc->sc_card_alive_init, ar,
2260                     sizeof (struct iwk_init_alive_resp));
2261                 /* XXX get temperature */
2262                 iwk_mac_access_enter(sc);
2263                 iwk_reg_write(sc, BSM_DRAM_INST_PTR_REG,
2264                     sc->sc_dma_fw_text.cookie.dmac_address >> 4);
2265                 iwk_reg_write(sc, BSM_DRAM_DATA_PTR_REG,
2266                     sc->sc_dma_fw_data_bak.cookie.dmac_address >> 4);
2267                 iwk_reg_write(sc, BSM_DRAM_DATA_BYTECOUNT_REG,
2268                     sc->sc_dma_fw_data.cookie.dmac_size);
2269                 iwk_reg_write(sc, BSM_DRAM_INST_BYTECOUNT_REG,
2270                     sc->sc_dma_fw_text.cookie.dmac_size | 0x80000000);
2271                 iwk_mac_access_exit(sc);
2272         } else {
2273                 IWK_DBG((IWK_DEBUG_FW, "runtime alive received.\n"));
2274                 (void) memcpy(&sc->sc_card_alive_run, ar,
2275                     sizeof (struct iwk_alive_resp));
2276 
2277                 /*
2278                  * Init SCD related registers to make Tx work. XXX
2279                  */
2280                 iwk_mac_access_enter(sc);
2281 
2282                 /* read sram address of data base */
2283                 sc->sc_scd_base = iwk_reg_read(sc, SCD_SRAM_BASE_ADDR);
2284 
2285                 /* clear and init SCD_CONTEXT_DATA_OFFSET area. 128 bytes */
2286                 for (base = sc->sc_scd_base + SCD_CONTEXT_DATA_OFFSET, i = 0;
2287                     i < 128; i += 4)
2288                         iwk_mem_write(sc, base + i, 0);
2289 
2290                 /* clear and init SCD_TX_STTS_BITMAP_OFFSET area. 256 bytes */
2291                 for (base = sc->sc_scd_base + SCD_TX_STTS_BITMAP_OFFSET;
2292                     i < 256; i += 4)
2293                         iwk_mem_write(sc, base + i, 0);
2294 
2295                 /* clear and init SCD_TRANSLATE_TBL_OFFSET area. 32 bytes */
2296                 for (base = sc->sc_scd_base + SCD_TRANSLATE_TBL_OFFSET;
2297                     i < sizeof (uint16_t) * IWK_NUM_QUEUES; i += 4)
2298                         iwk_mem_write(sc, base + i, 0);
2299 
2300                 iwk_reg_write(sc, SCD_DRAM_BASE_ADDR,
2301                     sc->sc_dma_sh.cookie.dmac_address >> 10);
2302                 iwk_reg_write(sc, SCD_QUEUECHAIN_SEL, 0);
2303 
2304                 /* initiate the tx queues */
2305                 for (i = 0; i < IWK_NUM_QUEUES; i++) {
2306                         iwk_reg_write(sc, SCD_QUEUE_RDPTR(i), 0);
2307                         IWK_WRITE(sc, HBUS_TARG_WRPTR, (i << 8));
2308                         iwk_mem_write(sc, sc->sc_scd_base +
2309                             SCD_CONTEXT_QUEUE_OFFSET(i),
2310                             (SCD_WIN_SIZE & 0x7f));
2311                         iwk_mem_write(sc, sc->sc_scd_base +
2312                             SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof (uint32_t),
2313                             (SCD_FRAME_LIMIT & 0x7f) << 16);
2314                 }
2315                 /* interrupt enable on each queue0-7 */
2316                 iwk_reg_write(sc, SCD_INTERRUPT_MASK,
2317                     (1 << IWK_NUM_QUEUES) - 1);
2318                 /* enable  each channel 0-7 */
2319                 iwk_reg_write(sc, SCD_TXFACT,
2320                     SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
2321                 /*
2322                  * queue 0-7 maps to FIFO 0-7 and
2323                  * all queues work under FIFO mode (none-scheduler-ack)
2324                  */
2325                 for (i = 0; i < 7; i++) {
2326                         iwk_reg_write(sc,
2327                             SCD_QUEUE_STATUS_BITS(i),
2328                             (1 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
2329                             (i << SCD_QUEUE_STTS_REG_POS_TXF)|
2330                             SCD_QUEUE_STTS_REG_MSK);
2331                 }
2332                 iwk_mac_access_exit(sc);
2333 
2334                 sc->sc_flags |= IWK_F_FW_INIT;
2335                 cv_signal(&sc->sc_fw_cv);
2336         }
2337 
2338 }
2339 
2340 static uint_t
2341 /* LINTED: argument unused in function: unused */
2342 iwk_rx_softintr(caddr_t arg, caddr_t unused)
2343 {
2344         iwk_sc_t *sc = (iwk_sc_t *)arg;
2345         ieee80211com_t *ic = &sc->sc_ic;
2346         iwk_rx_desc_t *desc;
2347         iwk_rx_data_t *data;
2348         uint32_t index;
2349 
2350         mutex_enter(&sc->sc_glock);
2351         if (sc->sc_rx_softint_pending != 1) {
2352                 mutex_exit(&sc->sc_glock);
2353                 return (DDI_INTR_UNCLAIMED);
2354         }
2355         /* disable interrupts */
2356         IWK_WRITE(sc, CSR_INT_MASK, 0);
2357         mutex_exit(&sc->sc_glock);
2358 
2359         /*
2360          * firmware has moved the index of the rx queue, driver get it,
2361          * and deal with it.
2362          */
2363         index = sc->sc_shared->val0 & 0xfff;
2364 
2365         while (sc->sc_rxq.cur != index) {
2366                 data = &sc->sc_rxq.data[sc->sc_rxq.cur];
2367                 desc = (iwk_rx_desc_t *)data->dma_data.mem_va;
2368 
2369                 IWK_DBG((IWK_DEBUG_INTR, "rx notification index = %d"
2370                     " cur = %d qid=%x idx=%d flags=%x type=%x len=%d\n",
2371                     index, sc->sc_rxq.cur, desc->hdr.qid, desc->hdr.idx,
2372                     desc->hdr.flags, desc->hdr.type, LE_32(desc->len)));
2373 
2374                 /* a command other than a tx need to be replied */
2375                 if (!(desc->hdr.qid & 0x80) &&
2376                     (desc->hdr.type != REPLY_RX_PHY_CMD) &&
2377                     (desc->hdr.type != REPLY_TX) &&
2378                     (desc->hdr.type != REPLY_TX_PWR_TABLE_CMD) &&
2379                     (desc->hdr.type != REPLY_PHY_CALIBRATION_CMD) &&
2380                     (desc->hdr.type != SENSITIVITY_CMD))
2381                         iwk_cmd_intr(sc, desc);
2382 
2383                 switch (desc->hdr.type) {
2384                 case REPLY_4965_RX:
2385                         iwk_rx_intr(sc, desc, data);
2386                         break;
2387 
2388                 case REPLY_TX:
2389                         iwk_tx_intr(sc, desc, data);
2390                         break;
2391 
2392                 case REPLY_ALIVE:
2393                         iwk_ucode_alive(sc, desc);
2394                         break;
2395 
2396                 case CARD_STATE_NOTIFICATION:
2397                 {
2398                         uint32_t *status = (uint32_t *)(desc + 1);
2399 
2400                         IWK_DBG((IWK_DEBUG_RADIO, "state changed to %x\n",
2401                             LE_32(*status)));
2402 
2403                         if (LE_32(*status) & 1) {
2404                                 /*
2405                                  * the radio button has to be pushed(OFF). It
2406                                  * is considered as a hw error, the
2407                                  * iwk_thread() tries to recover it after the
2408                                  * button is pushed again(ON)
2409                                  */
2410                                 cmn_err(CE_NOTE,
2411                                     "iwk_rx_softintr(): "
2412                                     "Radio transmitter is off\n");
2413                                 sc->sc_ostate = sc->sc_ic.ic_state;
2414                                 ieee80211_new_state(&sc->sc_ic,
2415                                     IEEE80211_S_INIT, -1);
2416                                 sc->sc_flags |=
2417                                     (IWK_F_HW_ERR_RECOVER | IWK_F_RADIO_OFF);
2418                         }
2419                         break;
2420                 }
2421                 case SCAN_START_NOTIFICATION:
2422                 {
2423                         iwk_start_scan_t *scan =
2424                             (iwk_start_scan_t *)(desc + 1);
2425 
2426                         IWK_DBG((IWK_DEBUG_SCAN,
2427                             "scanning channel %d status %x\n",
2428                             scan->chan, LE_32(scan->status)));
2429 
2430                         ic->ic_curchan = &ic->ic_sup_channels[scan->chan];
2431                         break;
2432                 }
2433                 case SCAN_COMPLETE_NOTIFICATION:
2434                 {
2435                         iwk_stop_scan_t *scan =
2436                             (iwk_stop_scan_t *)(desc + 1);
2437 
2438                         IWK_DBG((IWK_DEBUG_SCAN,
2439                             "completed channel %d (burst of %d) status %02x\n",
2440                             scan->chan, scan->nchan, scan->status));
2441 
2442                         sc->sc_scan_pending++;
2443                         break;
2444                 }
2445                 case STATISTICS_NOTIFICATION:
2446                         /* handle statistics notification */
2447                         iwk_statistics_notify(sc, desc);
2448                         break;
2449                 }
2450 
2451                 sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % RX_QUEUE_SIZE;
2452         }
2453 
2454         /*
2455          * driver dealt with what reveived in rx queue and tell the information
2456          * to the firmware.
2457          */
2458         index = (index == 0) ? RX_QUEUE_SIZE - 1 : index - 1;
2459         IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, index & (~7));
2460 
2461         mutex_enter(&sc->sc_glock);
2462         /* re-enable interrupts */
2463         IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2464         sc->sc_rx_softint_pending = 0;
2465         mutex_exit(&sc->sc_glock);
2466 
2467         return (DDI_INTR_CLAIMED);
2468 }
2469 
2470 static uint_t
2471 /* LINTED: argument unused in function: unused */
2472 iwk_intr(caddr_t arg, caddr_t unused)
2473 {
2474         iwk_sc_t *sc = (iwk_sc_t *)arg;
2475         uint32_t r, rfh;
2476 
2477         mutex_enter(&sc->sc_glock);
2478 
2479         if (sc->sc_flags & IWK_F_SUSPEND) {
2480                 mutex_exit(&sc->sc_glock);
2481                 return (DDI_INTR_UNCLAIMED);
2482         }
2483 
2484         r = IWK_READ(sc, CSR_INT);
2485         if (r == 0 || r == 0xffffffff) {
2486                 mutex_exit(&sc->sc_glock);
2487                 return (DDI_INTR_UNCLAIMED);
2488         }
2489 
2490         IWK_DBG((IWK_DEBUG_INTR, "interrupt reg %x\n", r));
2491 
2492         rfh = IWK_READ(sc, CSR_FH_INT_STATUS);
2493         IWK_DBG((IWK_DEBUG_INTR, "FH interrupt reg %x\n", rfh));
2494         /* disable interrupts */
2495         IWK_WRITE(sc, CSR_INT_MASK, 0);
2496         /* ack interrupts */
2497         IWK_WRITE(sc, CSR_INT, r);
2498         IWK_WRITE(sc, CSR_FH_INT_STATUS, rfh);
2499 
2500         if (sc->sc_soft_hdl == NULL) {
2501                 mutex_exit(&sc->sc_glock);
2502                 return (DDI_INTR_CLAIMED);
2503         }
2504         if (r & (BIT_INT_SWERROR | BIT_INT_ERR)) {
2505                 cmn_err(CE_WARN, "fatal firmware error\n");
2506                 mutex_exit(&sc->sc_glock);
2507 #ifdef DEBUG
2508                 /* dump event and error logs to dmesg */
2509                 iwk_write_error_log(sc);
2510                 iwk_write_event_log(sc);
2511 #endif /* DEBUG */
2512                 iwk_stop(sc);
2513                 sc->sc_ostate = sc->sc_ic.ic_state;
2514 
2515                 /* not capable of fast recovery */
2516                 if (!IWK_CHK_FAST_RECOVER(sc))
2517                         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
2518 
2519                 sc->sc_flags |= IWK_F_HW_ERR_RECOVER;
2520                 return (DDI_INTR_CLAIMED);
2521         }
2522 
2523         if (r & BIT_INT_RF_KILL) {
2524                 uint32_t tmp = IWK_READ(sc, CSR_GP_CNTRL);
2525                 if (tmp & (1 << 27))
2526                         cmn_err(CE_NOTE, "RF switch: radio on\n");
2527         }
2528 
2529         if ((r & (BIT_INT_FH_RX | BIT_INT_SW_RX)) ||
2530             (rfh & FH_INT_RX_MASK)) {
2531                 sc->sc_rx_softint_pending = 1;
2532                 (void) ddi_intr_trigger_softint(sc->sc_soft_hdl, NULL);
2533         }
2534 
2535         if (r & BIT_INT_ALIVE)      {
2536                 IWK_DBG((IWK_DEBUG_FW, "firmware initialized.\n"));
2537         }
2538 
2539         /* re-enable interrupts */
2540         IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
2541         mutex_exit(&sc->sc_glock);
2542 
2543         return (DDI_INTR_CLAIMED);
2544 }
2545 
2546 static uint8_t
2547 iwk_rate_to_plcp(int rate)
2548 {
2549         uint8_t ret;
2550 
2551         switch (rate) {
2552         /* CCK rates */
2553         case 2:
2554                 ret = 0xa;
2555                 break;
2556         case 4:
2557                 ret = 0x14;
2558                 break;
2559         case 11:
2560                 ret = 0x37;
2561                 break;
2562         case 22:
2563                 ret = 0x6e;
2564                 break;
2565         /* OFDM rates */
2566         case 12:
2567                 ret = 0xd;
2568                 break;
2569         case 18:
2570                 ret = 0xf;
2571                 break;
2572         case 24:
2573                 ret = 0x5;
2574                 break;
2575         case 36:
2576                 ret = 0x7;
2577                 break;
2578         case 48:
2579                 ret = 0x9;
2580                 break;
2581         case 72:
2582                 ret = 0xb;
2583                 break;
2584         case 96:
2585                 ret = 0x1;
2586                 break;
2587         case 108:
2588                 ret = 0x3;
2589                 break;
2590         default:
2591                 ret = 0;
2592                 break;
2593         }
2594         return (ret);
2595 }
2596 
2597 static mblk_t *
2598 iwk_m_tx(void *arg, mblk_t *mp)
2599 {
2600         iwk_sc_t        *sc = (iwk_sc_t *)arg;
2601         ieee80211com_t  *ic = &sc->sc_ic;
2602         mblk_t                  *next;
2603 
2604         if (sc->sc_flags & IWK_F_SUSPEND) {
2605                 freemsgchain(mp);
2606                 return (NULL);
2607         }
2608 
2609         if (ic->ic_state != IEEE80211_S_RUN) {
2610                 freemsgchain(mp);
2611                 return (NULL);
2612         }
2613 
2614         if ((sc->sc_flags & IWK_F_HW_ERR_RECOVER) &&
2615             IWK_CHK_FAST_RECOVER(sc)) {
2616                 IWK_DBG((IWK_DEBUG_FW, "iwk_m_tx(): hold queue\n"));
2617                 return (mp);
2618         }
2619 
2620         while (mp != NULL) {
2621                 next = mp->b_next;
2622                 mp->b_next = NULL;
2623                 if (iwk_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) {
2624                         mp->b_next = next;
2625                         break;
2626                 }
2627                 mp = next;
2628         }
2629         return (mp);
2630 }
2631 
2632 /* ARGSUSED */
2633 static int
2634 iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
2635 {
2636         iwk_sc_t *sc = (iwk_sc_t *)ic;
2637         iwk_tx_ring_t *ring;
2638         iwk_tx_desc_t *desc;
2639         iwk_tx_data_t *data;
2640         iwk_cmd_t *cmd;
2641         iwk_tx_cmd_t *tx;
2642         ieee80211_node_t *in;
2643         struct ieee80211_frame *wh;
2644         struct ieee80211_key *k = NULL;
2645         mblk_t *m, *m0;
2646         int rate, hdrlen, len, len0, mblen, off, err = IWK_SUCCESS;
2647         uint16_t masks = 0;
2648         uint8_t index, index1, index2;
2649 
2650         ring = &sc->sc_txq[0];
2651         data = &ring->data[ring->cur];
2652         desc = data->desc;
2653         cmd = data->cmd;
2654         bzero(desc, sizeof (*desc));
2655         bzero(cmd, sizeof (*cmd));
2656 
2657         mutex_enter(&sc->sc_tx_lock);
2658         if (sc->sc_flags & IWK_F_SUSPEND) {
2659                 mutex_exit(&sc->sc_tx_lock);
2660                 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2661                     IEEE80211_FC0_TYPE_DATA) {
2662                         freemsg(mp);
2663                 }
2664                 err = IWK_FAIL;
2665                 goto exit;
2666         }
2667 
2668         if (ring->queued > ring->count - 64) {
2669                 IWK_DBG((IWK_DEBUG_TX, "iwk_send(): no txbuf\n"));
2670                 sc->sc_need_reschedule = 1;
2671                 mutex_exit(&sc->sc_tx_lock);
2672                 if ((type & IEEE80211_FC0_TYPE_MASK) !=
2673                     IEEE80211_FC0_TYPE_DATA) {
2674                         freemsg(mp);
2675                 }
2676                 sc->sc_tx_nobuf++;
2677                 err = IWK_FAIL;
2678                 goto exit;
2679         }
2680         mutex_exit(&sc->sc_tx_lock);
2681 
2682         hdrlen = sizeof (struct ieee80211_frame);
2683 
2684         m = allocb(msgdsize(mp) + 32, BPRI_MED);
2685         if (m == NULL) { /* can not alloc buf, drop this package */
2686                 cmn_err(CE_WARN,
2687                     "iwk_send(): failed to allocate msgbuf\n");
2688                 freemsg(mp);
2689                 err = IWK_SUCCESS;
2690                 goto exit;
2691         }
2692         for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
2693                 mblen = MBLKL(m0);
2694                 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
2695                 off += mblen;
2696         }
2697         m->b_wptr += off;
2698         freemsg(mp);
2699 
2700         wh = (struct ieee80211_frame *)m->b_rptr;
2701 
2702         if (ic->ic_opmode == IEEE80211_M_IBSS &&
2703             (!(IEEE80211_IS_MULTICAST(wh->i_addr1)))) {
2704                 mutex_enter(&sc->sc_glock);
2705                 mutex_enter(&sc->sc_ibss.node_tb_lock);
2706 
2707                 /*
2708                  * search for node in ibss node table
2709                  */
2710                 for (index1 = IWK_STA_ID;
2711                     index1 < IWK_STATION_COUNT; index1++) {
2712                         if (sc->sc_ibss.ibss_node_tb[index1].used &&
2713                             IEEE80211_ADDR_EQ(sc->sc_ibss.
2714                             ibss_node_tb[index1].node.bssid,
2715                             wh->i_addr1)) {
2716                                 break;
2717                         }
2718                 }
2719 
2720                 /*
2721                  * if don't find in ibss node table
2722                  */
2723                 if (index1 >= IWK_BROADCAST_ID) {
2724                         err = iwk_clean_add_node_ibss(ic,
2725                             wh->i_addr1, &index2);
2726                         if (err != IWK_SUCCESS) {
2727                                 cmn_err(CE_WARN, "iwk_send(): "
2728                                     "failed to clean all nodes "
2729                                     "and add one node\n");
2730                                 mutex_exit(&sc->sc_ibss.node_tb_lock);
2731                                 mutex_exit(&sc->sc_glock);
2732                                 freemsg(m);
2733                                 sc->sc_tx_err++;
2734                                 err = IWK_SUCCESS;
2735                                 goto exit;
2736                         }
2737                         index = index2;
2738                 } else {
2739                         index = index1;
2740                 }
2741                 mutex_exit(&sc->sc_ibss.node_tb_lock);
2742                 mutex_exit(&sc->sc_glock);
2743         }
2744 
2745         in = ieee80211_find_txnode(ic, wh->i_addr1);
2746         if (in == NULL) {
2747                 cmn_err(CE_WARN, "iwk_send(): failed to find tx node\n");
2748                 freemsg(m);
2749                 sc->sc_tx_err++;
2750                 err = IWK_SUCCESS;
2751                 goto exit;
2752         }
2753         (void) ieee80211_encap(ic, m, in);
2754 
2755         cmd->hdr.type = REPLY_TX;
2756         cmd->hdr.flags = 0;
2757         cmd->hdr.qid = ring->qid;
2758         cmd->hdr.idx = ring->cur;
2759 
2760         tx = (iwk_tx_cmd_t *)cmd->data;
2761         tx->tx_flags = 0;
2762 
2763         if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2764                 tx->tx_flags &= ~(LE_32(TX_CMD_FLG_ACK_MSK));
2765         } else {
2766                 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK);
2767         }
2768 
2769         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2770                 k = ieee80211_crypto_encap(ic, m);
2771                 if (k == NULL) {
2772                         freemsg(m);
2773                         sc->sc_tx_err++;
2774                         err = IWK_SUCCESS;
2775                         goto exit;
2776                 }
2777 
2778                 if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM) {
2779                         tx->sec_ctl = 2; /* for CCMP */
2780                         tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK);
2781                         (void) memcpy(&tx->key, k->wk_key, k->wk_keylen);
2782                 }
2783 
2784                 /* packet header may have moved, reset our local pointer */
2785                 wh = (struct ieee80211_frame *)m->b_rptr;
2786         }
2787 
2788         len = msgdsize(m);
2789 
2790 #ifdef DEBUG
2791         if (iwk_dbg_flags & IWK_DEBUG_TX)
2792                 ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0);
2793 #endif
2794 
2795         /* pickup a rate */
2796         if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2797             IEEE80211_FC0_TYPE_MGT) {
2798                 /* mgmt frames are sent at 1M */
2799                 rate = in->in_rates.ir_rates[0];
2800         } else {
2801                 /*
2802                  * do it here for the software way rate control.
2803                  * later for rate scaling in hardware.
2804                  * maybe like the following, for management frame:
2805                  * tx->initial_rate_index = LINK_QUAL_MAX_RETRY_NUM - 1;
2806                  * for data frame:
2807                  * tx->tx_flags |= (LE_32(TX_CMD_FLG_STA_RATE_MSK));
2808                  * rate = in->in_rates.ir_rates[in->in_txrate];
2809                  * tx->initial_rate_index = 1;
2810                  *
2811                  * now the txrate is determined in tx cmd flags, set to the
2812                  * max value 54M for 11g and 11M for 11b.
2813                  */
2814 
2815                 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
2816                         rate = ic->ic_fixed_rate;
2817                 } else {
2818                         rate = in->in_rates.ir_rates[in->in_txrate];
2819                 }
2820         }
2821         rate &= IEEE80211_RATE_VAL;
2822         IWK_DBG((IWK_DEBUG_TX, "tx rate[%d of %d] = %x",
2823             in->in_txrate, in->in_rates.ir_nrates, rate));
2824 
2825         tx->tx_flags |= (LE_32(TX_CMD_FLG_SEQ_CTL_MSK));
2826 
2827         len0 = roundup(4 + sizeof (iwk_tx_cmd_t) + hdrlen, 4);
2828         if (len0 != (4 + sizeof (iwk_tx_cmd_t) + hdrlen))
2829                 tx->tx_flags |= LE_32(TX_CMD_FLG_MH_PAD_MSK);
2830 
2831         /* retrieve destination node's id */
2832         if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2833                 tx->sta_id = IWK_BROADCAST_ID;
2834         } else {
2835                 if (ic->ic_opmode == IEEE80211_M_IBSS)
2836                         tx->sta_id = index;
2837                 else
2838                         tx->sta_id = IWK_AP_ID;
2839         }
2840 
2841         if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2842             IEEE80211_FC0_TYPE_MGT) {
2843                 /* tell h/w to set timestamp in probe responses */
2844                 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2845                     IEEE80211_FC0_SUBTYPE_PROBE_RESP)
2846                         tx->tx_flags |= LE_32(TX_CMD_FLG_TSF_MSK);
2847 
2848                 if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2849                     IEEE80211_FC0_SUBTYPE_ASSOC_REQ) ||
2850                     ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2851                     IEEE80211_FC0_SUBTYPE_REASSOC_REQ))
2852                         tx->timeout.pm_frame_timeout = LE_16(3);
2853                 else
2854                         tx->timeout.pm_frame_timeout = LE_16(2);
2855         } else
2856                 tx->timeout.pm_frame_timeout = 0;
2857         if (rate == 2 || rate == 4 || rate == 11 || rate == 22)
2858                 masks |= RATE_MCS_CCK_MSK;
2859 
2860         masks |= RATE_MCS_ANT_B_MSK;
2861         tx->rate.r.rate_n_flags = LE_32(iwk_rate_to_plcp(rate) | masks);
2862 
2863         IWK_DBG((IWK_DEBUG_TX, "tx flag = %x",
2864             LE_32(tx->tx_flags)));
2865 
2866         tx->rts_retry_limit = 60;
2867         tx->data_retry_limit = 15;
2868 
2869         tx->stop_time.life_time  = LE_32(0xffffffff);
2870 
2871         tx->len = LE_16(len);
2872 
2873         tx->dram_lsb_ptr =
2874             LE_32(data->paddr_cmd + 4 + offsetof(iwk_tx_cmd_t, scratch));
2875         tx->dram_msb_ptr = 0;
2876         tx->driver_txop = 0;
2877         tx->next_frame_len = 0;
2878 
2879         (void) memcpy(tx + 1, m->b_rptr, hdrlen);
2880         m->b_rptr += hdrlen;
2881         (void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen);
2882 
2883         IWK_DBG((IWK_DEBUG_TX, "sending data: qid=%d idx=%d len=%d",
2884             ring->qid, ring->cur, len));
2885 
2886         /*
2887          * first segment includes the tx cmd plus the 802.11 header,
2888          * the second includes the remaining of the 802.11 frame.
2889          */
2890         desc->val0 = 2 << 24;
2891         desc->pa[0].tb1_addr = data->paddr_cmd;
2892         desc->pa[0].val1 = ((len0 << 4) & 0xfff0) |
2893             ((data->dma_data.cookie.dmac_address & 0xffff) << 16);
2894         desc->pa[0].val2 =
2895             ((data->dma_data.cookie.dmac_address & 0xffff0000) >> 16) |
2896             ((len - hdrlen) << 20);
2897         IWK_DBG((IWK_DEBUG_TX, "phy addr1 = 0x%x phy addr2 = 0x%x "
2898             "len1 = 0x%x, len2 = 0x%x val1 = 0x%x val2 = 0x%x",
2899             data->paddr_cmd, data->dma_data.cookie.dmac_address,
2900             len0, len - hdrlen, LE_32(desc->pa[0].val1),
2901             LE_32(desc->pa[0].val2)));
2902 
2903         mutex_enter(&sc->sc_tx_lock);
2904         ring->queued++;
2905         mutex_exit(&sc->sc_tx_lock);
2906 
2907         /* kick ring */
2908         sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
2909             tfd_offset[ring->cur].val = 8 + len;
2910         if (ring->cur < IWK_MAX_WIN_SIZE) {
2911                 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
2912                     tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8 + len;
2913         }
2914 
2915         IWK_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV);
2916         IWK_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV);
2917 
2918         ring->cur = (ring->cur + 1) % ring->count;
2919         IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
2920         freemsg(m);
2921         /* release node reference */
2922         ieee80211_free_node(in);
2923 
2924         ic->ic_stats.is_tx_bytes += len;
2925         ic->ic_stats.is_tx_frags++;
2926 
2927         if (sc->sc_tx_timer == 0)
2928                 sc->sc_tx_timer = 4;
2929 
2930 exit:
2931         return (err);
2932 }
2933 
2934 static void
2935 iwk_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
2936 {
2937         iwk_sc_t        *sc  = (iwk_sc_t *)arg;
2938         ieee80211com_t  *ic = &sc->sc_ic;
2939 
2940         enum ieee80211_opmode           oldmod;
2941         iwk_tx_power_table_cmd_t        txpower;
2942         iwk_add_sta_t                   node;
2943         iwk_link_quality_cmd_t          link_quality;
2944         uint16_t                        masks = 0;
2945         int                             i, err, err1;
2946 
2947         oldmod = ic->ic_opmode;
2948 
2949         err = ieee80211_ioctl(ic, wq, mp);
2950 
2951         /*
2952          * return to STA mode
2953          */
2954         if ((0 == err || ENETRESET == err) && (oldmod != ic->ic_opmode) &&
2955             (ic->ic_opmode == IEEE80211_M_STA)) {
2956                 /* configure rxon */
2957                 (void) memset(&sc->sc_config, 0, sizeof (iwk_rxon_cmd_t));
2958                 IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr);
2959                 IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr);
2960                 sc->sc_config.chan =
2961                     LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
2962                 sc->sc_config.flags = LE_32(RXON_FLG_TSF2HOST_MSK |
2963                     RXON_FLG_AUTO_DETECT_MSK |
2964                     RXON_FLG_BAND_24G_MSK);
2965                 sc->sc_config.flags &= LE_32(~RXON_FLG_CCK_MSK);
2966                 switch (ic->ic_opmode) {
2967                 case IEEE80211_M_STA:
2968                         sc->sc_config.dev_type = RXON_DEV_TYPE_ESS;
2969                         sc->sc_config.filter_flags |=
2970                             LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
2971                             RXON_FILTER_DIS_DECRYPT_MSK |
2972                             RXON_FILTER_DIS_GRP_DECRYPT_MSK);
2973                         break;
2974                 case IEEE80211_M_IBSS:
2975                 case IEEE80211_M_AHDEMO:
2976                         sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
2977                         sc->sc_config.flags |=
2978                             LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
2979                         sc->sc_config.filter_flags =
2980                             LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
2981                             RXON_FILTER_DIS_DECRYPT_MSK |
2982                             RXON_FILTER_DIS_GRP_DECRYPT_MSK);
2983                         break;
2984                 case IEEE80211_M_HOSTAP:
2985                         sc->sc_config.dev_type = RXON_DEV_TYPE_AP;
2986                         break;
2987                 case IEEE80211_M_MONITOR:
2988                         sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER;
2989                         sc->sc_config.filter_flags |=
2990                             LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
2991                             RXON_FILTER_CTL2HOST_MSK |
2992                             RXON_FILTER_PROMISC_MSK);
2993                         break;
2994                 }
2995                 sc->sc_config.cck_basic_rates  = 0x0f;
2996                 sc->sc_config.ofdm_basic_rates = 0xff;
2997                 sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
2998                 sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff;
2999                 /* set antenna */
3000                 mutex_enter(&sc->sc_glock);
3001                 sc->sc_config.rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
3002                     (0x7 << RXON_RX_CHAIN_VALID_POS) |
3003                     (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
3004                     (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
3005                 err1 = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
3006                     sizeof (iwk_rxon_cmd_t), 1);
3007                 if (err1 != IWK_SUCCESS) {
3008                         cmn_err(CE_WARN, "iwk_m_ioctl(): "
3009                             "failed to set configure command"
3010                             " please run (ifconfig unplumb and"
3011                             " ifconfig plumb)\n");
3012                 }
3013                 /*
3014                  * set Tx power for 2.4GHz channels
3015                  * (need further investigation. fix tx power at present)
3016                  */
3017                 (void) memset(&txpower, 0, sizeof (txpower));
3018                 txpower.band = 1; /* for 2.4G */
3019                 txpower.channel = sc->sc_config.chan;
3020                 txpower.channel_normal_width = 0;
3021                 for (i = 0; i < POWER_TABLE_NUM_HT_OFDM_ENTRIES; i++) {
3022                         txpower.tx_power.ht_ofdm_power[i].
3023                             s.ramon_tx_gain = LE_16(0x3f3f);
3024                         txpower.tx_power.ht_ofdm_power[i].
3025                             s.dsp_predis_atten = LE_16(110 | (110 << 8));
3026                 }
3027                 txpower.tx_power.legacy_cck_power.s.
3028                     ramon_tx_gain = LE_16(0x3f3f);
3029                 txpower.tx_power.legacy_cck_power.s.
3030                     dsp_predis_atten = LE_16(110 | (110 << 8));
3031                 err1 = iwk_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &txpower,
3032                     sizeof (txpower), 1);
3033                 if (err1 != IWK_SUCCESS) {
3034                         cmn_err(CE_WARN, "iwk_m_ioctl(): failed to set txpower"
3035                             " please run (ifconfig unplumb "
3036                             "and ifconfig plumb)\n");
3037                 }
3038                 /* add broadcast node so that we can send broadcast frame */
3039                 (void) memset(&node, 0, sizeof (node));
3040                 (void) memset(node.bssid, 0xff, 6);
3041                 node.id = IWK_BROADCAST_ID;
3042                 err1 = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
3043                 if (err1 != IWK_SUCCESS) {
3044                         cmn_err(CE_WARN, "iwk_m_ioctl(): "
3045                             "failed to add broadcast node\n");
3046                 }
3047 
3048                 /* TX_LINK_QUALITY cmd */
3049                 (void) memset(&link_quality, 0, sizeof (link_quality));
3050                 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
3051                         masks |= RATE_MCS_CCK_MSK;
3052                         masks |= RATE_MCS_ANT_B_MSK;
3053                         masks &= ~RATE_MCS_ANT_A_MSK;
3054                         link_quality.rate_n_flags[i] =
3055                             LE_32(iwk_rate_to_plcp(2) | masks);
3056                 }
3057                 link_quality.general_params.single_stream_ant_msk = 2;
3058                 link_quality.general_params.dual_stream_ant_msk = 3;
3059                 link_quality.agg_params.agg_dis_start_th = 3;
3060                 link_quality.agg_params.agg_time_limit = LE_16(4000);
3061                 link_quality.sta_id = IWK_BROADCAST_ID;
3062                 err1 = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
3063                     sizeof (link_quality), 1);
3064                 if (err1 != IWK_SUCCESS) {
3065                         cmn_err(CE_WARN, "iwk_m_ioctl(): "
3066                             "failed to config link quality table\n");
3067                 }
3068                 mutex_exit(&sc->sc_glock);
3069                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3070         }
3071 
3072         if (err == ENETRESET) {
3073                 /*
3074                  * This is special for the hidden AP connection.
3075                  * In any case, we should make sure only one 'scan'
3076                  * in the driver for a 'connect' CLI command. So
3077                  * when connecting to a hidden AP, the scan is just
3078                  * sent out to the air when we know the desired
3079                  * essid of the AP we want to connect.
3080                  */
3081                 if (ic->ic_des_esslen) {
3082                         if (sc->sc_flags & IWK_F_RUNNING) {
3083                                 iwk_m_stop(sc);
3084                                 (void) iwk_m_start(sc);
3085                                 (void) ieee80211_new_state(ic,
3086                                     IEEE80211_S_SCAN, -1);
3087                         }
3088                 }
3089         }
3090 }
3091 
3092 /*
3093  * callback functions for set/get properties
3094  */
3095 
3096 static int
3097 iwk_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3098     uint_t wldp_length, void *wldp_buf)
3099 {
3100         int             err = 0;
3101         iwk_sc_t        *sc = (iwk_sc_t *)arg;
3102 
3103         err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
3104             wldp_length, wldp_buf);
3105 
3106         return (err);
3107 }
3108 
3109 static int
3110 iwk_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3111     uint_t wldp_length, const void *wldp_buf)
3112 {
3113         int             err;
3114         iwk_sc_t        *sc = (iwk_sc_t *)arg;
3115         ieee80211com_t  *ic = &sc->sc_ic;
3116 
3117         err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
3118             wldp_buf);
3119 
3120         if (err == ENETRESET) {
3121                 if (ic->ic_des_esslen) {
3122                         if (sc->sc_flags & IWK_F_RUNNING) {
3123                                 iwk_m_stop(sc);
3124                                 (void) iwk_m_start(sc);
3125                                 (void) ieee80211_new_state(ic,
3126                                     IEEE80211_S_SCAN, -1);
3127                         }
3128                 }
3129                 err = 0;
3130         }
3131 
3132         return (err);
3133 }
3134 
3135 static void
3136 iwk_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
3137     mac_prop_info_handle_t mph)
3138 {
3139         iwk_sc_t        *sc = (iwk_sc_t *)arg;
3140         ieee80211com_t  *ic = &sc->sc_ic;
3141 
3142         ieee80211_propinfo(ic, pr_name, wldp_pr_num, mph);
3143 }
3144 
3145 /*ARGSUSED*/
3146 static int
3147 iwk_m_stat(void *arg, uint_t stat, uint64_t *val)
3148 {
3149         iwk_sc_t        *sc  = (iwk_sc_t *)arg;
3150         ieee80211com_t  *ic = &sc->sc_ic;
3151         ieee80211_node_t *in;
3152 
3153         mutex_enter(&sc->sc_glock);
3154         switch (stat) {
3155         case MAC_STAT_IFSPEED:
3156                 in = ic->ic_bss;
3157                 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
3158                     IEEE80211_RATE(in->in_txrate) :
3159                     ic->ic_fixed_rate) / 2 * 1000000;
3160                 break;
3161         case MAC_STAT_NOXMTBUF:
3162                 *val = sc->sc_tx_nobuf;
3163                 break;
3164         case MAC_STAT_NORCVBUF:
3165                 *val = sc->sc_rx_nobuf;
3166                 break;
3167         case MAC_STAT_IERRORS:
3168                 *val = sc->sc_rx_err;
3169                 break;
3170         case MAC_STAT_RBYTES:
3171                 *val = ic->ic_stats.is_rx_bytes;
3172                 break;
3173         case MAC_STAT_IPACKETS:
3174                 *val = ic->ic_stats.is_rx_frags;
3175                 break;
3176         case MAC_STAT_OBYTES:
3177                 *val = ic->ic_stats.is_tx_bytes;
3178                 break;
3179         case MAC_STAT_OPACKETS:
3180                 *val = ic->ic_stats.is_tx_frags;
3181                 break;
3182         case MAC_STAT_OERRORS:
3183         case WIFI_STAT_TX_FAILED:
3184                 *val = sc->sc_tx_err;
3185                 break;
3186         case WIFI_STAT_TX_RETRANS:
3187                 *val = sc->sc_tx_retries;
3188                 break;
3189         case WIFI_STAT_FCS_ERRORS:
3190         case WIFI_STAT_WEP_ERRORS:
3191         case WIFI_STAT_TX_FRAGS:
3192         case WIFI_STAT_MCAST_TX:
3193         case WIFI_STAT_RTS_SUCCESS:
3194         case WIFI_STAT_RTS_FAILURE:
3195         case WIFI_STAT_ACK_FAILURE:
3196         case WIFI_STAT_RX_FRAGS:
3197         case WIFI_STAT_MCAST_RX:
3198         case WIFI_STAT_RX_DUPS:
3199                 mutex_exit(&sc->sc_glock);
3200                 return (ieee80211_stat(ic, stat, val));
3201         default:
3202                 mutex_exit(&sc->sc_glock);
3203                 return (ENOTSUP);
3204         }
3205         mutex_exit(&sc->sc_glock);
3206 
3207         return (IWK_SUCCESS);
3208 
3209 }
3210 
3211 static int
3212 iwk_m_start(void *arg)
3213 {
3214         iwk_sc_t *sc = (iwk_sc_t *)arg;
3215         ieee80211com_t  *ic = &sc->sc_ic;
3216         int err;
3217 
3218         err = iwk_init(sc);
3219 
3220         if (err != IWK_SUCCESS) {
3221                 /*
3222                  * The hw init err(eg. RF is OFF). Return Success to make
3223                  * the 'plumb' succeed. The iwk_thread() tries to re-init
3224                  * background.
3225                  */
3226                 mutex_enter(&sc->sc_glock);
3227                 sc->sc_flags |= IWK_F_HW_ERR_RECOVER;
3228                 mutex_exit(&sc->sc_glock);
3229                 return (IWK_SUCCESS);
3230         }
3231 
3232         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3233 
3234         mutex_enter(&sc->sc_glock);
3235         sc->sc_flags |= IWK_F_RUNNING;
3236         mutex_exit(&sc->sc_glock);
3237 
3238         return (IWK_SUCCESS);
3239 }
3240 
3241 static void
3242 iwk_m_stop(void *arg)
3243 {
3244         iwk_sc_t *sc = (iwk_sc_t *)arg;
3245         ieee80211com_t  *ic = &sc->sc_ic;
3246 
3247         iwk_stop(sc);
3248         ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3249         ieee80211_stop_watchdog(ic);
3250         mutex_enter(&sc->sc_mt_lock);
3251         sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER;
3252         sc->sc_flags &= ~IWK_F_RATE_AUTO_CTL;
3253         mutex_exit(&sc->sc_mt_lock);
3254         mutex_enter(&sc->sc_glock);
3255         sc->sc_flags &= ~IWK_F_RUNNING;
3256         mutex_exit(&sc->sc_glock);
3257 }
3258 
3259 /*ARGSUSED*/
3260 static int
3261 iwk_m_unicst(void *arg, const uint8_t *macaddr)
3262 {
3263         iwk_sc_t *sc = (iwk_sc_t *)arg;
3264         ieee80211com_t  *ic = &sc->sc_ic;
3265         int err;
3266 
3267         if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) {
3268                 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
3269                 mutex_enter(&sc->sc_glock);
3270                 err = iwk_config(sc);
3271                 mutex_exit(&sc->sc_glock);
3272                 if (err != IWK_SUCCESS) {
3273                         cmn_err(CE_WARN,
3274                             "iwk_m_unicst(): "
3275                             "failed to configure device\n");
3276                         goto fail;
3277                 }
3278         }
3279         return (IWK_SUCCESS);
3280 fail:
3281         return (err);
3282 }
3283 
3284 /*ARGSUSED*/
3285 static int
3286 iwk_m_multicst(void *arg, boolean_t add, const uint8_t *m)
3287 {
3288         return (IWK_SUCCESS);
3289 }
3290 
3291 /*ARGSUSED*/
3292 static int
3293 iwk_m_promisc(void *arg, boolean_t on)
3294 {
3295         return (IWK_SUCCESS);
3296 }
3297 
3298 static void
3299 iwk_thread(iwk_sc_t *sc)
3300 {
3301         ieee80211com_t  *ic = &sc->sc_ic;
3302         clock_t clk;
3303         int times = 0, err, n = 0, timeout = 0;
3304         uint32_t tmp;
3305 
3306         mutex_enter(&sc->sc_mt_lock);
3307         while (sc->sc_mf_thread_switch) {
3308                 tmp = IWK_READ(sc, CSR_GP_CNTRL);
3309                 if (tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) {
3310                         sc->sc_flags &= ~IWK_F_RADIO_OFF;
3311                 } else {
3312                         sc->sc_flags |= IWK_F_RADIO_OFF;
3313                 }
3314                 /*
3315                  * If in SUSPEND or the RF is OFF, do nothing
3316                  */
3317                 if ((sc->sc_flags & IWK_F_SUSPEND) ||
3318                     (sc->sc_flags & IWK_F_RADIO_OFF)) {
3319                         mutex_exit(&sc->sc_mt_lock);
3320                         delay(drv_usectohz(100000));
3321                         mutex_enter(&sc->sc_mt_lock);
3322                         continue;
3323                 }
3324 
3325                 /*
3326                  * recovery fatal error
3327                  */
3328                 if (ic->ic_mach &&
3329                     (sc->sc_flags & IWK_F_HW_ERR_RECOVER)) {
3330 
3331                         IWK_DBG((IWK_DEBUG_FW,
3332                             "iwk_thread(): "
3333                             "try to recover fatal hw error: %d\n", times++));
3334 
3335                         iwk_stop(sc);
3336 
3337                         if (IWK_CHK_FAST_RECOVER(sc)) {
3338                                 /* save runtime configuration */
3339                                 bcopy(&sc->sc_config, &sc->sc_config_save,
3340                                     sizeof (sc->sc_config));
3341                         } else {
3342                                 mutex_exit(&sc->sc_mt_lock);
3343                                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3344                                 delay(drv_usectohz(2000000 + n*500000));
3345                                 mutex_enter(&sc->sc_mt_lock);
3346                         }
3347 
3348                         err = iwk_init(sc);
3349                         if (err != IWK_SUCCESS) {
3350                                 n++;
3351                                 if (n < 20)
3352                                         continue;
3353                         }
3354                         n = 0;
3355                         if (!err)
3356                                 sc->sc_flags |= IWK_F_RUNNING;
3357 
3358                         if (!IWK_CHK_FAST_RECOVER(sc) ||
3359                             iwk_fast_recover(sc) != IWK_SUCCESS) {
3360                                 sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER;
3361 
3362                                 mutex_exit(&sc->sc_mt_lock);
3363                                 delay(drv_usectohz(2000000));
3364                                 if (sc->sc_ostate != IEEE80211_S_INIT)
3365                                         ieee80211_new_state(ic,
3366                                             IEEE80211_S_SCAN, 0);
3367                                 mutex_enter(&sc->sc_mt_lock);
3368                         }
3369                 }
3370 
3371                 if (ic->ic_mach && (sc->sc_flags & IWK_F_LAZY_RESUME)) {
3372                         IWK_DBG((IWK_DEBUG_RESUME,
3373                             "iwk_thread(): lazy resume\n"));
3374 
3375                         sc->sc_flags &= ~IWK_F_LAZY_RESUME;
3376                         mutex_exit(&sc->sc_mt_lock);
3377                         /*
3378                          * NB: under WPA mode, this call hangs (door problem?)
3379                          * when called in iwk_attach() and iwk_detach() while
3380                          * system is in the procedure of CPR. To be safe, let
3381                          * the thread do this.
3382                          */
3383                         ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
3384                         mutex_enter(&sc->sc_mt_lock);
3385                 }
3386 
3387                 if (ic->ic_mach &&
3388                     (sc->sc_flags & IWK_F_SCANNING) && sc->sc_scan_pending) {
3389                         IWK_DBG((IWK_DEBUG_SCAN,
3390                             "iwk_thread(): "
3391                             "wait for probe response\n"));
3392                         sc->sc_scan_pending--;
3393                         mutex_exit(&sc->sc_mt_lock);
3394                         delay(drv_usectohz(200000));
3395                         if (sc->sc_flags & IWK_F_SCANNING)
3396                                 ieee80211_next_scan(ic);
3397                         mutex_enter(&sc->sc_mt_lock);
3398                 }
3399 
3400                 /*
3401                  * rate ctl
3402                  */
3403                 if (ic->ic_mach &&
3404                     (sc->sc_flags & IWK_F_RATE_AUTO_CTL)) {
3405                         clk = ddi_get_lbolt();
3406                         if (clk > sc->sc_clk + drv_usectohz(500000)) {
3407                                 iwk_amrr_timeout(sc);
3408                         }
3409                 }
3410 
3411                 if ((ic->ic_state == IEEE80211_S_RUN) &&
3412                     (ic->ic_beaconmiss++ > 50)) { /* 5 seconds */
3413                         cmn_err(CE_WARN, "iwk: beacon missed for 5 seconds\n");
3414                         (void) ieee80211_new_state(ic,
3415                             IEEE80211_S_INIT, -1);
3416                 }
3417 
3418                 mutex_exit(&sc->sc_mt_lock);
3419                 delay(drv_usectohz(100000));
3420                 mutex_enter(&sc->sc_mt_lock);
3421 
3422                 if (sc->sc_tx_timer) {
3423                         timeout++;
3424                         if (timeout == 10) {
3425                                 sc->sc_tx_timer--;
3426                                 if (sc->sc_tx_timer == 0) {
3427                                         sc->sc_flags |= IWK_F_HW_ERR_RECOVER;
3428                                         sc->sc_ostate = IEEE80211_S_RUN;
3429                                         IWK_DBG((IWK_DEBUG_FW,
3430                                             "iwk_thread(): try to recover from"
3431                                             " 'send fail\n"));
3432                                 }
3433                                 timeout = 0;
3434                         }
3435                 }
3436 
3437         }
3438         sc->sc_mf_thread = NULL;
3439         cv_signal(&sc->sc_mt_cv);
3440         mutex_exit(&sc->sc_mt_lock);
3441 }
3442 
3443 
3444 /*
3445  * Send a command to the firmware.
3446  */
3447 static int
3448 iwk_cmd(iwk_sc_t *sc, int code, const void *buf, int size, int async)
3449 {
3450         iwk_tx_ring_t *ring = &sc->sc_txq[IWK_CMD_QUEUE_NUM];
3451         iwk_tx_desc_t *desc;
3452         iwk_cmd_t *cmd;
3453         clock_t clk;
3454 
3455         ASSERT(size <= sizeof (cmd->data));
3456         ASSERT(mutex_owned(&sc->sc_glock));
3457 
3458         IWK_DBG((IWK_DEBUG_CMD, "iwk_cmd() code[%d]", code));
3459         desc = ring->data[ring->cur].desc;
3460         cmd = ring->data[ring->cur].cmd;
3461 
3462         cmd->hdr.type = (uint8_t)code;
3463         cmd->hdr.flags = 0;
3464         cmd->hdr.qid = ring->qid;
3465         cmd->hdr.idx = ring->cur;
3466         (void) memcpy(cmd->data, buf, size);
3467         (void) memset(desc, 0, sizeof (*desc));
3468 
3469         desc->val0 = 1 << 24;
3470         desc->pa[0].tb1_addr =
3471             (uint32_t)(ring->data[ring->cur].paddr_cmd & 0xffffffff);
3472         desc->pa[0].val1 = ((4 + size) << 4) & 0xfff0;
3473 
3474         /* kick cmd ring XXX */
3475         sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3476             tfd_offset[ring->cur].val = 8;
3477         if (ring->cur < IWK_MAX_WIN_SIZE) {
3478                 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3479                     tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8;
3480         }
3481         ring->cur = (ring->cur + 1) % ring->count;
3482         IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
3483 
3484         if (async)
3485                 return (IWK_SUCCESS);
3486         else {
3487                 sc->sc_flags &= ~IWK_F_CMD_DONE;
3488                 clk = ddi_get_lbolt() + drv_usectohz(2000000);
3489                 while (!(sc->sc_flags & IWK_F_CMD_DONE)) {
3490                         if (cv_timedwait(&sc->sc_cmd_cv, &sc->sc_glock, clk) <
3491                             0)
3492                                 break;
3493                 }
3494                 if (sc->sc_flags & IWK_F_CMD_DONE)
3495                         return (IWK_SUCCESS);
3496                 else
3497                         return (IWK_FAIL);
3498         }
3499 }
3500 
3501 static void
3502 iwk_set_led(iwk_sc_t *sc, uint8_t id, uint8_t off, uint8_t on)
3503 {
3504         iwk_led_cmd_t led;
3505 
3506         led.interval = LE_32(100000);   /* unit: 100ms */
3507         led.id = id;
3508         led.off = off;
3509         led.on = on;
3510 
3511         (void) iwk_cmd(sc, REPLY_LEDS_CMD, &led, sizeof (led), 1);
3512 }
3513 
3514 static int
3515 iwk_hw_set_before_auth(iwk_sc_t *sc)
3516 {
3517         ieee80211com_t *ic = &sc->sc_ic;
3518         ieee80211_node_t *in = ic->ic_bss;
3519         iwk_add_sta_t node;
3520         iwk_link_quality_cmd_t link_quality;
3521         struct ieee80211_rateset rs;
3522         uint16_t masks = 0, rate;
3523         int i, err;
3524 
3525         if (in->in_chan == IEEE80211_CHAN_ANYC) {
3526                 cmn_err(CE_WARN, "iwk_hw_set_before_auth():"
3527                     "channel (%d) isn't in proper range\n",
3528                     LE_16(ieee80211_chan2ieee(ic, in->in_chan)));
3529                 return (IWK_FAIL);
3530         }
3531 
3532         /* update adapter's configuration according the info of target AP */
3533         IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
3534         sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, in->in_chan));
3535         if (ic->ic_curmode == IEEE80211_MODE_11B) {
3536                 sc->sc_config.cck_basic_rates  = 0x03;
3537                 sc->sc_config.ofdm_basic_rates = 0;
3538         } else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
3539             (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
3540                 sc->sc_config.cck_basic_rates  = 0;
3541                 sc->sc_config.ofdm_basic_rates = 0x15;
3542         } else { /* assume 802.11b/g */
3543                 sc->sc_config.cck_basic_rates  = 0x0f;
3544                 sc->sc_config.ofdm_basic_rates = 0xff;
3545         }
3546 
3547         sc->sc_config.flags &= ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
3548             RXON_FLG_SHORT_SLOT_MSK);
3549 
3550         if (ic->ic_flags & IEEE80211_F_SHSLOT)
3551                 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_SLOT_MSK);
3552         else
3553                 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_SLOT_MSK);
3554 
3555         if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
3556                 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
3557         else
3558                 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_PREAMBLE_MSK);
3559 
3560         IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x "
3561             "filter_flags %x  cck %x ofdm %x"
3562             " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n",
3563             LE_16(sc->sc_config.chan), LE_32(sc->sc_config.flags),
3564             LE_32(sc->sc_config.filter_flags),
3565             sc->sc_config.cck_basic_rates, sc->sc_config.ofdm_basic_rates,
3566             sc->sc_config.bssid[0], sc->sc_config.bssid[1],
3567             sc->sc_config.bssid[2], sc->sc_config.bssid[3],
3568             sc->sc_config.bssid[4], sc->sc_config.bssid[5]));
3569         err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
3570             sizeof (iwk_rxon_cmd_t), 1);
3571         if (err != IWK_SUCCESS) {
3572                 cmn_err(CE_WARN, "iwk_hw_set_before_auth():"
3573                     " failed to config chan%d\n",
3574                     sc->sc_config.chan);
3575                 return (err);
3576         }
3577 
3578         /* obtain current temperature of chipset */
3579         sc->sc_tempera = iwk_curr_tempera(sc);
3580 
3581         /* make Tx power calibration to determine the gains of DSP and radio */
3582         err = iwk_tx_power_calibration(sc);
3583         if (err) {
3584                 cmn_err(CE_WARN, "iwk_hw_set_before_auth():"
3585                     "failed to set tx power table\n");
3586                 return (err);
3587         }
3588 
3589         /* add default AP node */
3590         (void) memset(&node, 0, sizeof (node));
3591         IEEE80211_ADDR_COPY(node.bssid, in->in_bssid);
3592         node.id = IWK_AP_ID;
3593         err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
3594         if (err != IWK_SUCCESS) {
3595                 cmn_err(CE_WARN, "iwk_hw_set_before_auth(): "
3596                     "failed to add BSS node\n");
3597                 return (err);
3598         }
3599 
3600         /* TX_LINK_QUALITY cmd */
3601         (void) memset(&link_quality, 0, sizeof (link_quality));
3602         rs = ic->ic_sup_rates[ieee80211_chan2mode(ic, ic->ic_curchan)];
3603         for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
3604                 if (i < rs.ir_nrates)
3605                         rate = rs.ir_rates[rs.ir_nrates - i];
3606                 else
3607                         rate = 2;
3608                 if (rate == 2 || rate == 4 || rate == 11 || rate == 22)
3609                         masks |= RATE_MCS_CCK_MSK;
3610                 masks |= RATE_MCS_ANT_B_MSK;
3611                 masks &= ~RATE_MCS_ANT_A_MSK;
3612                 link_quality.rate_n_flags[i] =
3613                     LE_32(iwk_rate_to_plcp(rate) | masks);
3614         }
3615 
3616         link_quality.general_params.single_stream_ant_msk = 2;
3617         link_quality.general_params.dual_stream_ant_msk = 3;
3618         link_quality.agg_params.agg_dis_start_th = 3;
3619         link_quality.agg_params.agg_time_limit = LE_16(4000);
3620         link_quality.sta_id = IWK_AP_ID;
3621         err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
3622             sizeof (link_quality), 1);
3623         if (err != IWK_SUCCESS) {
3624                 cmn_err(CE_WARN, "iwk_hw_set_before_auth(): "
3625                     "failed to config link quality table\n");
3626                 return (err);
3627         }
3628 
3629         return (IWK_SUCCESS);
3630 }
3631 
3632 /*
3633  * Send a scan request(assembly scan cmd) to the firmware.
3634  */
3635 static int
3636 iwk_scan(iwk_sc_t *sc)
3637 {
3638         ieee80211com_t *ic = &sc->sc_ic;
3639         iwk_tx_ring_t *ring = &sc->sc_txq[IWK_CMD_QUEUE_NUM];
3640         iwk_tx_desc_t *desc;
3641         iwk_tx_data_t *data;
3642         iwk_cmd_t *cmd;
3643         iwk_scan_hdr_t *hdr;
3644         iwk_scan_chan_t *chan;
3645         struct ieee80211_frame *wh;
3646         ieee80211_node_t *in = ic->ic_bss;
3647         uint8_t essid[IEEE80211_NWID_LEN+1];
3648         struct ieee80211_rateset *rs;
3649         enum ieee80211_phymode mode;
3650         uint8_t *frm;
3651         int i, pktlen, nrates;
3652 
3653         data = &ring->data[ring->cur];
3654         desc = data->desc;
3655         cmd = (iwk_cmd_t *)data->dma_data.mem_va;
3656 
3657         cmd->hdr.type = REPLY_SCAN_CMD;
3658         cmd->hdr.flags = 0;
3659         cmd->hdr.qid = ring->qid;
3660         cmd->hdr.idx = ring->cur | 0x40;
3661 
3662         hdr = (iwk_scan_hdr_t *)cmd->data;
3663         (void) memset(hdr, 0, sizeof (iwk_scan_hdr_t));
3664         hdr->nchan = 1;
3665         hdr->quiet_time = LE_16(50);
3666         hdr->quiet_plcp_th = LE_16(1);
3667 
3668         hdr->flags = LE_32(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK);
3669         hdr->rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
3670             (0x7 << RXON_RX_CHAIN_VALID_POS) |
3671             (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
3672             (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
3673 
3674         hdr->tx_cmd.tx_flags = LE_32(TX_CMD_FLG_SEQ_CTL_MSK);
3675         hdr->tx_cmd.sta_id = IWK_BROADCAST_ID;
3676         hdr->tx_cmd.stop_time.life_time = LE_32(0xffffffff);
3677         hdr->tx_cmd.tx_flags |= LE_32(0x200);
3678         hdr->tx_cmd.rate.r.rate_n_flags = LE_32(iwk_rate_to_plcp(2));
3679         hdr->tx_cmd.rate.r.rate_n_flags |=
3680             LE_32(RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
3681         hdr->direct_scan[0].len = ic->ic_des_esslen;
3682         hdr->direct_scan[0].id  = IEEE80211_ELEMID_SSID;
3683 
3684         if (ic->ic_des_esslen) {
3685                 bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen);
3686                 essid[ic->ic_des_esslen] = '\0';
3687                 IWK_DBG((IWK_DEBUG_SCAN, "directed scan %s\n", essid));
3688 
3689                 bcopy(ic->ic_des_essid, hdr->direct_scan[0].ssid,
3690                     ic->ic_des_esslen);
3691         } else {
3692                 bzero(hdr->direct_scan[0].ssid,
3693                     sizeof (hdr->direct_scan[0].ssid));
3694         }
3695         /*
3696          * a probe request frame is required after the REPLY_SCAN_CMD
3697          */
3698         wh = (struct ieee80211_frame *)(hdr + 1);
3699         wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
3700             IEEE80211_FC0_SUBTYPE_PROBE_REQ;
3701         wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
3702         (void) memset(wh->i_addr1, 0xff, 6);
3703         IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr);
3704         (void) memset(wh->i_addr3, 0xff, 6);
3705         *(uint16_t *)&wh->i_dur[0] = 0;
3706         *(uint16_t *)&wh->i_seq[0] = 0;
3707 
3708         frm = (uint8_t *)(wh + 1);
3709 
3710         /* essid IE */
3711         if (in->in_esslen) {
3712                 bcopy(in->in_essid, essid, in->in_esslen);
3713                 essid[in->in_esslen] = '\0';
3714                 IWK_DBG((IWK_DEBUG_SCAN, "probe with ESSID %s\n",
3715                     essid));
3716         }
3717         *frm++ = IEEE80211_ELEMID_SSID;
3718         *frm++ = in->in_esslen;
3719         (void) memcpy(frm, in->in_essid, in->in_esslen);
3720         frm += in->in_esslen;
3721 
3722         mode = ieee80211_chan2mode(ic, ic->ic_curchan);
3723         rs = &ic->ic_sup_rates[mode];
3724 
3725         /* supported rates IE */
3726         *frm++ = IEEE80211_ELEMID_RATES;
3727         nrates = rs->ir_nrates;
3728         if (nrates > IEEE80211_RATE_SIZE)
3729                 nrates = IEEE80211_RATE_SIZE;
3730         *frm++ = (uint8_t)nrates;
3731         (void) memcpy(frm, rs->ir_rates, nrates);
3732         frm += nrates;
3733 
3734         /* supported xrates IE */
3735         if (rs->ir_nrates > IEEE80211_RATE_SIZE) {
3736                 nrates = rs->ir_nrates - IEEE80211_RATE_SIZE;
3737                 *frm++ = IEEE80211_ELEMID_XRATES;
3738                 *frm++ = (uint8_t)nrates;
3739                 (void) memcpy(frm, rs->ir_rates + IEEE80211_RATE_SIZE, nrates);
3740                 frm += nrates;
3741         }
3742 
3743         /* optionnal IE (usually for wpa) */
3744         if (ic->ic_opt_ie != NULL) {
3745                 (void) memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len);
3746                 frm += ic->ic_opt_ie_len;
3747         }
3748 
3749         /* setup length of probe request */
3750         hdr->tx_cmd.len = LE_16(_PTRDIFF(frm, wh));
3751         hdr->len = LE_16(hdr->nchan * sizeof (iwk_scan_chan_t) +
3752             LE_16(hdr->tx_cmd.len) + sizeof (iwk_scan_hdr_t));
3753 
3754         /*
3755          * the attribute of the scan channels are required after the probe
3756          * request frame.
3757          */
3758         chan = (iwk_scan_chan_t *)frm;
3759         for (i = 1; i <= hdr->nchan; i++, chan++) {
3760                 if (ic->ic_des_esslen) {
3761                         chan->type = 3;
3762                 } else {
3763                         chan->type = 1;
3764                 }
3765 
3766                 chan->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
3767                 chan->tpc.tx_gain = 0x3f;
3768                 chan->tpc.dsp_atten = 110;
3769                 chan->active_dwell = LE_16(50);
3770                 chan->passive_dwell = LE_16(120);
3771 
3772                 frm += sizeof (iwk_scan_chan_t);
3773         }
3774 
3775         pktlen = _PTRDIFF(frm, cmd);
3776 
3777         (void) memset(desc, 0, sizeof (*desc));
3778         desc->val0 = 1 << 24;
3779         desc->pa[0].tb1_addr =
3780             (uint32_t)(data->dma_data.cookie.dmac_address & 0xffffffff);
3781         desc->pa[0].val1 = (pktlen << 4) & 0xfff0;
3782 
3783         /*
3784          * maybe for cmd, filling the byte cnt table is not necessary.
3785          * anyway, we fill it here.
3786          */
3787         sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3788             tfd_offset[ring->cur].val = 8;
3789         if (ring->cur < IWK_MAX_WIN_SIZE) {
3790                 sc->sc_shared->queues_byte_cnt_tbls[ring->qid].
3791                     tfd_offset[IWK_QUEUE_SIZE + ring->cur].val = 8;
3792         }
3793 
3794         /* kick cmd ring */
3795         ring->cur = (ring->cur + 1) % ring->count;
3796         IWK_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur);
3797 
3798         return (IWK_SUCCESS);
3799 }
3800 
3801 static int
3802 iwk_config(iwk_sc_t *sc)
3803 {
3804         ieee80211com_t *ic = &sc->sc_ic;
3805         iwk_powertable_cmd_t powertable;
3806         iwk_bt_cmd_t bt;
3807         iwk_add_sta_t node;
3808         iwk_link_quality_cmd_t link_quality;
3809         int i, err;
3810         uint16_t masks = 0;
3811 
3812         /*
3813          * set power mode. Disable power management at present, do it later
3814          */
3815         (void) memset(&powertable, 0, sizeof (powertable));
3816         powertable.flags = LE_16(0x8);
3817         err = iwk_cmd(sc, POWER_TABLE_CMD, &powertable,
3818             sizeof (powertable), 0);
3819         if (err != IWK_SUCCESS) {
3820                 cmn_err(CE_WARN, "iwk_config(): failed to set power mode\n");
3821                 return (err);
3822         }
3823 
3824         /* configure bt coexistence */
3825         (void) memset(&bt, 0, sizeof (bt));
3826         bt.flags = 3;
3827         bt.lead_time = 0xaa;
3828         bt.max_kill = 1;
3829         err = iwk_cmd(sc, REPLY_BT_CONFIG, &bt,
3830             sizeof (bt), 0);
3831         if (err != IWK_SUCCESS) {
3832                 cmn_err(CE_WARN,
3833                     "iwk_config(): "
3834                     "failed to configurate bt coexistence\n");
3835                 return (err);
3836         }
3837 
3838         /* configure rxon */
3839         (void) memset(&sc->sc_config, 0, sizeof (iwk_rxon_cmd_t));
3840         IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr);
3841         IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr);
3842         sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic, ic->ic_curchan));
3843         sc->sc_config.flags = LE_32(RXON_FLG_TSF2HOST_MSK |
3844             RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_BAND_24G_MSK);
3845         sc->sc_config.flags &= LE_32(~RXON_FLG_CCK_MSK);
3846         switch (ic->ic_opmode) {
3847         case IEEE80211_M_STA:
3848                 sc->sc_config.dev_type = RXON_DEV_TYPE_ESS;
3849                 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
3850                     RXON_FILTER_DIS_DECRYPT_MSK |
3851                     RXON_FILTER_DIS_GRP_DECRYPT_MSK);
3852                 break;
3853         case IEEE80211_M_IBSS:
3854         case IEEE80211_M_AHDEMO:
3855                 sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
3856                 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
3857                 sc->sc_config.filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
3858                     RXON_FILTER_DIS_DECRYPT_MSK |
3859                     RXON_FILTER_DIS_GRP_DECRYPT_MSK);
3860                 break;
3861         case IEEE80211_M_HOSTAP:
3862                 sc->sc_config.dev_type = RXON_DEV_TYPE_AP;
3863                 break;
3864         case IEEE80211_M_MONITOR:
3865                 sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER;
3866                 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
3867                     RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
3868                 break;
3869         }
3870         sc->sc_config.cck_basic_rates  = 0x0f;
3871         sc->sc_config.ofdm_basic_rates = 0xff;
3872 
3873         sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
3874         sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff;
3875 
3876         /* set antenna */
3877 
3878         sc->sc_config.rx_chain = LE_16(RXON_RX_CHAIN_DRIVER_FORCE_MSK |
3879             (0x7 << RXON_RX_CHAIN_VALID_POS) |
3880             (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
3881             (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
3882 
3883         err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
3884             sizeof (iwk_rxon_cmd_t), 0);
3885         if (err != IWK_SUCCESS) {
3886                 cmn_err(CE_WARN, "iwk_config(): "
3887                     "failed to set configure command\n");
3888                 return (err);
3889         }
3890         /* obtain current temperature of chipset */
3891         sc->sc_tempera = iwk_curr_tempera(sc);
3892 
3893         /* make Tx power calibration to determine the gains of DSP and radio */
3894         err = iwk_tx_power_calibration(sc);
3895         if (err) {
3896                 cmn_err(CE_WARN, "iwk_config(): "
3897                     "failed to set tx power table\n");
3898                 return (err);
3899         }
3900 
3901         /* add broadcast node so that we can send broadcast frame */
3902         (void) memset(&node, 0, sizeof (node));
3903         (void) memset(node.bssid, 0xff, 6);
3904         node.id = IWK_BROADCAST_ID;
3905         err = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 0);
3906         if (err != IWK_SUCCESS) {
3907                 cmn_err(CE_WARN, "iwk_config(): "
3908                     "failed to add broadcast node\n");
3909                 return (err);
3910         }
3911 
3912         /* TX_LINK_QUALITY cmd ? */
3913         (void) memset(&link_quality, 0, sizeof (link_quality));
3914         for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
3915                 masks |= RATE_MCS_CCK_MSK;
3916                 masks |= RATE_MCS_ANT_B_MSK;
3917                 masks &= ~RATE_MCS_ANT_A_MSK;
3918                 link_quality.rate_n_flags[i] =
3919                     LE_32(iwk_rate_to_plcp(2) | masks);
3920         }
3921 
3922         link_quality.general_params.single_stream_ant_msk = 2;
3923         link_quality.general_params.dual_stream_ant_msk = 3;
3924         link_quality.agg_params.agg_dis_start_th = 3;
3925         link_quality.agg_params.agg_time_limit = LE_16(4000);
3926         link_quality.sta_id = IWK_BROADCAST_ID;
3927         err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
3928             sizeof (link_quality), 0);
3929         if (err != IWK_SUCCESS) {
3930                 cmn_err(CE_WARN, "iwk_config(): "
3931                     "failed to config link quality table\n");
3932                 return (err);
3933         }
3934 
3935         return (IWK_SUCCESS);
3936 }
3937 
3938 static void
3939 iwk_stop_master(iwk_sc_t *sc)
3940 {
3941         uint32_t tmp;
3942         int n;
3943 
3944         tmp = IWK_READ(sc, CSR_RESET);
3945         IWK_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_STOP_MASTER);
3946 
3947         tmp = IWK_READ(sc, CSR_GP_CNTRL);
3948         if ((tmp & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE) ==
3949             CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE)
3950                 return;
3951 
3952         for (n = 0; n < 2000; n++) {
3953                 if (IWK_READ(sc, CSR_RESET) &
3954                     CSR_RESET_REG_FLAG_MASTER_DISABLED)
3955                         break;
3956                 DELAY(1000);
3957         }
3958         if (n == 2000)
3959                 IWK_DBG((IWK_DEBUG_HW,
3960                     "timeout waiting for master stop\n"));
3961 }
3962 
3963 static int
3964 iwk_power_up(iwk_sc_t *sc)
3965 {
3966         uint32_t tmp;
3967 
3968         iwk_mac_access_enter(sc);
3969         tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL);
3970         tmp &= ~APMG_PS_CTRL_REG_MSK_POWER_SRC;
3971         tmp |= APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN;
3972         iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp);
3973         iwk_mac_access_exit(sc);
3974 
3975         DELAY(5000);
3976         return (IWK_SUCCESS);
3977 }
3978 
3979 static int
3980 iwk_preinit(iwk_sc_t *sc)
3981 {
3982         uint32_t tmp;
3983         int n;
3984         uint8_t vlink;
3985 
3986         /* clear any pending interrupts */
3987         IWK_WRITE(sc, CSR_INT, 0xffffffff);
3988 
3989         tmp = IWK_READ(sc, CSR_GIO_CHICKEN_BITS);
3990         IWK_WRITE(sc, CSR_GIO_CHICKEN_BITS,
3991             tmp | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
3992 
3993         tmp = IWK_READ(sc, CSR_GP_CNTRL);
3994         IWK_WRITE(sc, CSR_GP_CNTRL, tmp | CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
3995 
3996         /* wait for clock ready */
3997         for (n = 0; n < 1000; n++) {
3998                 if (IWK_READ(sc, CSR_GP_CNTRL) &
3999                     CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY)
4000                         break;
4001                 DELAY(10);
4002         }
4003         if (n == 1000) {
4004                 cmn_err(CE_WARN,
4005                     "iwk_preinit(): timeout waiting for clock ready\n");
4006                 return (ETIMEDOUT);
4007         }
4008         iwk_mac_access_enter(sc);
4009         tmp = iwk_reg_read(sc, APMG_CLK_CTRL_REG);
4010         iwk_reg_write(sc, APMG_CLK_CTRL_REG, tmp |
4011             APMG_CLK_REG_VAL_DMA_CLK_RQT | APMG_CLK_REG_VAL_BSM_CLK_RQT);
4012 
4013         DELAY(20);
4014         tmp = iwk_reg_read(sc, ALM_APMG_PCIDEV_STT);
4015         iwk_reg_write(sc, ALM_APMG_PCIDEV_STT, tmp |
4016             APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE);
4017         iwk_mac_access_exit(sc);
4018 
4019         IWK_WRITE(sc, CSR_INT_COALESCING, 512 / 32); /* ??? */
4020 
4021         (void) iwk_power_up(sc);
4022 
4023         if ((sc->sc_rev & 0x80) == 0x80 && (sc->sc_rev & 0x7f) < 8) {
4024                 tmp = ddi_get32(sc->sc_cfg_handle,
4025                     (uint32_t *)(sc->sc_cfg_base + 0xe8));
4026                 ddi_put32(sc->sc_cfg_handle,
4027                     (uint32_t *)(sc->sc_cfg_base + 0xe8),
4028                     tmp & ~(1 << 11));
4029         }
4030 
4031 
4032         vlink = ddi_get8(sc->sc_cfg_handle,
4033             (uint8_t *)(sc->sc_cfg_base + 0xf0));
4034         ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0xf0),
4035             vlink & ~2);
4036 
4037         tmp = IWK_READ(sc, CSR_SW_VER);
4038         tmp |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
4039             CSR_HW_IF_CONFIG_REG_BIT_MAC_SI |
4040             CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R;
4041         IWK_WRITE(sc, CSR_SW_VER, tmp);
4042 
4043         /* make sure power supply on each part of the hardware */
4044         iwk_mac_access_enter(sc);
4045         tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL);
4046         tmp |= APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4047         iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4048         DELAY(5);
4049         tmp = iwk_reg_read(sc, ALM_APMG_PS_CTL);
4050         tmp &= ~APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ;
4051         iwk_reg_write(sc, ALM_APMG_PS_CTL, tmp);
4052         iwk_mac_access_exit(sc);
4053         return (IWK_SUCCESS);
4054 }
4055 
4056 /*
4057  * set up semphore flag to own EEPROM
4058  */
4059 static int iwk_eep_sem_down(iwk_sc_t *sc)
4060 {
4061         int count1, count2;
4062         uint32_t tmp;
4063 
4064         for (count1 = 0; count1 < 1000; count1++) {
4065                 tmp = IWK_READ(sc, CSR_HW_IF_CONFIG_REG);
4066                 IWK_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4067                     tmp | CSR_HW_IF_CONFIG_REG_EEP_SEM);
4068 
4069                 for (count2 = 0; count2 < 2; count2++) {
4070                         if (IWK_READ(sc, CSR_HW_IF_CONFIG_REG) &
4071                             CSR_HW_IF_CONFIG_REG_EEP_SEM)
4072                                 return (IWK_SUCCESS);
4073                         DELAY(10000);
4074                 }
4075         }
4076         return (IWK_FAIL);
4077 }
4078 
4079 /*
4080  * reset semphore flag to release EEPROM
4081  */
4082 static void iwk_eep_sem_up(iwk_sc_t *sc)
4083 {
4084         uint32_t tmp;
4085 
4086         tmp = IWK_READ(sc, CSR_HW_IF_CONFIG_REG);
4087         IWK_WRITE(sc, CSR_HW_IF_CONFIG_REG,
4088             tmp & (~CSR_HW_IF_CONFIG_REG_EEP_SEM));
4089 }
4090 
4091 /*
4092  * This function load all infomation in eeprom into iwk_eep
4093  * structure in iwk_sc_t structure
4094  */
4095 static int iwk_eep_load(iwk_sc_t *sc)
4096 {
4097         int i, rr;
4098         uint32_t rv, tmp, eep_gp;
4099         uint16_t addr, eep_sz = sizeof (sc->sc_eep_map);
4100         uint16_t *eep_p = (uint16_t *)&sc->sc_eep_map;
4101 
4102         /* read eeprom gp register in CSR */
4103         eep_gp = IWK_READ(sc, CSR_EEPROM_GP);
4104         if ((eep_gp & CSR_EEPROM_GP_VALID_MSK) ==
4105             CSR_EEPROM_GP_BAD_SIGNATURE) {
4106                 cmn_err(CE_WARN, "EEPROM not found\n");
4107                 return (IWK_FAIL);
4108         }
4109 
4110         rr = iwk_eep_sem_down(sc);
4111         if (rr != 0) {
4112                 cmn_err(CE_WARN, "failed to own EEPROM\n");
4113                 return (IWK_FAIL);
4114         }
4115 
4116         for (addr = 0; addr < eep_sz; addr += 2) {
4117                 IWK_WRITE(sc, CSR_EEPROM_REG, addr<<1);
4118                 tmp = IWK_READ(sc, CSR_EEPROM_REG);
4119                 IWK_WRITE(sc, CSR_EEPROM_REG, tmp & ~(0x2));
4120 
4121                 for (i = 0; i < 10; i++) {
4122                         rv = IWK_READ(sc, CSR_EEPROM_REG);
4123                         if (rv & 1)
4124                                 break;
4125                         DELAY(10);
4126                 }
4127 
4128                 if (!(rv & 1)) {
4129                         cmn_err(CE_WARN, "time out when read EEPROM\n");
4130                         iwk_eep_sem_up(sc);
4131                         return (IWK_FAIL);
4132                 }
4133 
4134                 eep_p[addr/2] = LE_16(rv >> 16);
4135         }
4136 
4137         iwk_eep_sem_up(sc);
4138         return (IWK_SUCCESS);
4139 }
4140 
4141 /*
4142  * init mac address in ieee80211com_t struct
4143  */
4144 static void iwk_get_mac_from_eep(iwk_sc_t *sc)
4145 {
4146         ieee80211com_t *ic = &sc->sc_ic;
4147         struct iwk_eep *ep = &sc->sc_eep_map;
4148 
4149         IEEE80211_ADDR_COPY(ic->ic_macaddr, ep->mac_address);
4150 
4151         IWK_DBG((IWK_DEBUG_EEPROM, "mac:%2x:%2x:%2x:%2x:%2x:%2x\n",
4152             ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
4153             ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]));
4154 }
4155 
4156 static int
4157 iwk_init(iwk_sc_t *sc)
4158 {
4159         int qid, n, err;
4160         clock_t clk;
4161         uint32_t tmp;
4162 
4163         mutex_enter(&sc->sc_glock);
4164         sc->sc_flags &= ~IWK_F_FW_INIT;
4165 
4166         (void) iwk_preinit(sc);
4167 
4168         tmp = IWK_READ(sc, CSR_GP_CNTRL);
4169         if (!(tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) {
4170                 cmn_err(CE_NOTE, "iwk_init(): Radio transmitter is off\n");
4171                 goto fail1;
4172         }
4173 
4174         /* init Rx ring */
4175         iwk_mac_access_enter(sc);
4176         IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
4177 
4178         IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
4179         IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
4180             sc->sc_rxq.dma_desc.cookie.dmac_address >> 8);
4181 
4182         IWK_WRITE(sc, FH_RSCSR_CHNL0_STTS_WPTR_REG,
4183             ((uint32_t)(sc->sc_dma_sh.cookie.dmac_address +
4184             offsetof(struct iwk_shared, val0)) >> 4));
4185 
4186         IWK_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG,
4187             FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
4188             FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
4189             IWK_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
4190             (RX_QUEUE_SIZE_LOG <<
4191             FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
4192         iwk_mac_access_exit(sc);
4193         IWK_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG,
4194             (RX_QUEUE_SIZE - 1) & ~0x7);
4195 
4196         /* init Tx rings */
4197         iwk_mac_access_enter(sc);
4198         iwk_reg_write(sc, SCD_TXFACT, 0);
4199 
4200         /* keep warm page */
4201         iwk_reg_write(sc, IWK_FH_KW_MEM_ADDR_REG,
4202             sc->sc_dma_kw.cookie.dmac_address >> 4);
4203 
4204         for (qid = 0; qid < IWK_NUM_QUEUES; qid++) {
4205                 IWK_WRITE(sc, FH_MEM_CBBC_QUEUE(qid),
4206                     sc->sc_txq[qid].dma_desc.cookie.dmac_address >> 8);
4207                 IWK_WRITE(sc, IWK_FH_TCSR_CHNL_TX_CONFIG_REG(qid),
4208                     IWK_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
4209                     IWK_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
4210         }
4211         iwk_mac_access_exit(sc);
4212 
4213         /* clear "radio off" and "disable command" bits */
4214         IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
4215         IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR,
4216             CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
4217 
4218         /* clear any pending interrupts */
4219         IWK_WRITE(sc, CSR_INT, 0xffffffff);
4220 
4221         /* enable interrupts */
4222         IWK_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK);
4223 
4224         IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
4225         IWK_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
4226 
4227         /*
4228          * backup ucode data part for future use.
4229          */
4230         (void) memcpy(sc->sc_dma_fw_data_bak.mem_va,
4231             sc->sc_dma_fw_data.mem_va,
4232             sc->sc_dma_fw_data.alength);
4233 
4234         for (n = 0; n < 2; n++) {
4235                 /* load firmware init segment into NIC */
4236                 err = iwk_load_firmware(sc);
4237                 if (err != IWK_SUCCESS) {
4238                         cmn_err(CE_WARN, "iwk_init(): "
4239                             "failed to setup boot firmware\n");
4240                         continue;
4241                 }
4242 
4243                 /* now press "execute" start running */
4244                 IWK_WRITE(sc, CSR_RESET, 0);
4245                 break;
4246         }
4247         if (n == 2) {
4248                 cmn_err(CE_WARN, "iwk_init(): failed to load firmware\n");
4249                 goto fail1;
4250         }
4251         /* ..and wait at most one second for adapter to initialize */
4252         clk = ddi_get_lbolt() + drv_usectohz(2000000);
4253         while (!(sc->sc_flags & IWK_F_FW_INIT)) {
4254                 if (cv_timedwait(&sc->sc_fw_cv, &sc->sc_glock, clk) < 0)
4255                         break;
4256         }
4257         if (!(sc->sc_flags & IWK_F_FW_INIT)) {
4258                 cmn_err(CE_WARN,
4259                     "iwk_init(): timeout waiting for firmware init\n");
4260                 goto fail1;
4261         }
4262 
4263         /*
4264          * at this point, the firmware is loaded OK, then config the hardware
4265          * with the ucode API, including rxon, txpower, etc.
4266          */
4267         err = iwk_config(sc);
4268         if (err) {
4269                 cmn_err(CE_WARN, "iwk_init(): failed to configure device\n");
4270                 goto fail1;
4271         }
4272 
4273         /* at this point, hardware may receive beacons :) */
4274         mutex_exit(&sc->sc_glock);
4275         return (IWK_SUCCESS);
4276 
4277 fail1:
4278         err = IWK_FAIL;
4279         mutex_exit(&sc->sc_glock);
4280         return (err);
4281 }
4282 
4283 static void
4284 iwk_stop(iwk_sc_t *sc)
4285 {
4286         uint32_t tmp;
4287         int i;
4288 
4289         if (!(sc->sc_flags & IWK_F_QUIESCED))
4290                 mutex_enter(&sc->sc_glock);
4291 
4292         IWK_WRITE(sc, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
4293         /* disable interrupts */
4294         IWK_WRITE(sc, CSR_INT_MASK, 0);
4295         IWK_WRITE(sc, CSR_INT, CSR_INI_SET_MASK);
4296         IWK_WRITE(sc, CSR_FH_INT_STATUS, 0xffffffff);
4297 
4298         /* reset all Tx rings */
4299         for (i = 0; i < IWK_NUM_QUEUES; i++)
4300                 iwk_reset_tx_ring(sc, &sc->sc_txq[i]);
4301 
4302         /* reset Rx ring */
4303         iwk_reset_rx_ring(sc);
4304 
4305         iwk_mac_access_enter(sc);
4306         iwk_reg_write(sc, ALM_APMG_CLK_DIS, APMG_CLK_REG_VAL_DMA_CLK_RQT);
4307         iwk_mac_access_exit(sc);
4308 
4309         DELAY(5);
4310 
4311         iwk_stop_master(sc);
4312 
4313         sc->sc_tx_timer = 0;
4314         sc->sc_flags &= ~IWK_F_SCANNING;
4315         sc->sc_scan_pending = 0;
4316 
4317         tmp = IWK_READ(sc, CSR_RESET);
4318         IWK_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_SW_RESET);
4319 
4320         if (!(sc->sc_flags & IWK_F_QUIESCED))
4321                 mutex_exit(&sc->sc_glock);
4322 }
4323 
4324 /*
4325  * Naive implementation of the Adaptive Multi Rate Retry algorithm:
4326  * "IEEE 802.11 Rate Adaptation: A Practical Approach"
4327  * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
4328  * INRIA Sophia - Projet Planete
4329  * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
4330  */
4331 #define is_success(amrr)        \
4332         ((amrr)->retrycnt < (amrr)->txcnt / 10)
4333 #define is_failure(amrr)        \
4334         ((amrr)->retrycnt > (amrr)->txcnt / 3)
4335 #define is_enough(amrr)         \
4336         ((amrr)->txcnt > 100)
4337 #define is_min_rate(in)         \
4338         ((in)->in_txrate == 0)
4339 #define is_max_rate(in)         \
4340         ((in)->in_txrate == (in)->in_rates.ir_nrates - 1)
4341 #define increase_rate(in)       \
4342         ((in)->in_txrate++)
4343 #define decrease_rate(in)       \
4344         ((in)->in_txrate--)
4345 #define reset_cnt(amrr)         \
4346         { (amrr)->txcnt = (amrr)->retrycnt = 0; }
4347 
4348 #define IWK_AMRR_MIN_SUCCESS_THRESHOLD   1
4349 #define IWK_AMRR_MAX_SUCCESS_THRESHOLD  15
4350 
4351 static void
4352 iwk_amrr_init(iwk_amrr_t *amrr)
4353 {
4354         amrr->success = 0;
4355         amrr->recovery = 0;
4356         amrr->txcnt = amrr->retrycnt = 0;
4357         amrr->success_threshold = IWK_AMRR_MIN_SUCCESS_THRESHOLD;
4358 }
4359 
4360 static void
4361 iwk_amrr_timeout(iwk_sc_t *sc)
4362 {
4363         ieee80211com_t *ic = &sc->sc_ic;
4364 
4365         IWK_DBG((IWK_DEBUG_RATECTL, "iwk_amrr_timeout() enter\n"));
4366         if (ic->ic_opmode == IEEE80211_M_STA)
4367                 iwk_amrr_ratectl(NULL, ic->ic_bss);
4368         else
4369                 ieee80211_iterate_nodes(&ic->ic_sta, iwk_amrr_ratectl, NULL);
4370         sc->sc_clk = ddi_get_lbolt();
4371 }
4372 
4373 /* ARGSUSED */
4374 static void
4375 iwk_amrr_ratectl(void *arg, ieee80211_node_t *in)
4376 {
4377         iwk_amrr_t *amrr = (iwk_amrr_t *)in;
4378         int need_change = 0;
4379 
4380         if (is_success(amrr) && is_enough(amrr)) {
4381                 amrr->success++;
4382                 if (amrr->success >= amrr->success_threshold &&
4383                     !is_max_rate(in)) {
4384                         amrr->recovery = 1;
4385                         amrr->success = 0;
4386                         increase_rate(in);
4387                         IWK_DBG((IWK_DEBUG_RATECTL,
4388                             "AMRR increasing rate %d (txcnt=%d retrycnt=%d)\n",
4389                             in->in_txrate, amrr->txcnt, amrr->retrycnt));
4390                         need_change = 1;
4391                 } else {
4392                         amrr->recovery = 0;
4393                 }
4394         } else if (is_failure(amrr)) {
4395                 amrr->success = 0;
4396                 if (!is_min_rate(in)) {
4397                         if (amrr->recovery) {
4398                                 amrr->success_threshold++;
4399                                 if (amrr->success_threshold >
4400                                     IWK_AMRR_MAX_SUCCESS_THRESHOLD)
4401                                         amrr->success_threshold =
4402                                             IWK_AMRR_MAX_SUCCESS_THRESHOLD;
4403                         } else {
4404                                 amrr->success_threshold =
4405                                     IWK_AMRR_MIN_SUCCESS_THRESHOLD;
4406                         }
4407                         decrease_rate(in);
4408                         IWK_DBG((IWK_DEBUG_RATECTL,
4409                             "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)\n",
4410                             in->in_txrate, amrr->txcnt, amrr->retrycnt));
4411                         need_change = 1;
4412                 }
4413                 amrr->recovery = 0;  /* paper is incorrect */
4414         }
4415 
4416         if (is_enough(amrr) || need_change)
4417                 reset_cnt(amrr);
4418 }
4419 
4420 /*
4421  * calculate 4965 chipset's kelvin temperature according to
4422  * the data of init alive and satistics notification.
4423  * The details is described in iwk_calibration.h file
4424  */
4425 static int32_t iwk_curr_tempera(iwk_sc_t *sc)
4426 {
4427         int32_t  tempera;
4428         int32_t  r1, r2, r3;
4429         uint32_t  r4_u;
4430         int32_t   r4_s;
4431 
4432         if (iwk_is_fat_channel(sc)) {
4433                 r1 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r1[1]);
4434                 r2 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r2[1]);
4435                 r3 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r3[1]);
4436                 r4_u = LE_32(sc->sc_card_alive_init.therm_r4[1]);
4437         } else {
4438                 r1 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r1[0]);
4439                 r2 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r2[0]);
4440                 r3 = (int32_t)LE_32(sc->sc_card_alive_init.therm_r3[0]);
4441                 r4_u = LE_32(sc->sc_card_alive_init.therm_r4[0]);
4442         }
4443 
4444         if (sc->sc_flags & IWK_F_STATISTICS) {
4445                 r4_s = (int32_t)(LE_32(sc->sc_statistics.general.temperature) <<
4446                     (31-23)) >> (31-23);
4447         } else {
4448                 r4_s = (int32_t)(r4_u << (31-23)) >> (31-23);
4449         }
4450 
4451         IWK_DBG((IWK_DEBUG_CALIBRATION, "temperature R[1-4]: %d %d %d %d\n",
4452             r1, r2, r3, r4_s));
4453 
4454         if (r3 == r1) {
4455                 cmn_err(CE_WARN, "iwk_curr_tempera(): "
4456                     "failed to calculate temperature"
4457                     "because r3 = r1\n");
4458                 return (DDI_FAILURE);
4459         }
4460 
4461         tempera = TEMPERATURE_CALIB_A_VAL * (r4_s - r2);
4462         tempera /= (r3 - r1);
4463         tempera = (tempera*97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
4464 
4465         IWK_DBG((IWK_DEBUG_CALIBRATION, "calculated temperature: %dK, %dC\n",
4466             tempera, KELVIN_TO_CELSIUS(tempera)));
4467 
4468         return (tempera);
4469 }
4470 
4471 /* Determine whether 4965 is using 2.4 GHz band */
4472 static inline int iwk_is_24G_band(iwk_sc_t *sc)
4473 {
4474         return (LE_32(sc->sc_config.flags) & RXON_FLG_BAND_24G_MSK);
4475 }
4476 
4477 /* Determine whether 4965 is using fat channel */
4478 static inline int iwk_is_fat_channel(iwk_sc_t *sc)
4479 {
4480         return ((LE_32(sc->sc_config.flags) &
4481             RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
4482             (LE_32(sc->sc_config.flags) & RXON_FLG_CHANNEL_MODE_MIXED_MSK));
4483 }
4484 
4485 /*
4486  * In MIMO mode, determine which group 4965's current channel belong to.
4487  * For more infomation about "channel group",
4488  * please refer to iwk_calibration.h file
4489  */
4490 static int iwk_txpower_grp(uint16_t channel)
4491 {
4492         if (channel >= CALIB_IWK_TX_ATTEN_GR5_FCH &&
4493             channel <= CALIB_IWK_TX_ATTEN_GR5_LCH) {
4494                 return (CALIB_CH_GROUP_5);
4495         }
4496 
4497         if (channel >= CALIB_IWK_TX_ATTEN_GR1_FCH &&
4498             channel <= CALIB_IWK_TX_ATTEN_GR1_LCH) {
4499                 return (CALIB_CH_GROUP_1);
4500         }
4501 
4502         if (channel >= CALIB_IWK_TX_ATTEN_GR2_FCH &&
4503             channel <= CALIB_IWK_TX_ATTEN_GR2_LCH) {
4504                 return (CALIB_CH_GROUP_2);
4505         }
4506 
4507         if (channel >= CALIB_IWK_TX_ATTEN_GR3_FCH &&
4508             channel <= CALIB_IWK_TX_ATTEN_GR3_LCH) {
4509                 return (CALIB_CH_GROUP_3);
4510         }
4511 
4512         if (channel >= CALIB_IWK_TX_ATTEN_GR4_FCH &&
4513             channel <= CALIB_IWK_TX_ATTEN_GR4_LCH) {
4514                 return (CALIB_CH_GROUP_4);
4515         }
4516 
4517         cmn_err(CE_WARN, "iwk_txpower_grp(): "
4518             "can't find txpower group for channel %d.\n", channel);
4519 
4520         return (DDI_FAILURE);
4521 }
4522 
4523 /* 2.4 GHz */
4524 static uint16_t iwk_eep_band_1[14] = {
4525         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
4526 };
4527 
4528 /* 5.2 GHz bands */
4529 static uint16_t iwk_eep_band_2[13] = {
4530         183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
4531 };
4532 
4533 static uint16_t iwk_eep_band_3[12] = {
4534         34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
4535 };
4536 
4537 static uint16_t iwk_eep_band_4[11] = {
4538         100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
4539 };
4540 
4541 static uint16_t iwk_eep_band_5[6] = {
4542         145, 149, 153, 157, 161, 165
4543 };
4544 
4545 static uint16_t iwk_eep_band_6[7] = {
4546         1, 2, 3, 4, 5, 6, 7
4547 };
4548 
4549 static uint16_t iwk_eep_band_7[11] = {
4550         36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
4551 };
4552 
4553 /* Get regulatory data from eeprom for a given channel */
4554 static struct iwk_eep_channel *iwk_get_eep_channel(iwk_sc_t *sc,
4555     uint16_t channel,
4556     int is_24G, int is_fat, int is_hi_chan)
4557 {
4558         int32_t i;
4559         uint16_t chan;
4560 
4561         if (is_fat) {  /* 11n mode */
4562 
4563                 if (is_hi_chan) {
4564                         chan = channel - 4;
4565                 } else {
4566                         chan = channel;
4567                 }
4568 
4569                 for (i = 0; i < 7; i++) {
4570                         if (iwk_eep_band_6[i] == chan) {
4571                                 return (&sc->sc_eep_map.band_24_channels[i]);
4572                         }
4573                 }
4574                 for (i = 0; i < 11; i++) {
4575                         if (iwk_eep_band_7[i] == chan) {
4576                                 return (&sc->sc_eep_map.band_52_channels[i]);
4577                         }
4578                 }
4579         } else if (is_24G) {  /* 2.4 GHz band */
4580                 for (i = 0; i < 14; i++) {
4581                         if (iwk_eep_band_1[i] == channel) {
4582                                 return (&sc->sc_eep_map.band_1_channels[i]);
4583                         }
4584                 }
4585         } else {  /* 5 GHz band */
4586                 for (i = 0; i < 13; i++) {
4587                         if (iwk_eep_band_2[i] == channel) {
4588                                 return (&sc->sc_eep_map.band_2_channels[i]);
4589                         }
4590                 }
4591                 for (i = 0; i < 12; i++) {
4592                         if (iwk_eep_band_3[i] == channel) {
4593                                 return (&sc->sc_eep_map.band_3_channels[i]);
4594                         }
4595                 }
4596                 for (i = 0; i < 11; i++) {
4597                         if (iwk_eep_band_4[i] == channel) {
4598                                 return (&sc->sc_eep_map.band_4_channels[i]);
4599                         }
4600                 }
4601                 for (i = 0; i < 6; i++) {
4602                         if (iwk_eep_band_5[i] == channel) {
4603                                 return (&sc->sc_eep_map.band_5_channels[i]);
4604                         }
4605                 }
4606         }
4607 
4608         return (NULL);
4609 }
4610 
4611 /*
4612  * Determine which subband a given channel belongs
4613  * to in 2.4 GHz or 5 GHz band
4614  */
4615 static int32_t iwk_band_number(iwk_sc_t *sc, uint16_t channel)
4616 {
4617         int32_t b_n = -1;
4618 
4619         for (b_n = 0; b_n < EEP_TX_POWER_BANDS; b_n++) {
4620                 if (0 == sc->sc_eep_map.calib_info.band_info_tbl[b_n].ch_from) {
4621                         continue;
4622                 }
4623 
4624                 if ((channel >=
4625                     (uint16_t)sc->sc_eep_map.calib_info.
4626                     band_info_tbl[b_n].ch_from) &&
4627                     (channel <=
4628                     (uint16_t)sc->sc_eep_map.calib_info.
4629                     band_info_tbl[b_n].ch_to)) {
4630                         break;
4631                 }
4632         }
4633 
4634         return (b_n);
4635 }
4636 
4637 /* Make a special division for interpolation operation */
4638 static int iwk_division(int32_t num, int32_t denom, int32_t *res)
4639 {
4640         int32_t sign = 1;
4641 
4642         if (num < 0) {
4643                 sign = -sign;
4644                 num = -num;
4645         }
4646 
4647         if (denom < 0) {
4648                 sign = -sign;
4649                 denom = -denom;
4650         }
4651 
4652         *res = ((num*2 + denom) / (denom*2)) * sign;
4653 
4654         return (IWK_SUCCESS);
4655 }
4656 
4657 /* Make interpolation operation */
4658 static int32_t iwk_interpolate_value(int32_t x, int32_t x1, int32_t y1,
4659     int32_t x2, int32_t y2)
4660 {
4661         int32_t val;
4662 
4663         if (x2 == x1) {
4664                 return (y1);
4665         } else {
4666                 (void) iwk_division((x2-x)*(y1-y2), (x2-x1), &val);
4667                 return (val + y2);
4668         }
4669 }
4670 
4671 /* Get interpolation measurement data of a given channel for all chains. */
4672 static int iwk_channel_interpolate(iwk_sc_t *sc, uint16_t channel,
4673     struct iwk_eep_calib_channel_info *chan_info)
4674 {
4675         int32_t ban_n;
4676         uint32_t ch1_n, ch2_n;
4677         int32_t c, m;
4678         struct iwk_eep_calib_measure *m1_p, *m2_p, *m_p;
4679 
4680         /* determine subband number */
4681         ban_n = iwk_band_number(sc, channel);
4682         if (ban_n >= EEP_TX_POWER_BANDS) {
4683                 return (DDI_FAILURE);
4684         }
4685 
4686         ch1_n =
4687             (uint32_t)sc->sc_eep_map.calib_info.band_info_tbl[ban_n].ch1.ch_num;
4688         ch2_n =
4689             (uint32_t)sc->sc_eep_map.calib_info.band_info_tbl[ban_n].ch2.ch_num;
4690 
4691         chan_info->ch_num = (uint8_t)channel;  /* given channel number */
4692 
4693         /*
4694          * go through all chains on chipset
4695          */
4696         for (c = 0; c < EEP_TX_POWER_TX_CHAINS; c++) {
4697                 /*
4698                  * go through all factory measurements
4699                  */
4700                 for (m = 0; m < EEP_TX_POWER_MEASUREMENTS; m++) {
4701                         m1_p =
4702                             &(sc->sc_eep_map.calib_info.
4703                             band_info_tbl[ban_n].ch1.measure[c][m]);
4704                         m2_p =
4705                             &(sc->sc_eep_map.calib_info.band_info_tbl[ban_n].
4706                             ch2.measure[c][m]);
4707                         m_p = &(chan_info->measure[c][m]);
4708 
4709                         /*
4710                          * make interpolation to get actual
4711                          * Tx power for given channel
4712                          */
4713                         m_p->actual_pow = iwk_interpolate_value(channel,
4714                             ch1_n, m1_p->actual_pow,
4715                             ch2_n, m2_p->actual_pow);
4716 
4717                         /* make interpolation to get index into gain table */
4718                         m_p->gain_idx = iwk_interpolate_value(channel,
4719                             ch1_n, m1_p->gain_idx,
4720                             ch2_n, m2_p->gain_idx);
4721 
4722                         /* make interpolation to get chipset temperature */
4723                         m_p->temperature = iwk_interpolate_value(channel,
4724                             ch1_n, m1_p->temperature,
4725                             ch2_n, m2_p->temperature);
4726 
4727                         /*
4728                          * make interpolation to get power
4729                          * amp detector level
4730                          */
4731                         m_p->pa_det = iwk_interpolate_value(channel, ch1_n,
4732                             m1_p->pa_det,
4733                             ch2_n, m2_p->pa_det);
4734                 }
4735         }
4736 
4737         return (IWK_SUCCESS);
4738 }
4739 
4740 /*
4741  * Calculate voltage compensation for Tx power. For more infomation,
4742  * please refer to iwk_calibration.h file
4743  */
4744 static int32_t iwk_voltage_compensation(int32_t eep_voltage,
4745     int32_t curr_voltage)
4746 {
4747         int32_t vol_comp = 0;
4748 
4749         if ((TX_POWER_IWK_ILLEGAL_VOLTAGE == eep_voltage) ||
4750             (TX_POWER_IWK_ILLEGAL_VOLTAGE == curr_voltage)) {
4751                 return (vol_comp);
4752         }
4753 
4754         (void) iwk_division(curr_voltage-eep_voltage,
4755             TX_POWER_IWK_VOLTAGE_CODES_PER_03V, &vol_comp);
4756 
4757         if (curr_voltage > eep_voltage) {
4758                 vol_comp *= 2;
4759         }
4760         if ((vol_comp < -2) || (vol_comp > 2)) {
4761                 vol_comp = 0;
4762         }
4763 
4764         return (vol_comp);
4765 }
4766 
4767 /*
4768  * Thermal compensation values for txpower for various frequency ranges ...
4769  * ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust
4770  */
4771 static struct iwk_txpower_tempera_comp {
4772         int32_t degrees_per_05db_a;
4773         int32_t degrees_per_05db_a_denom;
4774 } txpower_tempera_comp_table[CALIB_CH_GROUP_MAX] = {
4775         {9, 2},                 /* group 0 5.2, ch  34-43 */
4776         {4, 1},                 /* group 1 5.2, ch  44-70 */
4777         {4, 1},                 /* group 2 5.2, ch  71-124 */
4778         {4, 1},                 /* group 3 5.2, ch 125-200 */
4779         {3, 1}                  /* group 4 2.4, ch   all */
4780 };
4781 
4782 /*
4783  * bit-rate-dependent table to prevent Tx distortion, in half-dB units,
4784  * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates.
4785  */
4786 static int32_t back_off_table[] = {
4787         10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */
4788         10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */
4789         10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */
4790         10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */
4791         10                      /* CCK */
4792 };
4793 
4794 /* determine minimum Tx power index in gain table */
4795 static int32_t iwk_min_power_index(int32_t rate_pow_idx, int32_t is_24G)
4796 {
4797         if ((!is_24G) && ((rate_pow_idx & 7) <= 4)) {
4798                 return (MIN_TX_GAIN_INDEX_52GHZ_EXT);
4799         }
4800 
4801         return (MIN_TX_GAIN_INDEX);
4802 }
4803 
4804 /*
4805  * Determine DSP and radio gain according to temperature and other factors.
4806  * This function is the majority of Tx power calibration
4807  */
4808 static int iwk_txpower_table_cmd_init(iwk_sc_t *sc,
4809     struct iwk_tx_power_db *tp_db)
4810 {
4811         int is_24G, is_fat, is_high_chan, is_mimo;
4812         int c, r;
4813         int32_t target_power;
4814         int32_t tx_grp = CALIB_CH_GROUP_MAX;
4815         uint16_t channel;
4816         uint8_t saturation_power;
4817         int32_t regu_power;
4818         int32_t curr_regu_power;
4819         struct iwk_eep_channel *eep_chan_p;
4820         struct iwk_eep_calib_channel_info eep_chan_calib;
4821         int32_t eep_voltage, init_voltage;
4822         int32_t voltage_compensation;
4823         int32_t temperature;
4824         int32_t degrees_per_05db_num;
4825         int32_t degrees_per_05db_denom;
4826         struct iwk_eep_calib_measure *measure_p;
4827         int32_t interpo_temp;
4828         int32_t power_limit;
4829         int32_t atten_value;
4830         int32_t tempera_comp[2];
4831         int32_t interpo_gain_idx[2];
4832         int32_t interpo_actual_pow[2];
4833         union iwk_tx_power_dual_stream txpower_gains;
4834         int32_t txpower_gains_idx;
4835 
4836         channel = LE_16(sc->sc_config.chan);
4837 
4838         /* 2.4 GHz or 5 GHz band */
4839         is_24G = iwk_is_24G_band(sc);
4840 
4841         /* fat channel or not */
4842         is_fat = iwk_is_fat_channel(sc);
4843 
4844         /*
4845          * using low half channel number or high half channel number
4846          * identify fat channel
4847          */
4848         if (is_fat && (LE_32(sc->sc_config.flags) &
4849             RXON_FLG_CONTROL_CHANNEL_LOC_HIGH_MSK)) {
4850                 is_high_chan = 1;
4851         }
4852 
4853         if ((channel > 0) && (channel < 200)) {
4854                 /* get regulatory channel data from eeprom */
4855                 eep_chan_p = iwk_get_eep_channel(sc, channel, is_24G,
4856                     is_fat, is_high_chan);
4857                 if (NULL == eep_chan_p) {
4858                         cmn_err(CE_WARN,
4859                             "iwk_txpower_table_cmd_init(): "
4860                             "can't get channel infomation\n");
4861                         return (DDI_FAILURE);
4862                 }
4863         } else {
4864                 cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): "
4865                     "channel(%d) isn't in proper range\n",
4866                     channel);
4867                 return (DDI_FAILURE);
4868         }
4869 
4870         /* initial value of Tx power */
4871         sc->sc_user_txpower = (int32_t)eep_chan_p->max_power_avg;
4872         if (sc->sc_user_txpower < IWK_TX_POWER_TARGET_POWER_MIN) {
4873                 cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): "
4874                     "user TX power is too weak\n");
4875                 return (DDI_FAILURE);
4876         } else if (sc->sc_user_txpower > IWK_TX_POWER_TARGET_POWER_MAX) {
4877                 cmn_err(CE_WARN, "iwk_txpower_table_cmd_init(): "
4878                     "user TX power is too strong\n");
4879                 return (DDI_FAILURE);
4880         }
4881 
4882         target_power = 2 * sc->sc_user_txpower;
4883 
4884         /* determine which group current channel belongs to */
4885         tx_grp = iwk_txpower_grp(channel);
4886         if (tx_grp < 0) {
4887                 return (tx_grp);
4888         }
4889 
4890 
4891         if (is_fat) {
4892                 if (is_high_chan) {
4893                         channel -= 2;
4894                 } else {
4895                         channel += 2;
4896                 }
4897         }
4898 
4899         /* determine saturation power */
4900         if (is_24G) {
4901                 saturation_power =
4902                     sc->sc_eep_map.calib_info.saturation_power24;
4903         } else {
4904                 saturation_power =
4905                     sc->sc_eep_map.calib_info.saturation_power52;
4906         }
4907 
4908         if (saturation_power < IWK_TX_POWER_SATURATION_MIN ||
4909             saturation_power > IWK_TX_POWER_SATURATION_MAX) {
4910                 if (is_24G) {
4911                         saturation_power = IWK_TX_POWER_DEFAULT_SATURATION_24;
4912                 } else {
4913                         saturation_power = IWK_TX_POWER_DEFAULT_SATURATION_52;
4914                 }
4915         }
4916 
4917         /* determine regulatory power */
4918         regu_power = (int32_t)eep_chan_p->max_power_avg * 2;
4919         if ((regu_power < IWK_TX_POWER_REGULATORY_MIN) ||
4920             (regu_power > IWK_TX_POWER_REGULATORY_MAX)) {
4921                 if (is_24G) {
4922                         regu_power = IWK_TX_POWER_DEFAULT_REGULATORY_24;
4923                 } else {
4924                         regu_power = IWK_TX_POWER_DEFAULT_REGULATORY_52;
4925                 }
4926         }
4927 
4928         /*
4929          * get measurement data for current channel
4930          * suach as temperature,index to gain table,actual Tx power
4931          */
4932         (void) iwk_channel_interpolate(sc, channel, &eep_chan_calib);
4933 
4934         eep_voltage = (int32_t)LE_16(sc->sc_eep_map.calib_info.voltage);
4935         init_voltage = (int32_t)LE_32(sc->sc_card_alive_init.voltage);
4936 
4937         /* calculate voltage compensation to Tx power */
4938         voltage_compensation =
4939             iwk_voltage_compensation(eep_voltage, init_voltage);
4940 
4941         if (sc->sc_tempera >= IWK_TX_POWER_TEMPERATURE_MIN) {
4942                 temperature = sc->sc_tempera;
4943         } else {
4944                 temperature = IWK_TX_POWER_TEMPERATURE_MIN;
4945         }
4946         if (sc->sc_tempera <= IWK_TX_POWER_TEMPERATURE_MAX) {
4947                 temperature = sc->sc_tempera;
4948         } else {
4949                 temperature = IWK_TX_POWER_TEMPERATURE_MAX;
4950         }
4951         temperature = KELVIN_TO_CELSIUS(temperature);
4952 
4953         degrees_per_05db_num =
4954             txpower_tempera_comp_table[tx_grp].degrees_per_05db_a;
4955         degrees_per_05db_denom =
4956             txpower_tempera_comp_table[tx_grp].degrees_per_05db_a_denom;
4957 
4958         for (c = 0; c < 2; c++) {  /* go through all chains */
4959                 measure_p = &eep_chan_calib.measure[c][1];
4960                 interpo_temp = measure_p->temperature;
4961 
4962                 /* determine temperature compensation to Tx power */
4963                 (void) iwk_division(
4964                     (temperature-interpo_temp)*degrees_per_05db_denom,
4965                     degrees_per_05db_num, &tempera_comp[c]);
4966 
4967                 interpo_gain_idx[c] = measure_p->gain_idx;
4968                 interpo_actual_pow[c] = measure_p->actual_pow;
4969         }
4970 
4971         /*
4972          * go through all rate entries in Tx power table
4973          */
4974         for (r = 0; r < POWER_TABLE_NUM_ENTRIES; r++) {
4975                 if (r & 0x8) {
4976                         /* need to lower regulatory power for MIMO mode */
4977                         curr_regu_power = regu_power -
4978                             IWK_TX_POWER_MIMO_REGULATORY_COMPENSATION;
4979                         is_mimo = 1;
4980                 } else {
4981                         curr_regu_power = regu_power;
4982                         is_mimo = 0;
4983                 }
4984 
4985                 power_limit = saturation_power - back_off_table[r];
4986                 if (power_limit > curr_regu_power) {
4987                         /* final Tx power limit */
4988                         power_limit = curr_regu_power;
4989                 }
4990 
4991                 if (target_power > power_limit) {
4992                         target_power = power_limit; /* final target Tx power */
4993                 }
4994 
4995                 for (c = 0; c < 2; c++) {      /* go through all Tx chains */
4996                         if (is_mimo) {
4997                                 atten_value =
4998                                     LE_32(sc->sc_card_alive_init.
4999                                     tx_atten[tx_grp][c]);
5000                         } else {
5001                                 atten_value = 0;
5002                         }
5003 
5004                         /*
5005                          * calculate index in gain table
5006                          * this step is very important
5007                          */
5008                         txpower_gains_idx = interpo_gain_idx[c] -
5009                             (target_power - interpo_actual_pow[c]) -
5010                             tempera_comp[c] - voltage_compensation +
5011                             atten_value;
5012 
5013                         if (txpower_gains_idx <
5014                             iwk_min_power_index(r, is_24G)) {
5015                                 txpower_gains_idx =
5016                                     iwk_min_power_index(r, is_24G);
5017                         }
5018 
5019                         if (!is_24G) {
5020                                 /*
5021                                  * support negative index for 5 GHz
5022                                  * band
5023                                  */
5024                                 txpower_gains_idx += 9;
5025                         }
5026 
5027                         if (POWER_TABLE_CCK_ENTRY == r) {
5028                                 /* for CCK mode, make necessary attenuaton */
5029                                 txpower_gains_idx +=
5030                                     IWK_TX_POWER_CCK_COMPENSATION_C_STEP;
5031                         }
5032 
5033                         if (txpower_gains_idx > 107) {
5034                                 txpower_gains_idx = 107;
5035                         } else if (txpower_gains_idx < 0) {
5036                                 txpower_gains_idx = 0;
5037                         }
5038 
5039                         /* search DSP and radio gains in gain table */
5040                         txpower_gains.s.radio_tx_gain[c] =
5041                             gains_table[is_24G][txpower_gains_idx].radio;
5042                         txpower_gains.s.dsp_predis_atten[c] =
5043                             gains_table[is_24G][txpower_gains_idx].dsp;
5044 
5045                         IWK_DBG((IWK_DEBUG_CALIBRATION,
5046                             "rate_index: %d, "
5047                             "gain_index %d, c: %d,is_mimo: %d\n",
5048                             r, txpower_gains_idx, c, is_mimo));
5049                 }
5050 
5051                 /* initialize Tx power table */
5052                 if (r < POWER_TABLE_NUM_HT_OFDM_ENTRIES) {
5053                         tp_db->ht_ofdm_power[r].dw = LE_32(txpower_gains.dw);
5054                 } else {
5055                         tp_db->legacy_cck_power.dw = LE_32(txpower_gains.dw);
5056                 }
5057         }
5058 
5059         return (IWK_SUCCESS);
5060 }
5061 
5062 /*
5063  * make Tx power calibration to adjust Tx power.
5064  * This is completed by sending out Tx power table command.
5065  */
5066 static int iwk_tx_power_calibration(iwk_sc_t *sc)
5067 {
5068         iwk_tx_power_table_cmd_t cmd;
5069         int rv;
5070 
5071         if (sc->sc_flags & IWK_F_SCANNING) {
5072                 return (IWK_SUCCESS);
5073         }
5074 
5075         /* necessary initialization to Tx power table command */
5076         cmd.band = (uint8_t)iwk_is_24G_band(sc);
5077         cmd.channel = sc->sc_config.chan;
5078         cmd.channel_normal_width = 0;
5079 
5080         /* initialize Tx power table */
5081         rv = iwk_txpower_table_cmd_init(sc, &cmd.tx_power);
5082         if (rv) {
5083                 cmn_err(CE_NOTE, "rv= %d\n", rv);
5084                 return (rv);
5085         }
5086 
5087         /* send out Tx power table command */
5088         rv = iwk_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &cmd, sizeof (cmd), 1);
5089         if (rv) {
5090                 return (rv);
5091         }
5092 
5093         /* record current temperature */
5094         sc->sc_last_tempera = sc->sc_tempera;
5095 
5096         return (IWK_SUCCESS);
5097 }
5098 
5099 /* This function is the handler of statistics notification from uCode */
5100 static void iwk_statistics_notify(iwk_sc_t *sc, iwk_rx_desc_t *desc)
5101 {
5102         int is_diff;
5103         struct iwk_notif_statistics *statistics_p =
5104             (struct iwk_notif_statistics *)(desc + 1);
5105 
5106         mutex_enter(&sc->sc_glock);
5107 
5108         is_diff = (sc->sc_statistics.general.temperature !=
5109             statistics_p->general.temperature) ||
5110             (LE_32(sc->sc_statistics.flag) &
5111             STATISTICS_REPLY_FLG_FAT_MODE_MSK) !=
5112             (LE_32(statistics_p->flag) & STATISTICS_REPLY_FLG_FAT_MODE_MSK);
5113 
5114         /* update statistics data */
5115         (void) memcpy(&sc->sc_statistics, statistics_p,
5116             sizeof (struct iwk_notif_statistics));
5117 
5118         sc->sc_flags |= IWK_F_STATISTICS;
5119 
5120         if (!(sc->sc_flags & IWK_F_SCANNING)) {
5121                 /* make Receiver gain balance calibration */
5122                 (void) iwk_rxgain_diff(sc);
5123 
5124                 /* make Receiver sensitivity calibration */
5125                 (void) iwk_rx_sens(sc);
5126         }
5127 
5128 
5129         if (!is_diff) {
5130                 mutex_exit(&sc->sc_glock);
5131                 return;
5132         }
5133 
5134         /* calibration current temperature of 4965 chipset */
5135         sc->sc_tempera = iwk_curr_tempera(sc);
5136 
5137         /* distinct temperature change will trigger Tx power calibration */
5138         if (((sc->sc_tempera - sc->sc_last_tempera) >= 3) ||
5139             ((sc->sc_last_tempera - sc->sc_tempera) >= 3)) {
5140                 /* make Tx power calibration */
5141                 (void) iwk_tx_power_calibration(sc);
5142         }
5143 
5144         mutex_exit(&sc->sc_glock);
5145 }
5146 
5147 /* Determine this station is in associated state or not */
5148 static int iwk_is_associated(iwk_sc_t *sc)
5149 {
5150         return (LE_32(sc->sc_config.filter_flags) & RXON_FILTER_ASSOC_MSK);
5151 }
5152 
5153 /* Make necessary preparation for Receiver gain balance calibration */
5154 static int iwk_rxgain_diff_init(iwk_sc_t *sc)
5155 {
5156         int i, rv;
5157         struct iwk_calibration_cmd cmd;
5158         struct iwk_rx_gain_diff *gain_diff_p;
5159 
5160         gain_diff_p = &sc->sc_rxgain_diff;
5161 
5162         (void) memset(gain_diff_p, 0, sizeof (struct iwk_rx_gain_diff));
5163         (void) memset(&cmd, 0, sizeof (struct iwk_calibration_cmd));
5164 
5165         for (i = 0; i < RX_CHAINS_NUM; i++) {
5166                 gain_diff_p->gain_diff_chain[i] = CHAIN_GAIN_DIFF_INIT_VAL;
5167         }
5168 
5169         if (iwk_is_associated(sc)) {
5170                 cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
5171                 cmd.diff_gain_a = 0;
5172                 cmd.diff_gain_b = 0;
5173                 cmd.diff_gain_c = 0;
5174 
5175                 /* assume the gains of every Rx chains is balanceable */
5176                 rv = iwk_cmd(sc, REPLY_PHY_CALIBRATION_CMD, &cmd,
5177                     sizeof (cmd), 1);
5178                 if (rv) {
5179                         return (rv);
5180                 }
5181 
5182                 gain_diff_p->state = IWK_GAIN_DIFF_ACCUMULATE;
5183         }
5184 
5185         return (IWK_SUCCESS);
5186 }
5187 
5188 /*
5189  * make Receiver gain balance to balance Rx gain between Rx chains
5190  * and determine which chain is disconnected
5191  */
5192 static int iwk_rxgain_diff(iwk_sc_t *sc)
5193 {
5194         int i, is_24G, rv;
5195         int max_beacon_chain_n;
5196         int min_noise_chain_n;
5197         uint16_t channel_n;
5198         int32_t beacon_diff;
5199         int32_t noise_diff;
5200         uint32_t noise_chain_a, noise_chain_b, noise_chain_c;
5201         uint32_t beacon_chain_a, beacon_chain_b, beacon_chain_c;
5202         struct iwk_calibration_cmd cmd;
5203         uint32_t beacon_aver[RX_CHAINS_NUM] = {0xFFFFFFFF};
5204         uint32_t noise_aver[RX_CHAINS_NUM] = {0xFFFFFFFF};
5205         struct statistics_rx_non_phy *rx_general_p =
5206             &sc->sc_statistics.rx.general;
5207         struct iwk_rx_gain_diff *gain_diff_p = &sc->sc_rxgain_diff;
5208 
5209         if (INTERFERENCE_DATA_AVAILABLE !=
5210             LE_32(rx_general_p->interference_data_flag)) {
5211                 return (IWK_SUCCESS);
5212         }
5213 
5214         if (IWK_GAIN_DIFF_ACCUMULATE != gain_diff_p->state) {
5215                 return (IWK_SUCCESS);
5216         }
5217 
5218         is_24G = iwk_is_24G_band(sc);
5219         channel_n = sc->sc_config.chan;       /* channel number */
5220 
5221         if ((channel_n != (LE_32(sc->sc_statistics.flag) >> 16)) ||
5222             ((STATISTICS_REPLY_FLG_BAND_24G_MSK ==
5223             (LE_32(sc->sc_statistics.flag) &
5224             STATISTICS_REPLY_FLG_BAND_24G_MSK)) &&
5225             !is_24G)) {
5226                 return (IWK_SUCCESS);
5227         }
5228 
5229         /* Rx chain's noise strength from statistics notification */
5230         noise_chain_a = LE_32(rx_general_p->beacon_silence_rssi_a) & 0xFF;
5231         noise_chain_b = LE_32(rx_general_p->beacon_silence_rssi_b) & 0xFF;
5232         noise_chain_c = LE_32(rx_general_p->beacon_silence_rssi_c) & 0xFF;
5233 
5234         /* Rx chain's beacon strength from statistics notification */
5235         beacon_chain_a = LE_32(rx_general_p->beacon_rssi_a) & 0xFF;
5236         beacon_chain_b = LE_32(rx_general_p->beacon_rssi_b) & 0xFF;
5237         beacon_chain_c = LE_32(rx_general_p->beacon_rssi_c) & 0xFF;
5238 
5239         gain_diff_p->beacon_count++;
5240 
5241         /* accumulate chain's noise strength */
5242         gain_diff_p->noise_stren_a += noise_chain_a;
5243         gain_diff_p->noise_stren_b += noise_chain_b;
5244         gain_diff_p->noise_stren_c += noise_chain_c;
5245 
5246         /* accumulate chain's beacon strength */
5247         gain_diff_p->beacon_stren_a += beacon_chain_a;
5248         gain_diff_p->beacon_stren_b += beacon_chain_b;
5249         gain_diff_p->beacon_stren_c += beacon_chain_c;
5250 
5251         if (BEACON_NUM_20 == gain_diff_p->beacon_count) {
5252                 /* calculate average beacon strength */
5253                 beacon_aver[0] = (gain_diff_p->beacon_stren_a) / BEACON_NUM_20;
5254                 beacon_aver[1] = (gain_diff_p->beacon_stren_b) / BEACON_NUM_20;
5255                 beacon_aver[2] = (gain_diff_p->beacon_stren_c) / BEACON_NUM_20;
5256 
5257                 /* calculate average noise strength */
5258                 noise_aver[0] = (gain_diff_p->noise_stren_a) / BEACON_NUM_20;
5259                 noise_aver[1] = (gain_diff_p->noise_stren_b) / BEACON_NUM_20;
5260                 noise_aver[2] = (gain_diff_p->noise_stren_b) / BEACON_NUM_20;
5261 
5262                 /* determine maximum beacon strength among 3 chains */
5263                 if ((beacon_aver[0] >= beacon_aver[1]) &&
5264                     (beacon_aver[0] >= beacon_aver[2])) {
5265                         max_beacon_chain_n = 0;
5266                         gain_diff_p->connected_chains = 1 << 0;
5267                 } else if (beacon_aver[1] >= beacon_aver[2]) {
5268                         max_beacon_chain_n = 1;
5269                         gain_diff_p->connected_chains = 1 << 1;
5270                 } else {
5271                         max_beacon_chain_n = 2;
5272                         gain_diff_p->connected_chains = 1 << 2;
5273                 }
5274 
5275                 /* determine which chain is disconnected */
5276                 for (i = 0; i < RX_CHAINS_NUM; i++) {
5277                         if (i != max_beacon_chain_n) {
5278                                 beacon_diff = beacon_aver[max_beacon_chain_n] -
5279                                     beacon_aver[i];
5280                                 if (beacon_diff > MAX_ALLOWED_DIFF) {
5281                                         gain_diff_p->disconnect_chain[i] = 1;
5282                                 } else {
5283                                         gain_diff_p->connected_chains |=
5284                                             (1 << i);
5285                                 }
5286                         }
5287                 }
5288 
5289                 /*
5290                  * if chain A and B are both disconnected,
5291                  * assume the stronger in beacon strength is connected
5292                  */
5293                 if (gain_diff_p->disconnect_chain[0] &&
5294                     gain_diff_p->disconnect_chain[1]) {
5295                         if (beacon_aver[0] >= beacon_aver[1]) {
5296                                 gain_diff_p->disconnect_chain[0] = 0;
5297                                 gain_diff_p->connected_chains |= (1 << 0);
5298                         } else {
5299                                 gain_diff_p->disconnect_chain[1] = 0;
5300                                 gain_diff_p->connected_chains |= (1 << 1);
5301                         }
5302                 }
5303 
5304                 /* determine minimum noise strength among 3 chains */
5305                 if (!gain_diff_p->disconnect_chain[0]) {
5306                         min_noise_chain_n = 0;
5307 
5308                         for (i = 0; i < RX_CHAINS_NUM; i++) {
5309                                 if (!gain_diff_p->disconnect_chain[i] &&
5310                                     (noise_aver[i] <=
5311                                     noise_aver[min_noise_chain_n])) {
5312                                         min_noise_chain_n = i;
5313                                 }
5314 
5315                         }
5316                 } else {
5317                         min_noise_chain_n = 1;
5318 
5319                         for (i = 0; i < RX_CHAINS_NUM; i++) {
5320                                 if (!gain_diff_p->disconnect_chain[i] &&
5321                                     (noise_aver[i] <=
5322                                     noise_aver[min_noise_chain_n])) {
5323                                         min_noise_chain_n = i;
5324                                 }
5325                         }
5326                 }
5327 
5328                 gain_diff_p->gain_diff_chain[min_noise_chain_n] = 0;
5329 
5330                 /* determine gain difference between chains */
5331                 for (i = 0; i < RX_CHAINS_NUM; i++) {
5332                         if (!gain_diff_p->disconnect_chain[i] &&
5333                             (CHAIN_GAIN_DIFF_INIT_VAL ==
5334                             gain_diff_p->gain_diff_chain[i])) {
5335 
5336                                 noise_diff = noise_aver[i] -
5337                                     noise_aver[min_noise_chain_n];
5338                                 gain_diff_p->gain_diff_chain[i] =
5339                                     (uint8_t)((noise_diff * 10) / 15);
5340 
5341                                 if (gain_diff_p->gain_diff_chain[i] > 3) {
5342                                         gain_diff_p->gain_diff_chain[i] = 3;
5343                                 }
5344 
5345                                 gain_diff_p->gain_diff_chain[i] |= (1 << 2);
5346                         } else {
5347                                 gain_diff_p->gain_diff_chain[i] = 0;
5348                         }
5349                 }
5350 
5351                 if (!gain_diff_p->gain_diff_send) {
5352                         gain_diff_p->gain_diff_send = 1;
5353 
5354                         (void) memset(&cmd, 0, sizeof (cmd));
5355 
5356                         cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
5357                         cmd.diff_gain_a = gain_diff_p->gain_diff_chain[0];
5358                         cmd.diff_gain_b = gain_diff_p->gain_diff_chain[1];
5359                         cmd.diff_gain_c = gain_diff_p->gain_diff_chain[2];
5360 
5361                         /*
5362                          * send out PHY calibration command to
5363                          * adjust every chain's Rx gain
5364                          */
5365                         rv = iwk_cmd(sc, REPLY_PHY_CALIBRATION_CMD,
5366                             &cmd, sizeof (cmd), 1);
5367                         if (rv) {
5368                                 return (rv);
5369                         }
5370 
5371                         gain_diff_p->state = IWK_GAIN_DIFF_CALIBRATED;
5372                 }
5373 
5374                 gain_diff_p->beacon_stren_a = 0;
5375                 gain_diff_p->beacon_stren_b = 0;
5376                 gain_diff_p->beacon_stren_c = 0;
5377 
5378                 gain_diff_p->noise_stren_a = 0;
5379                 gain_diff_p->noise_stren_b = 0;
5380                 gain_diff_p->noise_stren_c = 0;
5381         }
5382 
5383         return (IWK_SUCCESS);
5384 }
5385 
5386 /* Make necessary preparation for Receiver sensitivity calibration */
5387 static int iwk_rx_sens_init(iwk_sc_t *sc)
5388 {
5389         int i, rv;
5390         struct iwk_rx_sensitivity_cmd cmd;
5391         struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5392 
5393         (void) memset(&cmd, 0, sizeof (struct iwk_rx_sensitivity_cmd));
5394         (void) memset(rx_sens_p, 0, sizeof (struct iwk_rx_sensitivity));
5395 
5396         rx_sens_p->auto_corr_ofdm_x4 = 90;
5397         rx_sens_p->auto_corr_mrc_ofdm_x4 = 170;
5398         rx_sens_p->auto_corr_ofdm_x1 = 105;
5399         rx_sens_p->auto_corr_mrc_ofdm_x1 = 220;
5400 
5401         rx_sens_p->auto_corr_cck_x4 = 125;
5402         rx_sens_p->auto_corr_mrc_cck_x4 = 200;
5403         rx_sens_p->min_energy_det_cck = 100;
5404 
5405         rx_sens_p->flags &= (~IWK_SENSITIVITY_CALIB_ALLOW_MSK);
5406         rx_sens_p->flags &= (~IWK_SENSITIVITY_OFDM_UPDATE_MSK);
5407         rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK);
5408 
5409         rx_sens_p->last_bad_plcp_cnt_ofdm = 0;
5410         rx_sens_p->last_false_alarm_cnt_ofdm = 0;
5411         rx_sens_p->last_bad_plcp_cnt_cck = 0;
5412         rx_sens_p->last_false_alarm_cnt_cck = 0;
5413 
5414         rx_sens_p->cck_curr_state = IWK_TOO_MANY_FALSE_ALARM;
5415         rx_sens_p->cck_prev_state = IWK_TOO_MANY_FALSE_ALARM;
5416         rx_sens_p->cck_no_false_alarm_num = 0;
5417         rx_sens_p->cck_beacon_idx = 0;
5418 
5419         for (i = 0; i < 10; i++) {
5420                 rx_sens_p->cck_beacon_min[i] = 0;
5421         }
5422 
5423         rx_sens_p->cck_noise_idx = 0;
5424         rx_sens_p->cck_noise_ref = 0;
5425 
5426         for (i = 0; i < 20; i++) {
5427                 rx_sens_p->cck_noise_max[i] = 0;
5428         }
5429 
5430         rx_sens_p->cck_noise_diff = 0;
5431         rx_sens_p->cck_no_false_alarm_num = 0;
5432 
5433         cmd.control = LE_16(IWK_SENSITIVITY_CONTROL_WORK_TABLE);
5434 
5435         cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_IDX] =
5436             LE_16(rx_sens_p->auto_corr_ofdm_x4);
5437         cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] =
5438             LE_16(rx_sens_p->auto_corr_mrc_ofdm_x4);
5439         cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_IDX] =
5440             LE_16(rx_sens_p->auto_corr_ofdm_x1);
5441         cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] =
5442             LE_16(rx_sens_p->auto_corr_mrc_ofdm_x1);
5443 
5444         cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_IDX] =
5445             LE_16(rx_sens_p->auto_corr_cck_x4);
5446         cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] =
5447             LE_16(rx_sens_p->auto_corr_mrc_cck_x4);
5448         cmd.table[MIN_ENERGY_CCK_DET_IDX] =
5449             LE_16(rx_sens_p->min_energy_det_cck);
5450 
5451         cmd.table[MIN_ENERGY_OFDM_DET_IDX] = LE_16(100);
5452         cmd.table[BARKER_CORR_TH_ADD_MIN_IDX] = LE_16(190);
5453         cmd.table[BARKER_CORR_TH_ADD_MIN_MRC_IDX] = LE_16(390);
5454         cmd.table[PTAM_ENERGY_TH_IDX] = LE_16(62);
5455 
5456         /* at first, set up Rx to maximum sensitivity */
5457         rv = iwk_cmd(sc, SENSITIVITY_CMD, &cmd, sizeof (cmd), 1);
5458         if (rv) {
5459                 cmn_err(CE_WARN, "iwk_rx_sens_init(): "
5460                     "in the process of initialization, "
5461                     "failed to send rx sensitivity command\n");
5462                 return (rv);
5463         }
5464 
5465         rx_sens_p->flags |= IWK_SENSITIVITY_CALIB_ALLOW_MSK;
5466 
5467         return (IWK_SUCCESS);
5468 }
5469 
5470 /*
5471  * make Receiver sensitivity calibration to adjust every chain's Rx sensitivity.
5472  * for more infomation, please refer to iwk_calibration.h file
5473  */
5474 static int iwk_rx_sens(iwk_sc_t *sc)
5475 {
5476         int rv;
5477         uint32_t actual_rx_time;
5478         struct statistics_rx_non_phy *rx_general_p =
5479             &sc->sc_statistics.rx.general;
5480         struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5481         struct iwk_rx_sensitivity_cmd cmd;
5482 
5483         if (!(rx_sens_p->flags & IWK_SENSITIVITY_CALIB_ALLOW_MSK)) {
5484                 cmn_err(CE_WARN, "iwk_rx_sens(): "
5485                     "sensitivity initialization has not finished.\n");
5486                 return (DDI_FAILURE);
5487         }
5488 
5489         if (INTERFERENCE_DATA_AVAILABLE !=
5490             LE_32(rx_general_p->interference_data_flag)) {
5491                 cmn_err(CE_WARN, "iwk_rx_sens(): "
5492                     "can't make rx sensitivity calibration,"
5493                     "because of invalid statistics\n");
5494                 return (DDI_FAILURE);
5495         }
5496 
5497         actual_rx_time = LE_32(rx_general_p->channel_load);
5498         if (!actual_rx_time) {
5499                 IWK_DBG((IWK_DEBUG_CALIBRATION, "iwk_rx_sens(): "
5500                     "can't make rx sensitivity calibration,"
5501                     "because has not enough rx time\n"));
5502                 return (DDI_FAILURE);
5503         }
5504 
5505         /* make Rx sensitivity calibration for OFDM mode */
5506         rv = iwk_ofdm_sens(sc, actual_rx_time);
5507         if (rv) {
5508                 return (rv);
5509         }
5510 
5511         /* make Rx sensitivity calibration for CCK mode */
5512         rv = iwk_cck_sens(sc, actual_rx_time);
5513         if (rv) {
5514                 return (rv);
5515         }
5516 
5517         /*
5518          * if the sum of false alarm had not changed, nothing will be done
5519          */
5520         if ((!(rx_sens_p->flags & IWK_SENSITIVITY_OFDM_UPDATE_MSK)) &&
5521             (!(rx_sens_p->flags & IWK_SENSITIVITY_CCK_UPDATE_MSK))) {
5522                 return (IWK_SUCCESS);
5523         }
5524 
5525         cmd.control = IWK_SENSITIVITY_CONTROL_WORK_TABLE;
5526 
5527         cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_IDX] =
5528             rx_sens_p->auto_corr_ofdm_x4;
5529         cmd.table[AUTO_CORR32_X4_TH_ADD_MIN_MRC_IDX] =
5530             rx_sens_p->auto_corr_mrc_ofdm_x4;
5531         cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_IDX] =
5532             rx_sens_p->auto_corr_ofdm_x1;
5533         cmd.table[AUTO_CORR32_X1_TH_ADD_MIN_MRC_IDX] =
5534             rx_sens_p->auto_corr_mrc_ofdm_x1;
5535 
5536         cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_IDX] =
5537             rx_sens_p->auto_corr_cck_x4;
5538         cmd.table[AUTO_CORR40_X4_TH_ADD_MIN_MRC_IDX] =
5539             rx_sens_p->auto_corr_mrc_cck_x4;
5540         cmd.table[MIN_ENERGY_CCK_DET_IDX] =
5541             rx_sens_p->min_energy_det_cck;
5542 
5543         cmd.table[MIN_ENERGY_OFDM_DET_IDX] = 100;
5544         cmd.table[BARKER_CORR_TH_ADD_MIN_IDX] = 190;
5545         cmd.table[BARKER_CORR_TH_ADD_MIN_MRC_IDX] = 390;
5546         cmd.table[PTAM_ENERGY_TH_IDX] = 62;
5547 
5548         /*
5549          * send sensitivity command to complete actual sensitivity calibration
5550          */
5551         rv = iwk_cmd(sc, SENSITIVITY_CMD, &cmd, sizeof (cmd), 1);
5552         if (rv) {
5553                 cmn_err(CE_WARN, "iwk_rx_sens(): "
5554                     "fail to send rx sensitivity command\n");
5555                 return (rv);
5556         }
5557 
5558         return (IWK_SUCCESS);
5559 
5560 }
5561 
5562 /*
5563  * make Rx sensitivity calibration for CCK mode.
5564  * This is preparing parameters for Sensitivity command
5565  */
5566 static int iwk_cck_sens(iwk_sc_t *sc, uint32_t actual_rx_time)
5567 {
5568         int i;
5569         uint8_t noise_a, noise_b, noise_c;
5570         uint8_t max_noise_abc, max_noise_20;
5571         uint32_t beacon_a, beacon_b, beacon_c;
5572         uint32_t min_beacon_abc, max_beacon_10;
5573         uint32_t cck_fa, cck_bp;
5574         uint32_t cck_sum_fa_bp;
5575         uint32_t temp;
5576         struct statistics_rx_non_phy *rx_general_p =
5577             &sc->sc_statistics.rx.general;
5578         struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5579 
5580         cck_fa = LE_32(sc->sc_statistics.rx.cck.false_alarm_cnt);
5581         cck_bp = LE_32(sc->sc_statistics.rx.cck.plcp_err);
5582 
5583         /* accumulate false alarm */
5584         if (rx_sens_p->last_false_alarm_cnt_cck > cck_fa) {
5585                 temp = rx_sens_p->last_false_alarm_cnt_cck;
5586                 rx_sens_p->last_false_alarm_cnt_cck = cck_fa;
5587                 cck_fa += (0xFFFFFFFF - temp);
5588         } else {
5589                 cck_fa -= rx_sens_p->last_false_alarm_cnt_cck;
5590                 rx_sens_p->last_false_alarm_cnt_cck += cck_fa;
5591         }
5592 
5593         /* accumulate bad plcp */
5594         if (rx_sens_p->last_bad_plcp_cnt_cck > cck_bp) {
5595                 temp = rx_sens_p->last_bad_plcp_cnt_cck;
5596                 rx_sens_p->last_bad_plcp_cnt_cck = cck_bp;
5597                 cck_bp += (0xFFFFFFFF - temp);
5598         } else {
5599                 cck_bp -= rx_sens_p->last_bad_plcp_cnt_cck;
5600                 rx_sens_p->last_bad_plcp_cnt_cck += cck_bp;
5601         }
5602 
5603         /*
5604          * calculate relative value
5605          */
5606         cck_sum_fa_bp = (cck_fa + cck_bp) * 200 * 1024;
5607         rx_sens_p->cck_noise_diff = 0;
5608 
5609         noise_a =
5610             (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_a) & 0xFF00) >>
5611             8);
5612         noise_b =
5613             (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_b) & 0xFF00) >>
5614             8);
5615         noise_c =
5616             (uint8_t)((LE_32(rx_general_p->beacon_silence_rssi_c) & 0xFF00) >>
5617             8);
5618 
5619         beacon_a = LE_32(rx_general_p->beacon_energy_a);
5620         beacon_b = LE_32(rx_general_p->beacon_energy_b);
5621         beacon_c = LE_32(rx_general_p->beacon_energy_c);
5622 
5623         /* determine maximum noise among 3 chains */
5624         if ((noise_a >= noise_b) && (noise_a >= noise_c)) {
5625                 max_noise_abc = noise_a;
5626         } else if (noise_b >= noise_c) {
5627                 max_noise_abc = noise_b;
5628         } else {
5629                 max_noise_abc = noise_c;
5630         }
5631 
5632         /* record maximum noise among 3 chains */
5633         rx_sens_p->cck_noise_max[rx_sens_p->cck_noise_idx] = max_noise_abc;
5634         rx_sens_p->cck_noise_idx++;
5635         if (rx_sens_p->cck_noise_idx >= 20) {
5636                 rx_sens_p->cck_noise_idx = 0;
5637         }
5638 
5639         /* determine maximum noise among 20 max noise */
5640         max_noise_20 = rx_sens_p->cck_noise_max[0];
5641         for (i = 0; i < 20; i++) {
5642                 if (rx_sens_p->cck_noise_max[i] >= max_noise_20) {
5643                         max_noise_20 = rx_sens_p->cck_noise_max[i];
5644                 }
5645         }
5646 
5647         /* determine minimum beacon among 3 chains */
5648         if ((beacon_a <= beacon_b) && (beacon_a <= beacon_c)) {
5649                 min_beacon_abc = beacon_a;
5650         } else if (beacon_b <= beacon_c) {
5651                 min_beacon_abc = beacon_b;
5652         } else {
5653                 min_beacon_abc = beacon_c;
5654         }
5655 
5656         /* record miminum beacon among 3 chains */
5657         rx_sens_p->cck_beacon_min[rx_sens_p->cck_beacon_idx] = min_beacon_abc;
5658         rx_sens_p->cck_beacon_idx++;
5659         if (rx_sens_p->cck_beacon_idx >= 10) {
5660                 rx_sens_p->cck_beacon_idx = 0;
5661         }
5662 
5663         /* determine maximum beacon among 10 miminum beacon among 3 chains */
5664         max_beacon_10 = rx_sens_p->cck_beacon_min[0];
5665         for (i = 0; i < 10; i++) {
5666                 if (rx_sens_p->cck_beacon_min[i] >= max_beacon_10) {
5667                         max_beacon_10 = rx_sens_p->cck_beacon_min[i];
5668                 }
5669         }
5670 
5671         /* add a little margin */
5672         max_beacon_10 += 6;
5673 
5674         /* record the count of having no false alarms */
5675         if (cck_sum_fa_bp < (5 * actual_rx_time)) {
5676                 rx_sens_p->cck_no_false_alarm_num++;
5677         } else {
5678                 rx_sens_p->cck_no_false_alarm_num = 0;
5679         }
5680 
5681         /*
5682          * adjust parameters in sensitivity command
5683          * according to different status.
5684          * for more infomation, please refer to iwk_calibration.h file
5685          */
5686         if (cck_sum_fa_bp > (50 * actual_rx_time)) {
5687                 rx_sens_p->cck_curr_state = IWK_TOO_MANY_FALSE_ALARM;
5688 
5689                 if (rx_sens_p->auto_corr_cck_x4 > 160) {
5690                         rx_sens_p->cck_noise_ref = max_noise_20;
5691 
5692                         if (rx_sens_p->min_energy_det_cck > 2) {
5693                                 rx_sens_p->min_energy_det_cck -= 2;
5694                         }
5695                 }
5696 
5697                 if (rx_sens_p->auto_corr_cck_x4 < 160) {
5698                         rx_sens_p->auto_corr_cck_x4 = 160 + 1;
5699                 } else {
5700                         if ((rx_sens_p->auto_corr_cck_x4 + 3) < 200) {
5701                                 rx_sens_p->auto_corr_cck_x4 += 3;
5702                         } else {
5703                                 rx_sens_p->auto_corr_cck_x4 = 200;
5704                         }
5705                 }
5706 
5707                 if ((rx_sens_p->auto_corr_mrc_cck_x4 + 3) < 400) {
5708                         rx_sens_p->auto_corr_mrc_cck_x4 += 3;
5709                 } else {
5710                         rx_sens_p->auto_corr_mrc_cck_x4 = 400;
5711                 }
5712 
5713                 rx_sens_p->flags |= IWK_SENSITIVITY_CCK_UPDATE_MSK;
5714 
5715         } else if (cck_sum_fa_bp < (5 * actual_rx_time)) {
5716                 rx_sens_p->cck_curr_state = IWK_TOO_FEW_FALSE_ALARM;
5717 
5718                 rx_sens_p->cck_noise_diff = (int32_t)rx_sens_p->cck_noise_ref -
5719                     (int32_t)max_noise_20;
5720 
5721                 if ((rx_sens_p->cck_prev_state != IWK_TOO_MANY_FALSE_ALARM) &&
5722                     ((rx_sens_p->cck_noise_diff > 2) ||
5723                     (rx_sens_p->cck_no_false_alarm_num > 100))) {
5724                         if ((rx_sens_p->min_energy_det_cck + 2) < 97) {
5725                                 rx_sens_p->min_energy_det_cck += 2;
5726                         } else {
5727                                 rx_sens_p->min_energy_det_cck = 97;
5728                         }
5729 
5730                         if ((rx_sens_p->auto_corr_cck_x4 - 3) > 125) {
5731                                 rx_sens_p->auto_corr_cck_x4 -= 3;
5732                         } else {
5733                                 rx_sens_p->auto_corr_cck_x4 = 125;
5734                         }
5735 
5736                         if ((rx_sens_p->auto_corr_mrc_cck_x4 -3) > 200) {
5737                                 rx_sens_p->auto_corr_mrc_cck_x4 -= 3;
5738                         } else {
5739                                 rx_sens_p->auto_corr_mrc_cck_x4 = 200;
5740                         }
5741 
5742                         rx_sens_p->flags |= IWK_SENSITIVITY_CCK_UPDATE_MSK;
5743                 } else {
5744                         rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK);
5745                 }
5746         } else {
5747                 rx_sens_p->cck_curr_state = IWK_GOOD_RANGE_FALSE_ALARM;
5748 
5749                 rx_sens_p->cck_noise_ref = max_noise_20;
5750 
5751                 if (IWK_TOO_MANY_FALSE_ALARM == rx_sens_p->cck_prev_state) {
5752                         rx_sens_p->min_energy_det_cck -= 8;
5753                 }
5754 
5755                 rx_sens_p->flags &= (~IWK_SENSITIVITY_CCK_UPDATE_MSK);
5756         }
5757 
5758         if (rx_sens_p->min_energy_det_cck < max_beacon_10) {
5759                 rx_sens_p->min_energy_det_cck = (uint16_t)max_beacon_10;
5760         }
5761 
5762         rx_sens_p->cck_prev_state = rx_sens_p->cck_curr_state;
5763 
5764         return (IWK_SUCCESS);
5765 }
5766 
5767 /*
5768  * make Rx sensitivity calibration for OFDM mode.
5769  * This is preparing parameters for Sensitivity command
5770  */
5771 static int iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time)
5772 {
5773         uint32_t temp;
5774         uint16_t temp1;
5775         uint32_t ofdm_fa, ofdm_bp;
5776         uint32_t ofdm_sum_fa_bp;
5777         struct iwk_rx_sensitivity *rx_sens_p = &sc->sc_rx_sens;
5778 
5779         ofdm_fa = LE_32(sc->sc_statistics.rx.ofdm.false_alarm_cnt);
5780         ofdm_bp = LE_32(sc->sc_statistics.rx.ofdm.plcp_err);
5781 
5782         /* accumulate false alarm */
5783         if (rx_sens_p->last_false_alarm_cnt_ofdm > ofdm_fa) {
5784                 temp = rx_sens_p->last_false_alarm_cnt_ofdm;
5785                 rx_sens_p->last_false_alarm_cnt_ofdm = ofdm_fa;
5786                 ofdm_fa += (0xFFFFFFFF - temp);
5787         } else {
5788                 ofdm_fa -= rx_sens_p->last_false_alarm_cnt_ofdm;
5789                 rx_sens_p->last_false_alarm_cnt_ofdm += ofdm_fa;
5790         }
5791 
5792         /* accumulate bad plcp */
5793         if (rx_sens_p->last_bad_plcp_cnt_ofdm > ofdm_bp) {
5794                 temp = rx_sens_p->last_bad_plcp_cnt_ofdm;
5795                 rx_sens_p->last_bad_plcp_cnt_ofdm = ofdm_bp;
5796                 ofdm_bp += (0xFFFFFFFF - temp);
5797         } else {
5798                 ofdm_bp -= rx_sens_p->last_bad_plcp_cnt_ofdm;
5799                 rx_sens_p->last_bad_plcp_cnt_ofdm += ofdm_bp;
5800         }
5801 
5802         ofdm_sum_fa_bp = (ofdm_fa + ofdm_bp) * 200 * 1024; /* relative value */
5803 
5804         /*
5805          * adjust parameter in sensitivity command according to different status
5806          */
5807         if (ofdm_sum_fa_bp > (50 * actual_rx_time)) {
5808                 temp1 = rx_sens_p->auto_corr_ofdm_x4 + 1;
5809                 rx_sens_p->auto_corr_ofdm_x4 = (temp1 <= 120) ? temp1 : 120;
5810 
5811                 temp1 = rx_sens_p->auto_corr_mrc_ofdm_x4 + 1;
5812                 rx_sens_p->auto_corr_mrc_ofdm_x4 =
5813                     (temp1 <= 210) ? temp1 : 210;
5814 
5815                 temp1 = rx_sens_p->auto_corr_ofdm_x1 + 1;
5816                 rx_sens_p->auto_corr_ofdm_x1 = (temp1 <= 140) ? temp1 : 140;
5817 
5818                 temp1 = rx_sens_p->auto_corr_mrc_ofdm_x1 + 1;
5819                 rx_sens_p->auto_corr_mrc_ofdm_x1 =
5820                     (temp1 <= 270) ? temp1 : 270;
5821 
5822                 rx_sens_p->flags |= IWK_SENSITIVITY_OFDM_UPDATE_MSK;
5823 
5824         } else if (ofdm_sum_fa_bp < (5 * actual_rx_time)) {
5825                 temp1 = rx_sens_p->auto_corr_ofdm_x4 - 1;
5826                 rx_sens_p->auto_corr_ofdm_x4 = (temp1 >= 85) ? temp1 : 85;
5827 
5828                 temp1 = rx_sens_p->auto_corr_mrc_ofdm_x4 - 1;
5829                 rx_sens_p->auto_corr_mrc_ofdm_x4 =
5830                     (temp1 >= 170) ? temp1 : 170;
5831 
5832                 temp1 = rx_sens_p->auto_corr_ofdm_x1 - 1;
5833                 rx_sens_p->auto_corr_ofdm_x1 = (temp1 >= 105) ? temp1 : 105;
5834 
5835                 temp1 = rx_sens_p->auto_corr_mrc_ofdm_x1 - 1;
5836                 rx_sens_p->auto_corr_mrc_ofdm_x1 =
5837                     (temp1 >= 220) ? temp1 : 220;
5838 
5839                 rx_sens_p->flags |= IWK_SENSITIVITY_OFDM_UPDATE_MSK;
5840 
5841         } else {
5842                 rx_sens_p->flags &= (~IWK_SENSITIVITY_OFDM_UPDATE_MSK);
5843         }
5844 
5845         return (IWK_SUCCESS);
5846 }
5847 
5848 /*
5849  * additional process to management frames
5850  */
5851 static void iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp,
5852     struct ieee80211_node *in,
5853     int subtype, int rssi, uint32_t rstamp)
5854 {
5855         iwk_sc_t *sc = (iwk_sc_t *)ic;
5856         struct ieee80211_frame *wh;
5857         uint8_t index1, index2;
5858         int err;
5859 
5860         sc->sc_recv_mgmt(ic, mp, in, subtype, rssi, rstamp);
5861 
5862         mutex_enter(&sc->sc_glock);
5863         switch (subtype) {
5864         case IEEE80211_FC0_SUBTYPE_BEACON:
5865                 if (sc->sc_ibss.ibss_beacon.syncbeacon && in == ic->ic_bss &&
5866                     ic->ic_state == IEEE80211_S_RUN) {
5867                         if (ieee80211_beacon_update(ic, in,
5868                             &sc->sc_ibss.ibss_beacon.iwk_boff,
5869                             sc->sc_ibss.ibss_beacon.mp, 0)) {
5870                                 bcopy(sc->sc_ibss.ibss_beacon.mp->b_rptr,
5871                                     sc->sc_ibss.ibss_beacon.beacon_cmd.
5872                                     bcon_frame,
5873                                     MBLKL(sc->sc_ibss.ibss_beacon.mp));
5874                         }
5875                         err = iwk_cmd(sc, REPLY_TX_BEACON,
5876                             &sc->sc_ibss.ibss_beacon.beacon_cmd,
5877                             sc->sc_ibss.ibss_beacon.beacon_cmd_len, 1);
5878                         if (err != IWK_SUCCESS) {
5879                                 cmn_err(CE_WARN, "iwk_recv_mgmt(): "
5880                                     "failed to TX beacon.\n");
5881                         }
5882                         sc->sc_ibss.ibss_beacon.syncbeacon = 0;
5883                 }
5884                 if (ic->ic_opmode == IEEE80211_M_IBSS &&
5885                     ic->ic_state == IEEE80211_S_RUN) {
5886                         wh = (struct ieee80211_frame *)mp->b_rptr;
5887                         mutex_enter(&sc->sc_ibss.node_tb_lock);
5888                         /*
5889                          * search for node in ibss node table
5890                          */
5891                         for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT;
5892                             index1++) {
5893                                 if (sc->sc_ibss.ibss_node_tb[index1].used &&
5894                                     IEEE80211_ADDR_EQ(sc->sc_ibss.
5895                                     ibss_node_tb[index1].node.bssid,
5896                                     wh->i_addr2)) {
5897                                         break;
5898                                 }
5899                         }
5900                         /*
5901                          * if don't find in ibss node table
5902                          */
5903                         if (index1 >= IWK_BROADCAST_ID) {
5904                                 err = iwk_clean_add_node_ibss(ic,
5905                                     wh->i_addr2, &index2);
5906                                 if (err != IWK_SUCCESS) {
5907                                         cmn_err(CE_WARN, "iwk_recv_mgmt(): "
5908                                             "failed to clean all nodes "
5909                                             "and add one node\n");
5910                                 }
5911                         }
5912                         mutex_exit(&sc->sc_ibss.node_tb_lock);
5913                 }
5914                 break;
5915         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
5916                 break;
5917         }
5918         mutex_exit(&sc->sc_glock);
5919 }
5920 
5921 /*
5922  * 1)  log_event_table_ptr indicates base of the event log.  This traces
5923  *     a 256-entry history of uCode execution within a circular buffer.
5924  *     Its header format is:
5925  *
5926  *      uint32_t log_size;      log capacity (in number of entries)
5927  *      uint32_t type;  (1) timestamp with each entry, (0) no timestamp
5928  *      uint32_t wraps; # times uCode has wrapped to top of circular buffer
5929  *      uint32_t write_index;   next circular buffer entry that uCode would fill
5930  *
5931  *     The header is followed by the circular buffer of log entries.  Entries
5932  *     with timestamps have the following format:
5933  *
5934  *      uint32_t event_id;     range 0 - 1500
5935  *      uint32_t timestamp;    low 32 bits of TSF (of network, if associated)
5936  *      uint32_t data;         event_id-specific data value
5937  *
5938  *     Entries without timestamps contain only event_id and data.
5939  */
5940 
5941 /*
5942  * iwk_write_event_log - Write event log to dmesg
5943  */
5944 static void iwk_write_event_log(iwk_sc_t *sc)
5945 {
5946         uint32_t log_event_table_ptr;   /* Start address of event table */
5947         uint32_t startptr;      /* Start address of log data */
5948         uint32_t logptr;        /* address of log data entry */
5949         uint32_t i, n, num_events;
5950         uint32_t event_id, data1, data2; /* log data */
5951 
5952         uint32_t log_size;   /* log capacity (in number of entries) */
5953         uint32_t type;  /* (1)timestamp with each entry,(0) no timestamp */
5954         uint32_t wraps; /* # times uCode has wrapped to */
5955                         /* the top of circular buffer */
5956         uint32_t idx; /* index of entry to be filled in next */
5957 
5958         log_event_table_ptr = LE_32(sc->sc_card_alive_run.log_event_table_ptr);
5959         if (!(log_event_table_ptr)) {
5960                 IWK_DBG((IWK_DEBUG_EEPROM, "NULL event table pointer\n"));
5961                 return;
5962         }
5963 
5964         iwk_mac_access_enter(sc);
5965 
5966         /* Read log header */
5967         log_size = iwk_mem_read(sc, log_event_table_ptr);
5968         log_event_table_ptr += sizeof (uint32_t); /* addr of "type" */
5969         type = iwk_mem_read(sc, log_event_table_ptr);
5970         log_event_table_ptr += sizeof (uint32_t); /* addr of "wraps" */
5971         wraps = iwk_mem_read(sc, log_event_table_ptr);
5972         log_event_table_ptr += sizeof (uint32_t); /* addr of "idx" */
5973         idx = iwk_mem_read(sc, log_event_table_ptr);
5974         startptr = log_event_table_ptr +
5975             sizeof (uint32_t); /* addr of start of log data */
5976         if (!log_size & !wraps) {
5977                 IWK_DBG((IWK_DEBUG_EEPROM, "Empty log\n"));
5978                 iwk_mac_access_exit(sc);
5979                 return;
5980         }
5981 
5982         if (!wraps) {
5983                 num_events = idx;
5984                 logptr = startptr;
5985         } else {
5986                 num_events = log_size - idx;
5987                 n = type ? 2 : 3;
5988                 logptr = startptr + (idx * n * sizeof (uint32_t));
5989         }
5990 
5991         for (i = 0; i < num_events; i++) {
5992                 event_id = iwk_mem_read(sc, logptr);
5993                 logptr += sizeof (uint32_t);
5994                 data1 = iwk_mem_read(sc, logptr);
5995                 logptr += sizeof (uint32_t);
5996                 if (type == 0) { /* no timestamp */
5997                         IWK_DBG((IWK_DEBUG_EEPROM, "Event ID=%d, Data=%x0x",
5998                             event_id, data1));
5999                 } else { /* timestamp */
6000                         data2 = iwk_mem_read(sc, logptr);
6001                         IWK_DBG((IWK_DEBUG_EEPROM,
6002                             "Time=%d, Event ID=%d, Data=0x%x\n",
6003                             data1, event_id, data2));
6004                         logptr += sizeof (uint32_t);
6005                 }
6006         }
6007 
6008         /*
6009          * Print the wrapped around entries, if any
6010          */
6011         if (wraps) {
6012                 logptr = startptr;
6013                 for (i = 0; i < idx; i++) {
6014                         event_id = iwk_mem_read(sc, logptr);
6015                         logptr += sizeof (uint32_t);
6016                         data1 = iwk_mem_read(sc, logptr);
6017                         logptr += sizeof (uint32_t);
6018                         if (type == 0) { /* no timestamp */
6019                                 IWK_DBG((IWK_DEBUG_EEPROM,
6020                                     "Event ID=%d, Data=%x0x", event_id, data1));
6021                         } else { /* timestamp */
6022                                 data2 = iwk_mem_read(sc, logptr);
6023                                 IWK_DBG((IWK_DEBUG_EEPROM,
6024                                     "Time = %d, Event ID=%d, Data=0x%x\n",
6025                                     data1, event_id, data2));
6026                                 logptr += sizeof (uint32_t);
6027                         }
6028                 }
6029         }
6030 
6031         iwk_mac_access_exit(sc);
6032 }
6033 
6034 /*
6035  * error_event_table_ptr indicates base of the error log.  This contains
6036  * information about any uCode error that occurs.  For 4965, the format is:
6037  *
6038  * uint32_t valid;        (nonzero) valid, (0) log is empty
6039  * uint32_t error_id;     type of error
6040  * uint32_t pc;           program counter
6041  * uint32_t blink1;       branch link
6042  * uint32_t blink2;       branch link
6043  * uint32_t ilink1;       interrupt link
6044  * uint32_t ilink2;       interrupt link
6045  * uint32_t data1;        error-specific data
6046  * uint32_t data2;        error-specific data
6047  * uint32_t line;         source code line of error
6048  * uint32_t bcon_time;    beacon timer
6049  * uint32_t tsf_low;      network timestamp function timer
6050  * uint32_t tsf_hi;       network timestamp function timer
6051  */
6052 /*
6053  * iwk_write_error_log - Write error log to dmesg
6054  */
6055 static void iwk_write_error_log(iwk_sc_t *sc)
6056 {
6057         uint32_t err_ptr;       /* Start address of error log */
6058         uint32_t valid;         /* is error log valid */
6059 
6060         err_ptr = LE_32(sc->sc_card_alive_run.error_event_table_ptr);
6061         if (!(err_ptr)) {
6062                 IWK_DBG((IWK_DEBUG_EEPROM, "NULL error table pointer\n"));
6063                 return;
6064         }
6065 
6066         iwk_mac_access_enter(sc);
6067 
6068         valid = iwk_mem_read(sc, err_ptr);
6069         if (!(valid)) {
6070                 IWK_DBG((IWK_DEBUG_EEPROM, "Error data not valid\n"));
6071                 iwk_mac_access_exit(sc);
6072                 return;
6073         }
6074         err_ptr += sizeof (uint32_t);
6075         IWK_DBG((IWK_DEBUG_EEPROM, "err=%d ", iwk_mem_read(sc, err_ptr)));
6076         err_ptr += sizeof (uint32_t);
6077         IWK_DBG((IWK_DEBUG_EEPROM, "pc=0x%X ", iwk_mem_read(sc, err_ptr)));
6078         err_ptr += sizeof (uint32_t);
6079         IWK_DBG((IWK_DEBUG_EEPROM,
6080             "branch link1=0x%X ", iwk_mem_read(sc, err_ptr)));
6081         err_ptr += sizeof (uint32_t);
6082         IWK_DBG((IWK_DEBUG_EEPROM,
6083             "branch link2=0x%X ", iwk_mem_read(sc, err_ptr)));
6084         err_ptr += sizeof (uint32_t);
6085         IWK_DBG((IWK_DEBUG_EEPROM,
6086             "interrupt link1=0x%X ", iwk_mem_read(sc, err_ptr)));
6087         err_ptr += sizeof (uint32_t);
6088         IWK_DBG((IWK_DEBUG_EEPROM,
6089             "interrupt link2=0x%X ", iwk_mem_read(sc, err_ptr)));
6090         err_ptr += sizeof (uint32_t);
6091         IWK_DBG((IWK_DEBUG_EEPROM, "data1=0x%X ", iwk_mem_read(sc, err_ptr)));
6092         err_ptr += sizeof (uint32_t);
6093         IWK_DBG((IWK_DEBUG_EEPROM, "data2=0x%X ", iwk_mem_read(sc, err_ptr)));
6094         err_ptr += sizeof (uint32_t);
6095         IWK_DBG((IWK_DEBUG_EEPROM, "line=%d ", iwk_mem_read(sc, err_ptr)));
6096         err_ptr += sizeof (uint32_t);
6097         IWK_DBG((IWK_DEBUG_EEPROM, "bcon_time=%d ", iwk_mem_read(sc, err_ptr)));
6098         err_ptr += sizeof (uint32_t);
6099         IWK_DBG((IWK_DEBUG_EEPROM, "tsf_low=%d ", iwk_mem_read(sc, err_ptr)));
6100         err_ptr += sizeof (uint32_t);
6101         IWK_DBG((IWK_DEBUG_EEPROM, "tsf_hi=%d\n", iwk_mem_read(sc, err_ptr)));
6102 
6103         iwk_mac_access_exit(sc);
6104 }
6105 
6106 static int
6107 iwk_run_state_config_ibss(ieee80211com_t *ic)
6108 {
6109         iwk_sc_t *sc = (iwk_sc_t *)ic;
6110         ieee80211_node_t *in = ic->ic_bss;
6111         int i, err = IWK_SUCCESS;
6112 
6113         mutex_enter(&sc->sc_ibss.node_tb_lock);
6114 
6115         /*
6116          * clean all nodes in ibss node table assure be
6117          * consistent with hardware
6118          */
6119         for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) {
6120                 sc->sc_ibss.ibss_node_tb[i].used = 0;
6121                 (void) memset(&sc->sc_ibss.ibss_node_tb[i].node,
6122                     0,
6123                     sizeof (iwk_add_sta_t));
6124         }
6125 
6126         sc->sc_ibss.node_number = 0;
6127 
6128         mutex_exit(&sc->sc_ibss.node_tb_lock);
6129 
6130         /*
6131          * configure RX and TX
6132          */
6133         sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
6134 
6135         sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
6136         sc->sc_config.filter_flags =
6137             LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
6138             RXON_FILTER_DIS_DECRYPT_MSK |
6139             RXON_FILTER_DIS_GRP_DECRYPT_MSK);
6140 
6141         sc->sc_config.assoc_id = 0;
6142 
6143         IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
6144         sc->sc_config.chan = LE_16(ieee80211_chan2ieee(ic,
6145             in->in_chan));
6146 
6147         if (ic->ic_curmode == IEEE80211_MODE_11B) {
6148                 sc->sc_config.cck_basic_rates = 0x03;
6149                 sc->sc_config.ofdm_basic_rates = 0;
6150         } else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
6151             (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
6152                 sc->sc_config.cck_basic_rates = 0;
6153                 sc->sc_config.ofdm_basic_rates = 0x15;
6154 
6155         } else {
6156                 sc->sc_config.cck_basic_rates = 0x0f;
6157                 sc->sc_config.ofdm_basic_rates = 0xff;
6158         }
6159 
6160         sc->sc_config.flags &=
6161             ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
6162             RXON_FLG_SHORT_SLOT_MSK);
6163 
6164         if (ic->ic_flags & IEEE80211_F_SHSLOT) {
6165                 sc->sc_config.flags |=
6166                     LE_32(RXON_FLG_SHORT_SLOT_MSK);
6167         }
6168 
6169         if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
6170                 sc->sc_config.flags |=
6171                     LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
6172         }
6173 
6174         sc->sc_config.filter_flags |=
6175             LE_32(RXON_FILTER_ASSOC_MSK);
6176 
6177         err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
6178             sizeof (iwk_rxon_cmd_t), 1);
6179         if (err != IWK_SUCCESS) {
6180                 cmn_err(CE_WARN, "iwk_run_state_config_ibss(): "
6181                     "failed to update configuration.\n");
6182                 return (err);
6183         }
6184 
6185         return (err);
6186 
6187 }
6188 
6189 static int
6190 iwk_run_state_config_sta(ieee80211com_t *ic)
6191 {
6192         iwk_sc_t *sc = (iwk_sc_t *)ic;
6193         ieee80211_node_t *in = ic->ic_bss;
6194         int err = IWK_SUCCESS;
6195 
6196         /* update adapter's configuration */
6197         if (sc->sc_assoc_id != in->in_associd) {
6198                 cmn_err(CE_WARN, "iwk_run_state_config_sta(): "
6199                     "associate ID mismatch: expected %d, "
6200                     "got %d\n",
6201                     in->in_associd, sc->sc_assoc_id);
6202         }
6203         sc->sc_config.assoc_id = LE_16(in->in_associd & 0x3fff);
6204 
6205         /*
6206          * short preamble/slot time are
6207          * negotiated when associating
6208          */
6209         sc->sc_config.flags &=
6210             ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
6211             RXON_FLG_SHORT_SLOT_MSK);
6212 
6213         if (ic->ic_flags & IEEE80211_F_SHSLOT)
6214                 sc->sc_config.flags |=
6215                     LE_32(RXON_FLG_SHORT_SLOT_MSK);
6216 
6217         if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
6218                 sc->sc_config.flags |=
6219                     LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
6220 
6221         sc->sc_config.filter_flags |=
6222             LE_32(RXON_FILTER_ASSOC_MSK);
6223 
6224         if (ic->ic_opmode != IEEE80211_M_STA)
6225                 sc->sc_config.filter_flags |=
6226                     LE_32(RXON_FILTER_BCON_AWARE_MSK);
6227 
6228         IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x"
6229             " filter_flags %x\n",
6230             sc->sc_config.chan, sc->sc_config.flags,
6231             sc->sc_config.filter_flags));
6232 
6233         err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
6234             sizeof (iwk_rxon_cmd_t), 1);
6235         if (err != IWK_SUCCESS) {
6236                 cmn_err(CE_WARN, "iwk_run_state_config_sta(): "
6237                     "failed to update configuration\n");
6238                 return (err);
6239         }
6240 
6241         return (err);
6242 }
6243 
6244 static int
6245 iwk_fast_recover(iwk_sc_t *sc)
6246 {
6247         ieee80211com_t *ic = &sc->sc_ic;
6248         int err;
6249 
6250         mutex_enter(&sc->sc_glock);
6251 
6252         /* restore runtime configuration */
6253         bcopy(&sc->sc_config_save, &sc->sc_config,
6254             sizeof (sc->sc_config));
6255 
6256         /* reset state to handle reassociations correctly */
6257         sc->sc_config.assoc_id = 0;
6258         sc->sc_config.filter_flags &=
6259             ~LE_32(RXON_FILTER_ASSOC_MSK);
6260 
6261         if ((err = iwk_hw_set_before_auth(sc)) != 0) {
6262                 cmn_err(CE_WARN, "iwk_fast_recover(): "
6263                     "failed to setup authentication\n");
6264                 mutex_exit(&sc->sc_glock);
6265                 return (err);
6266         }
6267 
6268         bcopy(&sc->sc_config_save, &sc->sc_config,
6269             sizeof (sc->sc_config));
6270 
6271         /* update adapter's configuration */
6272         err = iwk_run_state_config_sta(ic);
6273         if (err != IWK_SUCCESS) {
6274                 cmn_err(CE_WARN, "iwk_fast_recover(): "
6275                     "failed to setup association\n");
6276                 mutex_exit(&sc->sc_glock);
6277                 return (err);
6278         }
6279 
6280         /* obtain current temperature of chipset */
6281         sc->sc_tempera = iwk_curr_tempera(sc);
6282 
6283         /*
6284          * make Tx power calibration to determine
6285          * the gains of DSP and radio
6286          */
6287         err = iwk_tx_power_calibration(sc);
6288         if (err) {
6289                 cmn_err(CE_WARN, "iwk_fast_recover(): "
6290                     "failed to set tx power table\n");
6291                 mutex_exit(&sc->sc_glock);
6292                 return (err);
6293         }
6294 
6295         /*
6296          * make initialization for Receiver
6297          * sensitivity calibration
6298          */
6299         err = iwk_rx_sens_init(sc);
6300         if (err) {
6301                 cmn_err(CE_WARN, "iwk_fast_recover(): "
6302                     "failed to init RX sensitivity\n");
6303                 mutex_exit(&sc->sc_glock);
6304                 return (err);
6305         }
6306 
6307         /* make initialization for Receiver gain balance */
6308         err = iwk_rxgain_diff_init(sc);
6309         if (err) {
6310                 cmn_err(CE_WARN, "iwk_fast_recover(): "
6311                     "failed to init phy calibration\n");
6312                 mutex_exit(&sc->sc_glock);
6313                 return (err);
6314 
6315         }
6316         /* set LED on */
6317         iwk_set_led(sc, 2, 0, 1);
6318 
6319         mutex_exit(&sc->sc_glock);
6320 
6321         /* update keys */
6322         if (ic->ic_flags & IEEE80211_F_PRIVACY) {
6323                 for (int i = 0; i < IEEE80211_KEY_MAX; i++) {
6324                         if (ic->ic_nw_keys[i].wk_keyix == IEEE80211_KEYIX_NONE)
6325                                 continue;
6326                         err = iwk_key_set(ic, &ic->ic_nw_keys[i],
6327                             ic->ic_bss->in_macaddr);
6328                         /* failure */
6329                         if (err == 0) {
6330                                 cmn_err(CE_WARN, "iwk_fast_recover(): "
6331                                     "failed to setup hardware keys\n");
6332                                 return (IWK_FAIL);
6333                         }
6334                 }
6335         }
6336 
6337         sc->sc_flags &= ~IWK_F_HW_ERR_RECOVER;
6338 
6339         /* start queue */
6340         IWK_DBG((IWK_DEBUG_FW, "iwk_fast_recover(): resume xmit\n"));
6341         mac_tx_update(ic->ic_mach);
6342 
6343 
6344         return (IWK_SUCCESS);
6345 }
6346 
6347 static int
6348 iwk_start_tx_beacon(ieee80211com_t *ic)
6349 {
6350         iwk_sc_t *sc = (iwk_sc_t *)ic;
6351         ieee80211_node_t *in = ic->ic_bss;
6352         int err = IWK_SUCCESS;
6353         iwk_tx_beacon_cmd_t  *tx_beacon_p;
6354         uint16_t  masks = 0;
6355         mblk_t *mp;
6356         int rate;
6357 
6358         /*
6359          * allocate and transmit beacon frames
6360          */
6361         tx_beacon_p = &sc->sc_ibss.ibss_beacon.beacon_cmd;
6362 
6363         (void) memset(tx_beacon_p, 0,
6364             sizeof (iwk_tx_beacon_cmd_t));
6365         rate = 0;
6366         masks = 0;
6367 
6368         tx_beacon_p->config.sta_id = IWK_BROADCAST_ID;
6369         tx_beacon_p->config.stop_time.life_time =
6370             LE_32(0xffffffff);
6371 
6372         if (sc->sc_ibss.ibss_beacon.mp != NULL) {
6373                 freemsg(sc->sc_ibss.ibss_beacon.mp);
6374                 sc->sc_ibss.ibss_beacon.mp = NULL;
6375         }
6376 
6377         sc->sc_ibss.ibss_beacon.mp =
6378             ieee80211_beacon_alloc(ic, in,
6379             &sc->sc_ibss.ibss_beacon.iwk_boff);
6380         if (sc->sc_ibss.ibss_beacon.mp == NULL) {
6381                 cmn_err(CE_WARN, "iwk_start_tx_beacon(): "
6382                     "failed to get beacon frame.\n");
6383                 return (IWK_FAIL);
6384         }
6385 
6386         mp = sc->sc_ibss.ibss_beacon.mp;
6387 
6388         ASSERT(mp->b_cont == NULL);
6389 
6390         bcopy(mp->b_rptr, tx_beacon_p->bcon_frame, MBLKL(mp));
6391 
6392         tx_beacon_p->config.len = LE_16((uint16_t)(MBLKL(mp)));
6393         sc->sc_ibss.ibss_beacon.beacon_cmd_len =
6394             sizeof (iwk_tx_cmd_t) +
6395             4 + LE_16(tx_beacon_p->config.len);
6396 
6397         /*
6398          * beacons are sent at 1M
6399          */
6400         rate = in->in_rates.ir_rates[0];
6401         rate &= IEEE80211_RATE_VAL;
6402 
6403         if (2 == rate || 4 == rate || 11 == rate ||
6404             22 == rate) {
6405                 masks |= RATE_MCS_CCK_MSK;
6406         }
6407 
6408         masks |= RATE_MCS_ANT_B_MSK;
6409 
6410         tx_beacon_p->config.rate.r.rate_n_flags =
6411             LE_32(iwk_rate_to_plcp(rate) | masks);
6412 
6413 
6414         tx_beacon_p->config.tx_flags =
6415             LE_32(TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK);
6416 
6417         if (ic->ic_bss->in_tstamp.tsf != 0) {
6418                 sc->sc_ibss.ibss_beacon.syncbeacon = 1;
6419         } else {
6420                 if (ieee80211_beacon_update(ic, in,
6421                     &sc->sc_ibss.ibss_beacon.iwk_boff,
6422                     mp, 0)) {
6423                         bcopy(mp->b_rptr,
6424                             tx_beacon_p->bcon_frame,
6425                             MBLKL(mp));
6426                 }
6427 
6428                 err = iwk_cmd(sc, REPLY_TX_BEACON,
6429                     tx_beacon_p,
6430                     sc->sc_ibss.ibss_beacon.beacon_cmd_len,
6431                     1);
6432                 if (err != IWK_SUCCESS) {
6433                         cmn_err(CE_WARN, "iwk_start_tx_beacon(): "
6434                             "failed to TX beacon.\n");
6435                         return (err);
6436                 }
6437 
6438                 sc->sc_ibss.ibss_beacon.syncbeacon = 0;
6439         }
6440 
6441         return (err);
6442 }
6443 
6444 static int
6445 iwk_clean_add_node_ibss(struct ieee80211com *ic,
6446     uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2)
6447 {
6448         iwk_sc_t *sc = (iwk_sc_t *)ic;
6449         uint8_t index;
6450         iwk_add_sta_t bc_node;
6451         iwk_link_quality_cmd_t bc_link_quality;
6452         iwk_link_quality_cmd_t link_quality;
6453         uint16_t  bc_masks = 0;
6454         uint16_t  masks = 0;
6455         int i, rate;
6456         struct ieee80211_rateset rs;
6457         iwk_ibss_node_t *ibss_node_p;
6458         int err = IWK_SUCCESS;
6459 
6460         /*
6461          * find a location that is not
6462          * used in ibss node table
6463          */
6464         for (index = IWK_STA_ID;
6465             index < IWK_STATION_COUNT; index++) {
6466                 if (!sc->sc_ibss.ibss_node_tb[index].used) {
6467                         break;
6468                 }
6469         }
6470 
6471         /*
6472          * if have too many nodes in hardware, clean up
6473          */
6474         if (index < IWK_BROADCAST_ID &&
6475             sc->sc_ibss.node_number >= 25) {
6476                 if (iwk_cmd(sc, REPLY_REMOVE_ALL_STA,
6477                     NULL, 0, 1) != IWK_SUCCESS) {
6478                         cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
6479                             "failed to remove all nodes in hardware\n");
6480                         return (IWK_FAIL);
6481                 }
6482 
6483                 for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) {
6484                         sc->sc_ibss.ibss_node_tb[i].used = 0;
6485                         (void) memset(&sc->sc_ibss.ibss_node_tb[i].node,
6486                             0, sizeof (iwk_add_sta_t));
6487                 }
6488 
6489                 sc->sc_ibss.node_number = 0;
6490 
6491                 /*
6492                  * add broadcast node so that we
6493                  * can send broadcast frame
6494                  */
6495                 (void) memset(&bc_node, 0, sizeof (bc_node));
6496                 (void) memset(bc_node.bssid, 0xff, 6);
6497                 bc_node.id = IWK_BROADCAST_ID;
6498 
6499                 err = iwk_cmd(sc, REPLY_ADD_STA, &bc_node, sizeof (bc_node), 1);
6500                 if (err != IWK_SUCCESS) {
6501                 cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
6502                     "failed to add broadcast node\n");
6503                 return (err);
6504                 }
6505 
6506                 /* TX_LINK_QUALITY cmd */
6507                 (void) memset(&bc_link_quality, 0, sizeof (bc_link_quality));
6508                 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
6509                         bc_masks |= RATE_MCS_CCK_MSK;
6510                         bc_masks |= RATE_MCS_ANT_B_MSK;
6511                         bc_masks &= ~RATE_MCS_ANT_A_MSK;
6512                         bc_link_quality.rate_n_flags[i] =
6513                             LE_32(iwk_rate_to_plcp(2) | bc_masks);
6514                 }
6515 
6516                 bc_link_quality.general_params.single_stream_ant_msk = 2;
6517                 bc_link_quality.general_params.dual_stream_ant_msk = 3;
6518                 bc_link_quality.agg_params.agg_dis_start_th = 3;
6519                 bc_link_quality.agg_params.agg_time_limit = LE_16(4000);
6520                 bc_link_quality.sta_id = IWK_BROADCAST_ID;
6521 
6522                 err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD,
6523                     &bc_link_quality, sizeof (bc_link_quality), 1);
6524                 if (err != IWK_SUCCESS) {
6525                         cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
6526                             "failed to config link quality table\n");
6527                         return (err);
6528                 }
6529         }
6530 
6531         if (index >= IWK_BROADCAST_ID) {
6532                 cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
6533                     "the count of node in hardware is too much\n");
6534                 return (IWK_FAIL);
6535         }
6536 
6537         /*
6538          * add a node into hardware
6539          */
6540         ibss_node_p = &sc->sc_ibss.ibss_node_tb[index];
6541 
6542         ibss_node_p->used = 1;
6543 
6544         (void) memset(&ibss_node_p->node, 0,
6545             sizeof (iwk_add_sta_t));
6546 
6547         IEEE80211_ADDR_COPY(ibss_node_p->node.bssid, addr);
6548         ibss_node_p->node.id = index;
6549         ibss_node_p->node.control = 0;
6550         ibss_node_p->node.flags = 0;
6551 
6552         err = iwk_cmd(sc, REPLY_ADD_STA, &ibss_node_p->node,
6553             sizeof (iwk_add_sta_t), 1);
6554         if (err != IWK_SUCCESS) {
6555                 cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
6556                     "failed to add IBSS node\n");
6557                 ibss_node_p->used = 0;
6558                 (void) memset(&ibss_node_p->node, 0,
6559                     sizeof (iwk_add_sta_t));
6560                 return (err);
6561         }
6562 
6563         sc->sc_ibss.node_number++;
6564 
6565         (void) memset(&link_quality, 0, sizeof (link_quality));
6566 
6567         rs = ic->ic_sup_rates[ieee80211_chan2mode(ic,
6568             ic->ic_curchan)];
6569 
6570         for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
6571                 if (i < rs.ir_nrates) {
6572                         rate = rs.
6573                             ir_rates[rs.ir_nrates - i];
6574                 } else {
6575                         rate = 2;
6576                 }
6577 
6578                 if (2 == rate || 4 == rate ||
6579                     11 == rate || 22 == rate) {
6580                         masks |= RATE_MCS_CCK_MSK;
6581                 }
6582 
6583                 masks |= RATE_MCS_ANT_B_MSK;
6584                 masks &= ~RATE_MCS_ANT_A_MSK;
6585 
6586                 link_quality.rate_n_flags[i] =
6587                     LE_32(iwk_rate_to_plcp(rate) | masks);
6588         }
6589 
6590         link_quality.general_params.single_stream_ant_msk = 2;
6591         link_quality.general_params.dual_stream_ant_msk = 3;
6592         link_quality.agg_params.agg_dis_start_th = 3;
6593         link_quality.agg_params.agg_time_limit = LE_16(4000);
6594         link_quality.sta_id = ibss_node_p->node.id;
6595 
6596         err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD,
6597             &link_quality, sizeof (link_quality), 1);
6598         if (err != IWK_SUCCESS) {
6599                 cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
6600                     "failed to set up TX link quality\n");
6601                 ibss_node_p->used = 0;
6602                 (void) memset(ibss_node_p->node.bssid, 0, 6);
6603                 return (err);
6604         }
6605 
6606         *index2 = index;
6607 
6608         return (err);
6609 }