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

Cache object: aaf0861215636b3a41b6a22fe04a6015


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