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/ic/acx111.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 /*      $OpenBSD: acx111.c,v 1.24 2022/01/09 05:42:38 jsg Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
   21  *
   22  * This code is derived from software contributed to The DragonFly Project
   23  * by Sepherosa Ziehau <sepherosa@gmail.com>
   24  *
   25  * Redistribution and use in source and binary forms, with or without
   26  * modification, are permitted provided that the following conditions
   27  * are met:
   28  *
   29  * 1. Redistributions of source code must retain the above copyright
   30  *    notice, this list of conditions and the following disclaimer.
   31  * 2. Redistributions in binary form must reproduce the above copyright
   32  *    notice, this list of conditions and the following disclaimer in
   33  *    the documentation and/or other materials provided with the
   34  *    distribution.
   35  * 3. Neither the name of The DragonFly Project nor the names of its
   36  *    contributors may be used to endorse or promote products derived
   37  *    from this software without specific, prior written permission.
   38  *
   39  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   40  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   41  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   42  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   43  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   44  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   45  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   47  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   50  * SUCH DAMAGE.
   51  */
   52 
   53 #include "bpfilter.h"
   54 
   55 #include <sys/param.h>
   56 #include <sys/endian.h>
   57 #include <sys/socket.h>
   58 #include <sys/systm.h>
   59 #include <sys/device.h>
   60 
   61 #include <machine/bus.h>
   62 
   63 #include <net/if.h>
   64 #include <net/if_media.h>
   65 
   66 #include <netinet/in.h>
   67 #include <netinet/if_ether.h>
   68 
   69 #include <net80211/ieee80211_var.h>
   70 #include <net80211/ieee80211_amrr.h>
   71 #include <net80211/ieee80211_radiotap.h>
   72 
   73 #include <dev/pci/pcireg.h>
   74 
   75 #include <dev/ic/acxvar.h>
   76 #include <dev/ic/acxreg.h>
   77 
   78 #define ACX111_CONF_MEM         0x0003
   79 #define ACX111_CONF_MEMINFO     0x0005
   80 
   81 #define ACX111_INTR_ENABLE      (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
   82 /*
   83  * XXX do we really care about fowlling interrupts?
   84  *
   85  * ACXRV_INTR_IV_ICV_FAILURE | ACXRV_INTR_INFO |
   86  * ACXRV_INTR_SCAN_FINI | ACXRV_INTR_FCS_THRESHOLD
   87  */
   88 
   89 #define ACX111_INTR_DISABLE     (uint16_t)~(ACXRV_INTR_CMD_FINI)
   90 
   91 #define ACX111_RATE_2           0x0001
   92 #define ACX111_RATE_4           0x0002
   93 #define ACX111_RATE_11          0x0004
   94 #define ACX111_RATE_12          0x0008
   95 #define ACX111_RATE_18          0x0010
   96 #define ACX111_RATE_22          0x0020
   97 #define ACX111_RATE_24          0x0040
   98 #define ACX111_RATE_36          0x0080
   99 #define ACX111_RATE_44          0x0100
  100 #define ACX111_RATE_48          0x0200
  101 #define ACX111_RATE_72          0x0400
  102 #define ACX111_RATE_96          0x0800
  103 #define ACX111_RATE_108         0x1000
  104 
  105 /* XXX skip ACX111_RATE_44 */
  106 #define ACX111_RATE_ALL         0x1eff
  107 
  108 #define ACX111_TXPOWER          15
  109 #define ACX111_GPIO_POWER_LED   0x0040
  110 #define ACX111_EE_EADDR_OFS     0x21
  111 
  112 #define ACX111_FW_TXDESC_SIZE   (sizeof(struct acx_fw_txdesc) + 4)
  113 
  114 #if ACX111_TXPOWER <= 12
  115 #define ACX111_TXPOWER_VAL      1
  116 #else
  117 #define ACX111_TXPOWER_VAL      2
  118 #endif
  119 
  120 int     acx111_init(struct acx_softc *);
  121 int     acx111_init_memory(struct acx_softc *);
  122 void    acx111_init_fw_txring(struct acx_softc *, uint32_t);
  123 int     acx111_write_config(struct acx_softc *, struct acx_config *);
  124 void    acx111_set_fw_txdesc_rate(struct acx_softc *,
  125             struct acx_txbuf *, int);
  126 void    acx111_set_bss_join_param(struct acx_softc *, void *, int);
  127 
  128 /*
  129  * NOTE:
  130  * Following structs' fields are little endian
  131  */
  132 struct acx111_bss_join {
  133         uint16_t        basic_rates;
  134         uint8_t         dtim_intvl;
  135 } __packed;
  136 
  137 struct acx111_conf_mem {
  138         struct acx_conf confcom;
  139 
  140         uint16_t        sta_max;        /* max num of sta, ACX111_STA_MAX */
  141         uint16_t        memblk_size;    /* mem block size */
  142         uint8_t         rx_memblk_perc; /* percent of RX mem block, unit: 5% */
  143         uint8_t         fw_rxring_num;  /* num of RX ring */
  144         uint8_t         fw_txring_num;  /* num of TX ring */
  145         uint8_t         opt;            /* see ACX111_MEMOPT_ */
  146         uint8_t         xfer_perc;      /* frag/xfer proportion, unit: 5% */
  147         uint16_t        reserved0;
  148         uint8_t         reserved1;
  149 
  150         uint8_t         fw_rxdesc_num;  /* num of fw rx desc */
  151         uint8_t         fw_rxring_reserved1;
  152         uint8_t         fw_rxring_type; /* see ACX111_RXRING_TYPE_ */
  153         uint8_t         fw_rxring_prio; /* see ACX111_RXRING_PRIO_ */
  154 
  155         uint32_t        h_rxring_paddr; /* host rx desc start phyaddr */
  156 
  157         uint8_t         fw_txdesc_num;  /* num of fw tx desc */
  158         uint8_t         fw_txring_reserved1;
  159         uint8_t         fw_txring_reserved2;
  160         uint8_t         fw_txring_attr; /* see ACX111_TXRING_ATTR_ */
  161 } __packed;
  162 
  163 #define ACX111_STA_MAX                  32
  164 #define ACX111_RX_MEMBLK_PERCENT        10      /* 50% */
  165 #define ACX111_XFER_PERCENT             15      /* 75% */
  166 #define ACX111_RXRING_TYPE_DEFAULT      7
  167 #define ACX111_RXRING_PRIO_DEFAULT      0
  168 #define ACX111_TXRING_ATTR_DEFAULT      0
  169 #define ACX111_MEMOPT_DEFAULT           0
  170 
  171 struct acx111_conf_meminfo {
  172         struct acx_conf confcom;
  173         uint32_t        tx_memblk_addr; /* start addr of tx mem blocks */
  174         uint32_t        rx_memblk_addr; /* start addr of rx mem blocks */
  175         uint32_t        fw_rxring_start; /* start phyaddr of fw rx ring */
  176         uint32_t        reserved0;
  177         uint32_t        fw_txring_start; /* start phyaddr of fw tx ring */
  178         uint8_t         fw_txring_attr; /* XXX see ACX111_TXRING_ATTR_ */
  179         uint16_t        reserved1;
  180         uint8_t         reserved2;
  181 } __packed;
  182 
  183 struct acx111_conf_txpower {
  184         struct acx_conf confcom;
  185         uint8_t         txpower;
  186 } __packed;
  187 
  188 struct acx111_conf_option {
  189         struct acx_conf confcom;
  190         uint32_t        feature;
  191         uint32_t        dataflow;       /* see ACX111_DF_ */
  192 } __packed;
  193 
  194 #define ACX111_DF_NO_RXDECRYPT  0x00000080
  195 #define ACX111_DF_NO_TXENCRYPT  0x00000001
  196 
  197 struct acx111_wepkey {
  198         uint8_t         mac_addr[IEEE80211_ADDR_LEN];
  199         uint16_t        action;         /* see ACX111_WEPKEY_ACT_ */
  200         uint16_t        reserved;
  201         uint8_t         key_len;
  202         uint8_t         key_type;       /* see ACX111_WEPKEY_TYPE_ */
  203         uint8_t         index;          /* XXX ?? */
  204         uint8_t         key_idx;
  205         uint8_t         counter[6];
  206 #define ACX111_WEPKEY_LEN       32
  207         uint8_t         key[ACX111_WEPKEY_LEN];
  208 } __packed;
  209 
  210 #define ACX111_WEPKEY_ACT_ADD           1
  211 #define ACX111_WEPKEY_TYPE_DEFAULT      0
  212 
  213 static const uint16_t acx111_reg[ACXREG_MAX] = {
  214         ACXREG(SOFT_RESET,              0x0000),
  215 
  216         ACXREG(FWMEM_ADDR,              0x0014),
  217         ACXREG(FWMEM_DATA,              0x0018),
  218         ACXREG(FWMEM_CTRL,              0x001c),
  219         ACXREG(FWMEM_START,             0x0020),
  220 
  221         ACXREG(EVENT_MASK,              0x0034),
  222 
  223         ACXREG(INTR_TRIG,               0x00b4),
  224         ACXREG(INTR_MASK,               0x00d4),
  225         ACXREG(INTR_STATUS,             0x00f0),
  226         ACXREG(INTR_STATUS_CLR,         0x00e4),
  227         ACXREG(INTR_ACK,                0x00e8),
  228 
  229         ACXREG(HINTR_TRIG,              0x00ec),
  230         ACXREG(RADIO_ENABLE,            0x01d0),
  231 
  232         ACXREG(EEPROM_INIT,             0x0100),
  233         ACXREG(EEPROM_CTRL,             0x0338),
  234         ACXREG(EEPROM_ADDR,             0x033c),
  235         ACXREG(EEPROM_DATA,             0x0340),
  236         ACXREG(EEPROM_CONF,             0x0344),
  237         ACXREG(EEPROM_INFO,             0x0390),
  238 
  239         ACXREG(PHY_ADDR,                0x0350),
  240         ACXREG(PHY_DATA,                0x0354),
  241         ACXREG(PHY_CTRL,                0x0358),
  242 
  243         ACXREG(GPIO_OUT_ENABLE,         0x0374),
  244         ACXREG(GPIO_OUT,                0x037c),
  245 
  246         ACXREG(CMD_REG_OFFSET,          0x0388),
  247         ACXREG(INFO_REG_OFFSET,         0x038c),
  248 
  249         ACXREG(RESET_SENSE,             0x0104),
  250         ACXREG(ECPU_CTRL,               0x0108)
  251 };
  252 
  253 /* XXX */
  254 static uint16_t acx111_rate_map[109] = {
  255         ACX111_RATE_2,
  256         ACX111_RATE_4,
  257         ACX111_RATE_11,
  258         ACX111_RATE_22,
  259         ACX111_RATE_12,
  260         ACX111_RATE_18,
  261         ACX111_RATE_24,
  262         ACX111_RATE_36,
  263         ACX111_RATE_48,
  264         ACX111_RATE_72,
  265         ACX111_RATE_96,
  266         ACX111_RATE_108
  267 };
  268 
  269 void
  270 acx111_set_param(struct acx_softc *sc)
  271 {
  272         sc->chip_mem1_rid = PCIR_BAR(0);
  273         sc->chip_mem2_rid = PCIR_BAR(1);
  274         sc->chip_ioreg = acx111_reg;
  275         sc->chip_intr_enable = ACX111_INTR_ENABLE;
  276 #ifndef IEEE80211_STA_ONLY
  277         sc->chip_intr_enable |= ACXRV_INTR_DTIM;
  278 #endif
  279         sc->chip_intr_disable = ACX111_INTR_DISABLE;
  280         sc->chip_gpio_pled = ACX111_GPIO_POWER_LED;
  281         sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS;
  282 
  283         sc->chip_phymode = IEEE80211_MODE_11G;
  284         sc->chip_chan_flags = IEEE80211_CHAN_CCK |
  285             IEEE80211_CHAN_OFDM |
  286             IEEE80211_CHAN_DYN |
  287             IEEE80211_CHAN_2GHZ;
  288         sc->sc_ic.ic_caps = IEEE80211_C_WEP | IEEE80211_C_SHSLOT;
  289         sc->sc_ic.ic_phytype = IEEE80211_T_OFDM;
  290         sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
  291         sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
  292 
  293         sc->chip_init = acx111_init;
  294         sc->chip_write_config = acx111_write_config;
  295         sc->chip_set_fw_txdesc_rate = acx111_set_fw_txdesc_rate;
  296         sc->chip_set_bss_join_param = acx111_set_bss_join_param;
  297         sc->sc_flags |= ACX_FLAG_ACX111;
  298 }
  299 
  300 int
  301 acx111_init(struct acx_softc *sc)
  302 {
  303         struct ifnet *ifp = &sc->sc_ic.ic_if;
  304 
  305         /*
  306          * NOTE:
  307          * Order of initialization:
  308          * 1) Templates
  309          * 2) Hardware memory
  310          * Above order is critical to get a correct memory map
  311          */
  312         if (acx_init_tmplt_ordered(sc) != 0) {
  313                 printf("%s: %s can't initialize templates\n",
  314                     ifp->if_xname, __func__);
  315                 return (ENXIO);
  316         }
  317 
  318         if (acx111_init_memory(sc) != 0) {
  319                 printf("%s: %s can't initialize hw memory\n",
  320                     ifp->if_xname, __func__);
  321                 return (ENXIO);
  322         }
  323 
  324         return (0);
  325 }
  326 
  327 int
  328 acx111_init_memory(struct acx_softc *sc)
  329 {
  330         struct acx111_conf_mem mem;
  331         struct acx111_conf_meminfo mem_info;
  332         struct ifnet *ifp = &sc->sc_ic.ic_if;
  333 
  334         /* Set memory configuration */
  335         bzero(&mem, sizeof(mem));
  336 
  337         mem.sta_max = htole16(ACX111_STA_MAX);
  338         mem.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
  339         mem.rx_memblk_perc = ACX111_RX_MEMBLK_PERCENT;
  340         mem.opt = ACX111_MEMOPT_DEFAULT;
  341         mem.xfer_perc = ACX111_XFER_PERCENT;
  342 
  343         mem.fw_rxring_num = 1;
  344         mem.fw_rxring_type = ACX111_RXRING_TYPE_DEFAULT;
  345         mem.fw_rxring_prio = ACX111_RXRING_PRIO_DEFAULT;
  346         mem.fw_rxdesc_num = ACX_RX_DESC_CNT;
  347         mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
  348 
  349         mem.fw_txring_num = 1;
  350         mem.fw_txring_attr = ACX111_TXRING_ATTR_DEFAULT;
  351         mem.fw_txdesc_num = ACX_TX_DESC_CNT;
  352 
  353         if (acx_set_conf(sc, ACX111_CONF_MEM, &mem, sizeof(mem)) != 0) {
  354                 printf("%s: can't set mem\n", ifp->if_xname);
  355                 return (1);
  356         }
  357 
  358         /* Get memory configuration */
  359         if (acx_get_conf(sc, ACX111_CONF_MEMINFO, &mem_info,
  360             sizeof(mem_info)) != 0) {
  361                 printf("%s: can't get meminfo\n", ifp->if_xname);
  362                 return (1);
  363         }
  364 
  365         /* Setup firmware TX descriptor ring */
  366         acx111_init_fw_txring(sc, letoh32(mem_info.fw_txring_start));
  367 
  368         /*
  369          * There is no need to setup firmware RX descriptor ring,
  370          * it is automatically setup by hardware.
  371          */
  372 
  373         return (0);
  374 }
  375 
  376 void
  377 acx111_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
  378 {
  379         struct acx_txbuf *tx_buf;
  380         uint32_t desc_paddr;
  381         int i;
  382 
  383         tx_buf = sc->sc_buf_data.tx_buf;
  384         desc_paddr = sc->sc_ring_data.tx_ring_paddr;
  385 
  386         for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
  387                 tx_buf[i].tb_fwdesc_ofs = fw_txdesc_start +
  388                     (i * ACX111_FW_TXDESC_SIZE);
  389 
  390                 /*
  391                  * Except for the following fields, rest of the fields
  392                  * are setup by hardware.
  393                  */
  394                 FW_TXDESC_SETFIELD_4(sc, &tx_buf[i], f_tx_host_desc,
  395                     desc_paddr);
  396                 FW_TXDESC_SETFIELD_1(sc, &tx_buf[i], f_tx_ctrl,
  397                     DESC_CTRL_HOSTOWN);
  398 
  399                 desc_paddr += (2 * sizeof(struct acx_host_desc));
  400         }
  401 }
  402 
  403 int
  404 acx111_write_config(struct acx_softc *sc, struct acx_config *conf)
  405 {
  406         struct acx111_conf_txpower tx_power;
  407         struct acx111_conf_option opt;
  408         struct ifnet *ifp = &sc->sc_ic.ic_if;
  409         uint32_t dataflow;
  410 
  411         /* Set TX power */
  412         tx_power.txpower = ACX111_TXPOWER_VAL;
  413         if (acx_set_conf(sc, ACX_CONF_TXPOWER, &tx_power,
  414             sizeof(tx_power)) != 0) {
  415                 printf("%s: %s can't set TX power\n",
  416                     ifp->if_xname, __func__);
  417                 return (ENXIO);
  418         }
  419 
  420         /*
  421          * Turn off hardware WEP
  422          */
  423         if (acx_get_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) {
  424                 printf("%s: %s can't get option\n", ifp->if_xname, __func__);
  425                 return (ENXIO);
  426         }
  427 
  428         dataflow = letoh32(opt.dataflow) |
  429             ACX111_DF_NO_TXENCRYPT |
  430             ACX111_DF_NO_RXDECRYPT;
  431         opt.dataflow = htole32(dataflow);
  432 
  433         if (acx_set_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) {
  434                 printf("%s: %s can't set option\n", ifp->if_xname, __func__);
  435                 return (ENXIO);
  436         }
  437 
  438         return (0);
  439 }
  440 
  441 void
  442 acx111_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
  443     int rate0)
  444 {
  445         uint16_t rate;
  446 
  447         rate = acx111_rate_map[rate0];
  448         if (rate == 0)
  449                 /* set rate to 1Mbit/s if rate was zero */
  450                 rate = acx111_rate_map[2];
  451 
  452         FW_TXDESC_SETFIELD_2(sc, tx_buf, u.r2.rate111, rate);
  453 }
  454 
  455 void
  456 acx111_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
  457 {
  458         struct acx111_bss_join *bj = param;
  459 
  460         bj->basic_rates = htole16(ACX111_RATE_ALL);
  461         bj->dtim_intvl = dtim_intvl;
  462 }

Cache object: 5f2a04cc959f4e9ad01bb73991cb153e


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