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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/netif/acx/acx100.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) 2006 The DragonFly Project.  All rights reserved.
    3  * 
    4  * This code is derived from software contributed to The DragonFly Project
    5  * by Sepherosa Ziehau <sepherosa@gmail.com>
    6  * 
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in
   15  *    the documentation and/or other materials provided with the
   16  *    distribution.
   17  * 3. Neither the name of The DragonFly Project nor the names of its
   18  *    contributors may be used to endorse or promote products derived
   19  *    from this software without specific, prior written permission.
   20  * 
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/bus.h>
   37 #include <sys/endian.h>
   38 #include <sys/rman.h>
   39 #include <sys/socket.h>
   40 #include <sys/sysctl.h>
   41 
   42 #include <net/if.h>
   43 #include <net/if_arp.h>
   44 #include <net/if_media.h>
   45 
   46 #include <netproto/802_11/ieee80211_var.h>
   47 #include <netproto/802_11/ieee80211_radiotap.h>
   48 #include <netproto/802_11/wlan_ratectl/amrr/ieee80211_amrr_param.h>
   49 #include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
   50 
   51 #include <bus/pci/pcireg.h>
   52 
   53 #define ACX_DEBUG
   54 
   55 #include <dev/netif/acx/if_acxreg.h>
   56 #include <dev/netif/acx/if_acxvar.h>
   57 #include <dev/netif/acx/acxcmd.h>
   58 
   59 #define ACX100_CONF_FW_RING     0x0003
   60 #define ACX100_CONF_MEMOPT      0x0005
   61 
   62 #define ACX100_INTR_ENABLE      (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
   63 /*
   64  * XXX do we really care about following interrupts?
   65  *
   66  * ACXRV_INTR_INFO | ACXRV_INTR_SCAN_FINI
   67  */
   68 
   69 #define ACX100_INTR_DISABLE     (uint16_t)~(ACXRV_INTR_UNKN)
   70 
   71 #define ACX100_RATE(rate)       ((rate) * 5)
   72 
   73 #define ACX100_RSSI_CORR        8
   74 #define ACX100_TXPOWER          18
   75 #define ACX100_GPIO_POWER_LED   0x0800
   76 #define ACX100_EE_EADDR_OFS     0x1a
   77 
   78 #define ACX100_FW_TXRING_SIZE   (ACX_TX_DESC_CNT * sizeof(struct acx_fw_txdesc))
   79 #define ACX100_FW_RXRING_SIZE   (ACX_RX_DESC_CNT * sizeof(struct acx_fw_rxdesc))
   80 
   81 /*
   82  * NOTE:
   83  * Following structs' fields are little endian
   84  */
   85 
   86 struct acx100_bss_join {
   87         uint8_t dtim_intvl;
   88         uint8_t basic_rates;
   89         uint8_t op_rates;
   90 } __packed;
   91 
   92 struct acx100_conf_fw_ring {
   93         struct acx_conf confcom;
   94         uint32_t        fw_ring_size;   /* total size of fw (tx + rx) ring */
   95         uint32_t        fw_rxring_addr; /* start phyaddr of fw rx desc */
   96         uint8_t         opt;            /* see ACX100_RINGOPT_ */
   97         uint8_t         fw_txring_num;  /* num of TX ring */
   98         uint8_t         fw_rxdesc_num;  /* num of fw rx desc */
   99         uint8_t         reserved0;
  100         uint32_t        fw_ring_end[2]; /* see ACX100_SET_RING_END() */
  101         uint32_t        fw_txring_addr; /* start phyaddr of fw tx desc */
  102         uint8_t         fw_txring_prio; /* see ACX100_TXRING_PRIO_ */
  103         uint8_t         fw_txdesc_num;  /* num of fw tx desc */
  104         uint16_t        reserved1;
  105 } __packed;
  106 
  107 #define ACX100_RINGOPT_AUTO_RESET       0x1
  108 #define ACX100_TXRING_PRIO_DEFAULT      0
  109 #define ACX100_SET_RING_END(conf, end)                  \
  110 do {                                                    \
  111         (conf)->fw_ring_end[0] = htole32(end);          \
  112         (conf)->fw_ring_end[1] = htole32(end + 8);      \
  113 } while (0)
  114 
  115 struct acx100_conf_memblk_size {
  116         struct acx_conf confcom;
  117         uint16_t        memblk_size;    /* size of each mem block */
  118 } __packed;
  119 
  120 struct acx100_conf_mem {
  121         struct acx_conf confcom;
  122         uint32_t        opt;            /* see ACX100_MEMOPT_ */
  123         uint32_t        h_rxring_paddr; /* host rx desc start phyaddr */
  124 
  125         /*
  126          * Memory blocks are controled by hardware
  127          * once after they are initialized
  128          */
  129         uint32_t        rx_memblk_addr; /* start addr of rx mem blocks */
  130         uint32_t        tx_memblk_addr; /* start addr of tx mem blocks */
  131         uint16_t        rx_memblk_num;  /* num of RX mem block */
  132         uint16_t        tx_memblk_num;  /* num of TX mem block */
  133 } __packed;
  134 
  135 #define ACX100_MEMOPT_MEM_INSTR         0x00000000 /* memory access instruct */
  136 #define ACX100_MEMOPT_HOSTDESC          0x00010000 /* host indirect desc */
  137 #define ACX100_MEMOPT_MEMBLOCK          0x00020000 /* local mem block list */
  138 #define ACX100_MEMOPT_IO_INSTR          0x00040000 /* IO instruct */
  139 #define ACX100_MEMOPT_PCICONF           0x00080000 /* PCI conf space */
  140 
  141 #define ACX100_MEMBLK_ALIGN             0x20
  142 
  143 struct acx100_conf_cca_mode {
  144         struct acx_conf confcom;
  145         uint8_t         cca_mode;
  146         uint8_t         unknown;
  147 } __packed;
  148 
  149 struct acx100_conf_ed_thresh {
  150         struct acx_conf confcom;
  151         uint8_t         ed_thresh;
  152         uint8_t         unknown[3];
  153 } __packed;
  154 
  155 struct acx100_conf_wepkey {
  156         struct acx_conf confcom;
  157         uint8_t         action; /* see ACX100_WEPKEY_ACT_ */
  158         uint8_t         key_len;
  159         uint8_t         key_idx;
  160 #define ACX100_WEPKEY_LEN       29
  161         uint8_t         key[ACX100_WEPKEY_LEN];
  162 } __packed;
  163 
  164 #define ACX100_WEPKEY_ACT_ADD   1
  165 
  166 #define ACX100_CONF_FUNC(sg, name)      _ACX_CONF_FUNC(sg, name, 100)
  167 #define ACX_CONF_fw_ring                ACX100_CONF_FW_RING
  168 #define ACX_CONF_memblk_size            ACX_CONF_MEMBLK_SIZE
  169 #define ACX_CONF_mem                    ACX100_CONF_MEMOPT
  170 #define ACX_CONF_cca_mode               ACX_CONF_CCA_MODE
  171 #define ACX_CONF_ed_thresh              ACX_CONF_ED_THRESH
  172 #define ACX_CONF_wepkey                 ACX_CONF_WEPKEY
  173 ACX100_CONF_FUNC(set, fw_ring);
  174 ACX100_CONF_FUNC(set, memblk_size);
  175 ACX100_CONF_FUNC(set, mem);
  176 ACX100_CONF_FUNC(get, cca_mode);
  177 ACX100_CONF_FUNC(set, cca_mode);
  178 ACX100_CONF_FUNC(get, ed_thresh);
  179 ACX100_CONF_FUNC(set, ed_thresh);
  180 ACX100_CONF_FUNC(set, wepkey);
  181 
  182 #define ACXCMD_init_mem                 ACXCMD_INIT_MEM
  183 ACX_NOARG_FUNC(init_mem);
  184 
  185 static const uint16_t   acx100_reg[ACXREG_MAX] = {
  186         ACXREG(SOFT_RESET,              0x0000),
  187 
  188         ACXREG(FWMEM_ADDR,              0x0014),
  189         ACXREG(FWMEM_DATA,              0x0018),
  190         ACXREG(FWMEM_CTRL,              0x001c),
  191         ACXREG(FWMEM_START,             0x0020),
  192 
  193         ACXREG(EVENT_MASK,              0x0034),
  194 
  195         ACXREG(INTR_TRIG,               0x007c),
  196         ACXREG(INTR_MASK,               0x0098),
  197         ACXREG(INTR_STATUS,             0x00a4),
  198         ACXREG(INTR_STATUS_CLR,         0x00a8),
  199         ACXREG(INTR_ACK,                0x00ac),
  200 
  201         ACXREG(HINTR_TRIG,              0x00b0),
  202         ACXREG(RADIO_ENABLE,            0x0104),
  203 
  204         ACXREG(EEPROM_INIT,             0x02d0),
  205         ACXREG(EEPROM_CTRL,             0x0250),
  206         ACXREG(EEPROM_ADDR,             0x0254),
  207         ACXREG(EEPROM_DATA,             0x0258),
  208         ACXREG(EEPROM_CONF,             0x025c),
  209         ACXREG(EEPROM_INFO,             0x02ac),
  210 
  211         ACXREG(PHY_ADDR,                0x0268),
  212         ACXREG(PHY_DATA,                0x026c),
  213         ACXREG(PHY_CTRL,                0x0270),
  214 
  215         ACXREG(GPIO_OUT_ENABLE,         0x0290),
  216         ACXREG(GPIO_OUT,                0x0298),
  217 
  218         ACXREG(CMD_REG_OFFSET,          0x02a4),
  219         ACXREG(INFO_REG_OFFSET,         0x02a8),
  220 
  221         ACXREG(RESET_SENSE,             0x02d4),
  222         ACXREG(ECPU_CTRL,               0x02d8) 
  223 };
  224 
  225 static const uint8_t    acx100_txpower_maxim[21] = {
  226         63, 63, 63, 62,
  227         61, 61, 60, 60,
  228         59, 58, 57, 55,
  229         53, 50, 47, 43,
  230         38, 31, 23, 13,
  231         0
  232 };
  233 
  234 static const uint8_t    acx100_txpower_rfmd[21] = {
  235          0,  0,  0,  1,
  236          2,  2,  3,  3,
  237          4,  5,  6,  8,
  238         10, 13, 16, 20,
  239         25, 32, 41, 50,
  240         63
  241 };
  242 
  243 static const uint8_t    acx100_rate_map[45] = {
  244         [2]     = 0x01,
  245         [4]     = 0x02,
  246         [11]    = 0x04,
  247         [22]    = 0x08,
  248         [44]    = 0x10
  249 };
  250 
  251 static int      acx100_init(struct acx_softc *);
  252 static int      acx100_init_wep(struct acx_softc *);
  253 static int      acx100_init_tmplt(struct acx_softc *);
  254 static int      acx100_init_fw_ring(struct acx_softc *);
  255 static int      acx100_init_memory(struct acx_softc *);
  256 
  257 static void     acx100_init_fw_txring(struct acx_softc *, uint32_t);
  258 static void     acx100_init_fw_rxring(struct acx_softc *, uint32_t);
  259 
  260 static int      acx100_read_config(struct acx_softc *, struct acx_config *);
  261 static int      acx100_write_config(struct acx_softc *, struct acx_config *);
  262 
  263 static void     *acx100_ratectl_attach(struct ieee80211com *, u_int);
  264 
  265 static int      acx100_set_txpower(struct acx_softc *);
  266 
  267 static uint8_t  acx100_set_fw_txdesc_rate(struct acx_softc *,
  268                                           struct acx_txbuf *,
  269                                           struct ieee80211_node *, int);
  270 static void     acx100_tx_complete(struct acx_softc *, struct acx_txbuf *,
  271                                    int, int);
  272 static void     acx100_set_bss_join_param(struct acx_softc *, void *, int);
  273 
  274 static int      acx100_set_wepkey(struct acx_softc *, struct ieee80211_key *,
  275                                   int);
  276 
  277 static void     acx100_proc_wep_rxbuf(struct acx_softc *, struct mbuf *, int *);
  278 
  279 #define ACX100_CHK_RATE(ifp, rate, rate_idx)    \
  280         acx100_check_rate(ifp, rate, rate_idx, __func__)
  281 
  282 static __inline int
  283 acx100_check_rate(struct ifnet *ifp, u_int rate, int rate_idx,
  284                   const char *fname)
  285 {
  286         if (rate >= NELEM(acx100_rate_map)) {
  287                 if_printf(ifp, "%s rate out of range %u (idx %d)\n",
  288                           fname, rate, rate_idx);
  289                 return -1;
  290         }
  291 
  292         if (acx100_rate_map[rate] == 0) {
  293                 if_printf(ifp, "%s invalid rate %u (idx %d)\n",
  294                           fname, rate, rate_idx);
  295                 return -1;
  296         }
  297         return 0;
  298 }
  299 
  300 void
  301 acx100_set_param(device_t dev)
  302 {
  303         struct acx_softc *sc = device_get_softc(dev);
  304         struct ieee80211com *ic = &sc->sc_ic;
  305         struct acx_firmware *fw = &sc->sc_firmware;
  306 
  307         sc->chip_mem1_rid = PCIR_BAR(1);
  308         sc->chip_mem2_rid = PCIR_BAR(2);
  309         sc->chip_ioreg = acx100_reg;
  310         sc->chip_hw_crypt = 1;
  311         sc->chip_intr_enable = ACX100_INTR_ENABLE;
  312         sc->chip_intr_disable = ACX100_INTR_DISABLE;
  313         sc->chip_gpio_pled = ACX100_GPIO_POWER_LED;
  314         sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS;
  315         sc->chip_txdesc1_len = ACX_FRAME_HDRLEN;
  316         sc->chip_fw_txdesc_ctrl = DESC_CTRL_AUTODMA |
  317                                   DESC_CTRL_RECLAIM |
  318                                   DESC_CTRL_FIRST_FRAG;
  319         sc->chip_short_retry_limit = 7;
  320         sc->chip_rssi_corr = ACX100_RSSI_CORR;
  321 
  322         sc->chip_phymode = IEEE80211_MODE_11B;
  323         sc->chip_chan_flags = IEEE80211_CHAN_B;
  324 
  325         ic->ic_phytype = IEEE80211_T_DS;
  326         if (acx_enable_pbcc)
  327                 ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b_pbcc;
  328         else
  329                 ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b;
  330 
  331         IEEE80211_ONOE_PARAM_SETUP(&sc->sc_onoe_param);
  332 
  333         ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE;
  334         ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE;
  335         ic->ic_ratectl.rc_st_attach = acx100_ratectl_attach;
  336 
  337         sc->chip_init = acx100_init;
  338         sc->chip_set_wepkey = acx100_set_wepkey;
  339         sc->chip_read_config = acx100_read_config;
  340         sc->chip_write_config = acx100_write_config;
  341         sc->chip_set_fw_txdesc_rate = acx100_set_fw_txdesc_rate;
  342         sc->chip_tx_complete = acx100_tx_complete;
  343         sc->chip_set_bss_join_param = acx100_set_bss_join_param;
  344         sc->chip_proc_wep_rxbuf = acx100_proc_wep_rxbuf;
  345 
  346         fw->combined_radio_fw = 0;
  347         fw->fwdir = "100";
  348 }
  349 
  350 static int
  351 acx100_init(struct acx_softc *sc)
  352 {
  353         /*
  354          * NOTE:
  355          * Order of initialization:
  356          * 1) WEP
  357          * 2) Templates
  358          * 3) Firmware TX/RX ring
  359          * 4) Hardware memory
  360          * Above order is critical to get a correct memory map
  361          */
  362 
  363         if (acx100_init_wep(sc) != 0) {
  364                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize wep\n",
  365                           __func__);
  366                 return ENXIO;
  367         }
  368 
  369         if (acx100_init_tmplt(sc) != 0) {
  370                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize templates\n",
  371                           __func__);
  372                 return ENXIO;
  373         }
  374 
  375         if (acx100_init_fw_ring(sc) != 0) {
  376                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize fw ring\n",
  377                           __func__);
  378                 return ENXIO;
  379         }
  380 
  381         if (acx100_init_memory(sc) != 0) {
  382                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize hw memory\n",
  383                           __func__);
  384                 return ENXIO;
  385         }
  386         return 0;
  387 }
  388 
  389 static int
  390 acx100_init_wep(struct acx_softc *sc)
  391 {
  392         struct acx_conf_wepopt wep_opt;
  393         struct acx_conf_mmap mem_map;
  394 
  395         /* Set WEP cache start/end address */
  396         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
  397                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
  398                 return 1;
  399         }
  400 
  401         mem_map.wep_cache_start = htole32(le32toh(mem_map.code_end) + 4);
  402         mem_map.wep_cache_end = htole32(le32toh(mem_map.code_end) + 4);
  403         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
  404                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
  405                 return 1;
  406         }
  407 
  408         /* Set WEP options */
  409         wep_opt.nkey = htole16(IEEE80211_WEP_NKID + 10);
  410         wep_opt.opt = WEPOPT_HDWEP;
  411         if (acx_set_wepopt_conf(sc, &wep_opt) != 0) {
  412                 if_printf(&sc->sc_ic.ic_if, "can't set wep opt\n");
  413                 return 1;
  414         }
  415         return 0;
  416 }
  417 
  418 static int
  419 acx100_init_tmplt(struct acx_softc *sc)
  420 {
  421         struct acx_conf_mmap mem_map;
  422 
  423         /* Set templates start address */
  424         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
  425                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
  426                 return 1;
  427         }
  428 
  429         mem_map.pkt_tmplt_start = mem_map.wep_cache_end;
  430         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
  431                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
  432                 return 1;
  433         }
  434 
  435         /* Initialize various packet templates */
  436         if (acx_init_tmplt_ordered(sc) != 0) {
  437                 if_printf(&sc->sc_ic.ic_if, "can't init tmplt\n");
  438                 return 1;
  439         }
  440         return 0;
  441 }
  442 
  443 static int
  444 acx100_init_fw_ring(struct acx_softc *sc)
  445 {
  446         struct acx100_conf_fw_ring ring;
  447         struct acx_conf_mmap mem_map;
  448         uint32_t txring_start, rxring_start, ring_end;
  449 
  450         /* Set firmware descriptor ring start address */
  451         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
  452                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
  453                 return 1;
  454         }
  455 
  456         txring_start = le32toh(mem_map.pkt_tmplt_end) + 4;
  457         rxring_start = txring_start + ACX100_FW_TXRING_SIZE;
  458         ring_end = rxring_start + ACX100_FW_RXRING_SIZE;
  459 
  460         mem_map.fw_desc_start = htole32(txring_start);
  461         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
  462                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
  463                 return 1;
  464         }
  465 
  466         /* Set firmware descriptor ring configure */
  467         bzero(&ring, sizeof(ring));
  468         ring.fw_ring_size = htole32(ACX100_FW_TXRING_SIZE +
  469                                     ACX100_FW_RXRING_SIZE + 8);
  470 
  471         ring.fw_txring_num = 1;
  472         ring.fw_txring_addr = htole32(txring_start);
  473         ring.fw_txring_prio = ACX100_TXRING_PRIO_DEFAULT;
  474         ring.fw_txdesc_num = 0; /* XXX ignored?? */
  475 
  476         ring.fw_rxring_addr = htole32(rxring_start);
  477         ring.fw_rxdesc_num = 0; /* XXX ignored?? */
  478 
  479         ring.opt = ACX100_RINGOPT_AUTO_RESET;
  480         ACX100_SET_RING_END(&ring, ring_end);
  481         if (acx100_set_fw_ring_conf(sc, &ring) != 0) {
  482                 if_printf(&sc->sc_ic.ic_if, "can't set fw ring configure\n");
  483                 return 1;
  484         }
  485 
  486         /* Setup firmware TX/RX descriptor ring */
  487         acx100_init_fw_txring(sc, txring_start);
  488         acx100_init_fw_rxring(sc, rxring_start);
  489 
  490         return 0;
  491 }
  492 
  493 #define MEMBLK_ALIGN(addr)      \
  494         (((addr) + (ACX100_MEMBLK_ALIGN - 1)) & ~(ACX100_MEMBLK_ALIGN - 1))
  495 
  496 static int
  497 acx100_init_memory(struct acx_softc *sc)
  498 {
  499         struct acx100_conf_memblk_size memblk_sz;
  500         struct acx100_conf_mem mem;
  501         struct acx_conf_mmap mem_map;
  502         uint32_t memblk_start, memblk_end;
  503         int total_memblk, txblk_num, rxblk_num;
  504 
  505         /* Set memory block start address */
  506         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
  507                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
  508                 return 1;
  509         }
  510 
  511         mem_map.memblk_start =
  512                 htole32(MEMBLK_ALIGN(le32toh(mem_map.fw_desc_end) + 4));
  513 
  514         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
  515                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
  516                 return 1;
  517         }
  518 
  519         /* Set memory block size */
  520         memblk_sz.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
  521         if (acx100_set_memblk_size_conf(sc, &memblk_sz) != 0) {
  522                 if_printf(&sc->sc_ic.ic_if, "can't set mem block size\n");
  523                 return 1;
  524         }
  525 
  526         /* Get memory map after setting it */
  527         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
  528                 if_printf(&sc->sc_ic.ic_if, "can't get mmap again\n");
  529                 return 1;
  530         }
  531         memblk_start = le32toh(mem_map.memblk_start);
  532         memblk_end = le32toh(mem_map.memblk_end);
  533 
  534         /* Set memory options */
  535         mem.opt = htole32(ACX100_MEMOPT_MEMBLOCK | ACX100_MEMOPT_HOSTDESC);
  536         mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
  537 
  538         total_memblk = (memblk_end - memblk_start) / ACX_MEMBLOCK_SIZE;
  539 
  540         rxblk_num = total_memblk / 2;           /* 50% */
  541         txblk_num = total_memblk - rxblk_num;   /* 50% */
  542 
  543         DPRINTF((&sc->sc_ic.ic_if, "\ttotal memory blocks\t%d\n"
  544                                    "\trx memory blocks\t%d\n"
  545                                    "\ttx memory blocks\t%d\n",
  546                                    total_memblk, rxblk_num, txblk_num));
  547 
  548         mem.rx_memblk_num = htole16(rxblk_num);
  549         mem.tx_memblk_num = htole16(txblk_num);
  550 
  551         mem.rx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start));
  552         mem.tx_memblk_addr =
  553                 htole32(MEMBLK_ALIGN(memblk_start +
  554                                      (ACX_MEMBLOCK_SIZE * rxblk_num)));
  555 
  556         if (acx100_set_mem_conf(sc, &mem) != 0) {
  557                 if_printf(&sc->sc_ic.ic_if, "can't set mem options\n");
  558                 return 1;
  559         }
  560 
  561         /* Initialize memory */
  562         if (acx_init_mem(sc) != 0) {
  563                 if_printf(&sc->sc_ic.ic_if, "can't init mem\n");
  564                 return 1;
  565         }
  566         return 0;
  567 }
  568 
  569 #undef MEMBLK_ALIGN
  570 
  571 static void
  572 acx100_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
  573 {
  574         struct acx_fw_txdesc fw_desc;
  575         struct acx_txbuf *tx_buf;
  576         uint32_t desc_paddr, fw_desc_offset;
  577         int i;
  578 
  579         bzero(&fw_desc, sizeof(fw_desc));
  580         fw_desc.f_tx_ctrl = DESC_CTRL_HOSTOWN |
  581                             DESC_CTRL_RECLAIM |
  582                             DESC_CTRL_AUTODMA |
  583                             DESC_CTRL_FIRST_FRAG;
  584 
  585         tx_buf = sc->sc_buf_data.tx_buf;
  586         fw_desc_offset = fw_txdesc_start;
  587         desc_paddr = sc->sc_ring_data.tx_ring_paddr;
  588 
  589         for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
  590                 fw_desc.f_tx_host_desc = htole32(desc_paddr);
  591 
  592                 if (i == ACX_TX_DESC_CNT - 1) {
  593                         fw_desc.f_tx_next_desc = htole32(fw_txdesc_start);
  594                 } else {
  595                         fw_desc.f_tx_next_desc =
  596                                 htole32(fw_desc_offset +
  597                                         sizeof(struct acx_fw_txdesc));
  598                 }
  599 
  600                 tx_buf[i].tb_fwdesc_ofs = fw_desc_offset;
  601                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
  602                                     sizeof(fw_desc));
  603 
  604                 desc_paddr += (2 * sizeof(struct acx_host_desc));
  605                 fw_desc_offset += sizeof(fw_desc);
  606         }
  607 }
  608 
  609 static void
  610 acx100_init_fw_rxring(struct acx_softc *sc, uint32_t fw_rxdesc_start)
  611 {
  612         struct acx_fw_rxdesc fw_desc;
  613         uint32_t fw_desc_offset;
  614         int i;
  615 
  616         bzero(&fw_desc, sizeof(fw_desc));
  617         fw_desc.f_rx_ctrl = DESC_CTRL_RECLAIM | DESC_CTRL_AUTODMA;
  618 
  619         fw_desc_offset = fw_rxdesc_start;
  620 
  621         for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
  622                 if (i == ACX_RX_DESC_CNT - 1) {
  623                         fw_desc.f_rx_next_desc = htole32(fw_rxdesc_start);
  624                 } else {
  625                         fw_desc.f_rx_next_desc =
  626                                 htole32(fw_desc_offset +
  627                                         sizeof(struct acx_fw_rxdesc));
  628                 }
  629 
  630                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
  631                                     sizeof(fw_desc));
  632 
  633                 fw_desc_offset += sizeof(fw_desc);
  634         }
  635 }
  636 
  637 static int
  638 acx100_read_config(struct acx_softc *sc, struct acx_config *conf)
  639 {
  640         struct acx100_conf_cca_mode cca;
  641         struct acx100_conf_ed_thresh ed;
  642 
  643         /*
  644          * NOTE:
  645          * CCA mode and ED threshold MUST be read during initialization
  646          * or the acx100 card won't work as expected
  647          */
  648 
  649         /* Get CCA mode */
  650         if (acx100_get_cca_mode_conf(sc, &cca) != 0) {
  651                 if_printf(&sc->sc_ic.ic_if, "%s can't get cca mode\n",
  652                           __func__);
  653                 return ENXIO;
  654         }
  655         conf->cca_mode = cca.cca_mode;
  656         DPRINTF((&sc->sc_ic.ic_if, "cca mode %02x\n", cca.cca_mode));
  657 
  658         /* Get ED threshold */
  659         if (acx100_get_ed_thresh_conf(sc, &ed) != 0) {
  660                 if_printf(&sc->sc_ic.ic_if, "%s can't get ed threshold\n",
  661                           __func__);
  662                 return ENXIO;
  663         }
  664         conf->ed_thresh = ed.ed_thresh;
  665         DPRINTF((&sc->sc_ic.ic_if, "ed threshold %02x\n", ed.ed_thresh));
  666 
  667         return 0;
  668 }
  669 
  670 static int
  671 acx100_write_config(struct acx_softc *sc, struct acx_config *conf)
  672 {
  673         struct acx100_conf_cca_mode cca;
  674         struct acx100_conf_ed_thresh ed;
  675 
  676         /* Set CCA mode */
  677         cca.cca_mode = conf->cca_mode;
  678         if (acx100_set_cca_mode_conf(sc, &cca) != 0) {
  679                 if_printf(&sc->sc_ic.ic_if, "%s can't set cca mode\n",
  680                           __func__);
  681                 return ENXIO;
  682         }
  683 
  684         /* Set ED threshold */
  685         ed.ed_thresh = conf->ed_thresh;
  686         if (acx100_set_ed_thresh_conf(sc, &ed) != 0) {
  687                 if_printf(&sc->sc_ic.ic_if, "%s can't set ed threshold\n",
  688                           __func__);
  689                 return ENXIO;
  690         }
  691 
  692         /* Set TX power */
  693         acx100_set_txpower(sc); /* ignore return value */
  694 
  695         return 0;
  696 }
  697 
  698 static int
  699 acx100_set_txpower(struct acx_softc *sc)
  700 {
  701         const uint8_t *map;
  702 
  703         switch (sc->sc_radio_type) {
  704         case ACX_RADIO_TYPE_MAXIM:
  705                 map = acx100_txpower_maxim;
  706                 break;
  707         case ACX_RADIO_TYPE_RFMD:
  708         case ACX_RADIO_TYPE_RALINK:
  709                 map = acx100_txpower_rfmd;
  710                 break;
  711         default:
  712                 if_printf(&sc->sc_ic.ic_if, "TX power for radio type 0x%02x "
  713                           "can't be set yet\n", sc->sc_radio_type);
  714                 return 1;
  715         }
  716 
  717         acx_write_phyreg(sc, ACXRV_PHYREG_TXPOWER, map[ACX100_TXPOWER]);
  718         return 0;
  719 }
  720 
  721 static uint8_t
  722 acx100_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
  723                           struct ieee80211_node *ni, int data_len)
  724 {
  725         int rate;
  726 
  727         tx_buf->tb_rateidx_len = 1;
  728         if (ni == NULL) {
  729                 rate = 2;       /* 1Mbit/s */
  730                 tx_buf->tb_rateidx[0] = 0;
  731         } else {
  732                 ieee80211_ratectl_findrate(ni, data_len,
  733                                            tx_buf->tb_rateidx, 1);
  734                 rate = IEEE80211_RS_RATE(&ni->ni_rates,
  735                                          tx_buf->tb_rateidx[0]);
  736                 if (ACX100_CHK_RATE(&sc->sc_ic.ic_if, rate,
  737                                     tx_buf->tb_rateidx[0]) < 0)
  738                         rate = 2;
  739         }
  740         FW_TXDESC_SETFIELD_1(sc, tx_buf, f_tx_rate100, ACX100_RATE(rate));
  741 
  742         return rate;
  743 }
  744 
  745 static void
  746 acx100_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
  747 {
  748         struct acx100_bss_join *bj = param;
  749         struct ifnet *ifp = &sc->sc_ic.ic_if;
  750         const struct ieee80211_rateset *rs = &sc->sc_ic.ic_bss->ni_rates;
  751         int i;
  752 
  753         bj->basic_rates = 0;
  754         bj->op_rates = 0;
  755         for (i = 0; i < rs->rs_nrates; ++i) {
  756                 u_int map_idx = IEEE80211_RS_RATE(rs, i);
  757                 uint8_t rate;
  758 
  759                 if (ACX100_CHK_RATE(ifp, map_idx, i) < 0)
  760                         continue;
  761 
  762                 rate = acx100_rate_map[map_idx];
  763                 if (rs->rs_rates[i] & IEEE80211_RATE_BASIC)
  764                         bj->basic_rates |= rate;
  765                 bj->op_rates |= rate;
  766         }
  767         DPRINTF((ifp, "basic rates:0x%02x, op rates:0x%02x\n",
  768                  bj->basic_rates, bj->op_rates));
  769 
  770         bj->dtim_intvl = dtim_intvl;
  771 }
  772 
  773 static int
  774 acx100_set_wepkey(struct acx_softc *sc, struct ieee80211_key *wk, int wk_idx)
  775 {
  776         struct acx100_conf_wepkey conf_wk;
  777 
  778         if (wk->wk_keylen > ACX100_WEPKEY_LEN) {
  779                 if_printf(&sc->sc_ic.ic_if, "%dth WEP key size beyond %d\n",
  780                           wk_idx, ACX100_WEPKEY_LEN);
  781                 return EINVAL;
  782         }
  783 
  784         conf_wk.action = ACX100_WEPKEY_ACT_ADD;
  785         conf_wk.key_len = wk->wk_keylen;
  786         conf_wk.key_idx = wk_idx;
  787         bcopy(wk->wk_key, conf_wk.key, wk->wk_keylen);
  788         if (acx100_set_wepkey_conf(sc, &conf_wk) != 0) {
  789                 if_printf(&sc->sc_ic.ic_if, "%s set %dth WEP key failed\n",
  790                           __func__, wk_idx);
  791                 return ENXIO;
  792         }
  793         return 0;
  794 }
  795 
  796 static void
  797 acx100_proc_wep_rxbuf(struct acx_softc *sc, struct mbuf *m, int *len)
  798 {
  799         int mac_hdrlen;
  800         struct ieee80211_frame *f;
  801 
  802         /*
  803          * Strip leading IV and KID, and trailing CRC
  804          */
  805 
  806         f = mtod(m, struct ieee80211_frame *);
  807 
  808         if ((f->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
  809                 mac_hdrlen = sizeof(struct ieee80211_frame_addr4);
  810         else
  811                 mac_hdrlen = sizeof(struct ieee80211_frame);
  812 
  813 #define IEEEWEP_IVLEN   (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
  814 #define IEEEWEP_EXLEN   (IEEEWEP_IVLEN + IEEE80211_WEP_CRCLEN)
  815 
  816         *len = *len - IEEEWEP_EXLEN;
  817 
  818         /* Move MAC header toward frame body */
  819         ovbcopy(f, (uint8_t *)f + IEEEWEP_IVLEN, mac_hdrlen);
  820         m_adj(m, IEEEWEP_IVLEN);
  821 
  822 #undef IEEEWEP_EXLEN
  823 #undef IEEEWEP_IVLEN
  824 }
  825 
  826 static void
  827 acx100_tx_complete(struct acx_softc *sc, struct acx_txbuf *tx_buf,
  828                    int frame_len, int is_fail)
  829 {
  830         int rts_retries, data_retries;
  831         struct ieee80211_ratectl_res rc_res;
  832 
  833         rts_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_rts_nretry);
  834         data_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_data_nretry);
  835 
  836         rc_res.rc_res_rateidx = tx_buf->tb_rateidx[0];
  837         rc_res.rc_res_tries = data_retries + 1;
  838 
  839         ieee80211_ratectl_tx_complete(tx_buf->tb_node, frame_len,
  840                                       &rc_res, 1, data_retries, rts_retries,
  841                                       is_fail);
  842 }
  843 
  844 static void *
  845 acx100_ratectl_attach(struct ieee80211com *ic, u_int rc)
  846 {
  847         struct acx_softc *sc = ic->ic_if.if_softc;
  848 
  849         switch (rc) {
  850         case IEEE80211_RATECTL_ONOE:
  851                 return &sc->sc_onoe_param;
  852         case IEEE80211_RATECTL_NONE:
  853                 /* This could only happen during detaching */
  854                 return NULL;
  855         default:
  856                 panic("unknown rate control algo %u", rc);
  857                 return NULL;
  858         }
  859 }

Cache object: b6ee80247514a3af6cb12c4670dc4408


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