Subject: [PATCH 2/2] bcm43xx: convert driver to use ssb

From: Michael Buesch <[email-masked]>
Date: Wed, 23 Aug 2006 12:01:07 +0200

This patch converts the bcm43xx driver to use the new
ssb driver backend.

Signed-off-by: Michael Buesch <[email-masked]>

Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx.h	2006-08-23 11:27:27.000000000 +0200
@@ -11,6 +11,7 @@
 #include <asm/atomic.h>
 #include <asm/io.h>
 
+#include <linux/ssb.h>
 #include <linux/wireless.h>
 #include <net/d80211.h>
 #include <net/d80211_mgmt.h>
@@ -22,18 +23,10 @@
 
 #define PFX				KBUILD_MODNAME ": "
 
-#define BCM43xx_SWITCH_CORE_MAX_RETRIES	50
 #define BCM43xx_IRQWAIT_MAX_RETRIES	50
 
 #define BCM43xx_IO_SIZE			8192
 
-/* Active Core PCI Configuration Register. */
-#define BCM43xx_PCICFG_ACTIVE_CORE	0x80
-/* SPROM control register. */
-#define BCM43xx_PCICFG_SPROMCTL		0x88
-/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
-#define BCM43xx_PCICFG_ICR		0x94
-
 /* MMIO offsets */
 #define BCM43xx_MMIO_DMA0_REASON	0x20
 #define BCM43xx_MMIO_DMA0_IRQ_MASK	0x24
@@ -104,29 +97,7 @@
 #define BCM43xx_MMIO_TSF_3		0x638 /* core rev < 3 only */
 #define BCM43xx_MMIO_POWERUP_DELAY	0x6A8
 
-/* SPROM offsets. */
-#define BCM43xx_SPROM_BASE		0x1000
-#define BCM43xx_SPROM_BOARDFLAGS2	0x1c
-#define BCM43xx_SPROM_IL0MACADDR	0x24
-#define BCM43xx_SPROM_ET0MACADDR	0x27
-#define BCM43xx_SPROM_ET1MACADDR	0x2a
-#define BCM43xx_SPROM_ETHPHY		0x2d
-#define BCM43xx_SPROM_BOARDREV		0x2e
-#define BCM43xx_SPROM_PA0B0		0x2f
-#define BCM43xx_SPROM_PA0B1		0x30
-#define BCM43xx_SPROM_PA0B2		0x31
-#define BCM43xx_SPROM_WL0GPIO0		0x32
-#define BCM43xx_SPROM_WL0GPIO2		0x33
-#define BCM43xx_SPROM_MAXPWR		0x34
-#define BCM43xx_SPROM_PA1B0		0x35
-#define BCM43xx_SPROM_PA1B1		0x36
-#define BCM43xx_SPROM_PA1B2		0x37
-#define BCM43xx_SPROM_IDL_TSSI_TGT	0x38
-#define BCM43xx_SPROM_BOARDFLAGS	0x39
-#define BCM43xx_SPROM_ANTENNA_GAIN	0x3a
-#define BCM43xx_SPROM_VERSION		0x3f
-
-/* BCM43xx_SPROM_BOARDFLAGS values */
+/* SPROM boardflags_lo values */
 #define BCM43xx_BFL_BTCOEXIST		0x0001 /* implements Bluetooth coexistance */
 #define BCM43xx_BFL_PACTRL		0x0002 /* GPIO 9 controlling the PA */
 #define BCM43xx_BFL_AIRLINEMODE		0x0004 /* implements GPIO 13 radio disable indication */
@@ -158,35 +129,6 @@
 #define BCM43xx_MACFILTER_SELF		0x0000
 #define BCM43xx_MACFILTER_ASSOC		0x0003
 
-/* Chipcommon registers. */
-#define BCM43xx_CHIPCOMMON_CAPABILITIES 	0x04
-#define BCM43xx_CHIPCOMMON_PLLONDELAY		0xB0
-#define BCM43xx_CHIPCOMMON_FREFSELDELAY		0xB4
-#define BCM43xx_CHIPCOMMON_SLOWCLKCTL		0xB8
-#define BCM43xx_CHIPCOMMON_SYSCLKCTL		0xC0
-
-/* PCI core specific registers. */
-#define BCM43xx_PCICORE_BCAST_ADDR	0x50
-#define BCM43xx_PCICORE_BCAST_DATA	0x54
-#define BCM43xx_PCICORE_SBTOPCI2	0x108
-
-/* SBTOPCI2 values. */
-#define BCM43xx_SBTOPCI2_PREFETCH	0x4
-#define BCM43xx_SBTOPCI2_BURST		0x8
-
-/* Chipcommon capabilities. */
-#define BCM43xx_CAPABILITIES_PCTL		0x00040000
-#define BCM43xx_CAPABILITIES_PLLMASK		0x00030000
-#define BCM43xx_CAPABILITIES_PLLSHIFT		16
-#define BCM43xx_CAPABILITIES_FLASHMASK		0x00000700
-#define BCM43xx_CAPABILITIES_FLASHSHIFT		8
-#define BCM43xx_CAPABILITIES_EXTBUSPRESENT	0x00000040
-#define BCM43xx_CAPABILITIES_UARTGPIO		0x00000020
-#define BCM43xx_CAPABILITIES_UARTCLOCKMASK	0x00000018
-#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT	3
-#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN	0x00000004
-#define BCM43xx_CAPABILITIES_NRUARTSMASK	0x00000003
-
 /* PowerControl */
 #define BCM43xx_PCTL_IN			0xB0
 #define BCM43xx_PCTL_OUT		0xB4
@@ -203,67 +145,6 @@
 #define BCM43xx_PCTL_FORCE_PLL		0x1000
 #define BCM43xx_PCTL_DYN_XTAL		0x2000
 
-/* COREIDs */
-#define BCM43xx_COREID_CHIPCOMMON	0x800
-#define BCM43xx_COREID_ILINE20          0x801
-#define BCM43xx_COREID_SDRAM            0x803
-#define BCM43xx_COREID_PCI		0x804
-#define BCM43xx_COREID_MIPS             0x805
-#define BCM43xx_COREID_ETHERNET         0x806
-#define BCM43xx_COREID_V90		0x807
-#define BCM43xx_COREID_USB11_HOSTDEV    0x80a
-#define BCM43xx_COREID_IPSEC            0x80b
-#define BCM43xx_COREID_PCMCIA		0x80d
-#define BCM43xx_COREID_EXT_IF           0x80f
-#define BCM43xx_COREID_80211		0x812
-#define BCM43xx_COREID_MIPS_3302        0x816
-#define BCM43xx_COREID_USB11_HOST       0x817
-#define BCM43xx_COREID_USB11_DEV        0x818
-#define BCM43xx_COREID_USB20_HOST       0x819
-#define BCM43xx_COREID_USB20_DEV        0x81a
-#define BCM43xx_COREID_SDIO_HOST        0x81b
-
-/* Core Information Registers */
-#define BCM43xx_CIR_BASE		0xf00
-#define BCM43xx_CIR_SBTPSFLAG		(BCM43xx_CIR_BASE + 0x18)
-#define BCM43xx_CIR_SBIMSTATE		(BCM43xx_CIR_BASE + 0x90)
-#define BCM43xx_CIR_SBINTVEC		(BCM43xx_CIR_BASE + 0x94)
-#define BCM43xx_CIR_SBTMSTATELOW	(BCM43xx_CIR_BASE + 0x98)
-#define BCM43xx_CIR_SBTMSTATEHIGH	(BCM43xx_CIR_BASE + 0x9c)
-#define BCM43xx_CIR_SBIMCONFIGLOW	(BCM43xx_CIR_BASE + 0xa8)
-#define BCM43xx_CIR_SB_ID_HI		(BCM43xx_CIR_BASE + 0xfc)
-
-/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
-#define BCM43xx_BACKPLANE_FLAG_NR_MASK	0x3f
-
-/* SBIMCONFIGLOW values/masks. */
-#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK		0x00000007
-#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT	0
-#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK		0x00000070
-#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT	4
-#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK		0x00ff0000
-#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT		16
-
-/* sbtmstatelow state flags */
-#define BCM43xx_SBTMSTATELOW_RESET		0x01
-#define BCM43xx_SBTMSTATELOW_REJECT		0x02
-#define BCM43xx_SBTMSTATELOW_CLOCK		0x10000
-#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK	0x20000
-
-/* sbtmstatehigh state flags */
-#define BCM43xx_SBTMSTATEHIGH_SERROR		0x00000001
-#define BCM43xx_SBTMSTATEHIGH_BUSY		0x00000004
-#define BCM43xx_SBTMSTATEHIGH_TIMEOUT		0x00000020
-#define BCM43xx_SBTMSTATEHIGH_COREFLAGS		0x1FFF0000
-#define BCM43xx_SBTMSTATEHIGH_DMA64BIT		0x10000000
-#define BCM43xx_SBTMSTATEHIGH_GATEDCLK		0x20000000
-#define BCM43xx_SBTMSTATEHIGH_BISTFAILED	0x40000000
-#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE	0x80000000
-
-/* sbimstate flags */
-#define BCM43xx_SBIMSTATE_IB_ERROR		0x20000
-#define BCM43xx_SBIMSTATE_TIMEOUT		0x40000
-
 /* PHYVersioning */
 #define BCM43xx_PHYTYPE_A		0x00
 #define BCM43xx_PHYTYPE_B		0x01
@@ -429,54 +310,6 @@
 	u32 value;
 } __attribute__((__packed__));
 
