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