summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2007-03-15 14:30:50 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2007-03-15 14:30:50 +0000
commitb550624e3aaf045504c970f073b30a2660690a6a (patch)
tree1094c860f81e7a99ea9be98ecc8c49cfca096d4d /sys
parent5334f79b7436e2f6c3db0b4b66e9406e7e902f1c (diff)
Set chip operation mode in the init path. Add first bits to enable
interrupts at some point.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/bcw.c169
-rw-r--r--sys/dev/ic/bcwreg.h24
2 files changed, 187 insertions, 6 deletions
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c
index 3e524e5e8f4..d8e1dc88e99 100644
--- a/sys/dev/ic/bcw.c
+++ b/sys/dev/ic/bcw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcw.c,v 1.70 2007/03/12 22:29:38 mglocker Exp $ */
+/* $OpenBSD: bcw.c,v 1.71 2007/03/15 14:30:49 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -67,6 +67,7 @@ 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_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);
@@ -88,6 +89,10 @@ 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_mac_enable(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 *);
//void bcw_add_mac(struct bcw_softc *, uint8_t *, unsigned long);
@@ -195,6 +200,8 @@ 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);
+/* power */
+void bcw_power_saving_ctl_bits(struct bcw_softc *, int, int);
struct cfdriver bcw_cd = {
NULL, "bcw", DV_IFNET
@@ -549,6 +556,29 @@ bcw_shm_write16(struct bcw_softc *sc, uint16_t routing, uint16_t offset,
BCW_WRITE16(sc, BCW_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_CONTROL_SHARED) {
+ if (offset & 0x003) {
+ /* unaligned acccess */
+ bcw_shm_ctl_word(sc, routing, offset >> 2);
+ r = BCW_READ16(sc, BCW_SHM_DATAHIGH);
+ r <<= 16;
+ bcw_shm_ctl_word(sc, routing, (offset >> 2) + 1);
+ r |= BCW_READ16(sc, BCW_SHM_DATA);
+ return (r);
+ }
+ offset >>= 2;
+ }
+ bcw_shm_ctl_word(sc, routing, offset);
+ r = BCW_READ(sc, BCW_SHM_DATA);
+
+ return (r);
+}
+
void
bcw_radio_write16(struct bcw_softc *sc, uint16_t offset, uint16_t val)
{
@@ -1499,17 +1529,105 @@ bcw_watchdog(struct ifnet *ifp)
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_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_mac_enable(struct bcw_softc *sc)
+{
+ BCW_WRITE(sc, BCW_SBF, BCW_READ(sc, BCW_SBF) | BCW_SBF_MAC_ENABLED);
+ BCW_WRITE(sc, BCW_GIR, BCW_INTR_READY);
+ BCW_READ(sc, BCW_SBF); /* dummy read */
+ BCW_READ(sc, BCW_GIR); /* dummy read */
+ bcw_power_saving_ctl_bits(sc, -1, -1);
+}
+
+uint32_t
+bcw_intr_enable(struct bcw_softc *sc, uint32_t mask)
+{
+ uint32_t old_mask;
+
+ old_mask = BCW_READ(sc, BCW_GIM);
+ BCW_WRITE(sc, BCW_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_GIM);
+ BCW_WRITE(sc, BCW_GIM, old_mask & ~mask);
+
+ DPRINTF(("%s: interrupts disabled\n", sc->sc_dev.dv_xname));
+
+ return (old_mask);
+}
+
int
-bcw_intr(void *xsc)
+bcw_intr(void *arg)
{
- struct bcw_softc *sc;
+ //struct bcw_softc *sc = arg;
+ //uint32_t reason;
+
+ return (0);
+#if 0
struct ifnet *ifp;
uint32_t intstatus;
int wantinit;
int handled = 0;
- sc = xsc;
-
for (wantinit = 0; wantinit == 0;) {
intstatus = (sc->sc_conf_read)(sc->sc_dev_softc, BCW_INT_STS);
@@ -1566,6 +1684,7 @@ bcw_intr(void *xsc)
}
return (handled);
+#endif
}
/* Receive interrupt handler */
@@ -1834,8 +1953,12 @@ bcw_init(struct ifnet *ifp)
bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED, 0x0034, 0);
}
+ /* probe response timeout value */
bcw_shm_write16(sc, BCW_SHM_CONTROL_SHARED, 0x0074, 0);
+ /* initially set the wireless operation mode */
+ bcw_set_opmode(ifp);
+
if (sc->sc_core[sc->sc_currentcore].rev < 3) {
BCW_WRITE16(sc, 0x060e, 0);
BCW_WRITE16(sc, 0x0610, 0x8000);
@@ -6672,3 +6795,39 @@ bcw_ilt_read(struct bcw_softc *sc, uint16_t offset)
return (bcw_phy_read16(sc, BCW_PHY_ILT_G_DATA1));
}
}
+
+/*
+ * Power
+ */
+void
+bcw_power_saving_ctl_bits(struct bcw_softc *sc, int bit25, int bit26)
+{
+ int i;
+ uint32_t status;
+
+ if (bit25 == -1) {
+ /* TODO */
+ }
+ if (bit26 == -1) {
+ /* TODO */
+ }
+
+ status = BCW_READ(sc, BCW_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_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_CONTROL_SHARED, 0x0040)
+ != 4)
+ break;
+ delay(10);
+ }
+ }
+}
diff --git a/sys/dev/ic/bcwreg.h b/sys/dev/ic/bcwreg.h
index 0874ec15724..085a9e72f1b 100644
--- a/sys/dev/ic/bcwreg.h
+++ b/sys/dev/ic/bcwreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcwreg.h,v 1.17 2007/03/12 06:51:16 mglocker Exp $ */
+/* $OpenBSD: bcwreg.h,v 1.18 2007/03/15 14:30:49 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -214,6 +214,8 @@
#define BCW_SBF_TIME_UPDATE 0x10000000 /* Related to TSF updates */
#define BCW_GIR 0x128 /* MIMO - Generic Interrupt Reason */
+#define BCW_GIM 0x12c /* MMIO - Generic Interrupt Mask */
+
#define BCW_MMIO_RAM_CONTROL 0x130
#define BCW_MMIO_RAM_DATA 0x134
@@ -339,6 +341,26 @@
/* 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)
/* firmware revision informations */
#define BCW_UCODE_REVISION 0x0000