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