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