ba9edfc736bec37e83f730cc9923d604c21accae
[dragonfly.git] / sys / dev / netif / acx / acx100.c
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  * $DragonFly: src/sys/dev/netif/acx/acx100.c,v 1.5 2006/10/25 20:55:55 dillon Exp $
35  */
36
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/endian.h>
40 #include <sys/rman.h>
41 #include <sys/socket.h>
42 #include <sys/sysctl.h>
43
44 #include <net/if.h>
45 #include <net/if_arp.h>
46 #include <net/if_media.h>
47
48 #include <netproto/802_11/ieee80211.h>
49 #include <netproto/802_11/ieee80211_var.h>
50
51 #include <bus/pci/pcireg.h>
52
53 #define ACX_DEBUG
54
55 #include "if_acxreg.h"
56 #include "if_acxvar.h"
57 #include "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_TXPOWER          18
74 #define ACX100_GPIO_POWER_LED   0x0800
75 #define ACX100_EE_EADDR_OFS     0x1a
76
77 #define ACX100_FW_TXRING_SIZE   (ACX_TX_DESC_CNT * sizeof(struct acx_fw_txdesc))
78 #define ACX100_FW_RXRING_SIZE   (ACX_RX_DESC_CNT * sizeof(struct acx_fw_rxdesc))
79
80 /*
81  * NOTE:
82  * Following structs' fields are little endian
83  */
84
85 struct acx100_bss_join {
86         uint8_t dtim_intvl;
87         uint8_t basic_rates;
88         uint8_t all_rates;
89 } __packed;
90
91 struct acx100_conf_fw_ring {
92         struct acx_conf confcom;
93         uint32_t        fw_ring_size;   /* total size of fw (tx + rx) ring */
94         uint32_t        fw_rxring_addr; /* start phyaddr of fw rx desc */
95         uint8_t         opt;            /* see ACX100_RINGOPT_ */
96         uint8_t         fw_txring_num;  /* num of TX ring */
97         uint8_t         fw_rxdesc_num;  /* num of fw rx desc */
98         uint8_t         reserved0;
99         uint32_t        fw_ring_end[2]; /* see ACX100_SET_RING_END() */
100         uint32_t        fw_txring_addr; /* start phyaddr of fw tx desc */
101         uint8_t         fw_txring_prio; /* see ACX100_TXRING_PRIO_ */
102         uint8_t         fw_txdesc_num;  /* num of fw tx desc */
103         uint16_t        reserved1;
104 } __packed;
105
106 #define ACX100_RINGOPT_AUTO_RESET       0x1
107 #define ACX100_TXRING_PRIO_DEFAULT      0
108 #define ACX100_SET_RING_END(conf, end)                  \
109 do {                                                    \
110         (conf)->fw_ring_end[0] = htole32(end);          \
111         (conf)->fw_ring_end[1] = htole32(end + 8);      \
112 } while (0)
113
114 struct acx100_conf_memblk_size {
115         struct acx_conf confcom;
116         uint16_t        memblk_size;    /* size of each mem block */
117 } __packed;
118
119 struct acx100_conf_mem {
120         struct acx_conf confcom;
121         uint32_t        opt;            /* see ACX100_MEMOPT_ */
122         uint32_t        h_rxring_paddr; /* host rx desc start phyaddr */
123
124         /*
125          * Memory blocks are controled by hardware
126          * once after they are initialized
127          */
128         uint32_t        rx_memblk_addr; /* start addr of rx mem blocks */
129         uint32_t        tx_memblk_addr; /* start addr of tx mem blocks */
130         uint16_t        rx_memblk_num;  /* num of RX mem block */
131         uint16_t        tx_memblk_num;  /* num of TX mem block */
132 } __packed;
133
134 #define ACX100_MEMOPT_MEM_INSTR         0x00000000 /* memory access instruct */
135 #define ACX100_MEMOPT_HOSTDESC          0x00010000 /* host indirect desc */
136 #define ACX100_MEMOPT_MEMBLOCK          0x00020000 /* local mem block list */
137 #define ACX100_MEMOPT_IO_INSTR          0x00040000 /* IO instruct */
138 #define ACX100_MEMOPT_PCICONF           0x00080000 /* PCI conf space */
139
140 #define ACX100_MEMBLK_ALIGN             0x20
141
142 struct acx100_conf_cca_mode {
143         struct acx_conf confcom;
144         uint8_t         cca_mode;
145         uint8_t         unknown;
146 } __packed;
147
148 struct acx100_conf_ed_thresh {
149         struct acx_conf confcom;
150         uint8_t         ed_thresh;
151         uint8_t         unknown[3];
152 } __packed;
153
154 struct acx100_conf_wepkey {
155         struct acx_conf confcom;
156         uint8_t         action; /* see ACX100_WEPKEY_ACT_ */
157         uint8_t         key_len;
158         uint8_t         key_idx;
159 #define ACX100_WEPKEY_LEN       29
160         uint8_t         key[ACX100_WEPKEY_LEN];
161 } __packed;
162
163 #define ACX100_WEPKEY_ACT_ADD   1
164
165 #define ACX100_CONF_FUNC(sg, name)      _ACX_CONF_FUNC(sg, name, 100)
166 #define ACX_CONF_fw_ring                ACX100_CONF_FW_RING
167 #define ACX_CONF_memblk_size            ACX_CONF_MEMBLK_SIZE
168 #define ACX_CONF_mem                    ACX100_CONF_MEMOPT
169 #define ACX_CONF_cca_mode               ACX_CONF_CCA_MODE
170 #define ACX_CONF_ed_thresh              ACX_CONF_ED_THRESH
171 #define ACX_CONF_wepkey                 ACX_CONF_WEPKEY
172 ACX100_CONF_FUNC(set, fw_ring);
173 ACX100_CONF_FUNC(set, memblk_size);
174 ACX100_CONF_FUNC(set, mem);
175 ACX100_CONF_FUNC(get, cca_mode);
176 ACX100_CONF_FUNC(set, cca_mode);
177 ACX100_CONF_FUNC(get, ed_thresh);
178 ACX100_CONF_FUNC(set, ed_thresh);
179 ACX100_CONF_FUNC(set, wepkey);
180
181 #define ACXCMD_init_mem                 ACXCMD_INIT_MEM
182 ACX_NOARG_FUNC(init_mem);
183
184 static const uint16_t   acx100_reg[ACXREG_MAX] = {
185         ACXREG(SOFT_RESET,              0x0000),
186
187         ACXREG(FWMEM_ADDR,              0x0014),
188         ACXREG(FWMEM_DATA,              0x0018),
189         ACXREG(FWMEM_CTRL,              0x001c),
190         ACXREG(FWMEM_START,             0x0020),
191
192         ACXREG(EVENT_MASK,              0x0034),
193
194         ACXREG(INTR_TRIG,               0x007c),
195         ACXREG(INTR_MASK,               0x0098),
196         ACXREG(INTR_STATUS,             0x00a4),
197         ACXREG(INTR_STATUS_CLR,         0x00a8),
198         ACXREG(INTR_ACK,                0x00ac),
199
200         ACXREG(HINTR_TRIG,              0x00b0),
201         ACXREG(RADIO_ENABLE,            0x0104),
202
203         ACXREG(EEPROM_INIT,             0x02d0),
204         ACXREG(EEPROM_CTRL,             0x0250),
205         ACXREG(EEPROM_ADDR,             0x0254),
206         ACXREG(EEPROM_DATA,             0x0258),
207         ACXREG(EEPROM_CONF,             0x025c),
208         ACXREG(EEPROM_INFO,             0x02ac),
209
210         ACXREG(PHY_ADDR,                0x0268),
211         ACXREG(PHY_DATA,                0x026c),
212         ACXREG(PHY_CTRL,                0x0270),
213
214         ACXREG(GPIO_OUT_ENABLE,         0x0290),
215         ACXREG(GPIO_OUT,                0x0298),
216
217         ACXREG(CMD_REG_OFFSET,          0x02a4),
218         ACXREG(INFO_REG_OFFSET,         0x02a8),
219
220         ACXREG(RESET_SENSE,             0x02d4),
221         ACXREG(ECPU_CTRL,               0x02d8) 
222 };
223
224 static const uint8_t    acx100_txpower_maxim[21] = {
225         63, 63, 63, 62,
226         61, 61, 60, 60,
227         59, 58, 57, 55,
228         53, 50, 47, 43,
229         38, 31, 23, 13,
230         0
231 };
232
233 static const uint8_t    acx100_txpower_rfmd[21] = {
234          0,  0,  0,  1,
235          2,  2,  3,  3,
236          4,  5,  6,  8,
237         10, 13, 16, 20,
238         25, 32, 41, 50,
239         63
240 };
241
242 static int      acx100_init(struct acx_softc *);
243 static int      acx100_init_wep(struct acx_softc *);
244 static int      acx100_init_tmplt(struct acx_softc *);
245 static int      acx100_init_fw_ring(struct acx_softc *);
246 static int      acx100_init_memory(struct acx_softc *);
247
248 static void     acx100_init_fw_txring(struct acx_softc *, uint32_t);
249 static void     acx100_init_fw_rxring(struct acx_softc *, uint32_t);
250
251 static int      acx100_read_config(struct acx_softc *, struct acx_config *);
252 static int      acx100_write_config(struct acx_softc *, struct acx_config *);
253
254 static int      acx100_set_txpower(struct acx_softc *);
255
256 static void     acx100_set_fw_txdesc_rate(struct acx_softc *,
257                                           struct acx_txbuf *,
258                                           struct ieee80211_node *, int);
259 static void     acx100_tx_complete(struct acx_softc *, struct acx_txbuf *,
260                                    int, int);
261 static void     acx100_set_bss_join_param(struct acx_softc *, void *, int);
262
263 static int      acx100_set_wepkey(struct acx_softc *, struct ieee80211_key *,
264                                   int);
265
266 static void     acx100_proc_wep_rxbuf(struct acx_softc *, struct mbuf *, int *);
267
268 void
269 acx100_set_param(device_t dev)
270 {
271         struct acx_softc *sc = device_get_softc(dev);
272         struct ieee80211com *ic = &sc->sc_ic;
273
274         sc->chip_mem1_rid = PCIR_BAR(1);
275         sc->chip_mem2_rid = PCIR_BAR(2);
276         sc->chip_ioreg = acx100_reg;
277         sc->chip_hw_crypt = 1;
278         sc->chip_intr_enable = ACX100_INTR_ENABLE;
279         sc->chip_intr_disable = ACX100_INTR_DISABLE;
280         sc->chip_gpio_pled = ACX100_GPIO_POWER_LED;
281         sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS;
282         sc->chip_txdesc1_len = ACX_FRAME_HDRLEN;
283         sc->chip_fw_txdesc_ctrl = DESC_CTRL_AUTODMA |
284                                   DESC_CTRL_RECLAIM |
285                                   DESC_CTRL_FIRST_FRAG;
286         sc->chip_short_retry_limit = 7;
287
288         sc->chip_phymode = IEEE80211_MODE_11B;
289         sc->chip_chan_flags = IEEE80211_CHAN_B;
290
291         ic->ic_phytype = IEEE80211_T_DS;
292         ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b;
293
294         ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE;
295         ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE;
296
297         sc->chip_init = acx100_init;
298         sc->chip_set_wepkey = acx100_set_wepkey;
299         sc->chip_read_config = acx100_read_config;
300         sc->chip_write_config = acx100_write_config;
301         sc->chip_set_fw_txdesc_rate = acx100_set_fw_txdesc_rate;
302         sc->chip_tx_complete = acx100_tx_complete;
303         sc->chip_set_bss_join_param = acx100_set_bss_join_param;
304         sc->chip_proc_wep_rxbuf = acx100_proc_wep_rxbuf;
305 }
306
307 static int
308 acx100_init(struct acx_softc *sc)
309 {
310         /*
311          * NOTE:
312          * Order of initialization:
313          * 1) WEP
314          * 2) Templates
315          * 3) Firmware TX/RX ring
316          * 4) Hardware memory
317          * Above order is critical to get a correct memory map
318          */
319
320         if (acx100_init_wep(sc) != 0) {
321                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize wep\n",
322                           __func__);
323                 return ENXIO;
324         }
325
326         if (acx100_init_tmplt(sc) != 0) {
327                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize templates\n",
328                           __func__);
329                 return ENXIO;
330         }
331
332         if (acx100_init_fw_ring(sc) != 0) {
333                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize fw ring\n",
334                           __func__);
335                 return ENXIO;
336         }
337
338         if (acx100_init_memory(sc) != 0) {
339                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize hw memory\n",
340                           __func__);
341                 return ENXIO;
342         }
343         return 0;
344 }
345
346 static int
347 acx100_init_wep(struct acx_softc *sc)
348 {
349         struct acx_conf_wepopt wep_opt;
350         struct acx_conf_mmap mem_map;
351
352         /* Set WEP cache start/end address */
353         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
354                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
355                 return 1;
356         }
357
358         mem_map.wep_cache_start = htole32(le32toh(mem_map.code_end) + 4);
359         mem_map.wep_cache_end = htole32(le32toh(mem_map.code_end) + 4);
360         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
361                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
362                 return 1;
363         }
364
365         /* Set WEP options */
366         wep_opt.nkey = htole16(IEEE80211_WEP_NKID + 10);
367         wep_opt.opt = WEPOPT_HDWEP;
368         if (acx_set_wepopt_conf(sc, &wep_opt) != 0) {
369                 if_printf(&sc->sc_ic.ic_if, "can't set wep opt\n");
370                 return 1;
371         }
372         return 0;
373 }
374
375 static int
376 acx100_init_tmplt(struct acx_softc *sc)
377 {
378         struct acx_conf_mmap mem_map;
379         struct acx_tmplt_tim tim;
380
381         /* Set templates start address */
382         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
383                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
384                 return 1;
385         }
386
387         mem_map.pkt_tmplt_start = mem_map.wep_cache_end;
388         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
389                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
390                 return 1;
391         }
392
393         /* Initialize various packet templates */
394         if (acx_init_tmplt_ordered(sc) != 0) {
395                 if_printf(&sc->sc_ic.ic_if, "can't init tmplt\n");
396                 return 1;
397         }
398
399         /* Setup TIM template */
400         bzero(&tim, sizeof(tim));
401         tim.tim_eid = IEEE80211_ELEMID_TIM;
402         tim.tim_len = ACX_TIM_LEN(ACX_TIM_BITMAP_LEN);
403         if (_acx_set_tim_tmplt(sc, &tim,
404                                ACX_TMPLT_TIM_SIZ(ACX_TIM_BITMAP_LEN)) != 0) {
405                 if_printf(&sc->sc_ic.ic_if, "can't set tim tmplt\n");
406                 return 1;
407         }
408         return 0;
409 }
410
411 static int
412 acx100_init_fw_ring(struct acx_softc *sc)
413 {
414         struct acx100_conf_fw_ring ring;
415         struct acx_conf_mmap mem_map;
416         uint32_t txring_start, rxring_start, ring_end;
417
418         /* Set firmware descriptor ring start address */
419         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
420                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
421                 return 1;
422         }
423
424         txring_start = le32toh(mem_map.pkt_tmplt_end) + 4;
425         rxring_start = txring_start + ACX100_FW_TXRING_SIZE;
426         ring_end = rxring_start + ACX100_FW_RXRING_SIZE;
427
428         mem_map.fw_desc_start = htole32(txring_start);
429         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
430                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
431                 return 1;
432         }
433
434         /* Set firmware descriptor ring configure */
435         bzero(&ring, sizeof(ring));
436         ring.fw_ring_size = htole32(ACX100_FW_TXRING_SIZE +
437                                     ACX100_FW_RXRING_SIZE + 8);
438
439         ring.fw_txring_num = 1;
440         ring.fw_txring_addr = htole32(txring_start);
441         ring.fw_txring_prio = ACX100_TXRING_PRIO_DEFAULT;
442         ring.fw_txdesc_num = 0; /* XXX ignored?? */
443
444         ring.fw_rxring_addr = htole32(rxring_start);
445         ring.fw_rxdesc_num = 0; /* XXX ignored?? */
446
447         ring.opt = ACX100_RINGOPT_AUTO_RESET;
448         ACX100_SET_RING_END(&ring, ring_end);
449         if (acx100_set_fw_ring_conf(sc, &ring) != 0) {
450                 if_printf(&sc->sc_ic.ic_if, "can't set fw ring configure\n");
451                 return 1;
452         }
453
454         /* Setup firmware TX/RX descriptor ring */
455         acx100_init_fw_txring(sc, txring_start);
456         acx100_init_fw_rxring(sc, rxring_start);
457
458         return 0;
459 }
460
461 #define MEMBLK_ALIGN(addr)      \
462         (((addr) + (ACX100_MEMBLK_ALIGN - 1)) & ~(ACX100_MEMBLK_ALIGN - 1))
463
464 static int
465 acx100_init_memory(struct acx_softc *sc)
466 {
467         struct acx100_conf_memblk_size memblk_sz;
468         struct acx100_conf_mem mem;
469         struct acx_conf_mmap mem_map;
470         uint32_t memblk_start, memblk_end;
471         int total_memblk, txblk_num, rxblk_num;
472
473         /* Set memory block start address */
474         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
475                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
476                 return 1;
477         }
478
479         mem_map.memblk_start =
480                 htole32(MEMBLK_ALIGN(le32toh(mem_map.fw_desc_end) + 4));
481
482         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
483                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
484                 return 1;
485         }
486
487         /* Set memory block size */
488         memblk_sz.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
489         if (acx100_set_memblk_size_conf(sc, &memblk_sz) != 0) {
490                 if_printf(&sc->sc_ic.ic_if, "can't set mem block size\n");
491                 return 1;
492         }
493
494         /* Get memory map after setting it */
495         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
496                 if_printf(&sc->sc_ic.ic_if, "can't get mmap again\n");
497                 return 1;
498         }
499         memblk_start = le32toh(mem_map.memblk_start);
500         memblk_end = le32toh(mem_map.memblk_end);
501
502         /* Set memory options */
503         mem.opt = htole32(ACX100_MEMOPT_MEMBLOCK | ACX100_MEMOPT_HOSTDESC);
504         mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
505
506         total_memblk = (memblk_end - memblk_start) / ACX_MEMBLOCK_SIZE;
507
508         rxblk_num = total_memblk / 2;           /* 50% */
509         txblk_num = total_memblk - rxblk_num;   /* 50% */
510
511         DPRINTF((&sc->sc_ic.ic_if, "\ttotal memory blocks\t%d\n"
512                                    "\trx memory blocks\t%d\n"
513                                    "\ttx memory blocks\t%d\n",
514                                    total_memblk, rxblk_num, txblk_num));
515
516         mem.rx_memblk_num = htole16(rxblk_num);
517         mem.tx_memblk_num = htole16(txblk_num);
518
519         mem.rx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start));
520         mem.tx_memblk_addr =
521                 htole32(MEMBLK_ALIGN(memblk_start +
522                                      (ACX_MEMBLOCK_SIZE * rxblk_num)));
523
524         if (acx100_set_mem_conf(sc, &mem) != 0) {
525                 if_printf(&sc->sc_ic.ic_if, "can't set mem options\n");
526                 return 1;
527         }
528
529         /* Initialize memory */
530         if (acx_init_mem(sc) != 0) {
531                 if_printf(&sc->sc_ic.ic_if, "can't init mem\n");
532                 return 1;
533         }
534         return 0;
535 }
536
537 #undef MEMBLK_ALIGN
538
539 static void
540 acx100_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
541 {
542         struct acx_fw_txdesc fw_desc;
543         struct acx_txbuf *tx_buf;
544         uint32_t desc_paddr, fw_desc_offset;
545         int i;
546
547         bzero(&fw_desc, sizeof(fw_desc));
548         fw_desc.f_tx_ctrl = DESC_CTRL_HOSTOWN |
549                             DESC_CTRL_RECLAIM |
550                             DESC_CTRL_AUTODMA |
551                             DESC_CTRL_FIRST_FRAG;
552
553         tx_buf = sc->sc_buf_data.tx_buf;
554         fw_desc_offset = fw_txdesc_start;
555         desc_paddr = sc->sc_ring_data.tx_ring_paddr;
556
557         for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
558                 fw_desc.f_tx_host_desc = htole32(desc_paddr);
559
560                 if (i == ACX_TX_DESC_CNT - 1) {
561                         fw_desc.f_tx_next_desc = htole32(fw_txdesc_start);
562                 } else {
563                         fw_desc.f_tx_next_desc =
564                                 htole32(fw_desc_offset +
565                                         sizeof(struct acx_fw_txdesc));
566                 }
567
568                 tx_buf[i].tb_fwdesc_ofs = fw_desc_offset;
569                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
570                                     sizeof(fw_desc));
571
572                 desc_paddr += (2 * sizeof(struct acx_host_desc));
573                 fw_desc_offset += sizeof(fw_desc);
574         }
575 }
576
577 static void
578 acx100_init_fw_rxring(struct acx_softc *sc, uint32_t fw_rxdesc_start)
579 {
580         struct acx_fw_rxdesc fw_desc;
581         uint32_t fw_desc_offset;
582         int i;
583
584         bzero(&fw_desc, sizeof(fw_desc));
585         fw_desc.f_rx_ctrl = DESC_CTRL_RECLAIM | DESC_CTRL_AUTODMA;
586
587         fw_desc_offset = fw_rxdesc_start;
588
589         for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
590                 if (i == ACX_RX_DESC_CNT - 1) {
591                         fw_desc.f_rx_next_desc = htole32(fw_rxdesc_start);
592                 } else {
593                         fw_desc.f_rx_next_desc =
594                                 htole32(fw_desc_offset +
595                                         sizeof(struct acx_fw_rxdesc));
596                 }
597
598                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
599                                     sizeof(fw_desc));
600
601                 fw_desc_offset += sizeof(fw_desc);
602         }
603 }
604
605 static int
606 acx100_read_config(struct acx_softc *sc, struct acx_config *conf)
607 {
608         struct acx100_conf_cca_mode cca;
609         struct acx100_conf_ed_thresh ed;
610
611         /*
612          * NOTE:
613          * CCA mode and ED threshold MUST be read during initialization
614          * or the acx100 card won't work as expected
615          */
616
617         /* Get CCA mode */
618         if (acx100_get_cca_mode_conf(sc, &cca) != 0) {
619                 if_printf(&sc->sc_ic.ic_if, "%s can't get cca mode\n",
620                           __func__);
621                 return ENXIO;
622         }
623         conf->cca_mode = cca.cca_mode;
624         DPRINTF((&sc->sc_ic.ic_if, "cca mode %02x\n", cca.cca_mode));
625
626         /* Get ED threshold */
627         if (acx100_get_ed_thresh_conf(sc, &ed) != 0) {
628                 if_printf(&sc->sc_ic.ic_if, "%s can't get ed threshold\n",
629                           __func__);
630                 return ENXIO;
631         }
632         conf->ed_thresh = ed.ed_thresh;
633         DPRINTF((&sc->sc_ic.ic_if, "ed threshold %02x\n", ed.ed_thresh));
634
635         return 0;
636 }
637
638 static int
639 acx100_write_config(struct acx_softc *sc, struct acx_config *conf)
640 {
641         struct acx100_conf_cca_mode cca;
642         struct acx100_conf_ed_thresh ed;
643
644         /* Set CCA mode */
645         cca.cca_mode = conf->cca_mode;
646         if (acx100_set_cca_mode_conf(sc, &cca) != 0) {
647                 if_printf(&sc->sc_ic.ic_if, "%s can't set cca mode\n",
648                           __func__);
649                 return ENXIO;
650         }
651
652         /* Set ED threshold */
653         ed.ed_thresh = conf->ed_thresh;
654         if (acx100_set_ed_thresh_conf(sc, &ed) != 0) {
655                 if_printf(&sc->sc_ic.ic_if, "%s can't set ed threshold\n",
656                           __func__);
657                 return ENXIO;
658         }
659
660         /* Set TX power */
661         acx100_set_txpower(sc); /* ignore return value */
662
663         return 0;
664 }
665
666 static int
667 acx100_set_txpower(struct acx_softc *sc)
668 {
669         const uint8_t *map;
670
671         switch (sc->sc_radio_type) {
672         case ACX_RADIO_TYPE_MAXIM:
673                 map = acx100_txpower_maxim;
674                 break;
675         case ACX_RADIO_TYPE_RFMD:
676         case ACX_RADIO_TYPE_RALINK:
677                 map = acx100_txpower_rfmd;
678                 break;
679         default:
680                 if_printf(&sc->sc_ic.ic_if, "TX power for radio type 0x%02x "
681                           "can't be set yet\n", sc->sc_radio_type);
682                 return 1;
683         }
684
685         acx_write_phyreg(sc, ACXRV_PHYREG_TXPOWER, map[ACX100_TXPOWER]);
686         return 0;
687 }
688
689 static void
690 acx100_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
691                           struct ieee80211_node *ni, int data_len)
692 {
693         int rate;
694
695         tx_buf->tb_rateidx_len = 1;
696         if (ni == NULL) {
697                 rate = 2;       /* 1Mbit/s */
698                 tx_buf->tb_rateidx[0] = 0;
699         } else {
700                 ieee80211_ratectl_findrate(ni, data_len,
701                                            tx_buf->tb_rateidx, 1);
702                 rate = IEEE80211_RS_RATE(&ni->ni_rates,
703                                          tx_buf->tb_rateidx[0]);
704         }
705         FW_TXDESC_SETFIELD_1(sc, tx_buf, f_tx_rate100, ACX100_RATE(rate));
706 }
707
708 static void
709 acx100_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
710 {
711         struct acx100_bss_join *bj = param;
712
713         bj->dtim_intvl = dtim_intvl;
714         bj->basic_rates = 15;   /* XXX */
715         bj->all_rates = 31;     /* XXX */
716 }
717
718 static int
719 acx100_set_wepkey(struct acx_softc *sc, struct ieee80211_key *wk, int wk_idx)
720 {
721         struct acx100_conf_wepkey conf_wk;
722
723         if (wk->wk_keylen > ACX100_WEPKEY_LEN) {
724                 if_printf(&sc->sc_ic.ic_if, "%dth WEP key size beyond %d\n",
725                           wk_idx, ACX100_WEPKEY_LEN);
726                 return EINVAL;
727         }
728
729         conf_wk.action = ACX100_WEPKEY_ACT_ADD;
730         conf_wk.key_len = wk->wk_keylen;
731         conf_wk.key_idx = wk_idx;
732         bcopy(wk->wk_key, conf_wk.key, wk->wk_keylen);
733         if (acx100_set_wepkey_conf(sc, &conf_wk) != 0) {
734                 if_printf(&sc->sc_ic.ic_if, "%s set %dth WEP key failed\n",
735                           __func__, wk_idx);
736                 return ENXIO;
737         }
738         return 0;
739 }
740
741 static void
742 acx100_proc_wep_rxbuf(struct acx_softc *sc, struct mbuf *m, int *len)
743 {
744         int mac_hdrlen;
745         struct ieee80211_frame *f;
746
747         /*
748          * Strip leading IV and KID, and trailing CRC
749          */
750
751         f = mtod(m, struct ieee80211_frame *);
752
753         if ((f->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
754                 mac_hdrlen = sizeof(struct ieee80211_frame_addr4);
755         else
756                 mac_hdrlen = sizeof(struct ieee80211_frame);
757
758 #define IEEEWEP_IVLEN   (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
759 #define IEEEWEP_EXLEN   (IEEEWEP_IVLEN + IEEE80211_WEP_CRCLEN)
760
761         *len = *len - IEEEWEP_EXLEN;
762
763         /* Move MAC header toward frame body */
764         ovbcopy(f, (uint8_t *)f + IEEEWEP_IVLEN, mac_hdrlen);
765         m_adj(m, IEEEWEP_IVLEN);
766
767 #undef IEEEWEP_EXLEN
768 #undef IEEEWEP_IVLEN
769 }
770
771 static void
772 acx100_tx_complete(struct acx_softc *sc, struct acx_txbuf *tx_buf,
773                    int frame_len, int is_fail)
774 {
775         int long_retries, short_retries;
776         struct ieee80211_ratectl_res rc_res;
777
778         long_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_rts_nretry);
779         short_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_data_nretry);
780
781         rc_res.rc_res_rateidx = tx_buf->tb_rateidx[0];
782         rc_res.rc_res_tries = short_retries + 1;
783
784         ieee80211_ratectl_tx_complete(tx_buf->tb_node, frame_len,
785                                       &rc_res, 1, short_retries, long_retries,
786                                       is_fail);
787 }