-/* Values for bcm430x_sprominfo.locale */
-enum {
-	BCM43xx_LOCALE_WORLD = 0,
-	BCM43xx_LOCALE_THAILAND,
-	BCM43xx_LOCALE_ISRAEL,
-	BCM43xx_LOCALE_JORDAN,
-	BCM43xx_LOCALE_CHINA,
-	BCM43xx_LOCALE_JAPAN,
-	BCM43xx_LOCALE_USA_CANADA_ANZ,
-	BCM43xx_LOCALE_EUROPE,
-	BCM43xx_LOCALE_USA_LOW,
-	BCM43xx_LOCALE_JAPAN_HIGH,
-	BCM43xx_LOCALE_ALL,
-	BCM43xx_LOCALE_NONE,
-};
-
-#define BCM43xx_SPROM_SIZE	64 /* in 16-bit words. */
-struct bcm43xx_sprominfo {
-	u16 boardflags2;
-	u8 il0macaddr[6];
-	u8 et0macaddr[6];
-	u8 et1macaddr[6];
-	u8 et0phyaddr:5;
-	u8 et1phyaddr:5;
-	u8 et0mdcport:1;
-	u8 et1mdcport:1;
-	u8 boardrev;
-	u8 locale:4;
-	u8 antennas_aphy:2;
-	u8 antennas_bgphy:2;
-	u16 pa0b0;
-	u16 pa0b1;
-	u16 pa0b2;
-	u8 wl0gpio0;
-	u8 wl0gpio1;
-	u8 wl0gpio2;
-	u8 wl0gpio3;
-	u8 maxpower_aphy;
-	u8 maxpower_bgphy;
-	u16 pa1b0;
-	u16 pa1b1;
-	u16 pa1b2;
-	u8 idle_tssi_tgt_aphy;
-	u8 idle_tssi_tgt_bgphy;
-	u16 boardflags;
-	u16 antennagain_aphy;
-	u16 antennagain_bgphy;
-};
 
 /* Value pair to measure the LocalOscillator. */
 struct bcm43xx_lopair {
@@ -604,29 +437,9 @@
 
 #define BCM43xx_MAX_80211_CORES		2
 
-#ifdef CONFIG_BCM947XX
-#define core_offset(bcm) (bcm)->current_core_offset
-#else
-#define core_offset(bcm) 0
-#endif
-
-/* Generic information about a core. */
-struct bcm43xx_coreinfo {
-	u8 available:1,
-	   enabled:1,
-	   initialized:1;
-	/** core_rev revision number */
-	u8 rev;
-	/** Index number for _switch_core() */
-	u8 index;
-	/** core_id ID number */
-	u16 id;
-	/** Core-specific data. */
-	void *priv;
-};
-
 /* Additional information for each 80211 core. */
-struct bcm43xx_coreinfo_80211 {
+struct bcm43xx_corepriv_80211 {
+	u8 initialized:1;
 	/* PHY device. */
 	struct bcm43xx_phyinfo phy;
 	/* Radio device. */
@@ -641,7 +454,7 @@
 
 /* Context information for a noise calculation (Link Quality). */
 struct bcm43xx_noise_calculation {
-	struct bcm43xx_coreinfo *core_at_start;
+	struct ssb_core *core_at_start;
 	u8 channel_at_start;
 	u8 calculation_running:1;
 	u8 nr_samples;
@@ -711,15 +524,15 @@
  */
 
 struct bcm43xx_private {
+	/* The Sonics Silicon Backplane. */
+	struct ssb ssb;
+
 	struct ieee80211_hw *ieee;
 	struct ieee80211_low_level_stats ieee_stats;
 
 	struct net_device *net_dev;
-	struct pci_dev *pci_dev;
 	unsigned int irq;
 
-	void __iomem *mmio_addr;
-
 	spinlock_t irq_lock;
 	struct mutex mutex;
 
@@ -752,36 +565,24 @@
 	u16 board_type;
 	u16 board_revision;
 
-	u16 chip_id;
-	u8 chip_rev;
-	u8 chip_package;
-
-	struct bcm43xx_sprominfo sprom;
+	struct ssb_sprom sprom;
 #define BCM43xx_NR_LEDS		4
 	struct bcm43xx_led leds[BCM43xx_NR_LEDS];
 	spinlock_t leds_lock;
 
-	/* The currently active core. */
-	struct bcm43xx_coreinfo *current_core;
-#ifdef CONFIG_BCM947XX
-	/** current core memory offset */
-	u32 current_core_offset;
-#endif
-	struct bcm43xx_coreinfo *active_80211_core;
-	/* coreinfo structs for all possible cores follow.
-	 * Note that a core might not exist.
-	 * So check the coreinfo flags before using it.
+	/* Pointers to the available cores.
+	 * If a core is not available, this is NULL.
 	 */
-	struct bcm43xx_coreinfo core_chipcommon;
-	struct bcm43xx_coreinfo core_pci;
-	struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
+	struct ssb_core *core_80211[ BCM43xx_MAX_80211_CORES ];
+	struct ssb_core *active_80211_core;
+	struct ssb_core *core_chipcommon;
+	struct ssb_core *core_pci;
+
 	/* Additional information, specific to the 80211 cores. */
-	struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
+	struct bcm43xx_corepriv_80211 corepriv_80211[ BCM43xx_MAX_80211_CORES ];
 	/* Number of available 80211 cores. */
 	int nr_80211_available;
 
-	u32 chipcommon_capabilities;
-
 	/* Reason code of the last interrupt. */
 	u32 irq_reason;
 	u32 dma_reason[6];
@@ -801,9 +602,6 @@
 
 	struct work_struct restart_work;
 
-	/* Informational stuff. */
-	char nick[IW_ESSID_MAX_SIZE + 1];
-
 	/* encryption/decryption */
 	u16 security_offset;
 	struct bcm43xx_key key[54];
@@ -825,6 +623,12 @@
 	return ieee80211_dev_hw_data(dev);
 }
 
+static inline
+struct bcm43xx_private * ssb_to_bcm43xx(struct ssb *ssb)
+{
+	return container_of(ssb, struct bcm43xx_private, ssb);
+}
+
 /* Helper function, which returns a boolean.
  * TRUE, if PIO is used; FALSE, if DMA is used.
  */
@@ -855,11 +659,11 @@
  * any of these functions.
  */
 static inline
-struct bcm43xx_coreinfo_80211 *
+struct bcm43xx_corepriv_80211 *
 bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
 {
-	assert(bcm->current_core->id == BCM43xx_COREID_80211);
-	return bcm->current_core->priv;
+	assert(bcm->ssb.current_core->cc == SSB_CC_80211);
+	return bcm->ssb.current_core->priv;
 }
 static inline
 struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
@@ -920,49 +724,49 @@
 static inline
 u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
 {
-	return ioread16(bcm->mmio_addr + core_offset(bcm) + offset);
+	return ioread16(bcm->ssb.mmio + ssb_core_offset(&bcm->ssb) + offset);
 }
 
 static inline
 void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
 {
-	iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset);
+	iowrite16(value, bcm->ssb.mmio + ssb_core_offset(&bcm->ssb) + offset);
 }
 
 static inline
 u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
 {
-	return ioread32(bcm->mmio_addr + core_offset(bcm) + offset);
+	return ioread32(bcm->ssb.mmio + ssb_core_offset(&bcm->ssb) + offset);
 }
 
 static inline
 void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
 {
-	iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset);
+	iowrite32(value, bcm->ssb.mmio + ssb_core_offset(&bcm->ssb) + offset);
 }
 
 static inline
 int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
 {
-	return pci_read_config_word(bcm->pci_dev, offset, value);
+	return pci_read_config_word(bcm->ssb.pci_dev, offset, value);
 }
 
 static inline
 int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
 {
-	return pci_read_config_dword(bcm->pci_dev, offset, value);
+	return pci_read_config_dword(bcm->ssb.pci_dev, offset, value);
 }
 
 static inline
 int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
 {
-	return pci_write_config_word(bcm->pci_dev, offset, value);
+	return pci_write_config_word(bcm->ssb.pci_dev, offset, value);
 }
 
 static inline
 int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
 {
-	return pci_write_config_dword(bcm->pci_dev, offset, value);
+	return pci_write_config_dword(bcm->ssb.pci_dev, offset, value);
 }
 
 /** Limit a value between two limits */
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c	2006-08-23 11:40:07.000000000 +0200
@@ -118,6 +118,9 @@
 //#define DEBUG_ENABLE_PCILOG

+static int bcm43xx_net_stop(struct net_device *net_dev);
+static int bcm43xx_net_open(struct net_device *net_dev);
+
 /* Detailed list maintained at:
  * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
  */
@@ -341,7 +344,7 @@
 	 * We try to be atomic here, by restaring the read process,
 	 * if any of the high registers changed (overflew).
 	 */
-	if (bcm->current_core->rev >= 3) {
+	if (bcm->ssb.current_core->rev >= 3) {
 		u32 low, high, high2;
 
 		do {
@@ -406,7 +409,7 @@
 	 * First zero out the low register, so we have a full
 	 * register-overflow duration to complete the operation.
 	 */
-	if (bcm->current_core->rev >= 3) {
+	if (bcm->ssb.current_core->rev >= 3) {
 		u32 lo = (tsf & 0x00000000FFFFFFFFULL);
 		u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
 
@@ -609,10 +612,10 @@
 	u16 version;
 	u8 revision;
 
-	if (bcm->chip_id == 0x4317) {
-		if (bcm->chip_rev == 0x00)
+	if (bcm->ssb.chip_id == 0x4317) {
+		if (bcm->ssb.chip_rev == 0x00)
 			radio_id = 0x3205017F;
-		else if (bcm->chip_rev == 0x01)
+		else if (bcm->ssb.chip_rev == 0x01)
 			radio_id = 0x4205017F;
 		else
 			radio_id = 0x5205017F;
@@ -657,140 +660,10 @@
 	return -ENODEV;
 }
 
-static inline u8 bcm43xx_crc8(u8 crc, u8 data)
-{
-	static const u8 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];
-}
-
-static u8 bcm43xx_sprom_crc(const u16 *sprom)
-{
-	int word;
-	u8 crc = 0xFF;
-
-	for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
-		crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
-		crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
-	}
-	crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
-	crc ^= 0xFF;
-
-	return crc;
-}
-
-int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
-{
-	int i;
-	u8 crc, expected_crc;
-
-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
-		sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
-	/* CRC-8 check. */
-	crc = bcm43xx_sprom_crc(sprom);
-	expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
-	if (crc != expected_crc) {
-		printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
-					"(0x%02X, expected: 0x%02X)\n",
-		       crc, expected_crc);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
-{
-	int i, err;
-	u8 crc, expected_crc;
-	u32 spromctl;
-
-	/* CRC-8 validation of the input data. */
-	crc = bcm43xx_sprom_crc(sprom);
-	expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
-	if (crc != expected_crc) {
-		printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
-		return -EINVAL;
-	}
-
-	printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
-	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
-	if (err)
-		goto err_ctlreg;
-	spromctl |= 0x10; /* SPROM WRITE enable. */
-	bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
-	if (err)
-		goto err_ctlreg;
-	/* We must burn lots of CPU cycles here, but that does not
-	 * really matter as one does not write the SPROM every other minute...
-	 */
-	printk(KERN_INFO PFX "[ 0%%");
-	mdelay(500);
-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-		if (i == 16)
-			printk("25%%");
-		else if (i == 32)
-			printk("50%%");
-		else if (i == 48)
-			printk("75%%");
-		else if (i % 2)
-			printk(".");
-		bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
-		mmiowb();
-		mdelay(20);
-	}
-	spromctl &= ~0x10; /* SPROM WRITE enable. */
-	bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
-	if (err)
-		goto err_ctlreg;
-	mdelay(500);
-	printk("100%% ]\n");
-	printk(KERN_INFO PFX "SPROM written.\n");
-	bcm43xx_controller_restart(bcm, "SPROM update");
-
-	return 0;
-err_ctlreg:
-	printk(KERN_ERR PFX "Could not access SPROM control register.\n");
-	return -ENODEV;
-}
-
 #ifdef CONFIG_BCM947XX
-static void bcm43xx_aton(const char *str, char *dest)
+static void bcm43xx_aton(const char *str, u8 *dest)
 {
 	int i = 0;
-	u16 *d = (u16 *)dest;
 
 	for (;;) {
 		dest[i++] = (char)simple_strtoul(str, NULL, 16);
@@ -798,173 +671,76 @@
 		if (!*str++ || i == 6)
 			break;
 	}
-	for (i = 0; i < 3; i++)
-		d[i] = be16_to_cpu(d[i]);
 }
 #endif
 
 static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
 {
-	u16 value;
-	u16 *sprom;
-#ifdef CONFIG_BCM947XX
-	const char *c;
-#endif
-
-	sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
-			GFP_KERNEL);
-	if (!sprom) {
-		printk(KERN_ERR PFX "sprom_extract OOM\n");
-		return -ENOMEM;
-	}
-
-	bcm43xx_sprom_read(bcm, sprom);
+	int err = 0;
 
 #ifdef CONFIG_BCM947XX
-	/* In the case some settings are found in nvram, use them
-	 * to override those read from sprom.
+	char *c;
+
+	/* Can't read the SPROM on this embedded device.
+	 * (This would result in a bus error). Data is
+	 * stored in nvram instead.
 	 */
-	c = nvram_get("boardflags2");
-	if (c)
-		sprom[BCM43xx_SPROM_BOARDFLAGS2] = simple_strtoul(c, NULL, 0);
         c = nvram_get("boardflags");
 	if (c)
-		sprom[BCM43xx_SPROM_BOARDFLAGS] = simple_strtoul(c, NULL, 0);
+		bcm->sprom.r1.boardflags_lo = simple_strtoul(c, NULL, 0);
 	c = nvram_get("il0macaddr");
 	if (c)
-		bcm43xx_aton(c, (char *)&(sprom[BCM43xx_SPROM_IL0MACADDR]));
+		bcm43xx_aton(c, bcm->sprom.r1.il0mac);
 	c = nvram_get("et1macaddr");
 	if (c)
-		bcm43xx_aton(c, (char *)&(sprom[BCM43xx_SPROM_ET1MACADDR]));
+		bcm43xx_aton(c, bcm->sprom.r1.et1mac);
 	c = nvram_get("pa0b0");
 	if (c)
-		sprom[BCM43xx_SPROM_PA0B0] = simple_strtoul(c, NULL, 0);
+		bcm->sprom.r1.pa0b0 = simple_strtoul(c, NULL, 0);
 	c = nvram_get("pa0b1");
 	if (c)
-		sprom[BCM43xx_SPROM_PA0B1] = simple_strtoul(c, NULL, 0);
+		bcm->sprom.r1.pa0b1 = simple_strtoul(c, NULL, 0);
 	c = nvram_get("pa0b2");
 	if (c)
-		sprom[BCM43xx_SPROM_PA0B2] = simple_strtoul(c, NULL, 0);
+		bcm->sprom.r1.pa0b2 = simple_strtoul(c, NULL, 0);
 	c = nvram_get("pa1b0");
 	if (c)
-		sprom[BCM43xx_SPROM_PA1B0] = simple_strtoul(c, NULL, 0);
+		bcm->sprom.r1.pa1b0 = simple_strtoul(c, NULL, 0);
 	c = nvram_get("pa1b1");
 	if (c)
-		sprom[BCM43xx_SPROM_PA1B1] = simple_strtoul(c, NULL, 0);
+		bcm->sprom.r1.pa1b1 = simple_strtoul(c, NULL, 0);
 	c = nvram_get("pa1b2");
 	if (c)
-		sprom[BCM43xx_SPROM_PA1B2] = simple_strtoul(c, NULL, 0);
+		bcm->sprom.r1.pa1b2 = simple_strtoul(c, NULL, 0);
 	c = nvram_get("boardrev");
 	if (c)
-		sprom[BCM43xx_SPROM_BOARDREV] = simple_strtoul(c, NULL, 0);
-#endif
+		bcm->sprom.r1.board_rev = simple_strtoul(c, NULL, 0);
+	if (0)
+		goto out; /* suppress gcc warning about unused "out" */
+#else /* CONFIG_BCM947XX */
+
+	err = ssb_sprom_read(&bcm->ssb, &bcm->sprom, 0);
+	if (err)
+		goto out;
+
+#endif /* CONFIG_BCM947XX */
 
-	/* boardflags2 */
-	value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
-	bcm->sprom.boardflags2 = value;
-
-	/* il0macaddr */
-	value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
-	*(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
-	value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
-	*(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
-	value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
-	*(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
-
-	/* et0macaddr */
-	value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
-	*(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
-	value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
-	*(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
-	value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
-	*(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
-
-	/* et1macaddr */
-	value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
-	*(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
-	value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
-	*(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
-	value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
-	*(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
-
-	/* ethernet phy settings */
-	value = sprom[BCM43xx_SPROM_ETHPHY];
-	bcm->sprom.et0phyaddr = (value & 0x001F);
-	bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
-	bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14;
-	bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15;
-
-	/* boardrev, antennas, locale */
-	value = sprom[BCM43xx_SPROM_BOARDREV];
-	bcm->sprom.boardrev = (value & 0x00FF);
-	bcm->sprom.locale = (value & 0x0F00) >> 8;
-	bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
-	bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
-
-	/* pa0b* */
-	value = sprom[BCM43xx_SPROM_PA0B0];
-	bcm->sprom.pa0b0 = value;
-	value = sprom[BCM43xx_SPROM_PA0B1];
-	bcm->sprom.pa0b1 = value;
-	value = sprom[BCM43xx_SPROM_PA0B2];
-	bcm->sprom.pa0b2 = value;
-
-	/* wl0gpio* */
-	value = sprom[BCM43xx_SPROM_WL0GPIO0];
-	if (value == 0x0000)
-		value = 0xFFFF;
-	bcm->sprom.wl0gpio0 = value & 0x00FF;
-	bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
-	value = sprom[BCM43xx_SPROM_WL0GPIO2];
-	if (value == 0x0000)
-		value = 0xFFFF;
-	bcm->sprom.wl0gpio2 = value & 0x00FF;
-	bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
-
-	/* maxpower */
-	value = sprom[BCM43xx_SPROM_MAXPWR];
-	bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
-	bcm->sprom.maxpower_bgphy = value & 0x00FF;
-
-	/* pa1b* */
-	value = sprom[BCM43xx_SPROM_PA1B0];
-	bcm->sprom.pa1b0 = value;
-	value = sprom[BCM43xx_SPROM_PA1B1];
-	bcm->sprom.pa1b1 = value;
-	value = sprom[BCM43xx_SPROM_PA1B2];
-	bcm->sprom.pa1b2 = value;
-
-	/* idle tssi target */
-	value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
-	bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
-	bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
-
-	/* boardflags */
-	value = sprom[BCM43xx_SPROM_BOARDFLAGS];
-	if (value == 0xFFFF)
-		value = 0x0000;
-	bcm->sprom.boardflags = value;
 	/* boardflags workarounds */
 	if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
-	    bcm->chip_id == 0x4301 &&
+	    bcm->ssb.chip_id == 0x4301 &&
 	    bcm->board_revision == 0x74)
-		bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
+		bcm->sprom.r1.boardflags_lo |= BCM43xx_BFL_BTCOEXIST;
 	if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
 	    bcm->board_type == 0x4E &&
 	    bcm->board_revision > 0x40)
-		bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
+		bcm->sprom.r1.boardflags_lo |= BCM43xx_BFL_PACTRL;
 
-	/* antenna gain */
-	value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
-	if (value == 0x0000 || value == 0xFFFF)
-		value = 0x0202;
-	/* convert values to Q5.2 */
-	bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
-	bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
+	/* Convert Antennagain values to Q5.2 */
+	bcm->sprom.r1.antenna_gain_a <<= 2;
+	bcm->sprom.r1.antenna_gain_bg <<= 2;
 
-	kfree(sprom);
-
-	return 0;
+out:
+	return err;
 }
 
 /* DummyTransmission function, as documented on 
@@ -1079,7 +855,7 @@
 		return;
 
 	index -= 4;
-	if (bcm->current_core->rev >= 5) {
+	if (bcm->ssb.current_core->rev >= 5) {
 		bcm43xx_shm_write32(bcm,
 				    BCM43xx_SHM_HWMAC,
 				    index * 2,
@@ -1128,7 +904,7 @@
 	unsigned int i,j, nr_keys = 54;
 	u16 offset;
 
-	if (bcm->current_core->rev < 5)
+	if (bcm->ssb.current_core->rev < 5)
 		nr_keys = 16;
 	assert(nr_keys <= ARRAY_SIZE(bcm->key));
 
@@ -1147,194 +923,12 @@
 	dprintk(KERN_INFO PFX "Keys cleared\n");
 }
 
-/* Lowlevel core-switch function. This is only to be used in
- * bcm43xx_switch_core() and bcm43xx_probe_cores()
- */
-static int _switch_core(struct bcm43xx_private *bcm, int core)
-{
-	int err;
-	int attempts = 0;
-	u32 current_core;
-
-	assert(core >= 0);
-	while (1) {
-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
-						 (core * 0x1000) + 0x18000000);
-		if (unlikely(err))
-			goto error;
-		err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
-						&current_core);
-		if (unlikely(err))
-			goto error;
-		current_core = (current_core - 0x18000000) / 0x1000;
-		if (current_core == core)
-			break;
-
-		if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
-			goto error;
-		udelay(10);
-	}
-#ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0)
-		bcm->current_core_offset = 0x1000 * core;
-	else
-		bcm->current_core_offset = 0;
-#endif
-
-	return 0;
-error:
-	printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
-	return -ENODEV;
-}
-
-int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
-{
-	int err;
-
-	if (unlikely(!new_core))
-		return 0;
-	if (!new_core->available)
-		return -ENODEV;
-	if (bcm->current_core == new_core)
-		return 0;
-	err = _switch_core(bcm, new_core->index);
-	if (unlikely(err))
-		goto out;
-
-	bcm->current_core = new_core;
-out:
-	return err;
-}
-
-static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
-{
-	u32 value;
-
-	value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-	value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
-		 | BCM43xx_SBTMSTATELOW_REJECT;
-
-	return (value == BCM43xx_SBTMSTATELOW_CLOCK);
-}
-
-/* disable current core */
-static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
-{
-	u32 sbtmstatelow;
-	u32 sbtmstatehigh;
-	int i;
-
-	/* fetch sbtmstatelow from core information registers */
-	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-
-	/* core is already in reset */
-	if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
-		goto out;
-
-	if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
-		sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
-			       BCM43xx_SBTMSTATELOW_REJECT;
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-
-		for (i = 0; i < 1000; i++) {
-			sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-			if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
-				i = -1;
-				break;
-			}
-			udelay(10);
-		}
-		if (i != -1) {
-			printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
-			return -EBUSY;
-		}
-
-		for (i = 0; i < 1000; i++) {
-			sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-			if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
-				i = -1;
-				break;
-			}
-			udelay(10);
-		}
-		if (i != -1) {
-			printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
-			return -EBUSY;
-		}
-
-		sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
-			       BCM43xx_SBTMSTATELOW_REJECT |
-			       BCM43xx_SBTMSTATELOW_RESET |
-			       BCM43xx_SBTMSTATELOW_CLOCK |
-			       core_flags;
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-		udelay(10);
-	}
-
-	sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
-		       BCM43xx_SBTMSTATELOW_REJECT |
-		       core_flags;
-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-
-out:
-	bcm->current_core->enabled = 0;
-
-	return 0;
-}
-
-/* enable (reset) current core */
-static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
-{
-	u32 sbtmstatelow;
-	u32 sbtmstatehigh;
-	u32 sbimstate;
-	int err;
-
-	err = bcm43xx_core_disable(bcm, core_flags);
-	if (err)
-		goto out;
-
-	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
-		       BCM43xx_SBTMSTATELOW_RESET |
-		       BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
-		       core_flags;
-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-	udelay(1);
-
-	sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-	if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
-		sbtmstatehigh = 0x00000000;
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
-	}
-
-	sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
-	if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
-		sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
-	}
-
-	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
-		       BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
-		       core_flags;
-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-	udelay(1);
-
-	sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-	udelay(1);
-
-	bcm->current_core->enabled = 1;
-	assert(err == 0);
-out:
-	return err;
-}
-
 /* http://bcm-specs.sipsolutions.net/80211CoreReset */
 void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
 {
 	u32 flags = 0x00040000;
 
-	if ((bcm43xx_core_enabled(bcm)) &&
+	if ((ssb_core_is_enabled(&bcm->ssb)) &&
 	    !bcm43xx_using_pio(bcm)) {
 //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
 #if 0
@@ -1345,7 +939,7 @@
 		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE);
 		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
 		bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
-		if (bcm->current_core->rev < 5)
+		if (bcm->ssb.current_core->rev < 5)
 			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
 #endif
 #endif
@@ -1358,7 +952,7 @@
 		if (connect_phy)
 			flags |= 0x20000000;
 		bcm43xx_phy_connect(bcm, connect_phy);
-		bcm43xx_core_enable(bcm, flags);
+		ssb_core_enable(&bcm->ssb, flags);
 		bcm43xx_write16(bcm, 0x03E6, 0x0000);
 		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
 				bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
@@ -1370,7 +964,7 @@
 {
 	bcm43xx_radio_turn_off(bcm);
 	bcm43xx_write16(bcm, 0x03E6, 0x00F4);
-	bcm43xx_core_disable(bcm, 0);
+	ssb_core_disable(&bcm->ssb, 0);
 }
 
 /* Mark the current 80211 core inactive. */
@@ -1380,15 +974,15 @@
 
 	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 	bcm43xx_radio_turn_off(bcm);
-	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+	sbtmstatelow = bcm43xx_read32(bcm, SSB_TMSLOW);
 	sbtmstatelow &= 0xDFF5FFFF;
 	sbtmstatelow |= 0x000A0000;
-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	bcm43xx_write32(bcm, SSB_TMSLOW, sbtmstatelow);
 	udelay(1);
-	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+	sbtmstatelow = bcm43xx_read32(bcm, SSB_TMSLOW);
 	sbtmstatelow &= 0xFFF5FFFF;
 	sbtmstatelow |= 0x00080000;
-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	bcm43xx_write32(bcm, SSB_TMSLOW, sbtmstatelow);
 	udelay(1);
 }
 
@@ -1433,7 +1027,7 @@
 	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
 			bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
-	assert(bcm->noisecalc.core_at_start == bcm->current_core);
+	assert(bcm->noisecalc.core_at_start == bcm->ssb.current_core);
 	assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
 }
 
@@ -1443,7 +1037,7 @@
 
 	if (bcm->noisecalc.calculation_running)
 		return;
-	bcm->noisecalc.core_at_start = bcm->current_core;
+	bcm->noisecalc.core_at_start = bcm->ssb.current_core;
 	bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
 	bcm->noisecalc.calculation_running = 1;
 	bcm->noisecalc.nr_samples = 0;
@@ -1462,7 +1056,7 @@
 	/* Bottom half of Link Quality calculation. */
 
 	assert(bcm->noisecalc.calculation_running);
-	if (bcm->noisecalc.core_at_start != bcm->current_core ||
+	if (bcm->noisecalc.core_at_start != bcm->ssb.current_core ||
 	    bcm->noisecalc.channel_at_start != radio->channel)
 		goto drop_calculation;
 	tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
@@ -1804,7 +1398,7 @@
 static void bcm43xx_set_beacon_int(struct bcm43xx_private *bcm, u16 beacon_int)
 {
 	bcm43xx_time_lock(bcm);
-	if (bcm->current_core->rev >= 3) {
+	if (bcm->ssb.current_core->rev >= 3) {
 		bcm43xx_write32(bcm, 0x188, (beacon_int << 16));
 	} else {
 		bcm43xx_write16(bcm, 0x606, (beacon_int >> 6));
@@ -1995,7 +1589,7 @@
 static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
 {
 	if (bcm43xx_using_pio(bcm) &&
-	    (bcm->current_core->rev < 3) &&
+	    (bcm->ssb.current_core->rev < 3) &&
 	    (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
 		/* Apply a PIO specific workaround to the dma_reasons */
 		pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
@@ -2033,7 +1627,7 @@
 	spin_lock(&bcm->irq_lock);
 
 	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-	assert(bcm->current_core->id == BCM43xx_COREID_80211);
+	assert(bcm->ssb.current_core->cc == SSB_CC_80211);
 
 	reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff) {
@@ -2090,7 +1684,7 @@
 static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-	u8 rev = bcm->current_core->rev;
+	u8 rev = bcm->ssb.current_core->rev;
 	int err = 0;
 	int nr;
 	char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
@@ -2099,7 +1693,7 @@
 		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
 			 (rev >= 5 ? 5 : rev),
 			 modparam_fwpostfix);
-		err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
+		err = request_firmware(&phy->ucode, buf, &bcm->ssb.pci_dev->dev);
 		if (err) {
 			printk(KERN_ERR PFX 
 			       "Error: Microcode \"%s\" not available or load failed.\n",
@@ -2113,7 +1707,7 @@
 			 "bcm43xx_pcm%d%s.fw",
 			 (rev < 5 ? 4 : 5),
 			 modparam_fwpostfix);
-		err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
+		err = request_firmware(&phy->pcm, buf, &bcm->ssb.pci_dev->dev);
 		if (err) {
 			printk(KERN_ERR PFX
 			       "Error: PCM \"%s\" not available or load failed.\n",
@@ -2153,7 +1747,7 @@
 		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
 			 nr, modparam_fwpostfix);
 
-		err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
+		err = request_firmware(&phy->initvals0, buf, &bcm->ssb.pci_dev->dev);
 		if (err) {
 			printk(KERN_ERR PFX 
 			       "Error: InitVals \"%s\" not available or load failed.\n",
@@ -2172,7 +1766,7 @@
 
 			switch (phy->type) {
 			case BCM43xx_PHYTYPE_A:
-				sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+				sbtmstatehigh = bcm43xx_read32(bcm, SSB_TMSHIGH);
 				if (sbtmstatehigh & 0x00010000)
 					nr = 9;
 				else
@@ -2188,7 +1782,7 @@
 			snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
 				 nr, modparam_fwpostfix);
 
-			err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
+			err = request_firmware(&phy->initvals1, buf, &bcm->ssb.pci_dev->dev);
 			if (err) {
 				printk(KERN_ERR PFX 
 				       "Error: InitVals \"%s\" not available or load failed.\n",
@@ -2298,9 +1892,9 @@
 {
 	int err;
 
-	bcm->irq = bcm->pci_dev->irq;
+	bcm->irq = bcm->ssb.pci_dev->irq;
 #ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0) {
+	if (bcm->ssb.pci_dev->bus->number == 0) {
 		struct pci_dev *d = NULL;
 		/* FIXME: we will probably need more device IDs here... */
 		d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
@@ -2322,22 +1916,26 @@
  */
 static int switch_to_gpio_core(struct bcm43xx_private *bcm)
 {
-	int err;
+	int err = -ENODEV;
 
 	/* 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.
 	 */
-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-	if (err == -ENODEV) {
-		err = bcm43xx_switch_core(bcm, &bcm->core_pci);
-		if (unlikely(err == -ENODEV)) {
-			printk(KERN_ERR PFX "gpio error: "
-			       "Neither ChipCommon nor PCI core available!\n");
-		}
+	if (bcm->core_chipcommon) {
+		err = ssb_switch_core(&bcm->ssb, bcm->core_chipcommon);
+		if (err)
+			goto out;
+	} else if (bcm->core_pci) {
+		err = ssb_switch_core(&bcm->ssb, bcm->core_pci);
+		if (err)
+			goto out;
+	} else {
+		printk(KERN_ERR PFX "gpio error: "
+				    "Neither ChipCommon nor PCI core available!\n");
 	}
-
+out:
 	return err;
 }
 
@@ -2346,7 +1944,7 @@
  */
 static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
 {
-	struct bcm43xx_coreinfo *old_core;
+	struct ssb_core *old_core;
 	int err;
 	u32 mask, set;
 
@@ -2360,7 +1958,7 @@
 
 	mask = 0x0000001F;
 	set = 0x0000000F;
-	if (bcm->chip_id == 0x4301) {
+	if (bcm->ssb.chip_id == 0x4301) {
 		mask |= 0x0060;
 		set |= 0x0060;
 	}
@@ -2371,23 +1969,23 @@
 		mask |= 0x0180;
 		set |= 0x0180;
 	}
-	if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+	if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL) {
 		bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
 				bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
 				| 0x0200);
 		mask |= 0x0200;
 		set |= 0x0200;
 	}
-	if (bcm->current_core->rev >= 2)
+	if (bcm->ssb.current_core->rev >= 2)
 		mask  |= 0x0010; /* FIXME: This is redundant. */
 
-	old_core = bcm->current_core;
+	old_core = bcm->ssb.current_core;
 	err = switch_to_gpio_core(bcm);
 	if (err)
 		goto out;
 	bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
 	                (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
-	err = bcm43xx_switch_core(bcm, old_core);
+	err = ssb_switch_core(&bcm->ssb, old_core);
 out:
 	return err;
 }
@@ -2395,15 +1993,15 @@
 /* Turn off all GPIO stuff. Call this on module unload, for example. */
 static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
 {
-	struct bcm43xx_coreinfo *old_core;
+	struct ssb_core *old_core;
 	int err;
 
-	old_core = bcm->current_core;
+	old_core = bcm->ssb.current_core;
 	err = switch_to_gpio_core(bcm);
 	if (err)
 		return err;
 	bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
-	err = bcm43xx_switch_core(bcm, old_core);
+	err = ssb_switch_core(&bcm->ssb, old_core);
 	assert(err == 0);
 
 	return 0;
@@ -2493,7 +2091,7 @@
 	value = 0x0002;
 	if ((status & BCM43xx_SBF_MODE_NOTADHOC) &&
 	    !(status & BCM43xx_SBF_MODE_AP)) {
-		if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
+		if (bcm->ssb.chip_id == 0x4306 && bcm->ssb.chip_rev == 3)
 			value = 0x0064;
 		else
 			value = 0x0032;
@@ -2615,7 +2213,7 @@
 		bcm43xx_write16(bcm, 0x005E, value16);
 	}
 	bcm43xx_write32(bcm, 0x0100, 0x01000000);
-	if (bcm->current_core->rev < 5)
+	if (bcm->ssb.current_core->rev < 5)
 		bcm43xx_write32(bcm, 0x010C, 0x01000000);
 
 	value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
@@ -2644,7 +2242,7 @@
 	/* Initially set the wireless operation mode. */
 	bcm43xx_select_opmode(bcm);
 
-	if (bcm->current_core->rev < 3) {
+	if (bcm->ssb.current_core->rev < 3) {
 		bcm43xx_write16(bcm, 0x060E, 0x0000);
 		bcm43xx_write16(bcm, 0x0610, 0x8000);
 		bcm43xx_write16(bcm, 0x0604, 0x0000);
@@ -2661,9 +2259,9 @@
 	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
 	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
 
-	value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+	value32 = bcm43xx_read32(bcm, SSB_TMSLOW);
 	value32 |= 0x00100000;
-	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
+	bcm43xx_write32(bcm, SSB_TMSLOW, value32);
 
 	bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
 
@@ -2687,7 +2285,7 @@
 	bcm43xx_pio_free(bcm);
 	bcm43xx_dma_free(bcm);
 
-	bcm->current_core->initialized = 0;
+	bcm43xx_current_80211_priv(bcm)->initialized = 0;
 }
 
 /* http://bcm-specs.sipsolutions.net/80211Init */
@@ -2701,17 +2299,17 @@
 	u32 sbimconfiglow;
 	u8 limit;
 
-	if (bcm->chip_rev < 5) {
-		sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
-		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
-		sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
+	if (bcm->ssb.chip_rev < 5) {
+		sbimconfiglow = bcm43xx_read32(bcm, SSB_IMCFGLO);
+		sbimconfiglow &= ~SSB_IMCFGLO_REQTO;
+		sbimconfiglow &= ~SSB_IMCFGLO_SERTO;
 		if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
 			sbimconfiglow |= 0x32;
 		else if (bcm->bustype == BCM43xx_BUSTYPE_SB)
 			sbimconfiglow |= 0x53;
 		else
 			assert(0);
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
+		bcm43xx_write32(bcm, SSB_IMCFGLO, sbimconfiglow);
 	}
 
 	bcm43xx_phy_calibrate(bcm);
@@ -2719,7 +2317,7 @@
 	if (err)
 		goto out;
 
-	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
+	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->ssb.current_core->rev);
 	ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
 
 	if (0 /*FIXME: which condition has to be used here? */)
@@ -2732,7 +2330,7 @@
 		ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
 		if (phy->rev == 1)
 			ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
-		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+		if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL)
 			ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
 	} else if (phy->type == BCM43xx_PHYTYPE_B) {
 		ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
@@ -2770,7 +2368,7 @@
 
 	bcm43xx_write_mac_bssid_templates(bcm);
 
-	if (bcm->current_core->rev >= 5)
+	if (bcm->ssb.current_core->rev >= 5)
 		bcm43xx_write16(bcm, 0x043C, 0x000C);
 
 	if (active_wlcore) {
@@ -2793,7 +2391,7 @@
 	/* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
 	 * We enable it later.
 	 */
-	bcm->current_core->initialized = 1;
+	bcm43xx_current_80211_priv(bcm)->initialized = 1;
 out:
 	return err;
 
@@ -2817,7 +2415,7 @@
 static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
 {
 	bcm43xx_phy_lo_mark_all_unused(bcm);
-	if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+	if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI) {
 		bcm43xx_mac_suspend(bcm);
 		bcm43xx_calc_nrssi_slope(bcm);
 		bcm43xx_mac_enable(bcm);
@@ -2965,15 +2563,16 @@
 {
 	int ret = 0;
 	int i, err;
-	struct bcm43xx_coreinfo *core;
+	struct ssb_core *core;
+	struct bcm43xx_corepriv_80211 *wlpriv;
 
 	bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
 	for (i = 0; i < bcm->nr_80211_available; i++) {
-		core = &(bcm->core_80211[i]);
-		assert(core->available);
-		if (!core->initialized)
+		core = bcm->core_80211[i];
+		wlpriv = core->priv;
+		if (!wlpriv->initialized)
 			continue;
-		err = bcm43xx_switch_core(bcm, core);
+		err = ssb_switch_core(&bcm->ssb, core);
 		if (err) {
 			dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
 					     "switch_core failed (%d)\n", err);
@@ -3057,213 +2656,122 @@
 
 static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
 {
-	int err, i;
-	int current_core;
-	u32 core_vendor, core_id, core_rev;
-	u32 sb_id_hi, chip_id_32 = 0;
-	u16 pci_device, chip_id_16;
-	u8 core_count;
-
-	memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
-	memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
-	memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
-				    * BCM43xx_MAX_80211_CORES);
-	memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
-					* BCM43xx_MAX_80211_CORES);
-	bcm->nr_80211_available = 0;
-	bcm->current_core = NULL;
-	bcm->active_80211_core = NULL;
-
-	/* map core 0 */
-	err = _switch_core(bcm, 0);
-	if (err)
-		goto out;
+	struct ssb *ssb = &bcm->ssb;
+	int err;
+	u16 chipid_fallback = 0;
+	struct ssb_core *core;
+	struct bcm43xx_corepriv_80211 *priv_80211;
+	int i;
 
-	/* fetch sb_id_hi from core information registers */
-	sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
+	static const struct ssb_nrcores_elem nrcores_fallback[] = {
+		{ .chip_id_key = 0x5365, .nr_cores_value = 7, },
+		{ .chip_id_key = 0x4306, .nr_cores_value = 6, },
+		{ .chip_id_key = 0x4310, .nr_cores_value = 8, },
+		{ .chip_id_key = 0x4307, .nr_cores_value = 5, },
+		{ .chip_id_key = 0x4301, .nr_cores_value = 5, },
+		{ .chip_id_key = 0x4402, .nr_cores_value = 3, },
+		{ .chip_id_key = 0x4710, .nr_cores_value = 9, },
+		{ .chip_id_key = 0x4610, .nr_cores_value = 9, },
+		{ .chip_id_key = 0x4704, .nr_cores_value = 9, },
+	};
 
-	core_id = (sb_id_hi & 0xFFF0) >> 4;
-	core_rev = (sb_id_hi & 0xF);
-	core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
-
-	/* if present, chipcommon is always core 0; read the chipid from it */
-	if (core_id == BCM43xx_COREID_CHIPCOMMON) {
-		chip_id_32 = bcm43xx_read32(bcm, 0);
-		chip_id_16 = chip_id_32 & 0xFFFF;
-		bcm->core_chipcommon.available = 1;
-		bcm->core_chipcommon.id = core_id;
-		bcm->core_chipcommon.rev = core_rev;
-		bcm->core_chipcommon.index = 0;
-		/* While we are at it, also read the capabilities. */
-		bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
-	} else {
-		/* without a chipCommon, use a hard coded table. */
-		pci_device = bcm->pci_dev->device;
-		if (pci_device == 0x4301)
-			chip_id_16 = 0x4301;
-		else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
-			chip_id_16 = 0x4307;
-		else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
-			chip_id_16 = 0x4402;
-		else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
-			chip_id_16 = 0x4610;
-		else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
-			chip_id_16 = 0x4710;
+	switch (bcm->ssb.pci_dev->device) {
+	case 0x4301:
+		chipid_fallback = 0x4301;
+		break;
+	case 0x4305 ... 0x4307:
+		chipid_fallback = 0x4307;
+		break;
+	case 0x4402 ... 0x4403:
+		chipid_fallback = 0x4402;
+		break;
+	case 0x4610 ... 0x4615:
+		chipid_fallback = 0x4610;
+		break;
+	case 0x4710 ... 0x4715:
+		chipid_fallback = 0x4710;
+		break;
 #ifdef CONFIG_BCM947XX
-		else if ((pci_device >= 0x4320) && (pci_device <= 0x4325))
-			chip_id_16 = 0x4309;
+	case 0x4320 ... 0x4325:
+		chipid_fallback = 0x4309;
+		break;
 #endif
-		else {
-			printk(KERN_ERR PFX "Could not determine Chip ID\n");
-			return -ENODEV;
-		}
-	}
-
-	/* ChipCommon with Core Rev >=4 encodes number of cores,
-	 * otherwise consult hardcoded table */
-	if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
-		core_count = (chip_id_32 & 0x0F000000) >> 24;
-	} else {
-		switch (chip_id_16) {
-			case 0x4610:
-			case 0x4704:
-			case 0x4710:
-				core_count = 9;
-				break;
-			case 0x4310:
-				core_count = 8;
-				break;
-			case 0x5365:
-				core_count = 7;
-				break;
-			case 0x4306:
-				core_count = 6;
-				break;
-			case 0x4301:
-			case 0x4307:
-				core_count = 5;
-				break;
-			case 0x4402:
-				core_count = 3;
-				break;
-			default:
-				/* SOL if we get here */
-				assert(0);
-				core_count = 1;
-		}
-	}
-
-	bcm->chip_id = chip_id_16;
-	bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
-	bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
-
-	dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
-		bcm->chip_id, bcm->chip_rev);
-	dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
-	if (bcm->core_chipcommon.available) {
-		dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
-			core_id, core_rev, core_vendor,
-			bcm43xx_core_enabled(bcm) ? "enabled" : "disabled");
 	}
+	err = ssb_probe_cores(ssb, chipid_fallback,
+			      nrcores_fallback,
+			      ARRAY_SIZE(nrcores_fallback));
+	if (err)
+		goto out;
 
-	if (bcm->core_chipcommon.available)
-		current_core = 1;
-	else
-		current_core = 0;
-	for ( ; current_core < core_count; current_core++) {
-		struct bcm43xx_coreinfo *core;
-		struct bcm43xx_coreinfo_80211 *ext_80211;
+	bcm->nr_80211_available = 0;
+	bcm->active_80211_core = NULL;
+	for (i = 0; i < ssb->nr_cores; i++) {
+		core = &(ssb->cores[i]);
 
-		err = _switch_core(bcm, current_core);
-		if (err)
-			goto out;
-		/* Gather information */
-		/* fetch sb_id_hi from core information registers */
-		sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
-
-		/* extract core_id, core_rev, core_vendor */
-		core_id = (sb_id_hi & 0xFFF0) >> 4;
-		core_rev = (sb_id_hi & 0xF);
-		core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
-
-		dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n",
-			current_core, core_id, core_rev, core_vendor,
-			bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" );
-
-		core = NULL;
-		switch (core_id) {
-		case BCM43xx_COREID_PCI:
-			core = &bcm->core_pci;
-			if (core->available) {
+		switch (core->cc) {
+		case SSB_CC_PCI:
+			if (bcm->core_pci) {
 				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
-				continue;
+				break;
 			}
+			bcm->core_pci = core;
 			break;
-		case BCM43xx_COREID_80211:
-			for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-				core = &(bcm->core_80211[i]);
-				ext_80211 = &(bcm->core_80211_ext[i]);
-				if (!core->available)
-					break;
-				core = NULL;
-			}
-			if (!core) {
-				printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
+		case SSB_CC_80211:
+			if (bcm->nr_80211_available == BCM43xx_MAX_80211_CORES) {
+				printk(KERN_WARNING PFX "More tham %d cores of "
+							"type 802.11 found.\n",
 				       BCM43xx_MAX_80211_CORES);
-				continue;
+				break;
 			}
-			if (i != 0) {
+			if (bcm->nr_80211_available == 1) {
 				/* More than one 80211 core is only supported
 				 * by special chips.
 				 * There are chips with two 80211 cores, but with
 				 * dangling pins on the second core. Be careful
 				 * and ignore these cores here.
 				 */
-				if (bcm->pci_dev->device != 0x4324) {
+				if (bcm->ssb.pci_dev->device != 0x4324) {
 					dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n");
-					continue;
+					break;
 				}
 			}
-			switch (core_rev) {
-			case 2:
-			case 4:
-			case 5:
-			case 6:
-			case 7:
-			case 9:
+
+			bcm->core_80211[bcm->nr_80211_available] = core;
+			priv_80211 = &(bcm->corepriv_80211[bcm->nr_80211_available]);
+			bcm->nr_80211_available++;
+
+			switch (core->rev) {
+			case 2: case 4: case 5: case 6:
+			case 7: case 9:
 				break;
 			default:
 				printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
-				       core_rev);
+				       core->rev);
 				err = -ENODEV;
 				goto out;
 			}
-			bcm->nr_80211_available++;
-			core->priv = ext_80211;
-			bcm43xx_init_struct_phyinfo(&ext_80211->phy);
-			bcm43xx_init_struct_radioinfo(&ext_80211->radio);
+			core->priv = priv_80211;
+			bcm43xx_init_struct_phyinfo(&priv_80211->phy);
+			bcm43xx_init_struct_radioinfo(&priv_80211->radio);
 			break;
-		case BCM43xx_COREID_CHIPCOMMON:
-			printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
+		case SSB_CC_CHIPCOMMON:
+			if (bcm->core_chipcommon) {
+				printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
+				break;
+			}
+			bcm->core_chipcommon = core;
 			break;
 		}
-		if (core) {
-			core->available = 1;
-			core->id = core_id;
-			core->rev = core_rev;
-			core->index = current_core;
-		}
 	}
-
-	if (!bcm->core_80211[0].available) {
+	if (!bcm->core_80211[0]) {
 		printk(KERN_ERR PFX "Error: No 80211 core found!\n");
 		err = -ENODEV;
 		goto out;
 	}
+	err = ssb_switch_core(ssb, bcm->core_80211[0]);
+	if (err)
+		goto out;
 
-	err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
-
-	assert(err == 0);
 out:
 	return err;
 }
@@ -3289,90 +2797,6 @@
 	bcm43xx_pctl_set_crystal(bcm, 0);
 }
 
-static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
-					    u32 address,
-					    u32 data)
-{
-	bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
-	bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
-}
-
-static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
-{
-	int err;
-	struct bcm43xx_coreinfo *old_core;
-
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_pci);
-	if (err)
-		goto out;
-
-	bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
-
-	bcm43xx_switch_core(bcm, old_core);
-	assert(err == 0);
-out:
-	return err;
-}
-
-/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
- * To enable core 0, pass a core_mask of 1<<0
- */
-static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
-						  u32 core_mask)
-{
-	u32 backplane_flag_nr;
-	u32 value;
-	struct bcm43xx_coreinfo *old_core;
-	int err = 0;
-
-	value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
-	backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
-
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_pci);
-	if (err)
-		goto out;
-
-	if (bcm->core_pci.rev < 6) {
-		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
-		value |= (1 << backplane_flag_nr);
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
-	} else {
-		err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
-		if (err) {
-			printk(KERN_ERR PFX "Error: ICR setup failure!\n");
-			goto out_switch_back;
-		}
-		value |= core_mask << 8;
-		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
-		if (err) {
-			printk(KERN_ERR PFX "Error: ICR setup failure!\n");
-			goto out_switch_back;
-		}
-	}
-
-	value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
-	value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
-	bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
-
-	if (bcm->core_pci.rev < 5) {
-		value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
-		value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
-			 & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
-		value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
-			 & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
-		err = bcm43xx_pcicore_commit_settings(bcm);
-		assert(err == 0);
-	}
-
-out_switch_back:
-	err = bcm43xx_switch_core(bcm, old_core);
-out:
-	return err;
-}
-
 static void bcm43xx_free_modes(struct bcm43xx_private *bcm)
 {
 	struct ieee80211_hw *ieee = bcm->ieee;
@@ -3434,8 +2858,8 @@
 {
 	int err = -ENOMEM;
 	struct ieee80211_hw *ieee = bcm->ieee;
-	struct bcm43xx_coreinfo *core;
-	struct bcm43xx_coreinfo_80211 *wlext;
+	struct ssb_core *core;
+	struct bcm43xx_corepriv_80211 *wlpriv;
 	int i, nr_modes;
 
 	nr_modes = bcm->nr_80211_available;
@@ -3446,10 +2870,10 @@
 	ieee->num_modes = 0;
 
 	for (i = 0; i < bcm->nr_80211_available; i++) {
-		core = &(bcm->core_80211[i]);
-		wlext = core->priv;
+		core = bcm->core_80211[i];
+		wlpriv = core->priv;
 
-		switch (wlext->phy.type) {
+		switch (wlpriv->phy.type) {
 		case BCM43xx_PHYTYPE_A:
 			err = bcm43xx_append_mode(bcm->ieee, MODE_IEEE80211A,
 						  ARRAY_SIZE(bcm43xx_a_chantable),
@@ -3543,8 +2967,8 @@
 static void prepare_priv_for_init(struct bcm43xx_private *bcm)
 {
 	int i;
-	struct bcm43xx_coreinfo *core;
-	struct bcm43xx_coreinfo_80211 *wlext;
+	struct ssb_core *core;
+	struct bcm43xx_corepriv_80211 *wlpriv;
 
 	assert(!bcm->active_80211_core);
 
@@ -3558,16 +2982,13 @@
 	memset(&bcm->stats, 0, sizeof(bcm->stats));
 
 	/* Wireless core data */
-	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-		core = &(bcm->core_80211[i]);
-		wlext = core->priv;
-
-		if (!core->available)
-			continue;
-		assert(wlext == &(bcm->core_80211_ext[i]));
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		core = bcm->core_80211[i];
+		wlpriv = core->priv;
+		assert(wlpriv == &(bcm->corepriv_80211[i]));
 
-		prepare_phydata_for_init(&wlext->phy);
-		prepare_radiodata_for_init(bcm, &wlext->radio);
+		prepare_phydata_for_init(&wlpriv->phy);
+		prepare_radiodata_for_init(bcm, &wlpriv->radio);
 	}
 
 	/* IRQ related flags */
@@ -3589,7 +3010,7 @@
 {
 	int err;
 
-	if (!bcm43xx_core_enabled(bcm))
+	if (!ssb_core_is_enabled(&bcm->ssb))
 		bcm43xx_wireless_core_reset(bcm, 1);
 	if (!active_wlcore)
 		bcm43xx_wireless_core_mark_inactive(bcm);
@@ -3610,27 +3031,27 @@
 				 int phytype)
 {
 	int i, err;
-	struct bcm43xx_coreinfo *active_core = NULL;
-	struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
-	struct bcm43xx_coreinfo *core;
-	struct bcm43xx_coreinfo_80211 *wlext;
+	struct ssb_core *active_core = NULL;
+	struct bcm43xx_corepriv_80211 *active_wlpriv = NULL;
+	struct ssb_core *core;
+	struct bcm43xx_corepriv_80211 *wlpriv;
 	int adjust_active_sbtmstatelow = 0;
 
 	might_sleep();
 
 	if (phytype < 0) {
 		/* If no phytype is requested, select the first core. */
-		assert(bcm->core_80211[0].available);
-		wlext = bcm->core_80211[0].priv;
-		phytype = wlext->phy.type;
+		assert(bcm->nr_80211_available != 0);
+		wlpriv = bcm->core_80211[0]->priv;
+		phytype = wlpriv->phy.type;
 	}
 	/* Find the requested core. */
 	for (i = 0; i < bcm->nr_80211_available; i++) {
-		core = &(bcm->core_80211[i]);
-		wlext = core->priv;
-		if (wlext->phy.type == phytype) {
+		core = bcm->core_80211[i];
+		wlpriv = core->priv;
+		if (wlpriv->phy.type == phytype) {
 			active_core = core;
-			active_wlext = wlext;
+			active_wlpriv = wlpriv;
 			break;
 		}
 	}
@@ -3667,12 +3088,12 @@
 
 	/* Mark all unused cores "inactive". */
 	for (i = 0; i < bcm->nr_80211_available; i++) {
-		core = &(bcm->core_80211[i]);
-		wlext = core->priv;
+		core = bcm->core_80211[i];
+		wlpriv = core->priv;
 
 		if (core == active_core)
 			continue;
-		err = bcm43xx_switch_core(bcm, core);
+		err = ssb_switch_core(&bcm->ssb, core);
 		if (err) {
 			dprintk(KERN_ERR PFX "Could not switch to inactive "
 					     "802.11 core (%d)\n", err);
@@ -3688,19 +3109,19 @@
 	}
 
 	/* Now initialize the active 802.11 core. */
-	err = bcm43xx_switch_core(bcm, active_core);
+	err = ssb_switch_core(&bcm->ssb, active_core);
 	if (err) {
 		dprintk(KERN_ERR PFX "Could not switch to active "
 				     "802.11 core (%d)\n", err);
 		goto error;
 	}
 	if (adjust_active_sbtmstatelow &&
-	    active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
+	    active_wlpriv->phy.type == BCM43xx_PHYTYPE_G) {
 		u32 sbtmstatelow;
 
-		sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+		sbtmstatelow = bcm43xx_read32(bcm, SSB_TMSLOW);
 		sbtmstatelow |= 0x20000000;
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+		bcm43xx_write32(bcm, SSB_TMSLOW, sbtmstatelow);
 	}
 	err = wireless_core_up(bcm, 1);
 	if (err) {
@@ -3732,7 +3153,7 @@
 	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
 
 	dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
-		active_wlext->phy.type);
+		active_wlpriv->phy.type);
 
 	return 0;
 
@@ -3778,20 +3199,21 @@
 
 static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
 {
-	struct pci_dev *pci_dev = bcm->pci_dev;
+	struct pci_dev *pci_dev = bcm->ssb.pci_dev;
 	int i;
 
 	bcm43xx_chipset_detach(bcm);
+	ssb_exit(&bcm->ssb);
 	/* Do _not_ access the chip, after it is detached. */
-	pci_iounmap(pci_dev, bcm->mmio_addr);
+	pci_iounmap(pci_dev, bcm->ssb.mmio);
 	pci_release_regions(pci_dev);
 	pci_disable_device(pci_dev);
 
 	/* Free allocated structures/fields */
 	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-		kfree(bcm->core_80211_ext[i].phy._lo_pairs);
-		if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
-			kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+		kfree(bcm->corepriv_80211[i].phy._lo_pairs);
+		if (bcm->corepriv_80211[i].phy.dyn_tssi_tbl)
+			kfree(bcm->corepriv_80211[i].phy.tssi2dbm);
 	}
 	bcm43xx_free_modes(bcm);
 }
@@ -3852,13 +3274,42 @@
 	return 0;
 }
 
-static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
+static int bcm43xx_ssb_suspend(struct ssb *ssb)
+{
+	int i;
+	int err;
+	struct bcm43xx_private *bcm = ssb_to_bcm43xx(ssb);
+
+	for (i = 0; i < bcm->ieee->queues; i++)
+		ieee80211_stop_queue(bcm->net_dev, i);
+	ieee80211_netif_oper(bcm->net_dev, NETIF_DETACH);
+
+	err = bcm43xx_net_stop(bcm->net_dev);
+	if (!err)
+		mutex_lock(&bcm->mutex);
+
+	return err;
+}
+
+static int bcm43xx_ssb_resume(struct ssb *ssb)
+{
+	int err;
+	struct bcm43xx_private *bcm = ssb_to_bcm43xx(ssb);
+
+	mutex_unlock(&bcm->mutex);
+	err = bcm43xx_net_open(bcm->net_dev);
+
+	return err;
+}
+
+static int bcm43xx_attach_board(struct bcm43xx_private *bcm,
+				struct pci_dev *pci_dev)
 {
-	struct pci_dev *pci_dev = bcm->pci_dev;
 	struct net_device *net_dev = bcm->net_dev;
 	int err;
 	int i;
 	u32 coremask;
+	void __iomem *mmio;
 
 	err = pci_enable_device(pci_dev);
 	if (err) {
@@ -3872,13 +3323,19 @@
 	}
 	/* enable PCI bus-mastering */
 	pci_set_master(pci_dev);
-	bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL);
-	if (!bcm->mmio_addr) {
+	mmio = pci_iomap(pci_dev, 0, ~0UL);
+	if (!mmio) {
 		printk(KERN_ERR PFX "pci_iomap() failed\n");
 		err = -EIO;
 		goto err_pci_release;
 	}
-	net_dev->base_addr = (unsigned long)bcm->mmio_addr;
+	net_dev->base_addr = (unsigned long)mmio;
+
+	err = ssb_init(&bcm->ssb, pci_dev, mmio,
+		       bcm43xx_ssb_suspend,
+		       bcm43xx_ssb_resume);
+	if (err)
+		goto err_iounmap;
 
 	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
 	                          &bcm->board_vendor);
@@ -3889,22 +3346,23 @@
 
 	err = bcm43xx_chipset_attach(bcm);
 	if (err)
-		goto err_iounmap;
+		goto err_ssb_exit;
 	err = bcm43xx_pctl_init(bcm);
 	if (err)
 		goto err_chipset_detach;
 	err = bcm43xx_probe_cores(bcm);
 	if (err)
 		goto err_chipset_detach;
-	
+
+	printk(KERN_INFO PFX "Broadcom %04X WLAN found\n", bcm->ssb.chip_id);
+
 	/* Attach all IO cores to the backplane. */
 	coremask = 0;
 	for (i = 0; i < bcm->nr_80211_available; i++)
-		coremask |= (1 << bcm->core_80211[i].index);
-	//FIXME: Also attach some non80211 cores?
-	err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
+		coremask |= (1 << bcm->core_80211[i]->index);
+	err = ssb_cores_connect(&bcm->ssb, coremask);
 	if (err) {
-		printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
+		printk(KERN_ERR PFX "Could not connect cores\n");
 		goto err_chipset_detach;
 	}
 
@@ -3916,7 +3374,7 @@
 		goto err_chipset_detach;
 
 	for (i = 0; i < bcm->nr_80211_available; i++) {
-		err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
+		err = ssb_switch_core(&bcm->ssb, bcm->core_80211[i]);
 		assert(err != -ENODEV);
 		if (err)
 			goto err_80211_unwind;
@@ -3947,29 +3405,28 @@
 	bcm43xx_pctl_set_crystal(bcm, 0);
 
 	/* Set the MAC address in the networking subsystem */
-	if (is_valid_ether_addr(bcm->sprom.et1macaddr))
-		memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
+	if (is_valid_ether_addr(bcm->sprom.r1.et1mac))
+		memcpy(bcm->net_dev->dev_addr, bcm->sprom.r1.et1mac, 6);
 	else
-		memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
+		memcpy(bcm->net_dev->dev_addr, bcm->sprom.r1.il0mac, 6);
 	bcm43xx_setup_modes(bcm);
 
-	snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
-		 "Broadcom %04X", bcm->chip_id);
-
 	assert(err == 0);
 out:
 	return err;
 
 err_80211_unwind:
 	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-		kfree(bcm->core_80211_ext[i].phy._lo_pairs);
-		if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
-			kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
+		kfree(bcm->corepriv_80211[i].phy._lo_pairs);
+		if (bcm->corepriv_80211[i].phy.dyn_tssi_tbl)
+			kfree(bcm->corepriv_80211[i].phy.tssi2dbm);
 	}
 err_chipset_detach:
 	bcm43xx_chipset_detach(bcm);
+err_ssb_exit:
+	ssb_exit(&bcm->ssb);
 err_iounmap:
-	pci_iounmap(pci_dev, bcm->mmio_addr);
+	pci_iounmap(pci_dev, mmio);
 err_pci_release:
 	pci_release_regions(pci_dev);
 err_pci_disable:
@@ -4386,7 +3843,6 @@
 
 	bcm->ieee = ieee;
 	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
-	bcm->pci_dev = pci_dev;
 	bcm->net_dev = net_dev;
 	bcm->bad_frames_preempt = modparam_bad_frames_preempt;
 	spin_lock_init(&bcm->irq_lock);
@@ -4475,7 +3931,7 @@
 	pci_set_drvdata(pdev, net_dev);
 	SET_NETDEV_DEV(net_dev, &pdev->dev);
 
-	err = bcm43xx_attach_board(bcm);
+	err = bcm43xx_attach_board(bcm, pdev);
 	if (err)
 		goto err_free_netdev;
 	err = ieee80211_register_hw(net_dev, ieee);
@@ -4632,7 +4088,6 @@
 
 static int __init bcm43xx_init(void)
 {
-	printk(KERN_INFO KBUILD_MODNAME " driver\n");
 	bcm43xx_debugfs_init();
 	return pci_register_driver(&bcm43xx_pci_driver);
 }
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c	2006-08-23 10:58:41.000000000 +0200
@@ -84,7 +84,7 @@
 		goto out;
 	}
 	net_dev = bcm->net_dev;
-	pci_dev = bcm->pci_dev;
+	pci_dev = bcm->ssb.pci_dev;
 
 	/* This is where the information is written to the "devinfo" file */
 	fappend("*** %s devinfo ***\n", net_dev->name);
@@ -93,23 +93,23 @@
 	fappend("subsystem_vendor: 0x%04x   subsystem_device: 0x%04x\n",
 		pci_dev->subsystem_vendor, pci_dev->subsystem_device);
 	fappend("IRQ: %d\n", bcm->irq);
-	fappend("mmio_addr: 0x%p\n", bcm->mmio_addr);
-	fappend("chip_id: 0x%04x   chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
-	if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
+	fappend("mmio: 0x%p\n", bcm->ssb.mmio);
+	fappend("chip_id: 0x%04x   chip_rev: 0x%02x\n", bcm->ssb.chip_id, bcm->ssb.chip_rev);
+	if ((bcm->core_80211[0]->rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
 		fappend("Radio disabled by hardware!\n");
-	if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
+	if ((bcm->core_80211[0]->rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
 		fappend("Radio disabled by hardware!\n");
 	fappend("board_vendor: 0x%04x   board_type: 0x%04x\n", bcm->board_vendor,
 	        bcm->board_type);
 
 	fappend("\nCores:\n");
-#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, "	\
+#define fappend_core(name, info) fappend("core \"" name "\" %s, id: 0x%04x, "		\
 					 "rev: 0x%02x, index: 0x%02x\n",		\
-					 (info).available				\
+					 (info)						\
 						? "available" : "nonavailable",		\
-					 (info).enabled					\
-						? "enabled" : "disabled",		\
-					 (info).id, (info).rev, (info).index)
+					 (info) ? (info)->cc : 0,			\
+					 (info) ? (info)->rev : 0,			\
+					 (info) ? (info)->index : 0)
 	fappend_core("CHIPCOMMON", bcm->core_chipcommon);
 	fappend_core("PCI", bcm->core_pci);
 	fappend_core("first 80211", bcm->core_80211[0]);
@@ -149,36 +149,6 @@
 	return res;
 }
 
-static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
-				 size_t count, loff_t *ppos)
-{
-	const size_t len = REALLY_BIG_BUFFER_SIZE;
-
-	struct bcm43xx_private *bcm = file->private_data;
-	char *buf = really_big_buffer;
-	size_t pos = 0;
-	ssize_t res;
-	unsigned long flags;
-
-	down(&big_buffer_sem);
-	mutex_lock(&bcm->mutex);
-	spin_lock_irqsave(&bcm->irq_lock, flags);
-	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
-		fappend("Board not initialized.\n");
-		goto out;
-	}
-
-	/* This is where the information is written to the "sprom_dump" file */
-	fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
-
-out:
-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
-	mutex_unlock(&bcm->mutex);
-	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-	up(&big_buffer_sem);
-	return res;
-}
-
 static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
 			     size_t count, loff_t *ppos)
 {
@@ -361,12 +331,6 @@
 	.open = open_file_generic,
 };
 
-static struct file_operations spromdump_fops = {
-	.read = spromdump_read_file,
-	.write = write_file_dummy,
-	.open = open_file_generic,
-};
-
 static struct file_operations drvinfo_fops = {
 	.read = drvinfo_read_file,
 	.write = write_file_dummy,
@@ -429,10 +393,6 @@
 						bcm, &devinfo_fops);
 	if (!e->dentry_devinfo)
 		printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
-	e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
-						  bcm, &spromdump_fops);
-	if (!e->dentry_spromdump)
-		printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
 	e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
 	                                    bcm, &tsf_fops);
 	if (!e->dentry_tsf)
@@ -456,7 +416,6 @@
 
 	e = bcm->dfsentry;
 	assert(e);
-	debugfs_remove(e->dentry_spromdump);
 	debugfs_remove(e->dentry_devinfo);
 	debugfs_remove(e->dentry_tsf);
 	debugfs_remove(e->dentry_txstat);
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c	2006-08-23 10:58:41.000000000 +0200
@@ -327,11 +327,11 @@
 	dma_addr_t dmaaddr;
 
 	if (tx) {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+		dmaaddr = dma_map_single(&ring->bcm->ssb.pci_dev->dev,
 					 buf, len,
 					 DMA_TO_DEVICE);
 	} else {
-		dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev,
+		dmaaddr = dma_map_single(&ring->bcm->ssb.pci_dev->dev,
 					 buf, len,
 					 DMA_FROM_DEVICE);
 	}
@@ -346,11 +346,11 @@
 		      int tx)
 {
 	if (tx) {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		dma_unmap_single(&ring->bcm->ssb.pci_dev->dev,
 				 addr, len,
 				 DMA_TO_DEVICE);
 	} else {
-		dma_unmap_single(&ring->bcm->pci_dev->dev,
+		dma_unmap_single(&ring->bcm->ssb.pci_dev->dev,
 				 addr, len,
 				 DMA_FROM_DEVICE);
 	}
@@ -363,7 +363,7 @@
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev,
+	dma_sync_single_for_cpu(&ring->bcm->ssb.pci_dev->dev,
 				addr, len, DMA_FROM_DEVICE);
 }
 
@@ -374,7 +374,7 @@
 {
 	assert(!ring->tx);
 
-	dma_sync_single_for_device(&ring->bcm->pci_dev->dev,
+	dma_sync_single_for_device(&ring->bcm->ssb.pci_dev->dev,
 				   addr, len, DMA_FROM_DEVICE);
 }
 
@@ -393,7 +393,7 @@
 
 static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
 {
-	struct device *dev = &(ring->bcm->pci_dev->dev);
+	struct device *dev = &(ring->bcm->ssb.pci_dev->dev);
 
 	ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
 					    &(ring->dmabase), GFP_KERNEL);
@@ -408,7 +408,7 @@
 
 static void free_ringmemory(struct bcm43xx_dmaring *ring)
 {
-	struct device *dev = &(ring->bcm->pci_dev->dev);
+	struct device *dev = &(ring->bcm->ssb.pci_dev->dev);
 
 	dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
 			  ring->descbase, ring->dmabase);
@@ -727,7 +727,7 @@
 	if (dma64)
 		ring->routing = BCM43xx_DMA64_CLIENTTRANS;
 #ifdef CONFIG_BCM947XX
-	if (bcm->pci_dev->bus->number == 0)
+	if (bcm->ssb.pci_dev->bus->number == 0)
 		ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS;
 #endif
 
@@ -832,8 +832,8 @@
 	int dma64 = 0;
 	u32 sbtmstatehi;
 
-	sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-	if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT)
+	sbtmstatehi = bcm43xx_read32(bcm, SSB_TMSHIGH);
+	if (sbtmstatehi & SSB_TMSHIGH_DMA64)
 		dma64 = 1;
 
 	/* setup TX DMA channels. */
@@ -873,7 +873,7 @@
 		goto err_destroy_tx5;
 	dma->rx_ring0 = ring;
 
-	if (bcm->current_core->rev < 5) {
+	if (bcm->ssb.current_core->rev < 5) {
 		ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64);
 		if (!ring)
 			goto err_destroy_rx0;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h	2006-08-23 10:58:41.000000000 +0200
@@ -128,8 +128,6 @@
 
 void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
 
-int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
-
 int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
 				 int phytype);
 
@@ -140,7 +138,4 @@
 
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
 
-int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
-int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
-
 #endif /* BCM43xx_MAIN_H_ */
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c	2006-08-23 10:58:41.000000000 +0200
@@ -90,7 +90,7 @@
 		phy->is_locked = 0;
 		return;
 	}
-	if (bcm->current_core->rev < 3) {
+	if (bcm->ssb.current_core->rev < 3) {
 		bcm43xx_mac_suspend(bcm);
 		spin_lock(&phy->lock);
 	} else {
@@ -105,7 +105,7 @@
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 
 	assert(irqs_disabled());
-	if (bcm->current_core->rev < 3) {
+	if (bcm->ssb.current_core->rev < 3) {
 		if (phy->is_locked) {
 			spin_unlock(&phy->lock);
 			bcm43xx_mac_enable(bcm);
@@ -161,22 +161,22 @@
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	u32 flags;
 
-	if (bcm->current_core->rev < 5)
+	if (bcm->ssb.current_core->rev < 5)
 		goto out;
 
-	flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+	flags = bcm43xx_read32(bcm, SSB_TMSHIGH);
 	if (connect) {
 		if (!(flags & 0x00010000))
 			return -ENODEV;
-		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+		flags = bcm43xx_read32(bcm, SSB_TMSLOW);
 		flags |= (0x800 << 18);
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+		bcm43xx_write32(bcm, SSB_TMSLOW, flags);
 	} else {
 		if (!(flags & 0x00020000))
 			return -ENODEV;
-		flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+		flags = bcm43xx_read32(bcm, SSB_TMSHIGH);
 		flags &= ~(0x800 << 18);
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
+		bcm43xx_write32(bcm, SSB_TMSLOW, flags);
 	}
 out:
 	phy->connected = connect;
@@ -565,7 +565,7 @@
 		bcm43xx_phy_setupa(bcm);
 	} else {
 		bcm43xx_phy_setupg(bcm);
-		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+		if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL)
 			bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
 		return;
 	}
@@ -715,7 +715,7 @@
 	if (radio->version == 0x2050)
 		bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
 	bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
-	if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+	if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI) {
 		bcm43xx_calc_nrssi_slope(bcm);
 		bcm43xx_calc_nrssi_threshold(bcm);
 	}
@@ -895,7 +895,7 @@
 		bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
 		bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
 		bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
-		if (bcm->sprom.boardflags & 0x8000) {
+		if (bcm->sprom.r1.boardflags_lo & 0x8000) {
 			bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
 			bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
 		} else {
@@ -985,7 +985,7 @@
 		bcm43xx_phy_write(bcm, 0x0062, 0x0007);
 		(void) bcm43xx_radio_calibrationvalue(bcm);
 		bcm43xx_phy_lo_b_measure(bcm);
-		if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+		if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI) {
 			bcm43xx_calc_nrssi_slope(bcm);
 			bcm43xx_calc_nrssi_threshold(bcm);
 		}
@@ -1105,7 +1105,7 @@
 			  bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
 	bcm43xx_phy_write(bcm, 0x0812,
 			  bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
-	if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
+	if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_EXTLNA) {
 		if (phy->rev >= 7) {
 			bcm43xx_phy_write(bcm, 0x0811,
 					  bcm43xx_phy_read(bcm, 0x0811)
@@ -1252,7 +1252,7 @@
 					   & 0xF000) | (FIXME << 12));
 			*/
 		}
-		if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
+		if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL)
 			bcm43xx_phy_write(bcm, 0x002E, 0x8075);
 		else
 			bcm43xx_phy_write(bcm, 0x003E, 0x807F);
@@ -1266,7 +1266,7 @@
 		bcm43xx_phy_write(bcm, 0x080F, 0x8078);
 	}
 
-	if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+	if (!(bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI)) {
 		/* The specs state to update the NRSSI LT with
 		 * the value 0x7FFFFFFF here. I think that is some weird
 		 * compiler optimization in the original driver.
@@ -1287,7 +1287,7 @@
 	if (radio->revision == 8)
 		bcm43xx_phy_write(bcm, 0x0805, 0x3230);
 	bcm43xx_phy_init_pctl(bcm);
-	if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
+	if (bcm->ssb.chip_id == 0x4306 && bcm->ssb.chip_package == 2) {
 		bcm43xx_phy_write(bcm, 0x0429,
 				  bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
 		bcm43xx_phy_write(bcm, 0x04C3,
@@ -1985,9 +1985,9 @@
 
 		estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
 
-		max_pwr = bcm->sprom.maxpower_bgphy;
+		max_pwr = bcm->sprom.r1.maxpwr_bg;
 
-		if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
+		if ((bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL) &&
 		    (phy->type == BCM43xx_PHYTYPE_G))
 			max_pwr -= 0x3;
 
@@ -2043,7 +2043,7 @@
 					txpower = 3;
 					radio_attenuation += 2;
 					baseband_attenuation += 2;
-				} else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
+				} else if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_PACTRL) {
 					baseband_attenuation += 4 * (radio_attenuation - 2);
 					radio_attenuation = 2;
 				}
@@ -2116,16 +2116,16 @@
 	s8 *dyn_tssi2dbm;
 	
 	if (phy->type == BCM43xx_PHYTYPE_A) {
-		pab0 = (s16)(bcm->sprom.pa1b0);
-		pab1 = (s16)(bcm->sprom.pa1b1);
-		pab2 = (s16)(bcm->sprom.pa1b2);
+		pab0 = (s16)(bcm->sprom.r1.pa1b0);
+		pab1 = (s16)(bcm->sprom.r1.pa1b1);
+		pab2 = (s16)(bcm->sprom.r1.pa1b2);
 	} else {
-		pab0 = (s16)(bcm->sprom.pa0b0);
-		pab1 = (s16)(bcm->sprom.pa0b1);
-		pab2 = (s16)(bcm->sprom.pa0b2);
+		pab0 = (s16)(bcm->sprom.r1.pa0b0);
+		pab1 = (s16)(bcm->sprom.r1.pa0b1);
+		pab2 = (s16)(bcm->sprom.r1.pa0b2);
 	}
 
-	if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
+	if ((bcm->ssb.chip_id == 0x4301) && (radio->version != 0x2050)) {
 		phy->idle_tssi = 0x34;
 		phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
 		return 0;
@@ -2135,15 +2135,15 @@
 	    pab0 != -1 && pab1 != -1 && pab2 != -1) {
 		/* The pabX values are set in SPROM. Use them. */
 		if (phy->type == BCM43xx_PHYTYPE_A) {
-			if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
-			    (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
-				phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
+			if ((s8)bcm->sprom.r1.itssi_a != 0 &&
+			    (s8)bcm->sprom.r1.itssi_a != -1)
+				phy->idle_tssi = (s8)(bcm->sprom.r1.itssi_a);
 			else
 				phy->idle_tssi = 62;
 		} else {
-			if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
-			    (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
-				phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
+			if ((s8)bcm->sprom.r1.itssi_bg != 0 &&
+			    (s8)bcm->sprom.r1.itssi_bg != -1)
+				phy->idle_tssi = (s8)(bcm->sprom.r1.itssi_bg);
 			else
 				phy->idle_tssi = 62;
 		}
@@ -2329,7 +2329,7 @@
 		}
 		break;
 	case BCM43xx_PHYTYPE_B:
-		if (bcm->current_core->rev == 2)
+		if (bcm->ssb.current_core->rev == 2)
 			value = (3/*automatic*/ << 7);
 		else
 			value = (antennadiv << 7);
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c	2006-08-23 10:58:41.000000000 +0200
@@ -315,7 +315,7 @@
 
 	queue->bcm = bcm;
 	queue->mmio_base = pio_mmio_base;
-	queue->need_workarounds = (bcm->current_core->rev < 3);
+	queue->need_workarounds = (bcm->ssb.current_core->rev < 3);
 
 	INIT_LIST_HEAD(&queue->txfree);
 	INIT_LIST_HEAD(&queue->txqueue);
@@ -419,7 +419,7 @@
 		goto err_destroy2;
 	pio->queue3 = queue;
 
-	if (bcm->current_core->rev < 3)
+	if (bcm->ssb.current_core->rev < 3)
 		bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
 
 	dprintk(KERN_INFO PFX "PIO initialized\n");
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c	2006-08-23 10:58:41.000000000 +0200
@@ -41,8 +41,8 @@
 	u32 tmp;
 	int err;
 
-	assert(bcm->current_core == &bcm->core_chipcommon);
-	if (bcm->current_core->rev < 6) {
+	assert(bcm->ssb.current_core == bcm->core_chipcommon);
+	if (bcm->ssb.current_core->rev < 6) {
 		if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
 		    bcm->bustype == BCM43xx_BUSTYPE_SB)
 			return BCM43xx_PCTL_CLKSRC_XTALOS;
@@ -54,8 +54,8 @@
 			return BCM43xx_PCTL_CLKSRC_XTALOS;
 		}
 	}
-	if (bcm->current_core->rev < 10) {
-		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+	if (bcm->ssb.current_core->rev < 10) {
+		tmp = bcm43xx_read32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL);
 		tmp &= 0x7;
 		if (tmp == 0)
 			return BCM43xx_PCTL_CLKSRC_LOPWROS;
@@ -79,11 +79,11 @@
 	int divisor;
 	u32 tmp;
 
-	assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
-	assert(bcm->current_core == &bcm->core_chipcommon);
+	assert(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL);
+	assert(bcm->ssb.current_core == bcm->core_chipcommon);
 
 	clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
-	if (bcm->current_core->rev < 6) {
+	if (bcm->ssb.current_core->rev < 6) {
 		switch (clocksrc) {
 		case BCM43xx_PCTL_CLKSRC_PCI:
 			divisor = 64;
@@ -95,14 +95,14 @@
 			assert(0);
 			divisor = 1;
 		}
-	} else if (bcm->current_core->rev < 10) {
+	} else if (bcm->ssb.current_core->rev < 10) {
 		switch (clocksrc) {
 		case BCM43xx_PCTL_CLKSRC_LOPWROS:
 			divisor = 1;
 			break;
 		case BCM43xx_PCTL_CLKSRC_XTALOS:
 		case BCM43xx_PCTL_CLKSRC_PCI:
-			tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+			tmp = bcm43xx_read32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL);
 			divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
 			divisor *= 4;
 			break;
@@ -111,7 +111,7 @@
 			divisor = 1;
 		}
 	} else {
-		tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
+		tmp = bcm43xx_read32(bcm, SSB_CHIPCOMMON_SYSCLKCTL);
 		divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
 		divisor *= 4;
 	}
@@ -151,24 +151,25 @@
 int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
 {
 	int err, maxfreq;
-	struct bcm43xx_coreinfo *old_core;
+	struct ssb_core *old_core;
 
-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+	if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
 		return 0;
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-	if (err == -ENODEV)
+	if (!bcm->core_chipcommon)
 		return 0;
+
+	old_core = bcm->ssb.current_core;
+	err = ssb_switch_core(&bcm->ssb, bcm->core_chipcommon);
 	if (err)
 		goto out;
 
 	maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
-	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
+	bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
 			(maxfreq * 150 + 999999) / 1000000);
-	bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
+	bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
 			(maxfreq * 15 + 999999) / 1000000);
 
-	err = bcm43xx_switch_core(bcm, old_core);
+	err = ssb_switch_core(&bcm->ssb, old_core);
 	assert(err == 0);
 
 out:
@@ -180,23 +181,26 @@
 	u16 delay = 0;
 	int err;
 	u32 pll_on_delay;
-	struct bcm43xx_coreinfo *old_core;
+	struct ssb_core *old_core;
 	int minfreq;
 
 	if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
 		goto out;
-	if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
+	if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
 		goto out;
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-	if (err == -ENODEV)
+	if (!bcm->core_chipcommon)
+		goto out;
+
+	old_core = bcm->ssb.current_core;
+	err = ssb_switch_core(&bcm->ssb, bcm->core_chipcommon);
+	if (err)
 		goto out;
 
 	minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
-	pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
+	pll_on_delay = bcm43xx_read32(bcm, SSB_CHIPCOMMON_PLLONDELAY);
 	delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
 
-	err = bcm43xx_switch_core(bcm, old_core);
+	err = ssb_switch_core(&bcm->ssb, old_core);
 	assert(err == 0);
 
 out:
@@ -209,47 +213,48 @@
 int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
 {
 	int err;
-	struct bcm43xx_coreinfo *old_core;
+	struct ssb_core *old_core;
 	u32 tmp;
 
-	old_core = bcm->current_core;
-	err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-	if (err == -ENODEV)
+	if (!bcm->core_chipcommon)
 		return 0;
+
+	old_core = bcm->ssb.current_core;
+	err = ssb_switch_core(&bcm->ssb, bcm->core_chipcommon);
 	if (err)
 		goto out;
-	
-	if (bcm->core_chipcommon.rev < 6) {
+
+	if (bcm->core_chipcommon->rev < 6) {
 		if (mode == BCM43xx_PCTL_CLK_FAST) {
 			err = bcm43xx_pctl_set_crystal(bcm, 1);
 			if (err)
 				goto out;
 		}
 	} else {
-		if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
-			(bcm->core_chipcommon.rev < 10)) {
+		if ((bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL) &&
+		    (bcm->core_chipcommon->rev < 10)) {
 			switch (mode) {
 			case BCM43xx_PCTL_CLK_FAST:
-				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+				tmp = bcm43xx_read32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL);
 				tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
-				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+				bcm43xx_write32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL, tmp);
 				break;
 			case BCM43xx_PCTL_CLK_SLOW:
-				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+				tmp = bcm43xx_read32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL);
 				tmp |= BCM43xx_PCTL_FORCE_SLOW;
-				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+				bcm43xx_write32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL, tmp);
 				break;
 			case BCM43xx_PCTL_CLK_DYNAMIC:
-				tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
+				tmp = bcm43xx_read32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL);
 				tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
 				tmp |= BCM43xx_PCTL_FORCE_PLL;
 				tmp &= ~BCM43xx_PCTL_DYN_XTAL;
-				bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
+				bcm43xx_write32(bcm, SSB_CHIPCOMMON_SLOWCLKCTL, tmp);
 			}
 		}
 	}
 	
-	err = bcm43xx_switch_core(bcm, old_core);
+	err = ssb_switch_core(&bcm->ssb, old_core);
 	assert(err == 0);
 
 out:
@@ -261,6 +266,8 @@
 	int err;
 	u32 in, out, outenable;
 
+	might_sleep();
+
 	err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
 	if (err)
 		goto err_pci;
@@ -285,33 +292,34 @@
 		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
 		if (err)
 			goto err_pci;
-		udelay(1000);
+		msleep(1);
 
 		out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
 		err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
 		if (err)
 			goto err_pci;
-		udelay(5000);
+		msleep(5);
 	} else {
-		if (bcm->current_core->rev < 5)
+		if (!bcm->ssb.current_core)
+			return 0;
+		if (bcm->ssb.current_core->rev < 5)
 			return 0;
-		if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
+		if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_XTAL_NOSLOW)
 			return 0;
 
 /*		XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
  *		err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
  *		if (err)
  *			return err;
- *		if (((bcm->current_core->rev >= 3) &&
+ *		if (((bcm->ssb.current_core->rev >= 3) &&
  *			(bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
- *		      ((bcm->current_core->rev < 3) &&
+ *		      ((bcm->ssb.current_core->rev < 3) &&
  *			!(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
  *			return 0;
  *		err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
  *		if (err)
  *			return err;
  */
-		
 		err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
 		if (err)
 			goto out;
@@ -369,7 +377,7 @@
 	else
 		status &= ~BCM43xx_SBF_PS2;
 	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
-	if (bit26 && bcm->current_core->rev >= 5) {
+	if (bit26 && bcm->ssb.current_core->rev >= 5) {
 		for (i = 0; i < 100; i++) {
 			if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
 				break;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_radio.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_radio.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_radio.c	2006-08-23 10:58:41.000000000 +0200
@@ -791,7 +791,7 @@
 	case BCM43xx_PHYTYPE_B: {
 		if (radio->version != 0x2050)
 			return;
-		if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
+		if (!(bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI))
 			return;
 
 		if (radio->revision >= 6) {
@@ -819,7 +819,7 @@
 	}
 	case BCM43xx_PHYTYPE_G:
 		if (!phy->connected ||
-		    !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
+		    !(bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI)) {
 			tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
 			if (tmp16 >= 0x20)
 				tmp16 -= 0x40;
@@ -1661,7 +1661,7 @@
 				channel2freq_bg(channel));
 
 		if (channel == 14) {
-			if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
+			if (bcm->sprom.r1.country_code == SSB_SPROM1CCODE_JAPAN) {
 				bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
 						    BCM43xx_UCODEFLAGS_OFFSET,
 						    bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
@@ -1900,7 +1900,7 @@
 				else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
 					 bcm->board_type == 0x416)
 					att = 5;
-				else if (bcm->chip_id == 0x4320)
+				else if (bcm->ssb.chip_id == 0x4320)
 					att = 4;
 				else
 					att = 3;
@@ -1997,7 +1997,7 @@
 		bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
 		bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
 	}
-	if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
+	if (phy->type == BCM43xx_PHYTYPE_G && bcm->ssb.current_core->rev >= 5) {
 		bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
 		bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
 	} else
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/Kconfig
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/Kconfig	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/Kconfig	2006-08-23 10:58:41.000000000 +0200
@@ -2,6 +2,7 @@
 	tristate "Broadcom BCM43xx wireless support (DeviceScape stack)"
 	depends on PCI && D80211 && NET_RADIO && EXPERIMENTAL
 	select FW_LOADER
+	select SONICS_SILICON_BACKPLANE
 	---help---
 	  This is an experimental driver for the Broadcom 43xx wireless chip,
 	  found in the Apple Airport Extreme and various other devices.
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.h
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.h	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_debugfs.h	2006-08-23 10:58:41.000000000 +0200
@@ -17,7 +17,6 @@
 struct bcm43xx_dfsentry {
 	struct dentry *subdir;
 	struct dentry *dentry_devinfo;
-	struct dentry *dentry_spromdump;
 	struct dentry *dentry_tsf;
 	struct dentry *dentry_txstat;
 	struct dentry *dentry_restart;
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c	2006-08-23 10:58:41.000000000 +0200
@@ -133,10 +133,10 @@
 	u8 sprom[4];
 	int i;
 
-	sprom[0] = bcm->sprom.wl0gpio0;
-	sprom[1] = bcm->sprom.wl0gpio1;
-	sprom[2] = bcm->sprom.wl0gpio2;
-	sprom[3] = bcm->sprom.wl0gpio3;
+	sprom[0] = bcm->sprom.r1.gpio0;
+	sprom[1] = bcm->sprom.r1.gpio1;
+	sprom[2] = bcm->sprom.r1.gpio2;
+	sprom[3] = bcm->sprom.r1.gpio3;
 
 	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
 		led = &(bcm->leds[i]);
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c	2006-08-23 10:58:41.000000000 +0200
@@ -71,106 +71,6 @@
 	return -EINVAL;
 }
 
-static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
-{
-	int i, pos = 0;
-
-	for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-		pos += snprintf(buf + pos, buf_len - pos - 1,
-				"%04X", swab16(sprom[i]) & 0xFFFF);
-	}
-	pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
-
-	return pos + 1;
-}
-
-static int hex2sprom(u16 *sprom, const char *dump, size_t len)
-{
-	char tmp[5] = { 0 };
-	int cnt = 0;
-	unsigned long parsed;
-
-	if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
-		return -EINVAL;
-
-	while (cnt < BCM43xx_SPROM_SIZE) {
-		memcpy(tmp, dump, 4);
-		dump += 4;
-		parsed = simple_strtoul(tmp, NULL, 16);
-		sprom[cnt++] = swab16((u16)parsed);
-	}
-
-	return 0;
-}
-
-static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
-				       struct device_attribute *attr,
-				       char *buf)
-{
-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	u16 *sprom;
-	unsigned long flags;
-	int err;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
-			GFP_KERNEL);
-	if (!sprom)
-		return -ENOMEM;
-	mutex_lock(&bcm->mutex);
-	spin_lock_irqsave(&bcm->irq_lock, flags);
-	err = bcm43xx_sprom_read(bcm, sprom);
-	if (!err)
-		err = sprom2hex(sprom, buf, PAGE_SIZE);
-	mmiowb();
-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
-	mutex_unlock(&bcm->mutex);
-	kfree(sprom);
-
-	return err;
-}
-
-static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
-{
-	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	u16 *sprom;
-	unsigned long flags;
-	int err;
-
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
-			GFP_KERNEL);
-	if (!sprom)
-		return -ENOMEM;
-	err = hex2sprom(sprom, buf, count);
-	if (err)
-		goto out_kfree;
-	mutex_lock(&bcm->mutex);
-	spin_lock_irqsave(&bcm->irq_lock, flags);
-	spin_lock(&bcm->leds_lock);
-	err = bcm43xx_sprom_write(bcm, sprom);
-	mmiowb();
-	spin_unlock(&bcm->leds_lock);
-	spin_unlock_irqrestore(&bcm->irq_lock, flags);
-	mutex_unlock(&bcm->mutex);
-out_kfree:
-	kfree(sprom);
-
-	return err ? err : count;
-
-}
-
-static DEVICE_ATTR(sprom, 0600,
-		   bcm43xx_attr_sprom_show,
-		   bcm43xx_attr_sprom_store);
-
 static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
 					    struct device_attribute *attr,
 					    char *buf)
@@ -311,17 +211,14 @@
 
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
 {
-	struct device *dev = &bcm->pci_dev->dev;
+	struct device *dev = &bcm->ssb.pci_dev->dev;
 	int err;
 
 	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
 
-	err = device_create_file(dev, &dev_attr_sprom);
-	if (err)
-		goto out;
 	err = device_create_file(dev, &dev_attr_interference);
 	if (err)
-		goto err_remove_sprom;
+		goto out;
 	err = device_create_file(dev, &dev_attr_shortpreamble);
 	if (err)
 		goto err_remove_interfmode;
@@ -330,16 +227,13 @@
 	return err;
 err_remove_interfmode:
 	device_remove_file(dev, &dev_attr_interference);
-err_remove_sprom:
-	device_remove_file(dev, &dev_attr_sprom);
 	goto out;
 }
 
 void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
 {
-	struct device *dev = &bcm->pci_dev->dev;
+	struct device *dev = &bcm->ssb.pci_dev->dev;
 
 	device_remove_file(dev, &dev_attr_shortpreamble);
 	device_remove_file(dev, &dev_attr_interference);
-	device_remove_file(dev, &dev_attr_sprom);
 }
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c	2006-08-23 10:58:41.000000000 +0200
@@ -390,7 +390,7 @@
 			else
 				tmp -= 3;
 		} else {
-			if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
+			if (bcm->sprom.r1.boardflags_lo & BCM43xx_BFL_RSSI) {
 				if (in_rssi > 63)
 					in_rssi = 63;
 				tmp = radio->nrssi_lt[in_rssi];
Index: wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_ethtool.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/d80211/bcm43xx/bcm43xx_ethtool.c	2006-08-23 10:47:32.000000000 +0200
+++ wireless-dev/drivers/net/wireless/d80211/bcm43xx/bcm43xx_ethtool.c	2006-08-23 10:58:41.000000000 +0200
@@ -42,7 +42,7 @@
 
 	strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 	strncpy(info->version, UTS_RELEASE, sizeof(info->version));
-	strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
+	strncpy(info->bus_info, pci_name(bcm->ssb.pci_dev), ETHTOOL_BUSINFO_LEN);
 }
 
 struct ethtool_ops bcm43xx_ethtool_ops = {

-- 
Greetings Michael.