LCOV - code coverage report
Current view: top level - dev/ic - acx100.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 257 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: acx100.c,v 1.27 2017/09/22 13:44:00 kevlo 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/systm.h>
      57             : #include <sys/mbuf.h>
      58             : #include <sys/endian.h>
      59             : #include <sys/socket.h>
      60             : #include <sys/device.h>
      61             : 
      62             : #include <machine/bus.h>
      63             : 
      64             : #include <net/if.h>
      65             : #include <net/if_media.h>
      66             : 
      67             : #include <netinet/in.h>
      68             : #include <netinet/if_ether.h>
      69             : 
      70             : #include <net80211/ieee80211_var.h>
      71             : #include <net80211/ieee80211_amrr.h>
      72             : #include <net80211/ieee80211_radiotap.h>
      73             : 
      74             : #include <dev/pci/pcireg.h>
      75             : 
      76             : #include <dev/ic/acxvar.h>
      77             : #include <dev/ic/acxreg.h>
      78             : 
      79             : #define ACX100_CONF_FW_RING     0x0003
      80             : #define ACX100_CONF_MEMOPT      0x0005
      81             : 
      82             : #define ACX100_INTR_ENABLE      (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
      83             : /*
      84             :  * XXX do we really care about following interrupts?
      85             :  *
      86             :  * ACXRV_INTR_INFO | ACXRV_INTR_SCAN_FINI
      87             :  */
      88             : 
      89             : #define ACX100_INTR_DISABLE     (uint16_t)~(ACXRV_INTR_UNKN)
      90             : 
      91             : #define ACX100_RATE(rate)       ((rate) * 5)
      92             : 
      93             : #define ACX100_TXPOWER          18
      94             : #define ACX100_GPIO_POWER_LED   0x0800
      95             : #define ACX100_EE_EADDR_OFS     0x1a
      96             : 
      97             : #define ACX100_FW_TXRING_SIZE   (ACX_TX_DESC_CNT * sizeof(struct acx_fw_txdesc))
      98             : #define ACX100_FW_RXRING_SIZE   (ACX_RX_DESC_CNT * sizeof(struct acx_fw_rxdesc))
      99             : 
     100             : int     acx100_init(struct acx_softc *);
     101             : int     acx100_init_wep(struct acx_softc *);
     102             : int     acx100_init_tmplt(struct acx_softc *);
     103             : int     acx100_init_fw_ring(struct acx_softc *);
     104             : int     acx100_init_memory(struct acx_softc *);
     105             : void    acx100_init_fw_txring(struct acx_softc *, uint32_t);
     106             : void    acx100_init_fw_rxring(struct acx_softc *, uint32_t);
     107             : int     acx100_read_config(struct acx_softc *, struct acx_config *);
     108             : int     acx100_write_config(struct acx_softc *, struct acx_config *);
     109             : int     acx100_set_txpower(struct acx_softc *);
     110             : void    acx100_set_fw_txdesc_rate(struct acx_softc *,
     111             :             struct acx_txbuf *, int);
     112             : void    acx100_set_bss_join_param(struct acx_softc *, void *, int);
     113             : int     acx100_set_wepkey(struct acx_softc *, struct ieee80211_key *, int);
     114             : void    acx100_proc_wep_rxbuf(struct acx_softc *, struct mbuf *, int *);
     115             : 
     116             : /*
     117             :  * NOTE:
     118             :  * Following structs' fields are little endian
     119             :  */
     120             : struct acx100_bss_join {
     121             :         uint8_t dtim_intvl;
     122             :         uint8_t basic_rates;
     123             :         uint8_t all_rates;
     124             : } __packed;
     125             : 
     126             : struct acx100_conf_fw_ring {
     127             :         struct acx_conf confcom;
     128             :         uint32_t        fw_ring_size;   /* total size of fw (tx + rx) ring */
     129             :         uint32_t        fw_rxring_addr; /* start phyaddr of fw rx desc */
     130             :         uint8_t         opt;            /* see ACX100_RINGOPT_ */
     131             :         uint8_t         fw_txring_num;  /* num of TX ring */
     132             :         uint8_t         fw_rxdesc_num;  /* num of fw rx desc */
     133             :         uint8_t         reserved0;
     134             :         uint32_t        fw_ring_end[2]; /* see ACX100_SET_RING_END() */
     135             :         uint32_t        fw_txring_addr; /* start phyaddr of fw tx desc */
     136             :         uint8_t         fw_txring_prio; /* see ACX100_TXRING_PRIO_ */
     137             :         uint8_t         fw_txdesc_num;  /* num of fw tx desc */
     138             :         uint16_t        reserved1;
     139             : } __packed;
     140             : 
     141             : #define ACX100_RINGOPT_AUTO_RESET       0x1
     142             : #define ACX100_TXRING_PRIO_DEFAULT      0
     143             : #define ACX100_SET_RING_END(conf, end)                  \
     144             : do {                                                    \
     145             :         (conf)->fw_ring_end[0] = htole32(end);               \
     146             :         (conf)->fw_ring_end[1] = htole32(end + 8);   \
     147             : } while (0)
     148             : 
     149             : struct acx100_conf_memblk_size {
     150             :         struct acx_conf confcom;
     151             :         uint16_t        memblk_size;    /* size of each mem block */
     152             : } __packed;
     153             : 
     154             : struct acx100_conf_mem {
     155             :         struct acx_conf confcom;
     156             :         uint32_t        opt;            /* see ACX100_MEMOPT_ */
     157             :         uint32_t        h_rxring_paddr; /* host rx desc start phyaddr */
     158             : 
     159             :         /*
     160             :          * Memory blocks are controled by hardware
     161             :          * once after they are initialized
     162             :          */
     163             :         uint32_t        rx_memblk_addr; /* start addr of rx mem blocks */
     164             :         uint32_t        tx_memblk_addr; /* start addr of tx mem blocks */
     165             :         uint16_t        rx_memblk_num;  /* num of RX mem block */
     166             :         uint16_t        tx_memblk_num;  /* num of TX mem block */
     167             : } __packed;
     168             : 
     169             : #define ACX100_MEMOPT_MEM_INSTR         0x00000000 /* memory access instruct */
     170             : #define ACX100_MEMOPT_HOSTDESC          0x00010000 /* host indirect desc */
     171             : #define ACX100_MEMOPT_MEMBLOCK          0x00020000 /* local mem block list */
     172             : #define ACX100_MEMOPT_IO_INSTR          0x00040000 /* IO instruct */
     173             : #define ACX100_MEMOPT_PCICONF           0x00080000 /* PCI conf space */
     174             : 
     175             : #define ACX100_MEMBLK_ALIGN             0x20
     176             : 
     177             : struct acx100_conf_cca_mode {
     178             :         struct acx_conf confcom;
     179             :         uint8_t         cca_mode;
     180             :         uint8_t         unknown;
     181             : } __packed;
     182             : 
     183             : struct acx100_conf_ed_thresh {
     184             :         struct acx_conf confcom;
     185             :         uint8_t         ed_thresh;
     186             :         uint8_t         unknown[3];
     187             : } __packed;
     188             : 
     189             : struct acx100_conf_wepkey {
     190             :         struct acx_conf confcom;
     191             :         uint8_t         action; /* see ACX100_WEPKEY_ACT_ */
     192             :         uint8_t         key_len;
     193             :         uint8_t         key_idx;
     194             : #define ACX100_WEPKEY_LEN       29
     195             :         uint8_t         key[ACX100_WEPKEY_LEN];
     196             : } __packed;
     197             : 
     198             : #define ACX100_WEPKEY_ACT_ADD   1
     199             : 
     200             : static const uint16_t   acx100_reg[ACXREG_MAX] = {
     201             :         ACXREG(SOFT_RESET,              0x0000),
     202             : 
     203             :         ACXREG(FWMEM_ADDR,              0x0014),
     204             :         ACXREG(FWMEM_DATA,              0x0018),
     205             :         ACXREG(FWMEM_CTRL,              0x001c),
     206             :         ACXREG(FWMEM_START,             0x0020),
     207             : 
     208             :         ACXREG(EVENT_MASK,              0x0034),
     209             : 
     210             :         ACXREG(INTR_TRIG,               0x007c),
     211             :         ACXREG(INTR_MASK,               0x0098),
     212             :         ACXREG(INTR_STATUS,             0x00a4),
     213             :         ACXREG(INTR_STATUS_CLR,         0x00a8),
     214             :         ACXREG(INTR_ACK,                0x00ac),
     215             : 
     216             :         ACXREG(HINTR_TRIG,              0x00b0),
     217             :         ACXREG(RADIO_ENABLE,            0x0104),
     218             : 
     219             :         ACXREG(EEPROM_INIT,             0x02d0),
     220             :         ACXREG(EEPROM_CTRL,             0x0250),
     221             :         ACXREG(EEPROM_ADDR,             0x0254),
     222             :         ACXREG(EEPROM_DATA,             0x0258),
     223             :         ACXREG(EEPROM_CONF,             0x025c),
     224             :         ACXREG(EEPROM_INFO,             0x02ac),
     225             : 
     226             :         ACXREG(PHY_ADDR,                0x0268),
     227             :         ACXREG(PHY_DATA,                0x026c),
     228             :         ACXREG(PHY_CTRL,                0x0270),
     229             : 
     230             :         ACXREG(GPIO_OUT_ENABLE,         0x0290),
     231             :         ACXREG(GPIO_OUT,                0x0298),
     232             : 
     233             :         ACXREG(CMD_REG_OFFSET,          0x02a4),
     234             :         ACXREG(INFO_REG_OFFSET,         0x02a8),
     235             : 
     236             :         ACXREG(RESET_SENSE,             0x02d4),
     237             :         ACXREG(ECPU_CTRL,               0x02d8)
     238             : };
     239             : 
     240             : static const uint8_t    acx100_txpower_maxim[21] = {
     241             :         63, 63, 63, 62,
     242             :         61, 61, 60, 60,
     243             :         59, 58, 57, 55,
     244             :         53, 50, 47, 43,
     245             :         38, 31, 23, 13,
     246             :         0
     247             : };
     248             : 
     249             : static const uint8_t    acx100_txpower_rfmd[21] = {
     250             :          0,  0,  0,  1,
     251             :          2,  2,  3,  3,
     252             :          4,  5,  6,  8,
     253             :         10, 13, 16, 20,
     254             :         25, 32, 41, 50,
     255             :         63
     256             : };
     257             : 
     258             : void
     259           0 : acx100_set_param(struct acx_softc *sc)
     260             : {
     261           0 :         sc->chip_mem1_rid = PCIR_BAR(1);
     262           0 :         sc->chip_mem2_rid = PCIR_BAR(2);
     263           0 :         sc->chip_ioreg = acx100_reg;
     264           0 :         sc->chip_hw_crypt = 1;
     265           0 :         sc->chip_intr_enable = ACX100_INTR_ENABLE;
     266             : #ifndef IEEE80211_STA_ONLY
     267           0 :         sc->chip_intr_enable |= ACXRV_INTR_DTIM;
     268             : #endif
     269           0 :         sc->chip_intr_disable = ACX100_INTR_DISABLE;
     270           0 :         sc->chip_gpio_pled = ACX100_GPIO_POWER_LED;
     271           0 :         sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS;
     272           0 :         sc->chip_txdesc1_len = ACX_FRAME_HDRLEN;
     273           0 :         sc->chip_fw_txdesc_ctrl = DESC_CTRL_AUTODMA |
     274             :             DESC_CTRL_RECLAIM | DESC_CTRL_FIRST_FRAG;
     275             : 
     276           0 :         sc->chip_phymode = IEEE80211_MODE_11B;
     277           0 :         sc->chip_chan_flags = IEEE80211_CHAN_B;
     278           0 :         sc->sc_ic.ic_phytype = IEEE80211_T_DS;
     279           0 :         sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
     280             : 
     281           0 :         sc->chip_init = acx100_init;
     282           0 :         sc->chip_set_wepkey = acx100_set_wepkey;
     283           0 :         sc->chip_read_config = acx100_read_config;
     284           0 :         sc->chip_write_config = acx100_write_config;
     285           0 :         sc->chip_set_fw_txdesc_rate = acx100_set_fw_txdesc_rate;
     286           0 :         sc->chip_set_bss_join_param = acx100_set_bss_join_param;
     287           0 :         sc->chip_proc_wep_rxbuf = acx100_proc_wep_rxbuf;
     288           0 : }
     289             : 
     290             : int
     291           0 : acx100_init(struct acx_softc *sc)
     292             : {
     293           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     294             : 
     295             :         /*
     296             :          * NOTE:
     297             :          * Order of initialization:
     298             :          * 1) WEP
     299             :          * 2) Templates
     300             :          * 3) Firmware TX/RX ring
     301             :          * 4) Hardware memory
     302             :          * Above order is critical to get a correct memory map
     303             :          */
     304           0 :         if (acx100_init_wep(sc) != 0) {
     305           0 :                 printf("%s: %s can't initialize wep\n",
     306           0 :                     ifp->if_xname, __func__);
     307           0 :                 return (ENXIO);
     308             :         }
     309             : 
     310           0 :         if (acx100_init_tmplt(sc) != 0) {
     311           0 :                 printf("%s: %s can't initialize templates\n",
     312           0 :                     ifp->if_xname, __func__);
     313           0 :                 return (ENXIO);
     314             :         }
     315             : 
     316           0 :         if (acx100_init_fw_ring(sc) != 0) {
     317           0 :                 printf("%s: %s can't initialize fw ring\n",
     318           0 :                     ifp->if_xname, __func__);
     319           0 :                 return (ENXIO);
     320             :         }
     321             : 
     322           0 :         if (acx100_init_memory(sc) != 0) {
     323           0 :                 printf("%s: %s can't initialize hw memory\n",
     324           0 :                     ifp->if_xname, __func__);
     325           0 :                 return (ENXIO);
     326             :         }
     327             : 
     328           0 :         return (0);
     329           0 : }
     330             : 
     331             : int
     332           0 : acx100_init_wep(struct acx_softc *sc)
     333             : {
     334           0 :         struct acx_conf_wepopt wep_opt;
     335           0 :         struct acx_conf_mmap mem_map;
     336           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     337             : 
     338             :         /* Set WEP cache start/end address */
     339           0 :         if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     340           0 :                 printf("%s: can't get mmap\n", ifp->if_xname);
     341           0 :                 return (1);
     342             :         }
     343             : 
     344           0 :         mem_map.wep_cache_start = htole32(letoh32(mem_map.code_end) + 4);
     345           0 :         mem_map.wep_cache_end = htole32(letoh32(mem_map.code_end) + 4);
     346           0 :         if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     347           0 :                 printf("%s: can't set mmap\n", ifp->if_xname);
     348           0 :                 return (1);
     349             :         }
     350             : 
     351             :         /* Set WEP options */
     352           0 :         wep_opt.nkey = htole16(IEEE80211_WEP_NKID + 10);
     353           0 :         wep_opt.opt = WEPOPT_HDWEP;
     354           0 :         if (acx_set_conf(sc, ACX_CONF_WEPOPT, &wep_opt, sizeof(wep_opt)) != 0) {
     355           0 :                 printf("%s: can't set wep opt\n", ifp->if_xname);
     356           0 :                 return (1);
     357             :         }
     358             : 
     359           0 :         return (0);
     360           0 : }
     361             : 
     362             : int
     363           0 : acx100_init_tmplt(struct acx_softc *sc)
     364             : {
     365           0 :         struct acx_conf_mmap mem_map;
     366           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     367             : 
     368             :         /* Set templates start address */
     369           0 :         if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     370           0 :                 printf("%s: can't get mmap\n", ifp->if_xname);
     371           0 :                 return (1);
     372             :         }
     373             : 
     374           0 :         mem_map.pkt_tmplt_start = mem_map.wep_cache_end;
     375           0 :         if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     376           0 :                 printf("%s: can't set mmap\n", ifp->if_xname);
     377           0 :                 return (1);
     378             :         }
     379             : 
     380             :         /* Initialize various packet templates */
     381           0 :         if (acx_init_tmplt_ordered(sc) != 0) {
     382           0 :                 printf("%s: can't init tmplt\n", ifp->if_xname);
     383           0 :                 return (1);
     384             :         }
     385             : 
     386           0 :         return (0);
     387           0 : }
     388             : 
     389             : int
     390           0 : acx100_init_fw_ring(struct acx_softc *sc)
     391             : {
     392           0 :         struct acx100_conf_fw_ring ring;
     393           0 :         struct acx_conf_mmap mem_map;
     394           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     395             :         uint32_t txring_start, rxring_start, ring_end;
     396             : 
     397             :         /* Set firmware descriptor ring start address */
     398           0 :         if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     399           0 :                 printf("%s: can't get mmap\n", ifp->if_xname);
     400           0 :                 return (1);
     401             :         }
     402             : 
     403           0 :         txring_start = letoh32(mem_map.pkt_tmplt_end) + 4;
     404           0 :         rxring_start = txring_start + ACX100_FW_TXRING_SIZE;
     405           0 :         ring_end = rxring_start + ACX100_FW_RXRING_SIZE;
     406             : 
     407           0 :         mem_map.fw_desc_start = htole32(txring_start);
     408           0 :         if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     409           0 :                 printf("%s: can't set mmap\n", ifp->if_xname);
     410           0 :                 return (1);
     411             :         }
     412             : 
     413             :         /* Set firmware descriptor ring configure */
     414           0 :         bzero(&ring, sizeof(ring));
     415           0 :         ring.fw_ring_size = htole32(ACX100_FW_TXRING_SIZE +
     416             :             ACX100_FW_RXRING_SIZE + 8);
     417             : 
     418           0 :         ring.fw_txring_num = 1;
     419           0 :         ring.fw_txring_addr = htole32(txring_start);
     420           0 :         ring.fw_txring_prio = ACX100_TXRING_PRIO_DEFAULT;
     421           0 :         ring.fw_txdesc_num = 0; /* XXX ignored?? */
     422             : 
     423           0 :         ring.fw_rxring_addr = htole32(rxring_start);
     424           0 :         ring.fw_rxdesc_num = 0; /* XXX ignored?? */
     425             : 
     426           0 :         ring.opt = ACX100_RINGOPT_AUTO_RESET;
     427           0 :         ACX100_SET_RING_END(&ring, ring_end);
     428           0 :         if (acx_set_conf(sc, ACX100_CONF_FW_RING, &ring, sizeof(ring)) != 0) {
     429           0 :                 printf("%s: can't set fw ring configure\n", ifp->if_xname);
     430           0 :                 return (1);
     431             :         }
     432             : 
     433             :         /* Setup firmware TX/RX descriptor ring */
     434           0 :         acx100_init_fw_txring(sc, txring_start);
     435           0 :         acx100_init_fw_rxring(sc, rxring_start);
     436             : 
     437           0 :         return (0);
     438           0 : }
     439             : 
     440             : #define MEMBLK_ALIGN(addr)      \
     441             :     (((addr) + (ACX100_MEMBLK_ALIGN - 1)) & ~(ACX100_MEMBLK_ALIGN - 1))
     442             : 
     443             : int
     444           0 : acx100_init_memory(struct acx_softc *sc)
     445             : {
     446           0 :         struct acx100_conf_memblk_size memblk_sz;
     447           0 :         struct acx100_conf_mem mem;
     448           0 :         struct acx_conf_mmap mem_map;
     449           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     450             :         uint32_t memblk_start, memblk_end;
     451             :         int total_memblk, txblk_num, rxblk_num;
     452             : 
     453             :         /* Set memory block start address */
     454           0 :         if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     455           0 :                 printf("%s: can't get mmap\n", ifp->if_xname);
     456           0 :                 return (1);
     457             :         }
     458             : 
     459           0 :         mem_map.memblk_start =
     460           0 :             htole32(MEMBLK_ALIGN(letoh32(mem_map.fw_desc_end) + 4));
     461             : 
     462           0 :         if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     463           0 :                 printf("%s: can't set mmap\n", ifp->if_xname);
     464           0 :                 return (1);
     465             :         }
     466             : 
     467             :         /* Set memory block size */
     468           0 :         memblk_sz.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
     469           0 :         if (acx_set_conf(sc, ACX_CONF_MEMBLK_SIZE, &memblk_sz,
     470           0 :             sizeof(memblk_sz)) != 0) {
     471           0 :                 printf("%s: can't set mem block size\n", ifp->if_xname);
     472           0 :                 return (1);
     473             :         }
     474             : 
     475             :         /* Get memory map after setting it */
     476           0 :         if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
     477           0 :                 printf("%s: can't get mmap again\n", ifp->if_xname);
     478           0 :                 return (1);
     479             :         }
     480           0 :         memblk_start = letoh32(mem_map.memblk_start);
     481           0 :         memblk_end = letoh32(mem_map.memblk_end);
     482             : 
     483             :         /* Set memory options */
     484           0 :         mem.opt = htole32(ACX100_MEMOPT_MEMBLOCK | ACX100_MEMOPT_HOSTDESC);
     485           0 :         mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
     486             : 
     487           0 :         total_memblk = (memblk_end - memblk_start) / ACX_MEMBLOCK_SIZE;
     488             : 
     489           0 :         rxblk_num = total_memblk / 2;           /* 50% */
     490           0 :         txblk_num = total_memblk - rxblk_num;   /* 50% */
     491             : 
     492             :         DPRINTF(("%s: \ttotal memory blocks\t%d\n"
     493             :             "\trx memory blocks\t%d\n"
     494             :             "\ttx memory blocks\t%d\n",
     495             :             ifp->if_xname, total_memblk, rxblk_num, txblk_num));
     496             : 
     497           0 :         mem.rx_memblk_num = htole16(rxblk_num);
     498           0 :         mem.tx_memblk_num = htole16(txblk_num);
     499             : 
     500           0 :         mem.rx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start));
     501           0 :         mem.tx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start +
     502             :             (ACX_MEMBLOCK_SIZE * rxblk_num)));
     503             : 
     504           0 :         if (acx_set_conf(sc, ACX100_CONF_MEMOPT, &mem, sizeof(mem)) != 0) {
     505           0 :                 printf("%s: can't set mem options\n", ifp->if_xname);
     506           0 :                 return (1);
     507             :         }
     508             : 
     509             :         /* Initialize memory */
     510           0 :         if (acx_exec_command(sc, ACXCMD_INIT_MEM, NULL, 0, NULL, 0) != 0) {
     511           0 :                 printf("%s: can't init mem\n", ifp->if_xname);
     512           0 :                 return (1);
     513             :         }
     514             : 
     515           0 :         return (0);
     516           0 : }
     517             : 
     518             : #undef MEMBLK_ALIGN
     519             : 
     520             : void
     521           0 : acx100_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
     522             : {
     523           0 :         struct acx_fw_txdesc fw_desc;
     524             :         struct acx_txbuf *tx_buf;
     525             :         uint32_t desc_paddr, fw_desc_offset;
     526             :         int i;
     527             : 
     528           0 :         bzero(&fw_desc, sizeof(fw_desc));
     529           0 :         fw_desc.f_tx_ctrl = DESC_CTRL_HOSTOWN | DESC_CTRL_RECLAIM |
     530             :             DESC_CTRL_AUTODMA | DESC_CTRL_FIRST_FRAG;
     531             : 
     532           0 :         tx_buf = sc->sc_buf_data.tx_buf;
     533             :         fw_desc_offset = fw_txdesc_start;
     534           0 :         desc_paddr = sc->sc_ring_data.tx_ring_paddr;
     535             : 
     536           0 :         for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
     537           0 :                 fw_desc.f_tx_host_desc = htole32(desc_paddr);
     538             : 
     539           0 :                 if (i == ACX_TX_DESC_CNT - 1) {
     540           0 :                         fw_desc.f_tx_next_desc = htole32(fw_txdesc_start);
     541           0 :                 } else {
     542           0 :                         fw_desc.f_tx_next_desc = htole32(fw_desc_offset +
     543             :                             sizeof(struct acx_fw_txdesc));
     544             :                 }
     545             : 
     546           0 :                 tx_buf[i].tb_fwdesc_ofs = fw_desc_offset;
     547           0 :                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
     548             :                     sizeof(fw_desc));
     549             : 
     550           0 :                 desc_paddr += (2 * sizeof(struct acx_host_desc));
     551           0 :                 fw_desc_offset += sizeof(fw_desc);
     552             :         }
     553           0 : }
     554             : 
     555             : void
     556           0 : acx100_init_fw_rxring(struct acx_softc *sc, uint32_t fw_rxdesc_start)
     557             : {
     558           0 :         struct acx_fw_rxdesc fw_desc;
     559             :         uint32_t fw_desc_offset;
     560             :         int i;
     561             : 
     562           0 :         bzero(&fw_desc, sizeof(fw_desc));
     563           0 :         fw_desc.f_rx_ctrl = DESC_CTRL_RECLAIM | DESC_CTRL_AUTODMA;
     564             : 
     565             :         fw_desc_offset = fw_rxdesc_start;
     566             : 
     567           0 :         for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
     568           0 :                 if (i == ACX_RX_DESC_CNT - 1) {
     569           0 :                         fw_desc.f_rx_next_desc = htole32(fw_rxdesc_start);
     570           0 :                 } else {
     571           0 :                         fw_desc.f_rx_next_desc =
     572           0 :                             htole32(fw_desc_offset +
     573             :                             sizeof(struct acx_fw_rxdesc));
     574             :                 }
     575             : 
     576           0 :                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
     577             :                     sizeof(fw_desc));
     578             : 
     579           0 :                 fw_desc_offset += sizeof(fw_desc);
     580             :         }
     581           0 : }
     582             : 
     583             : int
     584           0 : acx100_read_config(struct acx_softc *sc, struct acx_config *conf)
     585             : {
     586           0 :         struct acx100_conf_cca_mode cca;
     587           0 :         struct acx100_conf_ed_thresh ed;
     588           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     589             : 
     590             :         /*
     591             :          * NOTE:
     592             :          * CCA mode and ED threshold MUST be read during initialization
     593             :          * or the acx100 card won't work as expected
     594             :          */
     595             : 
     596             :         /* Get CCA mode */
     597           0 :         if (acx_get_conf(sc, ACX_CONF_CCA_MODE, &cca, sizeof(cca)) != 0) {
     598           0 :                 printf("%s: %s can't get cca mode\n",
     599           0 :                     ifp->if_xname, __func__);
     600           0 :                 return (ENXIO);
     601             :         }
     602           0 :         conf->cca_mode = cca.cca_mode;
     603             :         DPRINTF(("%s: cca mode %02x\n", ifp->if_xname, cca.cca_mode));
     604             : 
     605             :         /* Get ED threshold */
     606           0 :         if (acx_get_conf(sc, ACX_CONF_ED_THRESH, &ed, sizeof(ed)) != 0) {
     607           0 :                 printf("%s: %s can't get ed threshold\n",
     608           0 :                     ifp->if_xname, __func__);
     609           0 :                 return (ENXIO);
     610             :         }
     611           0 :         conf->ed_thresh = ed.ed_thresh;
     612             :         DPRINTF(("%s: ed threshold %02x\n", ifp->if_xname, ed.ed_thresh));
     613             : 
     614           0 :         return (0);
     615           0 : }
     616             : 
     617             : int
     618           0 : acx100_write_config(struct acx_softc *sc, struct acx_config *conf)
     619             : {
     620           0 :         struct acx100_conf_cca_mode cca;
     621           0 :         struct acx100_conf_ed_thresh ed;
     622           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     623             : 
     624             :         /* Set CCA mode */
     625           0 :         cca.cca_mode = conf->cca_mode;
     626           0 :         if (acx_set_conf(sc, ACX_CONF_CCA_MODE, &cca, sizeof(cca)) != 0) {
     627           0 :                 printf("%s: %s can't set cca mode\n",
     628           0 :                     ifp->if_xname, __func__);
     629           0 :                 return (ENXIO);
     630             :         }
     631             : 
     632             :         /* Set ED threshold */
     633           0 :         ed.ed_thresh = conf->ed_thresh;
     634           0 :         if (acx_set_conf(sc, ACX_CONF_ED_THRESH, &ed, sizeof(ed)) != 0) {
     635           0 :                 printf("%s: %s can't set ed threshold\n",
     636           0 :                     ifp->if_xname, __func__);
     637           0 :                 return (ENXIO);
     638             :         }
     639             : 
     640             :         /* Set TX power */
     641           0 :         acx100_set_txpower(sc); /* ignore return value */
     642             : 
     643           0 :         return (0);
     644           0 : }
     645             : 
     646             : int
     647           0 : acx100_set_txpower(struct acx_softc *sc)
     648             : {
     649           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     650             :         const uint8_t *map;
     651             : 
     652           0 :         switch (sc->sc_radio_type) {
     653             :         case ACX_RADIO_TYPE_MAXIM:
     654             :                 map = acx100_txpower_maxim;
     655           0 :                 break;
     656             :         case ACX_RADIO_TYPE_RFMD:
     657             :         case ACX_RADIO_TYPE_RALINK:
     658             :                 map = acx100_txpower_rfmd;
     659           0 :                 break;
     660             :         default:
     661           0 :                 printf("%s: TX power for radio type 0x%02x can't be set yet\n",
     662           0 :                     ifp->if_xname, sc->sc_radio_type);
     663           0 :                 return (1);
     664             :         }
     665             : 
     666           0 :         acx_write_phyreg(sc, ACXRV_PHYREG_TXPOWER, map[ACX100_TXPOWER]);
     667             : 
     668           0 :         return (0);
     669           0 : }
     670             : 
     671             : void
     672           0 : acx100_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
     673             :     int rate)
     674             : {
     675           0 :         FW_TXDESC_SETFIELD_1(sc, tx_buf, f_tx_rate100, ACX100_RATE(rate));
     676           0 : }
     677             : 
     678             : void
     679           0 : acx100_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
     680             : {
     681           0 :         struct acx100_bss_join *bj = param;
     682             : 
     683           0 :         bj->dtim_intvl = dtim_intvl;
     684           0 :         bj->basic_rates = 15;        /* XXX */
     685           0 :         bj->all_rates = 31;  /* XXX */
     686           0 : }
     687             : 
     688             : int
     689           0 : acx100_set_wepkey(struct acx_softc *sc, struct ieee80211_key *k, int k_idx)
     690             : {
     691           0 :         struct acx100_conf_wepkey conf_wk;
     692           0 :         struct ifnet *ifp = &sc->sc_ic.ic_if;
     693             : 
     694           0 :         if (k->k_len > ACX100_WEPKEY_LEN) {
     695           0 :                 printf("%s: %dth WEP key size beyond %d\n",
     696           0 :                     ifp->if_xname, k_idx, ACX100_WEPKEY_LEN);
     697           0 :                 return EINVAL;
     698             :         }
     699             : 
     700           0 :         conf_wk.action = ACX100_WEPKEY_ACT_ADD;
     701           0 :         conf_wk.key_len = k->k_len;
     702           0 :         conf_wk.key_idx = k_idx;
     703           0 :         bcopy(k->k_key, conf_wk.key, k->k_len);
     704           0 :         if (acx_set_conf(sc, ACX_CONF_WEPKEY, &conf_wk, sizeof(conf_wk)) != 0) {
     705           0 :                 printf("%s: %s set %dth WEP key failed\n",
     706           0 :                     ifp->if_xname, __func__, k_idx);
     707           0 :                 return ENXIO;
     708             :         }
     709           0 :         return 0;
     710           0 : }
     711             : 
     712             : void
     713           0 : acx100_proc_wep_rxbuf(struct acx_softc *sc, struct mbuf *m, int *len)
     714             : {
     715             :         int mac_hdrlen;
     716             :         struct ieee80211_frame *f;
     717             : 
     718             :         /*
     719             :          * Strip leading IV and KID, and trailing CRC
     720             :          */
     721           0 :         f = mtod(m, struct ieee80211_frame *);
     722             : 
     723           0 :         if (ieee80211_has_addr4(f))
     724           0 :                 mac_hdrlen = sizeof(struct ieee80211_frame_addr4);
     725             :         else
     726             :                 mac_hdrlen = sizeof(struct ieee80211_frame);
     727             : 
     728             : #define IEEEWEP_IVLEN   (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
     729             : #define IEEEWEP_EXLEN   (IEEEWEP_IVLEN + IEEE80211_WEP_CRCLEN)
     730             : 
     731           0 :         *len = *len - IEEEWEP_EXLEN;
     732             : 
     733             :         /* Move MAC header toward frame body */
     734           0 :         memmove((uint8_t *)f + IEEEWEP_IVLEN, f, mac_hdrlen);
     735           0 :         m_adj(m, IEEEWEP_IVLEN);
     736             : 
     737             : #undef IEEEWEP_EXLEN
     738             : #undef IEEEWEP_IVLEN
     739           0 : }

Generated by: LCOV version 1.13