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