This source file includes following definitions.
- acx100_set_param
- acx100_init
- acx100_init_wep
- acx100_init_tmplt
- acx100_init_fw_ring
- acx100_init_memory
- acx100_init_fw_txring
- acx100_init_fw_rxring
- acx100_read_config
- acx100_write_config
- acx100_set_txpower
- acx100_set_fw_txdesc_rate
- acx100_set_bss_join_param
- acx100_set_wepkey
- acx100_proc_wep_rxbuf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/mbuf.h>
56 #include <sys/endian.h>
57 #include <sys/socket.h>
58 #include <sys/sysctl.h>
59 #include <sys/device.h>
60
61 #include <machine/bus.h>
62
63 #include <net/if.h>
64 #include <net/if_arp.h>
65 #include <net/if_media.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 ACX100_CONF_FW_RING 0x0003
82 #define ACX100_CONF_MEMOPT 0x0005
83
84 #define ACX100_INTR_ENABLE (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
85
86
87
88
89
90
91 #define ACX100_INTR_DISABLE (uint16_t)~(ACXRV_INTR_UNKN)
92
93 #define ACX100_RATE(rate) ((rate) * 5)
94
95 #define ACX100_TXPOWER 18
96 #define ACX100_GPIO_POWER_LED 0x0800
97 #define ACX100_EE_EADDR_OFS 0x1a
98
99 #define ACX100_FW_TXRING_SIZE (ACX_TX_DESC_CNT * sizeof(struct acx_fw_txdesc))
100 #define ACX100_FW_RXRING_SIZE (ACX_RX_DESC_CNT * sizeof(struct acx_fw_rxdesc))
101
102 int acx100_init(struct acx_softc *);
103 int acx100_init_wep(struct acx_softc *);
104 int acx100_init_tmplt(struct acx_softc *);
105 int acx100_init_fw_ring(struct acx_softc *);
106 int acx100_init_memory(struct acx_softc *);
107 void acx100_init_fw_txring(struct acx_softc *, uint32_t);
108 void acx100_init_fw_rxring(struct acx_softc *, uint32_t);
109 int acx100_read_config(struct acx_softc *, struct acx_config *);
110 int acx100_write_config(struct acx_softc *, struct acx_config *);
111 int acx100_set_txpower(struct acx_softc *);
112 void acx100_set_fw_txdesc_rate(struct acx_softc *,
113 struct acx_txbuf *, int);
114 void acx100_set_bss_join_param(struct acx_softc *, void *, int);
115 int acx100_set_wepkey(struct acx_softc *, struct ieee80211_key *, int);
116 void acx100_proc_wep_rxbuf(struct acx_softc *, struct mbuf *, int *);
117
118
119
120
121
122 struct acx100_bss_join {
123 uint8_t dtim_intvl;
124 uint8_t basic_rates;
125 uint8_t all_rates;
126 } __packed;
127
128 struct acx100_conf_fw_ring {
129 struct acx_conf confcom;
130 uint32_t fw_ring_size;
131 uint32_t fw_rxring_addr;
132 uint8_t opt;
133 uint8_t fw_txring_num;
134 uint8_t fw_rxdesc_num;
135 uint8_t reserved0;
136 uint32_t fw_ring_end[2];
137 uint32_t fw_txring_addr;
138 uint8_t fw_txring_prio;
139 uint8_t fw_txdesc_num;
140 uint16_t reserved1;
141 } __packed;
142
143 #define ACX100_RINGOPT_AUTO_RESET 0x1
144 #define ACX100_TXRING_PRIO_DEFAULT 0
145 #define ACX100_SET_RING_END(conf, end) \
146 do { \
147 (conf)->fw_ring_end[0] = htole32(end); \
148 (conf)->fw_ring_end[1] = htole32(end + 8); \
149 } while (0)
150
151 struct acx100_conf_memblk_size {
152 struct acx_conf confcom;
153 uint16_t memblk_size;
154 } __packed;
155
156 struct acx100_conf_mem {
157 struct acx_conf confcom;
158 uint32_t opt;
159 uint32_t h_rxring_paddr;
160
161
162
163
164
165 uint32_t rx_memblk_addr;
166 uint32_t tx_memblk_addr;
167 uint16_t rx_memblk_num;
168 uint16_t tx_memblk_num;
169 } __packed;
170
171 #define ACX100_MEMOPT_MEM_INSTR 0x00000000
172 #define ACX100_MEMOPT_HOSTDESC 0x00010000
173 #define ACX100_MEMOPT_MEMBLOCK 0x00020000
174 #define ACX100_MEMOPT_IO_INSTR 0x00040000
175 #define ACX100_MEMOPT_PCICONF 0x00080000
176
177 #define ACX100_MEMBLK_ALIGN 0x20
178
179 struct acx100_conf_cca_mode {
180 struct acx_conf confcom;
181 uint8_t cca_mode;
182 uint8_t unknown;
183 } __packed;
184
185 struct acx100_conf_ed_thresh {
186 struct acx_conf confcom;
187 uint8_t ed_thresh;
188 uint8_t unknown[3];
189 } __packed;
190
191 struct acx100_conf_wepkey {
192 struct acx_conf confcom;
193 uint8_t action;
194 uint8_t key_len;
195 uint8_t key_idx;
196 #define ACX100_WEPKEY_LEN 29
197 uint8_t key[ACX100_WEPKEY_LEN];
198 } __packed;
199
200 #define ACX100_WEPKEY_ACT_ADD 1
201
202 static const uint16_t acx100_reg[ACXREG_MAX] = {
203 ACXREG(SOFT_RESET, 0x0000),
204
205 ACXREG(FWMEM_ADDR, 0x0014),
206 ACXREG(FWMEM_DATA, 0x0018),
207 ACXREG(FWMEM_CTRL, 0x001c),
208 ACXREG(FWMEM_START, 0x0020),
209
210 ACXREG(EVENT_MASK, 0x0034),
211
212 ACXREG(INTR_TRIG, 0x007c),
213 ACXREG(INTR_MASK, 0x0098),
214 ACXREG(INTR_STATUS, 0x00a4),
215 ACXREG(INTR_STATUS_CLR, 0x00a8),
216 ACXREG(INTR_ACK, 0x00ac),
217
218 ACXREG(HINTR_TRIG, 0x00b0),
219 ACXREG(RADIO_ENABLE, 0x0104),
220
221 ACXREG(EEPROM_INIT, 0x02d0),
222 ACXREG(EEPROM_CTRL, 0x0250),
223 ACXREG(EEPROM_ADDR, 0x0254),
224 ACXREG(EEPROM_DATA, 0x0258),
225 ACXREG(EEPROM_CONF, 0x025c),
226 ACXREG(EEPROM_INFO, 0x02ac),
227
228 ACXREG(PHY_ADDR, 0x0268),
229 ACXREG(PHY_DATA, 0x026c),
230 ACXREG(PHY_CTRL, 0x0270),
231
232 ACXREG(GPIO_OUT_ENABLE, 0x0290),
233 ACXREG(GPIO_OUT, 0x0298),
234
235 ACXREG(CMD_REG_OFFSET, 0x02a4),
236 ACXREG(INFO_REG_OFFSET, 0x02a8),
237
238 ACXREG(RESET_SENSE, 0x02d4),
239 ACXREG(ECPU_CTRL, 0x02d8)
240 };
241
242 static const uint8_t acx100_txpower_maxim[21] = {
243 63, 63, 63, 62,
244 61, 61, 60, 60,
245 59, 58, 57, 55,
246 53, 50, 47, 43,
247 38, 31, 23, 13,
248 0
249 };
250
251 static const uint8_t acx100_txpower_rfmd[21] = {
252 0, 0, 0, 1,
253 2, 2, 3, 3,
254 4, 5, 6, 8,
255 10, 13, 16, 20,
256 25, 32, 41, 50,
257 63
258 };
259
260 void
261 acx100_set_param(struct acx_softc *sc)
262 {
263 sc->chip_mem1_rid = PCIR_BAR(1);
264 sc->chip_mem2_rid = PCIR_BAR(2);
265 sc->chip_ioreg = acx100_reg;
266 sc->chip_hw_crypt = 1;
267 sc->chip_intr_enable = ACX100_INTR_ENABLE;
268 sc->chip_intr_disable = ACX100_INTR_DISABLE;
269 sc->chip_gpio_pled = ACX100_GPIO_POWER_LED;
270 sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS;
271 sc->chip_txdesc1_len = ACX_FRAME_HDRLEN;
272 sc->chip_fw_txdesc_ctrl = DESC_CTRL_AUTODMA |
273 DESC_CTRL_RECLAIM | DESC_CTRL_FIRST_FRAG;
274
275 sc->chip_phymode = IEEE80211_MODE_11B;
276 sc->chip_chan_flags = IEEE80211_CHAN_B;
277 sc->sc_ic.ic_phytype = IEEE80211_T_DS;
278 sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
279
280 sc->chip_init = acx100_init;
281 sc->chip_set_wepkey = acx100_set_wepkey;
282 sc->chip_read_config = acx100_read_config;
283 sc->chip_write_config = acx100_write_config;
284 sc->chip_set_fw_txdesc_rate = acx100_set_fw_txdesc_rate;
285 sc->chip_set_bss_join_param = acx100_set_bss_join_param;
286 sc->chip_proc_wep_rxbuf = acx100_proc_wep_rxbuf;
287 }
288
289 int
290 acx100_init(struct acx_softc *sc)
291 {
292 struct ifnet *ifp = &sc->sc_ic.ic_if;
293
294
295
296
297
298
299
300
301
302
303 if (acx100_init_wep(sc) != 0) {
304 printf("%s: %s can't initialize wep\n",
305 ifp->if_xname, __func__);
306 return (ENXIO);
307 }
308
309 if (acx100_init_tmplt(sc) != 0) {
310 printf("%s: %s can't initialize templates\n",
311 ifp->if_xname, __func__);
312 return (ENXIO);
313 }
314
315 if (acx100_init_fw_ring(sc) != 0) {
316 printf("%s: %s can't initialize fw ring\n",
317 ifp->if_xname, __func__);
318 return (ENXIO);
319 }
320
321 if (acx100_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 acx100_init_wep(struct acx_softc *sc)
332 {
333 struct acx_conf_wepopt wep_opt;
334 struct acx_conf_mmap mem_map;
335 struct ifnet *ifp = &sc->sc_ic.ic_if;
336
337
338 if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
339 printf("%s: can't get mmap\n", ifp->if_xname);
340 return (1);
341 }
342
343 mem_map.wep_cache_start = htole32(letoh32(mem_map.code_end) + 4);
344 mem_map.wep_cache_end = htole32(letoh32(mem_map.code_end) + 4);
345 if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
346 printf("%s: can't set mmap\n", ifp->if_xname);
347 return (1);
348 }
349
350
351 wep_opt.nkey = htole16(IEEE80211_WEP_NKID + 10);
352 wep_opt.opt = WEPOPT_HDWEP;
353 if (acx_set_conf(sc, ACX_CONF_WEPOPT, &wep_opt, sizeof(wep_opt)) != 0) {
354 printf("%s: can't set wep opt\n", ifp->if_xname);
355 return (1);
356 }
357
358 return (0);
359 }
360
361 int
362 acx100_init_tmplt(struct acx_softc *sc)
363 {
364 struct acx_conf_mmap mem_map;
365 struct ifnet *ifp = &sc->sc_ic.ic_if;
366
367
368 if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
369 printf("%s: can't get mmap\n", ifp->if_xname);
370 return (1);
371 }
372
373 mem_map.pkt_tmplt_start = mem_map.wep_cache_end;
374 if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
375 printf("%s: can't set mmap\n", ifp->if_xname);
376 return (1);
377 }
378
379
380 if (acx_init_tmplt_ordered(sc) != 0) {
381 printf("%s: can't init tmplt\n", ifp->if_xname);
382 return (1);
383 }
384
385 return (0);
386 }
387
388 int
389 acx100_init_fw_ring(struct acx_softc *sc)
390 {
391 struct acx100_conf_fw_ring ring;
392 struct acx_conf_mmap mem_map;
393 struct ifnet *ifp = &sc->sc_ic.ic_if;
394 uint32_t txring_start, rxring_start, ring_end;
395
396
397 if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
398 printf("%s: can't get mmap\n", ifp->if_xname);
399 return (1);
400 }
401
402 txring_start = letoh32(mem_map.pkt_tmplt_end) + 4;
403 rxring_start = txring_start + ACX100_FW_TXRING_SIZE;
404 ring_end = rxring_start + ACX100_FW_RXRING_SIZE;
405
406 mem_map.fw_desc_start = htole32(txring_start);
407 if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
408 printf("%s: can't set mmap\n", ifp->if_xname);
409 return (1);
410 }
411
412
413 bzero(&ring, sizeof(ring));
414 ring.fw_ring_size = htole32(ACX100_FW_TXRING_SIZE +
415 ACX100_FW_RXRING_SIZE + 8);
416
417 ring.fw_txring_num = 1;
418 ring.fw_txring_addr = htole32(txring_start);
419 ring.fw_txring_prio = ACX100_TXRING_PRIO_DEFAULT;
420 ring.fw_txdesc_num = 0;
421
422 ring.fw_rxring_addr = htole32(rxring_start);
423 ring.fw_rxdesc_num = 0;
424
425 ring.opt = ACX100_RINGOPT_AUTO_RESET;
426 ACX100_SET_RING_END(&ring, ring_end);
427 if (acx_set_conf(sc, ACX100_CONF_FW_RING, &ring, sizeof(ring)) != 0) {
428 printf("%s: can't set fw ring configure\n", ifp->if_xname);
429 return (1);
430 }
431
432
433 acx100_init_fw_txring(sc, txring_start);
434 acx100_init_fw_rxring(sc, rxring_start);
435
436 return (0);
437 }
438
439 #define MEMBLK_ALIGN(addr) \
440 (((addr) + (ACX100_MEMBLK_ALIGN - 1)) & ~(ACX100_MEMBLK_ALIGN - 1))
441
442 int
443 acx100_init_memory(struct acx_softc *sc)
444 {
445 struct acx100_conf_memblk_size memblk_sz;
446 struct acx100_conf_mem mem;
447 struct acx_conf_mmap mem_map;
448 struct ifnet *ifp = &sc->sc_ic.ic_if;
449 uint32_t memblk_start, memblk_end;
450 int total_memblk, txblk_num, rxblk_num;
451
452
453 if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
454 printf("%s: can't get mmap\n", ifp->if_xname);
455 return (1);
456 }
457
458 mem_map.memblk_start =
459 htole32(MEMBLK_ALIGN(letoh32(mem_map.fw_desc_end) + 4));
460
461 if (acx_set_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
462 printf("%s: can't set mmap\n", ifp->if_xname);
463 return (1);
464 }
465
466
467 memblk_sz.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
468 if (acx_set_conf(sc, ACX_CONF_MEMBLK_SIZE, &memblk_sz,
469 sizeof(memblk_sz)) != 0) {
470 printf("%s: can't set mem block size\n", ifp->if_xname);
471 return (1);
472 }
473
474
475 if (acx_get_conf(sc, ACX_CONF_MMAP, &mem_map, sizeof(mem_map)) != 0) {
476 printf("%s: can't get mmap again\n", ifp->if_xname);
477 return (1);
478 }
479 memblk_start = letoh32(mem_map.memblk_start);
480 memblk_end = letoh32(mem_map.memblk_end);
481
482
483 mem.opt = htole32(ACX100_MEMOPT_MEMBLOCK | ACX100_MEMOPT_HOSTDESC);
484 mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
485
486 total_memblk = (memblk_end - memblk_start) / ACX_MEMBLOCK_SIZE;
487
488 rxblk_num = total_memblk / 2;
489 txblk_num = total_memblk - rxblk_num;
490
491 DPRINTF(("%s: \ttotal memory blocks\t%d\n"
492 "\trx memory blocks\t%d\n"
493 "\ttx memory blocks\t%d\n",
494 ifp->if_xname, total_memblk, rxblk_num, txblk_num));
495
496 mem.rx_memblk_num = htole16(rxblk_num);
497 mem.tx_memblk_num = htole16(txblk_num);
498
499 mem.rx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start));
500 mem.tx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start +
501 (ACX_MEMBLOCK_SIZE * rxblk_num)));
502
503 if (acx_set_conf(sc, ACX100_CONF_MEMOPT, &mem, sizeof(mem)) != 0) {
504 printf("%s: can't set mem options\n", ifp->if_xname);
505 return (1);
506 }
507
508
509 if (acx_exec_command(sc, ACXCMD_INIT_MEM, NULL, 0, NULL, 0) != 0) {
510 printf("%s: can't init mem\n", ifp->if_xname);
511 return (1);
512 }
513
514 return (0);
515 }
516
517 #undef MEMBLK_ALIGN
518
519 void
520 acx100_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
521 {
522 struct acx_fw_txdesc fw_desc;
523 struct acx_txbuf *tx_buf;
524 uint32_t desc_paddr, fw_desc_offset;
525 int i;
526
527 bzero(&fw_desc, sizeof(fw_desc));
528 fw_desc.f_tx_ctrl = DESC_CTRL_HOSTOWN | DESC_CTRL_RECLAIM |
529 DESC_CTRL_AUTODMA | DESC_CTRL_FIRST_FRAG;
530
531 tx_buf = sc->sc_buf_data.tx_buf;
532 fw_desc_offset = fw_txdesc_start;
533 desc_paddr = sc->sc_ring_data.tx_ring_paddr;
534
535 for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
536 fw_desc.f_tx_host_desc = htole32(desc_paddr);
537
538 if (i == ACX_TX_DESC_CNT - 1) {
539 fw_desc.f_tx_next_desc = htole32(fw_txdesc_start);
540 } else {
541 fw_desc.f_tx_next_desc = htole32(fw_desc_offset +
542 sizeof(struct acx_fw_txdesc));
543 }
544
545 tx_buf[i].tb_fwdesc_ofs = fw_desc_offset;
546 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
547 sizeof(fw_desc));
548
549 desc_paddr += (2 * sizeof(struct acx_host_desc));
550 fw_desc_offset += sizeof(fw_desc);
551 }
552 }
553
554 void
555 acx100_init_fw_rxring(struct acx_softc *sc, uint32_t fw_rxdesc_start)
556 {
557 struct acx_fw_rxdesc fw_desc;
558 uint32_t fw_desc_offset;
559 int i;
560
561 bzero(&fw_desc, sizeof(fw_desc));
562 fw_desc.f_rx_ctrl = DESC_CTRL_RECLAIM | DESC_CTRL_AUTODMA;
563
564 fw_desc_offset = fw_rxdesc_start;
565
566 for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
567 if (i == ACX_RX_DESC_CNT - 1) {
568 fw_desc.f_rx_next_desc = htole32(fw_rxdesc_start);
569 } else {
570 fw_desc.f_rx_next_desc =
571 htole32(fw_desc_offset +
572 sizeof(struct acx_fw_rxdesc));
573 }
574
575 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
576 sizeof(fw_desc));
577
578 fw_desc_offset += sizeof(fw_desc);
579 }
580 }
581
582 int
583 acx100_read_config(struct acx_softc *sc, struct acx_config *conf)
584 {
585 struct acx100_conf_cca_mode cca;
586 struct acx100_conf_ed_thresh ed;
587 struct ifnet *ifp = &sc->sc_ic.ic_if;
588
589
590
591
592
593
594
595
596 if (acx_get_conf(sc, ACX_CONF_CCA_MODE, &cca, sizeof(cca)) != 0) {
597 printf("%s: %s can't get cca mode\n",
598 ifp->if_xname, __func__);
599 return (ENXIO);
600 }
601 conf->cca_mode = cca.cca_mode;
602 DPRINTF(("%s: cca mode %02x\n", ifp->if_xname, cca.cca_mode));
603
604
605 if (acx_get_conf(sc, ACX_CONF_ED_THRESH, &ed, sizeof(ed)) != 0) {
606 printf("%s: %s can't get ed threshold\n",
607 ifp->if_xname, __func__);
608 return (ENXIO);
609 }
610 conf->ed_thresh = ed.ed_thresh;
611 DPRINTF(("%s: ed threshold %02x\n", ifp->if_xname, ed.ed_thresh));
612
613 return (0);
614 }
615
616 int
617 acx100_write_config(struct acx_softc *sc, struct acx_config *conf)
618 {
619 struct acx100_conf_cca_mode cca;
620 struct acx100_conf_ed_thresh ed;
621 struct ifnet *ifp = &sc->sc_ic.ic_if;
622
623
624 cca.cca_mode = conf->cca_mode;
625 if (acx_set_conf(sc, ACX_CONF_CCA_MODE, &cca, sizeof(cca)) != 0) {
626 printf("%s: %s can't set cca mode\n",
627 ifp->if_xname, __func__);
628 return (ENXIO);
629 }
630
631
632 ed.ed_thresh = conf->ed_thresh;
633 if (acx_set_conf(sc, ACX_CONF_ED_THRESH, &ed, sizeof(ed)) != 0) {
634 printf("%s: %s can't set ed threshold\n",
635 ifp->if_xname, __func__);
636 return (ENXIO);
637 }
638
639
640 acx100_set_txpower(sc);
641
642 return (0);
643 }
644
645 int
646 acx100_set_txpower(struct acx_softc *sc)
647 {
648 struct ifnet *ifp = &sc->sc_ic.ic_if;
649 const uint8_t *map;
650
651 switch (sc->sc_radio_type) {
652 case ACX_RADIO_TYPE_MAXIM:
653 map = acx100_txpower_maxim;
654 break;
655 case ACX_RADIO_TYPE_RFMD:
656 case ACX_RADIO_TYPE_RALINK:
657 map = acx100_txpower_rfmd;
658 break;
659 default:
660 printf("%s: TX power for radio type 0x%02x can't be set yet\n",
661 ifp->if_xname, sc->sc_radio_type);
662 return (1);
663 }
664
665 acx_write_phyreg(sc, ACXRV_PHYREG_TXPOWER, map[ACX100_TXPOWER]);
666
667 return (0);
668 }
669
670 void
671 acx100_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
672 int rate)
673 {
674 FW_TXDESC_SETFIELD_1(sc, tx_buf, f_tx_rate100, ACX100_RATE(rate));
675 }
676
677 void
678 acx100_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
679 {
680 struct acx100_bss_join *bj = param;
681
682 bj->dtim_intvl = dtim_intvl;
683 bj->basic_rates = 15;
684 bj->all_rates = 31;
685 }
686
687 int
688 acx100_set_wepkey(struct acx_softc *sc, struct ieee80211_key *k, int k_idx)
689 {
690 struct acx100_conf_wepkey conf_wk;
691 struct ifnet *ifp = &sc->sc_ic.ic_if;
692
693 if (k->k_len > ACX100_WEPKEY_LEN) {
694 printf("%s: %dth WEP key size beyond %d\n",
695 ifp->if_xname, k_idx, ACX100_WEPKEY_LEN);
696 return EINVAL;
697 }
698
699 conf_wk.action = ACX100_WEPKEY_ACT_ADD;
700 conf_wk.key_len = k->k_len;
701 conf_wk.key_idx = k_idx;
702 bcopy(k->k_key, conf_wk.key, k->k_len);
703 if (acx_set_conf(sc, ACX_CONF_WEPKEY, &conf_wk, sizeof(conf_wk)) != 0) {
704 printf("%s: %s set %dth WEP key failed\n",
705 ifp->if_xname, __func__, k_idx);
706 return ENXIO;
707 }
708 return 0;
709 }
710
711 void
712 acx100_proc_wep_rxbuf(struct acx_softc *sc, struct mbuf *m, int *len)
713 {
714 int mac_hdrlen;
715 struct ieee80211_frame *f;
716
717
718
719
720 f = mtod(m, struct ieee80211_frame *);
721
722 if ((f->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
723 mac_hdrlen = sizeof(struct ieee80211_frame_addr4);
724 else
725 mac_hdrlen = sizeof(struct ieee80211_frame);
726
727 #define IEEEWEP_IVLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
728 #define IEEEWEP_EXLEN (IEEEWEP_IVLEN + IEEE80211_WEP_CRCLEN)
729
730 *len = *len - IEEEWEP_EXLEN;
731
732
733 ovbcopy(f, (uint8_t *)f + IEEEWEP_IVLEN, mac_hdrlen);
734 m_adj(m, IEEEWEP_IVLEN);
735
736 #undef IEEEWEP_EXLEN
737 #undef IEEEWEP_IVLEN
738 }