1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 2004 David Young. All rights reserved. 8 * 9 * This code was written by David Young. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the author nor the names of any co-contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY 24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David 27 * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 34 * OF SUCH DAMAGE. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/types.h> 39 #include <sys/signal.h> 40 #include <sys/stream.h> 41 #include <sys/termio.h> 42 #include <sys/errno.h> 43 #include <sys/file.h> 44 #include <sys/cmn_err.h> 45 #include <sys/stropts.h> 46 #include <sys/strtty.h> 47 #include <sys/kbio.h> 48 #include <sys/cred.h> 49 #include <sys/stat.h> 50 #include <sys/consdev.h> 51 #include <sys/kmem.h> 52 #include <sys/modctl.h> 53 #include <sys/ddi.h> 54 #include <sys/sunddi.h> 55 #include <sys/pci.h> 56 #include <sys/errno.h> 57 #include <sys/mac.h> 58 #include <sys/dlpi.h> 59 #include <sys/ethernet.h> 60 #include <sys/list.h> 61 #include <sys/byteorder.h> 62 #include <sys/strsun.h> 63 #include <sys/strsubr.h> 64 #include <sys/policy.h> 65 #include <inet/common.h> 66 #include <inet/nd.h> 67 #include <inet/mi.h> 68 #include <inet/wifi_ioctl.h> 69 #include <sys/mac_wifi.h> 70 #include <sys/crypto/common.h> 71 #include <sys/crypto/api.h> 72 73 #include "rtwreg.h" 74 #include "rtwvar.h" 75 #include "smc93cx6var.h" 76 #include "rtwphy.h" 77 #include "rtwphyio.h" 78 79 /* 80 * PIO access attributes for registers 81 */ 82 static ddi_device_acc_attr_t rtw_reg_accattr = { 83 DDI_DEVICE_ATTR_V0, 84 DDI_STRUCTURE_LE_ACC, 85 DDI_STRICTORDER_ACC, 86 DDI_DEFAULT_ACC 87 }; 88 89 /* 90 * DMA access attributes for descriptors and bufs: NOT to be byte swapped. 91 */ 92 static ddi_device_acc_attr_t rtw_desc_accattr = { 93 DDI_DEVICE_ATTR_V0, 94 DDI_NEVERSWAP_ACC, 95 DDI_STRICTORDER_ACC, 96 DDI_DEFAULT_ACC 97 }; 98 static ddi_device_acc_attr_t rtw_buf_accattr = { 99 DDI_DEVICE_ATTR_V0, 100 DDI_NEVERSWAP_ACC, 101 DDI_STRICTORDER_ACC, 102 DDI_DEFAULT_ACC 103 }; 104 105 /* 106 * Describes the chip's DMA engine 107 */ 108 static ddi_dma_attr_t dma_attr_desc = { 109 DMA_ATTR_V0, /* dma_attr version */ 110 0x0000000000000000ull, /* dma_attr_addr_lo */ 111 0xFFFFFFFF, /* dma_attr_addr_hi */ 112 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 113 0x100, /* dma_attr_align */ 114 0xFFFFFFFF, /* dma_attr_burstsizes */ 115 0x00000001, /* dma_attr_minxfer */ 116 0x00000000FFFFull, /* dma_attr_maxxfer */ 117 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 118 1, /* dma_attr_sgllen */ 119 1, /* dma_attr_granular */ 120 0 /* dma_attr_flags */ 121 }; 122 123 static ddi_dma_attr_t dma_attr_rxbuf = { 124 DMA_ATTR_V0, /* dma_attr version */ 125 0x0000000000000000ull, /* dma_attr_addr_lo */ 126 0xFFFFFFFF, /* dma_attr_addr_hi */ 127 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 128 (uint32_t)16, /* dma_attr_align */ 129 0xFFFFFFFF, /* dma_attr_burstsizes */ 130 0x00000001, /* dma_attr_minxfer */ 131 0x00000000FFFFull, /* dma_attr_maxxfer */ 132 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 133 1, /* dma_attr_sgllen */ 134 1, /* dma_attr_granular */ 135 0 /* dma_attr_flags */ 136 }; 137 138 static ddi_dma_attr_t dma_attr_txbuf = { 139 DMA_ATTR_V0, /* dma_attr version */ 140 0x0000000000000000ull, /* dma_attr_addr_lo */ 141 0xFFFFFFFF, /* dma_attr_addr_hi */ 142 0x00000000FFFFFFFFull, /* dma_attr_count_max */ 143 (uint32_t)16, /* dma_attr_align */ 144 0xFFFFFFFF, /* dma_attr_burstsizes */ 145 0x00000001, /* dma_attr_minxfer */ 146 0x00000000FFFFull, /* dma_attr_maxxfer */ 147 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */ 148 1, /* dma_attr_sgllen */ 149 1, /* dma_attr_granular */ 150 0 /* dma_attr_flags */ 151 }; 152 153 154 static void *rtw_soft_state_p = NULL; 155 156 static int rtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd); 157 static int rtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd); 158 static int rtw_quiesce(dev_info_t *dip); 159 static int rtw_m_stat(void *, uint_t, uint64_t *); 160 static int rtw_m_start(void *); 161 static void rtw_m_stop(void *); 162 static int rtw_m_promisc(void *, boolean_t); 163 static int rtw_m_multicst(void *, boolean_t, const uint8_t *); 164 static int rtw_m_unicst(void *, const uint8_t *); 165 static mblk_t *rtw_m_tx(void *, mblk_t *); 166 static void rtw_m_ioctl(void *, queue_t *, mblk_t *); 167 static int rtw_m_setprop(void *, const char *, mac_prop_id_t, 168 uint_t, const void *); 169 static int rtw_m_getprop(void *, const char *, mac_prop_id_t, 170 uint_t, uint_t, void *, uint_t *); 171 172 static mac_callbacks_t rtw_m_callbacks = { 173 MC_IOCTL | MC_SETPROP | MC_GETPROP, 174 rtw_m_stat, 175 rtw_m_start, 176 rtw_m_stop, 177 rtw_m_promisc, 178 rtw_m_multicst, 179 rtw_m_unicst, 180 rtw_m_tx, 181 NULL, 182 rtw_m_ioctl, 183 NULL, /* mc_getcapab */ 184 NULL, 185 NULL, 186 rtw_m_setprop, 187 rtw_m_getprop 188 }; 189 190 DDI_DEFINE_STREAM_OPS(rtw_dev_ops, nulldev, nulldev, rtw_attach, rtw_detach, 191 nodev, NULL, D_MP, NULL, rtw_quiesce); 192 193 static struct modldrv rtw_modldrv = { 194 &mod_driverops, /* Type of module. This one is a driver */ 195 "realtek 802.11b driver", /* short description */ 196 &rtw_dev_ops /* driver specific ops */ 197 }; 198 199 static struct modlinkage modlinkage = { 200 MODREV_1, (void *)&rtw_modldrv, NULL 201 }; 202 203 static uint32_t rtw_qlen[RTW_NTXPRI] = { 204 RTW_TXQLENLO, 205 RTW_TXQLENMD, 206 RTW_TXQLENHI, 207 RTW_TXQLENBCN 208 }; 209 210 uint32_t rtw_dbg_flags = 0; 211 /* 212 * RTW_DEBUG_ATTACH | RTW_DEBUG_TUNE | 213 * RTW_DEBUG_ACCESS | RTW_DEBUG_INIT | RTW_DEBUG_PKTFILT | 214 * RTW_DEBUG_RECV | RTW_DEBUG_XMIT | RTW_DEBUG_80211 | RTW_DEBUG_INTR | 215 * RTW_DEBUG_PKTDUMP; 216 */ 217 218 /* 219 * Supported rates for 802.11b modes (in 500Kbps unit). 220 */ 221 static const struct ieee80211_rateset rtw_rateset_11b = 222 { 4, { 2, 4, 11, 22 } }; 223 224 int 225 _info(struct modinfo *modinfop) 226 { 227 return (mod_info(&modlinkage, modinfop)); 228 } 229 230 int 231 _init(void) 232 { 233 int status; 234 235 status = ddi_soft_state_init(&rtw_soft_state_p, 236 sizeof (rtw_softc_t), 1); 237 if (status != 0) 238 return (status); 239 240 mac_init_ops(&rtw_dev_ops, "rtw"); 241 status = mod_install(&modlinkage); 242 if (status != 0) { 243 mac_fini_ops(&rtw_dev_ops); 244 ddi_soft_state_fini(&rtw_soft_state_p); 245 } 246 return (status); 247 } 248 249 int 250 _fini(void) 251 { 252 int status; 253 254 status = mod_remove(&modlinkage); 255 if (status == 0) { 256 mac_fini_ops(&rtw_dev_ops); 257 ddi_soft_state_fini(&rtw_soft_state_p); 258 } 259 return (status); 260 } 261 262 void 263 rtw_dbg(uint32_t dbg_flags, const int8_t *fmt, ...) 264 { 265 va_list args; 266 267 if (dbg_flags & rtw_dbg_flags) { 268 va_start(args, fmt); 269 vcmn_err(CE_CONT, fmt, args); 270 va_end(args); 271 } 272 } 273 274 #ifdef DEBUG 275 static void 276 rtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where) 277 { 278 #define PRINTREG32(sc, reg) \ 279 RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ 280 "%s: reg[ " #reg " / %03x ] = %08x\n", \ 281 dvname, reg, RTW_READ(regs, reg)) 282 283 #define PRINTREG16(sc, reg) \ 284 RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ 285 "%s: reg[ " #reg " / %03x ] = %04x\n", \ 286 dvname, reg, RTW_READ16(regs, reg)) 287 288 #define PRINTREG8(sc, reg) \ 289 RTW_DPRINTF(RTW_DEBUG_REGDUMP, \ 290 "%s: reg[ " #reg " / %03x ] = %02x\n", \ 291 dvname, reg, RTW_READ8(regs, reg)) 292 293 RTW_DPRINTF(RTW_DEBUG_REGDUMP, "%s: %s\n", dvname, where); 294 295 PRINTREG32(regs, RTW_IDR0); 296 PRINTREG32(regs, RTW_IDR1); 297 PRINTREG32(regs, RTW_MAR0); 298 PRINTREG32(regs, RTW_MAR1); 299 PRINTREG32(regs, RTW_TSFTRL); 300 PRINTREG32(regs, RTW_TSFTRH); 301 PRINTREG32(regs, RTW_TLPDA); 302 PRINTREG32(regs, RTW_TNPDA); 303 PRINTREG32(regs, RTW_THPDA); 304 PRINTREG32(regs, RTW_TCR); 305 PRINTREG32(regs, RTW_RCR); 306 PRINTREG32(regs, RTW_TINT); 307 PRINTREG32(regs, RTW_TBDA); 308 PRINTREG32(regs, RTW_ANAPARM); 309 PRINTREG32(regs, RTW_BB); 310 PRINTREG32(regs, RTW_PHYCFG); 311 PRINTREG32(regs, RTW_WAKEUP0L); 312 PRINTREG32(regs, RTW_WAKEUP0H); 313 PRINTREG32(regs, RTW_WAKEUP1L); 314 PRINTREG32(regs, RTW_WAKEUP1H); 315 PRINTREG32(regs, RTW_WAKEUP2LL); 316 PRINTREG32(regs, RTW_WAKEUP2LH); 317 PRINTREG32(regs, RTW_WAKEUP2HL); 318 PRINTREG32(regs, RTW_WAKEUP2HH); 319 PRINTREG32(regs, RTW_WAKEUP3LL); 320 PRINTREG32(regs, RTW_WAKEUP3LH); 321 PRINTREG32(regs, RTW_WAKEUP3HL); 322 PRINTREG32(regs, RTW_WAKEUP3HH); 323 PRINTREG32(regs, RTW_WAKEUP4LL); 324 PRINTREG32(regs, RTW_WAKEUP4LH); 325 PRINTREG32(regs, RTW_WAKEUP4HL); 326 PRINTREG32(regs, RTW_WAKEUP4HH); 327 PRINTREG32(regs, RTW_DK0); 328 PRINTREG32(regs, RTW_DK1); 329 PRINTREG32(regs, RTW_DK2); 330 PRINTREG32(regs, RTW_DK3); 331 PRINTREG32(regs, RTW_RETRYCTR); 332 PRINTREG32(regs, RTW_RDSAR); 333 PRINTREG32(regs, RTW_FER); 334 PRINTREG32(regs, RTW_FEMR); 335 PRINTREG32(regs, RTW_FPSR); 336 PRINTREG32(regs, RTW_FFER); 337 338 /* 16-bit registers */ 339 PRINTREG16(regs, RTW_BRSR); 340 PRINTREG16(regs, RTW_IMR); 341 PRINTREG16(regs, RTW_ISR); 342 PRINTREG16(regs, RTW_BCNITV); 343 PRINTREG16(regs, RTW_ATIMWND); 344 PRINTREG16(regs, RTW_BINTRITV); 345 PRINTREG16(regs, RTW_ATIMTRITV); 346 PRINTREG16(regs, RTW_CRC16ERR); 347 PRINTREG16(regs, RTW_CRC0); 348 PRINTREG16(regs, RTW_CRC1); 349 PRINTREG16(regs, RTW_CRC2); 350 PRINTREG16(regs, RTW_CRC3); 351 PRINTREG16(regs, RTW_CRC4); 352 PRINTREG16(regs, RTW_CWR); 353 354 /* 8-bit registers */ 355 PRINTREG8(regs, RTW_CR); 356 PRINTREG8(regs, RTW_9346CR); 357 PRINTREG8(regs, RTW_CONFIG0); 358 PRINTREG8(regs, RTW_CONFIG1); 359 PRINTREG8(regs, RTW_CONFIG2); 360 PRINTREG8(regs, RTW_MSR); 361 PRINTREG8(regs, RTW_CONFIG3); 362 PRINTREG8(regs, RTW_CONFIG4); 363 PRINTREG8(regs, RTW_TESTR); 364 PRINTREG8(regs, RTW_PSR); 365 PRINTREG8(regs, RTW_SCR); 366 PRINTREG8(regs, RTW_PHYDELAY); 367 PRINTREG8(regs, RTW_CRCOUNT); 368 PRINTREG8(regs, RTW_PHYADDR); 369 PRINTREG8(regs, RTW_PHYDATAW); 370 PRINTREG8(regs, RTW_PHYDATAR); 371 PRINTREG8(regs, RTW_CONFIG5); 372 PRINTREG8(regs, RTW_TPPOLL); 373 374 PRINTREG16(regs, RTW_BSSID16); 375 PRINTREG32(regs, RTW_BSSID32); 376 #undef PRINTREG32 377 #undef PRINTREG16 378 #undef PRINTREG8 379 } 380 381 #endif /* DEBUG */ 382 static const char * 383 rtw_access_string(enum rtw_access access) 384 { 385 switch (access) { 386 case RTW_ACCESS_NONE: 387 return ("none"); 388 case RTW_ACCESS_CONFIG: 389 return ("config"); 390 case RTW_ACCESS_ANAPARM: 391 return ("anaparm"); 392 default: 393 return ("unknown"); 394 } 395 } 396 397 /* 398 * Enable registers, switch register banks. 399 */ 400 void 401 rtw_config0123_enable(struct rtw_regs *regs, int enable) 402 { 403 uint8_t ecr; 404 ecr = RTW_READ8(regs, RTW_9346CR); 405 ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK); 406 if (enable) 407 ecr |= RTW_9346CR_EEM_CONFIG; 408 else { 409 RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3)); 410 ecr |= RTW_9346CR_EEM_NORMAL; 411 } 412 RTW_WRITE8(regs, RTW_9346CR, ecr); 413 RTW_SYNC(regs, RTW_9346CR, RTW_9346CR); 414 } 415 416 /* 417 * requires rtw_config0123_enable(, 1) 418 */ 419 void 420 rtw_anaparm_enable(struct rtw_regs *regs, int enable) 421 { 422 uint8_t cfg3; 423 424 cfg3 = RTW_READ8(regs, RTW_CONFIG3); 425 cfg3 |= RTW_CONFIG3_CLKRUNEN; 426 if (enable) 427 cfg3 |= RTW_CONFIG3_PARMEN; 428 else 429 cfg3 &= ~RTW_CONFIG3_PARMEN; 430 RTW_WRITE8(regs, RTW_CONFIG3, cfg3); 431 RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3); 432 } 433 434 /* 435 * requires rtw_anaparm_enable(, 1) 436 */ 437 void 438 rtw_txdac_enable(rtw_softc_t *rsc, int enable) 439 { 440 uint32_t anaparm; 441 struct rtw_regs *regs = &rsc->sc_regs; 442 443 anaparm = RTW_READ(regs, RTW_ANAPARM); 444 if (enable) 445 anaparm &= ~RTW_ANAPARM_TXDACOFF; 446 else 447 anaparm |= RTW_ANAPARM_TXDACOFF; 448 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 449 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 450 } 451 452 static void 453 rtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess) 454 { 455 ASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM); 456 ASSERT(regs->r_access >= RTW_ACCESS_NONE && 457 regs->r_access <= RTW_ACCESS_ANAPARM); 458 459 if (naccess == regs->r_access) 460 return; 461 462 switch (naccess) { 463 case RTW_ACCESS_NONE: 464 switch (regs->r_access) { 465 case RTW_ACCESS_ANAPARM: 466 rtw_anaparm_enable(regs, 0); 467 /*FALLTHROUGH*/ 468 case RTW_ACCESS_CONFIG: 469 rtw_config0123_enable(regs, 0); 470 /*FALLTHROUGH*/ 471 case RTW_ACCESS_NONE: 472 break; 473 } 474 break; 475 case RTW_ACCESS_CONFIG: 476 switch (regs->r_access) { 477 case RTW_ACCESS_NONE: 478 rtw_config0123_enable(regs, 1); 479 /*FALLTHROUGH*/ 480 case RTW_ACCESS_CONFIG: 481 break; 482 case RTW_ACCESS_ANAPARM: 483 rtw_anaparm_enable(regs, 0); 484 break; 485 } 486 break; 487 case RTW_ACCESS_ANAPARM: 488 switch (regs->r_access) { 489 case RTW_ACCESS_NONE: 490 rtw_config0123_enable(regs, 1); 491 /*FALLTHROUGH*/ 492 case RTW_ACCESS_CONFIG: 493 rtw_anaparm_enable(regs, 1); 494 /*FALLTHROUGH*/ 495 case RTW_ACCESS_ANAPARM: 496 break; 497 } 498 break; 499 } 500 } 501 502 void 503 rtw_set_access(struct rtw_regs *regs, enum rtw_access access) 504 { 505 rtw_set_access1(regs, access); 506 RTW_DPRINTF(RTW_DEBUG_ACCESS, 507 "%s: access %s -> %s\n", __func__, 508 rtw_access_string(regs->r_access), 509 rtw_access_string(access)); 510 regs->r_access = access; 511 } 512 513 514 void 515 rtw_continuous_tx_enable(rtw_softc_t *rsc, int enable) 516 { 517 struct rtw_regs *regs = &rsc->sc_regs; 518 519 uint32_t tcr; 520 tcr = RTW_READ(regs, RTW_TCR); 521 tcr &= ~RTW_TCR_LBK_MASK; 522 if (enable) 523 tcr |= RTW_TCR_LBK_CONT; 524 else 525 tcr |= RTW_TCR_LBK_NORMAL; 526 RTW_WRITE(regs, RTW_TCR, tcr); 527 RTW_SYNC(regs, RTW_TCR, RTW_TCR); 528 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 529 rtw_txdac_enable(rsc, !enable); 530 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 531 rtw_set_access(regs, RTW_ACCESS_NONE); 532 } 533 534 static int 535 rtw_chip_reset1(struct rtw_regs *regs, const char *dvname) 536 { 537 uint8_t cr; 538 int i; 539 540 RTW_WRITE8(regs, RTW_CR, RTW_CR_RST); 541 542 RTW_WBR(regs, RTW_CR, RTW_CR); 543 544 for (i = 0; i < 1000; i++) { 545 cr = RTW_READ8(regs, RTW_CR); 546 if ((cr & RTW_CR_RST) == 0) { 547 RTW_DPRINTF(RTW_DEBUG_RESET, 548 "%s: reset in %dus\n", dvname, i); 549 return (0); 550 } 551 RTW_RBR(regs, RTW_CR, RTW_CR); 552 DELAY(10); /* 10us */ 553 } 554 555 cmn_err(CE_WARN, "%s: reset failed\n", dvname); 556 return (ETIMEDOUT); 557 } 558 559 static int 560 rtw_chip_reset(struct rtw_regs *regs, const char *dvname) 561 { 562 RTW_WBW(regs, RTW_CR, RTW_TCR); 563 return (rtw_chip_reset1(regs, dvname)); 564 } 565 566 static void 567 rtw_disable_interrupts(struct rtw_regs *regs) 568 { 569 RTW_WRITE16(regs, RTW_IMR, 0); 570 RTW_WRITE16(regs, RTW_ISR, 0xffff); 571 (void) RTW_READ16(regs, RTW_IMR); 572 } 573 574 static void 575 rtw_enable_interrupts(rtw_softc_t *rsc) 576 { 577 struct rtw_regs *regs = &rsc->sc_regs; 578 579 rsc->sc_inten = RTW_INTR_RX | RTW_INTR_TX | RTW_INTR_IOERROR; 580 581 RTW_WRITE16(regs, RTW_IMR, rsc->sc_inten); 582 RTW_WRITE16(regs, RTW_ISR, 0xffff); 583 584 /* XXX necessary? */ 585 if (rsc->sc_intr_ack != NULL) 586 (*rsc->sc_intr_ack)(regs); 587 } 588 589 static int 590 rtw_recall_eeprom(struct rtw_regs *regs, const char *dvname) 591 { 592 int i; 593 uint8_t ecr; 594 595 ecr = RTW_READ8(regs, RTW_9346CR); 596 ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD; 597 RTW_WRITE8(regs, RTW_9346CR, ecr); 598 599 RTW_WBR(regs, RTW_9346CR, RTW_9346CR); 600 601 /* wait 25ms for completion */ 602 for (i = 0; i < 250; i++) { 603 ecr = RTW_READ8(regs, RTW_9346CR); 604 if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) { 605 RTW_DPRINTF(RTW_DEBUG_RESET, 606 "%s: recall EEPROM in %dus\n", dvname, i * 100); 607 return (0); 608 } 609 RTW_RBR(regs, RTW_9346CR, RTW_9346CR); 610 DELAY(100); 611 } 612 cmn_err(CE_WARN, "%s: recall EEPROM failed\n", dvname); 613 return (ETIMEDOUT); 614 } 615 616 static int 617 rtw_reset(rtw_softc_t *rsc) 618 { 619 int rc; 620 621 rc = rtw_chip_reset(&rsc->sc_regs, "rtw"); 622 if (rc != 0) 623 return (rc); 624 625 (void) rtw_recall_eeprom(&rsc->sc_regs, "rtw"); 626 return (0); 627 } 628 629 void 630 rtw_set_mode(struct rtw_regs *regs, int mode) 631 { 632 uint8_t command; 633 command = RTW_READ8(regs, RTW_9346CR); 634 command = command &~ RTW_EPROM_CMD_OPERATING_MODE_MASK; 635 command = command | (mode<<RTW_EPROM_CMD_OPERATING_MODE_SHIFT); 636 command = command &~ (1<<RTW_EPROM_CS_SHIFT); 637 command = command &~ (1<<RTW_EPROM_CK_SHIFT); 638 RTW_WRITE8(regs, RTW_9346CR, command); 639 } 640 641 void 642 rtw_dma_start(struct rtw_regs *regs, int priority) 643 { 644 uint8_t check = 0; 645 646 check = RTW_READ8(regs, RTW_TPPOLL); 647 switch (priority) { 648 case (0): 649 RTW_WRITE8(regs, RTW_TPPOLL, 650 (1<< RTW_TX_DMA_POLLING_LOWPRIORITY_SHIFT) | check); 651 break; 652 case (1): 653 RTW_WRITE8(regs, RTW_TPPOLL, 654 (1<< RTW_TX_DMA_POLLING_NORMPRIORITY_SHIFT) | check); 655 break; 656 case (2): 657 RTW_WRITE8(regs, RTW_TPPOLL, 658 (1<< RTW_TX_DMA_POLLING_HIPRIORITY_SHIFT) | check); 659 break; 660 } 661 (void) RTW_READ8(regs, RTW_TPPOLL); 662 } 663 664 void 665 rtw_beacon_tx_disable(struct rtw_regs *regs) 666 { 667 uint8_t mask = 0; 668 mask |= (1 << RTW_TX_DMA_STOP_BEACON_SHIFT); 669 rtw_set_mode(regs, RTW_EPROM_CMD_CONFIG); 670 RTW_WRITE8(regs, RTW_TPPOLL, mask); 671 rtw_set_mode(regs, RTW_EPROM_CMD_NORMAL); 672 } 673 674 static void 675 rtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable); 676 677 void 678 rtw_rtx_disable(rtw_softc_t *rsc) 679 { 680 struct rtw_regs *regs = &rsc->sc_regs; 681 682 rtw_io_enable(rsc, RTW_CR_RE|RTW_CR_TE, 0); 683 (void) RTW_READ8(regs, RTW_CR); 684 } 685 686 static void 687 rtw_srom_free(struct rtw_srom *sr) 688 { 689 if (sr->sr_content == NULL) 690 return; 691 kmem_free(sr->sr_content, sr->sr_size); 692 sr->sr_size = 0; 693 sr->sr_content = NULL; 694 } 695 696 /*ARGSUSED*/ 697 static void 698 rtw_srom_defaults(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold, 699 enum rtw_rfchipid *rfchipid, uint32_t *rcr) 700 { 701 *flags |= (RTW_F_DIGPHY|RTW_F_ANTDIV); 702 *cs_threshold = RTW_SR_ENERGYDETTHR_DEFAULT; 703 *rcr |= RTW_RCR_ENCS1; 704 *rfchipid = RTW_RFCHIPID_PHILIPS; 705 } 706 707 static int 708 rtw_srom_parse(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold, 709 enum rtw_rfchipid *rfchipid, uint32_t *rcr, enum rtw_locale *locale, 710 const char *dvname) 711 { 712 int i; 713 const char *rfname, *paname; 714 char scratch[sizeof ("unknown 0xXX")]; 715 uint16_t version; 716 uint8_t mac[IEEE80211_ADDR_LEN]; 717 718 *flags &= ~(RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV); 719 *rcr &= ~(RTW_RCR_ENCS1 | RTW_RCR_ENCS2); 720 721 version = RTW_SR_GET16(sr, RTW_SR_VERSION); 722 RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: SROM version %d.%d", dvname, 723 version >> 8, version & 0xff); 724 725 if (version <= 0x0101) { 726 cmn_err(CE_NOTE, " is not understood, limping along " 727 "with defaults\n"); 728 rtw_srom_defaults(sr, flags, cs_threshold, rfchipid, rcr); 729 return (0); 730 } 731 732 for (i = 0; i < IEEE80211_ADDR_LEN; i++) 733 mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i); 734 735 RTW_DPRINTF(RTW_DEBUG_ATTACH, 736 "%s: EEPROM MAC %s\n", dvname, mac); 737 738 *cs_threshold = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR); 739 740 if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW_CONFIG2_ANT) != 0) 741 *flags |= RTW_F_ANTDIV; 742 743 /* 744 * Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems 745 * to be reversed. 746 */ 747 if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0) 748 *flags |= RTW_F_DIGPHY; 749 if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0) 750 *flags |= RTW_F_DFLANTB; 751 752 *rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM), 753 RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1); 754 755 *rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID); 756 switch (*rfchipid) { 757 case RTW_RFCHIPID_GCT: /* this combo seen in the wild */ 758 rfname = "GCT GRF5101"; 759 paname = "Winspring WS9901"; 760 break; 761 case RTW_RFCHIPID_MAXIM: 762 rfname = "Maxim MAX2820"; /* guess */ 763 paname = "Maxim MAX2422"; /* guess */ 764 break; 765 case RTW_RFCHIPID_INTERSIL: 766 rfname = "Intersil HFA3873"; /* guess */ 767 paname = "Intersil <unknown>"; 768 break; 769 case RTW_RFCHIPID_PHILIPS: /* this combo seen in the wild */ 770 rfname = "Philips SA2400A"; 771 paname = "Philips SA2411"; 772 break; 773 case RTW_RFCHIPID_RFMD: 774 /* 775 * this is the same front-end as an atw(4)! 776 */ 777 rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */ 778 "LNA: RFMD RF2494, " /* mentioned in Realtek docs */ 779 "SYN: Silicon Labs Si4126"; 780 paname = "RFMD RF2189"; /* mentioned in Realtek docs */ 781 break; 782 case RTW_RFCHIPID_RESERVED: 783 rfname = paname = "reserved"; 784 break; 785 default: 786 (void) snprintf(scratch, sizeof (scratch), 787 "unknown 0x%02x", *rfchipid); 788 rfname = paname = scratch; 789 } 790 RTW_DPRINTF(RTW_DEBUG_PHY, "%s: RF: %s, PA: %s\n", 791 dvname, rfname, paname); 792 793 switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_GL_MASK) { 794 case RTW_CONFIG0_GL_USA: 795 *locale = RTW_LOCALE_USA; 796 break; 797 case RTW_CONFIG0_GL_EUROPE: 798 *locale = RTW_LOCALE_EUROPE; 799 break; 800 case RTW_CONFIG0_GL_JAPAN: 801 *locale = RTW_LOCALE_JAPAN; 802 break; 803 default: 804 *locale = RTW_LOCALE_UNKNOWN; 805 break; 806 } 807 return (0); 808 } 809 810 /* 811 * Returns -1 on failure. 812 */ 813 static int 814 rtw_srom_read(struct rtw_regs *regs, uint32_t flags, struct rtw_srom *sr, 815 const char *dvname) 816 { 817 int rc; 818 struct seeprom_descriptor sd; 819 uint8_t ecr; 820 821 (void) memset(&sd, 0, sizeof (sd)); 822 823 ecr = RTW_READ8(regs, RTW_9346CR); 824 825 if ((flags & RTW_F_9356SROM) != 0) { 826 RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c56 SROM\n", dvname); 827 sr->sr_size = 256; 828 sd.sd_chip = C56_66; 829 } else { 830 RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c46 SROM\n", dvname); 831 sr->sr_size = 128; 832 sd.sd_chip = C46; 833 } 834 835 ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK | 836 RTW_9346CR_EEM_MASK | RTW_9346CR_EECS); 837 ecr |= RTW_9346CR_EEM_PROGRAM; 838 839 RTW_WRITE8(regs, RTW_9346CR, ecr); 840 841 sr->sr_content = kmem_zalloc(sr->sr_size, KM_SLEEP); 842 843 if (sr->sr_content == NULL) { 844 cmn_err(CE_WARN, "%s: unable to allocate SROM buffer\n", 845 dvname); 846 return (ENOMEM); 847 } 848 849 (void) memset(sr->sr_content, 0, sr->sr_size); 850 851 /* 852 * RTL8180 has a single 8-bit register for controlling the 853 * 93cx6 SROM. There is no "ready" bit. The RTL8180 854 * input/output sense is the reverse of read_seeprom's. 855 */ 856 sd.sd_handle = regs->r_handle; 857 sd.sd_base = regs->r_base; 858 sd.sd_regsize = 1; 859 sd.sd_control_offset = RTW_9346CR; 860 sd.sd_status_offset = RTW_9346CR; 861 sd.sd_dataout_offset = RTW_9346CR; 862 sd.sd_CK = RTW_9346CR_EESK; 863 sd.sd_CS = RTW_9346CR_EECS; 864 sd.sd_DI = RTW_9346CR_EEDO; 865 sd.sd_DO = RTW_9346CR_EEDI; 866 /* 867 * make read_seeprom enter EEPROM read/write mode 868 */ 869 sd.sd_MS = ecr; 870 sd.sd_RDY = 0; 871 872 /* 873 * TBD bus barriers 874 */ 875 if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) { 876 cmn_err(CE_WARN, "%s: could not read SROM\n", dvname); 877 kmem_free(sr->sr_content, sr->sr_size); 878 sr->sr_content = NULL; 879 return (-1); /* XXX */ 880 } 881 882 /* 883 * end EEPROM read/write mode 884 */ 885 RTW_WRITE8(regs, RTW_9346CR, 886 (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL); 887 RTW_WBRW(regs, RTW_9346CR, RTW_9346CR); 888 889 if ((rc = rtw_recall_eeprom(regs, dvname)) != 0) 890 return (rc); 891 892 #ifdef SROM_DEBUG 893 { 894 int i; 895 RTW_DPRINTF(RTW_DEBUG_ATTACH, 896 "\n%s: serial ROM:\n\t", dvname); 897 for (i = 0; i < sr->sr_size/2; i++) { 898 RTW_DPRINTF(RTW_DEBUG_ATTACH, 899 "offset-0x%x: %04x", 2*i, sr->sr_content[i]); 900 } 901 } 902 #endif /* DEBUG */ 903 return (0); 904 } 905 906 static void 907 rtw_set_rfprog(struct rtw_regs *regs, enum rtw_rfchipid rfchipid, 908 const char *dvname) 909 { 910 uint8_t cfg4; 911 const char *method; 912 913 cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK; 914 915 switch (rfchipid) { 916 default: 917 cfg4 |= LSHIFT(0, RTW_CONFIG4_RFTYPE_MASK); 918 method = "fallback"; 919 break; 920 case RTW_RFCHIPID_INTERSIL: 921 cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL; 922 method = "Intersil"; 923 break; 924 case RTW_RFCHIPID_PHILIPS: 925 cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS; 926 method = "Philips"; 927 break; 928 case RTW_RFCHIPID_GCT: /* XXX a guess */ 929 case RTW_RFCHIPID_RFMD: 930 cfg4 |= RTW_CONFIG4_RFTYPE_RFMD; 931 method = "RFMD"; 932 break; 933 } 934 935 RTW_WRITE8(regs, RTW_CONFIG4, cfg4); 936 937 RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4); 938 939 RTW_DPRINTF(RTW_DEBUG_INIT, 940 "%s: %s RF programming method, %02x\n", dvname, method, 941 RTW_READ8(regs, RTW_CONFIG4)); 942 } 943 944 static void 945 rtw_init_channels(enum rtw_locale locale, 946 struct ieee80211_channel (*chans)[IEEE80211_CHAN_MAX+1], 947 const char *dvname) 948 { 949 int i; 950 const char *name = NULL; 951 #define ADD_CHANNEL(_chans, _chan) { \ 952 (*_chans)[_chan].ich_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK;\ 953 (*_chans)[_chan].ich_freq = \ 954 ieee80211_ieee2mhz(_chan, (*_chans)[_chan].ich_flags);\ 955 } 956 957 switch (locale) { 958 case RTW_LOCALE_USA: /* 1-11 */ 959 name = "USA"; 960 for (i = 1; i <= 11; i++) 961 ADD_CHANNEL(chans, i); 962 break; 963 case RTW_LOCALE_JAPAN: /* 1-14 */ 964 name = "Japan"; 965 ADD_CHANNEL(chans, 14); 966 for (i = 1; i <= 14; i++) 967 ADD_CHANNEL(chans, i); 968 break; 969 case RTW_LOCALE_EUROPE: /* 1-13 */ 970 name = "Europe"; 971 for (i = 1; i <= 13; i++) 972 ADD_CHANNEL(chans, i); 973 break; 974 default: /* 10-11 allowed by most countries */ 975 name = "<unknown>"; 976 for (i = 10; i <= 11; i++) 977 ADD_CHANNEL(chans, i); 978 break; 979 } 980 RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: Geographic Location %s\n", 981 dvname, name); 982 #undef ADD_CHANNEL 983 } 984 985 static void 986 rtw_set80211props(struct ieee80211com *ic) 987 { 988 ic->ic_phytype = IEEE80211_T_DS; 989 ic->ic_opmode = IEEE80211_M_STA; 990 ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS | 991 IEEE80211_C_SHPREAMBLE; 992 /* IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP */ 993 994 ic->ic_sup_rates[IEEE80211_MODE_11B] = rtw_rateset_11b; 995 } 996 997 /*ARGSUSED*/ 998 static void 999 rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale, 1000 const char *dvname) 1001 { 1002 uint8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0); 1003 1004 switch (cfg0 & RTW_CONFIG0_GL_MASK) { 1005 case RTW_CONFIG0_GL_USA: 1006 *locale = RTW_LOCALE_USA; 1007 break; 1008 case RTW_CONFIG0_GL_JAPAN: 1009 *locale = RTW_LOCALE_JAPAN; 1010 break; 1011 case RTW_CONFIG0_GL_EUROPE: 1012 *locale = RTW_LOCALE_EUROPE; 1013 break; 1014 default: 1015 *locale = RTW_LOCALE_UNKNOWN; 1016 break; 1017 } 1018 } 1019 1020 static int 1021 rtw_identify_sta(struct rtw_regs *regs, uint8_t *addr, 1022 const char *dvname) 1023 { 1024 uint32_t idr0 = RTW_READ(regs, RTW_IDR0), 1025 idr1 = RTW_READ(regs, RTW_IDR1); 1026 1027 *addr = MASK_AND_RSHIFT(idr0, BITS(0, 7)); 1028 *(addr + 1) = MASK_AND_RSHIFT(idr0, BITS(8, 15)); 1029 *(addr + 2) = MASK_AND_RSHIFT(idr0, BITS(16, 23)); 1030 *(addr + 3) = MASK_AND_RSHIFT(idr0, BITS(24, 31)); 1031 1032 *(addr + 4) = MASK_AND_RSHIFT(idr1, BITS(0, 7)); 1033 *(addr + 5) = MASK_AND_RSHIFT(idr1, BITS(8, 15)); 1034 1035 RTW_DPRINTF(RTW_DEBUG_ATTACH, 1036 "%s: 802.11mac address %x:%x:%x:%x:%x:%x\n", dvname, 1037 *addr, *(addr+1), *(addr+2), *(addr+3), *(addr+4), *(addr+5)); 1038 1039 return (0); 1040 } 1041 1042 static uint8_t 1043 rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic, 1044 struct ieee80211_channel *chan) 1045 { 1046 uint32_t idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1; 1047 return (RTW_SR_GET(sr, idx)); 1048 } 1049 1050 static void 1051 rtw_rxdesc_init(rtw_softc_t *rsc, struct rtw_rxbuf *rbf, int idx, int is_last) 1052 { 1053 uint32_t ctl = 0; 1054 uint8_t *buf = (uint8_t *)rbf->bf_dma.mem_va; 1055 1056 ASSERT(rbf != NULL); 1057 rbf->rxdesc->rd_buf = (rbf->bf_dma.cookie.dmac_address); 1058 bzero(buf, rbf->bf_dma.alength); 1059 RTW_DMA_SYNC(rbf->bf_dma, DDI_DMA_SYNC_FORDEV); 1060 1061 ctl = (rbf->bf_dma.alength & 0xfff) | RTW_RXCTL_OWN; 1062 1063 if (is_last) 1064 ctl |= RTW_RXCTL_EOR; 1065 1066 rbf->rxdesc->rd_ctl = (ctl); 1067 /* sync the mbuf */ 1068 1069 /* sync the descriptor */ 1070 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 1071 RTW_DESC_OFFSET(hd_rx, idx), 1072 sizeof (struct rtw_rxdesc), 1073 DDI_DMA_SYNC_FORDEV); 1074 } 1075 1076 static void 1077 rtw_idle(struct rtw_regs *regs) 1078 { 1079 int active; 1080 1081 /* request stop DMA; wait for packets to stop transmitting. */ 1082 1083 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); 1084 1085 for (active = 0; active < 300 && 1086 (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ALL) != 0; active++) 1087 drv_usecwait(10); 1088 } 1089 1090 static void 1091 rtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable) 1092 { 1093 uint8_t cr; 1094 struct rtw_regs *regs = &rsc->sc_regs; 1095 1096 RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: %s 0x%02x\n", __func__, 1097 enable ? "enable" : "disable", flags); 1098 1099 cr = RTW_READ8(regs, RTW_CR); 1100 1101 /* The receive engine will always start at RDSAR. */ 1102 if (enable && (flags & ~cr & RTW_CR_RE)) { 1103 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 1104 RTW_DESC_OFFSET(hd_rx, 0), 1105 sizeof (struct rtw_rxdesc), 1106 DDI_DMA_SYNC_FORCPU); 1107 rsc->rx_next = 0; 1108 rtw_rxdesc_init(rsc, rsc->rxbuf_h, 0, 0); 1109 } 1110 1111 if (enable) 1112 cr |= flags; 1113 else 1114 cr &= ~flags; 1115 RTW_WRITE8(regs, RTW_CR, cr); 1116 (void) RTW_READ8(regs, RTW_CR); 1117 } 1118 1119 /* 1120 * Allocate an area of memory and a DMA handle for accessing it 1121 */ 1122 static int 1123 rtw_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, 1124 size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags, 1125 uint_t bind_flags, dma_area_t *dma_p) 1126 { 1127 int err; 1128 1129 /* 1130 * Allocate handle 1131 */ 1132 err = ddi_dma_alloc_handle(devinfo, dma_attr, 1133 DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 1134 if (err != DDI_SUCCESS) 1135 return (DDI_FAILURE); 1136 1137 /* 1138 * Allocate memory 1139 */ 1140 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 1141 alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va, 1142 &dma_p->alength, &dma_p->acc_hdl); 1143 if (err != DDI_SUCCESS) 1144 return (DDI_FAILURE); 1145 1146 /* 1147 * Bind the two together 1148 */ 1149 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 1150 dma_p->mem_va, dma_p->alength, bind_flags, 1151 DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies); 1152 if ((dma_p->ncookies != 1) || (err != DDI_DMA_MAPPED)) 1153 return (DDI_FAILURE); 1154 1155 dma_p->nslots = ~0U; 1156 dma_p->size = ~0U; 1157 dma_p->token = ~0U; 1158 dma_p->offset = 0; 1159 return (DDI_SUCCESS); 1160 } 1161 1162 /* 1163 * Free one allocated area of DMAable memory 1164 */ 1165 static void 1166 rtw_free_dma_mem(dma_area_t *dma_p) 1167 { 1168 if (dma_p->dma_hdl != NULL) { 1169 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 1170 if (dma_p->acc_hdl != NULL) { 1171 ddi_dma_mem_free(&dma_p->acc_hdl); 1172 dma_p->acc_hdl = NULL; 1173 } 1174 ddi_dma_free_handle(&dma_p->dma_hdl); 1175 dma_p->ncookies = 0; 1176 dma_p->dma_hdl = NULL; 1177 } 1178 } 1179 1180 static void 1181 rtw_dma_free(rtw_softc_t *rsc) 1182 { 1183 struct rtw_txbuf *txbf; 1184 struct rtw_rxbuf *rxbf; 1185 int i, j; 1186 1187 /* Free TX DMA buffer */ 1188 for (i = 0; i < RTW_NTXPRI; i++) { 1189 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1190 while (txbf != NULL) { 1191 rtw_free_dma_mem(&txbf->bf_dma); 1192 list_remove(&rsc->sc_txq[i].tx_free_list, txbf); 1193 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1194 } 1195 list_destroy(&rsc->sc_txq[i].tx_free_list); 1196 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1197 while (txbf != NULL) { 1198 rtw_free_dma_mem(&txbf->bf_dma); 1199 list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf); 1200 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1201 } 1202 list_destroy(&rsc->sc_txq[i].tx_dirty_list); 1203 1204 if (rsc->sc_txq[i].txbuf_h != NULL) { 1205 kmem_free(rsc->sc_txq[i].txbuf_h, 1206 sizeof (struct rtw_txbuf) * rtw_qlen[i]); 1207 rsc->sc_txq[i].txbuf_h = NULL; 1208 } 1209 } 1210 1211 /* Free RX DMA buffer */ 1212 rxbf = rsc->rxbuf_h; 1213 for (j = 0; j < RTW_RXQLEN; j++) { 1214 rtw_free_dma_mem(&rxbf->bf_dma); 1215 rxbf++; 1216 } 1217 1218 if (rsc->rxbuf_h != NULL) { 1219 kmem_free(rsc->rxbuf_h, 1220 sizeof (struct rtw_rxbuf) * RTW_RXQLEN); 1221 rsc->rxbuf_h = NULL; 1222 } 1223 1224 rtw_free_dma_mem(&rsc->sc_desc_dma); 1225 } 1226 1227 static int 1228 rtw_dma_init(dev_info_t *devinfo, rtw_softc_t *rsc) 1229 { 1230 int i, j, err; 1231 size_t size; 1232 uint32_t buflen; 1233 struct rtw_txdesc *txds; 1234 struct rtw_rxdesc *rxds; 1235 struct rtw_txbuf *txbf; 1236 struct rtw_rxbuf *rxbf; 1237 uint32_t phybaseaddr, ptx[RTW_NTXPRI], prx; 1238 caddr_t virbaseaddr, vtx[RTW_NTXPRI], vrx; 1239 1240 /* DMA buffer size for each TX/RX packet */ 1241 rsc->sc_dmabuf_size = roundup(sizeof (struct ieee80211_frame) + 0x100 + 1242 IEEE80211_MTU + IEEE80211_CRC_LEN + sizeof (struct ieee80211_llc) + 1243 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 1244 IEEE80211_WEP_CRCLEN), rsc->sc_cachelsz); 1245 size = sizeof (struct rtw_descs); 1246 err = rtw_alloc_dma_mem(devinfo, &dma_attr_desc, size, 1247 &rtw_desc_accattr, 1248 DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 1249 &rsc->sc_desc_dma); 1250 if (err != DDI_SUCCESS) 1251 goto error; 1252 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address; 1253 virbaseaddr = rsc->sc_desc_dma.mem_va; 1254 ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo); 1255 ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd); 1256 ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi); 1257 ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn); 1258 vtx[0] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txlo)); 1259 vtx[1] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txmd)); 1260 vtx[2] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txhi)); 1261 vtx[3] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_bcn)); 1262 for (i = 0; i < RTW_NTXPRI; i++) { 1263 RTW_DPRINTF(RTW_DEBUG_DMA, "p[%d]=%x, v[%d]=%x", i, ptx[i], 1264 i, vtx[i]); 1265 RTW_DPRINTF(RTW_DEBUG_DMA, "ring%d:", i); 1266 list_create(&rsc->sc_txq[i].tx_free_list, 1267 sizeof (struct rtw_txbuf), 1268 offsetof(struct rtw_txbuf, bf_node)); 1269 list_create(&rsc->sc_txq[i].tx_dirty_list, 1270 sizeof (struct rtw_txbuf), 1271 offsetof(struct rtw_txbuf, bf_node)); 1272 /* virtual address of the first descriptor */ 1273 rsc->sc_txq[i].txdesc_h = 1274 (struct rtw_txdesc *)(uintptr_t)vtx[i]; 1275 1276 txds = rsc->sc_txq[i].txdesc_h; 1277 /* allocate data structures to describe TX DMA buffers */ 1278 buflen = sizeof (struct rtw_txbuf) * rtw_qlen[i]; 1279 txbf = (struct rtw_txbuf *)kmem_zalloc(buflen, KM_SLEEP); 1280 rsc->sc_txq[i].txbuf_h = txbf; 1281 for (j = 0; j < rtw_qlen[i]; j++, txbf++, txds++) { 1282 txbf->txdesc = txds; 1283 txbf->bf_daddr = ptx[i] + ((uintptr_t)txds - 1284 (uintptr_t)rsc->sc_txq[i].txdesc_h); 1285 list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf); 1286 1287 /* alloc DMA memory */ 1288 err = rtw_alloc_dma_mem(devinfo, &dma_attr_txbuf, 1289 rsc->sc_dmabuf_size, 1290 &rtw_buf_accattr, 1291 DDI_DMA_STREAMING, 1292 DDI_DMA_WRITE | DDI_DMA_STREAMING, 1293 &txbf->bf_dma); 1294 if (err != DDI_SUCCESS) 1295 goto error; 1296 RTW_DPRINTF(RTW_DEBUG_DMA, "pbufaddr[%d]=%x", 1297 j, txbf->bf_dma.cookie.dmac_address); 1298 } 1299 } 1300 prx = RTW_RING_BASE(phybaseaddr, hd_rx); 1301 vrx = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_rx)); 1302 /* virtual address of the first descriptor */ 1303 rsc->rxdesc_h = (struct rtw_rxdesc *)(uintptr_t)vrx; 1304 rxds = rsc->rxdesc_h; 1305 1306 /* allocate data structures to describe RX DMA buffers */ 1307 buflen = sizeof (struct rtw_rxbuf) * RTW_RXQLEN; 1308 rxbf = (struct rtw_rxbuf *)kmem_zalloc(buflen, KM_SLEEP); 1309 rsc->rxbuf_h = rxbf; 1310 1311 for (j = 0; j < RTW_RXQLEN; j++, rxbf++, rxds++) { 1312 rxbf->rxdesc = rxds; 1313 rxbf->bf_daddr = 1314 prx + ((uintptr_t)rxds - (uintptr_t)rsc->rxdesc_h); 1315 1316 /* alloc DMA memory */ 1317 err = rtw_alloc_dma_mem(devinfo, &dma_attr_rxbuf, 1318 rsc->sc_dmabuf_size, 1319 &rtw_buf_accattr, 1320 DDI_DMA_STREAMING, DDI_DMA_READ | DDI_DMA_STREAMING, 1321 &rxbf->bf_dma); 1322 if (err != DDI_SUCCESS) 1323 goto error; 1324 } 1325 1326 return (DDI_SUCCESS); 1327 error: 1328 return (DDI_FAILURE); 1329 } 1330 1331 static void 1332 rtw_hwring_setup(rtw_softc_t *rsc) 1333 { 1334 struct rtw_regs *regs = &rsc->sc_regs; 1335 uint32_t phybaseaddr; 1336 1337 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address; 1338 1339 RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(phybaseaddr, hd_rx)); 1340 RTW_WRITE(regs, RTW_TLPDA, RTW_RING_BASE(phybaseaddr, hd_txlo)); 1341 RTW_WRITE(regs, RTW_TNPDA, RTW_RING_BASE(phybaseaddr, hd_txmd)); 1342 RTW_WRITE(regs, RTW_THPDA, RTW_RING_BASE(phybaseaddr, hd_txhi)); 1343 RTW_WRITE(regs, RTW_TBDA, RTW_RING_BASE(phybaseaddr, hd_bcn)); 1344 rsc->hw_start = RTW_READ(regs, RTW_TNPDA); 1345 rsc->hw_go = RTW_READ(regs, RTW_TNPDA); 1346 } 1347 1348 static void 1349 rtw_swring_setup(rtw_softc_t *rsc, int flag) 1350 { 1351 int i, j; 1352 int is_last; 1353 struct rtw_txbuf *txbf; 1354 struct rtw_rxbuf *rxbf; 1355 uint32_t phybaseaddr, ptx[RTW_NTXPRI], baddr_desc, taddr_desc; 1356 1357 phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address; 1358 ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo); 1359 ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd); 1360 ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi); 1361 ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn); 1362 RTW_DMA_SYNC(rsc->sc_desc_dma, DDI_DMA_SYNC_FORDEV); 1363 /* sync tx desc and tx buf */ 1364 for (i = 0; i < RTW_NTXPRI; i++) { 1365 rsc->sc_txq[i].tx_prod = rsc->sc_txq[i].tx_cons = 0; 1366 rsc->sc_txq[i].tx_nfree = rtw_qlen[i]; 1367 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1368 while (txbf != NULL) { 1369 list_remove(&rsc->sc_txq[i].tx_free_list, txbf); 1370 txbf = list_head(&rsc->sc_txq[i].tx_free_list); 1371 } 1372 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1373 while (txbf != NULL) { 1374 list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf); 1375 txbf = list_head(&rsc->sc_txq[i].tx_dirty_list); 1376 } 1377 txbf = rsc->sc_txq[i].txbuf_h; 1378 baddr_desc = ptx[i]; 1379 taddr_desc = baddr_desc + sizeof (struct rtw_txdesc); 1380 for (j = 0; j < rtw_qlen[i]; j++) { 1381 list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf); 1382 if (j == (rtw_qlen[i] - 1)) { 1383 is_last = 1; 1384 } else { 1385 is_last = 0; 1386 } 1387 1388 if (is_last) { 1389 txbf->txdesc->td_next = baddr_desc; 1390 } else { 1391 txbf->txdesc->td_next = taddr_desc; 1392 } 1393 txbf->next_bf_daddr = txbf->txdesc->td_next; 1394 RTW_DMA_SYNC(txbf->bf_dma, DDI_DMA_SYNC_FORDEV); 1395 txbf->order = j; 1396 txbf++; 1397 taddr_desc += sizeof (struct rtw_txdesc); 1398 } 1399 } 1400 if (!flag) 1401 return; 1402 1403 /* sync rx desc and rx buf */ 1404 rsc->rx_next = 0; 1405 rxbf = rsc->rxbuf_h; 1406 for (j = 0; j < RTW_RXQLEN; j++) { 1407 RTW_DMA_SYNC(rxbf->bf_dma, DDI_DMA_SYNC_FORCPU); 1408 if (j == (RTW_RXQLEN - 1)) 1409 is_last = 1; 1410 else 1411 is_last = 0; 1412 rtw_rxdesc_init(rsc, rxbf, j, is_last); 1413 rxbf++; 1414 } 1415 } 1416 1417 static void 1418 rtw_resume_ticks(rtw_softc_t *rsc) 1419 { 1420 RTW_WRITE(&rsc->sc_regs, RTW_TINT, 0xffffffff); 1421 } 1422 1423 const char * 1424 rtw_pwrstate_string(enum rtw_pwrstate power) 1425 { 1426 switch (power) { 1427 case RTW_ON: 1428 return ("on"); 1429 case RTW_SLEEP: 1430 return ("sleep"); 1431 case RTW_OFF: 1432 return ("off"); 1433 default: 1434 return ("unknown"); 1435 } 1436 } 1437 1438 /* 1439 * XXX For Maxim, I am using the RFMD settings gleaned from the 1440 * reference driver, plus a magic Maxim "ON" value that comes from 1441 * the Realtek document "Windows PG for Rtl8180." 1442 */ 1443 /*ARGSUSED*/ 1444 static void 1445 rtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, 1446 int before_rf, int digphy) 1447 { 1448 uint32_t anaparm; 1449 1450 anaparm = RTW_READ(regs, RTW_ANAPARM); 1451 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); 1452 1453 switch (power) { 1454 case RTW_OFF: 1455 if (before_rf) 1456 return; 1457 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF; 1458 anaparm |= RTW_ANAPARM_TXDACOFF; 1459 break; 1460 case RTW_SLEEP: 1461 if (!before_rf) 1462 return; 1463 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP; 1464 anaparm |= RTW_ANAPARM_TXDACOFF; 1465 break; 1466 case RTW_ON: 1467 if (!before_rf) 1468 return; 1469 anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON; 1470 break; 1471 } 1472 RTW_DPRINTF(RTW_DEBUG_PWR, 1473 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", 1474 __func__, rtw_pwrstate_string(power), 1475 (before_rf) ? "before" : "after", anaparm); 1476 1477 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 1478 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 1479 } 1480 1481 /* 1482 * XXX I am using the RFMD settings gleaned from the reference 1483 * driver. They agree 1484 */ 1485 /*ARGSUSED*/ 1486 static void 1487 rtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, 1488 int before_rf, int digphy) 1489 { 1490 uint32_t anaparm; 1491 1492 anaparm = RTW_READ(regs, RTW_ANAPARM); 1493 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); 1494 1495 switch (power) { 1496 case RTW_OFF: 1497 if (before_rf) 1498 return; 1499 anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF; 1500 anaparm |= RTW_ANAPARM_TXDACOFF; 1501 break; 1502 case RTW_SLEEP: 1503 if (!before_rf) 1504 return; 1505 anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP; 1506 anaparm |= RTW_ANAPARM_TXDACOFF; 1507 break; 1508 case RTW_ON: 1509 if (!before_rf) 1510 return; 1511 anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON; 1512 break; 1513 } 1514 RTW_DPRINTF(RTW_DEBUG_PWR, 1515 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", 1516 __func__, rtw_pwrstate_string(power), 1517 (before_rf) ? "before" : "after", anaparm); 1518 1519 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 1520 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 1521 } 1522 1523 static void 1524 rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power, 1525 int before_rf, int digphy) 1526 { 1527 uint32_t anaparm; 1528 1529 anaparm = RTW_READ(regs, RTW_ANAPARM); 1530 anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF); 1531 1532 switch (power) { 1533 case RTW_OFF: 1534 if (before_rf) 1535 return; 1536 anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF; 1537 anaparm |= RTW_ANAPARM_TXDACOFF; 1538 break; 1539 case RTW_SLEEP: 1540 if (!before_rf) 1541 return; 1542 anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP; 1543 anaparm |= RTW_ANAPARM_TXDACOFF; 1544 break; 1545 case RTW_ON: 1546 if (!before_rf) 1547 return; 1548 if (digphy) { 1549 anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON; 1550 /* XXX guess */ 1551 anaparm |= RTW_ANAPARM_TXDACOFF; 1552 } else 1553 anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON; 1554 break; 1555 } 1556 RTW_DPRINTF(RTW_DEBUG_PWR, 1557 "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n", 1558 __func__, rtw_pwrstate_string(power), 1559 (before_rf) ? "before" : "after", anaparm); 1560 1561 RTW_WRITE(regs, RTW_ANAPARM, anaparm); 1562 RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM); 1563 } 1564 1565 static void 1566 rtw_pwrstate0(rtw_softc_t *rsc, enum rtw_pwrstate power, int before_rf, 1567 int digphy) 1568 { 1569 struct rtw_regs *regs = &rsc->sc_regs; 1570 1571 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 1572 1573 (*rsc->sc_pwrstate_cb)(regs, power, before_rf, digphy); 1574 1575 rtw_set_access(regs, RTW_ACCESS_NONE); 1576 } 1577 1578 static void 1579 rtw_rf_destroy(struct rtw_rf *rf) 1580 { 1581 (*rf->rf_destroy)(rf); 1582 } 1583 1584 static int 1585 rtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power) 1586 { 1587 return (*rf->rf_pwrstate)(rf, power); 1588 } 1589 1590 static int 1591 rtw_pwrstate(rtw_softc_t *rsc, enum rtw_pwrstate power) 1592 { 1593 int rc; 1594 1595 RTW_DPRINTF(RTW_DEBUG_PWR, 1596 "%s: %s->%s\n", __func__, 1597 rtw_pwrstate_string(rsc->sc_pwrstate), rtw_pwrstate_string(power)); 1598 1599 if (rsc->sc_pwrstate == power) 1600 return (0); 1601 1602 rtw_pwrstate0(rsc, power, 1, rsc->sc_flags & RTW_F_DIGPHY); 1603 rc = rtw_rf_pwrstate(rsc->sc_rf, power); 1604 rtw_pwrstate0(rsc, power, 0, rsc->sc_flags & RTW_F_DIGPHY); 1605 1606 switch (power) { 1607 case RTW_ON: 1608 /* TBD set LEDs */ 1609 break; 1610 case RTW_SLEEP: 1611 /* TBD */ 1612 break; 1613 case RTW_OFF: 1614 /* TBD */ 1615 break; 1616 } 1617 if (rc == 0) 1618 rsc->sc_pwrstate = power; 1619 else 1620 rsc->sc_pwrstate = RTW_OFF; 1621 return (rc); 1622 } 1623 1624 void 1625 rtw_disable(rtw_softc_t *rsc) 1626 { 1627 int rc; 1628 1629 if ((rsc->sc_flags & RTW_F_ENABLED) == 0) 1630 return; 1631 1632 /* turn off PHY */ 1633 if ((rsc->sc_flags & RTW_F_INVALID) == 0 && 1634 (rc = rtw_pwrstate(rsc, RTW_OFF)) != 0) { 1635 cmn_err(CE_WARN, "failed to turn off PHY (%d)\n", rc); 1636 } 1637 1638 if (rsc->sc_disable != NULL) 1639 (*rsc->sc_disable)(rsc); 1640 1641 rsc->sc_flags &= ~RTW_F_ENABLED; 1642 } 1643 1644 int 1645 rtw_enable(rtw_softc_t *rsc) 1646 { 1647 if ((rsc->sc_flags & RTW_F_ENABLED) == 0) { 1648 if (rsc->sc_enable != NULL && (*rsc->sc_enable)(rsc) != 0) { 1649 cmn_err(CE_WARN, "device enable failed\n"); 1650 return (EIO); 1651 } 1652 rsc->sc_flags |= RTW_F_ENABLED; 1653 if (rtw_pwrstate(rsc, RTW_ON) != 0) 1654 cmn_err(CE_WARN, "PHY turn on failed\n"); 1655 } 1656 return (0); 1657 } 1658 1659 static void 1660 rtw_set_nettype(rtw_softc_t *rsc, enum ieee80211_opmode opmode) 1661 { 1662 uint8_t msr; 1663 1664 /* I'm guessing that MSR is protected as CONFIG[0123] are. */ 1665 rtw_set_access(&rsc->sc_regs, RTW_ACCESS_CONFIG); 1666 1667 msr = RTW_READ8(&rsc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK; 1668 1669 switch (opmode) { 1670 case IEEE80211_M_AHDEMO: 1671 case IEEE80211_M_IBSS: 1672 msr |= RTW_MSR_NETYPE_ADHOC_OK; 1673 break; 1674 case IEEE80211_M_HOSTAP: 1675 msr |= RTW_MSR_NETYPE_AP_OK; 1676 break; 1677 case IEEE80211_M_STA: 1678 msr |= RTW_MSR_NETYPE_INFRA_OK; 1679 break; 1680 } 1681 RTW_WRITE8(&rsc->sc_regs, RTW_MSR, msr); 1682 1683 rtw_set_access(&rsc->sc_regs, RTW_ACCESS_NONE); 1684 } 1685 1686 static void 1687 rtw_pktfilt_load(rtw_softc_t *rsc) 1688 { 1689 struct rtw_regs *regs = &rsc->sc_regs; 1690 struct ieee80211com *ic = &rsc->sc_ic; 1691 1692 /* XXX might be necessary to stop Rx/Tx engines while setting filters */ 1693 rsc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK; 1694 rsc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK); 1695 1696 rsc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT; 1697 /* MAC auto-reset PHY (huh?) */ 1698 rsc->sc_rcr |= RTW_RCR_ENMARP; 1699 /* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */ 1700 rsc->sc_rcr |= RTW_RCR_RXFTH_WHOLE |RTW_RCR_MXDMA_1024; 1701 1702 switch (ic->ic_opmode) { 1703 case IEEE80211_M_AHDEMO: 1704 case IEEE80211_M_IBSS: 1705 /* receive broadcasts in our BSS */ 1706 rsc->sc_rcr |= RTW_RCR_ADD3; 1707 break; 1708 default: 1709 break; 1710 } 1711 #if 0 1712 /* XXX accept all broadcast if scanning */ 1713 rsc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */ 1714 #endif 1715 RTW_WRITE(regs, RTW_MAR0, 0xffffffff); 1716 RTW_WRITE(regs, RTW_MAR1, 0xffffffff); 1717 rsc->sc_rcr |= RTW_RCR_AM; 1718 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 1719 RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */ 1720 1721 RTW_DPRINTF(RTW_DEBUG_PKTFILT, 1722 "RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n", 1723 RTW_READ(regs, RTW_MAR0), 1724 RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR)); 1725 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 1726 } 1727 1728 static void 1729 rtw_transmit_config(struct rtw_regs *regs) 1730 { 1731 uint32_t tcr; 1732 1733 tcr = RTW_READ(regs, RTW_TCR); 1734 1735 tcr |= RTW_TCR_CWMIN; 1736 tcr &= ~RTW_TCR_MXDMA_MASK; 1737 tcr |= RTW_TCR_MXDMA_1024; 1738 tcr |= RTW_TCR_SAT; /* send ACK as fast as possible */ 1739 tcr &= ~RTW_TCR_LBK_MASK; 1740 tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */ 1741 1742 /* set short/long retry limits */ 1743 tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK); 1744 tcr |= LSHIFT(0x4, RTW_TCR_SRL_MASK) | LSHIFT(0x4, RTW_TCR_LRL_MASK); 1745 1746 tcr &= ~RTW_TCR_CRC; /* NIC appends CRC32 */ 1747 RTW_WRITE(regs, RTW_TCR, tcr); 1748 RTW_SYNC(regs, RTW_TCR, RTW_TCR); 1749 } 1750 1751 int 1752 rtw_refine_setting(rtw_softc_t *rsc) 1753 { 1754 struct rtw_regs *regs; 1755 int rc = 0; 1756 1757 regs = &rsc->sc_regs; 1758 rc = rtw_reset(rsc); 1759 if (rc != 0) 1760 return (-1); 1761 1762 rtw_beacon_tx_disable(regs); 1763 rtw_io_enable(rsc, RTW_CR_RE|RTW_CR_TE, 1); 1764 rtw_set_mode(regs, RTW_EPROM_CMD_CONFIG); 1765 1766 rtw_transmit_config(regs); 1767 rtw_pktfilt_load(rsc); 1768 rtw_set_access(regs, RTW_ACCESS_CONFIG); 1769 RTW_WRITE(regs, RTW_TINT, 0xffffffff); 1770 RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */ 1771 RTW_WRITE16(regs, RTW_BRSR, 0); 1772 1773 rtw_set_access(regs, RTW_ACCESS_ANAPARM); 1774 rtw_set_access(regs, RTW_ACCESS_NONE); 1775 RTW_WRITE(regs, RTW_FEMR, 0xffff); 1776 RTW_SYNC(regs, RTW_FEMR, RTW_FEMR); 1777 rtw_set_rfprog(regs, rsc->sc_rfchipid, "rtw"); 1778 1779 RTW_WRITE8(regs, RTW_PHYDELAY, rsc->sc_phydelay); 1780 RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC); 1781 rtw_set_mode(regs, RTW_EPROM_CMD_NORMAL); 1782 return (0); 1783 } 1784 1785 static int 1786 rtw_tune(rtw_softc_t *rsc) 1787 { 1788 struct ieee80211com *ic = &rsc->sc_ic; 1789 uint32_t chan; 1790 int rc; 1791 int antdiv = rsc->sc_flags & RTW_F_ANTDIV, 1792 dflantb = rsc->sc_flags & RTW_F_DFLANTB; 1793 1794 ASSERT(ic->ic_curchan != NULL); 1795 1796 chan = ieee80211_chan2ieee(ic, ic->ic_curchan); 1797 RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw: chan no = %x", chan); 1798 1799 if (chan == IEEE80211_CHAN_ANY) { 1800 cmn_err(CE_WARN, "%s: chan == IEEE80211_CHAN_ANY\n", __func__); 1801 return (-1); 1802 } 1803 1804 if (chan == rsc->sc_cur_chan) { 1805 RTW_DPRINTF(RTW_DEBUG_TUNE, 1806 "%s: already tuned chan %d\n", __func__, chan); 1807 return (0); 1808 } 1809 rtw_idle(&rsc->sc_regs); 1810 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0); 1811 ASSERT((rsc->sc_flags & RTW_F_ENABLED) != 0); 1812 1813 if ((rc = rtw_phy_init(&rsc->sc_regs, rsc->sc_rf, 1814 rtw_chan2txpower(&rsc->sc_srom, ic, ic->ic_curchan), 1815 rsc->sc_csthr, ic->ic_curchan->ich_freq, antdiv, 1816 dflantb, RTW_ON)) != 0) { 1817 /* XXX condition on powersaving */ 1818 cmn_err(CE_NOTE, "phy init failed\n"); 1819 } 1820 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1); 1821 rtw_resume_ticks(rsc); 1822 rsc->sc_cur_chan = chan; 1823 return (rc); 1824 } 1825 1826 static int 1827 rtw_init(rtw_softc_t *rsc) 1828 { 1829 struct ieee80211com *ic = &rsc->sc_ic; 1830 int rc = 0; 1831 1832 if ((rc = rtw_enable(rsc)) != 0) 1833 goto out; 1834 rc = rtw_refine_setting(rsc); 1835 if (rc != 0) 1836 return (rc); 1837 1838 rtw_swring_setup(rsc, 1); 1839 rtw_hwring_setup(rsc); 1840 RTW_WRITE16(&rsc->sc_regs, RTW_BSSID16, 0x0); 1841 RTW_WRITE(&rsc->sc_regs, RTW_BSSID32, 0x0); 1842 rtw_enable_interrupts(rsc); 1843 1844 ic->ic_ibss_chan = &ic->ic_sup_channels[1]; 1845 ic->ic_curchan = ic->ic_ibss_chan; 1846 RTW_DPRINTF(RTW_DEBUG_TUNE, "%s: channel %d freq %d flags 0x%04x\n", 1847 __func__, ieee80211_chan2ieee(ic, ic->ic_curchan), 1848 ic->ic_curchan->ich_freq, ic->ic_curchan->ich_flags); 1849 out: 1850 return (rc); 1851 } 1852 1853 static struct rtw_rf * 1854 rtw_rf_attach(rtw_softc_t *rsc, enum rtw_rfchipid rfchipid, int digphy) 1855 { 1856 rtw_rf_write_t rf_write; 1857 struct rtw_rf *rf; 1858 int rtw_host_rfio; 1859 1860 switch (rfchipid) { 1861 default: 1862 rf_write = rtw_rf_hostwrite; 1863 break; 1864 case RTW_RFCHIPID_INTERSIL: 1865 case RTW_RFCHIPID_PHILIPS: 1866 case RTW_RFCHIPID_GCT: /* XXX a guess */ 1867 case RTW_RFCHIPID_RFMD: 1868 rtw_host_rfio = 1; 1869 rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite; 1870 break; 1871 } 1872 1873 switch (rfchipid) { 1874 case RTW_RFCHIPID_MAXIM: 1875 rf = rtw_max2820_create(&rsc->sc_regs, rf_write, 0); 1876 rsc->sc_pwrstate_cb = rtw_maxim_pwrstate; 1877 break; 1878 case RTW_RFCHIPID_PHILIPS: 1879 rf = rtw_sa2400_create(&rsc->sc_regs, rf_write, digphy); 1880 rsc->sc_pwrstate_cb = rtw_philips_pwrstate; 1881 break; 1882 case RTW_RFCHIPID_RFMD: 1883 /* XXX RFMD has no RF constructor */ 1884 rsc->sc_pwrstate_cb = rtw_rfmd_pwrstate; 1885 /*FALLTHROUGH*/ 1886 default: 1887 return (NULL); 1888 } 1889 if (rf != NULL) { 1890 rf->rf_continuous_tx_cb = 1891 (rtw_continuous_tx_cb_t)rtw_continuous_tx_enable; 1892 rf->rf_continuous_tx_arg = (void *)rsc; 1893 } 1894 return (rf); 1895 } 1896 1897 /* 1898 * Revision C and later use a different PHY delay setting than 1899 * revisions A and B. 1900 */ 1901 static uint8_t 1902 rtw_check_phydelay(struct rtw_regs *regs, uint32_t rcr0) 1903 { 1904 #define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV) 1905 #define REVC (REVAB | RTW_RCR_RXFTH_WHOLE) 1906 1907 uint8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY); 1908 1909 RTW_WRITE(regs, RTW_RCR, REVAB); 1910 RTW_WBW(regs, RTW_RCR, RTW_RCR); 1911 RTW_WRITE(regs, RTW_RCR, REVC); 1912 1913 RTW_WBR(regs, RTW_RCR, RTW_RCR); 1914 if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC) 1915 phydelay |= RTW_PHYDELAY_REVC_MAGIC; 1916 1917 RTW_WRITE(regs, RTW_RCR, rcr0); /* restore RCR */ 1918 RTW_SYNC(regs, RTW_RCR, RTW_RCR); 1919 1920 return (phydelay); 1921 #undef REVC 1922 } 1923 1924 static void rtw_intr_rx(rtw_softc_t *rsc); 1925 static void rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri); 1926 1927 static int 1928 rtw_get_rate(struct ieee80211com *ic) 1929 { 1930 uint8_t (*rates)[IEEE80211_RATE_MAXSIZE]; 1931 int rate; 1932 1933 rates = &ic->ic_bss->in_rates.ir_rates; 1934 1935 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) 1936 rate = ic->ic_fixed_rate; 1937 else if (ic->ic_state == IEEE80211_S_RUN) 1938 rate = (*rates)[ic->ic_bss->in_txrate]; 1939 else 1940 rate = 0; 1941 return (rate & IEEE80211_RATE_VAL); 1942 } 1943 1944 /* 1945 * Arguments in: 1946 * 1947 * paylen: payload length (no FCS, no WEP header) 1948 * 1949 * hdrlen: header length 1950 * 1951 * rate: MSDU speed, units 500kb/s 1952 * 1953 * flags: IEEE80211_F_SHPREAMBLE (use short preamble), 1954 * IEEE80211_F_SHSLOT (use short slot length) 1955 * 1956 * Arguments out: 1957 * 1958 * d: 802.11 Duration field for RTS, 1959 * 802.11 Duration field for data frame, 1960 * PLCP Length for data frame, 1961 * residual octets at end of data slot 1962 */ 1963 static int 1964 rtw_compute_duration1(int len, int use_ack, uint32_t flags, int rate, 1965 struct rtw_ieee80211_duration *d) 1966 { 1967 int pre, ctsrate; 1968 uint16_t ack, bitlen, data_dur, remainder; 1969 1970 /* 1971 * RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK 1972 * DATA reserves medium for SIFS | ACK 1973 * 1974 * XXXMYC: no ACK on multicast/broadcast or control packets 1975 */ 1976 1977 bitlen = len * 8; 1978 1979 pre = IEEE80211_DUR_DS_SIFS; 1980 if ((flags & IEEE80211_F_SHPREAMBLE) != 0) 1981 pre += IEEE80211_DUR_DS_SHORT_PREAMBLE + 1982 IEEE80211_DUR_DS_FAST_PLCPHDR; 1983 else 1984 pre += IEEE80211_DUR_DS_LONG_PREAMBLE + 1985 IEEE80211_DUR_DS_SLOW_PLCPHDR; 1986 1987 d->d_residue = 0; 1988 data_dur = (bitlen * 2) / rate; 1989 remainder = (bitlen * 2) % rate; 1990 if (remainder != 0) { 1991 if (rate == 22) 1992 d->d_residue = (rate - remainder) / 16; 1993 data_dur++; 1994 } 1995 1996 switch (rate) { 1997 case 2: /* 1 Mb/s */ 1998 case 4: /* 2 Mb/s */ 1999 /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */ 2000 ctsrate = 2; 2001 break; 2002 case 11: /* 5.5 Mb/s */ 2003 case 22: /* 11 Mb/s */ 2004 case 44: /* 22 Mb/s */ 2005 /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */ 2006 ctsrate = 4; 2007 break; 2008 default: 2009 /* TBD */ 2010 return (-1); 2011 } 2012 2013 d->d_plcp_len = data_dur; 2014 2015 ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0; 2016 2017 d->d_rts_dur = 2018 pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate + 2019 pre + data_dur + 2020 ack; 2021 2022 d->d_data_dur = ack; 2023 2024 return (0); 2025 } 2026 2027 /* 2028 * Arguments in: 2029 * 2030 * wh: 802.11 header 2031 * 2032 * paylen: payload length (no FCS, no WEP header) 2033 * 2034 * rate: MSDU speed, units 500kb/s 2035 * 2036 * fraglen: fragment length, set to maximum (or higher) for no 2037 * fragmentation 2038 * 2039 * flags: IEEE80211_F_PRIVACY (hardware adds WEP), 2040 * IEEE80211_F_SHPREAMBLE (use short preamble), 2041 * IEEE80211_F_SHSLOT (use short slot length) 2042 * 2043 * Arguments out: 2044 * 2045 * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields 2046 * of first/only fragment 2047 * 2048 * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields 2049 * of first/only fragment 2050 */ 2051 static int 2052 rtw_compute_duration(struct ieee80211_frame *wh, int len, 2053 uint32_t flags, int fraglen, int rate, struct rtw_ieee80211_duration *d0, 2054 struct rtw_ieee80211_duration *dn, int *npktp) 2055 { 2056 int ack, rc; 2057 int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen; 2058 2059 /* don't think about addr4 here */ 2060 hdrlen = sizeof (struct ieee80211_frame); 2061 2062 paylen = len - hdrlen; 2063 2064 if ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0) { 2065 overlen = 8 + IEEE80211_CRC_LEN; 2066 paylen -= 8; 2067 } else 2068 overlen = IEEE80211_CRC_LEN; 2069 2070 npkt = paylen / fraglen; 2071 lastlen0 = paylen % fraglen; 2072 2073 if (npkt == 0) /* no fragments */ 2074 lastlen = paylen + overlen; 2075 else if (lastlen0 != 0) { /* a short "tail" fragment */ 2076 lastlen = lastlen0 + overlen; 2077 npkt++; 2078 } else /* full-length "tail" fragment */ 2079 lastlen = fraglen + overlen; 2080 2081 if (npktp != NULL) 2082 *npktp = npkt; 2083 2084 if (npkt > 1) 2085 firstlen = fraglen + overlen; 2086 else 2087 firstlen = paylen + overlen; 2088 2089 ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) && 2090 (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != 2091 IEEE80211_FC0_TYPE_CTL; 2092 2093 rc = rtw_compute_duration1(firstlen + hdrlen, 2094 ack, flags, rate, d0); 2095 if (rc == -1) 2096 return (rc); 2097 2098 if (npkt <= 1) { 2099 *dn = *d0; 2100 return (0); 2101 } 2102 return (rtw_compute_duration1(lastlen + hdrlen, ack, flags, 2103 rate, dn)); 2104 } 2105 2106 static int 2107 rtw_assembly_80211(rtw_softc_t *rsc, struct rtw_txbuf *bf, 2108 mblk_t *mp) 2109 { 2110 ieee80211com_t *ic; 2111 struct rtw_txdesc *ds; 2112 struct ieee80211_frame *wh; 2113 uint8_t *buf; 2114 uint32_t ctl0 = 0, ctl1 = 0; 2115 int npkt, rate; 2116 struct rtw_ieee80211_duration d0, dn; 2117 int32_t iswep, pktlen, mblen; 2118 mblk_t *mp0; 2119 2120 ic = &rsc->sc_ic; 2121 ds = bf->txdesc; 2122 buf = (uint8_t *)bf->bf_dma.mem_va; 2123 bzero(buf, bf->bf_dma.alength); 2124 bzero((uint8_t *)ds, sizeof (struct rtw_txdesc)); 2125 wh = (struct ieee80211_frame *)mp->b_rptr; 2126 iswep = wh->i_fc[1] & IEEE80211_FC1_WEP; 2127 2128 /* ieee80211_crypto_encap() needs a single mblk */ 2129 mp0 = allocb(bf->bf_dma.alength, BPRI_MED); 2130 if (mp0 == NULL) { 2131 cmn_err(CE_WARN, "%s: allocb(mp) error", __func__); 2132 return (-1); 2133 } 2134 for (; mp != NULL; mp = mp->b_cont) { 2135 mblen = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr; 2136 bcopy(mp->b_rptr, mp0->b_wptr, mblen); 2137 mp0->b_wptr += mblen; 2138 } 2139 2140 if (iswep) { 2141 struct ieee80211_key *k; 2142 2143 k = ieee80211_crypto_encap(ic, mp0); 2144 if (k == NULL) { 2145 cmn_err(CE_WARN, "%s: ieee80211_crypto_encap() error", 2146 __func__); 2147 freemsg(mp0); 2148 return (-1); 2149 } 2150 } 2151 pktlen = msgdsize(mp0); 2152 2153 #if 0 2154 RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------begin--------"); 2155 ieee80211_dump_pkt((uint8_t *)(mp0->b_rptr), pktlen, 0, 0); 2156 RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------end--------"); 2157 #endif 2158 /* RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV); */ 2159 if (pktlen > bf->bf_dma.alength) { 2160 cmn_err(CE_WARN, "%s: overlength packet pktlen = %d\n", 2161 __func__, pktlen); 2162 freemsg(mp0); 2163 return (-1); 2164 } 2165 bcopy(mp0->b_rptr, buf, pktlen); 2166 RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV); 2167 2168 /* setup descriptor */ 2169 ctl0 = RTW_TXCTL0_RTSRATE_1MBPS; 2170 2171 if (((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0) && 2172 (ic->ic_bss->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) { 2173 ctl0 |= RTW_TXCTL0_SPLCP; 2174 } 2175 /* XXX do real rate control */ 2176 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2177 IEEE80211_FC0_TYPE_MGT) 2178 rate = 2; 2179 else { 2180 rate = MAX(2, rtw_get_rate(ic)); 2181 } 2182 ctl0 = ctl0 | 2183 LSHIFT(pktlen, RTW_TXCTL0_TPKTSIZE_MASK); 2184 2185 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: rate = %d", __func__, rate); 2186 2187 switch (rate) { 2188 default: 2189 case 2: 2190 ctl0 |= RTW_TXCTL0_RATE_1MBPS; 2191 break; 2192 case 4: 2193 ctl0 |= RTW_TXCTL0_RATE_2MBPS; 2194 break; 2195 case 11: 2196 ctl0 |= RTW_TXCTL0_RATE_5MBPS; 2197 break; 2198 case 22: 2199 ctl0 |= RTW_TXCTL0_RATE_11MBPS; 2200 break; 2201 } 2202 2203 /* XXX >= ? Compare after fragmentation? */ 2204 if (pktlen > ic->ic_rtsthreshold) { 2205 ctl0 |= RTW_TXCTL0_RTSEN; 2206 cmn_err(CE_NOTE, "%s: fragmentation: pktlen = %d", 2207 __func__, pktlen); 2208 } 2209 2210 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2211 IEEE80211_FC0_TYPE_MGT) { 2212 ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN); 2213 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 2214 IEEE80211_FC0_SUBTYPE_BEACON) 2215 ctl0 |= RTW_TXCTL0_BEACON; 2216 } 2217 2218 if (rtw_compute_duration(wh, pktlen, 2219 ic->ic_flags, ic->ic_fragthreshold, 2220 rate, &d0, &dn, &npkt) == -1) { 2221 RTW_DPRINTF(RTW_DEBUG_XMIT, 2222 "%s: fail compute duration\n", __func__); 2223 freemsg(mp0); 2224 return (-1); 2225 } 2226 *(uint16_t *)(uintptr_t)wh->i_dur = (d0.d_data_dur); 2227 2228 ctl1 = LSHIFT(d0.d_plcp_len, RTW_TXCTL1_LENGTH_MASK) | 2229 LSHIFT(d0.d_rts_dur, RTW_TXCTL1_RTSDUR_MASK); 2230 2231 if (d0.d_residue) 2232 ctl1 |= RTW_TXCTL1_LENGEXT; 2233 2234 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: duration=%x, ctl1=%x", __func__, 2235 *(uint16_t *)(uintptr_t)wh->i_dur, ctl1); 2236 2237 if (bf->bf_dma.alength > RTW_TXLEN_LENGTH_MASK) { 2238 RTW_DPRINTF(RTW_DEBUG_XMIT, 2239 "%s: seg too long\n", __func__); 2240 freemsg(mp0); 2241 return (-1); 2242 } 2243 ds->td_ctl0 = ctl0; 2244 ds->td_ctl0 |= RTW_TXCTL0_OWN | RTW_TXCTL0_LS | RTW_TXCTL0_FS; 2245 ds->td_ctl1 = ctl1; 2246 ds->td_buf = bf->bf_dma.cookie.dmac_address; 2247 ds->td_len = pktlen & 0xfff; 2248 ds->td_next = bf->next_bf_daddr; 2249 2250 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2251 RTW_DESC_OFFSET(hd_txmd, bf->order), 2252 sizeof (struct rtw_txdesc), 2253 DDI_DMA_SYNC_FORDEV); 2254 2255 RTW_DPRINTF(RTW_DEBUG_XMIT, 2256 "descriptor: order = %d, phy_addr=%x, ctl0=%x," 2257 " ctl1=%x, buf=%x, len=%x, next=%x", bf->order, 2258 bf->bf_daddr, ds->td_ctl0, ds->td_ctl1, 2259 ds->td_buf, ds->td_len, ds->td_next); 2260 rsc->sc_pktxmt64++; 2261 rsc->sc_bytexmt64 += pktlen; 2262 2263 freemsg(mp0); 2264 return (0); 2265 } 2266 2267 static int 2268 rtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 2269 { 2270 rtw_softc_t *rsc = (rtw_softc_t *)ic; 2271 struct ieee80211_node *in = ic->ic_bss; 2272 struct rtw_txbuf *bf = NULL; 2273 int ret, i = RTW_TXPRIMD; 2274 2275 mutex_enter(&rsc->sc_txlock); 2276 mutex_enter(&rsc->sc_txq[i].txbuf_lock); 2277 bf = list_head(&rsc->sc_txq[i].tx_free_list); 2278 2279 if ((bf == NULL) || (rsc->sc_txq[i].tx_nfree <= 4)) { 2280 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: no tx buf\n", __func__); 2281 rsc->sc_noxmtbuf++; 2282 if ((type & IEEE80211_FC0_TYPE_MASK) == 2283 IEEE80211_FC0_TYPE_DATA) { 2284 RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: need reschedule\n", 2285 __func__); 2286 rsc->sc_need_reschedule = 1; 2287 } else { 2288 freemsg(mp); 2289 } 2290 mutex_exit(&rsc->sc_txq[i].txbuf_lock); 2291 mutex_exit(&rsc->sc_txlock); 2292 return (1); 2293 } 2294 list_remove(&rsc->sc_txq[i].tx_free_list, bf); 2295 rsc->sc_txq[i].tx_nfree--; 2296 2297 /* assemble 802.11 frame here */ 2298 ret = rtw_assembly_80211(rsc, bf, mp); 2299 if (ret != 0) { 2300 cmn_err(CE_WARN, "%s assembly frame error\n", __func__); 2301 mutex_exit(&rsc->sc_txq[i].txbuf_lock); 2302 mutex_exit(&rsc->sc_txlock); 2303 if ((type & IEEE80211_FC0_TYPE_MASK) != 2304 IEEE80211_FC0_TYPE_DATA) { 2305 freemsg(mp); 2306 } 2307 return (1); 2308 } 2309 list_insert_tail(&rsc->sc_txq[i].tx_dirty_list, bf); 2310 bf->bf_in = in; 2311 rtw_dma_start(&rsc->sc_regs, i); 2312 2313 mutex_exit(&rsc->sc_txq[i].txbuf_lock); 2314 mutex_exit(&rsc->sc_txlock); 2315 2316 freemsg(mp); 2317 return (0); 2318 } 2319 2320 static mblk_t * 2321 rtw_m_tx(void *arg, mblk_t *mp) 2322 { 2323 rtw_softc_t *rsc = arg; 2324 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2325 mblk_t *next; 2326 2327 if (ic->ic_state != IEEE80211_S_RUN) { 2328 freemsgchain(mp); 2329 return (NULL); 2330 } 2331 2332 while (mp != NULL) { 2333 next = mp->b_next; 2334 mp->b_next = NULL; 2335 2336 if (rtw_send(ic, mp, IEEE80211_FC0_TYPE_DATA)) { 2337 mp->b_next = next; 2338 break; 2339 } 2340 mp = next; 2341 } 2342 2343 return (mp); 2344 2345 } 2346 2347 static void 2348 rtw_next_scan(void *arg) 2349 { 2350 ieee80211com_t *ic = arg; 2351 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2352 2353 rsc->sc_scan_id = 0; 2354 if (ic->ic_state == IEEE80211_S_SCAN) { 2355 RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw_next_scan\n"); 2356 (void) ieee80211_next_scan(ic); 2357 } 2358 2359 } 2360 2361 static void 2362 rtw_join_bss(rtw_softc_t *rsc, uint8_t *bssid, uint16_t intval0) 2363 { 2364 uint16_t bcnitv, intval; 2365 int i; 2366 struct rtw_regs *regs = &rsc->sc_regs; 2367 2368 for (i = 0; i < IEEE80211_ADDR_LEN; i++) 2369 RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]); 2370 2371 RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32); 2372 rtw_set_access(regs, RTW_ACCESS_CONFIG); 2373 2374 RTW_WRITE8(regs, RTW_MSR, 0x8); /* sta mode link ok */ 2375 intval = MIN(intval0, PRESHIFT(RTW_BCNITV_BCNITV_MASK)); 2376 2377 bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK; 2378 bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK); 2379 RTW_WRITE16(regs, RTW_BCNITV, bcnitv); 2380 RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND)); 2381 RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV)); 2382 2383 rtw_set_access(regs, RTW_ACCESS_NONE); 2384 2385 /* TBD WEP */ 2386 /* RTW_WRITE8(regs, RTW_SCR, 0); */ 2387 2388 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1); 2389 } 2390 2391 /* 2392 * Set the starting transmit rate for a node. 2393 */ 2394 static void 2395 rtw_rate_ctl_start(rtw_softc_t *rsc, struct ieee80211_node *in) 2396 { 2397 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2398 int32_t srate; 2399 2400 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 2401 /* 2402 * No fixed rate is requested. For 11b start with 2403 * the highest negotiated rate; otherwise, for 11g 2404 * and 11a, we start "in the middle" at 24Mb or 36Mb. 2405 */ 2406 srate = in->in_rates.ir_nrates - 1; 2407 if (ic->ic_curmode != IEEE80211_MODE_11B) { 2408 /* 2409 * Scan the negotiated rate set to find the 2410 * closest rate. 2411 */ 2412 /* NB: the rate set is assumed sorted */ 2413 for (; srate >= 0 && IEEE80211_RATE(srate) > 72; 2414 srate--) 2415 ; 2416 } 2417 } else { 2418 /* 2419 * A fixed rate is to be used; We know the rate is 2420 * there because the rate set is checked when the 2421 * station associates. 2422 */ 2423 /* NB: the rate set is assumed sorted */ 2424 srate = in->in_rates.ir_nrates - 1; 2425 for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate; 2426 srate--) 2427 ; 2428 } 2429 in->in_txrate = srate; 2430 } 2431 2432 2433 /* 2434 * Reset the rate control state for each 802.11 state transition. 2435 */ 2436 static void 2437 rtw_rate_ctl_reset(rtw_softc_t *rsc, enum ieee80211_state state) 2438 { 2439 ieee80211com_t *ic = &rsc->sc_ic; 2440 ieee80211_node_t *in; 2441 2442 if (ic->ic_opmode == IEEE80211_M_STA) { 2443 /* 2444 * Reset local xmit state; this is really only 2445 * meaningful when operating in station mode. 2446 */ 2447 in = (struct ieee80211_node *)ic->ic_bss; 2448 2449 if (state == IEEE80211_S_RUN) { 2450 rtw_rate_ctl_start(rsc, in); 2451 } else { 2452 in->in_txrate = 0; 2453 } 2454 } 2455 #if 0 2456 else { 2457 /* 2458 * When operating as a station the node table holds 2459 * the AP's that were discovered during scanning. 2460 * For any other operating mode we want to reset the 2461 * tx rate state of each node. 2462 */ 2463 in = list_head(&ic->ic_in_list); 2464 while (in != NULL) { 2465 in->in_txrate = 0; 2466 in = list_next(&ic->ic_in_list, in); 2467 } 2468 in->in_txrate = 0; 2469 } 2470 #endif 2471 } 2472 2473 static int startctl = 0; 2474 2475 /* 2476 * Examine and potentially adjust the transmit rate. 2477 */ 2478 static void 2479 rtw_rate_ctl(void *arg) 2480 { 2481 ieee80211com_t *ic = (ieee80211com_t *)arg; 2482 rtw_softc_t *rsc = (rtw_softc_t *)ic; 2483 struct ieee80211_node *in = ic->ic_bss; 2484 struct ieee80211_rateset *rs = &in->in_rates; 2485 int32_t mod = 0, nrate, enough; 2486 2487 mutex_enter(&rsc->sc_genlock); 2488 2489 enough = (rsc->sc_tx_ok + rsc->sc_tx_err >= 10); 2490 2491 /* no packet reached -> down */ 2492 if (rsc->sc_tx_err > 0 && rsc->sc_tx_ok == 0) 2493 mod = -1; 2494 2495 /* all packets needs retry in average -> down */ 2496 if (enough && rsc->sc_tx_ok < rsc->sc_tx_err) 2497 mod = -1; 2498 2499 /* no error and less than 10% of packets needs retry -> up */ 2500 if (enough && 2501 rsc->sc_tx_ok > rsc->sc_tx_err * 5) 2502 mod = 1; 2503 2504 nrate = in->in_txrate; 2505 switch (mod) { 2506 case 0: 2507 if (enough && rsc->sc_tx_upper > 0) 2508 rsc->sc_tx_upper--; 2509 break; 2510 case -1: 2511 if (nrate > 0) { 2512 nrate--; 2513 } 2514 rsc->sc_tx_upper = 0; 2515 break; 2516 case 1: 2517 if (++rsc->sc_tx_upper < 10) 2518 break; 2519 rsc->sc_tx_upper = 0; 2520 if (nrate + 1 < rs->ir_nrates) { 2521 nrate++; 2522 } 2523 break; 2524 } 2525 2526 if (nrate != in->in_txrate) { 2527 in->in_txrate = nrate; 2528 } else if (enough) 2529 rsc->sc_tx_ok = rsc->sc_tx_err = rsc->sc_tx_retr = 0; 2530 if (!startctl) { 2531 rsc->sc_tx_ok = rsc->sc_tx_err = rsc->sc_tx_retr = 0; 2532 startctl = 1; 2533 } 2534 2535 mutex_exit(&rsc->sc_genlock); 2536 if (ic->ic_state == IEEE80211_S_RUN) 2537 rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic, 2538 drv_usectohz(1000000)); 2539 } 2540 2541 static int32_t 2542 rtw_new_state(ieee80211com_t *ic, enum ieee80211_state nstate, int arg) 2543 { 2544 rtw_softc_t *rsc = (rtw_softc_t *)ic; 2545 int error; 2546 enum ieee80211_state ostate; 2547 2548 ostate = ic->ic_state; 2549 2550 RTW_DPRINTF(RTW_DEBUG_ATTACH, 2551 "rtw_new_state: ostate:0x%x, nstate:0x%x, opmode:0x%x\n", 2552 ostate, nstate, ic->ic_opmode); 2553 2554 2555 mutex_enter(&rsc->sc_genlock); 2556 if (rsc->sc_scan_id != 0) { 2557 (void) untimeout(rsc->sc_scan_id); 2558 rsc->sc_scan_id = 0; 2559 } 2560 if (rsc->sc_ratectl_id != 0) { 2561 (void) untimeout(rsc->sc_ratectl_id); 2562 rsc->sc_ratectl_id = 0; 2563 } 2564 rtw_rate_ctl_reset(rsc, nstate); 2565 if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT) 2566 (void) rtw_pwrstate(rsc, RTW_ON); 2567 if ((error = rtw_tune(rsc)) != 0) { 2568 mutex_exit(&rsc->sc_genlock); 2569 return (error); 2570 } 2571 switch (nstate) { 2572 case IEEE80211_S_INIT: 2573 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_INIT\n"); 2574 startctl = 0; 2575 break; 2576 case IEEE80211_S_SCAN: 2577 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_SCAN\n"); 2578 rsc->sc_scan_id = timeout(rtw_next_scan, ic, 2579 drv_usectohz(200000)); 2580 rtw_set_nettype(rsc, IEEE80211_M_MONITOR); 2581 break; 2582 case IEEE80211_S_RUN: 2583 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_RUN\n"); 2584 switch (ic->ic_opmode) { 2585 case IEEE80211_M_HOSTAP: 2586 case IEEE80211_M_IBSS: 2587 rtw_set_nettype(rsc, IEEE80211_M_MONITOR); 2588 /* TBD */ 2589 /*FALLTHROUGH*/ 2590 case IEEE80211_M_AHDEMO: 2591 case IEEE80211_M_STA: 2592 RTW_DPRINTF(RTW_DEBUG_ATTACH, 2593 "rtw_new_state: sta\n"); 2594 rtw_join_bss(rsc, ic->ic_bss->in_bssid, 0); 2595 rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic, 2596 drv_usectohz(1000000)); 2597 break; 2598 case IEEE80211_M_MONITOR: 2599 break; 2600 } 2601 rtw_set_nettype(rsc, ic->ic_opmode); 2602 break; 2603 case IEEE80211_S_ASSOC: 2604 case IEEE80211_S_AUTH: 2605 break; 2606 } 2607 2608 mutex_exit(&rsc->sc_genlock); 2609 /* 2610 * Invoke the parent method to complete the work. 2611 */ 2612 error = rsc->sc_newstate(ic, nstate, arg); 2613 2614 return (error); 2615 } 2616 2617 static void 2618 rtw_intr_rx(rtw_softc_t *rsc) 2619 { 2620 #define IS_BEACON(__fc0) \ 2621 ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\ 2622 (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON)) 2623 /* 2624 * ratetbl[4] = {2, 4, 11, 22}; 2625 */ 2626 struct rtw_rxbuf *bf; 2627 struct rtw_rxdesc *ds; 2628 int hwrate, len, rssi; 2629 uint32_t hstat, hrssi, htsftl; 2630 int is_last, next, n = 0, i; 2631 struct ieee80211_frame *wh; 2632 ieee80211com_t *ic = (ieee80211com_t *)rsc; 2633 mblk_t *mp; 2634 2635 RTW_DPRINTF(RTW_DEBUG_RECV, "%s rtw_intr_rx: enter ic_state=%x\n", 2636 __func__, rsc->sc_ic.ic_state); 2637 mutex_enter(&rsc->rxbuf_lock); 2638 next = rsc->rx_next; 2639 mutex_exit(&rsc->rxbuf_lock); 2640 for (i = 0; i < RTW_RXQLEN; i++) { 2641 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2642 RTW_DESC_OFFSET(hd_rx, next), 2643 sizeof (struct rtw_rxdesc), 2644 DDI_DMA_SYNC_FORKERNEL); 2645 n++; 2646 bf = rsc->rxbuf_h + next; 2647 ds = bf->rxdesc; 2648 hstat = (ds->rd_stat); 2649 hrssi = ds->rd_rssi; 2650 htsftl = ds->rd_tsftl; 2651 /* htsfth = ds->rd_tsfth; */ 2652 RTW_DPRINTF(RTW_DEBUG_RECV, "%s: stat=%x\n", __func__, hstat); 2653 /* still belongs to NIC */ 2654 if ((hstat & RTW_RXSTAT_OWN) != 0) { 2655 if (n > 1) { 2656 RTW_DPRINTF(RTW_DEBUG_RECV, 2657 "%s: n > 1\n", __func__); 2658 break; 2659 } 2660 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2661 RTW_DESC_OFFSET(hd_rx, 0), 2662 sizeof (struct rtw_rxdesc), 2663 DDI_DMA_SYNC_FORCPU); 2664 bf = rsc->rxbuf_h; 2665 ds = bf->rxdesc; 2666 hstat = (ds->rd_stat); 2667 if ((hstat & RTW_RXSTAT_OWN) != 0) 2668 break; 2669 next = 0 /* RTW_RXQLEN - 1 */; 2670 continue; 2671 } 2672 2673 rsc->sc_pktrcv64++; 2674 if ((hstat & RTW_RXSTAT_IOERROR) != 0) { 2675 RTW_DPRINTF(RTW_DEBUG_RECV, 2676 "rtw: DMA error/FIFO overflow %08x, " 2677 "rx descriptor %d\n", 2678 hstat & RTW_RXSTAT_IOERROR, next); 2679 goto next; 2680 } 2681 2682 len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK); 2683 rsc->sc_bytercv64 += len; 2684 2685 /* CRC is included with the packet; trim it off. */ 2686 /* len -= IEEE80211_CRC_LEN; */ 2687 2688 hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK); 2689 if (hwrate >= 4) { 2690 goto next; 2691 } 2692 2693 if ((hstat & RTW_RXSTAT_RES) != 0 && 2694 rsc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) { 2695 goto next; 2696 } 2697 2698 /* if bad flags, skip descriptor */ 2699 if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) { 2700 RTW_DPRINTF(RTW_DEBUG_RECV, 2701 "rtw too many rx segments\n"); 2702 goto next; 2703 } 2704 2705 if (rsc->sc_rfchipid == RTW_RFCHIPID_PHILIPS) 2706 rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI); 2707 else { 2708 rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI); 2709 /* 2710 * TBD find out each front-end's LNA gain in the 2711 * front-end's units 2712 */ 2713 if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0) 2714 rssi |= 0x80; 2715 } 2716 /* sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ); */ 2717 2718 2719 /* deal with the frame itself here */ 2720 mp = allocb(rsc->sc_dmabuf_size, BPRI_MED); 2721 if (mp == NULL) { 2722 cmn_err(CE_WARN, "rtw: alloc mblk error"); 2723 rsc->sc_norcvbuf++; 2724 return; 2725 } 2726 len -= IEEE80211_CRC_LEN; 2727 RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORKERNEL); 2728 bcopy(bf->bf_dma.mem_va, mp->b_rptr, len); 2729 mp->b_wptr += len; 2730 wh = (struct ieee80211_frame *)mp->b_rptr; 2731 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 2732 IEEE80211_FC0_TYPE_CTL) { 2733 cmn_err(CE_WARN, "TYPE CTL !!\n"); 2734 freemsg(mp); 2735 goto next; 2736 } 2737 (void) ieee80211_input(ic, mp, ic->ic_bss, rssi, htsftl); 2738 next: 2739 if (next == 63) 2740 is_last = 1; 2741 else 2742 is_last = 0; 2743 rtw_rxdesc_init(rsc, bf, next, is_last); 2744 2745 next = (next + 1)%RTW_RXQLEN; 2746 RTW_DPRINTF(RTW_DEBUG_RECV, "%s: next = %d\n", __func__, next); 2747 } 2748 mutex_enter(&rsc->rxbuf_lock); 2749 rsc->rx_next = next; 2750 mutex_exit(&rsc->rxbuf_lock); 2751 } 2752 2753 static void 2754 rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri) 2755 { 2756 struct rtw_txbuf *bf; 2757 struct rtw_txdesc *ds; 2758 uint32_t hstat; 2759 uint32_t head = 0; 2760 uint32_t cnt = 0, idx = 0; 2761 2762 mutex_enter(&rsc->sc_txq[pri].txbuf_lock); 2763 head = RTW_READ(&rsc->sc_regs, RTW_TNPDA); 2764 if (head == rsc->hw_go) { 2765 mutex_exit(&rsc->sc_txq[pri].txbuf_lock); 2766 return; 2767 } 2768 RTW_DPRINTF(RTW_DEBUG_XMIT, "rtw_ring_recycling: enter ic_state=%x\n", 2769 rsc->sc_ic.ic_state); 2770 2771 bf = list_head(&rsc->sc_txq[pri].tx_dirty_list); 2772 if (bf == NULL) { 2773 RTW_DPRINTF(RTW_DEBUG_XMIT, 2774 "rtw_ring_recycling: dirty bf[%d] NULL\n", pri); 2775 mutex_exit(&rsc->sc_txq[pri].txbuf_lock); 2776 return; 2777 } 2778 2779 while ((bf != NULL) && (rsc->hw_go != head)) { 2780 cnt++; 2781 idx = (rsc->hw_go - rsc->hw_start) / sizeof (struct rtw_txdesc); 2782 if (idx == 63) 2783 rsc->hw_go = rsc->hw_start; 2784 else 2785 rsc->hw_go += sizeof (struct rtw_txdesc); 2786 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2787 RTW_DESC_OFFSET(hd_txmd, idx), 2788 sizeof (struct rtw_txdesc), 2789 DDI_DMA_SYNC_FORCPU); 2790 2791 RTW_DPRINTF(RTW_DEBUG_XMIT, "Head = 0x%x\n", head); 2792 ds = bf->txdesc; 2793 hstat = (ds->td_stat); 2794 ds->td_len = ds->td_len & 0xfff; 2795 RTW_DPRINTF(RTW_DEBUG_XMIT, 2796 "%s rtw_ring_recycling: stat=%x, pri=%x\n", 2797 __func__, hstat, pri); 2798 if (hstat & RTW_TXSTAT_TOK) 2799 rsc->sc_tx_ok++; 2800 else { 2801 RTW_DPRINTF(RTW_DEBUG_XMIT, 2802 "TX err @%d, o %d, retry[%d], isr[0x%x], cnt %d\n", 2803 idx, (hstat & RTW_TXSTAT_OWN)?1:0, 2804 (hstat & RTW_TXSTAT_DRC_MASK), isr, cnt); 2805 if ((hstat & RTW_TXSTAT_DRC_MASK) <= 4) { 2806 rsc->sc_tx_ok++; 2807 } else { 2808 rsc->sc_tx_err++; 2809 } 2810 } 2811 rsc->sc_tx_retr += 2812 (hstat & RTW_TXSTAT_DRC_MASK); 2813 rsc->sc_xmtretry += 2814 (hstat & RTW_TXSTAT_DRC_MASK); 2815 list_remove(&rsc->sc_txq[pri].tx_dirty_list, bf); 2816 list_insert_tail(&rsc->sc_txq[pri].tx_free_list, 2817 bf); 2818 (rsc->sc_txq[pri].tx_nfree)++; 2819 if (rsc->sc_need_reschedule == 1) { 2820 mac_tx_update(rsc->sc_ic.ic_mach); 2821 rsc->sc_need_reschedule = 0; 2822 } 2823 RTW_DPRINTF(RTW_DEBUG_XMIT, 2824 "rtw_ring_recycling: nfree[%d]=%d\n", 2825 pri, rsc->sc_txq[pri].tx_nfree); 2826 bzero((uint8_t *)ds, sizeof (struct rtw_txdesc)); 2827 RTW_DMA_SYNC_DESC(rsc->sc_desc_dma, 2828 RTW_DESC_OFFSET(hd_txmd, idx), 2829 sizeof (struct rtw_txdesc), 2830 DDI_DMA_SYNC_FORDEV); 2831 bf = list_head(&rsc->sc_txq[pri].tx_dirty_list); 2832 } 2833 mutex_exit(&rsc->sc_txq[pri].txbuf_lock); 2834 } 2835 2836 static void 2837 rtw_intr_timeout(rtw_softc_t *rsc) 2838 { 2839 rtw_resume_ticks(rsc); 2840 } 2841 2842 static uint_t 2843 rtw_intr(caddr_t arg) 2844 { 2845 /* LINTED E_BAD_PTR_CAST_ALIGN */ 2846 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2847 struct rtw_regs *regs = &rsc->sc_regs; 2848 uint16_t isr = 0; 2849 2850 mutex_enter(&rsc->sc_genlock); 2851 isr = RTW_READ16(regs, RTW_ISR); 2852 RTW_WRITE16(regs, RTW_ISR, isr); 2853 2854 if (isr == 0) { 2855 mutex_exit(&rsc->sc_genlock); 2856 return (DDI_INTR_UNCLAIMED); 2857 } 2858 2859 #ifdef DEBUG 2860 #define PRINTINTR(flag) { \ 2861 if ((isr & flag) != 0) { \ 2862 RTW_DPRINTF(RTW_DEBUG_INTR, "|" #flag); \ 2863 } \ 2864 } 2865 2866 if ((rtw_dbg_flags & RTW_DEBUG_INTR) != 0 && isr != 0) { 2867 2868 RTW_DPRINTF(RTW_DEBUG_INTR, "rtw: reg[ISR] = %x", isr); 2869 2870 PRINTINTR(RTW_INTR_TXFOVW); 2871 PRINTINTR(RTW_INTR_TIMEOUT); 2872 PRINTINTR(RTW_INTR_BCNINT); 2873 PRINTINTR(RTW_INTR_ATIMINT); 2874 PRINTINTR(RTW_INTR_TBDER); 2875 PRINTINTR(RTW_INTR_TBDOK); 2876 PRINTINTR(RTW_INTR_THPDER); 2877 PRINTINTR(RTW_INTR_THPDOK); 2878 PRINTINTR(RTW_INTR_TNPDER); 2879 PRINTINTR(RTW_INTR_TNPDOK); 2880 PRINTINTR(RTW_INTR_RXFOVW); 2881 PRINTINTR(RTW_INTR_RDU); 2882 PRINTINTR(RTW_INTR_TLPDER); 2883 PRINTINTR(RTW_INTR_TLPDOK); 2884 PRINTINTR(RTW_INTR_RER); 2885 PRINTINTR(RTW_INTR_ROK); 2886 } 2887 #undef PRINTINTR 2888 #endif /* DEBUG */ 2889 2890 rsc->sc_intr++; 2891 2892 if ((isr & RTW_INTR_RX) != 0) { 2893 mutex_exit(&rsc->sc_genlock); 2894 rtw_intr_rx(rsc); 2895 mutex_enter(&rsc->sc_genlock); 2896 } 2897 if ((isr & RTW_INTR_TIMEOUT) != 0) 2898 rtw_intr_timeout(rsc); 2899 2900 if ((isr & RTW_INTR_TX) != 0) 2901 rtw_ring_recycling(rsc, isr, 1); 2902 mutex_exit(&rsc->sc_genlock); 2903 return (DDI_INTR_CLAIMED); 2904 } 2905 2906 static void 2907 rtw_m_stop(void *arg) 2908 { 2909 rtw_softc_t *rsc = (rtw_softc_t *)arg; 2910 struct rtw_regs *regs = &rsc->sc_regs; 2911 2912 (void) ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1); 2913 /* 2914 * Stop the transmit and receive processes. First stop DMA, 2915 * then disable receiver and transmitter. 2916 */ 2917 mutex_enter(&rsc->sc_genlock); 2918 rtw_disable_interrupts(regs); 2919 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0); 2920 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); 2921 mutex_exit(&rsc->sc_genlock); 2922 delay(1); 2923 2924 rsc->sc_invalid = 1; 2925 } 2926 2927 /* 2928 * quiesce(9E) entry point. 2929 * 2930 * This function is called when the system is single-threaded at high 2931 * PIL with preemption disabled. Therefore, this function must not be 2932 * blocked. 2933 * 2934 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 2935 * DDI_FAILURE indicates an error condition and should almost never happen. 2936 */ 2937 int 2938 rtw_quiesce(dev_info_t *dip) 2939 { 2940 rtw_softc_t *rsc = NULL; 2941 struct rtw_regs *regs; 2942 2943 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(dip)); 2944 ASSERT(rsc != NULL); 2945 regs = &rsc->sc_regs; 2946 2947 rtw_dbg_flags = 0; 2948 rtw_disable_interrupts(regs); 2949 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0); 2950 RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL); 2951 2952 return (DDI_SUCCESS); 2953 } 2954 2955 /* 2956 * callback functions for /get/set properties 2957 */ 2958 static int 2959 rtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2960 uint_t wldp_length, const void *wldp_buf) 2961 { 2962 rtw_softc_t *rsc = arg; 2963 int err; 2964 2965 err = ieee80211_setprop(&rsc->sc_ic, pr_name, wldp_pr_num, 2966 wldp_length, wldp_buf); 2967 2968 mutex_enter(&rsc->sc_genlock); 2969 if (err == ENETRESET) { 2970 if (rsc->sc_invalid == 0) { 2971 mutex_exit(&rsc->sc_genlock); 2972 rtw_m_stop(rsc); 2973 (void) rtw_m_start(rsc); 2974 (void) ieee80211_new_state(&rsc->sc_ic, 2975 IEEE80211_S_SCAN, -1); 2976 mutex_enter(&rsc->sc_genlock); 2977 } 2978 err = 0; 2979 } 2980 mutex_exit(&rsc->sc_genlock); 2981 return (err); 2982 } 2983 2984 static int 2985 rtw_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2986 uint_t pr_flags, uint_t wldp_length, void *wldp_buf, uint_t *perm) 2987 { 2988 rtw_softc_t *rsc = arg; 2989 int err; 2990 2991 err = ieee80211_getprop(&rsc->sc_ic, pr_name, wldp_pr_num, 2992 pr_flags, wldp_length, wldp_buf, perm); 2993 2994 return (err); 2995 } 2996 2997 2998 static int 2999 rtw_m_start(void *arg) 3000 { 3001 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3002 ieee80211com_t *ic = (ieee80211com_t *)rsc; 3003 int ret; 3004 #ifdef DEBUG 3005 rtw_print_regs(&rsc->sc_regs, "rtw", "rtw_start"); 3006 #endif 3007 mutex_enter(&rsc->sc_genlock); 3008 ret = rtw_init(rsc); 3009 if (ret) { 3010 cmn_err(CE_WARN, "rtw: failed to do rtw_init\n"); 3011 mutex_exit(&rsc->sc_genlock); 3012 return (-1); 3013 } 3014 ic->ic_state = IEEE80211_S_INIT; 3015 mutex_exit(&rsc->sc_genlock); 3016 3017 /* 3018 * fix KCF bug. - workaround, need to fix it in net80211 3019 */ 3020 (void) crypto_mech2id(SUN_CKM_RC4); 3021 3022 (void) ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 3023 rsc->sc_invalid = 0; 3024 return (0); 3025 } 3026 3027 3028 static int 3029 rtw_m_unicst(void *arg, const uint8_t *macaddr) 3030 { 3031 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3032 ieee80211com_t *ic = (ieee80211com_t *)rsc; 3033 struct rtw_regs *regs = &rsc->sc_regs; 3034 uint32_t t; 3035 3036 mutex_enter(&rsc->sc_genlock); 3037 bcopy(macaddr, ic->ic_macaddr, 6); 3038 t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) | 3039 ((*(macaddr + 2))<<8) | (*(macaddr + 3)); 3040 RTW_WRITE(regs, RTW_IDR0, ntohl(t)); 3041 t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16); 3042 RTW_WRITE(regs, RTW_IDR1, ntohl(t)); 3043 mutex_exit(&rsc->sc_genlock); 3044 return (0); 3045 } 3046 3047 static int 3048 rtw_m_promisc(void *arg, boolean_t on) 3049 { 3050 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3051 struct rtw_regs *regs = &rsc->sc_regs; 3052 3053 mutex_enter(&rsc->sc_genlock); 3054 3055 if (on) 3056 rsc->sc_rcr |= RTW_RCR_PROMIC; 3057 else 3058 rsc->sc_rcr &= ~RTW_RCR_PROMIC; 3059 3060 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 3061 3062 mutex_exit(&rsc->sc_genlock); 3063 return (0); 3064 } 3065 3066 static int 3067 rtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr) 3068 { 3069 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3070 struct rtw_regs *regs = &rsc->sc_regs; 3071 uint32_t t; 3072 3073 mutex_enter(&rsc->sc_genlock); 3074 if (add) { 3075 rsc->sc_rcr |= RTW_RCR_AM; 3076 t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) | 3077 ((*(macaddr + 2))<<8) | (*(macaddr + 3)); 3078 RTW_WRITE(regs, RTW_MAR0, ntohl(t)); 3079 t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16); 3080 RTW_WRITE(regs, RTW_MAR1, ntohl(t)); 3081 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 3082 RTW_SYNC(regs, RTW_MAR0, RTW_RCR); 3083 } else { 3084 rsc->sc_rcr &= ~RTW_RCR_AM; 3085 RTW_WRITE(regs, RTW_MAR0, 0); 3086 RTW_WRITE(regs, RTW_MAR1, 0); 3087 RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr); 3088 RTW_SYNC(regs, RTW_MAR0, RTW_RCR); 3089 } 3090 mutex_exit(&rsc->sc_genlock); 3091 return (0); 3092 } 3093 3094 static void 3095 rtw_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 3096 { 3097 rtw_softc_t *rsc = arg; 3098 int32_t err; 3099 3100 err = ieee80211_ioctl(&rsc->sc_ic, wq, mp); 3101 if (err == ENETRESET) { 3102 if (rsc->sc_invalid == 0) { 3103 rtw_m_stop(rsc); 3104 (void) rtw_m_start(rsc); 3105 (void) ieee80211_new_state(&rsc->sc_ic, 3106 IEEE80211_S_SCAN, -1); 3107 } 3108 } 3109 } 3110 3111 static int 3112 rtw_m_stat(void *arg, uint_t stat, uint64_t *val) 3113 { 3114 rtw_softc_t *rsc = (rtw_softc_t *)arg; 3115 ieee80211com_t *ic = (ieee80211com_t *)rsc; 3116 struct ieee80211_node *in = ic->ic_bss; 3117 struct ieee80211_rateset *rs = &in->in_rates; 3118 3119 mutex_enter(&rsc->sc_genlock); 3120 switch (stat) { 3121 case MAC_STAT_IFSPEED: 3122 *val = ((rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL)) 3123 * 500000; 3124 break; 3125 case MAC_STAT_NOXMTBUF: 3126 *val = rsc->sc_noxmtbuf; 3127 break; 3128 case MAC_STAT_NORCVBUF: 3129 *val = rsc->sc_norcvbuf; 3130 break; 3131 case MAC_STAT_RBYTES: 3132 *val = rsc->sc_bytercv64; 3133 break; 3134 case MAC_STAT_IPACKETS: 3135 *val = rsc->sc_pktrcv64; 3136 break; 3137 case MAC_STAT_OBYTES: 3138 *val = rsc->sc_bytexmt64; 3139 break; 3140 case MAC_STAT_OPACKETS: 3141 *val = rsc->sc_pktxmt64; 3142 break; 3143 case WIFI_STAT_TX_RETRANS: 3144 *val = rsc->sc_xmtretry; 3145 break; 3146 case WIFI_STAT_TX_FRAGS: 3147 case WIFI_STAT_MCAST_TX: 3148 case WIFI_STAT_RTS_SUCCESS: 3149 case WIFI_STAT_RTS_FAILURE: 3150 case WIFI_STAT_ACK_FAILURE: 3151 case WIFI_STAT_RX_FRAGS: 3152 case WIFI_STAT_MCAST_RX: 3153 case WIFI_STAT_RX_DUPS: 3154 mutex_exit(&rsc->sc_genlock); 3155 return (ieee80211_stat(ic, stat, val)); 3156 default: 3157 *val = 0; 3158 break; 3159 } 3160 mutex_exit(&rsc->sc_genlock); 3161 3162 return (0); 3163 } 3164 3165 3166 static void 3167 rtw_mutex_destroy(rtw_softc_t *rsc) 3168 { 3169 int i; 3170 3171 mutex_destroy(&rsc->rxbuf_lock); 3172 mutex_destroy(&rsc->sc_txlock); 3173 for (i = 0; i < RTW_NTXPRI; i++) { 3174 mutex_destroy(&rsc->sc_txq[RTW_NTXPRI - 1 - i].txbuf_lock); 3175 } 3176 mutex_destroy(&rsc->sc_genlock); 3177 } 3178 3179 static int 3180 rtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 3181 { 3182 rtw_softc_t *rsc; 3183 ieee80211com_t *ic; 3184 uint8_t csz; 3185 uint32_t i; 3186 uint16_t vendor_id, device_id, command; 3187 int32_t err; 3188 char strbuf[32]; 3189 wifi_data_t wd = { 0 }; 3190 mac_register_t *macp; 3191 int instance = ddi_get_instance(devinfo); 3192 3193 switch (cmd) { 3194 case DDI_ATTACH: 3195 break; 3196 default: 3197 return (DDI_FAILURE); 3198 } 3199 3200 if (ddi_soft_state_zalloc(rtw_soft_state_p, 3201 ddi_get_instance(devinfo)) != DDI_SUCCESS) { 3202 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3203 "Unable to alloc softstate\n"); 3204 return (DDI_FAILURE); 3205 } 3206 3207 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo)); 3208 ic = &rsc->sc_ic; 3209 rsc->sc_dev = devinfo; 3210 3211 err = ddi_regs_map_setup(devinfo, 0, (caddr_t *)&rsc->sc_cfg_base, 0, 0, 3212 &rtw_reg_accattr, &rsc->sc_cfg_handle); 3213 if (err != DDI_SUCCESS) { 3214 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3215 "ddi_regs_map_setup() failed"); 3216 goto attach_fail0; 3217 } 3218 csz = ddi_get8(rsc->sc_cfg_handle, 3219 (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_CACHE_LINESZ)); 3220 if (!csz) 3221 csz = 16; 3222 rsc->sc_cachelsz = csz << 2; 3223 vendor_id = ddi_get16(rsc->sc_cfg_handle, 3224 (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_VENID)); 3225 device_id = ddi_get16(rsc->sc_cfg_handle, 3226 (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_DEVID)); 3227 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): vendor 0x%x, " 3228 "device id 0x%x, cache size %d\n", vendor_id, device_id, csz); 3229 3230 /* 3231 * Enable response to memory space accesses, 3232 * and enabe bus master. 3233 */ 3234 command = PCI_COMM_MAE | PCI_COMM_ME; 3235 ddi_put16(rsc->sc_cfg_handle, 3236 (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_COMM), command); 3237 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3238 "set command reg to 0x%x \n", command); 3239 3240 ddi_put8(rsc->sc_cfg_handle, 3241 (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8); 3242 3243 ddi_regs_map_free(&rsc->sc_cfg_handle); 3244 3245 err = ddi_regs_map_setup(devinfo, 2, (caddr_t *)&rsc->sc_regs.r_base, 3246 0, 0, &rtw_reg_accattr, &rsc->sc_regs.r_handle); 3247 if (err != DDI_SUCCESS) { 3248 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3249 "ddi_regs_map_setup() failed"); 3250 goto attach_fail0; 3251 } 3252 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: r_base=%x, r_handle=%x\n", 3253 rsc->sc_regs.r_base, rsc->sc_regs.r_handle); 3254 3255 err = rtw_dma_init(devinfo, rsc); 3256 if (err != DDI_SUCCESS) { 3257 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3258 "failed to init dma: %d\n", err); 3259 goto attach_fail1; 3260 } 3261 3262 /* 3263 * Stop the transmit and receive processes. First stop DMA, 3264 * then disable receiver and transmitter. 3265 */ 3266 RTW_WRITE8(&rsc->sc_regs, RTW_TPPOLL, RTW_TPPOLL_SALL); 3267 rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0); 3268 3269 /* Reset the chip to a known state. */ 3270 if (rtw_reset(rsc) != 0) { 3271 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3272 "failed to reset\n"); 3273 goto attach_fail2; 3274 } 3275 rsc->sc_rcr = RTW_READ(&rsc->sc_regs, RTW_RCR); 3276 3277 if ((rsc->sc_rcr & RTW_RCR_9356SEL) != 0) 3278 rsc->sc_flags |= RTW_F_9356SROM; 3279 3280 if (rtw_srom_read(&rsc->sc_regs, rsc->sc_flags, &rsc->sc_srom, 3281 "rtw") != 0) { 3282 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3283 "failed to read srom\n"); 3284 goto attach_fail2; 3285 } 3286 3287 if (rtw_srom_parse(&rsc->sc_srom, &rsc->sc_flags, &rsc->sc_csthr, 3288 &rsc->sc_rfchipid, &rsc->sc_rcr, &rsc->sc_locale, 3289 "rtw") != 0) { 3290 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_attach():" 3291 " malformed serial ROM\n"); 3292 goto attach_fail3; 3293 } 3294 3295 RTW_DPRINTF(RTW_DEBUG_PHY, "rtw: %s PHY\n", 3296 ((rsc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog"); 3297 3298 3299 rsc->sc_rf = rtw_rf_attach(rsc, rsc->sc_rfchipid, 3300 rsc->sc_flags & RTW_F_DIGPHY); 3301 3302 if (rsc->sc_rf == NULL) { 3303 cmn_err(CE_WARN, "rtw: rtw_attach(): could not attach RF\n"); 3304 goto attach_fail3; 3305 } 3306 rsc->sc_phydelay = rtw_check_phydelay(&rsc->sc_regs, rsc->sc_rcr); 3307 3308 RTW_DPRINTF(RTW_DEBUG_ATTACH, 3309 "rtw: PHY delay %d\n", rsc->sc_phydelay); 3310 3311 if (rsc->sc_locale == RTW_LOCALE_UNKNOWN) 3312 rtw_identify_country(&rsc->sc_regs, &rsc->sc_locale, 3313 "rtw"); 3314 3315 rtw_init_channels(rsc->sc_locale, &rsc->sc_ic.ic_sup_channels, 3316 "rtw"); 3317 3318 rtw_set80211props(ic); 3319 3320 if (rtw_identify_sta(&rsc->sc_regs, ic->ic_macaddr, 3321 "rtw") != 0) 3322 goto attach_fail4; 3323 3324 ic->ic_xmit = rtw_send; 3325 ieee80211_attach(ic); 3326 3327 rsc->sc_newstate = ic->ic_newstate; 3328 ic->ic_newstate = rtw_new_state; 3329 ieee80211_media_init(ic); 3330 ic->ic_def_txkey = 0; 3331 3332 if (ddi_get_iblock_cookie(devinfo, 0, &(rsc->sc_iblock)) 3333 != DDI_SUCCESS) { 3334 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3335 "Can not get iblock cookie for INT\n"); 3336 goto attach_fail5; 3337 } 3338 3339 mutex_init(&rsc->sc_genlock, NULL, MUTEX_DRIVER, rsc->sc_iblock); 3340 for (i = 0; i < RTW_NTXPRI; i++) { 3341 mutex_init(&rsc->sc_txq[i].txbuf_lock, NULL, MUTEX_DRIVER, 3342 rsc->sc_iblock); 3343 } 3344 mutex_init(&rsc->rxbuf_lock, NULL, MUTEX_DRIVER, rsc->sc_iblock); 3345 mutex_init(&rsc->sc_txlock, NULL, MUTEX_DRIVER, rsc->sc_iblock); 3346 3347 if (ddi_add_intr(devinfo, 0, &rsc->sc_iblock, NULL, rtw_intr, 3348 (caddr_t)(rsc)) != DDI_SUCCESS) { 3349 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3350 "Can not add intr for rtw driver\n"); 3351 goto attach_fail7; 3352 } 3353 3354 /* 3355 * Provide initial settings for the WiFi plugin; whenever this 3356 * information changes, we need to call mac_plugindata_update() 3357 */ 3358 wd.wd_opmode = ic->ic_opmode; 3359 wd.wd_secalloc = WIFI_SEC_NONE; 3360 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 3361 3362 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 3363 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3364 "MAC version mismatch\n"); 3365 goto attach_fail8; 3366 } 3367 3368 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 3369 macp->m_driver = rsc; 3370 macp->m_dip = devinfo; 3371 macp->m_src_addr = ic->ic_macaddr; 3372 macp->m_callbacks = &rtw_m_callbacks; 3373 macp->m_min_sdu = 0; 3374 macp->m_max_sdu = IEEE80211_MTU; 3375 macp->m_pdata = &wd; 3376 macp->m_pdata_size = sizeof (wd); 3377 3378 err = mac_register(macp, &ic->ic_mach); 3379 mac_free(macp); 3380 if (err != 0) { 3381 RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): " 3382 "mac_register err %x\n", err); 3383 goto attach_fail8; 3384 } 3385 3386 /* Create minor node of type DDI_NT_NET_WIFI */ 3387 (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 3388 "rtw", instance); 3389 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 3390 instance + 1, DDI_NT_NET_WIFI, 0); 3391 if (err != DDI_SUCCESS) { 3392 RTW_DPRINTF(RTW_DEBUG_ATTACH, "WARN: rtw: rtw_attach(): " 3393 "Create minor node failed - %d\n", err); 3394 goto attach_fail9; 3395 } 3396 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 3397 rsc->sc_flags |= RTW_F_ATTACHED; 3398 rsc->sc_need_reschedule = 0; 3399 rsc->sc_invalid = 1; 3400 return (DDI_SUCCESS); 3401 attach_fail9: 3402 (void) mac_unregister(ic->ic_mach); 3403 attach_fail8: 3404 ddi_remove_intr(devinfo, 0, rsc->sc_iblock); 3405 attach_fail7: 3406 attach_fail6: 3407 rtw_mutex_destroy(rsc); 3408 attach_fail5: 3409 ieee80211_detach(ic); 3410 attach_fail4: 3411 rtw_rf_destroy(rsc->sc_rf); 3412 attach_fail3: 3413 rtw_srom_free(&rsc->sc_srom); 3414 attach_fail2: 3415 rtw_dma_free(rsc); 3416 attach_fail1: 3417 ddi_regs_map_free(&rsc->sc_regs.r_handle); 3418 attach_fail0: 3419 ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo)); 3420 return (DDI_FAILURE); 3421 } 3422 3423 static int32_t 3424 rtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 3425 { 3426 rtw_softc_t *rsc; 3427 3428 rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo)); 3429 ASSERT(rsc != NULL); 3430 3431 switch (cmd) { 3432 case DDI_DETACH: 3433 break; 3434 default: 3435 return (DDI_FAILURE); 3436 } 3437 if (!(rsc->sc_flags & RTW_F_ATTACHED)) 3438 return (DDI_FAILURE); 3439 3440 if (mac_disable(rsc->sc_ic.ic_mach) != 0) 3441 return (DDI_FAILURE); 3442 3443 /* free intterrupt resources */ 3444 ddi_remove_intr(devinfo, 0, rsc->sc_iblock); 3445 3446 rtw_mutex_destroy(rsc); 3447 ieee80211_detach((ieee80211com_t *)rsc); 3448 /* 3449 * Unregister from the MAC layer subsystem 3450 */ 3451 (void) mac_unregister(rsc->sc_ic.ic_mach); 3452 3453 rtw_rf_destroy(rsc->sc_rf); 3454 rtw_srom_free(&rsc->sc_srom); 3455 rtw_dma_free(rsc); 3456 ddi_remove_minor_node(devinfo, NULL); 3457 ddi_regs_map_free(&rsc->sc_regs.r_handle); 3458 3459 ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo)); 3460 3461 return (DDI_SUCCESS); 3462 } 3463