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