Merge from vendor branch LIBARCHIVE:
[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.10 2007/03/19 13:38:43 sephe 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_var.h>
49 #include <netproto/802_11/ieee80211_radiotap.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 int      acx100_set_txpower(struct acx_softc *);
264
265 static uint8_t  acx100_set_fw_txdesc_rate(struct acx_softc *,
266                                           struct acx_txbuf *,
267                                           struct ieee80211_node *, int);
268 static void     acx100_tx_complete(struct acx_softc *, struct acx_txbuf *,
269                                    int, int);
270 static void     acx100_set_bss_join_param(struct acx_softc *, void *, int);
271
272 static int      acx100_set_wepkey(struct acx_softc *, struct ieee80211_key *,
273                                   int);
274
275 static void     acx100_proc_wep_rxbuf(struct acx_softc *, struct mbuf *, int *);
276
277 #define ACX100_CHK_RATE(ifp, rate, rate_idx)    \
278         acx100_check_rate(ifp, rate, rate_idx, __func__)
279
280 static __inline int
281 acx100_check_rate(struct ifnet *ifp, u_int rate, int rate_idx,
282                   const char *fname)
283 {
284 #define N(arr)  (sizeof(arr) / sizeof(arr[0]))
285         if (rate >= N(acx100_rate_map)) {
286                 if_printf(ifp, "%s rate out of range %u (idx %d)\n",
287                           fname, rate, rate_idx);
288                 return -1;
289         }
290 #undef N
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
306         sc->chip_mem1_rid = PCIR_BAR(1);
307         sc->chip_mem2_rid = PCIR_BAR(2);
308         sc->chip_ioreg = acx100_reg;
309         sc->chip_hw_crypt = 1;
310         sc->chip_intr_enable = ACX100_INTR_ENABLE;
311         sc->chip_intr_disable = ACX100_INTR_DISABLE;
312         sc->chip_gpio_pled = ACX100_GPIO_POWER_LED;
313         sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS;
314         sc->chip_txdesc1_len = ACX_FRAME_HDRLEN;
315         sc->chip_fw_txdesc_ctrl = DESC_CTRL_AUTODMA |
316                                   DESC_CTRL_RECLAIM |
317                                   DESC_CTRL_FIRST_FRAG;
318         sc->chip_short_retry_limit = 7;
319         sc->chip_rssi_corr = ACX100_RSSI_CORR;
320
321         sc->chip_phymode = IEEE80211_MODE_11B;
322         sc->chip_chan_flags = IEEE80211_CHAN_B;
323
324         ic->ic_phytype = IEEE80211_T_DS;
325         ic->ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b;
326
327         ic->ic_ratectl.rc_st_ratectl_cap = IEEE80211_RATECTL_CAP_ONOE;
328         ic->ic_ratectl.rc_st_ratectl = IEEE80211_RATECTL_ONOE;
329
330         sc->chip_init = acx100_init;
331         sc->chip_set_wepkey = acx100_set_wepkey;
332         sc->chip_read_config = acx100_read_config;
333         sc->chip_write_config = acx100_write_config;
334         sc->chip_set_fw_txdesc_rate = acx100_set_fw_txdesc_rate;
335         sc->chip_tx_complete = acx100_tx_complete;
336         sc->chip_set_bss_join_param = acx100_set_bss_join_param;
337         sc->chip_proc_wep_rxbuf = acx100_proc_wep_rxbuf;
338 }
339
340 static int
341 acx100_init(struct acx_softc *sc)
342 {
343         /*
344          * NOTE:
345          * Order of initialization:
346          * 1) WEP
347          * 2) Templates
348          * 3) Firmware TX/RX ring
349          * 4) Hardware memory
350          * Above order is critical to get a correct memory map
351          */
352
353         if (acx100_init_wep(sc) != 0) {
354                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize wep\n",
355                           __func__);
356                 return ENXIO;
357         }
358
359         if (acx100_init_tmplt(sc) != 0) {
360                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize templates\n",
361                           __func__);
362                 return ENXIO;
363         }
364
365         if (acx100_init_fw_ring(sc) != 0) {
366                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize fw ring\n",
367                           __func__);
368                 return ENXIO;
369         }
370
371         if (acx100_init_memory(sc) != 0) {
372                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize hw memory\n",
373                           __func__);
374                 return ENXIO;
375         }
376         return 0;
377 }
378
379 static int
380 acx100_init_wep(struct acx_softc *sc)
381 {
382         struct acx_conf_wepopt wep_opt;
383         struct acx_conf_mmap mem_map;
384
385         /* Set WEP cache start/end address */
386         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
387                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
388                 return 1;
389         }
390
391         mem_map.wep_cache_start = htole32(le32toh(mem_map.code_end) + 4);
392         mem_map.wep_cache_end = htole32(le32toh(mem_map.code_end) + 4);
393         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
394                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
395                 return 1;
396         }
397
398         /* Set WEP options */
399         wep_opt.nkey = htole16(IEEE80211_WEP_NKID + 10);
400         wep_opt.opt = WEPOPT_HDWEP;
401         if (acx_set_wepopt_conf(sc, &wep_opt) != 0) {
402                 if_printf(&sc->sc_ic.ic_if, "can't set wep opt\n");
403                 return 1;
404         }
405         return 0;
406 }
407
408 static int
409 acx100_init_tmplt(struct acx_softc *sc)
410 {
411         struct acx_conf_mmap mem_map;
412
413         /* Set templates start address */
414         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
415                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
416                 return 1;
417         }
418
419         mem_map.pkt_tmplt_start = mem_map.wep_cache_end;
420         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
421                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
422                 return 1;
423         }
424
425         /* Initialize various packet templates */
426         if (acx_init_tmplt_ordered(sc) != 0) {
427                 if_printf(&sc->sc_ic.ic_if, "can't init tmplt\n");
428                 return 1;
429         }
430         return 0;
431 }
432
433 static int
434 acx100_init_fw_ring(struct acx_softc *sc)
435 {
436         struct acx100_conf_fw_ring ring;
437         struct acx_conf_mmap mem_map;
438         uint32_t txring_start, rxring_start, ring_end;
439
440         /* Set firmware descriptor ring start address */
441         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
442                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
443                 return 1;
444         }
445
446         txring_start = le32toh(mem_map.pkt_tmplt_end) + 4;
447         rxring_start = txring_start + ACX100_FW_TXRING_SIZE;
448         ring_end = rxring_start + ACX100_FW_RXRING_SIZE;
449
450         mem_map.fw_desc_start = htole32(txring_start);
451         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
452                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
453                 return 1;
454         }
455
456         /* Set firmware descriptor ring configure */
457         bzero(&ring, sizeof(ring));
458         ring.fw_ring_size = htole32(ACX100_FW_TXRING_SIZE +
459                                     ACX100_FW_RXRING_SIZE + 8);
460
461         ring.fw_txring_num = 1;
462         ring.fw_txring_addr = htole32(txring_start);
463         ring.fw_txring_prio = ACX100_TXRING_PRIO_DEFAULT;
464         ring.fw_txdesc_num = 0; /* XXX ignored?? */
465
466         ring.fw_rxring_addr = htole32(rxring_start);
467         ring.fw_rxdesc_num = 0; /* XXX ignored?? */
468
469         ring.opt = ACX100_RINGOPT_AUTO_RESET;
470         ACX100_SET_RING_END(&ring, ring_end);
471         if (acx100_set_fw_ring_conf(sc, &ring) != 0) {
472                 if_printf(&sc->sc_ic.ic_if, "can't set fw ring configure\n");
473                 return 1;
474         }
475
476         /* Setup firmware TX/RX descriptor ring */
477         acx100_init_fw_txring(sc, txring_start);
478         acx100_init_fw_rxring(sc, rxring_start);
479
480         return 0;
481 }
482
483 #define MEMBLK_ALIGN(addr)      \
484         (((addr) + (ACX100_MEMBLK_ALIGN - 1)) & ~(ACX100_MEMBLK_ALIGN - 1))
485
486 static int
487 acx100_init_memory(struct acx_softc *sc)
488 {
489         struct acx100_conf_memblk_size memblk_sz;
490         struct acx100_conf_mem mem;
491         struct acx_conf_mmap mem_map;
492         uint32_t memblk_start, memblk_end;
493         int total_memblk, txblk_num, rxblk_num;
494
495         /* Set memory block start address */
496         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
497                 if_printf(&sc->sc_ic.ic_if, "can't get mmap\n");
498                 return 1;
499         }
500
501         mem_map.memblk_start =
502                 htole32(MEMBLK_ALIGN(le32toh(mem_map.fw_desc_end) + 4));
503
504         if (acx_set_mmap_conf(sc, &mem_map) != 0) {
505                 if_printf(&sc->sc_ic.ic_if, "can't set mmap\n");
506                 return 1;
507         }
508
509         /* Set memory block size */
510         memblk_sz.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
511         if (acx100_set_memblk_size_conf(sc, &memblk_sz) != 0) {
512                 if_printf(&sc->sc_ic.ic_if, "can't set mem block size\n");
513                 return 1;
514         }
515
516         /* Get memory map after setting it */
517         if (acx_get_mmap_conf(sc, &mem_map) != 0) {
518                 if_printf(&sc->sc_ic.ic_if, "can't get mmap again\n");
519                 return 1;
520         }
521         memblk_start = le32toh(mem_map.memblk_start);
522         memblk_end = le32toh(mem_map.memblk_end);
523
524         /* Set memory options */
525         mem.opt = htole32(ACX100_MEMOPT_MEMBLOCK | ACX100_MEMOPT_HOSTDESC);
526         mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
527
528         total_memblk = (memblk_end - memblk_start) / ACX_MEMBLOCK_SIZE;
529
530         rxblk_num = total_memblk / 2;           /* 50% */
531         txblk_num = total_memblk - rxblk_num;   /* 50% */
532
533         DPRINTF((&sc->sc_ic.ic_if, "\ttotal memory blocks\t%d\n"
534                                    "\trx memory blocks\t%d\n"
535                                    "\ttx memory blocks\t%d\n",
536                                    total_memblk, rxblk_num, txblk_num));
537
538         mem.rx_memblk_num = htole16(rxblk_num);
539         mem.tx_memblk_num = htole16(txblk_num);
540
541         mem.rx_memblk_addr = htole32(MEMBLK_ALIGN(memblk_start));
542         mem.tx_memblk_addr =
543                 htole32(MEMBLK_ALIGN(memblk_start +
544                                      (ACX_MEMBLOCK_SIZE * rxblk_num)));
545
546         if (acx100_set_mem_conf(sc, &mem) != 0) {
547                 if_printf(&sc->sc_ic.ic_if, "can't set mem options\n");
548                 return 1;
549         }
550
551         /* Initialize memory */
552         if (acx_init_mem(sc) != 0) {
553                 if_printf(&sc->sc_ic.ic_if, "can't init mem\n");
554                 return 1;
555         }
556         return 0;
557 }
558
559 #undef MEMBLK_ALIGN
560
561 static void
562 acx100_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
563 {
564         struct acx_fw_txdesc fw_desc;
565         struct acx_txbuf *tx_buf;
566         uint32_t desc_paddr, fw_desc_offset;
567         int i;
568
569         bzero(&fw_desc, sizeof(fw_desc));
570         fw_desc.f_tx_ctrl = DESC_CTRL_HOSTOWN |
571                             DESC_CTRL_RECLAIM |
572                             DESC_CTRL_AUTODMA |
573                             DESC_CTRL_FIRST_FRAG;
574
575         tx_buf = sc->sc_buf_data.tx_buf;
576         fw_desc_offset = fw_txdesc_start;
577         desc_paddr = sc->sc_ring_data.tx_ring_paddr;
578
579         for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
580                 fw_desc.f_tx_host_desc = htole32(desc_paddr);
581
582                 if (i == ACX_TX_DESC_CNT - 1) {
583                         fw_desc.f_tx_next_desc = htole32(fw_txdesc_start);
584                 } else {
585                         fw_desc.f_tx_next_desc =
586                                 htole32(fw_desc_offset +
587                                         sizeof(struct acx_fw_txdesc));
588                 }
589
590                 tx_buf[i].tb_fwdesc_ofs = fw_desc_offset;
591                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
592                                     sizeof(fw_desc));
593
594                 desc_paddr += (2 * sizeof(struct acx_host_desc));
595                 fw_desc_offset += sizeof(fw_desc);
596         }
597 }
598
599 static void
600 acx100_init_fw_rxring(struct acx_softc *sc, uint32_t fw_rxdesc_start)
601 {
602         struct acx_fw_rxdesc fw_desc;
603         uint32_t fw_desc_offset;
604         int i;
605
606         bzero(&fw_desc, sizeof(fw_desc));
607         fw_desc.f_rx_ctrl = DESC_CTRL_RECLAIM | DESC_CTRL_AUTODMA;
608
609         fw_desc_offset = fw_rxdesc_start;
610
611         for (i = 0; i < ACX_RX_DESC_CNT; ++i) {
612                 if (i == ACX_RX_DESC_CNT - 1) {
613                         fw_desc.f_rx_next_desc = htole32(fw_rxdesc_start);
614                 } else {
615                         fw_desc.f_rx_next_desc =
616                                 htole32(fw_desc_offset +
617                                         sizeof(struct acx_fw_rxdesc));
618                 }
619
620                 DESC_WRITE_REGION_1(sc, fw_desc_offset, &fw_desc,
621                                     sizeof(fw_desc));
622
623                 fw_desc_offset += sizeof(fw_desc);
624         }
625 }
626
627 static int
628 acx100_read_config(struct acx_softc *sc, struct acx_config *conf)
629 {
630         struct acx100_conf_cca_mode cca;
631         struct acx100_conf_ed_thresh ed;
632
633         /*
634          * NOTE:
635          * CCA mode and ED threshold MUST be read during initialization
636          * or the acx100 card won't work as expected
637          */
638
639         /* Get CCA mode */
640         if (acx100_get_cca_mode_conf(sc, &cca) != 0) {
641                 if_printf(&sc->sc_ic.ic_if, "%s can't get cca mode\n",
642                           __func__);
643                 return ENXIO;
644         }
645         conf->cca_mode = cca.cca_mode;
646         DPRINTF((&sc->sc_ic.ic_if, "cca mode %02x\n", cca.cca_mode));
647
648         /* Get ED threshold */
649         if (acx100_get_ed_thresh_conf(sc, &ed) != 0) {
650                 if_printf(&sc->sc_ic.ic_if, "%s can't get ed threshold\n",
651                           __func__);
652                 return ENXIO;
653         }
654         conf->ed_thresh = ed.ed_thresh;
655         DPRINTF((&sc->sc_ic.ic_if, "ed threshold %02x\n", ed.ed_thresh));
656
657         return 0;
658 }
659
660 static int
661 acx100_write_config(struct acx_softc *sc, struct acx_config *conf)
662 {
663         struct acx100_conf_cca_mode cca;
664         struct acx100_conf_ed_thresh ed;
665
666         /* Set CCA mode */
667         cca.cca_mode = conf->cca_mode;
668         if (acx100_set_cca_mode_conf(sc, &cca) != 0) {
669                 if_printf(&sc->sc_ic.ic_if, "%s can't set cca mode\n",
670                           __func__);
671                 return ENXIO;
672         }
673
674         /* Set ED threshold */
675         ed.ed_thresh = conf->ed_thresh;
676         if (acx100_set_ed_thresh_conf(sc, &ed) != 0) {
677                 if_printf(&sc->sc_ic.ic_if, "%s can't set ed threshold\n",
678                           __func__);
679                 return ENXIO;
680         }
681
682         /* Set TX power */
683         acx100_set_txpower(sc); /* ignore return value */
684
685         return 0;
686 }
687
688 static int
689 acx100_set_txpower(struct acx_softc *sc)
690 {
691         const uint8_t *map;
692
693         switch (sc->sc_radio_type) {
694         case ACX_RADIO_TYPE_MAXIM:
695                 map = acx100_txpower_maxim;
696                 break;
697         case ACX_RADIO_TYPE_RFMD:
698         case ACX_RADIO_TYPE_RALINK:
699                 map = acx100_txpower_rfmd;
700                 break;
701         default:
702                 if_printf(&sc->sc_ic.ic_if, "TX power for radio type 0x%02x "
703                           "can't be set yet\n", sc->sc_radio_type);
704                 return 1;
705         }
706
707         acx_write_phyreg(sc, ACXRV_PHYREG_TXPOWER, map[ACX100_TXPOWER]);
708         return 0;
709 }
710
711 static uint8_t
712 acx100_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
713                           struct ieee80211_node *ni, int data_len)
714 {
715         int rate;
716
717         tx_buf->tb_rateidx_len = 1;
718         if (ni == NULL) {
719                 rate = 2;       /* 1Mbit/s */
720                 tx_buf->tb_rateidx[0] = 0;
721         } else {
722                 ieee80211_ratectl_findrate(ni, data_len,
723                                            tx_buf->tb_rateidx, 1);
724                 rate = IEEE80211_RS_RATE(&ni->ni_rates,
725                                          tx_buf->tb_rateidx[0]);
726                 if (ACX100_CHK_RATE(&sc->sc_ic.ic_if, rate,
727                                     tx_buf->tb_rateidx[0]) < 0)
728                         rate = 2;
729         }
730         FW_TXDESC_SETFIELD_1(sc, tx_buf, f_tx_rate100, ACX100_RATE(rate));
731
732         return rate;
733 }
734
735 static void
736 acx100_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
737 {
738         struct acx100_bss_join *bj = param;
739         struct ifnet *ifp = &sc->sc_ic.ic_if;
740         const struct ieee80211_rateset *rs = &sc->sc_ic.ic_bss->ni_rates;
741         int i;
742
743         bj->basic_rates = 0;
744         bj->op_rates = 0;
745         for (i = 0; i < rs->rs_nrates; ++i) {
746                 u_int map_idx = IEEE80211_RS_RATE(rs, i);
747                 uint8_t rate;
748
749                 if (ACX100_CHK_RATE(ifp, map_idx, i) < 0)
750                         continue;
751
752                 rate = acx100_rate_map[map_idx];
753                 if (rs->rs_rates[i] & IEEE80211_RATE_BASIC)
754                         bj->basic_rates |= rate;
755                 bj->op_rates |= rate;
756         }
757         DPRINTF((ifp, "basic rates:0x%02x, op rates:0x%02x\n",
758                  bj->basic_rates, bj->op_rates));
759
760         bj->dtim_intvl = dtim_intvl;
761 }
762
763 static int
764 acx100_set_wepkey(struct acx_softc *sc, struct ieee80211_key *wk, int wk_idx)
765 {
766         struct acx100_conf_wepkey conf_wk;
767
768         if (wk->wk_keylen > ACX100_WEPKEY_LEN) {
769                 if_printf(&sc->sc_ic.ic_if, "%dth WEP key size beyond %d\n",
770                           wk_idx, ACX100_WEPKEY_LEN);
771                 return EINVAL;
772         }
773
774         conf_wk.action = ACX100_WEPKEY_ACT_ADD;
775         conf_wk.key_len = wk->wk_keylen;
776         conf_wk.key_idx = wk_idx;
777         bcopy(wk->wk_key, conf_wk.key, wk->wk_keylen);
778         if (acx100_set_wepkey_conf(sc, &conf_wk) != 0) {
779                 if_printf(&sc->sc_ic.ic_if, "%s set %dth WEP key failed\n",
780                           __func__, wk_idx);
781                 return ENXIO;
782         }
783         return 0;
784 }
785
786 static void
787 acx100_proc_wep_rxbuf(struct acx_softc *sc, struct mbuf *m, int *len)
788 {
789         int mac_hdrlen;
790         struct ieee80211_frame *f;
791
792         /*
793          * Strip leading IV and KID, and trailing CRC
794          */
795
796         f = mtod(m, struct ieee80211_frame *);
797
798         if ((f->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
799                 mac_hdrlen = sizeof(struct ieee80211_frame_addr4);
800         else
801                 mac_hdrlen = sizeof(struct ieee80211_frame);
802
803 #define IEEEWEP_IVLEN   (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
804 #define IEEEWEP_EXLEN   (IEEEWEP_IVLEN + IEEE80211_WEP_CRCLEN)
805
806         *len = *len - IEEEWEP_EXLEN;
807
808         /* Move MAC header toward frame body */
809         ovbcopy(f, (uint8_t *)f + IEEEWEP_IVLEN, mac_hdrlen);
810         m_adj(m, IEEEWEP_IVLEN);
811
812 #undef IEEEWEP_EXLEN
813 #undef IEEEWEP_IVLEN
814 }
815
816 static void
817 acx100_tx_complete(struct acx_softc *sc, struct acx_txbuf *tx_buf,
818                    int frame_len, int is_fail)
819 {
820         int rts_retries, data_retries;
821         struct ieee80211_ratectl_res rc_res;
822
823         rts_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_rts_nretry);
824         data_retries = FW_TXDESC_GETFIELD_1(sc, tx_buf, f_tx_data_nretry);
825
826         rc_res.rc_res_rateidx = tx_buf->tb_rateidx[0];
827         rc_res.rc_res_tries = data_retries + 1;
828
829         ieee80211_ratectl_tx_complete(tx_buf->tb_node, frame_len,
830                                       &rc_res, 1, data_retries, rts_retries,
831                                       is_fail);
832 }