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