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