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