The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/bwi/bwimac.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
    5  * 
    6  * This code is derived from software contributed to The DragonFly Project
    7  * by Sepherosa Ziehau <sepherosa@gmail.com>
    8  * 
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in
   17  *    the documentation and/or other materials provided with the
   18  *    distribution.
   19  * 3. Neither the name of The DragonFly Project nor the names of its
   20  *    contributors may be used to endorse or promote products derived
   21  *    from this software without specific, prior written permission.
   22  * 
   23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   24  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   27  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   28  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   31  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   33  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  * 
   36  * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.13 2008/02/15 11:15:38 sephe Exp $
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD$");
   41 
   42 #include "opt_inet.h"
   43 #include "opt_bwi.h"
   44 #include "opt_wlan.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/endian.h>
   48 #include <sys/kernel.h>
   49 #include <sys/bus.h>
   50 #include <sys/malloc.h>
   51 #include <sys/proc.h>
   52 #include <sys/rman.h>
   53 #include <sys/socket.h>
   54 #include <sys/sockio.h>
   55 #include <sys/sysctl.h>
   56 #include <sys/systm.h>
   57 
   58 #include <sys/linker.h>
   59 #include <sys/firmware.h>
   60 
   61 #include <net/if.h>
   62 #include <net/if_var.h>
   63 #include <net/if_dl.h>
   64 #include <net/if_media.h>
   65 #include <net/if_types.h>
   66 #include <net/if_arp.h>
   67 #include <net/ethernet.h>
   68 #include <net/if_llc.h>
   69 
   70 #include <net80211/ieee80211_var.h>
   71 #include <net80211/ieee80211_radiotap.h>
   72 #include <net80211/ieee80211_amrr.h>
   73 #include <net80211/ieee80211_phy.h>
   74 
   75 #include <machine/bus.h>
   76 
   77 #include <dev/bwi/bitops.h>
   78 #include <dev/bwi/if_bwireg.h>
   79 #include <dev/bwi/if_bwivar.h>
   80 #include <dev/bwi/bwimac.h>
   81 #include <dev/bwi/bwirf.h>
   82 #include <dev/bwi/bwiphy.h>
   83 
   84 struct bwi_retry_lim {
   85         uint16_t        shretry;
   86         uint16_t        shretry_fb;
   87         uint16_t        lgretry;
   88         uint16_t        lgretry_fb;
   89 };
   90 
   91 static int      bwi_mac_test(struct bwi_mac *);
   92 static int      bwi_mac_get_property(struct bwi_mac *);
   93 
   94 static void     bwi_mac_set_retry_lim(struct bwi_mac *,
   95                         const struct bwi_retry_lim *);
   96 static void     bwi_mac_set_ackrates(struct bwi_mac *,
   97                         const struct ieee80211_rate_table *rt,
   98                         const struct ieee80211_rateset *);
   99 
  100 static int      bwi_mac_gpio_init(struct bwi_mac *);
  101 static int      bwi_mac_gpio_fini(struct bwi_mac *);
  102 static void     bwi_mac_opmode_init(struct bwi_mac *);
  103 static void     bwi_mac_hostflags_init(struct bwi_mac *);
  104 static void     bwi_mac_bss_param_init(struct bwi_mac *);
  105 
  106 static void     bwi_mac_fw_free(struct bwi_mac *);
  107 static int      bwi_mac_fw_load(struct bwi_mac *);
  108 static int      bwi_mac_fw_init(struct bwi_mac *);
  109 static int      bwi_mac_fw_load_iv(struct bwi_mac *, const struct firmware *);
  110 
  111 static void     bwi_mac_setup_tpctl(struct bwi_mac *);
  112 static void     bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
  113 
  114 static void     bwi_mac_lock(struct bwi_mac *);
  115 static void     bwi_mac_unlock(struct bwi_mac *);
  116 
  117 static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10 };
  118 
  119 void
  120 bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val)
  121 {
  122         struct bwi_softc *sc = mac->mac_sc;
  123 
  124         if (mac->mac_flags & BWI_MAC_F_BSWAP)
  125                 val = bswap32(val);
  126 
  127         CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs);
  128         CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val);
  129 }
  130 
  131 void
  132 bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags)
  133 {
  134         uint64_t val;
  135 
  136         val = flags & 0xffff;
  137         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val);
  138 
  139         val = (flags >> 16) & 0xffff;
  140         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val);
  141 
  142         /* HI has unclear meaning, so leave it as it is */
  143 }
  144 
  145 uint64_t
  146 bwi_hostflags_read(struct bwi_mac *mac)
  147 {
  148         uint64_t flags, val;
  149 
  150         /* HI has unclear meaning, so don't touch it */
  151         flags = 0;
  152 
  153         val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI);
  154         flags |= val << 16;
  155 
  156         val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO);
  157         flags |= val;
  158 
  159         return flags;
  160 }
  161 
  162 uint16_t
  163 bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
  164 {
  165         struct bwi_softc *sc = mac->mac_sc;
  166         uint32_t data_reg;
  167         int ofs;
  168 
  169         data_reg = BWI_MOBJ_DATA;
  170         ofs = ofs0 / 4;
  171 
  172         if (ofs0 % 4 != 0)
  173                 data_reg = BWI_MOBJ_DATA_UNALIGN;
  174 
  175         CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
  176         return CSR_READ_2(sc, data_reg);
  177 }
  178 
  179 uint32_t
  180 bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
  181 {
  182         struct bwi_softc *sc = mac->mac_sc;
  183         int ofs;
  184 
  185         ofs = ofs0 / 4;
  186         if (ofs0 % 4 != 0) {
  187                 uint32_t ret;
  188 
  189                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
  190                 ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN);
  191                 ret <<= 16;
  192 
  193                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
  194                             BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
  195                 ret |= CSR_READ_2(sc, BWI_MOBJ_DATA);
  196 
  197                 return ret;
  198         } else {
  199                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
  200                 return CSR_READ_4(sc, BWI_MOBJ_DATA);
  201         }
  202 }
  203 
  204 void
  205 bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
  206                    uint16_t v)
  207 {
  208         struct bwi_softc *sc = mac->mac_sc;
  209         uint32_t data_reg;
  210         int ofs;
  211 
  212         data_reg = BWI_MOBJ_DATA;
  213         ofs = ofs0 / 4;
  214 
  215         if (ofs0 % 4 != 0)
  216                 data_reg = BWI_MOBJ_DATA_UNALIGN;
  217 
  218         CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
  219         CSR_WRITE_2(sc, data_reg, v);
  220 }
  221 
  222 void
  223 bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
  224                    uint32_t v)
  225 {
  226         struct bwi_softc *sc = mac->mac_sc;
  227         int ofs;
  228 
  229         ofs = ofs0 / 4;
  230         if (ofs0 % 4 != 0) {
  231                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
  232                 CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16);
  233 
  234                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
  235                             BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
  236                 CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff);
  237         } else {
  238                 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
  239                 CSR_WRITE_4(sc, BWI_MOBJ_DATA, v);
  240         }
  241 }
  242 
  243 int
  244 bwi_mac_lateattach(struct bwi_mac *mac)
  245 {
  246         int error;
  247 
  248         if (mac->mac_rev >= 5)
  249                 CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */
  250 
  251         bwi_mac_reset(mac, 1);
  252 
  253         error = bwi_phy_attach(mac);
  254         if (error)
  255                 return error;
  256 
  257         error = bwi_rf_attach(mac);
  258         if (error)
  259                 return error;
  260 
  261         /* Link 11B/G PHY, unlink 11A PHY */
  262         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A)
  263                 bwi_mac_reset(mac, 0);
  264         else
  265                 bwi_mac_reset(mac, 1);
  266 
  267         error = bwi_mac_test(mac);
  268         if (error)
  269                 return error;
  270 
  271         error = bwi_mac_get_property(mac);
  272         if (error)
  273                 return error;
  274 
  275         error = bwi_rf_map_txpower(mac);
  276         if (error)
  277                 return error;
  278 
  279         bwi_rf_off(mac);
  280         CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
  281         bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0);
  282 
  283         return 0;
  284 }
  285 
  286 int
  287 bwi_mac_init(struct bwi_mac *mac)
  288 {
  289         struct bwi_softc *sc = mac->mac_sc;
  290         int error, i;
  291 
  292         /* Clear MAC/PHY/RF states */
  293         bwi_mac_setup_tpctl(mac);
  294         bwi_rf_clear_state(&mac->mac_rf);
  295         bwi_phy_clear_state(&mac->mac_phy);
  296 
  297         /* Enable MAC and linked it to PHY */
  298         if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin))
  299                 bwi_mac_reset(mac, 1);
  300 
  301         /* Initialize backplane */
  302         error = bwi_bus_init(sc, mac);
  303         if (error)
  304                 return error;
  305 
  306         /* do timeout fixup */
  307         if (sc->sc_bus_regwin.rw_rev <= 5 &&
  308             sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) {
  309                 CSR_SETBITS_4(sc, BWI_CONF_LO,
  310                 __SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) |
  311                 __SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK));
  312         }
  313 
  314         /* Calibrate PHY */
  315         error = bwi_phy_calibrate(mac);
  316         if (error) {
  317                 device_printf(sc->sc_dev, "PHY calibrate failed\n");
  318                 return error;
  319         }
  320 
  321         /* Prepare to initialize firmware */
  322         CSR_WRITE_4(sc, BWI_MAC_STATUS,
  323                     BWI_MAC_STATUS_UCODE_JUMP0 |
  324                     BWI_MAC_STATUS_IHREN);
  325 
  326         /*
  327          * Load and initialize firmwares
  328          */
  329         error = bwi_mac_fw_load(mac);
  330         if (error)
  331                 return error;
  332 
  333         error = bwi_mac_gpio_init(mac);
  334         if (error)
  335                 return error;
  336 
  337         error = bwi_mac_fw_init(mac);
  338         if (error)
  339                 return error;
  340 
  341         /*
  342          * Turn on RF
  343          */
  344         bwi_rf_on(mac);
  345 
  346         /* TODO: LED, hardware rf enabled is only related to LED setting */
  347 
  348         /*
  349          * Initialize PHY
  350          */
  351         CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
  352         bwi_phy_init(mac);
  353 
  354         /* TODO: interference mitigation */
  355 
  356         /*
  357          * Setup antenna mode
  358          */
  359         bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode);
  360 
  361         /*
  362          * Initialize operation mode (RX configuration)
  363          */
  364         bwi_mac_opmode_init(mac);
  365 
  366         /* set up Beacon interval */
  367         if (mac->mac_rev < 3) {
  368                 CSR_WRITE_2(sc, 0x60e, 0);
  369                 CSR_WRITE_2(sc, 0x610, 0x8000);
  370                 CSR_WRITE_2(sc, 0x604, 0);
  371                 CSR_WRITE_2(sc, 0x606, 0x200);
  372         } else {
  373                 CSR_WRITE_4(sc, 0x188, 0x80000000);
  374                 CSR_WRITE_4(sc, 0x18c, 0x2000000);
  375         }
  376 
  377         /*
  378          * Initialize TX/RX interrupts' mask
  379          */
  380         CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1);
  381         for (i = 0; i < BWI_TXRX_NRING; ++i) {
  382                 uint32_t intrs;
  383 
  384                 if (BWI_TXRX_IS_RX(i))
  385                         intrs = BWI_TXRX_RX_INTRS;
  386                 else
  387                         intrs = BWI_TXRX_TX_INTRS;
  388                 CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs);
  389         }
  390 
  391         /* allow the MAC to control the PHY clock (dynamic on/off) */
  392         CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000);
  393 
  394         /* Setup MAC power up delay */
  395         CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay);
  396 
  397         /* Set MAC regwin revision */
  398         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev);
  399 
  400         /*
  401          * Initialize host flags
  402          */
  403         bwi_mac_hostflags_init(mac);
  404 
  405         /*
  406          * Initialize BSS parameters
  407          */
  408         bwi_mac_bss_param_init(mac);
  409 
  410         /*
  411          * Initialize TX rings
  412          */
  413         for (i = 0; i < BWI_TX_NRING; ++i) {
  414                 error = sc->sc_init_tx_ring(sc, i);
  415                 if (error) {
  416                         device_printf(sc->sc_dev,
  417                                   "can't initialize %dth TX ring\n", i);
  418                         return error;
  419                 }
  420         }
  421 
  422         /*
  423          * Initialize RX ring
  424          */
  425         error = sc->sc_init_rx_ring(sc);
  426         if (error) {
  427                 device_printf(sc->sc_dev, "can't initialize RX ring\n");
  428                 return error;
  429         }
  430 
  431         /*
  432          * Initialize TX stats if the current MAC uses that
  433          */
  434         if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) {
  435                 error = sc->sc_init_txstats(sc);
  436                 if (error) {
  437                         device_printf(sc->sc_dev,
  438                                   "can't initialize TX stats ring\n");
  439                         return error;
  440                 }
  441         }
  442 
  443         /* update PRETBTT */
  444         CSR_WRITE_2(sc, 0x612, 0x50);   /* Force Pre-TBTT to 80? */
  445         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50);
  446         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4);
  447 
  448         mac->mac_flags |= BWI_MAC_F_INITED;
  449         return 0;
  450 }
  451 
  452 void
  453 bwi_mac_reset(struct bwi_mac *mac, int link_phy)
  454 {
  455         struct bwi_softc *sc = mac->mac_sc;
  456         uint32_t flags, state_lo, status;
  457 
  458         flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN;
  459         if (link_phy)
  460                 flags |= BWI_STATE_LO_FLAG_PHYLNK;
  461         bwi_regwin_enable(sc, &mac->mac_regwin, flags);
  462         DELAY(2000);
  463 
  464         state_lo = CSR_READ_4(sc, BWI_STATE_LO);
  465         state_lo |= BWI_STATE_LO_GATED_CLOCK;
  466         state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST,
  467                                BWI_STATE_LO_FLAGS_MASK);
  468         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
  469         /* Flush pending bus write */
  470         CSR_READ_4(sc, BWI_STATE_LO);
  471         DELAY(1000);
  472 
  473         state_lo &= ~BWI_STATE_LO_GATED_CLOCK;
  474         CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
  475         /* Flush pending bus write */
  476         CSR_READ_4(sc, BWI_STATE_LO);
  477         DELAY(1000);
  478 
  479         CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
  480 
  481         status = CSR_READ_4(sc, BWI_MAC_STATUS);
  482         status |= BWI_MAC_STATUS_IHREN;
  483         if (link_phy)
  484                 status |= BWI_MAC_STATUS_PHYLNK;
  485         else
  486                 status &= ~BWI_MAC_STATUS_PHYLNK;
  487         CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
  488 
  489         if (link_phy) {
  490                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
  491                         "%s\n", "PHY is linked");
  492                 mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED;
  493         } else {
  494                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
  495                         "%s\n", "PHY is unlinked");
  496                 mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED;
  497         }
  498 }
  499 
  500 void
  501 bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl)
  502 {
  503         struct bwi_rf *rf = &mac->mac_rf;
  504         struct bwi_tpctl *tpctl = &mac->mac_tpctl;
  505 
  506         if (new_tpctl != NULL) {
  507                 KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX,
  508                     ("bbp_atten %d", new_tpctl->bbp_atten));
  509                 KASSERT(new_tpctl->rf_atten <=
  510                          (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0
  511                                          : BWI_RF_ATTEN_MAX1),
  512                     ("rf_atten %d", new_tpctl->rf_atten));
  513                 KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX,
  514                     ("tp_ctrl1 %d", new_tpctl->tp_ctrl1));
  515 
  516                 tpctl->bbp_atten = new_tpctl->bbp_atten;
  517                 tpctl->rf_atten = new_tpctl->rf_atten;
  518                 tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1;
  519         }
  520 
  521         /* Set BBP attenuation */
  522         bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten);
  523 
  524         /* Set RF attenuation */
  525         RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten);
  526         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN,
  527                      tpctl->rf_atten);
  528 
  529         /* Set TX power */
  530         if (rf->rf_type == BWI_RF_T_BCM2050) {
  531                 RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK,
  532                         __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK));
  533         }
  534 
  535         /* Adjust RF Local Oscillator */
  536         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
  537                 bwi_rf_lo_adjust(mac, tpctl);
  538 }
  539 
  540 static int
  541 bwi_mac_test(struct bwi_mac *mac)
  542 {
  543         struct bwi_softc *sc = mac->mac_sc;
  544         uint32_t orig_val, val;
  545 
  546 #define TEST_VAL1       0xaa5555aa
  547 #define TEST_VAL2       0x55aaaa55
  548 
  549         /* Save it for later restoring */
  550         orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
  551 
  552         /* Test 1 */
  553         MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1);
  554         val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
  555         if (val != TEST_VAL1) {
  556                 device_printf(sc->sc_dev, "TEST1 failed\n");
  557                 return ENXIO;
  558         }
  559 
  560         /* Test 2 */
  561         MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2);
  562         val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
  563         if (val != TEST_VAL2) {
  564                 device_printf(sc->sc_dev, "TEST2 failed\n");
  565                 return ENXIO;
  566         }
  567 
  568         /* Restore to the original value */
  569         MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val);
  570 
  571         val = CSR_READ_4(sc, BWI_MAC_STATUS);
  572         if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) {
  573                 device_printf(sc->sc_dev, "%s failed, MAC status 0x%08x\n",
  574                               __func__, val);
  575                 return ENXIO;
  576         }
  577 
  578         val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
  579         if (val != 0) {
  580                 device_printf(sc->sc_dev, "%s failed, intr status %08x\n",
  581                               __func__, val);
  582                 return ENXIO;
  583         }
  584 
  585 #undef TEST_VAL2
  586 #undef TEST_VAL1
  587 
  588         return 0;
  589 }
  590 
  591 static void
  592 bwi_mac_setup_tpctl(struct bwi_mac *mac)
  593 {
  594         struct bwi_softc *sc = mac->mac_sc;
  595         struct bwi_rf *rf = &mac->mac_rf;
  596         struct bwi_phy *phy = &mac->mac_phy;
  597         struct bwi_tpctl *tpctl = &mac->mac_tpctl;
  598 
  599         /* Calc BBP attenuation */
  600         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6)
  601                 tpctl->bbp_atten = 0;
  602         else
  603                 tpctl->bbp_atten = 2;
  604 
  605         /* Calc TX power CTRL1?? */
  606         tpctl->tp_ctrl1 = 0;
  607         if (rf->rf_type == BWI_RF_T_BCM2050) {
  608                 if (rf->rf_rev == 1)
  609                         tpctl->tp_ctrl1 = 3;
  610                 else if (rf->rf_rev < 6)
  611                         tpctl->tp_ctrl1 = 2;
  612                 else if (rf->rf_rev == 8)
  613                         tpctl->tp_ctrl1 = 1;
  614         }
  615 
  616         /* Empty TX power CTRL2?? */
  617         tpctl->tp_ctrl2 = 0xffff;
  618 
  619         /*
  620          * Calc RF attenuation
  621          */
  622         if (phy->phy_mode == IEEE80211_MODE_11A) {
  623                 tpctl->rf_atten = 0x60;
  624                 goto back;
  625         }
  626 
  627         if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) {
  628                 tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3;
  629                 goto back;
  630         }
  631 
  632         tpctl->rf_atten = 5;
  633 
  634         if (rf->rf_type != BWI_RF_T_BCM2050) {
  635                 if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1)
  636                         tpctl->rf_atten = 6;
  637                 goto back;
  638         }
  639 
  640         /*
  641          * NB: If we reaches here and the card is BRCM_BCM4309G,
  642          *     then the card's PCI revision must >= 0x51
  643          */
  644 
  645         /* BCM2050 RF */
  646         switch (rf->rf_rev) {
  647         case 1:
  648                 if (phy->phy_mode == IEEE80211_MODE_11G) {
  649                         if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc))
  650                                 tpctl->rf_atten = 3;
  651                         else
  652                                 tpctl->rf_atten = 1;
  653                 } else {
  654                         if (BWI_IS_BRCM_BCM4309G(sc))
  655                                 tpctl->rf_atten = 7;
  656                         else
  657                                 tpctl->rf_atten = 6;
  658                 }
  659                 break;
  660         case 2:
  661                 if (phy->phy_mode == IEEE80211_MODE_11G) {
  662                         /*
  663                          * NOTE: Order of following conditions is critical
  664                          */
  665                         if (BWI_IS_BRCM_BCM4309G(sc))
  666                                 tpctl->rf_atten = 3;
  667                         else if (BWI_IS_BRCM_BU4306(sc))
  668                                 tpctl->rf_atten = 5;
  669                         else if (sc->sc_bbp_id == BWI_BBPID_BCM4320)
  670                                 tpctl->rf_atten = 4;
  671                         else
  672                                 tpctl->rf_atten = 3;
  673                 } else {
  674                         tpctl->rf_atten = 6;
  675                 }
  676                 break;
  677         case 4:
  678         case 5:
  679                 tpctl->rf_atten = 1;
  680                 break;
  681         case 8:
  682                 tpctl->rf_atten = 0x1a;
  683                 break;
  684         }
  685 back:
  686         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
  687                 "bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n",
  688                 tpctl->bbp_atten, tpctl->rf_atten,
  689                 tpctl->tp_ctrl1, tpctl->tp_ctrl2);
  690 }
  691 
  692 void
  693 bwi_mac_dummy_xmit(struct bwi_mac *mac)
  694 {
  695 #define PACKET_LEN      5
  696         static const uint32_t   packet_11a[PACKET_LEN] =
  697         { 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
  698         static const uint32_t   packet_11bg[PACKET_LEN] =
  699         { 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
  700 
  701         struct bwi_softc *sc = mac->mac_sc;
  702         struct bwi_rf *rf = &mac->mac_rf;
  703         const uint32_t *packet;
  704         uint16_t val_50c;
  705         int wait_max, i;
  706 
  707         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
  708                 wait_max = 30;
  709                 packet = packet_11a;
  710                 val_50c = 1;
  711         } else {
  712                 wait_max = 250;
  713                 packet = packet_11bg;
  714                 val_50c = 0;
  715         }
  716 
  717         for (i = 0; i < PACKET_LEN; ++i)
  718                 TMPLT_WRITE_4(mac, i * 4, packet[i]);
  719 
  720         CSR_READ_4(sc, BWI_MAC_STATUS); /* dummy read */
  721 
  722         CSR_WRITE_2(sc, 0x568, 0);
  723         CSR_WRITE_2(sc, 0x7c0, 0);
  724         CSR_WRITE_2(sc, 0x50c, val_50c);
  725         CSR_WRITE_2(sc, 0x508, 0);
  726         CSR_WRITE_2(sc, 0x50a, 0);
  727         CSR_WRITE_2(sc, 0x54c, 0);
  728         CSR_WRITE_2(sc, 0x56a, 0x14);
  729         CSR_WRITE_2(sc, 0x568, 0x826);
  730         CSR_WRITE_2(sc, 0x500, 0);
  731         CSR_WRITE_2(sc, 0x502, 0x30);
  732 
  733         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
  734                 RF_WRITE(mac, 0x51, 0x17);
  735 
  736         for (i = 0; i < wait_max; ++i) {
  737                 if (CSR_READ_2(sc, 0x50e) & 0x80)
  738                         break;
  739                 DELAY(10);
  740         }
  741         for (i = 0; i < 10; ++i) {
  742                 if (CSR_READ_2(sc, 0x50e) & 0x400)
  743                         break;
  744                 DELAY(10);
  745         }
  746         for (i = 0; i < 10; ++i) {
  747                 if ((CSR_READ_2(sc, 0x690) & 0x100) == 0)
  748                         break;
  749                 DELAY(10);
  750         }
  751 
  752         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
  753                 RF_WRITE(mac, 0x51, 0x37);
  754 #undef PACKET_LEN
  755 }
  756 
  757 void
  758 bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
  759 {
  760         struct bwi_softc *sc = mac->mac_sc;
  761         struct bwi_phy *phy = &mac->mac_phy;
  762         struct bwi_rf *rf = &mac->mac_rf;
  763         struct bwi_tpctl tpctl_orig;
  764         int restore_tpctl = 0;
  765 
  766         KASSERT(phy->phy_mode != IEEE80211_MODE_11A,
  767             ("phy_mode %d", phy->phy_mode));
  768 
  769         if (BWI_IS_BRCM_BU4306(sc))
  770                 return;
  771 
  772         PHY_WRITE(mac, 0x28, 0x8018);
  773         CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20);
  774 
  775         if (phy->phy_mode == IEEE80211_MODE_11G) {
  776                 if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
  777                         return;
  778                 PHY_WRITE(mac, 0x47a, 0xc111);
  779         }
  780         if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED)
  781                 return;
  782 
  783         if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 &&
  784             rf->rf_type == BWI_RF_T_BCM2050) {
  785                 RF_SETBITS(mac, 0x76, 0x84);
  786         } else {
  787                 struct bwi_tpctl tpctl;
  788 
  789                 /* Backup original TX power control variables */
  790                 bcopy(&mac->mac_tpctl, &tpctl_orig, sizeof(tpctl_orig));
  791                 restore_tpctl = 1;
  792 
  793                 bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
  794                 tpctl.bbp_atten = 11;
  795                 tpctl.tp_ctrl1 = 0;
  796 #ifdef notyet
  797                 if (rf->rf_rev >= 6 && rf->rf_rev <= 8)
  798                         tpctl.rf_atten = 31;
  799                 else
  800 #endif
  801                         tpctl.rf_atten = 9;
  802 
  803                 bwi_mac_set_tpctl_11bg(mac, &tpctl);
  804         }
  805 
  806         bwi_mac_dummy_xmit(mac);
  807 
  808         mac->mac_flags |= BWI_MAC_F_TPCTL_INITED;
  809         rf->rf_base_tssi = PHY_READ(mac, 0x29);
  810         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
  811                 "base tssi %d\n", rf->rf_base_tssi);
  812 
  813         if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) {
  814                 device_printf(sc->sc_dev, "base tssi measure failed\n");
  815                 mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR;
  816         }
  817 
  818         if (restore_tpctl)
  819                 bwi_mac_set_tpctl_11bg(mac, &tpctl_orig);
  820         else
  821                 RF_CLRBITS(mac, 0x76, 0x84);
  822 
  823         bwi_rf_clear_tssi(mac);
  824 }
  825 
  826 void
  827 bwi_mac_detach(struct bwi_mac *mac)
  828 {
  829         bwi_mac_fw_free(mac);
  830 }
  831 
  832 static __inline int
  833 bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
  834                      uint8_t fw_type)
  835 {
  836         const struct bwi_fwhdr *hdr;
  837 
  838         if (fw->datasize < sizeof(*hdr)) {
  839                 device_printf(sc->sc_dev,
  840                     "invalid firmware (%s): invalid size %zu\n",
  841                     fw->name, fw->datasize);
  842                 return 0;
  843         }
  844 
  845         hdr = (const struct bwi_fwhdr *)fw->data;
  846 
  847         if (fw_type != BWI_FW_T_IV) {
  848                 /*
  849                  * Don't verify IV's size, it has different meaning
  850                  */
  851                 if (be32toh(hdr->fw_size) != fw->datasize - sizeof(*hdr)) {
  852                         device_printf(sc->sc_dev,
  853                             "invalid firmware (%s): size mismatch, "
  854                             "fw %u, real %zu\n", fw->name,
  855                             be32toh(hdr->fw_size), fw->datasize - sizeof(*hdr));
  856                         return 0;
  857                 }
  858         }
  859 
  860         if (hdr->fw_type != fw_type) {
  861                 device_printf(sc->sc_dev,
  862                     "invalid firmware (%s): type mismatch, "
  863                     "fw \'%c\', target \'%c\'\n", fw->name,
  864                     hdr->fw_type, fw_type);
  865                 return 0;
  866         }
  867 
  868         if (hdr->fw_gen != BWI_FW_GEN_1) {
  869                 device_printf(sc->sc_dev,
  870                     "invalid firmware (%s): wrong generation, "
  871                     "fw %d, target %d\n", fw->name, hdr->fw_gen, BWI_FW_GEN_1);
  872                 return 0;
  873         }
  874         return 1;
  875 }
  876 
  877 /*
  878  * XXX Error cleanup
  879  */
  880 int
  881 bwi_mac_fw_alloc(struct bwi_mac *mac)
  882 {
  883         struct bwi_softc *sc = mac->mac_sc;
  884         char fwname[64];
  885         int idx;
  886 
  887         /*
  888          * Try getting the firmware stub so firmware
  889          * module would be loaded automatically
  890          */
  891         if (mac->mac_stub == NULL) {
  892                 snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH,
  893                          sc->sc_fw_version);
  894                 mac->mac_stub = firmware_get(fwname);
  895                 if (mac->mac_stub == NULL)
  896                         goto no_firmware;
  897         }
  898 
  899         if (mac->mac_ucode == NULL) {
  900                 snprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH,
  901                           sc->sc_fw_version,
  902                           mac->mac_rev >= 5 ? 5 : mac->mac_rev);
  903 
  904                 mac->mac_ucode = firmware_get(fwname);
  905                 if (mac->mac_ucode == NULL)
  906                         goto no_firmware;
  907                 if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE))
  908                         return EINVAL;
  909         }
  910 
  911         if (mac->mac_pcm == NULL) {
  912                 snprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH,
  913                           sc->sc_fw_version,
  914                           mac->mac_rev < 5 ? 4 : 5);
  915 
  916                 mac->mac_pcm = firmware_get(fwname);
  917                 if (mac->mac_pcm == NULL)
  918                         goto no_firmware;
  919                 if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM))
  920                         return EINVAL;
  921         }
  922 
  923         if (mac->mac_iv == NULL) {
  924                 /* TODO: 11A */
  925                 if (mac->mac_rev == 2 || mac->mac_rev == 4) {
  926                         idx = 2;
  927                 } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
  928                         idx = 5;
  929                 } else {
  930                         device_printf(sc->sc_dev,
  931                             "no suitible IV for MAC rev %d\n", mac->mac_rev);
  932                         return ENODEV;
  933                 }
  934 
  935                 snprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH,
  936                           sc->sc_fw_version, idx);
  937 
  938                 mac->mac_iv = firmware_get(fwname);
  939                 if (mac->mac_iv == NULL)
  940                         goto no_firmware;
  941                 if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV))
  942                         return EINVAL;
  943         }
  944 
  945         if (mac->mac_iv_ext == NULL) {
  946                 /* TODO: 11A */
  947                 if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
  948                     mac->mac_rev >= 11) {
  949                         /* No extended IV */
  950                         return (0);
  951                 } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
  952                         idx = 5;
  953                 } else {
  954                         device_printf(sc->sc_dev,
  955                             "no suitible ExtIV for MAC rev %d\n", mac->mac_rev);
  956                         return ENODEV;
  957                 }
  958 
  959                 snprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH,
  960                           sc->sc_fw_version, idx);
  961 
  962                 mac->mac_iv_ext = firmware_get(fwname);
  963                 if (mac->mac_iv_ext == NULL)
  964                         goto no_firmware;
  965                 if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV))
  966                         return EINVAL;
  967         }
  968         return (0);
  969 
  970 no_firmware:
  971         device_printf(sc->sc_dev, "request firmware %s failed\n", fwname);
  972         return (ENOENT);
  973 }
  974 
  975 static void
  976 bwi_mac_fw_free(struct bwi_mac *mac)
  977 {
  978         if (mac->mac_ucode != NULL) {
  979                 firmware_put(mac->mac_ucode, FIRMWARE_UNLOAD);
  980                 mac->mac_ucode = NULL;
  981         }
  982 
  983         if (mac->mac_pcm != NULL) {
  984                 firmware_put(mac->mac_pcm, FIRMWARE_UNLOAD);
  985                 mac->mac_pcm = NULL;
  986         }
  987 
  988         if (mac->mac_iv != NULL) {
  989                 firmware_put(mac->mac_iv, FIRMWARE_UNLOAD);
  990                 mac->mac_iv = NULL;
  991         }
  992 
  993         if (mac->mac_iv_ext != NULL) {
  994                 firmware_put(mac->mac_iv_ext, FIRMWARE_UNLOAD);
  995                 mac->mac_iv_ext = NULL;
  996         }
  997 
  998         if (mac->mac_stub != NULL) {
  999                 firmware_put(mac->mac_stub, FIRMWARE_UNLOAD);
 1000                 mac->mac_stub = NULL;
 1001         }
 1002 }
 1003 
 1004 static int
 1005 bwi_mac_fw_load(struct bwi_mac *mac)
 1006 {
 1007         struct bwi_softc *sc = mac->mac_sc;
 1008         const uint32_t *fw;
 1009         uint16_t fw_rev;
 1010         int fw_len, i;
 1011 
 1012         /*
 1013          * Load ucode image
 1014          */
 1015         fw = (const uint32_t *)
 1016              ((const uint8_t *)mac->mac_ucode->data + BWI_FWHDR_SZ);
 1017         fw_len = (mac->mac_ucode->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t);
 1018 
 1019         CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
 1020                     BWI_MOBJ_CTRL_VAL(
 1021                     BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0));
 1022         for (i = 0; i < fw_len; ++i) {
 1023                 CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
 1024                 DELAY(10);
 1025         }
 1026 
 1027         /*
 1028          * Load PCM image
 1029          */
 1030         fw = (const uint32_t *)
 1031              ((const uint8_t *)mac->mac_pcm->data + BWI_FWHDR_SZ);
 1032         fw_len = (mac->mac_pcm->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t);
 1033 
 1034         CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
 1035                     BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea));
 1036         CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000);
 1037 
 1038         CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
 1039                     BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb));
 1040         for (i = 0; i < fw_len; ++i) {
 1041                 CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
 1042                 DELAY(10);
 1043         }
 1044 
 1045         CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS);
 1046         CSR_WRITE_4(sc, BWI_MAC_STATUS,
 1047                     BWI_MAC_STATUS_UCODE_START |
 1048                     BWI_MAC_STATUS_IHREN |
 1049                     BWI_MAC_STATUS_INFRA);
 1050 
 1051 #define NRETRY  200
 1052 
 1053         for (i = 0; i < NRETRY; ++i) {
 1054                 uint32_t intr_status;
 1055 
 1056                 intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
 1057                 if (intr_status == BWI_INTR_READY)
 1058                         break;
 1059                 DELAY(10);
 1060         }
 1061         if (i == NRETRY) {
 1062                 device_printf(sc->sc_dev,
 1063                     "firmware (ucode&pcm) loading timed out\n");
 1064                 return ETIMEDOUT;
 1065         }
 1066 
 1067 #undef NRETRY
 1068 
 1069         CSR_READ_4(sc, BWI_MAC_INTR_STATUS);    /* dummy read */
 1070 
 1071         fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
 1072         if (fw_rev > BWI_FW_VERSION3_REVMAX) {
 1073                 device_printf(sc->sc_dev,
 1074                     "firmware version 4 is not supported yet\n");
 1075                 return ENODEV;
 1076         }
 1077 
 1078         device_printf(sc->sc_dev,
 1079             "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
 1080             MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
 1081         return 0;
 1082 }
 1083 
 1084 static int
 1085 bwi_mac_gpio_init(struct bwi_mac *mac)
 1086 {
 1087         struct bwi_softc *sc = mac->mac_sc;
 1088         struct bwi_regwin *old, *gpio_rw;
 1089         uint32_t filt, bits;
 1090         int error;
 1091 
 1092         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK);
 1093         /* TODO:LED */
 1094 
 1095         CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf);
 1096 
 1097         filt = 0x1f;
 1098         bits = 0xf;
 1099         if (sc->sc_bbp_id == BWI_BBPID_BCM4301) {
 1100                 filt |= 0x60;
 1101                 bits |= 0x60;
 1102         }
 1103         if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
 1104                 CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200);
 1105                 filt |= 0x200;
 1106                 bits |= 0x200;
 1107         }
 1108 
 1109         gpio_rw = BWI_GPIO_REGWIN(sc);
 1110         error = bwi_regwin_switch(sc, gpio_rw, &old);
 1111         if (error)
 1112                 return error;
 1113 
 1114         CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits);
 1115 
 1116         return bwi_regwin_switch(sc, old, NULL);
 1117 }
 1118 
 1119 static int
 1120 bwi_mac_gpio_fini(struct bwi_mac *mac)
 1121 {
 1122         struct bwi_softc *sc = mac->mac_sc;
 1123         struct bwi_regwin *old, *gpio_rw;
 1124         int error;
 1125 
 1126         gpio_rw = BWI_GPIO_REGWIN(sc);
 1127         error = bwi_regwin_switch(sc, gpio_rw, &old);
 1128         if (error)
 1129                 return error;
 1130 
 1131         CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0);
 1132 
 1133         return bwi_regwin_switch(sc, old, NULL);
 1134 }
 1135 
 1136 static int
 1137 bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
 1138 {
 1139         struct bwi_softc *sc = mac->mac_sc;
 1140         const struct bwi_fwhdr *hdr;
 1141         const struct bwi_fw_iv *iv;
 1142         int n, i, iv_img_size;
 1143 
 1144         /* Get the number of IVs in the IV image */
 1145         hdr = (const struct bwi_fwhdr *)fw->data;
 1146         n = be32toh(hdr->fw_iv_cnt);
 1147         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
 1148                 "IV count %d\n", n);
 1149 
 1150         /* Calculate the IV image size, for later sanity check */
 1151         iv_img_size = fw->datasize - sizeof(*hdr);
 1152 
 1153         /* Locate the first IV */
 1154         iv = (const struct bwi_fw_iv *)
 1155              ((const uint8_t *)fw->data + sizeof(*hdr));
 1156 
 1157         for (i = 0; i < n; ++i) {
 1158                 uint16_t iv_ofs, ofs;
 1159                 int sz = 0;
 1160 
 1161                 if (iv_img_size < sizeof(iv->iv_ofs)) {
 1162                         device_printf(sc->sc_dev, "invalid IV image, ofs\n");
 1163                         return EINVAL;
 1164                 }
 1165                 iv_img_size -= sizeof(iv->iv_ofs);
 1166                 sz += sizeof(iv->iv_ofs);
 1167 
 1168                 iv_ofs = be16toh(iv->iv_ofs);
 1169 
 1170                 ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
 1171                 if (ofs >= 0x1000) {
 1172                         device_printf(sc->sc_dev, "invalid ofs (0x%04x) "
 1173                                   "for %dth iv\n", ofs, i);
 1174                         return EINVAL;
 1175                 }
 1176 
 1177                 if (iv_ofs & BWI_FW_IV_IS_32BIT) {
 1178                         uint32_t val32;
 1179 
 1180                         if (iv_img_size < sizeof(iv->iv_val.val32)) {
 1181                                 device_printf(sc->sc_dev,
 1182                                     "invalid IV image, val32\n");
 1183                                 return EINVAL;
 1184                         }
 1185                         iv_img_size -= sizeof(iv->iv_val.val32);
 1186                         sz += sizeof(iv->iv_val.val32);
 1187 
 1188                         val32 = be32toh(iv->iv_val.val32);
 1189                         CSR_WRITE_4(sc, ofs, val32);
 1190                 } else {
 1191                         uint16_t val16;
 1192 
 1193                         if (iv_img_size < sizeof(iv->iv_val.val16)) {
 1194                                 device_printf(sc->sc_dev,
 1195                                     "invalid IV image, val16\n");
 1196                                 return EINVAL;
 1197                         }
 1198                         iv_img_size -= sizeof(iv->iv_val.val16);
 1199                         sz += sizeof(iv->iv_val.val16);
 1200 
 1201                         val16 = be16toh(iv->iv_val.val16);
 1202                         CSR_WRITE_2(sc, ofs, val16);
 1203                 }
 1204 
 1205                 iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz);
 1206         }
 1207 
 1208         if (iv_img_size != 0) {
 1209                 device_printf(sc->sc_dev, "invalid IV image, size left %d\n",
 1210                     iv_img_size);
 1211                 return EINVAL;
 1212         }
 1213         return 0;
 1214 }
 1215 
 1216 static int
 1217 bwi_mac_fw_init(struct bwi_mac *mac)
 1218 {
 1219         device_t dev = mac->mac_sc->sc_dev;
 1220         int error;
 1221 
 1222         error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
 1223         if (error) {
 1224                 device_printf(dev, "load IV failed\n");
 1225                 return error;
 1226         }
 1227 
 1228         if (mac->mac_iv_ext != NULL) {
 1229                 error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext);
 1230                 if (error)
 1231                         device_printf(dev, "load ExtIV failed\n");
 1232         }
 1233         return error;
 1234 }
 1235 
 1236 static void
 1237 bwi_mac_opmode_init(struct bwi_mac *mac)
 1238 {
 1239         struct bwi_softc *sc = mac->mac_sc;
 1240         struct ieee80211com *ic = &sc->sc_ic;
 1241         uint32_t mac_status;
 1242         uint16_t pre_tbtt;
 1243 
 1244         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
 1245         CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
 1246 
 1247         /* Set probe resp timeout to infinite */
 1248         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0);
 1249 
 1250         /*
 1251          * TODO: factor out following part
 1252          */
 1253 
 1254         mac_status = CSR_READ_4(sc, BWI_MAC_STATUS);
 1255         mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP |
 1256                         BWI_MAC_STATUS_PASS_CTL |
 1257                         BWI_MAC_STATUS_PASS_BCN |
 1258                         BWI_MAC_STATUS_PASS_BADPLCP |
 1259                         BWI_MAC_STATUS_PASS_BADFCS |
 1260                         BWI_MAC_STATUS_PROMISC);
 1261         mac_status |= BWI_MAC_STATUS_INFRA;
 1262 
 1263         /* Always turn on PROMISC on old hardware */
 1264         if (mac->mac_rev < 5)
 1265                 mac_status |= BWI_MAC_STATUS_PROMISC;
 1266 
 1267         switch (ic->ic_opmode) {
 1268         case IEEE80211_M_IBSS:
 1269                 mac_status &= ~BWI_MAC_STATUS_INFRA;
 1270                 break;
 1271         case IEEE80211_M_HOSTAP:
 1272                 mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP;
 1273                 break;
 1274         case IEEE80211_M_MONITOR:
 1275 #if 0
 1276                 /* Do you want data from your microwave oven? */
 1277                 mac_status |= BWI_MAC_STATUS_PASS_CTL |
 1278                               BWI_MAC_STATUS_PASS_BADPLCP |
 1279                               BWI_MAC_STATUS_PASS_BADFCS;
 1280 #else
 1281                 mac_status |= BWI_MAC_STATUS_PASS_CTL;
 1282 #endif
 1283                 /* Promisc? */
 1284                 break;
 1285         default:
 1286                 break;
 1287         }
 1288 
 1289         if (ic->ic_promisc > 0)
 1290                 mac_status |= BWI_MAC_STATUS_PROMISC;
 1291 
 1292         CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
 1293 
 1294         if (ic->ic_opmode != IEEE80211_M_IBSS &&
 1295             ic->ic_opmode != IEEE80211_M_HOSTAP) {
 1296                 if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3)
 1297                         pre_tbtt = 100;
 1298                 else
 1299                         pre_tbtt = 50;
 1300         } else {
 1301                 pre_tbtt = 2;
 1302         }
 1303         CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt);
 1304 }
 1305 
 1306 static void
 1307 bwi_mac_hostflags_init(struct bwi_mac *mac)
 1308 {
 1309         struct bwi_softc *sc = mac->mac_sc;
 1310         struct bwi_phy *phy = &mac->mac_phy;
 1311         struct bwi_rf *rf = &mac->mac_rf;
 1312         uint64_t host_flags;
 1313 
 1314         if (phy->phy_mode == IEEE80211_MODE_11A)
 1315                 return;
 1316 
 1317         host_flags = HFLAGS_READ(mac);
 1318         host_flags |= BWI_HFLAG_SYM_WA;
 1319 
 1320         if (phy->phy_mode == IEEE80211_MODE_11G) {
 1321                 if (phy->phy_rev == 1)
 1322                         host_flags |= BWI_HFLAG_GDC_WA;
 1323                 if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
 1324                         host_flags |= BWI_HFLAG_OFDM_PA;
 1325         } else if (phy->phy_mode == IEEE80211_MODE_11B) {
 1326                 if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050)
 1327                         host_flags &= ~BWI_HFLAG_GDC_WA;
 1328         } else {
 1329                 panic("unknown PHY mode %u\n", phy->phy_mode);
 1330         }
 1331 
 1332         HFLAGS_WRITE(mac, host_flags);
 1333 }
 1334 
 1335 static void
 1336 bwi_mac_bss_param_init(struct bwi_mac *mac)
 1337 {
 1338         struct bwi_softc *sc = mac->mac_sc;
 1339         struct bwi_phy *phy = &mac->mac_phy;
 1340         struct ieee80211com *ic = &sc->sc_ic;
 1341         const struct ieee80211_rate_table *rt;
 1342         struct bwi_retry_lim lim;
 1343         uint16_t cw_min;
 1344 
 1345         /*
 1346          * Set short/long retry limits
 1347          */
 1348         bzero(&lim, sizeof(lim));
 1349         lim.shretry = BWI_SHRETRY;
 1350         lim.shretry_fb = BWI_SHRETRY_FB;
 1351         lim.lgretry = BWI_LGRETRY;
 1352         lim.lgretry_fb = BWI_LGRETRY_FB;
 1353         bwi_mac_set_retry_lim(mac, &lim);
 1354 
 1355         /*
 1356          * Implicitly prevent firmware from sending probe response
 1357          * by setting its "probe response timeout" to 1us.
 1358          */
 1359         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1);
 1360 
 1361         /*
 1362          * XXX MAC level acknowledge and CW min/max should depend
 1363          * on the char rateset of the IBSS/BSS to join.
 1364          * XXX this is all wrong; should be done on channel change
 1365          */
 1366         if (phy->phy_mode == IEEE80211_MODE_11B) {
 1367                 rt = ieee80211_get_ratetable(
 1368                     ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_B));
 1369                 bwi_mac_set_ackrates(mac, rt,
 1370                     &ic->ic_sup_rates[IEEE80211_MODE_11B]);
 1371         } else {
 1372                 rt = ieee80211_get_ratetable(
 1373                     ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_G));
 1374                 bwi_mac_set_ackrates(mac, rt,
 1375                     &ic->ic_sup_rates[IEEE80211_MODE_11G]);
 1376         }
 1377 
 1378         /*
 1379          * Set CW min
 1380          */
 1381         if (phy->phy_mode == IEEE80211_MODE_11B)
 1382                 cw_min = IEEE80211_CW_MIN_0;
 1383         else
 1384                 cw_min = IEEE80211_CW_MIN_1;
 1385         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min);
 1386 
 1387         /*
 1388          * Set CW max
 1389          */
 1390         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX,
 1391                      IEEE80211_CW_MAX);
 1392 }
 1393 
 1394 static void
 1395 bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim)
 1396 {
 1397         /* Short/Long retry limit */
 1398         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY,
 1399                      lim->shretry);
 1400         MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY,
 1401                      lim->lgretry);
 1402 
 1403         /* Short/Long retry fallback limit */
 1404         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB,
 1405                      lim->shretry_fb);
 1406         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB,
 1407                      lim->lgretry_fb);
 1408 }
 1409 
 1410 static void
 1411 bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rate_table *rt,
 1412         const struct ieee80211_rateset *rs)
 1413 {
 1414         int i;
 1415 
 1416         /* XXX not standard conforming */
 1417         for (i = 0; i < rs->rs_nrates; ++i) {
 1418                 enum ieee80211_phytype modtype;
 1419                 uint16_t ofs;
 1420 
 1421                 modtype = ieee80211_rate2phytype(rt,
 1422                     rs->rs_rates[i] & IEEE80211_RATE_VAL);
 1423                 switch (modtype) {
 1424                 case IEEE80211_T_DS:
 1425                         ofs = 0x4c0;
 1426                         break;
 1427                 case IEEE80211_T_OFDM:
 1428                         ofs = 0x480;
 1429                         break;
 1430                 default:
 1431                         panic("unsupported modtype %u\n", modtype);
 1432                 }
 1433                 ofs += 2*(ieee80211_rate2plcp(
 1434                     rs->rs_rates[i] & IEEE80211_RATE_VAL,
 1435                     modtype) & 0xf);
 1436 
 1437                 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,
 1438                              MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs));
 1439         }
 1440 }
 1441 
 1442 int
 1443 bwi_mac_start(struct bwi_mac *mac)
 1444 {
 1445         struct bwi_softc *sc = mac->mac_sc;
 1446 
 1447         CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
 1448         CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY);
 1449 
 1450         /* Flush pending bus writes */
 1451         CSR_READ_4(sc, BWI_MAC_STATUS);
 1452         CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
 1453 
 1454         return bwi_mac_config_ps(mac);
 1455 }
 1456 
 1457 int
 1458 bwi_mac_stop(struct bwi_mac *mac)
 1459 {
 1460         struct bwi_softc *sc = mac->mac_sc;
 1461         int error, i;
 1462 
 1463         error = bwi_mac_config_ps(mac);
 1464         if (error)
 1465                 return error;
 1466 
 1467         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
 1468 
 1469         /* Flush pending bus write */
 1470         CSR_READ_4(sc, BWI_MAC_STATUS);
 1471 
 1472 #define NRETRY  10000
 1473         for (i = 0; i < NRETRY; ++i) {
 1474                 if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY)
 1475                         break;
 1476                 DELAY(1);
 1477         }
 1478         if (i == NRETRY) {
 1479                 device_printf(sc->sc_dev, "can't stop MAC\n");
 1480                 return ETIMEDOUT;
 1481         }
 1482 #undef NRETRY
 1483 
 1484         return 0;
 1485 }
 1486 
 1487 int
 1488 bwi_mac_config_ps(struct bwi_mac *mac)
 1489 {
 1490         struct bwi_softc *sc = mac->mac_sc;
 1491         uint32_t status;
 1492 
 1493         status = CSR_READ_4(sc, BWI_MAC_STATUS);
 1494 
 1495         status &= ~BWI_MAC_STATUS_HW_PS;
 1496         status |= BWI_MAC_STATUS_WAKEUP;
 1497         CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
 1498 
 1499         /* Flush pending bus write */
 1500         CSR_READ_4(sc, BWI_MAC_STATUS);
 1501 
 1502         if (mac->mac_rev >= 5) {
 1503                 int i;
 1504 
 1505 #define NRETRY  100
 1506                 for (i = 0; i < NRETRY; ++i) {
 1507                         if (MOBJ_READ_2(mac, BWI_COMM_MOBJ,
 1508                             BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS)
 1509                                 break;
 1510                         DELAY(10);
 1511                 }
 1512                 if (i == NRETRY) {
 1513                         device_printf(sc->sc_dev, "config PS failed\n");
 1514                         return ETIMEDOUT;
 1515                 }
 1516 #undef NRETRY
 1517         }
 1518         return 0;
 1519 }
 1520 
 1521 void
 1522 bwi_mac_reset_hwkeys(struct bwi_mac *mac)
 1523 {
 1524         /* TODO: firmware crypto */
 1525         MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS);
 1526 }
 1527 
 1528 void
 1529 bwi_mac_shutdown(struct bwi_mac *mac)
 1530 {
 1531         struct bwi_softc *sc = mac->mac_sc;
 1532         int i;
 1533 
 1534         if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS)
 1535                 sc->sc_free_txstats(sc);
 1536 
 1537         sc->sc_free_rx_ring(sc);
 1538 
 1539         for (i = 0; i < BWI_TX_NRING; ++i)
 1540                 sc->sc_free_tx_ring(sc, i);
 1541 
 1542         bwi_rf_off(mac);
 1543 
 1544         /* TODO:LED */
 1545 
 1546         bwi_mac_gpio_fini(mac);
 1547 
 1548         bwi_rf_off(mac); /* XXX again */
 1549         CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
 1550         bwi_regwin_disable(sc, &mac->mac_regwin, 0);
 1551 
 1552         mac->mac_flags &= ~BWI_MAC_F_INITED;
 1553 }
 1554 
 1555 static int
 1556 bwi_mac_get_property(struct bwi_mac *mac)
 1557 {
 1558         struct bwi_softc *sc = mac->mac_sc;
 1559         enum bwi_bus_space old_bus_space;
 1560         uint32_t val;
 1561 
 1562         /*
 1563          * Byte swap
 1564          */
 1565         val = CSR_READ_4(sc, BWI_MAC_STATUS);
 1566         if (val & BWI_MAC_STATUS_BSWAP) {
 1567                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
 1568                         "need byte swap");
 1569                 mac->mac_flags |= BWI_MAC_F_BSWAP;
 1570         }
 1571 
 1572         /*
 1573          * DMA address space
 1574          */
 1575         old_bus_space = sc->sc_bus_space;
 1576 
 1577         val = CSR_READ_4(sc, BWI_STATE_HI);
 1578         if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) &
 1579             BWI_STATE_HI_FLAG_64BIT) {
 1580                 /* 64bit address */
 1581                 sc->sc_bus_space = BWI_BUS_SPACE_64BIT;
 1582                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
 1583                         "64bit bus space");
 1584         } else {
 1585                 uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL;
 1586 
 1587                 CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK);
 1588                 if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) {
 1589                         /* 32bit address */
 1590                         sc->sc_bus_space = BWI_BUS_SPACE_32BIT;
 1591                         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
 1592                                 "32bit bus space");
 1593                 } else {
 1594                         /* 30bit address */
 1595                         sc->sc_bus_space = BWI_BUS_SPACE_30BIT;
 1596                         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
 1597                                 "30bit bus space");
 1598                 }
 1599         }
 1600 
 1601         if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) {
 1602                 device_printf(sc->sc_dev, "MACs bus space mismatch!\n");
 1603                 return ENXIO;
 1604         }
 1605         return 0;
 1606 }
 1607 
 1608 void
 1609 bwi_mac_updateslot(struct bwi_mac *mac, int shslot)
 1610 {
 1611         uint16_t slot_time;
 1612 
 1613         if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
 1614                 return;
 1615 
 1616         if (shslot)
 1617                 slot_time = IEEE80211_DUR_SHSLOT;
 1618         else
 1619                 slot_time = IEEE80211_DUR_SLOT;
 1620 
 1621         CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME,
 1622                     slot_time + BWI_MAC_SLOTTIME_ADJUST);
 1623         MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time);
 1624 }
 1625 
 1626 int
 1627 bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
 1628 {
 1629         struct bwi_mac *mac;
 1630         int i;
 1631 
 1632         KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0,
 1633             ("sc_nmac %d", sc->sc_nmac));
 1634 
 1635         if (sc->sc_nmac == BWI_MAC_MAX) {
 1636                 device_printf(sc->sc_dev, "too many MACs\n");
 1637                 return 0;
 1638         }
 1639 
 1640         /*
 1641          * More than one MAC is only supported by BCM4309
 1642          */
 1643         if (sc->sc_nmac != 0 &&
 1644             sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM4309) {
 1645                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
 1646                         "ignore second MAC");
 1647                 return 0;
 1648         }
 1649 
 1650         mac = &sc->sc_mac[sc->sc_nmac];
 1651 
 1652         /* XXX will this happen? */
 1653         if (BWI_REGWIN_EXIST(&mac->mac_regwin)) {
 1654                 device_printf(sc->sc_dev, "%dth MAC already attached\n",
 1655                               sc->sc_nmac);
 1656                 return 0;
 1657         }
 1658 
 1659         /*
 1660          * Test whether the revision of this MAC is supported
 1661          */
 1662         for (i = 0; i < nitems(bwi_sup_macrev); ++i) {
 1663                 if (bwi_sup_macrev[i] == rev)
 1664                         break;
 1665         }
 1666         if (i == nitems(bwi_sup_macrev)) {
 1667                 device_printf(sc->sc_dev, "MAC rev %u is "
 1668                               "not supported\n", rev);
 1669                 return ENXIO;
 1670         }
 1671 
 1672         BWI_CREATE_MAC(mac, sc, id, rev);
 1673         sc->sc_nmac++;
 1674 
 1675         if (mac->mac_rev < 5) {
 1676                 mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
 1677                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
 1678                         "has TX stats");
 1679         } else {
 1680                 mac->mac_flags |= BWI_MAC_F_PHYE_RESET;
 1681         }
 1682 
 1683         device_printf(sc->sc_dev, "MAC: rev %u\n", rev);
 1684         return 0;
 1685 }
 1686 
 1687 static __inline void
 1688 bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0)
 1689 {
 1690         int bbp_atten, rf_atten, rf_atten_lim = -1;
 1691 
 1692         bbp_atten = *bbp_atten0;
 1693         rf_atten = *rf_atten0;
 1694 
 1695         /*
 1696          * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times
 1697          * as much as BBP attenuation, so we try our best to keep RF
 1698          * attenuation within range.  BBP attenuation will be clamped
 1699          * later if it is out of range during balancing.
 1700          *
 1701          * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit.
 1702          */
 1703 
 1704         /*
 1705          * Use BBP attenuation to balance RF attenuation
 1706          */
 1707         if (rf_atten < 0)
 1708                 rf_atten_lim = 0;
 1709         else if (rf_atten > BWI_RF_ATTEN_MAX0)
 1710                 rf_atten_lim = BWI_RF_ATTEN_MAX0;
 1711 
 1712         if (rf_atten_lim >= 0) {
 1713                 bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim));
 1714                 rf_atten = rf_atten_lim;
 1715         }
 1716 
 1717         /*
 1718          * If possible, use RF attenuation to balance BBP attenuation
 1719          * NOTE: RF attenuation is still kept within range.
 1720          */
 1721         while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) {
 1722                 bbp_atten -= BWI_RF_ATTEN_FACTOR;
 1723                 ++rf_atten;
 1724         }
 1725         while (rf_atten > 0 && bbp_atten < 0) {
 1726                 bbp_atten += BWI_RF_ATTEN_FACTOR;
 1727                 --rf_atten;
 1728         }
 1729 
 1730         /* RF attenuation MUST be within range */
 1731         KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0,
 1732             ("rf_atten %d", rf_atten));
 1733 
 1734         /*
 1735          * Clamp BBP attenuation
 1736          */
 1737         if (bbp_atten < 0)
 1738                 bbp_atten = 0;
 1739         else if (bbp_atten > BWI_BBP_ATTEN_MAX)
 1740                 bbp_atten = BWI_BBP_ATTEN_MAX;
 1741 
 1742         *rf_atten0 = rf_atten;
 1743         *bbp_atten0 = bbp_atten;
 1744 }
 1745 
 1746 static void
 1747 bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj)
 1748 {
 1749         struct bwi_softc *sc = mac->mac_sc;
 1750         struct bwi_rf *rf = &mac->mac_rf;
 1751         struct bwi_tpctl tpctl;
 1752         int bbp_atten, rf_atten, tp_ctrl1;
 1753 
 1754         bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
 1755 
 1756         /* NOTE: Use signed value to do calulation */
 1757         bbp_atten = tpctl.bbp_atten;
 1758         rf_atten = tpctl.rf_atten;
 1759         tp_ctrl1 = tpctl.tp_ctrl1;
 1760 
 1761         bbp_atten += bbp_atten_adj;
 1762         rf_atten += rf_atten_adj;
 1763 
 1764         bwi_mac_balance_atten(&bbp_atten, &rf_atten);
 1765 
 1766         if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) {
 1767                 if (rf_atten <= 1) {
 1768                         if (tp_ctrl1 == 0) {
 1769                                 tp_ctrl1 = 3;
 1770                                 bbp_atten += 2;
 1771                                 rf_atten += 2;
 1772                         } else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
 1773                                 bbp_atten +=
 1774                                 (BWI_RF_ATTEN_FACTOR * (rf_atten - 2));
 1775                                 rf_atten = 2;
 1776                         }
 1777                 } else if (rf_atten > 4 && tp_ctrl1 != 0) {
 1778                         tp_ctrl1 = 0;
 1779                         if (bbp_atten < 3) {
 1780                                 bbp_atten += 2;
 1781                                 rf_atten -= 3;
 1782                         } else {
 1783                                 bbp_atten -= 2;
 1784                                 rf_atten -= 2;
 1785                         }
 1786                 }
 1787                 bwi_mac_balance_atten(&bbp_atten, &rf_atten);
 1788         }
 1789 
 1790         tpctl.bbp_atten = bbp_atten;
 1791         tpctl.rf_atten = rf_atten;
 1792         tpctl.tp_ctrl1 = tp_ctrl1;
 1793 
 1794         bwi_mac_lock(mac);
 1795         bwi_mac_set_tpctl_11bg(mac, &tpctl);
 1796         bwi_mac_unlock(mac);
 1797 }
 1798 
 1799 /*
 1800  * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower
 1801  */
 1802 void
 1803 bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type)
 1804 {
 1805         struct bwi_softc *sc = mac->mac_sc;
 1806         struct bwi_rf *rf = &mac->mac_rf;
 1807         int8_t tssi[4], tssi_avg, cur_txpwr;
 1808         int error, i, ofdm_tssi;
 1809         int txpwr_diff, rf_atten_adj, bbp_atten_adj;
 1810 
 1811         if (!sc->sc_txpwr_calib)
 1812                 return;
 1813 
 1814         if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) {
 1815                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
 1816                         "tpctl error happened, can't set txpower");
 1817                 return;
 1818         }
 1819 
 1820         if (BWI_IS_BRCM_BU4306(sc)) {
 1821                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
 1822                         "BU4306, can't set txpower");
 1823                 return;
 1824         }
 1825 
 1826         /*
 1827          * Save latest TSSI and reset the related memory objects
 1828          */
 1829         ofdm_tssi = 0;
 1830         error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS);
 1831         if (error) {
 1832                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
 1833                         "no DS tssi");
 1834 
 1835                 if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) {
 1836                         if (type == BWI_TXPWR_FORCE) {
 1837                                 rf_atten_adj = 0;
 1838                                 bbp_atten_adj = 1;
 1839                                 goto calib;
 1840                         } else {
 1841                                 return;
 1842                         }
 1843                 }
 1844 
 1845                 error = bwi_rf_get_latest_tssi(mac, tssi,
 1846                                 BWI_COMM_MOBJ_TSSI_OFDM);
 1847                 if (error) {
 1848                         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
 1849                                 "no OFDM tssi");
 1850                         if (type == BWI_TXPWR_FORCE) {
 1851                                 rf_atten_adj = 0;
 1852                                 bbp_atten_adj = 1;
 1853                                 goto calib;
 1854                         } else {
 1855                                 return;
 1856                         }
 1857                 }
 1858 
 1859                 for (i = 0; i < 4; ++i) {
 1860                         tssi[i] += 0x20;
 1861                         tssi[i] &= 0x3f;
 1862                 }
 1863                 ofdm_tssi = 1;
 1864         }
 1865         bwi_rf_clear_tssi(mac);
 1866 
 1867         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
 1868                 "tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n",
 1869                 tssi[0], tssi[1], tssi[2], tssi[3]);
 1870 
 1871         /*
 1872          * Calculate RF/BBP attenuation adjustment based on
 1873          * the difference between desired TX power and sampled
 1874          * TX power.
 1875          */
 1876         /* +8 == "each incremented by 1/2" */
 1877         tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4;
 1878         if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS))
 1879                 tssi_avg -= 13;
 1880 
 1881         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "tssi avg %d\n", tssi_avg);
 1882 
 1883         error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr);
 1884         if (error)
 1885                 return;
 1886         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "current txpower %d\n",
 1887                 cur_txpwr);
 1888 
 1889         txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */
 1890 
 1891         rf_atten_adj = -howmany(txpwr_diff, 8);
 1892         if (type == BWI_TXPWR_INIT) {
 1893                 /*
 1894                  * Move toward EEPROM max TX power as fast as we can
 1895                  */
 1896                 bbp_atten_adj = -txpwr_diff;
 1897         } else {
 1898                 bbp_atten_adj = -(txpwr_diff / 2);
 1899         }
 1900         bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
 1901 
 1902         if (rf_atten_adj == 0 && bbp_atten_adj == 0) {
 1903                 DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
 1904                         "no need to adjust RF/BBP attenuation");
 1905                 /* TODO: LO */
 1906                 return;
 1907         }
 1908 
 1909 calib:
 1910         DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
 1911                 "rf atten adjust %d, bbp atten adjust %d\n",
 1912                 rf_atten_adj, bbp_atten_adj);
 1913         bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj);
 1914         /* TODO: LO */
 1915 }
 1916 
 1917 static void
 1918 bwi_mac_lock(struct bwi_mac *mac)
 1919 {
 1920         struct bwi_softc *sc = mac->mac_sc;
 1921         struct ieee80211com *ic = &sc->sc_ic;
 1922 
 1923         KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0,
 1924             ("mac_flags 0x%x", mac->mac_flags));
 1925 
 1926         if (mac->mac_rev < 3)
 1927                 bwi_mac_stop(mac);
 1928         else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
 1929                 bwi_mac_config_ps(mac);
 1930 
 1931         CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
 1932 
 1933         /* Flush pending bus write */
 1934         CSR_READ_4(sc, BWI_MAC_STATUS);
 1935         DELAY(10);
 1936 
 1937         mac->mac_flags |= BWI_MAC_F_LOCKED;
 1938 }
 1939 
 1940 static void
 1941 bwi_mac_unlock(struct bwi_mac *mac)
 1942 {
 1943         struct bwi_softc *sc = mac->mac_sc;
 1944         struct ieee80211com *ic = &sc->sc_ic;
 1945 
 1946         KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED,
 1947             ("mac_flags 0x%x", mac->mac_flags));
 1948 
 1949         CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */
 1950 
 1951         CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
 1952 
 1953         if (mac->mac_rev < 3)
 1954                 bwi_mac_start(mac);
 1955         else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
 1956                 bwi_mac_config_ps(mac);
 1957 
 1958         mac->mac_flags &= ~BWI_MAC_F_LOCKED;
 1959 }
 1960 
 1961 void
 1962 bwi_mac_set_promisc(struct bwi_mac *mac, int promisc)
 1963 {
 1964         struct bwi_softc *sc = mac->mac_sc;
 1965 
 1966         if (mac->mac_rev < 5) /* Promisc is always on */
 1967                 return;
 1968 
 1969         if (promisc)
 1970                 CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
 1971         else
 1972                 CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
 1973 }

Cache object: 5bedc3fd85203fe6f47844fb51981cc2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.