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