1 /* $OpenBSD: acx111.c,v 1.19 2012/10/27 16:13:28 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/systm.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 #ifndef IEEE80211_STA_ONLY 280 sc->chip_intr_enable |= ACXRV_INTR_DTIM; 281 #endif 282 sc->chip_intr_disable = ACX111_INTR_DISABLE; 283 sc->chip_gpio_pled = ACX111_GPIO_POWER_LED; 284 sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS; 285 286 sc->chip_phymode = IEEE80211_MODE_11G; 287 sc->chip_chan_flags = IEEE80211_CHAN_CCK | 288 IEEE80211_CHAN_OFDM | 289 IEEE80211_CHAN_DYN | 290 IEEE80211_CHAN_2GHZ; 291 sc->sc_ic.ic_caps = IEEE80211_C_WEP | IEEE80211_C_SHSLOT; 292 sc->sc_ic.ic_phytype = IEEE80211_T_OFDM; 293 sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; 294 sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; 295 296 sc->chip_init = acx111_init; 297 sc->chip_write_config = acx111_write_config; 298 sc->chip_set_fw_txdesc_rate = acx111_set_fw_txdesc_rate; 299 sc->chip_set_bss_join_param = acx111_set_bss_join_param; 300 sc->sc_flags |= ACX_FLAG_ACX111; 301 } 302 303 int 304 acx111_init(struct acx_softc *sc) 305 { 306 struct ifnet *ifp = &sc->sc_ic.ic_if; 307 308 /* 309 * NOTE: 310 * Order of initialization: 311 * 1) Templates 312 * 2) Hardware memory 313 * Above order is critical to get a correct memory map 314 */ 315 if (acx_init_tmplt_ordered(sc) != 0) { 316 printf("%s: %s can't initialize templates\n", 317 ifp->if_xname, __func__); 318 return (ENXIO); 319 } 320 321 if (acx111_init_memory(sc) != 0) { 322 printf("%s: %s can't initialize hw memory\n", 323 ifp->if_xname, __func__); 324 return (ENXIO); 325 } 326 327 return (0); 328 } 329 330 int 331 acx111_init_memory(struct acx_softc *sc) 332 { 333 struct acx111_conf_mem mem; 334 struct acx111_conf_meminfo mem_info; 335 struct ifnet *ifp = &sc->sc_ic.ic_if; 336 337 /* Set memory configuration */ 338 bzero(&mem, sizeof(mem)); 339 340 mem.sta_max = htole16(ACX111_STA_MAX); 341 mem.memblk_size = htole16(ACX_MEMBLOCK_SIZE); 342 mem.rx_memblk_perc = ACX111_RX_MEMBLK_PERCENT; 343 mem.opt = ACX111_MEMOPT_DEFAULT; 344 mem.xfer_perc = ACX111_XFER_PERCENT; 345 346 mem.fw_rxring_num = 1; 347 mem.fw_rxring_type = ACX111_RXRING_TYPE_DEFAULT; 348 mem.fw_rxring_prio = ACX111_RXRING_PRIO_DEFAULT; 349 mem.fw_rxdesc_num = ACX_RX_DESC_CNT; 350 mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr); 351 352 mem.fw_txring_num = 1; 353 mem.fw_txring_attr = ACX111_TXRING_ATTR_DEFAULT; 354 mem.fw_txdesc_num = ACX_TX_DESC_CNT; 355 356 if (acx_set_conf(sc, ACX111_CONF_MEM, &mem, sizeof(mem)) != 0) { 357 printf("%s: can't set mem\n", ifp->if_xname); 358 return (1); 359 } 360 361 /* Get memory configuration */ 362 if (acx_get_conf(sc, ACX111_CONF_MEMINFO, &mem_info, 363 sizeof(mem_info)) != 0) { 364 printf("%s: can't get meminfo\n", ifp->if_xname); 365 return (1); 366 } 367 368 /* Setup firmware TX descriptor ring */ 369 acx111_init_fw_txring(sc, letoh32(mem_info.fw_txring_start)); 370 371 /* 372 * There is no need to setup firmware RX descriptor ring, 373 * it is automaticly setup by hardware. 374 */ 375 376 return (0); 377 } 378 379 void 380 acx111_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start) 381 { 382 struct acx_txbuf *tx_buf; 383 uint32_t desc_paddr; 384 int i; 385 386 tx_buf = sc->sc_buf_data.tx_buf; 387 desc_paddr = sc->sc_ring_data.tx_ring_paddr; 388 389 for (i = 0; i < ACX_TX_DESC_CNT; ++i) { 390 tx_buf[i].tb_fwdesc_ofs = fw_txdesc_start + 391 (i * ACX111_FW_TXDESC_SIZE); 392 393 /* 394 * Except for the following fields, rest of the fields 395 * are setup by hardware. 396 */ 397 FW_TXDESC_SETFIELD_4(sc, &tx_buf[i], f_tx_host_desc, 398 desc_paddr); 399 FW_TXDESC_SETFIELD_1(sc, &tx_buf[i], f_tx_ctrl, 400 DESC_CTRL_HOSTOWN); 401 402 desc_paddr += (2 * sizeof(struct acx_host_desc)); 403 } 404 } 405 406 int 407 acx111_write_config(struct acx_softc *sc, struct acx_config *conf) 408 { 409 struct acx111_conf_txpower tx_power; 410 struct acx111_conf_option opt; 411 struct ifnet *ifp = &sc->sc_ic.ic_if; 412 uint32_t dataflow; 413 414 /* Set TX power */ 415 tx_power.txpower = ACX111_TXPOWER_VAL; 416 if (acx_set_conf(sc, ACX_CONF_TXPOWER, &tx_power, 417 sizeof(tx_power)) != 0) { 418 printf("%s: %s can't set TX power\n", 419 ifp->if_xname, __func__); 420 return (ENXIO); 421 } 422 423 /* 424 * Turn off hardware WEP 425 */ 426 if (acx_get_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) { 427 printf("%s: %s can't get option\n", ifp->if_xname, __func__); 428 return (ENXIO); 429 } 430 431 dataflow = letoh32(opt.dataflow) | 432 ACX111_DF_NO_TXENCRYPT | 433 ACX111_DF_NO_RXDECRYPT; 434 opt.dataflow = htole32(dataflow); 435 436 if (acx_set_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) { 437 printf("%s: %s can't set option\n", ifp->if_xname, __func__); 438 return (ENXIO); 439 } 440 441 return (0); 442 } 443 444 void 445 acx111_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf, 446 int rate0) 447 { 448 uint16_t rate; 449 450 rate = acx111_rate_map[rate0]; 451 if (rate == 0) 452 /* set rate to 1Mbit/s if rate was zero */ 453 rate = acx111_rate_map[2]; 454 455 FW_TXDESC_SETFIELD_2(sc, tx_buf, u.r2.rate111, rate); 456 } 457 458 void 459 acx111_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl) 460 { 461 struct acx111_bss_join *bj = param; 462 463 bj->basic_rates = htole16(ACX111_RATE_ALL); 464 bj->dtim_intvl = dtim_intvl; 465 } 466