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.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 void iwh_amrr_init(iwh_amrr_t *); 299 static void iwh_amrr_timeout(iwh_sc_t *); 300 static void iwh_amrr_ratectl(void *, ieee80211_node_t *); 301 static void iwh_ucode_alive(iwh_sc_t *, iwh_rx_desc_t *); 302 static void iwh_rx_phy_intr(iwh_sc_t *, iwh_rx_desc_t *); 303 static void iwh_rx_mpdu_intr(iwh_sc_t *, iwh_rx_desc_t *); 304 static void iwh_release_calib_buffer(iwh_sc_t *); 305 static int iwh_init_common(iwh_sc_t *); 306 static uint8_t *iwh_eep_addr_trans(iwh_sc_t *, uint32_t); 307 static int iwh_put_seg_fw(iwh_sc_t *, uint32_t, uint32_t, uint32_t); 308 static int iwh_alive_common(iwh_sc_t *); 309 static void iwh_save_calib_result(iwh_sc_t *, iwh_rx_desc_t *); 310 static int iwh_tx_power_table(iwh_sc_t *, int); 311 static int iwh_attach(dev_info_t *, ddi_attach_cmd_t); 312 static int iwh_detach(dev_info_t *, ddi_detach_cmd_t); 313 static void iwh_destroy_locks(iwh_sc_t *); 314 static int iwh_send(ieee80211com_t *, mblk_t *, uint8_t); 315 static void iwh_thread(iwh_sc_t *); 316 /* 317 * GLD specific operations 318 */ 319 static int iwh_m_stat(void *, uint_t, uint64_t *); 320 static int iwh_m_start(void *); 321 static void iwh_m_stop(void *); 322 static int iwh_m_unicst(void *, const uint8_t *); 323 static int iwh_m_multicst(void *, boolean_t, const uint8_t *); 324 static int iwh_m_promisc(void *, boolean_t); 325 static mblk_t *iwh_m_tx(void *, mblk_t *); 326 static void iwh_m_ioctl(void *, queue_t *, mblk_t *); 327 328 /* 329 * Supported rates for 802.11b/g modes (in 500Kbps unit). 330 * 11n support will be added later. 331 */ 332 static const struct ieee80211_rateset iwh_rateset_11b = 333 { 4, { 2, 4, 11, 22 } }; 334 335 static const struct ieee80211_rateset iwh_rateset_11g = 336 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 337 338 /* 339 * For mfthread only 340 */ 341 extern pri_t minclsyspri; 342 343 #define DRV_NAME_SP "iwh" 344 345 /* 346 * Module Loading Data & Entry Points 347 */ 348 DDI_DEFINE_STREAM_OPS(iwh_devops, nulldev, nulldev, iwh_attach, 349 iwh_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_supported); 350 351 static struct modldrv iwh_modldrv = { 352 &mod_driverops, 353 "Intel(R) ShirleyPeak driver(N)", 354 &iwh_devops 355 }; 356 357 static struct modlinkage iwh_modlinkage = { 358 MODREV_1, 359 &iwh_modldrv, 360 NULL 361 }; 362 363 int 364 _init(void) 365 { 366 int status; 367 368 status = ddi_soft_state_init(&iwh_soft_state_p, 369 sizeof (iwh_sc_t), 1); 370 if (status != DDI_SUCCESS) { 371 return (status); 372 } 373 374 mac_init_ops(&iwh_devops, DRV_NAME_SP); 375 status = mod_install(&iwh_modlinkage); 376 if (status != DDI_SUCCESS) { 377 mac_fini_ops(&iwh_devops); 378 ddi_soft_state_fini(&iwh_soft_state_p); 379 } 380 381 return (status); 382 } 383 384 int 385 _fini(void) 386 { 387 int status; 388 389 status = mod_remove(&iwh_modlinkage); 390 if (DDI_SUCCESS == status) { 391 mac_fini_ops(&iwh_devops); 392 ddi_soft_state_fini(&iwh_soft_state_p); 393 } 394 395 return (status); 396 } 397 398 int 399 _info(struct modinfo *mip) 400 { 401 return (mod_info(&iwh_modlinkage, mip)); 402 } 403 404 /* 405 * Mac Call Back entries 406 */ 407 mac_callbacks_t iwh_m_callbacks = { 408 MC_IOCTL, 409 iwh_m_stat, 410 iwh_m_start, 411 iwh_m_stop, 412 iwh_m_promisc, 413 iwh_m_multicst, 414 iwh_m_unicst, 415 iwh_m_tx, 416 NULL, 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 for (i = 0; i < ring->count; i++) { 1560 data = &ring->data[i]; 1561 IWH_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV); 1562 } 1563 1564 ring->queued = 0; 1565 ring->cur = 0; 1566 } 1567 1568 static void 1569 iwh_free_tx_ring(iwh_tx_ring_t *ring) 1570 { 1571 int i; 1572 1573 if (ring->dma_desc.dma_hdl != NULL) { 1574 IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 1575 } 1576 iwh_free_dma_mem(&ring->dma_desc); 1577 1578 if (ring->dma_cmd.dma_hdl != NULL) { 1579 IWH_DMA_SYNC(ring->dma_cmd, DDI_DMA_SYNC_FORDEV); 1580 } 1581 iwh_free_dma_mem(&ring->dma_cmd); 1582 1583 if (ring->data != NULL) { 1584 for (i = 0; i < ring->count; i++) { 1585 if (ring->data[i].dma_data.dma_hdl) { 1586 IWH_DMA_SYNC(ring->data[i].dma_data, 1587 DDI_DMA_SYNC_FORDEV); 1588 } 1589 iwh_free_dma_mem(&ring->data[i].dma_data); 1590 } 1591 kmem_free(ring->data, ring->count * sizeof (iwh_tx_data_t)); 1592 } 1593 } 1594 1595 /* 1596 * initialize TX and RX ring 1597 */ 1598 static int 1599 iwh_ring_init(iwh_sc_t *sc) 1600 { 1601 int i, err = DDI_SUCCESS; 1602 1603 for (i = 0; i < IWH_NUM_QUEUES; i++) { 1604 if (IWH_CMD_QUEUE_NUM == i) { 1605 continue; 1606 } 1607 1608 err = iwh_alloc_tx_ring(sc, &sc->sc_txq[i], TFD_TX_CMD_SLOTS, 1609 i); 1610 if (err != DDI_SUCCESS) { 1611 goto fail; 1612 } 1613 } 1614 1615 /* 1616 * initialize command queue 1617 */ 1618 err = iwh_alloc_tx_ring(sc, &sc->sc_txq[IWH_CMD_QUEUE_NUM], 1619 TFD_CMD_SLOTS, IWH_CMD_QUEUE_NUM); 1620 if (err != DDI_SUCCESS) { 1621 goto fail; 1622 } 1623 1624 err = iwh_alloc_rx_ring(sc); 1625 if (err != DDI_SUCCESS) { 1626 goto fail; 1627 } 1628 1629 return (err); 1630 1631 fail: 1632 return (err); 1633 } 1634 1635 static void 1636 iwh_ring_free(iwh_sc_t *sc) 1637 { 1638 int i = IWH_NUM_QUEUES; 1639 1640 iwh_free_rx_ring(sc); 1641 while (--i >= 0) { 1642 iwh_free_tx_ring(&sc->sc_txq[i]); 1643 } 1644 } 1645 1646 /* 1647 * allocate buffer for a node 1648 */ 1649 /*ARGSUSED*/ 1650 static ieee80211_node_t * 1651 iwh_node_alloc(ieee80211com_t *ic) 1652 { 1653 iwh_amrr_t *amrr; 1654 1655 amrr = kmem_zalloc(sizeof (iwh_amrr_t), KM_SLEEP); 1656 if (amrr != NULL) { 1657 iwh_amrr_init(amrr); 1658 } 1659 1660 return (&amrr->in); 1661 } 1662 1663 static void 1664 iwh_node_free(ieee80211_node_t *in) 1665 { 1666 ieee80211com_t *ic = in->in_ic; 1667 1668 ic->ic_node_cleanup(in); 1669 if (in->in_wpa_ie != NULL) { 1670 ieee80211_free(in->in_wpa_ie); 1671 } 1672 1673 kmem_free(in, sizeof (iwh_amrr_t)); 1674 } 1675 1676 /* 1677 * change station's state. this function will be invoked by 80211 module 1678 * when need to change staton's state. 1679 */ 1680 static int 1681 iwh_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg) 1682 { 1683 iwh_sc_t *sc = (iwh_sc_t *)ic; 1684 ieee80211_node_t *in = ic->ic_bss; 1685 enum ieee80211_state ostate = ic->ic_state; 1686 int i, err = IWH_SUCCESS; 1687 1688 mutex_enter(&sc->sc_glock); 1689 1690 switch (nstate) { 1691 case IEEE80211_S_SCAN: 1692 switch (ostate) { 1693 case IEEE80211_S_INIT: 1694 { 1695 iwh_add_sta_t node; 1696 sc->sc_flags |= IWH_F_SCANNING; 1697 iwh_set_led(sc, 2, 10, 2); 1698 1699 /* 1700 * clear association to receive beacons from 1701 * all BSS'es 1702 */ 1703 sc->sc_config.assoc_id = 0; 1704 sc->sc_config.filter_flags &= 1705 ~LE_32(RXON_FILTER_ASSOC_MSK); 1706 1707 IWH_DBG((IWH_DEBUG_80211, "config chan %d " 1708 "flags %x filter_flags %x\n", sc->sc_config.chan, 1709 sc->sc_config.flags, sc->sc_config.filter_flags)); 1710 1711 err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config, 1712 sizeof (iwh_rxon_cmd_t), 1); 1713 if (err != IWH_SUCCESS) { 1714 cmn_err(CE_WARN, 1715 "could not clear association\n"); 1716 sc->sc_flags &= ~IWH_F_SCANNING; 1717 mutex_exit(&sc->sc_glock); 1718 return (err); 1719 } 1720 1721 /* add broadcast node to send probe request */ 1722 (void) memset(&node, 0, sizeof (node)); 1723 (void) memset(&node.sta.addr, 0xff, IEEE80211_ADDR_LEN); 1724 node.sta.sta_id = IWH_BROADCAST_ID; 1725 err = iwh_cmd(sc, REPLY_ADD_STA, &node, 1726 sizeof (node), 1); 1727 if (err != IWH_SUCCESS) { 1728 cmn_err(CE_WARN, "could not add " 1729 "broadcast node\n"); 1730 sc->sc_flags &= ~IWH_F_SCANNING; 1731 mutex_exit(&sc->sc_glock); 1732 return (err); 1733 } 1734 break; 1735 } 1736 case IEEE80211_S_SCAN: 1737 mutex_exit(&sc->sc_glock); 1738 /* step to next channel before actual FW scan */ 1739 err = sc->sc_newstate(ic, nstate, arg); 1740 mutex_enter(&sc->sc_glock); 1741 if ((err != 0) || ((err = iwh_scan(sc)) != 0)) { 1742 cmn_err(CE_WARN, 1743 "could not initiate scan\n"); 1744 sc->sc_flags &= ~IWH_F_SCANNING; 1745 ieee80211_cancel_scan(ic); 1746 } 1747 mutex_exit(&sc->sc_glock); 1748 return (err); 1749 default: 1750 break; 1751 } 1752 sc->sc_clk = 0; 1753 break; 1754 1755 case IEEE80211_S_AUTH: 1756 if (ostate == IEEE80211_S_SCAN) { 1757 sc->sc_flags &= ~IWH_F_SCANNING; 1758 } 1759 1760 /* 1761 * reset state to handle reassociations correctly 1762 */ 1763 sc->sc_config.assoc_id = 0; 1764 sc->sc_config.filter_flags &= ~LE_32(RXON_FILTER_ASSOC_MSK); 1765 1766 /* 1767 * before sending authentication and association request frame, 1768 * we need do something in the hardware, such as setting the 1769 * channel same to the target AP... 1770 */ 1771 if ((err = iwh_hw_set_before_auth(sc)) != 0) { 1772 IWH_DBG((IWH_DEBUG_80211, 1773 "could not send authentication request\n")); 1774 mutex_exit(&sc->sc_glock); 1775 return (err); 1776 } 1777 break; 1778 1779 case IEEE80211_S_RUN: 1780 if (ostate == IEEE80211_S_SCAN) { 1781 sc->sc_flags &= ~IWH_F_SCANNING; 1782 } 1783 1784 if (IEEE80211_M_MONITOR == ic->ic_opmode) { 1785 /* let LED blink when monitoring */ 1786 iwh_set_led(sc, 2, 10, 10); 1787 break; 1788 } 1789 1790 IWH_DBG((IWH_DEBUG_80211, "iwh: associated.")); 1791 1792 /* 1793 * update adapter's configuration 1794 */ 1795 if (sc->sc_assoc_id != in->in_associd) { 1796 cmn_err(CE_WARN, 1797 "associate ID mismatch: expected %d, " 1798 "got %d\n", 1799 in->in_associd, sc->sc_assoc_id); 1800 } 1801 sc->sc_config.assoc_id = in->in_associd & 0x3fff; 1802 1803 /* 1804 * short preamble/slot time are 1805 * negotiated when associating 1806 */ 1807 sc->sc_config.flags &= 1808 ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK | 1809 RXON_FLG_SHORT_SLOT_MSK); 1810 1811 if (ic->ic_flags & IEEE80211_F_SHSLOT) { 1812 sc->sc_config.flags |= 1813 LE_32(RXON_FLG_SHORT_SLOT_MSK); 1814 } 1815 1816 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) { 1817 sc->sc_config.flags |= 1818 LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 1819 } 1820 1821 sc->sc_config.filter_flags |= 1822 LE_32(RXON_FILTER_ASSOC_MSK); 1823 1824 if (ic->ic_opmode != IEEE80211_M_STA) { 1825 sc->sc_config.filter_flags |= 1826 LE_32(RXON_FILTER_BCON_AWARE_MSK); 1827 } 1828 1829 IWH_DBG((IWH_DEBUG_80211, "config chan %d flags %x" 1830 " filter_flags %x\n", 1831 sc->sc_config.chan, sc->sc_config.flags, 1832 sc->sc_config.filter_flags)); 1833 1834 err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config, 1835 sizeof (iwh_rxon_cmd_t), 1); 1836 if (err != IWH_SUCCESS) { 1837 IWH_DBG((IWH_DEBUG_80211, 1838 "could not update configuration\n")); 1839 mutex_exit(&sc->sc_glock); 1840 return (err); 1841 } 1842 1843 /* 1844 * send tx power talbe command 1845 */ 1846 err = iwh_tx_power_table(sc, 1); 1847 if (err != IWH_SUCCESS) { 1848 cmn_err(CE_WARN, "iwh_config(): " 1849 "failed to set tx power table.\n"); 1850 return (err); 1851 } 1852 1853 /* 1854 * start automatic rate control 1855 */ 1856 mutex_enter(&sc->sc_mt_lock); 1857 if (IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) { 1858 sc->sc_flags |= IWH_F_RATE_AUTO_CTL; 1859 /* 1860 * set rate to some reasonable initial value 1861 */ 1862 i = in->in_rates.ir_nrates - 1; 1863 while (i > 0 && IEEE80211_RATE(i) > 72) { 1864 i--; 1865 } 1866 in->in_txrate = i; 1867 } else { 1868 sc->sc_flags &= ~IWH_F_RATE_AUTO_CTL; 1869 } 1870 1871 mutex_exit(&sc->sc_mt_lock); 1872 1873 /* 1874 * set LED on after associated 1875 */ 1876 iwh_set_led(sc, 2, 0, 1); 1877 break; 1878 1879 case IEEE80211_S_INIT: 1880 if (ostate == IEEE80211_S_SCAN) { 1881 sc->sc_flags &= ~IWH_F_SCANNING; 1882 } 1883 /* 1884 * set LED off after init 1885 */ 1886 iwh_set_led(sc, 2, 1, 0); 1887 break; 1888 1889 case IEEE80211_S_ASSOC: 1890 if (ostate == IEEE80211_S_SCAN) { 1891 sc->sc_flags &= ~IWH_F_SCANNING; 1892 } 1893 break; 1894 } 1895 1896 mutex_exit(&sc->sc_glock); 1897 1898 return (sc->sc_newstate(ic, nstate, arg)); 1899 } 1900 1901 /* 1902 * exclusive access to mac begin. 1903 */ 1904 static void 1905 iwh_mac_access_enter(iwh_sc_t *sc) 1906 { 1907 uint32_t tmp; 1908 int n; 1909 1910 tmp = IWH_READ(sc, CSR_GP_CNTRL); 1911 IWH_WRITE(sc, CSR_GP_CNTRL, 1912 tmp | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1913 1914 /* wait until we succeed */ 1915 for (n = 0; n < 1000; n++) { 1916 if ((IWH_READ(sc, CSR_GP_CNTRL) & 1917 (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | 1918 CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP)) == 1919 CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN) { 1920 break; 1921 } 1922 DELAY(10); 1923 } 1924 1925 #ifdef DEBUG 1926 if (1000 == n) { 1927 IWH_DBG((IWH_DEBUG_PIO, "could not lock memory\n")); 1928 } 1929 #endif 1930 } 1931 1932 /* 1933 * exclusive access to mac end. 1934 */ 1935 static void 1936 iwh_mac_access_exit(iwh_sc_t *sc) 1937 { 1938 uint32_t tmp = IWH_READ(sc, CSR_GP_CNTRL); 1939 IWH_WRITE(sc, CSR_GP_CNTRL, 1940 tmp & ~CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1941 } 1942 1943 /* 1944 * this function defined here for future use. 1945 * static uint32_t 1946 * iwh_mem_read(iwh_sc_t *sc, uint32_t addr) 1947 * { 1948 * IWH_WRITE(sc, HBUS_TARG_MEM_RADDR, addr); 1949 * return (IWH_READ(sc, HBUS_TARG_MEM_RDAT)); 1950 * } 1951 */ 1952 1953 /* 1954 * write mac memory 1955 */ 1956 static void 1957 iwh_mem_write(iwh_sc_t *sc, uint32_t addr, uint32_t data) 1958 { 1959 IWH_WRITE(sc, HBUS_TARG_MEM_WADDR, addr); 1960 IWH_WRITE(sc, HBUS_TARG_MEM_WDAT, data); 1961 } 1962 1963 /* 1964 * read mac register 1965 */ 1966 static uint32_t 1967 iwh_reg_read(iwh_sc_t *sc, uint32_t addr) 1968 { 1969 IWH_WRITE(sc, HBUS_TARG_PRPH_RADDR, addr | (3 << 24)); 1970 return (IWH_READ(sc, HBUS_TARG_PRPH_RDAT)); 1971 } 1972 1973 /* 1974 * write mac register 1975 */ 1976 static void 1977 iwh_reg_write(iwh_sc_t *sc, uint32_t addr, uint32_t data) 1978 { 1979 IWH_WRITE(sc, HBUS_TARG_PRPH_WADDR, addr | (3 << 24)); 1980 IWH_WRITE(sc, HBUS_TARG_PRPH_WDAT, data); 1981 } 1982 1983 1984 /* 1985 * steps of loading ucode: 1986 * load init ucode=>init alive=>calibrate=> 1987 * receive calibration result=>reinitialize NIC=> 1988 * load runtime ucode=>runtime alive=> 1989 * send calibration result=>running. 1990 */ 1991 static int 1992 iwh_load_init_firmware(iwh_sc_t *sc) 1993 { 1994 int err; 1995 clock_t clk; 1996 1997 sc->sc_flags &= ~IWH_F_PUT_SEG; 1998 1999 /* 2000 * load init_text section of uCode to hardware 2001 */ 2002 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_init_text.cookie.dmac_address, 2003 RTC_INST_LOWER_BOUND, sc->sc_dma_fw_init_text.cookie.dmac_size); 2004 if (err != IWH_SUCCESS) { 2005 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2006 "failed to write init uCode.\n"); 2007 return (err); 2008 } 2009 2010 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2011 2012 /* wait loading init_text until completed or timeout */ 2013 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2014 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2015 break; 2016 } 2017 } 2018 2019 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2020 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2021 "timeout waiting for init uCode load.\n"); 2022 return (IWH_FAIL); 2023 } 2024 2025 sc->sc_flags &= ~IWH_F_PUT_SEG; 2026 2027 /* 2028 * load init_data section of uCode to hardware 2029 */ 2030 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_init_data.cookie.dmac_address, 2031 RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_init_data.cookie.dmac_size); 2032 if (err != IWH_SUCCESS) { 2033 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2034 "failed to write init_data uCode.\n"); 2035 return (err); 2036 } 2037 2038 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2039 2040 /* 2041 * wait loading init_data until completed or timeout 2042 */ 2043 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2044 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2045 break; 2046 } 2047 } 2048 2049 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2050 cmn_err(CE_WARN, "iwh_load_init_firmware(): " 2051 "timeout waiting for init_data uCode load.\n"); 2052 return (IWH_FAIL); 2053 } 2054 2055 sc->sc_flags &= ~IWH_F_PUT_SEG; 2056 2057 return (err); 2058 } 2059 2060 static int 2061 iwh_load_run_firmware(iwh_sc_t *sc) 2062 { 2063 int err; 2064 clock_t clk; 2065 2066 sc->sc_flags &= ~IWH_F_PUT_SEG; 2067 2068 /* 2069 * load init_text section of uCode to hardware 2070 */ 2071 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_text.cookie.dmac_address, 2072 RTC_INST_LOWER_BOUND, sc->sc_dma_fw_text.cookie.dmac_size); 2073 if (err != IWH_SUCCESS) { 2074 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2075 "failed to write run uCode.\n"); 2076 return (err); 2077 } 2078 2079 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2080 2081 /* wait loading run_text until completed or timeout */ 2082 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2083 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2084 break; 2085 } 2086 } 2087 2088 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2089 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2090 "timeout waiting for run uCode load.\n"); 2091 return (IWH_FAIL); 2092 } 2093 2094 sc->sc_flags &= ~IWH_F_PUT_SEG; 2095 2096 /* 2097 * load run_data section of uCode to hardware 2098 */ 2099 err = iwh_put_seg_fw(sc, sc->sc_dma_fw_data_bak.cookie.dmac_address, 2100 RTC_DATA_LOWER_BOUND, sc->sc_dma_fw_data.cookie.dmac_size); 2101 if (err != IWH_SUCCESS) { 2102 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2103 "failed to write run_data uCode.\n"); 2104 return (err); 2105 } 2106 2107 clk = ddi_get_lbolt() + drv_usectohz(1000000); 2108 2109 /* 2110 * wait loading run_data until completed or timeout 2111 */ 2112 while (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2113 if (cv_timedwait(&sc->sc_put_seg_cv, &sc->sc_glock, clk) < 0) { 2114 break; 2115 } 2116 } 2117 2118 if (!(sc->sc_flags & IWH_F_PUT_SEG)) { 2119 cmn_err(CE_WARN, "iwh_load_run_firmware(): " 2120 "timeout waiting for run_data uCode load.\n"); 2121 return (IWH_FAIL); 2122 } 2123 2124 sc->sc_flags &= ~IWH_F_PUT_SEG; 2125 2126 return (err); 2127 } 2128 2129 /* 2130 * this function will be invoked to receive phy information 2131 * when a frame is received. 2132 */ 2133 static void 2134 iwh_rx_phy_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2135 { 2136 2137 sc->sc_rx_phy_res.flag = 1; 2138 2139 (void) memcpy(sc->sc_rx_phy_res.buf, (uint8_t *)(desc + 1), 2140 sizeof (iwh_rx_phy_res_t)); 2141 } 2142 2143 /* 2144 * this function will be invoked to receive body of frame when 2145 * a frame is received. 2146 */ 2147 static void 2148 iwh_rx_mpdu_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2149 { 2150 ieee80211com_t *ic = &sc->sc_ic; 2151 #ifdef DEBUG 2152 iwh_rx_ring_t *ring = &sc->sc_rxq; 2153 #endif 2154 iwh_rx_phy_res_t *stat; 2155 ieee80211_node_t *in; 2156 uint32_t *tail; 2157 struct ieee80211_frame *wh; 2158 mblk_t *mp; 2159 uint16_t len, rssi, agc; 2160 int16_t t; 2161 struct iwh_rx_non_cfg_phy *phyinfo; 2162 uint32_t temp; 2163 uint32_t arssi, brssi, crssi, mrssi; 2164 struct iwh_rx_mpdu_body_size *mpdu_size; 2165 2166 /* 2167 * assuming not 11n here. cope with 11n in phase-II 2168 */ 2169 mpdu_size = (struct iwh_rx_mpdu_body_size *)(desc + 1); 2170 stat = (iwh_rx_phy_res_t *)sc->sc_rx_phy_res.buf; 2171 if (stat->cfg_phy_cnt > 20) { 2172 return; 2173 } 2174 2175 phyinfo = (struct iwh_rx_non_cfg_phy *)stat->non_cfg_phy; 2176 temp = phyinfo->non_cfg_phy[IWH_RX_RES_AGC_IDX]; 2177 agc = (temp & IWH_OFDM_AGC_MSK) >> IWH_OFDM_AGC_BIT_POS; 2178 2179 temp = phyinfo->non_cfg_phy[IWH_RX_RES_RSSI_AB_IDX]; 2180 arssi = (temp & IWH_OFDM_RSSI_A_MSK) >> IWH_OFDM_RSSI_A_BIT_POS; 2181 brssi = (temp & IWH_OFDM_RSSI_B_MSK) >> IWH_OFDM_RSSI_B_BIT_POS; 2182 2183 temp = phyinfo->non_cfg_phy[IWH_RX_RES_RSSI_C_IDX]; 2184 crssi = (temp & IWH_OFDM_RSSI_C_MSK) >> IWH_OFDM_RSSI_C_BIT_POS; 2185 2186 mrssi = MAX(arssi, brssi); 2187 mrssi = MAX(mrssi, crssi); 2188 2189 t = mrssi - agc - IWH_RSSI_OFFSET; 2190 /* 2191 * convert dBm to percentage 2192 */ 2193 rssi = (100 * 75 * 75 - (-20 - t) * (15 * 75 + 62 * (-20 - t))) 2194 / (75 * 75); 2195 if (rssi > 100) { 2196 rssi = 100; 2197 } 2198 if (rssi < 1) { 2199 rssi = 1; 2200 } 2201 2202 /* 2203 * size of frame, not include FCS 2204 */ 2205 len = mpdu_size->byte_count; 2206 tail = (uint32_t *)((uint8_t *)(desc + 1) + 2207 sizeof (struct iwh_rx_mpdu_body_size) + len); 2208 2209 2210 IWH_DBG((IWH_DEBUG_RX, "rx intr: idx=%d phy_len=%x len=%d " 2211 "rate=%x chan=%d tstamp=%x non_cfg_phy_count=%x " 2212 "cfg_phy_count=%x tail=%x", ring->cur, sizeof (*stat), 2213 len, stat->rate.r.s.rate, stat->channel, 2214 LE_32(stat->timestampl), stat->non_cfg_phy_cnt, 2215 stat->cfg_phy_cnt, LE_32(*tail))); 2216 2217 if ((len < 16) || (len > sc->sc_dmabuf_sz)) { 2218 IWH_DBG((IWH_DEBUG_RX, "rx frame oversize\n")); 2219 return; 2220 } 2221 2222 /* 2223 * discard Rx frames with bad CRC 2224 */ 2225 if ((LE_32(*tail) & 2226 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) != 2227 (RX_RES_STATUS_NO_CRC32_ERROR | RX_RES_STATUS_NO_RXE_OVERFLOW)) { 2228 IWH_DBG((IWH_DEBUG_RX, "rx crc error tail: %x\n", 2229 LE_32(*tail))); 2230 sc->sc_rx_err++; 2231 return; 2232 } 2233 2234 wh = (struct ieee80211_frame *) 2235 ((uint8_t *)(desc + 1)+ sizeof (struct iwh_rx_mpdu_body_size)); 2236 2237 if (IEEE80211_FC0_SUBTYPE_ASSOC_RESP == *(uint8_t *)wh) { 2238 sc->sc_assoc_id = *((uint16_t *)(wh + 1) + 2); 2239 IWH_DBG((IWH_DEBUG_RX, "rx : association id = %x\n", 2240 sc->sc_assoc_id)); 2241 } 2242 2243 #ifdef DEBUG 2244 if (iwh_dbg_flags & IWH_DEBUG_RX) { 2245 ieee80211_dump_pkt((uint8_t *)wh, len, 0, 0); 2246 } 2247 #endif 2248 2249 in = ieee80211_find_rxnode(ic, wh); 2250 mp = allocb(len, BPRI_MED); 2251 if (mp) { 2252 (void) memcpy(mp->b_wptr, wh, len); 2253 mp->b_wptr += len; 2254 2255 /* 2256 * send the frame to the 802.11 layer 2257 */ 2258 (void) ieee80211_input(ic, mp, in, rssi, 0); 2259 } else { 2260 sc->sc_rx_nobuf++; 2261 IWH_DBG((IWH_DEBUG_RX, 2262 "iwh_rx_mpdu_intr(): alloc rx buf failed\n")); 2263 } 2264 2265 /* 2266 * release node reference 2267 */ 2268 ieee80211_free_node(in); 2269 } 2270 2271 /* 2272 * process correlative affairs after a frame is sent. 2273 */ 2274 static void 2275 iwh_tx_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2276 { 2277 ieee80211com_t *ic = &sc->sc_ic; 2278 iwh_tx_ring_t *ring = &sc->sc_txq[desc->hdr.qid & 0x3]; 2279 iwh_tx_stat_t *stat = (iwh_tx_stat_t *)(desc + 1); 2280 iwh_amrr_t *amrr = (iwh_amrr_t *)ic->ic_bss; 2281 2282 amrr->txcnt++; 2283 IWH_DBG((IWH_DEBUG_RATECTL, "tx: %d cnt\n", amrr->txcnt)); 2284 2285 if (stat->ntries > 0) { 2286 amrr->retrycnt++; 2287 sc->sc_tx_retries++; 2288 IWH_DBG((IWH_DEBUG_TX, "tx: %d retries\n", 2289 sc->sc_tx_retries)); 2290 } 2291 2292 sc->sc_tx_timer = 0; 2293 2294 mutex_enter(&sc->sc_tx_lock); 2295 2296 ring->queued--; 2297 if (ring->queued < 0) { 2298 ring->queued = 0; 2299 } 2300 2301 if ((sc->sc_need_reschedule) && (ring->queued <= (ring->count << 3))) { 2302 sc->sc_need_reschedule = 0; 2303 mutex_exit(&sc->sc_tx_lock); 2304 mac_tx_update(ic->ic_mach); 2305 mutex_enter(&sc->sc_tx_lock); 2306 } 2307 2308 mutex_exit(&sc->sc_tx_lock); 2309 } 2310 2311 /* 2312 * inform a given command has been executed 2313 */ 2314 static void 2315 iwh_cmd_intr(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2316 { 2317 if ((desc->hdr.qid & 7) != 4) { 2318 return; 2319 } 2320 2321 mutex_enter(&sc->sc_glock); 2322 2323 sc->sc_flags |= IWH_F_CMD_DONE; 2324 cv_signal(&sc->sc_cmd_cv); 2325 2326 mutex_exit(&sc->sc_glock); 2327 2328 IWH_DBG((IWH_DEBUG_CMD, "rx cmd: " 2329 "qid=%x idx=%d flags=%x type=0x%x\n", 2330 desc->hdr.qid, desc->hdr.idx, desc->hdr.flags, 2331 desc->hdr.type)); 2332 } 2333 2334 /* 2335 * this function will be invoked when alive notification occur. 2336 */ 2337 static void 2338 iwh_ucode_alive(iwh_sc_t *sc, iwh_rx_desc_t *desc) 2339 { 2340 uint32_t rv; 2341 struct iwh_calib_cfg_cmd cmd; 2342 struct iwh_alive_resp *ar = 2343 (struct iwh_alive_resp *)(desc + 1); 2344 struct iwh_calib_results *res_p = &sc->sc_calib_results; 2345 2346 /* 2347 * the microcontroller is ready 2348 */ 2349 IWH_DBG((IWH_DEBUG_FW, 2350 "microcode alive notification minor: %x major: %x type:" 2351 " %x subtype: %x\n", 2352 ar->ucode_minor, ar->ucode_minor, ar->ver_type, ar->ver_subtype)); 2353 2354 #ifdef DEBUG 2355 if (LE_32(ar->is_valid) != UCODE_VALID_OK) { 2356 IWH_DBG((IWH_DEBUG_FW, 2357 "microcontroller initialization failed\n")); 2358 } 2359 #endif 2360 2361 /* 2362 * determine if init alive or runtime alive. 2363 */ 2364 if (INITIALIZE_SUBTYPE == ar->ver_subtype) { 2365 IWH_DBG((IWH_DEBUG_FW, 2366 "initialization alive received.\n")); 2367 2368 (void) memcpy(&sc->sc_card_alive_init, ar, 2369 sizeof (struct iwh_init_alive_resp)); 2370 2371 /* 2372 * necessary configuration to NIC 2373 */ 2374 mutex_enter(&sc->sc_glock); 2375 2376 rv = iwh_alive_common(sc); 2377 if (rv != IWH_SUCCESS) { 2378 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2379 "common alive process failed in init alive.\n"); 2380 mutex_exit(&sc->sc_glock); 2381 return; 2382 } 2383 2384 (void) memset(&cmd, 0, sizeof (cmd)); 2385 2386 cmd.ucd_calib_cfg.once.is_enable = IWH_CALIB_INIT_CFG_ALL; 2387 cmd.ucd_calib_cfg.once.start = IWH_CALIB_INIT_CFG_ALL; 2388 cmd.ucd_calib_cfg.once.send_res = IWH_CALIB_INIT_CFG_ALL; 2389 cmd.ucd_calib_cfg.flags = IWH_CALIB_INIT_CFG_ALL; 2390 2391 /* 2392 * require ucode execute calibration 2393 */ 2394 rv = iwh_cmd(sc, CALIBRATION_CFG_CMD, &cmd, sizeof (cmd), 1); 2395 if (rv != IWH_SUCCESS) { 2396 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2397 "failed to send calibration configure command.\n"); 2398 mutex_exit(&sc->sc_glock); 2399 return; 2400 } 2401 2402 mutex_exit(&sc->sc_glock); 2403 2404 } else { /* runtime alive */ 2405 2406 IWH_DBG((IWH_DEBUG_FW, "runtime alive received.\n")); 2407 2408 (void) memcpy(&sc->sc_card_alive_run, ar, 2409 sizeof (struct iwh_alive_resp)); 2410 2411 mutex_enter(&sc->sc_glock); 2412 2413 /* 2414 * necessary configuration to NIC 2415 */ 2416 rv = iwh_alive_common(sc); 2417 if (rv != IWH_SUCCESS) { 2418 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2419 "common alive process failed in run alive.\n"); 2420 mutex_exit(&sc->sc_glock); 2421 return; 2422 } 2423 2424 /* 2425 * send the result of local oscilator calibration to uCode. 2426 */ 2427 if (res_p->lo_res != NULL) { 2428 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, 2429 res_p->lo_res, res_p->lo_res_len, 1); 2430 if (rv != IWH_SUCCESS) { 2431 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2432 "failed to send local" 2433 "oscilator calibration command.\n"); 2434 mutex_exit(&sc->sc_glock); 2435 return; 2436 } 2437 2438 DELAY(1000); 2439 } 2440 2441 /* 2442 * send the result of TX IQ calibration to uCode. 2443 */ 2444 if (res_p->tx_iq_res != NULL) { 2445 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, 2446 res_p->tx_iq_res, res_p->tx_iq_res_len, 1); 2447 if (rv != IWH_SUCCESS) { 2448 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2449 "failed to send TX IQ" 2450 "calibration command.\n"); 2451 mutex_exit(&sc->sc_glock); 2452 return; 2453 } 2454 2455 DELAY(1000); 2456 } 2457 2458 /* 2459 * sned the result of TX IQ perd calibration to uCode. 2460 */ 2461 if (res_p->tx_iq_perd_res != NULL) { 2462 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, 2463 res_p->tx_iq_perd_res, 2464 res_p->tx_iq_perd_res_len, 1); 2465 if (rv != IWH_SUCCESS) { 2466 cmn_err(CE_WARN, "iwh_ucode_alive(): " 2467 "failed to send TX IQ perd" 2468 "calibration command.\n"); 2469 mutex_exit(&sc->sc_glock); 2470 return; 2471 } 2472 2473 DELAY(1000); 2474 } 2475 2476 mutex_exit(&sc->sc_glock); 2477 2478 sc->sc_flags |= IWH_F_FW_INIT; 2479 cv_signal(&sc->sc_ucode_cv); 2480 } 2481 2482 } 2483 2484 /* 2485 * deal with receiving frames, command response 2486 * and all notifications from ucode. 2487 */ 2488 static uint_t 2489 /* LINTED: argument unused in function: unused */ 2490 iwh_rx_softintr(caddr_t arg, caddr_t unused) 2491 { 2492 iwh_sc_t *sc = (iwh_sc_t *)arg; 2493 ieee80211com_t *ic = &sc->sc_ic; 2494 iwh_rx_desc_t *desc; 2495 iwh_rx_data_t *data; 2496 uint32_t index; 2497 2498 mutex_enter(&sc->sc_glock); 2499 2500 if (sc->sc_rx_softint_pending != 1) { 2501 mutex_exit(&sc->sc_glock); 2502 return (DDI_INTR_UNCLAIMED); 2503 } 2504 2505 /* 2506 * disable interrupts 2507 */ 2508 IWH_WRITE(sc, CSR_INT_MASK, 0); 2509 2510 mutex_exit(&sc->sc_glock); 2511 2512 /* 2513 * firmware has moved the index of the rx queue, driver get it, 2514 * and deal with it. 2515 */ 2516 index = LE_32(sc->sc_shared->val0) & 0xfff; 2517 2518 while (sc->sc_rxq.cur != index) { 2519 data = &sc->sc_rxq.data[sc->sc_rxq.cur]; 2520 desc = (iwh_rx_desc_t *)data->dma_data.mem_va; 2521 2522 IWH_DBG((IWH_DEBUG_INTR, "rx notification index = %d" 2523 " cur = %d qid=%x idx=%d flags=%x type=%x len=%d\n", 2524 index, sc->sc_rxq.cur, desc->hdr.qid, desc->hdr.idx, 2525 desc->hdr.flags, desc->hdr.type, LE_32(desc->len))); 2526 2527 /* 2528 * a command other than a tx need to be replied 2529 */ 2530 if (!(desc->hdr.qid & 0x80) && 2531 (desc->hdr.type != REPLY_RX_PHY_CMD) && 2532 (desc->hdr.type != REPLY_RX_MPDU_CMD) && 2533 (desc->hdr.type != REPLY_TX) && 2534 (desc->hdr.type != REPLY_PHY_CALIBRATION_CMD)) { 2535 iwh_cmd_intr(sc, desc); 2536 } 2537 2538 switch (desc->hdr.type) { 2539 case REPLY_RX_PHY_CMD: 2540 iwh_rx_phy_intr(sc, desc); 2541 break; 2542 2543 case REPLY_RX_MPDU_CMD: 2544 iwh_rx_mpdu_intr(sc, desc); 2545 break; 2546 2547 case REPLY_TX: 2548 iwh_tx_intr(sc, desc); 2549 break; 2550 2551 case REPLY_ALIVE: 2552 iwh_ucode_alive(sc, desc); 2553 break; 2554 2555 case CARD_STATE_NOTIFICATION: 2556 { 2557 uint32_t *status = (uint32_t *)(desc + 1); 2558 2559 IWH_DBG((IWH_DEBUG_RADIO, "state changed to %x\n", 2560 LE_32(*status))); 2561 2562 if (LE_32(*status) & 1) { 2563 /* 2564 * the radio button has to be pushed(OFF). It 2565 * is considered as a hw error, the 2566 * iwh_thread() tries to recover it after the 2567 * button is pushed again(ON) 2568 */ 2569 cmn_err(CE_WARN, "iwh_rx_softintr(): " 2570 "radio transmitter is off\n"); 2571 sc->sc_ostate = sc->sc_ic.ic_state; 2572 ieee80211_new_state(&sc->sc_ic, 2573 IEEE80211_S_INIT, -1); 2574 sc->sc_flags |= 2575 (IWH_F_HW_ERR_RECOVER | IWH_F_RADIO_OFF); 2576 } 2577 break; 2578 } 2579 2580 case SCAN_START_NOTIFICATION: 2581 { 2582 iwh_start_scan_t *scan = 2583 (iwh_start_scan_t *)(desc + 1); 2584 2585 IWH_DBG((IWH_DEBUG_SCAN, 2586 "scanning channel %d status %x\n", 2587 scan->chan, LE_32(scan->status))); 2588 2589 ic->ic_curchan = &ic->ic_sup_channels[scan->chan]; 2590 break; 2591 } 2592 2593 case SCAN_COMPLETE_NOTIFICATION: 2594 { 2595 iwh_stop_scan_t *scan = 2596 (iwh_stop_scan_t *)(desc + 1); 2597 2598 IWH_DBG((IWH_DEBUG_SCAN, 2599 "completed channel %d (burst of %d) status %02x\n", 2600 scan->chan, scan->nchan, scan->status)); 2601 2602 sc->sc_scan_pending++; 2603 break; 2604 } 2605 2606 case STATISTICS_NOTIFICATION: 2607 { 2608 /* 2609 * handle statistics notification 2610 */ 2611 break; 2612 } 2613 2614 case CALIBRATION_RES_NOTIFICATION: 2615 iwh_save_calib_result(sc, desc); 2616 break; 2617 2618 case CALIBRATION_COMPLETE_NOTIFICATION: 2619 sc->sc_flags |= IWH_F_FW_INIT; 2620 cv_signal(&sc->sc_ucode_cv); 2621 break; 2622 } 2623 2624 sc->sc_rxq.cur = (sc->sc_rxq.cur + 1) % RX_QUEUE_SIZE; 2625 } 2626 2627 /* 2628 * driver dealt with what received in rx queue and tell the information 2629 * to the firmware. 2630 */ 2631 index = (0 == index) ? RX_QUEUE_SIZE - 1 : index - 1; 2632 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, index & (~7)); 2633 2634 mutex_enter(&sc->sc_glock); 2635 2636 /* 2637 * re-enable interrupts 2638 */ 2639 IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 2640 sc->sc_rx_softint_pending = 0; 2641 2642 mutex_exit(&sc->sc_glock); 2643 2644 return (DDI_INTR_CLAIMED); 2645 } 2646 2647 /* 2648 * the handle of interrupt 2649 */ 2650 static uint_t 2651 /* LINTED: argument unused in function: unused */ 2652 iwh_intr(caddr_t arg, caddr_t unused) 2653 { 2654 iwh_sc_t *sc = (iwh_sc_t *)arg; 2655 uint32_t r, rfh; 2656 2657 mutex_enter(&sc->sc_glock); 2658 2659 if (sc->sc_flags & IWH_F_SUSPEND) { 2660 mutex_exit(&sc->sc_glock); 2661 return (DDI_INTR_UNCLAIMED); 2662 } 2663 r = IWH_READ(sc, CSR_INT); 2664 if (0 == r || 0xffffffff == r) { 2665 mutex_exit(&sc->sc_glock); 2666 return (DDI_INTR_UNCLAIMED); 2667 } 2668 2669 IWH_DBG((IWH_DEBUG_INTR, "interrupt reg %x\n", r)); 2670 2671 rfh = IWH_READ(sc, CSR_FH_INT_STATUS); 2672 2673 IWH_DBG((IWH_DEBUG_INTR, "FH interrupt reg %x\n", rfh)); 2674 2675 /* 2676 * disable interrupts 2677 */ 2678 IWH_WRITE(sc, CSR_INT_MASK, 0); 2679 2680 /* 2681 * ack interrupts 2682 */ 2683 IWH_WRITE(sc, CSR_INT, r); 2684 IWH_WRITE(sc, CSR_FH_INT_STATUS, rfh); 2685 2686 if (NULL == sc->sc_soft_hdl) { 2687 mutex_exit(&sc->sc_glock); 2688 return (DDI_INTR_CLAIMED); 2689 } 2690 2691 if (r & (BIT_INT_SWERROR | BIT_INT_ERR)) { 2692 IWH_DBG((IWH_DEBUG_FW, "fatal firmware error\n")); 2693 mutex_exit(&sc->sc_glock); 2694 iwh_stop(sc); 2695 sc->sc_ostate = sc->sc_ic.ic_state; 2696 ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 2697 sc->sc_flags |= IWH_F_HW_ERR_RECOVER; 2698 return (DDI_INTR_CLAIMED); 2699 } 2700 2701 #ifdef DEBUG 2702 if (r & BIT_INT_RF_KILL) { 2703 IWH_DBG((IWH_DEBUG_RADIO, "RF kill\n")); 2704 } 2705 #endif 2706 2707 if ((r & (BIT_INT_FH_RX | BIT_INT_SW_RX)) || 2708 (rfh & FH_INT_RX_MASK)) { 2709 sc->sc_rx_softint_pending = 1; 2710 (void) ddi_intr_trigger_softint(sc->sc_soft_hdl, NULL); 2711 } 2712 2713 if (r & BIT_INT_FH_TX) { 2714 sc->sc_flags |= IWH_F_PUT_SEG; 2715 cv_signal(&sc->sc_put_seg_cv); 2716 } 2717 2718 #ifdef DEBUG 2719 if (r & BIT_INT_ALIVE) { 2720 IWH_DBG((IWH_DEBUG_FW, "firmware initialized.\n")); 2721 } 2722 #endif 2723 2724 /* 2725 * re-enable interrupts 2726 */ 2727 IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 2728 2729 mutex_exit(&sc->sc_glock); 2730 2731 return (DDI_INTR_CLAIMED); 2732 } 2733 2734 static uint8_t 2735 iwh_rate_to_plcp(int rate) 2736 { 2737 uint8_t ret; 2738 2739 switch (rate) { 2740 /* 2741 * CCK rates 2742 */ 2743 case 2: 2744 ret = 0xa; 2745 break; 2746 2747 case 4: 2748 ret = 0x14; 2749 break; 2750 2751 case 11: 2752 ret = 0x37; 2753 break; 2754 2755 case 22: 2756 ret = 0x6e; 2757 break; 2758 2759 /* 2760 * OFDM rates 2761 */ 2762 case 12: 2763 ret = 0xd; 2764 break; 2765 2766 case 18: 2767 ret = 0xf; 2768 break; 2769 2770 case 24: 2771 ret = 0x5; 2772 break; 2773 2774 case 36: 2775 ret = 0x7; 2776 break; 2777 2778 case 48: 2779 ret = 0x9; 2780 break; 2781 2782 case 72: 2783 ret = 0xb; 2784 break; 2785 2786 case 96: 2787 ret = 0x1; 2788 break; 2789 2790 case 108: 2791 ret = 0x3; 2792 break; 2793 2794 default: 2795 ret = 0; 2796 break; 2797 } 2798 2799 return (ret); 2800 } 2801 2802 /* 2803 * invoked by GLD send frames 2804 */ 2805 static mblk_t * 2806 iwh_m_tx(void *arg, mblk_t *mp) 2807 { 2808 iwh_sc_t *sc = (iwh_sc_t *)arg; 2809 ieee80211com_t *ic = &sc->sc_ic; 2810 mblk_t *next; 2811 2812 if (sc->sc_flags & IWH_F_SUSPEND) { 2813 freemsgchain(mp); 2814 return (NULL); 2815 } 2816 2817 if (ic->ic_state != IEEE80211_S_RUN) { 2818 freemsgchain(mp); 2819 return (NULL); 2820 } 2821 2822 while (mp != NULL) { 2823 next = mp->b_next; 2824 mp->b_next = NULL; 2825 if (iwh_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 0) { 2826 mp->b_next = next; 2827 break; 2828 } 2829 mp = next; 2830 } 2831 2832 return (mp); 2833 } 2834 2835 /* 2836 * send frames 2837 */ 2838 static int 2839 iwh_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 2840 { 2841 iwh_sc_t *sc = (iwh_sc_t *)ic; 2842 iwh_tx_ring_t *ring; 2843 iwh_tx_desc_t *desc; 2844 iwh_tx_data_t *data; 2845 iwh_cmd_t *cmd; 2846 iwh_tx_cmd_t *tx; 2847 ieee80211_node_t *in; 2848 struct ieee80211_frame *wh; 2849 struct ieee80211_key *k = NULL; 2850 mblk_t *m, *m0; 2851 int rate, hdrlen, len, len0, mblen, off, err = IWH_SUCCESS; 2852 uint16_t masks = 0; 2853 uint32_t s_id = 0; 2854 2855 ring = &sc->sc_txq[0]; 2856 data = &ring->data[ring->cur]; 2857 desc = data->desc; 2858 cmd = data->cmd; 2859 bzero(desc, sizeof (*desc)); 2860 bzero(cmd, sizeof (*cmd)); 2861 2862 mutex_enter(&sc->sc_tx_lock); 2863 if (sc->sc_flags & IWH_F_SUSPEND) { 2864 mutex_exit(&sc->sc_tx_lock); 2865 if ((type & IEEE80211_FC0_TYPE_MASK) != 2866 IEEE80211_FC0_TYPE_DATA) { 2867 freemsg(mp); 2868 } 2869 err = IWH_FAIL; 2870 goto exit; 2871 } 2872 if (ring->queued > ring->count - 64) { 2873 IWH_DBG((IWH_DEBUG_TX, "iwh_send(): no txbuf\n")); 2874 2875 sc->sc_need_reschedule = 1; 2876 mutex_exit(&sc->sc_tx_lock); 2877 if ((type & IEEE80211_FC0_TYPE_MASK) != 2878 IEEE80211_FC0_TYPE_DATA) { 2879 freemsg(mp); 2880 } 2881 sc->sc_tx_nobuf++; 2882 err = IWH_FAIL; 2883 goto exit; 2884 } 2885 2886 mutex_exit(&sc->sc_tx_lock); 2887 2888 hdrlen = sizeof (struct ieee80211_frame); 2889 2890 m = allocb(msgdsize(mp) + 32, BPRI_MED); 2891 if (NULL == m) { /* can not alloc buf, drop this package */ 2892 cmn_err(CE_WARN, "iwh_send(): " 2893 "failed to allocate msgbuf\n"); 2894 freemsg(mp); 2895 err = IWH_SUCCESS; 2896 goto exit; 2897 } 2898 2899 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 2900 mblen = MBLKL(m0); 2901 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen); 2902 off += mblen; 2903 } 2904 2905 m->b_wptr += off; 2906 2907 freemsg(mp); 2908 2909 wh = (struct ieee80211_frame *)m->b_rptr; 2910 2911 /* 2912 * determine send which AP or station in IBSS 2913 */ 2914 in = ieee80211_find_txnode(ic, wh->i_addr1); 2915 if (NULL == in) { 2916 cmn_err(CE_WARN, "iwh_send(): " 2917 "failed to find tx node\n"); 2918 freemsg(m); 2919 sc->sc_tx_err++; 2920 err = IWH_SUCCESS; 2921 goto exit; 2922 } 2923 2924 (void) ieee80211_encap(ic, m, in); 2925 2926 cmd->hdr.type = REPLY_TX; 2927 cmd->hdr.flags = 0; 2928 cmd->hdr.qid = ring->qid; 2929 cmd->hdr.idx = ring->cur; 2930 2931 tx = (iwh_tx_cmd_t *)cmd->data; 2932 tx->tx_flags = 0; 2933 2934 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2935 tx->tx_flags &= ~(LE_32(TX_CMD_FLG_ACK_MSK)); 2936 } else { 2937 tx->tx_flags |= LE_32(TX_CMD_FLG_ACK_MSK); 2938 } 2939 2940 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2941 k = ieee80211_crypto_encap(ic, m); 2942 if (NULL == k) { 2943 freemsg(m); 2944 sc->sc_tx_err++; 2945 err = IWH_SUCCESS; 2946 goto exit; 2947 } 2948 2949 /* packet header may have moved, reset our local pointer */ 2950 wh = (struct ieee80211_frame *)m->b_rptr; 2951 } 2952 2953 len = msgdsize(m); 2954 2955 #ifdef DEBUG 2956 if (iwh_dbg_flags & IWH_DEBUG_TX) { 2957 ieee80211_dump_pkt((uint8_t *)wh, hdrlen, 0, 0); 2958 } 2959 #endif 2960 2961 /* 2962 * pickup a rate 2963 */ 2964 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2965 IEEE80211_FC0_TYPE_MGT) { 2966 /* 2967 * mgmt frames are sent at 1M 2968 */ 2969 rate = in->in_rates.ir_rates[0]; 2970 } else { 2971 /* 2972 * do it here for the software way rate control. 2973 * later for rate scaling in hardware. 2974 * maybe like the following, for management frame: 2975 * tx->initial_rate_index = LINK_QUAL_MAX_RETRY_NUM - 1; 2976 * for data frame: 2977 * tx->tx_flags |= (LE_32(TX_CMD_FLG_STA_RATE_MSK)); 2978 * rate = in->in_rates.ir_rates[in->in_txrate]; 2979 * tx->initial_rate_index = 1; 2980 * 2981 * now the txrate is determined in tx cmd flags, set to the 2982 * max value 54M for 11g and 11M for 11b. 2983 */ 2984 2985 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 2986 rate = ic->ic_fixed_rate; 2987 } else { 2988 rate = in->in_rates.ir_rates[in->in_txrate]; 2989 } 2990 } 2991 2992 rate &= IEEE80211_RATE_VAL; 2993 2994 IWH_DBG((IWH_DEBUG_TX, "tx rate[%d of %d] = %x", 2995 in->in_txrate, in->in_rates.ir_nrates, rate)); 2996 2997 tx->tx_flags |= (LE_32(TX_CMD_FLG_SEQ_CTL_MSK)); 2998 2999 len0 = roundup(4 + sizeof (iwh_tx_cmd_t) + hdrlen, 4); 3000 if (len0 != (4 + sizeof (iwh_tx_cmd_t) + hdrlen)) { 3001 tx->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; 3002 } 3003 3004 /* 3005 * retrieve destination node's id 3006 */ 3007 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3008 tx->sta_id = IWH_BROADCAST_ID; 3009 } else { 3010 tx->sta_id = IWH_AP_ID; 3011 } 3012 3013 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 3014 IEEE80211_FC0_TYPE_MGT) { 3015 /* tell h/w to set timestamp in probe responses */ 3016 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 3017 IEEE80211_FC0_SUBTYPE_PROBE_RESP) { 3018 tx->tx_flags |= LE_32(TX_CMD_FLG_TSF_MSK); 3019 } 3020 3021 if (((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 3022 IEEE80211_FC0_SUBTYPE_ASSOC_REQ) || 3023 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 3024 IEEE80211_FC0_SUBTYPE_REASSOC_REQ)) { 3025 tx->timeout.pm_frame_timeout = 3; 3026 } else { 3027 tx->timeout.pm_frame_timeout = 2; 3028 } 3029 } else { 3030 tx->timeout.pm_frame_timeout = 0; 3031 } 3032 3033 if (2 == rate || 4 == rate || 11 == rate || 22 == rate) { 3034 masks |= RATE_MCS_CCK_MSK; 3035 } 3036 3037 masks |= RATE_MCS_ANT_B_MSK; 3038 tx->rate.r.rate_n_flags = (iwh_rate_to_plcp(rate) | masks); 3039 3040 IWH_DBG((IWH_DEBUG_TX, "tx flag = %x", 3041 tx->tx_flags)); 3042 3043 tx->rts_retry_limit = 60; 3044 tx->data_retry_limit = 15; 3045 3046 tx->stop_time.life_time = LE_32(0xffffffff); 3047 3048 tx->len = LE_16(len); 3049 3050 tx->dram_lsb_ptr = 3051 data->paddr_cmd + 4 + offsetof(iwh_tx_cmd_t, scratch); 3052 tx->dram_msb_ptr = 0; 3053 tx->driver_txop = 0; 3054 tx->next_frame_len = 0; 3055 3056 (void) memcpy(tx + 1, m->b_rptr, hdrlen); 3057 m->b_rptr += hdrlen; 3058 (void) memcpy(data->dma_data.mem_va, m->b_rptr, len - hdrlen); 3059 3060 IWH_DBG((IWH_DEBUG_TX, "sending data: qid=%d idx=%d len=%d", 3061 ring->qid, ring->cur, len)); 3062 3063 /* 3064 * first segment includes the tx cmd plus the 802.11 header, 3065 * the second includes the remaining of the 802.11 frame. 3066 */ 3067 desc->val0 = LE_32(2 << 24); 3068 desc->pa[0].tb1_addr = LE_32(data->paddr_cmd); 3069 desc->pa[0].val1 = ((len0 << 4) & 0xfff0) | 3070 ((data->dma_data.cookie.dmac_address & 0xffff) << 16); 3071 desc->pa[0].val2 = 3072 ((data->dma_data.cookie.dmac_address & 0xffff0000) >> 16) | 3073 ((len - hdrlen) << 20); 3074 IWH_DBG((IWH_DEBUG_TX, "phy addr1 = 0x%x phy addr2 = 0x%x " 3075 "len1 = 0x%x, len2 = 0x%x val1 = 0x%x val2 = 0x%x", 3076 data->paddr_cmd, data->dma_data.cookie.dmac_address, 3077 len0, len - hdrlen, desc->pa[0].val1, desc->pa[0].val2)); 3078 3079 mutex_enter(&sc->sc_tx_lock); 3080 ring->queued++; 3081 mutex_exit(&sc->sc_tx_lock); 3082 3083 /* 3084 * kick ring 3085 */ 3086 s_id = tx->sta_id; 3087 3088 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3089 tfd_offset[ring->cur].val = 3090 (8 + len) | (s_id << 12); 3091 if (ring->cur < IWH_MAX_WIN_SIZE) { 3092 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3093 tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 3094 (8 + len) | (s_id << 12); 3095 } 3096 3097 IWH_DMA_SYNC(data->dma_data, DDI_DMA_SYNC_FORDEV); 3098 IWH_DMA_SYNC(ring->dma_desc, DDI_DMA_SYNC_FORDEV); 3099 3100 ring->cur = (ring->cur + 1) % ring->count; 3101 IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3102 freemsg(m); 3103 3104 /* 3105 * release node reference 3106 */ 3107 ieee80211_free_node(in); 3108 3109 ic->ic_stats.is_tx_bytes += len; 3110 ic->ic_stats.is_tx_frags++; 3111 3112 if (0 == sc->sc_tx_timer) { 3113 sc->sc_tx_timer = 10; 3114 } 3115 3116 exit: 3117 return (err); 3118 } 3119 3120 /* 3121 * invoked by GLD to deal with IOCTL affaires 3122 */ 3123 static void 3124 iwh_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 3125 { 3126 iwh_sc_t *sc = (iwh_sc_t *)arg; 3127 ieee80211com_t *ic = &sc->sc_ic; 3128 int err; 3129 3130 3131 err = ieee80211_ioctl(ic, wq, mp); 3132 if (ENETRESET == err) { 3133 /* 3134 * This is special for the hidden AP connection. 3135 * In any case, we should make sure only one 'scan' 3136 * in the driver for a 'connect' CLI command. So 3137 * when connecting to a hidden AP, the scan is just 3138 * sent out to the air when we know the desired 3139 * essid of the AP we want to connect. 3140 */ 3141 if (ic->ic_des_esslen) { 3142 if (sc->sc_flags & IWH_F_RUNNING) { 3143 iwh_m_stop(sc); 3144 (void) iwh_m_start(sc); 3145 (void) ieee80211_new_state(ic, 3146 IEEE80211_S_SCAN, -1); 3147 } 3148 } 3149 } 3150 } 3151 3152 /* 3153 * invoked by GLD supply statistics NIC and driver 3154 */ 3155 static int 3156 iwh_m_stat(void *arg, uint_t stat, uint64_t *val) 3157 { 3158 iwh_sc_t *sc = (iwh_sc_t *)arg; 3159 ieee80211com_t *ic = &sc->sc_ic; 3160 ieee80211_node_t *in = ic->ic_bss; 3161 struct ieee80211_rateset *rs = &in->in_rates; 3162 3163 mutex_enter(&sc->sc_glock); 3164 3165 switch (stat) { 3166 case MAC_STAT_IFSPEED: 3167 *val = ((IEEE80211_FIXED_RATE_NONE == ic->ic_fixed_rate) ? 3168 (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL) : 3169 ic->ic_fixed_rate) /2 * 1000000; 3170 break; 3171 3172 case MAC_STAT_NOXMTBUF: 3173 *val = sc->sc_tx_nobuf; 3174 break; 3175 3176 case MAC_STAT_NORCVBUF: 3177 *val = sc->sc_rx_nobuf; 3178 break; 3179 3180 case MAC_STAT_IERRORS: 3181 *val = sc->sc_rx_err; 3182 break; 3183 3184 case MAC_STAT_RBYTES: 3185 *val = ic->ic_stats.is_rx_bytes; 3186 break; 3187 3188 case MAC_STAT_IPACKETS: 3189 *val = ic->ic_stats.is_rx_frags; 3190 break; 3191 3192 case MAC_STAT_OBYTES: 3193 *val = ic->ic_stats.is_tx_bytes; 3194 break; 3195 3196 case MAC_STAT_OPACKETS: 3197 *val = ic->ic_stats.is_tx_frags; 3198 break; 3199 3200 case MAC_STAT_OERRORS: 3201 case WIFI_STAT_TX_FAILED: 3202 *val = sc->sc_tx_err; 3203 break; 3204 3205 case WIFI_STAT_TX_RETRANS: 3206 *val = sc->sc_tx_retries; 3207 break; 3208 3209 case WIFI_STAT_FCS_ERRORS: 3210 case WIFI_STAT_WEP_ERRORS: 3211 case WIFI_STAT_TX_FRAGS: 3212 case WIFI_STAT_MCAST_TX: 3213 case WIFI_STAT_RTS_SUCCESS: 3214 case WIFI_STAT_RTS_FAILURE: 3215 case WIFI_STAT_ACK_FAILURE: 3216 case WIFI_STAT_RX_FRAGS: 3217 case WIFI_STAT_MCAST_RX: 3218 case WIFI_STAT_RX_DUPS: 3219 mutex_exit(&sc->sc_glock); 3220 return (ieee80211_stat(ic, stat, val)); 3221 3222 default: 3223 mutex_exit(&sc->sc_glock); 3224 return (ENOTSUP); 3225 } 3226 3227 mutex_exit(&sc->sc_glock); 3228 3229 return (IWH_SUCCESS); 3230 3231 } 3232 3233 /* 3234 * invoked by GLD to start or open NIC 3235 */ 3236 static int 3237 iwh_m_start(void *arg) 3238 { 3239 iwh_sc_t *sc = (iwh_sc_t *)arg; 3240 ieee80211com_t *ic = &sc->sc_ic; 3241 int err; 3242 3243 err = iwh_init(sc); 3244 3245 if (err != IWH_SUCCESS) { 3246 /* 3247 * The hw init err(eg. RF is OFF). Return Success to make 3248 * the 'plumb' succeed. The iwh_thread() tries to re-init 3249 * background. 3250 */ 3251 mutex_enter(&sc->sc_glock); 3252 sc->sc_flags |= IWH_F_HW_ERR_RECOVER; 3253 mutex_exit(&sc->sc_glock); 3254 return (IWH_SUCCESS); 3255 } 3256 3257 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3258 3259 mutex_enter(&sc->sc_glock); 3260 sc->sc_flags |= IWH_F_RUNNING; 3261 mutex_exit(&sc->sc_glock); 3262 3263 return (IWH_SUCCESS); 3264 } 3265 3266 /* 3267 * invoked by GLD to stop or down NIC 3268 */ 3269 static void 3270 iwh_m_stop(void *arg) 3271 { 3272 iwh_sc_t *sc = (iwh_sc_t *)arg; 3273 ieee80211com_t *ic = &sc->sc_ic; 3274 3275 iwh_stop(sc); 3276 3277 /* 3278 * release buffer for calibration 3279 */ 3280 iwh_release_calib_buffer(sc); 3281 3282 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3283 3284 mutex_enter(&sc->sc_mt_lock); 3285 3286 sc->sc_flags &= ~IWH_F_HW_ERR_RECOVER; 3287 sc->sc_flags &= ~IWH_F_RATE_AUTO_CTL; 3288 mutex_exit(&sc->sc_mt_lock); 3289 mutex_enter(&sc->sc_glock); 3290 sc->sc_flags &= ~IWH_F_RUNNING; 3291 sc->sc_flags &= ~IWH_F_SCANNING; 3292 3293 mutex_exit(&sc->sc_glock); 3294 } 3295 3296 /* 3297 * invoked by GLD to configure NIC 3298 */ 3299 static int 3300 iwh_m_unicst(void *arg, const uint8_t *macaddr) 3301 { 3302 iwh_sc_t *sc = (iwh_sc_t *)arg; 3303 ieee80211com_t *ic = &sc->sc_ic; 3304 int err; 3305 3306 if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) { 3307 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr); 3308 mutex_enter(&sc->sc_glock); 3309 err = iwh_config(sc); 3310 mutex_exit(&sc->sc_glock); 3311 if (err != IWH_SUCCESS) { 3312 cmn_err(CE_WARN, "iwh_m_unicst(): " 3313 "failed to configure device\n"); 3314 goto fail; 3315 } 3316 } 3317 3318 return (IWH_SUCCESS); 3319 3320 fail: 3321 return (err); 3322 } 3323 3324 static int 3325 /* LINTED: argument unused in function: arg add m */ 3326 iwh_m_multicst(void *arg, boolean_t add, const uint8_t *m) 3327 { 3328 return (IWH_SUCCESS); 3329 } 3330 3331 static int 3332 /* LINTED: argument unused in function: arg on */ 3333 iwh_m_promisc(void *arg, boolean_t on) 3334 { 3335 return (IWH_SUCCESS); 3336 } 3337 3338 /* 3339 * kernel thread to deal with exceptional situation 3340 */ 3341 static void 3342 iwh_thread(iwh_sc_t *sc) 3343 { 3344 ieee80211com_t *ic = &sc->sc_ic; 3345 clock_t clk; 3346 int err, n = 0, timeout = 0; 3347 uint32_t tmp; 3348 #ifdef DEBUG 3349 int times = 0; 3350 #endif 3351 3352 mutex_enter(&sc->sc_mt_lock); 3353 3354 while (sc->sc_mf_thread_switch) { 3355 tmp = IWH_READ(sc, CSR_GP_CNTRL); 3356 if (tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) { 3357 sc->sc_flags &= ~IWH_F_RADIO_OFF; 3358 } else { 3359 sc->sc_flags |= IWH_F_RADIO_OFF; 3360 } 3361 3362 /* 3363 * If in SUSPEND or the RF is OFF, do nothing. 3364 */ 3365 if ((sc->sc_flags & IWH_F_SUSPEND) || 3366 (sc->sc_flags & IWH_F_RADIO_OFF)) { 3367 mutex_exit(&sc->sc_mt_lock); 3368 delay(drv_usectohz(100000)); 3369 mutex_enter(&sc->sc_mt_lock); 3370 continue; 3371 } 3372 3373 /* 3374 * recovery fatal error 3375 */ 3376 if (ic->ic_mach && 3377 (sc->sc_flags & IWH_F_HW_ERR_RECOVER)) { 3378 3379 IWH_DBG((IWH_DEBUG_FW, 3380 "iwh_thread(): " 3381 "try to recover fatal hw error: %d\n", times++)); 3382 3383 iwh_stop(sc); 3384 3385 mutex_exit(&sc->sc_mt_lock); 3386 3387 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3388 delay(drv_usectohz(2000000 + n*500000)); 3389 3390 mutex_enter(&sc->sc_mt_lock); 3391 3392 err = iwh_init(sc); 3393 if (err != IWH_SUCCESS) { 3394 n++; 3395 if (n < 20) { 3396 continue; 3397 } 3398 } 3399 3400 n = 0; 3401 if (!err) { 3402 sc->sc_flags |= IWH_F_RUNNING; 3403 } 3404 3405 sc->sc_flags &= ~IWH_F_HW_ERR_RECOVER; 3406 3407 mutex_exit(&sc->sc_mt_lock); 3408 3409 delay(drv_usectohz(2000000)); 3410 3411 if (sc->sc_ostate != IEEE80211_S_INIT) { 3412 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); 3413 } 3414 3415 mutex_enter(&sc->sc_mt_lock); 3416 } 3417 3418 if (ic->ic_mach && 3419 (sc->sc_flags & IWH_F_SCANNING) && sc->sc_scan_pending) { 3420 IWH_DBG((IWH_DEBUG_SCAN, 3421 "iwh_thread(): " 3422 "wait for probe response\n")); 3423 3424 sc->sc_scan_pending--; 3425 mutex_exit(&sc->sc_mt_lock); 3426 delay(drv_usectohz(200000)); 3427 ieee80211_next_scan(ic); 3428 mutex_enter(&sc->sc_mt_lock); 3429 } 3430 3431 /* 3432 * rate ctl 3433 */ 3434 if (ic->ic_mach && 3435 (sc->sc_flags & IWH_F_RATE_AUTO_CTL)) { 3436 clk = ddi_get_lbolt(); 3437 if (clk > sc->sc_clk + drv_usectohz(500000)) { 3438 iwh_amrr_timeout(sc); 3439 } 3440 } 3441 3442 mutex_exit(&sc->sc_mt_lock); 3443 delay(drv_usectohz(100000)); 3444 mutex_enter(&sc->sc_mt_lock); 3445 3446 if (sc->sc_tx_timer) { 3447 timeout++; 3448 if (10 == timeout) { 3449 sc->sc_tx_timer--; 3450 if (0 == sc->sc_tx_timer) { 3451 sc->sc_flags |= IWH_F_HW_ERR_RECOVER; 3452 sc->sc_ostate = IEEE80211_S_RUN; 3453 IWH_DBG((IWH_DEBUG_FW, 3454 "iwh_thread(): try to recover from" 3455 " 'send fail\n")); 3456 } 3457 timeout = 0; 3458 } 3459 } 3460 3461 } 3462 3463 sc->sc_mf_thread = NULL; 3464 cv_signal(&sc->sc_mt_cv); 3465 mutex_exit(&sc->sc_mt_lock); 3466 } 3467 3468 3469 /* 3470 * Send a command to the ucode. 3471 */ 3472 static int 3473 iwh_cmd(iwh_sc_t *sc, int code, const void *buf, int size, int async) 3474 { 3475 iwh_tx_ring_t *ring = &sc->sc_txq[IWH_CMD_QUEUE_NUM]; 3476 iwh_tx_desc_t *desc; 3477 iwh_cmd_t *cmd; 3478 3479 ASSERT(size <= sizeof (cmd->data)); 3480 ASSERT(mutex_owned(&sc->sc_glock)); 3481 3482 IWH_DBG((IWH_DEBUG_CMD, "iwh_cmd() code[%d]", code)); 3483 desc = ring->data[ring->cur].desc; 3484 cmd = ring->data[ring->cur].cmd; 3485 3486 cmd->hdr.type = (uint8_t)code; 3487 cmd->hdr.flags = 0; 3488 cmd->hdr.qid = ring->qid; 3489 cmd->hdr.idx = ring->cur; 3490 (void) memcpy(cmd->data, buf, size); 3491 (void) memset(desc, 0, sizeof (*desc)); 3492 3493 desc->val0 = LE_32(1 << 24); 3494 desc->pa[0].tb1_addr = 3495 (uint32_t)(ring->data[ring->cur].paddr_cmd & 0xffffffff); 3496 desc->pa[0].val1 = ((4 + size) << 4) & 0xfff0; 3497 3498 /* 3499 * kick cmd ring XXX 3500 */ 3501 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3502 tfd_offset[ring->cur].val = 8; 3503 if (ring->cur < IWH_MAX_WIN_SIZE) { 3504 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3505 tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 8; 3506 } 3507 ring->cur = (ring->cur + 1) % ring->count; 3508 IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3509 3510 if (async) { 3511 return (IWH_SUCCESS); 3512 } else { 3513 clock_t clk; 3514 sc->sc_flags &= ~IWH_F_CMD_DONE; 3515 clk = ddi_get_lbolt() + drv_usectohz(2000000); 3516 while (!(sc->sc_flags & IWH_F_CMD_DONE)) { 3517 if (cv_timedwait(&sc->sc_cmd_cv, 3518 &sc->sc_glock, clk) < 0) { 3519 break; 3520 } 3521 } 3522 3523 if (sc->sc_flags & IWH_F_CMD_DONE) { 3524 return (IWH_SUCCESS); 3525 } else { 3526 return (IWH_FAIL); 3527 } 3528 } 3529 } 3530 3531 /* 3532 * require ucode seting led of NIC 3533 */ 3534 static void 3535 iwh_set_led(iwh_sc_t *sc, uint8_t id, uint8_t off, uint8_t on) 3536 { 3537 iwh_led_cmd_t led; 3538 3539 led.interval = LE_32(100000); /* unit: 100ms */ 3540 led.id = id; 3541 led.off = off; 3542 led.on = on; 3543 3544 (void) iwh_cmd(sc, REPLY_LEDS_CMD, &led, sizeof (led), 1); 3545 } 3546 3547 /* 3548 * necessary setting to NIC before authentication 3549 */ 3550 static int 3551 iwh_hw_set_before_auth(iwh_sc_t *sc) 3552 { 3553 ieee80211com_t *ic = &sc->sc_ic; 3554 ieee80211_node_t *in = ic->ic_bss; 3555 iwh_add_sta_t node; 3556 iwh_link_quality_cmd_t link_quality; 3557 struct ieee80211_rateset rs; 3558 uint16_t masks = 0, rate; 3559 int i, err; 3560 3561 /* 3562 * update adapter's configuration according 3563 * the info of target AP 3564 */ 3565 IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid); 3566 sc->sc_config.chan = ieee80211_chan2ieee(ic, in->in_chan); 3567 if (IEEE80211_MODE_11B == ic->ic_curmode) { 3568 sc->sc_config.cck_basic_rates = 0x03; 3569 sc->sc_config.ofdm_basic_rates = 0; 3570 } else if ((in->in_chan != IEEE80211_CHAN_ANYC) && 3571 (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) { 3572 sc->sc_config.cck_basic_rates = 0; 3573 sc->sc_config.ofdm_basic_rates = 0x15; 3574 } else { /* assume 802.11b/g */ 3575 sc->sc_config.cck_basic_rates = 0x0f; 3576 sc->sc_config.ofdm_basic_rates = 0xff; 3577 } 3578 3579 sc->sc_config.flags &= ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK | 3580 RXON_FLG_SHORT_SLOT_MSK); 3581 3582 if (ic->ic_flags & IEEE80211_F_SHSLOT) { 3583 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_SLOT_MSK); 3584 } else { 3585 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_SLOT_MSK); 3586 } 3587 3588 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) { 3589 sc->sc_config.flags |= LE_32(RXON_FLG_SHORT_PREAMBLE_MSK); 3590 } else { 3591 sc->sc_config.flags &= LE_32(~RXON_FLG_SHORT_PREAMBLE_MSK); 3592 } 3593 3594 IWH_DBG((IWH_DEBUG_80211, "config chan %d flags %x " 3595 "filter_flags %x cck %x ofdm %x" 3596 " bssid:%02x:%02x:%02x:%02x:%02x:%2x\n", 3597 sc->sc_config.chan, sc->sc_config.flags, 3598 sc->sc_config.filter_flags, 3599 sc->sc_config.cck_basic_rates, sc->sc_config.ofdm_basic_rates, 3600 sc->sc_config.bssid[0], sc->sc_config.bssid[1], 3601 sc->sc_config.bssid[2], sc->sc_config.bssid[3], 3602 sc->sc_config.bssid[4], sc->sc_config.bssid[5])); 3603 3604 err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config, 3605 sizeof (iwh_rxon_cmd_t), 1); 3606 if (err != IWH_SUCCESS) { 3607 cmn_err(CE_WARN, "iwh_hw_set_before_auth(): " 3608 "failed to config chan%d\n", sc->sc_config.chan); 3609 return (err); 3610 } 3611 3612 err = iwh_tx_power_table(sc, 1); 3613 if (err != IWH_SUCCESS) { 3614 cmn_err(CE_WARN, "iwh_config(): " 3615 "failed to set tx power table.\n"); 3616 return (err); 3617 } 3618 3619 /* 3620 * add default AP node 3621 */ 3622 (void) memset(&node, 0, sizeof (node)); 3623 IEEE80211_ADDR_COPY(node.sta.addr, in->in_bssid); 3624 node.mode = 0; 3625 node.sta.sta_id = IWH_AP_ID; 3626 node.station_flags = 0; 3627 err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1); 3628 if (err != IWH_SUCCESS) { 3629 cmn_err(CE_WARN, "iwh_hw_set_before_auth(): " 3630 "failed to add BSS node\n"); 3631 return (err); 3632 } 3633 3634 /* 3635 * TX_LINK_QUALITY cmd 3636 */ 3637 (void) memset(&link_quality, 0, sizeof (link_quality)); 3638 rs = ic->ic_sup_rates[ieee80211_chan2mode(ic, ic->ic_curchan)]; 3639 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 3640 if (i < rs.ir_nrates) { 3641 rate = rs.ir_rates[rs.ir_nrates - i]; 3642 } else { 3643 rate = 2; 3644 } 3645 3646 if (2 == rate || 4 == rate || 11 == rate || 22 == rate) { 3647 masks |= RATE_MCS_CCK_MSK; 3648 } 3649 masks |= RATE_MCS_ANT_B_MSK; 3650 masks &= ~RATE_MCS_ANT_A_MSK; 3651 link_quality.rate_n_flags[i] = 3652 iwh_rate_to_plcp(rate) | masks; 3653 } 3654 3655 link_quality.general_params.single_stream_ant_msk = 2; 3656 link_quality.general_params.dual_stream_ant_msk = 3; 3657 link_quality.agg_params.agg_dis_start_th = 3; 3658 link_quality.agg_params.agg_time_limit = LE_16(4000); 3659 link_quality.sta_id = IWH_AP_ID; 3660 err = iwh_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality, 3661 sizeof (link_quality), 1); 3662 if (err != IWH_SUCCESS) { 3663 cmn_err(CE_WARN, "iwh_hw_set_before_auth(): " 3664 "failed to config link quality table\n"); 3665 return (err); 3666 } 3667 3668 return (IWH_SUCCESS); 3669 } 3670 3671 /* 3672 * Send a scan request(assembly scan cmd) to the firmware. 3673 */ 3674 static int 3675 iwh_scan(iwh_sc_t *sc) 3676 { 3677 ieee80211com_t *ic = &sc->sc_ic; 3678 iwh_tx_ring_t *ring = &sc->sc_txq[IWH_CMD_QUEUE_NUM]; 3679 iwh_tx_desc_t *desc; 3680 iwh_tx_data_t *data; 3681 iwh_cmd_t *cmd; 3682 iwh_scan_hdr_t *hdr; 3683 iwh_scan_chan_t *chan; 3684 struct ieee80211_frame *wh; 3685 ieee80211_node_t *in = ic->ic_bss; 3686 uint8_t essid[IEEE80211_NWID_LEN+1]; 3687 struct ieee80211_rateset *rs; 3688 enum ieee80211_phymode mode; 3689 uint8_t *frm; 3690 int i, pktlen, nrates; 3691 3692 data = &ring->data[ring->cur]; 3693 desc = data->desc; 3694 cmd = (iwh_cmd_t *)data->dma_data.mem_va; 3695 3696 cmd->hdr.type = REPLY_SCAN_CMD; 3697 cmd->hdr.flags = 0; 3698 cmd->hdr.qid = ring->qid; 3699 cmd->hdr.idx = ring->cur | 0x40; 3700 3701 hdr = (iwh_scan_hdr_t *)cmd->data; 3702 (void) memset(hdr, 0, sizeof (iwh_scan_hdr_t)); 3703 hdr->nchan = 1; 3704 hdr->quiet_time = LE_16(50); 3705 hdr->quiet_plcp_th = LE_16(1); 3706 3707 hdr->flags = RXON_FLG_BAND_24G_MSK; 3708 hdr->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | 3709 LE_16((0x7 << RXON_RX_CHAIN_VALID_POS) | 3710 (0x2 << RXON_RX_CHAIN_FORCE_SEL_POS) | 3711 (0x2 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 3712 3713 hdr->tx_cmd.tx_flags = LE_32(TX_CMD_FLG_SEQ_CTL_MSK); 3714 hdr->tx_cmd.sta_id = IWH_BROADCAST_ID; 3715 hdr->tx_cmd.stop_time.life_time = 0xffffffff; 3716 hdr->tx_cmd.rate.r.rate_n_flags = iwh_rate_to_plcp(2); 3717 hdr->tx_cmd.rate.r.rate_n_flags |= 3718 (RATE_MCS_ANT_B_MSK |RATE_MCS_CCK_MSK); 3719 hdr->direct_scan[0].len = ic->ic_des_esslen; 3720 hdr->direct_scan[0].id = IEEE80211_ELEMID_SSID; 3721 3722 hdr->filter_flags = RXON_FILTER_ACCEPT_GRP_MSK | 3723 RXON_FILTER_BCON_AWARE_MSK; 3724 3725 if (ic->ic_des_esslen) { 3726 bcopy(ic->ic_des_essid, essid, ic->ic_des_esslen); 3727 essid[ic->ic_des_esslen] = '\0'; 3728 IWH_DBG((IWH_DEBUG_SCAN, "directed scan %s\n", essid)); 3729 3730 bcopy(ic->ic_des_essid, hdr->direct_scan[0].ssid, 3731 ic->ic_des_esslen); 3732 } else { 3733 bzero(hdr->direct_scan[0].ssid, 3734 sizeof (hdr->direct_scan[0].ssid)); 3735 } 3736 3737 /* 3738 * a probe request frame is required after the REPLY_SCAN_CMD 3739 */ 3740 wh = (struct ieee80211_frame *)(hdr + 1); 3741 wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | 3742 IEEE80211_FC0_SUBTYPE_PROBE_REQ; 3743 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; 3744 (void) memset(wh->i_addr1, 0xff, 6); 3745 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_macaddr); 3746 (void) memset(wh->i_addr3, 0xff, 6); 3747 *(uint16_t *)&wh->i_dur[0] = 0; 3748 *(uint16_t *)&wh->i_seq[0] = 0; 3749 3750 frm = (uint8_t *)(wh + 1); 3751 3752 /* 3753 * essid IE 3754 */ 3755 if (in->in_esslen) { 3756 bcopy(in->in_essid, essid, in->in_esslen); 3757 essid[in->in_esslen] = '\0'; 3758 IWH_DBG((IWH_DEBUG_SCAN, "probe with ESSID %s\n", 3759 essid)); 3760 } 3761 *frm++ = IEEE80211_ELEMID_SSID; 3762 *frm++ = in->in_esslen; 3763 (void) memcpy(frm, in->in_essid, in->in_esslen); 3764 frm += in->in_esslen; 3765 3766 mode = ieee80211_chan2mode(ic, ic->ic_curchan); 3767 rs = &ic->ic_sup_rates[mode]; 3768 3769 /* 3770 * supported rates IE 3771 */ 3772 *frm++ = IEEE80211_ELEMID_RATES; 3773 nrates = rs->ir_nrates; 3774 if (nrates > IEEE80211_RATE_SIZE) { 3775 nrates = IEEE80211_RATE_SIZE; 3776 } 3777 3778 *frm++ = (uint8_t)nrates; 3779 (void) memcpy(frm, rs->ir_rates, nrates); 3780 frm += nrates; 3781 3782 /* 3783 * supported xrates IE 3784 */ 3785 if (rs->ir_nrates > IEEE80211_RATE_SIZE) { 3786 nrates = rs->ir_nrates - IEEE80211_RATE_SIZE; 3787 *frm++ = IEEE80211_ELEMID_XRATES; 3788 *frm++ = (uint8_t)nrates; 3789 (void) memcpy(frm, rs->ir_rates + IEEE80211_RATE_SIZE, nrates); 3790 frm += nrates; 3791 } 3792 3793 /* 3794 * optionnal IE (usually for wpa) 3795 */ 3796 if (ic->ic_opt_ie != NULL) { 3797 (void) memcpy(frm, ic->ic_opt_ie, ic->ic_opt_ie_len); 3798 frm += ic->ic_opt_ie_len; 3799 } 3800 3801 /* setup length of probe request */ 3802 hdr->tx_cmd.len = _PTRDIFF(frm, wh); 3803 hdr->len = hdr->nchan * sizeof (iwh_scan_chan_t) + 3804 hdr->tx_cmd.len + sizeof (iwh_scan_hdr_t); 3805 3806 /* 3807 * the attribute of the scan channels are required after the probe 3808 * request frame. 3809 */ 3810 chan = (iwh_scan_chan_t *)frm; 3811 for (i = 1; i <= hdr->nchan; i++, chan++) { 3812 if (ic->ic_des_esslen) { 3813 chan->type = 3; 3814 } else { 3815 chan->type = 1; 3816 } 3817 3818 chan->chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 3819 chan->tpc.tx_gain = 0x28; 3820 chan->tpc.dsp_atten = 110; 3821 chan->active_dwell = 50; 3822 chan->passive_dwell = 120; 3823 3824 frm += sizeof (iwh_scan_chan_t); 3825 } 3826 3827 pktlen = _PTRDIFF(frm, cmd); 3828 3829 (void) memset(desc, 0, sizeof (*desc)); 3830 desc->val0 = LE_32(1 << 24); 3831 desc->pa[0].tb1_addr = 3832 (uint32_t)(data->dma_data.cookie.dmac_address & 0xffffffff); 3833 desc->pa[0].val1 = (pktlen << 4) & 0xfff0; 3834 3835 /* 3836 * maybe for cmd, filling the byte cnt table is not necessary. 3837 * anyway, we fill it here. 3838 */ 3839 sc->sc_shared->queues_byte_cnt_tbls[ring->qid] 3840 .tfd_offset[ring->cur].val = 8; 3841 if (ring->cur < IWH_MAX_WIN_SIZE) { 3842 sc->sc_shared->queues_byte_cnt_tbls[ring->qid]. 3843 tfd_offset[IWH_QUEUE_SIZE + ring->cur].val = 8; 3844 } 3845 3846 /* 3847 * kick cmd ring 3848 */ 3849 ring->cur = (ring->cur + 1) % ring->count; 3850 IWH_WRITE(sc, HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); 3851 3852 return (IWH_SUCCESS); 3853 } 3854 3855 /* 3856 * configure NIC by using ucode commands after loading ucode. 3857 */ 3858 static int 3859 iwh_config(iwh_sc_t *sc) 3860 { 3861 ieee80211com_t *ic = &sc->sc_ic; 3862 iwh_powertable_cmd_t powertable; 3863 iwh_bt_cmd_t bt; 3864 iwh_add_sta_t node; 3865 iwh_rem_sta_t rm_sta; 3866 const uint8_t bcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 3867 iwh_link_quality_cmd_t link_quality; 3868 int i, err; 3869 uint16_t masks = 0; 3870 3871 /* 3872 * set power mode. Disable power management at present, do it later 3873 */ 3874 (void) memset(&powertable, 0, sizeof (powertable)); 3875 powertable.flags = LE_16(0x8); 3876 err = iwh_cmd(sc, POWER_TABLE_CMD, &powertable, 3877 sizeof (powertable), 0); 3878 if (err != IWH_SUCCESS) { 3879 cmn_err(CE_WARN, "iwh_config(): " 3880 "failed to set power mode\n"); 3881 return (err); 3882 } 3883 3884 /* 3885 * configure bt coexistence 3886 */ 3887 (void) memset(&bt, 0, sizeof (bt)); 3888 bt.flags = 3; 3889 bt.lead_time = 0xaa; 3890 bt.max_kill = 1; 3891 err = iwh_cmd(sc, REPLY_BT_CONFIG, &bt, 3892 sizeof (bt), 0); 3893 if (err != IWH_SUCCESS) { 3894 cmn_err(CE_WARN, "iwh_config(): " 3895 "failed to configurate bt coexistence\n"); 3896 return (err); 3897 } 3898 3899 /* 3900 * configure rxon 3901 */ 3902 (void) memset(&sc->sc_config, 0, sizeof (iwh_rxon_cmd_t)); 3903 IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr); 3904 IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr); 3905 sc->sc_config.chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 3906 sc->sc_config.flags = RXON_FLG_BAND_24G_MSK; 3907 3908 switch (ic->ic_opmode) { 3909 case IEEE80211_M_STA: 3910 sc->sc_config.dev_type = RXON_DEV_TYPE_ESS; 3911 sc->sc_config.filter_flags |= 3912 LE_32(RXON_FILTER_DIS_DECRYPT_MSK | 3913 RXON_FILTER_DIS_GRP_DECRYPT_MSK); 3914 break; 3915 3916 case IEEE80211_M_IBSS: 3917 case IEEE80211_M_AHDEMO: 3918 sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS; 3919 3920 sc->sc_config.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; 3921 sc->sc_config.filter_flags = LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 3922 RXON_FILTER_DIS_DECRYPT_MSK | 3923 RXON_FILTER_DIS_GRP_DECRYPT_MSK); 3924 break; 3925 3926 case IEEE80211_M_HOSTAP: 3927 sc->sc_config.dev_type = RXON_DEV_TYPE_AP; 3928 break; 3929 3930 case IEEE80211_M_MONITOR: 3931 sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER; 3932 sc->sc_config.filter_flags |= LE_32(RXON_FILTER_ACCEPT_GRP_MSK | 3933 RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK); 3934 break; 3935 } 3936 3937 sc->sc_config.cck_basic_rates = 0x0f; 3938 sc->sc_config.ofdm_basic_rates = 0xff; 3939 3940 /* 3941 * set antenna 3942 */ 3943 sc->sc_config.rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | 3944 LE_16((0x7 << RXON_RX_CHAIN_VALID_POS) | 3945 (0x2 << RXON_RX_CHAIN_FORCE_SEL_POS) | 3946 (0x2 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 3947 3948 err = iwh_cmd(sc, REPLY_RXON, &sc->sc_config, 3949 sizeof (iwh_rxon_cmd_t), 0); 3950 if (err != IWH_SUCCESS) { 3951 cmn_err(CE_WARN, "iwh_config(): " 3952 "failed to set configure command\n"); 3953 return (err); 3954 } 3955 3956 /* 3957 * remove all nodes in NIC 3958 */ 3959 (void) memset(&rm_sta, 0, sizeof (rm_sta)); 3960 rm_sta.num_sta = 1; 3961 (void) memcpy(rm_sta.addr, bcast, 6); 3962 3963 err = iwh_cmd(sc, REPLY_REMOVE_STA, &rm_sta, sizeof (iwh_rem_sta_t), 0); 3964 if (err != IWH_SUCCESS) { 3965 cmn_err(CE_WARN, "iwh_config(): " 3966 "failed to remove broadcast node in hardware.\n"); 3967 return (err); 3968 } 3969 3970 /* 3971 * configure TX pwoer table 3972 */ 3973 err = iwh_tx_power_table(sc, 0); 3974 if (err != IWH_SUCCESS) { 3975 cmn_err(CE_WARN, "iwh_config(): " 3976 "failed to set tx power table.\n"); 3977 return (err); 3978 } 3979 3980 /* 3981 * add broadcast node so that we can send broadcast frame 3982 */ 3983 (void) memset(&node, 0, sizeof (node)); 3984 (void) memset(node.sta.addr, 0xff, 6); 3985 node.mode = 0; 3986 node.sta.sta_id = IWH_BROADCAST_ID; 3987 node.station_flags = 0; 3988 3989 err = iwh_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 0); 3990 if (err != IWH_SUCCESS) { 3991 cmn_err(CE_WARN, "iwh_config(): " 3992 "failed to add broadcast node\n"); 3993 return (err); 3994 } 3995 3996 /* 3997 * TX_LINK_QUALITY cmd 3998 */ 3999 (void) memset(&link_quality, 0, sizeof (link_quality)); 4000 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { 4001 masks |= RATE_MCS_CCK_MSK; 4002 masks |= RATE_MCS_ANT_B_MSK; 4003 masks &= ~RATE_MCS_ANT_A_MSK; 4004 link_quality.rate_n_flags[i] = iwh_rate_to_plcp(2) | masks; 4005 } 4006 4007 link_quality.general_params.single_stream_ant_msk = 2; 4008 link_quality.general_params.dual_stream_ant_msk = 3; 4009 link_quality.agg_params.agg_dis_start_th = 3; 4010 link_quality.agg_params.agg_time_limit = LE_16(4000); 4011 link_quality.sta_id = IWH_BROADCAST_ID; 4012 err = iwh_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality, 4013 sizeof (link_quality), 0); 4014 if (err != IWH_SUCCESS) { 4015 cmn_err(CE_WARN, "iwh_config(): " 4016 "failed to config link quality table\n"); 4017 return (err); 4018 } 4019 4020 return (IWH_SUCCESS); 4021 } 4022 4023 static void 4024 iwh_stop_master(iwh_sc_t *sc) 4025 { 4026 uint32_t tmp; 4027 int n; 4028 4029 tmp = IWH_READ(sc, CSR_RESET); 4030 IWH_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_STOP_MASTER); 4031 4032 tmp = IWH_READ(sc, CSR_GP_CNTRL); 4033 if ((tmp & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE) == 4034 CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE) { 4035 return; 4036 } 4037 4038 for (n = 0; n < 2000; n++) { 4039 if (IWH_READ(sc, CSR_RESET) & 4040 CSR_RESET_REG_FLAG_MASTER_DISABLED) { 4041 break; 4042 } 4043 DELAY(1000); 4044 } 4045 4046 #ifdef DEBUG 4047 if (2000 == n) { 4048 IWH_DBG((IWH_DEBUG_HW, 4049 "timeout waiting for master stop\n")); 4050 } 4051 #endif 4052 } 4053 4054 static int 4055 iwh_power_up(iwh_sc_t *sc) 4056 { 4057 uint32_t tmp; 4058 4059 iwh_mac_access_enter(sc); 4060 tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL); 4061 tmp &= ~APMG_PS_CTRL_REG_MSK_POWER_SRC; 4062 tmp |= APMG_PS_CTRL_REG_VAL_POWER_SRC_VMAIN; 4063 iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4064 iwh_mac_access_exit(sc); 4065 4066 DELAY(5000); 4067 return (IWH_SUCCESS); 4068 } 4069 4070 /* 4071 * hardware initialization 4072 */ 4073 static int 4074 iwh_preinit(iwh_sc_t *sc) 4075 { 4076 uint32_t tmp; 4077 int n; 4078 uint8_t vlink; 4079 uint16_t radio_cfg; 4080 4081 /* 4082 * clear any pending interrupts 4083 */ 4084 IWH_WRITE(sc, CSR_INT, 0xffffffff); 4085 4086 tmp = IWH_READ(sc, CSR_GIO_CHICKEN_BITS); 4087 IWH_WRITE(sc, CSR_GIO_CHICKEN_BITS, 4088 tmp | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); 4089 4090 tmp = IWH_READ(sc, CSR_ANA_PLL_CFG); 4091 IWH_WRITE(sc, CSR_ANA_PLL_CFG, tmp | IWH_CSR_ANA_PLL_CFG); 4092 4093 tmp = IWH_READ(sc, CSR_GP_CNTRL); 4094 IWH_WRITE(sc, CSR_GP_CNTRL, tmp | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); 4095 4096 /* 4097 * wait for clock ready 4098 */ 4099 for (n = 0; n < 1000; n++) { 4100 if (IWH_READ(sc, CSR_GP_CNTRL) & 4101 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) { 4102 break; 4103 } 4104 DELAY(10); 4105 } 4106 4107 if (1000 == n) { 4108 return (ETIMEDOUT); 4109 } 4110 4111 iwh_mac_access_enter(sc); 4112 4113 iwh_reg_write(sc, ALM_APMG_CLK_EN, APMG_CLK_REG_VAL_DMA_CLK_RQT); 4114 4115 DELAY(20); 4116 tmp = iwh_reg_read(sc, ALM_APMG_PCIDEV_STT); 4117 iwh_reg_write(sc, ALM_APMG_PCIDEV_STT, tmp | 4118 APMG_DEV_STATE_REG_VAL_L1_ACTIVE_DISABLE); 4119 iwh_mac_access_exit(sc); 4120 4121 radio_cfg = IWH_READ_EEP_SHORT(sc, EEP_SP_RADIO_CONFIGURATION); 4122 if (SP_RADIO_TYPE_MSK(radio_cfg) < SP_RADIO_TYPE_MAX) { 4123 tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG); 4124 IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4125 tmp | SP_RADIO_TYPE_MSK(radio_cfg) | 4126 SP_RADIO_STEP_MSK(radio_cfg) | 4127 SP_RADIO_DASH_MSK(radio_cfg)); 4128 } else { 4129 cmn_err(CE_WARN, "iwh_preinit(): " 4130 "radio configuration information in eeprom is wrong\n"); 4131 return (IWH_FAIL); 4132 } 4133 4134 4135 IWH_WRITE(sc, CSR_INT_COALESCING, 512 / 32); 4136 4137 (void) iwh_power_up(sc); 4138 4139 if ((sc->sc_rev & 0x80) == 0x80 && (sc->sc_rev & 0x7f) < 8) { 4140 tmp = ddi_get32(sc->sc_cfg_handle, 4141 (uint32_t *)(sc->sc_cfg_base + 0xe8)); 4142 ddi_put32(sc->sc_cfg_handle, 4143 (uint32_t *)(sc->sc_cfg_base + 0xe8), 4144 tmp & ~(1 << 11)); 4145 } 4146 4147 vlink = ddi_get8(sc->sc_cfg_handle, 4148 (uint8_t *)(sc->sc_cfg_base + 0xf0)); 4149 ddi_put8(sc->sc_cfg_handle, (uint8_t *)(sc->sc_cfg_base + 0xf0), 4150 vlink & ~2); 4151 4152 tmp = IWH_READ(sc, CSR_SW_VER); 4153 tmp |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | 4154 CSR_HW_IF_CONFIG_REG_BIT_MAC_SI; 4155 IWH_WRITE(sc, CSR_SW_VER, tmp); 4156 4157 /* 4158 * make sure power supply on each part of the hardware 4159 */ 4160 iwh_mac_access_enter(sc); 4161 tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL); 4162 tmp |= APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ; 4163 iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4164 DELAY(5); 4165 4166 tmp = iwh_reg_read(sc, ALM_APMG_PS_CTL); 4167 tmp &= ~APMG_PS_CTRL_REG_VAL_ALM_R_RESET_REQ; 4168 iwh_reg_write(sc, ALM_APMG_PS_CTL, tmp); 4169 iwh_mac_access_exit(sc); 4170 4171 return (IWH_SUCCESS); 4172 } 4173 4174 /* 4175 * set up semphore flag to own EEPROM 4176 */ 4177 static int 4178 iwh_eep_sem_down(iwh_sc_t *sc) 4179 { 4180 int count1, count2; 4181 uint32_t tmp; 4182 4183 for (count1 = 0; count1 < 1000; count1++) { 4184 tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG); 4185 IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4186 tmp | CSR_HW_IF_CONFIG_REG_EEP_SEM); 4187 4188 for (count2 = 0; count2 < 2; count2++) { 4189 if (IWH_READ(sc, CSR_HW_IF_CONFIG_REG) & 4190 CSR_HW_IF_CONFIG_REG_EEP_SEM) { 4191 return (IWH_SUCCESS); 4192 } 4193 DELAY(10000); 4194 } 4195 } 4196 return (IWH_FAIL); 4197 } 4198 4199 /* 4200 * reset semphore flag to release EEPROM 4201 */ 4202 static void 4203 iwh_eep_sem_up(iwh_sc_t *sc) 4204 { 4205 uint32_t tmp; 4206 4207 tmp = IWH_READ(sc, CSR_HW_IF_CONFIG_REG); 4208 IWH_WRITE(sc, CSR_HW_IF_CONFIG_REG, 4209 tmp & (~CSR_HW_IF_CONFIG_REG_EEP_SEM)); 4210 } 4211 4212 /* 4213 * This function read all infomation from eeprom 4214 */ 4215 static int 4216 iwh_eep_load(iwh_sc_t *sc) 4217 { 4218 int i, rr; 4219 uint32_t rv, tmp, eep_gp; 4220 uint16_t addr, eep_sz = sizeof (sc->sc_eep_map); 4221 uint16_t *eep_p = (uint16_t *)&sc->sc_eep_map; 4222 4223 /* 4224 * read eeprom gp register in CSR 4225 */ 4226 eep_gp = IWH_READ(sc, CSR_EEPROM_GP); 4227 if ((eep_gp & CSR_EEPROM_GP_VALID_MSK) == 4228 CSR_EEPROM_GP_BAD_SIGNATURE) { 4229 IWH_DBG((IWH_DEBUG_EEPROM, "not find eeprom\n")); 4230 return (IWH_FAIL); 4231 } 4232 4233 rr = iwh_eep_sem_down(sc); 4234 if (rr != 0) { 4235 IWH_DBG((IWH_DEBUG_EEPROM, "driver failed to own EEPROM\n")); 4236 return (IWH_FAIL); 4237 } 4238 4239 for (addr = 0; addr < eep_sz; addr += 2) { 4240 IWH_WRITE(sc, CSR_EEPROM_REG, addr<<1); 4241 tmp = IWH_READ(sc, CSR_EEPROM_REG); 4242 IWH_WRITE(sc, CSR_EEPROM_REG, tmp & ~(0x2)); 4243 4244 for (i = 0; i < 10; i++) { 4245 rv = IWH_READ(sc, CSR_EEPROM_REG); 4246 if (rv & 1) { 4247 break; 4248 } 4249 DELAY(10); 4250 } 4251 4252 if (!(rv & 1)) { 4253 IWH_DBG((IWH_DEBUG_EEPROM, 4254 "time out when read eeprome\n")); 4255 iwh_eep_sem_up(sc); 4256 return (IWH_FAIL); 4257 } 4258 4259 eep_p[addr/2] = rv >> 16; 4260 } 4261 4262 iwh_eep_sem_up(sc); 4263 return (IWH_SUCCESS); 4264 } 4265 4266 /* 4267 * initialize mac address in ieee80211com_t struct 4268 */ 4269 static void 4270 iwh_get_mac_from_eep(iwh_sc_t *sc) 4271 { 4272 ieee80211com_t *ic = &sc->sc_ic; 4273 4274 IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->sc_eep_map[EEP_MAC_ADDRESS]); 4275 4276 IWH_DBG((IWH_DEBUG_EEPROM, "mac:%2x:%2x:%2x:%2x:%2x:%2x\n", 4277 ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2], 4278 ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5])); 4279 } 4280 4281 /* 4282 * main initialization function 4283 */ 4284 static int 4285 iwh_init(iwh_sc_t *sc) 4286 { 4287 int n, err; 4288 clock_t clk; 4289 4290 /* 4291 * release buffer for calibration 4292 */ 4293 iwh_release_calib_buffer(sc); 4294 4295 mutex_enter(&sc->sc_glock); 4296 sc->sc_flags &= ~IWH_F_FW_INIT; 4297 4298 err = iwh_init_common(sc); 4299 if (err != IWH_SUCCESS) { 4300 cmn_err(CE_WARN, "iwh_init(): " 4301 "failed to initialize chipset\n"); 4302 mutex_exit(&sc->sc_glock); 4303 return (IWH_FAIL); 4304 } 4305 4306 /* 4307 * backup ucode data part for future use. 4308 */ 4309 (void) memcpy(sc->sc_dma_fw_data_bak.mem_va, 4310 sc->sc_dma_fw_data.mem_va, 4311 sc->sc_dma_fw_data.alength); 4312 4313 for (n = 0; n < 2; n++) { 4314 /* load firmware init segment into NIC */ 4315 err = iwh_load_init_firmware(sc); 4316 if (err != IWH_SUCCESS) { 4317 cmn_err(CE_WARN, "iwh_init(): " 4318 "failed to setup init firmware\n"); 4319 continue; 4320 } 4321 4322 /* 4323 * now press "execute" start running 4324 */ 4325 IWH_WRITE(sc, CSR_RESET, 0); 4326 break; 4327 } 4328 4329 mutex_exit(&sc->sc_glock); 4330 4331 if (2 == n) { 4332 cmn_err(CE_WARN, "iwh_init(): " 4333 "failed to load init firmware\n"); 4334 return (IWH_FAIL); 4335 } 4336 4337 mutex_enter(&sc->sc_ucode_lock); 4338 4339 clk = ddi_get_lbolt() + drv_usectohz(1000000); 4340 while (!(sc->sc_flags & IWH_F_FW_INIT)) { 4341 if (cv_timedwait(&sc->sc_ucode_cv, 4342 &sc->sc_ucode_lock, clk) < 0) { 4343 break; 4344 } 4345 } 4346 4347 if (!(sc->sc_flags & IWH_F_FW_INIT)) { 4348 cmn_err(CE_WARN, "iwh_init(): " 4349 "failed to process init alive.\n"); 4350 mutex_exit(&sc->sc_ucode_lock); 4351 return (IWH_FAIL); 4352 } 4353 4354 mutex_exit(&sc->sc_ucode_lock); 4355 4356 /* 4357 * stop chipset for initializing chipset again 4358 */ 4359 iwh_stop(sc); 4360 4361 mutex_enter(&sc->sc_glock); 4362 sc->sc_flags &= ~IWH_F_FW_INIT; 4363 4364 err = iwh_init_common(sc); 4365 if (err != IWH_SUCCESS) { 4366 cmn_err(CE_WARN, "iwh_init(): " 4367 "failed to initialize chipset\n"); 4368 mutex_exit(&sc->sc_glock); 4369 return (IWH_FAIL); 4370 } 4371 4372 for (n = 0; n < 2; n++) { 4373 /* 4374 * load firmware run segment into NIC 4375 */ 4376 err = iwh_load_run_firmware(sc); 4377 if (err != IWH_SUCCESS) { 4378 cmn_err(CE_WARN, "iwh_init(): " 4379 "failed to setup run firmware\n"); 4380 continue; 4381 } 4382 4383 /* 4384 * now press "execute" start running 4385 */ 4386 IWH_WRITE(sc, CSR_RESET, 0); 4387 break; 4388 } 4389 4390 mutex_exit(&sc->sc_glock); 4391 4392 if (2 == n) { 4393 cmn_err(CE_WARN, "iwh_init(): " 4394 "failed to load run firmware\n"); 4395 return (IWH_FAIL); 4396 } 4397 4398 mutex_enter(&sc->sc_ucode_lock); 4399 4400 clk = ddi_get_lbolt() + drv_usectohz(1000000); 4401 while (!(sc->sc_flags & IWH_F_FW_INIT)) { 4402 if (cv_timedwait(&sc->sc_ucode_cv, 4403 &sc->sc_ucode_lock, clk) < 0) { 4404 break; 4405 } 4406 } 4407 4408 if (!(sc->sc_flags & IWH_F_FW_INIT)) { 4409 cmn_err(CE_WARN, "iwh_init(): " 4410 "failed to process runtime alive.\n"); 4411 mutex_exit(&sc->sc_ucode_lock); 4412 return (IWH_FAIL); 4413 } 4414 4415 mutex_exit(&sc->sc_ucode_lock); 4416 4417 mutex_enter(&sc->sc_glock); 4418 sc->sc_flags &= ~IWH_F_FW_INIT; 4419 4420 /* 4421 * at this point, the firmware is loaded OK, then config the hardware 4422 * with the ucode API, including rxon, txpower, etc. 4423 */ 4424 err = iwh_config(sc); 4425 if (err) { 4426 cmn_err(CE_WARN, "iwh_init(): " 4427 "failed to configure device\n"); 4428 mutex_exit(&sc->sc_glock); 4429 return (IWH_FAIL); 4430 } 4431 4432 /* 4433 * at this point, hardware may receive beacons :) 4434 */ 4435 mutex_exit(&sc->sc_glock); 4436 return (IWH_SUCCESS); 4437 } 4438 4439 /* 4440 * stop or disable NIC 4441 */ 4442 static void 4443 iwh_stop(iwh_sc_t *sc) 4444 { 4445 uint32_t tmp; 4446 int i; 4447 4448 mutex_enter(&sc->sc_glock); 4449 4450 IWH_WRITE(sc, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); 4451 /* 4452 * disable interrupts 4453 */ 4454 IWH_WRITE(sc, CSR_INT_MASK, 0); 4455 IWH_WRITE(sc, CSR_INT, CSR_INI_SET_MASK); 4456 IWH_WRITE(sc, CSR_FH_INT_STATUS, 0xffffffff); 4457 4458 /* 4459 * reset all Tx rings 4460 */ 4461 for (i = 0; i < IWH_NUM_QUEUES; i++) { 4462 iwh_reset_tx_ring(sc, &sc->sc_txq[i]); 4463 } 4464 4465 /* 4466 * reset Rx ring 4467 */ 4468 iwh_reset_rx_ring(sc); 4469 4470 iwh_mac_access_enter(sc); 4471 iwh_reg_write(sc, ALM_APMG_CLK_DIS, APMG_CLK_REG_VAL_DMA_CLK_RQT); 4472 iwh_mac_access_exit(sc); 4473 4474 DELAY(5); 4475 4476 iwh_stop_master(sc); 4477 4478 sc->sc_tx_timer = 0; 4479 tmp = IWH_READ(sc, CSR_RESET); 4480 IWH_WRITE(sc, CSR_RESET, tmp | CSR_RESET_REG_FLAG_SW_RESET); 4481 4482 mutex_exit(&sc->sc_glock); 4483 } 4484 4485 /* 4486 * Naive implementation of the Adaptive Multi Rate Retry algorithm: 4487 * "IEEE 802.11 Rate Adaptation: A Practical Approach" 4488 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti 4489 * INRIA Sophia - Projet Planete 4490 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html 4491 */ 4492 #define is_success(amrr) \ 4493 ((amrr)->retrycnt < (amrr)->txcnt / 10) 4494 #define is_failure(amrr) \ 4495 ((amrr)->retrycnt > (amrr)->txcnt / 3) 4496 #define is_enough(amrr) \ 4497 ((amrr)->txcnt > 100) 4498 #define is_min_rate(in) \ 4499 (0 == (in)->in_txrate) 4500 #define is_max_rate(in) \ 4501 ((in)->in_rates.ir_nrates - 1 == (in)->in_txrate) 4502 #define increase_rate(in) \ 4503 ((in)->in_txrate++) 4504 #define decrease_rate(in) \ 4505 ((in)->in_txrate--) 4506 #define reset_cnt(amrr) \ 4507 { (amrr)->txcnt = (amrr)->retrycnt = 0; } 4508 4509 #define IWH_AMRR_MIN_SUCCESS_THRESHOLD 1 4510 #define IWH_AMRR_MAX_SUCCESS_THRESHOLD 15 4511 4512 static void 4513 iwh_amrr_init(iwh_amrr_t *amrr) 4514 { 4515 amrr->success = 0; 4516 amrr->recovery = 0; 4517 amrr->txcnt = amrr->retrycnt = 0; 4518 amrr->success_threshold = IWH_AMRR_MIN_SUCCESS_THRESHOLD; 4519 } 4520 4521 static void 4522 iwh_amrr_timeout(iwh_sc_t *sc) 4523 { 4524 ieee80211com_t *ic = &sc->sc_ic; 4525 4526 IWH_DBG((IWH_DEBUG_RATECTL, "iwh_amrr_timeout() enter\n")); 4527 4528 if (IEEE80211_M_STA == ic->ic_opmode) { 4529 iwh_amrr_ratectl(NULL, ic->ic_bss); 4530 } else { 4531 ieee80211_iterate_nodes(&ic->ic_sta, iwh_amrr_ratectl, NULL); 4532 } 4533 4534 sc->sc_clk = ddi_get_lbolt(); 4535 } 4536 4537 static void 4538 /* LINTED: argument unused in function: arg */ 4539 iwh_amrr_ratectl(void *arg, ieee80211_node_t *in) 4540 { 4541 iwh_amrr_t *amrr = (iwh_amrr_t *)in; 4542 int need_change = 0; 4543 4544 if (is_success(amrr) && is_enough(amrr)) { 4545 amrr->success++; 4546 if (amrr->success >= amrr->success_threshold && 4547 !is_max_rate(in)) { 4548 amrr->recovery = 1; 4549 amrr->success = 0; 4550 increase_rate(in); 4551 IWH_DBG((IWH_DEBUG_RATECTL, 4552 "AMRR increasing rate %d (txcnt=%d retrycnt=%d)\n", 4553 in->in_txrate, amrr->txcnt, amrr->retrycnt)); 4554 need_change = 1; 4555 } else { 4556 amrr->recovery = 0; 4557 } 4558 } else if (is_failure(amrr)) { 4559 amrr->success = 0; 4560 if (!is_min_rate(in)) { 4561 if (amrr->recovery) { 4562 amrr->success_threshold++; 4563 if (amrr->success_threshold > 4564 IWH_AMRR_MAX_SUCCESS_THRESHOLD) { 4565 amrr->success_threshold = 4566 IWH_AMRR_MAX_SUCCESS_THRESHOLD; 4567 } 4568 } else { 4569 amrr->success_threshold = 4570 IWH_AMRR_MIN_SUCCESS_THRESHOLD; 4571 } 4572 decrease_rate(in); 4573 IWH_DBG((IWH_DEBUG_RATECTL, 4574 "AMRR decreasing rate %d (txcnt=%d retrycnt=%d)\n", 4575 in->in_txrate, amrr->txcnt, amrr->retrycnt)); 4576 need_change = 1; 4577 } 4578 amrr->recovery = 0; /* paper is incorrect */ 4579 } 4580 4581 if (is_enough(amrr) || need_change) { 4582 reset_cnt(amrr); 4583 } 4584 } 4585 4586 /* 4587 * translate indirect address in eeprom to direct address 4588 * in eeprom and return address of entry whos indirect address 4589 * is indi_addr 4590 */ 4591 static uint8_t * 4592 iwh_eep_addr_trans(iwh_sc_t *sc, uint32_t indi_addr) 4593 { 4594 uint32_t di_addr; 4595 uint16_t temp; 4596 4597 if (!(indi_addr & INDIRECT_ADDRESS)) { 4598 di_addr = indi_addr; 4599 return (&sc->sc_eep_map[di_addr]); 4600 } 4601 4602 switch (indi_addr & INDIRECT_TYPE_MSK) { 4603 case INDIRECT_GENERAL: 4604 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_GENERAL); 4605 break; 4606 4607 case INDIRECT_HOST: 4608 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_HOST); 4609 break; 4610 4611 case INDIRECT_REGULATORY: 4612 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_REGULATORY); 4613 break; 4614 4615 case INDIRECT_CALIBRATION: 4616 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_CALIBRATION); 4617 break; 4618 4619 case INDIRECT_PROCESS_ADJST: 4620 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_PROCESS_ADJST); 4621 break; 4622 4623 case INDIRECT_OTHERS: 4624 temp = IWH_READ_EEP_SHORT(sc, EEP_LINK_OTHERS); 4625 break; 4626 4627 default: 4628 temp = 0; 4629 cmn_err(CE_WARN, "iwh_eep_addr_trans(): " 4630 "incorrect indirect eeprom address.\n"); 4631 break; 4632 } 4633 4634 di_addr = (indi_addr & ADDRESS_MSK) + (temp << 1); 4635 4636 return (&sc->sc_eep_map[di_addr]); 4637 } 4638 4639 /* 4640 * loade a section of ucode into NIC 4641 */ 4642 static int 4643 iwh_put_seg_fw(iwh_sc_t *sc, uint32_t addr_s, uint32_t addr_d, uint32_t len) 4644 { 4645 4646 iwh_mac_access_enter(sc); 4647 4648 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(IWH_FH_SRVC_CHNL), 4649 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); 4650 4651 IWH_WRITE(sc, IWH_FH_SRVC_CHNL_SRAM_ADDR_REG(IWH_FH_SRVC_CHNL), addr_d); 4652 4653 IWH_WRITE(sc, IWH_FH_TFDIB_CTRL0_REG(IWH_FH_SRVC_CHNL), 4654 (addr_s & FH_MEM_TFDIB_DRAM_ADDR_LSB_MASK)); 4655 4656 IWH_WRITE(sc, IWH_FH_TFDIB_CTRL1_REG(IWH_FH_SRVC_CHNL), len); 4657 4658 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_BUF_STS_REG(IWH_FH_SRVC_CHNL), 4659 (1 << IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM) | 4660 (1 << IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX) | 4661 IWH_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); 4662 4663 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(IWH_FH_SRVC_CHNL), 4664 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | 4665 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL | 4666 IWH_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); 4667 4668 iwh_mac_access_exit(sc); 4669 4670 return (IWH_SUCCESS); 4671 } 4672 4673 /* 4674 * necessary setting during alive notification 4675 */ 4676 static int 4677 iwh_alive_common(iwh_sc_t *sc) 4678 { 4679 uint32_t base; 4680 uint32_t i; 4681 iwh_wimax_coex_cmd_t w_cmd; 4682 iwh_calibration_crystal_cmd_t c_cmd; 4683 uint32_t rv; 4684 4685 /* 4686 * initialize SCD related registers to make TX work. 4687 */ 4688 iwh_mac_access_enter(sc); 4689 4690 /* 4691 * read sram address of data base. 4692 */ 4693 sc->sc_scd_base = iwh_reg_read(sc, IWH_SCD_SRAM_BASE_ADDR); 4694 4695 for (base = sc->sc_scd_base + IWH_SCD_CONTEXT_DATA_OFFSET; 4696 base < sc->sc_scd_base + IWH_SCD_TX_STTS_BITMAP_OFFSET; 4697 base += 4) { 4698 iwh_mem_write(sc, base, 0); 4699 } 4700 4701 for (; base < sc->sc_scd_base + IWH_SCD_TRANSLATE_TBL_OFFSET; 4702 base += 4) { 4703 iwh_mem_write(sc, base, 0); 4704 } 4705 4706 for (i = 0; i < sizeof (uint16_t) * IWH_NUM_QUEUES; i += 4) { 4707 iwh_mem_write(sc, base + i, 0); 4708 } 4709 4710 iwh_reg_write(sc, IWH_SCD_DRAM_BASE_ADDR, 4711 sc->sc_dma_sh.cookie.dmac_address >> 10); 4712 4713 iwh_reg_write(sc, IWH_SCD_QUEUECHAIN_SEL, 4714 IWH_SCD_QUEUECHAIN_SEL_ALL(IWH_NUM_QUEUES)); 4715 4716 iwh_reg_write(sc, IWH_SCD_AGGR_SEL, 0); 4717 4718 for (i = 0; i < IWH_NUM_QUEUES; i++) { 4719 iwh_reg_write(sc, IWH_SCD_QUEUE_RDPTR(i), 0); 4720 IWH_WRITE(sc, HBUS_TARG_WRPTR, 0 | (i << 8)); 4721 iwh_mem_write(sc, sc->sc_scd_base + 4722 IWH_SCD_CONTEXT_QUEUE_OFFSET(i), 0); 4723 iwh_mem_write(sc, sc->sc_scd_base + 4724 IWH_SCD_CONTEXT_QUEUE_OFFSET(i) + 4725 sizeof (uint32_t), 4726 ((SCD_WIN_SIZE << IWH_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & 4727 IWH_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | 4728 ((SCD_FRAME_LIMIT << 4729 IWH_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & 4730 IWH_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); 4731 } 4732 4733 iwh_reg_write(sc, IWH_SCD_INTERRUPT_MASK, (1 << IWH_NUM_QUEUES) - 1); 4734 4735 iwh_reg_write(sc, (IWH_SCD_BASE + 0x10), 4736 SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); 4737 4738 IWH_WRITE(sc, HBUS_TARG_WRPTR, (IWH_CMD_QUEUE_NUM << 8)); 4739 iwh_reg_write(sc, IWH_SCD_QUEUE_RDPTR(IWH_CMD_QUEUE_NUM), 0); 4740 4741 /* 4742 * queue 0-7 map to FIFO 0-7 and 4743 * all queues work under FIFO mode(none-scheduler_ack) 4744 */ 4745 for (i = 0; i < 4; i++) { 4746 iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(i), 4747 (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 4748 ((3-i) << IWH_SCD_QUEUE_STTS_REG_POS_TXF) | 4749 (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) | 4750 IWH_SCD_QUEUE_STTS_REG_MSK); 4751 } 4752 4753 iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(IWH_CMD_QUEUE_NUM), 4754 (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 4755 (IWH_CMD_FIFO_NUM << IWH_SCD_QUEUE_STTS_REG_POS_TXF) | 4756 (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) | 4757 IWH_SCD_QUEUE_STTS_REG_MSK); 4758 4759 for (i = 5; i < 7; i++) { 4760 iwh_reg_write(sc, IWH_SCD_QUEUE_STATUS_BITS(i), 4761 (1 << IWH_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 4762 (i << IWH_SCD_QUEUE_STTS_REG_POS_TXF) | 4763 (1 << IWH_SCD_QUEUE_STTS_REG_POS_WSL) | 4764 IWH_SCD_QUEUE_STTS_REG_MSK); 4765 } 4766 4767 iwh_mac_access_exit(sc); 4768 4769 (void) memset(&w_cmd, 0, sizeof (w_cmd)); 4770 4771 rv = iwh_cmd(sc, COEX_PRIORITY_TABLE_CMD, &w_cmd, sizeof (w_cmd), 1); 4772 if (rv != IWH_SUCCESS) { 4773 cmn_err(CE_WARN, "iwh_alive_common(): " 4774 "failed to send wimax coexist command.\n"); 4775 return (rv); 4776 } 4777 4778 (void) memset(&c_cmd, 0, sizeof (c_cmd)); 4779 4780 c_cmd.opCode = PHY_CALIBRATE_CRYSTAL_FRQ_CMD; 4781 c_cmd.data.cap_pin1 = sc->sc_eep_calib->xtal_calib[0]; 4782 c_cmd.data.cap_pin2 = sc->sc_eep_calib->xtal_calib[1]; 4783 4784 rv = iwh_cmd(sc, REPLY_PHY_CALIBRATION_CMD, &c_cmd, sizeof (c_cmd), 1); 4785 if (rv != IWH_SUCCESS) { 4786 cmn_err(CE_WARN, "iwh_alive_common(): " 4787 "failed to send crystal frq calibration command.\n"); 4788 return (rv); 4789 } 4790 4791 /* 4792 * make sure crystal frequency calibration ready 4793 * before next operations. 4794 */ 4795 DELAY(1000); 4796 4797 return (IWH_SUCCESS); 4798 } 4799 4800 /* 4801 * save results of calibration from ucode 4802 */ 4803 static void 4804 iwh_save_calib_result(iwh_sc_t *sc, iwh_rx_desc_t *desc) 4805 { 4806 struct iwh_calib_results *res_p = &sc->sc_calib_results; 4807 struct iwh_calib_hdr *calib_hdr = (struct iwh_calib_hdr *)(desc + 1); 4808 int len = desc->len; 4809 4810 /* 4811 * ensure the size of buffer is not too big 4812 */ 4813 len = (len & FH_RSCSR_FRAME_SIZE_MASK) - 4; 4814 4815 switch (calib_hdr->op_code) { 4816 case PHY_CALIBRATE_LO_CMD: 4817 if (NULL == res_p->lo_res) { 4818 res_p->lo_res = kmem_alloc(len, KM_NOSLEEP); 4819 } 4820 4821 if (NULL == res_p->lo_res) { 4822 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4823 "failed to allocate memory.\n"); 4824 return; 4825 } 4826 4827 res_p->lo_res_len = len; 4828 (void) memcpy(res_p->lo_res, calib_hdr, len); 4829 break; 4830 4831 case PHY_CALIBRATE_TX_IQ_CMD: 4832 if (NULL == res_p->tx_iq_res) { 4833 res_p->tx_iq_res = kmem_alloc(len, KM_NOSLEEP); 4834 } 4835 4836 if (NULL == res_p->tx_iq_res) { 4837 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4838 "failed to allocate memory.\n"); 4839 return; 4840 } 4841 4842 res_p->tx_iq_res_len = len; 4843 (void) memcpy(res_p->tx_iq_res, calib_hdr, len); 4844 break; 4845 4846 case PHY_CALIBRATE_TX_IQ_PERD_CMD: 4847 if (NULL == res_p->tx_iq_perd_res) { 4848 res_p->tx_iq_perd_res = kmem_alloc(len, KM_NOSLEEP); 4849 } 4850 4851 if (NULL == res_p->tx_iq_perd_res) { 4852 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4853 "failed to allocate memory.\n"); 4854 } 4855 4856 res_p->tx_iq_perd_res_len = len; 4857 (void) memcpy(res_p->tx_iq_perd_res, calib_hdr, len); 4858 break; 4859 4860 default: 4861 cmn_err(CE_WARN, "iwh_save_calib_result(): " 4862 "incorrect calibration type.\n"); 4863 break; 4864 } 4865 4866 } 4867 4868 /* 4869 * configure TX pwoer table 4870 */ 4871 static int 4872 iwh_tx_power_table(iwh_sc_t *sc, int async) 4873 { 4874 iwh_tx_power_table_cmd_t txpower; 4875 int i, err; 4876 4877 (void) memset(&txpower, 0, sizeof (txpower)); 4878 4879 txpower.band = 1; /* for 2.4G */ 4880 txpower.channel = sc->sc_config.chan; 4881 txpower.pa_measurements = 1; 4882 txpower.max_mcs = 23; 4883 4884 for (i = 0; i < 24; i++) { 4885 txpower.db.ht_ofdm_power[i].s.radio_tx_gain[0] = 0x16; 4886 txpower.db.ht_ofdm_power[i].s.radio_tx_gain[1] = 0x16; 4887 txpower.db.ht_ofdm_power[i].s.radio_tx_gain[2] = 0x16; 4888 txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[0] = 0x6E; 4889 txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[1] = 0x6E; 4890 txpower.db.ht_ofdm_power[i].s.dsp_predis_atten[2] = 0x6E; 4891 } 4892 4893 for (i = 0; i < 2; i++) { 4894 txpower.db.cck_power[i].s.radio_tx_gain[0] = 0x16; 4895 txpower.db.cck_power[i].s.radio_tx_gain[1] = 0x16; 4896 txpower.db.cck_power[i].s.radio_tx_gain[2] = 0x16; 4897 txpower.db.cck_power[i].s.dsp_predis_atten[0] = 0x6E; 4898 txpower.db.cck_power[i].s.dsp_predis_atten[1] = 0x6E; 4899 txpower.db.cck_power[i].s.dsp_predis_atten[2] = 0x6E; 4900 } 4901 4902 err = iwh_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &txpower, 4903 sizeof (txpower), async); 4904 if (err != IWH_SUCCESS) { 4905 cmn_err(CE_WARN, "iwh_tx_power_table(): " 4906 "failed to set tx power table.\n"); 4907 return (err); 4908 } 4909 4910 return (IWH_SUCCESS); 4911 } 4912 4913 static void 4914 iwh_release_calib_buffer(iwh_sc_t *sc) 4915 { 4916 if (sc->sc_calib_results.lo_res != NULL) { 4917 kmem_free(sc->sc_calib_results.lo_res, 4918 sc->sc_calib_results.lo_res_len); 4919 sc->sc_calib_results.lo_res = NULL; 4920 } 4921 4922 if (sc->sc_calib_results.tx_iq_res != NULL) { 4923 kmem_free(sc->sc_calib_results.tx_iq_res, 4924 sc->sc_calib_results.tx_iq_res_len); 4925 sc->sc_calib_results.tx_iq_res = NULL; 4926 } 4927 4928 if (sc->sc_calib_results.tx_iq_perd_res != NULL) { 4929 kmem_free(sc->sc_calib_results.tx_iq_perd_res, 4930 sc->sc_calib_results.tx_iq_perd_res_len); 4931 sc->sc_calib_results.tx_iq_perd_res = NULL; 4932 } 4933 4934 } 4935 4936 /* 4937 * a section of intialization 4938 */ 4939 static int 4940 iwh_init_common(iwh_sc_t *sc) 4941 { 4942 int32_t qid; 4943 uint32_t tmp; 4944 4945 (void) iwh_preinit(sc); 4946 4947 tmp = IWH_READ(sc, CSR_GP_CNTRL); 4948 if (!(tmp & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) { 4949 cmn_err(CE_WARN, "iwh_init_common(): " 4950 "radio transmitter is off\n"); 4951 return (IWH_FAIL); 4952 } 4953 4954 /* 4955 * init Rx ring 4956 */ 4957 iwh_mac_access_enter(sc); 4958 IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 4959 4960 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); 4961 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_BASE_REG, 4962 sc->sc_rxq.dma_desc.cookie.dmac_address >> 8); 4963 4964 IWH_WRITE(sc, FH_RSCSR_CHNL0_STTS_WPTR_REG, 4965 ((uint32_t)(sc->sc_dma_sh.cookie.dmac_address + 4966 offsetof(struct iwh_shared, val0)) >> 4)); 4967 4968 IWH_WRITE(sc, FH_MEM_RCSR_CHNL0_CONFIG_REG, 4969 FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | 4970 FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | 4971 IWH_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K | 4972 (RX_QUEUE_SIZE_LOG << 4973 FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); 4974 iwh_mac_access_exit(sc); 4975 IWH_WRITE(sc, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 4976 (RX_QUEUE_SIZE - 1) & ~0x7); 4977 4978 /* 4979 * init Tx rings 4980 */ 4981 iwh_mac_access_enter(sc); 4982 iwh_reg_write(sc, IWH_SCD_TXFACT, 0); 4983 4984 /* 4985 * keep warm page 4986 */ 4987 IWH_WRITE(sc, IWH_FH_KW_MEM_ADDR_REG, 4988 sc->sc_dma_kw.cookie.dmac_address >> 4); 4989 4990 for (qid = 0; qid < IWH_NUM_QUEUES; qid++) { 4991 IWH_WRITE(sc, FH_MEM_CBBC_QUEUE(qid), 4992 sc->sc_txq[qid].dma_desc.cookie.dmac_address >> 8); 4993 IWH_WRITE(sc, IWH_FH_TCSR_CHNL_TX_CONFIG_REG(qid), 4994 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | 4995 IWH_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL); 4996 } 4997 4998 iwh_mac_access_exit(sc); 4999 5000 /* 5001 * clear "radio off" and "disable command" bits 5002 */ 5003 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 5004 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, 5005 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); 5006 5007 /* 5008 * clear any pending interrupts 5009 */ 5010 IWH_WRITE(sc, CSR_INT, 0xffffffff); 5011 5012 /* 5013 * enable interrupts 5014 */ 5015 IWH_WRITE(sc, CSR_INT_MASK, CSR_INI_SET_MASK); 5016 5017 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 5018 IWH_WRITE(sc, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); 5019 5020 return (IWH_SUCCESS); 5021 } 5022