1191762Simp/* 2191762Simp * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3191762Simp * 4191762Simp * This code is derived from software contributed to The DragonFly Project 5191762Simp * by Sepherosa Ziehau <sepherosa@gmail.com> 6191762Simp * 7191762Simp * Redistribution and use in source and binary forms, with or without 8191762Simp * modification, are permitted provided that the following conditions 9191762Simp * are met: 10191762Simp * 11191762Simp * 1. Redistributions of source code must retain the above copyright 12191762Simp * notice, this list of conditions and the following disclaimer. 13191762Simp * 2. Redistributions in binary form must reproduce the above copyright 14191762Simp * notice, this list of conditions and the following disclaimer in 15191762Simp * the documentation and/or other materials provided with the 16191762Simp * distribution. 17191762Simp * 3. Neither the name of The DragonFly Project nor the names of its 18191762Simp * contributors may be used to endorse or promote products derived 19191762Simp * from this software without specific, prior written permission. 20191762Simp * 21191762Simp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22191762Simp * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23191762Simp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24191762Simp * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25191762Simp * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26191762Simp * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27191762Simp * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28191762Simp * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29191762Simp * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30191762Simp * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31191762Simp * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32191762Simp * SUCH DAMAGE. 33191762Simp * 34191762Simp * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.13 2008/02/15 11:15:38 sephe Exp $ 35191762Simp */ 36191762Simp 37191762Simp#include <sys/cdefs.h> 38191762Simp__FBSDID("$FreeBSD$"); 39191762Simp 40191762Simp#include "opt_inet.h" 41191762Simp#include "opt_bwi.h" 42191762Simp 43191762Simp#include <sys/param.h> 44191762Simp#include <sys/endian.h> 45191762Simp#include <sys/kernel.h> 46191762Simp#include <sys/bus.h> 47191762Simp#include <sys/malloc.h> 48191762Simp#include <sys/proc.h> 49191762Simp#include <sys/rman.h> 50191762Simp#include <sys/socket.h> 51191762Simp#include <sys/sockio.h> 52191762Simp#include <sys/sysctl.h> 53191762Simp#include <sys/systm.h> 54191762Simp 55191762Simp#include <sys/linker.h> 56191762Simp#include <sys/firmware.h> 57191762Simp 58191762Simp#include <net/if.h> 59191762Simp#include <net/if_dl.h> 60191762Simp#include <net/if_media.h> 61191762Simp#include <net/if_types.h> 62191762Simp#include <net/if_arp.h> 63191762Simp#include <net/ethernet.h> 64191762Simp#include <net/if_llc.h> 65191762Simp 66191762Simp#include <net80211/ieee80211_var.h> 67191762Simp#include <net80211/ieee80211_radiotap.h> 68191762Simp#include <net80211/ieee80211_amrr.h> 69191762Simp#include <net80211/ieee80211_phy.h> 70191762Simp 71191762Simp#include <machine/bus.h> 72191762Simp 73191762Simp#include <dev/bwi/bitops.h> 74191762Simp#include <dev/bwi/if_bwireg.h> 75191762Simp#include <dev/bwi/if_bwivar.h> 76191762Simp#include <dev/bwi/bwimac.h> 77191762Simp#include <dev/bwi/bwirf.h> 78191762Simp#include <dev/bwi/bwiphy.h> 79191762Simp 80191762Simpstruct bwi_retry_lim { 81191762Simp uint16_t shretry; 82191762Simp uint16_t shretry_fb; 83191762Simp uint16_t lgretry; 84191762Simp uint16_t lgretry_fb; 85191762Simp}; 86191762Simp 87191762Simpstatic int bwi_mac_test(struct bwi_mac *); 88191762Simpstatic int bwi_mac_get_property(struct bwi_mac *); 89191762Simp 90191762Simpstatic void bwi_mac_set_retry_lim(struct bwi_mac *, 91191762Simp const struct bwi_retry_lim *); 92191762Simpstatic void bwi_mac_set_ackrates(struct bwi_mac *, 93191762Simp const struct ieee80211_rate_table *rt, 94191762Simp const struct ieee80211_rateset *); 95191762Simp 96191762Simpstatic int bwi_mac_gpio_init(struct bwi_mac *); 97191762Simpstatic int bwi_mac_gpio_fini(struct bwi_mac *); 98191762Simpstatic void bwi_mac_opmode_init(struct bwi_mac *); 99191762Simpstatic void bwi_mac_hostflags_init(struct bwi_mac *); 100191762Simpstatic void bwi_mac_bss_param_init(struct bwi_mac *); 101191762Simp 102191762Simpstatic int bwi_mac_fw_alloc(struct bwi_mac *); 103191762Simpstatic void bwi_mac_fw_free(struct bwi_mac *); 104191762Simpstatic int bwi_mac_fw_load(struct bwi_mac *); 105191762Simpstatic int bwi_mac_fw_init(struct bwi_mac *); 106191762Simpstatic int bwi_mac_fw_load_iv(struct bwi_mac *, const struct firmware *); 107191762Simp 108191762Simpstatic void bwi_mac_setup_tpctl(struct bwi_mac *); 109191762Simpstatic void bwi_mac_adjust_tpctl(struct bwi_mac *, int, int); 110191762Simp 111191762Simpstatic void bwi_mac_lock(struct bwi_mac *); 112191762Simpstatic void bwi_mac_unlock(struct bwi_mac *); 113191762Simp 114191762Simpstatic const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10 }; 115191762Simp 116191762Simpvoid 117191762Simpbwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val) 118191762Simp{ 119191762Simp struct bwi_softc *sc = mac->mac_sc; 120191762Simp 121191762Simp if (mac->mac_flags & BWI_MAC_F_BSWAP) 122191762Simp val = bswap32(val); 123191762Simp 124191762Simp CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs); 125191762Simp CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val); 126191762Simp} 127191762Simp 128191762Simpvoid 129191762Simpbwi_hostflags_write(struct bwi_mac *mac, uint64_t flags) 130191762Simp{ 131191762Simp uint64_t val; 132191762Simp 133191762Simp val = flags & 0xffff; 134191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val); 135191762Simp 136191762Simp val = (flags >> 16) & 0xffff; 137191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val); 138191762Simp 139191762Simp /* HI has unclear meaning, so leave it as it is */ 140191762Simp} 141191762Simp 142191762Simpuint64_t 143191762Simpbwi_hostflags_read(struct bwi_mac *mac) 144191762Simp{ 145191762Simp uint64_t flags, val; 146191762Simp 147191762Simp /* HI has unclear meaning, so don't touch it */ 148191762Simp flags = 0; 149191762Simp 150191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI); 151191762Simp flags |= val << 16; 152191762Simp 153191762Simp val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO); 154191762Simp flags |= val; 155191762Simp 156191762Simp return flags; 157191762Simp} 158191762Simp 159191762Simpuint16_t 160191762Simpbwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0) 161191762Simp{ 162191762Simp struct bwi_softc *sc = mac->mac_sc; 163191762Simp uint32_t data_reg; 164191762Simp int ofs; 165191762Simp 166191762Simp data_reg = BWI_MOBJ_DATA; 167191762Simp ofs = ofs0 / 4; 168191762Simp 169191762Simp if (ofs0 % 4 != 0) 170191762Simp data_reg = BWI_MOBJ_DATA_UNALIGN; 171191762Simp 172191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); 173191762Simp return CSR_READ_2(sc, data_reg); 174191762Simp} 175191762Simp 176191762Simpuint32_t 177191762Simpbwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0) 178191762Simp{ 179191762Simp struct bwi_softc *sc = mac->mac_sc; 180191762Simp int ofs; 181191762Simp 182191762Simp ofs = ofs0 / 4; 183191762Simp if (ofs0 % 4 != 0) { 184191762Simp uint32_t ret; 185191762Simp 186191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); 187191762Simp ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN); 188191762Simp ret <<= 16; 189191762Simp 190191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, 191191762Simp BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1)); 192191762Simp ret |= CSR_READ_2(sc, BWI_MOBJ_DATA); 193191762Simp 194191762Simp return ret; 195191762Simp } else { 196191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); 197191762Simp return CSR_READ_4(sc, BWI_MOBJ_DATA); 198191762Simp } 199191762Simp} 200191762Simp 201191762Simpvoid 202191762Simpbwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0, 203191762Simp uint16_t v) 204191762Simp{ 205191762Simp struct bwi_softc *sc = mac->mac_sc; 206191762Simp uint32_t data_reg; 207191762Simp int ofs; 208191762Simp 209191762Simp data_reg = BWI_MOBJ_DATA; 210191762Simp ofs = ofs0 / 4; 211191762Simp 212191762Simp if (ofs0 % 4 != 0) 213191762Simp data_reg = BWI_MOBJ_DATA_UNALIGN; 214191762Simp 215191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); 216191762Simp CSR_WRITE_2(sc, data_reg, v); 217191762Simp} 218191762Simp 219191762Simpvoid 220191762Simpbwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0, 221191762Simp uint32_t v) 222191762Simp{ 223191762Simp struct bwi_softc *sc = mac->mac_sc; 224191762Simp int ofs; 225191762Simp 226191762Simp ofs = ofs0 / 4; 227191762Simp if (ofs0 % 4 != 0) { 228191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); 229191762Simp CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16); 230191762Simp 231191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, 232191762Simp BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1)); 233191762Simp CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff); 234191762Simp } else { 235191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs)); 236191762Simp CSR_WRITE_4(sc, BWI_MOBJ_DATA, v); 237191762Simp } 238191762Simp} 239191762Simp 240191762Simpint 241191762Simpbwi_mac_lateattach(struct bwi_mac *mac) 242191762Simp{ 243191762Simp int error; 244191762Simp 245191762Simp if (mac->mac_rev >= 5) 246191762Simp CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */ 247191762Simp 248191762Simp bwi_mac_reset(mac, 1); 249191762Simp 250191762Simp error = bwi_phy_attach(mac); 251191762Simp if (error) 252191762Simp return error; 253191762Simp 254191762Simp error = bwi_rf_attach(mac); 255191762Simp if (error) 256191762Simp return error; 257191762Simp 258191762Simp /* Link 11B/G PHY, unlink 11A PHY */ 259191762Simp if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) 260191762Simp bwi_mac_reset(mac, 0); 261191762Simp else 262191762Simp bwi_mac_reset(mac, 1); 263191762Simp 264191762Simp error = bwi_mac_test(mac); 265191762Simp if (error) 266191762Simp return error; 267191762Simp 268191762Simp error = bwi_mac_get_property(mac); 269191762Simp if (error) 270191762Simp return error; 271191762Simp 272191762Simp error = bwi_rf_map_txpower(mac); 273191762Simp if (error) 274191762Simp return error; 275191762Simp 276191762Simp bwi_rf_off(mac); 277191762Simp CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC); 278191762Simp bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0); 279191762Simp 280191762Simp return 0; 281191762Simp} 282191762Simp 283191762Simpint 284191762Simpbwi_mac_init(struct bwi_mac *mac) 285191762Simp{ 286191762Simp struct bwi_softc *sc = mac->mac_sc; 287191762Simp int error, i; 288191762Simp 289191762Simp /* Clear MAC/PHY/RF states */ 290191762Simp bwi_mac_setup_tpctl(mac); 291191762Simp bwi_rf_clear_state(&mac->mac_rf); 292191762Simp bwi_phy_clear_state(&mac->mac_phy); 293191762Simp 294191762Simp /* Enable MAC and linked it to PHY */ 295191762Simp if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin)) 296191762Simp bwi_mac_reset(mac, 1); 297191762Simp 298191762Simp /* Initialize backplane */ 299191762Simp error = bwi_bus_init(sc, mac); 300191762Simp if (error) 301191762Simp return error; 302191762Simp 303191995Simp /* do timeout fixup */ 304191762Simp if (sc->sc_bus_regwin.rw_rev <= 5 && 305191762Simp sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) { 306191762Simp CSR_SETBITS_4(sc, BWI_CONF_LO, 307191762Simp __SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) | 308191762Simp __SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK)); 309191762Simp } 310191762Simp 311191762Simp /* Calibrate PHY */ 312191762Simp error = bwi_phy_calibrate(mac); 313191762Simp if (error) { 314191762Simp device_printf(sc->sc_dev, "PHY calibrate failed\n"); 315191762Simp return error; 316191762Simp } 317191762Simp 318191762Simp /* Prepare to initialize firmware */ 319191762Simp CSR_WRITE_4(sc, BWI_MAC_STATUS, 320191762Simp BWI_MAC_STATUS_UCODE_JUMP0 | 321191762Simp BWI_MAC_STATUS_IHREN); 322191762Simp 323191762Simp /* 324191762Simp * Load and initialize firmwares 325191762Simp */ 326191762Simp error = bwi_mac_fw_alloc(mac); 327191762Simp if (error) 328191762Simp return error; 329191762Simp 330191762Simp error = bwi_mac_fw_load(mac); 331191762Simp if (error) 332191762Simp return error; 333191762Simp 334191762Simp error = bwi_mac_gpio_init(mac); 335191762Simp if (error) 336191762Simp return error; 337191762Simp 338191762Simp error = bwi_mac_fw_init(mac); 339191762Simp if (error) 340191762Simp return error; 341191762Simp 342191762Simp /* 343191762Simp * Turn on RF 344191762Simp */ 345191762Simp bwi_rf_on(mac); 346191762Simp 347191762Simp /* TODO: LED, hardware rf enabled is only related to LED setting */ 348191762Simp 349191762Simp /* 350191762Simp * Initialize PHY 351191762Simp */ 352191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0); 353191762Simp bwi_phy_init(mac); 354191762Simp 355191762Simp /* TODO: interference mitigation */ 356191762Simp 357191762Simp /* 358191762Simp * Setup antenna mode 359191762Simp */ 360191762Simp bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode); 361191762Simp 362191762Simp /* 363191762Simp * Initialize operation mode (RX configuration) 364191762Simp */ 365191762Simp bwi_mac_opmode_init(mac); 366191762Simp 367191995Simp /* set up Beacon interval */ 368191762Simp if (mac->mac_rev < 3) { 369191762Simp CSR_WRITE_2(sc, 0x60e, 0); 370191762Simp CSR_WRITE_2(sc, 0x610, 0x8000); 371191762Simp CSR_WRITE_2(sc, 0x604, 0); 372191762Simp CSR_WRITE_2(sc, 0x606, 0x200); 373191762Simp } else { 374191762Simp CSR_WRITE_4(sc, 0x188, 0x80000000); 375191762Simp CSR_WRITE_4(sc, 0x18c, 0x2000000); 376191762Simp } 377191762Simp 378191762Simp /* 379191762Simp * Initialize TX/RX interrupts' mask 380191762Simp */ 381191762Simp CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1); 382191762Simp for (i = 0; i < BWI_TXRX_NRING; ++i) { 383191762Simp uint32_t intrs; 384191762Simp 385191762Simp if (BWI_TXRX_IS_RX(i)) 386191762Simp intrs = BWI_TXRX_RX_INTRS; 387191762Simp else 388191762Simp intrs = BWI_TXRX_TX_INTRS; 389191762Simp CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs); 390191762Simp } 391191762Simp 392191995Simp /* allow the MAC to control the PHY clock (dynamic on/off) */ 393191762Simp CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000); 394191762Simp 395191762Simp /* Setup MAC power up delay */ 396191762Simp CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay); 397191762Simp 398191762Simp /* Set MAC regwin revision */ 399191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev); 400191762Simp 401191762Simp /* 402191762Simp * Initialize host flags 403191762Simp */ 404191762Simp bwi_mac_hostflags_init(mac); 405191762Simp 406191762Simp /* 407191762Simp * Initialize BSS parameters 408191762Simp */ 409191762Simp bwi_mac_bss_param_init(mac); 410191762Simp 411191762Simp /* 412191762Simp * Initialize TX rings 413191762Simp */ 414191762Simp for (i = 0; i < BWI_TX_NRING; ++i) { 415191762Simp error = sc->sc_init_tx_ring(sc, i); 416191762Simp if (error) { 417191762Simp device_printf(sc->sc_dev, 418191762Simp "can't initialize %dth TX ring\n", i); 419191762Simp return error; 420191762Simp } 421191762Simp } 422191762Simp 423191762Simp /* 424191762Simp * Initialize RX ring 425191762Simp */ 426191762Simp error = sc->sc_init_rx_ring(sc); 427191762Simp if (error) { 428191762Simp device_printf(sc->sc_dev, "can't initialize RX ring\n"); 429191762Simp return error; 430191762Simp } 431191762Simp 432191762Simp /* 433191762Simp * Initialize TX stats if the current MAC uses that 434191762Simp */ 435191762Simp if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) { 436191762Simp error = sc->sc_init_txstats(sc); 437191762Simp if (error) { 438191762Simp device_printf(sc->sc_dev, 439191762Simp "can't initialize TX stats ring\n"); 440191762Simp return error; 441191762Simp } 442191762Simp } 443191762Simp 444191995Simp /* update PRETBTT */ 445191762Simp CSR_WRITE_2(sc, 0x612, 0x50); /* Force Pre-TBTT to 80? */ 446191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50); 447191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4); 448191762Simp 449191762Simp mac->mac_flags |= BWI_MAC_F_INITED; 450191762Simp return 0; 451191762Simp} 452191762Simp 453191762Simpvoid 454191762Simpbwi_mac_reset(struct bwi_mac *mac, int link_phy) 455191762Simp{ 456191762Simp struct bwi_softc *sc = mac->mac_sc; 457191762Simp uint32_t flags, state_lo, status; 458191762Simp 459191762Simp flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN; 460191762Simp if (link_phy) 461191762Simp flags |= BWI_STATE_LO_FLAG_PHYLNK; 462191762Simp bwi_regwin_enable(sc, &mac->mac_regwin, flags); 463191762Simp DELAY(2000); 464191762Simp 465191762Simp state_lo = CSR_READ_4(sc, BWI_STATE_LO); 466191762Simp state_lo |= BWI_STATE_LO_GATED_CLOCK; 467191762Simp state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST, 468191762Simp BWI_STATE_LO_FLAGS_MASK); 469191762Simp CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); 470191762Simp /* Flush pending bus write */ 471191762Simp CSR_READ_4(sc, BWI_STATE_LO); 472191762Simp DELAY(1000); 473191762Simp 474191762Simp state_lo &= ~BWI_STATE_LO_GATED_CLOCK; 475191762Simp CSR_WRITE_4(sc, BWI_STATE_LO, state_lo); 476191762Simp /* Flush pending bus write */ 477191762Simp CSR_READ_4(sc, BWI_STATE_LO); 478191762Simp DELAY(1000); 479191762Simp 480191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0); 481191762Simp 482191762Simp status = CSR_READ_4(sc, BWI_MAC_STATUS); 483191762Simp status |= BWI_MAC_STATUS_IHREN; 484191762Simp if (link_phy) 485191762Simp status |= BWI_MAC_STATUS_PHYLNK; 486191762Simp else 487191762Simp status &= ~BWI_MAC_STATUS_PHYLNK; 488191762Simp CSR_WRITE_4(sc, BWI_MAC_STATUS, status); 489191762Simp 490191762Simp if (link_phy) { 491191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT, 492191762Simp "%s\n", "PHY is linked"); 493191762Simp mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED; 494191762Simp } else { 495191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT, 496191762Simp "%s\n", "PHY is unlinked"); 497191762Simp mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED; 498191762Simp } 499191762Simp} 500191762Simp 501191762Simpvoid 502191762Simpbwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl) 503191762Simp{ 504191762Simp struct bwi_rf *rf = &mac->mac_rf; 505191762Simp struct bwi_tpctl *tpctl = &mac->mac_tpctl; 506191762Simp 507191762Simp if (new_tpctl != NULL) { 508191762Simp KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX, 509191762Simp ("bbp_atten %d", new_tpctl->bbp_atten)); 510191762Simp KASSERT(new_tpctl->rf_atten <= 511191762Simp (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0 512191762Simp : BWI_RF_ATTEN_MAX1), 513191762Simp ("rf_atten %d", new_tpctl->rf_atten)); 514191762Simp KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX, 515191762Simp ("tp_ctrl1 %d", new_tpctl->tp_ctrl1)); 516191762Simp 517191762Simp tpctl->bbp_atten = new_tpctl->bbp_atten; 518191762Simp tpctl->rf_atten = new_tpctl->rf_atten; 519191762Simp tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1; 520191762Simp } 521191762Simp 522191762Simp /* Set BBP attenuation */ 523191762Simp bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten); 524191762Simp 525191762Simp /* Set RF attenuation */ 526191762Simp RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten); 527191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN, 528191762Simp tpctl->rf_atten); 529191762Simp 530191762Simp /* Set TX power */ 531191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 532191762Simp RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK, 533191762Simp __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK)); 534191762Simp } 535191762Simp 536191762Simp /* Adjust RF Local Oscillator */ 537191762Simp if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G) 538191762Simp bwi_rf_lo_adjust(mac, tpctl); 539191762Simp} 540191762Simp 541191762Simpstatic int 542191762Simpbwi_mac_test(struct bwi_mac *mac) 543191762Simp{ 544191762Simp struct bwi_softc *sc = mac->mac_sc; 545191762Simp uint32_t orig_val, val; 546191762Simp 547191762Simp#define TEST_VAL1 0xaa5555aa 548191762Simp#define TEST_VAL2 0x55aaaa55 549191762Simp 550191762Simp /* Save it for later restoring */ 551191762Simp orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0); 552191762Simp 553191762Simp /* Test 1 */ 554191762Simp MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1); 555191762Simp val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0); 556191762Simp if (val != TEST_VAL1) { 557191762Simp device_printf(sc->sc_dev, "TEST1 failed\n"); 558191762Simp return ENXIO; 559191762Simp } 560191762Simp 561191762Simp /* Test 2 */ 562191762Simp MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2); 563191762Simp val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0); 564191762Simp if (val != TEST_VAL2) { 565191762Simp device_printf(sc->sc_dev, "TEST2 failed\n"); 566191762Simp return ENXIO; 567191762Simp } 568191762Simp 569191762Simp /* Restore to the original value */ 570191762Simp MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val); 571191762Simp 572191762Simp val = CSR_READ_4(sc, BWI_MAC_STATUS); 573191762Simp if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) { 574191762Simp device_printf(sc->sc_dev, "%s failed, MAC status 0x%08x\n", 575191762Simp __func__, val); 576191762Simp return ENXIO; 577191762Simp } 578191762Simp 579191762Simp val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); 580191762Simp if (val != 0) { 581191762Simp device_printf(sc->sc_dev, "%s failed, intr status %08x\n", 582191762Simp __func__, val); 583191762Simp return ENXIO; 584191762Simp } 585191762Simp 586191762Simp#undef TEST_VAL2 587191762Simp#undef TEST_VAL1 588191762Simp 589191762Simp return 0; 590191762Simp} 591191762Simp 592191762Simpstatic void 593191762Simpbwi_mac_setup_tpctl(struct bwi_mac *mac) 594191762Simp{ 595191762Simp struct bwi_softc *sc = mac->mac_sc; 596191762Simp struct bwi_rf *rf = &mac->mac_rf; 597191762Simp struct bwi_phy *phy = &mac->mac_phy; 598191762Simp struct bwi_tpctl *tpctl = &mac->mac_tpctl; 599191762Simp 600191762Simp /* Calc BBP attenuation */ 601191762Simp if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6) 602191762Simp tpctl->bbp_atten = 0; 603191762Simp else 604191762Simp tpctl->bbp_atten = 2; 605191762Simp 606191762Simp /* Calc TX power CTRL1?? */ 607191762Simp tpctl->tp_ctrl1 = 0; 608191762Simp if (rf->rf_type == BWI_RF_T_BCM2050) { 609191762Simp if (rf->rf_rev == 1) 610191762Simp tpctl->tp_ctrl1 = 3; 611191762Simp else if (rf->rf_rev < 6) 612191762Simp tpctl->tp_ctrl1 = 2; 613191762Simp else if (rf->rf_rev == 8) 614191762Simp tpctl->tp_ctrl1 = 1; 615191762Simp } 616191762Simp 617191762Simp /* Empty TX power CTRL2?? */ 618191762Simp tpctl->tp_ctrl2 = 0xffff; 619191762Simp 620191762Simp /* 621191762Simp * Calc RF attenuation 622191762Simp */ 623191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) { 624191762Simp tpctl->rf_atten = 0x60; 625191762Simp goto back; 626191762Simp } 627191762Simp 628191762Simp if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) { 629191762Simp tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3; 630191762Simp goto back; 631191762Simp } 632191762Simp 633191762Simp tpctl->rf_atten = 5; 634191762Simp 635191762Simp if (rf->rf_type != BWI_RF_T_BCM2050) { 636191762Simp if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1) 637191762Simp tpctl->rf_atten = 6; 638191762Simp goto back; 639191762Simp } 640191762Simp 641191762Simp /* 642191762Simp * NB: If we reaches here and the card is BRCM_BCM4309G, 643191762Simp * then the card's PCI revision must >= 0x51 644191762Simp */ 645191762Simp 646191762Simp /* BCM2050 RF */ 647191762Simp switch (rf->rf_rev) { 648191762Simp case 1: 649191762Simp if (phy->phy_mode == IEEE80211_MODE_11G) { 650191762Simp if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc)) 651191762Simp tpctl->rf_atten = 3; 652191762Simp else 653191762Simp tpctl->rf_atten = 1; 654191762Simp } else { 655191762Simp if (BWI_IS_BRCM_BCM4309G(sc)) 656191762Simp tpctl->rf_atten = 7; 657191762Simp else 658191762Simp tpctl->rf_atten = 6; 659191762Simp } 660191762Simp break; 661191762Simp case 2: 662191762Simp if (phy->phy_mode == IEEE80211_MODE_11G) { 663191762Simp /* 664191762Simp * NOTE: Order of following conditions is critical 665191762Simp */ 666191762Simp if (BWI_IS_BRCM_BCM4309G(sc)) 667191762Simp tpctl->rf_atten = 3; 668191762Simp else if (BWI_IS_BRCM_BU4306(sc)) 669191762Simp tpctl->rf_atten = 5; 670191762Simp else if (sc->sc_bbp_id == BWI_BBPID_BCM4320) 671191762Simp tpctl->rf_atten = 4; 672191762Simp else 673191762Simp tpctl->rf_atten = 3; 674191762Simp } else { 675191762Simp tpctl->rf_atten = 6; 676191762Simp } 677191762Simp break; 678191762Simp case 4: 679191762Simp case 5: 680191762Simp tpctl->rf_atten = 1; 681191762Simp break; 682191762Simp case 8: 683191762Simp tpctl->rf_atten = 0x1a; 684191762Simp break; 685191762Simp } 686191762Simpback: 687191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER, 688191762Simp "bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n", 689191762Simp tpctl->bbp_atten, tpctl->rf_atten, 690191762Simp tpctl->tp_ctrl1, tpctl->tp_ctrl2); 691191762Simp} 692191762Simp 693191762Simpvoid 694191762Simpbwi_mac_dummy_xmit(struct bwi_mac *mac) 695191762Simp{ 696191762Simp#define PACKET_LEN 5 697191762Simp static const uint32_t packet_11a[PACKET_LEN] = 698191762Simp { 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 }; 699191762Simp static const uint32_t packet_11bg[PACKET_LEN] = 700191762Simp { 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 }; 701191762Simp 702191762Simp struct bwi_softc *sc = mac->mac_sc; 703191762Simp struct bwi_rf *rf = &mac->mac_rf; 704191762Simp const uint32_t *packet; 705191762Simp uint16_t val_50c; 706191762Simp int wait_max, i; 707191762Simp 708191762Simp if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) { 709191762Simp wait_max = 30; 710191762Simp packet = packet_11a; 711191762Simp val_50c = 1; 712191762Simp } else { 713191762Simp wait_max = 250; 714191762Simp packet = packet_11bg; 715191762Simp val_50c = 0; 716191762Simp } 717191762Simp 718191762Simp for (i = 0; i < PACKET_LEN; ++i) 719191762Simp TMPLT_WRITE_4(mac, i * 4, packet[i]); 720191762Simp 721191762Simp CSR_READ_4(sc, BWI_MAC_STATUS); /* dummy read */ 722191762Simp 723191762Simp CSR_WRITE_2(sc, 0x568, 0); 724191762Simp CSR_WRITE_2(sc, 0x7c0, 0); 725191762Simp CSR_WRITE_2(sc, 0x50c, val_50c); 726191762Simp CSR_WRITE_2(sc, 0x508, 0); 727191762Simp CSR_WRITE_2(sc, 0x50a, 0); 728191762Simp CSR_WRITE_2(sc, 0x54c, 0); 729191762Simp CSR_WRITE_2(sc, 0x56a, 0x14); 730191762Simp CSR_WRITE_2(sc, 0x568, 0x826); 731191762Simp CSR_WRITE_2(sc, 0x500, 0); 732191762Simp CSR_WRITE_2(sc, 0x502, 0x30); 733191762Simp 734191762Simp if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5) 735191762Simp RF_WRITE(mac, 0x51, 0x17); 736191762Simp 737191762Simp for (i = 0; i < wait_max; ++i) { 738191762Simp if (CSR_READ_2(sc, 0x50e) & 0x80) 739191762Simp break; 740191762Simp DELAY(10); 741191762Simp } 742191762Simp for (i = 0; i < 10; ++i) { 743191762Simp if (CSR_READ_2(sc, 0x50e) & 0x400) 744191762Simp break; 745191762Simp DELAY(10); 746191762Simp } 747191762Simp for (i = 0; i < 10; ++i) { 748191762Simp if ((CSR_READ_2(sc, 0x690) & 0x100) == 0) 749191762Simp break; 750191762Simp DELAY(10); 751191762Simp } 752191762Simp 753191762Simp if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5) 754191762Simp RF_WRITE(mac, 0x51, 0x37); 755191762Simp#undef PACKET_LEN 756191762Simp} 757191762Simp 758191762Simpvoid 759191762Simpbwi_mac_init_tpctl_11bg(struct bwi_mac *mac) 760191762Simp{ 761191762Simp struct bwi_softc *sc = mac->mac_sc; 762191762Simp struct bwi_phy *phy = &mac->mac_phy; 763191762Simp struct bwi_rf *rf = &mac->mac_rf; 764191762Simp struct bwi_tpctl tpctl_orig; 765191762Simp int restore_tpctl = 0; 766191762Simp 767191762Simp KASSERT(phy->phy_mode != IEEE80211_MODE_11A, 768191762Simp ("phy_mode %d", phy->phy_mode)); 769191762Simp 770191762Simp if (BWI_IS_BRCM_BU4306(sc)) 771191762Simp return; 772191762Simp 773191762Simp PHY_WRITE(mac, 0x28, 0x8018); 774191762Simp CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20); 775191762Simp 776191762Simp if (phy->phy_mode == IEEE80211_MODE_11G) { 777191762Simp if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0) 778191762Simp return; 779191762Simp PHY_WRITE(mac, 0x47a, 0xc111); 780191762Simp } 781191762Simp if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED) 782191762Simp return; 783191762Simp 784191762Simp if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 && 785191762Simp rf->rf_type == BWI_RF_T_BCM2050) { 786191762Simp RF_SETBITS(mac, 0x76, 0x84); 787191762Simp } else { 788191762Simp struct bwi_tpctl tpctl; 789191762Simp 790191762Simp /* Backup original TX power control variables */ 791191762Simp bcopy(&mac->mac_tpctl, &tpctl_orig, sizeof(tpctl_orig)); 792191762Simp restore_tpctl = 1; 793191762Simp 794191762Simp bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl)); 795191762Simp tpctl.bbp_atten = 11; 796191762Simp tpctl.tp_ctrl1 = 0; 797191762Simp#ifdef notyet 798191762Simp if (rf->rf_rev >= 6 && rf->rf_rev <= 8) 799191762Simp tpctl.rf_atten = 31; 800191762Simp else 801191762Simp#endif 802191762Simp tpctl.rf_atten = 9; 803191762Simp 804191762Simp bwi_mac_set_tpctl_11bg(mac, &tpctl); 805191762Simp } 806191762Simp 807191762Simp bwi_mac_dummy_xmit(mac); 808191762Simp 809191762Simp mac->mac_flags |= BWI_MAC_F_TPCTL_INITED; 810191762Simp rf->rf_base_tssi = PHY_READ(mac, 0x29); 811191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER, 812191762Simp "base tssi %d\n", rf->rf_base_tssi); 813191762Simp 814191762Simp if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) { 815191762Simp device_printf(sc->sc_dev, "base tssi measure failed\n"); 816191762Simp mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR; 817191762Simp } 818191762Simp 819191762Simp if (restore_tpctl) 820191762Simp bwi_mac_set_tpctl_11bg(mac, &tpctl_orig); 821191762Simp else 822191762Simp RF_CLRBITS(mac, 0x76, 0x84); 823191762Simp 824191762Simp bwi_rf_clear_tssi(mac); 825191762Simp} 826191762Simp 827191762Simpvoid 828191762Simpbwi_mac_detach(struct bwi_mac *mac) 829191762Simp{ 830191762Simp bwi_mac_fw_free(mac); 831191762Simp} 832191762Simp 833191762Simpstatic __inline int 834191762Simpbwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw, 835191762Simp uint8_t fw_type) 836191762Simp{ 837191762Simp const struct bwi_fwhdr *hdr; 838191762Simp struct ifnet *ifp = sc->sc_ifp; 839191762Simp 840191762Simp if (fw->datasize < sizeof(*hdr)) { 841191762Simp if_printf(ifp, "invalid firmware (%s): invalid size %zu\n", 842191762Simp fw->name, fw->datasize); 843191762Simp return 0; 844191762Simp } 845191762Simp 846191762Simp hdr = (const struct bwi_fwhdr *)fw->data; 847191762Simp 848191762Simp if (fw_type != BWI_FW_T_IV) { 849191762Simp /* 850191762Simp * Don't verify IV's size, it has different meaning 851191762Simp */ 852191762Simp if (be32toh(hdr->fw_size) != fw->datasize - sizeof(*hdr)) { 853191762Simp if_printf(ifp, "invalid firmware (%s): size mismatch, " 854191762Simp "fw %u, real %zu\n", fw->name, 855191762Simp be32toh(hdr->fw_size), 856191762Simp fw->datasize - sizeof(*hdr)); 857191762Simp return 0; 858191762Simp } 859191762Simp } 860191762Simp 861191762Simp if (hdr->fw_type != fw_type) { 862191762Simp if_printf(ifp, "invalid firmware (%s): type mismatch, " 863191762Simp "fw \'%c\', target \'%c\'\n", fw->name, 864191762Simp hdr->fw_type, fw_type); 865191762Simp return 0; 866191762Simp } 867191762Simp 868191762Simp if (hdr->fw_gen != BWI_FW_GEN_1) { 869191762Simp if_printf(ifp, "invalid firmware (%s): wrong generation, " 870191762Simp "fw %d, target %d\n", fw->name, 871191762Simp hdr->fw_gen, BWI_FW_GEN_1); 872191762Simp return 0; 873191762Simp } 874191762Simp return 1; 875191762Simp} 876191762Simp 877191762Simp/* 878191762Simp * XXX Error cleanup 879191762Simp */ 880191762Simpstatic int 881191762Simpbwi_mac_fw_alloc(struct bwi_mac *mac) 882191762Simp{ 883191762Simp struct bwi_softc *sc = mac->mac_sc; 884191762Simp struct ifnet *ifp = sc->sc_ifp; 885191762Simp char fwname[64]; 886191762Simp int idx; 887191762Simp 888191762Simp /* 889191762Simp * Try getting the firmware stub so firmware 890191762Simp * module would be loaded automatically 891191762Simp */ 892191762Simp if (mac->mac_stub == NULL) { 893191762Simp snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH, 894191762Simp sc->sc_fw_version); 895191762Simp mac->mac_stub = firmware_get(fwname); 896191762Simp if (mac->mac_stub == NULL) { 897191762Simp if_printf(ifp, "request firmware %s failed\n", fwname); 898191762Simp return ENOMEM; 899191762Simp } 900191762Simp } 901191762Simp 902191762Simp if (mac->mac_ucode == NULL) { 903191762Simp snprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH, 904191762Simp sc->sc_fw_version, 905191762Simp mac->mac_rev >= 5 ? 5 : mac->mac_rev); 906191762Simp 907191762Simp mac->mac_ucode = firmware_get(fwname); 908191762Simp if (mac->mac_ucode == NULL) { 909191762Simp if_printf(ifp, "request firmware %s failed\n", fwname); 910191762Simp return ENOMEM; 911191762Simp } 912191762Simp 913191762Simp if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE)) 914191762Simp return EINVAL; 915191762Simp } 916191762Simp 917191762Simp if (mac->mac_pcm == NULL) { 918191762Simp snprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH, 919191762Simp sc->sc_fw_version, 920191762Simp mac->mac_rev < 5 ? 4 : 5); 921191762Simp 922191762Simp mac->mac_pcm = firmware_get(fwname); 923191762Simp if (mac->mac_pcm == NULL) { 924191762Simp if_printf(ifp, "request firmware %s failed\n", fwname); 925191762Simp return ENOMEM; 926191762Simp } 927191762Simp 928191762Simp if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM)) 929191762Simp return EINVAL; 930191762Simp } 931191762Simp 932191762Simp if (mac->mac_iv == NULL) { 933191762Simp /* TODO: 11A */ 934191762Simp if (mac->mac_rev == 2 || mac->mac_rev == 4) { 935191762Simp idx = 2; 936191762Simp } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) { 937191762Simp idx = 5; 938191762Simp } else { 939191762Simp if_printf(ifp, "no suitible IV for MAC rev %d\n", 940191762Simp mac->mac_rev); 941191762Simp return ENODEV; 942191762Simp } 943191762Simp 944191762Simp snprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH, 945191762Simp sc->sc_fw_version, idx); 946191762Simp 947191762Simp mac->mac_iv = firmware_get(fwname); 948191762Simp if (mac->mac_iv == NULL) { 949191762Simp if_printf(ifp, "request firmware %s failed\n", fwname); 950191762Simp return ENOMEM; 951191762Simp } 952191762Simp if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV)) 953191762Simp return EINVAL; 954191762Simp } 955191762Simp 956191762Simp if (mac->mac_iv_ext == NULL) { 957191762Simp /* TODO: 11A */ 958191762Simp if (mac->mac_rev == 2 || mac->mac_rev == 4 || 959191762Simp mac->mac_rev >= 11) { 960191762Simp /* No extended IV */ 961191762Simp goto back; 962191762Simp } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) { 963191762Simp idx = 5; 964191762Simp } else { 965191762Simp if_printf(ifp, "no suitible ExtIV for MAC rev %d\n", 966191762Simp mac->mac_rev); 967191762Simp return ENODEV; 968191762Simp } 969191762Simp 970191762Simp snprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH, 971191762Simp sc->sc_fw_version, idx); 972191762Simp 973191762Simp mac->mac_iv_ext = firmware_get(fwname); 974191762Simp if (mac->mac_iv_ext == NULL) { 975191762Simp if_printf(ifp, "request firmware %s failed\n", fwname); 976191762Simp return ENOMEM; 977191762Simp } 978191762Simp if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV)) 979191762Simp return EINVAL; 980191762Simp } 981191762Simpback: 982191762Simp return 0; 983191762Simp} 984191762Simp 985191762Simpstatic void 986191762Simpbwi_mac_fw_free(struct bwi_mac *mac) 987191762Simp{ 988191762Simp if (mac->mac_ucode != NULL) { 989191762Simp firmware_put(mac->mac_ucode, FIRMWARE_UNLOAD); 990191762Simp mac->mac_ucode = NULL; 991191762Simp } 992191762Simp 993191762Simp if (mac->mac_pcm != NULL) { 994191762Simp firmware_put(mac->mac_pcm, FIRMWARE_UNLOAD); 995191762Simp mac->mac_pcm = NULL; 996191762Simp } 997191762Simp 998191762Simp if (mac->mac_iv != NULL) { 999191762Simp firmware_put(mac->mac_iv, FIRMWARE_UNLOAD); 1000191762Simp mac->mac_iv = NULL; 1001191762Simp } 1002191762Simp 1003191762Simp if (mac->mac_iv_ext != NULL) { 1004191762Simp firmware_put(mac->mac_iv_ext, FIRMWARE_UNLOAD); 1005191762Simp mac->mac_iv_ext = NULL; 1006191762Simp } 1007191762Simp 1008191762Simp if (mac->mac_stub != NULL) { 1009191762Simp firmware_put(mac->mac_stub, FIRMWARE_UNLOAD); 1010191762Simp mac->mac_stub = NULL; 1011191762Simp } 1012191762Simp} 1013191762Simp 1014191762Simpstatic int 1015191762Simpbwi_mac_fw_load(struct bwi_mac *mac) 1016191762Simp{ 1017191762Simp struct bwi_softc *sc = mac->mac_sc; 1018191762Simp struct ifnet *ifp = sc->sc_ifp; 1019191762Simp const uint32_t *fw; 1020191762Simp uint16_t fw_rev; 1021191762Simp int fw_len, i; 1022191762Simp 1023191762Simp /* 1024191762Simp * Load ucode image 1025191762Simp */ 1026191762Simp fw = (const uint32_t *) 1027191762Simp ((const uint8_t *)mac->mac_ucode->data + BWI_FWHDR_SZ); 1028191762Simp fw_len = (mac->mac_ucode->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t); 1029191762Simp 1030191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, 1031191762Simp BWI_MOBJ_CTRL_VAL( 1032191762Simp BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0)); 1033191762Simp for (i = 0; i < fw_len; ++i) { 1034191762Simp CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i])); 1035191762Simp DELAY(10); 1036191762Simp } 1037191762Simp 1038191762Simp /* 1039191762Simp * Load PCM image 1040191762Simp */ 1041191762Simp fw = (const uint32_t *) 1042191762Simp ((const uint8_t *)mac->mac_pcm->data + BWI_FWHDR_SZ); 1043191762Simp fw_len = (mac->mac_pcm->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t); 1044191762Simp 1045191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, 1046191762Simp BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea)); 1047191762Simp CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000); 1048191762Simp 1049191762Simp CSR_WRITE_4(sc, BWI_MOBJ_CTRL, 1050191762Simp BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb)); 1051191762Simp for (i = 0; i < fw_len; ++i) { 1052191762Simp CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i])); 1053191762Simp DELAY(10); 1054191762Simp } 1055191762Simp 1056191762Simp CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS); 1057191762Simp CSR_WRITE_4(sc, BWI_MAC_STATUS, 1058191762Simp BWI_MAC_STATUS_UCODE_START | 1059191762Simp BWI_MAC_STATUS_IHREN | 1060191762Simp BWI_MAC_STATUS_INFRA); 1061191762Simp 1062191762Simp#define NRETRY 200 1063191762Simp 1064191762Simp for (i = 0; i < NRETRY; ++i) { 1065191762Simp uint32_t intr_status; 1066191762Simp 1067191762Simp intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); 1068191762Simp if (intr_status == BWI_INTR_READY) 1069191762Simp break; 1070191762Simp DELAY(10); 1071191762Simp } 1072191762Simp if (i == NRETRY) { 1073191762Simp if_printf(ifp, "firmware (ucode&pcm) loading timed out\n"); 1074191762Simp return ETIMEDOUT; 1075191762Simp } 1076191762Simp 1077191762Simp#undef NRETRY 1078191762Simp 1079191762Simp CSR_READ_4(sc, BWI_MAC_INTR_STATUS); /* dummy read */ 1080191762Simp 1081191762Simp fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV); 1082191762Simp if (fw_rev > BWI_FW_VERSION3_REVMAX) { 1083191762Simp if_printf(ifp, "firmware version 4 is not supported yet\n"); 1084191762Simp return ENODEV; 1085191762Simp } 1086191762Simp 1087191762Simp if_printf(ifp, "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev, 1088191762Simp MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV)); 1089191762Simp return 0; 1090191762Simp} 1091191762Simp 1092191762Simpstatic int 1093191762Simpbwi_mac_gpio_init(struct bwi_mac *mac) 1094191762Simp{ 1095191762Simp struct bwi_softc *sc = mac->mac_sc; 1096191762Simp struct bwi_regwin *old, *gpio_rw; 1097191762Simp uint32_t filt, bits; 1098191762Simp int error; 1099191762Simp 1100191762Simp CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK); 1101191762Simp /* TODO:LED */ 1102191762Simp 1103191762Simp CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf); 1104191762Simp 1105191762Simp filt = 0x1f; 1106191762Simp bits = 0xf; 1107191762Simp if (sc->sc_bbp_id == BWI_BBPID_BCM4301) { 1108191762Simp filt |= 0x60; 1109191762Simp bits |= 0x60; 1110191762Simp } 1111191762Simp if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) { 1112191762Simp CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200); 1113191762Simp filt |= 0x200; 1114191762Simp bits |= 0x200; 1115191762Simp } 1116191762Simp 1117191762Simp gpio_rw = BWI_GPIO_REGWIN(sc); 1118191762Simp error = bwi_regwin_switch(sc, gpio_rw, &old); 1119191762Simp if (error) 1120191762Simp return error; 1121191762Simp 1122191762Simp CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits); 1123191762Simp 1124191762Simp return bwi_regwin_switch(sc, old, NULL); 1125191762Simp} 1126191762Simp 1127191762Simpstatic int 1128191762Simpbwi_mac_gpio_fini(struct bwi_mac *mac) 1129191762Simp{ 1130191762Simp struct bwi_softc *sc = mac->mac_sc; 1131191762Simp struct bwi_regwin *old, *gpio_rw; 1132191762Simp int error; 1133191762Simp 1134191762Simp gpio_rw = BWI_GPIO_REGWIN(sc); 1135191762Simp error = bwi_regwin_switch(sc, gpio_rw, &old); 1136191762Simp if (error) 1137191762Simp return error; 1138191762Simp 1139191762Simp CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0); 1140191762Simp 1141191762Simp return bwi_regwin_switch(sc, old, NULL); 1142191762Simp} 1143191762Simp 1144191762Simpstatic int 1145191762Simpbwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw) 1146191762Simp{ 1147191762Simp struct bwi_softc *sc = mac->mac_sc; 1148191762Simp struct ifnet *ifp = sc->sc_ifp; 1149191762Simp const struct bwi_fwhdr *hdr; 1150191762Simp const struct bwi_fw_iv *iv; 1151191762Simp int n, i, iv_img_size; 1152191762Simp 1153191762Simp /* Get the number of IVs in the IV image */ 1154191762Simp hdr = (const struct bwi_fwhdr *)fw->data; 1155191762Simp n = be32toh(hdr->fw_iv_cnt); 1156191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE, 1157191762Simp "IV count %d\n", n); 1158191762Simp 1159191762Simp /* Calculate the IV image size, for later sanity check */ 1160191762Simp iv_img_size = fw->datasize - sizeof(*hdr); 1161191762Simp 1162191762Simp /* Locate the first IV */ 1163191762Simp iv = (const struct bwi_fw_iv *) 1164191762Simp ((const uint8_t *)fw->data + sizeof(*hdr)); 1165191762Simp 1166191762Simp for (i = 0; i < n; ++i) { 1167191762Simp uint16_t iv_ofs, ofs; 1168191762Simp int sz = 0; 1169191762Simp 1170191762Simp if (iv_img_size < sizeof(iv->iv_ofs)) { 1171191762Simp if_printf(ifp, "invalid IV image, ofs\n"); 1172191762Simp return EINVAL; 1173191762Simp } 1174191762Simp iv_img_size -= sizeof(iv->iv_ofs); 1175191762Simp sz += sizeof(iv->iv_ofs); 1176191762Simp 1177191762Simp iv_ofs = be16toh(iv->iv_ofs); 1178191762Simp 1179191762Simp ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK); 1180191762Simp if (ofs >= 0x1000) { 1181191762Simp if_printf(ifp, "invalid ofs (0x%04x) " 1182191762Simp "for %dth iv\n", ofs, i); 1183191762Simp return EINVAL; 1184191762Simp } 1185191762Simp 1186191762Simp if (iv_ofs & BWI_FW_IV_IS_32BIT) { 1187191762Simp uint32_t val32; 1188191762Simp 1189191762Simp if (iv_img_size < sizeof(iv->iv_val.val32)) { 1190191762Simp if_printf(ifp, "invalid IV image, val32\n"); 1191191762Simp return EINVAL; 1192191762Simp } 1193191762Simp iv_img_size -= sizeof(iv->iv_val.val32); 1194191762Simp sz += sizeof(iv->iv_val.val32); 1195191762Simp 1196191762Simp val32 = be32toh(iv->iv_val.val32); 1197191762Simp CSR_WRITE_4(sc, ofs, val32); 1198191762Simp } else { 1199191762Simp uint16_t val16; 1200191762Simp 1201191762Simp if (iv_img_size < sizeof(iv->iv_val.val16)) { 1202191762Simp if_printf(ifp, "invalid IV image, val16\n"); 1203191762Simp return EINVAL; 1204191762Simp } 1205191762Simp iv_img_size -= sizeof(iv->iv_val.val16); 1206191762Simp sz += sizeof(iv->iv_val.val16); 1207191762Simp 1208191762Simp val16 = be16toh(iv->iv_val.val16); 1209191762Simp CSR_WRITE_2(sc, ofs, val16); 1210191762Simp } 1211191762Simp 1212191762Simp iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz); 1213191762Simp } 1214191762Simp 1215191762Simp if (iv_img_size != 0) { 1216191762Simp if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size); 1217191762Simp return EINVAL; 1218191762Simp } 1219191762Simp return 0; 1220191762Simp} 1221191762Simp 1222191762Simpstatic int 1223191762Simpbwi_mac_fw_init(struct bwi_mac *mac) 1224191762Simp{ 1225191762Simp struct ifnet *ifp = mac->mac_sc->sc_ifp; 1226191762Simp int error; 1227191762Simp 1228191762Simp error = bwi_mac_fw_load_iv(mac, mac->mac_iv); 1229191762Simp if (error) { 1230191762Simp if_printf(ifp, "load IV failed\n"); 1231191762Simp return error; 1232191762Simp } 1233191762Simp 1234191762Simp if (mac->mac_iv_ext != NULL) { 1235191762Simp error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext); 1236191762Simp if (error) 1237191762Simp if_printf(ifp, "load ExtIV failed\n"); 1238191762Simp } 1239191762Simp return error; 1240191762Simp} 1241191762Simp 1242191762Simpstatic void 1243191762Simpbwi_mac_opmode_init(struct bwi_mac *mac) 1244191762Simp{ 1245191762Simp struct bwi_softc *sc = mac->mac_sc; 1246191762Simp struct ifnet *ifp = sc->sc_ifp; 1247191762Simp struct ieee80211com *ic = ifp->if_l2com; 1248191762Simp uint32_t mac_status; 1249191762Simp uint16_t pre_tbtt; 1250191762Simp 1251191762Simp CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA); 1252191762Simp CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA); 1253191762Simp 1254191762Simp /* Set probe resp timeout to infinite */ 1255191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0); 1256191762Simp 1257191762Simp /* 1258191762Simp * TODO: factor out following part 1259191762Simp */ 1260191762Simp 1261191762Simp mac_status = CSR_READ_4(sc, BWI_MAC_STATUS); 1262191762Simp mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP | 1263191762Simp BWI_MAC_STATUS_PASS_CTL | 1264191762Simp BWI_MAC_STATUS_PASS_BCN | 1265191762Simp BWI_MAC_STATUS_PASS_BADPLCP | 1266191762Simp BWI_MAC_STATUS_PASS_BADFCS | 1267191762Simp BWI_MAC_STATUS_PROMISC); 1268191762Simp mac_status |= BWI_MAC_STATUS_INFRA; 1269191762Simp 1270191762Simp /* Always turn on PROMISC on old hardware */ 1271191762Simp if (mac->mac_rev < 5) 1272191762Simp mac_status |= BWI_MAC_STATUS_PROMISC; 1273191762Simp 1274191762Simp switch (ic->ic_opmode) { 1275191762Simp case IEEE80211_M_IBSS: 1276191762Simp mac_status &= ~BWI_MAC_STATUS_INFRA; 1277191762Simp break; 1278191762Simp case IEEE80211_M_HOSTAP: 1279191762Simp mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP; 1280191762Simp break; 1281191762Simp case IEEE80211_M_MONITOR: 1282191762Simp#if 0 1283191762Simp /* Do you want data from your microwave oven? */ 1284191762Simp mac_status |= BWI_MAC_STATUS_PASS_CTL | 1285191762Simp BWI_MAC_STATUS_PASS_BADPLCP | 1286191762Simp BWI_MAC_STATUS_PASS_BADFCS; 1287191762Simp#else 1288191762Simp mac_status |= BWI_MAC_STATUS_PASS_CTL; 1289191762Simp#endif 1290191762Simp /* Promisc? */ 1291191762Simp break; 1292191762Simp default: 1293191762Simp break; 1294191762Simp } 1295191762Simp 1296191762Simp if (ic->ic_ifp->if_flags & IFF_PROMISC) 1297191762Simp mac_status |= BWI_MAC_STATUS_PROMISC; 1298191762Simp 1299191762Simp CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status); 1300191762Simp 1301191762Simp if (ic->ic_opmode != IEEE80211_M_IBSS && 1302191762Simp ic->ic_opmode != IEEE80211_M_HOSTAP) { 1303191762Simp if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3) 1304191762Simp pre_tbtt = 100; 1305191762Simp else 1306191762Simp pre_tbtt = 50; 1307191762Simp } else { 1308191762Simp pre_tbtt = 2; 1309191762Simp } 1310191762Simp CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt); 1311191762Simp} 1312191762Simp 1313191762Simpstatic void 1314191762Simpbwi_mac_hostflags_init(struct bwi_mac *mac) 1315191762Simp{ 1316191762Simp struct bwi_softc *sc = mac->mac_sc; 1317191762Simp struct bwi_phy *phy = &mac->mac_phy; 1318191762Simp struct bwi_rf *rf = &mac->mac_rf; 1319191762Simp uint64_t host_flags; 1320191762Simp 1321191762Simp if (phy->phy_mode == IEEE80211_MODE_11A) 1322191762Simp return; 1323191762Simp 1324191762Simp host_flags = HFLAGS_READ(mac); 1325191762Simp host_flags |= BWI_HFLAG_SYM_WA; 1326191762Simp 1327191762Simp if (phy->phy_mode == IEEE80211_MODE_11G) { 1328191762Simp if (phy->phy_rev == 1) 1329191762Simp host_flags |= BWI_HFLAG_GDC_WA; 1330191762Simp if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) 1331191762Simp host_flags |= BWI_HFLAG_OFDM_PA; 1332191762Simp } else if (phy->phy_mode == IEEE80211_MODE_11B) { 1333191762Simp if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050) 1334191762Simp host_flags &= ~BWI_HFLAG_GDC_WA; 1335191762Simp } else { 1336191762Simp panic("unknown PHY mode %u\n", phy->phy_mode); 1337191762Simp } 1338191762Simp 1339191762Simp HFLAGS_WRITE(mac, host_flags); 1340191762Simp} 1341191762Simp 1342191762Simpstatic void 1343191762Simpbwi_mac_bss_param_init(struct bwi_mac *mac) 1344191762Simp{ 1345191762Simp struct bwi_softc *sc = mac->mac_sc; 1346191762Simp struct bwi_phy *phy = &mac->mac_phy; 1347191762Simp struct ifnet *ifp = sc->sc_ifp; 1348191762Simp struct ieee80211com *ic = ifp->if_l2com; 1349191762Simp const struct ieee80211_rate_table *rt; 1350191762Simp struct bwi_retry_lim lim; 1351191762Simp uint16_t cw_min; 1352191762Simp 1353191762Simp /* 1354191762Simp * Set short/long retry limits 1355191762Simp */ 1356191762Simp bzero(&lim, sizeof(lim)); 1357191762Simp lim.shretry = BWI_SHRETRY; 1358191762Simp lim.shretry_fb = BWI_SHRETRY_FB; 1359191762Simp lim.lgretry = BWI_LGRETRY; 1360191762Simp lim.lgretry_fb = BWI_LGRETRY_FB; 1361191762Simp bwi_mac_set_retry_lim(mac, &lim); 1362191762Simp 1363191762Simp /* 1364191762Simp * Implicitly prevent firmware from sending probe response 1365191762Simp * by setting its "probe response timeout" to 1us. 1366191762Simp */ 1367191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1); 1368191762Simp 1369191762Simp /* 1370191762Simp * XXX MAC level acknowledge and CW min/max should depend 1371191762Simp * on the char rateset of the IBSS/BSS to join. 1372191762Simp * XXX this is all wrong; should be done on channel change 1373191762Simp */ 1374191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) { 1375191762Simp rt = ieee80211_get_ratetable( 1376191762Simp ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_B)); 1377191762Simp bwi_mac_set_ackrates(mac, rt, 1378191762Simp &ic->ic_sup_rates[IEEE80211_MODE_11B]); 1379191762Simp } else { 1380191762Simp rt = ieee80211_get_ratetable( 1381191762Simp ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_G)); 1382191762Simp bwi_mac_set_ackrates(mac, rt, 1383191762Simp &ic->ic_sup_rates[IEEE80211_MODE_11G]); 1384191762Simp } 1385191762Simp 1386191762Simp /* 1387191762Simp * Set CW min 1388191762Simp */ 1389191762Simp if (phy->phy_mode == IEEE80211_MODE_11B) 1390191762Simp cw_min = IEEE80211_CW_MIN_0; 1391191762Simp else 1392191762Simp cw_min = IEEE80211_CW_MIN_1; 1393191762Simp MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min); 1394191762Simp 1395191762Simp /* 1396191762Simp * Set CW max 1397191762Simp */ 1398191762Simp MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX, 1399191762Simp IEEE80211_CW_MAX); 1400191762Simp} 1401191762Simp 1402191762Simpstatic void 1403191762Simpbwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim) 1404191762Simp{ 1405191762Simp /* Short/Long retry limit */ 1406191762Simp MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY, 1407191762Simp lim->shretry); 1408191762Simp MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY, 1409191762Simp lim->lgretry); 1410191762Simp 1411191762Simp /* Short/Long retry fallback limit */ 1412191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB, 1413191762Simp lim->shretry_fb); 1414191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB, 1415191762Simp lim->lgretry_fb); 1416191762Simp} 1417191762Simp 1418191762Simpstatic void 1419191762Simpbwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rate_table *rt, 1420191762Simp const struct ieee80211_rateset *rs) 1421191762Simp{ 1422191762Simp int i; 1423191762Simp 1424191762Simp /* XXX not standard conforming */ 1425191762Simp for (i = 0; i < rs->rs_nrates; ++i) { 1426191762Simp enum ieee80211_phytype modtype; 1427191762Simp uint16_t ofs; 1428191762Simp 1429191762Simp modtype = ieee80211_rate2phytype(rt, rs->rs_rates[i]); 1430191762Simp switch (modtype) { 1431191762Simp case IEEE80211_T_DS: 1432191762Simp ofs = 0x4c0; 1433191762Simp break; 1434191762Simp case IEEE80211_T_OFDM: 1435191762Simp ofs = 0x480; 1436191762Simp break; 1437191762Simp default: 1438191762Simp panic("unsupported modtype %u\n", modtype); 1439191762Simp } 1440191762Simp ofs += 2*(ieee80211_rate2plcp(rs->rs_rates[i], modtype) & 0xf); 1441191762Simp 1442191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20, 1443191762Simp MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs)); 1444191762Simp } 1445191762Simp} 1446191762Simp 1447191762Simpint 1448191762Simpbwi_mac_start(struct bwi_mac *mac) 1449191762Simp{ 1450191762Simp struct bwi_softc *sc = mac->mac_sc; 1451191762Simp 1452191762Simp CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE); 1453191762Simp CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY); 1454191762Simp 1455191762Simp /* Flush pending bus writes */ 1456191762Simp CSR_READ_4(sc, BWI_MAC_STATUS); 1457191762Simp CSR_READ_4(sc, BWI_MAC_INTR_STATUS); 1458191762Simp 1459191762Simp return bwi_mac_config_ps(mac); 1460191762Simp} 1461191762Simp 1462191762Simpint 1463191762Simpbwi_mac_stop(struct bwi_mac *mac) 1464191762Simp{ 1465191762Simp struct bwi_softc *sc = mac->mac_sc; 1466191762Simp int error, i; 1467191762Simp 1468191762Simp error = bwi_mac_config_ps(mac); 1469191762Simp if (error) 1470191762Simp return error; 1471191762Simp 1472191762Simp CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE); 1473191762Simp 1474191762Simp /* Flush pending bus write */ 1475191762Simp CSR_READ_4(sc, BWI_MAC_STATUS); 1476191762Simp 1477191762Simp#define NRETRY 10000 1478191762Simp for (i = 0; i < NRETRY; ++i) { 1479191762Simp if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY) 1480191762Simp break; 1481191762Simp DELAY(1); 1482191762Simp } 1483191762Simp if (i == NRETRY) { 1484191762Simp device_printf(sc->sc_dev, "can't stop MAC\n"); 1485191762Simp return ETIMEDOUT; 1486191762Simp } 1487191762Simp#undef NRETRY 1488191762Simp 1489191762Simp return 0; 1490191762Simp} 1491191762Simp 1492191762Simpint 1493191762Simpbwi_mac_config_ps(struct bwi_mac *mac) 1494191762Simp{ 1495191762Simp struct bwi_softc *sc = mac->mac_sc; 1496191762Simp uint32_t status; 1497191762Simp 1498191762Simp status = CSR_READ_4(sc, BWI_MAC_STATUS); 1499191762Simp 1500191762Simp status &= ~BWI_MAC_STATUS_HW_PS; 1501191762Simp status |= BWI_MAC_STATUS_WAKEUP; 1502191762Simp CSR_WRITE_4(sc, BWI_MAC_STATUS, status); 1503191762Simp 1504191762Simp /* Flush pending bus write */ 1505191762Simp CSR_READ_4(sc, BWI_MAC_STATUS); 1506191762Simp 1507191762Simp if (mac->mac_rev >= 5) { 1508191762Simp int i; 1509191762Simp 1510191762Simp#define NRETRY 100 1511191762Simp for (i = 0; i < NRETRY; ++i) { 1512191762Simp if (MOBJ_READ_2(mac, BWI_COMM_MOBJ, 1513191762Simp BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS) 1514191762Simp break; 1515191762Simp DELAY(10); 1516191762Simp } 1517191762Simp if (i == NRETRY) { 1518191762Simp device_printf(sc->sc_dev, "config PS failed\n"); 1519191762Simp return ETIMEDOUT; 1520191762Simp } 1521191762Simp#undef NRETRY 1522191762Simp } 1523191762Simp return 0; 1524191762Simp} 1525191762Simp 1526191762Simpvoid 1527191762Simpbwi_mac_reset_hwkeys(struct bwi_mac *mac) 1528191762Simp{ 1529191762Simp /* TODO: firmware crypto */ 1530191762Simp MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS); 1531191762Simp} 1532191762Simp 1533191762Simpvoid 1534191762Simpbwi_mac_shutdown(struct bwi_mac *mac) 1535191762Simp{ 1536191762Simp struct bwi_softc *sc = mac->mac_sc; 1537191762Simp int i; 1538191762Simp 1539191762Simp if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) 1540191762Simp sc->sc_free_txstats(sc); 1541191762Simp 1542191762Simp sc->sc_free_rx_ring(sc); 1543191762Simp 1544191762Simp for (i = 0; i < BWI_TX_NRING; ++i) 1545191762Simp sc->sc_free_tx_ring(sc, i); 1546191762Simp 1547191762Simp bwi_rf_off(mac); 1548191762Simp 1549191762Simp /* TODO:LED */ 1550191762Simp 1551191762Simp bwi_mac_gpio_fini(mac); 1552191762Simp 1553191762Simp bwi_rf_off(mac); /* XXX again */ 1554191762Simp CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC); 1555191762Simp bwi_regwin_disable(sc, &mac->mac_regwin, 0); 1556191762Simp 1557191762Simp mac->mac_flags &= ~BWI_MAC_F_INITED; 1558191762Simp} 1559191762Simp 1560191762Simpstatic int 1561191762Simpbwi_mac_get_property(struct bwi_mac *mac) 1562191762Simp{ 1563191762Simp struct bwi_softc *sc = mac->mac_sc; 1564191762Simp enum bwi_bus_space old_bus_space; 1565191762Simp uint32_t val; 1566191762Simp 1567191762Simp /* 1568191762Simp * Byte swap 1569191762Simp */ 1570191762Simp val = CSR_READ_4(sc, BWI_MAC_STATUS); 1571191762Simp if (val & BWI_MAC_STATUS_BSWAP) { 1572191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", 1573191762Simp "need byte swap"); 1574191762Simp mac->mac_flags |= BWI_MAC_F_BSWAP; 1575191762Simp } 1576191762Simp 1577191762Simp /* 1578191762Simp * DMA address space 1579191762Simp */ 1580191762Simp old_bus_space = sc->sc_bus_space; 1581191762Simp 1582191762Simp val = CSR_READ_4(sc, BWI_STATE_HI); 1583191762Simp if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) & 1584191762Simp BWI_STATE_HI_FLAG_64BIT) { 1585191762Simp /* 64bit address */ 1586191762Simp sc->sc_bus_space = BWI_BUS_SPACE_64BIT; 1587191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", 1588191762Simp "64bit bus space"); 1589191762Simp } else { 1590191762Simp uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL; 1591191762Simp 1592191762Simp CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK); 1593191762Simp if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) { 1594191762Simp /* 32bit address */ 1595191762Simp sc->sc_bus_space = BWI_BUS_SPACE_32BIT; 1596191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", 1597191762Simp "32bit bus space"); 1598191762Simp } else { 1599191762Simp /* 30bit address */ 1600191762Simp sc->sc_bus_space = BWI_BUS_SPACE_30BIT; 1601191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", 1602191762Simp "30bit bus space"); 1603191762Simp } 1604191762Simp } 1605191762Simp 1606191762Simp if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) { 1607191762Simp device_printf(sc->sc_dev, "MACs bus space mismatch!\n"); 1608191762Simp return ENXIO; 1609191762Simp } 1610191762Simp return 0; 1611191762Simp} 1612191762Simp 1613191762Simpvoid 1614191762Simpbwi_mac_updateslot(struct bwi_mac *mac, int shslot) 1615191762Simp{ 1616191762Simp uint16_t slot_time; 1617191762Simp 1618191762Simp if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) 1619191762Simp return; 1620191762Simp 1621191762Simp if (shslot) 1622191762Simp slot_time = IEEE80211_DUR_SHSLOT; 1623191762Simp else 1624191762Simp slot_time = IEEE80211_DUR_SLOT; 1625191762Simp 1626191762Simp CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME, 1627191762Simp slot_time + BWI_MAC_SLOTTIME_ADJUST); 1628191762Simp MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time); 1629191762Simp} 1630191762Simp 1631191762Simpint 1632191762Simpbwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev) 1633191762Simp{ 1634191762Simp struct bwi_mac *mac; 1635191762Simp int i; 1636191762Simp 1637191762Simp KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0, 1638191762Simp ("sc_nmac %d", sc->sc_nmac)); 1639191762Simp 1640191762Simp if (sc->sc_nmac == BWI_MAC_MAX) { 1641191762Simp device_printf(sc->sc_dev, "too many MACs\n"); 1642191762Simp return 0; 1643191762Simp } 1644191762Simp 1645191762Simp /* 1646191762Simp * More than one MAC is only supported by BCM4309 1647191762Simp */ 1648191762Simp if (sc->sc_nmac != 0 && 1649191762Simp sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM4309) { 1650191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", 1651191762Simp "ignore second MAC"); 1652191762Simp return 0; 1653191762Simp } 1654191762Simp 1655191762Simp mac = &sc->sc_mac[sc->sc_nmac]; 1656191762Simp 1657191762Simp /* XXX will this happen? */ 1658191762Simp if (BWI_REGWIN_EXIST(&mac->mac_regwin)) { 1659191762Simp device_printf(sc->sc_dev, "%dth MAC already attached\n", 1660191762Simp sc->sc_nmac); 1661191762Simp return 0; 1662191762Simp } 1663191762Simp 1664191762Simp /* 1665191762Simp * Test whether the revision of this MAC is supported 1666191762Simp */ 1667191762Simp#define N(arr) (int)(sizeof(arr) / sizeof(arr[0])) 1668191762Simp for (i = 0; i < N(bwi_sup_macrev); ++i) { 1669191762Simp if (bwi_sup_macrev[i] == rev) 1670191762Simp break; 1671191762Simp } 1672191762Simp if (i == N(bwi_sup_macrev)) { 1673191762Simp device_printf(sc->sc_dev, "MAC rev %u is " 1674191762Simp "not supported\n", rev); 1675191762Simp return ENXIO; 1676191762Simp } 1677191762Simp#undef N 1678191762Simp 1679191762Simp BWI_CREATE_MAC(mac, sc, id, rev); 1680191762Simp sc->sc_nmac++; 1681191762Simp 1682191762Simp if (mac->mac_rev < 5) { 1683191762Simp mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS; 1684191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n", 1685191762Simp "has TX stats"); 1686191762Simp } else { 1687191762Simp mac->mac_flags |= BWI_MAC_F_PHYE_RESET; 1688191762Simp } 1689191762Simp 1690191762Simp device_printf(sc->sc_dev, "MAC: rev %u\n", rev); 1691191762Simp return 0; 1692191762Simp} 1693191762Simp 1694191762Simpstatic __inline void 1695191762Simpbwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0) 1696191762Simp{ 1697191762Simp int bbp_atten, rf_atten, rf_atten_lim = -1; 1698191762Simp 1699191762Simp bbp_atten = *bbp_atten0; 1700191762Simp rf_atten = *rf_atten0; 1701191762Simp 1702191762Simp /* 1703191762Simp * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times 1704191762Simp * as much as BBP attenuation, so we try our best to keep RF 1705191762Simp * attenuation within range. BBP attenuation will be clamped 1706191762Simp * later if it is out of range during balancing. 1707191762Simp * 1708191762Simp * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit. 1709191762Simp */ 1710191762Simp 1711191762Simp /* 1712191762Simp * Use BBP attenuation to balance RF attenuation 1713191762Simp */ 1714191762Simp if (rf_atten < 0) 1715191762Simp rf_atten_lim = 0; 1716191762Simp else if (rf_atten > BWI_RF_ATTEN_MAX0) 1717191762Simp rf_atten_lim = BWI_RF_ATTEN_MAX0; 1718191762Simp 1719191762Simp if (rf_atten_lim >= 0) { 1720191762Simp bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim)); 1721191762Simp rf_atten = rf_atten_lim; 1722191762Simp } 1723191762Simp 1724191762Simp /* 1725191762Simp * If possible, use RF attenuation to balance BBP attenuation 1726191762Simp * NOTE: RF attenuation is still kept within range. 1727191762Simp */ 1728191762Simp while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) { 1729191762Simp bbp_atten -= BWI_RF_ATTEN_FACTOR; 1730191762Simp ++rf_atten; 1731191762Simp } 1732191762Simp while (rf_atten > 0 && bbp_atten < 0) { 1733191762Simp bbp_atten += BWI_RF_ATTEN_FACTOR; 1734191762Simp --rf_atten; 1735191762Simp } 1736191762Simp 1737191762Simp /* RF attenuation MUST be within range */ 1738191762Simp KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0, 1739191762Simp ("rf_atten %d", rf_atten)); 1740191762Simp 1741191762Simp /* 1742191762Simp * Clamp BBP attenuation 1743191762Simp */ 1744191762Simp if (bbp_atten < 0) 1745191762Simp bbp_atten = 0; 1746191762Simp else if (bbp_atten > BWI_BBP_ATTEN_MAX) 1747191762Simp bbp_atten = BWI_BBP_ATTEN_MAX; 1748191762Simp 1749191762Simp *rf_atten0 = rf_atten; 1750191762Simp *bbp_atten0 = bbp_atten; 1751191762Simp} 1752191762Simp 1753191762Simpstatic void 1754191762Simpbwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj) 1755191762Simp{ 1756191762Simp struct bwi_softc *sc = mac->mac_sc; 1757191762Simp struct bwi_rf *rf = &mac->mac_rf; 1758191762Simp struct bwi_tpctl tpctl; 1759191762Simp int bbp_atten, rf_atten, tp_ctrl1; 1760191762Simp 1761191762Simp bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl)); 1762191762Simp 1763191762Simp /* NOTE: Use signed value to do calulation */ 1764191762Simp bbp_atten = tpctl.bbp_atten; 1765191762Simp rf_atten = tpctl.rf_atten; 1766191762Simp tp_ctrl1 = tpctl.tp_ctrl1; 1767191762Simp 1768191762Simp bbp_atten += bbp_atten_adj; 1769191762Simp rf_atten += rf_atten_adj; 1770191762Simp 1771191762Simp bwi_mac_balance_atten(&bbp_atten, &rf_atten); 1772191762Simp 1773191762Simp if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) { 1774191762Simp if (rf_atten <= 1) { 1775191762Simp if (tp_ctrl1 == 0) { 1776191762Simp tp_ctrl1 = 3; 1777191762Simp bbp_atten += 2; 1778191762Simp rf_atten += 2; 1779191762Simp } else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) { 1780191762Simp bbp_atten += 1781191762Simp (BWI_RF_ATTEN_FACTOR * (rf_atten - 2)); 1782191762Simp rf_atten = 2; 1783191762Simp } 1784191762Simp } else if (rf_atten > 4 && tp_ctrl1 != 0) { 1785191762Simp tp_ctrl1 = 0; 1786191762Simp if (bbp_atten < 3) { 1787191762Simp bbp_atten += 2; 1788191762Simp rf_atten -= 3; 1789191762Simp } else { 1790191762Simp bbp_atten -= 2; 1791191762Simp rf_atten -= 2; 1792191762Simp } 1793191762Simp } 1794191762Simp bwi_mac_balance_atten(&bbp_atten, &rf_atten); 1795191762Simp } 1796191762Simp 1797191762Simp tpctl.bbp_atten = bbp_atten; 1798191762Simp tpctl.rf_atten = rf_atten; 1799191762Simp tpctl.tp_ctrl1 = tp_ctrl1; 1800191762Simp 1801191762Simp bwi_mac_lock(mac); 1802191762Simp bwi_mac_set_tpctl_11bg(mac, &tpctl); 1803191762Simp bwi_mac_unlock(mac); 1804191762Simp} 1805191762Simp 1806191762Simp/* 1807191762Simp * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower 1808191762Simp */ 1809191762Simpvoid 1810191762Simpbwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type) 1811191762Simp{ 1812191762Simp struct bwi_softc *sc = mac->mac_sc; 1813191762Simp struct bwi_rf *rf = &mac->mac_rf; 1814191762Simp int8_t tssi[4], tssi_avg, cur_txpwr; 1815191762Simp int error, i, ofdm_tssi; 1816191762Simp int txpwr_diff, rf_atten_adj, bbp_atten_adj; 1817191762Simp 1818191762Simp if (!sc->sc_txpwr_calib) 1819191762Simp return; 1820191762Simp 1821191762Simp if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) { 1822191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", 1823191762Simp "tpctl error happened, can't set txpower"); 1824191762Simp return; 1825191762Simp } 1826191762Simp 1827191762Simp if (BWI_IS_BRCM_BU4306(sc)) { 1828191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", 1829191762Simp "BU4306, can't set txpower"); 1830191762Simp return; 1831191762Simp } 1832191762Simp 1833191762Simp /* 1834191762Simp * Save latest TSSI and reset the related memory objects 1835191762Simp */ 1836191762Simp ofdm_tssi = 0; 1837191762Simp error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS); 1838191762Simp if (error) { 1839191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", 1840191762Simp "no DS tssi"); 1841191762Simp 1842191762Simp if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) { 1843191762Simp if (type == BWI_TXPWR_FORCE) { 1844191762Simp rf_atten_adj = 0; 1845191762Simp bbp_atten_adj = 1; 1846191762Simp goto calib; 1847191762Simp } else { 1848191762Simp return; 1849191762Simp } 1850191762Simp } 1851191762Simp 1852191762Simp error = bwi_rf_get_latest_tssi(mac, tssi, 1853191762Simp BWI_COMM_MOBJ_TSSI_OFDM); 1854191762Simp if (error) { 1855191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", 1856191762Simp "no OFDM tssi"); 1857191762Simp if (type == BWI_TXPWR_FORCE) { 1858191762Simp rf_atten_adj = 0; 1859191762Simp bbp_atten_adj = 1; 1860191762Simp goto calib; 1861191762Simp } else { 1862191762Simp return; 1863191762Simp } 1864191762Simp } 1865191762Simp 1866191762Simp for (i = 0; i < 4; ++i) { 1867191762Simp tssi[i] += 0x20; 1868191762Simp tssi[i] &= 0x3f; 1869191762Simp } 1870191762Simp ofdm_tssi = 1; 1871191762Simp } 1872191762Simp bwi_rf_clear_tssi(mac); 1873191762Simp 1874191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, 1875191762Simp "tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n", 1876191762Simp tssi[0], tssi[1], tssi[2], tssi[3]); 1877191762Simp 1878191762Simp /* 1879191762Simp * Calculate RF/BBP attenuation adjustment based on 1880191762Simp * the difference between desired TX power and sampled 1881191762Simp * TX power. 1882191762Simp */ 1883191762Simp /* +8 == "each incremented by 1/2" */ 1884191762Simp tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4; 1885191762Simp if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS)) 1886191762Simp tssi_avg -= 13; 1887191762Simp 1888191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "tssi avg %d\n", tssi_avg); 1889191762Simp 1890191762Simp error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr); 1891191762Simp if (error) 1892191762Simp return; 1893191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "current txpower %d\n", 1894191762Simp cur_txpwr); 1895191762Simp 1896191762Simp txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */ 1897191762Simp 1898191762Simp rf_atten_adj = -howmany(txpwr_diff, 8); 1899191762Simp if (type == BWI_TXPWR_INIT) { 1900191762Simp /* 1901191762Simp * Move toward EEPROM max TX power as fast as we can 1902191762Simp */ 1903191762Simp bbp_atten_adj = -txpwr_diff; 1904191762Simp } else { 1905191762Simp bbp_atten_adj = -(txpwr_diff / 2); 1906191762Simp } 1907191762Simp bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj); 1908191762Simp 1909191762Simp if (rf_atten_adj == 0 && bbp_atten_adj == 0) { 1910191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n", 1911191762Simp "no need to adjust RF/BBP attenuation"); 1912191762Simp /* TODO: LO */ 1913191762Simp return; 1914191762Simp } 1915191762Simp 1916191762Simpcalib: 1917191762Simp DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, 1918191762Simp "rf atten adjust %d, bbp atten adjust %d\n", 1919191762Simp rf_atten_adj, bbp_atten_adj); 1920191762Simp bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj); 1921191762Simp /* TODO: LO */ 1922191762Simp} 1923191762Simp 1924191762Simpstatic void 1925191762Simpbwi_mac_lock(struct bwi_mac *mac) 1926191762Simp{ 1927191762Simp struct bwi_softc *sc = mac->mac_sc; 1928191762Simp struct ifnet *ifp = sc->sc_ifp; 1929191762Simp struct ieee80211com *ic = ifp->if_l2com; 1930191762Simp 1931191762Simp KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0, 1932191762Simp ("mac_flags 0x%x", mac->mac_flags)); 1933191762Simp 1934191762Simp if (mac->mac_rev < 3) 1935191762Simp bwi_mac_stop(mac); 1936191762Simp else if (ic->ic_opmode != IEEE80211_M_HOSTAP) 1937191762Simp bwi_mac_config_ps(mac); 1938191762Simp 1939191762Simp CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK); 1940191762Simp 1941191762Simp /* Flush pending bus write */ 1942191762Simp CSR_READ_4(sc, BWI_MAC_STATUS); 1943191762Simp DELAY(10); 1944191762Simp 1945191762Simp mac->mac_flags |= BWI_MAC_F_LOCKED; 1946191762Simp} 1947191762Simp 1948191762Simpstatic void 1949191762Simpbwi_mac_unlock(struct bwi_mac *mac) 1950191762Simp{ 1951191762Simp struct bwi_softc *sc = mac->mac_sc; 1952191762Simp struct ifnet *ifp = sc->sc_ifp; 1953191762Simp struct ieee80211com *ic = ifp->if_l2com; 1954191762Simp 1955191762Simp KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED, 1956191762Simp ("mac_flags 0x%x", mac->mac_flags)); 1957191762Simp 1958191762Simp CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */ 1959191762Simp 1960191762Simp CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK); 1961191762Simp 1962191762Simp if (mac->mac_rev < 3) 1963191762Simp bwi_mac_start(mac); 1964191762Simp else if (ic->ic_opmode != IEEE80211_M_HOSTAP) 1965191762Simp bwi_mac_config_ps(mac); 1966191762Simp 1967191762Simp mac->mac_flags &= ~BWI_MAC_F_LOCKED; 1968191762Simp} 1969191762Simp 1970191762Simpvoid 1971191762Simpbwi_mac_set_promisc(struct bwi_mac *mac, int promisc) 1972191762Simp{ 1973191762Simp struct bwi_softc *sc = mac->mac_sc; 1974191762Simp 1975191762Simp if (mac->mac_rev < 5) /* Promisc is always on */ 1976191762Simp return; 1977191762Simp 1978191762Simp if (promisc) 1979191762Simp CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC); 1980191762Simp else 1981191762Simp CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC); 1982191762Simp} 1983