summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/bcw.c507
-rw-r--r--sys/dev/ic/bcwreg.h19
-rw-r--r--sys/dev/ic/bcwvar.h12
3 files changed, 523 insertions, 15 deletions
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c
index 0fa159d043f..00d6b4391c5 100644
--- a/sys/dev/ic/bcw.c
+++ b/sys/dev/ic/bcw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcw.c,v 1.68 2007/03/04 19:04:31 mglocker Exp $ */
+/* $OpenBSD: bcw.c,v 1.69 2007/03/12 06:51:16 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -78,6 +78,10 @@ void bcw_dummy_transmission(struct bcw_softc *);
struct bcw_lopair *
bcw_get_lopair(struct bcw_softc *sc, uint16_t radio_atten,
uint16_t baseband_atten);
+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_reset(struct bcw_softc *);
int bcw_init(struct ifnet *);
@@ -151,6 +155,7 @@ struct bcw_lopair *
struct bcw_lopair *
bcw_phy_current_lopair(struct bcw_softc *);
void bcw_phy_prepare_init(struct bcw_softc *);
+void bcw_phy_set_antenna_diversity(struct bcw_softc *);
/* radio */
void bcw_radio_off(struct bcw_softc *);
void bcw_radio_on(struct bcw_softc *);
@@ -183,6 +188,10 @@ 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);
void bcw_radio_prepare_init(struct bcw_softc *);
+int bcw_radio_set_interference_mitigation(struct bcw_softc *, int);
+int bcw_radio_interference_mitigation_enable(struct bcw_softc *,
+ int);
+void bcw_radio_set_txantenna(struct bcw_softc *, uint32_t);
/* ilt */
void bcw_ilt_write(struct bcw_softc *, uint16_t, uint16_t);
uint16_t bcw_ilt_read(struct bcw_softc *, uint16_t);
@@ -191,6 +200,17 @@ 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)
+
/*
* Table for bcw_radio_calibrationvalue()
*/
@@ -680,6 +700,48 @@ bcw_get_lopair(struct bcw_softc *sc, uint16_t radio_atten,
}
void
+bcw_stack_save(uint32_t *_stackptr, size_t *stackidx, uint8_t id,
+ uint16_t offset, uint16_t val)
+{
+ uint32_t *stackptr = &(_stackptr[*stackidx]);
+
+ /* XXX assert() */
+
+ *stackptr = offset;
+ *stackptr |= ((uint32_t)id) << 12;
+ *stackptr |= ((uint32_t)val) << 16;
+ (*stackidx)++;
+
+ /* XXX assert() */
+}
+
+uint16_t
+bcw_stack_restore(uint32_t *stackptr, uint8_t id, uint16_t offset)
+{
+ size_t i;
+
+ /* XXX assert() */
+
+ for (i = 0; i < BCW_INTERFSTACK_SIZE; i++, stackptr++) {
+ if ((*stackptr & 0x00000fff) != offset)
+ continue;
+ if (((*stackptr & 0x0000f000) >> 12) != id)
+ continue;
+ return (((*stackptr & 0xffff0000) >> 16));
+ }
+
+ /* XXX assert() */
+
+ return (0);
+}
+
+int
+bcw_using_pio(struct bcw_softc *sc)
+{
+ return (sc->sc_using_pio);
+}
+
+void
bcw_attach(struct bcw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -1672,7 +1734,8 @@ bcw_init(struct ifnet *ifp)
{
struct bcw_softc *sc = ifp->if_softc;
uint16_t val16;
- int error, i;
+ uint32_t val32;
+ int error, i, tmp;
BCW_WRITE(sc, BCW_SBF, BCW_SBF_CORE_READY | BCW_SBF_400_MAGIC);
@@ -1736,8 +1799,67 @@ bcw_init(struct ifnet *ifp)
if ((error = bcw_phy_init(sc)))
return (error);
- return (0);
+ /* select initial interference mitigation */
+ tmp = sc->sc_radio_interfmode;
+ sc->sc_radio_interfmode = BCW_RADIO_INTERFMODE_NONE;
+ bcw_radio_set_interference_mitigation(sc, tmp);
+
+ bcw_phy_set_antenna_diversity(sc);
+ bcw_radio_set_txantenna(sc, BCW_RADIO_TXANTENNA_DEFAULT);
+ if (sc->sc_phy_type == BCW_PHY_TYPEB) {
+ val16 = BCW_READ16(sc, 0x005e);
+ val16 |= 0x0004;
+ BCW_WRITE16(sc, 0x005e, val16);
+ }
+ BCW_WRITE(sc, 0x0100, 0x01000000);
+ if (1) /* XXX current_core->rev */
+ BCW_WRITE(sc, 0x010c, 0x01000000);
+
+ val32 = BCW_READ(sc, BCW_SBF);
+ val32 &= ~BCW_SBF_ADHOC;
+ BCW_WRITE(sc, BCW_SBF, val32);
+ val32 = BCW_READ(sc, BCW_SBF);
+ val32 |= BCW_SBF_ADHOC;
+ BCW_WRITE(sc, BCW_SBF, val32);
+
+ val32 = BCW_READ(sc, BCW_SBF);
+ val32 |= 0x100000;
+ BCW_WRITE(sc, BCW_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_CONTROL_SHARED, 0x0034, 0);
+ }
+
+ bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED, 0x0074, 0);
+
+ if (1) { /* XXX core_rev */
+ 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, 0x0606, 0x02000000);
+ }
+ BCW_WRITE(sc, BCW_GIR, 0x00004000);
+ BCW_WRITE(sc, BCW_DMA0_INT_MASK, 0x0001dc00);
+ BCW_WRITE(sc, BCW_DMA1_INT_MASK, 0x0000dc00);
+ BCW_WRITE(sc, BCW_DMA2_INT_MASK, 0x0000dc00);
+ BCW_WRITE(sc, BCW_DMA3_INT_MASK, 0x0001dc00);
+ BCW_WRITE(sc, BCW_DMA4_INT_MASK, 0x0000dc00);
+ BCW_WRITE(sc, BCW_DMA5_INT_MASK, 0x0000dc00);
+
+ val32 = BCW_READ(sc, BCW_CIR_SBTMSTATELOW);
+ val32 |= 0x00100000;
+ BCW_WRITE(sc, BCW_CIR_SBTMSTATELOW, val32);
+ DPRINTF(("%s: Chip initialized\n", sc->sc_dev.dv_xname));
+
+#if 0
/* Cancel any pending I/O. */
bcw_stop(ifp, 0);
@@ -1751,7 +1873,6 @@ bcw_init(struct ifnet *ifp)
/* enable pci interrupts, bursts, and prefetch */
/* remap the pci registers to the Sonics config registers */
-#if 0
/* XXX - use (sc->sc_conf_read/write) */
/* save the current map, so it can be restored */
reg_win = BCW_READ(sc, BCW_REG0_WIN);
@@ -1771,14 +1892,12 @@ bcw_init(struct ifnet *ifp)
/* Reset the chip to a known state. */
bcw_reset(sc);
-#endif
-#if 0 /* FIXME */
+ /* FIXME */
/* Initialize transmit descriptors */
memset(sc->bcw_tx_ring, 0, BCW_NTXDESC * sizeof(struct bcw_dma_slot));
sc->sc_txsnext = 0;
sc->sc_txin = 0;
-#endif
/* enable crc32 generation and set proper LED modes */
BCW_WRITE(sc, BCW_MACCTL,
@@ -1817,16 +1936,14 @@ bcw_init(struct ifnet *ifp)
I_XI | I_RI | I_XU | I_RO | I_RU | I_DE | I_PD | I_PC | I_TO;
BCW_WRITE(sc, BCW_INT_MASK, sc->sc_intmask);
-#if 0
/* FIXME */
/* start the receive dma */
BCW_WRITE(sc, BCW_DMA_RXDPTR,
BCW_NRXDESC * sizeof(struct bcw_dma_slot));
-#endif
/* set media */
//mii_mediachg(&sc->bcw_mii);
-#if 0
+
/* turn on the ethernet mac */
BCW_WRITE(sc, BCW_ENET_CTL, BCW_READ(sc, BCW_ENET_CTL) | EC_EE);
@@ -1915,7 +2032,7 @@ bcw_stop(struct ifnet *ifp, int disable)
ifp->if_timer = 0;
/* Disable interrupts. */
- BCW_WRITE(sc, BCW_INT_MASK, 0);
+ BCW_WRITE(sc, BCW_DMA0_INT_MASK, 0);
sc->sc_intmask = 0;
delay(10);
@@ -4999,6 +5116,112 @@ bcw_phy_prepare_init(struct bcw_softc *sc)
memset(sc->sc_phy_loopback_gain, 0, sizeof(sc->sc_phy_loopback_gain));
}
+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;
+ /* XXX assert() */
+
+ ucodeflags = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED,
+ BCW_SHM_MICROCODEFLAGSLOW);
+ bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED, BCW_SHM_MICROCODEFLAGSLOW,
+ ucodeflags & ~BCW_SHM_MICROCODEFLAGSAUTODIV);
+
+ 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 (1) /* XXX current_core->rev */
+ val = (3 << 7);
+ else
+ val = (antennadiv << 7);
+ bcw_phy_write16(sc, 0x03e2, (bcw_phy_read16(sc, 0x03e2) &
+ 0xfe7f) | val);
+ break;
+ default:
+ /* XXX assert() */
+ break;
+ }
+
+ if (antennadiv >= 2) {
+ ucodeflags = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED,
+ BCW_SHM_MICROCODEFLAGSLOW);
+ bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED,
+ BCW_SHM_MICROCODEFLAGSLOW, ucodeflags |
+ BCW_SHM_MICROCODEFLAGSAUTODIV);
+ }
+
+ sc->sc_phy_antenna_diversity = antennadiv;
+}
+
/*
* Radio
*/
@@ -6160,6 +6383,268 @@ bcw_radio_prepare_init(struct bcw_softc *sc)
sc->sc_radio_aci_hw_rssi = 0;
}
+int
+bcw_radio_set_interference_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_interference_mitigation_enable(sc, mode);
+ sc->sc_radio_interfmode = mode;
+
+ return (0);
+}
+
+int
+bcw_radio_interference_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;
+ }
+ /* XXX radio_stacksave() */
+ tmp = (bcw_radio_read16(sc, 0x0078) & 0x001e);
+ flipped = tmp; /* XXX flip_4bit(tmp) */
+ if (flipped < 10 && flipped >= 8)
+ flipped = 7;
+ else if (flipped >= 10)
+ flipped -= 3;
+ flipped = flipped; /* XXX 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_CONTROL_SHARED,
+ BCW_SHM_MICROCODEFLAGSLOW);
+ if (!(tmp32 & 0x800)) {
+ tmp32 |= 0x800;
+ bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED,
+ BCW_SHM_MICROCODEFLAGSLOW, 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 assert () */
+ 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_CONTROL_SHARED, 0x0022) & 0xfcff;
+ bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED, 0x0022, tmp | val);
+ tmp = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED, 0x03a8) & 0xfcff;
+ bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED, 0x03a8, tmp | val);
+ tmp = bcw_shm_read16(sc, BCW_SHM_CONTROL_SHARED, 0x0054) & 0xfcff;
+ bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED, 0x0054, tmp | val);
+}
+
/*
* ILT
*/
diff --git a/sys/dev/ic/bcwreg.h b/sys/dev/ic/bcwreg.h
index 2e8182ce6fb..0874ec15724 100644
--- a/sys/dev/ic/bcwreg.h
+++ b/sys/dev/ic/bcwreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcwreg.h,v 1.16 2007/03/04 14:27:27 mglocker Exp $ */
+/* $OpenBSD: bcwreg.h,v 1.17 2007/03/12 06:51:16 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -48,6 +48,10 @@
/* Core select address macro */
#define BCW_CORE_SELECT(x) (0x18000000 + (x * 0x1000))
+/* Core information registers */
+#define BCW_CIR_BASE 0xf00
+#define BCW_CIR_SBTMSTATELOW (BCW_CIR_BASE + 0x98)
+
/* Some Core Types */
#define BCW_CORE_COMMON 0x800
#define BCW_CORE_PCI 0x804
@@ -80,8 +84,14 @@
#define BCW_DC_IP 0x00000400 /* internal phy present */
#define BCW_DC_ER 0x00008000 /* ephy reset */
/* Interrupt Control */
-#define BCW_INT_STS 0x0020
-#define BCW_INT_MASK 0x0024
+#define BCW_INT_STS 0x20
+#define BCW_DMA0_INT_MASK 0x24
+#define BCW_DMA1_INT_MASK 0x2c
+#define BCW_DMA2_INT_MASK 0x34
+#define BCW_DMA3_INT_MASK 0x3c
+#define BCW_DMA4_INT_MASK 0x44
+#define BCW_DMA5_INT_MASK 0x4c
+
/* bits for both status, and mask */
#define I_TO 0x00000080 /* general timeout */
#define I_PC 0x00000400 /* descriptor error */
@@ -220,6 +230,7 @@
/* SHM Addresses */
#define BCW_SHM_MICROCODEFLAGSLOW 0x005e /* Flags for Microcode ops */
#define BCW_SHM_MICROCODEFLAGSHIGH 0x0060 /* Flags for Microcode ops */
+#define BCW_SHM_MICROCODEFLAGSAUTODIV 0x0001
/* http://bcm-specs.sipsolutions.net/MicrocodeFlagsBitfield */
/* 0x200 DMA Register space, there are 6 controllers */
@@ -336,6 +347,8 @@
#define BCW_UCODE_TIME 0x0006
#define BCW_UCODE_STATUS 0x0040
+#define BCW_PHY_RADIO_BITFIELD 0x0401
+
/* GPIO */
#define BCW_GPIO_MASK 0x49e
#define BCW_GPIO_CTRL 0x6c
diff --git a/sys/dev/ic/bcwvar.h b/sys/dev/ic/bcwvar.h
index 7baa47c1622..a21f073b829 100644
--- a/sys/dev/ic/bcwvar.h
+++ b/sys/dev/ic/bcwvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcwvar.h,v 1.27 2007/03/04 00:43:26 mglocker Exp $ */
+/* $OpenBSD: bcwvar.h,v 1.28 2007/03/12 06:51:16 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -73,7 +73,12 @@ enum {
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
@@ -155,6 +160,9 @@ struct bcw_lopair {
#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
@@ -233,6 +241,7 @@ struct bcw_softc {
uint16_t sc_prodid; /* Product ID */
struct bcw_core sc_core[BCW_MAX_CORES];
// struct bcw_radio radio[BCW_RADIO_MAX];
+ uint16_t sc_using_pio:1;
uint16_t sc_phy_ver;
uint16_t sc_phy_type;
uint16_t sc_phy_rev;
@@ -280,6 +289,7 @@ struct bcw_softc {
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];
uint8_t sc_idletssi;
uint8_t sc_spromrev;
uint16_t sc_boardflags;