[BACK]Return to acx111.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/acx111.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: acx111.c,v 1.16 2007/08/05 21:37:29 claudio 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 <sys/param.h>
                     54: #include <sys/endian.h>
                     55: #include <sys/socket.h>
                     56: #include <sys/sysctl.h>
                     57: #include <sys/device.h>
                     58:
                     59: #include <machine/bus.h>
                     60:
                     61: #include <net/if.h>
                     62: #include <net/if_arp.h>
                     63: #include <net/if_media.h>
                     64:
                     65: #include <net/if.h>
                     66:
                     67: #ifdef INET
                     68: #include <netinet/in.h>
                     69: #include <netinet/if_ether.h>
                     70: #endif
                     71:
                     72: #include <net80211/ieee80211_var.h>
                     73: #include <net80211/ieee80211_amrr.h>
                     74: #include <net80211/ieee80211_radiotap.h>
                     75:
                     76: #include <dev/pci/pcireg.h>
                     77:
                     78: #include <dev/ic/acxvar.h>
                     79: #include <dev/ic/acxreg.h>
                     80:
                     81: #define ACX111_CONF_MEM                0x0003
                     82: #define ACX111_CONF_MEMINFO    0x0005
                     83:
                     84: #define ACX111_INTR_ENABLE     (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
                     85: /*
                     86:  * XXX do we really care about fowlling interrupts?
                     87:  *
                     88:  * ACXRV_INTR_IV_ICV_FAILURE | ACXRV_INTR_INFO |
                     89:  * ACXRV_INTR_SCAN_FINI | ACXRV_INTR_FCS_THRESHOLD
                     90:  */
                     91:
                     92: #define ACX111_INTR_DISABLE    (uint16_t)~(ACXRV_INTR_CMD_FINI)
                     93:
                     94: #define ACX111_RATE_2          0x0001
                     95: #define ACX111_RATE_4          0x0002
                     96: #define ACX111_RATE_11         0x0004
                     97: #define ACX111_RATE_12         0x0008
                     98: #define ACX111_RATE_18         0x0010
                     99: #define ACX111_RATE_22         0x0020
                    100: #define ACX111_RATE_24         0x0040
                    101: #define ACX111_RATE_36         0x0080
                    102: #define ACX111_RATE_44         0x0100
                    103: #define ACX111_RATE_48         0x0200
                    104: #define ACX111_RATE_72         0x0400
                    105: #define ACX111_RATE_96         0x0800
                    106: #define ACX111_RATE_108                0x1000
                    107:
                    108: /* XXX skip ACX111_RATE_44 */
                    109: #define ACX111_RATE_ALL                0x1eff
                    110:
                    111: #define ACX111_TXPOWER         15
                    112: #define ACX111_GPIO_POWER_LED  0x0040
                    113: #define ACX111_EE_EADDR_OFS    0x21
                    114:
                    115: #define ACX111_FW_TXDESC_SIZE  (sizeof(struct acx_fw_txdesc) + 4)
                    116:
                    117: #if ACX111_TXPOWER <= 12
                    118: #define ACX111_TXPOWER_VAL     1
                    119: #else
                    120: #define ACX111_TXPOWER_VAL     2
                    121: #endif
                    122:
                    123: int    acx111_init(struct acx_softc *);
                    124: int    acx111_init_memory(struct acx_softc *);
                    125: void   acx111_init_fw_txring(struct acx_softc *, uint32_t);
                    126: int    acx111_write_config(struct acx_softc *, struct acx_config *);
                    127: void   acx111_set_fw_txdesc_rate(struct acx_softc *,
                    128:            struct acx_txbuf *, int);
                    129: void   acx111_set_bss_join_param(struct acx_softc *, void *, int);
                    130:
                    131: /*
                    132:  * NOTE:
                    133:  * Following structs' fields are little endian
                    134:  */
                    135: struct acx111_bss_join {
                    136:        uint16_t        basic_rates;
                    137:        uint8_t         dtim_intvl;
                    138: } __packed;
                    139:
                    140: struct acx111_conf_mem {
                    141:        struct acx_conf confcom;
                    142:
                    143:        uint16_t        sta_max;        /* max num of sta, ACX111_STA_MAX */
                    144:        uint16_t        memblk_size;    /* mem block size */
                    145:        uint8_t         rx_memblk_perc; /* percent of RX mem block, unit: 5% */
                    146:        uint8_t         fw_rxring_num;  /* num of RX ring */
                    147:        uint8_t         fw_txring_num;  /* num of TX ring */
                    148:        uint8_t         opt;            /* see ACX111_MEMOPT_ */
                    149:        uint8_t         xfer_perc;      /* frag/xfer proportion, unit: 5% */
                    150:        uint16_t        reserved0;
                    151:        uint8_t         reserved1;
                    152:
                    153:        uint8_t         fw_rxdesc_num;  /* num of fw rx desc */
                    154:        uint8_t         fw_rxring_reserved1;
                    155:        uint8_t         fw_rxring_type; /* see ACX111_RXRING_TYPE_ */
                    156:        uint8_t         fw_rxring_prio; /* see ACX111_RXRING_PRIO_ */
                    157:
                    158:        uint32_t        h_rxring_paddr; /* host rx desc start phyaddr */
                    159:
                    160:        uint8_t         fw_txdesc_num;  /* num of fw tx desc */
                    161:        uint8_t         fw_txring_reserved1;
                    162:        uint8_t         fw_txring_reserved2;
                    163:        uint8_t         fw_txring_attr; /* see ACX111_TXRING_ATTR_ */
                    164: } __packed;
                    165:
                    166: #define ACX111_STA_MAX                 32
                    167: #define ACX111_RX_MEMBLK_PERCENT       10      /* 50% */
                    168: #define ACX111_XFER_PERCENT            15      /* 75% */
                    169: #define ACX111_RXRING_TYPE_DEFAULT     7
                    170: #define ACX111_RXRING_PRIO_DEFAULT     0
                    171: #define ACX111_TXRING_ATTR_DEFAULT     0
                    172: #define ACX111_MEMOPT_DEFAULT          0
                    173:
                    174: struct acx111_conf_meminfo {
                    175:        struct acx_conf confcom;
                    176:        uint32_t        tx_memblk_addr; /* start addr of tx mem blocks */
                    177:        uint32_t        rx_memblk_addr; /* start addr of rx mem blocks */
                    178:        uint32_t        fw_rxring_start; /* start phyaddr of fw rx ring */
                    179:        uint32_t        reserved0;
                    180:        uint32_t        fw_txring_start; /* start phyaddr of fw tx ring */
                    181:        uint8_t         fw_txring_attr; /* XXX see ACX111_TXRING_ATTR_ */
                    182:        uint16_t        reserved1;
                    183:        uint8_t         reserved2;
                    184: } __packed;
                    185:
                    186: struct acx111_conf_txpower {
                    187:        struct acx_conf confcom;
                    188:        uint8_t         txpower;
                    189: } __packed;
                    190:
                    191: struct acx111_conf_option {
                    192:        struct acx_conf confcom;
                    193:        uint32_t        feature;
                    194:        uint32_t        dataflow;       /* see ACX111_DF_ */
                    195: } __packed;
                    196:
                    197: #define ACX111_DF_NO_RXDECRYPT 0x00000080
                    198: #define ACX111_DF_NO_TXENCRYPT 0x00000001
                    199:
                    200: struct acx111_wepkey {
                    201:        uint8_t         mac_addr[IEEE80211_ADDR_LEN];
                    202:        uint16_t        action;         /* see ACX111_WEPKEY_ACT_ */
                    203:        uint16_t        reserved;
                    204:        uint8_t         key_len;
                    205:        uint8_t         key_type;       /* see ACX111_WEPKEY_TYPE_ */
                    206:        uint8_t         index;          /* XXX ?? */
                    207:        uint8_t         key_idx;
                    208:        uint8_t         counter[6];
                    209: #define ACX111_WEPKEY_LEN      32
                    210:        uint8_t         key[ACX111_WEPKEY_LEN];
                    211: } __packed;
                    212:
                    213: #define ACX111_WEPKEY_ACT_ADD          1
                    214: #define ACX111_WEPKEY_TYPE_DEFAULT     0
                    215:
                    216: static const uint16_t acx111_reg[ACXREG_MAX] = {
                    217:        ACXREG(SOFT_RESET,              0x0000),
                    218:
                    219:        ACXREG(FWMEM_ADDR,              0x0014),
                    220:        ACXREG(FWMEM_DATA,              0x0018),
                    221:        ACXREG(FWMEM_CTRL,              0x001c),
                    222:        ACXREG(FWMEM_START,             0x0020),
                    223:
                    224:        ACXREG(EVENT_MASK,              0x0034),
                    225:
                    226:        ACXREG(INTR_TRIG,               0x00b4),
                    227:        ACXREG(INTR_MASK,               0x00d4),
                    228:        ACXREG(INTR_STATUS,             0x00f0),
                    229:        ACXREG(INTR_STATUS_CLR,         0x00e4),
                    230:        ACXREG(INTR_ACK,                0x00e8),
                    231:
                    232:        ACXREG(HINTR_TRIG,              0x00ec),
                    233:        ACXREG(RADIO_ENABLE,            0x01d0),
                    234:
                    235:        ACXREG(EEPROM_INIT,             0x0100),
                    236:        ACXREG(EEPROM_CTRL,             0x0338),
                    237:        ACXREG(EEPROM_ADDR,             0x033c),
                    238:        ACXREG(EEPROM_DATA,             0x0340),
                    239:        ACXREG(EEPROM_CONF,             0x0344),
                    240:        ACXREG(EEPROM_INFO,             0x0390),
                    241:
                    242:        ACXREG(PHY_ADDR,                0x0350),
                    243:        ACXREG(PHY_DATA,                0x0354),
                    244:        ACXREG(PHY_CTRL,                0x0358),
                    245:
                    246:        ACXREG(GPIO_OUT_ENABLE,         0x0374),
                    247:        ACXREG(GPIO_OUT,                0x037c),
                    248:
                    249:        ACXREG(CMD_REG_OFFSET,          0x0388),
                    250:        ACXREG(INFO_REG_OFFSET,         0x038c),
                    251:
                    252:        ACXREG(RESET_SENSE,             0x0104),
                    253:        ACXREG(ECPU_CTRL,               0x0108)
                    254: };
                    255:
                    256: /* XXX */
                    257: static uint16_t        acx111_rate_map[109] = {
                    258:        ACX111_RATE_2,
                    259:        ACX111_RATE_4,
                    260:        ACX111_RATE_11,
                    261:        ACX111_RATE_22,
                    262:        ACX111_RATE_12,
                    263:        ACX111_RATE_18,
                    264:        ACX111_RATE_24,
                    265:        ACX111_RATE_36,
                    266:        ACX111_RATE_48,
                    267:        ACX111_RATE_72,
                    268:        ACX111_RATE_96,
                    269:        ACX111_RATE_108
                    270: };
                    271:
                    272: void
                    273: acx111_set_param(struct acx_softc *sc)
                    274: {
                    275:        sc->chip_mem1_rid = PCIR_BAR(0);
                    276:        sc->chip_mem2_rid = PCIR_BAR(1);
                    277:        sc->chip_ioreg = acx111_reg;
                    278:        sc->chip_intr_enable = ACX111_INTR_ENABLE;
                    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;
                    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 automaticly 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: }

CVSweb