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