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 120int acx111_init(struct acx_softc *); 121int acx111_init_memory(struct acx_softc *); 122void acx111_init_fw_txring(struct acx_softc *, uint32_t); 123int acx111_write_config(struct acx_softc *, struct acx_config *); 124void acx111_set_fw_txdesc_rate(struct acx_softc *, 125 struct acx_txbuf *, int); 126void acx111_set_bss_join_param(struct acx_softc *, void *, int); 127 128/* 129 * NOTE: 130 * Following structs' fields are little endian 131 */ 132struct acx111_bss_join { 133 uint16_t basic_rates; 134 uint8_t dtim_intvl; 135} __packed; 136 137struct 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 171struct 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 183struct acx111_conf_txpower { 184 struct acx_conf confcom; 185 uint8_t txpower; 186} __packed; 187 188struct 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 197struct 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 213static 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 */ 254static 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 269void 270acx111_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 300int 301acx111_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 327int 328acx111_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 376void 377acx111_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 403int 404acx111_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 441void 442acx111_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 455void 456acx111_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} 463