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

Cache object: 7bdea38888d436b71b456e5f3d8ebd68


[ 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.