xref: /openbsd-src/sys/dev/ic/acx111.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: acx111.c,v 1.19 2012/10/27 16:13:28 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/systm.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 #ifndef IEEE80211_STA_ONLY
280 	sc->chip_intr_enable |= ACXRV_INTR_DTIM;
281 #endif
282 	sc->chip_intr_disable = ACX111_INTR_DISABLE;
283 	sc->chip_gpio_pled = ACX111_GPIO_POWER_LED;
284 	sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS;
285 
286 	sc->chip_phymode = IEEE80211_MODE_11G;
287 	sc->chip_chan_flags = IEEE80211_CHAN_CCK |
288 	    IEEE80211_CHAN_OFDM |
289 	    IEEE80211_CHAN_DYN |
290 	    IEEE80211_CHAN_2GHZ;
291 	sc->sc_ic.ic_caps = IEEE80211_C_WEP | IEEE80211_C_SHSLOT;
292 	sc->sc_ic.ic_phytype = IEEE80211_T_OFDM;
293 	sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
294 	sc->sc_ic.ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
295 
296 	sc->chip_init = acx111_init;
297 	sc->chip_write_config = acx111_write_config;
298 	sc->chip_set_fw_txdesc_rate = acx111_set_fw_txdesc_rate;
299 	sc->chip_set_bss_join_param = acx111_set_bss_join_param;
300 	sc->sc_flags |= ACX_FLAG_ACX111;
301 }
302 
303 int
304 acx111_init(struct acx_softc *sc)
305 {
306 	struct ifnet *ifp = &sc->sc_ic.ic_if;
307 
308 	/*
309 	 * NOTE:
310 	 * Order of initialization:
311 	 * 1) Templates
312 	 * 2) Hardware memory
313 	 * Above order is critical to get a correct memory map
314 	 */
315 	if (acx_init_tmplt_ordered(sc) != 0) {
316 		printf("%s: %s can't initialize templates\n",
317 		    ifp->if_xname, __func__);
318 		return (ENXIO);
319 	}
320 
321 	if (acx111_init_memory(sc) != 0) {
322 		printf("%s: %s can't initialize hw memory\n",
323 		    ifp->if_xname, __func__);
324 		return (ENXIO);
325 	}
326 
327 	return (0);
328 }
329 
330 int
331 acx111_init_memory(struct acx_softc *sc)
332 {
333 	struct acx111_conf_mem mem;
334 	struct acx111_conf_meminfo mem_info;
335 	struct ifnet *ifp = &sc->sc_ic.ic_if;
336 
337 	/* Set memory configuration */
338 	bzero(&mem, sizeof(mem));
339 
340 	mem.sta_max = htole16(ACX111_STA_MAX);
341 	mem.memblk_size = htole16(ACX_MEMBLOCK_SIZE);
342 	mem.rx_memblk_perc = ACX111_RX_MEMBLK_PERCENT;
343 	mem.opt = ACX111_MEMOPT_DEFAULT;
344 	mem.xfer_perc = ACX111_XFER_PERCENT;
345 
346 	mem.fw_rxring_num = 1;
347 	mem.fw_rxring_type = ACX111_RXRING_TYPE_DEFAULT;
348 	mem.fw_rxring_prio = ACX111_RXRING_PRIO_DEFAULT;
349 	mem.fw_rxdesc_num = ACX_RX_DESC_CNT;
350 	mem.h_rxring_paddr = htole32(sc->sc_ring_data.rx_ring_paddr);
351 
352 	mem.fw_txring_num = 1;
353 	mem.fw_txring_attr = ACX111_TXRING_ATTR_DEFAULT;
354 	mem.fw_txdesc_num = ACX_TX_DESC_CNT;
355 
356 	if (acx_set_conf(sc, ACX111_CONF_MEM, &mem, sizeof(mem)) != 0) {
357 		printf("%s: can't set mem\n", ifp->if_xname);
358 		return (1);
359 	}
360 
361 	/* Get memory configuration */
362 	if (acx_get_conf(sc, ACX111_CONF_MEMINFO, &mem_info,
363 	    sizeof(mem_info)) != 0) {
364 		printf("%s: can't get meminfo\n", ifp->if_xname);
365 		return (1);
366 	}
367 
368 	/* Setup firmware TX descriptor ring */
369 	acx111_init_fw_txring(sc, letoh32(mem_info.fw_txring_start));
370 
371 	/*
372 	 * There is no need to setup firmware RX descriptor ring,
373 	 * it is automaticly setup by hardware.
374 	 */
375 
376 	return (0);
377 }
378 
379 void
380 acx111_init_fw_txring(struct acx_softc *sc, uint32_t fw_txdesc_start)
381 {
382 	struct acx_txbuf *tx_buf;
383 	uint32_t desc_paddr;
384 	int i;
385 
386 	tx_buf = sc->sc_buf_data.tx_buf;
387 	desc_paddr = sc->sc_ring_data.tx_ring_paddr;
388 
389 	for (i = 0; i < ACX_TX_DESC_CNT; ++i) {
390 		tx_buf[i].tb_fwdesc_ofs = fw_txdesc_start +
391 		    (i * ACX111_FW_TXDESC_SIZE);
392 
393 		/*
394 		 * Except for the following fields, rest of the fields
395 		 * are setup by hardware.
396 		 */
397 		FW_TXDESC_SETFIELD_4(sc, &tx_buf[i], f_tx_host_desc,
398 		    desc_paddr);
399 		FW_TXDESC_SETFIELD_1(sc, &tx_buf[i], f_tx_ctrl,
400 		    DESC_CTRL_HOSTOWN);
401 
402 		desc_paddr += (2 * sizeof(struct acx_host_desc));
403 	}
404 }
405 
406 int
407 acx111_write_config(struct acx_softc *sc, struct acx_config *conf)
408 {
409 	struct acx111_conf_txpower tx_power;
410 	struct acx111_conf_option opt;
411 	struct ifnet *ifp = &sc->sc_ic.ic_if;
412 	uint32_t dataflow;
413 
414 	/* Set TX power */
415 	tx_power.txpower = ACX111_TXPOWER_VAL;
416 	if (acx_set_conf(sc, ACX_CONF_TXPOWER, &tx_power,
417 	    sizeof(tx_power)) != 0) {
418 		printf("%s: %s can't set TX power\n",
419 		    ifp->if_xname, __func__);
420 		return (ENXIO);
421 	}
422 
423 	/*
424 	 * Turn off hardware WEP
425 	 */
426 	if (acx_get_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) {
427 		printf("%s: %s can't get option\n", ifp->if_xname, __func__);
428 		return (ENXIO);
429 	}
430 
431 	dataflow = letoh32(opt.dataflow) |
432 	    ACX111_DF_NO_TXENCRYPT |
433 	    ACX111_DF_NO_RXDECRYPT;
434 	opt.dataflow = htole32(dataflow);
435 
436 	if (acx_set_conf(sc, ACX_CONF_OPTION, &opt, sizeof(opt)) != 0) {
437 		printf("%s: %s can't set option\n", ifp->if_xname, __func__);
438 		return (ENXIO);
439 	}
440 
441 	return (0);
442 }
443 
444 void
445 acx111_set_fw_txdesc_rate(struct acx_softc *sc, struct acx_txbuf *tx_buf,
446     int rate0)
447 {
448 	uint16_t rate;
449 
450 	rate = acx111_rate_map[rate0];
451 	if (rate == 0)
452 		/* set rate to 1Mbit/s if rate was zero */
453 		rate = acx111_rate_map[2];
454 
455 	FW_TXDESC_SETFIELD_2(sc, tx_buf, u.r2.rate111, rate);
456 }
457 
458 void
459 acx111_set_bss_join_param(struct acx_softc *sc, void *param, int dtim_intvl)
460 {
461 	struct acx111_bss_join *bj = param;
462 
463 	bj->basic_rates = htole16(ACX111_RATE_ALL);
464 	bj->dtim_intvl = dtim_intvl;
465 }
466