summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2006-12-06 19:21:46 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2006-12-06 19:21:46 +0000
commit481941268c9ea63c8c4a41c0e5d17f2017e81bed (patch)
tree130cb0f5e2729e19c76322d008f35932e10c3a24
parentcda371b9624e25284a31f2cb0d04702c88bdd8e8 (diff)
From Jon Simola <simola@mecha.com>:
Add bus-specific config space read and write functions, this fixes the attach for ian@darwinsys.com and properly enumerates multiple cores.
-rw-r--r--sys/dev/cardbus/if_bcw_cardbus.c22
-rw-r--r--sys/dev/ic/bcw.c124
-rw-r--r--sys/dev/ic/bcwreg.h4
-rw-r--r--sys/dev/ic/bcwvar.h9
-rw-r--r--sys/dev/pci/if_bcw_pci.c25
5 files changed, 130 insertions, 54 deletions
diff --git a/sys/dev/cardbus/if_bcw_cardbus.c b/sys/dev/cardbus/if_bcw_cardbus.c
index 38d473c7e0d..3c51ca6cc2f 100644
--- a/sys/dev/cardbus/if_bcw_cardbus.c
+++ b/sys/dev/cardbus/if_bcw_cardbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bcw_cardbus.c,v 1.3 2006/11/22 23:46:49 brad Exp $ */
+/* $OpenBSD: if_bcw_cardbus.c,v 1.4 2006/12/06 19:21:45 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -64,6 +64,8 @@ void bcw_cardbus_power(struct bcw_softc *, int);
void bcw_cardbus_setup(struct bcw_cardbus_softc *);
int bcw_cardbus_enable(struct bcw_softc *);
void bcw_cardbus_disable(struct bcw_softc *);
+void bcw_cardbus_conf_write(struct bcw_softc *, u_int32_t, u_int32_t);
+u_int32_t bcw_cardbus_conf_read(struct bcw_softc *, u_int32_t);
struct cfattach bcw_cardbus_ca = {
sizeof (struct bcw_cardbus_softc), bcw_cardbus_match,
@@ -105,12 +107,18 @@ bcw_cardbus_attach(struct device *parent, struct device *self, void *aux)
csc->sc_ct = ct;
csc->sc_tag = ca->ca_tag;
csc->sc_intrline = ca->ca_intrline;
+ sc->sc_ca.ca_tag = ca->ca_tag;
+ sc->sc_ca.ca_ct = ca->ca_ct;
/* power management hooks */
sc->sc_enable = bcw_cardbus_enable;
sc->sc_disable = bcw_cardbus_disable;
sc->sc_power = bcw_cardbus_power;
+ /* config register read/write functions */
+ sc->sc_conf_read = bcw_cardbus_conf_read;
+ sc->sc_conf_write = bcw_cardbus_conf_write;
+
/* map control/status registers */
error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_iot,
@@ -246,3 +254,15 @@ bcw_cardbus_disable(struct bcw_softc *sc)
/* power down the socket */
Cardbus_function_disable(ct);
}
+
+void
+bcw_cardbus_conf_write(struct bcw_softc *sc, u_int32_t reg, u_int32_t val)
+{
+ Cardbus_conf_write(sc->sc_ca.ca_ct, sc->sc_ca.ca_tag, reg, val);
+}
+
+u_int32_t
+bcw_cardbus_conf_read(struct bcw_softc *sc, u_int32_t reg)
+{
+ return Cardbus_conf_read(sc->sc_ca.ca_ct, sc->sc_ca.ca_tag, reg);
+}
diff --git a/sys/dev/ic/bcw.c b/sys/dev/ic/bcw.c
index 6721a83e872..7fc3cc176da 100644
--- a/sys/dev/ic/bcw.c
+++ b/sys/dev/ic/bcw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcw.c,v 1.8 2006/11/29 21:34:06 mglocker Exp $ */
+/* $OpenBSD: bcw.c,v 1.9 2006/12/06 19:21:45 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -56,6 +56,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
+#include <dev/cardbus/cardbusvar.h>
#include <dev/ic/bcwreg.h>
#include <dev/ic/bcwvar.h>
@@ -90,6 +91,7 @@ int bcw_media_change(struct ifnet *);
void bcw_media_status(struct ifnet *, struct ifmediareq *);
/* fashionably new functions */
int bcw_validatechipaccess(struct bcw_softc *);
+void bcw_powercontrol_crystal_off(struct bcw_softc *);
struct cfdriver bcw_cd = {
NULL, "bcw", DV_IFNET
@@ -137,20 +139,9 @@ bcw_attach(struct bcw_softc *sc)
* below for an example of just figuring out what the chip id is and
* how many cores it has.
*/
-
- /*
- * XXX Can we read BCW_ADDR_SPACE0 and see if it returns a likely
- * Core? On the 4318 that only has an 802.11 core, it always reads as
- * some garbage, so if we do a read first we could set a "singlecore"
- * flag instead of thrashing around trying to select non-existant
- * cores. Testing requires cards that do have multiple cores. This
- * would also simplify identifying cards into 3 classes early:
- * - Multiple Cores without a Chip Common Core
- * - Multiple Cores with a Chip Common Core
- * - Single Core
- */
-
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_ADDR_SPACE0);
+#if 0
+ sbval = pci_conf_read(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag,
+ BCW_ADDR_SPACE0);
if ((sbval & 0xffff0000) != 0x18000000) {
DPRINTF(("\n%s: Trial Core read was 0x%x, single core only?\n",
sc->sc_dev.dv_xname, sbval));
@@ -158,18 +149,17 @@ bcw_attach(struct bcw_softc *sc)
} else
DPRINTF(("\n%s: Trial Core read was 0x%x\n",
sc->sc_dev.dv_xname, sbval));
-
+#endif
/*
* Try and change to the ChipCommon Core
*/
for (i = 0; i < 10; i++) {
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_ADDR_SPACE0,
- BCW_CORE_SELECT(0));
+ (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0, BCW_CORE_SELECT(0));
delay(10);
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- BCW_ADDR_SPACE0);
+ sbval = (sc->sc_conf_read)(sc, BCW_ADDR_SPACE0);
if (sbval == BCW_CORE_SELECT(0)) {
- DPRINTF(("%s: Selected ChipCommon Core\n"));
+ DPRINTF(("%s: Selected ChipCommon Core\n",
+ sc->sc_dev.dv_xname));
break;
}
delay(10);
@@ -259,8 +249,8 @@ bcw_attach(struct bcw_softc *sc)
break;
default:
sc->sc_chipid = sc->sc_prodid;
- /* XXX educated guess */
- sc->sc_numcores = 1;
+ /* Set to max */
+ sc->sc_numcores = BCW_MAX_CORES;
} /* end of switch */
} /* End of if/else */
@@ -270,25 +260,27 @@ bcw_attach(struct bcw_softc *sc)
/* Identify each core */
if (sc->sc_numcores >= 2) { /* Exclude single core chips */
- for (i = 0; i <= sc->sc_numcores; i++) {
- DPRINTF(("%s: Trying core %d -\n",
- sc->sc_dev.dv_xname, i));
- bus_space_write_4(sc->sc_iot, sc->sc_ioh,
- BCW_ADDR_SPACE0, BCW_CORE_SELECT(i));
+ for (i = 0; i < sc->sc_numcores; i++) {
+// DPRINTF(("%s: Trying core %d -\n",
+// sc->sc_dev.dv_xname, i));
+ (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0,
+ BCW_CORE_SELECT(i));
/* loop to see if the selected core shows up */
for (j = 0; j < 10; j++) {
- sbval=bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- BCW_ADDR_SPACE0);
- DPRINTF(("%s: read %d for core %d = 0x%x\n",
- sc->sc_dev.dv_xname, j, i, sbval));
+ sbval = (sc->sc_conf_read)(sc, BCW_ADDR_SPACE0);
+// DPRINTF(("%s: read %d for core %d = 0x%x\n",
+// sc->sc_dev.dv_xname, j, i, sbval));
if (sbval == BCW_CORE_SELECT(i)) break;
delay(10);
}
- if (j < 10)
+ if (j < 10) {
+ sbval = bus_space_read_4(sc->sc_iot,
+ sc->sc_ioh, BCW_CIR_SBID_HI);
DPRINTF(("%s: Found core %d of type 0x%x\n",
sc->sc_dev.dv_xname, i,
(sbval & 0x00008ff0) >> 4));
- //sc->sc_core[i].id = (sbval & 0x00008ff0) >> 4;
+ }
+ sc->sc_core[i].id = (sbval & 0x00008ff0) >> 4;
} /* End of For loop */
}
@@ -296,15 +288,22 @@ bcw_attach(struct bcw_softc *sc)
* XXX Attach cores to the backplane, if we have more than one
*/
// ??? if (!sc->sc_singlecore) {
+#if 0
if (sc->sc_havecommon == 1) {
sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_PCICR);
sbval |= 0x1 << 8; /* XXX hardcoded bitmask of single core */
bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_PCICR, sbval);
}
-
+#endif
/*
+ * XXX Select the 802.11 core, then
* Get and display the PHY info from the MIMO
*/
+ for (i=0; i < sc->sc_numcores; i++) {
+ if (sc->sc_core[i].id == BCW_CORE_80211)
+ (sc->sc_conf_write)(sc, BCW_ADDR_SPACE0,
+ BCW_CORE_SELECT(i));
+ }
sbval = bus_space_read_2(sc->sc_iot, sc->sc_ioh, 0x3E0);
sc->sc_phy_version = (sbval&0xf000)>>12;
sc->sc_phy_rev = sbval&0xf;
@@ -512,8 +511,9 @@ bcw_attach(struct bcw_softc *sc)
/* Read antenna gain from SPROM and multiply by 4 */
sbval = bus_space_read_2(sc->sc_iot, sc->sc_ioh, BCW_SPROM_ANTGAIN);
/* If unset, assume 2 */
- if((sbval == 0) || (sbval == 0xffff)) sbval = 0x0202;
- if(sc->sc_phy_type == BCW_PHY_TYPEA)
+ if ((sbval == 0) || (sbval == 0xffff))
+ sbval = 0x0202;
+ if (sc->sc_phy_type == BCW_PHY_TYPEA)
sc->sc_radio_gain = (sbval & 0xff);
else
sc->sc_radio_gain = ((sbval & 0xff00) >> 8);
@@ -600,9 +600,9 @@ bcw_attach(struct bcw_softc *sc)
/*
* XXX TODO still for the card attach:
* - Disable the 80211 Core (and wrapper for on/off)
- * - Powercontrol Crystal Off (and write a wrapper for on/off)
* - Setup LEDs to blink in whatever fashionable manner
*/
+ bcw_powercontrol_crystal_off(sc);
/*
* Allocate DMA-safe memory for ring descriptors.
@@ -916,8 +916,7 @@ bcw_intr(void *xsc)
sc = xsc;
for (wantinit = 0; wantinit == 0;) {
- intstatus = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
- BCW_INT_STS);
+ intstatus = (sc->sc_conf_read)(sc, BCW_INT_STS);
/* ignore if not ours, or unsolicited interrupts */
intstatus &= sc->sc_intmask;
@@ -927,8 +926,7 @@ bcw_intr(void *xsc)
handled = 1;
/* Ack interrupt */
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_INT_STS,
- intstatus);
+ (sc->sc_conf_write)(sc, BCW_INT_STS, intstatus);
/* Receive interrupts. */
if (intstatus & I_RI)
@@ -1375,12 +1373,22 @@ bcw_reset(struct bcw_softc *sc)
u_int32_t val;
u_int32_t reject;
+ /* Really stupid PCI space dump */
+#if 0
+ for (i=0xe00; i<0x1000; i+=4) {
+ if ((i % 16) == 0)
+ DPRINTF(("%s: 0x%04x - ",sc->sc_dev.dv_xname, i));
+ DPRINTF(("0x%08x ",bus_space_read_4(sc->sc_iot, sc->sc_ioh,i)));
+ if ((i % 16) == 12) DPRINTF(("\n"));
+ }
+#endif
/*
* Figure out what revision the Sonic Backplane is, as the position
* of the Reject bit changed. Save the revision in the softc, and
* use the local variable 'reject' in all the bit banging.
*/
sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_CIR_SBID_LO);
+
sc->sc_sbrev = (sbval & SBREV_MASK) >> SBREV_MASK_SHIFT;
switch (sc->sc_sbrev) {
case 0:
@@ -2129,15 +2137,37 @@ bcw_powercontrol_crystal_on(struct bcw_softc *sc)
{
u_int32_t sbval;
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOI);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOI);
if ((sbval & BCW_XTALPOWERUP) != BCW_XTALPOWERUP) {
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOO);
sbval |= (BCW_XTALPOWERUP & BCW_PLLPOWERDOWN);
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO, sbval);
+ (sc->sc_conf_write)(sc, BCW_GPIOO, sbval);
delay(1000);
- sbval = bus_space_read_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOO);
sbval &= ~BCW_PLLPOWERDOWN;
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, BCW_GPIOO, sbval);
+ (sc->sc_conf_write)(sc, BCW_GPIOO, sbval);
delay(5000);
}
}
+
+void
+bcw_powercontrol_crystal_off(struct bcw_softc *sc)
+{
+ u_int32_t sbval;
+
+ /* XXX Return if radio is hardware disabled */
+ if (sc->sc_corerev < 5)
+ return;
+ if ((sc->sc_boardflags & BCW_BF_XTAL) == BCW_BF_XTAL)
+ return;
+
+ /* XXX bcw_powercontrol_clock_slow() */
+
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOO);
+ sbval |= BCW_PLLPOWERDOWN;
+ sbval &= ~BCW_XTALPOWERUP;
+ (sc->sc_conf_write)(sc, BCW_GPIOO, sbval);
+ sbval = (sc->sc_conf_read)(sc, BCW_GPIOE);
+ sbval |= BCW_PLLPOWERDOWN | BCW_XTALPOWERUP;
+ (sc->sc_conf_write)(sc, BCW_GPIOE, sbval);
+}
diff --git a/sys/dev/ic/bcwreg.h b/sys/dev/ic/bcwreg.h
index 2c6e30d9d0d..19b17661ad1 100644
--- a/sys/dev/ic/bcwreg.h
+++ b/sys/dev/ic/bcwreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcwreg.h,v 1.4 2006/11/24 20:27:41 mglocker Exp $ */
+/* $OpenBSD: bcwreg.h,v 1.5 2006/12/06 19:21:45 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -52,9 +52,11 @@
#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
#define BCW_CORE_COMMON_CHIPID 0x0
diff --git a/sys/dev/ic/bcwvar.h b/sys/dev/ic/bcwvar.h
index 08f59231442..b857cb374a4 100644
--- a/sys/dev/ic/bcwvar.h
+++ b/sys/dev/ic/bcwvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcwvar.h,v 1.7 2006/11/29 21:34:06 mglocker Exp $ */
+/* $OpenBSD: bcwvar.h,v 1.8 2006/12/06 19:21:45 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -128,6 +128,10 @@ struct bcw_softc {
int (*sc_enable)(struct bcw_softc *);
void (*sc_disable)(struct bcw_softc *);
void (*sc_power)(struct bcw_softc *, int);
+ void (*sc_conf_write)(struct bcw_softc *,
+ u_int32_t, u_int32_t);
+ u_int32_t (*sc_conf_read)(struct bcw_softc *, u_int32_t);
+
struct timeout sc_scan_to;
bus_dma_tag_t sc_dmat;
@@ -137,6 +141,7 @@ struct bcw_softc {
void *bcw_intrhand;
const char *bcw_intrstr; /* interrupt description */
struct pci_attach_args sc_pa;
+ struct cardbus_attach_args sc_ca;
u_int32_t sc_phy; /* eeprom indicated phy */
struct bcw_dma_slot *bcw_rx_ring; /* receive ring */
struct bcw_dma_slot *bcw_tx_ring; /* transmit ring */
@@ -152,7 +157,7 @@ struct bcw_softc {
u_int16_t sc_chipid; /* Chip ID */
u_int16_t sc_chiprev; /* Chip Revision */
u_int16_t sc_prodid; /* Product ID */
-// struct bcw_core core[BCW_MAX_CORES];
+ struct bcw_core sc_core[BCW_MAX_CORES];
// struct bcw_radio radio[BCW_MAX_RADIOS];
u_int16_t sc_phy_version;
u_int16_t sc_phy_type;
diff --git a/sys/dev/pci/if_bcw_pci.c b/sys/dev/pci/if_bcw_pci.c
index a1bd93e0dff..b38f74e3194 100644
--- a/sys/dev/pci/if_bcw_pci.c
+++ b/sys/dev/pci/if_bcw_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bcw_pci.c,v 1.5 2006/11/29 21:34:06 mglocker Exp $ */
+/* $OpenBSD: if_bcw_pci.c,v 1.6 2006/12/06 19:21:45 mglocker Exp $ */
/*
* Copyright (c) 2006 Jon Simola <jsimola@gmail.com>
@@ -60,6 +60,7 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
+#include <dev/cardbus/cardbusvar.h>
#include <dev/ic/bcwreg.h>
#include <dev/ic/bcwvar.h>
@@ -95,6 +96,8 @@ int bcw_pci_match(struct device *, void *, void *);
int bcw_pci_enable(struct bcw_softc *sc);
void bcw_pci_disable(struct bcw_softc *sc);
void bcw_pci_attach(struct device *, struct device *, void *);
+void bcw_pci_conf_write(struct bcw_softc *, u_int32_t, u_int32_t);
+u_int32_t bcw_pci_conf_read(struct bcw_softc *, u_int32_t);
struct cfattach bcw_pci_ca = {
sizeof(struct bcw_pci_softc), bcw_pci_match, bcw_pci_attach
@@ -150,6 +153,8 @@ bcw_pci_attach(struct device *parent, struct device *self, void *aux)
psc->psc_pc = pa->pa_pc;
psc->psc_pcitag = pa->pa_tag;
+ sc->sc_pa.pa_pc = pa->pa_pc;
+ sc->sc_pa.pa_tag = pa->pa_tag;
/* Get it out of power save mode if needed. */
if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
@@ -216,6 +221,8 @@ bcw_pci_attach(struct device *parent, struct device *self, void *aux)
sc->sc_enable = bcw_pci_enable;
sc->sc_disable = bcw_pci_disable;
+ sc->sc_conf_write = bcw_pci_conf_write;
+ sc->sc_conf_read = bcw_pci_conf_read;
/*
* Get some PCI based info into the softc
@@ -234,9 +241,9 @@ bcw_pci_attach(struct device *parent, struct device *self, void *aux)
* Clear PCI_STATUS_TARGET_TARGET_ABORT, Docs and Linux call it
* PCI_STATUS_SIG_TARGET_ABORT - should use pci_conf_read/write?
*/
- bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+ pci_conf_write(pa->pa_pc, pa->pa_tag,
PCI_COMMAND_STATUS_REG,
- bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ pci_conf_read(pa->pa_pc, pa->pa_tag,
PCI_COMMAND_STATUS_REG)
& ~PCI_STATUS_TARGET_TARGET_ABORT);
@@ -247,3 +254,15 @@ bcw_pci_attach(struct device *parent, struct device *self, void *aux)
bcw_attach(sc);
}
+
+void
+bcw_pci_conf_write(struct bcw_softc *sc, u_int32_t reg, u_int32_t val)
+{
+ pci_conf_write(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag, reg, val);
+}
+
+u_int32_t
+bcw_pci_conf_read(struct bcw_softc *sc, u_int32_t reg)
+{
+ return pci_conf_read(sc->sc_pa.pa_pc, sc->sc_pa.pa_tag, reg);
+}