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

Cache object: da6a64d5ffccaf16c4c5f5ffb6d820c8


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