bwimac.c revision 191762
1/*
2 * Copyright (c) 2007 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/bwi/bwimac.c,v 1.13 2008/02/15 11:15:38 sephe Exp $
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/dev/bwi/bwimac.c 191762 2009-05-03 04:01:43Z imp $");
39
40#include "opt_inet.h"
41#include "opt_bwi.h"
42
43#include <sys/param.h>
44#include <sys/endian.h>
45#include <sys/kernel.h>
46#include <sys/bus.h>
47#include <sys/malloc.h>
48#include <sys/proc.h>
49#include <sys/rman.h>
50#include <sys/socket.h>
51#include <sys/sockio.h>
52#include <sys/sysctl.h>
53#include <sys/systm.h>
54
55#include <sys/linker.h>
56#include <sys/firmware.h>
57
58#include <net/if.h>
59#include <net/if_dl.h>
60#include <net/if_media.h>
61#include <net/if_types.h>
62#include <net/if_arp.h>
63#include <net/ethernet.h>
64#include <net/if_llc.h>
65
66#include <net80211/ieee80211_var.h>
67#include <net80211/ieee80211_radiotap.h>
68#include <net80211/ieee80211_amrr.h>
69#include <net80211/ieee80211_phy.h>
70
71#include <machine/bus.h>
72
73#include <dev/bwi/bitops.h>
74#include <dev/bwi/if_bwireg.h>
75#include <dev/bwi/if_bwivar.h>
76#include <dev/bwi/bwimac.h>
77#include <dev/bwi/bwirf.h>
78#include <dev/bwi/bwiphy.h>
79
80struct bwi_retry_lim {
81	uint16_t	shretry;
82	uint16_t	shretry_fb;
83	uint16_t	lgretry;
84	uint16_t	lgretry_fb;
85};
86
87static int	bwi_mac_test(struct bwi_mac *);
88static int	bwi_mac_get_property(struct bwi_mac *);
89
90static void	bwi_mac_set_retry_lim(struct bwi_mac *,
91			const struct bwi_retry_lim *);
92static void	bwi_mac_set_ackrates(struct bwi_mac *,
93			const struct ieee80211_rate_table *rt,
94			const struct ieee80211_rateset *);
95
96static int	bwi_mac_gpio_init(struct bwi_mac *);
97static int	bwi_mac_gpio_fini(struct bwi_mac *);
98static void	bwi_mac_opmode_init(struct bwi_mac *);
99static void	bwi_mac_hostflags_init(struct bwi_mac *);
100static void	bwi_mac_bss_param_init(struct bwi_mac *);
101
102static int	bwi_mac_fw_alloc(struct bwi_mac *);
103static void	bwi_mac_fw_free(struct bwi_mac *);
104static int	bwi_mac_fw_load(struct bwi_mac *);
105static int	bwi_mac_fw_init(struct bwi_mac *);
106static int	bwi_mac_fw_load_iv(struct bwi_mac *, const struct firmware *);
107
108static void	bwi_mac_setup_tpctl(struct bwi_mac *);
109static void	bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
110
111static void	bwi_mac_lock(struct bwi_mac *);
112static void	bwi_mac_unlock(struct bwi_mac *);
113
114static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10 };
115
116void
117bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val)
118{
119	struct bwi_softc *sc = mac->mac_sc;
120
121	if (mac->mac_flags & BWI_MAC_F_BSWAP)
122		val = bswap32(val);
123
124	CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs);
125	CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val);
126}
127
128void
129bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags)
130{
131	uint64_t val;
132
133	val = flags & 0xffff;
134	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val);
135
136	val = (flags >> 16) & 0xffff;
137	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val);
138
139	/* HI has unclear meaning, so leave it as it is */
140}
141
142uint64_t
143bwi_hostflags_read(struct bwi_mac *mac)
144{
145	uint64_t flags, val;
146
147	/* HI has unclear meaning, so don't touch it */
148	flags = 0;
149
150	val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI);
151	flags |= val << 16;
152
153	val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO);
154	flags |= val;
155
156	return flags;
157}
158
159uint16_t
160bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
161{
162	struct bwi_softc *sc = mac->mac_sc;
163	uint32_t data_reg;
164	int ofs;
165
166	data_reg = BWI_MOBJ_DATA;
167	ofs = ofs0 / 4;
168
169	if (ofs0 % 4 != 0)
170		data_reg = BWI_MOBJ_DATA_UNALIGN;
171
172	CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
173	return CSR_READ_2(sc, data_reg);
174}
175
176uint32_t
177bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
178{
179	struct bwi_softc *sc = mac->mac_sc;
180	int ofs;
181
182	ofs = ofs0 / 4;
183	if (ofs0 % 4 != 0) {
184		uint32_t ret;
185
186		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
187		ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN);
188		ret <<= 16;
189
190		CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
191			    BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
192		ret |= CSR_READ_2(sc, BWI_MOBJ_DATA);
193
194		return ret;
195	} else {
196		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
197		return CSR_READ_4(sc, BWI_MOBJ_DATA);
198	}
199}
200
201void
202bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
203		   uint16_t v)
204{
205	struct bwi_softc *sc = mac->mac_sc;
206	uint32_t data_reg;
207	int ofs;
208
209	data_reg = BWI_MOBJ_DATA;
210	ofs = ofs0 / 4;
211
212	if (ofs0 % 4 != 0)
213		data_reg = BWI_MOBJ_DATA_UNALIGN;
214
215	CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
216	CSR_WRITE_2(sc, data_reg, v);
217}
218
219void
220bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
221		   uint32_t v)
222{
223	struct bwi_softc *sc = mac->mac_sc;
224	int ofs;
225
226	ofs = ofs0 / 4;
227	if (ofs0 % 4 != 0) {
228		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
229		CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16);
230
231		CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
232			    BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
233		CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff);
234	} else {
235		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
236		CSR_WRITE_4(sc, BWI_MOBJ_DATA, v);
237	}
238}
239
240int
241bwi_mac_lateattach(struct bwi_mac *mac)
242{
243	int error;
244
245	if (mac->mac_rev >= 5)
246		CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */
247
248	bwi_mac_reset(mac, 1);
249
250	error = bwi_phy_attach(mac);
251	if (error)
252		return error;
253
254	error = bwi_rf_attach(mac);
255	if (error)
256		return error;
257
258	/* Link 11B/G PHY, unlink 11A PHY */
259	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A)
260		bwi_mac_reset(mac, 0);
261	else
262		bwi_mac_reset(mac, 1);
263
264	error = bwi_mac_test(mac);
265	if (error)
266		return error;
267
268	error = bwi_mac_get_property(mac);
269	if (error)
270		return error;
271
272	error = bwi_rf_map_txpower(mac);
273	if (error)
274		return error;
275
276	bwi_rf_off(mac);
277	CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
278	bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0);
279
280	return 0;
281}
282
283int
284bwi_mac_init(struct bwi_mac *mac)
285{
286	struct bwi_softc *sc = mac->mac_sc;
287	int error, i;
288
289	/* Clear MAC/PHY/RF states */
290	bwi_mac_setup_tpctl(mac);
291	bwi_rf_clear_state(&mac->mac_rf);
292	bwi_phy_clear_state(&mac->mac_phy);
293
294	/* Enable MAC and linked it to PHY */
295	if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin))
296		bwi_mac_reset(mac, 1);
297
298	/* Initialize backplane */
299	error = bwi_bus_init(sc, mac);
300	if (error)
301		return error;
302
303	/* XXX work around for hardware bugs? */
304	if (sc->sc_bus_regwin.rw_rev <= 5 &&
305	    sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) {
306		CSR_SETBITS_4(sc, BWI_CONF_LO,
307		__SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) |
308		__SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK));
309	}
310
311	/* Calibrate PHY */
312	error = bwi_phy_calibrate(mac);
313	if (error) {
314		device_printf(sc->sc_dev, "PHY calibrate failed\n");
315		return error;
316	}
317
318	/* Prepare to initialize firmware */
319	CSR_WRITE_4(sc, BWI_MAC_STATUS,
320		    BWI_MAC_STATUS_UCODE_JUMP0 |
321		    BWI_MAC_STATUS_IHREN);
322
323	/*
324	 * Load and initialize firmwares
325	 */
326	error = bwi_mac_fw_alloc(mac);
327	if (error)
328		return error;
329
330	error = bwi_mac_fw_load(mac);
331	if (error)
332		return error;
333
334	error = bwi_mac_gpio_init(mac);
335	if (error)
336		return error;
337
338	error = bwi_mac_fw_init(mac);
339	if (error)
340		return error;
341
342	/*
343	 * Turn on RF
344	 */
345	bwi_rf_on(mac);
346
347	/* TODO: LED, hardware rf enabled is only related to LED setting */
348
349	/*
350	 * Initialize PHY
351	 */
352	CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
353	bwi_phy_init(mac);
354
355	/* TODO: interference mitigation */
356
357	/*
358	 * Setup antenna mode
359	 */
360	bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode);
361
362	/*
363	 * Initialize operation mode (RX configuration)
364	 */
365	bwi_mac_opmode_init(mac);
366
367	/* XXX what's these */
368	if (mac->mac_rev < 3) {
369		CSR_WRITE_2(sc, 0x60e, 0);
370		CSR_WRITE_2(sc, 0x610, 0x8000);
371		CSR_WRITE_2(sc, 0x604, 0);
372		CSR_WRITE_2(sc, 0x606, 0x200);
373	} else {
374		CSR_WRITE_4(sc, 0x188, 0x80000000);
375		CSR_WRITE_4(sc, 0x18c, 0x2000000);
376	}
377
378	/*
379	 * Initialize TX/RX interrupts' mask
380	 */
381	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1);
382	for (i = 0; i < BWI_TXRX_NRING; ++i) {
383		uint32_t intrs;
384
385		if (BWI_TXRX_IS_RX(i))
386			intrs = BWI_TXRX_RX_INTRS;
387		else
388			intrs = BWI_TXRX_TX_INTRS;
389		CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs);
390	}
391
392	/* XXX what's this */
393	CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000);
394
395	/* Setup MAC power up delay */
396	CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay);
397
398	/* Set MAC regwin revision */
399	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev);
400
401	/*
402	 * Initialize host flags
403	 */
404	bwi_mac_hostflags_init(mac);
405
406	/*
407	 * Initialize BSS parameters
408	 */
409	bwi_mac_bss_param_init(mac);
410
411	/*
412	 * Initialize TX rings
413	 */
414	for (i = 0; i < BWI_TX_NRING; ++i) {
415		error = sc->sc_init_tx_ring(sc, i);
416		if (error) {
417			device_printf(sc->sc_dev,
418				  "can't initialize %dth TX ring\n", i);
419			return error;
420		}
421	}
422
423	/*
424	 * Initialize RX ring
425	 */
426	error = sc->sc_init_rx_ring(sc);
427	if (error) {
428		device_printf(sc->sc_dev, "can't initialize RX ring\n");
429		return error;
430	}
431
432	/*
433	 * Initialize TX stats if the current MAC uses that
434	 */
435	if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) {
436		error = sc->sc_init_txstats(sc);
437		if (error) {
438			device_printf(sc->sc_dev,
439				  "can't initialize TX stats ring\n");
440			return error;
441		}
442	}
443
444	/* XXX what's these */
445	CSR_WRITE_2(sc, 0x612, 0x50);	/* Force Pre-TBTT to 80? */
446	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50);
447	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4);
448
449	mac->mac_flags |= BWI_MAC_F_INITED;
450	return 0;
451}
452
453void
454bwi_mac_reset(struct bwi_mac *mac, int link_phy)
455{
456	struct bwi_softc *sc = mac->mac_sc;
457	uint32_t flags, state_lo, status;
458
459	flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN;
460	if (link_phy)
461		flags |= BWI_STATE_LO_FLAG_PHYLNK;
462	bwi_regwin_enable(sc, &mac->mac_regwin, flags);
463	DELAY(2000);
464
465	state_lo = CSR_READ_4(sc, BWI_STATE_LO);
466	state_lo |= BWI_STATE_LO_GATED_CLOCK;
467	state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST,
468			       BWI_STATE_LO_FLAGS_MASK);
469	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
470	/* Flush pending bus write */
471	CSR_READ_4(sc, BWI_STATE_LO);
472	DELAY(1000);
473
474	state_lo &= ~BWI_STATE_LO_GATED_CLOCK;
475	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
476	/* Flush pending bus write */
477	CSR_READ_4(sc, BWI_STATE_LO);
478	DELAY(1000);
479
480	CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
481
482	status = CSR_READ_4(sc, BWI_MAC_STATUS);
483	status |= BWI_MAC_STATUS_IHREN;
484	if (link_phy)
485		status |= BWI_MAC_STATUS_PHYLNK;
486	else
487		status &= ~BWI_MAC_STATUS_PHYLNK;
488	CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
489
490	if (link_phy) {
491		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
492			"%s\n", "PHY is linked");
493		mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED;
494	} else {
495		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
496			"%s\n", "PHY is unlinked");
497		mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED;
498	}
499}
500
501void
502bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl)
503{
504	struct bwi_rf *rf = &mac->mac_rf;
505	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
506
507	if (new_tpctl != NULL) {
508		KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX,
509		    ("bbp_atten %d", new_tpctl->bbp_atten));
510		KASSERT(new_tpctl->rf_atten <=
511			 (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0
512			 		 : BWI_RF_ATTEN_MAX1),
513		    ("rf_atten %d", new_tpctl->rf_atten));
514		KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX,
515		    ("tp_ctrl1 %d", new_tpctl->tp_ctrl1));
516
517		tpctl->bbp_atten = new_tpctl->bbp_atten;
518		tpctl->rf_atten = new_tpctl->rf_atten;
519		tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1;
520	}
521
522	/* Set BBP attenuation */
523	bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten);
524
525	/* Set RF attenuation */
526	RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten);
527	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN,
528		     tpctl->rf_atten);
529
530	/* Set TX power */
531	if (rf->rf_type == BWI_RF_T_BCM2050) {
532		RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK,
533			__SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK));
534	}
535
536	/* Adjust RF Local Oscillator */
537	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
538		bwi_rf_lo_adjust(mac, tpctl);
539}
540
541static int
542bwi_mac_test(struct bwi_mac *mac)
543{
544	struct bwi_softc *sc = mac->mac_sc;
545	uint32_t orig_val, val;
546
547#define TEST_VAL1	0xaa5555aa
548#define TEST_VAL2	0x55aaaa55
549
550	/* Save it for later restoring */
551	orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
552
553	/* Test 1 */
554	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1);
555	val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
556	if (val != TEST_VAL1) {
557		device_printf(sc->sc_dev, "TEST1 failed\n");
558		return ENXIO;
559	}
560
561	/* Test 2 */
562	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2);
563	val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
564	if (val != TEST_VAL2) {
565		device_printf(sc->sc_dev, "TEST2 failed\n");
566		return ENXIO;
567	}
568
569	/* Restore to the original value */
570	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val);
571
572	val = CSR_READ_4(sc, BWI_MAC_STATUS);
573	if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) {
574		device_printf(sc->sc_dev, "%s failed, MAC status 0x%08x\n",
575			      __func__, val);
576		return ENXIO;
577	}
578
579	val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
580	if (val != 0) {
581		device_printf(sc->sc_dev, "%s failed, intr status %08x\n",
582			      __func__, val);
583		return ENXIO;
584	}
585
586#undef TEST_VAL2
587#undef TEST_VAL1
588
589	return 0;
590}
591
592static void
593bwi_mac_setup_tpctl(struct bwi_mac *mac)
594{
595	struct bwi_softc *sc = mac->mac_sc;
596	struct bwi_rf *rf = &mac->mac_rf;
597	struct bwi_phy *phy = &mac->mac_phy;
598	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
599
600	/* Calc BBP attenuation */
601	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6)
602		tpctl->bbp_atten = 0;
603	else
604		tpctl->bbp_atten = 2;
605
606	/* Calc TX power CTRL1?? */
607	tpctl->tp_ctrl1 = 0;
608	if (rf->rf_type == BWI_RF_T_BCM2050) {
609		if (rf->rf_rev == 1)
610			tpctl->tp_ctrl1 = 3;
611		else if (rf->rf_rev < 6)
612			tpctl->tp_ctrl1 = 2;
613		else if (rf->rf_rev == 8)
614			tpctl->tp_ctrl1 = 1;
615	}
616
617	/* Empty TX power CTRL2?? */
618	tpctl->tp_ctrl2 = 0xffff;
619
620	/*
621	 * Calc RF attenuation
622	 */
623	if (phy->phy_mode == IEEE80211_MODE_11A) {
624		tpctl->rf_atten = 0x60;
625		goto back;
626	}
627
628	if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) {
629		tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3;
630		goto back;
631	}
632
633	tpctl->rf_atten = 5;
634
635	if (rf->rf_type != BWI_RF_T_BCM2050) {
636		if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1)
637			tpctl->rf_atten = 6;
638		goto back;
639	}
640
641	/*
642	 * NB: If we reaches here and the card is BRCM_BCM4309G,
643	 *     then the card's PCI revision must >= 0x51
644	 */
645
646	/* BCM2050 RF */
647	switch (rf->rf_rev) {
648	case 1:
649		if (phy->phy_mode == IEEE80211_MODE_11G) {
650			if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc))
651				tpctl->rf_atten = 3;
652			else
653				tpctl->rf_atten = 1;
654		} else {
655			if (BWI_IS_BRCM_BCM4309G(sc))
656				tpctl->rf_atten = 7;
657			else
658				tpctl->rf_atten = 6;
659		}
660		break;
661	case 2:
662		if (phy->phy_mode == IEEE80211_MODE_11G) {
663			/*
664			 * NOTE: Order of following conditions is critical
665			 */
666			if (BWI_IS_BRCM_BCM4309G(sc))
667				tpctl->rf_atten = 3;
668			else if (BWI_IS_BRCM_BU4306(sc))
669				tpctl->rf_atten = 5;
670			else if (sc->sc_bbp_id == BWI_BBPID_BCM4320)
671				tpctl->rf_atten = 4;
672			else
673				tpctl->rf_atten = 3;
674		} else {
675			tpctl->rf_atten = 6;
676		}
677		break;
678	case 4:
679	case 5:
680		tpctl->rf_atten = 1;
681		break;
682	case 8:
683		tpctl->rf_atten = 0x1a;
684		break;
685	}
686back:
687	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
688		"bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n",
689		tpctl->bbp_atten, tpctl->rf_atten,
690		tpctl->tp_ctrl1, tpctl->tp_ctrl2);
691}
692
693void
694bwi_mac_dummy_xmit(struct bwi_mac *mac)
695{
696#define PACKET_LEN	5
697	static const uint32_t	packet_11a[PACKET_LEN] =
698	{ 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
699	static const uint32_t	packet_11bg[PACKET_LEN] =
700	{ 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
701
702	struct bwi_softc *sc = mac->mac_sc;
703	struct bwi_rf *rf = &mac->mac_rf;
704	const uint32_t *packet;
705	uint16_t val_50c;
706	int wait_max, i;
707
708	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
709		wait_max = 30;
710		packet = packet_11a;
711		val_50c = 1;
712	} else {
713		wait_max = 250;
714		packet = packet_11bg;
715		val_50c = 0;
716	}
717
718	for (i = 0; i < PACKET_LEN; ++i)
719		TMPLT_WRITE_4(mac, i * 4, packet[i]);
720
721	CSR_READ_4(sc, BWI_MAC_STATUS);	/* dummy read */
722
723	CSR_WRITE_2(sc, 0x568, 0);
724	CSR_WRITE_2(sc, 0x7c0, 0);
725	CSR_WRITE_2(sc, 0x50c, val_50c);
726	CSR_WRITE_2(sc, 0x508, 0);
727	CSR_WRITE_2(sc, 0x50a, 0);
728	CSR_WRITE_2(sc, 0x54c, 0);
729	CSR_WRITE_2(sc, 0x56a, 0x14);
730	CSR_WRITE_2(sc, 0x568, 0x826);
731	CSR_WRITE_2(sc, 0x500, 0);
732	CSR_WRITE_2(sc, 0x502, 0x30);
733
734	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
735		RF_WRITE(mac, 0x51, 0x17);
736
737	for (i = 0; i < wait_max; ++i) {
738		if (CSR_READ_2(sc, 0x50e) & 0x80)
739			break;
740		DELAY(10);
741	}
742	for (i = 0; i < 10; ++i) {
743		if (CSR_READ_2(sc, 0x50e) & 0x400)
744			break;
745		DELAY(10);
746	}
747	for (i = 0; i < 10; ++i) {
748		if ((CSR_READ_2(sc, 0x690) & 0x100) == 0)
749			break;
750		DELAY(10);
751	}
752
753	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
754		RF_WRITE(mac, 0x51, 0x37);
755#undef PACKET_LEN
756}
757
758void
759bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
760{
761	struct bwi_softc *sc = mac->mac_sc;
762	struct bwi_phy *phy = &mac->mac_phy;
763	struct bwi_rf *rf = &mac->mac_rf;
764	struct bwi_tpctl tpctl_orig;
765	int restore_tpctl = 0;
766
767	KASSERT(phy->phy_mode != IEEE80211_MODE_11A,
768	    ("phy_mode %d", phy->phy_mode));
769
770	if (BWI_IS_BRCM_BU4306(sc))
771		return;
772
773	PHY_WRITE(mac, 0x28, 0x8018);
774	CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20);
775
776	if (phy->phy_mode == IEEE80211_MODE_11G) {
777		if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
778			return;
779		PHY_WRITE(mac, 0x47a, 0xc111);
780	}
781	if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED)
782		return;
783
784	if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 &&
785	    rf->rf_type == BWI_RF_T_BCM2050) {
786		RF_SETBITS(mac, 0x76, 0x84);
787	} else {
788		struct bwi_tpctl tpctl;
789
790		/* Backup original TX power control variables */
791		bcopy(&mac->mac_tpctl, &tpctl_orig, sizeof(tpctl_orig));
792		restore_tpctl = 1;
793
794		bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
795		tpctl.bbp_atten = 11;
796		tpctl.tp_ctrl1 = 0;
797#ifdef notyet
798		if (rf->rf_rev >= 6 && rf->rf_rev <= 8)
799			tpctl.rf_atten = 31;
800		else
801#endif
802			tpctl.rf_atten = 9;
803
804		bwi_mac_set_tpctl_11bg(mac, &tpctl);
805	}
806
807	bwi_mac_dummy_xmit(mac);
808
809	mac->mac_flags |= BWI_MAC_F_TPCTL_INITED;
810	rf->rf_base_tssi = PHY_READ(mac, 0x29);
811	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
812		"base tssi %d\n", rf->rf_base_tssi);
813
814	if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) {
815		device_printf(sc->sc_dev, "base tssi measure failed\n");
816		mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR;
817	}
818
819	if (restore_tpctl)
820		bwi_mac_set_tpctl_11bg(mac, &tpctl_orig);
821	else
822		RF_CLRBITS(mac, 0x76, 0x84);
823
824	bwi_rf_clear_tssi(mac);
825}
826
827void
828bwi_mac_detach(struct bwi_mac *mac)
829{
830	bwi_mac_fw_free(mac);
831}
832
833static __inline int
834bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
835		     uint8_t fw_type)
836{
837	const struct bwi_fwhdr *hdr;
838	struct ifnet *ifp = sc->sc_ifp;
839
840	if (fw->datasize < sizeof(*hdr)) {
841		if_printf(ifp, "invalid firmware (%s): invalid size %zu\n",
842			  fw->name, fw->datasize);
843		return 0;
844	}
845
846	hdr = (const struct bwi_fwhdr *)fw->data;
847
848	if (fw_type != BWI_FW_T_IV) {
849		/*
850		 * Don't verify IV's size, it has different meaning
851		 */
852		if (be32toh(hdr->fw_size) != fw->datasize - sizeof(*hdr)) {
853			if_printf(ifp, "invalid firmware (%s): size mismatch, "
854				  "fw %u, real %zu\n", fw->name,
855				  be32toh(hdr->fw_size),
856				  fw->datasize - sizeof(*hdr));
857			return 0;
858		}
859	}
860
861	if (hdr->fw_type != fw_type) {
862		if_printf(ifp, "invalid firmware (%s): type mismatch, "
863			  "fw \'%c\', target \'%c\'\n", fw->name,
864			  hdr->fw_type, fw_type);
865		return 0;
866	}
867
868	if (hdr->fw_gen != BWI_FW_GEN_1) {
869		if_printf(ifp, "invalid firmware (%s): wrong generation, "
870			  "fw %d, target %d\n", fw->name,
871			  hdr->fw_gen, BWI_FW_GEN_1);
872		return 0;
873	}
874	return 1;
875}
876
877/*
878 * XXX Error cleanup
879 */
880static int
881bwi_mac_fw_alloc(struct bwi_mac *mac)
882{
883	struct bwi_softc *sc = mac->mac_sc;
884	struct ifnet *ifp = sc->sc_ifp;
885	char fwname[64];
886	int idx;
887
888	/*
889	 * Try getting the firmware stub so firmware
890	 * module would be loaded automatically
891	 */
892	if (mac->mac_stub == NULL) {
893		snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH,
894			 sc->sc_fw_version);
895		mac->mac_stub = firmware_get(fwname);
896		if (mac->mac_stub == NULL) {
897			if_printf(ifp, "request firmware %s failed\n", fwname);
898			return ENOMEM;
899		}
900	}
901
902	if (mac->mac_ucode == NULL) {
903		snprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH,
904			  sc->sc_fw_version,
905			  mac->mac_rev >= 5 ? 5 : mac->mac_rev);
906
907		mac->mac_ucode = firmware_get(fwname);
908		if (mac->mac_ucode == NULL) {
909			if_printf(ifp, "request firmware %s failed\n", fwname);
910			return ENOMEM;
911		}
912
913		if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE))
914			return EINVAL;
915	}
916
917	if (mac->mac_pcm == NULL) {
918		snprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH,
919			  sc->sc_fw_version,
920			  mac->mac_rev < 5 ? 4 : 5);
921
922		mac->mac_pcm = firmware_get(fwname);
923		if (mac->mac_pcm == NULL) {
924			if_printf(ifp, "request firmware %s failed\n", fwname);
925			return ENOMEM;
926		}
927
928		if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM))
929			return EINVAL;
930	}
931
932	if (mac->mac_iv == NULL) {
933		/* TODO: 11A */
934		if (mac->mac_rev == 2 || mac->mac_rev == 4) {
935			idx = 2;
936		} else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
937			idx = 5;
938		} else {
939			if_printf(ifp, "no suitible IV for MAC rev %d\n",
940				  mac->mac_rev);
941			return ENODEV;
942		}
943
944		snprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH,
945			  sc->sc_fw_version, idx);
946
947		mac->mac_iv = firmware_get(fwname);
948		if (mac->mac_iv == NULL) {
949			if_printf(ifp, "request firmware %s failed\n", fwname);
950			return ENOMEM;
951		}
952		if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV))
953			return EINVAL;
954	}
955
956	if (mac->mac_iv_ext == NULL) {
957		/* TODO: 11A */
958		if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
959		    mac->mac_rev >= 11) {
960			/* No extended IV */
961			goto back;
962		} else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
963			idx = 5;
964		} else {
965			if_printf(ifp, "no suitible ExtIV for MAC rev %d\n",
966				  mac->mac_rev);
967			return ENODEV;
968		}
969
970		snprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH,
971			  sc->sc_fw_version, idx);
972
973		mac->mac_iv_ext = firmware_get(fwname);
974		if (mac->mac_iv_ext == NULL) {
975			if_printf(ifp, "request firmware %s failed\n", fwname);
976			return ENOMEM;
977		}
978		if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV))
979			return EINVAL;
980	}
981back:
982	return 0;
983}
984
985static void
986bwi_mac_fw_free(struct bwi_mac *mac)
987{
988	if (mac->mac_ucode != NULL) {
989		firmware_put(mac->mac_ucode, FIRMWARE_UNLOAD);
990		mac->mac_ucode = NULL;
991	}
992
993	if (mac->mac_pcm != NULL) {
994		firmware_put(mac->mac_pcm, FIRMWARE_UNLOAD);
995		mac->mac_pcm = NULL;
996	}
997
998	if (mac->mac_iv != NULL) {
999		firmware_put(mac->mac_iv, FIRMWARE_UNLOAD);
1000		mac->mac_iv = NULL;
1001	}
1002
1003	if (mac->mac_iv_ext != NULL) {
1004		firmware_put(mac->mac_iv_ext, FIRMWARE_UNLOAD);
1005		mac->mac_iv_ext = NULL;
1006	}
1007
1008	if (mac->mac_stub != NULL) {
1009		firmware_put(mac->mac_stub, FIRMWARE_UNLOAD);
1010		mac->mac_stub = NULL;
1011	}
1012}
1013
1014static int
1015bwi_mac_fw_load(struct bwi_mac *mac)
1016{
1017	struct bwi_softc *sc = mac->mac_sc;
1018	struct ifnet *ifp = sc->sc_ifp;
1019	const uint32_t *fw;
1020	uint16_t fw_rev;
1021	int fw_len, i;
1022
1023	/*
1024	 * Load ucode image
1025	 */
1026	fw = (const uint32_t *)
1027	     ((const uint8_t *)mac->mac_ucode->data + BWI_FWHDR_SZ);
1028	fw_len = (mac->mac_ucode->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t);
1029
1030	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1031		    BWI_MOBJ_CTRL_VAL(
1032		    BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0));
1033	for (i = 0; i < fw_len; ++i) {
1034		CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
1035		DELAY(10);
1036	}
1037
1038	/*
1039	 * Load PCM image
1040	 */
1041	fw = (const uint32_t *)
1042	     ((const uint8_t *)mac->mac_pcm->data + BWI_FWHDR_SZ);
1043	fw_len = (mac->mac_pcm->datasize - BWI_FWHDR_SZ) / sizeof(uint32_t);
1044
1045	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1046		    BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea));
1047	CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000);
1048
1049	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1050		    BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb));
1051	for (i = 0; i < fw_len; ++i) {
1052		CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
1053		DELAY(10);
1054	}
1055
1056	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS);
1057	CSR_WRITE_4(sc, BWI_MAC_STATUS,
1058		    BWI_MAC_STATUS_UCODE_START |
1059		    BWI_MAC_STATUS_IHREN |
1060		    BWI_MAC_STATUS_INFRA);
1061
1062#define NRETRY	200
1063
1064	for (i = 0; i < NRETRY; ++i) {
1065		uint32_t intr_status;
1066
1067		intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
1068		if (intr_status == BWI_INTR_READY)
1069			break;
1070		DELAY(10);
1071	}
1072	if (i == NRETRY) {
1073		if_printf(ifp, "firmware (ucode&pcm) loading timed out\n");
1074		return ETIMEDOUT;
1075	}
1076
1077#undef NRETRY
1078
1079	CSR_READ_4(sc, BWI_MAC_INTR_STATUS);	/* dummy read */
1080
1081	fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
1082	if (fw_rev > BWI_FW_VERSION3_REVMAX) {
1083		if_printf(ifp, "firmware version 4 is not supported yet\n");
1084		return ENODEV;
1085	}
1086
1087	if_printf(ifp, "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
1088		  MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
1089	return 0;
1090}
1091
1092static int
1093bwi_mac_gpio_init(struct bwi_mac *mac)
1094{
1095	struct bwi_softc *sc = mac->mac_sc;
1096	struct bwi_regwin *old, *gpio_rw;
1097	uint32_t filt, bits;
1098	int error;
1099
1100	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK);
1101	/* TODO:LED */
1102
1103	CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf);
1104
1105	filt = 0x1f;
1106	bits = 0xf;
1107	if (sc->sc_bbp_id == BWI_BBPID_BCM4301) {
1108		filt |= 0x60;
1109		bits |= 0x60;
1110	}
1111	if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
1112		CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200);
1113		filt |= 0x200;
1114		bits |= 0x200;
1115	}
1116
1117	gpio_rw = BWI_GPIO_REGWIN(sc);
1118	error = bwi_regwin_switch(sc, gpio_rw, &old);
1119	if (error)
1120		return error;
1121
1122	CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits);
1123
1124	return bwi_regwin_switch(sc, old, NULL);
1125}
1126
1127static int
1128bwi_mac_gpio_fini(struct bwi_mac *mac)
1129{
1130	struct bwi_softc *sc = mac->mac_sc;
1131	struct bwi_regwin *old, *gpio_rw;
1132	int error;
1133
1134	gpio_rw = BWI_GPIO_REGWIN(sc);
1135	error = bwi_regwin_switch(sc, gpio_rw, &old);
1136	if (error)
1137		return error;
1138
1139	CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0);
1140
1141	return bwi_regwin_switch(sc, old, NULL);
1142}
1143
1144static int
1145bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
1146{
1147	struct bwi_softc *sc = mac->mac_sc;
1148	struct ifnet *ifp = sc->sc_ifp;
1149	const struct bwi_fwhdr *hdr;
1150	const struct bwi_fw_iv *iv;
1151	int n, i, iv_img_size;
1152
1153	/* Get the number of IVs in the IV image */
1154	hdr = (const struct bwi_fwhdr *)fw->data;
1155	n = be32toh(hdr->fw_iv_cnt);
1156	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
1157		"IV count %d\n", n);
1158
1159	/* Calculate the IV image size, for later sanity check */
1160	iv_img_size = fw->datasize - sizeof(*hdr);
1161
1162	/* Locate the first IV */
1163	iv = (const struct bwi_fw_iv *)
1164	     ((const uint8_t *)fw->data + sizeof(*hdr));
1165
1166	for (i = 0; i < n; ++i) {
1167		uint16_t iv_ofs, ofs;
1168		int sz = 0;
1169
1170		if (iv_img_size < sizeof(iv->iv_ofs)) {
1171			if_printf(ifp, "invalid IV image, ofs\n");
1172			return EINVAL;
1173		}
1174		iv_img_size -= sizeof(iv->iv_ofs);
1175		sz += sizeof(iv->iv_ofs);
1176
1177		iv_ofs = be16toh(iv->iv_ofs);
1178
1179		ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
1180		if (ofs >= 0x1000) {
1181			if_printf(ifp, "invalid ofs (0x%04x) "
1182				  "for %dth iv\n", ofs, i);
1183			return EINVAL;
1184		}
1185
1186		if (iv_ofs & BWI_FW_IV_IS_32BIT) {
1187			uint32_t val32;
1188
1189			if (iv_img_size < sizeof(iv->iv_val.val32)) {
1190				if_printf(ifp, "invalid IV image, val32\n");
1191				return EINVAL;
1192			}
1193			iv_img_size -= sizeof(iv->iv_val.val32);
1194			sz += sizeof(iv->iv_val.val32);
1195
1196			val32 = be32toh(iv->iv_val.val32);
1197			CSR_WRITE_4(sc, ofs, val32);
1198		} else {
1199			uint16_t val16;
1200
1201			if (iv_img_size < sizeof(iv->iv_val.val16)) {
1202				if_printf(ifp, "invalid IV image, val16\n");
1203				return EINVAL;
1204			}
1205			iv_img_size -= sizeof(iv->iv_val.val16);
1206			sz += sizeof(iv->iv_val.val16);
1207
1208			val16 = be16toh(iv->iv_val.val16);
1209			CSR_WRITE_2(sc, ofs, val16);
1210		}
1211
1212		iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz);
1213	}
1214
1215	if (iv_img_size != 0) {
1216		if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size);
1217		return EINVAL;
1218	}
1219	return 0;
1220}
1221
1222static int
1223bwi_mac_fw_init(struct bwi_mac *mac)
1224{
1225	struct ifnet *ifp = mac->mac_sc->sc_ifp;
1226	int error;
1227
1228	error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
1229	if (error) {
1230		if_printf(ifp, "load IV failed\n");
1231		return error;
1232	}
1233
1234	if (mac->mac_iv_ext != NULL) {
1235		error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext);
1236		if (error)
1237			if_printf(ifp, "load ExtIV failed\n");
1238	}
1239	return error;
1240}
1241
1242static void
1243bwi_mac_opmode_init(struct bwi_mac *mac)
1244{
1245	struct bwi_softc *sc = mac->mac_sc;
1246	struct ifnet *ifp = sc->sc_ifp;
1247	struct ieee80211com *ic = ifp->if_l2com;
1248	uint32_t mac_status;
1249	uint16_t pre_tbtt;
1250
1251	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
1252	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
1253
1254	/* Set probe resp timeout to infinite */
1255	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0);
1256
1257	/*
1258	 * TODO: factor out following part
1259	 */
1260
1261	mac_status = CSR_READ_4(sc, BWI_MAC_STATUS);
1262	mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP |
1263			BWI_MAC_STATUS_PASS_CTL |
1264			BWI_MAC_STATUS_PASS_BCN |
1265			BWI_MAC_STATUS_PASS_BADPLCP |
1266			BWI_MAC_STATUS_PASS_BADFCS |
1267			BWI_MAC_STATUS_PROMISC);
1268	mac_status |= BWI_MAC_STATUS_INFRA;
1269
1270	/* Always turn on PROMISC on old hardware */
1271	if (mac->mac_rev < 5)
1272		mac_status |= BWI_MAC_STATUS_PROMISC;
1273
1274	switch (ic->ic_opmode) {
1275	case IEEE80211_M_IBSS:
1276		mac_status &= ~BWI_MAC_STATUS_INFRA;
1277		break;
1278	case IEEE80211_M_HOSTAP:
1279		mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP;
1280		break;
1281	case IEEE80211_M_MONITOR:
1282#if 0
1283		/* Do you want data from your microwave oven? */
1284		mac_status |= BWI_MAC_STATUS_PASS_CTL |
1285			      BWI_MAC_STATUS_PASS_BADPLCP |
1286			      BWI_MAC_STATUS_PASS_BADFCS;
1287#else
1288		mac_status |= BWI_MAC_STATUS_PASS_CTL;
1289#endif
1290		/* Promisc? */
1291		break;
1292	default:
1293		break;
1294	}
1295
1296	if (ic->ic_ifp->if_flags & IFF_PROMISC)
1297		mac_status |= BWI_MAC_STATUS_PROMISC;
1298
1299	CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
1300
1301	if (ic->ic_opmode != IEEE80211_M_IBSS &&
1302	    ic->ic_opmode != IEEE80211_M_HOSTAP) {
1303		if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3)
1304			pre_tbtt = 100;
1305		else
1306			pre_tbtt = 50;
1307	} else {
1308		pre_tbtt = 2;
1309	}
1310	CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt);
1311}
1312
1313static void
1314bwi_mac_hostflags_init(struct bwi_mac *mac)
1315{
1316	struct bwi_softc *sc = mac->mac_sc;
1317	struct bwi_phy *phy = &mac->mac_phy;
1318	struct bwi_rf *rf = &mac->mac_rf;
1319	uint64_t host_flags;
1320
1321	if (phy->phy_mode == IEEE80211_MODE_11A)
1322		return;
1323
1324	host_flags = HFLAGS_READ(mac);
1325	host_flags |= BWI_HFLAG_SYM_WA;
1326
1327	if (phy->phy_mode == IEEE80211_MODE_11G) {
1328		if (phy->phy_rev == 1)
1329			host_flags |= BWI_HFLAG_GDC_WA;
1330		if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
1331			host_flags |= BWI_HFLAG_OFDM_PA;
1332	} else if (phy->phy_mode == IEEE80211_MODE_11B) {
1333		if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050)
1334			host_flags &= ~BWI_HFLAG_GDC_WA;
1335	} else {
1336		panic("unknown PHY mode %u\n", phy->phy_mode);
1337	}
1338
1339	HFLAGS_WRITE(mac, host_flags);
1340}
1341
1342static void
1343bwi_mac_bss_param_init(struct bwi_mac *mac)
1344{
1345	struct bwi_softc *sc = mac->mac_sc;
1346	struct bwi_phy *phy = &mac->mac_phy;
1347	struct ifnet *ifp = sc->sc_ifp;
1348	struct ieee80211com *ic = ifp->if_l2com;
1349	const struct ieee80211_rate_table *rt;
1350	struct bwi_retry_lim lim;
1351	uint16_t cw_min;
1352
1353	/*
1354	 * Set short/long retry limits
1355	 */
1356	bzero(&lim, sizeof(lim));
1357	lim.shretry = BWI_SHRETRY;
1358	lim.shretry_fb = BWI_SHRETRY_FB;
1359	lim.lgretry = BWI_LGRETRY;
1360	lim.lgretry_fb = BWI_LGRETRY_FB;
1361	bwi_mac_set_retry_lim(mac, &lim);
1362
1363	/*
1364	 * Implicitly prevent firmware from sending probe response
1365	 * by setting its "probe response timeout" to 1us.
1366	 */
1367	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1);
1368
1369	/*
1370	 * XXX MAC level acknowledge and CW min/max should depend
1371	 * on the char rateset of the IBSS/BSS to join.
1372	 * XXX this is all wrong; should be done on channel change
1373	 */
1374	if (phy->phy_mode == IEEE80211_MODE_11B) {
1375		rt = ieee80211_get_ratetable(
1376		    ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_B));
1377		bwi_mac_set_ackrates(mac, rt,
1378		    &ic->ic_sup_rates[IEEE80211_MODE_11B]);
1379	} else {
1380		rt = ieee80211_get_ratetable(
1381		    ieee80211_find_channel(ic, 2412, IEEE80211_CHAN_G));
1382		bwi_mac_set_ackrates(mac, rt,
1383		    &ic->ic_sup_rates[IEEE80211_MODE_11G]);
1384	}
1385
1386	/*
1387	 * Set CW min
1388	 */
1389	if (phy->phy_mode == IEEE80211_MODE_11B)
1390		cw_min = IEEE80211_CW_MIN_0;
1391	else
1392		cw_min = IEEE80211_CW_MIN_1;
1393	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min);
1394
1395	/*
1396	 * Set CW max
1397	 */
1398	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX,
1399		     IEEE80211_CW_MAX);
1400}
1401
1402static void
1403bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim)
1404{
1405	/* Short/Long retry limit */
1406	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY,
1407		     lim->shretry);
1408	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY,
1409		     lim->lgretry);
1410
1411	/* Short/Long retry fallback limit */
1412	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB,
1413		     lim->shretry_fb);
1414	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB,
1415		     lim->lgretry_fb);
1416}
1417
1418static void
1419bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rate_table *rt,
1420	const struct ieee80211_rateset *rs)
1421{
1422	int i;
1423
1424	/* XXX not standard conforming */
1425	for (i = 0; i < rs->rs_nrates; ++i) {
1426		enum ieee80211_phytype modtype;
1427		uint16_t ofs;
1428
1429		modtype = ieee80211_rate2phytype(rt, rs->rs_rates[i]);
1430		switch (modtype) {
1431		case IEEE80211_T_DS:
1432			ofs = 0x4c0;
1433			break;
1434		case IEEE80211_T_OFDM:
1435			ofs = 0x480;
1436			break;
1437		default:
1438			panic("unsupported modtype %u\n", modtype);
1439		}
1440		ofs += 2*(ieee80211_rate2plcp(rs->rs_rates[i], modtype) & 0xf);
1441
1442		MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,
1443			     MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs));
1444	}
1445}
1446
1447int
1448bwi_mac_start(struct bwi_mac *mac)
1449{
1450	struct bwi_softc *sc = mac->mac_sc;
1451
1452	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
1453	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY);
1454
1455	/* Flush pending bus writes */
1456	CSR_READ_4(sc, BWI_MAC_STATUS);
1457	CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
1458
1459	return bwi_mac_config_ps(mac);
1460}
1461
1462int
1463bwi_mac_stop(struct bwi_mac *mac)
1464{
1465	struct bwi_softc *sc = mac->mac_sc;
1466	int error, i;
1467
1468	error = bwi_mac_config_ps(mac);
1469	if (error)
1470		return error;
1471
1472	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
1473
1474	/* Flush pending bus write */
1475	CSR_READ_4(sc, BWI_MAC_STATUS);
1476
1477#define NRETRY	10000
1478	for (i = 0; i < NRETRY; ++i) {
1479		if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY)
1480			break;
1481		DELAY(1);
1482	}
1483	if (i == NRETRY) {
1484		device_printf(sc->sc_dev, "can't stop MAC\n");
1485		return ETIMEDOUT;
1486	}
1487#undef NRETRY
1488
1489	return 0;
1490}
1491
1492int
1493bwi_mac_config_ps(struct bwi_mac *mac)
1494{
1495	struct bwi_softc *sc = mac->mac_sc;
1496	uint32_t status;
1497
1498	status = CSR_READ_4(sc, BWI_MAC_STATUS);
1499
1500	status &= ~BWI_MAC_STATUS_HW_PS;
1501	status |= BWI_MAC_STATUS_WAKEUP;
1502	CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
1503
1504	/* Flush pending bus write */
1505	CSR_READ_4(sc, BWI_MAC_STATUS);
1506
1507	if (mac->mac_rev >= 5) {
1508		int i;
1509
1510#define NRETRY	100
1511		for (i = 0; i < NRETRY; ++i) {
1512			if (MOBJ_READ_2(mac, BWI_COMM_MOBJ,
1513			    BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS)
1514				break;
1515			DELAY(10);
1516		}
1517		if (i == NRETRY) {
1518			device_printf(sc->sc_dev, "config PS failed\n");
1519			return ETIMEDOUT;
1520		}
1521#undef NRETRY
1522	}
1523	return 0;
1524}
1525
1526void
1527bwi_mac_reset_hwkeys(struct bwi_mac *mac)
1528{
1529	/* TODO: firmware crypto */
1530	MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS);
1531}
1532
1533void
1534bwi_mac_shutdown(struct bwi_mac *mac)
1535{
1536	struct bwi_softc *sc = mac->mac_sc;
1537	int i;
1538
1539	if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS)
1540		sc->sc_free_txstats(sc);
1541
1542	sc->sc_free_rx_ring(sc);
1543
1544	for (i = 0; i < BWI_TX_NRING; ++i)
1545		sc->sc_free_tx_ring(sc, i);
1546
1547	bwi_rf_off(mac);
1548
1549	/* TODO:LED */
1550
1551	bwi_mac_gpio_fini(mac);
1552
1553	bwi_rf_off(mac); /* XXX again */
1554	CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
1555	bwi_regwin_disable(sc, &mac->mac_regwin, 0);
1556
1557	mac->mac_flags &= ~BWI_MAC_F_INITED;
1558}
1559
1560static int
1561bwi_mac_get_property(struct bwi_mac *mac)
1562{
1563	struct bwi_softc *sc = mac->mac_sc;
1564	enum bwi_bus_space old_bus_space;
1565	uint32_t val;
1566
1567	/*
1568	 * Byte swap
1569	 */
1570	val = CSR_READ_4(sc, BWI_MAC_STATUS);
1571	if (val & BWI_MAC_STATUS_BSWAP) {
1572		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
1573			"need byte swap");
1574		mac->mac_flags |= BWI_MAC_F_BSWAP;
1575	}
1576
1577	/*
1578	 * DMA address space
1579	 */
1580	old_bus_space = sc->sc_bus_space;
1581
1582	val = CSR_READ_4(sc, BWI_STATE_HI);
1583	if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) &
1584	    BWI_STATE_HI_FLAG_64BIT) {
1585		/* 64bit address */
1586		sc->sc_bus_space = BWI_BUS_SPACE_64BIT;
1587		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
1588			"64bit bus space");
1589	} else {
1590		uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL;
1591
1592		CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK);
1593		if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) {
1594			/* 32bit address */
1595			sc->sc_bus_space = BWI_BUS_SPACE_32BIT;
1596			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
1597				"32bit bus space");
1598		} else {
1599			/* 30bit address */
1600			sc->sc_bus_space = BWI_BUS_SPACE_30BIT;
1601			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
1602				"30bit bus space");
1603		}
1604	}
1605
1606	if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) {
1607		device_printf(sc->sc_dev, "MACs bus space mismatch!\n");
1608		return ENXIO;
1609	}
1610	return 0;
1611}
1612
1613void
1614bwi_mac_updateslot(struct bwi_mac *mac, int shslot)
1615{
1616	uint16_t slot_time;
1617
1618	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
1619		return;
1620
1621	if (shslot)
1622		slot_time = IEEE80211_DUR_SHSLOT;
1623	else
1624		slot_time = IEEE80211_DUR_SLOT;
1625
1626	CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME,
1627		    slot_time + BWI_MAC_SLOTTIME_ADJUST);
1628	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time);
1629}
1630
1631int
1632bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
1633{
1634	struct bwi_mac *mac;
1635	int i;
1636
1637	KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0,
1638	    ("sc_nmac %d", sc->sc_nmac));
1639
1640	if (sc->sc_nmac == BWI_MAC_MAX) {
1641		device_printf(sc->sc_dev, "too many MACs\n");
1642		return 0;
1643	}
1644
1645	/*
1646	 * More than one MAC is only supported by BCM4309
1647	 */
1648	if (sc->sc_nmac != 0 &&
1649	    sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM4309) {
1650		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
1651			"ignore second MAC");
1652		return 0;
1653	}
1654
1655	mac = &sc->sc_mac[sc->sc_nmac];
1656
1657	/* XXX will this happen? */
1658	if (BWI_REGWIN_EXIST(&mac->mac_regwin)) {
1659		device_printf(sc->sc_dev, "%dth MAC already attached\n",
1660			      sc->sc_nmac);
1661		return 0;
1662	}
1663
1664	/*
1665	 * Test whether the revision of this MAC is supported
1666	 */
1667#define N(arr)	(int)(sizeof(arr) / sizeof(arr[0]))
1668	for (i = 0; i < N(bwi_sup_macrev); ++i) {
1669		if (bwi_sup_macrev[i] == rev)
1670			break;
1671	}
1672	if (i == N(bwi_sup_macrev)) {
1673		device_printf(sc->sc_dev, "MAC rev %u is "
1674			      "not supported\n", rev);
1675		return ENXIO;
1676	}
1677#undef N
1678
1679	BWI_CREATE_MAC(mac, sc, id, rev);
1680	sc->sc_nmac++;
1681
1682	if (mac->mac_rev < 5) {
1683		mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
1684		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
1685			"has TX stats");
1686	} else {
1687		mac->mac_flags |= BWI_MAC_F_PHYE_RESET;
1688	}
1689
1690	device_printf(sc->sc_dev, "MAC: rev %u\n", rev);
1691	return 0;
1692}
1693
1694static __inline void
1695bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0)
1696{
1697	int bbp_atten, rf_atten, rf_atten_lim = -1;
1698
1699	bbp_atten = *bbp_atten0;
1700	rf_atten = *rf_atten0;
1701
1702	/*
1703	 * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times
1704	 * as much as BBP attenuation, so we try our best to keep RF
1705	 * attenuation within range.  BBP attenuation will be clamped
1706	 * later if it is out of range during balancing.
1707	 *
1708	 * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit.
1709	 */
1710
1711	/*
1712	 * Use BBP attenuation to balance RF attenuation
1713	 */
1714	if (rf_atten < 0)
1715		rf_atten_lim = 0;
1716	else if (rf_atten > BWI_RF_ATTEN_MAX0)
1717		rf_atten_lim = BWI_RF_ATTEN_MAX0;
1718
1719	if (rf_atten_lim >= 0) {
1720		bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim));
1721		rf_atten = rf_atten_lim;
1722	}
1723
1724	/*
1725	 * If possible, use RF attenuation to balance BBP attenuation
1726	 * NOTE: RF attenuation is still kept within range.
1727	 */
1728	while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) {
1729		bbp_atten -= BWI_RF_ATTEN_FACTOR;
1730		++rf_atten;
1731	}
1732	while (rf_atten > 0 && bbp_atten < 0) {
1733		bbp_atten += BWI_RF_ATTEN_FACTOR;
1734		--rf_atten;
1735	}
1736
1737	/* RF attenuation MUST be within range */
1738	KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0,
1739	    ("rf_atten %d", rf_atten));
1740
1741	/*
1742	 * Clamp BBP attenuation
1743	 */
1744	if (bbp_atten < 0)
1745		bbp_atten = 0;
1746	else if (bbp_atten > BWI_BBP_ATTEN_MAX)
1747		bbp_atten = BWI_BBP_ATTEN_MAX;
1748
1749	*rf_atten0 = rf_atten;
1750	*bbp_atten0 = bbp_atten;
1751}
1752
1753static void
1754bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj)
1755{
1756	struct bwi_softc *sc = mac->mac_sc;
1757	struct bwi_rf *rf = &mac->mac_rf;
1758	struct bwi_tpctl tpctl;
1759	int bbp_atten, rf_atten, tp_ctrl1;
1760
1761	bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
1762
1763	/* NOTE: Use signed value to do calulation */
1764	bbp_atten = tpctl.bbp_atten;
1765	rf_atten = tpctl.rf_atten;
1766	tp_ctrl1 = tpctl.tp_ctrl1;
1767
1768	bbp_atten += bbp_atten_adj;
1769	rf_atten += rf_atten_adj;
1770
1771	bwi_mac_balance_atten(&bbp_atten, &rf_atten);
1772
1773	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) {
1774		if (rf_atten <= 1) {
1775			if (tp_ctrl1 == 0) {
1776				tp_ctrl1 = 3;
1777				bbp_atten += 2;
1778				rf_atten += 2;
1779			} else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
1780				bbp_atten +=
1781				(BWI_RF_ATTEN_FACTOR * (rf_atten - 2));
1782				rf_atten = 2;
1783			}
1784		} else if (rf_atten > 4 && tp_ctrl1 != 0) {
1785			tp_ctrl1 = 0;
1786			if (bbp_atten < 3) {
1787				bbp_atten += 2;
1788				rf_atten -= 3;
1789			} else {
1790				bbp_atten -= 2;
1791				rf_atten -= 2;
1792			}
1793		}
1794		bwi_mac_balance_atten(&bbp_atten, &rf_atten);
1795	}
1796
1797	tpctl.bbp_atten = bbp_atten;
1798	tpctl.rf_atten = rf_atten;
1799	tpctl.tp_ctrl1 = tp_ctrl1;
1800
1801	bwi_mac_lock(mac);
1802	bwi_mac_set_tpctl_11bg(mac, &tpctl);
1803	bwi_mac_unlock(mac);
1804}
1805
1806/*
1807 * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower
1808 */
1809void
1810bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type)
1811{
1812	struct bwi_softc *sc = mac->mac_sc;
1813	struct bwi_rf *rf = &mac->mac_rf;
1814	int8_t tssi[4], tssi_avg, cur_txpwr;
1815	int error, i, ofdm_tssi;
1816	int txpwr_diff, rf_atten_adj, bbp_atten_adj;
1817
1818	if (!sc->sc_txpwr_calib)
1819		return;
1820
1821	if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) {
1822		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
1823			"tpctl error happened, can't set txpower");
1824		return;
1825	}
1826
1827	if (BWI_IS_BRCM_BU4306(sc)) {
1828		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
1829			"BU4306, can't set txpower");
1830		return;
1831	}
1832
1833	/*
1834	 * Save latest TSSI and reset the related memory objects
1835	 */
1836	ofdm_tssi = 0;
1837	error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS);
1838	if (error) {
1839		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
1840			"no DS tssi");
1841
1842		if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) {
1843			if (type == BWI_TXPWR_FORCE) {
1844				rf_atten_adj = 0;
1845				bbp_atten_adj = 1;
1846				goto calib;
1847			} else {
1848				return;
1849			}
1850		}
1851
1852		error = bwi_rf_get_latest_tssi(mac, tssi,
1853				BWI_COMM_MOBJ_TSSI_OFDM);
1854		if (error) {
1855			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
1856				"no OFDM tssi");
1857			if (type == BWI_TXPWR_FORCE) {
1858				rf_atten_adj = 0;
1859				bbp_atten_adj = 1;
1860				goto calib;
1861			} else {
1862				return;
1863			}
1864		}
1865
1866		for (i = 0; i < 4; ++i) {
1867			tssi[i] += 0x20;
1868			tssi[i] &= 0x3f;
1869		}
1870		ofdm_tssi = 1;
1871	}
1872	bwi_rf_clear_tssi(mac);
1873
1874	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
1875		"tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n",
1876		tssi[0], tssi[1], tssi[2], tssi[3]);
1877
1878	/*
1879	 * Calculate RF/BBP attenuation adjustment based on
1880	 * the difference between desired TX power and sampled
1881	 * TX power.
1882	 */
1883	/* +8 == "each incremented by 1/2" */
1884	tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4;
1885	if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS))
1886		tssi_avg -= 13;
1887
1888	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "tssi avg %d\n", tssi_avg);
1889
1890	error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr);
1891	if (error)
1892		return;
1893	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "current txpower %d\n",
1894		cur_txpwr);
1895
1896	txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */
1897
1898	rf_atten_adj = -howmany(txpwr_diff, 8);
1899	if (type == BWI_TXPWR_INIT) {
1900		/*
1901		 * Move toward EEPROM max TX power as fast as we can
1902		 */
1903		bbp_atten_adj = -txpwr_diff;
1904	} else {
1905		bbp_atten_adj = -(txpwr_diff / 2);
1906	}
1907	bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
1908
1909	if (rf_atten_adj == 0 && bbp_atten_adj == 0) {
1910		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
1911			"no need to adjust RF/BBP attenuation");
1912		/* TODO: LO */
1913		return;
1914	}
1915
1916calib:
1917	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
1918		"rf atten adjust %d, bbp atten adjust %d\n",
1919		rf_atten_adj, bbp_atten_adj);
1920	bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj);
1921	/* TODO: LO */
1922}
1923
1924static void
1925bwi_mac_lock(struct bwi_mac *mac)
1926{
1927	struct bwi_softc *sc = mac->mac_sc;
1928	struct ifnet *ifp = sc->sc_ifp;
1929	struct ieee80211com *ic = ifp->if_l2com;
1930
1931	KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0,
1932	    ("mac_flags 0x%x", mac->mac_flags));
1933
1934	if (mac->mac_rev < 3)
1935		bwi_mac_stop(mac);
1936	else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1937		bwi_mac_config_ps(mac);
1938
1939	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
1940
1941	/* Flush pending bus write */
1942	CSR_READ_4(sc, BWI_MAC_STATUS);
1943	DELAY(10);
1944
1945	mac->mac_flags |= BWI_MAC_F_LOCKED;
1946}
1947
1948static void
1949bwi_mac_unlock(struct bwi_mac *mac)
1950{
1951	struct bwi_softc *sc = mac->mac_sc;
1952	struct ifnet *ifp = sc->sc_ifp;
1953	struct ieee80211com *ic = ifp->if_l2com;
1954
1955	KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED,
1956	    ("mac_flags 0x%x", mac->mac_flags));
1957
1958	CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */
1959
1960	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
1961
1962	if (mac->mac_rev < 3)
1963		bwi_mac_start(mac);
1964	else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1965		bwi_mac_config_ps(mac);
1966
1967	mac->mac_flags &= ~BWI_MAC_F_LOCKED;
1968}
1969
1970void
1971bwi_mac_set_promisc(struct bwi_mac *mac, int promisc)
1972{
1973	struct bwi_softc *sc = mac->mac_sc;
1974
1975	if (mac->mac_rev < 5) /* Promisc is always on */
1976		return;
1977
1978	if (promisc)
1979		CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
1980	else
1981		CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
1982}
1983