diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-04-05 16:25:26 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2007-04-05 16:25:26 +0000 |
commit | e3a017b4b7d56ce099f4d8d35709274aa9fceafc (patch) | |
tree | de2675a70c0ce76a1e77964cb71eebbc2fc7f7c3 /sys/dev/ic | |
parent | b379106f42e39d77dcc563db6fbc48b4e47d06d5 (diff) |
After been attacked by Michael Buesch <mb@bu3sch.de> because we initially
were using some of their routines in the bcw driver, I decided to stop
working on it. To avoid any further license chit chat I plain drop the
driver.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/bcw.c | 7160 | ||||
-rw-r--r-- | sys/dev/ic/bcwreg.h | 410 | ||||
-rw-r--r-- | sys/dev/ic/bcwvar.h | 397 |
3 files changed, 0 insertions, 7967 deletions
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c deleted file mode 100644 index b329cb730da..00000000000 --- a/sys/dev/ic/bcw.c +++ /dev/null @@ -1,7160 +0,0 @@ -/* $OpenBSD: bcw.c,v 1.88 2007/04/04 20:48:12 mglocker Exp $ */ - -/* - * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> - * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Broadcom BCM43xx Wireless network chipsets (broadcom.com) - * SiliconBackplane is technology from Sonics, Inc. (sonicsinc.com) - */ - -#include "bpfilter.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/timeout.h> -#include <sys/sockio.h> -#include <sys/mbuf.h> -#include <sys/malloc.h> -#include <sys/kernel.h> -#include <sys/device.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <net/if_dl.h> -#include <net/if_media.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#endif -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif - -#include <net80211/ieee80211_var.h> -#include <net80211/ieee80211_radiotap.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#include <dev/pci/pcidevs.h> - -#include <dev/ic/bcwreg.h> -#include <dev/ic/bcwvar.h> - -#include <uvm/uvm_extern.h> - -/* - * Helper Routines - */ -void bcw_shm_ctl_word(struct bcw_softc *, uint16_t, - uint16_t); -uint16_t bcw_shm_read16(struct bcw_softc *, uint16_t, uint16_t); -void bcw_shm_write16(struct bcw_softc *, uint16_t, uint16_t, - uint16_t); -uint32_t bcw_shm_read32(struct bcw_softc *, uint16_t, uint16_t); -void bcw_shm_write32(struct bcw_softc *, uint16_t, uint16_t, - uint32_t); -void bcw_radio_write16(struct bcw_softc *, uint16_t, - uint16_t); -int bcw_radio_read16(struct bcw_softc *, uint16_t); -void bcw_phy_write16(struct bcw_softc *, uint16_t, uint16_t); -int bcw_phy_read16(struct bcw_softc *, uint16_t); -void bcw_ram_write(struct bcw_softc *, uint16_t, uint32_t); -int bcw_lv(int, int, int); -void bcw_dummy_transmission(struct bcw_softc *); -struct bcw_lopair * bcw_get_lopair(struct bcw_softc *, uint16_t, - uint16_t); -void bcw_stack_save(uint32_t *, size_t *, uint8_t, uint16_t, - uint16_t); -uint16_t bcw_stack_restore(uint32_t *, uint8_t, uint16_t); -int bcw_using_pio(struct bcw_softc *); -void bcw_rate_memory_write(struct bcw_softc *, uint16_t, - int); -void bcw_rate_memory_init(struct bcw_softc *); -uint16_t bcw_flip_4bit(uint16_t); - -/* - * 80211 - */ -int bcw_init(struct ifnet *); -void bcw_start(struct ifnet *); -void bcw_stop(struct ifnet *, int); -void bcw_watchdog(struct ifnet *); -void bcw_set_opmode(struct ifnet *); -void bcw_macfilter_set(struct bcw_softc *, uint16_t, - const uint8_t *); -void bcw_macfilter_clear(struct bcw_softc *, uint16_t); -void bcw_templateram_set(struct bcw_softc *); -void bcw_mac_enable(struct bcw_softc *); -void bcw_mac_disable(struct bcw_softc *); -uint32_t bcw_intr_enable(struct bcw_softc *, uint32_t); -uint32_t bcw_intr_disable(struct bcw_softc *, uint32_t); -void bcw_rxintr(struct bcw_softc *); -void bcw_txintr(struct bcw_softc *); -int bcw_add_rxbuf(struct bcw_softc *, int); -void bcw_rxdrain(struct bcw_softc *); -void bcw_tick(void *); -int bcw_ioctl(struct ifnet *, u_long, caddr_t); -int bcw_alloc_rx_ring(struct bcw_softc *, - struct bcw_rx_ring *, int); -void bcw_reset_rx_ring(struct bcw_softc *, - struct bcw_rx_ring *); -void bcw_free_rx_ring(struct bcw_softc *, - struct bcw_rx_ring *); -int bcw_alloc_tx_ring(struct bcw_softc *, - struct bcw_tx_ring *, int); -void bcw_reset_tx_ring(struct bcw_softc *, - struct bcw_tx_ring *); -void bcw_free_tx_ring(struct bcw_softc *, - struct bcw_tx_ring *); -int bcw_newstate(struct ieee80211com *, - enum ieee80211_state, int); -int bcw_media_change(struct ifnet *); -void bcw_media_status(struct ifnet *, struct ifmediareq *); -int bcw_validate_chip_access(struct bcw_softc *); -int bcw_change_core(struct bcw_softc *, int); -int bcw_core_enable(struct bcw_softc *, uint32_t); -int bcw_core_disable(struct bcw_softc *, uint32_t); -void bcw_80211_core_reset(struct bcw_softc *, int); -void bcw_80211_core_disable(struct bcw_softc *); -int bcw_iocore_enable(struct bcw_softc *, uint32_t); -int bcw_get_firmware(const char *, const uint8_t *, size_t, - size_t *, size_t *); -int bcw_load_firmware(struct bcw_softc *); -int bcw_write_initvals(struct bcw_softc *, - const struct bcw_initval *, const unsigned int); -int bcw_load_initvals(struct bcw_softc *); -void bcw_leds_switch_all(struct bcw_softc *, int); -int bcw_gpio_init(struct bcw_softc *); -int bcw_chip_init(struct bcw_softc *); -int bcw_bs_init(struct bcw_softc *); -int bcw_80211_core_init(struct bcw_softc *, int); -uint8_t bcw_sprom_crc8(uint8_t, uint8_t); -uint8_t bcw_sprom_crc(const uint16_t *); -int bcw_sprom_read(struct bcw_softc *, uint16_t *); -int bcw_sprom_get(struct bcw_softc *); -void bcw_microcode_init_fbf(struct bcw_softc *); - -/* - * PHY - */ -int bcw_phy_get(struct bcw_softc *); -int bcw_phy_init(struct bcw_softc *); -void bcw_phy_initg(struct bcw_softc *); -void bcw_phy_initb2(struct bcw_softc *); -void bcw_phy_initb4(struct bcw_softc *); -void bcw_phy_initb5(struct bcw_softc *); -void bcw_phy_initb6(struct bcw_softc *); -void bcw_phy_inita(struct bcw_softc *); -void bcw_phy_setupa(struct bcw_softc *); -void bcw_phy_setupg(struct bcw_softc *); -void bcw_phy_calc_loopback_gain(struct bcw_softc *); -void bcw_phy_agcsetup(struct bcw_softc *); -void bcw_phy_init_pctl(struct bcw_softc *); -void bcw_phy_init_noisescaletbl(struct bcw_softc *); -void bcw_phy_set_baseband_atten(struct bcw_softc *, - uint16_t); -int8_t bcw_phy_estimate_powerout(struct bcw_softc *, int8_t); -void bcw_phy_xmitpower(struct bcw_softc *); -uint16_t bcw_phy_lo_b_r15_loop(struct bcw_softc *); -void bcw_phy_lo_b_measure(struct bcw_softc *); -void bcw_phy_lo_g_state(struct bcw_softc *, - struct bcw_lopair *, struct bcw_lopair *, uint16_t); -void bcw_phy_lo_g_measure(struct bcw_softc *); -void bcw_phy_lo_g_measure_txctl2(struct bcw_softc *); -uint32_t bcw_phy_lo_g_singledeviation(struct bcw_softc *, - uint16_t); -uint16_t bcw_phy_lo_g_deviation_subval(struct bcw_softc *, - uint16_t); -void bcw_phy_lo_adjust(struct bcw_softc *, int); -void bcw_phy_lo_mark_current_used(struct bcw_softc *); -void bcw_phy_lo_write(struct bcw_softc *, - struct bcw_lopair *); -struct bcw_lopair * bcw_phy_find_lopair(struct bcw_softc *, uint16_t, - uint16_t, uint16_t); -struct bcw_lopair * bcw_phy_current_lopair(struct bcw_softc *); -void bcw_phy_set_antenna_diversity(struct bcw_softc *); -void bcw_phy_calibrate(struct bcw_softc *); -int bcw_phy_connect(struct bcw_softc *, int); -void bcw_phy_lock(struct bcw_softc *); -void bcw_phy_unlock(struct bcw_softc *); - -/* - * Radio - */ -int bcw_radio_get(struct bcw_softc *); -void bcw_radio_off(struct bcw_softc *); -void bcw_radio_on(struct bcw_softc *); -void bcw_radio_nrssi_hw_write(struct bcw_softc *, - uint16_t, int16_t); -int16_t bcw_radio_nrssi_hw_read(struct bcw_softc *, uint16_t); -void bcw_radio_nrssi_hw_update(struct bcw_softc *, uint16_t); -void bcw_radio_calc_nrssi_threshold(struct bcw_softc *); -void bcw_radio_calc_nrssi_slope(struct bcw_softc *); -void bcw_radio_calc_nrssi_offset(struct bcw_softc *); -void bcw_radio_set_all_gains(struct bcw_softc *, int16_t, - int16_t, int16_t); -void bcw_radio_set_original_gains(struct bcw_softc *); -uint16_t bcw_radio_calibrationvalue(struct bcw_softc *); -void bcw_radio_set_txpower_a(struct bcw_softc *, uint16_t); -void bcw_radio_set_txpower_bg(struct bcw_softc *, uint16_t, - uint16_t, uint16_t); -uint16_t bcw_radio_init2050(struct bcw_softc *); -void bcw_radio_init2060(struct bcw_softc *); -void bcw_radio_spw(struct bcw_softc *, uint8_t); -int bcw_radio_select_channel(struct bcw_softc *, uint8_t, - int); -uint16_t bcw_radio_chan2freq_a(uint8_t); -uint16_t bcw_radio_chan2freq_bg(uint8_t); -uint16_t bcw_radio_default_baseband_atten(struct bcw_softc *); -uint16_t bcw_radio_default_radio_atten(struct bcw_softc *); -uint16_t bcw_radio_default_txctl1(struct bcw_softc *); -void bcw_radio_clear_tssi(struct bcw_softc *); -void bcw_radio_set_tx_iq(struct bcw_softc *); -uint16_t bcw_radio_get_txgain_baseband(uint16_t); -uint16_t bcw_radio_get_txgain_freq_power_amp(uint16_t); -uint16_t bcw_radio_get_txgain_dac(uint16_t); -uint16_t bcw_radio_freq_r3a_value(uint16_t); -int bcw_radio_set_interf_mitigation(struct bcw_softc *, - int); -int bcw_radio_interf_mitigation_enable(struct bcw_softc *, - int); -void bcw_radio_set_txantenna(struct bcw_softc *, uint32_t); -void bcw_radio_lock(struct bcw_softc *); -void bcw_radio_unlock(struct bcw_softc *); - -/* - * ILT - */ -void bcw_ilt_write(struct bcw_softc *, uint16_t, uint16_t); -uint16_t bcw_ilt_read(struct bcw_softc *, uint16_t); - -/* - * Power Control - */ -void bcw_pc_crystal_on(struct bcw_softc *); -void bcw_pc_crystal_off(struct bcw_softc *); -int bcw_pc_init(struct bcw_softc *); -int bcw_pc_set_clock(struct bcw_softc *, uint16_t); -void bcw_pc_saving_ctl_bits(struct bcw_softc *, int, int); -uint16_t bcw_pc_powerup_delay(struct bcw_softc *); -int bcw_pc_clock_freqlimit(struct bcw_softc *, int); -int bcw_pc_get_slowclocksrc(struct bcw_softc *); - -/* - * XMIT - */ -uint8_t bcw_xmit_plcp_get_ratecode_cck(const uint8_t); -uint8_t bcw_xmit_plcp_get_ratecode_ofdm(const uint8_t); - -struct cfdriver bcw_cd = { - NULL, "bcw", DV_IFNET -}; - -#define BCW_PHY_STACKSAVE(offset) \ - do { \ - bcw_stack_save(stack, &stackidx, 0x1, (offset), \ - bcw_phy_read16(sc, (offset))); \ - } while (0) -#define BCW_ILT_STACKSAVE(offset) \ - do { \ - bcw_stack_save(stack, &stackidx, 0x3, (offset), \ - bcw_ilt_read(sc, (offset))); \ - } while (0) -#define BCW_RADIO_STACKSAVE(offset) \ - do { \ - bcw_stack_save(stack, &stackidx, 0x2, (offset), \ - bcw_radio_read16(sc, (offset))); \ - } while (0) - -/* - * Table for bcw_radio_calibrationvalue() - */ -const uint16_t rcc_table[16] = { - 0x0002, 0x0003, 0x0001, 0x000F, - 0x0006, 0x0007, 0x0005, 0x000F, - 0x000A, 0x000B, 0x0009, 0x000F, - 0x000E, 0x000F, 0x000D, 0x000F, -}; - -/* - * ILT (Internal Lookup Table) - */ -const uint32_t bcw_ilt_rotor[BCW_ILT_ROTOR_SIZE] = { - 0xFEB93FFD, 0xFEC63FFD, /* 0 */ - 0xFED23FFD, 0xFEDF3FFD, - 0xFEEC3FFE, 0xFEF83FFE, - 0xFF053FFE, 0xFF113FFE, - 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */ - 0xFF373FFF, 0xFF443FFF, - 0xFF503FFF, 0xFF5D3FFF, - 0xFF693FFF, 0xFF763FFF, - 0xFF824000, 0xFF8F4000, /* 16 */ - 0xFF9B4000, 0xFFA84000, - 0xFFB54000, 0xFFC14000, - 0xFFCE4000, 0xFFDA4000, - 0xFFE74000, 0xFFF34000, /* 24 */ - 0x00004000, 0x000D4000, - 0x00194000, 0x00264000, - 0x00324000, 0x003F4000, - 0x004B4000, 0x00584000, /* 32 */ - 0x00654000, 0x00714000, - 0x007E4000, 0x008A3FFF, - 0x00973FFF, 0x00A33FFF, - 0x00B03FFF, 0x00BC3FFF, /* 40 */ - 0x00C93FFF, 0x00D63FFF, - 0x00E23FFE, 0x00EF3FFE, - 0x00FB3FFE, 0x01083FFE, - 0x01143FFE, 0x01213FFD, /* 48 */ - 0x012E3FFD, 0x013A3FFD, - 0x01473FFD, -}; - -const uint16_t bcw_ilt_sigmasqr1[BCW_ILT_SIGMASQR_SIZE] = { - 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */ - 0x0067, 0x0063, 0x005E, 0x0059, - 0x0054, 0x0050, 0x004B, 0x0046, - 0x0042, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x0000, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x0042, 0x0046, 0x004B, 0x0050, - 0x0054, 0x0059, 0x005E, 0x0063, - 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */ - 0x007A, -}; - -const uint16_t bcw_ilt_sigmasqr2[BCW_ILT_SIGMASQR_SIZE] = { - 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */ - 0x00D6, 0x00D4, 0x00D2, 0x00CF, - 0x00CD, 0x00CA, 0x00C7, 0x00C4, - 0x00C1, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x0000, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00C1, 0x00C4, 0x00C7, 0x00CA, - 0x00CD, 0x00CF, 0x00D2, 0x00D4, - 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */ - 0x00DE, -}; - -const uint32_t bcw_ilt_retard[BCW_ILT_RETARD_SIZE] = { - 0xDB93CB87, 0xD666CF64, /* 0 */ - 0xD1FDD358, 0xCDA6D826, - 0xCA38DD9F, 0xC729E2B4, - 0xC469E88E, 0xC26AEE2B, - 0xC0DEF46C, 0xC073FA62, /* 8 */ - 0xC01D00D5, 0xC0760743, - 0xC1560D1E, 0xC2E51369, - 0xC4ED18FF, 0xC7AC1ED7, - 0xCB2823B2, 0xCEFA28D9, /* 16 */ - 0xD2F62D3F, 0xD7BB3197, - 0xDCE53568, 0xE1FE3875, - 0xE7D13B35, 0xED663D35, - 0xF39B3EC4, 0xF98E3FA7, /* 24 */ - 0x00004000, 0x06723FA7, - 0x0C653EC4, 0x129A3D35, - 0x182F3B35, 0x1E023875, - 0x231B3568, 0x28453197, /* 32 */ - 0x2D0A2D3F, 0x310628D9, - 0x34D823B2, 0x38541ED7, - 0x3B1318FF, 0x3D1B1369, - 0x3EAA0D1E, 0x3F8A0743, /* 40 */ - 0x3FE300D5, 0x3F8DFA62, - 0x3F22F46C, 0x3D96EE2B, - 0x3B97E88E, 0x38D7E2B4, - 0x35C8DD9F, 0x325AD826, /* 48 */ - 0x2E03D358, 0x299ACF64, - 0x246DCB87, -}; - -const uint16_t bcw_ilt_finefreqa[BCW_ILT_FINEFREQA_SIZE] = { - 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */ - 0x0202, 0x0282, 0x0302, 0x0382, - 0x0402, 0x0482, 0x0502, 0x0582, - 0x05E2, 0x0662, 0x06E2, 0x0762, - 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */ - 0x09C2, 0x0A22, 0x0AA2, 0x0B02, - 0x0B82, 0x0BE2, 0x0C62, 0x0CC2, - 0x0D42, 0x0DA2, 0x0E02, 0x0E62, - 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */ - 0x1062, 0x10C2, 0x1122, 0x1182, - 0x11E2, 0x1242, 0x12A2, 0x12E2, - 0x1342, 0x13A2, 0x1402, 0x1442, - 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */ - 0x15E2, 0x1622, 0x1662, 0x16C1, - 0x1701, 0x1741, 0x1781, 0x17E1, - 0x1821, 0x1861, 0x18A1, 0x18E1, - 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */ - 0x1A21, 0x1A61, 0x1AA1, 0x1AC1, - 0x1B01, 0x1B41, 0x1B81, 0x1BA1, - 0x1BE1, 0x1C21, 0x1C41, 0x1C81, - 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */ - 0x1D61, 0x1DA1, 0x1DC1, 0x1E01, - 0x1E21, 0x1E61, 0x1E81, 0x1EA1, - 0x1EE1, 0x1F01, 0x1F21, 0x1F41, - 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */ - 0x2001, 0x2041, 0x2061, 0x2081, - 0x20A1, 0x20C1, 0x20E1, 0x2101, - 0x2121, 0x2141, 0x2161, 0x2181, - 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */ - 0x2221, 0x2241, 0x2261, 0x2281, - 0x22A1, 0x22C1, 0x22C1, 0x22E1, - 0x2301, 0x2321, 0x2341, 0x2361, - 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */ - 0x23E1, 0x23E1, 0x2401, 0x2421, - 0x2441, 0x2441, 0x2461, 0x2481, - 0x2481, 0x24A1, 0x24C1, 0x24C1, - 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */ - 0x2541, 0x2541, 0x2561, 0x2561, - 0x2581, 0x25A1, 0x25A1, 0x25C1, - 0x25C1, 0x25E1, 0x2601, 0x2601, - 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */ - 0x2661, 0x2661, 0x2681, 0x2681, - 0x26A1, 0x26A1, 0x26C1, 0x26C1, - 0x26E1, 0x26E1, 0x2701, 0x2701, - 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */ - 0x2760, 0x2760, 0x2780, 0x2780, - 0x2780, 0x27A0, 0x27A0, 0x27C0, - 0x27C0, 0x27E0, 0x27E0, 0x27E0, - 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */ - 0x2820, 0x2840, 0x2840, 0x2840, - 0x2860, 0x2860, 0x2880, 0x2880, - 0x2880, 0x28A0, 0x28A0, 0x28A0, - 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */ - 0x28E0, 0x28E0, 0x2900, 0x2900, - 0x2900, 0x2920, 0x2920, 0x2920, - 0x2940, 0x2940, 0x2940, 0x2960, - 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */ - 0x2980, 0x2980, 0x29A0, 0x29A0, - 0x29A0, 0x29A0, 0x29C0, 0x29C0, - 0x29C0, 0x29E0, 0x29E0, 0x29E0, - 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */ - 0x2A00, 0x2A20, 0x2A20, 0x2A20, - 0x2A20, 0x2A40, 0x2A40, 0x2A40, - 0x2A40, 0x2A60, 0x2A60, 0x2A60, -}; - -const uint16_t bcw_ilt_noisea2[BCW_ILT_NOISEA2_SIZE] = { - 0x0001, 0x0001, 0x0001, 0xFFFE, - 0xFFFE, 0x3FFF, 0x1000, 0x0393, -}; - -const uint16_t bcw_ilt_noisea3[BCW_ILT_NOISEA3_SIZE] = { - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, -}; - -const uint16_t bcw_ilt_finefreqg[BCW_ILT_FINEFREQG_SIZE] = { - 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */ - 0x05A9, 0x0669, 0x0709, 0x0789, - 0x0829, 0x08A9, 0x0929, 0x0989, - 0x0A09, 0x0A69, 0x0AC9, 0x0B29, - 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */ - 0x0D09, 0x0D69, 0x0DA9, 0x0E09, - 0x0E69, 0x0EA9, 0x0F09, 0x0F49, - 0x0FA9, 0x0FE9, 0x1029, 0x1089, - 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */ - 0x11E9, 0x1229, 0x1289, 0x12C9, - 0x1309, 0x1349, 0x1389, 0x13C9, - 0x1409, 0x1449, 0x14A9, 0x14E9, - 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */ - 0x1629, 0x1669, 0x16A9, 0x16E8, - 0x1728, 0x1768, 0x17A8, 0x17E8, - 0x1828, 0x1868, 0x18A8, 0x18E8, - 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */ - 0x1A28, 0x1A68, 0x1AA8, 0x1AE8, - 0x1B28, 0x1B68, 0x1BA8, 0x1BE8, - 0x1C28, 0x1C68, 0x1CA8, 0x1CE8, - 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */ - 0x1E48, 0x1E88, 0x1EC8, 0x1F08, - 0x1F48, 0x1F88, 0x1FE8, 0x2028, - 0x2068, 0x20A8, 0x2108, 0x2148, - 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */ - 0x22C8, 0x2308, 0x2348, 0x23A8, - 0x23E8, 0x2448, 0x24A8, 0x24E8, - 0x2548, 0x25A8, 0x2608, 0x2668, - 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */ - 0x2847, 0x28C7, 0x2947, 0x29A7, - 0x2A27, 0x2AC7, 0x2B47, 0x2BE7, - 0x2CA7, 0x2D67, 0x2E47, 0x2F67, - 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */ - 0x3806, 0x38A6, 0x3946, 0x39E6, - 0x3A66, 0x3AE6, 0x3B66, 0x3BC6, - 0x3C45, 0x3CA5, 0x3D05, 0x3D85, - 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */ - 0x3F45, 0x3FA5, 0x4005, 0x4045, - 0x40A5, 0x40E5, 0x4145, 0x4185, - 0x41E5, 0x4225, 0x4265, 0x42C5, - 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */ - 0x4424, 0x4464, 0x44C4, 0x4504, - 0x4544, 0x4584, 0x45C4, 0x4604, - 0x4644, 0x46A4, 0x46E4, 0x4724, - 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */ - 0x4864, 0x48A4, 0x48E4, 0x4924, - 0x4964, 0x49A4, 0x49E4, 0x4A24, - 0x4A64, 0x4AA4, 0x4AE4, 0x4B23, - 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */ - 0x4C63, 0x4CA3, 0x4CE3, 0x4D23, - 0x4D63, 0x4DA3, 0x4DE3, 0x4E23, - 0x4E63, 0x4EA3, 0x4EE3, 0x4F23, - 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */ - 0x5083, 0x50C3, 0x5103, 0x5143, - 0x5183, 0x51E2, 0x5222, 0x5262, - 0x52A2, 0x52E2, 0x5342, 0x5382, - 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */ - 0x5502, 0x5542, 0x55A2, 0x55E2, - 0x5642, 0x5682, 0x56E2, 0x5722, - 0x5782, 0x57E1, 0x5841, 0x58A1, - 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */ - 0x5AA1, 0x5B01, 0x5B81, 0x5BE1, - 0x5C61, 0x5D01, 0x5D80, 0x5E20, - 0x5EE0, 0x5FA0, 0x6080, 0x61C0, -}; - -const uint16_t bcw_ilt_noiseg1[BCW_ILT_NOISEG1_SIZE] = { - 0x013C, 0x01F5, 0x031A, 0x0631, - 0x0001, 0x0001, 0x0001, 0x0001, -}; - -const uint16_t bcw_ilt_noiseg2[BCW_ILT_NOISEG2_SIZE] = { - 0x5484, 0x3C40, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, -}; - -const uint16_t bcw_ilt_noisescaleg1[BCW_ILT_NOISESCALEG_SIZE] = { - 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */ - 0x2F2D, 0x2A2A, 0x2527, 0x1F21, - 0x1A1D, 0x1719, 0x1616, 0x1414, - 0x1414, 0x1400, 0x1414, 0x1614, - 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */ - 0x2A27, 0x2F2A, 0x332D, 0x3B35, - 0x5140, 0x6C62, 0x0077, -}; - -const uint16_t bcw_ilt_noisescaleg3[BCW_ILT_NOISESCALEG_SIZE] = { - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA400, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0x00A4, -}; - -const uint16_t bcw_ilt_noisescaleg2[BCW_ILT_NOISESCALEG_SIZE] = { - 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */ - 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1, - 0x969B, 0x9195, 0x8F8F, 0x8A8A, - 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A, - 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */ - 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7, - 0xCBC0, 0xD8D4, 0x00DD, -}; - -/* - * Helper routines - */ -void -bcw_shm_ctl_word(struct bcw_softc *sc, uint16_t routing, uint16_t offset) -{ - uint32_t control; - - control = routing; - control <<= 16; - control |= offset; - - BCW_WRITE(sc, BCW_MMIO_SHM_CONTROL, control); -} - -uint16_t -bcw_shm_read16(struct bcw_softc *sc, uint16_t routing, uint16_t offset) -{ - if (routing == BCW_SHM_SHARED) { - if (offset & 0x0003) { - bcw_shm_ctl_word(sc, routing, offset >> 2); - - return (BCW_READ16(sc, BCW_MMIO_SHM_DATA_UNALIGNED)); - } - offset >>= 2; - } - bcw_shm_ctl_word(sc, routing, offset); - - return (BCW_READ16(sc, BCW_MMIO_SHM_DATA)); -} - -void -bcw_shm_write16(struct bcw_softc *sc, uint16_t routing, uint16_t offset, - uint16_t val) -{ - if (routing == BCW_SHM_SHARED) { - if (offset & 0x0003) { - bcw_shm_ctl_word(sc, routing, offset >> 2); - BCW_WRITE16(sc, BCW_MMIO_SHM_DATA_UNALIGNED, val); - return; - } - offset >>= 2; - } - bcw_shm_ctl_word(sc, routing, offset); - BCW_WRITE16(sc, BCW_MMIO_SHM_DATA, val); -} - -uint32_t -bcw_shm_read32(struct bcw_softc *sc, uint16_t routing, uint16_t offset) -{ - uint32_t r; - - if (routing == BCW_SHM_SHARED) { - if (offset & 0x003) { - bcw_shm_ctl_word(sc, routing, offset >> 2); - r = BCW_READ16(sc, BCW_MMIO_SHM_DATA_UNALIGNED); - r <<= 16; - bcw_shm_ctl_word(sc, routing, (offset >> 2) + 1); - r |= BCW_READ16(sc, BCW_MMIO_SHM_DATA); - return (r); - } - offset >>= 2; - } - bcw_shm_ctl_word(sc, routing, offset); - r = BCW_READ(sc, BCW_MMIO_SHM_DATA); - - return (r); -} - -void -bcw_shm_write32(struct bcw_softc *sc, uint16_t routing, uint16_t offset, - uint32_t val) -{ - if (routing == BCW_SHM_SHARED) { - if (offset & 0x0003) { - bcw_shm_ctl_word(sc, routing, offset >> 2); - BCW_WRITE16(sc, BCW_MMIO_SHM_DATA_UNALIGNED, - (val >> 16) & 0xffff); - bcw_shm_ctl_word(sc, routing, (offset >> 2) + 1); - BCW_WRITE16(sc, BCW_MMIO_SHM_DATA, val & 0xffff); - return; - } - offset >>= 2; - } - bcw_shm_ctl_word(sc, routing, offset); - BCW_WRITE(sc, BCW_MMIO_SHM_DATA, val); -} - -void -bcw_radio_write16(struct bcw_softc *sc, uint16_t offset, uint16_t val) -{ - BCW_WRITE16(sc, BCW_MMIO_RADIO_CONTROL, offset); - BCW_WRITE16(sc, BCW_MMIO_RADIO_DATA_LOW, val); -} - -int -bcw_radio_read16(struct bcw_softc *sc, uint16_t offset) -{ - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - offset |= 0x0040; - break; - case BCW_PHY_TYPEB: - if (sc->sc_radio_ver == 0x2053) { - if (offset < 0x70) - offset += 0x80; - else if (offset < 0x80) - offset += 0x70; - } else if (sc->sc_radio_ver == 0x2050) - offset |= 0x80; - else - return (0); - break; - case BCW_PHY_TYPEG: - offset |= 0x80; - break; - } - - BCW_WRITE16(sc, BCW_MMIO_RADIO_CONTROL, offset); - - return (BCW_READ16(sc, BCW_MMIO_RADIO_DATA_LOW)); -} - -void -bcw_phy_write16(struct bcw_softc *sc, uint16_t offset, uint16_t val) -{ - BCW_WRITE16(sc, BCW_MMIO_PHY_CONTROL, offset); - BCW_WRITE16(sc, BCW_MMIO_PHY_DATA, val); -} - -int -bcw_phy_read16(struct bcw_softc *sc, uint16_t offset) -{ - BCW_WRITE16(sc, BCW_MMIO_PHY_CONTROL, offset); - - return (BCW_READ16(sc, BCW_MMIO_PHY_DATA)); -} - -void -bcw_ram_write(struct bcw_softc *sc, uint16_t offset, uint32_t val) -{ - uint32_t status; - - status = BCW_READ(sc, BCW_MMIO_SBF); - if (!(status & BCW_SBF_REGISTER_BYTESWAP)) - val = swap32(val); - - BCW_WRITE(sc, BCW_MMIO_RAM_CONTROL, offset); - BCW_WRITE(sc, BCW_MMIO_RAM_DATA, val); -} - -int -bcw_lv(int number, int min, int max) -{ - if (number < min) - return (min); - else if (number > max) - return (max); - else - return (number); -} - -uint16_t -bcw_flip_4bit(uint16_t val) -{ - uint16_t flip = 0; - - flip |= (val & 0x0001) << 3; - flip |= (val & 0x0002) << 1; - flip |= (val & 0x0004) >> 1; - flip |= (val & 0x0008) >> 3; - - return (flip); -} - -/* - * Dummy Transmission - * - * http://bcm-specs.sipsolutions.net/DummyTransmission - */ -void -bcw_dummy_transmission(struct bcw_softc *sc) -{ - unsigned int i, max_loop; - uint16_t val = 0; - uint32_t buffer[5] = { - 0x00000000, - 0x00000400, - 0x00000000, - 0x00000001, - 0x00000000 - }; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - max_loop = 0x1e; - buffer[0] = 0xcc010200; - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: - max_loop = 0xfa; - buffer[0] = 0x6e840b00; - break; - default: - /* XXX panic()? */ - return; - } - - for (i = 0; i < 5; i++) - bcw_ram_write(sc, i * 4, buffer[i]); - - BCW_READ(sc, BCW_MMIO_SBF); - - BCW_WRITE16(sc, 0x0568, 0); - BCW_WRITE16(sc, 0x07c0, 0); - BCW_WRITE16(sc, 0x050c, sc->sc_phy_type == BCW_PHY_TYPEA ? 1 : 0); - - BCW_WRITE16(sc, 0x0508, 0); - BCW_WRITE16(sc, 0x050a, 0); - BCW_WRITE16(sc, 0x054c, 0); - BCW_WRITE16(sc, 0x056a, 0x0014); - BCW_WRITE16(sc, 0x0568, 0x0826); - BCW_WRITE16(sc, 0x0500, 0); - BCW_WRITE16(sc, 0x0502, 0x0030); - - if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev <= 0x5) - bcw_radio_write16(sc, 0x0051, 0x0017); - for (i = 0; i < max_loop; i++) { - val = BCW_READ16(sc, 0x050e); - if (val & 0x0080) - break; - delay(10); - } - for (i = 0; i < 0x0a; i++) { - val = BCW_READ16(sc, 0x050e); - if (val & 0x0400) - break; - delay(10); - } - for (i = 0; i < 0x0a; i++) { - val = BCW_READ16(sc, 0x0690); - if (!(val & 0x0100)) - break; - delay(10); - } - if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev <= 0x5) - bcw_radio_write16(sc, 0x0051, 0x0037); -} - -struct bcw_lopair * -bcw_get_lopair(struct bcw_softc *sc, uint16_t radio_atten, - uint16_t baseband_atten) -{ - return (sc->sc_phy_lopairs + (radio_atten + 14 * - (baseband_atten / 2))); -} - -void -bcw_stack_save(uint32_t *_stackptr, size_t *stackidx, uint8_t id, - uint16_t offset, uint16_t val) -{ - uint32_t *stackptr = &(_stackptr[*stackidx]); - - *stackptr = offset; - *stackptr |= ((uint32_t)id) << 12; - *stackptr |= ((uint32_t)val) << 16; - (*stackidx)++; -} - -uint16_t -bcw_stack_restore(uint32_t *stackptr, uint8_t id, uint16_t offset) -{ - size_t i; - - for (i = 0; i < BCW_INTERFSTACK_SIZE; i++, stackptr++) { - if ((*stackptr & 0x00000fff) != offset) - continue; - if (((*stackptr & 0x0000f000) >> 12) != id) - continue; - return (((*stackptr & 0xffff0000) >> 16)); - } - - return (0); -} - -int -bcw_using_pio(struct bcw_softc *sc) -{ - return (sc->sc_using_pio); -} - -void -bcw_rate_memory_write(struct bcw_softc *sc, uint16_t rate, int is_ofdm) -{ - uint16_t offset; - - if (is_ofdm) { - offset = 0x480; - offset += (bcw_xmit_plcp_get_ratecode_ofdm(rate) & 0x000f) * 2; - } else { - offset = 0x4c0; - offset += (bcw_xmit_plcp_get_ratecode_cck(rate) & 0x000f) * 2; - } - bcw_shm_write16(sc, BCW_SHM_SHARED, offset + 0x20, - bcw_shm_read16(sc, BCW_SHM_SHARED, offset)); -} - -void -bcw_rate_memory_init(struct bcw_softc *sc) -{ - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - case BCW_PHY_TYPEG: - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[0], 1); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[1], 1); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[2], 1); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[3], 1); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[4], 1); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[5], 1); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[6], 1); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11g.rs_rates[7], 1); - case BCW_PHY_TYPEB: - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11b.rs_rates[0], 0); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11b.rs_rates[1], 0); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11b.rs_rates[2], 0); - bcw_rate_memory_write(sc, - ieee80211_std_rateset_11b.rs_rates[3], 0); - default: - /* XXX panic()? */ - break; - } -} - -/* - * Attach device - * - * http://bcm-specs.sipsolutions.net/DeviceAttach - */ -void -bcw_attach(struct bcw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - int i; - uint32_t sbval; - uint32_t core_id, core_rev, core_vendor; - - /* power on cardbus socket */ - if (sc->sc_enable) - sc->sc_enable(sc); - - DPRINTF(("\n%s: BoardVendor=0x%x, BoardType=0x%x, BoardRev=0x%x\n", - sc->sc_dev.dv_xname, - sc->sc_board_vendor, sc->sc_board_type, sc->sc_board_rev)); - - /* - * Attach chipset to backplane - */ - bcw_pc_crystal_on(sc); - (sc->sc_conf_write)(sc, PCI_COMMAND_STATUS_REG, - (sc->sc_conf_read)(sc, PCI_COMMAND_STATUS_REG) & - ~PCI_STATUS_TARGET_TARGET_ABORT); - - /* - * Try and change to the ChipCommon Core - */ - if (bcw_change_core(sc, 0) == 0) { - DPRINTF(("%s: Selected ChipCommon Core\n", - sc->sc_dev.dv_xname)); - sc->sc_chip_common_capa = - BCW_READ(sc, BCW_CHIPCOMMON_CAPABILITIES); /* XXX */ - } - - /* - * Core ID REG, this is either the default wireless core (0x812) or - * a ChipCommon core that was successfully selected above - */ - sbval = BCW_READ(sc, BCW_CIR_SBID_HI); - core_id = (sbval & 0x8ff0) >> 4; - core_rev = (sbval & 0x7000) >> 8; - core_rev |= (sbval & 0xf); - core_vendor = (sbval & 0xffff0000) >> 16; - DPRINTF(("%s: CoreID=0x%x, CoreRev=0x%x, CoreVendor=0x%x\n", - sc->sc_dev.dv_xname, core_id, core_rev, core_vendor)); - - /* - * If we successfully got a commoncore, and the corerev=4 or >=6 - * get the number of cores from the chipid reg - */ - if (core_id == BCW_CORE_COMMON) { - sc->sc_havecommon = 1; - - /* powercontrol init is done if a common core exists */ - bcw_pc_init(sc); - - sbval = BCW_READ(sc, BCW_CORE_COMMON_CHIPID); - sc->sc_chip_id = (sbval & 0x0000ffff); - sc->sc_chip_rev = (sbval & 0x000f0000) >> 16; - sc->sc_chip_pkg = (sbval & 0x00f00000) >> 20; - - if (core_rev >= 4) - sc->sc_numcores = (sbval & 0x0f000000) >> 24; - else { - switch (sc->sc_chip_id) { - case 0x4710: - case 0x4610: - case 0x4704: - sc->sc_numcores = 9; - break; - case 0x4310: - sc->sc_numcores = 8; - break; - case 0x5365: - sc->sc_numcores = 7; - break; - case 0x4306: - sc->sc_numcores = 6; - break; - case 0x4307: - case 0x4301: - sc->sc_numcores = 5; - break; - case 0x4402: - sc->sc_numcores = 3; - break; - default: - /* set to max */ - sc->sc_numcores = BCW_MAX_CORES; - } - } - } else { /* No CommonCore, set chipid, cores, rev based on product id */ - sc->sc_core_common = NULL; - sc->sc_havecommon = 0; - switch (sc->sc_prodid) { - case 0x4710: - case 0x4711: - case 0x4712: - case 0x4713: - case 0x4714: - case 0x4715: - sc->sc_chip_id = 0x4710; - sc->sc_numcores = 9; - break; - case 0x4610: - case 0x4611: - case 0x4612: - case 0x4613: - case 0x4614: - case 0x4615: - sc->sc_chip_id = 0x4610; - sc->sc_numcores = 9; - break; - case 0x4402: - case 0x4403: - sc->sc_chip_id = 0x4402; - sc->sc_numcores = 3; - break; - case 0x4305: - case 0x4306: - case 0x4307: - sc->sc_chip_id = 0x4307; - sc->sc_numcores = 5; - break; - case 0x4301: - sc->sc_chip_id = 0x4301; - sc->sc_numcores = 5; - break; - default: - sc->sc_chip_id = sc->sc_prodid; - /* Set to max */ - sc->sc_numcores = BCW_MAX_CORES; - } - } - - DPRINTF(("%s: ChipID=0x%x, ChipRev=0x%x, ChipPkg=0x%x, NumCores=%d\n", - sc->sc_dev.dv_xname, - sc->sc_chip_id, sc->sc_chip_rev, sc->sc_chip_pkg, - sc->sc_numcores)); - - bcw_pc_set_clock(sc, BCW_PCTL_CLK_FAST); - - bcw_phy_connect(sc, 0); - - /* - * Get SPROM values and save them where they belong - */ - bcw_sprom_get(sc); - - /* Identify each core and reset the 802.11 cores */ - for (i = 0; i < sc->sc_numcores; i++) { - if (bcw_change_core(sc, i)) { - printf("%s: Failed change to core %d\n", - sc->sc_dev.dv_xname, i); - continue; - } - - sbval = BCW_READ(sc, BCW_CIR_SBID_HI); - sc->sc_core[i].id = (sbval & 0x00008ff0) >> 4; - sc->sc_core[i].rev = ((sbval & 0x00007000) >> 8 | - (sbval & 0x0000000f)); - - switch (sc->sc_core[i].id) { - case BCW_CORE_COMMON: - sc->sc_core_common = &sc->sc_core[i]; - break; -#if 0 - case BCW_CORE_PCI: - (sc->sc_ca == NULL) - sc->sc_core_bus = &sc->sc_core[i]; - break; - case BCW_CORE_PCMCIA: - if (sc->sc_pa == NULL) - sc->sc_core_bus = &sc->sc_core[i]; - break; -#endif - case BCW_CORE_80211: - sc->sc_core_80211 = &sc->sc_core[i]; - bcw_80211_core_reset(sc, 1); - if (bcw_phy_get(sc)) - return; - if (bcw_radio_get(sc)) - return; - if (bcw_validate_chip_access(sc)) - return; - bcw_radio_off(sc); - bcw_microcode_init_fbf(sc); - break; - case BCW_CORE_NONEXIST: - sc->sc_numcores = i + 1; - break; - default: - /* ignore all other core types */ - break; - } - - sc->sc_core[i].index = i; - - DPRINTF(("%s: core %d is type 0x%x rev %d\n", - sc->sc_dev.dv_xname, sc->sc_core[i].index, - sc->sc_core[i].id, sc->sc_core[i].rev)); - } - - /* turn crystal off */ - bcw_pc_crystal_off(sc); - - /* - * Switch to the 80211 core - */ - bcw_change_core(sc, sc->sc_core_80211->index); - - /* - * Set MAC address - */ - if (!IEEE80211_IS_MULTICAST(sc->sc_sprom.et1macaddr)) - memcpy(ic->ic_myaddr, sc->sc_sprom.et1macaddr, ETHER_ADDR_LEN); - else - memcpy(ic->ic_myaddr, sc->sc_sprom.il0macaddr, ETHER_ADDR_LEN); - printf(", address %s\n", ether_sprintf(ic->ic_myaddr)); - - /* - * Initialize the TSSI to DBM table - * The method is described at - * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table - * but I suspect there's a standard way to do it in the 80211 stuff - */ - - /* - * Allocate DMA-safe memory for ring descriptors. - * The receive and transmit rings are 4k aligned. - */ - bcw_alloc_rx_ring(sc, &sc->sc_rxring, BCW_RX_RING_COUNT); - bcw_alloc_tx_ring(sc, &sc->sc_txring, BCW_TX_RING_COUNT); - - ic->ic_phytype = IEEE80211_T_OFDM; - ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ - ic->ic_state = IEEE80211_S_INIT; - - /* Set device capabilities - keep it simple */ - ic->ic_caps = IEEE80211_C_IBSS; /* IBSS mode supported */ - - /* Set supported rates */ - ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; - ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; - - /* Set supported channels */ - for (i = 1; i <= 14; i++) { - ic->ic_channels[i].ic_freq = - ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); - ic->ic_channels[i].ic_flags = - IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; - } - - /* IBSS channel undefined for now */ - ic->ic_ibss_chan = &ic->ic_channels[0]; - - ifp->if_softc = sc; - ifp->if_init = bcw_init; - ifp->if_ioctl = bcw_ioctl; - ifp->if_start = bcw_start; - ifp->if_watchdog = bcw_watchdog; - ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); - IFQ_SET_READY(&ifp->if_snd); - - /* Attach the interface */ - if_attach(ifp); - ieee80211_ifattach(ifp); - - /* override state transition machine */ - sc->sc_newstate = ic->ic_newstate; - ic->ic_newstate = bcw_newstate; - - ieee80211_media_init(ifp, bcw_media_change, bcw_media_status); - - timeout_set(&sc->sc_timeout, bcw_tick, sc); -} - -/* handle media, and ethernet requests */ -int -bcw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct bcw_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifreq *ifr = (struct ifreq *) data; - struct ifaddr *ifa = (struct ifaddr *)data; - int s, error = 0; - - s = splnet(); - - switch (cmd) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - //bcw_init(ifp); - //arp_ifinit(&sc->bcw_ac, ifa); /* XXX */ - break; -#endif /* INET */ - default: - //bcw_init(ifp); - break; - } - break; - case SIOCSIFFLAGS: - if ((ifp->if_flags & IFF_UP) && - (!(ifp->if_flags & IFF_RUNNING))) - bcw_init(ifp); - else if (ifp->if_flags & IFF_RUNNING) - bcw_stop(ifp, 1); - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - error = (cmd == SIOCADDMULTI) ? - ether_addmulti(ifr, &ic->ic_ac) : - ether_delmulti(ifr, &ic->ic_ac); - - if (error == ENETRESET) - error = 0; - break; - - case SIOCG80211TXPOWER: - /* - * If the hardware radio transmitter switch is off, report a - * tx power of IEEE80211_TXPOWER_MIN to indicate that radio - * transmitter is killed. - */ - break; - - default: - error = ieee80211_ioctl(ifp, cmd, data); - break; - } - - if (error == ENETRESET) { - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == - (IFF_UP | IFF_RUNNING)) - bcw_init(ifp); - error = 0; - } - - splx(s); - return error; -} - -/* - * Start packet transmission on the interface - */ -void -bcw_start(struct ifnet *ifp) -{ -#if 0 - struct malo_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni; - struct mbuf *m; -#endif - - /* if device is not up return directly */ - if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) - return; -} - -/* Watchdog timer handler. */ -void -bcw_watchdog(struct ifnet *ifp) -{ - struct bcw_softc *sc = ifp->if_softc; - - printf("%s: device timeout\n", sc->sc_dev.dv_xname); - ifp->if_oerrors++; - - (void) bcw_init(ifp); - - /* Try to get more packets going. */ - bcw_start(ifp); -} - -void -bcw_set_opmode(struct ifnet *ifp) -{ - struct bcw_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - uint32_t status; - uint16_t val; - - /* TODO */ - - status = BCW_READ(sc, BCW_MMIO_SBF); - /* reset status to infrastructure mode */ - status &= ~(BCW_SBF_AP | BCW_SBF_MONITOR); - status &= ~BCW_SBF_PROMISC; - status |= BCW_SBF_ADHOC; - status |= BCW_SBF_PROMISC; /* XXX */ - - switch (ic->ic_opmode) { - case IEEE80211_M_MONITOR: - status |= BCW_SBF_MONITOR; - status |= BCW_SBF_PROMISC; - break; - case IEEE80211_M_IBSS: - status &= ~BCW_SBF_ADHOC; - break; - case IEEE80211_M_HOSTAP: - status |= BCW_SBF_AP; - break; - case IEEE80211_M_STA: - /* nothing todo here */ - break; - default: - printf("%s: unknown mode in bcw_set_opmode()\n", - sc->sc_dev.dv_xname); - break; - } - if (ifp->if_flags & IFF_PROMISC) - status |= BCW_SBF_PROMISC; - - val = 0x0002; - if (ic->ic_opmode != IEEE80211_M_IBSS && - ic->ic_opmode != IEEE80211_M_HOSTAP) { - if (sc->sc_chip_id == 0x4306 && sc->sc_chip_rev == 3) - val = 0x0064; - else - val = 0x0032; - } - BCW_WRITE16(sc, 0x0612, val); -} - -void -bcw_macfilter_set(struct bcw_softc *sc, uint16_t offset, const uint8_t *mac) -{ - uint16_t data; - - offset |= 0x0020; - BCW_WRITE16(sc, BCW_MMIO_MACFILTER_CONTROL, offset); - - data = mac[0]; - data |= mac[1] << 8; - BCW_WRITE16(sc, BCW_MMIO_MACFILTER_DATA, data); - data = mac[2]; - data |= mac[3] << 8; - BCW_WRITE16(sc, BCW_MMIO_MACFILTER_DATA, data); - data = mac[4]; - data |= mac[5] << 8; - BCW_WRITE16(sc, BCW_MMIO_MACFILTER_DATA, data); -} - -void -bcw_macfilter_clear(struct bcw_softc *sc, uint16_t offset) -{ - const uint8_t zero_addr[ETHER_ADDR_LEN] = { 0 }; - - bcw_macfilter_set(sc, offset, zero_addr); -} - -/* - * Write MAC and BSSID into template RAM - * - * http://bcm-specs.sipsolutions.net/TemplateRam - */ -void -bcw_templateram_set(struct bcw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - uint8_t mac_bssid[ETHER_ADDR_LEN * 2]; - int i; - - bcopy(ic->ic_myaddr, mac_bssid, ETHER_ADDR_LEN); - bcopy(ic->ic_bss->ni_bssid, mac_bssid + ETHER_ADDR_LEN, ETHER_ADDR_LEN); - - /* - * We write our MAC and BSSID at three different addresses in the - * template RAM, in 4 byte blocks. - */ - for (i = 0; i < sizeof(mac_bssid); i += sizeof(uint32_t)) - bcw_ram_write(sc, 0x20 + i, *((int32_t *)(mac_bssid + i))); - for (i = 0; i < sizeof(mac_bssid); i += sizeof(uint32_t)) - bcw_ram_write(sc, 0x78 + i, *((int32_t *)(mac_bssid + i))); - for (i = 0; i < sizeof(mac_bssid); i += sizeof(uint32_t)) - bcw_ram_write(sc, 0x478 + i, *((int32_t *)(mac_bssid + i))); -} - -/* - * Enable MAC on a PHY - * - * http://bcm-specs.sipsolutions.net/EnableMAC - */ -void -bcw_mac_enable(struct bcw_softc *sc) -{ - BCW_WRITE(sc, BCW_MMIO_SBF, - BCW_READ(sc, BCW_MMIO_SBF) | BCW_SBF_MAC_ENABLED); - BCW_WRITE(sc, BCW_MMIO_GIR, BCW_INTR_READY); - BCW_READ(sc, BCW_MMIO_SBF); /* dummy read */ - BCW_READ(sc, BCW_MMIO_GIR); /* dummy read */ - bcw_pc_saving_ctl_bits(sc, -1, -1); -} - -/* - * Disable MAC on a PHY - * - * http://bcm-specs.sipsolutions.net/SuspendMAC - */ -void -bcw_mac_disable(struct bcw_softc *sc) -{ - int i; - uint32_t tmp; - - bcw_pc_saving_ctl_bits(sc, -1, -1); - BCW_WRITE(sc, BCW_MMIO_SBF, - BCW_READ(sc, BCW_MMIO_SBF) & ~BCW_SBF_MAC_ENABLED); - BCW_READ(sc, BCW_MMIO_GIR); /* dummy read */ - for (i = 10000; i; i--) { - tmp = BCW_READ(sc, BCW_MMIO_GIR); - if (tmp & BCW_INTR_READY) - return; - delay(1); - } - DPRINTF(("%s: MAC disable failed!\n", sc->sc_dev.dv_xname)); -} - -uint32_t -bcw_intr_enable(struct bcw_softc *sc, uint32_t mask) -{ - uint32_t old_mask; - - old_mask = BCW_READ(sc, BCW_MMIO_GIM); - BCW_WRITE(sc, BCW_MMIO_GIM, old_mask | mask); - - DPRINTF(("%s: interrupts enabled\n", sc->sc_dev.dv_xname)); - - return (old_mask); -} - -uint32_t -bcw_intr_disable(struct bcw_softc *sc, uint32_t mask) -{ - uint32_t old_mask; - - old_mask = BCW_READ(sc, BCW_MMIO_GIM); - BCW_WRITE(sc, BCW_MMIO_GIM, old_mask & ~mask); - - DPRINTF(("%s: interrupts disabled\n", sc->sc_dev.dv_xname)); - - return (old_mask); -} - -int -bcw_intr(void *arg) -{ - struct bcw_softc *sc = arg; - uint32_t reason; - uint32_t dma_reason[6]; - - if (!(sc->sc_flags & BCW_FLAGS_INITIALIZED)) - return (0); - - reason = BCW_READ(sc, BCW_MMIO_GIR); - if (reason == 0xffffffff) - return (0); - - reason &= BCW_READ(sc, BCW_MMIO_GIM); - if (!reason) - return (0); - - dma_reason[0] = BCW_READ(sc, BCW_MMIO_DMA0_REASON) & 0x0001dc00; - dma_reason[1] = BCW_READ(sc, BCW_MMIO_DMA1_REASON) & 0x0000dc00; - dma_reason[2] = BCW_READ(sc, BCW_MMIO_DMA2_REASON) & 0x0000dc00; - dma_reason[3] = BCW_READ(sc, BCW_MMIO_DMA3_REASON) & 0x0001dc00; - dma_reason[4] = BCW_READ(sc, BCW_MMIO_DMA4_REASON) & 0x0000dc00; - dma_reason[5] = BCW_READ(sc, BCW_MMIO_DMA5_REASON) & 0x0000dc00; - - /* ACK interrupt */ - BCW_WRITE(sc, BCW_MMIO_GIR, reason); - BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[0]); - BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[1]); - BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[2]); - BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[3]); - BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[4]); - BCW_WRITE(sc, BCW_MMIO_GIM, dma_reason[5]); - - bcw_intr_disable(sc, BCW_INTR_ALL); - - if (reason & BCW_INTR_PS) { - printf("handle PS intr\n"); - bcw_pc_saving_ctl_bits(sc, -1, -1); - } else - printf("INTR ALERT!!!\n"); - - bcw_intr_enable(sc, BCW_INTR_INITIAL); - - return (1); -} - -/* - * Receive interrupt handler - */ -void -bcw_rxintr(struct bcw_softc *sc) -{ -#if 0 - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; -#endif -} - -/* - * Transmit interrupt handler - */ -void -bcw_txintr(struct bcw_softc *sc) -{ -#if 0 - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; -#endif - -} - -/* - * Initialize the interface - * - * http://bcm-specs.sipsolutions.net/DeviceUp - */ -int -bcw_init(struct ifnet *ifp) -{ - struct bcw_softc *sc = ifp->if_softc; - //struct ieee80211com *ic = &sc->sc_ic; - int i, error; - uint32_t coremask = 0; - - /* initialize PHY values */ - sc->sc_phy_antenna_diversity = 0xffff; - memset(sc->sc_phy_minlowsig, 0xff, sizeof(sc->sc_phy_minlowsig)); - memset(sc->sc_phy_minlowsigpos, 0, sizeof(sc->sc_phy_minlowsigpos)); - sc->sc_phy_calibrated = 0; - sc->sc_phy_is_locked = 0; - sc->sc_phy_lopairs = malloc(sizeof(struct bcw_lopair) * BCW_LO_COUNT, - M_DEVBUF, M_NOWAIT); - if (sc->sc_phy_lopairs) - memset(sc->sc_phy_lopairs, 0, sizeof(struct bcw_lopair) * - BCW_LO_COUNT); - memset(sc->sc_phy_loopback_gain, 0, sizeof(sc->sc_phy_loopback_gain)); - - /* initialize Radio values */ - sc->sc_radio_baseband_atten = - bcw_radio_default_baseband_atten(sc); - sc->sc_radio_radio_atten = - bcw_radio_default_radio_atten(sc); - sc->sc_radio_txctl1 = bcw_radio_default_txctl1(sc); - sc->sc_radio_txctl2 = 0xffff; - sc->sc_radio_txpwr_offset = 0; - sc->sc_radio_nrssislope = 0; - for (i = 0; i < BCW_ARRAY_SIZE(sc->sc_radio_nrssi); i++) - sc->sc_radio_nrssi[i] = -1000; - for (i = 0; i < BCW_ARRAY_SIZE(sc->sc_radio_nrssi_lt); i++) - sc->sc_radio_nrssi_lt[i] = i; - sc->sc_radio_lofcal = 0xffff; - sc->sc_radio_initval = 0xffff; - sc->sc_radio_aci_enable = 0; - sc->sc_radio_aci_wlan_automatic = 0; - sc->sc_radio_aci_hw_rssi = 0; - - bcw_change_core(sc, sc->sc_core_80211->index); - - bcw_pc_crystal_on(sc); - - bcw_pc_init(sc); - - bcw_pc_set_clock(sc, BCW_PCTL_CLK_FAST); - - coremask |= (1 << 1); - bcw_iocore_enable(sc, coremask); - - bcw_80211_core_reset(sc, 1); - - /* initialize 80211 core */ - if ((error = bcw_80211_core_init(sc, 1))) - return (error); - - bcw_pc_set_clock(sc, BCW_PCTL_CLK_DYNAMIC); - - bcw_mac_enable(sc); - bcw_intr_enable(sc, BCW_INTR_INITIAL); - bcw_pc_set_clock(sc, BCW_PCTL_CLK_DYNAMIC); - - /* start timer */ - timeout_add(&sc->sc_timeout, hz); - - /* mark as running, and no outputs active */ - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; - - sc->sc_flags |= BCW_FLAGS_INITIALIZED; - - return (0); -} - -/* - * Add a receive buffer to the indicated descriptor - */ -int -bcw_add_rxbuf(struct bcw_softc *sc, int idx) -{ - return (0); -} - -/* - * Drain the receive queue - */ -void -bcw_rxdrain(struct bcw_softc *sc) -{ - -} - -/* - * Stop transmission on the interface - * - * http://bcm-specs.sipsolutions.net/DeviceDown - */ -void -bcw_stop(struct ifnet *ifp, int disable) -{ - struct bcw_softc *sc = ifp->if_softc; - - /* disable all interrupts */ - bcw_intr_disable(sc, BCW_INTR_ALL); - - /* disable the 80211 core */ - bcw_80211_core_disable(sc); - - /* turn off crystal */ - bcw_pc_crystal_off(sc); - - /* Stop the 1 second timer */ - timeout_del(&sc->sc_timeout); - - /* Mark the interface down and cancel the watchdog timer. */ - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - ifp->if_timer = 0; - - /* Disable interrupts. */ - BCW_WRITE(sc, BCW_MMIO_DMA0_INT_MASK, 0); - sc->sc_intmask = 0; - delay(10); - - /* Stop the DMA */ - BCW_WRITE(sc, BCW_DMA_RXCONTROL(0), 0); - BCW_WRITE(sc, BCW_DMA_TXCONTROL(0), 0); - delay(10); - - /* drain receive queue */ - if (disable) - bcw_rxdrain(sc); -} - -int -bcw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) -{ - return (0); -} - -int -bcw_media_change(struct ifnet *ifp) -{ - int error; - - error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return error; - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) - bcw_init(ifp); - - return (0); -} - - void -bcw_media_status(struct ifnet *ifp, struct ifmediareq *imr) -{ - struct bcw_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - int rate; - - imr->ifm_status = IFM_AVALID; - imr->ifm_active = IFM_IEEE80211; - if (ic->ic_state == IEEE80211_S_RUN) - imr->ifm_status |= IFM_ACTIVE; - - /* - * XXX Read current transmission rate from the adapter. - */ - //val = CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE); - /* convert PLCP signal to 802.11 rate */ - //rate = bcw_rate(val); - rate = 0; - - imr->ifm_active |= ieee80211_rate2media(ic, rate, ic->ic_curmode); - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - break; - case IEEE80211_M_IBSS: - imr->ifm_active |= IFM_IEEE80211_ADHOC; - break; - case IEEE80211_M_MONITOR: - imr->ifm_active |= IFM_IEEE80211_MONITOR; - break; - case IEEE80211_M_AHDEMO: - case IEEE80211_M_HOSTAP: - /* should not get there */ - break; - } -} - -/* - * One second timer, checks link status - */ -void -bcw_tick(void *v) -{ -#if 0 - struct bcw_softc *sc = v; - - /* http://bcm-specs.sipsolutions.net/PeriodicTasks */ - timeout_add(&sc->bcw_timeout, hz); -#endif -} - -/* - * Validate Chip Access - * - * This function ensures that the 80211 core is setup correctly and - * and is read for use. - * - * http://bcm-specs.sipsolutions.net/ValidateChipAccess - */ -int -bcw_validate_chip_access(struct bcw_softc *sc) -{ - uint32_t save, val; - - /* test 1 (this test is just for the 80211 core) */ - if (sc->sc_core[sc->sc_currentcore].id != BCW_CORE_80211) - goto fail; - - /* save value */ - save = bcw_shm_read32(sc, BCW_SHM_SHARED, 0); - - /* test 2 */ - bcw_shm_write32(sc, BCW_SHM_SHARED, 0, 0xaa5555aa); - val = bcw_shm_read32(sc, BCW_SHM_SHARED, 0); - if (val != 0xaa5555aa) - goto fail; - - /* test 3 */ - bcw_shm_write32(sc, BCW_SHM_SHARED, 0, 0x55aaaa55); - val = bcw_shm_read32(sc, BCW_SHM_SHARED, 0); - if (val != 0x55aaaa55) - goto fail; - - /* restore value */ - bcw_shm_write32(sc, BCW_SHM_SHARED, 0, save); - - if (sc->sc_core_80211->rev >= 3) { - /* test 4 */ - BCW_WRITE16(sc, 0x18c, 0xaaaa); - BCW_WRITE(sc, 0x18c, 0xccccbbbb); - val = BCW_READ16(sc, 0x604); - if (val != 0xbbbb) - goto fail; - /* test 5 */ - val = BCW_READ16(sc, 0x606); - if (val != 0xcccc) - goto fail; - BCW_WRITE(sc, 0x18c, 0); - } - - /* test 6 */ - val = BCW_READ(sc, BCW_MMIO_SBF); - if ((val | 0x80000000) != 0x80000400) - goto fail; - - /* test 7 */ - val = BCW_READ(sc, BCW_MMIO_GIR); - if (val != 0) - goto fail; - - /* test 8 */ - if (sc->sc_phy_type > BCW_PHY_TYPEG) - goto fail; - - return (0); - -fail: - printf("%s: Chip Access Validation failed!\n", sc->sc_dev.dv_xname); - return (1); -} - -int -bcw_detach(void *arg) -{ - struct bcw_softc *sc = arg; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - - timeout_del(&sc->sc_scan_to); - - bcw_stop(ifp, 1); - ieee80211_ifdetach(ifp); - if_detach(ifp); - bcw_free_rx_ring(sc, &sc->sc_rxring); - bcw_free_tx_ring(sc, &sc->sc_txring); - - /* power off cardbus socket */ - if (sc->sc_disable) - sc->sc_disable(sc); - - return (0); -} - -int -bcw_alloc_rx_ring(struct bcw_softc *sc, struct bcw_rx_ring *ring, int count) -{ - struct bcw_desc *desc; - struct bcw_rx_data *data; - int i, nsegs, error; - - ring->count = count; - ring->cur = ring->next = 0; - - error = bus_dmamap_create(sc->sc_dmat, - count * sizeof(struct bcw_desc), 1, - count * sizeof(struct bcw_desc), 0, - BUS_DMA_NOWAIT, &ring->map); - if (error != 0) { - printf("%s: could not create desc DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - - error = bus_dmamem_alloc(sc->sc_dmat, - count * sizeof(struct bcw_desc), - PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - printf("%s: could not allocate DMA memory\n", - sc->sc_dev.dv_xname); - goto fail; - } - - error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs, - count * sizeof(struct bcw_desc), (caddr_t *)&ring->desc, - BUS_DMA_NOWAIT); - if (error != 0) { - printf("%s: could not map desc DMA memory\n", - sc->sc_dev.dv_xname); - goto fail; - } - - error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc, - count * sizeof(struct bcw_desc), NULL, BUS_DMA_NOWAIT); - if (error != 0) { - printf("%s: could not load desc DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - - bzero(ring->desc, count * sizeof(struct bcw_desc)); - ring->physaddr = ring->map->dm_segs->ds_addr; - - ring->data = malloc(count * sizeof (struct bcw_rx_data), M_DEVBUF, - M_NOWAIT); - if (ring->data == NULL) { - printf("%s: could not allocate soft data\n", - sc->sc_dev.dv_xname); - error = ENOMEM; - goto fail; - } - - BCW_WRITE(sc, BCW_DMA_RXADDR, ring->physaddr + 0x40000000); - - /* - * Pre-allocate Rx buffers and populate Rx ring. - */ - bzero(ring->data, count * sizeof (struct bcw_rx_data)); - for (i = 0; i < count; i++) { - desc = &ring->desc[i]; - data = &ring->data[i]; - - error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, - 0, BUS_DMA_NOWAIT, &data->map); - if (error != 0) { - printf("%s: could not create DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - - MGETHDR(data->m, M_DONTWAIT, MT_DATA); - if (data->m == NULL) { - printf("%s: could not allocate rx mbuf\n", - sc->sc_dev.dv_xname); - error = ENOMEM; - goto fail; - } - - MCLGET(data->m, M_DONTWAIT); - if (!(data->m->m_flags & M_EXT)) { - printf("%s: could not allocate rx mbuf cluster\n", - sc->sc_dev.dv_xname); - error = ENOMEM; - goto fail; - } - - error = bus_dmamap_load(sc->sc_dmat, data->map, - mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT); - if (error != 0) { - printf("%s: could not load rx buf DMA map", - sc->sc_dev.dv_xname); - goto fail; - } - - desc->addr = htole32(data->map->dm_segs->ds_addr); - - if (i != (count - 1)) - desc->ctrl = htole32(BCW_RXBUF_LEN); - else - desc->ctrl = htole32(BCW_RXBUF_LEN | CTRL_EOT); - } - - bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize, - BUS_DMASYNC_PREWRITE); - - return (0); - -fail: bcw_free_rx_ring(sc, ring); - return (error); -} - -void -bcw_reset_rx_ring(struct bcw_softc *sc, struct bcw_rx_ring *ring) -{ - bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize, - BUS_DMASYNC_PREWRITE); - - ring->cur = ring->next = 0; -} - -void -bcw_free_rx_ring(struct bcw_softc *sc, struct bcw_rx_ring *ring) -{ - struct bcw_rx_data *data; - int i; - - if (ring->desc != NULL) { - bus_dmamap_sync(sc->sc_dmat, ring->map, 0, - ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, ring->map); - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc, - ring->count * sizeof(struct bcw_desc)); - bus_dmamem_free(sc->sc_dmat, &ring->seg, 1); - } - - if (ring->data != NULL) { - for (i = 0; i < ring->count; i++) { - data = &ring->data[i]; - - if (data->m != NULL) { - bus_dmamap_sync(sc->sc_dmat, data->map, 0, - data->map->dm_mapsize, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, data->map); - m_freem(data->m); - } - - if (data->map != NULL) - bus_dmamap_destroy(sc->sc_dmat, data->map); - } - free(ring->data, M_DEVBUF); - } -} - -int -bcw_alloc_tx_ring(struct bcw_softc *sc, struct bcw_tx_ring *ring, - int count) -{ - int i, nsegs, error; - - ring->count = count; - ring->queued = 0; - ring->cur = ring->next = ring->stat = 0; - - error = bus_dmamap_create(sc->sc_dmat, - count * sizeof(struct bcw_desc), 1, - count * sizeof(struct bcw_desc), 0, BUS_DMA_NOWAIT, &ring->map); - if (error != 0) { - printf("%s: could not create desc DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - - error = bus_dmamem_alloc(sc->sc_dmat, - count * sizeof(struct bcw_desc), - PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - printf("%s: could not allocate DMA memory\n", - sc->sc_dev.dv_xname); - goto fail; - } - - error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs, - count * sizeof(struct bcw_desc), (caddr_t *)&ring->desc, - BUS_DMA_NOWAIT); - if (error != 0) { - printf("%s: could not map desc DMA memory\n", - sc->sc_dev.dv_xname); - goto fail; - } - - error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc, - count * sizeof(struct bcw_desc), NULL, BUS_DMA_NOWAIT); - if (error != 0) { - printf("%s: could not load desc DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - - memset(ring->desc, 0, count * sizeof(struct bcw_desc)); - ring->physaddr = ring->map->dm_segs->ds_addr; - - /* MAGIC */ - BCW_WRITE(sc, BCW_DMA_TXADDR, ring->physaddr + 0x40000000); - - ring->data = malloc(count * sizeof(struct bcw_tx_data), M_DEVBUF, - M_NOWAIT); - if (ring->data == NULL) { - printf("%s: could not allocate soft data\n", - sc->sc_dev.dv_xname); - error = ENOMEM; - goto fail; - } - - memset(ring->data, 0, count * sizeof(struct bcw_tx_data)); - for (i = 0; i < count; i++) { - error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, - BCW_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT, - &ring->data[i].map); - if (error != 0) { - printf("%s: could not create DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - } - - return (0); - -fail: bcw_free_tx_ring(sc, ring); - return (error); -} - -void -bcw_reset_tx_ring(struct bcw_softc *sc, struct bcw_tx_ring *ring) -{ - struct bcw_desc *desc; - struct bcw_tx_data *data; - int i; - - for (i = 0; i < ring->count; i++) { - desc = &ring->desc[i]; - data = &ring->data[i]; - - if (data->m != NULL) { - bus_dmamap_sync(sc->sc_dmat, data->map, 0, - data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, data->map); - m_freem(data->m); - data->m = NULL; - } - - /* - * The node has already been freed at that point so don't call - * ieee80211_release_node() here. - */ - data->ni = NULL; - } - - bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize, - BUS_DMASYNC_PREWRITE); - - ring->queued = 0; - ring->cur = ring->next = ring->stat = 0; -} - -void -bcw_free_tx_ring(struct bcw_softc *sc, struct bcw_tx_ring *ring) -{ - struct bcw_tx_data *data; - int i; - - if (ring->desc != NULL) { - bus_dmamap_sync(sc->sc_dmat, ring->map, 0, - ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, ring->map); - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc, - ring->count * sizeof(struct bcw_desc)); - bus_dmamem_free(sc->sc_dmat, &ring->seg, 1); - } - - if (ring->data != NULL) { - for (i = 0; i < ring->count; i++) { - data = &ring->data[i]; - - if (data->m != NULL) { - bus_dmamap_sync(sc->sc_dmat, data->map, 0, - data->map->dm_mapsize, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, data->map); - m_freem(data->m); - } - - /* - * The node has already been freed at that point so - * don't call ieee80211_release_node() here. - */ - data->ni = NULL; - - if (data->map != NULL) - bus_dmamap_destroy(sc->sc_dmat, data->map); - } - free(ring->data, M_DEVBUF); - } -} - -int -bcw_change_core(struct bcw_softc *sc, int changeto) -{ - int i; - uint32_t sbval; - - (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0, BCW_CORE_SELECT(changeto)); - - /* loop to see if the selected core shows up */ - for (i = 0; i < 10; i++) { - sbval = (sc->sc_conf_read)(sc, BCW_ADDR_SPACE0); - if (sbval == BCW_CORE_SELECT(changeto)) - break; - delay(10); - } - if (i == 10) { - DPRINTF(("%s: can not change to core %d!\n", - sc->sc_dev.dv_xname, changeto)); - return (1); - } - - /* core changed */ - sc->sc_lastcore = sc->sc_currentcore; - sc->sc_currentcore = changeto; - - return (0); -} - -/* - * Enable current core - */ -int -bcw_core_enable(struct bcw_softc *sc, uint32_t core_flags) -{ - uint32_t sbtmstatelow; - uint32_t sbtmstatehigh; - uint32_t sbimstate; - int error; - - if ((error = bcw_core_disable(sc, core_flags))) - return (error); - - sbtmstatelow = - BCW_SBTMSTATELOW_CLOCK | - BCW_SBTMSTATELOW_RESET | - BCW_SBTMSTATELOW_FGCLOCK | - core_flags; - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, sbtmstatelow); - delay(1); - - sbtmstatehigh = BCW_READ(sc, BCW_CIR_SBTMSTATEHIGH); - if (sbtmstatehigh & BCW_SBTMSTATEHIGH_SERROR) { - sbtmstatehigh = 0; - BCW_WRITE(sc, BCW_CIR_SBTMSTATEHIGH, sbtmstatehigh); - } - - sbimstate = BCW_READ(sc, BCW_CIR_SBIMSTATE); - if (sbimstate & (BCW_SBIMSTATE_IB_ERROR | BCW_SBIMSTATE_TIMEOUT)) { - sbimstate &= ~(BCW_SBIMSTATE_IB_ERROR | BCW_SBIMSTATE_TIMEOUT); - BCW_WRITE(sc, BCW_CIR_SBIMSTATE, sbimstate); - } - - sbtmstatelow = - BCW_SBTMSTATELOW_CLOCK | - BCW_SBTMSTATELOW_FGCLOCK | - core_flags; - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, sbtmstatelow); - delay(1); - - sbtmstatelow = BCW_SBTMSTATELOW_CLOCK | core_flags; - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, sbtmstatelow); - delay(1); - - return (0); -} - -/* - * Disable current core - */ -int -bcw_core_disable(struct bcw_softc *sc, uint32_t core_flags) -{ - uint32_t sbtmstatelow; - uint32_t sbtmstatehigh; - int i; - - /* fetch sbtmstatelow from core information registers */ - sbtmstatelow = BCW_READ(sc, BCW_CIR_SBTMSTATELOW); - - /* core is already in reset */ - if (sbtmstatelow & BCW_SBTMSTATELOW_RESET) - goto out; - - if (sbtmstatelow & BCW_SBTMSTATELOW_CLOCK) { - sbtmstatelow = - BCW_SBTMSTATELOW_CLOCK | - BCW_SBTMSTATELOW_REJECT; - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, sbtmstatelow); - - for (i = 0; i < 1000; i++) { - sbtmstatelow = BCW_READ(sc, BCW_CIR_SBTMSTATELOW); - if (sbtmstatelow & BCW_SBTMSTATELOW_REJECT) { - i = -1; - break; - } - delay(10); - } - if (i != -1) { - DPRINTF(("%s: can not disable core, REJECT timeout!\n", - sc->sc_dev.dv_xname)); - return (EBUSY); - } - - for (i = 0; i < 1000; i++) { - sbtmstatehigh = BCW_READ(sc, BCW_CIR_SBTMSTATEHIGH); - if (!(sbtmstatehigh & BCW_SBTMSTATEHIGH_BUSY)) { - i = -1; - break; - } - delay(10); - } - if (i != -1) { - DPRINTF(("%s: can not disable, core, BUSY timeout!\n", - sc->sc_dev.dv_xname)); - return (EBUSY); - } - - sbtmstatelow = - BCW_SBTMSTATELOW_FGCLOCK | - BCW_SBTMSTATELOW_REJECT | - BCW_SBTMSTATELOW_RESET | - BCW_SBTMSTATELOW_CLOCK | - core_flags; - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, sbtmstatelow); - delay(10); - } - - sbtmstatelow = - BCW_SBTMSTATELOW_RESET | - BCW_SBTMSTATELOW_REJECT | - core_flags; - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, sbtmstatelow); - -out: - /* XXX sc_current_core_enabled = 0 */ - - return (0); -} - -/* - * Reset the 80211 core - * - * http://bcm-specs.sipsolutions.net/80211CoreReset - */ -void -bcw_80211_core_reset(struct bcw_softc *sc, int connect_phy) -{ - uint32_t flags = 0x00040000; - - if (connect_phy) - flags |= 0x20000000; - bcw_phy_connect(sc, connect_phy); - bcw_core_enable(sc, flags); - BCW_WRITE16(sc, 0x03e6, 0); - BCW_WRITE(sc, BCW_MMIO_SBF, BCW_READ(sc, BCW_MMIO_SBF) | - BCW_SBF_400_MAGIC); -} - -/* - * Disable the 80211 core - * - * http://bcm-specs.sipsolutions.net/80211CoreDisable - */ -void -bcw_80211_core_disable(struct bcw_softc *sc) -{ - bcw_radio_off(sc); - BCW_WRITE16(sc, 0x03e6, 0x00f4); - bcw_core_disable(sc, 0); -} - -int -bcw_iocore_enable(struct bcw_softc *sc, uint32_t coremask) -{ - uint32_t val; - uint32_t bp_flag_nr; - int error; - - val = BCW_READ(sc, BCW_CIR_SBTPSFLAG); - bp_flag_nr = val & SBTPS_BACKPLANEFLAGMASK; - - if ((error = bcw_change_core(sc, 2))) - return (error); - - if (sc->sc_core[sc->sc_currentcore].rev < 6 && - sc->sc_core[sc->sc_currentcore].id == BCW_CORE_PCI) { - val = BCW_READ(sc, BCW_CIR_SBINTVEC); - val |= (1 << bp_flag_nr); - BCW_WRITE(sc, BCW_CIR_SBINTVEC, val); - } else { - val = (sc->sc_conf_read)(sc, BCW_PCICFG_ICR); - val |= coremask << 8; - (sc->sc_conf_write)(sc, BCW_PCICFG_ICR, val); - } - - if (sc->sc_core[sc->sc_currentcore].id == BCW_CORE_PCI) { - val = BCW_READ(sc, BCW_PCICORE_SBTOPCI2); - val |= BCW_SBTOPCI2_PREFETCH | BCW_SBTOPCI2_BURST; - BCW_WRITE(sc, BCW_PCICORE_SBTOPCI2, val); - - if (sc->sc_core[sc->sc_currentcore].rev < 5) { - val = BCW_READ(sc, BCW_CIR_SBIMCONFIGLOW); - val |= (2 << BCW_SBIMCONFIGLOW_STS) & - BCW_SBIMCONFIGLOW_STM; - val |= (3 << BCW_SBIMCONFIGLOW_STS) & - BCW_SBIMCONFIGLOW_STM; - BCW_WRITE(sc, BCW_CIR_SBIMCONFIGLOW, val); - /* TODO commit PCI settings */ - } else if (sc->sc_core[sc->sc_currentcore].rev >= 11) { - val = BCW_READ(sc, BCW_PCICORE_SBTOPCI2); - val |= BCW_SBTOPCI2_MEMREAD_MULTI; - BCW_WRITE(sc, BCW_PCICORE_SBTOPCI2, val); - } - } - - if ((error = bcw_change_core(sc, sc->sc_lastcore))) - return (error); - - return (0); -} - -int -bcw_get_firmware(const char *name, const uint8_t *ucode, size_t size_ucode, - size_t *size, size_t *offset) -{ - int i, nfiles, off = 0, ret = 1; - struct fwheader *h; - - if ((h = malloc(sizeof(struct fwheader), M_DEVBUF, M_NOWAIT)) == NULL) - return (ret); - - /* get number of firmware files */ - bcopy(ucode, &nfiles, sizeof(nfiles)); - nfiles = ntohl(nfiles); - off += sizeof(nfiles); - - /* parse header and search the firmware */ - for (i = 0; i < nfiles && off < size_ucode; i++) { - bzero(h, sizeof(struct fwheader)); - bcopy(ucode + off, h, sizeof(struct fwheader)); - off += sizeof(struct fwheader); - - if (strcmp(name, h->filename) == 0) { - ret = 0; - *size = ntohl(h->filesize); - *offset = ntohl(h->fileoffset); - break; - } - } - - free(h, M_DEVBUF); - - return (ret); -} - -int -bcw_load_firmware(struct bcw_softc *sc) -{ - int rev = sc->sc_core[sc->sc_currentcore].rev; - int error, len, i; - uint32_t *data; - uint8_t *ucode; - size_t size_ucode, size_micro, size_pcm, off_micro, off_pcm; - char *name = "bcw-bcm43xx"; - char filename[64]; - - /* load firmware */ - if ((error = loadfirmware(name, &ucode, &size_ucode)) != 0) { - printf("%s: error %d, could not read microcode %s!\n", - sc->sc_dev.dv_xname, error, name); - return (EIO); - } - DPRINTF(("%s: successfully read %s\n", sc->sc_dev.dv_xname, name)); - - /* get microcode file offset */ - snprintf(filename, sizeof(filename), "bcm43xx_microcode%d.fw", - rev >= 5 ? 5 : rev); - - if (bcw_get_firmware(filename, ucode, size_ucode, &size_micro, - &off_micro) != 0) { - printf("%s: get offset for firmware file %s failed!\n", - sc->sc_dev.dv_xname, filename); - goto fail; - } - - /* get pcm file offset */ - snprintf(filename, sizeof(filename), "bcm43xx_pcm%d.fw", - rev < 5 ? 4 : 5); - - if (bcw_get_firmware(filename, ucode, size_ucode, &size_pcm, - &off_pcm) != 0) { - printf("%s: get offset for firmware file %s failed!\n", - sc->sc_dev.dv_xname, filename); - goto fail; - } - - /* upload microcode */ - data = (uint32_t *)(ucode + off_micro); - len = size_micro / sizeof(uint32_t); - bcw_shm_ctl_word(sc, BCW_SHM_UCODE, 0); - for (i = 0; i < len; i++) { - BCW_WRITE(sc, BCW_MMIO_SHM_DATA, betoh32(data[i])); - delay(10); - } - DPRINTF(("%s: uploaded microcode\n", sc->sc_dev.dv_xname)); - - /* upload pcm */ - data = (uint32_t *)(ucode + off_pcm); - len = size_pcm / sizeof(uint32_t); - bcw_shm_ctl_word(sc, BCW_SHM_PCM, 0x01ea); - BCW_WRITE(sc, BCW_MMIO_SHM_DATA, 0x00004000); - bcw_shm_ctl_word(sc, BCW_SHM_PCM, 0x01eb); - for (i = 0; i < len; i++) { - BCW_WRITE(sc, BCW_MMIO_SHM_DATA, betoh32(data[i])); - delay(10); - } - DPRINTF(("%s: uploaded pcm\n", sc->sc_dev.dv_xname)); - - free(ucode, M_DEVBUF); - - return (0); - -fail: free(ucode, M_DEVBUF); - return (EIO); -} - -int -bcw_write_initvals(struct bcw_softc *sc, const struct bcw_initval *data, - const unsigned int len) -{ - int i; - uint16_t offset, size; - uint32_t value; - - for (i = 0; i < len; i++) { - offset = betoh16(data[i].offset); - size = betoh16(data[i].size); - value = betoh32(data[i].value); - - if (offset >= 0x1000) - goto bad_format; - if (size == 2) { - if (value & 0xffff0000) - goto bad_format; - BCW_WRITE16(sc, offset, (uint16_t)value); - } else if (size == 4) - BCW_WRITE(sc, offset, value); - else - goto bad_format; - } - - return (0); - -bad_format: - printf("%s: initvals file-format error!\n", sc->sc_dev.dv_xname); - return (EIO); -} - -int -bcw_load_initvals(struct bcw_softc *sc) -{ - int rev = sc->sc_core[sc->sc_currentcore].rev; - int error, nr; - uint32_t val; - uint8_t *ucode; - size_t size_ucode, size_ival0, size_ival1, off_ival0, off_ival1; - char *name = "bcw-bcm43xx"; - char filename[64]; - - /* load firmware */ - if ((error = loadfirmware(name, &ucode, &size_ucode)) != 0) { - printf("%s: error %d, could not read microcode %s!\n", - sc->sc_dev.dv_xname, error, name); - return (EIO); - } - DPRINTF(("%s: successfully read %s\n", sc->sc_dev.dv_xname, name)); - - /* get initval0 file offset */ - if (rev == 2 || rev == 4) { - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - nr = 3; - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: - nr = 1; - break; - default: - printf("%s: no initvals available!\n", - sc->sc_dev.dv_xname); - goto fail; - } - } else if (rev >= 5) { - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - nr = 7; - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: - nr = 5; - break; - default: - printf("%s: no initvals available!\n", - sc->sc_dev.dv_xname); - goto fail; - } - } else { - printf("%s: no initvals available!\n", sc->sc_dev.dv_xname); - goto fail; - } - - snprintf(filename, sizeof(filename), "bcm43xx_initval%02d.fw", nr); - - if (bcw_get_firmware(filename, ucode, size_ucode, &size_ival0, - &off_ival0) != 0) { - printf("%s: get offset for initval0 file %s failed\n", - sc->sc_dev.dv_xname, filename); - goto fail; - } - - /* get initval1 file offset */ - if (rev >= 5) { - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - val = BCW_READ(sc, BCW_SBTMSTATEHI); - if (val & 0x00010000) - nr = 9; - else - nr = 10; - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: - nr = 6; - break; - default: - printf("%s: no initvals available!\n", - sc->sc_dev.dv_xname); - goto fail; - } - - snprintf(filename, sizeof(filename), "bcm43xx_initval%02d.fw", - nr); - - if (bcw_get_firmware(filename, ucode, size_ucode, &size_ival1, - &off_ival1) != 0) { - printf("%s: get offset for initval1 file %s failed\n", - sc->sc_dev.dv_xname, filename); - goto fail; - } - } - - /* upload initval0 */ - if (bcw_write_initvals(sc, (struct bcw_initval *)(ucode + off_ival0), - size_ival0 / sizeof(struct bcw_initval))) - goto fail; - DPRINTF(("%s: uploaded initval0\n", sc->sc_dev.dv_xname)); - - /* upload initval1 */ - if (off_ival1 != 0) { - if (bcw_write_initvals(sc, - (struct bcw_initval *)(ucode + off_ival1), - size_ival1 / sizeof(struct bcw_initval))) - goto fail; - DPRINTF(("%s: uploaded initval1\n", sc->sc_dev.dv_xname)); - } - - free(ucode, M_DEVBUF); - - return (0); - -fail: free(ucode, M_DEVBUF); - return (EIO); -} - -void -bcw_leds_switch_all(struct bcw_softc *sc, int on) -{ - struct bcw_led *led; - uint16_t ledctl; - int i, bit_on; - - ledctl = BCW_READ16(sc, BCW_MMIO_GPIO_CONTROL); - - for (i = 0; i < BCW_NR_LEDS; i++) { - led = &(sc->leds[i]); - if (led->behaviour == BCW_LED_INACTIVE) - continue; - if (on) - bit_on = led->activelow ? 0 : 1; - else - bit_on = led->activelow ? 0 : 1; - if (bit_on) - ledctl |= (1 << i); - else - ledctl &= ~(1 << i); - } - - BCW_WRITE16(sc, BCW_MMIO_GPIO_CONTROL, ledctl); -} - -int -bcw_gpio_init(struct bcw_softc *sc) -{ - uint32_t mask, set; - int error = 0; - - BCW_WRITE(sc, BCW_MMIO_SBF, BCW_READ(sc, BCW_MMIO_SBF) & 0xffff3fff); - - bcw_leds_switch_all(sc, 0); - - BCW_WRITE16(sc, BCW_MMIO_GPIO_MASK, - BCW_READ16(sc, BCW_MMIO_GPIO_MASK) | 0x000f); - - mask = 0x0000001f; - set = 0x0000000f; - - if (sc->sc_chip_id == 0x4301) { - mask |= 0x0060; - set |= 0x0060; - } - if (0) { /* XXX conditional unknown */ - BCW_WRITE16(sc, BCW_MMIO_GPIO_MASK, - BCW_READ16(sc, BCW_MMIO_GPIO_MASK) | 0x0100); - mask |= 0x0180; - set |= 0x0180; - } - if (sc->sc_sprom.boardflags & BCW_BF_PACTRL) { - BCW_WRITE16(sc, BCW_MMIO_GPIO_MASK, - BCW_READ16(sc, BCW_MMIO_GPIO_MASK) | 0x0200); - mask |= 0x0200; - set |= 0x0200; - } - if (sc->sc_chip_rev >= 2) - mask |= 0x0010; /* XXX this is redundant */ - - /* - * TODO bcw_change_core_to_gpio() - * - * Where to find the GPIO register depends on the chipset. - * If it has a ChipCommon, its register at offset 0x6c is the GPIO - * control register. Otherwise the register at offset 0x6c in the - * PCI core is the GPIO control register. - */ - if ((error = bcw_change_core(sc, 0))) - return (error); - - BCW_WRITE(sc, BCW_GPIO_CTRL, (BCW_READ(sc, BCW_GPIO_CTRL) & mask) | - set); - - error = bcw_change_core(sc, sc->sc_lastcore); - - return (error); -} - -/* - * Initialize the chip - * - * http://bcm-specs.sipsolutions.net/ChipInit - */ -int -bcw_chip_init(struct bcw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &sc->sc_ic.ic_if; - uint8_t limit; - uint16_t val16; - uint32_t val32; - int error, i; - - BCW_WRITE(sc, BCW_MMIO_SBF, BCW_SBF_CORE_READY | BCW_SBF_400_MAGIC); - - /* load firmware */ - if ((error = bcw_load_firmware(sc))) - return (error); - - /* - * verify firmware revision - */ - BCW_WRITE(sc, BCW_MMIO_GIR, 0xffffffff); - BCW_WRITE(sc, BCW_MMIO_SBF, 0x00020402); - for (i = 0; i < 50; i++) { - if (BCW_READ(sc, BCW_MMIO_GIR) == BCW_INTR_READY) - break; - delay(10); - } - if (i == 50) { - printf("%s: interrupt-ready timeout!\n", sc->sc_dev.dv_xname); - return (1); - } - BCW_READ(sc, BCW_MMIO_GIR); /* dummy read */ - - val16 = bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_REVISION); - - DPRINTF(("%s: Firmware revision 0x%x, patchlevel 0x%x " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", - sc->sc_dev.dv_xname, val16, - bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_PATCHLEVEL), - (bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_DATE) >> 12) - & 0xf, - (bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_DATE) >> 8) - & 0xf, - bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_DATE) - & 0xff, - (bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_TIME) >> 11) - & 0x1f, - (bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_TIME) >> 5) - & 0x3f, - bcw_shm_read16(sc, BCW_SHM_SHARED, BCW_UCODE_TIME) - & 0x1f)); - - if (val16 > 0x128) { - printf("%s: no support for this firmware revision!\n", - sc->sc_dev.dv_xname); - return (1); - } - - /* initialize GPIO */ - if ((error = bcw_gpio_init(sc))) - return (error); - - /* load init values */ - if ((error = bcw_load_initvals(sc))) - return (error); - - if (sc->sc_core[sc->sc_currentcore].rev > 9) { - BCW_WRITE(sc, 0x540, 0x540); - BCW_WRITE(sc, 0x520, 0x520); - BCW_WRITE(sc, 0x540, 0x540); - BCW_WRITE(sc, 0x418, 0xe0a); - BCW_WRITE(sc, 0x41a, 0x90b); - BCW_WRITE(sc, 0x41c, 0x20e); - BCW_WRITE(sc, 0x41e, 0); - } - - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x5c, 0xa); - - BCW_WRITE(sc, 0x0100, 0x01000000); - - if (sc->sc_core[sc->sc_currentcore].rev < 5) - BCW_WRITE(sc, 0x010c, 0x01000000); - - val32 = BCW_READ(sc, BCW_MMIO_SBF); - val32 &= ~BCW_SBF_AP; - BCW_WRITE(sc, BCW_MMIO_SBF, val32); - val32 = BCW_READ(sc, BCW_MMIO_SBF); - val32 |= BCW_SBF_ADHOC; - BCW_WRITE(sc, BCW_MMIO_SBF, val32); - - if (bcw_using_pio(sc)) { - BCW_WRITE(sc, 0x0210, 0x00000100); - BCW_WRITE(sc, 0x0230, 0x00000100); - BCW_WRITE(sc, 0x0250, 0x00000100); - BCW_WRITE(sc, 0x0270, 0x00000100); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0034, 0); - } - - /* probe response timeout value */ - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0074, 0); - - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x400, 0x8); - - /* TODO slot timing */ - - bcw_set_opmode(ifp); - - if (sc->sc_core[sc->sc_currentcore].rev < 3) { - BCW_WRITE16(sc, 0x060e, 0); - BCW_WRITE16(sc, 0x0610, 0x8000); - BCW_WRITE16(sc, 0x0604, 0); - BCW_WRITE16(sc, 0x0606, 0x0200); - } else { - BCW_WRITE(sc, 0x0188, 0x80000000); - BCW_WRITE(sc, 0x018c, 0x02000000); - } - - BCW_WRITE(sc, BCW_MMIO_GIR, 0x00004000); - BCW_WRITE(sc, BCW_MMIO_DMA0_INT_MASK, 0x0001dc00); - BCW_WRITE(sc, BCW_MMIO_DMA1_INT_MASK, 0x0000dc00); - BCW_WRITE(sc, BCW_MMIO_DMA2_INT_MASK, 0x0000dc00); - BCW_WRITE(sc, BCW_MMIO_DMA3_INT_MASK, 0x0001dc00); - BCW_WRITE(sc, BCW_MMIO_DMA4_INT_MASK, 0x0000dc00); - BCW_WRITE(sc, BCW_MMIO_DMA5_INT_MASK, 0x0000dc00); - - val32 = BCW_READ(sc, BCW_CIR_SBTMSTATELOW); - val32 |= 0x00100000; - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, val32); - - if (sc->sc_core[sc->sc_currentcore].rev >= 5) - BCW_WRITE16(sc, BCW_MMIO_POWERUP_DELAY, - bcw_pc_powerup_delay(sc)); - - val16 = sc->sc_core[sc->sc_currentcore].rev; - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x16, val16); - - /* short/long retry limit */ - limit = bcw_lv(BCW_DEFAULT_SHORT_RETRY_LIMIT, 0, 0xf); - bcw_shm_write32(sc, BCW_SHM_80211, 0x0006, limit); - limit = bcw_lv(BCW_DEFAULT_LONG_RETRY_LIMIT, 0, 0xf); - bcw_shm_write32(sc, BCW_SHM_80211, 0x0007, limit); - - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0044, 3); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0046, 2); - - bcw_macfilter_clear(sc, BCW_MACFILTER_SELF); - bcw_macfilter_set(sc, BCW_MACFILTER_SELF, ic->ic_myaddr); - - bcw_macfilter_clear(sc, BCW_MACFILTER_ASSOC); - bcw_macfilter_set(sc, BCW_MACFILTER_ASSOC, ic->ic_bss->ni_bssid); - - bcw_templateram_set(sc); - - DPRINTF(("%s: Chip initialized\n", sc->sc_dev.dv_xname)); - - return (0); -} - -/* - * Initialize the BS - * - * http://bcm-specs.sipsolutions.net/BSInit - */ -int -bcw_bs_init(struct bcw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - uint32_t ucodeflags; - - BCW_WRITE16(sc, 0x03e6, 0); - - bcw_radio_on(sc); - - bcw_phy_init(sc); - - bcw_radio_set_interf_mitigation(sc, sc->sc_radio_interfmode); - - bcw_phy_set_antenna_diversity(sc); - - bcw_radio_set_txantenna(sc, BCW_RADIO_TXANTENNA_DEFAULT); - - /* minimum contention window */ - if (sc->sc_phy_type == BCW_PHY_TYPEB) - bcw_shm_write32(sc, BCW_SHM_80211, 0x0003, 0x0000001f); - else - bcw_shm_write32(sc, BCW_SHM_80211, 0x0003, 0x0000000f); - - /* maximum contention window */ - bcw_shm_write32(sc, BCW_SHM_80211, 0x0004, 0x000003ff); - - bcw_rate_memory_init(sc); - - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x52, sc->sc_phy_type); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x50, sc->sc_phy_rev); - - ucodeflags = bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET); - ucodeflags |= 0x100000; - bcw_shm_write32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET, ucodeflags); - - if (sc->sc_phy_type == BCW_PHY_TYPEA && - sc->sc_core[sc->sc_currentcore].rev <= 4) - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x3c, 0x1d); - else - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x3c, 0x1e); - - if (ic->ic_opmode != IEEE80211_M_IBSS && - ic->ic_opmode == IEEE80211_M_HOSTAP) { - BCW_WRITE16(sc, 0x612, 0x2); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x416, 0x2); - } else if (sc->sc_phy_type == BCW_PHY_TYPEA) { - BCW_WRITE16(sc, 0x612, 0x78); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x416, 0x78); - } else { - BCW_WRITE16(sc, 0x612, 0xfa); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x416, 0xfa); - } - - return (0); -} - -/* - * Initialize the 80211 core - * - * http://bcm-specs.sipsolutions.net/80211Init - */ -int -bcw_80211_core_init(struct bcw_softc *sc, int active_80211_core) -{ - uint32_t ucodeflags; - //uint32_t sbimconfiglow; - int error; -#if 0 - if (sc->sc_core_bus->rev <= 5 && sc->sc_core_bus->id != BCW_CORE_PCIE) { - sbimconfiglow = BCW_READ(sc, BCW_CIR_SBIMCONFIGLOW); - sbimconfiglow &= ~BCW_SBIMCONFIGLOW_RTM; - sbimconfiglow &= ~BCW_SBIMCONFIGLOW_STM; - sbimconfiglow |= 0x32; - BCW_WRITE(sc, BCW_CIR_SBIMCONFIGLOW, sbimconfiglow); - } -#endif - - bcw_phy_calibrate(sc); - - if ((error = bcw_chip_init(sc))) - return (error); - - if ((error = bcw_bs_init(sc))) - return (error); - - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0016, 0); - - /* - * Set microcode flags if necessery - */ - ucodeflags = bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET); - //ucodeflags |= 0x00000010; /* XXX */ - if (sc->sc_phy_type == BCW_PHY_TYPEB || - sc->sc_phy_type == BCW_PHY_TYPEG) - ucodeflags |= BCW_UCODEFLAG_UNKBGPHY; - if (sc->sc_phy_type == BCW_PHY_TYPEG && sc->sc_phy_rev == 1) - ucodeflags |= BCW_UCODEFLAG_UNKGPHY; - if (sc->sc_phy_type == BCW_PHY_TYPEB && sc->sc_phy_rev >= 2 && - sc->sc_radio_ver == 0x2050) - ucodeflags &= ~BCW_UCODEFLAG_UNKGPHY; - if (sc->sc_sprom.boardflags & BCW_BF_PACTRL) - ucodeflags |= BCW_UCODEFLAG_UNKPACTRL; - if (ucodeflags != - bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET)) - bcw_shm_write32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET, - ucodeflags); - - if (sc->sc_core[sc->sc_currentcore].rev >= 5) - BCW_WRITE16(sc, 0x043c, 0x000c); - - if (active_80211_core) { - if (bcw_using_pio(sc)) { - /* TODO bcw_pio_init() */ - } else { - /* TODO bcw_dma_init() */ - } - } - - BCW_WRITE16(sc, 0x0612, 0x0050); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0416, 0x0050); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0414, 0x01f4); -#if 0 - bcw_mac_enable(sc); - bcw_intr_enable(sc, 0xb007a864); -#endif - - return (0); -} - -uint8_t -bcw_sprom_crc8(uint8_t crc, uint8_t data) -{ - static const uint8_t t[] = { - 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, - 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, - 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, - 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, - 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, - 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, - 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, - 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, - 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, - 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, - 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, - 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, - 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, - 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, - 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, - 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, - 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, - 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, - 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, - 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, - 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, - 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, - 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, - 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, - 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, - 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, - 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, - 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, - 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, - 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, - 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, - 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, - }; - - return (t[crc ^ data]); -} - -uint8_t -bcw_sprom_crc(const uint16_t *sprom) -{ - int word; - uint8_t crc = 0xff; - - for (word = 0; word < BCW_SPROM_SIZE - 1; word++) { - crc = bcw_sprom_crc8(crc, sprom[word] & 0x00ff); - crc = bcw_sprom_crc8(crc, (sprom[word] & 0xff00) >> 8); - } - crc = bcw_sprom_crc8(crc, sprom[BCW_SPROM_VERSION] & 0x00ff); - crc ^= 0xff; - - return (crc); -} - -int -bcw_sprom_read(struct bcw_softc *sc, uint16_t *sprom) -{ - int i; - uint8_t crc, expected_crc; - - for (i = 0; i < BCW_SPROM_SIZE; i++) - sprom[i] = BCW_READ16(sc, BCW_SPROM_BASE + (i * 2)); - - /* CRC-8 check */ - crc = bcw_sprom_crc(sprom); - expected_crc = (sprom[BCW_SPROM_VERSION] & 0xff00) >> 8; - if (crc != expected_crc) { - printf("%s: invalid SPROM checksum! (0x%02x, expected 0x%02x\n", - sc->sc_dev.dv_xname, crc, expected_crc); - return (EINVAL); - } - - return (0); -} - -/* - * Get whole SPROM content - * - * http://bcm-specs.sipsolutions.net/SPROM - */ -int -bcw_sprom_get(struct bcw_softc *sc) -{ - uint16_t val; - uint16_t *sprom; - - sprom = malloc(BCW_SPROM_SIZE * sizeof(uint16_t), M_DEVBUF, M_NOWAIT); - if (sprom == NULL) { - printf("%s: malloc in SPROM extract failed!\n", - sc->sc_dev.dv_xname); - return (ENOMEM); - } - - bcw_sprom_read(sc, sprom); - - /* boardflags */ - val = sprom[BCW_SPROM_BOARDFLAGS]; - sc->sc_sprom.boardflags2 = val; - - /* il0macaddr */ - val = sprom[BCW_SPROM_IL0MACADDR]; - *((uint16_t *)sc->sc_sprom.il0macaddr) = htobe16(val); - val = sprom[BCW_SPROM_IL0MACADDR + 1]; - *(((uint16_t *)sc->sc_sprom.il0macaddr) + 1) = htobe16(val); - val = sprom[BCW_SPROM_IL0MACADDR + 2]; - *(((uint16_t *)sc->sc_sprom.il0macaddr) + 2) = htobe16(val); - - /* et0macaddr */ - val = sprom[BCW_SPROM_ET0MACADDR]; - *((uint16_t *)sc->sc_sprom.et0macaddr) = htobe16(val); - val = sprom[BCW_SPROM_ET0MACADDR + 1]; - *(((uint16_t *)sc->sc_sprom.et0macaddr) + 1) = htobe16(val); - val = sprom[BCW_SPROM_ET0MACADDR + 2]; - *(((uint16_t *)sc->sc_sprom.et0macaddr) + 2) = htobe16(val); - - /* et1macaddr */ - val = sprom[BCW_SPROM_ET1MACADDR]; - *((uint16_t *)sc->sc_sprom.et1macaddr) = htobe16(val); - val = sprom[BCW_SPROM_ET1MACADDR + 1]; - *(((uint16_t *)sc->sc_sprom.et1macaddr) + 1) = htobe16(val); - val = sprom[BCW_SPROM_ET1MACADDR + 2]; - *(((uint16_t *)sc->sc_sprom.et1macaddr) + 2) = htobe16(val); - - /* ethernet phy settigns */ - val = sprom[BCW_SPROM_ETHPHY]; - sc->sc_sprom.et0phyaddr = (val & 0x001f); - sc->sc_sprom.et1phyaddr = (val & 0x03e0); - sc->sc_sprom.et0mdcport = (val & (1 << 14)) >> 14; - sc->sc_sprom.et1mdcport = (val & (1 << 15)) >> 15; - - /* boardrev, antennas, locale */ - val = sprom[BCW_SPROM_BOARDREV]; - sc->sc_sprom.boardrev = (val & 0x00ff); - sc->sc_sprom.locale = (val & 0x0f00); - sc->sc_sprom.antennas_aphy = (val & 0x3000) >> 12; - sc->sc_sprom.antennas_bgphy = (val & 0xc000) >> 14; - - /* pa0b */ - sc->sc_sprom.pa0b0 = sprom[BCW_SPROM_PA0B0]; - sc->sc_sprom.pa0b1 = sprom[BCW_SPROM_PA0B1]; - sc->sc_sprom.pa0b2 = sprom[BCW_SPROM_PA0B2]; - - /* wl0gpio */ - val = sprom[BCW_SPROM_WL0GPIO0]; - if (val == 0) - val = 0xffff; - sc->sc_sprom.wl0gpio0 = val & 0x00ff; - sc->sc_sprom.wl0gpio1 = (val & 0xff00) >> 8; - val = sprom[BCW_SPROM_WL0GPIO2]; - if (val == 0) - val = 0xffff; - sc->sc_sprom.wl0gpio2 = val & 0x00ff; - sc->sc_sprom.wl0gpio3 = (val & 0xff00) >> 8; - - /* maxpower */ - val = sprom[BCW_SPROM_MAXPWR]; - sc->sc_sprom.maxpower_aphy = (val & 0xff00) >> 8; - sc->sc_sprom.maxpower_bgphy = val & 0xff00; - - /* pa1b */ - sc->sc_sprom.pa1b0 = sprom[BCW_SPROM_PA1B0]; - sc->sc_sprom.pa1b1 = sprom[BCW_SPROM_PA1B1]; - sc->sc_sprom.pa1b2 = sprom[BCW_SPROM_PA1B2]; - - /* idle tssi target */ - val = sprom[BCW_SPROM_IDL_TSSI_TGT]; - sc->sc_sprom.idle_tssi_tgt_aphy = val & 0x00ff; - sc->sc_sprom.idle_tssi_tgt_bgphy = (val & 0xff00) >> 8; - - /* boardflags */ - val = sprom[BCW_SPROM_BOARDFLAGS]; - if (val == 0xffff) - val = 0; - sc->sc_sprom.boardflags = val; - /* TODO boardflags workarounds */ - - /* antenna gain */ - val = sprom[BCW_SPROM_ANTENNA_GAIN]; - if (val == 0 || val == 0xffff) - val = 0x0202; - sc->sc_sprom.antennagain_aphy = ((val & 0xff00) >> 8) * 4; - sc->sc_sprom.antennagain_bgphy = (val & 0x00ff) * 4; - - return (0); -} - -/* - * Init the Microcode Flags Bitfield - * - * http://bcm-specs.sipsolutions.net/MicrocodeFlagsBitfield - */ -void -bcw_microcode_init_fbf(struct bcw_softc *sc) -{ - uint32_t val; - - val = 0; - if (sc->sc_phy_type == BCW_PHY_TYPEA || - sc->sc_phy_type == BCW_PHY_TYPEB || - sc->sc_phy_type == BCW_PHY_TYPEG) - val |= 2; - if (sc->sc_phy_type == BCW_PHY_TYPEG && sc->sc_phy_rev == 1) - val |= 0x20; - if (sc->sc_phy_type == BCW_PHY_TYPEG && - sc->sc_sprom.boardflags & BCW_BF_PACTRL) - val |= 0x40; - if (sc->sc_phy_type == BCW_PHY_TYPEG && sc->sc_phy_rev < 3) - val |= 0x8; - if (sc->sc_sprom.boardflags & BCW_BF_XTAL) - val |= 0x400; - if (sc->sc_phy_type == BCW_PHY_TYPEB) - val |= 0x4; - if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev <= 5) - val |= 0x40000; - /* XXX device not up and PCI bus with rev =< 10 set 0x80000 */ - - bcw_shm_write32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET, val); -} - -/* - * PHY - */ -int -bcw_phy_get(struct bcw_softc *sc) -{ - uint32_t val; - - val = BCW_READ16(sc, 0x3E0); - sc->sc_phy_ver = (val & 0xf000) >> 12; - sc->sc_phy_rev = val & 0xf; - sc->sc_phy_type = (val & 0xf00) >> 8; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - DPRINTF(("%s: PHY %d (A) ", - sc->sc_dev.dv_xname, sc->sc_phy_type)); - if (sc->sc_phy_rev != 2 && - sc->sc_phy_rev != 3 && - sc->sc_phy_rev != 5 && - sc->sc_phy_rev != 6 && - sc->sc_phy_rev != 7) { - printf("has invalid revision %d!\n", sc->sc_phy_rev); - return (1); - } - break; - case BCW_PHY_TYPEB: - DPRINTF(("%s: PHY %d (B) ", - sc->sc_dev.dv_xname, sc->sc_phy_type)); - if (sc->sc_phy_rev != 2 && - sc->sc_phy_rev != 4 && - sc->sc_phy_rev != 7) { - printf("has invalid revision %d!\n", sc->sc_phy_rev); - return (1); - } - break; - case BCW_PHY_TYPEG: - DPRINTF(("%s: PHY %d (G) ", - sc->sc_dev.dv_xname, sc->sc_phy_type)); - if (sc->sc_phy_rev != 1 && - sc->sc_phy_rev != 2 && - sc->sc_phy_rev != 4 && - sc->sc_phy_rev != 6 && - sc->sc_phy_rev != 7 && - sc->sc_phy_rev != 8) { - printf("has invalid revision %d!\n", sc->sc_phy_rev); - return (1); - } - break; - default: - DPRINTF(("Unknown PHY type %d!\n", sc->sc_phy_type)); - return (1); - } - - DPRINTF(("ver %d rev %d\n", sc->sc_phy_ver, sc->sc_phy_rev)); - - return (0); -} - -int -bcw_phy_init(struct bcw_softc *sc) -{ - int error = ENODEV; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - if (sc->sc_phy_rev == 2 || sc->sc_phy_rev == 3) { - error = 0; - } - break; - case BCW_PHY_TYPEB: - switch (sc->sc_phy_rev) { - case 2: - bcw_phy_initb2(sc); - error = 0; - break; - case 4: - bcw_phy_initb4(sc); - error = 0; - break; - case 5: - bcw_phy_initb5(sc); - error = 0; - break; - case 6: - bcw_phy_initb6(sc); - error = 0; - break; - } - break; - case BCW_PHY_TYPEG: - bcw_phy_initg(sc); - error = 0; - DPRINTF(("%s: PHY type G initialized\n", sc->sc_dev.dv_xname)); - break; - } - - if (error) - printf("%s: PHY type unknown!\n", sc->sc_dev.dv_xname); - - return (error); -} - -void -bcw_phy_initg(struct bcw_softc *sc) -{ - uint16_t tmp; - - if (sc->sc_phy_rev == 1) - bcw_phy_initb5(sc); - else - bcw_phy_initb6(sc); - if (sc->sc_phy_rev >= 2 || sc->sc_phy_connected) - bcw_phy_inita(sc); - - if (sc->sc_phy_rev >= 2) { - bcw_phy_write16(sc, 0x0814, 0); - bcw_phy_write16(sc, 0x0815, 0); - if (sc->sc_phy_rev == 2) - bcw_phy_write16(sc, 0x0811, 0); - else if (sc->sc_phy_rev >= 3) - bcw_phy_write16(sc, 0x0811, 0x0400); - bcw_phy_write16(sc, 0x0015, 0x00c0); - if (sc->sc_phy_connected) { - tmp = bcw_phy_read16(sc, 0x0400) & 0xff; - if (tmp < 6) { - bcw_phy_write16(sc, 0x04c2, 0x1816); - bcw_phy_write16(sc, 0x04c3, 0x8006); - if (tmp != 3) - bcw_phy_write16(sc, 0x04cc, - (bcw_phy_read16(sc, 0x04cc) & - 0x00ff) | 0x1f00); - } - } - } - - if (sc->sc_phy_rev < 3 && sc->sc_phy_connected) - bcw_phy_write16(sc, 0x047e, 0x0078); - if (sc->sc_phy_rev >= 6 && sc->sc_phy_rev <= 8) { - bcw_phy_write16(sc, 0x0801, bcw_phy_read16(sc, 0x0801) | - 0x0080); - bcw_phy_write16(sc, 0x043e, bcw_phy_read16(sc, 0x043e) | - 0x0004); - } - if (sc->sc_phy_rev >= 2 && sc->sc_phy_connected) - bcw_phy_calc_loopback_gain(sc); - if (sc->sc_radio_rev != 8) { - if (sc->sc_radio_initval == 0xffff) - sc->sc_radio_initval = bcw_radio_init2050(sc); - else - bcw_radio_write16(sc, 0x0078, sc->sc_radio_initval); - } - if (sc->sc_radio_txctl2 == 0xffff) - bcw_phy_lo_g_measure(sc); - else { - if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev == 8) - bcw_radio_write16(sc, 0x0052, - (sc->sc_radio_txctl1 << 4) | sc->sc_radio_txctl2); - else - bcw_radio_write16(sc, 0x0052, - (bcw_radio_read16(sc, 0x0052) & 0xfff0) | - sc->sc_radio_txctl1); - if (sc->sc_phy_rev >= 6) - bcw_phy_write16(sc, 0x0036, - (bcw_phy_read16(sc, 0x0036) & 0xf000) | - (sc->sc_radio_txctl2 << 12)); - if (sc->sc_sprom.boardflags & BCW_BF_PACTRL) - bcw_phy_write16(sc, 0x002e, 0x8075); - else - bcw_phy_write16(sc, 0x002e, 0x807f); - if (sc->sc_phy_rev < 2) - bcw_phy_write16(sc, 0x002f, 0x0101); - else - bcw_phy_write16(sc, 0x002f, 0x0202); - } - if (sc->sc_phy_connected) { - bcw_phy_lo_adjust(sc, 0); - bcw_phy_write16(sc, 0x080f, 0x8078); - } - - if (!(sc->sc_sprom.boardflags & BCW_BF_RSSI)) { - bcw_radio_nrssi_hw_update(sc, 0xffff); - bcw_radio_calc_nrssi_threshold(sc); - } else if (sc->sc_phy_connected) { - if (sc->sc_radio_nrssi[0] == -1000) { - bcw_radio_calc_nrssi_slope(sc); - } else { - bcw_radio_calc_nrssi_threshold(sc); - } - } - - if (sc->sc_radio_rev == 8) - bcw_phy_write16(sc, 0x0805, 0x3230); - bcw_phy_init_pctl(sc); - if (sc->sc_chip_id == 0x4306 && sc->sc_chip_pkg == 2) { - bcw_phy_write16(sc, 0x0429, bcw_phy_read16(sc, 0x0429) & - 0xbfff); - bcw_phy_write16(sc, 0x04c3, bcw_phy_read16(sc, 0x04c3) & - 0x7fff); - } -} - -void -bcw_phy_initb5(struct bcw_softc *sc) -{ - uint16_t offset; - - if (sc->sc_phy_rev == 1 && sc->sc_radio_rev == 0x2050) - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | - 0x0050); - - if (sc->sc_board_vendor != PCI_VENDOR_BROADCOM && - sc->sc_board_type != 0x0416) { - for (offset = 0x00a8; offset < 0x00c7; offset++) - bcw_phy_write16(sc, offset, - (bcw_phy_read16(sc, offset) + 0x02020) & 0x3f3f); - } - - bcw_phy_write16(sc, 0x0035, (bcw_phy_read16(sc, 0x0035) & 0xf0ff) | - 0x0700); - - if (sc->sc_radio_rev == 0x2050) - bcw_phy_write16(sc, 0x0038, 0x0667); - - if (sc->sc_phy_connected) { - if (sc->sc_radio_rev == 0x2050) { - bcw_radio_write16(sc, 0x007a, - bcw_radio_read16(sc, 0x007a) | 0x0020); - bcw_radio_write16(sc, 0x0051, - bcw_radio_read16(sc, 0x0051) | 0x0004); - } - BCW_WRITE16(sc, BCW_MMIO_PHY_RADIO, 0); - bcw_phy_write16(sc, 0x0802, bcw_phy_read16(sc, 0x0802) | - 0x0100); - bcw_phy_write16(sc, 0x042b, bcw_phy_read16(sc, 0x042b) | - 0x2000); - bcw_phy_write16(sc, 0x001c, 0x186a); - bcw_phy_write16(sc, 0x0013, - (bcw_phy_read16(sc, 0x0013) & 0x00ff) | 0x1900); - bcw_phy_write16(sc, 0x0035, - (bcw_phy_read16(sc, 0x0035) & 0xffc0) | 0x0064); - bcw_phy_write16(sc, 0x005d, - (bcw_phy_read16(sc, 0x005d) & 0xff80) | 0x000a); - } - - if (sc->sc_phy_rev == 1 && sc->sc_radio_rev == 0x2050) { - bcw_phy_write16(sc, 0x0026, 0xce00); - bcw_phy_write16(sc, 0x0021, 0x3763); - bcw_phy_write16(sc, 0x0022, 0x1bc3); - bcw_phy_write16(sc, 0x0023, 0x06f9); - bcw_phy_write16(sc, 0x0024, 0x037e); - } else - bcw_phy_write16(sc, 0x0026, 0xcc00); - bcw_phy_write16(sc, 0x0030, 0x00c6); - BCW_WRITE16(sc, 0x3ec, 0x3f22); - - if (sc->sc_phy_rev == 1 && sc->sc_radio_rev == 0x2050) - bcw_phy_write16(sc, 0x0020, 0x3e1c); - else - bcw_phy_write16(sc, 0x0020, 0x301c); - - if (sc->sc_phy_rev == 0) - BCW_WRITE16(sc, 0x03e4, 0x3000); - - /* force to channel 7, even if not supported */ - bcw_radio_select_channel(sc, 7, 0); - - if (sc->sc_radio_rev != 0x2050) { - bcw_radio_write16(sc, 0x0075, 0x0080); - bcw_radio_write16(sc, 0x0079, 0x0081); - } - - bcw_radio_write16(sc, 0x0050, 0x0020); - bcw_radio_write16(sc, 0x0050, 0x0023); - - if (sc->sc_radio_rev == 0x2050) { - bcw_radio_write16(sc, 0x0050, 0x0020); - bcw_radio_write16(sc, 0x005a, 0x0070); - } - - bcw_radio_write16(sc, 0x005b, 0x007b); - bcw_radio_write16(sc, 0x005c, 0x00b0); - - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | 0x0007); - - bcw_radio_select_channel(sc, BCW_RADIO_DEFAULT_CHANNEL_BG, 0); - - bcw_phy_write16(sc, 0x0014, 0x0080); - bcw_phy_write16(sc, 0x0032, 0x00ca); - bcw_phy_write16(sc, 0x88a3, 0x002a); - - bcw_radio_set_txpower_bg(sc, 0xffff, 0xffff, 0xffff); - - if (sc->sc_radio_rev == 0x2050) - bcw_radio_write16(sc, 0x005d, 0x000d); - - BCW_WRITE16(sc, 0x03e4, (BCW_READ16(sc, 0x03e4) & 0xffc0) | 0x0004); -} - -void -bcw_phy_initb2(struct bcw_softc *sc) -{ - uint16_t offset, val; - - BCW_WRITE16(sc, 0x03ec, 0x3f22); - bcw_phy_write16(sc, 0x0020, 0x301c); - bcw_phy_write16(sc, 0x0026, 0x0000); - bcw_phy_write16(sc, 0x0030, 0x00c6); - bcw_phy_write16(sc, 0x0088, 0x3e00); - val = 0x3c3d; - for (offset = 0x0089; offset < 0x00a7; offset++) { - bcw_phy_write16(sc, offset, val); - val -= 0x0202; - } - bcw_phy_write16(sc, 0x03e4, 0x3000); - if (sc->sc_radio_channel == 0xff) - bcw_radio_select_channel(sc, BCW_RADIO_DEFAULT_CHANNEL_BG, 0); - else - bcw_radio_select_channel(sc, sc->sc_radio_channel, 0); - if (sc->sc_radio_ver != 0x2050) { - bcw_radio_write16(sc, 0x0075, 0x0080); - bcw_radio_write16(sc, 0x0079, 0x0081); - } - bcw_radio_write16(sc, 0x0050, 0x0020); - bcw_radio_write16(sc, 0x0050, 0x0023); - if (sc->sc_radio_ver == 0x2050) { - bcw_radio_write16(sc, 0x0050, 0x0020); - bcw_radio_write16(sc, 0x005a, 0x0070); - bcw_radio_write16(sc, 0x005b, 0x007b); - bcw_radio_write16(sc, 0x005c, 0x00b0); - bcw_radio_write16(sc, 0x007a, 0x000f); - bcw_phy_write16(sc, 0x0038, 0x0677); - bcw_radio_init2050(sc); - } - bcw_phy_write16(sc, 0x0014, 0x0080); - bcw_phy_write16(sc, 0x0032, 0x00ca); - bcw_phy_write16(sc, 0x0032, 0x00cc); - bcw_phy_write16(sc, 0x0035, 0x07c2); - bcw_phy_lo_b_measure(sc); - bcw_phy_write16(sc, 0x0026, 0xcc00); - if (sc->sc_radio_ver != 0x2050) - bcw_phy_write16(sc, 0x0026, 0xce00); - BCW_WRITE16(sc, BCW_MMIO_CHANNEL_EXT, 0x1000); - bcw_phy_write16(sc, 0x002a, 0x88a3); - bcw_radio_set_txpower_bg(sc, 0xffff, 0xffff, 0xffff); - bcw_phy_init_pctl(sc); -} - -void -bcw_phy_initb4(struct bcw_softc *sc) -{ - uint16_t offset, val; - - BCW_WRITE16(sc, 0x03ec, 0x3f22); - bcw_phy_write16(sc, 0x0020, 0x301c); - bcw_phy_write16(sc, 0x0026, 0x0000); - bcw_phy_write16(sc, 0x0030, 0x00c6); - bcw_phy_write16(sc, 0x0088, 0x3e00); - val = 0x3c3d; - for (offset = 0x0089; offset < 0x00a7; offset++) { - bcw_phy_write16(sc, offset, val); - val -= 0x0202; - } - bcw_phy_write16(sc, 0x3e4, 0x3000); - if (sc->sc_radio_channel == 0xff) - bcw_radio_select_channel(sc, BCW_RADIO_DEFAULT_CHANNEL_BG, 0); - else - bcw_radio_select_channel(sc, sc->sc_radio_channel, 0); - if (sc->sc_radio_ver == 0x2050) { - bcw_radio_write16(sc, 0x0050, 0x0020); - bcw_radio_write16(sc, 0x005a, 0x0070); - bcw_radio_write16(sc, 0x005b, 0x007b); - bcw_radio_write16(sc, 0x005c, 0x00b0); - bcw_radio_write16(sc, 0x007a, 0x000f); - bcw_phy_write16(sc, 0x0038, 0x0677); - bcw_radio_init2050(sc); - } - bcw_phy_write16(sc, 0x0014, 0x0080); - bcw_phy_write16(sc, 0x0032, 0x00ca); - if (sc->sc_radio_ver == 0x2050) - bcw_phy_write16(sc, 0x0032, 0x00e0); - bcw_phy_write16(sc, 0x0035, 0x07c2); - - bcw_phy_lo_b_measure(sc); - - bcw_phy_write16(sc, 0x0026, 0xcc00); - if (sc->sc_radio_ver == 0x2050) - bcw_phy_write16(sc, 0x0026, 0xce00); - BCW_WRITE16(sc, BCW_MMIO_CHANNEL_EXT, 0x1100); - bcw_phy_write16(sc, 0x002a, 0x88c2); - if (sc->sc_radio_ver == 0x2050) - bcw_phy_write16(sc, 0x002a, 0x88c2); - bcw_radio_set_txpower_bg(sc, 0xffff, 0xffff, 0xffff); - if (sc->sc_sprom.boardflags & BCW_BF_RSSI) { - bcw_radio_calc_nrssi_slope(sc); - bcw_radio_calc_nrssi_threshold(sc); - } - bcw_phy_init_pctl(sc); -} - -void -bcw_phy_initb6(struct bcw_softc *sc) -{ - uint16_t offset, val; - - bcw_phy_write16(sc, 0x003e, 0x817a); - bcw_radio_write16(sc, 0x007a, (bcw_radio_read16(sc, 0x007a) | 0x0058)); - - if (sc->sc_radio_mnf == 0x17f && sc->sc_radio_ver == 0x2050 && - (sc->sc_radio_rev == 3 || sc->sc_radio_rev == 4 || - sc->sc_radio_rev == 5)) { - bcw_radio_write16(sc, 0x0051, 0x001f); - bcw_radio_write16(sc, 0x0052, 0x0040); - bcw_radio_write16(sc, 0x0053, 0x005b); - bcw_radio_write16(sc, 0x0054, 0x0098); - bcw_radio_write16(sc, 0x005a, 0x0088); - bcw_radio_write16(sc, 0x005b, 0x0088); - bcw_radio_write16(sc, 0x005d, 0x0088); - bcw_radio_write16(sc, 0x005e, 0x0088); - bcw_radio_write16(sc, 0x007d, 0x0088); - } - - if (sc->sc_radio_mnf == 0x17f && sc->sc_radio_ver == 0x2050 && - sc->sc_radio_rev == 6) { - bcw_radio_write16(sc, 0x0051, 0); - bcw_radio_write16(sc, 0x0052, 0x0040); - bcw_radio_write16(sc, 0x0053, 0x00b7); - bcw_radio_write16(sc, 0x0054, 0x0098); - bcw_radio_write16(sc, 0x005a, 0x0088); - bcw_radio_write16(sc, 0x005b, 0x008b); - bcw_radio_write16(sc, 0x005c, 0x00b5); - bcw_radio_write16(sc, 0x005d, 0x0088); - bcw_radio_write16(sc, 0x005e, 0x0088); - bcw_radio_write16(sc, 0x007d, 0x0088); - bcw_radio_write16(sc, 0x007c, 0x0001); - bcw_radio_write16(sc, 0x007e, 0x0008); - } - - if (sc->sc_radio_mnf == 0x017f && sc->sc_radio_ver == 0x2050 && - sc->sc_radio_rev == 7) { - bcw_radio_write16(sc, 0x0051, 0); - bcw_radio_write16(sc, 0x0052, 0x0040); - bcw_radio_write16(sc, 0x0053, 0x00b7); - bcw_radio_write16(sc, 0x0054, 0x0098); - bcw_radio_write16(sc, 0x005a, 0x0088); - bcw_radio_write16(sc, 0x005b, 0x00a8); - bcw_radio_write16(sc, 0x005c, 0x0075); - bcw_radio_write16(sc, 0x005d, 0x00f5); - bcw_radio_write16(sc, 0x005e, 0x00b8); - bcw_radio_write16(sc, 0x007d, 0x00e8); - bcw_radio_write16(sc, 0x007c, 0x0001); - bcw_radio_write16(sc, 0x007e, 0x0008); - bcw_radio_write16(sc, 0x007b, 0); - } - - if (sc->sc_radio_mnf == 0x17f && sc->sc_radio_ver == 0x2050 && - sc->sc_radio_rev == 8) { - bcw_radio_write16(sc, 0x0051, 0); - bcw_radio_write16(sc, 0x0052, 0x0040); - bcw_radio_write16(sc, 0x0053, 0x00b7); - bcw_radio_write16(sc, 0x0054, 0x0098); - bcw_radio_write16(sc, 0x005a, 0x0088); - bcw_radio_write16(sc, 0x005b, 0x006b); - bcw_radio_write16(sc, 0x005c, 0x000f); - if (sc->sc_sprom.boardflags & 0x8000) { - bcw_radio_write16(sc, 0x005d, 0x00fa); - bcw_radio_write16(sc, 0x005e, 0x00d8); - } else { - bcw_radio_write16(sc, 0x005d, 0x00f5); - bcw_radio_write16(sc, 0x005e, 0x00b8); - } - bcw_radio_write16(sc, 0x0073, 0x0003); - bcw_radio_write16(sc, 0x007d, 0x00a8); - bcw_radio_write16(sc, 0x007c, 0x0001); - bcw_radio_write16(sc, 0x007e, 0x0008); - } - - val = 0x1e1f; - for (offset = 0x0088; offset < 0x0098; offset++) { - bcw_phy_write16(sc, offset, val); - val -= 0x0202; - } - val = 0x3e3f; - for (offset = 0x0098; offset < 0x00a8; offset++) { - bcw_phy_write16(sc, offset, val); - val -= 0x0202; - } - val = 0x2120; - for (offset = 0x00a8; offset < 0x00c8; offset++) { - bcw_phy_write16(sc, offset, (val & 0x3f3f)); - val += 0x0202; - } - - if (sc->sc_phy_type == BCW_PHY_TYPEG) { - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | - 0x0020); - bcw_radio_write16(sc, 0x0051, bcw_radio_read16(sc, 0x0051) | - 0x0004); - bcw_phy_write16(sc, 0x0802, bcw_phy_read16(sc, 0x0802) | - 0x0100); - bcw_phy_write16(sc, 0x042b, bcw_phy_read16(sc, 0x042b) | - 0x2000); - } - - /* force to channel 7, even if not supported */ - bcw_radio_select_channel(sc, 7, 0); - - bcw_radio_write16(sc, 0x0050, 0x0020); - bcw_radio_write16(sc, 0x0050, 0x0023); - delay(40); - bcw_radio_write16(sc, 0x007c, (bcw_radio_read16(sc, 0x007c) | - 0x0002)); - bcw_radio_write16(sc, 0x0050, 0x0020); - if (sc->sc_radio_mnf == 0x17f && sc->sc_radio_ver == 0x2050 && - sc->sc_radio_rev <= 2) { - bcw_radio_write16(sc, 0x0050, 0x0020); - bcw_radio_write16(sc, 0x005a, 0x0070); - bcw_radio_write16(sc, 0x005b, 0x007b); - bcw_radio_write16(sc, 0x005c, 0x00b0); - } - bcw_radio_write16(sc, 0x007a, (bcw_radio_read16(sc, 0x007a) & 0x00f8) | - 0x0007); - - bcw_radio_select_channel(sc, BCW_RADIO_DEFAULT_CHANNEL_BG, 0); - - bcw_phy_write16(sc, 0x0014, 0x0200); - if (sc->sc_radio_ver == 0x2050) { - if (sc->sc_radio_rev == 3 || sc->sc_radio_rev == 4 || - sc->sc_radio_rev == 5) - bcw_phy_write16(sc, 0x002a, 0x8ac0); - else - bcw_phy_write16(sc, 0x002a, 0x88c2); - } - bcw_phy_write16(sc, 0x0038, 0x0668); - bcw_radio_set_txpower_bg(sc, 0xffff, 0xffff, 0xffff); - if (sc->sc_radio_ver == 0x2050) { - if (sc->sc_radio_rev == 3 || sc->sc_radio_rev == 4 || - sc->sc_radio_rev == 5) - bcw_phy_write16(sc, 0x005d, - bcw_phy_read16(sc, 0x005d) | 0x0003); - else if (sc->sc_radio_rev <= 2) - bcw_phy_write16(sc, 0x005d, 0x000d); - } - - if (sc->sc_phy_rev == 4) - bcw_phy_write16(sc, 0x0002, (bcw_phy_read16(sc, 0x0002) & - 0xffc0) | 0x0004); - else - BCW_WRITE16(sc, 0x03e4, 0x0009); - if (sc->sc_phy_type == BCW_PHY_TYPEB) { - BCW_WRITE16(sc, 0x03e6, 0x8140); - bcw_phy_write16(sc, 0x0016, 0x0410); - bcw_phy_write16(sc, 0x0017, 0x0820); - bcw_phy_write16(sc, 0x0062, 0x0007); - (void)bcw_radio_calibrationvalue(sc); - bcw_phy_lo_b_measure(sc); - if (sc->sc_sprom.boardflags & BCW_BF_RSSI) { - bcw_radio_calc_nrssi_slope(sc); - bcw_radio_calc_nrssi_threshold(sc); - } - bcw_phy_init_pctl(sc); - } else - BCW_WRITE16(sc, 0x03e6, 0); -} - -void -bcw_phy_inita(struct bcw_softc *sc) -{ - uint16_t tval; - - if (sc->sc_phy_type == BCW_PHY_TYPEA) - bcw_phy_setupa(sc); - else { - bcw_phy_setupg(sc); - if (sc->sc_sprom.boardflags & BCW_BF_PACTRL) - bcw_phy_write16(sc, 0x046e, 0x03cf); - return; - } - - bcw_phy_write16(sc, BCW_PHY_A_CRS, (bcw_phy_read16(sc, BCW_PHY_A_CRS) & - 0xf83c) | 0x0340); - bcw_phy_write16(sc, 0x0034, 0x0001); - - bcw_phy_write16(sc, BCW_PHY_A_CRS, bcw_phy_read16(sc, BCW_PHY_A_CRS) | - (1 << 14)); - bcw_radio_init2060(sc); - - if (sc->sc_board_vendor == PCI_VENDOR_BROADCOM && - (sc->sc_board_type == 0x0416 || sc->sc_board_type == 0x040a)) { - if (sc->sc_radio_lofcal == 0xffff) - bcw_radio_set_tx_iq(sc); - else - bcw_radio_write16(sc, 0x001e, sc->sc_radio_lofcal); - } - - bcw_phy_write16(sc, 0x007a, 0xf111); - - if (sc->sc_phy_savedpctlreg == 0xffff) { - bcw_radio_write16(sc, 0x0019, 0); - bcw_radio_write16(sc, 0x0017, 0x0020); - - tval = bcw_ilt_read(sc, 0x3001); - if (sc->sc_phy_rev == 1) - bcw_ilt_write(sc, 0x3001, (bcw_ilt_read(sc, 0x3001) & - 0xff87) | 0x0058); - else - bcw_ilt_write(sc, 0x3001, (bcw_ilt_read(sc, 0x3001) & - 0xffc3) | 0x002c); - bcw_dummy_transmission(sc); - sc->sc_phy_savedpctlreg = bcw_phy_read16(sc, BCW_PHY_A_PCTL); - bcw_ilt_write(sc, 0x3001, tval); - - bcw_radio_set_txpower_a(sc, 0x0018); - } - bcw_radio_clear_tssi(sc); -} - -void -bcw_phy_setupa(struct bcw_softc *sc) -{ - uint16_t i; - - switch (sc->sc_phy_rev) { - case 2: - bcw_phy_write16(sc, 0x008e, 0x3800); - bcw_phy_write16(sc, 0x0035, 0x03ff); - bcw_phy_write16(sc, 0x0036, 0x0400); - - bcw_ilt_write(sc, 0x3807, 0x0051); - - bcw_phy_write16(sc, 0x001c, 0x0ff9); - bcw_phy_write16(sc, 0x0020, bcw_phy_read16(sc, 0x0020) & - 0xff0f); - bcw_ilt_write(sc, 0x3c0c, 0x07bf); - bcw_radio_write16(sc, 0x0002, 0x07bf); - - bcw_phy_write16(sc, 0x0024, 0x4680); - bcw_phy_write16(sc, 0x0020, 0x0003); - bcw_phy_write16(sc, 0x001d, 0x0f40); - bcw_phy_write16(sc, 0x001f, 0x1c00); - - bcw_phy_write16(sc, 0x002a, (bcw_phy_read16(sc, 0x002a) & - 0x00ff) | 0x0400); - bcw_phy_write16(sc, 0x002b, bcw_phy_read16(sc, 0x002b) & - 0xfbff); - bcw_phy_write16(sc, 0x008e, 0x58c1); - - bcw_ilt_write(sc, 0x0803, 0x000f); - bcw_ilt_write(sc, 0x0804, 0x001f); - bcw_ilt_write(sc, 0x0805, 0x002a); - bcw_ilt_write(sc, 0x0805, 0x0030); - bcw_ilt_write(sc, 0x0807, 0x003a); - - bcw_ilt_write(sc, 0x0000, 0x0013); - bcw_ilt_write(sc, 0x0001, 0x0013); - bcw_ilt_write(sc, 0x0002, 0x0013); - bcw_ilt_write(sc, 0x0003, 0x0013); - bcw_ilt_write(sc, 0x0004, 0x0015); - bcw_ilt_write(sc, 0x0005, 0x0015); - bcw_ilt_write(sc, 0x0006, 0x0019); - - bcw_ilt_write(sc, 0x0404, 0x0003); - bcw_ilt_write(sc, 0x0405, 0x0003); - bcw_ilt_write(sc, 0x0406, 0x0007); - - for (i = 0; i < 16; i++) - bcw_ilt_write(sc, 0x4000 + i, (0x8 + i) & 0x000f); - - bcw_ilt_write(sc, 0x3003, 0x1044); - bcw_ilt_write(sc, 0x3004, 0x7201); - bcw_ilt_write(sc, 0x3006, 0x0040); - bcw_ilt_write(sc, 0x3001, (bcw_ilt_read(sc, 0x3001) & 0x0010) | - 0x0008); - - for (i = 0; i < BCW_ILT_FINEFREQA_SIZE; i++) - bcw_ilt_write(sc, 0x5800 + i, bcw_ilt_finefreqa[i]); - - for (i = 0; i < BCW_ILT_NOISEA2_SIZE; i++) - bcw_ilt_write(sc, 0x1800 + i, bcw_ilt_noisea2[i]); - - for (i = 0; i < BCW_ILT_ROTOR_SIZE; i++) - bcw_ilt_write(sc, 0x2000 + i, bcw_ilt_rotor[i]); - - bcw_phy_init_noisescaletbl(sc); - for (i = 0; i < BCW_ILT_RETARD_SIZE; i++) - bcw_ilt_write(sc, 0x2400 + i, bcw_ilt_retard[i]); - - break; - case 3: - for (i = 0; i< 64; i++) - bcw_ilt_write(sc, 0x4000 + i, i); - - bcw_ilt_write(sc, 0x3807, 0x0051); - - bcw_phy_write16(sc, 0x001c, 0x0ff9); - bcw_phy_write16(sc, 0x0020, bcw_phy_read16(sc, 0x0020) & - 0x0ff0f); - bcw_radio_write16(sc, 0x0002, 0x07bf); - - bcw_phy_write16(sc, 0x0024, 0x4680); - bcw_phy_write16(sc, 0x0020, 0x0003); - bcw_phy_write16(sc, 0x001d, 0x0f40); - bcw_phy_write16(sc, 0x001f, 0x1c00); - bcw_phy_write16(sc, 0x002a, (bcw_phy_read16(sc, 0x002a) & - 0x00ff) | 0x0400); - bcw_ilt_write(sc, 0x3001, (bcw_ilt_read(sc, 0x3001) & - 0x0010) | 0x0008); - for (i = 0; i < BCW_ILT_NOISEA3_SIZE; i++) - bcw_ilt_write(sc, 0x1800 + i, bcw_ilt_noisea3[i]); - - bcw_phy_init_noisescaletbl(sc); - for (i = 0; i < BCW_ILT_SIGMASQR_SIZE; i++) - bcw_ilt_write(sc, 0x5000 + i, bcw_ilt_sigmasqr1[i]); - - bcw_phy_write16(sc, 0x0003, 0x1808); - - bcw_ilt_write(sc, 0x0803, 0x000f); - bcw_ilt_write(sc, 0x0804, 0x001f); - bcw_ilt_write(sc, 0x0805, 0x002a); - bcw_ilt_write(sc, 0x0805, 0x0030); - bcw_ilt_write(sc, 0x0807, 0x003a); - - bcw_ilt_write(sc, 0x0000, 0x0013); - bcw_ilt_write(sc, 0x0001, 0x0013); - bcw_ilt_write(sc, 0x0002, 0x0013); - bcw_ilt_write(sc, 0x0003, 0x0013); - bcw_ilt_write(sc, 0x0004, 0x0015); - bcw_ilt_write(sc, 0x0005, 0x0015); - bcw_ilt_write(sc, 0x0006, 0x0019); - - bcw_ilt_write(sc, 0x0404, 0x0003); - bcw_ilt_write(sc, 0x0405, 0x0003); - bcw_ilt_write(sc, 0x0406, 0x0007); - - bcw_ilt_write(sc, 0x3c02, 0x000f); - bcw_ilt_write(sc, 0x3c03, 0x0014); - break; - default: - /* XXX panic()? */ - break; - } -} - -void -bcw_phy_setupg(struct bcw_softc *sc) -{ - uint16_t i; - - if (sc->sc_phy_rev == 1) { - bcw_phy_write16(sc, 0x0406, 0x4f19); - bcw_phy_write16(sc, BCW_PHY_G_CRS, (bcw_phy_read16(sc, - BCW_PHY_G_CRS) & 0xfc3f) | 0x0340); - bcw_phy_write16(sc, 0x042c, 0x005a); - bcw_phy_write16(sc, 0x0427, 0x001a); - - for (i = 0; i < BCW_ILT_FINEFREQG_SIZE; i++) - bcw_ilt_write(sc, 0x5800 + i, bcw_ilt_finefreqg[i]); - - for (i = 0; i < BCW_ILT_NOISEG1_SIZE; i++) - bcw_ilt_write(sc, 0x1800 + i, bcw_ilt_noiseg1[i]); - - for (i = 0; i < BCW_ILT_ROTOR_SIZE; i++) - bcw_ilt_write(sc, 0x2000 + i, bcw_ilt_rotor[i]); - } else { - bcw_radio_nrssi_hw_write(sc, 0xba98, (int16_t) 0x7654); - - if (sc->sc_phy_type == 2) { - bcw_phy_write16(sc, 0x04c0, 0x1861); - bcw_phy_write16(sc, 0x04c1, 0x0271); - } else { - bcw_phy_write16(sc, 0x04c0, 0x0098); - bcw_phy_write16(sc, 0x04c1, 0x0070); - bcw_phy_write16(sc, 0x04c9, 0x0080); - } - bcw_phy_write16(sc, 0x042b, bcw_phy_read16(sc, 0x042b) | - 0x0800); - - for (i = 0; i < 64; i++) - bcw_ilt_write(sc, 0x4000 + i, i); - for (i = 0; i < BCW_ILT_NOISEG2_SIZE; i++) - bcw_ilt_write(sc, 0x1800 + i, bcw_ilt_noiseg2[i]); - } - - if (sc->sc_phy_rev <= 2) - for (i = 0; i < BCW_ILT_NOISESCALEG_SIZE; i++) - bcw_ilt_write(sc, 0x1400 + i, bcw_ilt_noisescaleg1[i]); - else if ((sc->sc_phy_rev >= 7) && (bcw_phy_read16(sc, 0x0449) & 0x0200)) - for (i = 0; i < BCW_ILT_NOISESCALEG_SIZE; i++) - bcw_ilt_write(sc, 0x1400 + i, bcw_ilt_noisescaleg3[i]); - else - for (i = 0; i < BCW_ILT_NOISESCALEG_SIZE; i++) - bcw_ilt_write(sc, 0x1400 + i, bcw_ilt_noisescaleg2[i]); - - if (sc->sc_phy_rev == 2) - for (i = 0; i < BCW_ILT_SIGMASQR_SIZE; i++) - bcw_ilt_write(sc, 0x5000 + i, bcw_ilt_sigmasqr1[i]); - else if ((sc->sc_phy_rev > 2) && (sc->sc_phy_rev <= 8)) - for (i = 0; i < BCW_ILT_SIGMASQR_SIZE; i++) - bcw_ilt_write(sc, 0x5000 + i, bcw_ilt_sigmasqr2[i]); - - if (sc->sc_phy_rev == 1) { - for (i = 0; i < BCW_ILT_RETARD_SIZE; i++) - bcw_ilt_write(sc, 0x2400 + i, bcw_ilt_retard[i]); - for (i = 0; i < 4; i++) { - bcw_ilt_write(sc, 0x5404 + i, 0x0020); - bcw_ilt_write(sc, 0x5408 + i, 0x0020); - bcw_ilt_write(sc, 0x540c + i, 0x0020); - bcw_ilt_write(sc, 0x5410 + i, 0x0020); - } - bcw_phy_agcsetup(sc); - - if (sc->sc_board_vendor == PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0416 && - sc->sc_board_rev == 0x0017) - return; - - bcw_ilt_write(sc, 0x5001, 0x0002); - bcw_ilt_write(sc, 0x5002, 0x0001); - } else { - for (i = 0; i <= 0x2f; i++) - bcw_ilt_write(sc, 0x1000 + i, 0x0820); - bcw_phy_agcsetup(sc); - bcw_phy_read16(sc, 0x0400); - bcw_phy_write16(sc, 0x0403, 0x1000); - bcw_ilt_write(sc, 0x3c02, 0x000f); - bcw_ilt_write(sc, 0x3c03, 0x0014); - - if (sc->sc_board_vendor == PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0416 && - sc->sc_board_rev == 0x0017) - return; - - bcw_ilt_write(sc, 0x0401, 0x0002); - bcw_ilt_write(sc, 0x0402, 0x0001); - } -} - -void -bcw_phy_calc_loopback_gain(struct bcw_softc *sc) -{ - uint16_t backup_phy[15]; - uint16_t backup_radio[3]; - uint16_t backup_bband; - uint16_t i; - uint16_t loop1_cnt, loop1_done, loop1_omitted; - uint16_t loop2_done; - - backup_phy[0] = bcw_phy_read16(sc, 0x0429); - backup_phy[1] = bcw_phy_read16(sc, 0x0001); - backup_phy[2] = bcw_phy_read16(sc, 0x0811); - backup_phy[3] = bcw_phy_read16(sc, 0x0812); - backup_phy[4] = bcw_phy_read16(sc, 0x0814); - backup_phy[5] = bcw_phy_read16(sc, 0x0815); - backup_phy[6] = bcw_phy_read16(sc, 0x005a); - backup_phy[7] = bcw_phy_read16(sc, 0x0059); - backup_phy[8] = bcw_phy_read16(sc, 0x0058); - backup_phy[9] = bcw_phy_read16(sc, 0x000a); - backup_phy[10] = bcw_phy_read16(sc, 0x0003); - backup_phy[11] = bcw_phy_read16(sc, 0x080f); - backup_phy[12] = bcw_phy_read16(sc, 0x0810); - backup_phy[13] = bcw_phy_read16(sc, 0x002b); - backup_phy[14] = bcw_phy_read16(sc, 0x0015); - bcw_phy_read16(sc, 0x002d); - backup_bband = sc->sc_radio_baseband_atten; - backup_radio[0] = bcw_radio_read16(sc, 0x0052); - backup_radio[1] = bcw_radio_read16(sc, 0x0043); - backup_radio[2] = bcw_radio_read16(sc, 0x007a); - - bcw_phy_write16(sc, 0x0429, bcw_phy_read16(sc, 0x0429) & 0x3fff); - bcw_phy_write16(sc, 0x0001, bcw_phy_read16(sc, 0x0001) & 0x8000); - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) & 0x0002); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) & 0xfffd); - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) & 0x0001); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) & 0xfffe); - bcw_phy_write16(sc, 0x0814, bcw_phy_read16(sc, 0x0814) & 0x0001); - bcw_phy_write16(sc, 0x0815, bcw_phy_read16(sc, 0x0815) & 0xfffe); - bcw_phy_write16(sc, 0x0814, bcw_phy_read16(sc, 0x0814) & 0x0002); - bcw_phy_write16(sc, 0x0815, bcw_phy_read16(sc, 0x0815) & 0xfffd); - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) & 0x000c); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) & 0x000c); - - bcw_phy_write16(sc, 0x0811, (bcw_phy_read16(sc, 0x0811) & 0xffcf) | - 0x0030); - bcw_phy_write16(sc, 0x0812, (bcw_phy_read16(sc, 0x0812) & 0xffcf) | - 0x0010); - - bcw_phy_write16(sc, 0x005a, 0x0780); - bcw_phy_write16(sc, 0x0059, 0xc810); - bcw_phy_write16(sc, 0x0058, 0x000d); - if (sc->sc_phy_ver == 9) - bcw_phy_write16(sc, 0x0003, 0x0122); - else - bcw_phy_write16(sc, 0x000a, bcw_phy_read16(sc, 0x000a) | - 0x2000); - bcw_phy_write16(sc, 0x0814, bcw_phy_read16(sc, 0x0814) | 0x0004); - bcw_phy_write16(sc, 0x0815, bcw_phy_read16(sc, 0x0815) & 0xfffb); - bcw_phy_write16(sc, 0x0003, (bcw_phy_read16(sc, 0x0003) & 0xff9f) | - 0x0040); - if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev == 2) { - bcw_radio_write16(sc, 0x0052, 0x0000); - bcw_radio_write16(sc, 0x0043, (bcw_radio_read16(sc, 0x0043) & - 0xfff0) | 0x0009); - loop1_cnt = 9; - } else if (sc->sc_radio_rev == 8) { - bcw_radio_write16(sc, 0x0043, 0x000f); - loop1_cnt = 15; - } else - loop1_cnt = 0; - - bcw_phy_set_baseband_atten(sc, 11); - - if (sc->sc_phy_rev >= 3) - bcw_phy_write16(sc, 0x080f, 0xc020); - else - bcw_phy_write16(sc, 0x080f, 0x8020); - bcw_phy_write16(sc, 0x0810, 0x0000); - - bcw_phy_write16(sc, 0x002b, (bcw_phy_read16(sc, 0x002b) & 0xffc0) | - 0x0001); - bcw_phy_write16(sc, 0x002b, (bcw_phy_read16(sc, 0x002b) & 0xc0ff) | - 0x0800); - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) | 0x0100); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) | 0xcfff); - if (sc->sc_sprom.boardflags & BCW_BF_EXTLNA) { - if (sc->sc_phy_rev >= 7) { - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) | - 0x0800); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) | - 0x8000); - } - } - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) & 0x00f7); - - for (i = 0; i < loop1_cnt; i++) { - bcw_radio_write16(sc, 0x0043, loop1_cnt); - bcw_phy_write16(sc, 0x0812, (bcw_phy_read16(sc, 0x0812) & - 0xf0ff) | (i << 8)); - bcw_phy_write16(sc, 0x0015, (bcw_phy_read16(sc, 0x0015) & - 0x0fff) | 0xa000); - bcw_phy_write16(sc, 0x0015, (bcw_phy_read16(sc, 0x0015) & - 0x0fff) | 0xf000); - delay(20); - if (bcw_phy_read16(sc, 0x0002d) >= 0x0dfc) - break; - } - loop1_done = i; - loop1_omitted = loop1_cnt - loop1_done; - - loop2_done = 0; - if (loop1_done >= 8) { - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) | - 0x0030); - for (i = loop1_done - 8; i < 16; i++) { - bcw_phy_write16(sc, 0x0812, - (bcw_phy_read16(sc, 0x0812) & 0xf0ff) | (i << 8)); - bcw_phy_write16(sc, 0x0015, - (bcw_phy_read16(sc, 0x0015) & 0x0fff) | 0xa000); - bcw_phy_write16(sc, 0x0015, - (bcw_phy_read16(sc, 0x0015) & 0x0fff) | 0xf000); - delay(20); - if (bcw_phy_read16(sc, 0x002d) >= 0x0dfc) - break; - } - } - - bcw_phy_write16(sc, 0x0814, backup_phy[4]); - bcw_phy_write16(sc, 0x0815, backup_phy[5]); - bcw_phy_write16(sc, 0x005a, backup_phy[6]); - bcw_phy_write16(sc, 0x0059, backup_phy[7]); - bcw_phy_write16(sc, 0x0058, backup_phy[8]); - bcw_phy_write16(sc, 0x000a, backup_phy[9]); - bcw_phy_write16(sc, 0x0003, backup_phy[10]); - bcw_phy_write16(sc, 0x080f, backup_phy[11]); - bcw_phy_write16(sc, 0x0810, backup_phy[12]); - bcw_phy_write16(sc, 0x002b, backup_phy[13]); - bcw_phy_write16(sc, 0x0015, backup_phy[14]); - - bcw_phy_set_baseband_atten(sc, backup_bband); - - bcw_radio_write16(sc, 0x0052, backup_radio[0]); - bcw_radio_write16(sc, 0x0043, backup_radio[1]); - bcw_radio_write16(sc, 0x007a, backup_radio[2]); - - bcw_phy_write16(sc, 0x0811, backup_phy[2] | 0x0003); - delay(10); - bcw_phy_write16(sc, 0x0811, backup_phy[2]); - bcw_phy_write16(sc, 0x0812, backup_phy[3]); - bcw_phy_write16(sc, 0x0429, backup_phy[0]); - bcw_phy_write16(sc, 0x0001, backup_phy[1]); - - sc->sc_phy_loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - - 11; - sc->sc_phy_loopback_gain[1] = (24 - (3 * loop2_done)) * 2; -} - -void -bcw_phy_agcsetup(struct bcw_softc *sc) -{ - uint16_t offset = 0; - - if (sc->sc_phy_rev == 1) - offset = 0x4c00; - - bcw_ilt_write(sc, offset, 0x00fe); - bcw_ilt_write(sc, offset + 1, 0x000d); - bcw_ilt_write(sc, offset + 2, 0x0013); - bcw_ilt_write(sc, offset + 3, 0x0019); - - if (sc->sc_phy_rev == 1) { - bcw_ilt_write(sc, 0x1800, 0x2710); - bcw_ilt_write(sc, 0x1801, 0x9b83); - bcw_ilt_write(sc, 0x1802, 0x9b83); - bcw_ilt_write(sc, 0x1803, 0x0f8d); - bcw_phy_write16(sc, 0x0455, 0x0004); - } - - bcw_phy_write16(sc, 0x04a5, (bcw_phy_read16(sc, 0x04a5) & 0x00ff) | - 0x5700); - bcw_phy_write16(sc, 0x041a, (bcw_phy_read16(sc, 0x041a) & 0xff80) | - 0x000f); - bcw_phy_write16(sc, 0x041a, (bcw_phy_read16(sc, 0x041a) & 0xc07f) | - 0x2b80); - bcw_phy_write16(sc, 0x048c, (bcw_phy_read16(sc, 0x048c) & 0xf0ff) | - 0x0300); - - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | 0x0008); - - bcw_phy_write16(sc, 0x04a0, (bcw_phy_read16(sc, 0x04a0) & 0xfff0) | - 0x0008); - bcw_phy_write16(sc, 0x04a1, (bcw_phy_read16(sc, 0x04a1) & 0xf0ff) | - 0x0600); - bcw_phy_write16(sc, 0x04a2, (bcw_phy_read16(sc, 0x04a2) & 0xf0ff) | - 0x0700); - bcw_phy_write16(sc, 0x04a0, (bcw_phy_read16(sc, 0x04a0) & 0xf0ff) | - 0x0100); - - if (sc->sc_phy_rev == 1) - bcw_phy_write16(sc, 0x04a2, (bcw_phy_read16(sc, 0x4a2) & - 0xfff0) | 0x0007); - - bcw_phy_write16(sc, 0x0488, (bcw_phy_read16(sc, 0x0488) & 0xff00) | - 0x001c); - bcw_phy_write16(sc, 0x0488, (bcw_phy_read16(sc, 0x0488) & 0xc0ff) | - 0x0200); - bcw_phy_write16(sc, 0x0496, (bcw_phy_read16(sc, 0x0496) & 0xff00) | - 0x001c); - bcw_phy_write16(sc, 0x0489, (bcw_phy_read16(sc, 0x0489) & 0xff00) | - 0x0020); - bcw_phy_write16(sc, 0x0489, (bcw_phy_read16(sc, 0x0489) & 0xc0ff) | - 0x0200); - bcw_phy_write16(sc, 0x0482, (bcw_phy_read16(sc, 0x0482) & 0xff00) | - 0x001c); - bcw_phy_write16(sc, 0x0496, (bcw_phy_read16(sc, 0x0496) & 0x00ff) | - 0x1a00); - bcw_phy_write16(sc, 0x0481, (bcw_phy_read16(sc, 0x0481) & 0xff00) | - 0x0028); - bcw_phy_write16(sc, 0x0481, (bcw_phy_read16(sc, 0x0481) & 0x00ff) | - 0x2c00); - - if (sc->sc_phy_rev == 1) { - bcw_phy_write16(sc, 0x0430, 0x092b); - bcw_phy_write16(sc, 0x041b, (bcw_phy_read16(sc, 0x041b) & - 0xffe1) | 0x0002); - } else { - bcw_phy_write16(sc, 0x041b, bcw_phy_read16(sc, 0x41b) & - 0xffe1); - bcw_phy_write16(sc, 0x041f, 0x287a); - bcw_phy_write16(sc, 0x0420, (bcw_phy_read16(sc, 0x0420) & - 0xfff0) | 0x0004); - } - - if (sc->sc_phy_rev > 2) { - bcw_phy_write16(sc, 0x0422, 0x287a); - bcw_phy_write16(sc, 0x0420, (bcw_phy_read16(sc, 0x0420) & - 0x0fff) | 0x3000); - } - - bcw_phy_write16(sc, 0x04a8, (bcw_phy_read16(sc, 0x04a8) & 0x8080) | - 0x7874); - bcw_phy_write16(sc, 0x048e, 0x1c00); - - if (sc->sc_phy_rev == 1) { - bcw_phy_write16(sc, 0x04ab, (bcw_phy_read16(sc, 0x04ab) & - 0xf0ff) | 0x0600); - bcw_phy_write16(sc, 0x048b, 0x005e); - bcw_phy_write16(sc, 0x048c, (bcw_phy_read16(sc, 0x048c) & - 0xff00) | 0x001e); - bcw_phy_write16(sc, 0x048d, 0x0002); - } - - bcw_ilt_write(sc, offset + 0x0800, 0); - bcw_ilt_write(sc, offset + 0x0801, 7); - bcw_ilt_write(sc, offset + 0x0802, 16); - bcw_ilt_write(sc, offset + 0x0803, 28); -} - -void -bcw_phy_init_pctl(struct bcw_softc *sc) -{ - uint16_t saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; - int must_reset_txpower = 0; - - if (sc->sc_board_vendor == PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0416) - return; - - BCW_WRITE16(sc, 0x03e6, BCW_READ16(sc, 0x03e6) & 0xffdf); - bcw_phy_write16(sc, 0x0028, 0x8018); - - if (sc->sc_phy_type == BCW_PHY_TYPEG) { - if (!sc->sc_phy_connected) - return; - bcw_phy_write16(sc, 0x047a, 0xc111); - } - if (sc->sc_phy_savedpctlreg != 0xffff) - return; - - if (sc->sc_phy_type == BCW_PHY_TYPEB && - sc->sc_phy_rev >= 2 && - sc->sc_radio_ver == 0x2050) { - bcw_radio_write16(sc, 0x0076, bcw_radio_read16(sc, 0x0076) | - 0x0084); - } else { - saved_batt = sc->sc_radio_baseband_atten; - saved_ratt = sc->sc_radio_radio_atten; - saved_txctl1 = sc->sc_radio_txctl1; - if ((sc->sc_radio_rev >= 6) && (sc->sc_radio_rev <= 8)) - bcw_radio_set_txpower_bg(sc, 0xb, 0x1f, 0); - else - bcw_radio_set_txpower_bg(sc, 0xb, 9, 0); - must_reset_txpower = 1; - } - bcw_dummy_transmission(sc); - - sc->sc_phy_savedpctlreg = bcw_phy_read16(sc, BCW_PHY_G_PCTL); - - if (must_reset_txpower) - bcw_radio_set_txpower_bg(sc, saved_batt, saved_ratt, - saved_txctl1); - else - bcw_radio_write16(sc, 0x0076, bcw_radio_read16(sc, 0x0076) & - 0xff7b); - bcw_radio_clear_tssi(sc); -} - -void -bcw_phy_init_noisescaletbl(struct bcw_softc *sc) -{ - int i; - - bcw_phy_write16(sc, BCW_PHY_ILT_A_CTRL, 0x1400); - for (i = 0; i < 12; i++) { - if (sc->sc_phy_rev == 2) - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x6767); - else - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x2323); - } - - if (sc->sc_phy_rev == 2) - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x6700); - else - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x2300); - - for (i = 0; i < 11; i++) { - if (sc->sc_phy_rev == 2) - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x6767); - else - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x0023); - } - - if (sc->sc_phy_rev == 2) - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x0067); - else - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, 0x0023); -} - -void -bcw_phy_set_baseband_atten(struct bcw_softc *sc, - uint16_t baseband_atten) -{ - uint16_t val; - - if (sc->sc_phy_ver == 0) { - val = (BCW_READ16(sc, 0x03e6) & 0xfff0); - val |= (baseband_atten & 0x000f); - BCW_WRITE16(sc, 0x03e6, val); - return; - } - - if (sc->sc_phy_ver > 1) { - val = bcw_phy_read16(sc, 0x0060) & ~0x003c; - val |= (baseband_atten << 2) & 0x003c; - } else { - val = bcw_phy_read16(sc, 0x0060) & ~0x0078; - val |= (baseband_atten << 3) & 0x0078; - } - bcw_phy_write16(sc, 0x0060, val); -} - -int8_t -bcw_phy_estimate_powerout(struct bcw_softc *sc, int8_t tssi) -{ - int8_t dbm = 0; - int32_t tmp; - - tmp = sc->sc_phy_idle_tssi; - tmp += tssi; - tmp -= sc->sc_phy_savedpctlreg; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - tmp += 0x80; - tmp = bcw_lv(tmp, 0x00, 0xff); - //dbm = sc->sc_phy_tssi2dbm[tmp]; /* XXX */ - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: - tmp = bcw_lv(tmp, 0x00, 0x3f); - //dbm = sc->sc_phy_tssi2dbm[tmp]; /* XXX "/ - break; - default: - /* XXX panic()? */ - break; - } - - return (dbm); -} - -void -bcw_phy_xmitpower(struct bcw_softc *sc) -{ - if (sc->sc_phy_savedpctlreg == 0xffff) - return; - if (sc->sc_board_type == 0x0416 && - sc->sc_board_vendor == PCI_VENDOR_BROADCOM) - return; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - /* nohting todo for A PHYs yet */ - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: { - uint16_t tmp; - uint16_t txpower; - int8_t v0, v1, v2, v3; - int8_t average; - uint8_t max_pwr; - int16_t desired_pwr, estimated_pwr, pwr_adjust; - int16_t radio_att_delta, baseband_att_delta; - int16_t radio_attenuation, baseband_attenuation; - - tmp = bcw_shm_read16(sc, BCW_SHM_SHARED, 0x0058); - v0 = (int8_t)(tmp & 0x00ff); - v1 = (int8_t)((tmp & 0xff00) >> 8); - tmp = bcw_shm_read16(sc, BCW_SHM_SHARED, 0x005a); - v2 = (int8_t)(tmp & 0x00ff); - v3 = (int8_t)((tmp & 0xff00) >> 8); - tmp = 0; - - if (v0 == 0x7f || v1 == 0x7f || v2 == 0x7f || v3 == 0x07) { - tmp = bcw_shm_read16(sc, BCW_SHM_SHARED, - 0x0070); - v0 = (int8_t)(tmp & 0x00ff); - v1 = (int8_t)((tmp & 0xff00) >> 8); - tmp = bcw_shm_read16(sc, BCW_SHM_SHARED, - 0x0072); - - v2 = (int8_t)(tmp & 0x00ff); - v3 = (int8_t)((tmp & 0xff00) >> 8); - if (v0 == 0x7f || v1 == 0x7f || v2 == 0x7f || - v3 == 0x7f) - return; - v0 = (v0 + 0x20) & 0x3f; - v1 = (v1 + 0x20) & 0x3f; - v2 = (v2 + 0x20) & 0x3f; - v3 = (v3 + 0x20) & 0x3f; - tmp = 1; - } - bcw_radio_clear_tssi(sc); - - average = (v0 + v1 + v2 + v3 + 2) / 4; - - if (tmp && (bcw_shm_read16(sc, BCW_SHM_SHARED, 0x005e) & - 0x8)) - average -= 13; - - bcw_phy_estimate_powerout(sc, average); - - if ((sc->sc_sprom.boardflags & BCW_BF_PACTRL) && - (sc->sc_phy_type == BCW_PHY_TYPEG)) - max_pwr -= 0x3; - - desired_pwr = bcw_lv(sc->sc_radio_txpower_desired, 0, max_pwr); - /* check if we need to adjust the current power */ - pwr_adjust = desired_pwr - estimated_pwr; - radio_att_delta = -(pwr_adjust + 7) >> 3; - baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); - if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { - bcw_phy_lo_mark_current_used(sc); - return; - } - - /* calculate the new attenuation values */ - baseband_attenuation = sc->sc_radio_baseband_atten; - baseband_attenuation += baseband_att_delta; - radio_attenuation = sc->sc_radio_radio_atten; - radio_attenuation += radio_att_delta; - - if (radio_attenuation < 0) { - baseband_attenuation -= (4 * -radio_attenuation); - radio_attenuation = 0; - } else if (radio_attenuation > 9) { - baseband_attenuation += (4 * (radio_attenuation - 9)); - radio_attenuation = 9; - } else { - while (baseband_attenuation < 0 && - radio_attenuation > 0) { - baseband_attenuation += 4; - radio_attenuation--; - } - while (baseband_attenuation > 11 && - radio_attenuation < 9) { - baseband_attenuation -= 4; - radio_attenuation++; - } - } - baseband_attenuation = bcw_lv(baseband_attenuation, 0, 11); - - txpower = sc->sc_radio_txctl1; - if ((sc->sc_radio_ver == 0x02050) && (sc->sc_radio_rev == 2)) { - if (radio_attenuation <= 1) { - if (txpower == 0) { - txpower = 3; - radio_attenuation += 2; - baseband_attenuation += 2; - } else if (sc->sc_sprom.boardflags & - BCW_BF_PACTRL) { - baseband_attenuation += 4 * - (radio_attenuation - 2); - radio_attenuation = 2; - } - } else if (radio_attenuation > 4 && txpower != 0) { - txpower = 0; - if (baseband_attenuation < 3) { - radio_attenuation -= 3; - baseband_attenuation += 2; - } else { - radio_attenuation -= 2; - baseband_attenuation -= 2; - } - } - } - sc->sc_radio_txctl1 = txpower; - baseband_attenuation = bcw_lv(baseband_attenuation, 0, 11); - radio_attenuation = bcw_lv(radio_attenuation, 0, 9); - - bcw_phy_lock(sc); - bcw_radio_lock(sc); - bcw_radio_set_txpower_bg(sc, baseband_attenuation, - radio_attenuation, txpower); - bcw_phy_lo_mark_current_used(sc); - bcw_radio_unlock(sc); - bcw_phy_unlock(sc); - break; - } - default: - /* XXX panic()? */ - break; - } -} - -uint16_t -bcw_phy_lo_b_r15_loop(struct bcw_softc *sc) -{ - int i; - uint16_t r = 0; - - /* XXX splnet()? */ - for (i = 0; i < 10; i++) { - bcw_phy_write16(sc, 0x0015, 0xafa0); - delay(1); - bcw_phy_write16(sc, 0x0015, 0xefa0); - delay(10); - bcw_phy_write16(sc, 0x0015, 0xffa0); - delay(40); - r += bcw_phy_read16(sc, 0x002c); - } - /* XXX splnet()? */ - - return (r); -} - -void -bcw_phy_lo_b_measure(struct bcw_softc *sc) -{ - uint16_t regstack[12] = { 0 }; - uint16_t mls; - uint16_t fval; - int i, j; - - regstack[0] = bcw_phy_read16(sc, 0x0015); - regstack[1] = bcw_radio_read16(sc, 0x0052) & 0xfff0; - - if (sc->sc_radio_ver == 0x2053) { - regstack[2] = bcw_phy_read16(sc, 0x000a); - regstack[3] = bcw_phy_read16(sc, 0x002a); - regstack[4] = bcw_phy_read16(sc, 0x0035); - regstack[5] = bcw_phy_read16(sc, 0x0003); - regstack[6] = bcw_phy_read16(sc, 0x0001); - regstack[7] = bcw_phy_read16(sc, 0x0030); - - regstack[8] = bcw_radio_read16(sc, 0x0043); - regstack[9] = bcw_radio_read16(sc, 0x007a); - regstack[10] = BCW_READ16(sc, 0x03ec); - regstack[11] = bcw_radio_read16(sc, 0x0052) & 0x00f0; - - bcw_phy_write16(sc, 0x0030, 0x00ff); - BCW_WRITE16(sc, 0x3ec, 0x3f3f); - bcw_phy_write16(sc, 0x0035, regstack[4] & 0xff7f); - bcw_radio_write16(sc, 0x007a, regstack[9] & 0xfff0); - } - bcw_phy_write16(sc, 0x0015, 0xb000); - bcw_phy_write16(sc, 0x002b, 0x0004); - - if (sc->sc_radio_ver == 0x2053) { - bcw_phy_write16(sc, 0x002b, 0x0203); - bcw_phy_write16(sc, 0x002a, 0x08a3); - } - - sc->sc_phy_minlowsig[0] = 0xffff; - - for (i = 0; i < 4; i++) { - bcw_radio_write16(sc, 0x0052, regstack[1] | i); - bcw_phy_lo_b_r15_loop(sc); - } - for (i = 0; i < 10; i++) { - bcw_radio_write16(sc, 0x0052, regstack[1] | i); - mls = bcw_phy_lo_b_r15_loop(sc) / 10; - if (mls < sc->sc_phy_minlowsig[0]) { - sc->sc_phy_minlowsig[0] = mls; - sc->sc_phy_minlowsigpos[0] = i; - } - } - bcw_radio_write16(sc, 0x0052, regstack[1] | sc->sc_phy_minlowsigpos[0]); - - sc->sc_phy_minlowsig[1] = 0xffff; - - for (i = -4; i < 5; i += 2) { - for (j = -4; j < 5; j += 2) { - if (j < 0) - fval = (0x0100 * i) + j + 0x0100; - else - fval = (0x0100 * i) + j; - bcw_phy_write16(sc, 0x002f, fval); - mls = bcw_phy_lo_b_r15_loop(sc) / 10; - if (mls < sc->sc_phy_minlowsig[1]) { - sc->sc_phy_minlowsig[1] = mls; - sc->sc_phy_minlowsigpos[1] = fval; - } - } - } - sc->sc_phy_minlowsigpos[1] += 0x0101; - - bcw_phy_write16(sc, 0x002f, sc->sc_phy_minlowsigpos[1]); - if (sc->sc_radio_ver == 0x2053) { - bcw_phy_write16(sc, 0x000a, regstack[2]); - bcw_phy_write16(sc, 0x002a, regstack[3]); - bcw_phy_write16(sc, 0x0035, regstack[4]); - bcw_phy_write16(sc, 0x0003, regstack[5]); - bcw_phy_write16(sc, 0x0001, regstack[6]); - bcw_phy_write16(sc, 0x0030, regstack[7]); - - bcw_radio_write16(sc, 0x0043, regstack[8]); - bcw_radio_write16(sc, 0x007a, regstack[9]); - - bcw_radio_write16(sc, 0x0052, (bcw_radio_read16(sc, 0x0052) & - 0x000f) | regstack[11]); - BCW_WRITE16(sc, 0x03ec, regstack[10]); - } - bcw_phy_write16(sc, 0x0015, regstack[0]); -} - -void -bcw_phy_lo_g_state(struct bcw_softc *sc, struct bcw_lopair *in_pair, - struct bcw_lopair *out_pair, uint16_t r27) -{ - const struct bcw_lopair transitions[8] = { - { .high = 1, .low = 1, }, - { .high = 1, .low = 0, }, - { .high = 1, .low = -1, }, - { .high = 0, .low = -1, }, - { .high = -1, .low = -1, }, - { .high = -1, .low = 0, }, - { .high = -1, .low = 1, }, - { .high = 0, .low = 1, } }; - struct bcw_lopair lowest_transition = { - .high = in_pair->high, - .low = in_pair->low }; - struct bcw_lopair tmp_pair; - struct bcw_lopair transition; - int i = 12; - int state = 0; - int found_lower; - int j, begin, end; - uint32_t lowest_deviation; - uint32_t tmp; - - bcw_phy_lo_write(sc, &lowest_transition); - lowest_deviation = bcw_phy_lo_g_singledeviation(sc, r27); - do { - found_lower = 0; - if (state == 0) { - begin = 1; - end = 8; - } else if (state % 2 == 0) { - begin = state - 1; - end = state + 1; - } else { - begin = state - 2; - end = state + 2; - } - if (begin < 1) - begin += 8; - if (end > 8) - end -= 8; - - j = begin; - tmp_pair.high = lowest_transition.high; - tmp_pair.low = lowest_transition.low; - while (1) { - transition.high = tmp_pair.high + - transitions[j - 1].high; - transition.low = tmp_pair.low + - transitions[j - 1].low; - if ((abs(transition.low) < 9) && (abs(transition.high) - < 9)) { - bcw_phy_lo_write(sc, &transition); - tmp = bcw_phy_lo_g_singledeviation(sc, r27); - if (tmp < lowest_deviation) { - lowest_deviation = tmp; - state = j; - found_lower = 1; - lowest_transition.high = - transition.high; - lowest_transition.low = - transition.low; - } - } - if (j == end) - break; - if (j == 8) - j = 1; - else - j++; - } - } while (i-- && found_lower); - - out_pair->high = lowest_transition.high; - out_pair->low = lowest_transition.low; -} - -void -bcw_phy_lo_g_measure(struct bcw_softc *sc) -{ - const uint8_t pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; - const int is_initializing = 0; /* XXX */ - uint16_t h, i, oldi = 0, j; - struct bcw_lopair control; - struct bcw_lopair *tmp_control; - uint16_t tmp; - uint16_t regstack[16] = { 0 }; - uint16_t oldchannel; - uint8_t r27 = 0, r31; - - oldchannel = sc->sc_radio_channel; - /* setup */ - if (sc->sc_phy_connected) { - regstack[0] = bcw_phy_read16(sc, BCW_PHY_G_CRS); - regstack[1] = bcw_phy_read16(sc, 0x0802); - bcw_phy_write16(sc, BCW_PHY_G_CRS, regstack[0] & 0x7fff); - bcw_phy_write16(sc, 0x0802, regstack[1] & 0xfffc); - } - regstack[3] = BCW_READ16(sc, 0x03e2); - BCW_WRITE16(sc, 0x03e2, regstack[3] | 0x8000); - regstack[4] = BCW_READ16(sc, BCW_MMIO_CHANNEL_EXT); - regstack[5] = bcw_phy_read16(sc, 0x15); - regstack[6] = bcw_phy_read16(sc, 0x2a); - regstack[7] = bcw_phy_read16(sc, 0x35); - regstack[8] = bcw_phy_read16(sc, 0x60); - regstack[9] = bcw_radio_read16(sc, 0x43); - regstack[10] = bcw_radio_read16(sc, 0x7a); - regstack[11] = bcw_radio_read16(sc, 0x52); - if (sc->sc_phy_connected) { - regstack[12] = bcw_phy_read16(sc, 0x0811); - regstack[13] = bcw_phy_read16(sc, 0x0812); - regstack[14] = bcw_phy_read16(sc, 0x0814); - regstack[15] = bcw_phy_read16(sc, 0x0815); - } - bcw_radio_select_channel(sc, 6, 0); - if (sc->sc_phy_connected) { - bcw_phy_write16(sc, BCW_PHY_G_CRS, regstack[0] & 0x7fff); - bcw_phy_write16(sc, 0x0802, regstack[1] & 0xfffc); - bcw_dummy_transmission(sc); - } - bcw_radio_write16(sc, 0x0043, 0x0006); - - bcw_phy_set_baseband_atten(sc, 2); - - BCW_WRITE16(sc, BCW_MMIO_CHANNEL_EXT, 0); - bcw_phy_write16(sc, 0x002e, 0x007f); - bcw_phy_write16(sc, 0x080f, 0x0078); - bcw_phy_write16(sc, 0x0035, regstack[7] & ~(1 << 7)); - bcw_radio_write16(sc, 0x007a, regstack[10] & 0xfff0); - bcw_phy_write16(sc, 0x002b, 0x0203); - bcw_phy_write16(sc, 0x002a, 0x08a3); - if (sc->sc_phy_type) { - bcw_phy_write16(sc, 0x0814, regstack[14] | 0x0003); - bcw_phy_write16(sc, 0x0815, regstack[15] & 0xfffc); - bcw_phy_write16(sc, 0x0811, 0x01b3); - bcw_phy_write16(sc, 0x0812, 0x00b2); - } - if (is_initializing) - bcw_phy_lo_g_measure_txctl2(sc); - - bcw_phy_write16(sc, 0x080f, 0x8078); - - /* measure */ - control.low = 0; - control.high = 0; - for (h = 0; h < 10; h++) { - /* loop over each possible RadioAttenuation (0 - 9) */ - i = pairorder[h]; - if (is_initializing) { - if (i == 3) { - control.low = 0; - control.high = 0; - } else if (((i % 2 == 1) && (oldi % 2 == 1)) || - ((i % 2 == 0) && (oldi % 2 == 0))) { - tmp_control = bcw_get_lopair(sc, oldi, 0); - memcpy(&control, tmp_control, sizeof(control)); - } else { - tmp_control = bcw_get_lopair(sc, 3, 0); - memcpy(&control, tmp_control, sizeof(control)); - } - } - /* loop over each possible BasebandAttenuation / 2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp = i * 2 + j; - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = bcw_get_lopair(sc, i, j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - bcw_radio_write16(sc, 0x43, i); - bcw_radio_write16(sc, 0x52, sc->sc_radio_txctl2); - delay(10); - - bcw_phy_set_baseband_atten(sc, j * 2); - - tmp = (regstack[10] & 0xfff0); - if (r31) - tmp |= 0x0008; - bcw_radio_write16(sc, 0x007a, tmp); - - tmp_control = bcw_get_lopair(sc, i, j * 2); - bcw_phy_lo_g_state(sc, &control, tmp_control, r27); - } - oldi = i; - } - /* loop over each possible RadioAttenuation (10 - 13) */ - for (i = 10; i < 14; i++) { - /* loop over each possible BasebandAttenuation / 2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp_control = bcw_get_lopair(sc, i - 9, j * 2); - memcpy(&control, tmp_control, sizeof(control)); - tmp = (i - 9) * 2 + j - 5; /* XXX */ - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = bcw_get_lopair(sc, i - 9, j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - bcw_radio_write16(sc, 0x043, i - 9); - bcw_radio_write16(sc, 0x052, sc->sc_radio_txctl2 | - (3 << 4)); /* XXX */ - delay(10); - - bcw_phy_set_baseband_atten(sc, j * 2); - - tmp = (regstack[10] & 0xfff0); - if (r31) - tmp |= 0x0008; - bcw_radio_write16(sc, 0x7a, tmp); - - tmp_control = bcw_get_lopair(sc, i, j * 2); - bcw_phy_lo_g_state(sc, &control, tmp_control, r27); - } - - } - - /* restoration */ - if (sc->sc_phy_connected) { - bcw_phy_write16(sc, 0x0015, 0xe300); - bcw_phy_write16(sc, 0x0812, (r27 << 8) | 0xa0); - delay(5); - bcw_phy_write16(sc, 0x0812, (r27 << 8) | 0xa2); - delay(2); - bcw_phy_write16(sc, 0x0812, (r27 << 8) | 0xa3); - } else - bcw_phy_write16(sc, 0x0015, r27 | 0xefa0); - bcw_phy_lo_adjust(sc, is_initializing); - bcw_phy_write16(sc, 0x002e, 0x807f); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x002f, 0x0202); - else - bcw_phy_write16(sc, 0x002f, 0x0101); - bcw_phy_write16(sc, BCW_MMIO_CHANNEL_EXT, regstack[4]); - bcw_phy_write16(sc, 0x0015, regstack[5]); - bcw_phy_write16(sc, 0x0015, regstack[6]); - bcw_phy_write16(sc, 0x0015, regstack[7]); - bcw_phy_write16(sc, 0x0015, regstack[8]); - bcw_radio_write16(sc, 0x0043, regstack[9]); - bcw_radio_write16(sc, 0x007a, regstack[10]); - regstack[11] &= 0x00f0; - regstack[11] |= (bcw_radio_read16(sc, 0x52) & 0x000f); - bcw_radio_write16(sc, 0x52, regstack[11]); - BCW_WRITE16(sc, 0x03e2, regstack[3]); - if (sc->sc_phy_connected) { - bcw_phy_write16(sc, 0x0811, regstack[12]); - bcw_phy_write16(sc, 0x0812, regstack[13]); - bcw_phy_write16(sc, 0x0814, regstack[14]); - bcw_phy_write16(sc, 0x0815, regstack[15]); - bcw_phy_write16(sc, BCW_PHY_G_CRS, regstack[0]); - bcw_phy_write16(sc, 0x0802, regstack[1]); - } - bcw_radio_select_channel(sc, oldchannel, 1); -} - -void -bcw_phy_lo_g_measure_txctl2(struct bcw_softc *sc) -{ - uint16_t txctl2 = 0, i; - uint32_t smallest, tmp; - - bcw_radio_write16(sc, 0x0052, 0); - delay(10); - smallest = bcw_phy_lo_g_singledeviation(sc, 0); - for (i = 0; i < 16; i++) { - bcw_radio_write16(sc, 0x0052, i); - delay(10); - tmp = bcw_phy_lo_g_singledeviation(sc, 0); - if (tmp < smallest) { - smallest = tmp; - txctl2 = i; - } - } - sc->sc_radio_txctl2 = txctl2; -} - -uint32_t -bcw_phy_lo_g_singledeviation(struct bcw_softc *sc, uint16_t control) -{ - int i; - uint32_t r = 0; - - for (i = 0; i < 8; i++) - r += bcw_phy_lo_g_deviation_subval(sc, control); - - return (r); -} - -uint16_t -bcw_phy_lo_g_deviation_subval(struct bcw_softc *sc, uint16_t control) -{ - uint16_t r; - //unsigned long flags; - - /* XXX splnet()? */ - - if (sc->sc_phy_connected) { - bcw_phy_write16(sc, 0x15, 0xe300); - control <<= 8; - bcw_phy_write16(sc, 0x0812, control | 0x00b0); - delay(5); - bcw_phy_write16(sc, 0x0812, control | 0x00b2); - delay(2); - bcw_phy_write16(sc, 0x0812, control | 0x00b3); - delay(4); - bcw_phy_write16(sc, 0x0015, 0xf300); - delay(8); - } else { - bcw_phy_write16(sc, 0x0015, control | 0xefa0); - delay(2); - bcw_phy_write16(sc, 0x0015, control | 0xefe0); - delay(4); - bcw_phy_write16(sc, 0x0015, control | 0xffe0); - delay(8); - } - r = bcw_phy_read16(sc, 0x002d); - - /* XXX splnet()? */ - - return (r); -} - -void -bcw_phy_lo_adjust(struct bcw_softc *sc, int fixed) -{ - struct bcw_lopair *pair; - - if (fixed) - pair = bcw_phy_find_lopair(sc, 2, 3, 0); - else - pair = bcw_phy_current_lopair(sc); - - bcw_phy_lo_write(sc, pair); -} - -void -bcw_phy_lo_mark_current_used(struct bcw_softc *sc) -{ - struct bcw_lopair *pair; - - pair = bcw_phy_current_lopair(sc); - pair->used = 1; -} - -void -bcw_phy_lo_write(struct bcw_softc *sc, struct bcw_lopair *pair) -{ - uint16_t val; - - val = (uint8_t)(pair->low); - val |= ((uint8_t)(pair->high)) << 8; - -#ifdef BCW_DEBUG - if (pair->low < -8 || pair->low > 8 || - pair->high < -8 || pair->high > 8) - printf("%s: writing invalid LO pair " - "low: %d, high: %d, index: %lu)\n", - pair->low, pair->high, - (unsigned long)(pair - sc->sc_phy_lopairs)); -#endif - - bcw_phy_write16(sc, BCW_PHY_G_LO_CONTROL, val); -} - -struct bcw_lopair * -bcw_phy_find_lopair(struct bcw_softc *sc, uint16_t baseband_atten, - uint16_t radio_atten, uint16_t tx) -{ - static const uint8_t dict[10] = - { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; - - if (baseband_atten > 6) - baseband_atten = 6; - - if (tx == 3) - return (bcw_get_lopair(sc, radio_atten, baseband_atten)); - - return (bcw_get_lopair(sc, dict[radio_atten], baseband_atten)); -} - -struct bcw_lopair * -bcw_phy_current_lopair(struct bcw_softc *sc) -{ - return (bcw_phy_find_lopair(sc, sc->sc_radio_baseband_atten, - sc->sc_radio_radio_atten, sc->sc_radio_txctl1)); -} - -void -bcw_phy_set_antenna_diversity(struct bcw_softc *sc) -{ - uint16_t antennadiv; - uint16_t offset; - uint16_t val; - uint32_t ucodeflags; - - if (antennadiv == 0xffff) - antennadiv = 3; - - ucodeflags = bcw_shm_read32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET); - bcw_shm_write32(sc, BCW_SHM_SHARED, BCW_UCODEFLAGS_OFFSET, - ucodeflags & ~BCW_UCODEFLAG_AUTODIV); - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - case BCW_PHY_TYPEG: - if (sc->sc_phy_type == BCW_PHY_TYPEA) - offset = 0; - else - offset = 0x0400; - - if (antennadiv == 2) - val = (3 << 7); - else - val = (antennadiv << 7); - bcw_phy_write16(sc, offset + 1, - (bcw_phy_read16(sc, offset + 1) & 0x7e7f) | val); - - if (antennadiv >= 2) { - if (antennadiv == 2) - val = (antennadiv << 7); - else - val = (0 << 7); - bcw_phy_write16(sc, offset + 0x2b, - (bcw_phy_read16(sc, offset + 0x2b) & 0xfeff) | val); - } - - if (sc->sc_phy_type == BCW_PHY_TYPEG) { - if (antennadiv >= 2) - bcw_phy_write16(sc, 0x048c, - bcw_phy_read16(sc, 0x048c) | 0x2000); - else - bcw_phy_write16(sc, 0x048c, - bcw_phy_read16(sc, 0x048c) | ~0x2000); - if (sc->sc_phy_rev >= 2) { - bcw_phy_write16(sc, 0x0461, - bcw_phy_read16(sc, 0x0461) | 0x0010); - bcw_phy_write16(sc, 0x04ad, - (bcw_phy_read16(sc, 0x04ad) & 0x00ff) | - 0x0015); - if (sc->sc_phy_rev == 2) - bcw_phy_write16(sc, 0x0427, 0x0008); - else - bcw_phy_write16(sc, 0x0427, - (bcw_phy_read16(sc, 0x0427) & - 0x00ff) | 0x0008); - } else if (sc->sc_phy_rev >= 6) - bcw_phy_write16(sc, 0x049b, 0x00dc); - } else { - if (sc->sc_phy_rev < 3) - bcw_phy_write16(sc, 0x002b, - (bcw_phy_read16(sc, 0x002b) & 0x00ff) | - 0x0024); - else { - bcw_phy_write16(sc, 0x0061, - bcw_phy_read16(sc, 0x0061) | 0x0010); - if (sc->sc_phy_rev == 3) { - bcw_phy_write16(sc, 0x0093, 0x001d); - bcw_phy_write16(sc, 0x0027, 0x0008); - } else { - bcw_phy_write16(sc, 0x0093, 0x003a); - bcw_phy_write16(sc, 0x0027, - (bcw_phy_read16(sc, 0x0027) & - 0x00ff) | 0x0008); - } - } - } - break; - case BCW_PHY_TYPEB: - if (sc->sc_core[sc->sc_currentcore].rev == 2) - val = (3 << 7); - else - val = (antennadiv << 7); - bcw_phy_write16(sc, 0x03e2, (bcw_phy_read16(sc, 0x03e2) & - 0xfe7f) | val); - break; - default: - /* XXX panic()? */ - break; - } - - if (antennadiv >= 2) { - ucodeflags = bcw_shm_read32(sc, BCW_SHM_SHARED, - BCW_UCODEFLAGS_OFFSET); - bcw_shm_write32(sc, BCW_SHM_SHARED, - BCW_UCODEFLAGS_OFFSET, ucodeflags | - BCW_UCODEFLAG_AUTODIV); - } - - sc->sc_phy_antenna_diversity = antennadiv; -} - -void -bcw_phy_calibrate(struct bcw_softc *sc) -{ - BCW_READ(sc, BCW_MMIO_SBF); - - if (sc->sc_phy_calibrated) - return; - if (sc->sc_phy_type == BCW_PHY_TYPEG && sc->sc_phy_rev == 1) { - bcw_80211_core_reset(sc, 0); - bcw_phy_initg(sc); - bcw_80211_core_reset(sc, 1); - } - sc->sc_phy_calibrated = 1; -} - -/* - * Connect the PHY - * - * http://bcm-specs.sipsolutions.net/SetPHY - */ -int -bcw_phy_connect(struct bcw_softc *sc, int connect) -{ - uint32_t flags; - - if (sc->sc_core[sc->sc_currentcore].rev < 5) - goto out; - - flags = BCW_READ(sc, BCW_CIR_SBTMSTATEHIGH); - if (connect) { - if (!(flags & 0x00010000)) - return (ENODEV); - flags = BCW_READ(sc, BCW_CIR_SBTMSTATELOW); - flags |= (0x800 << 18); - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, flags); - } else { - if (!(flags & 0x00020000)) - return (ENODEV); - flags = BCW_READ(sc, BCW_CIR_SBTMSTATELOW); - flags &= ~(0x800 << 18); - BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, flags); - } - -out: - sc->sc_phy_connected = connect; - if (connect) - DPRINTF(("%s: PHY connected\n", sc->sc_dev.dv_xname)); - else - DPRINTF(("%s: PHY disconnected\n", sc->sc_dev.dv_xname)); - - return (0); -} - -void -bcw_phy_lock(struct bcw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - - if (BCW_READ(sc, BCW_MMIO_SBF) == 0) { - sc->sc_phy_is_locked = 0; - return; - } - - if (sc->sc_core[sc->sc_currentcore].rev < 3) - bcw_mac_disable(sc); - else { - if (ic->ic_opmode != IEEE80211_M_HOSTAP) - bcw_pc_saving_ctl_bits(sc, -1, -1); - } - - sc->sc_phy_is_locked = 1; -} - -void -bcw_phy_unlock(struct bcw_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - - if (sc->sc_core[sc->sc_currentcore].rev < 3) { - if (sc->sc_phy_is_locked) - bcw_mac_enable(sc); - } else { - if (ic->ic_opmode != IEEE80211_M_HOSTAP) - bcw_pc_saving_ctl_bits(sc, -1, -1); - } - - sc->sc_phy_is_locked = 0; -} - -/* - * Radio - */ -int -bcw_radio_get(struct bcw_softc *sc) -{ - uint32_t val; - - /* - * XXX - * Query the RadioID register, on a 4317 use a lookup instead - * Different PHYs have different radio register layouts, so - * a wrapper func should be written. - * Getting the RadioID is the only 32bit operation done with the - * Radio registers, and requires seperate 16bit reads from the low - * and the high data addresses. - */ - if (sc->sc_chip_id != 0x4317) { - BCW_WRITE16(sc, BCW_MMIO_RADIO_CONTROL, BCW_RADIO_ID); - val = BCW_READ16(sc, BCW_MMIO_RADIO_DATA_HIGH); - val <<= 16; - BCW_WRITE16(sc, BCW_MMIO_RADIO_CONTROL, BCW_RADIO_ID); - sc->sc_radio_mnf = - val | BCW_READ16(sc, BCW_MMIO_RADIO_DATA_LOW); - } else { - switch (sc->sc_chip_rev) { - case 0: - sc->sc_radio_mnf = 0x3205017F; - break; - case 1: - sc->sc_radio_mnf = 0x4205017f; - break; - default: - sc->sc_radio_mnf = 0x5205017f; - } - } - - sc->sc_radio_rev = (sc->sc_radio_mnf & 0xf0000000) >> 28; - sc->sc_radio_ver = (sc->sc_radio_mnf & 0x0ffff000) >> 12; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - if (sc->sc_radio_ver != 0x2060) { - printf("%s: invalid PHY A radio 0x%x!\n", - sc->sc_dev.dv_xname, sc->sc_radio_ver); - return (1); - } - break; - case BCW_PHY_TYPEB: - if ((sc->sc_radio_ver & 0xfff0) != 0x2050) { - printf("%s: invalid PHY B radio 0x%x!\n", - sc->sc_dev.dv_xname, sc->sc_radio_ver); - return (1); - } - break; - case BCW_PHY_TYPEG: - if (sc->sc_radio_ver != 0x2050) { - printf("%s: invalid PHY G radio 0x%x!\n", - sc->sc_dev.dv_xname, sc->sc_radio_ver); - return (1); - } - break; - } - - DPRINTF(("%s: Radio rev %d ver 0x%x mnf 0x%x\n", - sc->sc_dev.dv_xname, sc->sc_radio_rev, sc->sc_radio_ver, - sc->sc_radio_mnf & 0xfff)); - - return (0); -} - -void -bcw_radio_off(struct bcw_softc *sc) -{ - /* Magic unexplained values */ - if (sc->sc_phy_type == BCW_PHY_TYPEA) { - bcw_radio_write16(sc, 0x0004, 0x00ff); - bcw_radio_write16(sc, 0x0005, 0x00fb); - bcw_phy_write16(sc, 0x0010, bcw_phy_read16(sc, 0x0010) | - 0x0008); - bcw_phy_write16(sc, 0x0011, bcw_phy_read16(sc, 0x0011) | - 0x0008); - } - if (sc->sc_phy_type == BCW_PHY_TYPEB && sc->sc_core_80211->rev >= 5) { - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) | - 0x008c); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) & - 0xff73); - } else - bcw_phy_write16(sc, 0x0015, 0xaa00); - - DPRINTF(("%s: Radio turned off\n", sc->sc_dev.dv_xname)); -} - -void -bcw_radio_on(struct bcw_softc *sc) -{ - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - bcw_radio_write16(sc, 0x0004, 0x00c0); - bcw_radio_write16(sc, 0x0005, 0x0008); - bcw_phy_write16(sc, 0x0010, bcw_phy_read16(sc, 0x0010) & - 0xfff7); - bcw_phy_write16(sc, 0x0011, bcw_phy_read16(sc, 0x0011) & - 0xfff7); - bcw_radio_init2060(sc); - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: - bcw_phy_write16(sc, 0x0015, 0x8000); - bcw_phy_write16(sc, 0x0015, 0xcc00); - bcw_phy_write16(sc, 0x0015, sc->sc_phy_connected ? 0x00c0 : 0); - if (bcw_radio_select_channel(sc, BCW_RADIO_DEFAULT_CHANNEL_BG, - 1)) - return; - break; - default: - return; - } - - DPRINTF(("%s: Radio turned on\n", sc->sc_dev.dv_xname)); -} - -void -bcw_radio_nrssi_hw_write(struct bcw_softc *sc, uint16_t offset, int16_t val) -{ - bcw_phy_write16(sc, BCW_PHY_NRSSILT_CTRL, offset); - bcw_phy_write16(sc, BCW_PHY_NRSSILT_DATA, (uint16_t)val); -} - -int16_t -bcw_radio_nrssi_hw_read(struct bcw_softc *sc, uint16_t offset) -{ - uint16_t val; - - bcw_phy_write16(sc, BCW_PHY_NRSSILT_CTRL, offset); - val = bcw_phy_read16(sc, BCW_PHY_NRSSILT_DATA); - - return ((int16_t)val); -} - -void -bcw_radio_nrssi_hw_update(struct bcw_softc *sc, uint16_t val) -{ - uint16_t i; - int16_t tmp; - - for (i = 0; i < 64; i++) { - tmp = bcw_radio_nrssi_hw_read(sc, i); - tmp -= val; - tmp = bcw_lv(tmp, 32, 31); - bcw_radio_nrssi_hw_write(sc, i, tmp); - } -} - -void -bcw_radio_calc_nrssi_threshold(struct bcw_softc *sc) -{ - int32_t threshold; - int32_t a, b; - int16_t tmp16; - uint16_t tmp_u16; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEB: - if (sc->sc_radio_ver != 0x2050) - return; - if (!(sc->sc_sprom.boardflags & BCW_BF_RSSI)) - return; - - if (sc->sc_radio_rev >= 6) { - threshold = (sc->sc_radio_nrssi[1] - - sc->sc_radio_nrssi[0]) * 32; - threshold += 20 * (sc->sc_radio_nrssi[0] + 1); - threshold /= 40; - } else - threshold = sc->sc_radio_nrssi[1] - 5; - - threshold = bcw_lv(threshold, 0, 0x3e); - bcw_phy_read16(sc, 0x0020); - bcw_phy_write16(sc, 0x0020, (((uint16_t)threshold) << 8) | - 0x001c); - - if (sc->sc_radio_rev >= 6) { - bcw_phy_write16(sc, 0x0087, 0x0e0d); - bcw_phy_write16(sc, 0x0086, 0x0c0d); - bcw_phy_write16(sc, 0x0085, 0x0a09); - bcw_phy_write16(sc, 0x0084, 0x0808); - bcw_phy_write16(sc, 0x0083, 0x0808); - bcw_phy_write16(sc, 0x0082, 0x0604); - bcw_phy_write16(sc, 0x0081, 0x0302); - bcw_phy_write16(sc, 0x0080, 0x0100); - } - break; - case BCW_PHY_TYPEG: - if (!sc->sc_phy_connected || - !(sc->sc_sprom.boardflags & BCW_BF_RSSI)) { - tmp16 = bcw_radio_nrssi_hw_read(sc, 0x20); - if (tmp16 >= 0x20) - tmp16 -= 0x40; - if (tmp16 < 3) - bcw_phy_write16(sc, 0x048a, - (bcw_phy_read16(sc, 0x048a) & 0xf000) | - 0x09eb); - else - bcw_phy_write16(sc, 0x048a, - (bcw_phy_read16(sc, 0x048a) & 0xf000) | - 0x0aed); - } else { - if (sc->sc_radio_interfmode == - BCW_RADIO_INTERFMODE_NONWLAN) { - a = 0xe; - b = 0xa; - } else if (sc->sc_radio_aci_wlan_automatic && - sc->sc_radio_aci_enable) { - a = 0x13; - b = 0x12; - } else { - a = 0xe; - b = 0x11; - } - - a = a * (sc->sc_radio_nrssi[1] - sc->sc_radio_nrssi[0]); - a += (sc->sc_radio_nrssi[0] << 6); - if (a < 32) - a += 31; - else - a += 32; - a = a >> 6; - a = bcw_lv(a, -31, 31); - - b = b * (sc->sc_radio_nrssi[1] - sc->sc_radio_nrssi[0]); - b += (sc->sc_radio_nrssi[0] << 6); - if (b < 32) - b += 31; - else - b += 32; - b = b >> 6; - b = bcw_lv(b, -31, 31); - - tmp_u16 = bcw_phy_read16(sc, 0x048a) & 0xf000; - tmp_u16 |= ((uint32_t)b & 0x0000003f); - tmp_u16 |= (((uint32_t)a & 0x0000003f) << 6); - bcw_phy_write16(sc, 0x048a, tmp_u16); - } - break; - default: - /* XXX panic()? */ - return; - } -} - -void -bcw_radio_calc_nrssi_slope(struct bcw_softc *sc) -{ - uint16_t backup[18] = { 0 }; - uint16_t tmp; - int16_t nrssi0, nrssi1; - - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEB: - backup[0] = bcw_radio_read16(sc, 0x007a); - backup[1] = bcw_radio_read16(sc, 0x0052); - backup[2] = bcw_radio_read16(sc, 0x0043); - backup[3] = bcw_phy_read16(sc, 0x0030); - backup[4] = bcw_phy_read16(sc, 0x0026); - backup[5] = bcw_phy_read16(sc, 0x0015); - backup[6] = bcw_phy_read16(sc, 0x0020); - backup[7] = bcw_phy_read16(sc, 0x005a); - backup[8] = bcw_phy_read16(sc, 0x0059); - backup[9] = bcw_phy_read16(sc, 0x0058); - backup[10] = bcw_phy_read16(sc, 0x03e2); - backup[11] = BCW_READ16(sc, 0x03e6); - backup[12] = BCW_READ16(sc, 0x007a); - backup[13] = BCW_READ16(sc, BCW_MMIO_CHANNEL_EXT); - - tmp = bcw_radio_read16(sc, 0x007a); - tmp &= ((sc->sc_phy_rev >= 5) ? 0x007f : 0x000f); - bcw_radio_write16(sc, 0x007a, tmp); - bcw_phy_write16(sc, 0x0030, 0x00f); - BCW_WRITE16(sc, 0x03ec, 0x7f7f); - bcw_phy_write16(sc, 0x0026, 0); - bcw_phy_write16(sc, 0x0015, bcw_phy_read16(sc, 0x0015) | - 0x0020); - bcw_phy_write16(sc, 0x002a, 0x08a3); - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | - 0x0080); - - nrssi0 = (uint16_t)bcw_phy_read16(sc, 0x0027); - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) & - 0x007f); - if (sc->sc_phy_rev >= 2) - BCW_WRITE16(sc, 0x03e6, 0x0040); - else if (sc->sc_phy_rev == 0) - BCW_WRITE16(sc, 0x03e6, 0x0122); - else - BCW_WRITE16(sc, BCW_MMIO_CHANNEL_EXT, - BCW_READ16(sc, BCW_MMIO_CHANNEL_EXT) & 0x2000); - bcw_phy_write16(sc, 0x0020, 0x3f3f); - bcw_phy_write16(sc, 0x0014, 0xf330); - bcw_radio_write16(sc, 0x005a, 0xf330); - bcw_radio_write16(sc, 0x0043, - bcw_radio_read16(sc, 0x0043) & 0x0f0); - bcw_phy_write16(sc, 0x005a, 0x0480); - bcw_phy_write16(sc, 0x0059, 0x0810); - bcw_phy_write16(sc, 0x0058, 0x000d); - delay(20); - - nrssi1 = (int16_t)bcw_phy_read16(sc, 0x0027); - bcw_phy_write16(sc, 0x0030, backup[3]); - bcw_radio_write16(sc, 0x007a, backup[0]); - BCW_WRITE16(sc, 0x03e2, backup[11]); - bcw_phy_write16(sc, 0x0026, backup[4]); - bcw_phy_write16(sc, 0x0015, backup[5]); - bcw_phy_write16(sc, 0x002a, backup[6]); - bcw_radio_spw(sc, sc->sc_radio_channel); - if (sc->sc_phy_rev != 0) - BCW_WRITE16(sc, 0x3f4, backup[13]); - - bcw_phy_write16(sc, 0x0020, backup[7]); - bcw_phy_write16(sc, 0x0020, backup[8]); - bcw_phy_write16(sc, 0x0020, backup[9]); - bcw_phy_write16(sc, 0x0020, backup[10]); - bcw_radio_write16(sc, 0x0052, backup[1]); - bcw_radio_write16(sc, 0x0043, backup[2]); - - if (nrssi0 == nrssi1) - sc->sc_radio_nrssislope = 0x00010000; - else - sc->sc_radio_nrssislope = 0x00400000 / - (nrssi0 - nrssi1); - - if (nrssi0 <= -4) { - sc->sc_radio_nrssi[0] = nrssi0; - sc->sc_radio_nrssi[1] = nrssi1; - } - break; - case BCW_PHY_TYPEG: - if (sc->sc_radio_rev >= 9) - return; - if (sc->sc_radio_rev == 8) - bcw_radio_calc_nrssi_offset(sc); - break; - } -} - -void -bcw_radio_calc_nrssi_offset(struct bcw_softc *sc) -{ - uint16_t backup[20] = { 0 }; - int16_t v47f; - uint16_t i; - uint16_t saved = 0xffff; - - backup[0] = bcw_phy_read16(sc, 0x0001); - backup[1] = bcw_phy_read16(sc, 0x0811); - backup[2] = bcw_phy_read16(sc, 0x0812); - backup[3] = bcw_phy_read16(sc, 0x0814); - backup[4] = bcw_phy_read16(sc, 0x0815); - backup[5] = bcw_phy_read16(sc, 0x005a); - backup[6] = bcw_phy_read16(sc, 0x0059); - backup[7] = bcw_phy_read16(sc, 0x0058); - backup[8] = bcw_phy_read16(sc, 0x000a); - backup[9] = bcw_phy_read16(sc, 0x0003); - backup[10] = bcw_radio_read16(sc, 0x007a); - backup[11] = bcw_radio_read16(sc, 0x0043); - - bcw_phy_write16(sc, 0x0429, bcw_phy_read16(sc, 0x0429) & 0x7fff); - bcw_phy_write16(sc, 0x0001, (bcw_phy_read16(sc, 0x0001) & 0x3fff) | - 0x4000); - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) | 0x000c); - bcw_phy_write16(sc, 0x0812, (bcw_phy_read16(sc, 0x0812) & 0xfff3) | - 0x0004); - bcw_phy_write16(sc, 0x0802, bcw_phy_read16(sc, 0x0802) & ~(0x1 | 0x2)); - - if (sc->sc_phy_rev >= 6) { - backup[12] = bcw_phy_read16(sc, 0x002e); - backup[13] = bcw_phy_read16(sc, 0x002f); - backup[14] = bcw_phy_read16(sc, 0x080f); - backup[15] = bcw_phy_read16(sc, 0x0810); - backup[16] = bcw_phy_read16(sc, 0x0801); - backup[17] = bcw_phy_read16(sc, 0x0060); - backup[18] = bcw_phy_read16(sc, 0x0014); - backup[19] = bcw_phy_read16(sc, 0x0478); - - bcw_phy_write16(sc, 0x002e, 0); - bcw_phy_write16(sc, 0x002e, 0); - bcw_phy_write16(sc, 0x002e, 0); - bcw_phy_write16(sc, 0x002e, 0); - bcw_phy_write16(sc, 0x0478, bcw_phy_read16(sc, 0x0478) | - 0x0100); - bcw_phy_write16(sc, 0x0801, bcw_phy_read16(sc, 0x0801) | - 0x0040); - bcw_phy_write16(sc, 0x0060, bcw_phy_read16(sc, 0x0060) | - 0x0040); - bcw_phy_write16(sc, 0x0014, bcw_phy_read16(sc, 0x0014) | - 0x0200); - } - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | 0x0070); - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | 0x0080); - delay(30); - - v47f = (int16_t)((bcw_phy_read16(sc, 0x047f) >> 8) & 0x00ef); - if (v47f >= 0x20) - v47f -= 0x40; - if (v47f == 31) { - for (i = 7; i >= 4; i--) { - bcw_radio_write16(sc, 0x007b, i); - delay(20); - v47f = (int16_t)((bcw_phy_read16(sc, 0x047f) >> 8) & - 0x003f); - if (v47f >= 0x20) - v47f -= 0x40; - if (v47f < 31 && saved == 0xffff) - saved = i; - } - if (saved == 0xffff) - saved = 4; - } else { - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) & - 0x007f); - - bcw_phy_write16(sc, 0x0814, bcw_phy_read16(sc, 0x0814) | - 0x0001); - bcw_phy_write16(sc, 0x0815, bcw_phy_read16(sc, 0x0815) & - 0xfffe); - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) | - 0x000c); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) | - 0x000c); - bcw_phy_write16(sc, 0x0811, bcw_phy_read16(sc, 0x0811) | - 0x0030); - bcw_phy_write16(sc, 0x0812, bcw_phy_read16(sc, 0x0812) | - 0x0030); - bcw_phy_write16(sc, 0x005a, 0x0480); - bcw_phy_write16(sc, 0x0059, 0x0810); - bcw_phy_write16(sc, 0x0058, 0x000d); - if (sc->sc_phy_rev == 0) - bcw_phy_write16(sc, 0x0003, 0x0122); - else - bcw_phy_write16(sc, 0x000a, bcw_phy_read16(sc, 0x000a) | - 0x2000); - bcw_phy_write16(sc, 0x0814, bcw_phy_read16(sc, 0x0814) | - 0x0004); - bcw_phy_write16(sc, 0x0815, bcw_phy_read16(sc, 0x0815) & - 0xfffb); - bcw_phy_write16(sc, 0x0003, (bcw_phy_read16(sc, 0x0003) & - 0xff9f) | 0x0040); - bcw_radio_write16(sc, 0x007a, bcw_radio_read16(sc, 0x007a) | - 0x000f); - bcw_radio_set_all_gains(sc, 3, 0, 1); - bcw_radio_write16(sc, 0x0043, (bcw_radio_read16(sc, 0x0043) & - 0x00f0) | 0x000f); - delay(30); - v47f = (int16_t)((bcw_phy_read16(sc, 0x047f) >> 8) & 0x003f); - if (v47f >= 0x20) - v47f -= 0x40; - if (v47f == -32) { - for (i = 0; i < 4; i++) { - bcw_radio_write16(sc, 0x007b, i); - delay(20); - v47f = (int16_t)((bcw_phy_read16(sc, 0x047f) >> - 8) & 0x003f); - if (v47f >= 0x20) - v47f -= 0x40; - if (v47f > -31 && saved == 0xffff) - saved = i; - } - if (saved == 0xfff) - saved = 3; - } else - saved = 0; - } - bcw_radio_write16(sc, 0x007b, saved); - - if (sc->sc_phy_rev >= 6) { - bcw_phy_write16(sc, 0x002e, backup[12]); - bcw_phy_write16(sc, 0x002f, backup[13]); - bcw_phy_write16(sc, 0x080f, backup[14]); - bcw_phy_write16(sc, 0x0810, backup[15]); - } - bcw_phy_write16(sc, 0x0814, backup[3]); - bcw_phy_write16(sc, 0x0815, backup[4]); - bcw_phy_write16(sc, 0x005a, backup[5]); - bcw_phy_write16(sc, 0x0059, backup[6]); - bcw_phy_write16(sc, 0x0058, backup[7]); - bcw_phy_write16(sc, 0x000a, backup[8]); - bcw_phy_write16(sc, 0x0003, backup[9]); - bcw_radio_write16(sc, 0x0043, backup[11]); - bcw_radio_write16(sc, 0x007a, backup[10]); - bcw_phy_write16(sc, 0x0802, bcw_phy_read16(sc, 0x0802) | 0x1 | 0x2); - bcw_phy_write16(sc, 0x0429, bcw_phy_read16(sc, 0x0429) | 0x8000); - bcw_radio_set_original_gains(sc); - if (sc->sc_phy_rev >= 6) { - bcw_phy_write16(sc, 0x0801, backup[16]); - bcw_phy_write16(sc, 0x0060, backup[17]); - bcw_phy_write16(sc, 0x0014, backup[18]); - bcw_phy_write16(sc, 0x0478, backup[19]); - } - bcw_phy_write16(sc, 0x0001, backup[0]); - bcw_phy_write16(sc, 0x0812, backup[2]); - bcw_phy_write16(sc, 0x0001, backup[1]); -} - -void -bcw_radio_set_all_gains(struct bcw_softc *sc, int16_t first, int16_t second, - int16_t third) -{ - uint16_t i; - uint16_t start = 0x08, end = 0x18; - uint16_t offset = 0x0400; - uint16_t tmp; - - if (sc->sc_phy_rev <= 1) { - offset = 0x5000; - start = 0x10; - end = 0x20; - } - - for (i = 0; i < 4; i++) - bcw_ilt_write(sc, offset + i, first); - - for (i = start; i < end; i++) - bcw_ilt_write(sc, offset + i, second); - - if (third != -1) { - bcw_phy_write16(sc, 0x04a0, (bcw_phy_read16(sc, 0x04a0) & - 0xbfbf) | tmp); - bcw_phy_write16(sc, 0x04a1, (bcw_phy_read16(sc, 0x04a1) & - 0xbfbf) | tmp); - bcw_phy_write16(sc, 0x04a2, (bcw_phy_read16(sc, 0x04a2) & - 0xbfbf) | tmp); - } - bcw_dummy_transmission(sc); -} - -void -bcw_radio_set_original_gains(struct bcw_softc *sc) -{ - uint16_t i, tmp; - uint16_t offset = 0x0400; - uint16_t start = 0x0008, end = 0x0018; - - if (sc->sc_phy_rev <= 1) { - offset = 0x5000; - start = 0x0010; - end = 0x0020; - } - - for (i = 0; i < 4; i++) { - tmp = (i & 0xfffc); - tmp |= (i & 0x0001) << 1; - tmp |= (i & 0x0002) >> 1; - - bcw_ilt_write(sc, offset + i, tmp); - } - - for (i = start; i < end; i++) - bcw_ilt_write(sc, offset + i, i - start); - - bcw_phy_write16(sc, 0x04a0, (bcw_phy_read16(sc, 0x04a0) & 0xbfbf) | - 0x4040); - bcw_phy_write16(sc, 0x04a1, (bcw_phy_read16(sc, 0x04a1) & 0xbfbf) | - 0x4040); - bcw_phy_write16(sc, 0x04a2, (bcw_phy_read16(sc, 0x04a2) & 0xbfbf) | - 0x4000); - bcw_dummy_transmission(sc); -} - -uint16_t -bcw_radio_calibrationvalue(struct bcw_softc *sc) -{ - uint16_t reg, index, r; - - reg = bcw_radio_read16(sc, 0x0060); - index = (reg & 0x001e) >> 1; - r = rcc_table[index] << 1; - r |= (reg & 0x0001); - r |= 0x0020; - - return (r); -} - -void -bcw_radio_set_txpower_a(struct bcw_softc *sc, uint16_t txpower) -{ - uint16_t pamp, base, dac, ilt; - - txpower = bcw_lv(txpower, 0, 63); - - pamp = bcw_radio_get_txgain_freq_power_amp(txpower); - pamp <<= 5; - pamp &= 0x00e0; - bcw_phy_write16(sc, 0x0019, pamp); - - base = bcw_radio_get_txgain_baseband(txpower); - base &= 0x000f; - bcw_phy_write16(sc, 0x0017, base | 0x0020); - - ilt = bcw_ilt_read(sc, 0x3001); - ilt &= 0x0007; - - dac = bcw_radio_get_txgain_dac(txpower); - dac <<= 3; - dac |= ilt; - - bcw_ilt_write(sc, 0x3001, dac); - - sc->sc_radio_txpwr_offset = txpower; -} - -void -bcw_radio_set_txpower_bg(struct bcw_softc *sc, uint16_t baseband_atten, - uint16_t radio_atten, uint16_t txpower) -{ - if (baseband_atten == 0xffff) - baseband_atten = sc->sc_radio_baseband_atten; - if (radio_atten == 0xffff) - radio_atten = sc->sc_radio_radio_atten; - if (txpower == 0xffff) - txpower = sc->sc_radio_txctl1; - - sc->sc_radio_baseband_atten = baseband_atten; - sc->sc_radio_radio_atten = radio_atten; - sc->sc_radio_txctl1 = txpower; - - bcw_phy_set_baseband_atten(sc, baseband_atten); - bcw_radio_write16(sc, 0x0043, radio_atten); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0064, radio_atten); - if (sc->sc_radio_ver == 0x2050) - bcw_radio_write16(sc, 0x0052, (bcw_radio_read16(sc, 0x0052) & - ~0x0070) | ((txpower << 4) & 0x0070)); - - /* XXX unclear specs */ - if (sc->sc_phy_type == BCW_PHY_TYPEG) - bcw_phy_lo_adjust(sc, 0); -} - -uint16_t -bcw_radio_init2050(struct bcw_softc *sc) -{ - uint16_t backup[19] = { 0 }; - uint16_t r; - uint16_t i, j; - uint32_t tmp1 = 0, tmp2 = 0; - - backup[0] = bcw_radio_read16(sc, 0x0043); - backup[14] = bcw_radio_read16(sc, 0x0051); - backup[15] = bcw_radio_read16(sc, 0x0052); - backup[1] = bcw_phy_read16(sc, 0x0015); - backup[16] = bcw_phy_read16(sc, 0x005a); - backup[17] = bcw_phy_read16(sc, 0x0059); - backup[18] = bcw_phy_read16(sc, 0x0058); - if (sc->sc_phy_type == BCW_PHY_TYPEB) { - backup[2] = bcw_phy_read16(sc, 0x0030); - backup[3] = BCW_READ16(sc, 0x03ec); - bcw_phy_write16(sc, 0x0030, 0x00ff); - BCW_WRITE16(sc, 0x03ec, 0x3f3f); - } else { - if (sc->sc_phy_connected) { - backup[4] = bcw_phy_read16(sc, 0x0811); - backup[5] = bcw_phy_read16(sc, 0x0812); - backup[6] = bcw_phy_read16(sc, 0x0814); - backup[7] = bcw_phy_read16(sc, 0x0815); - backup[8] = bcw_phy_read16(sc, BCW_PHY_G_CRS); - backup[9] = bcw_phy_read16(sc, 0x0802); - bcw_phy_write16(sc, 0x0814, - (bcw_phy_read16(sc, 0x0814) | 0x0003)); - bcw_phy_write16(sc, 0x0815, - (bcw_phy_read16(sc, 0x0815) & 0xfffc)); - bcw_phy_write16(sc, BCW_PHY_G_CRS, - (bcw_phy_read16(sc, BCW_PHY_G_CRS) & 0x7fff)); - bcw_phy_write16(sc, 0x0802, - (bcw_phy_read16(sc, 0x0802) & 0xfffc)); - bcw_phy_write16(sc, 0x0811, 0x01b3); - bcw_phy_write16(sc, 0x0812, 0x0fb2); - } - BCW_WRITE16(sc, BCW_MMIO_PHY_RADIO, - (BCW_READ16(sc, BCW_MMIO_PHY_RADIO) | 0x8000)); - } - backup[10] = bcw_phy_read16(sc, 0x0035); - bcw_phy_write16(sc, 0x0035, (bcw_phy_read16(sc, 0x0035) & 0xff7f)); - backup[11] = BCW_READ16(sc, 0x03e6); - backup[12] = BCW_READ16(sc, BCW_MMIO_CHANNEL_EXT); - - /* initialization */ - if (sc->sc_phy_ver == 0) - BCW_WRITE16(sc, 0x03e6, 0x0122); - else { - if (sc->sc_phy_ver >= 2) - BCW_WRITE16(sc, 0x03e6, 0x0040); - BCW_WRITE16(sc, BCW_MMIO_CHANNEL_EXT, - (BCW_READ16(sc, BCW_MMIO_CHANNEL_EXT) | 0x2000)); - } - - r = bcw_radio_calibrationvalue(sc); - - if (sc->sc_phy_type == BCW_PHY_TYPEB) - bcw_radio_write16(sc, 0x0078, 0x0003); - - bcw_phy_write16(sc, 0x0015, 0xbfaf); - bcw_phy_write16(sc, 0x002b, 0x1403); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x00b2); - bcw_phy_write16(sc, 0x0015, 0xbfa0); - bcw_radio_write16(sc, 0x0051, (bcw_radio_read16(sc, 0x0051) | - 0x0004)); - bcw_radio_write16(sc, 0x0052, 0); - bcw_radio_write16(sc, 0x0043, bcw_radio_read16(sc, 0x0043) | 0x0009); - bcw_phy_write16(sc, 0x0058, 0); - - for (i = 0; i < 16; i++) { - bcw_phy_write16(sc, 0x005a, 0x0480); - bcw_phy_write16(sc, 0x0059, 0xc810); - bcw_phy_write16(sc, 0x0058, 0x000d); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x30b2); - bcw_phy_write16(sc, 0x0015, 0xafb0); - delay(10); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x30b2); - bcw_phy_write16(sc, 0x0015, 0xefb0); - delay(10); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x30b2); - bcw_phy_write16(sc, 0x0015, 0xfff0); - delay(10); - tmp1 += bcw_phy_read16(sc, 0x002d); - bcw_phy_write16(sc, 0x0058, 0); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x30b2); - bcw_phy_write16(sc, 0x0015, 0xafb0); - } - - tmp1++; - tmp1 >>= 9; - delay(10); - bcw_phy_write16(sc, 0x0058, 0); - - for (i = 0; i < 16; i++) { - bcw_radio_write16(sc, 0x0078, (bcw_flip_4bit(i) << 1) | 0x0020); - - backup[13] = bcw_radio_read16(sc, 0x0078); - delay(10); - for (j = 0; j < 16; j++) { - bcw_phy_write16(sc, 0x005a, 0x0d80); - bcw_phy_write16(sc, 0x0059, 0xc810); - bcw_phy_write16(sc, 0x0058, 0x000d); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x30b2); - bcw_phy_write16(sc, 0x0015, 0xafb0); - delay(10); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x30b2); - bcw_phy_write16(sc, 0x0015, 0xefb0); - delay(10); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x812, 0x30b3); - bcw_phy_write16(sc, 0x0015, 0xfff0); - delay(10); - tmp2 += bcw_phy_read16(sc, 0x002d); - bcw_phy_write16(sc, 0x0058, 0); - if (sc->sc_phy_connected) - bcw_phy_write16(sc, 0x0812, 0x30b2); - bcw_phy_write16(sc, 0x0015, 0xafb0); - } - tmp2++; - tmp2 >>= 8; - if (tmp1 < tmp2) - break; - } - - /* restore the registers */ - bcw_phy_write16(sc, 0x0015, backup[1]); - bcw_radio_write16(sc, 0x0051, backup[14]); - bcw_radio_write16(sc, 0x0052, backup[15]); - bcw_radio_write16(sc, 0x0043, backup[0]); - bcw_phy_write16(sc, 0x005a, backup[16]); - bcw_phy_write16(sc, 0x0059, backup[17]); - bcw_phy_write16(sc, 0x0058, backup[18]); - BCW_WRITE16(sc, 0x03e6, backup[11]); - if (sc->sc_phy_ver != 0) - BCW_WRITE16(sc, BCW_MMIO_CHANNEL_EXT, backup[12]); - bcw_phy_write16(sc, 0x0035, backup[10]); - bcw_radio_select_channel(sc, sc->sc_radio_channel, 1); - if (sc->sc_phy_type == BCW_PHY_TYPEB) { - bcw_phy_write16(sc, 0x0030, backup[2]); - BCW_WRITE16(sc, 0x03ec, backup[3]); - } else { - BCW_WRITE16(sc, BCW_MMIO_PHY_RADIO, - (BCW_READ16(sc, BCW_MMIO_PHY_RADIO) & 0x7fff)); - if (sc->sc_phy_connected) { - bcw_phy_write16(sc, 0x0811, backup[4]); - bcw_phy_write16(sc, 0x0812, backup[5]); - bcw_phy_write16(sc, 0x0814, backup[6]); - bcw_phy_write16(sc, 0x0815, backup[7]); - bcw_phy_write16(sc, BCW_PHY_G_CRS, backup[8]); - bcw_phy_write16(sc, 0x0802, backup[9]); - } - } - if (i >= 15) - r = backup[13]; - - return (r); -} - -void -bcw_radio_init2060(struct bcw_softc *sc) -{ - int error; - - bcw_radio_write16(sc, 0x0004, 0x00c0); - bcw_radio_write16(sc, 0x0005, 0x0008); - bcw_radio_write16(sc, 0x0009, 0x0040); - bcw_radio_write16(sc, 0x0005, 0x00aa); - bcw_radio_write16(sc, 0x0032, 0x008f); - bcw_radio_write16(sc, 0x0006, 0x008f); - bcw_radio_write16(sc, 0x0034, 0x008f); - bcw_radio_write16(sc, 0x002c, 0x0007); - bcw_radio_write16(sc, 0x0082, 0x0080); - bcw_radio_write16(sc, 0x0080, 0x0000); - bcw_radio_write16(sc, 0x003f, 0x00d4); - bcw_radio_write16(sc, 0x0005, bcw_radio_read16(sc, 0x0005) & ~0x0008); - bcw_radio_write16(sc, 0x0081, bcw_radio_read16(sc, 0x0081) & ~0x0010); - bcw_radio_write16(sc, 0x0081, bcw_radio_read16(sc, 0x0081) & ~0x0020); - bcw_radio_write16(sc, 0x0081, bcw_radio_read16(sc, 0x0081) & ~0x0020); - delay(400); - bcw_radio_write16(sc, 0x0081, (bcw_radio_read16(sc, 0x0081) & ~0x0020) | - 0x0010); - delay(400); - bcw_radio_write16(sc, 0x0005, (bcw_radio_read16(sc, 0x0005) & ~0x0020) | - 0x0008); - bcw_radio_write16(sc, 0x0085, bcw_radio_read16(sc, 0x0085) & ~0x0010); - bcw_radio_write16(sc, 0x0005, bcw_radio_read16(sc, 0x0005) & ~0x0008); - bcw_radio_write16(sc, 0x0081, bcw_radio_read16(sc, 0x0081) & ~0x0040); - bcw_radio_write16(sc, 0x0081, (bcw_radio_read16(sc, 0x0081) & ~0x0040) | - 0x0040); - bcw_radio_write16(sc, 0x0005, (bcw_radio_read16(sc, 0x0081) & ~0x0008) | - 0x0008); - bcw_phy_write16(sc, 0x0063, 0xddc6); - bcw_phy_write16(sc, 0x0069, 0x07be); - bcw_phy_write16(sc, 0x006a, 0x0000); - - error = bcw_radio_select_channel(sc, BCW_RADIO_DEFAULT_CHANNEL_A, 0); - - delay(1000); -} - -void -bcw_radio_spw(struct bcw_softc *sc, uint8_t channel) -{ - if (sc->sc_radio_ver != 0x2050 || sc->sc_radio_rev >= 6) - /* we do not need the workaround */ - return; - - if (channel <= 10) - BCW_WRITE16(sc, BCW_MMIO_CHANNEL, - bcw_radio_chan2freq_bg(channel + 4)); - else - BCW_WRITE16(sc, BCW_MMIO_CHANNEL, bcw_radio_chan2freq_bg(1)); - - delay(100); - - BCW_WRITE16(sc, BCW_MMIO_CHANNEL, bcw_radio_chan2freq_bg(channel)); -} - -int -bcw_radio_select_channel(struct bcw_softc *sc, uint8_t channel, int spw) -{ - uint16_t freq, tmp, r8; - - if (sc->sc_radio_mnf == 0x17f && sc->sc_radio_ver == 0x2060 && - sc->sc_radio_rev == 1) { - freq = bcw_radio_chan2freq_a(channel); - - r8 = bcw_radio_read16(sc, 0x0008); - BCW_WRITE16(sc, 0x03f0, freq); - bcw_radio_write16(sc, 0x0008, r8); - - tmp = bcw_radio_read16(sc, 0x002e); - tmp &= 0x0080; - - bcw_radio_write16(sc, 0x002e, tmp); - - if (freq >= 4920 && freq <= 5500) - r8 = 3 * freq / 116; - bcw_radio_write16(sc, 0x0007, (r8 << 4) | r8); - bcw_radio_write16(sc, 0x0020, (r8 << 4) | r8); - bcw_radio_write16(sc, 0x0021, (r8 << 4) | r8); - bcw_radio_write16(sc, 0x0022, (bcw_radio_read16(sc, 0x0022) & - 0x000f) | (r8 << 4)); - bcw_radio_write16(sc, 0x002a, (r8 << 4)); - bcw_radio_write16(sc, 0x002b, (r8 << 4)); - bcw_radio_write16(sc, 0x0008, (bcw_radio_read16(sc, 0x0008) & - 0x00f0) | (r8 << 4)); - bcw_radio_write16(sc, 0x0029, (bcw_radio_read16(sc, 0x0029) & - 0xff0f) | 0x00b0); - bcw_radio_write16(sc, 0x0035, 0x00aa); - bcw_radio_write16(sc, 0x0036, 0x0085); - bcw_radio_write16(sc, 0x003a, (bcw_radio_read16(sc, 0x003a) & - 0xff20) | bcw_radio_freq_r3a_value(freq)); - bcw_radio_write16(sc, 0x003d, bcw_radio_read16(sc, 0x003d) & - 0x00ff); - bcw_radio_write16(sc, 0x0081, (bcw_radio_read16(sc, 0x0081) & - 0xff7f) | 0x0080); - bcw_radio_write16(sc, 0x0035, bcw_radio_read16(sc, 0x0035) & - 0xffef); - bcw_radio_write16(sc, 0x0035, (bcw_radio_read16(sc, 0x0035) & - 0xffef) | 0x0010); - bcw_radio_set_tx_iq(sc); - bcw_phy_xmitpower(sc); - } else { - if (spw) - bcw_radio_spw(sc, channel); - - BCW_WRITE16(sc, BCW_MMIO_CHANNEL, - bcw_radio_chan2freq_bg(channel)); - - if (channel == 14) { - /* TODO */ - } else { - BCW_WRITE16(sc, BCW_MMIO_CHANNEL_EXT, - BCW_READ16(sc, BCW_MMIO_CHANNEL_EXT) & 0xf7bf); - } - } - - sc->sc_radio_channel = channel; - - delay(8000); - - return (0); -} - -uint16_t -bcw_radio_chan2freq_a(uint8_t channel) -{ - return (5000 + 5 * channel); -} - -uint16_t -bcw_radio_chan2freq_bg(uint8_t channel) -{ - static const uint16_t freqs_bg[14] = { - 12, 17, 22, 27, - 32, 37, 42, 47, - 52, 57, 62, 67, - 72, 84 }; - - if (channel < 1 && channel > 14) - return (0); - - return (freqs_bg[channel - 1]); -} - -uint16_t -bcw_radio_default_baseband_atten(struct bcw_softc *sc) -{ - if (sc->sc_radio_ver == 0x2050 && sc->sc_radio_rev < 6) - return (0); - - return (2); -} - -uint16_t -bcw_radio_default_radio_atten(struct bcw_softc *sc) -{ - uint16_t att = 0xffff; - - if (sc->sc_phy_type == BCW_PHY_TYPEA) - return (0x60); - - switch (sc->sc_radio_ver) { - case 0x2053: - switch (sc->sc_radio_rev) { - case 1: - att = 6; - break; - } - break; - case 0x2050: - switch (sc->sc_radio_rev) { - case 0: - att = 5; - break; - case 1: - if (sc->sc_phy_type == BCW_PHY_TYPEG) { - if (sc->sc_board_vendor == - PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0421 && - sc->sc_board_rev >= 30) - att = 3; - else if (sc->sc_board_vendor == - PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0416) - att = 3; - else - att = 1; - } else { - if (sc->sc_board_vendor == - PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0421 && - sc->sc_board_rev >= 30) - att = 7; - else - att = 6; - } - break; - case 2: - if (sc->sc_phy_type == BCW_PHY_TYPEG) { - if (sc->sc_board_vendor == - PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0421 && - sc->sc_board_rev >= 30) - att = 3; - else if (sc->sc_board_vendor == - PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0416) - att = 5; - else if (sc->sc_chip_id == 0x4320) - att = 4; - else - att = 3; - } else - att = 6; - break; - case 3: - att = 5; - break; - case 4: - case 5: - att = 1; - break; - case 6: - case 7: - att = 5; - break; - case 8: - att = 0x1a; - break; - case 9: - default: - att = 5; - } - } - if (sc->sc_board_vendor == PCI_VENDOR_BROADCOM && - sc->sc_board_type == 0x0421) { - if (sc->sc_board_rev < 0x43) - att = 2; - else if (sc->sc_board_rev < 0x51) - att = 3; - } - if (att == 0x0ffff) - att = 5; - - return (att); -} - -uint16_t -bcw_radio_default_txctl1(struct bcw_softc *sc) -{ - if (sc->sc_radio_ver != 0x2050) - return (0); - if (sc->sc_radio_rev == 1) - return (3); - if (sc->sc_radio_rev < 6) - return (2); - if (sc->sc_radio_rev == 8) - return (1); - - return (0); -} - -void -bcw_radio_clear_tssi(struct bcw_softc *sc) -{ - switch (sc->sc_phy_type) { - case BCW_PHY_TYPEA: - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0068, 0x7f7f); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x006a, 0x7f7f); - break; - case BCW_PHY_TYPEB: - case BCW_PHY_TYPEG: - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0058, 0x7f7f); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x005a, 0x7f7f); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0070, 0x7f7f); - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0072, 0x7f7f); - break; - } -} - -void -bcw_radio_set_tx_iq(struct bcw_softc *sc) -{ - const uint8_t data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; - const uint8_t data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; - uint16_t tmp = bcw_radio_read16(sc, 0x001e); - int i, j; - - for (i = 0; i < 5; i++) { - for (j = 0; j < 5; j++) { - if (tmp == (data_high[i] << 4 | data_low[j])) { - bcw_phy_write16(sc, 0x0069, (i - j) << 8 | - 0x00c0); - return; - } - } - } -} - -uint16_t -bcw_radio_get_txgain_baseband(uint16_t txpower) -{ - uint16_t r; - - if (txpower >= 54) - r = 2; - else if (txpower >= 49) - r = 4; - else if (txpower >= 44) - r = 5; - else - r = 6; - - return (r); -} - -uint16_t -bcw_radio_get_txgain_freq_power_amp(uint16_t txpower) -{ - uint16_t r; - - if (txpower >= 32) - r = 0; - else if (txpower >= 25) - r = 1; - else if (txpower >= 20) - r = 2; - else if (txpower >= 12) - r = 3; - else - r = 4; - - return (r); -} - -uint16_t -bcw_radio_get_txgain_dac(uint16_t txpower) -{ - uint16_t r; - - if (txpower >= 54) - r = txpower - 53; - else if (txpower >= 49) - r = txpower - 42; - else if (txpower >= 44) - r = txpower - 37; - else if (txpower >= 32) - r = txpower - 32; - else if (txpower >= 25) - r = txpower - 20; - else if (txpower >= 20) - r = txpower - 13; - else if (txpower >= 12) - r = txpower - 8; - else - r = txpower; - - return (r); -} - -uint16_t -bcw_radio_freq_r3a_value(uint16_t frequency) -{ - uint16_t val; - - if (frequency < 5091) - val = 0x0040; - else if (frequency < 5321) - val = 0; - else if (frequency < 5806) - val = 0x0080; - else - val = 0x0040; - - return (val); -} - -int -bcw_radio_set_interf_mitigation(struct bcw_softc *sc, int mode) -{ - int currentmode; - - if (sc->sc_phy_type != BCW_PHY_TYPEG || sc->sc_phy_type == 0 || - sc->sc_phy_connected == 0) - return (ENODEV); - - sc->sc_radio_aci_wlan_automatic = 0; - switch (mode) { - case BCW_RADIO_INTERFMODE_AUTOWLAN: - sc->sc_radio_aci_wlan_automatic = 1; - if (sc->sc_radio_aci_enable) - mode = BCW_RADIO_INTERFMODE_MANUALWLAN; - else - mode = BCW_RADIO_INTERFMODE_NONE; - break; - case BCW_RADIO_INTERFMODE_NONE: - case BCW_RADIO_INTERFMODE_NONWLAN: - case BCW_RADIO_INTERFMODE_MANUALWLAN: - break; - default: - return (EINVAL); - } - - currentmode = sc->sc_radio_interfmode; - if (currentmode == mode) - return (0); - if (currentmode != BCW_RADIO_INTERFMODE_NONE) { - sc->sc_radio_aci_enable = 0; - sc->sc_radio_aci_hw_rssi = 0; - } else - bcw_radio_interf_mitigation_enable(sc, mode); - sc->sc_radio_interfmode = mode; - - return (0); -} - -int -bcw_radio_interf_mitigation_enable(struct bcw_softc *sc, int mode) -{ - uint16_t tmp, flipped; - uint32_t tmp32; - size_t stackidx = 0; - uint32_t *stack = sc->sc_radio_interfstack; - - switch (mode) { - case BCW_RADIO_INTERFMODE_NONWLAN: - if (sc->sc_phy_rev != 1) { - bcw_phy_write16(sc, 0x042b, - bcw_phy_read16(sc, 0x042b) | 0x0800); - bcw_phy_write16(sc, BCW_PHY_G_CRS, - bcw_phy_read16(sc, BCW_PHY_G_CRS) & ~0x4000); - break; - } - BCW_RADIO_STACKSAVE(0x0078); - tmp = (bcw_radio_read16(sc, 0x0078) & 0x001e); - flipped = bcw_flip_4bit(tmp); - if (flipped < 10 && flipped >= 8) - flipped = 7; - else if (flipped >= 10) - flipped -= 3; - flipped = bcw_flip_4bit(flipped); - flipped = (flipped << 1) | 0x0020; - bcw_radio_write16(sc, 0x0078, flipped); - - bcw_radio_calc_nrssi_threshold(sc); - - BCW_PHY_STACKSAVE(0x0406); - bcw_phy_write16(sc, 0x0406, 0x7e28); - - bcw_phy_write16(sc, 0x042b, - bcw_phy_read16(sc, 0x042b) | 0x08000); - bcw_phy_write16(sc, BCW_PHY_RADIO_BITFIELD, - bcw_phy_read16(sc, BCW_PHY_RADIO_BITFIELD) | 0x1000); - BCW_PHY_STACKSAVE(0x04a0); - bcw_phy_write16(sc, 0x04a0, - (bcw_phy_read16(sc, 0x04a0) & 0xc0c0) | 0x0008); - BCW_PHY_STACKSAVE(0x04a1); - bcw_phy_write16(sc, 0x04a1, - (bcw_phy_read16(sc, 0x04a1) & 0xc0c0) | 0x0605); - BCW_PHY_STACKSAVE(0x04a2); - bcw_phy_write16(sc, 0x04a2, - (bcw_phy_read16(sc, 0x04a2) & 0xc0c0) | 0x0204); - BCW_PHY_STACKSAVE(0x04a8); - bcw_phy_write16(sc, 0x04a8, - (bcw_phy_read16(sc, 0x04a8) & 0xc0c0) | 0x0803); - BCW_PHY_STACKSAVE(0x04ab); - bcw_phy_write16(sc, 0x04ab, - (bcw_phy_read16(sc, 0x04ab) & 0xc0c0) | 0x0605); - - BCW_PHY_STACKSAVE(0x04a7); - bcw_phy_write16(sc, 0x04a7, 0x0002); - BCW_PHY_STACKSAVE(0x04a3); - bcw_phy_write16(sc, 0x04a3, 0x287a); - BCW_PHY_STACKSAVE(0x04a9); - bcw_phy_write16(sc, 0x04a9, 0x2027); - BCW_PHY_STACKSAVE(0x0493); - bcw_phy_write16(sc, 0x0493, 0x32f5); - BCW_PHY_STACKSAVE(0x04aa); - bcw_phy_write16(sc, 0x04aa, 0x2027); - BCW_PHY_STACKSAVE(0x04ac); - bcw_phy_write16(sc, 0x04ac, 0x32f5); - break; - case BCW_RADIO_INTERFMODE_MANUALWLAN: - if (bcw_phy_read16(sc, 0x0033) & 0x0800) - break; - - sc->sc_radio_aci_enable = 1; - - BCW_PHY_STACKSAVE(BCW_PHY_RADIO_BITFIELD); - BCW_PHY_STACKSAVE(BCW_PHY_G_CRS); - if (sc->sc_phy_rev < 2) - BCW_PHY_STACKSAVE(0x0406); - else { - BCW_PHY_STACKSAVE(0x04c0); - BCW_PHY_STACKSAVE(0x04c1); - } - BCW_PHY_STACKSAVE(0x0033); - BCW_PHY_STACKSAVE(0x04a7); - BCW_PHY_STACKSAVE(0x04a3); - BCW_PHY_STACKSAVE(0x04a9); - BCW_PHY_STACKSAVE(0x04aa); - BCW_PHY_STACKSAVE(0x04ac); - BCW_PHY_STACKSAVE(0x0493); - BCW_PHY_STACKSAVE(0x04a1); - BCW_PHY_STACKSAVE(0x04a0); - BCW_PHY_STACKSAVE(0x04a2); - BCW_PHY_STACKSAVE(0x048a); - BCW_PHY_STACKSAVE(0x04a8); - BCW_PHY_STACKSAVE(0x04ab); - if (sc->sc_phy_rev == 2) { - BCW_PHY_STACKSAVE(0x04ad); - BCW_PHY_STACKSAVE(0x04ae); - } else if (sc->sc_phy_rev >= 3) { - BCW_PHY_STACKSAVE(0x04ad); - BCW_PHY_STACKSAVE(0x0415); - BCW_PHY_STACKSAVE(0x0416); - BCW_PHY_STACKSAVE(0x0417); - BCW_ILT_STACKSAVE(0x1a00 + 0x2); - BCW_ILT_STACKSAVE(0x1a00 + 0x3); - } - BCW_PHY_STACKSAVE(0x042b); - BCW_PHY_STACKSAVE(0x048c); - - bcw_phy_write16(sc, BCW_PHY_RADIO_BITFIELD, - bcw_phy_read16(sc, BCW_PHY_RADIO_BITFIELD) & ~0x1000); - bcw_phy_write16(sc, BCW_PHY_G_CRS, - (bcw_phy_read16(sc, BCW_PHY_G_CRS) & 0xfffc) | 0x0002); - - bcw_phy_write16(sc, 0x0033, 0x0800); - bcw_phy_write16(sc, 0x04a3, 0x2027); - bcw_phy_write16(sc, 0x04a9, 0x1ca8); - bcw_phy_write16(sc, 0x0493, 0x287a); - bcw_phy_write16(sc, 0x04aa, 0x1ca8); - bcw_phy_write16(sc, 0x04ac, 0x287a); - - bcw_phy_write16(sc, 0x04a0, - (bcw_phy_read16(sc, 0x04a0) & 0xffc0) | 0x001a); - bcw_phy_write16(sc, 0x04a7, 0x000d); - - if (sc->sc_phy_rev < 2) { - bcw_phy_write16(sc, 0x0406, 0xff0d); - } else if (sc->sc_phy_rev == 2) { - bcw_phy_write16(sc, 0x04c0, 0xffff); - bcw_phy_write16(sc, 0x04c1, 0x00a9); - } else { - bcw_phy_write16(sc, 0x04c0, 0x00c1); - bcw_phy_write16(sc, 0x04c1, 0x0059); - } - - bcw_phy_write16(sc, 0x04a1, - (bcw_phy_read16(sc, 0x04a1) & 0xc0ff) | 0x1800); - bcw_phy_write16(sc, 0x04a1, - (bcw_phy_read16(sc, 0x04a1) & 0xc0ff) | 0x0015); - bcw_phy_write16(sc, 0x04a8, - (bcw_phy_read16(sc, 0x04a8) & 0xcfff) | 0x1000); - bcw_phy_write16(sc, 0x04a8, - (bcw_phy_read16(sc, 0x04a8) & 0xf0ff) | 0x0a00); - bcw_phy_write16(sc, 0x04ab, - (bcw_phy_read16(sc, 0x04a8) & 0xcfff) | 0x1000); - bcw_phy_write16(sc, 0x04ab, - (bcw_phy_read16(sc, 0x04ab) & 0xf0ff) | 0x0800); - bcw_phy_write16(sc, 0x04ab, - (bcw_phy_read16(sc, 0x04ab) & 0xf0ff) | 0x0010); - bcw_phy_write16(sc, 0x04ab, - (bcw_phy_read16(sc, 0x04ab) & 0xfff0) | 0x0005); - bcw_phy_write16(sc, 0x04a8, - (bcw_phy_read16(sc, 0x04a8) & 0xffcf) | 0x0010); - bcw_phy_write16(sc, 0x04a8, - (bcw_phy_read16(sc, 0x04a8) & 0xfff0) | 0x0006); - bcw_phy_write16(sc, 0x04a2, - (bcw_phy_read16(sc, 0x04a2) & 0xf0ff) | 0x0800); - bcw_phy_write16(sc, 0x04a0, - (bcw_phy_read16(sc, 0x04a0) & 0xf0ff) | 0x0500); - bcw_phy_write16(sc, 0x04a2, - (bcw_phy_read16(sc, 0x04a2) & 0xfff0) | 0x000b); - - if (sc->sc_phy_rev >= 3) { - bcw_phy_write16(sc, 0x048a, - bcw_phy_read16(sc, 0x048a) & ~0x8000); - bcw_phy_write16(sc, 0x0415, - (bcw_phy_read16(sc, 0x0415) & 0x8000) | 0x36d8); - bcw_phy_write16(sc, 0x0416, - (bcw_phy_read16(sc, 0x0416) & 0x8000) | 0x36d8); - bcw_phy_write16(sc, 0x0417, - (bcw_phy_read16(sc, 0x0417) & 0xfe00) | 0x016d); - } else { - bcw_phy_write16(sc, 0x048a, - bcw_phy_read16(sc, 0x048a) | 0x1000); - bcw_phy_write16(sc, 0x048a, - (bcw_phy_read16(sc, 0x048a) & 0x9fff) | 0x2000); - tmp32 = bcw_shm_read16(sc, BCW_SHM_SHARED, - BCW_UCODEFLAGS_OFFSET); - if (!(tmp32 & 0x800)) { - tmp32 |= 0x800; - bcw_shm_write16(sc, BCW_SHM_SHARED, - BCW_UCODEFLAGS_OFFSET, tmp32); - } - } - if (sc->sc_phy_rev >= 2) { - bcw_phy_write16(sc, 0x042b, bcw_phy_read16(sc, 0x042b) | - 0x0800); - } - bcw_phy_write16(sc, 0x048c, (bcw_phy_read16(sc, 0x048c) & - 0xff00) | 0x007f); - if (sc->sc_phy_rev == 2) { - bcw_phy_write16(sc, 0x04ae, - (bcw_phy_read16(sc, 0x04ae) & 0xff00) | 0x007f); - bcw_phy_write16(sc, 0x04ad, - (bcw_phy_read16(sc, 0x04ad) & 0x00ff) | 0x1300); - } else if (sc->sc_phy_rev >= 6) { - bcw_ilt_write(sc, 0x1a00 + 0x3, 0x007f); - bcw_ilt_write(sc, 0x1a00 + 0x2, 0x007f); - bcw_phy_write16(sc, 0x04ad, - bcw_phy_read16(sc, 0x04ad) & 0x00ff); - } - bcw_radio_calc_nrssi_slope(sc); - break; - default: - /* XXX panic()? */ - break; - } - - return (0); -} - -void -bcw_radio_set_txantenna(struct bcw_softc *sc, uint32_t val) -{ - uint16_t tmp; - - val <<= 8; - tmp = bcw_shm_read16(sc, BCW_SHM_SHARED, 0x0022) & 0xfcff; - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0022, tmp | val); - tmp = bcw_shm_read16(sc, BCW_SHM_SHARED, 0x03a8) & 0xfcff; - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x03a8, tmp | val); - tmp = bcw_shm_read16(sc, BCW_SHM_SHARED, 0x0054) & 0xfcff; - bcw_shm_write16(sc, BCW_SHM_SHARED, 0x0054, tmp | val); -} - -void -bcw_radio_lock(struct bcw_softc *sc) -{ - uint32_t status; - - status = BCW_READ(sc, BCW_MMIO_SBF); - status |= BCW_SBF_RADIOREG_LOCK; - BCW_WRITE(sc, BCW_MMIO_SBF, status); - delay(10); -} - -void -bcw_radio_unlock(struct bcw_softc *sc) -{ - uint32_t status; - - BCW_READ16(sc, 0x3e0); - status = BCW_READ(sc, BCW_MMIO_SBF); - status &= ~BCW_SBF_RADIOREG_LOCK; - BCW_WRITE(sc, BCW_MMIO_SBF, status); -} - -/* - * ILT - */ -void -bcw_ilt_write(struct bcw_softc *sc, uint16_t offset, uint16_t val) -{ - if (sc->sc_phy_type == BCW_PHY_TYPEA) { - bcw_phy_write16(sc, BCW_PHY_ILT_A_CTRL, offset); - bcw_phy_write16(sc, BCW_PHY_ILT_A_DATA1, val); - } else { - bcw_phy_write16(sc, BCW_PHY_ILT_G_CTRL, offset); - bcw_phy_write16(sc, BCW_PHY_ILT_G_DATA1, val); - } -} - -uint16_t -bcw_ilt_read(struct bcw_softc *sc, uint16_t offset) -{ - if (sc->sc_phy_type == BCW_PHY_TYPEA) { - bcw_phy_write16(sc, BCW_PHY_ILT_A_CTRL, offset); - return (bcw_phy_read16(sc, BCW_PHY_ILT_A_DATA1)); - } else { - bcw_phy_write16(sc, BCW_PHY_ILT_G_CTRL, offset); - return (bcw_phy_read16(sc, BCW_PHY_ILT_G_DATA1)); - } -} - -/* - * Power Control - */ -void -bcw_pc_crystal_on(struct bcw_softc *sc) -{ - uint32_t val; - - val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOI); - if (val & BCW_PCTL_XTAL_POWERUP) - return; /* crystal is already on */ - - val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOO); - val |= (BCW_PCTL_XTAL_POWERUP | BCW_PCTL_PLL_POWERDOWN); - (sc->sc_conf_write)(sc->sc_dev_softc, BCW_GPIOO, val); - (sc->sc_conf_write)(sc->sc_dev_softc, BCW_GPIOE, val); - - delay(1000); - - val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOO); - val &= ~BCW_PCTL_PLL_POWERDOWN; - (sc->sc_conf_write)(sc->sc_dev_softc, BCW_GPIOO, val); - - delay(5000); -} - -void -bcw_pc_crystal_off(struct bcw_softc *sc) -{ - uint32_t val; - - /* TODO return if radio is hardware disabled */ - - if (sc->sc_chip_rev < 5) - return; - if (sc->sc_sprom.boardflags & BCW_BF_XTAL) - return; - - bcw_pc_set_clock(sc, BCW_PCTL_CLK_SLOW); - - val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOO); - val |= BCW_PCTL_PLL_POWERDOWN; - val &= ~BCW_PCTL_XTAL_POWERUP; - (sc->sc_conf_write)(sc->sc_dev_softc, BCW_GPIOO, val); - - val = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_GPIOE); - val |= (BCW_PCTL_PLL_POWERDOWN | BCW_PCTL_XTAL_POWERUP); - (sc->sc_conf_write)(sc->sc_dev_softc, BCW_GPIOE, val); -} - -int -bcw_pc_init(struct bcw_softc *sc) -{ - int maxfreq; - int error; - - if ((error = bcw_change_core(sc, 0))) - return (error); - - if (sc->sc_chip_id == 0x4321) { - if (sc->sc_chip_rev == 1) - BCW_WRITE(sc, BCW_CHIPCOMMON_CTL, 0x00a4); - if (sc->sc_chip_rev == 0) - BCW_WRITE(sc, BCW_CHIPCOMMON_CTL, 0x03a4); - } - - if (!(sc->sc_chip_common_capa & BCW_CAPABILITIES_PCTL)) - return (ENODEV); /* no power control */ - - if (sc->sc_core[sc->sc_currentcore].rev >= 10) { - BCW_WRITE(sc, BCW_CHIPCOMMON_SYSCLKCTL, - (BCW_READ(sc, BCW_CHIPCOMMON_SYSCLKCTL) & 0x0000ffff) | - 0x40000); - } else { - maxfreq = bcw_pc_clock_freqlimit(sc, 1); - BCW_WRITE(sc, BCW_CHIPCOMMON_PLLONDELAY, - (maxfreq * 150 + 99999) / 1000000); - BCW_WRITE(sc, BCW_CHIPCOMMON_FREFSELDELAY, - (maxfreq * 15 + 99999) / 100000); - } - - if ((error = bcw_change_core(sc, sc->sc_lastcore))) - return (error); - - return (0); -} - -int -bcw_pc_set_clock(struct bcw_softc *sc, uint16_t mode) -{ - int error; - uint32_t tmp; - - if ((error = bcw_change_core(sc, 0))) - return (error); - - if (sc->sc_core[sc->sc_currentcore].rev < 6) { - if (mode == BCW_PCTL_CLK_FAST) - bcw_pc_crystal_on(sc); - } else if (sc->sc_chip_common_capa & BCW_CAPABILITIES_PCTL && - sc->sc_core[sc->sc_currentcore].rev < 10) { - switch (mode) { - case BCW_PCTL_CLK_FAST: - tmp = BCW_READ(sc, BCW_CHIPCOMMON_SLOWCLKCTL); - tmp = (tmp & ~BCW_PCTL_FORCE_SLOW) | - BCW_PCTL_FORCE_PLL; - BCW_WRITE(sc, BCW_CHIPCOMMON_SLOWCLKCTL, tmp); - break; - case BCW_PCTL_CLK_SLOW: - tmp = BCW_READ(sc, BCW_CHIPCOMMON_SLOWCLKCTL); - tmp |= BCW_PCTL_FORCE_SLOW; - BCW_WRITE(sc, BCW_CHIPCOMMON_SLOWCLKCTL, tmp); - break; - case BCW_PCTL_CLK_DYNAMIC: - tmp = BCW_READ(sc, BCW_CHIPCOMMON_SLOWCLKCTL); - tmp &= ~BCW_PCTL_FORCE_SLOW; - tmp |= BCW_PCTL_FORCE_PLL; - tmp &= ~BCW_PCTL_DYN_XTAL; - BCW_WRITE(sc, BCW_CHIPCOMMON_SLOWCLKCTL, tmp); - break; - } - } - - if ((error = bcw_change_core(sc, sc->sc_lastcore))) - return (error); - - return (0); -} - -void -bcw_pc_saving_ctl_bits(struct bcw_softc *sc, int bit25, int bit26) -{ - int i; - uint32_t status; - - bit25 = 0; - bit26 = 1; - - if (bit25 == -1) { - /* TODO */ - } - if (bit26 == -1) { - /* TODO */ - } - - status = BCW_READ(sc, BCW_MMIO_SBF); - if (bit25) - status |= BCW_SBF_PS1; - else - status &= ~BCW_SBF_PS1; - if (bit26) - status |= BCW_SBF_PS2; - else - status &= ~BCW_SBF_PS2; - BCW_WRITE(sc, BCW_MMIO_SBF, status); - if (bit26 && sc->sc_core[sc->sc_currentcore].rev >= 5) { - for (i = 0; i < 100; i++) { - if (bcw_shm_read32(sc, BCW_SHM_SHARED, 0x0040) != 4) - break; - delay(10); - } - } -} - -uint16_t -bcw_pc_powerup_delay(struct bcw_softc *sc) -{ - uint16_t delay = 0; - uint32_t pllondelay; - int minfreq; - - /* TODO just for PCI bus type */ - - if (!(sc->sc_chip_common_capa & BCW_CAPABILITIES_PCTL)) - return (0); - - bcw_change_core(sc, 0); - - minfreq = bcw_pc_clock_freqlimit(sc, 0); - pllondelay = BCW_READ(sc, BCW_CHIPCOMMON_PLLONDELAY); - delay = (((pllondelay + 2) * 1000000) + (minfreq - 1)) / minfreq; - - bcw_change_core(sc, sc->sc_lastcore); - - return (delay); -} - -int -bcw_pc_clock_freqlimit(struct bcw_softc *sc, int getmax) -{ - int limit, clocksrc, divisor; - uint32_t tmp; - - clocksrc = bcw_pc_get_slowclocksrc(sc); - - if (sc->sc_core[sc->sc_currentcore].rev < 6) { - switch (clocksrc) { - case 0: - divisor = 64; - break; - case 1: - divisor = 32; - break; - default: - /* XXX panic()? */ - divisor = 1; - } - } else if (sc->sc_core[sc->sc_currentcore].rev < 10) { - switch (clocksrc) { - case 2: - divisor = 1; - break; - case 1: - case 0: - tmp = BCW_READ(sc, 0xb8); - divisor = ((tmp & 0xffff0000) >> 16) + 1; - divisor *= 4; - break; - default: - /* XXX panic()? */ - divisor = 1; - } - } else { - tmp = BCW_READ(sc, 0xb8); - divisor = ((tmp & 0xffff0000) >> 16) + 1; - divisor *= 4; - } - - switch (clocksrc) { - case 2: - if (getmax) - limit = 43000; - else - limit = 25000; - break; - case 1: - if (getmax) - limit = 20200000; - else - limit = 19800000; - break; - case 0: - if (getmax) - limit = 34000000; - else - limit = 25000000; - break; - default: - /* panic()? */ - limit = 0; - } - - limit /= divisor; - - return (limit); - -} - -int -bcw_pc_get_slowclocksrc(struct bcw_softc *sc) -{ - uint32_t tmp; - - if (sc->sc_core[sc->sc_currentcore].rev < 6) { - /* TODO check bus type */ - tmp = (sc->sc_conf_read)(sc, BCW_PCTL_OUT); - if (tmp & 0x10) - return (0); - return (1); - } - - if (sc->sc_core[sc->sc_currentcore].rev < 10) { - tmp = BCW_READ(sc, 0xb8); /* XXX */ - tmp &= 0x7; - if (tmp == 0) - return (2); - if (tmp == 1) - return (1); - if (tmp == 2) - return (0); - } - - return (1); -} - -/* - * XMIT - */ -uint8_t -bcw_xmit_plcp_get_ratecode_cck(const uint8_t bitrate) -{ - if (ieee80211_std_rateset_11b.rs_rates[0] == bitrate) - return (0x0a); - else if (ieee80211_std_rateset_11b.rs_rates[1] == bitrate) - return (0x14); - else if (ieee80211_std_rateset_11b.rs_rates[2] == bitrate) - return (0x37); - else if (ieee80211_std_rateset_11b.rs_rates[3] == bitrate) - return (0x6e); - - return (0); -} - -uint8_t -bcw_xmit_plcp_get_ratecode_ofdm(const uint8_t bitrate) -{ - if (ieee80211_std_rateset_11g.rs_rates[0] == bitrate) - return (0xb); - else if (ieee80211_std_rateset_11g.rs_rates[1] == bitrate) - return (0xf); - else if (ieee80211_std_rateset_11g.rs_rates[2] == bitrate) - return (0xa); - else if (ieee80211_std_rateset_11g.rs_rates[3] == bitrate) - return (0xe); - else if (ieee80211_std_rateset_11g.rs_rates[4] == bitrate) - return (0x9); - else if (ieee80211_std_rateset_11g.rs_rates[5] == bitrate) - return (0xd); - else if (ieee80211_std_rateset_11g.rs_rates[6] == bitrate) - return (0x8); - else if (ieee80211_std_rateset_11g.rs_rates[7] == bitrate) - return (0xc); - - return (0); -} diff --git a/sys/dev/ic/bcwreg.h b/sys/dev/ic/bcwreg.h deleted file mode 100644 index 751d7002755..00000000000 --- a/sys/dev/ic/bcwreg.h +++ /dev/null @@ -1,410 +0,0 @@ -/* $OpenBSD: bcwreg.h,v 1.27 2007/04/04 19:36:42 mglocker Exp $ */ - -/* - * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> - * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* Broadcom BCM43xx */ - -/* - * PCI registers defined in the PCI 2.2 specs - */ -#define BCW_PCI_BAR0 0x10 - -/* - * SPROM control register - */ -#define BCW_SPROM_CONTROL 0x88 - -/* - * PCI Interrupt Configuration Register - */ -#define BCW_PCICFG_ICR 0x94 - -/* - * MMIO offsets - */ -#define BCW_MMIO_DMA0_REASON 0x20 -#define BCW_MMIO_DMA0_INT_MASK 0x24 -#define BCW_MMIO_DMA1_REASON 0x28 -#define BCW_MMIO_DMA1_INT_MASK 0x2c -#define BCW_MMIO_DMA2_REASON 0x30 -#define BCW_MMIO_DMA2_INT_MASK 0x34 -#define BCW_MMIO_DMA3_REASON 0x38 -#define BCW_MMIO_DMA3_INT_MASK 0x3c -#define BCW_MMIO_DMA4_REASON 0x40 -#define BCW_MMIO_DMA4_INT_MASK 0x44 -#define BCW_MMIO_DMA5_REASON 0x48 -#define BCW_MMIO_DMA5_INT_MASK 0x4c -#define BCW_MMIO_SBF 0x120 /* Status Bit Field */ -#define BCW_MMIO_GIR 0x128 /* Generic Interrupt Reason */ -#define BCW_MMIO_GIM 0x12c /* Generic Interrupt Mask */ -#define BCW_MMIO_RAM_CONTROL 0x130 -#define BCW_MMIO_RAM_DATA 0x134 -#define BCW_MMIO_SHM_CONTROL 0x160 /* Control */ -#define BCW_MMIO_SHM_DATA 0x164 /* Data - 32bit */ -#define BCW_MMIO_SHM_DATALOW 0x164 /* Data Low - 16bit */ -#define BCW_MMIO_SHM_DATA_UNALIGNED 0x166 /* Data High - 16 bit */ - -#define BCW_MMIO_PHY_RADIO 0x3e2 -#define BCW_MMIO_CHANNEL 0x3f0 -#define BCW_MMIO_CHANNEL_EXT 0x3f4 -#define BCW_MMIO_RADIO_DATA_LOW 0x3fa -#define BCW_MMIO_RADIO_CONTROL 0x3f6 -#define BCW_MMIO_RADIO_DATA_HIGH 0x3f8 -#define BCW_MMIO_PHY_CONTROL 0x3fc -#define BCW_MMIO_PHY_DATA 0x3fe -#define BCW_MMIO_MACFILTER_CONTROL 0x420 -#define BCW_MMIO_MACFILTER_DATA 0x422 -#define BCW_MMIO_GPIO_CONTROL 0x49c -#define BCW_MMIO_GPIO_MASK 0x49e -#define BCW_MMIO_POWERUP_DELAY 0x6a8 - -/* - * SPROM registers are 16 bit and based at MMIO offset 0x1000 - */ -#define BCW_SPROM_BASE 0x1000 -#define BCW_SPROM_BOARDFLAGS2 0x1c -#define BCW_SPROM_IL0MACADDR 0x24 -#define BCW_SPROM_ET0MACADDR 0x27 -#define BCW_SPROM_ET1MACADDR 0x2a -#define BCW_SPROM_ETHPHY 0x2d -#define BCW_SPROM_BOARDREV 0x2e -#define BCW_SPROM_PA0B0 0x2f -#define BCW_SPROM_PA0B1 0x30 -#define BCW_SPROM_PA0B2 0x31 -#define BCW_SPROM_WL0GPIO0 0x32 -#define BCW_SPROM_WL0GPIO2 0x33 -#define BCW_SPROM_MAXPWR 0x34 -#define BCW_SPROM_PA1B0 0x35 -#define BCW_SPROM_PA1B1 0x36 -#define BCW_SPROM_PA1B2 0x37 -#define BCW_SPROM_IDL_TSSI_TGT 0x38 -#define BCW_SPROM_BOARDFLAGS 0x39 -#define BCW_SPROM_ANTENNA_GAIN 0x3a -#define BCW_SPROM_VERSION 0x3f - -/* - * SPROM Board Flags - */ -#define BCW_BF_BTCOEXIST 0x0001 /* Bluetooth Co-existance */ -#define BCW_BF_PACTRL 0x0002 /* GPIO 9 controls PA */ -#define BCW_BF_AIRLINEMODE 0x0004 /* GPIO13 -> radio off LED */ -#define BCW_BF_RSSI 0x0008 /* "something RSSI related */ -#define BCW_BF_ENETSPI 0x0010 /* EPHY Roboswitch SPI */ -#define BCW_BF_XTAL 0x0020 /* XTAL doesn't slow clock */ -#define BCW_BF_CCKHIPWR 0x0040 /* HiPower CCK xmission */ -#define BCW_BF_ENETADM 0x0080 /* has ADMtek Switch */ -#define BCW_BF_ENETVLAN 0x0100 /* VLAN capable - huh? */ -#define BCW_BF_AFTERBURNER 0x0200 /* Afterburner capable */ -#define BCW_BF_NOPCI 0x0400 /* Board leaves PCI floating */ -#define BCW_BF_FEM 0x0800 /* Front End Module support */ -#define BCW_BF_EXTLNA 0x1000 /* has external LNA */ -#define BCW_BF_HGPA 0x2000 /* has High Gain PA */ -#define BCW_BF_BTCMOD 0x4000 /* BTCOEXIST in alt GPIOs */ -#define BCW_BF_ALTIQ 0x8000 /* Alternate I/Q settings */ - -/* - * GPIO register offset, in both ChipCommon and PCI core - */ -#define BCW_GPIO_CTRL 0x6c - -/* - * SHM Routing - */ -#define BCW_SHM_SHARED 0x0001 -#define BCW_SHM_80211 0x0002 -#define BCW_SHM_PCM 0x0003 -#define BCW_SHM_HWMAC 0x0004 -#define BCW_SHM_UCODE 0x0300 - -/* - * MAC filter offsets - */ -#define BCW_MACFILTER_SELF 0 -#define BCW_MACFILTER_ASSOC 0x0003 - -/* - * Chip Common registers - */ -#define BCW_CHIPCOMMON_CAPABILITIES 0x04 -#define BCW_CHIPCOMMON_CTL 0x28 -#define BCW_CHIPCOMMON_PLLONDELAY 0xB0 -#define BCW_CHIPCOMMON_FREFSELDELAY 0xB4 -#define BCW_CHIPCOMMON_SLOWCLKCTL 0xB8 -#define BCW_CHIPCOMMON_SYSCLKCTL 0xC0 - -/* - * PCI core registers - */ -#define BCW_PCICORE_BCAST_ADDR 0x50 -#define BCW_PCICORE_BCAST_DATA 0x54 -#define BCW_PCICORE_SBTOPCI2 0x108 - -/* - * SBTOPCI2 values - */ -#define BCW_SBTOPCI2_PREFETCH 0x4 -#define BCW_SBTOPCI2_BURST 0x8 -#define BCW_SBTOPCI2_MEMREAD_MULTI 0x20 - -/* - * Chip Common capabilities - */ -#define BCW_CAPABILITIES_PCTL 0x00040000 -#define BCW_CAPABILITIES_PLLMASK 0x00030000 -#define BCW_CAPABILITIES_PLLSHIFT 16 -#define BCW_CAPABILITIES_FLASHMASK 0x00000700 -#define BCW_CAPABILITIES_FLASHSHIFT 8 -#define BCW_CAPABILITIES_EXTBUSPRESENT 0x00000040 -#define BCW_CAPABILITIES_UARTGPIO 0x00000020 -#define BCW_CAPABILITIES_UARTCLOCKMASK 0x00000018 -#define BCW_CAPABILITIES_UARTCLOCKSHIFT 3 -#define BCW_CAPABILITIES_MIPSBIGENDIAN 0x00000004 -#define BCW_CAPABILITIES_NRUARTSMASK 0x00000003 - -/* - * Power control - */ -#define BCW_PCTL_IN 0xb0 -#define BCW_PCTL_OUT 0xb4 -#define BCW_PCTL_OUTENABLE 0xb8 -#define BCW_PCTL_XTAL_POWERUP 0x40 -#define BCW_PCTL_PLL_POWERDOWN 0x80 - -/* - * Power control clock modes - */ -#define BCW_PCTL_CLK_FAST 0x00 -#define BCW_PCTL_CLK_SLOW 0x01 -#define BCW_PCTL_CLK_DYNAMIC 0x02 -#define BCW_PCTL_FORCE_SLOW 0x0800 -#define BCW_PCTL_FORCE_PLL 0x1000 -#define BCW_PCTL_DYN_XTAL 0x2000 - -/* - * Core IDs - */ -#define BCW_CORE_COMMON_CHIPID 0x0 -#define BCW_CORE_COMMON 0x800 -#define BCW_CORE_PCI 0x804 -#define BCW_CORE_ENET 0x806 -#define BCW_CORE_PCMCIA 0x80d -#define BCW_CORE_80211 0x812 -#define BCW_CORE_PCIE 0x820 -#define BCW_CORE_MIMOPHY 0x821 -#define BCW_CORE_NONEXIST 0x8ff - -/* - * Core information registers - */ -#define BCW_CIR_BASE 0xf00 -#define BCW_CIR_SBTPSFLAG (BCW_CIR_BASE + 0x18) -#define BCW_CIR_SBIMSTATE (BCW_CIR_BASE + 0x90) -#define BCW_CIR_SBINTVEC (BCW_CIR_BASE + 0x94) -#define BCW_CIR_SBTMSTATELOW (BCW_CIR_BASE + 0x98) -#define BCW_CIR_SBTMSTATEHIGH (BCW_CIR_BASE + 0x9c) -#define BCW_CIR_SBIMCONFIGLOW (BCW_CIR_BASE + 0xa8) -#define BCW_CIR_SB_ID_HI (BCW_CIR_BASE + 0xfc) - -/* sbimconfiglow values/masks */ -#define BCW_SBIMCONFIGLOW_STM 0x00000007 -#define BCW_SBIMCONFIGLOW_STS 0 -#define BCW_SBIMCONFIGLOW_RTM 0x00000070 -#define BCW_SBIMCONFIGLOW_RTS 4 -#define BCW_SBIMCONFIGLOW_CM 0x00ff0000 -#define BCW_SBIMCONFIGLOW_CS 16 - -/* sbtmstatelow state flags */ -#define BCW_SBTMSTATELOW_RESET 0x01 -#define BCW_SBTMSTATELOW_REJECT 0x02 -#define BCW_SBTMSTATELOW_CLOCK 0x10000 -#define BCW_SBTMSTATELOW_FGCLOCK 0x20000 - -/* sbtmstatehigh state flags */ -#define BCW_SBTMSTATEHIGH_SERROR 0x00000001 -#define BCW_SBTMSTATEHIGH_BUSY 0x00000004 -#define BCW_SBTMSTATEHIGH_TIMEOUT 0x00000020 -#define BCW_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000 -#define BCW_SBTMSTATEHIGH_DMA64BIT 0x10000000 -#define BCW_SBTMSTATEHIGH_GATEDCLK 0x20000000 -#define BCW_SBTMSTATEHIGH_BISTFAILED 0x40000000 -#define BCW_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000 - -/* sbimstate flags */ -#define BCW_SBIMSTATE_IB_ERROR 0x20000 -#define BCW_SBIMSTATE_TIMEOUT 0x40000 - -/* - * PHY Versioning - */ -#define BCW_PHY_TYPEA 0x0 /* 802.11a PHY */ -#define BCW_PHY_TYPEB 0x1 /* 802.11b PHY */ -#define BCW_PHY_TYPEG 0x2 /* 802.11g PHY */ -#define BCW_PHY_TYPEN 0x4 /* 802.11n PHY */ - -/* - * PHY registers - */ -#define BCW_PHY_ILT_A_CTRL 0x0072 -#define BCW_PHY_ILT_A_DATA1 0x0073 -#define BCW_PHY_G_LO_CONTROL 0x0810 -#define BCW_PHY_ILT_G_CTRL 0x0472 -#define BCW_PHY_ILT_G_DATA1 0x0473 -#define BCW_PHY_G_CRS 0x0429 -#define BCW_PHY_A_CRS 0x0029 -#define BCW_PHY_RADIO_BITFIELD 0x0401 -#define BCW_PHY_A_PCTL 0x007b -#define BCW_PHY_G_PCTL 0x0029 -#define BCW_PHY_NRSSILT_CTRL 0x0803 -#define BCW_PHY_NRSSILT_DATA 0x0804 - -/* - * Radio Registers - */ -#define BCW_RADIO_ID 0x01 - -/* - * Status Bit Fields - */ -#define BCW_SBF_MAC_ENABLED 0x00000001 -#define BCW_SBF_CORE_READY 0x00000004 -#define BCW_SBF_400_MAGIC 0x00000400 -#define BCW_SBF_REGISTER_BYTESWAP 0x00010000 -#define BCW_SBF_ADHOC 0x00020000 -#define BCW_SBF_AP 0x00040000 -#define BCW_SBF_RADIOREG_LOCK 0x00080000 -#define BCW_SBF_MONITOR 0x00400000 -#define BCW_SBF_PROMISC 0x01000000 -#define BCW_SBF_PS1 0x02000000 -#define BCW_SBF_PS2 0x04000000 -#define BCW_SBF_SSID_BCAST 0x08000000 -#define BCW_SBF_TIME_UPDATE 0x10000000 - -/* - * Microcode - */ -#define BCW_UCODE_REVISION 0x0000 -#define BCW_UCODE_PATCHLEVEL 0x0002 -#define BCW_UCODE_DATE 0x0004 -#define BCW_UCODE_TIME 0x0006 -#define BCW_UCODE_STATUS 0x0040 - -/* - * Microcode Flags Bitfield - * - * http://bcm-specs.sipsolutions.net/MicrocodeFlagsBitfield - */ -#define BCW_UCODEFLAGS_OFFSET 0x005e - -#define BCW_UCODEFLAG_AUTODIV 0x0001 -#define BCW_UCODEFLAG_UNKBGPHY 0x0002 -#define BCW_UCODEFLAG_UNKBPHY 0x0004 -#define BCW_UCODEFLAG_UNKGPHY 0x0020 -#define BCW_UCODEFLAG_UNKPACTRL 0x0040 -#define BCW_UCODEFLAG_JAPAN 0x0080 - -/* - * Generic interrupt reasons - */ -#define BCW_INTR_READY (1 << 0) -#define BCW_INTR_BEACON (1 << 1) -#define BCW_INTR_PS (1 << 2) -#define BCW_INTR_REG124 (1 << 5) -#define BCW_INTR_PMQ (1 << 6) -#define BCW_INTR_PIO_WORKAROUND (1 << 8) -#define BCW_INTR_XMIT_ERROR (1 << 11) -#define BCW_INTR_RX (1 << 15) -#define BCW_INTR_SCAN (1 << 16) -#define BCW_INTR_NOISE (1 << 18) -#define BCW_INTR_XMIT_STATUS (1 << 29) - -#define BCW_INTR_ALL 0xffffffff -#define BCW_INTR_INITIAL (BCW_INTR_PS | \ - BCW_INTR_REG124 | \ - BCW_INTR_PMQ | \ - BCW_INTR_XMIT_ERROR | \ - BCW_INTR_RX | \ - BCW_INTR_SCAN | \ - BCW_INTR_NOISE | \ - BCW_INTR_XMIT_STATUS) - -/* - * XXX 0x300 PIO Register space - */ -#define BCW_RADIO_BASEBAND 0x3e6 /* Baseband Attenuation */ - -/* - * XXX Do we really need those ... - */ -#define BCW_GPIOI 0xb0 -#define BCW_GPIOO 0xb4 -#define BCW_GPIOE 0xb8 -#define BCW_ADDR_SPACE0 0x80 -/* transmit control bits */ -#define BCW_DMA_TXADDR 0x0204 -#define BCW_DMA_RXADDR 0x0214 -/* receive status bits */ -#define RS_CD_MASK 0x0fff -/* SiliconBackplane registers 0xea8 through 0xffc */ -#define SBIM_REJECT 0x0200000 -#define SBIM_INBANDERR 0x20000 -#define SBIM_TIMEOUT 0x40000 -#define SBTML_RESET 0x1 -#define SBTML_REJ 0x6 -#define SBTML_REJ22 0x2 -#define SBTML_REJ23 0x4 -#define SBTML_CLK 0x10000 -#define SBTML_FGC 0x20000 -#define SBTML_80211FLAG 0x40000 -#define SBTML_80211PHY 0x20000000 -#define SBTMH_SERR 0x1 -#define SBTMH_BUSY 0x4 -#define SBREV_MASK 0xf0000000 -#define SBREV_MASK_SHIFT 28 -#define SBTPS_BACKPLANEFLAGMASK 0x3f -#define BCW_SBTMSTATEHI 0x0f9C -#define BCW_SBTPSFLAG 0x0f18 -#define BCW_SBIMSTATE 0x0f90 -#define BCW_SBTMSTATELOW 0x0f98 -#define BCW_CIR_SBID_LO 0xff8 -#define BCW_CIR_SBID_LO_INITIATOR 0x80 -#define BCW_CIR_SBID_HI 0xffc - -/* - * XXX Do we really need those ... - */ -#define BCW_DMA_TXCONTROL(x) (0x200 + (x * 0x20)) -#define BCW_DMA_RXCONTROL(x) (0x200 + (x * 0x20)) -#define BCW_DMA_RXSTATUS(x) (0x20c + (x * 0x20)) - -/* - * Core select address macro - */ -#define BCW_CORE_SELECT(x) (0x18000000 + (x * 0x1000)) - -/* - * 16-bit and 32-bit register read/write - */ -#define BCW_READ16(sc, reg) \ - bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg)) -#define BCW_READ(sc, reg) \ - bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)) -#define BCW_WRITE16(sc, reg, val) \ - bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) -#define BCW_WRITE(sc, reg, val) \ - bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) diff --git a/sys/dev/ic/bcwvar.h b/sys/dev/ic/bcwvar.h deleted file mode 100644 index 2f6ce9bca53..00000000000 --- a/sys/dev/ic/bcwvar.h +++ /dev/null @@ -1,397 +0,0 @@ -/* $OpenBSD: bcwvar.h,v 1.37 2007/04/04 19:36:42 mglocker Exp $ */ - -/* - * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> - * Copyright (c) 2006 Jon Simola <jsimola@gmail.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Broadcom BCM43xx Wireless network chipsets (broadcom.com) - * SiliconBackplane is technology from Sonics, Inc. (sonicsinc.com) - */ - -#define BCW_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) - -#define BCW_FLAGS_INITIALIZED 0x00000001 - -#define BCW_DEFAULT_SHORT_RETRY_LIMIT 7 -#define BCW_DEFAULT_LONG_RETRY_LIMIT 4 - -struct fwheader { - char filename[64]; - int filesize; - int fileoffset; -}; - -struct bcw_initval { - uint16_t offset; - uint16_t size; - uint32_t value; -} __packed; - -#define BCW_NR_LEDS 4 -struct bcw_led { - uint8_t behaviour:7; - uint8_t activelow:1; - unsigned long blink_interval; -}; -enum { - BCW_LED_OFF, - BCW_LED_ON, - BCW_LED_ACTIVITY, - BCW_LED_RADIO_ALL, - BCW_LED_RADIO_A, - BCW_LED_RADIO_B, - BCW_LED_MODE_BG, - BCW_LED_TRANSFER, - BCW_LED_APTRANSFER, - BCW_LED_WEIRD, /* XXX */ - BCW_LED_ASSOC, - BCW_LED_INACTIVE, - - /* - * Behaviour values for testing. - * With these values it is easier to figure out - * the real behaviour of leds, in case the SPROM - * is missing information. - */ - BCW_LED_TEST_BLINKSLOW, - BCW_LED_TEST_BLINKMEDIUM, - BCW_LED_TEST_BLINKFAST, - - /* misc values for BCM4303 */ - BCW_LED_BCM4303_0 = 0x2B, - BCW_LED_BCM4303_1 = 0x78, - BCW_LED_BCM4303_2 = 0x2E, - BCW_LED_BCM4303_3 = 0x19, -}; - -#define BCW_RADIO_TXANTENNA_LASTPLCP 3 -#define BCW_RADIO_TXANTENNA_DEFAULT BCW_RADIO_TXANTENNA_LASTPLCP -#define BCW_RADIO_INTERFMODE_NONE 0 -#define BCW_RADIO_INTERFMODE_NONWLAN 1 -#define BCW_RADIO_INTERFMODE_MANUALWLAN 2 -#define BCW_RADIO_INTERFMODE_AUTOWLAN 3 -#define BCW_RADIO_DEFAULT_CHANNEL_A 36 -#define BCW_RADIO_DEFAULT_CHANNEL_BG 6 -#define BCW_RADIO_MAX 2 -struct bcw_radio { - uint16_t id; - uint16_t info; - u_char enabled; -}; - -#define BCW_MAX_CORES 10 -struct bcw_core { - uint16_t id; - uint8_t index; - uint8_t rev; - uint8_t backplane_flag; -}; - -/* number of descriptors used in a ring */ -#define BCW_RX_RING_COUNT 128 -#define BCW_TX_RING_COUNT 128 -#define BCW_MAX_SCATTER 8 /* XXX unknown, wild guess */ - -struct bcw_rx_data { - bus_dmamap_t map; - struct mbuf *m; -}; - -struct bcw_tx_data { - bus_dmamap_t map; - struct mbuf *m; - uint32_t softstat; - struct ieee80211_node *ni; -}; - -struct bcw_rx_ring { - bus_dmamap_t map; - bus_dma_segment_t seg; - bus_addr_t physaddr; - struct bcw_desc *desc; - struct bcw_rx_data *data; - int count; - int cur; - int next; -}; - -struct bcw_tx_ring { - bus_dmamap_t map; - bus_dma_segment_t seg; - bus_addr_t physaddr; - struct bcw_desc *desc; - struct bcw_tx_data *data; - int count; - int queued; - int cur; - int next; - int stat; -}; - -struct bcw_desc { - uint32_t ctrl; - uint32_t addr; -}; - -/* ring descriptor */ -struct bcw_dma_slot { - uint32_t ctrl; - uint32_t addr; -}; - -struct bcw_lopair { - int8_t low; - int8_t high; - uint8_t used:1; -}; -#define BCW_LO_COUNT (14 * 4) - -#define CTRL_BC_MASK 0x1fff /* buffer byte count */ -#define CTRL_EOT 0x10000000 /* end of descriptor table */ -#define CTRL_IOC 0x20000000 /* interrupt on completion */ -#define CTRL_EOF 0x40000000 /* end of frame */ -#define CTRL_SOF 0x80000000 /* start of frame */ - -/* radio */ -#define BCW_INTERFSTACK_SIZE 26 - -/* ilt */ -#define BCW_ILT_FINEFREQA_SIZE 256 -#define BCW_ILT_FINEFREQG_SIZE 256 -#define BCW_ILT_NOISEA2_SIZE 8 -#define BCW_ILT_NOISEA3_SIZE 8 -#define BCW_ILT_NOISEG1_SIZE 8 -#define BCW_ILT_NOISEG2_SIZE 8 -#define BCW_ILT_ROTOR_SIZE 53 -#define BCW_ILT_RETARD_SIZE 53 -#define BCW_ILT_SIGMASQR_SIZE 53 -#define BCW_ILT_NOISESCALEG_SIZE 27 - -#if 0 -/* - * Mbuf pointers. We need these to keep track of the virtual addresses - * of our mbuf chains since we can only convert from physical to virtual, - * not the other way around. - * - * The chip has 6 DMA engines, looks like we only need to use one each - * for TX and RX, the others stay disabled. - */ -struct bcw_chain_data { - struct mbuf *bcw_tx_chain[BCW_NTXDESC]; - struct mbuf *bcw_rx_chain[BCW_NRXDESC]; - bus_dmamap_t bcw_tx_map[BCW_NTXDESC]; - bus_dmamap_t bcw_rx_map[BCW_NRXDESC]; -}; -#endif - -struct bcw_rx_ring; -struct bcw_tx_ring; - -#define BCW_SPROM_SIZE 64 /* in 16-bit words */ -struct bcw_sprom { - uint16_t boardflags2; - uint8_t il0macaddr[6]; - uint8_t et0macaddr[6]; - uint8_t et1macaddr[6]; - uint8_t et1phyaddr:5; - uint8_t et0phyaddr:5; - uint8_t et0mdcport:1; - uint8_t et1mdcport:1; - uint8_t boardrev; - uint8_t locale:4; - uint8_t antennas_aphy:2; - uint8_t antennas_bgphy:2; - uint16_t pa0b0; - uint16_t pa0b1; - uint16_t pa0b2; - uint8_t wl0gpio0; - uint8_t wl0gpio1; - uint8_t wl0gpio2; - uint8_t wl0gpio3; - uint8_t maxpower_aphy; - uint8_t maxpower_bgphy; - uint16_t pa1b0; - uint16_t pa1b1; - uint16_t pa1b2; - uint8_t idle_tssi_tgt_aphy; - uint8_t idle_tssi_tgt_bgphy; - uint16_t boardflags; - uint16_t antennagain_aphy; - uint16_t antennagain_bgphy; -}; - -struct bcw_softc { - struct device sc_dev; - struct ieee80211com sc_ic; - struct bcw_rx_ring sc_rxring; - struct bcw_tx_ring sc_txring; - /* function pointers */ - int (*sc_newstate)(struct ieee80211com *, - enum ieee80211_state, int); - int (*sc_enable)(struct bcw_softc *); - void (*sc_disable)(struct bcw_softc *); - void (*sc_power)(struct bcw_softc *, int); - void (*sc_conf_write)(void *, uint32_t, uint32_t); - uint32_t (*sc_conf_read)(void *, uint32_t); - - bus_dma_tag_t sc_dmat; - bus_space_tag_t sc_iot; - bus_space_handle_t sc_ioh; - - void *sc_dev_softc; - uint32_t sc_flags; - uint32_t sc_intmask; /* current intr mask */ - uint32_t sc_rxin; /* last rx desc seen */ - uint32_t sc_txin; /* last tx desc seen */ - int sc_txsfree; /* no. tx slots avail */ - int sc_txsnext; /* next avail tx slot */ - bus_dmamap_t sc_ring_map; - struct bcw_dma_slot *bcw_rx_ring; /* receive ring */ - struct bcw_dma_slot *bcw_tx_ring; /* transmit ring */ - struct timeout sc_timeout; - struct timeout sc_scan_to; - //struct bcw_chain_data sc_cdata; /* mbufs */ - - uint16_t sc_board_vendor; /* Board vendor */ - uint16_t sc_board_type; /* Board type */ - uint16_t sc_board_rev; /* Board revision */ - uint16_t sc_chip_id; /* Chip ID */ - uint16_t sc_chip_rev; /* Chip revision */ - uint16_t sc_chip_pkg; /* Chip package */ - uint16_t sc_prodid; /* Product ID */ - uint8_t sc_idletssi; - uint16_t sc_boardflags; - uint16_t sc_using_pio:1; - struct bcw_sprom sc_sprom; - struct bcw_led leds[BCW_NR_LEDS]; - /* cores */ - uint16_t sc_numcores; - uint16_t sc_havecommon; - int sc_currentcore; - int sc_lastcore; - uint32_t sc_chip_common_capa; - struct bcw_core sc_core[BCW_MAX_CORES]; - struct bcw_core *sc_core_common; - struct bcw_core *sc_core_80211; - struct bcw_core *sc_core_bus; /* PCI or cardbus */ - /* PHY */ - uint16_t sc_phy_ver; - uint16_t sc_phy_rev; - uint16_t sc_phy_type; - uint8_t sc_phy_connected:1, /* XXX */ - sc_phy_calibrated:1, - sc_phy_is_locked:1, - sc_phy_dyn_tssi_tbl:1; - uint16_t sc_phy_loopback_gain[2]; - uint16_t sc_phy_savedpctlreg; - uint16_t sc_phy_minlowsig[2]; - uint16_t sc_phy_minlowsigpos[2]; - int8_t sc_phy_idle_tssi; - const int8_t sc_phy_tssi2dbm; - uint16_t sc_phy_antenna_diversity; - struct bcw_lopair *sc_phy_lopairs; - /* radio */ - uint16_t sc_radio_ver; - uint16_t sc_radio_rev; - uint32_t sc_radio_mnf; - uint16_t sc_radio_initval; - int16_t sc_radio_nrssi[2]; - int sc_radio_interfmode; - uint8_t sc_radio_aci_enable:1, - sc_radio_aci_wlan_automatic:1, - sc_radio_aci_hw_rssi; - int32_t sc_radio_nrssislope; - uint16_t sc_radio_txpwr_offset; - uint16_t sc_radio_lofcal; - uint16_t sc_radio_txpower_desired; - uint16_t sc_radio_pa0b0; - uint16_t sc_radio_pa0b1; - uint16_t sc_radio_pa0b2; - uint16_t sc_radio_pa1b0; - uint16_t sc_radio_pa1b1; - uint16_t sc_radio_pa1b2; - uint16_t sc_radio_baseband_atten; - uint16_t sc_radio_radio_atten; - uint16_t sc_radio_txctl1; - uint16_t sc_radio_txctl2; - uint8_t sc_radio_channel; - int8_t sc_radio_nrssi_lt[64]; - uint32_t sc_radio_interfstack[BCW_INTERFSTACK_SIZE]; - //struct bcw_radio radio[BCW_RADIO_MAX]; -}; - -void bcw_attach(struct bcw_softc *); -int bcw_detach(void *); -int bcw_intr(void *); -void bcw_powercontrol_crystal_on(struct bcw_softc *); - -#define BCW_DEBUG -#ifdef BCW_DEBUG -//#define DPRINTF(x) do { if (bcw_debug) printf x; } while (0) -//#define DPRINTFN(n,x) do { if (bcwdebug >= (n)) printf x; } while (0) -#define DPRINTF(x) do { if (1) printf x; } while (0) -#define DPRINTFN(n,x) do { if (1 >= (n)) printf x; } while (0) -//int bcw_debug = 99; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -/* - * Some legacy stuff from bce and iwi to make this compile - */ -/* transmit buffer max frags allowed */ -#define BCW_NTXFRAGS 16 - -/* Packet status is returned in a pre-packet header */ -struct rx_pph { - uint16_t len; - uint16_t flags; - uint16_t pad[12]; -}; - -#define BCW_PREPKT_HEADER_SIZE 30 - -/* packet status flags bits */ -#define RXF_NO 0x8 /* odd number of nibbles */ -#define RXF_RXER 0x4 /* receive symbol error */ -#define RXF_CRC 0x2 /* crc error */ -#define RXF_OV 0x1 /* fifo overflow */ - -#define BCW_TIMEOUT 100 /* # 10us for mii read/write */ - -/* for ring descriptors */ -#define BCW_RXBUF_LEN (MCLBYTES - 4) -#define BCW_INIT_RXDESC(sc, x) \ -do { \ - struct bcw_dma_slot *__bcwd = &sc->bcw_rx_ring[x]; \ - \ - *mtod(sc->bcw_cdata.bcw_rx_chain[x], uint32_t *) = 0; \ - __bcwd->addr = \ - htole32(sc->bcw_cdata.bcw_rx_map[x]->dm_segs[0].ds_addr \ - + 0x40000000); \ - if (x != (BCW_NRXDESC - 1)) \ - __bcwd->ctrl = htole32(BCW_RXBUF_LEN); \ - else \ - __bcwd->ctrl = htole32(BCW_RXBUF_LEN | CTRL_EOT); \ - bus_dmamap_sync(sc->bcw_dmatag, sc->bcw_ring_map, \ - sizeof(struct bcw_dma_slot) * x, \ - sizeof(struct bcw_dma_slot), \ - BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \ -} while (/* CONSTCOND */ 0) - -#define BCW_NTXFRAGS 16 |