Annotation of sys/dev/ic/acx111.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: acx111.c,v 1.16 2007/08/05 21:37:29 claudio Exp $ */
2:
3: /*
4: * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: /*
20: * Copyright (c) 2006 The DragonFly Project. All rights reserved.
21: *
22: * This code is derived from software contributed to The DragonFly Project
23: * by Sepherosa Ziehau <sepherosa@gmail.com>
24: *
25: * Redistribution and use in source and binary forms, with or without
26: * modification, are permitted provided that the following conditions
27: * are met:
28: *
29: * 1. Redistributions of source code must retain the above copyright
30: * notice, this list of conditions and the following disclaimer.
31: * 2. Redistributions in binary form must reproduce the above copyright
32: * notice, this list of conditions and the following disclaimer in
33: * the documentation and/or other materials provided with the
34: * distribution.
35: * 3. Neither the name of The DragonFly Project nor the names of its
36: * contributors may be used to endorse or promote products derived
37: * from this software without specific, prior written permission.
38: *
39: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
40: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
41: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
42: * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
43: * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
44: * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
45: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
47: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50: * SUCH DAMAGE.
51: */
52:
53: #include <sys/param.h>
54: #include <sys/endian.h>
55: #include <sys/socket.h>
56: #include <sys/sysctl.h>
57: #include <sys/device.h>
58:
59: #include <machine/bus.h>
60:
61: #include <net/if.h>
62: #include <net/if_arp.h>
63: #include <net/if_media.h>
64:
65: #include <net/if.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 ACX111_CONF_MEM 0x0003
82: #define ACX111_CONF_MEMINFO 0x0005
83:
84: #define ACX111_INTR_ENABLE (ACXRV_INTR_TX_FINI | ACXRV_INTR_RX_FINI)
85: /*
86: * XXX do we really care about fowlling interrupts?
87: *
88: * ACXRV_INTR_IV_ICV_FAILURE | ACXRV_INTR_INFO |
89: * ACXRV_INTR_SCAN_FINI | ACXRV_INTR_FCS_THRESHOLD
90: */
91:
92: #define ACX111_INTR_DISABLE (uint16_t)~(ACXRV_INTR_CMD_FINI)
93:
94: #define ACX111_RATE_2 0x0001
95: #define ACX111_RATE_4 0x0002
96: #define ACX111_RATE_11 0x0004
97: #define ACX111_RATE_12 0x0008
98: #define ACX111_RATE_18 0x0010
99: #define ACX111_RATE_22 0x0020
100: #define ACX111_RATE_24 0x0040
101: #define ACX111_RATE_36 0x0080
102: #define ACX111_RATE_44 0x0100
103: #define ACX111_RATE_48 0x0200
104: #define ACX111_RATE_72 0x0400
105: #define ACX111_RATE_96 0x0800
106: #define ACX111_RATE_108 0x1000
107:
108: /* XXX skip ACX111_RATE_44 */
109: #define ACX111_RATE_ALL 0x1eff
110:
111: #define ACX111_TXPOWER 15
112: #define ACX111_GPIO_POWER_LED 0x0040
113: #define ACX111_EE_EADDR_OFS 0x21
114:
115: #define ACX111_FW_TXDESC_SIZE (sizeof(struct acx_fw_txdesc) + 4)
116:
117: #if ACX111_TXPOWER <= 12
118: #define ACX111_TXPOWER_VAL 1
119: #else
120: #define ACX111_TXPOWER_VAL 2
121: #endif
122:
123: int acx111_init(struct acx_softc *);
124: int acx111_init_memory(struct acx_softc *);
125: void acx111_init_fw_txring(struct acx_softc *, uint32_t);
126: int acx111_write_config(struct acx_softc *, struct acx_config *);
127: void acx111_set_fw_txdesc_rate(struct acx_softc *,
128: struct acx_txbuf *, int);
129: void acx111_set_bss_join_param(struct acx_softc *, void *, int);
130:
131: /*
132: * NOTE:
133: * Following structs' fields are little endian
134: */
135: struct acx111_bss_join {
136: uint16_t basic_rates;
137: uint8_t dtim_intvl;
138: } __packed;
139:
140: struct acx111_conf_mem {
141: struct acx_conf confcom;
142:
143: uint16_t sta_max; /* max num of sta, ACX111_STA_MAX */
144: uint16_t memblk_size; /* mem block size */
145: uint8_t rx_memblk_perc; /* percent of RX mem block, unit: 5% */
146: uint8_t fw_rxring_num; /* num of RX ring */
147: uint8_t fw_txring_num; /* num of TX ring */
148: uint8_t opt; /* see ACX111_MEMOPT_ */
149: uint8_t xfer_perc; /* frag/xfer proportion, unit: 5% */
150: uint16_t reserved0;
151: uint8_t reserved1;
152:
153: uint8_t fw_rxdesc_num; /* num of fw rx desc */
154: uint8_t fw_rxring_reserved1;
155: uint8_t fw_rxring_type; /* see ACX111_RXRING_TYPE_ */
156: uint8_t fw_rxring_prio; /* see ACX111_RXRING_PRIO_ */
157:
158: uint32_t h_rxring_paddr; /* host rx desc start phyaddr */
159:
160: uint8_t fw_txdesc_num; /* num of fw tx desc */
161: uint8_t fw_txring_reserved1;
162: uint8_t fw_txring_reserved2;
163: uint8_t fw_txring_attr; /* see ACX111_TXRING_ATTR_ */
164: } __packed;
165:
166: #define ACX111_STA_MAX 32
167: #define ACX111_RX_MEMBLK_PERCENT 10 /* 50% */
168: #define ACX111_XFER_PERCENT 15 /* 75% */
169: #define ACX111_RXRING_TYPE_DEFAULT 7
170: #define ACX111_RXRING_PRIO_DEFAULT 0
171: #define ACX111_TXRING_ATTR_DEFAULT 0
172: #define ACX111_MEMOPT_DEFAULT 0
173:
174: struct acx111_conf_meminfo {
175: struct acx_conf confcom;
176: uint32_t tx_memblk_addr; /* start addr of tx mem blocks */
177: uint32_t rx_memblk_addr; /* start addr of rx mem blocks */
178: uint32_t fw_rxring_start; /* start phyaddr of fw rx ring */
179: uint32_t reserved0;
180: uint32_t fw_txring_start; /* start phyaddr of fw tx ring */
181: uint8_t fw_txring_attr; /* XXX see ACX111_TXRING_ATTR_ */
182: uint16_t reserved1;
183: uint8_t reserved2;
184: } __packed;
185:
186: struct acx111_conf_txpower {
187: struct acx_conf confcom;
188: uint8_t txpower;
189: } __packed;
190:
191: struct acx111_conf_option {
192: struct acx_conf confcom;
193: uint32_t feature;
194: uint32_t dataflow; /* see ACX111_DF_ */
195: } __packed;
196:
197: #define ACX111_DF_NO_RXDECRYPT 0x00000080
198: #define ACX111_DF_NO_TXENCRYPT 0x00000001
199:
200: struct acx111_wepkey {
201: uint8_t mac_addr[IEEE80211_ADDR_LEN];
202: uint16_t action; /* see ACX111_WEPKEY_ACT_ */
203: uint16_t reserved;
204: uint8_t key_len;
205: uint8_t key_type; /* see ACX111_WEPKEY_TYPE_ */
206: uint8_t index; /* XXX ?? */
207: uint8_t key_idx;
208: uint8_t counter[6];
209: #define ACX111_WEPKEY_LEN 32
210: uint8_t key[ACX111_WEPKEY_LEN];
211: } __packed;
212:
213: #define ACX111_WEPKEY_ACT_ADD 1
214: #define ACX111_WEPKEY_TYPE_DEFAULT 0
215:
216: static const uint16_t acx111_reg[ACXREG_MAX] = {
217: ACXREG(SOFT_RESET, 0x0000),
218:
219: ACXREG(FWMEM_ADDR, 0x0014),
220: ACXREG(FWMEM_DATA, 0x0018),
221: ACXREG(FWMEM_CTRL, 0x001c),
222: ACXREG(FWMEM_START, 0x0020),
223:
224: ACXREG(EVENT_MASK, 0x0034),
225:
226: ACXREG(INTR_TRIG, 0x00b4),
227: ACXREG(INTR_MASK, 0x00d4),
228: ACXREG(INTR_STATUS, 0x00f0),
229: ACXREG(INTR_STATUS_CLR, 0x00e4),
230: ACXREG(INTR_ACK, 0x00e8),
231:
232: ACXREG(HINTR_TRIG, 0x00ec),
233: ACXREG(RADIO_ENABLE, 0x01d0),
234:
235: ACXREG(EEPROM_INIT, 0x0100),
236: ACXREG(EEPROM_CTRL, 0x0338),
237: ACXREG(EEPROM_ADDR, 0x033c),
238: ACXREG(EEPROM_DATA, 0x0340),
239: ACXREG(EEPROM_CONF, 0x0344),
240: ACXREG(EEPROM_INFO, 0x0390),
241:
242: ACXREG(PHY_ADDR, 0x0350),
243: ACXREG(PHY_DATA, 0x0354),
244: ACXREG(PHY_CTRL, 0x0358),
245:
246: ACXREG(GPIO_OUT_ENABLE, 0x0374),
247: ACXREG(GPIO_OUT, 0x037c),
248:
249: ACXREG(CMD_REG_OFFSET, 0x0388),
250: ACXREG(INFO_REG_OFFSET, 0x038c),
251:
252: ACXREG(RESET_SENSE, 0x0104),
253: ACXREG(ECPU_CTRL, 0x0108)
254: };
255:
256: /* XXX */
257: static uint16_t acx111_rate_map[109] = {
258: ACX111_RATE_2,
259: ACX111_RATE_4,
260: ACX111_RATE_11,
261: ACX111_RATE_22,
262: ACX111_RATE_12,
263: ACX111_RATE_18,
264: ACX111_RATE_24,
265: ACX111_RATE_36,
266: ACX111_RATE_48,
267: ACX111_RATE_72,
268: ACX111_RATE_96,
269: ACX111_RATE_108
270: };
271:
272: void
273: acx111_set_param(struct acx_softc *sc)
274: {
275: sc->chip_mem1_rid = PCIR_BAR(0);
276: sc->chip_mem2_rid = PCIR_BAR(1);
277: sc->chip_ioreg = acx111_reg;
278: sc->chip_intr_enable = ACX111_INTR_ENABLE;
279: sc->chip_intr_disable = ACX111_INTR_DISABLE;
280: sc->chip_gpio_pled = ACX111_GPIO_POWER_LED;
281: sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS;
282:
283: sc->chip_phymode = IEEE80211_MODE_11G;
284: sc->chip_chan_flags = IEEE80211_CHAN_CCK |
285: IEEE80211_CHAN_OFDM |
286: IEEE80211_CHAN_DYN |
287: IEEE80211_CHAN_2GHZ;
288: sc->sc_ic.ic_caps = IEEE80211_C_WEP;
289: sc->sc_ic.ic_phytype = IEEE80211_T_OFDM;
290: sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
291: sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
292:
293: sc->chip_init = acx111_init;
294: sc->chip_write_config = acx111_write_config;
295: sc->chip_set_fw_txdesc_rate = acx111_set_fw_txdesc_rate;
296: sc->chip_set_bss_join_param = acx111_set_bss_join_param;
297: sc->sc_flags |= ACX_FLAG_ACX111;
298: }
299:
300: int
301: acx111_init(struct acx_softc *sc)
302: {
303: struct ifnet *ifp = &sc->sc_ic.ic_if;
304:
305: /*
306: * NOTE:
307: * Order of initialization:
308: * 1) Templates
309: * 2) Hardware memory
310: * Above order is critical to get a correct memory map
311: */
312: if (acx_init_tmplt_ordered(sc) != 0) {
313: printf("%s: %s can't initialize templates\n",
314: ifp->if_xname, __func__);
315: return (ENXIO);
316: }
317:
318: if (acx111_init_memory(sc) != 0) {
319: printf("%s: %s can't initialize hw memory\n",
320: ifp->if_xname, __func__);
321: return (ENXIO);
322: }
323:
324: return (0);
325: }
326:
327: int
328: acx111_init_memory(struct acx_softc *sc)
329: {
330: struct acx111_conf_mem mem;
331: struct acx111_conf_meminfo mem_info;
332: struct ifnet *ifp = &sc->sc_ic.ic_if;
333:
334: /* Set memory configuration */
335: bzero(&mem, sizeof(mem));
336:
337: mem.sta_max = htole16(ACX111_STA_MAX);
338: mem.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
339: mem.rx_memblk_perc = ACX111_RX_MEMBLK_PERCENT;
340: mem.opt = ACX111_MEMOPT_DEFAULT;
341: mem.xfer_perc = ACX111_XFER_PERCENT;
342:
343: mem.fw_rxring_num = 1;
344: mem.fw_rxring_type = ACX111_RXRING_TYPE_DEFAULT;
345: mem.fw_rxring_prio = ACX111_RXRING_PRIO_DEFAULT;
346: mem.fw_rxdesc_num = ACX_RX_DESC_CNT;
347: mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
348:
349: mem.fw_txring_num = 1;
350: mem.fw_txring_attr = ACX111_TXRING_ATTR_DEFAULT;
351: mem.fw_txdesc_num = ACX_TX_DESC_CNT;
352:
353: if (acx_set_conf(sc, ACX111_CONF_MEM, &mem, sizeof(mem)) != 0) {
354: printf("%s: can't set mem\n", ifp->if_xname);
355: return (1);
356: }
357:
358: /* Get memory configuration */
359: if (acx_get_conf(sc, ACX111_CONF_MEMINFO, &mem_info,
360: sizeof(mem_info)) != 0) {
361: printf("%s: can't get meminfo\n", ifp->if_xname);
362: return (1);
363: }
364:
365: /* Setup firmware TX descriptor ring */
366: acx111_init_fw_txring(sc, letoh32(mem_info.fw_txring_start));
367:
368: /*
369: * There is no need to setup firmware RX descriptor ring,
370: * it is automaticly setup by hardware.
371: */
372:
373: return (0);
374: }
375:
376: void
377: acx111_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
378: {
379: struct acx_txbuf *tx_buf;
380: uint32_t desc_paddr;
381: int i;
382:
383: tx_buf = sc->sc_buf_data.tx_buf;
384: desc_paddr = sc->sc_ring_data.tx_ring_paddr;
385:
386: for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
387: tx_buf[i].tb_fwdesc_ofs = fw_txdesc_start +
388: (i * ACX111_FW_TXDESC_SIZE);
389:
390: /*
391: * Except for the following fields, rest of the fields
392: * are setup by hardware.
393: */
394: FW_TXDESC_SETFIELD_4(sc, &tx_buf[i], f_tx_host_desc,
395: desc_paddr);
396: FW_TXDESC_SETFIELD_1(sc, &tx_buf[i], f_tx_ctrl,
397: DESC_CTRL_HOSTOWN);
398:
399: desc_paddr += (2 * sizeof(struct acx_host_desc));
400: }
401: }
402:
403: int
404: acx111_write_config(struct acx_softc *sc, struct acx_config *conf)
405: {
406: struct acx111_conf_txpower tx_power;
407: struct acx111_conf_option opt;
408: struct ifnet *ifp = &sc->sc_ic.ic_if;
409: uint32_t dataflow;
410:
411: /* Set TX power */
412: tx_power.txpower = ACX111_TXPOWER_VAL;
413: if (acx_set_conf(sc, ACX_CONF_TXPOWER, &tx_power,
414: sizeof(tx_power)) != 0) {
415: printf("%s: %s can't set TX power\n",
416: ifp->if_xname, __func__);
417: return (ENXIO);
418: }
419:
420: /*
421: * Turn off hardware WEP
422: */
423: if (acx_get_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) {
424: printf("%s: %s can't get option\n", ifp->if_xname, __func__);
425: return (ENXIO);
426: }
427:
428: dataflow = letoh32(opt.dataflow) |
429: ACX111_DF_NO_TXENCRYPT |
430: ACX111_DF_NO_RXDECRYPT;
431: opt.dataflow = htole32(dataflow);
432:
433: if (acx_set_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) {
434: printf("%s: %s can't set option\n", ifp->if_xname, __func__);
435: return (ENXIO);
436: }
437:
438: return (0);
439: }
440:
441: void
442: acx111_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
443: int rate0)
444: {
445: uint16_t rate;
446:
447: rate = acx111_rate_map[rate0];
448: if (rate == 0)
449: /* set rate to 1Mbit/s if rate was zero */
450: rate = acx111_rate_map[2];
451:
452: FW_TXDESC_SETFIELD_2(sc, tx_buf, u.r2.rate111, rate);
453: }
454:
455: void
456: acx111_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
457: {
458: struct acx111_bss_join *bj = param;
459:
460: bj->basic_rates = htole16(ACX111_RATE_ALL);
461: bj->dtim_intvl = dtim_intvl;
462: }
CVSweb