1 /*
2 * Copyright (c) 2006 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <sys/bus.h>
37 #include <sys/endian.h>
38 #include <sys/rman.h>
39 #include <sys/socket.h>
40 #include <sys/sysctl.h>
41
42 #include <net/if.h>
43 #include <net/if_arp.h>
44 #include <net/if_media.h>
45
46 #include <netproto/802_11/ieee80211_var.h>
47 #include <netproto/802_11/ieee80211_radiotap.h>
48 #include <netproto/802_11/wlan_ratectl/amrr/ieee80211_amrr_param.h>
49 #include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
50
51 #include <bus/pci/pcireg.h>
52
53 #define ACX_DEBUG
54
55 #include <dev/netif/acx/if_acxreg.h>
56 #include <dev/netif/acx/if_acxvar.h>
57 #include <dev/netif/acx/acxcmd.h>
58
59 #define ACX100_CONF_FW_RING 0x0003
60 #define ACX100_CONF_MEMOPT 0x0005
61
62 #define ACX100_INTR_ENABLE (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
63 /*
64 * XXX do we really care about following interrupts?
65 *
66 * ACXRV_INTR_INFO | ACXRV_INTR_SCAN_FINI
67 */
68
69 #define ACX100_INTR_DISABLE (uint16_t)~(ACXRV_INTR_UNKN)
70
71 #define ACX100_RATE(rate) ((rate) * 5)
72
73 #define ACX100_RSSI_CORR 8
74 #define ACX100_TXPOWER 18
75 #define ACX100_GPIO_POWER_LED 0x0800
76 #define ACX100_EE_EADDR_OFS 0x1a
77
78 #define ACX100_FW_TXRING_SIZE (ACX_TX_DESC_CNT * sizeof(struct acx_fw_txdesc))
79 #define ACX100_FW_RXRING_SIZE (ACX_RX_DESC_CNT * sizeof(struct acx_fw_rxdesc))
80
81 /*
82 * NOTE:
83 * Following structs' fields are little endian
84 */
85
86 struct acx100_bss_join {
87 uint8_t dtim_intvl;
88 uint8_t basic_rates;
89 uint8_t op_rates;
90 } __packed;
91
92 struct acx100_conf_fw_ring {
93 struct acx_conf confcom;
94 uint32_t fw_ring_size; /* total size of fw (tx + rx) ring */
95 uint32_t fw_rxring_addr; /* start phyaddr of fw rx desc */
96 uint8_t opt; /* see ACX100_RINGOPT_ */
97 uint8_t fw_txring_num; /* num of TX ring */
98 uint8_t fw_rxdesc_num; /* num of fw rx desc */
99 uint8_t reserved0;
100 uint32_t fw_ring_end[2]; /* see ACX100_SET_RING_END() */
101 uint32_t fw_txring_addr; /* start phyaddr of fw tx desc */
102 uint8_t fw_txring_prio; /* see ACX100_TXRING_PRIO_ */
103 uint8_t fw_txdesc_num; /* num of fw tx desc */
104 uint16_t reserved1;
105 } __packed;
106
107 #define ACX100_RINGOPT_AUTO_RESET 0x1
108 #define ACX100_TXRING_PRIO_DEFAULT 0
109 #define ACX100_SET_RING_END(conf, end) \
110 do { \
111 (conf)->fw_ring_end[0] = htole32(end); \
112 (conf)->fw_ring_end[1] = htole32(end + 8); \
113 } while (0)
114
115 struct acx100_conf_memblk_size {
116 struct acx_conf confcom;
117 uint16_t memblk_size; /* size of each mem block */
118 } __packed;
119
120 struct acx100_conf_mem {
121 struct acx_conf confcom;
122 uint32_t opt; /* see ACX100_MEMOPT_ */
123 uint32_t h_rxring_paddr; /* host rx desc start phyaddr */
124
125 /*
126 * Memory blocks are controled by hardware
127 * once after they are initialized
128 */
129 uint32_t rx_memblk_addr; /* start addr of rx mem blocks */
130 uint32_t tx_memblk_addr; /* start addr of tx mem blocks */
131 uint16_t rx_memblk_num; /* num of RX mem block */
132 uint16_t tx_memblk_num; /* num of TX mem block */
133 } __packed;
134
135 #define ACX100_MEMOPT_MEM_INSTR 0x00000000 /* memory access instruct */
136 #define ACX100_MEMOPT_HOSTDESC 0x00010000 /* host indirect desc */
137 #define ACX100_MEMOPT_MEMBLOCK 0x00020000 /* local mem block list */
138 #define ACX100_MEMOPT_IO_INSTR 0x00040000 /* IO instruct */
139 #define ACX100_MEMOPT_PCICONF 0x00080000 /* PCI conf space */
140
141 #define ACX100_MEMBLK_ALIGN 0x20
142
143 struct acx100_conf_cca_mode {
144 struct acx_conf confcom;
145 uint8_t cca_mode;
146 uint8_t unknown;
147 } __packed;
148
149 struct acx100_conf_ed_thresh {
150 struct acx_conf confcom;
151 uint8_t ed_thresh;
152 uint8_t unknown[3];
153 } __packed;
154
155 struct acx100_conf_wepkey {
156 struct acx_conf confcom;
157 uint8_t action; /* see ACX100_WEPKEY_ACT_ */
158 uint8_t key_len;
159 uint8_t key_idx;
160 #define ACX100_WEPKEY_LEN 29
161 uint8_t key[ACX100_WEPKEY_LEN];
162 } __packed;
163
164 #define ACX100_WEPKEY_ACT_ADD 1
165
166 #define ACX100_CONF_FUNC(sg, name) _ACX_CONF_FUNC(sg, name, 100)
167 #define ACX_CONF_fw_ring ACX100_CONF_FW_RING
168 #define ACX_CONF_memblk_size ACX_CONF_MEMBLK_SIZE
169 #define ACX_CONF_mem ACX100_CONF_MEMOPT
170 #define ACX_CONF_cca_mode ACX_CONF_CCA_MODE
171 #define ACX_CONF_ed_thresh ACX_CONF_ED_THRESH
172 #define ACX_CONF_wepkey ACX_CONF_WEPKEY
173 ACX100_CONF_FUNC(set, fw_ring);
174 ACX100_CONF_FUNC(set, memblk_size);
175 ACX100_CONF_FUNC(set, mem);
176 ACX100_CONF_FUNC(get, cca_mode);
177 ACX100_CONF_FUNC(set, cca_mode);
178 ACX100_CONF_FUNC(get, ed_thresh);
179 ACX100_CONF_FUNC(set, ed_thresh);
180 ACX100_CONF_FUNC(set, wepkey);
181
182 #define ACXCMD_init_mem ACXCMD_INIT_MEM
183 ACX_NOARG_FUNC(init_mem);
184
185 static const uint16_t acx100_reg[ACXREG_MAX] = {
186 ACXREG(SOFT_RESET, 0x0000),
187
188 ACXREG(FWMEM_ADDR, 0x0014),
189 ACXREG(FWMEM_DATA, 0x0018),
190 ACXREG(FWMEM_CTRL, 0x001c),
191 ACXREG(FWMEM_START, 0x0020),
192
193 ACXREG(EVENT_MASK, 0x0034),
194
195 ACXREG(INTR_TRIG, 0x007c),
196 ACXREG(INTR_MASK, 0x0098),
197 ACXREG(INTR_STATUS, 0x00a4),
198 ACXREG(INTR_STATUS_CLR, 0x00a8),
199 ACXREG(INTR_ACK, 0x00ac),
200
201 ACXREG(HINTR_TRIG, 0x00b0),
202 ACXREG(RADIO_ENABLE, 0x0104),
203
204 ACXREG(EEPROM_INIT, 0x02d0),
205 ACXREG(EEPROM_CTRL, 0x0250),
206 ACXREG(EEPROM_ADDR, 0x0254),
207 ACXREG(EEPROM_DATA, 0x0258),
208 ACXREG(EEPROM_CONF, 0x025c),
209 ACXREG(EEPROM_INFO, 0x02ac),
210
211 ACXREG(PHY_ADDR, 0x0268),
212 ACXREG(PHY_DATA, 0x026c),
213 ACXREG(PHY_CTRL, 0x0270),
214
215 ACXREG(GPIO_OUT_ENABLE, 0x0290),
216 ACXREG(GPIO_OUT, 0x0298),
217
218 ACXREG(CMD_REG_OFFSET, 0x02a4),
219 ACXREG(INFO_REG_OFFSET, 0x02a8),
220
221 ACXREG(RESET_SENSE, 0x02d4),
222 ACXREG(ECPU_CTRL, 0x02d8)
223 };
224
225 static const uint8_t acx100_txpower_maxim[21] = {
226 63, 63, 63, 62,
227 61, 61, 60, 60,
228 59, 58, 57, 55,
229 53, 50, 47, 43,
230 38, 31, 23, 13,
231 0
232 };
233
234 static const uint8_t acx100_txpower_rfmd[21] = {
235 0, 0, 0, 1,
236 2, 2, 3, 3,
237 4, 5, 6, 8,
238 10, 13, 16, 20,
239 25, 32, 41, 50,
240 63
241 };
242
243 static const uint8_t acx100_rate_map[45] = {
244 [2] = 0x01,
245 [4] = 0x02,
246 [11] = 0x04,
247 [22] = 0x08,
248 [44] = 0x10
249 };
250
251 static int acx100_init(struct acx_softc *);
252 static int acx100_init_wep(struct acx_softc *);
253 static int acx100_init_tmplt(struct acx_softc *);
254 static int acx100_init_fw_ring(struct acx_softc *);
255 static int acx100_init_memory(struct acx_softc *);
256
257 static void acx100_init_fw_txring(struct acx_softc *, uint32_t);
258 static void acx100_init_fw_rxring(struct acx_softc *, uint32_t);
259
260 static int acx100_read_config(struct acx_softc *, struct acx_config *);
261 static int acx100_write_config(struct acx_softc *, struct acx_config *);
262
263 static void *acx100_ratectl_attach(struct ieee80211com *, u_int);
264
265 static int acx100_set_txpower(struct acx_softc *);
266
267 static uint8_t acx100_set_fw_txdesc_rate(struct acx_softc *,
268 struct acx_txbuf *,
269 struct ieee80211_node *, int);
270 static void acx100_tx_complete(struct acx_softc *, struct acx_txbuf *,
271 int, int);
272 static void acx100_set_bss_join_param(struct acx_softc *, void *, int);
273
274 static int acx100_set_wepkey(struct acx_softc *, struct ieee80211_key *,
275 int);
276
277 static void acx100_proc_wep_rxbuf(struct acx_softc *, struct mbuf *, int *);
278
279 #define ACX100_CHK_RATE(ifp, rate, rate_idx) \
280 acx100_check_rate(ifp, rate, rate_idx, __func__)
281
282 static __inline int
283 acx100_check_rate(struct ifnet *ifp, u_int rate, int rate_idx,
284 const char *fname)
285 {
286 if (rate >= NELEM(acx100_rate_map)) {
287 if_printf(ifp, "%s rate out of range %u (idx %d)\n",
288 fname, rate, rate_idx);
289 return -1;
290 }
291
292 if (acx100_rate_map[rate] == 0) {
293 if_printf(ifp, "%s invalid rate %u (idx %d)\n",
294 fname, rate, rate_idx);
295 return -1;
296 }
297 return 0;
298 }
299
300 void
301 acx100_set_param(device_t dev)
302 {
303 struct acx_softc *sc = device_get_softc(dev);
304 struct ieee80211com *ic = &sc->sc_ic;
305 struct acx_firmware *fw = &sc->sc_firmware;
306
307 sc->chip_mem1_rid = PCIR_BAR(1);
308 sc->chip_mem2_rid = PCIR_BAR(2);
309 sc->chip_ioreg = acx100_reg;
310 sc->chip_hw_crypt = 1;
311 sc->chip_intr_enable = ACX100_INTR_ENABLE;
312 sc->chip_intr_disable = ACX100_INTR_DISABLE;
313 sc->chip_gpio_pled = ACX100_GPIO_POWER_LED;
314 sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS;
315 sc->chip_txdesc1_len = ACX_FRAME_HDRLEN;
316 sc->chip_fw_txdesc_ctrl = DESC_CTRL_AUTODMA |
317 DESC_CTRL_RECLAIM |
318 DESC_CTRL_FIRST_FRAG;
319 sc->chip_short_retry_limit = 7;
320 sc->chip_rssi_corr = ACX100_RSSI_CORR;
321
322 sc->chip_phymode = IEEE80211_MODE_11B;
323 sc->chip_chan_flags = IEEE80211_CHAN_B;
324
325 ic->ic_phytype = IEEE80211_T_DS;
326 if (acx_enable_pbcc)
327 ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b_pbcc;
328 else
329 ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b;
330
331 IEEE80211_ONOE_PARAM_SETUP(&sc->sc_onoe_param);
332
333 ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE;
334 ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE;
335 ic->ic_ratectl.rc_st_attach = acx100_ratectl_attach;
336
337 sc->chip_init = acx100_init;
338 sc->chip_set_wepkey = acx100_set_wepkey;
339 sc->chip_read_config = acx100_read_config;
340 sc->chip_write_config = acx100_write_config;
341 sc->chip_set_fw_txdesc_rate = acx100_set_fw_txdesc_rate;
342 sc->chip_tx_complete = acx100_tx_complete;
343 sc->chip_set_bss_join_param = acx100_set_bss_join_param;
344 sc->chip_proc_wep_rxbuf = acx100_proc_wep_rxbuf;
345
346 fw->combined_radio_fw = 0;
347 fw->fwdir = "100";
348 }
349
350 static int
351 acx100_init(struct acx_softc *sc)
352 {
353 /*
354 * NOTE:
355 * Order of initialization:
356 * 1) WEP
357 * 2) Templates
358 * 3) Firmware TX/RX ring
359 * 4) Hardware memory
360 * Above order is critical to get a correct memory map
361 */
362
363 if (acx100_init_wep(sc) != 0) {
364 if_printf(&sc->sc_ic.ic_if, "%s can't initialize wep\n",
365 __func__);
366 return ENXIO;
367 }
368
369 if (acx100_init_tmplt(sc) != 0) {
370 if_printf(&sc->sc_ic.ic_if, "%s can't initialize templates\n",
371 __func__);
372 return ENXIO;
373 }
374
375 if (acx100_init_fw_ring(sc) != 0) {
376 if_printf(&sc->sc_ic.ic_if, "%s can't initialize fw ring\n",
377 __func__);
378 return ENXIO;
379 }
380
381 if (acx100_init_memory(sc) != 0) {
382 if_printf(&sc->sc_ic.ic_if, "%s can't initialize hw memory\n",
383 __func__);
384 return ENXIO;
385 }
386 return 0;
387 }
388
389 static int
390 acx100_init_wep(struct acx_softc *sc)
391 {
392 struct acx_conf_wepopt wep_opt;
393 struct acx_conf_mmap mem_map;
394
395 /* Set WEP cache start/end address */
396 if (acx_get_mmap_conf(sc, &mem_map) != 0) {
397 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
398 return 1;
399 }
400
401 mem_map.wep_cache_start = htole32(le32toh(mem_map.code_end) + 4);
402 mem_map.wep_cache_end = htole32(le32toh(mem_map.code_end) + 4);
403 if (acx_set_mmap_conf(sc, &mem_map) != 0) {
404 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
405 return 1;
406 }
407
408 /* Set WEP options */
409 wep_opt.nkey = htole16(IEEE80211_WEP_NKID + 10);
410 wep_opt.opt = WEPOPT_HDWEP;
411 if (acx_set_wepopt_conf(sc, &wep_opt) != 0) {
412 if_printf(&sc->sc_ic.ic_if, "can't set wep opt\n");
413 return 1;
414 }
415 return 0;
416 }
417
418 static int
419 acx100_init_tmplt(struct acx_softc *sc)
420 {
421 struct acx_conf_mmap mem_map;
422
423 /* Set templates start address */
424 if (acx_get_mmap_conf(sc, &mem_map) != 0) {
425 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
426 return 1;
427 }
428
429 mem_map.pkt_tmplt_start = mem_map.wep_cache_end;
430 if (acx_set_mmap_conf(sc, &mem_map) != 0) {
431 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
432 return 1;
433 }
434
435 /* Initialize various packet templates */
436 if (acx_init_tmplt_ordered(sc) != 0) {
437 if_printf(&sc->sc_ic.ic_if, "can't init tmplt\n");
438 return 1;
439 }
440 return 0;
441 }
442
443 static int
444 acx100_init_fw_ring(struct acx_softc *sc)
445 {
446 struct acx100_conf_fw_ring ring;
447 struct acx_conf_mmap mem_map;
448 uint32_t txring_start, rxring_start, ring_end;
449
450 /* Set firmware descriptor ring start address */
451 if (acx_get_mmap_conf(sc, &mem_map) != 0) {
452 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
453 return 1;
454 }
455
456 txring_start = le32toh(mem_map.pkt_tmplt_end) + 4;
457 rxring_start = txring_start + ACX100_FW_TXRING_SIZE;
458 ring_end = rxring_start + ACX100_FW_RXRING_SIZE;
459
460 mem_map.fw_desc_start = htole32(txring_start);
461 if (acx_set_mmap_conf(sc, &mem_map) != 0) {
462 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
463 return 1;
464 }
465
466 /* Set firmware descriptor ring configure */
467 bzero(&ring, sizeof(ring));
468 ring.fw_ring_size = htole32(ACX100_FW_TXRING_SIZE +
469 ACX100_FW_RXRING_SIZE + 8);
470
471 ring.fw_txring_num = 1;
472 ring.fw_txring_addr = htole32(txring_start);
473 ring.fw_txring_prio = ACX100_TXRING_PRIO_DEFAULT;
474 ring.fw_txdesc_num = 0; /* XXX ignored?? */
475
476 ring.fw_rxring_addr = htole32(rxring_start);
477 ring.fw_rxdesc_num = 0; /* XXX ignored?? */
478
479 ring.opt = ACX100_RINGOPT_AUTO_RESET;
480 ACX100_SET_RING_END(&ring, ring_end);
481 if (acx100_set_fw_ring_conf(sc, &ring) != 0) {
482 if_printf(&sc->sc_ic.ic_if, "can't set fw ring configure\n");
483 return 1;
484 }
485
486 /* Setup firmware TX/RX descriptor ring */
487 acx100_init_fw_txring(sc, txring_start);
488 acx100_init_fw_rxring(sc, rxring_start);
489
490 return 0;
491 }
492
493 #define MEMBLK_ALIGN(addr) \
494 (((addr) + (ACX100_MEMBLK_ALIGN - 1)) & ~(ACX100_MEMBLK_ALIGN - 1))
495
496 static int
497 acx100_init_memory(struct acx_softc *sc)
498 {
499 struct acx100_conf_memblk_size memblk_sz;
500 struct acx100_conf_mem mem;
501 struct acx_conf_mmap mem_map;
502 uint32_t memblk_start, memblk_end;
503 int total_memblk, txblk_num, rxblk_num;
504
505 /* Set memory block start address */
506 if (acx_get_mmap_conf(sc, &mem_map) != 0) {
507 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
508 return 1;
509 }
510
511 mem_map.memblk_start =
512 htole32(MEMBLK_ALIGN(le32toh(mem_map.fw_desc_end) + 4));
513
514 if (acx_set_mmap_conf(sc, &mem_map) != 0) {
515 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
516 return 1;
517 }
518
519 /* Set memory block size */
520 memblk_sz.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
521 if (acx100_set_memblk_size_conf(sc, &memblk_sz) != 0) {
522 if_printf(&sc->sc_ic.ic_if, "can't set mem block size\n");
523 return 1;
524 }
525
526 /* Get memory map after setting it */
527 if (acx_get_mmap_conf(sc, &mem_map) != 0) {
528 if_printf(&sc->sc_ic.ic_if, "can't get mmap again\n");
529 return 1;
530 }
531 memblk_start = le32toh(mem_map.memblk_start);
532 memblk_end = le32toh(mem_map.memblk_end);
533
534 /* Set memory options */
535 mem.opt = htole32(ACX100_MEMOPT_MEMBLOCK | ACX100_MEMOPT_HOSTDESC);
536 mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
537
538 total_memblk = (memblk_end - memblk_start) / ACX_MEMBLOCK_SIZE;
539
540 rxblk_num = total_memblk / 2; /* 50% */
541 txblk_num = total_memblk - rxblk_num; /* 50% */
542
543 DPRINTF((&sc->sc_ic.ic_if, "\ttotal memory blocks\t%d\n"
544 "\trx memory blocks\t%d\n"
545 "\ttx memory blocks\t%d\n",
546 total_memblk, rxblk_num, txblk_num));
547
548 mem.rx_memblk_num = htole16(rxblk_num);
549 mem.tx_memblk_num = htole16(txblk_num);
550
551 mem.rx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start));
552 mem.tx_memblk_addr =
553 htole32(MEMBLK_ALIGN(memblk_start +
554 (ACX_MEMBLOCK_SIZE * rxblk_num)));
555
556 if (acx100_set_mem_conf(sc, &mem) != 0) {
557 if_printf(&sc->sc_ic.ic_if, "can't set mem options\n");
558 return 1;
559 }
560
561 /* Initialize memory */
562 if (acx_init_mem(sc) != 0) {
563 if_printf(&sc->sc_ic.ic_if, "can't init mem\n");
564 return 1;
565 }
566 return 0;
567 }
568
569 #undef MEMBLK_ALIGN
570
571 static void
572 acx100_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
573 {
574 struct acx_fw_txdesc fw_desc;
575 struct acx_txbuf *tx_buf;
576 uint32_t desc_paddr, fw_desc_offset;
577 int i;
578
579 bzero(&fw_desc, sizeof(fw_desc));
580 fw_desc.f_tx_ctrl = DESC_CTRL_HOSTOWN |
581 DESC_CTRL_RECLAIM |
582 DESC_CTRL_AUTODMA |
583 DESC_CTRL_FIRST_FRAG;
584
585 tx_buf = sc->sc_buf_data.tx_buf;
586 fw_desc_offset = fw_txdesc_start;
587 desc_paddr = sc->sc_ring_data.tx_ring_paddr;
588
589 for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
590 fw_desc.f_tx_host_desc = htole32(desc_paddr);
591
592 if (i == ACX_TX_DESC_CNT - 1) {
593 fw_desc.f_tx_next_desc = htole32(fw_txdesc_start);
594 } else {
595 fw_desc.f_tx_next_desc =
596 htole32(fw_desc_offset +
597 sizeof(struct acx_fw_txdesc));
598 }
599
600 tx_buf[i].tb_fwdesc_ofs = fw_desc_offset;
601 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
602 sizeof(fw_desc));
603
604 desc_paddr += (2 * sizeof(struct acx_host_desc));
605 fw_desc_offset += sizeof(fw_desc);
606 }
607 }
608
609 static void
610 acx100_init_fw_rxring(struct acx_softc *sc, uint32_t fw_rxdesc_start)
611 {
612 struct acx_fw_rxdesc fw_desc;
613 uint32_t fw_desc_offset;
614 int i;
615
616 bzero(&fw_desc, sizeof(fw_desc));
617 fw_desc.f_rx_ctrl = DESC_CTRL_RECLAIM | DESC_CTRL_AUTODMA;
618
619 fw_desc_offset = fw_rxdesc_start;
620
621 for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
622 if (i == ACX_RX_DESC_CNT - 1) {
623 fw_desc.f_rx_next_desc = htole32(fw_rxdesc_start);
624 } else {
625 fw_desc.f_rx_next_desc =
626 htole32(fw_desc_offset +
627 sizeof(struct acx_fw_rxdesc));
628 }
629
630 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
631 sizeof(fw_desc));
632
633 fw_desc_offset += sizeof(fw_desc);
634 }
635 }
636
637 static int
638 acx100_read_config(struct acx_softc *sc, struct acx_config *conf)
639 {
640 struct acx100_conf_cca_mode cca;
641 struct acx100_conf_ed_thresh ed;
642
643 /*
644 * NOTE:
645 * CCA mode and ED threshold MUST be read during initialization
646 * or the acx100 card won't work as expected
647 */
648
649 /* Get CCA mode */
650 if (acx100_get_cca_mode_conf(sc, &cca) != 0) {
651 if_printf(&sc->sc_ic.ic_if, "%s can't get cca mode\n",
652 __func__);
653 return ENXIO;
654 }
655 conf->cca_mode = cca.cca_mode;
656 DPRINTF((&sc->sc_ic.ic_if, "cca mode %02x\n", cca.cca_mode));
657
658 /* Get ED threshold */
659 if (acx100_get_ed_thresh_conf(sc, &ed) != 0) {
660 if_printf(&sc->sc_ic.ic_if, "%s can't get ed threshold\n",
661 __func__);
662 return ENXIO;
663 }
664 conf->ed_thresh = ed.ed_thresh;
665 DPRINTF((&sc->sc_ic.ic_if, "ed threshold %02x\n", ed.ed_thresh));
666
667 return 0;
668 }
669
670 static int
671 acx100_write_config(struct acx_softc *sc, struct acx_config *conf)
672 {
673 struct acx100_conf_cca_mode cca;
674 struct acx100_conf_ed_thresh ed;
675
676 /* Set CCA mode */
677 cca.cca_mode = conf->cca_mode;
678 if (acx100_set_cca_mode_conf(sc, &cca) != 0) {
679 if_printf(&sc->sc_ic.ic_if, "%s can't set cca mode\n",
680 __func__);
681 return ENXIO;
682 }
683
684 /* Set ED threshold */
685 ed.ed_thresh = conf->ed_thresh;
686 if (acx100_set_ed_thresh_conf(sc, &ed) != 0) {
687 if_printf(&sc->sc_ic.ic_if, "%s can't set ed threshold\n",
688 __func__);
689 return ENXIO;
690 }
691
692 /* Set TX power */
693 acx100_set_txpower(sc); /* ignore return value */
694
695 return 0;
696 }
697
698 static int
699 acx100_set_txpower(struct acx_softc *sc)
700 {
701 const uint8_t *map;
702
703 switch (sc->sc_radio_type) {
704 case ACX_RADIO_TYPE_MAXIM:
705 map = acx100_txpower_maxim;
706 break;
707 case ACX_RADIO_TYPE_RFMD:
708 case ACX_RADIO_TYPE_RALINK:
709 map = acx100_txpower_rfmd;
710 break;
711 default:
712 if_printf(&sc->sc_ic.ic_if, "TX power for radio type 0x%02x "
713 "can't be set yet\n", sc->sc_radio_type);
714 return 1;
715 }
716
717 acx_write_phyreg(sc, ACXRV_PHYREG_TXPOWER, map[ACX100_TXPOWER]);
718 return 0;
719 }
720
721 static uint8_t
722 acx100_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
723 struct ieee80211_node *ni, int data_len)
724 {
725 int rate;
726
727 tx_buf->tb_rateidx_len = 1;
728 if (ni == NULL) {
729 rate = 2; /* 1Mbit/s */
730 tx_buf->tb_rateidx[0] = 0;
731 } else {
732 ieee80211_ratectl_findrate(ni, data_len,
733 tx_buf->tb_rateidx, 1);
734 rate = IEEE80211_RS_RATE(&ni->ni_rates,
735 tx_buf->tb_rateidx[0]);
736 if (ACX100_CHK_RATE(&sc->sc_ic.ic_if, rate,
737 tx_buf->tb_rateidx[0]) < 0)
738 rate = 2;
739 }
740 FW_TXDESC_SETFIELD_1(sc, tx_buf, f_tx_rate100, ACX100_RATE(rate));
741
742 return rate;
743 }
744
745 static void
746 acx100_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
747 {
748 struct acx100_bss_join *bj = param;
749 struct ifnet *ifp = &sc->sc_ic.ic_if;
750 const struct ieee80211_rateset *rs = &sc->sc_ic.ic_bss->ni_rates;
751 int i;
752
753 bj->basic_rates = 0;
754 bj->op_rates = 0;
755 for (i = 0; i < rs->rs_nrates; ++i) {
756 u_int map_idx = IEEE80211_RS_RATE(rs, i);
757 uint8_t rate;
758
759 if (ACX100_CHK_RATE(ifp, map_idx, i) < 0)
760 continue;
761
762 rate = acx100_rate_map[map_idx];
763 if (rs->rs_rates[i] & IEEE80211_RATE_BASIC)
764 bj->basic_rates |= rate;
765 bj->op_rates |= rate;
766 }
767 DPRINTF((ifp, "basic rates:0x%02x, op rates:0x%02x\n",
768 bj->basic_rates, bj->op_rates));
769
770 bj->dtim_intvl = dtim_intvl;
771 }
772
773 static int
774 acx100_set_wepkey(struct acx_softc *sc, struct ieee80211_key *wk, int wk_idx)
775 {
776 struct acx100_conf_wepkey conf_wk;
777
778 if (wk->wk_keylen > ACX100_WEPKEY_LEN) {
779 if_printf(&sc->sc_ic.ic_if, "%dth WEP key size beyond %d\n",
780 wk_idx, ACX100_WEPKEY_LEN);
781 return EINVAL;
782 }
783
784 conf_wk.action = ACX100_WEPKEY_ACT_ADD;
785 conf_wk.key_len = wk->wk_keylen;
786 conf_wk.key_idx = wk_idx;
787 bcopy(wk->wk_key, conf_wk.key, wk->wk_keylen);
788 if (acx100_set_wepkey_conf(sc, &conf_wk) != 0) {
789 if_printf(&sc->sc_ic.ic_if, "%s set %dth WEP key failed\n",
790 __func__, wk_idx);
791 return ENXIO;
792 }
793 return 0;
794 }
795
796 static void
797 acx100_proc_wep_rxbuf(struct acx_softc *sc, struct mbuf *m, int *len)
798 {
799 int mac_hdrlen;
800 struct ieee80211_frame *f;
801
802 /*
803 * Strip leading IV and KID, and trailing CRC
804 */
805
806 f = mtod(m, struct ieee80211_frame *);
807
808 if ((f->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
809 mac_hdrlen = sizeof(struct ieee80211_frame_addr4);
810 else
811 mac_hdrlen = sizeof(struct ieee80211_frame);
812
813 #define IEEEWEP_IVLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
814 #define IEEEWEP_EXLEN (IEEEWEP_IVLEN + IEEE80211_WEP_CRCLEN)
815
816 *len = *len - IEEEWEP_EXLEN;
817
818 /* Move MAC header toward frame body */
819 ovbcopy(f, (uint8_t *)f + IEEEWEP_IVLEN, mac_hdrlen);
820 m_adj(m, IEEEWEP_IVLEN);
821
822 #undef IEEEWEP_EXLEN
823 #undef IEEEWEP_IVLEN
824 }
825
826 static void
827 acx100_tx_complete(struct acx_softc *sc, struct acx_txbuf *tx_buf,
828 int frame_len, int is_fail)
829 {
830 int rts_retries, data_retries;
831 struct ieee80211_ratectl_res rc_res;
832
833 rts_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_rts_nretry);
834 data_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_data_nretry);
835
836 rc_res.rc_res_rateidx = tx_buf->tb_rateidx[0];
837 rc_res.rc_res_tries = data_retries + 1;
838
839 ieee80211_ratectl_tx_complete(tx_buf->tb_node, frame_len,
840 &rc_res, 1, data_retries, rts_retries,
841 is_fail);
842 }
843
844 static void *
845 acx100_ratectl_attach(struct ieee80211com *ic, u_int rc)
846 {
847 struct acx_softc *sc = ic->ic_if.if_softc;
848
849 switch (rc) {
850 case IEEE80211_RATECTL_ONOE:
851 return &sc->sc_onoe_param;
852 case IEEE80211_RATECTL_NONE:
853 /* This could only happen during detaching */
854 return NULL;
855 default:
856 panic("unknown rate control algo %u", rc);
857 return NULL;
858 }
859 }
Cache object: b6ee80247514a3af6cb12c4670dc4408
|