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