e381c2d3b5df24bd3a717cd3532eb6bf59662edc
[dragonfly.git] / sys / dev / netif / acx / acx111.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/acx111.c,v 1.1 2006/04/01 02:55:36 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 <machine/bus.h>
45 #include <machine/resource.h>
46
47 #include <net/if.h>
48 #include <net/if_arp.h>
49 #include <net/if_media.h>
50
51 #include <netproto/802_11/ieee80211_var.h>
52
53 #include <bus/pci/pcireg.h>
54
55 #define ACX_DEBUG
56
57 #include "if_acxreg.h"
58 #include "if_acxvar.h"
59 #include "acxcmd.h"
60
61 #define ACX111_CONF_MEM         0x0003
62 #define ACX111_CONF_MEMINFO     0x0005
63
64 #define ACX111_INTR_ENABLE      (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
65 /*
66  * XXX do we really care about fowlling interrupts?
67  *
68  * ACXRV_INTR_IV_ICV_FAILURE | ACXRV_INTR_INFO |
69  * ACXRV_INTR_SCAN_FINI | ACXRV_INTR_FCS_THRESHOLD
70  */
71
72 #define ACX111_INTR_DISABLE     (uint16_t)~(ACXRV_INTR_CMD_FINI)
73
74 #define ACX111_RATE_2           0x0001
75 #define ACX111_RATE_4           0x0002
76 #define ACX111_RATE_11          0x0004
77 #define ACX111_RATE_12          0x0008
78 #define ACX111_RATE_18          0x0010
79 #define ACX111_RATE_22          0x0020
80 #define ACX111_RATE_24          0x0040
81 #define ACX111_RATE_36          0x0080
82 #define ACX111_RATE_44          0x0100
83 #define ACX111_RATE_48          0x0200
84 #define ACX111_RATE_72          0x0400
85 #define ACX111_RATE_96          0x0800
86 #define ACX111_RATE_108         0x1000
87 #define ACX111_RATE(rate)       [rate] = ACX111_RATE_##rate
88
89 /* XXX skip ACX111_RATE_44 */
90 #define ACX111_RATE_ALL         0x1eff
91
92 #define ACX111_TXPOWER          15
93 #define ACX111_GPIO_POWER_LED   0x0040
94 #define ACX111_EE_EADDR_OFS     0x21
95
96 #define ACX111_FW_TXDESC_SIZE   (sizeof(struct acx_fw_txdesc) + 4)
97
98 #if ACX111_TXPOWER <= 12
99 #define ACX111_TXPOWER_VAL      1
100 #else
101 #define ACX111_TXPOWER_VAL      2
102 #endif
103
104 /*
105  * NOTE:
106  * Following structs' fields are little endian
107  */
108
109 struct acx111_bss_join {
110         uint16_t        basic_rates;
111         uint8_t         dtim_intvl;
112 } __packed;
113
114 struct acx111_conf_mem {
115         struct acx_conf confcom;
116
117         uint16_t        sta_max;        /* max num of sta, ACX111_STA_MAX */
118         uint16_t        memblk_size;    /* mem block size */
119         uint8_t         rx_memblk_perc; /* percent of RX mem block, unit: 5% */
120         uint8_t         fw_rxring_num;  /* num of RX ring */
121         uint8_t         fw_txring_num;  /* num of TX ring */
122         uint8_t         opt;            /* see ACX111_MEMOPT_ */
123         uint8_t         xfer_perc;      /* frag/xfer proportion, unit: 5% */
124         uint16_t        reserved0;
125         uint8_t         reserved1;
126
127         uint8_t         fw_rxdesc_num;  /* num of fw rx desc */
128         uint8_t         fw_rxring_reserved1;
129         uint8_t         fw_rxring_type; /* see ACX111_RXRING_TYPE_ */
130         uint8_t         fw_rxring_prio; /* see ACX111_RXRING_PRIO_ */
131
132         uint32_t        h_rxring_paddr; /* host rx desc start phyaddr */
133
134         uint8_t         fw_txdesc_num;  /* num of fw tx desc */
135         uint8_t         fw_txring_reserved1;
136         uint8_t         fw_txring_reserved2;
137         uint8_t         fw_txring_attr; /* see ACX111_TXRING_ATTR_ */
138 } __packed;
139
140 #define ACX111_STA_MAX                  32
141 #define ACX111_RX_MEMBLK_PERCENT        10      /* 50% */
142 #define ACX111_XFER_PERCENT             15      /* 75% */
143 #define ACX111_RXRING_TYPE_DEFAULT      7
144 #define ACX111_RXRING_PRIO_DEFAULT      0
145 #define ACX111_TXRING_ATTR_DEFAULT      0
146 #define ACX111_MEMOPT_DEFAULT           0
147
148 struct acx111_conf_meminfo {
149         struct acx_conf confcom;
150         uint32_t        tx_memblk_addr; /* start addr of tx mem blocks */
151         uint32_t        rx_memblk_addr; /* start addr of rx mem blocks */
152         uint32_t        fw_rxring_start; /* start phyaddr of fw rx ring */
153         uint32_t        reserved0;
154         uint32_t        fw_txring_start; /* start phyaddr of fw tx ring */
155         uint8_t         fw_txring_attr; /* XXX see ACX111_TXRING_ATTR_ */
156         uint16_t        reserved1;
157         uint8_t         reserved2;
158 } __packed;
159
160 struct acx111_conf_txpower {
161         struct acx_conf confcom;
162         uint8_t         txpower;
163 } __packed;
164
165 struct acx111_conf_option {
166         struct acx_conf confcom;
167         uint32_t        feature;
168         uint32_t        dataflow;       /* see ACX111_DATAFLOW_ */
169 } __packed;
170
171 #define ACX111_DATAFLOW_SNIFFER         0x00000080
172 #define ACX111_DATAFLOW_NO_TXCRYPT      0x00000001
173
174 struct acx111_wepkey {
175         uint8_t         mac_addr[IEEE80211_ADDR_LEN];
176         uint16_t        action;         /* see ACX111_WEPKEY_ACT_ */
177         uint16_t        reserved;
178         uint8_t         key_len;
179         uint8_t         key_type;       /* see ACX111_WEPKEY_TYPE_ */
180         uint8_t         index;          /* XXX ?? */
181         uint8_t         key_idx;
182         uint8_t         counter[6];
183 #define ACX111_WEPKEY_LEN       32
184         uint8_t         key[ACX111_WEPKEY_LEN];
185 } __packed;
186
187 #define ACX111_WEPKEY_ACT_ADD           1
188 #define ACX111_WEPKEY_TYPE_DEFAULT      0
189
190 #define ACX111_CONF_FUNC(sg, name)      _ACX_CONF_FUNC(sg, name, 111)
191 #define ACX_CONF_mem                    ACX111_CONF_MEM
192 #define ACX_CONF_meminfo                ACX111_CONF_MEMINFO
193 #define ACX_CONF_txpower                ACX_CONF_TXPOWER
194 #define ACX_CONF_option                 ACX_CONF_OPTION
195 ACX111_CONF_FUNC(set, mem);
196 ACX111_CONF_FUNC(get, meminfo);
197 ACX111_CONF_FUNC(set, txpower);
198 ACX111_CONF_FUNC(get, option);
199 ACX111_CONF_FUNC(set, option);
200
201 static const uint16_t acx111_reg[ACXREG_MAX] = {
202         ACXREG(SOFT_RESET,              0x0000),
203
204         ACXREG(FWMEM_ADDR,              0x0014),
205         ACXREG(FWMEM_DATA,              0x0018),
206         ACXREG(FWMEM_CTRL,              0x001c),
207         ACXREG(FWMEM_START,             0x0020),
208
209         ACXREG(EVENT_MASK,              0x0034),
210
211         ACXREG(INTR_TRIG,               0x00b4),
212         ACXREG(INTR_MASK,               0x00d4),
213         ACXREG(INTR_STATUS,             0x00f0),
214         ACXREG(INTR_STATUS_CLR,         0x00e4),
215         ACXREG(INTR_ACK,                0x00e8),
216
217         ACXREG(HINTR_TRIG,              0x00ec),
218         ACXREG(RADIO_ENABLE,            0x01d0),
219
220         ACXREG(EEPROM_INIT,             0x0100),
221         ACXREG(EEPROM_CTRL,             0x0338),
222         ACXREG(EEPROM_ADDR,             0x033c),
223         ACXREG(EEPROM_DATA,             0x0340),
224         ACXREG(EEPROM_CONF,             0x0344),
225         ACXREG(EEPROM_INFO,             0x0390),
226
227         ACXREG(PHY_ADDR,                0x0350),
228         ACXREG(PHY_DATA,                0x0354),
229         ACXREG(PHY_CTRL,                0x0358),
230
231         ACXREG(GPIO_OUT_ENABLE,         0x0374),
232         ACXREG(GPIO_OUT,                0x037c),
233
234         ACXREG(CMD_REG_OFFSET,          0x0388),
235         ACXREG(INFO_REG_OFFSET,         0x038c),
236
237         ACXREG(RESET_SENSE,             0x0104),
238         ACXREG(ECPU_CTRL,               0x0108) 
239 };
240
241 /* XXX */
242 static uint16_t acx111_rate_map[109] = {
243         ACX111_RATE(2),
244         ACX111_RATE(4),
245         ACX111_RATE(11),
246         ACX111_RATE(22),
247         ACX111_RATE(12),
248         ACX111_RATE(18),
249         ACX111_RATE(24),
250         ACX111_RATE(36),
251         ACX111_RATE(48),
252         ACX111_RATE(72),
253         ACX111_RATE(96),
254         ACX111_RATE(108)
255 };
256
257 /*
258  * For firmware whose version is listed in the following array,
259  * software WEP should be used, since hardware WEP's performance
260  * is too poor
261  */
262 static const uint32_t   acx111_softwep_fwver[] = {
263         0x01020030,
264         0       /* KEEP THIS */
265 };
266
267 static int      acx111_init(struct acx_softc *);
268 static int      acx111_init_memory(struct acx_softc *);
269 static void     acx111_init_fw_txring(struct acx_softc *, uint32_t);
270
271 static int      acx111_write_config(struct acx_softc *, struct acx_config *);
272
273 static void     acx111_set_fw_txdesc_rate(struct acx_softc *,
274                                           struct acx_txbuf *, int);
275 static void     acx111_set_bss_join_param(struct acx_softc *, void *, int);
276
277 static int      acx111_set_wepkey(struct acx_softc *,
278                                   struct ieee80211_wepkey *, int);
279
280 void
281 acx111_set_param(device_t dev)
282 {
283         struct acx_softc *sc = device_get_softc(dev);
284
285         sc->chip_mem1_rid = PCIR_BAR(0);
286         sc->chip_mem2_rid = PCIR_BAR(1);
287         sc->chip_ioreg = acx111_reg;
288         sc->chip_intr_enable = ACX111_INTR_ENABLE;
289         sc->chip_intr_disable = ACX111_INTR_DISABLE;
290         sc->chip_gpio_pled = ACX111_GPIO_POWER_LED;
291         sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS;
292
293         sc->chip_phymode = IEEE80211_MODE_11G;
294         sc->chip_chan_flags = IEEE80211_CHAN_CCK |
295                               IEEE80211_CHAN_OFDM |
296                               IEEE80211_CHAN_DYN |
297                               IEEE80211_CHAN_2GHZ;
298         sc->sc_ic.ic_phytype = IEEE80211_T_OFDM;
299         sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11B] = acx_rates_11b;
300         sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11G] = acx_rates_11g;
301
302         sc->chip_init = acx111_init;
303         sc->chip_set_wepkey = acx111_set_wepkey;
304         sc->chip_write_config = acx111_write_config;
305         sc->chip_set_fw_txdesc_rate = acx111_set_fw_txdesc_rate;
306         sc->chip_set_bss_join_param = acx111_set_bss_join_param;
307 }
308
309 static int
310 acx111_init(struct acx_softc *sc)
311 {
312         /*
313          * NOTE:
314          * Order of initialization:
315          * 1) Templates
316          * 2) Hardware memory
317          * Above order is critical to get a correct memory map
318          */
319
320         if (acx_init_tmplt_ordered(sc) != 0) {
321                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize templates\n",
322                           __func__);
323                 return ENXIO;
324         }
325
326         if (acx111_init_memory(sc) != 0) {
327                 if_printf(&sc->sc_ic.ic_if, "%s can't initialize hw memory\n",
328                           __func__);
329                 return ENXIO;
330         }
331         return 0;
332 }
333
334 static int
335 acx111_init_memory(struct acx_softc *sc)
336 {
337         struct acx111_conf_mem mem;
338         struct acx111_conf_meminfo mem_info;
339
340         /* Set memory configuration */
341         bzero(&mem, sizeof(mem));
342
343         mem.sta_max = htole16(ACX111_STA_MAX);
344         mem.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
345         mem.rx_memblk_perc = ACX111_RX_MEMBLK_PERCENT;
346         mem.opt = ACX111_MEMOPT_DEFAULT;
347         mem.xfer_perc = ACX111_XFER_PERCENT;
348
349         mem.fw_rxring_num = 1;
350         mem.fw_rxring_type = ACX111_RXRING_TYPE_DEFAULT;
351         mem.fw_rxring_prio = ACX111_RXRING_PRIO_DEFAULT;
352         mem.fw_rxdesc_num = ACX_RX_DESC_CNT;
353         mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
354
355         mem.fw_txring_num = 1;
356         mem.fw_txring_attr = ACX111_TXRING_ATTR_DEFAULT;
357         mem.fw_txdesc_num = ACX_TX_DESC_CNT;
358
359         if (acx111_set_mem_conf(sc, &mem) != 0) {
360                 if_printf(&sc->sc_ic.ic_if, "can't set mem\n");
361                 return 1;
362         }
363
364         /* Get memory configuration */
365         if (acx111_get_meminfo_conf(sc, &mem_info) != 0) {
366                 if_printf(&sc->sc_ic.ic_if, "can't get meminfo\n");
367                 return 1;
368         }
369
370         /* Setup firmware TX descriptor ring */
371         acx111_init_fw_txring(sc, le32toh(mem_info.fw_txring_start));
372
373         /*
374          * There is no need to setup firmware RX descriptor ring,
375          * it is automaticly setup by hardware.
376          */
377
378         return 0;
379 }
380
381 static void
382 acx111_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
383 {
384         struct acx_txbuf *tx_buf;
385         uint32_t desc_paddr;
386         int i;
387
388         tx_buf = sc->sc_buf_data.tx_buf;
389         desc_paddr = sc->sc_ring_data.tx_ring_paddr;
390
391         for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
392                 tx_buf[i].tb_fwdesc_ofs = fw_txdesc_start +
393                                           (i * ACX111_FW_TXDESC_SIZE);
394
395                 /*
396                  * Except for the following fields, rest of the fields
397                  * are setup by hardware.
398                  */
399                 FW_TXDESC_SETFIELD_4(sc, &tx_buf[i], f_tx_host_desc,
400                                      desc_paddr);
401                 FW_TXDESC_SETFIELD_1(sc, &tx_buf[i], f_tx_ctrl,
402                                      DESC_CTRL_HOSTOWN);
403
404                 desc_paddr += (2 * sizeof(struct acx_host_desc));
405         }
406 }
407
408 static int
409 acx111_write_config(struct acx_softc *sc, struct acx_config *conf)
410 {
411         struct acx111_conf_txpower tx_power;
412         struct acx111_conf_option opt;
413         uint32_t dataflow;
414         const uint32_t *fwver;
415
416         /* Set TX power */
417         tx_power.txpower = ACX111_TXPOWER_VAL;
418         if (acx111_set_txpower_conf(sc, &tx_power) != 0) {
419                 if_printf(&sc->sc_ic.ic_if, "%s can't set TX power\n",
420                           __func__);
421                 return ENXIO;
422         }
423
424         /*
425          * Turn off sniffering
426          * Turn on hardware/software WEP
427          */
428         if (acx111_get_option_conf(sc, &opt) != 0) {
429                 if_printf(&sc->sc_ic.ic_if, "%s can't get option\n", __func__);
430                 return ENXIO;
431         }
432
433         dataflow = le32toh(opt.dataflow) & ~ACX111_DATAFLOW_SNIFFER;
434
435         for (fwver = acx111_softwep_fwver; *fwver != 0; ++fwver) {
436                 if (sc->sc_firmware_ver == *fwver)
437                         break;
438         }
439
440         if (*fwver != 0) {
441                 DPRINTF((&sc->sc_ic.ic_if, "disable hardware WEP\n"));
442                 dataflow |= ACX111_DATAFLOW_NO_TXCRYPT;
443                 sc->sc_softwep = 1;
444         } else {
445                 DPRINTF((&sc->sc_ic.ic_if, "enable hardware WEP\n"));
446                 dataflow &= ~ACX111_DATAFLOW_NO_TXCRYPT;
447                 sc->sc_softwep = 0;
448         }
449
450         opt.dataflow = htole32(dataflow);
451
452         if (acx111_set_option_conf(sc, &opt) != 0) {
453                 if_printf(&sc->sc_ic.ic_if, "%s can't set option\n", __func__);
454                 return ENXIO;
455         }
456         return 0;
457 }
458
459 static void
460 acx111_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
461                           int rate0)
462 {
463         uint16_t rate;
464
465         rate = acx111_rate_map[rate0];
466         KASSERT(rate != 0, ("no rate map for %d\n", rate0));
467
468         FW_TXDESC_SETFIELD_2(sc, tx_buf, u.r2.rate111, rate);
469 }
470
471 static void
472 acx111_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
473 {
474         struct acx111_bss_join *bj = param;
475
476         bj->basic_rates = htole16(ACX111_RATE_ALL);
477         bj->dtim_intvl = dtim_intvl;
478 }
479
480 static int
481 acx111_set_wepkey(struct acx_softc *sc, struct ieee80211_wepkey *wk, int wk_idx)
482 {
483         struct acx111_wepkey wepkey;
484
485         if (wk->wk_len > ACX111_WEPKEY_LEN) {
486                 if_printf(&sc->sc_ic.ic_if, "%dth WEP key size beyond %d\n",
487                           wk_idx, ACX111_WEPKEY_LEN);
488                 return EINVAL;
489         }
490
491         bzero(&wepkey, sizeof(wepkey));
492         wepkey.action = htole16(ACX111_WEPKEY_ACT_ADD);
493         wepkey.key_type = ACX111_WEPKEY_TYPE_DEFAULT;
494         wepkey.index = 0; /* XXX ignored? */
495         wepkey.key_len = wk->wk_len;
496         wepkey.key_idx = wk_idx;
497         bcopy(wk->wk_key, wepkey.key, wk->wk_len);
498         if (acx_exec_command(sc, ACXCMD_WEP_MGMT, &wepkey, sizeof(wepkey),
499                              NULL, 0) != 0) {
500                 if_printf(&sc->sc_ic.ic_if, "%s set %dth WEP key failed\n",
501                           __func__, wk_idx);
502                 return ENXIO;
503         }
504         return 0;
505 }