Add WIP support for Broadcom wireless chips:
[dragonfly/port-amd64.git] / sys / dev / netif / bwi / bwimac.c
blobed6afa5d15f76103b139073f50bd607936ca9375
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:
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.
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.
34 * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.1 2007/09/08 06:15:54 sephe Exp $
37 #include <sys/param.h>
38 #include <sys/endian.h>
39 #include <sys/kernel.h>
40 #include <sys/bus.h>
41 #include <sys/firmware.h>
42 #include <sys/malloc.h>
43 #include <sys/proc.h>
44 #include <sys/rman.h>
45 #include <sys/serialize.h>
46 #include <sys/socket.h>
47 #include <sys/sockio.h>
49 #include <net/ethernet.h>
50 #include <net/if.h>
51 #include <net/bpf.h>
52 #include <net/if_arp.h>
53 #include <net/if_dl.h>
54 #include <net/if_media.h>
55 #include <net/ifq_var.h>
57 #include <netproto/802_11/ieee80211_var.h>
59 #include <bus/pci/pcireg.h>
60 #include <bus/pci/pcivar.h>
61 #include <bus/pci/pcidevs.h>
63 #include "bitops.h"
64 #include "if_bwireg.h"
65 #include "if_bwivar.h"
66 #include "bwiphy.h"
67 #include "bwirf.h"
68 #include "bwimac.h"
70 struct bwi_retry_lim {
71 uint16_t shretry;
72 uint16_t shretry_fb;
73 uint16_t lgretry;
74 uint16_t lgretry_fb;
77 static int bwi_mac_test(struct bwi_mac *);
78 static int bwi_mac_get_property(struct bwi_mac *);
80 static void bwi_mac_set_retry_lim(struct bwi_mac *,
81 const struct bwi_retry_lim *);
82 static void bwi_mac_set_ackrates(struct bwi_mac *,
83 const struct ieee80211_rateset *);
85 static int bwi_mac_gpio_init(struct bwi_mac *);
86 static int bwi_mac_gpio_fini(struct bwi_mac *);
87 static void bwi_mac_opmode_init(struct bwi_mac *);
88 static void bwi_mac_hostflags_init(struct bwi_mac *);
89 static void bwi_mac_bss_param_init(struct bwi_mac *);
91 static int bwi_mac_fw_alloc(struct bwi_mac *);
92 static void bwi_mac_fw_free(struct bwi_mac *);
93 static int bwi_mac_fw_load(struct bwi_mac *);
94 static int bwi_mac_fw_init(struct bwi_mac *);
95 static int bwi_mac_fw_load_iv(struct bwi_mac *, const struct fw_image *);
97 static void bwi_mac_setup_tpctl(struct bwi_mac *);
98 static void bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
100 static void bwi_mac_lock(struct bwi_mac *);
101 static void bwi_mac_unlock(struct bwi_mac *);
103 static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10 };
105 void
106 bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val)
108 struct bwi_softc *sc = mac->mac_sc;
110 if (mac->mac_flags & BWI_MAC_F_BSWAP)
111 val = bswap32(val);
113 CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs);
114 CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val);
117 void
118 bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags)
120 uint64_t val;
122 val = flags & 0xffff;
123 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val);
125 val = (flags >> 16) & 0xffff;
126 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val);
128 /* HI has unclear meaning, so leave it as it is */
131 uint64_t
132 bwi_hostflags_read(struct bwi_mac *mac)
134 uint64_t flags, val;
136 /* HI has unclear meaning, so don't touch it */
137 flags = 0;
139 val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI);
140 flags |= val << 16;
142 val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO);
143 flags |= val;
145 return flags;
148 uint16_t
149 bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
151 struct bwi_softc *sc = mac->mac_sc;
152 uint32_t data_reg;
153 int ofs;
155 data_reg = BWI_MOBJ_DATA;
156 ofs = ofs0 / 4;
158 if (ofs0 % 4 != 0)
159 data_reg = BWI_MOBJ_DATA_UNALIGN;
161 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
162 return CSR_READ_2(sc, data_reg);
165 uint32_t
166 bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
168 struct bwi_softc *sc = mac->mac_sc;
169 int ofs;
171 ofs = ofs0 / 4;
172 if (ofs0 % 4 != 0) {
173 uint32_t ret;
175 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
176 ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN);
177 ret <<= 16;
179 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
180 BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
181 ret |= CSR_READ_2(sc, BWI_MOBJ_DATA);
183 return ret;
184 } else {
185 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
186 return CSR_READ_4(sc, BWI_MOBJ_DATA);
190 void
191 bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
192 uint16_t v)
194 struct bwi_softc *sc = mac->mac_sc;
195 uint32_t data_reg;
196 int ofs;
198 data_reg = BWI_MOBJ_DATA;
199 ofs = ofs0 / 4;
201 if (ofs0 % 4 != 0)
202 data_reg = BWI_MOBJ_DATA_UNALIGN;
204 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
205 CSR_WRITE_2(sc, data_reg, v);
208 void
209 bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
210 uint32_t v)
212 struct bwi_softc *sc = mac->mac_sc;
213 int ofs;
215 ofs = ofs0 / 4;
216 if (ofs0 % 4 != 0) {
217 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
218 CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16);
220 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
221 BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
222 CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff);
223 } else {
224 CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
225 CSR_WRITE_4(sc, BWI_MOBJ_DATA, v);
230 bwi_mac_lateattach(struct bwi_mac *mac)
232 int error;
234 if (mac->mac_rev >= 5)
235 CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */
237 bwi_mac_reset(mac, 1);
239 error = bwi_phy_attach(mac);
240 if (error)
241 return error;
243 error = bwi_rf_attach(mac);
244 if (error)
245 return error;
247 /* Link 11B/G PHY, unlink 11A PHY */
248 if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A)
249 bwi_mac_reset(mac, 0);
250 else
251 bwi_mac_reset(mac, 1);
253 error = bwi_mac_test(mac);
254 if (error)
255 return error;
257 error = bwi_mac_get_property(mac);
258 if (error)
259 return error;
261 error = bwi_rf_map_txpower(mac);
262 if (error)
263 return error;
265 bwi_rf_off(mac);
266 CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
267 bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0);
269 return 0;
273 bwi_mac_init(struct bwi_mac *mac)
275 struct bwi_softc *sc = mac->mac_sc;
276 int error, i;
278 /* Clear MAC/PHY/RF states */
279 bwi_mac_setup_tpctl(mac);
280 bwi_rf_clear_state(&mac->mac_rf);
281 bwi_phy_clear_state(&mac->mac_phy);
283 /* Enable MAC and linked it to PHY */
284 if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin))
285 bwi_mac_reset(mac, 1);
287 /* Initialize backplane */
288 error = bwi_bus_init(sc, mac);
289 if (error)
290 return error;
292 /* XXX work around for hardware bugs? */
293 if (sc->sc_bus_regwin.rw_rev <= 5 &&
294 sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) {
295 CSR_SETBITS_4(sc, BWI_CONF_LO,
296 __SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) |
297 __SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK));
300 /* Calibrate PHY */
301 error = bwi_phy_calibrate(mac);
302 if (error) {
303 if_printf(&sc->sc_ic.ic_if, "PHY calibrate failed\n");
304 return error;
307 /* Prepare to initialize firmware */
308 CSR_WRITE_4(sc, BWI_MAC_STATUS,
309 BWI_MAC_STATUS_UCODE_JUMP0 |
310 BWI_MAC_STATUS_IHREN);
313 * Load and initialize firmwares
315 error = bwi_mac_fw_alloc(mac);
316 if (error)
317 return error;
319 error = bwi_mac_fw_load(mac);
320 if (error)
321 return error;
323 error = bwi_mac_gpio_init(mac);
324 if (error)
325 return error;
327 error = bwi_mac_fw_init(mac);
328 if (error)
329 return error;
332 * Turn on RF
334 bwi_rf_on(mac);
336 /* TODO: LED, hardware rf enabled is only related to LED setting */
339 * Initialize PHY
341 CSR_WRITE_4(sc, BWI_BBP_ATTEN, 0);
342 bwi_phy_init(mac);
344 /* TODO: interference mitigation */
347 * Setup antenna mode
349 bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode);
352 * Initialize operation mode (RX configuration)
354 bwi_mac_opmode_init(mac);
356 /* XXX what's these */
357 if (mac->mac_rev < 3) {
358 CSR_WRITE_2(sc, 0x60e, 0);
359 CSR_WRITE_2(sc, 0x610, 0x8000);
360 CSR_WRITE_2(sc, 0x604, 0);
361 CSR_WRITE_2(sc, 0x606, 0x200);
362 } else {
363 CSR_WRITE_4(sc, 0x188, 0x80000000);
364 CSR_WRITE_4(sc, 0x18c, 0x2000000);
368 * Initialize TX/RX interrupts' mask
370 CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1);
371 for (i = 0; i < BWI_TXRX_NRING; ++i) {
372 uint32_t intrs;
374 if (BWI_TXRX_IS_RX(i))
375 intrs = BWI_TXRX_RX_INTRS;
376 else
377 intrs = BWI_TXRX_TX_INTRS;
378 CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs);
381 /* XXX what's this */
382 CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000);
384 /* Setup MAC power up delay */
385 CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay);
387 /* Set MAC regwin revision */
388 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev);
391 * Initialize host flags
393 bwi_mac_hostflags_init(mac);
396 * Initialize BSS parameters
398 bwi_mac_bss_param_init(mac);
401 * Initialize TX rings
403 for (i = 0; i < BWI_TX_NRING; ++i) {
404 error = sc->sc_init_tx_ring(sc, i);
405 if (error) {
406 if_printf(&sc->sc_ic.ic_if,
407 "can't initialize %dth TX ring\n", i);
408 return error;
413 * Initialize RX ring
415 error = sc->sc_init_rx_ring(sc);
416 if (error) {
417 if_printf(&sc->sc_ic.ic_if, "can't initialize RX ring\n");
418 return error;
422 * Initialize TX stats if the current MAC uses that
424 if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) {
425 error = sc->sc_init_txstats(sc);
426 if (error) {
427 if_printf(&sc->sc_ic.ic_if,
428 "can't initialize TX stats ring\n");
429 return error;
433 /* XXX what's these */
434 CSR_WRITE_2(sc, 0x612, 0x50); /* Force Pre-TBTT to 80? */
435 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50);
436 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4);
438 mac->mac_flags |= BWI_MAC_F_INITED;
439 return 0;
442 void
443 bwi_mac_reset(struct bwi_mac *mac, int link_phy)
445 struct bwi_softc *sc = mac->mac_sc;
446 uint32_t flags, state_lo, status;
448 flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN;
449 if (link_phy)
450 flags |= BWI_STATE_LO_FLAG_PHYLNK;
451 bwi_regwin_enable(sc, &mac->mac_regwin, flags);
452 DELAY(2000);
454 state_lo = CSR_READ_4(sc, BWI_STATE_LO);
455 state_lo |= BWI_STATE_LO_GATED_CLOCK;
456 state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST,
457 BWI_STATE_LO_FLAGS_MASK);
458 CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
459 /* Flush pending bus write */
460 CSR_READ_4(sc, BWI_STATE_LO);
461 DELAY(1000);
463 state_lo &= ~BWI_STATE_LO_GATED_CLOCK;
464 CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
465 /* Flush pending bus write */
466 CSR_READ_4(sc, BWI_STATE_LO);
467 DELAY(1000);
469 CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
471 status = CSR_READ_4(sc, BWI_MAC_STATUS);
472 status |= BWI_MAC_STATUS_IHREN;
473 if (link_phy)
474 status |= BWI_MAC_STATUS_PHYLNK;
475 else
476 status &= ~BWI_MAC_STATUS_PHYLNK;
477 CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
479 if (link_phy) {
480 DPRINTF(sc, "%s\n", "PHY is linked");
481 mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED;
482 } else {
483 DPRINTF(sc, "%s\n", "PHY is unlinked");
484 mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED;
488 void
489 bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl)
491 struct bwi_rf *rf = &mac->mac_rf;
492 struct bwi_tpctl *tpctl = &mac->mac_tpctl;
494 if (new_tpctl != NULL) {
495 KKASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX);
496 KKASSERT(new_tpctl->rf_atten <=
497 (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0
498 : BWI_RF_ATTEN_MAX1));
499 KKASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX);
501 tpctl->bbp_atten = new_tpctl->bbp_atten;
502 tpctl->rf_atten = new_tpctl->rf_atten;
503 tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1;
506 /* Set BBP attenuation */
507 bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten);
509 /* Set RF attenuation */
510 RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten);
511 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN,
512 tpctl->rf_atten);
514 /* Set TX power */
515 if (rf->rf_type == BWI_RF_T_BCM2050) {
516 RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK,
517 __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK));
520 /* Adjust RF Local Oscillator */
521 if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
522 bwi_rf_lo_adjust(mac, tpctl);
525 static int
526 bwi_mac_test(struct bwi_mac *mac)
528 struct bwi_softc *sc = mac->mac_sc;
529 uint32_t orig_val, val;
531 #define TEST_VAL1 0xaa5555aa
532 #define TEST_VAL2 0x55aaaa55
534 /* Save it for later restoring */
535 orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
537 /* Test 1 */
538 MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1);
539 val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
540 if (val != TEST_VAL1) {
541 device_printf(sc->sc_dev, "TEST1 failed\n");
542 return ENXIO;
545 /* Test 2 */
546 MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2);
547 val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
548 if (val != TEST_VAL2) {
549 device_printf(sc->sc_dev, "TEST2 failed\n");
550 return ENXIO;
553 /* Restore to the original value */
554 MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val);
556 val = CSR_READ_4(sc, BWI_MAC_STATUS);
557 if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) {
558 device_printf(sc->sc_dev, "%s failed, MAC status 0x%08x\n",
559 __func__, val);
560 return ENXIO;
563 val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
564 if (val != 0) {
565 device_printf(sc->sc_dev, "%s failed, intr status %08x\n",
566 __func__, val);
567 return ENXIO;
570 #undef TEST_VAL2
571 #undef TEST_VAL1
573 return 0;
576 static void
577 bwi_mac_setup_tpctl(struct bwi_mac *mac)
579 struct bwi_softc *sc = mac->mac_sc;
580 struct bwi_rf *rf = &mac->mac_rf;
581 struct bwi_phy *phy = &mac->mac_phy;
582 struct bwi_tpctl *tpctl = &mac->mac_tpctl;
584 /* Calc BBP attenuation */
585 if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6)
586 tpctl->bbp_atten = 0;
587 else
588 tpctl->bbp_atten = 2;
590 /* Calc TX power CTRL1?? */
591 tpctl->tp_ctrl1 = 0;
592 if (rf->rf_type == BWI_RF_T_BCM2050) {
593 if (rf->rf_rev == 1)
594 tpctl->tp_ctrl1 = 3;
595 else if (rf->rf_rev < 6)
596 tpctl->tp_ctrl1 = 2;
597 else if (rf->rf_rev == 8)
598 tpctl->tp_ctrl1 = 1;
601 /* Empty TX power CTRL2?? */
602 tpctl->tp_ctrl2 = 0xffff;
605 * Calc RF attenuation
607 if (phy->phy_mode == IEEE80211_MODE_11A) {
608 tpctl->rf_atten = 0x60;
609 goto back;
612 if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) {
613 tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3;
614 goto back;
617 tpctl->rf_atten = 5;
619 if (rf->rf_type != BWI_RF_T_BCM2050) {
620 if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1)
621 tpctl->rf_atten = 6;
622 goto back;
626 * NB: If we reaches here and the card is BRCM_BCM4309G,
627 * then the card's PCI revision must >= 0x51
630 /* BCM2050 RF */
631 switch (rf->rf_rev) {
632 case 1:
633 if (phy->phy_mode == IEEE80211_MODE_11G) {
634 if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc))
635 tpctl->rf_atten = 3;
636 else
637 tpctl->rf_atten = 1;
638 } else {
639 if (BWI_IS_BRCM_BCM4309G(sc))
640 tpctl->rf_atten = 7;
641 else
642 tpctl->rf_atten = 6;
644 break;
645 case 2:
646 if (phy->phy_mode == IEEE80211_MODE_11G) {
648 * NOTE: Order of following conditions is critical
650 if (BWI_IS_BRCM_BCM4309G(sc))
651 tpctl->rf_atten = 3;
652 else if (BWI_IS_BRCM_BU4306(sc))
653 tpctl->rf_atten = 5;
654 else if (sc->sc_bbp_id == BWI_BBPID_BCM4320)
655 tpctl->rf_atten = 4;
656 else
657 tpctl->rf_atten = 3;
658 } else {
659 tpctl->rf_atten = 6;
661 break;
662 case 4:
663 case 5:
664 tpctl->rf_atten = 1;
665 break;
666 case 8:
667 tpctl->rf_atten = 0x1a;
668 break;
670 back:
671 DPRINTF(sc, "bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n",
672 tpctl->bbp_atten, tpctl->rf_atten,
673 tpctl->tp_ctrl1, tpctl->tp_ctrl2);
676 void
677 bwi_mac_dummy_xmit(struct bwi_mac *mac)
679 #define PACKET_LEN 5
680 static const uint32_t packet_11a[PACKET_LEN] =
681 { 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
682 static const uint32_t packet_11bg[PACKET_LEN] =
683 { 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
685 struct bwi_softc *sc = mac->mac_sc;
686 struct bwi_rf *rf = &mac->mac_rf;
687 const uint32_t *packet;
688 uint16_t val_50c;
689 int wait_max, i;
691 if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
692 wait_max = 30;
693 packet = packet_11a;
694 val_50c = 1;
695 } else {
696 wait_max = 250;
697 packet = packet_11bg;
698 val_50c = 0;
701 for (i = 0; i < PACKET_LEN; ++i)
702 TMPLT_WRITE_4(mac, i * 4, packet[i]);
704 CSR_READ_4(sc, BWI_MAC_STATUS); /* dummy read */
706 CSR_WRITE_2(sc, 0x568, 0);
707 CSR_WRITE_2(sc, 0x7c0, 0);
708 CSR_WRITE_2(sc, 0x50c, val_50c);
709 CSR_WRITE_2(sc, 0x508, 0);
710 CSR_WRITE_2(sc, 0x50a, 0);
711 CSR_WRITE_2(sc, 0x54c, 0);
712 CSR_WRITE_2(sc, 0x56a, 0x14);
713 CSR_WRITE_2(sc, 0x568, 0x826);
714 CSR_WRITE_2(sc, 0x500, 0);
715 CSR_WRITE_2(sc, 0x502, 0x30);
717 if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
718 RF_WRITE(mac, 0x51, 0x17);
720 for (i = 0; i < wait_max; ++i) {
721 if (CSR_READ_2(sc, 0x50e) & 0x80)
722 break;
723 DELAY(10);
725 for (i = 0; i < 10; ++i) {
726 if (CSR_READ_2(sc, 0x50e) & 0x400)
727 break;
728 DELAY(10);
730 for (i = 0; i < 10; ++i) {
731 if ((CSR_READ_2(sc, 0x690) & 0x100) == 0)
732 break;
733 DELAY(10);
736 if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
737 RF_WRITE(mac, 0x51, 0x37);
738 #undef PACKET_LEN
741 void
742 bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
744 struct bwi_softc *sc = mac->mac_sc;
745 struct bwi_phy *phy = &mac->mac_phy;
746 struct bwi_rf *rf = &mac->mac_rf;
747 struct bwi_tpctl tpctl_orig;
748 int restore_tpctl = 0;
750 KKASSERT(phy->phy_mode != IEEE80211_MODE_11A);
752 if (BWI_IS_BRCM_BU4306(sc))
753 return;
755 PHY_WRITE(mac, 0x28, 0x8018);
756 CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20);
758 if (phy->phy_mode == IEEE80211_MODE_11G) {
759 if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
760 return;
761 PHY_WRITE(mac, 0x47a, 0xc111);
763 if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED)
764 return;
766 if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 &&
767 rf->rf_type == BWI_RF_T_BCM2050) {
768 RF_SETBITS(mac, 0x76, 0x84);
769 } else {
770 struct bwi_tpctl tpctl;
772 /* Backup original TX power control variables */
773 bcopy(&mac->mac_tpctl, &tpctl_orig, sizeof(tpctl_orig));
774 restore_tpctl = 1;
776 bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
777 tpctl.bbp_atten = 11;
778 tpctl.tp_ctrl1 = 0;
779 #ifdef notyet
780 if (rf->rf_rev >= 6 && rf->rf_rev <= 8)
781 tpctl.rf_atten = 31;
782 else
783 #endif
784 tpctl.rf_atten = 9;
786 bwi_mac_set_tpctl_11bg(mac, &tpctl);
789 bwi_mac_dummy_xmit(mac);
791 mac->mac_flags |= BWI_MAC_F_TPCTL_INITED;
792 rf->rf_base_tssi = PHY_READ(mac, 0x29);
793 DPRINTF(sc, "base tssi %d\n", rf->rf_base_tssi);
795 if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) {
796 if_printf(&sc->sc_ic.ic_if, "base tssi measure failed\n");
797 mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR;
800 if (restore_tpctl)
801 bwi_mac_set_tpctl_11bg(mac, &tpctl_orig);
802 else
803 RF_CLRBITS(mac, 0x76, 0x84);
805 bwi_rf_clear_tssi(mac);
808 void
809 bwi_mac_detach(struct bwi_mac *mac)
811 bwi_mac_fw_free(mac);
814 static __inline int
815 bwi_fwimage_is_valid(struct bwi_softc *sc, const struct fw_image *fw,
816 uint8_t fw_type)
818 const struct bwi_fwhdr *hdr;
819 struct ifnet *ifp = &sc->sc_ic.ic_if;
821 if (fw->fw_imglen < sizeof(*hdr)) {
822 if_printf(ifp, "invalid firmware (%s): invalid size %u\n",
823 fw->fw_name, fw->fw_imglen);
824 return 0;
827 hdr = (const struct bwi_fwhdr *)fw->fw_image;
829 if (fw_type != BWI_FW_T_IV) {
831 * Don't verify IV's size, it has different meaning
833 if (be32toh(hdr->fw_size) != fw->fw_imglen - sizeof(*hdr)) {
834 if_printf(ifp, "invalid firmware (%s): size mismatch, "
835 "fw %u, real %u\n", fw->fw_name,
836 be32toh(hdr->fw_size),
837 fw->fw_imglen - sizeof(*hdr));
838 return 0;
842 if (hdr->fw_type != fw_type) {
843 if_printf(ifp, "invalid firmware (%s): type mismatch, "
844 "fw \'%c\', target \'%c\'\n", fw->fw_name,
845 hdr->fw_type, fw_type);
846 return 0;
849 if (hdr->fw_gen != BWI_FW_GEN_1) {
850 if_printf(ifp, "invalid firmware (%s): wrong generation, "
851 "fw %d, target %d\n", fw->fw_name,
852 hdr->fw_gen, BWI_FW_GEN_1);
853 return 0;
855 return 1;
859 * XXX Error cleanup
861 static int
862 bwi_mac_fw_alloc(struct bwi_mac *mac)
864 struct bwi_softc *sc = mac->mac_sc;
865 struct ifnet *ifp = &sc->sc_ic.ic_if;
866 char fwname[64];
867 int idx;
869 if (mac->mac_ucode == NULL) {
870 ksnprintf(fwname, sizeof(fwname), BWI_FW_UCODE_PATH,
871 sc->sc_fw_version,
872 mac->mac_rev >= 5 ? 5 : mac->mac_rev);
874 mac->mac_ucode = firmware_image_load(fwname);
875 if (mac->mac_ucode == NULL) {
876 if_printf(ifp, "request firmware %s failed\n", fwname);
877 return ENOMEM;
880 if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE))
881 return EINVAL;
884 if (mac->mac_pcm == NULL) {
885 ksnprintf(fwname, sizeof(fwname), BWI_FW_PCM_PATH,
886 sc->sc_fw_version,
887 mac->mac_rev < 5 ? 4 : 5);
889 mac->mac_pcm = firmware_image_load(fwname);
890 if (mac->mac_pcm == NULL) {
891 if_printf(ifp, "request firmware %s failed\n", fwname);
892 return ENOMEM;
895 if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM))
896 return EINVAL;
899 if (mac->mac_iv == NULL) {
900 /* TODO: 11A */
901 if (mac->mac_rev == 2 || mac->mac_rev == 4) {
902 idx = 2;
903 } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
904 idx = 5;
905 } else {
906 if_printf(ifp, "no suitible IV for MAC rev %d\n",
907 mac->mac_rev);
908 return ENODEV;
911 ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_PATH,
912 sc->sc_fw_version, idx);
914 mac->mac_iv = firmware_image_load(fwname);
915 if (mac->mac_iv == NULL) {
916 if_printf(ifp, "request firmware %s failed\n", fwname);
917 return ENOMEM;
919 if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV))
920 return EINVAL;
923 if (mac->mac_iv_ext == NULL) {
924 /* TODO: 11A */
925 if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
926 mac->mac_rev >= 11) {
927 /* No extended IV */
928 goto back;
929 } else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
930 idx = 5;
931 } else {
932 if_printf(ifp, "no suitible ExtIV for MAC rev %d\n",
933 mac->mac_rev);
934 return ENODEV;
937 ksnprintf(fwname, sizeof(fwname), BWI_FW_IV_EXT_PATH,
938 sc->sc_fw_version, idx);
940 mac->mac_iv_ext = firmware_image_load(fwname);
941 if (mac->mac_iv_ext == NULL) {
942 if_printf(ifp, "request firmware %s failed\n", fwname);
943 return ENOMEM;
945 if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV))
946 return EINVAL;
948 back:
949 return 0;
952 static void
953 bwi_mac_fw_free(struct bwi_mac *mac)
955 if (mac->mac_ucode != NULL) {
956 firmware_image_unload(mac->mac_ucode);
957 mac->mac_ucode = NULL;
960 if (mac->mac_pcm != NULL) {
961 firmware_image_unload(mac->mac_pcm);
962 mac->mac_pcm = NULL;
965 if (mac->mac_iv != NULL) {
966 firmware_image_unload(mac->mac_iv);
967 mac->mac_iv = NULL;
970 if (mac->mac_iv_ext != NULL) {
971 firmware_image_unload(mac->mac_iv_ext);
972 mac->mac_iv_ext = NULL;
976 static int
977 bwi_mac_fw_load(struct bwi_mac *mac)
979 struct bwi_softc *sc = mac->mac_sc;
980 struct ifnet *ifp = &sc->sc_ic.ic_if;
981 const uint32_t *fw;
982 uint16_t fw_rev;
983 int fw_len, i;
986 * Load ucode image
988 fw = (const uint32_t *)
989 ((const uint8_t *)mac->mac_ucode->fw_image + BWI_FWHDR_SZ);
990 fw_len = (mac->mac_ucode->fw_imglen - BWI_FWHDR_SZ) / sizeof(uint32_t);
992 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
993 BWI_MOBJ_CTRL_VAL(
994 BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0));
995 for (i = 0; i < fw_len; ++i) {
996 CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
997 DELAY(10);
1001 * Load PCM image
1003 fw = (const uint32_t *)
1004 ((const uint8_t *)mac->mac_pcm->fw_image + BWI_FWHDR_SZ);
1005 fw_len = (mac->mac_pcm->fw_imglen - BWI_FWHDR_SZ) / sizeof(uint32_t);
1007 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1008 BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea));
1009 CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000);
1011 CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1012 BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb));
1013 for (i = 0; i < fw_len; ++i) {
1014 CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
1015 DELAY(10);
1018 CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS);
1019 CSR_WRITE_4(sc, BWI_MAC_STATUS,
1020 BWI_MAC_STATUS_UCODE_START |
1021 BWI_MAC_STATUS_IHREN |
1022 BWI_MAC_STATUS_INFRA);
1024 #define NRETRY 200
1026 for (i = 0; i < NRETRY; ++i) {
1027 uint32_t intr_status;
1029 intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
1030 if (intr_status == BWI_INTR_READY)
1031 break;
1032 DELAY(10);
1034 if (i == NRETRY) {
1035 if_printf(ifp, "firmware (ucode&pcm) loading timed out\n");
1036 return ETIMEDOUT;
1039 #undef NRETRY
1041 CSR_READ_4(sc, BWI_MAC_INTR_STATUS); /* dummy read */
1043 fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
1044 if (fw_rev > BWI_FW_VERSION3_REVMAX) {
1045 if_printf(ifp, "firmware version 4 is not supported yet\n");
1046 return ENODEV;
1049 if_printf(ifp, "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
1050 MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
1051 return 0;
1054 static int
1055 bwi_mac_gpio_init(struct bwi_mac *mac)
1057 struct bwi_softc *sc = mac->mac_sc;
1058 struct bwi_regwin *old, *gpio_rw;
1059 uint32_t filt, bits;
1060 int error;
1062 CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK);
1063 /* TODO:LED */
1065 CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf);
1067 filt = 0x1f;
1068 bits = 0xf;
1069 if (sc->sc_bbp_id == BWI_BBPID_BCM4301) {
1070 filt |= 0x60;
1071 bits |= 0x60;
1073 if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
1074 CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200);
1075 filt |= 0x200;
1076 bits |= 0x200;
1079 gpio_rw = BWI_GPIO_REGWIN(sc);
1080 error = bwi_regwin_switch(sc, gpio_rw, &old);
1081 if (error)
1082 return error;
1084 CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits);
1086 return bwi_regwin_switch(sc, old, NULL);
1089 static int
1090 bwi_mac_gpio_fini(struct bwi_mac *mac)
1092 struct bwi_softc *sc = mac->mac_sc;
1093 struct bwi_regwin *old, *gpio_rw;
1094 int error;
1096 gpio_rw = BWI_GPIO_REGWIN(sc);
1097 error = bwi_regwin_switch(sc, gpio_rw, &old);
1098 if (error)
1099 return error;
1101 CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0);
1103 return bwi_regwin_switch(sc, old, NULL);
1106 static int
1107 bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct fw_image *fw)
1109 struct bwi_softc *sc = mac->mac_sc;
1110 struct ifnet *ifp = &sc->sc_ic.ic_if;
1111 const struct bwi_fwhdr *hdr;
1112 const struct bwi_fw_iv *iv;
1113 int n, i, iv_img_size;
1115 /* Get the number of IVs in the IV image */
1116 hdr = (const struct bwi_fwhdr *)fw->fw_image;
1117 n = be32toh(hdr->fw_iv_cnt);
1118 DPRINTF(sc, "IV count %d\n", n);
1120 /* Calculate the IV image size, for later sanity check */
1121 iv_img_size = fw->fw_imglen - sizeof(*hdr);
1123 /* Locate the first IV */
1124 iv = (const struct bwi_fw_iv *)
1125 ((const uint8_t *)fw->fw_image + sizeof(*hdr));
1127 for (i = 0; i < n; ++i) {
1128 uint16_t iv_ofs, ofs;
1129 int sz = 0;
1131 if (iv_img_size < sizeof(iv->iv_ofs)) {
1132 if_printf(ifp, "invalid IV image, ofs\n");
1133 return EINVAL;
1135 iv_img_size -= sizeof(iv->iv_ofs);
1136 sz += sizeof(iv->iv_ofs);
1138 iv_ofs = be16toh(iv->iv_ofs);
1140 ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
1141 if (ofs >= 0x1000) {
1142 if_printf(ifp, "invalid ofs (0x%04x) "
1143 "for %dth iv\n", ofs, i);
1144 return EINVAL;
1147 if (iv_ofs & BWI_FW_IV_IS_32BIT) {
1148 uint32_t val32;
1150 if (iv_img_size < sizeof(iv->iv_val.val32)) {
1151 if_printf(ifp, "invalid IV image, val32\n");
1152 return EINVAL;
1154 iv_img_size -= sizeof(iv->iv_val.val32);
1155 sz += sizeof(iv->iv_val.val32);
1157 val32 = be32toh(iv->iv_val.val32);
1158 CSR_WRITE_4(sc, ofs, val32);
1159 } else {
1160 uint16_t val16;
1162 if (iv_img_size < sizeof(iv->iv_val.val16)) {
1163 if_printf(ifp, "invalid IV image, val16\n");
1164 return EINVAL;
1166 iv_img_size -= sizeof(iv->iv_val.val16);
1167 sz += sizeof(iv->iv_val.val16);
1169 val16 = be16toh(iv->iv_val.val16);
1170 CSR_WRITE_2(sc, ofs, val16);
1173 iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz);
1176 if (iv_img_size != 0) {
1177 if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size);
1178 return EINVAL;
1180 return 0;
1183 static int
1184 bwi_mac_fw_init(struct bwi_mac *mac)
1186 struct ifnet *ifp = &mac->mac_sc->sc_ic.ic_if;
1187 int error;
1189 error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
1190 if (error) {
1191 if_printf(ifp, "load IV failed\n");
1192 return error;
1195 if (mac->mac_iv_ext != NULL) {
1196 error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext);
1197 if (error)
1198 if_printf(ifp, "load ExtIV failed\n");
1200 return error;
1203 static void
1204 bwi_mac_opmode_init(struct bwi_mac *mac)
1206 struct bwi_softc *sc = mac->mac_sc;
1207 struct ieee80211com *ic = &sc->sc_ic;
1208 uint32_t mac_status;
1209 uint16_t pre_tbtt;
1211 CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
1212 CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
1213 CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
1215 /* Set probe resp timeout to infinite */
1216 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0);
1219 * TODO: factor out following part
1222 mac_status = CSR_READ_4(sc, BWI_MAC_STATUS);
1223 mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP |
1224 BWI_MAC_STATUS_PASS_CTL |
1225 BWI_MAC_STATUS_PASS_BADPLCP |
1226 BWI_MAC_STATUS_PASS_BADFCS |
1227 BWI_MAC_STATUS_PROMISC);
1228 mac_status |= BWI_MAC_STATUS_INFRA;
1230 /* Always turn on PROMISC on old hardware */
1231 if (mac->mac_rev < 5)
1232 mac_status |= BWI_MAC_STATUS_PROMISC;
1234 switch (ic->ic_opmode) {
1235 case IEEE80211_M_IBSS:
1236 mac_status &= ~BWI_MAC_STATUS_INFRA;
1237 break;
1238 case IEEE80211_M_HOSTAP:
1239 mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP;
1240 break;
1241 case IEEE80211_M_MONITOR:
1242 #if 0
1243 /* Do you want data from your microwave oven? */
1244 mac_status |= BWI_MAC_STATUS_PASS_CTL |
1245 BWI_MAC_STATUS_PASS_BADPLCP |
1246 BWI_MAC_STATUS_PASS_BADFCS;
1247 #else
1248 mac_status |= BWI_MAC_STATUS_PASS_CTL;
1249 #endif
1250 /* Promisc? */
1251 break;
1252 default:
1253 break;
1256 if (ic->ic_if.if_flags & IFF_PROMISC)
1257 mac_status |= BWI_MAC_STATUS_PROMISC;
1259 CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
1261 if (ic->ic_opmode != IEEE80211_M_IBSS &&
1262 ic->ic_opmode != IEEE80211_M_HOSTAP) {
1263 if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3)
1264 pre_tbtt = 100;
1265 else
1266 pre_tbtt = 50;
1267 } else {
1268 pre_tbtt = 2;
1270 CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt);
1273 static void
1274 bwi_mac_hostflags_init(struct bwi_mac *mac)
1276 struct bwi_softc *sc = mac->mac_sc;
1277 struct bwi_phy *phy = &mac->mac_phy;
1278 struct bwi_rf *rf = &mac->mac_rf;
1279 uint64_t host_flags;
1281 if (phy->phy_mode == IEEE80211_MODE_11A)
1282 return;
1284 host_flags = HFLAGS_READ(mac);
1285 host_flags |= BWI_HFLAG_SYM_WA;
1287 if (phy->phy_mode == IEEE80211_MODE_11G) {
1288 if (phy->phy_rev == 1)
1289 host_flags |= BWI_HFLAG_GDC_WA;
1290 if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
1291 host_flags |= BWI_HFLAG_OFDM_PA;
1292 } else if (phy->phy_mode == IEEE80211_MODE_11B) {
1293 if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050)
1294 host_flags &= ~BWI_HFLAG_GDC_WA;
1295 } else {
1296 panic("unknown PHY mode %u\n", phy->phy_mode);
1299 HFLAGS_WRITE(mac, host_flags);
1302 static void
1303 bwi_mac_bss_param_init(struct bwi_mac *mac)
1305 struct bwi_softc *sc = mac->mac_sc;
1306 struct bwi_phy *phy = &mac->mac_phy;
1307 struct bwi_retry_lim lim;
1308 uint16_t cw_min;
1311 * Set short/long retry limits
1313 bzero(&lim, sizeof(lim));
1314 lim.shretry = BWI_SHRETRY;
1315 lim.shretry_fb = BWI_SHRETRY_FB;
1316 lim.lgretry = BWI_LGRETRY;
1317 lim.lgretry_fb = BWI_LGRETRY_FB;
1318 bwi_mac_set_retry_lim(mac, &lim);
1321 * Implicitly prevent firmware from sending probe response
1322 * by setting its "probe response timeout" to 1us.
1324 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1);
1327 * XXX MAC level acknowledge and CW min/max should depend
1328 * on the char rateset of the IBSS/BSS to join.
1332 * Set MAC level acknowledge rates
1334 bwi_mac_set_ackrates(mac, &sc->sc_ic.ic_sup_rates[phy->phy_mode]);
1337 * Set CW min
1339 if (phy->phy_mode == IEEE80211_MODE_11B)
1340 cw_min = IEEE80211_CW_MIN_0;
1341 else
1342 cw_min = IEEE80211_CW_MIN_1;
1343 MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min);
1346 * Set CW max
1348 MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX,
1349 IEEE80211_CW_MAX);
1352 static void
1353 bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim)
1355 /* Short/Long retry limit */
1356 MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY,
1357 lim->shretry);
1358 MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY,
1359 lim->lgretry);
1361 /* Short/Long retry fallback limit */
1362 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB,
1363 lim->shretry_fb);
1364 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB,
1365 lim->lgretry_fb);
1368 static void
1369 bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rateset *rs)
1371 int i;
1373 /* XXX not standard conforming */
1374 for (i = 0; i < rs->rs_nrates; ++i) {
1375 enum ieee80211_modtype modtype;
1376 uint16_t ofs;
1378 modtype = ieee80211_rate2modtype(rs->rs_rates[i]);
1379 switch (modtype) {
1380 case IEEE80211_MODTYPE_DS:
1381 ofs = 0x4c0;
1382 break;
1383 case IEEE80211_MODTYPE_OFDM:
1384 ofs = 0x480;
1385 break;
1386 default:
1387 panic("unsupported modtype %u\n", modtype);
1389 ofs += (bwi_rate2plcp(rs->rs_rates[i]) & 0xf) * 2;
1391 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,
1392 MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs));
1397 bwi_mac_start(struct bwi_mac *mac)
1399 struct bwi_softc *sc = mac->mac_sc;
1401 CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
1402 CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY);
1404 /* Flush pending bus writes */
1405 CSR_READ_4(sc, BWI_MAC_STATUS);
1406 CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
1408 return bwi_mac_config_ps(mac);
1412 bwi_mac_stop(struct bwi_mac *mac)
1414 struct bwi_softc *sc = mac->mac_sc;
1415 int error, i;
1417 error = bwi_mac_config_ps(mac);
1418 if (error)
1419 return error;
1421 CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
1423 /* Flush pending bus write */
1424 CSR_READ_4(sc, BWI_MAC_STATUS);
1426 #define NRETRY 10000
1427 for (i = 0; i < NRETRY; ++i) {
1428 if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY)
1429 break;
1430 DELAY(1);
1432 if (i == NRETRY) {
1433 if_printf(&sc->sc_ic.ic_if, "can't stop MAC\n");
1434 return ETIMEDOUT;
1436 #undef NRETRY
1438 return 0;
1442 bwi_mac_config_ps(struct bwi_mac *mac)
1444 struct bwi_softc *sc = mac->mac_sc;
1445 uint32_t status;
1447 status = CSR_READ_4(sc, BWI_MAC_STATUS);
1449 status &= ~BWI_MAC_STATUS_HW_PS;
1450 status |= BWI_MAC_STATUS_WAKEUP;
1451 CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
1453 /* Flush pending bus write */
1454 CSR_READ_4(sc, BWI_MAC_STATUS);
1456 if (mac->mac_rev >= 5) {
1457 int i;
1459 #define NRETRY 100
1460 for (i = 0; i < NRETRY; ++i) {
1461 if (MOBJ_READ_2(mac, BWI_COMM_MOBJ,
1462 BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS)
1463 break;
1464 DELAY(10);
1466 if (i == NRETRY) {
1467 if_printf(&sc->sc_ic.ic_if, "config PS failed\n");
1468 return ETIMEDOUT;
1470 #undef NRETRY
1472 return 0;
1475 void
1476 bwi_mac_reset_hwkeys(struct bwi_mac *mac)
1478 /* TODO: firmware crypto */
1479 MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS);
1482 void
1483 bwi_mac_shutdown(struct bwi_mac *mac)
1485 struct bwi_softc *sc = mac->mac_sc;
1486 int i;
1488 if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS)
1489 sc->sc_free_txstats(sc);
1491 sc->sc_free_rx_ring(sc);
1493 for (i = 0; i < BWI_TX_NRING; ++i)
1494 sc->sc_free_tx_ring(sc, i);
1496 bwi_rf_off(mac);
1498 /* TODO:LED */
1500 bwi_mac_gpio_fini(mac);
1502 bwi_rf_off(mac); /* XXX again */
1503 CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
1504 bwi_regwin_disable(sc, &mac->mac_regwin, 0);
1506 mac->mac_flags &= ~BWI_MAC_F_INITED;
1509 static int
1510 bwi_mac_get_property(struct bwi_mac *mac)
1512 struct bwi_softc *sc = mac->mac_sc;
1513 enum bwi_bus_space old_bus_space;
1514 uint32_t val;
1517 * Byte swap
1519 val = CSR_READ_4(sc, BWI_MAC_STATUS);
1520 if (val & BWI_MAC_STATUS_BSWAP) {
1521 DPRINTF(sc, "%s\n", "need byte swap");
1522 mac->mac_flags |= BWI_MAC_F_BSWAP;
1526 * DMA address space
1528 old_bus_space = sc->sc_bus_space;
1530 val = CSR_READ_4(sc, BWI_STATE_HI);
1531 if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) &
1532 BWI_STATE_HI_FLAG_64BIT) {
1533 /* 64bit address */
1534 sc->sc_bus_space = BWI_BUS_SPACE_64BIT;
1535 DPRINTF(sc, "%s\n", "64bit bus space");
1536 } else {
1537 uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL;
1539 CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK);
1540 if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) {
1541 /* 32bit address */
1542 sc->sc_bus_space = BWI_BUS_SPACE_32BIT;
1543 DPRINTF(sc, "%s\n", "32bit bus space");
1544 } else {
1545 /* 30bit address */
1546 sc->sc_bus_space = BWI_BUS_SPACE_30BIT;
1547 DPRINTF(sc, "%s\n", "30bit bus space");
1551 if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) {
1552 device_printf(sc->sc_dev, "MACs bus space mismatch!\n");
1553 return ENXIO;
1555 return 0;
1558 void
1559 bwi_mac_updateslot(struct bwi_mac *mac, int shslot)
1561 uint16_t slot_time;
1563 if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
1564 return;
1566 if (shslot)
1567 slot_time = IEEE80211_DUR_SHSLOT;
1568 else
1569 slot_time = IEEE80211_DUR_SLOT;
1571 CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME,
1572 slot_time + BWI_MAC_SLOTTIME_ADJUST);
1573 MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time);
1577 bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
1579 struct bwi_mac *mac;
1580 int i;
1582 KKASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0);
1584 if (sc->sc_nmac == BWI_MAC_MAX) {
1585 device_printf(sc->sc_dev, "too many MACs\n");
1586 return 0;
1590 * More than one MAC is only supported by BCM4309
1592 if (sc->sc_nmac != 0 &&
1593 pci_get_device(sc->sc_dev) != PCI_PRODUCT_BROADCOM_BCM4309) {
1594 DPRINTF(sc, "%s\n", "ignore second MAC");
1595 return 0;
1598 mac = &sc->sc_mac[sc->sc_nmac];
1600 /* XXX will this happen? */
1601 if (BWI_REGWIN_EXIST(&mac->mac_regwin)) {
1602 device_printf(sc->sc_dev, "%dth MAC already attached\n",
1603 sc->sc_nmac);
1604 return 0;
1608 * Test whether the revision of this MAC is supported
1610 #define N(arr) (int)(sizeof(arr) / sizeof(arr[0]))
1611 for (i = 0; i < N(bwi_sup_macrev); ++i) {
1612 if (bwi_sup_macrev[i] == rev)
1613 break;
1615 if (i == N(bwi_sup_macrev)) {
1616 device_printf(sc->sc_dev, "MAC rev %u is "
1617 "not supported\n", rev);
1618 return ENXIO;
1620 #undef N
1622 BWI_CREATE_MAC(mac, sc, id, rev);
1623 sc->sc_nmac++;
1625 if (mac->mac_rev < 5) {
1626 mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
1627 DPRINTF(sc, "%s\n", "has TX stats");
1630 return 0;
1633 static __inline void
1634 bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0)
1636 int bbp_atten, rf_atten, rf_atten_lim = -1;
1638 bbp_atten = *bbp_atten0;
1639 rf_atten = *rf_atten0;
1642 * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times
1643 * as much as BBP attenuation, so we try our best to keep RF
1644 * attenuation within range. BBP attenuation will be clamped
1645 * later if it is out of range during balancing.
1647 * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit.
1651 * Use BBP attenuation to balance RF attenuation
1653 if (rf_atten < 0)
1654 rf_atten_lim = 0;
1655 else if (rf_atten > BWI_RF_ATTEN_MAX0)
1656 rf_atten_lim = BWI_RF_ATTEN_MAX0;
1658 if (rf_atten_lim >= 0) {
1659 bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim));
1660 rf_atten = rf_atten_lim;
1664 * If possible, use RF attenuation to balance BBP attenuation
1665 * NOTE: RF attenuation is still kept within range.
1667 while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) {
1668 bbp_atten -= BWI_RF_ATTEN_FACTOR;
1669 ++rf_atten;
1671 while (rf_atten > 0 && bbp_atten < 0) {
1672 bbp_atten += BWI_RF_ATTEN_FACTOR;
1673 --rf_atten;
1676 /* RF attenuation MUST be within range */
1677 KKASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0);
1680 * Clamp BBP attenuation
1682 if (bbp_atten < 0)
1683 bbp_atten = 0;
1684 else if (bbp_atten > BWI_BBP_ATTEN_MAX)
1685 bbp_atten = BWI_BBP_ATTEN_MAX;
1687 *rf_atten0 = rf_atten;
1688 *bbp_atten0 = bbp_atten;
1691 static void
1692 bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj)
1694 struct bwi_softc *sc = mac->mac_sc;
1695 struct bwi_rf *rf = &mac->mac_rf;
1696 struct bwi_tpctl tpctl;
1697 int bbp_atten, rf_atten, tp_ctrl1;
1699 bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl));
1701 /* NOTE: Use signed value to do calulation */
1702 bbp_atten = tpctl.bbp_atten;
1703 rf_atten = tpctl.rf_atten;
1704 tp_ctrl1 = tpctl.tp_ctrl1;
1706 bbp_atten += bbp_atten_adj;
1707 rf_atten += rf_atten_adj;
1709 bwi_mac_balance_atten(&bbp_atten, &rf_atten);
1711 if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) {
1712 if (rf_atten <= 1) {
1713 if (tp_ctrl1 == 0) {
1714 tp_ctrl1 = 3;
1715 bbp_atten += 2;
1716 rf_atten += 2;
1717 } else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
1718 bbp_atten +=
1719 (BWI_RF_ATTEN_FACTOR * (rf_atten - 2));
1720 rf_atten = 2;
1722 } else if (rf_atten > 4 && tp_ctrl1 != 0) {
1723 tp_ctrl1 = 0;
1724 if (bbp_atten < 3) {
1725 bbp_atten += 2;
1726 rf_atten -= 3;
1727 } else {
1728 bbp_atten -= 2;
1729 rf_atten -= 2;
1732 bwi_mac_balance_atten(&bbp_atten, &rf_atten);
1735 tpctl.bbp_atten = bbp_atten;
1736 tpctl.rf_atten = rf_atten;
1737 tpctl.tp_ctrl1 = tp_ctrl1;
1739 bwi_mac_lock(mac);
1740 bwi_mac_set_tpctl_11bg(mac, &tpctl);
1741 bwi_mac_unlock(mac);
1745 * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower
1747 void
1748 bwi_mac_calibrate_txpower(struct bwi_mac *mac)
1750 struct bwi_softc *sc = mac->mac_sc;
1751 struct bwi_rf *rf = &mac->mac_rf;
1752 int8_t tssi[4], tssi_avg, cur_txpwr;
1753 int error, i, ofdm_tssi;
1754 int txpwr_diff, rf_atten_adj, bbp_atten_adj;
1756 if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) {
1757 DPRINTF(sc, "%s\n", "tpctl error happened, can't set txpower");
1758 return;
1761 if (BWI_IS_BRCM_BU4306(sc)) {
1762 DPRINTF(sc, "%s\n", "BU4306, can't set txpower");
1763 return;
1767 * Save latest TSSI and reset the related memory objects
1769 ofdm_tssi = 0;
1770 error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS);
1771 if (error) {
1772 DPRINTF(sc, "%s\n", "no DS tssi");
1774 if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
1775 return;
1777 error = bwi_rf_get_latest_tssi(mac, tssi,
1778 BWI_COMM_MOBJ_TSSI_OFDM);
1779 if (error) {
1780 DPRINTF(sc, "%s\n", "no OFDM tssi");
1781 return;
1784 for (i = 0; i < 4; ++i) {
1785 tssi[i] += 0x20;
1786 tssi[i] &= 0x3f;
1788 ofdm_tssi = 1;
1790 bwi_rf_clear_tssi(mac);
1792 DPRINTF(sc, "tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n",
1793 tssi[0], tssi[1], tssi[2], tssi[3]);
1796 * Calculate RF/BBP attenuation adjustment based on
1797 * the difference between desired TX power and sampled
1798 * TX power.
1800 /* +8 == "each incremented by 1/2" */
1801 tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4;
1802 if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS))
1803 tssi_avg -= 13;
1805 DPRINTF(sc, "tssi avg %d\n", tssi_avg);
1807 error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr);
1808 if (error)
1809 return;
1810 DPRINTF(sc, "current txpower %d\n", cur_txpwr);
1812 txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */
1814 rf_atten_adj = -howmany(txpwr_diff, 8);
1815 bbp_atten_adj = -(txpwr_diff / 2) -
1816 (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
1818 if (rf_atten_adj == 0 && bbp_atten_adj == 0) {
1819 DPRINTF(sc, "%s\n", "no need to adjust RF/BBP attenuation");
1820 /* TODO: LO */
1821 return;
1824 DPRINTF(sc, "rf atten adjust %d, bbp atten adjust %d\n",
1825 rf_atten_adj, bbp_atten_adj);
1826 bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj);
1827 /* TODO: LO */
1830 static void
1831 bwi_mac_lock(struct bwi_mac *mac)
1833 struct bwi_softc *sc = mac->mac_sc;
1834 struct ieee80211com *ic = &sc->sc_ic;
1836 KKASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0);
1838 if (mac->mac_rev < 3)
1839 bwi_mac_stop(mac);
1840 else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1841 bwi_mac_config_ps(mac);
1843 CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
1845 /* Flush pending bus write */
1846 CSR_READ_4(sc, BWI_MAC_STATUS);
1847 DELAY(10);
1849 mac->mac_flags |= BWI_MAC_F_LOCKED;
1852 static void
1853 bwi_mac_unlock(struct bwi_mac *mac)
1855 struct bwi_softc *sc = mac->mac_sc;
1856 struct ieee80211com *ic = &sc->sc_ic;
1858 KKASSERT(mac->mac_flags & BWI_MAC_F_LOCKED);
1860 CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */
1862 CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
1864 if (mac->mac_rev < 3)
1865 bwi_mac_start(mac);
1866 else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1867 bwi_mac_config_ps(mac);
1869 mac->mac_flags &= ~BWI_MAC_F_LOCKED;
1872 void
1873 bwi_mac_set_promisc(struct bwi_mac *mac, int promisc)
1875 struct bwi_softc *sc = mac->mac_sc;
1877 if (mac->mac_rev < 5) /* Promisc is always on */
1878 return;
1880 if (promisc)
1881 CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
1882 else
1883 CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);