summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2009-11-11 10:17:10 -0800
committerDmitry Shmidt <dimitrysh@google.com>2009-11-11 10:18:20 -0800
commit492884be0b302c6c6ea51b360c1f7b0996d96a8b (patch)
treeb9801743b16763d2a2e3e11632329527c30bdc6f
parent22f9d1ad355474108432add8967729252cb85fdf (diff)
downloadwlan-492884be0b302c6c6ea51b360c1f7b0996d96a8b.tar.gz
bcm4329: Update to version 4.218.161 (b/2249878)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r--bcm4329/src/GNUmakefile.inc10
-rw-r--r--bcm4329/src/Makerules.env5
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh.c32
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_linux.c88
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c245
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c28
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdstd.c27
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmspibrcm.c1726
-rw-r--r--bcm4329/src/dhd/exe/GNUmakefile6
-rw-r--r--bcm4329/src/dhd/exe/dhdu.c21
-rw-r--r--bcm4329/src/dhd/linux/Makefile60
-rw-r--r--bcm4329/src/dhd/sys/dhd.h136
-rw-r--r--bcm4329/src/dhd/sys/dhd_cdc.c232
-rw-r--r--bcm4329/src/dhd/sys/dhd_common.c80
-rw-r--r--bcm4329/src/dhd/sys/dhd_custom_gpio.c239
-rw-r--r--bcm4329/src/dhd/sys/dhd_dbg.h1
-rw-r--r--bcm4329/src/dhd/sys/dhd_linux.c594
-rw-r--r--bcm4329/src/dhd/sys/dhd_sdio.c167
-rw-r--r--bcm4329/src/include/bcmcdc.h4
-rw-r--r--bcm4329/src/include/bcmdefs.h25
-rw-r--r--bcm4329/src/include/bcmdevs.h2
-rw-r--r--bcm4329/src/include/bcmsdbus.h7
-rw-r--r--bcm4329/src/include/bcmsdh.h7
-rw-r--r--bcm4329/src/include/bcmsdh_sdmmc.h3
-rw-r--r--bcm4329/src/include/bcmspibrcm.h134
-rw-r--r--bcm4329/src/include/bcmutils.h6
-rw-r--r--bcm4329/src/include/bcmwifi.h21
-rw-r--r--bcm4329/src/include/dhdioctl.h3
-rw-r--r--bcm4329/src/include/epivers.h10
-rw-r--r--bcm4329/src/include/epivers.h.in48
-rw-r--r--bcm4329/src/include/epivers.sh121
-rw-r--r--bcm4329/src/include/hndpmu.h2
-rw-r--r--bcm4329/src/include/linux_osl.h16
-rw-r--r--bcm4329/src/include/proto/802.11.h2
-rw-r--r--bcm4329/src/include/proto/bcmevent.h6
-rw-r--r--bcm4329/src/include/proto/ethernet.h28
-rw-r--r--bcm4329/src/include/sbchipc.h97
-rw-r--r--bcm4329/src/include/sbhnddma.h12
-rw-r--r--bcm4329/src/include/sdio.h20
-rw-r--r--bcm4329/src/include/sdioh.h6
-rw-r--r--bcm4329/src/include/siutils.h3
-rw-r--r--bcm4329/src/include/spid.h153
-rw-r--r--bcm4329/src/include/wlioctl.h51
-rw-r--r--bcm4329/src/shared/aiutils.c21
-rw-r--r--bcm4329/src/shared/bcmutils.c20
-rw-r--r--bcm4329/src/shared/bcmwifi.c4
-rw-r--r--bcm4329/src/shared/hndpmu.c4
-rw-r--r--bcm4329/src/shared/linux_osl.c206
-rw-r--r--bcm4329/src/shared/miniopt.c4
-rw-r--r--bcm4329/src/shared/sbutils.c5
-rw-r--r--bcm4329/src/shared/siutils.c21
-rw-r--r--bcm4329/src/shared/siutils_priv.h3
-rw-r--r--bcm4329/src/wl/sys/wl_iw.c705
-rw-r--r--bcm4329/src/wl/sys/wl_iw.h5
54 files changed, 2407 insertions, 3075 deletions
diff --git a/bcm4329/src/GNUmakefile.inc b/bcm4329/src/GNUmakefile.inc
index 3ca3bdd..ae08afe 100644
--- a/bcm4329/src/GNUmakefile.inc
+++ b/bcm4329/src/GNUmakefile.inc
@@ -4,7 +4,7 @@
# and sources(windows style makefile). it doesn't depend on
# Makerules.env except to get SRCBASE if not yet defined.
#
-# $Id: GNUmakefile.inc,v 1.103.50.1 2009/05/20 19:39:45 Exp $
+# $Id: GNUmakefile.inc,v 1.103.50.2 2009/08/18 18:42:30 Exp $
SHELL=bash
export SHELL
@@ -540,11 +540,15 @@ define calculate_dependencies
| sed '\''s?$*\.o[ :]*?$@ &?g'\'' >$@'
endef
+# OTHER_SOURCES_PROCESSED removes recursive build of OTHER_SOURCES, when that
+# switch is set from cmd line
ifdef OTHER_SOURCES
+ifndef OTHER_SOURCES_PROCESSED
all clean :: $(OTHER_SOURCES)
@echo "Go through OTHER_SOURCES: $(OTHER_SOURCES)"
- $(foreach SRCFILE,$(OTHER_SOURCES),$(MAKE) SRCFILE=$(SRCFILE) TTYPE=$(TTYPE) $@; )
-endif
+ $(foreach SRCFILE,$(OTHER_SOURCES),$(MAKE) SRCFILE=$(SRCFILE) TTYPE=$(TTYPE) OTHER_SOURCES_PROCESSED=true $@; )
+endif # OTHER_SOURCES_PROCESSED
+endif # OTHER_SOURCES
vpath %.Lib $(LIBVPATH)
vpath %.LIB $(LIBVPATH)
diff --git a/bcm4329/src/Makerules.env b/bcm4329/src/Makerules.env
index dbe4c39..189f053 100644
--- a/bcm4329/src/Makerules.env
+++ b/bcm4329/src/Makerules.env
@@ -59,7 +59,7 @@ endif
export TARGETENV
# TARGETOS defaults to HOSTOS in most cases
-ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "linuxarm" "linuxarm_le" "android" "linuxarm_omap" "linuxmips" "sun4" "cygwin32" "win32" "macos"), )
+ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "linuxarm" "linuxarm_le" "android" "linuxmips" "sun4" "cygwin32" "win32" "macos"), )
TARGETOS = $(HOSTOS)
endif
ifeq ($(TARGETENV), bcmmips)
@@ -91,9 +91,6 @@ ifndef TARGETARCH
ifneq ($(findstring "$(TARGETENV)", "linuxarm" "nucleusarm"), )
TARGETARCH = arm
endif
- ifneq ($(findstring "$(TARGETENV)", "linuxarm_omap"), )
- TARGETARCH = arm_omap
- endif
ifneq ($(findstring "$(TARGETENV)", "bcmmips" "linuxmips"), )
TARGETARCH = mips
endif
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh.c b/bcm4329/src/bcmsdio/sys/bcmsdh.c
index 68295ba..4c62610 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh.c,v 1.35.2.1.4.8.6.8 2009/06/09 00:58:13 Exp $
+ * $Id: bcmsdh.c,v 1.35.2.1.4.8.6.11 2009/10/20 09:48:20 Exp $
*/
/* ****************** BCMSDH Interface Functions *************************** */
@@ -55,6 +55,19 @@ struct bcmsdh_info
/* local copy of bcm sd handler */
bcmsdh_info_t * l_bcmsdh = NULL;
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+
+extern int
+sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
+
+void
+bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
+{
+ sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
+}
+
+#endif
+
bcmsdh_info_t *
bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq)
{
@@ -89,14 +102,11 @@ bcmsdh_detach(osl_t *osh, void *sdh)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
- ASSERT(bcmsdh);
-
- if (bcmsdh->sdioh) {
- sdioh_detach(osh, bcmsdh->sdioh);
- bcmsdh->sdioh = NULL;
- }
-
- if (bcmsdh) {
+ if (bcmsdh != NULL) {
+ if (bcmsdh->sdioh) {
+ sdioh_detach(osh, bcmsdh->sdioh);
+ bcmsdh->sdioh = NULL;
+ }
MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t));
}
@@ -288,7 +298,7 @@ bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length)
uint8 *tmp_buf, *tmp_ptr;
uint8 *ptr;
bool ascii = func & ~0xf;
- func &= 0xf;
+ func &= 0x7;
if (!bcmsdh)
bcmsdh = l_bcmsdh;
@@ -341,7 +351,7 @@ bcmsdh_reg_read(void *sdh, uint32 addr, uint size)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
SDIOH_API_RC status;
- uint32 word;
+ uint32 word = 0;
uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __FUNCTION__, addr));
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
index 81b15b6..8ddffc6 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_linux.c,v 1.42.10.10.2.6 2009/04/10 19:13:00 Exp $
+ * $Id: bcmsdh_linux.c,v 1.42.10.10.2.8 2009/10/15 22:48:28 Exp $
*/
/**
@@ -41,6 +41,13 @@
#include <bcmdefs.h>
#include <bcmdevs.h>
+#if defined(OOB_INTR_ONLY)
+#include <linux/irq.h>
+extern void dhdsdio_isr(void * args);
+#include <bcmutils.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#endif /* defined(OOB_INTR_ONLY) */
#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270)
#if !defined(BCMPLATFORM_BUS)
#define BCMPLATFORM_BUS
@@ -67,6 +74,7 @@ struct bcmsdh_hc {
void *regs; /* SDIO Host Controller address */
bcmsdh_info_t *sdh; /* SDIO Host Controller handle */
void *ch;
+ unsigned int oob_irq;
};
static bcmsdh_hc_t *sdhcinfo = NULL;
@@ -176,6 +184,13 @@ int bcmsdh_probe(struct device *dev)
return -ENXIO;
#endif /* BCMLXSDMMC */
+#if defined(OOB_INTR_ONLY)
+ irq = dhd_customer_oob_irq_map();
+ if (irq < 0) {
+ SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__));
+ return 1;
+ }
+#endif /* defined(OOB_INTR_ONLY) */
/* allocate SDIO Host Controller state info */
if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) {
SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
@@ -206,7 +221,11 @@ int bcmsdh_probe(struct device *dev)
}
#endif /* BCMLXSDMMC */
sdhc->sdh = sdh;
+ sdhc->oob_irq = irq;
+ /* chain SDIO Host Controller info together */
+ sdhc->next = sdhcinfo;
+ sdhcinfo = sdhc;
/* Read the vendor/device ID from the CIS */
vendevid = bcmsdh_query_device(sdh);
@@ -218,10 +237,6 @@ int bcmsdh_probe(struct device *dev)
goto err;
}
- /* chain SDIO Host Controller info together */
- sdhc->next = sdhcinfo;
- sdhcinfo = sdhc;
-
return 0;
/* error handling */
@@ -244,6 +259,9 @@ int bcmsdh_remove(struct device *dev)
bcmsdh_hc_t *sdhc, *prev;
osl_t *osh;
+ sdhc = sdhcinfo;
+ drvinfo.detach(sdhc->ch);
+ bcmsdh_detach(sdhc->osh, sdhc->sdh);
/* find the SDIO Host Controller state for this pdev and take it out from the list */
for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
if (sdhc->dev == (void *)dev) {
@@ -260,9 +278,6 @@ int bcmsdh_remove(struct device *dev)
return 0;
}
- drvinfo.detach(sdhc->ch);
-
- bcmsdh_detach(sdhc->osh, sdhc->sdh);
/* release SDIO Host Controller info */
osh = sdhc->osh;
@@ -516,6 +531,63 @@ bcmsdh_unregister(void)
#endif /* BCMPLATFORM_BUS */
}
+#if defined(OOB_INTR_ONLY)
+static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
+{
+ dhd_pub_t *dhdp;
+
+ dhdp = (dhd_pub_t *)sdhcinfo->dev->driver_data;
+
+ if (dhdp == NULL) {
+ disable_irq(sdhcinfo->oob_irq);
+ SDLX_MSG(("Out of band GPIO interrupt fired way too early\n"));
+ return IRQ_HANDLED;
+ }
+
+ WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
+
+ dhdsdio_isr((void *)dhdp->bus);
+
+ return IRQ_HANDLED;
+}
+
+int bcmsdh_register_oob_intr(void * dhdp)
+{
+ int error = 0;
+
+ SDLX_MSG(("%s Enter\n", __FUNCTION__));
+
+ sdhcinfo->dev->driver_data = dhdp;
+
+ set_irq_wake(sdhcinfo->oob_irq, 1);
+
+ /* Refer to customer Host IRQ docs about proper irqflags definition */
+ error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, IRQF_TRIGGER_FALLING,
+ "bcmsdh_sdmmc", NULL);
+
+ if (error)
+ return -ENODEV;
+
+ return 0;
+}
+
+void bcmsdh_unregister_oob_intr(void)
+{
+ SDLX_MSG(("%s: Enter\n", __FUNCTION__));
+
+ set_irq_wake(sdhcinfo->oob_irq, 0);
+ disable_irq(sdhcinfo->oob_irq); /* just in case.. */
+ free_irq(sdhcinfo->oob_irq, NULL);
+}
+
+void bcmsdh_oob_intr_set(bool enable)
+{
+ if (enable)
+ enable_irq(sdhcinfo->oob_irq);
+ else
+ disable_irq(sdhcinfo->oob_irq);
+}
+#endif /* defined(OOB_INTR_ONLY) */
/* Module parameters specific to each host-controller driver */
extern uint sd_msglevel; /* Debug message level */
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
index 9f75672..a13a35c 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc.c,v 1.1.2.5.6.19 2009/06/09 00:57:07 Exp $
+ * $Id: bcmsdh_sdmmc.c,v 1.1.2.5.6.27 2009/10/28 19:42:29 Exp $
*/
#include <typedefs.h>
@@ -35,10 +35,16 @@
#include <sdiovar.h> /* ioctl/iovars */
#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+#include <linux/suspend.h>
+extern volatile bool dhd_mmc_suspend;
+#endif
#include "bcmsdh_sdmmc.h"
#ifndef BCMSDH_MODULE
@@ -46,8 +52,10 @@ extern int sdio_function_init(void);
extern void sdio_function_cleanup(void);
#endif /* BCMSDH_MODULE */
+#if !defined(OOB_INTR_ONLY)
static void IRQHandler(struct sdio_func *func);
static void IRQHandlerF2(struct sdio_func *func);
+#endif
static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
extern int sdio_reset_comm(struct mmc_card *card);
@@ -63,22 +71,15 @@ uint sd_clock = 1; /* Default to SD Clock turned ON */
uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */
uint sd_msglevel = 0x01;
uint sd_use_dma = TRUE;
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait);
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait);
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait);
+DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait);
#define DMA_ALIGN_MASK 0x03
int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data);
-
-void SDIO_CLAIM_HOST(uint32 func)
-{
- sdio_claim_host(gInstance->func[func]);
-}
-
-void SDIO_RELEASE_HOST(uint32 func)
-{
- sdio_release_host(gInstance->func[func]);
-}
-
static int
sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
{
@@ -105,10 +106,9 @@ sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
/* Enable Function 1 */
- gInstance->host_claimed = 0;
- SDIO_CLAIM_HOST(1);
+ sdio_claim_host(gInstance->func[1]);
err_ret = sdio_enable_func(gInstance->func[1]);
- SDIO_RELEASE_HOST(1);
+ sdio_release_host(gInstance->func[1]);
if (err_ret) {
sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret));
}
@@ -152,7 +152,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
gInstance->sd = sd;
/* Claim host controller */
- SDIO_CLAIM_HOST(1);
+ sdio_claim_host(gInstance->func[1]);
sd->client_block_size[1] = 64;
err_ret = sdio_set_block_size(gInstance->func[1], 64);
@@ -161,11 +161,11 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
}
/* Release host controller F1 */
- SDIO_RELEASE_HOST(1);
+ sdio_release_host(gInstance->func[1]);
if (gInstance->func[2]) {
/* Claim host controller F2 */
- SDIO_CLAIM_HOST(2);
+ sdio_claim_host(gInstance->func[2]);
sd->client_block_size[2] = sd_f2_blocksize;
err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
@@ -175,7 +175,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
}
/* Release host controller F2 */
- SDIO_RELEASE_HOST(2);
+ sdio_release_host(gInstance->func[2]);
}
sdioh_sdmmc_card_enablefuncs(sd);
@@ -193,14 +193,14 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd)
if (sd) {
/* Disable Function 2 */
- SDIO_CLAIM_HOST(2);
+ sdio_claim_host(gInstance->func[2]);
sdio_disable_func(gInstance->func[2]);
- SDIO_RELEASE_HOST(2);
+ sdio_release_host(gInstance->func[2]);
/* Disable Function 1 */
- SDIO_CLAIM_HOST(1);
+ sdio_claim_host(gInstance->func[1]);
sdio_disable_func(gInstance->func[1]);
- SDIO_RELEASE_HOST(1);
+ sdio_release_host(gInstance->func[1]);
/* deregister irq */
sdioh_sdmmc_osfree(sd);
@@ -210,6 +210,67 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd)
return SDIOH_API_RC_SUCCESS;
}
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+#define _SDIO_CCCR_IENx 0x04 /* Function/Master Interrupt Enable */
+
+extern SDIOH_API_RC
+sdioh_enable_func_intr(uint32 func)
+{
+ uint8 reg;
+ int err;
+
+ if (gInstance->func[0]) {
+ sdio_claim_host(gInstance->func[0]);
+ reg = sdio_readb(gInstance->func[0], _SDIO_CCCR_IENx, &err);
+ if (err) {
+ sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ sdio_release_host(gInstance->func[0]);
+ return SDIOH_API_RC_FAIL;
+ }
+ reg |= 1 << func; /* enable function-x interrupt */
+ reg |= 1; /* Master interrupt enable */
+ sdio_writeb(gInstance->func[0], reg, _SDIO_CCCR_IENx, &err);
+ sdio_release_host(gInstance->func[0]);
+ if (err) {
+ sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ return SDIOH_API_RC_FAIL;
+ }
+ }
+
+ return SDIOH_API_RC_SUCCESS;
+
+}
+
+extern SDIOH_API_RC
+sdioh_disable_func_intr(uint32 func)
+{
+ uint8 reg;
+ int err;
+
+ if (gInstance->func[0]) {
+ sdio_claim_host(gInstance->func[0]);
+ reg = sdio_readb(gInstance->func[0], _SDIO_CCCR_IENx, &err);
+ if (err) {
+ sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ sdio_release_host(gInstance->func[0]);
+ return SDIOH_API_RC_FAIL;
+ }
+ reg &= ~(1 << func);
+ /* Disable master interrupt with the last function interrupt */
+ if (!(reg & 0xFE))
+ reg = 0;
+ sdio_writeb(gInstance->func[0], reg, _SDIO_CCCR_IENx, &err);
+ sdio_release_host(gInstance->func[0]);
+ if (err) {
+ sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
+ return SDIOH_API_RC_FAIL;
+ }
+ }
+ return SDIOH_API_RC_SUCCESS;
+
+}
+#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+
/* Configure callback to client when we recieve client interrupt */
extern SDIOH_API_RC
sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
@@ -219,22 +280,26 @@ sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__));
return SDIOH_API_RC_FAIL;
}
+#if !defined(OOB_INTR_ONLY)
sd->intr_handler = fn;
sd->intr_handler_arg = argh;
sd->intr_handler_valid = TRUE;
/* register and unmask irq */
if (gInstance->func[2]) {
- SDIO_CLAIM_HOST(2);
+ sdio_claim_host(gInstance->func[2]);
sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
- SDIO_RELEASE_HOST(2);
+ sdio_release_host(gInstance->func[2]);
}
if (gInstance->func[1]) {
- SDIO_CLAIM_HOST(1);
+ sdio_claim_host(gInstance->func[1]);
sdio_claim_irq(gInstance->func[1], IRQHandler);
- SDIO_RELEASE_HOST(1);
+ sdio_release_host(gInstance->func[1]);
}
+#elif defined(HW_OOB)
+ sdioh_enable_func_intr(2);
+#endif /* defined(OOB_INTR_ONLY) */
return SDIOH_API_RC_SUCCESS;
}
@@ -243,24 +308,28 @@ sdioh_interrupt_deregister(sdioh_info_t *sd)
{
sd_trace(("%s: Entering\n", __FUNCTION__));
+#if !defined(OOB_INTR_ONLY)
if (gInstance->func[1]) {
/* register and unmask irq */
- SDIO_CLAIM_HOST(1);
+ sdio_claim_host(gInstance->func[1]);
sdio_release_irq(gInstance->func[1]);
- SDIO_RELEASE_HOST(1);
+ sdio_release_host(gInstance->func[1]);
}
if (gInstance->func[2]) {
/* Claim host controller F2 */
- SDIO_CLAIM_HOST(2);
+ sdio_claim_host(gInstance->func[2]);
sdio_release_irq(gInstance->func[2]);
/* Release host controller F2 */
- SDIO_RELEASE_HOST(2);
+ sdio_release_host(gInstance->func[2]);
}
sd->intr_handler_valid = FALSE;
sd->intr_handler = NULL;
sd->intr_handler_arg = NULL;
+#elif defined(HW_OOB)
+ sdioh_disable_func_intr(2);
+#endif /* !defined(OOB_INTR_ONLY) */
return SDIOH_API_RC_SUCCESS;
}
@@ -591,6 +660,25 @@ exit:
return bcmerror;
}
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+
+SDIOH_API_RC
+sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
+{
+ SDIOH_API_RC status;
+ uint8 data;
+
+ if (enable)
+ data = 3; /* enable hw oob interrupt */
+ else
+ data = 4; /* disable hw oob interrupt */
+
+ status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data);
+ return status;
+}
+#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
+
+
extern SDIOH_API_RC
sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
{
@@ -669,6 +757,8 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr));
+ DHD_PM_RESUME_WAIT(sdioh_request_byte_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
if(rw) { /* CMD52 Write */
if (func == 0) {
/* Can only directly write to some F0 registers. Handle F2 enable
@@ -676,7 +766,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
*/
if (regaddr == SDIOD_CCCR_IOEN) {
if (gInstance->func[2]) {
- SDIO_CLAIM_HOST(2);
+ sdio_claim_host(gInstance->func[2]);
if (*byte & SDIO_FUNC_ENABLE_2) {
/* Enable Function 2 */
err_ret = sdio_enable_func(gInstance->func[2]);
@@ -692,25 +782,40 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
err_ret));
}
}
- SDIO_RELEASE_HOST(2);
+ sdio_release_host(gInstance->func[2]);
}
- } else if (regaddr < 0xF0) {
+ }
+#if defined(MMC_SDIO_ABORT)
+ /* to allow abort command through F1 */
+ else if (regaddr == SDIOD_CCCR_IOABORT) {
+ sdio_claim_host(gInstance->func[func]);
+ /*
+ * this sdio_f0_writeb() can be replaced with another api
+ * depending upon MMC driver change.
+ * As of this time, this is temporaray one
+ */
+ sdio_f0_writeb(gInstance->func[func], *byte,
+ regaddr, &err_ret);
+ sdio_release_host(gInstance->func[func]);
+ }
+#endif /* MMC_SDIO_ABORT */
+ else if (regaddr < 0xF0) {
sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
} else {
/* Claim host controller, perform F0 write, and release */
- SDIO_CLAIM_HOST(func);
+ sdio_claim_host(gInstance->func[func]);
sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
- SDIO_RELEASE_HOST(func);
+ sdio_release_host(gInstance->func[func]);
}
} else {
/* Claim host controller, perform Fn write, and release */
- SDIO_CLAIM_HOST(func);
+ sdio_claim_host(gInstance->func[func]);
sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
- SDIO_RELEASE_HOST(func);
+ sdio_release_host(gInstance->func[func]);
}
} else { /* CMD52 Read */
/* Claim host controller, perform Fn read, and release */
- SDIO_CLAIM_HOST(func);
+ sdio_claim_host(gInstance->func[func]);
if (func == 0) {
*byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
@@ -718,7 +823,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
*byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
}
- SDIO_RELEASE_HOST(func);
+ sdio_release_host(gInstance->func[func]);
}
if (err_ret) {
@@ -733,7 +838,7 @@ extern SDIOH_API_RC
sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
uint32 *word, uint nbytes)
{
- int err_ret;
+ int err_ret = SDIOH_API_RC_FAIL;
if (func == 0) {
sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__));
@@ -743,8 +848,10 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add
sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
__FUNCTION__, cmd_type, rw, func, addr, nbytes));
+ DHD_PM_RESUME_WAIT(sdioh_request_word_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
/* Claim host controller */
- SDIO_CLAIM_HOST(func);
+ sdio_claim_host(gInstance->func[func]);
if(rw) { /* CMD52 Write */
if (nbytes == 4) {
@@ -765,7 +872,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add
}
/* Release host controller */
- SDIO_RELEASE_HOST(func);
+ sdio_release_host(gInstance->func[func]);
if (err_ret) {
sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
@@ -788,9 +895,11 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
sd_trace(("%s: Enter\n", __FUNCTION__));
ASSERT(pkt);
+ DHD_PM_RESUME_WAIT(sdioh_request_packet_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
/* Claim host controller */
- SDIO_CLAIM_HOST(func);
+ sdio_claim_host(gInstance->func[func]);
for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
uint pkt_len = PKTLEN(sd->osh, pnext);
pkt_len += 3;
@@ -848,7 +957,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
}
/* Release host controller */
- SDIO_RELEASE_HOST(func);
+ sdio_release_host(gInstance->func[func]);
sd_trace(("%s: Exit\n", __FUNCTION__));
return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
@@ -875,11 +984,17 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
sd_trace(("%s: Enter\n", __FUNCTION__));
+ DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait);
+ DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL);
/* Case 1: we don't have a packet. */
if (pkt == NULL) {
sd_data(("%s: Creating new %s Packet, len=%d\n",
__FUNCTION__, write ? "TX" : "RX", buflen_u));
+#ifdef DHD_USE_STATIC_BUF
+ if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) {
+#else
if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) {
+#endif /* DHD_USE_STATIC_BUF */
sd_err(("%s: PKTGET failed: len %d\n",
__FUNCTION__, buflen_u));
return SDIOH_API_RC_FAIL;
@@ -896,8 +1011,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
if (!write) {
bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u);
}
-
+#ifdef DHD_USE_STATIC_BUF
+ PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE);
+#else
PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE);
+#endif /* DHD_USE_STATIC_BUF */
} else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) {
/* Case 2: We have a packet, but it is unaligned. */
@@ -906,7 +1024,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
sd_data(("%s: Creating aligned %s Packet, len=%d\n",
__FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt)));
+#ifdef DHD_USE_STATIC_BUF
+ if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) {
+#else
if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) {
+#endif /* DHD_USE_STATIC_BUF */
sd_err(("%s: PKTGET failed: len %d\n",
__FUNCTION__, PKTLEN(sd->osh, pkt)));
return SDIOH_API_RC_FAIL;
@@ -927,8 +1049,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
PKTDATA(sd->osh, pkt),
PKTLEN(sd->osh, mypkt));
}
-
+#ifdef DHD_USE_STATIC_BUF
+ PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE);
+#else
PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE);
+#endif /* DHD_USE_STATIC_BUF */
} else { /* case 3: We have a packet and it is aligned. */
sd_data(("%s: Aligned %s Packet, direct DMA\n",
__FUNCTION__, write ? "Tx" : "Rx"));
@@ -943,6 +1068,10 @@ sdioh_abort(sdioh_info_t *sd, uint func)
{
sd_trace(("%s: Enter\n", __FUNCTION__));
+#if defined(MMC_SDIO_ABORT)
+ /* issue abort cmd52 command through F1 */
+ sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func);
+#endif /* defined(MMC_SDIO_ABORT) */
sd_trace(("%s: Exit\n", __FUNCTION__));
return SDIOH_API_RC_SUCCESS;
@@ -997,6 +1126,7 @@ sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize
return SUCCESS;
}
+#if !defined(OOB_INTR_ONLY)
/* bcmsdh_sdmmc interrupt handler */
static void IRQHandler(struct sdio_func *func)
{
@@ -1007,7 +1137,7 @@ static void IRQHandler(struct sdio_func *func)
ASSERT(sd != NULL);
sdio_release_host(gInstance->func[0]);
- gInstance->host_claimed = 1;
+
if (sd->use_client_ints) {
sd->intrcount++;
ASSERT(sd->intr_handler);
@@ -1019,7 +1149,6 @@ static void IRQHandler(struct sdio_func *func)
sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
__FUNCTION__, sd->client_intr_enabled, sd->intr_handler));
}
- gInstance->host_claimed = 0;
sdio_claim_host(gInstance->func[0]);
}
@@ -1035,6 +1164,7 @@ static void IRQHandlerF2(struct sdio_func *func)
ASSERT(sd != NULL);
}
+#endif /* !defined(OOB_INTR_ONLY) */
#ifdef NOTUSED
/* Write client card reg */
@@ -1121,11 +1251,17 @@ sdioh_start(sdioh_info_t *si, int stage)
sdioh_sdmmc_card_enablefuncs(sd);
}
} else {
+#if !defined(OOB_INTR_ONLY)
sdio_claim_host(gInstance->func[0]);
sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
sdio_claim_irq(gInstance->func[1], IRQHandler);
sdio_release_host(gInstance->func[0]);
-
+#else /* defined(OOB_INTR_ONLY) */
+#if defined(HW_OOB)
+ sdioh_enable_func_intr(2);
+#endif
+ bcmsdh_oob_intr_set(TRUE);
+#endif /* !defined(OOB_INTR_ONLY) */
}
}
else
@@ -1144,10 +1280,17 @@ sdioh_stop(sdioh_info_t *si)
polling
*/
if (gInstance->func[0]) {
+#if !defined(OOB_INTR_ONLY)
sdio_claim_host(gInstance->func[0]);
sdio_release_irq(gInstance->func[1]);
sdio_release_irq(gInstance->func[2]);
sdio_release_host(gInstance->func[0]);
+#else /* defined(OOB_INTR_ONLY) */
+#if defined(HW_OOB)
+ sdioh_disable_func_intr(2);
+#endif
+ bcmsdh_oob_intr_set(FALSE);
+#endif /* !defined(OOB_INTR_ONLY) */
}
else
sd_err(("%s Failed\n", __FUNCTION__));
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
index 46fe1f9..3643d1c 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.6.7 2009/05/22 00:31:44 Exp $
+ * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.6.10 2009/10/14 04:32:13 Exp $
*/
#include <typedefs.h>
@@ -49,6 +49,9 @@
#include <bcmsdh_sdmmc.h>
+#include <dhd_dbg.h>
+
+
extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
@@ -73,6 +76,7 @@ extern int bcmsdh_probe(struct device *dev);
extern int bcmsdh_remove(struct device *dev);
struct device sdmmc_dev;
+
static int bcmsdh_sdmmc_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
@@ -89,7 +93,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
if(func->device == 0x4) { /* 4318 */
gInstance->func[2] = NULL;
sd_trace(("NIC found, calling bcmsdh_probe...\n"));
- bcmsdh_probe(&sdmmc_dev);
+ ret = bcmsdh_probe(&sdmmc_dev);
}
}
@@ -97,7 +101,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
if (func->num == 2) {
sd_trace(("F2 found, calling bcmsdh_probe...\n"));
- bcmsdh_probe(&sdmmc_dev);
+ ret = bcmsdh_probe(&sdmmc_dev);
}
return ret;
@@ -165,6 +169,13 @@ sdioh_sdmmc_osfree(sdioh_info_t *sd)
sdos = (struct sdos_info *)sd->sdos_info;
MFREE(sd->osh, sdos, sizeof(struct sdos_info));
}
+#if defined(OOB_INTR_ONLY)
+int
+sdioh_mmc_irq(int irq)
+{
+ return (MSM_GPIO_TO_INT(irq));
+}
+#endif /* defined(OOB_INTR_ONLY) */
/* Interrupt enable/disable */
SDIOH_API_RC
@@ -178,19 +189,22 @@ sdioh_interrupt_set(sdioh_info_t *sd, bool enable)
sdos = (struct sdos_info *)sd->sdos_info;
ASSERT(sdos);
+#if !defined(OOB_INTR_ONLY)
if (enable && !(sd->intr_handler && sd->intr_handler_arg)) {
sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__));
return SDIOH_API_RC_FAIL;
}
+#endif /* !defined(OOB_INTR_ONLY) */
/* Ensure atomicity for enable/disable calls */
spin_lock_irqsave(&sdos->lock, flags);
sd->client_intr_enabled = enable;
- if (enable)
+ if (enable) {
sdioh_sdmmc_devintr_on(sd);
- else
+ } else {
sdioh_sdmmc_devintr_off(sd);
+ }
spin_unlock_irqrestore(&sdos->lock, flags);
@@ -233,7 +247,10 @@ int sdio_function_init(void)
if (!gInstance)
return -ENOMEM;
+ bzero(&sdmmc_dev, sizeof(sdmmc_dev));
error = sdio_register_driver(&bcmsdh_sdmmc_driver);
+
+
return error;
}
@@ -245,6 +262,7 @@ void sdio_function_cleanup(void)
{
sd_trace(("%s Enter\n", __FUNCTION__));
+
sdio_unregister_driver(&bcmsdh_sdmmc_driver);
if (gInstance)
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdstd.c b/bcm4329/src/bcmsdio/sys/bcmsdstd.c
index 2665716..51ff4af 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdstd.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdstd.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdstd.c,v 1.64.4.1.4.4.2.10 2009/05/22 00:31:44 Exp $
+ * $Id: bcmsdstd.c,v 1.64.4.1.4.4.2.14 2009/10/08 20:05:30 Exp $
*/
#include <typedefs.h>
@@ -35,7 +35,6 @@
#include <sdioh.h> /* SDIO Host Controller Specification */
#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
#include <sdiovar.h> /* ioctl/iovars */
-
#include <pcicfg.h>
@@ -853,9 +852,10 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint
len++;
tmpbuf = buffer;
if ((localbuf = (uint8 *)MALLOC(sd->osh, len)) == NULL) {
- sd_err(("out of memory, malloced %d bytes\n",
- MALLOCED(sd->osh)));
- return SDIOH_API_RC_FAIL;
+ sd_err(("out of memory, malloced %d bytes\n",
+ MALLOCED(sd->osh)));
+ sdstd_unlock(sd);
+ return SDIOH_API_RC_FAIL;
}
bcopy(buffer, localbuf, len);
buffer = localbuf;
@@ -1313,6 +1313,20 @@ sdstd_host_init(sdioh_info_t *sd)
num_slots &= 7;
num_slots++; /* map bits to num slots according to spec */
+ if (OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) ==
+ ((SDIOH_FPGA_ID << 16) | VENDOR_BROADCOM)) {
+ sd_err(("%s: Found Broadcom Standard SDIO Host Controller FPGA\n", __FUNCTION__));
+ /* Set BAR0 Window to SDIOSTH core */
+ OSL_PCI_WRITE_CONFIG(sd->osh, PCI_BAR0_WIN, 4, 0x18001000);
+
+ /* Set defaults particular to this controller. */
+ detect_slots = TRUE;
+ num_slots = 1;
+ first_bar = 0;
+
+ sd->sd_blockmode = FALSE;
+ }
+
/* Map in each slot on the board and query it to see if a
* card is inserted. Use the first populated slot found.
*/
@@ -2781,7 +2795,8 @@ sd_map_dma(sdioh_info_t * sd)
{
if (sd->sd_use_dma == FALSE)
return;
- if ((sd->dma_buf = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE, &sd->dma_phys, 0x12)) == NULL) {
+ if ((sd->dma_buf = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE, &sd->dma_phys,
+ 0x12, 12)) == NULL) {
sd_err(("%s: DMA_ALLOC failed. Disabling DMA support.\n", __FUNCTION__));
sd->sd_use_dma = FALSE;
}
diff --git a/bcm4329/src/bcmsdio/sys/bcmspibrcm.c b/bcm4329/src/bcmsdio/sys/bcmspibrcm.c
deleted file mode 100644
index dc6f0f5..0000000
--- a/bcm4329/src/bcmsdio/sys/bcmspibrcm.c
+++ /dev/null
@@ -1,1726 +0,0 @@
-/*
- * Broadcom BCMSDH to gSPI Protocol Conversion Layer
- *
- * Copyright (C) 2009, Broadcom Corporation
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
- * the contents of this file may not be disclosed to third parties, copied
- * or duplicated in any form, in whole or in part, without the prior
- * written permission of Broadcom Corporation.
- *
- * $Id: bcmspibrcm.c,v 1.11.2.10.2.9.6.11 2009/05/21 13:21:57 Exp $
- */
-
-#define HSMODE
-
-#include <typedefs.h>
-
-#include <bcmdevs.h>
-#include <bcmendian.h>
-#include <bcmutils.h>
-#include <osl.h>
-#include <hndsoc.h>
-#include <siutils.h>
-#include <sbchipc.h>
-#include <sbsdio.h>
-#include <spid.h>
-
-#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */
-#include <sdiovar.h> /* ioctl/iovars */
-#include <sdio.h>
-
-#include <pcicfg.h>
-
-
-#include <bcmspibrcm.h>
-#include <bcmspi.h>
-
-#define F0_RESPONSE_DELAY 16
-#define F1_RESPONSE_DELAY 16
-#define F2_RESPONSE_DELAY F0_RESPONSE_DELAY
-
-#define CMDLEN 4
-
-#define DWORDMODE_ON (sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 2) && (sd->dwordmode == TRUE)
-
-/* Globals */
-uint sd_msglevel = 0;
-
-uint sd_hiok = FALSE; /* Use hi-speed mode if available? */
-uint sd_sdmode = SDIOH_MODE_SPI; /* Use SD4 mode by default */
-uint sd_f2_blocksize = 64; /* Default blocksize */
-
-
-uint sd_divisor = 2;
-uint sd_power = 1; /* Default to SD Slot powered ON */
-uint sd_clock = 1; /* Default to SD Clock turned ON */
-uint sd_crc = 0; /* Default to SPI CRC Check turned OFF */
-
-uint8 spi_outbuf[SPI_MAX_PKT_LEN];
-uint8 spi_inbuf[SPI_MAX_PKT_LEN];
-
-/* 128bytes buffer is enough to clear data-not-available and program response-delay F0 bits
- * assuming we will not exceed F0 response delay > 100 bytes at 48MHz.
- */
-#define BUF2_PKT_LEN 128
-uint8 spi_outbuf2[BUF2_PKT_LEN];
-uint8 spi_inbuf2[BUF2_PKT_LEN];
-
-/* Prototypes */
-static bool bcmspi_test_card(sdioh_info_t *sd);
-static bool bcmspi_host_device_init_adapt(sdioh_info_t *sd);
-static int bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode);
-static int bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
- uint32 *data, uint32 datalen);
-static int bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr,
- int regsize, uint32 *data);
-static int bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr,
- int regsize, uint32 data);
-static int bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr,
- uint8 *data);
-static int bcmspi_driver_init(sdioh_info_t *sd);
-static int bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
- uint32 addr, int nbytes, uint32 *data);
-static int bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize,
- uint32 *data);
-static void bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer);
-static int bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg);
-
-/*
- * Public entry points & extern's
- */
-extern sdioh_info_t *
-sdioh_attach(osl_t *osh, void *bar0, uint irq)
-{
- sdioh_info_t *sd;
-
- sd_trace(("%s\n", __FUNCTION__));
- if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
- sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh)));
- return NULL;
- }
- bzero((char *)sd, sizeof(sdioh_info_t));
- sd->osh = osh;
- if (spi_osinit(sd) != 0) {
- sd_err(("%s: spi_osinit() failed\n", __FUNCTION__));
- MFREE(sd->osh, sd, sizeof(sdioh_info_t));
- return NULL;
- }
-
- sd->bar0 = bar0;
- sd->irq = irq;
- sd->intr_handler = NULL;
- sd->intr_handler_arg = NULL;
- sd->intr_handler_valid = FALSE;
-
- /* Set defaults */
- sd->use_client_ints = TRUE;
- sd->sd_use_dma = FALSE; /* DMA Not supported */
-
- /* Spi device default is 16bit mode, change to 4 when device is changed to 32bit
- * mode
- */
- sd->wordlen = 2;
-
- if (!spi_hw_attach(sd)) {
- sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__));
- spi_osfree(sd);
- MFREE(sd->osh, sd, sizeof(sdioh_info_t));
- return (NULL);
- }
-
- if (bcmspi_driver_init(sd) != SUCCESS) {
- sd_err(("%s: bcmspi_driver_init() failed()\n", __FUNCTION__));
- spi_hw_detach(sd);
- spi_osfree(sd);
- MFREE(sd->osh, sd, sizeof(sdioh_info_t));
- return (NULL);
- }
-
- if (spi_register_irq(sd, irq) != SUCCESS) {
- sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq));
- spi_hw_detach(sd);
- spi_osfree(sd);
- MFREE(sd->osh, sd, sizeof(sdioh_info_t));
- return (NULL);
- }
-
- sd_trace(("%s: Done\n", __FUNCTION__));
-
- return sd;
-}
-
-extern SDIOH_API_RC
-sdioh_detach(osl_t *osh, sdioh_info_t *sd)
-{
- sd_trace(("%s\n", __FUNCTION__));
- if (sd) {
- sd_err(("%s: detaching from hardware\n", __FUNCTION__));
- spi_free_irq(sd->irq, sd);
- spi_hw_detach(sd);
- spi_osfree(sd);
- MFREE(sd->osh, sd, sizeof(sdioh_info_t));
- }
- return SDIOH_API_RC_SUCCESS;
-}
-
-/* Configure callback to client when we recieve client interrupt */
-extern SDIOH_API_RC
-sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
-{
- sd_trace(("%s: Entering\n", __FUNCTION__));
- sd->intr_handler = fn;
- sd->intr_handler_arg = argh;
- sd->intr_handler_valid = TRUE;
- return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_interrupt_deregister(sdioh_info_t *sd)
-{
- sd_trace(("%s: Entering\n", __FUNCTION__));
- sd->intr_handler_valid = FALSE;
- sd->intr_handler = NULL;
- sd->intr_handler_arg = NULL;
- return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
-{
- sd_trace(("%s: Entering\n", __FUNCTION__));
- *onoff = sd->client_intr_enabled;
- return SDIOH_API_RC_SUCCESS;
-}
-
-#if defined(DHD_DEBUG)
-extern bool
-sdioh_interrupt_pending(sdioh_info_t *sd)
-{
- return 0;
-}
-#endif
-
-extern SDIOH_API_RC
-sdioh_query_device(sdioh_info_t *sd)
-{
- /* Return a BRCM ID appropriate to the dongle class */
- return (sd->num_funcs > 1) ? BCM4329_D11NDUAL_ID : BCM4318_D11G_ID;
-}
-
-/* Provide dstatus bits of spi-transaction for dhd layers. */
-extern uint32
-sdioh_get_dstatus(sdioh_info_t *sd)
-{
- return sd->card_dstatus;
-}
-
-extern void
-sdioh_chipinfo(sdioh_info_t *sd, uint32 chip, uint32 chiprev)
-{
- sd->chip = chip;
- sd->chiprev = chiprev;
-}
-
-extern void
-sdioh_dwordmode(sdioh_info_t *sd, bool set)
-{
- uint8 reg = 0;
- int status;
-
- if ((status = sdioh_request_byte(sd, SDIOH_READ, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
- SUCCESS) {
- sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
- return;
- }
-
- if (set) {
- reg |= DWORD_PKT_LEN_EN;
- sd->dwordmode = TRUE;
- sd->client_block_size[SPI_FUNC_2] = 4096; /* h2spi's limit is 4KB, we support 8KB */
- } else {
- reg &= ~DWORD_PKT_LEN_EN;
- sd->dwordmode = FALSE;
- sd->client_block_size[SPI_FUNC_2] = 2048;
- }
-
- if ((status = sdioh_request_byte(sd, SDIOH_WRITE, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
- SUCCESS) {
- sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
- return;
- }
-}
-
-
-uint
-sdioh_query_iofnum(sdioh_info_t *sd)
-{
- return sd->num_funcs;
-}
-
-/* IOVar table */
-enum {
- IOV_MSGLEVEL = 1,
- IOV_BLOCKMODE,
- IOV_BLOCKSIZE,
- IOV_DMA,
- IOV_USEINTS,
- IOV_NUMINTS,
- IOV_NUMLOCALINTS,
- IOV_HOSTREG,
- IOV_DEVREG,
- IOV_DIVISOR,
- IOV_SDMODE,
- IOV_HISPEED,
- IOV_HCIREGS,
- IOV_POWER,
- IOV_CLOCK,
- IOV_SPIERRSTATS,
- IOV_RESP_DELAY_ALL
-};
-
-const bcm_iovar_t sdioh_iovars[] = {
- {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
- {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */
- {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 },
- {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 },
- {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 },
- {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 },
- {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
- {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
- {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 },
- {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 },
- {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 },
- {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100},
- {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0},
- {"spi_errstats", IOV_SPIERRSTATS, 0, IOVT_BUFFER, sizeof(struct spierrstats_t) },
- {"spi_respdelay", IOV_RESP_DELAY_ALL, 0, IOVT_BOOL, 0 },
- {NULL, 0, 0, 0, 0 }
-};
-
-int
-sdioh_iovar_op(sdioh_info_t *si, const char *name,
- void *params, int plen, void *arg, int len, bool set)
-{
- const bcm_iovar_t *vi = NULL;
- int bcmerror = 0;
- int val_size;
- int32 int_val = 0;
- bool bool_val;
- uint32 actionid;
-/*
- sdioh_regs_t *regs;
-*/
-
- ASSERT(name);
- ASSERT(len >= 0);
-
- /* Get must have return space; Set does not take qualifiers */
- ASSERT(set || (arg && len));
- ASSERT(!set || (!params && !plen));
-
- sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
-
- if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
- bcmerror = BCME_UNSUPPORTED;
- goto exit;
- }
-
- if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
- goto exit;
-
- /* Set up params so get and set can share the convenience variables */
- if (params == NULL) {
- params = arg;
- plen = len;
- }
-
- if (vi->type == IOVT_VOID)
- val_size = 0;
- else if (vi->type == IOVT_BUFFER)
- val_size = len;
- else
- val_size = sizeof(int);
-
- if (plen >= (int)sizeof(int_val))
- bcopy(params, &int_val, sizeof(int_val));
-
- bool_val = (int_val != 0) ? TRUE : FALSE;
-
- actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
- switch (actionid) {
- case IOV_GVAL(IOV_MSGLEVEL):
- int_val = (int32)sd_msglevel;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_MSGLEVEL):
- sd_msglevel = int_val;
- break;
-
- case IOV_GVAL(IOV_BLOCKSIZE):
- if ((uint32)int_val > si->num_funcs) {
- bcmerror = BCME_BADARG;
- break;
- }
- int_val = (int32)si->client_block_size[int_val];
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_GVAL(IOV_DMA):
- int_val = (int32)si->sd_use_dma;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_DMA):
- si->sd_use_dma = (bool)int_val;
- break;
-
- case IOV_GVAL(IOV_USEINTS):
- int_val = (int32)si->use_client_ints;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_USEINTS):
- break;
-
- case IOV_GVAL(IOV_DIVISOR):
- int_val = (uint32)sd_divisor;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_DIVISOR):
- sd_divisor = int_val;
- if (!spi_start_clock(si, (uint16)sd_divisor)) {
- sd_err(("%s: set clock failed\n", __FUNCTION__));
- bcmerror = BCME_ERROR;
- }
- break;
-
- case IOV_GVAL(IOV_POWER):
- int_val = (uint32)sd_power;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_POWER):
- sd_power = int_val;
- break;
-
- case IOV_GVAL(IOV_CLOCK):
- int_val = (uint32)sd_clock;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_CLOCK):
- sd_clock = int_val;
- break;
-
- case IOV_GVAL(IOV_SDMODE):
- int_val = (uint32)sd_sdmode;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_SDMODE):
- sd_sdmode = int_val;
- break;
-
- case IOV_GVAL(IOV_HISPEED):
- int_val = (uint32)sd_hiok;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_HISPEED):
- sd_hiok = int_val;
-
- if (!bcmspi_set_highspeed_mode(si, (bool)sd_hiok)) {
- sd_err(("%s: Failed changing highspeed mode to %d.\n",
- __FUNCTION__, sd_hiok));
- bcmerror = BCME_ERROR;
- return ERROR;
- }
- break;
-
- case IOV_GVAL(IOV_NUMINTS):
- int_val = (int32)si->intrcount;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_GVAL(IOV_NUMLOCALINTS):
- int_val = (int32)si->local_intrcount;
- bcopy(&int_val, arg, val_size);
- break;
- case IOV_GVAL(IOV_DEVREG):
- {
- sdreg_t *sd_ptr = (sdreg_t *)params;
- uint8 data;
-
- if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
- bcmerror = BCME_SDIO_ERROR;
- break;
- }
-
- int_val = (int)data;
- bcopy(&int_val, arg, sizeof(int_val));
- break;
- }
-
- case IOV_SVAL(IOV_DEVREG):
- {
- sdreg_t *sd_ptr = (sdreg_t *)params;
- uint8 data = (uint8)sd_ptr->value;
-
- if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
- bcmerror = BCME_SDIO_ERROR;
- break;
- }
- break;
- }
-
-
- case IOV_GVAL(IOV_SPIERRSTATS):
- {
- bcopy(&si->spierrstats, arg, sizeof(struct spierrstats_t));
- break;
- }
-
- case IOV_SVAL(IOV_SPIERRSTATS):
- {
- bzero(&si->spierrstats, sizeof(struct spierrstats_t));
- break;
- }
-
- case IOV_GVAL(IOV_RESP_DELAY_ALL):
- int_val = (int32)si->resp_delay_all;
- bcopy(&int_val, arg, val_size);
- break;
-
- case IOV_SVAL(IOV_RESP_DELAY_ALL):
- si->resp_delay_all = (bool)int_val;
- int_val = STATUS_ENABLE|INTR_WITH_STATUS;
- if (si->resp_delay_all)
- int_val |= RESP_DELAY_ALL;
- else {
- if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_RESPONSE_DELAY, 1,
- F1_RESPONSE_DELAY) != SUCCESS) {
- sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
- bcmerror = BCME_SDIO_ERROR;
- break;
- }
- }
-
- if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_STATUS_ENABLE, 1, int_val)
- != SUCCESS) {
- sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
- bcmerror = BCME_SDIO_ERROR;
- break;
- }
- break;
-
- default:
- bcmerror = BCME_UNSUPPORTED;
- break;
- }
-exit:
-
- return bcmerror;
-}
-
-extern SDIOH_API_RC
-sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
-{
- SDIOH_API_RC status;
- /* No lock needed since sdioh_request_byte does locking */
- status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
- return status;
-}
-
-extern SDIOH_API_RC
-sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
-{
- /* No lock needed since sdioh_request_byte does locking */
- SDIOH_API_RC status;
-
- if ((fnc_num == SPI_FUNC_1) && (addr == SBSDIO_FUNC1_FRAMECTRL)) {
- uint8 dummy_data;
- status = sdioh_cfg_read(sd, fnc_num, addr, &dummy_data);
- if (status) {
- sd_err(("sdioh_cfg_read() failed.\n"));
- return status;
- }
- }
-
- status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
- return status;
-}
-
-extern SDIOH_API_RC
-sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
-{
- uint32 count;
- int offset;
- uint32 cis_byte;
- uint16 *cis = (uint16 *)cisd;
- uint bar0 = SI_ENUM_BASE;
- int status;
- uint8 data;
-
- sd_trace(("%s: Func %d\n", __FUNCTION__, func));
-
- spi_lock(sd);
-
- /* Set sb window address to 0x18000000 */
- data = (bar0 >> 8) & SBSDIO_SBADDRLOW_MASK;
- status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, &data);
- if (status == SUCCESS) {
- data = (bar0 >> 16) & SBSDIO_SBADDRMID_MASK;
- status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, &data);
- } else {
- sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
- spi_unlock(sd);
- return (BCME_ERROR);
- }
- if (status == SUCCESS) {
- data = (bar0 >> 24) & SBSDIO_SBADDRHIGH_MASK;
- status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, &data);
- } else {
- sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
- spi_unlock(sd);
- return (BCME_ERROR);
- }
-
- offset = CC_OTP; /* OTP offset in chipcommon. */
- for (count = 0; count < length/2; count++) {
- if (bcmspi_card_regread (sd, SDIO_FUNC_1, offset, 2, &cis_byte) < 0) {
- sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
- spi_unlock(sd);
- return (BCME_ERROR);
- }
-
- *cis = (uint16)cis_byte;
- cis++;
- offset += 2;
- }
-
- spi_unlock(sd);
-
- return (BCME_OK);
-}
-
-extern SDIOH_API_RC
-sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
-{
- int status;
- uint32 cmd_arg;
- uint32 dstatus;
- uint32 data = (uint32)(*byte);
-
- spi_lock(sd);
-
- cmd_arg = 0;
- cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
- cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
- cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, rw == SDIOH_READ ? 0 : 1);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
-
- sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
- sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, rw, func,
- regaddr, data));
-
- if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma,
- cmd_arg, &data, 1)) != SUCCESS) {
- spi_unlock(sd);
- return status;
- }
-
- if (rw == SDIOH_READ)
- *byte = (uint8)data;
-
- bcmspi_cmd_getdstatus(sd, &dstatus);
- if (dstatus)
- sd_trace(("dstatus =0x%x\n", dstatus));
-
- spi_unlock(sd);
- return SDIOH_API_RC_SUCCESS;
-}
-
-extern SDIOH_API_RC
-sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
- uint32 *word, uint nbytes)
-{
- int status;
-
- spi_lock(sd);
-
- if (rw == SDIOH_READ)
- status = bcmspi_card_regread(sd, func, addr, nbytes, word);
- else
- status = bcmspi_card_regwrite(sd, func, addr, nbytes, *word);
-
- spi_unlock(sd);
- return (status == SUCCESS ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
-}
-
-extern SDIOH_API_RC
-sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func,
- uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
-{
- int len;
- int buflen = (int)buflen_u;
- bool fifo = (fix_inc == SDIOH_DATA_FIX);
-
- spi_lock(sd);
-
- ASSERT(reg_width == 4);
- ASSERT(buflen_u < (1 << 30));
- ASSERT(sd->client_block_size[func]);
-
- sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n",
- __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W',
- buflen_u, sd->r_cnt, sd->t_cnt, pkt));
-
- /* Break buffer down into blocksize chunks. */
- while (buflen > 0) {
- len = MIN(sd->client_block_size[func], buflen);
- if (bcmspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) {
- sd_err(("%s: bcmspi_card_buf %s failed\n",
- __FUNCTION__, rw == SDIOH_READ ? "Read" : "Write"));
- spi_unlock(sd);
- return SDIOH_API_RC_FAIL;
- }
- buffer += len;
- buflen -= len;
- if (!fifo)
- addr += len;
- }
- spi_unlock(sd);
- return SDIOH_API_RC_SUCCESS;
-}
-
-/* This function allows write to gspi bus when another rd/wr function is deep down the call stack.
- * Its main aim is to have simpler spi writes rather than recursive writes.
- * e.g. When there is a need to program response delay on the fly after detecting the SPI-func
- * this call will allow to program the response delay.
- */
-static int
-bcmspi_card_byterewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 byte)
-{
- uint32 cmd_arg;
- uint32 datalen = 1;
- uint32 hostlen;
-
- cmd_arg = 0;
-
- cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
- cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
- cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, datalen);
-
- sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
-
-
- /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
- * according to the wordlen mode(16/32bit) the device is in.
- */
- ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
- datalen = ROUNDUP(datalen, sd->wordlen);
-
- /* Start by copying command in the spi-outbuffer */
- if (sd->wordlen == 4) { /* 32bit spid */
- *(uint32 *)spi_outbuf2 = bcmswap32(cmd_arg);
- if (datalen & 0x3)
- datalen += (4 - (datalen & 0x3));
- } else if (sd->wordlen == 2) { /* 16bit spid */
- *(uint16 *)spi_outbuf2 = bcmswap16(cmd_arg & 0xffff);
- *(uint16 *)&spi_outbuf2[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16);
- if (datalen & 0x1)
- datalen++;
- } else {
- sd_err(("%s: Host is %d bit spid, could not create SPI command.\n",
- __FUNCTION__, 8 * sd->wordlen));
- return ERROR;
- }
-
- /* for Write, put the data into the output buffer */
- if (datalen != 0) {
- if (sd->wordlen == 4) { /* 32bit spid */
- *(uint32 *)&spi_outbuf2[CMDLEN] = bcmswap32(byte);
- } else if (sd->wordlen == 2) { /* 16bit spid */
- *(uint16 *)&spi_outbuf2[CMDLEN] = bcmswap16(byte & 0xffff);
- *(uint16 *)&spi_outbuf2[CMDLEN + 2] =
- bcmswap16((byte & 0xffff0000) >> 16);
- }
- }
-
- /* +4 for cmd, +4 for dstatus */
- hostlen = datalen + 8;
- hostlen += (4 - (hostlen & 0x3));
- spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, hostlen);
-
- /* Last 4bytes are dstatus. Device is configured to return status bits. */
- if (sd->wordlen == 4) { /* 32bit spid */
- sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
- } else if (sd->wordlen == 2) { /* 16bit spid */
- sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) |
- (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16));
- } else {
- sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
- __FUNCTION__, 8 * sd->wordlen));
- return ERROR;
- }
-
- if (sd->card_dstatus)
- sd_trace(("dstatus after byte rewrite = 0x%x\n", sd->card_dstatus));
-
- return (BCME_OK);
-}
-
-/* Program the response delay corresponding to the spi function */
-static int
-bcmspi_prog_resp_delay(sdioh_info_t *sd, int func, uint8 resp_delay)
-{
- if (sd->resp_delay_all == FALSE)
- return (BCME_OK);
-
- if (sd->prev_fun == func)
- return (BCME_OK);
-
- if (F0_RESPONSE_DELAY == F1_RESPONSE_DELAY)
- return (BCME_OK);
-
- bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_RESPONSE_DELAY, resp_delay);
-
- /* Remember function for which to avoid reprogramming resp-delay in next iteration */
- sd->prev_fun = func;
-
- return (BCME_OK);
-
-}
-
-#define GSPI_RESYNC_PATTERN 0x0
-
-/* A resync pattern is a 32bit MOSI line with all zeros. Its a special command in gSPI.
- * It resets the spi-bkplane logic so that all F1 related ping-pong buffer logic is
- * synchronised and all queued resuests are cancelled.
- */
-static int
-bcmspi_resync_f1(sdioh_info_t *sd)
-{
- uint32 cmd_arg = GSPI_RESYNC_PATTERN, data = 0, datalen = 0;
-
-
- /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
- * according to the wordlen mode(16/32bit) the device is in.
- */
- ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
- datalen = ROUNDUP(datalen, sd->wordlen);
-
- /* Start by copying command in the spi-outbuffer */
- *(uint32 *)spi_outbuf2 = cmd_arg;
-
- /* for Write, put the data into the output buffer */
- *(uint32 *)&spi_outbuf2[CMDLEN] = data;
-
- /* +4 for cmd, +4 for dstatus */
- spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, datalen + 8);
-
- /* Last 4bytes are dstatus. Device is configured to return status bits. */
- if (sd->wordlen == 4) { /* 32bit spid */
- sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
- } else if (sd->wordlen == 2) { /* 16bit spid */
- sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) |
- (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16));
- } else {
- sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
- __FUNCTION__, 8 * sd->wordlen));
- return ERROR;
- }
-
- if (sd->card_dstatus)
- sd_trace(("dstatus after resync pattern write = 0x%x\n", sd->card_dstatus));
-
- return (BCME_OK);
-}
-
-uint32 dstatus_count = 0;
-
-static int
-bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg)
-{
- uint32 dstatus = sd->card_dstatus;
- struct spierrstats_t *spierrstats = &sd->spierrstats;
- int err = SUCCESS;
-
- sd_trace(("cmd = 0x%x, dstatus = 0x%x\n", cmd_arg, dstatus));
-
- /* Store dstatus of last few gSPI transactions */
- spierrstats->dstatus[dstatus_count % NUM_PREV_TRANSACTIONS] = dstatus;
- spierrstats->spicmd[dstatus_count % NUM_PREV_TRANSACTIONS] = cmd_arg;
- dstatus_count++;
-
- if (sd->card_init_done == FALSE)
- return err;
-
- if (dstatus & STATUS_DATA_NOT_AVAILABLE) {
- spierrstats->dna++;
- sd_trace(("Read data not available on F1 addr = 0x%x\n",
- GFIELD(cmd_arg, SPI_REG_ADDR)));
- /* Clear dna bit */
- bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, DATA_UNAVAILABLE);
- }
-
- if (dstatus & STATUS_UNDERFLOW) {
- spierrstats->rdunderflow++;
- sd_err(("FIFO underflow happened due to current F2 read command.\n"));
- }
-
- if (dstatus & STATUS_OVERFLOW) {
- spierrstats->wroverflow++;
- sd_err(("FIFO overflow happened due to current (F1/F2) write command.\n"));
- if ((sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 0)) {
- bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, F1_OVERFLOW);
- bcmspi_resync_f1(sd);
- sd_err(("Recovering from F1 FIFO overflow.\n"));
- } else {
- err = ERROR_OF;
- }
- }
-
- if (dstatus & STATUS_F2_INTR) {
- spierrstats->f2interrupt++;
- sd_trace(("Interrupt from F2. SW should clear corresponding IntStatus bits\n"));
- }
-
- if (dstatus & STATUS_F3_INTR) {
- spierrstats->f3interrupt++;
- sd_err(("Interrupt from F3. SW should clear corresponding IntStatus bits\n"));
- }
-
- if (dstatus & STATUS_HOST_CMD_DATA_ERR) {
- spierrstats->hostcmddataerr++;
- sd_err(("Error in CMD or Host data, detected by CRC/Checksum (optional)\n"));
- }
-
- if (dstatus & STATUS_F2_PKT_AVAILABLE) {
- spierrstats->f2pktavailable++;
- sd_trace(("Packet is available/ready in F2 TX FIFO\n"));
- sd_trace(("Packet length = %d\n", sd->dwordmode ?
- ((dstatus & STATUS_F2_PKT_LEN_MASK) >> (STATUS_F2_PKT_LEN_SHIFT - 2)) :
- ((dstatus & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT)));
- }
-
- if (dstatus & STATUS_F3_PKT_AVAILABLE) {
- spierrstats->f3pktavailable++;
- sd_err(("Packet is available/ready in F3 TX FIFO\n"));
- sd_err(("Packet length = %d\n",
- (dstatus & STATUS_F3_PKT_LEN_MASK) >> STATUS_F3_PKT_LEN_SHIFT));
- }
-
- return err;
-}
-
-extern int
-sdioh_abort(sdioh_info_t *sd, uint func)
-{
- return 0;
-}
-
-int
-sdioh_start(sdioh_info_t *sd, int stage)
-{
- return SUCCESS;
-}
-
-int
-sdioh_stop(sdioh_info_t *sd)
-{
- return SUCCESS;
-}
-
-
-
-/*
- * Private/Static work routines
- */
-static int
-bcmspi_host_init(sdioh_info_t *sd)
-{
-
- /* Default power on mode */
- sd->sd_mode = SDIOH_MODE_SPI;
- sd->polled_mode = TRUE;
- sd->host_init_done = TRUE;
- sd->card_init_done = FALSE;
- sd->adapter_slot = 1;
-
- return (SUCCESS);
-}
-
-static int
-get_client_blocksize(sdioh_info_t *sd)
-{
- uint32 regdata[2];
- int status;
-
- /* Find F1/F2/F3 max packet size */
- if ((status = bcmspi_card_regread(sd, 0, SPID_F1_INFO_REG,
- 8, regdata)) != SUCCESS) {
- return status;
- }
-
- sd_trace(("pkt_size regdata[0] = 0x%x, regdata[1] = 0x%x\n",
- regdata[0], regdata[1]));
-
- sd->client_block_size[1] = (regdata[0] & F1_MAX_PKT_SIZE) >> 2;
- sd_trace(("Func1 blocksize = %d\n", sd->client_block_size[1]));
- ASSERT(sd->client_block_size[1] == BLOCK_SIZE_F1);
-
- sd->client_block_size[2] = ((regdata[0] >> 16) & F2_MAX_PKT_SIZE) >> 2;
- sd_trace(("Func2 blocksize = %d\n", sd->client_block_size[2]));
- ASSERT(sd->client_block_size[2] == BLOCK_SIZE_F2);
-
- sd->client_block_size[3] = (regdata[1] & F3_MAX_PKT_SIZE) >> 2;
- sd_trace(("Func3 blocksize = %d\n", sd->client_block_size[3]));
- ASSERT(sd->client_block_size[3] == BLOCK_SIZE_F3);
-
- return 0;
-}
-
-static int
-bcmspi_client_init(sdioh_info_t *sd)
-{
- uint32 status_en_reg = 0;
- sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot));
-
-#ifdef HSMODE
- if (!spi_start_clock(sd, (uint16)sd_divisor)) {
- sd_err(("spi_start_clock failed\n"));
- return ERROR;
- }
-#else
- /* Start at ~400KHz clock rate for initialization */
- if (!spi_start_clock(sd, 128)) {
- sd_err(("spi_start_clock failed\n"));
- return ERROR;
- }
-#endif /* HSMODE */
-
- if (!bcmspi_host_device_init_adapt(sd)) {
- sd_err(("bcmspi_host_device_init_adapt failed\n"));
- return ERROR;
- }
-
- if (!bcmspi_test_card(sd)) {
- sd_err(("bcmspi_test_card failed\n"));
- return ERROR;
- }
-
- sd->num_funcs = SPI_MAX_IOFUNCS;
-
- get_client_blocksize(sd);
-
- /* Apply resync pattern cmd with all zeros to reset spi-bkplane F1 logic */
- bcmspi_resync_f1(sd);
-
- sd->dwordmode = FALSE;
-
- bcmspi_card_regread(sd, 0, SPID_STATUS_ENABLE, 1, &status_en_reg);
-
- sd_trace(("%s: Enabling interrupt with dstatus \n", __FUNCTION__));
- status_en_reg |= INTR_WITH_STATUS;
-
-
- if (bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_STATUS_ENABLE, 1,
- status_en_reg & 0xff) != SUCCESS) {
- sd_err(("%s: Unable to set response delay for all fun's.\n", __FUNCTION__));
- return ERROR;
- }
-
-
-#ifndef HSMODE
- /* After configuring for High-Speed mode, set the desired clock rate. */
- if (!spi_start_clock(sd, 4)) {
- sd_err(("spi_start_clock failed\n"));
- return ERROR;
- }
-#endif /* HSMODE */
-
- sd->card_init_done = TRUE;
-
-
- return SUCCESS;
-}
-
-static int
-bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode)
-{
- uint32 regdata;
- int status;
-
- if ((status = bcmspi_card_regread(sd, 0, SPID_CONFIG,
- 4, &regdata)) != SUCCESS)
- return status;
-
- sd_trace(("In %s spih-ctrl = 0x%x \n", __FUNCTION__, regdata));
-
-
- if (hsmode == TRUE) {
- sd_trace(("Attempting to enable High-Speed mode.\n"));
-
- if (regdata & HIGH_SPEED_MODE) {
- sd_trace(("Device is already in High-Speed mode.\n"));
- return status;
- } else {
- regdata |= HIGH_SPEED_MODE;
- sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
- if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
- 4, regdata)) != SUCCESS) {
- return status;
- }
- }
- } else {
- sd_trace(("Attempting to disable High-Speed mode.\n"));
-
- if (regdata & HIGH_SPEED_MODE) {
- regdata &= ~HIGH_SPEED_MODE;
- sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
- if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
- 4, regdata)) != SUCCESS)
- return status;
- }
- else {
- sd_trace(("Device is already in Low-Speed mode.\n"));
- return status;
- }
- }
-
- spi_controller_highspeed_mode(sd, hsmode);
-
- return TRUE;
-}
-
-#define bcmspi_find_curr_mode(sd) { \
- sd->wordlen = 2; \
- status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
- regdata &= 0xff; \
- if ((regdata == 0xad) || (regdata == 0x5b) || \
- (regdata == 0x5d) || (regdata == 0x5a)) \
- break; \
- sd->wordlen = 4; \
- status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
- regdata &= 0xff; \
- if ((regdata == 0xad) || (regdata == 0x5b) || \
- (regdata == 0x5d) || (regdata == 0x5a)) \
- break; \
- sd_trace(("Silicon testability issue: regdata = 0x%x." \
- " Expected 0xad, 0x5a, 0x5b or 0x5d.\n", regdata)); \
- OSL_DELAY(100000); \
-}
-
-#define INIT_ADAPT_LOOP 100
-
-/* Adapt clock-phase-speed-bitwidth between host and device */
-static bool
-bcmspi_host_device_init_adapt(sdioh_info_t *sd)
-{
- uint32 wrregdata, regdata = 0;
- int status;
- int i;
-
- /* Due to a silicon testability issue, the first command from the Host
- * to the device will get corrupted (first bit will be lost). So the
- * Host should poll the device with a safe read request. ie: The Host
- * should try to read F0 addr 0x14 using the Fixed address mode
- * (This will prevent a unintended write command to be detected by device)
- */
- for (i = 0; i < INIT_ADAPT_LOOP; i++) {
- /* If device was not power-cycled it will stay in 32bit mode with
- * response-delay-all bit set. Alternate the iteration so that
- * read either with or without response-delay for F0 to succeed.
- */
- bcmspi_find_curr_mode(sd);
- sd->resp_delay_all = (i & 0x1) ? TRUE : FALSE;
-
- bcmspi_find_curr_mode(sd);
- sd->dwordmode = TRUE;
-
- bcmspi_find_curr_mode(sd);
- sd->dwordmode = FALSE;
- }
-
- /* Bail out, device not detected */
- if (i == INIT_ADAPT_LOOP)
- return FALSE;
-
- /* Softreset the spid logic */
- if ((sd->dwordmode) || (sd->wordlen == 4)) {
- bcmspi_card_regwrite(sd, 0, SPID_RESET_BP, 1, RESET_ON_WLAN_BP_RESET|RESET_SPI);
- bcmspi_card_regread(sd, 0, SPID_RESET_BP, 1, &regdata);
- sd_trace(("reset reg read = 0x%x\n", regdata));
- sd_trace(("dwordmode = %d, wordlen = %d, resp_delay_all = %d\n", sd->dwordmode,
- sd->wordlen, sd->resp_delay_all));
- /* Restore default state after softreset */
- sd->wordlen = 2;
- sd->dwordmode = FALSE;
- }
-
- if (sd->wordlen == 4) {
- if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) !=
- SUCCESS)
- return FALSE;
- if (regdata == TEST_RO_DATA_32BIT_LE) {
- sd_trace(("Spid is already in 32bit LE mode. Value read = 0x%x\n",
- regdata));
- sd_trace(("Spid power was left on.\n"));
- } else {
- sd_err(("Spid power was left on but signature read failed."
- " Value read = 0x%x\n", regdata));
- return FALSE;
- }
- } else {
- sd->wordlen = 2;
-
-#define CTRL_REG_DEFAULT 0x00010430 /* according to the host m/c */
-
- wrregdata = (CTRL_REG_DEFAULT);
- sd->resp_delay_all = TRUE;
- if (sd->resp_delay_all == TRUE) {
- /* Enable response delay for all */
- wrregdata |= (RESP_DELAY_ALL << 16);
- /* Program response delay value */
- wrregdata &= 0xffff00ff;
- wrregdata |= (F1_RESPONSE_DELAY << 8);
- sd->prev_fun = SPI_FUNC_1;
- bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
- }
-
- if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
- return FALSE;
- sd_trace(("(we are still in 16bit mode) 32bit READ LE regdata = 0x%x\n", regdata));
-
-#ifndef HSMODE
- wrregdata |= (CLOCK_PHASE | CLOCK_POLARITY);
- wrregdata &= ~HIGH_SPEED_MODE;
- bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
-#endif /* HSMODE */
-
- for (i = 0; i < INIT_ADAPT_LOOP; i++) {
- if ((regdata == 0xfdda7d5b) || (regdata == 0xfdda7d5a)) {
- sd_trace(("0xfeedbead was leftshifted by 1-bit.\n"));
- if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4,
- &regdata)) != SUCCESS)
- return FALSE;
- }
- OSL_DELAY(1000);
- }
-
-
- /* Change to host controller intr-polarity of active-low */
- wrregdata &= ~INTR_POLARITY;
- sd_trace(("(we are still in 16bit mode) 32bit Write LE reg-ctrl-data = 0x%x\n",
- wrregdata));
- /* Change to 32bit mode */
- wrregdata |= WORD_LENGTH_32;
- bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
-
- /* Change command/data packaging in 32bit LE mode */
- sd->wordlen = 4;
-
- if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
- return FALSE;
-
- if (regdata == TEST_RO_DATA_32BIT_LE) {
- sd_trace(("Read spid passed. Value read = 0x%x\n", regdata));
- sd_trace(("Spid had power-on cycle OR spi was soft-resetted \n"));
- } else {
- sd_err(("Stale spid reg values read as it was kept powered. Value read ="
- "0x%x\n", regdata));
- return FALSE;
- }
- }
-
-
- return TRUE;
-}
-
-static bool
-bcmspi_test_card(sdioh_info_t *sd)
-{
- uint32 regdata;
- int status;
-
- if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
- return FALSE;
-
- if (regdata == (TEST_RO_DATA_32BIT_LE))
- sd_trace(("32bit LE regdata = 0x%x\n", regdata));
- else {
- sd_trace(("Incorrect 32bit LE regdata = 0x%x\n", regdata));
- return FALSE;
- }
-
-
-#define RW_PATTERN1 0xA0A1A2A3
-#define RW_PATTERN2 0x4B5B6B7B
-
- regdata = RW_PATTERN1;
- if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
- return FALSE;
- regdata = 0;
- if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
- return FALSE;
- if (regdata != RW_PATTERN1) {
- sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
- RW_PATTERN1, regdata));
- return FALSE;
- } else
- sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
-
- regdata = RW_PATTERN2;
- if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
- return FALSE;
- regdata = 0;
- if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
- return FALSE;
- if (regdata != RW_PATTERN2) {
- sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
- RW_PATTERN2, regdata));
- return FALSE;
- } else
- sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
-
- return TRUE;
-}
-
-static int
-bcmspi_driver_init(sdioh_info_t *sd)
-{
- sd_trace(("%s\n", __FUNCTION__));
- if ((bcmspi_host_init(sd)) != SUCCESS) {
- return ERROR;
- }
-
- if (bcmspi_client_init(sd) != SUCCESS) {
- return ERROR;
- }
-
- return SUCCESS;
-}
-
-/* Read device reg */
-static int
-bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
-{
- int status;
- uint32 cmd_arg, dstatus;
-
- ASSERT(regsize);
-
- if (func == 2)
- sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
-
- cmd_arg = 0;
- cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
- cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
- cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
-
- sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
- sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func,
- regaddr, *data));
-
- if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize))
- != SUCCESS)
- return status;
-
- bcmspi_cmd_getdstatus(sd, &dstatus);
- if (dstatus)
- sd_trace(("dstatus =0x%x\n", dstatus));
-
- return SUCCESS;
-}
-
-static int
-bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
-{
-
- int status;
- uint32 cmd_arg;
- uint32 dstatus;
-
- ASSERT(regsize);
-
- if (func == 2)
- sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
-
- cmd_arg = 0;
- cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0); /* Fixed access */
- cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
- cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize);
-
- sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
-
- if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize))
- != SUCCESS)
- return status;
-
- sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func,
- regaddr, *data));
-
- bcmspi_cmd_getdstatus(sd, &dstatus);
- sd_trace(("dstatus =0x%x\n", dstatus));
- return SUCCESS;
-}
-
-/* write a device register */
-static int
-bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
-{
- int status;
- uint32 cmd_arg, dstatus;
-
- ASSERT(regsize);
-
- cmd_arg = 0;
-
- cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
- cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
- cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
-
- sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
- sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 1, func,
- regaddr, data));
-
-
- if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, regsize))
- != SUCCESS)
- return status;
-
- bcmspi_cmd_getdstatus(sd, &dstatus);
- if (dstatus)
- sd_trace(("dstatus =0x%x\n", dstatus));
-
- return SUCCESS;
-}
-
-/* write a device register - 1 byte */
-static int
-bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 *byte)
-{
- int status;
- uint32 cmd_arg;
- uint32 dstatus;
- uint32 data = (uint32)(*byte);
-
- cmd_arg = 0;
- cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */
- cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
- cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
-
- sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
- sd_trace(("%s: func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, func,
- regaddr, data));
-
- if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma,
- cmd_arg, &data, 1)) != SUCCESS) {
- return status;
- }
-
- bcmspi_cmd_getdstatus(sd, &dstatus);
- if (dstatus)
- sd_trace(("dstatus =0x%x\n", dstatus));
-
- return SUCCESS;
-}
-
-void
-bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer)
-{
- *dstatus_buffer = sd->card_dstatus;
-}
-
-/* 'data' is of type uint32 whereas other buffers are of type uint8 */
-static int
-bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
- uint32 *data, uint32 datalen)
-{
- uint32 i, j;
- uint8 resp_delay = 0;
- int err = SUCCESS;
- uint32 hostlen;
- uint32 spilen = 0;
- uint32 dstatus_idx = 0;
- uint16 templen, buslen, len, *ptr = NULL;
-
- sd_trace(("spi cmd = 0x%x\n", cmd_arg));
-
- if (DWORDMODE_ON) {
- spilen = GFIELD(cmd_arg, SPI_LEN);
- if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_0) ||
- (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_1))
- dstatus_idx = spilen * 3;
-
- if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
- (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
- spilen = spilen << 2;
- dstatus_idx = (spilen % 16) ? (16 - (spilen % 16)) : 0;
- /* convert len to mod16 size */
- spilen = ROUNDUP(spilen, 16);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
- }
- }
-
- /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen
- * according to the wordlen mode(16/32bit) the device is in.
- */
- if (sd->wordlen == 4) { /* 32bit spid */
- *(uint32 *)spi_outbuf = bcmswap32(cmd_arg);
- if (datalen & 0x3)
- datalen += (4 - (datalen & 0x3));
- } else if (sd->wordlen == 2) { /* 16bit spid */
- *(uint16 *)spi_outbuf = bcmswap16(cmd_arg & 0xffff);
- *(uint16 *)&spi_outbuf[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16);
- if (datalen & 0x1)
- datalen++;
- if (datalen < 4)
- datalen = ROUNDUP(datalen, 4);
- } else {
- sd_err(("Host is %d bit spid, could not create SPI command.\n",
- 8 * sd->wordlen));
- return ERROR;
- }
-
- /* for Write, put the data into the output buffer */
- if (GFIELD(cmd_arg, SPI_RW_FLAG) == 1) {
- /* We send len field of hw-header always a mod16 size, both from host and dongle */
- if (DWORDMODE_ON) {
- if (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) {
- ptr = (uint16 *)&data[0];
- templen = *ptr;
- /* ASSERT(*ptr == ~*(ptr + 1)); */
- templen = ROUNDUP(templen, 16);
- *ptr = templen;
- sd_trace(("actual tx len = %d\n", (uint16)(~*(ptr+1))));
- }
- }
-
- if (datalen != 0) {
- for (i = 0; i < datalen/4; i++) {
- if (sd->wordlen == 4) { /* 32bit spid */
- *(uint32 *)&spi_outbuf[i * 4 + CMDLEN] =
- bcmswap32(data[i]);
- } else if (sd->wordlen == 2) { /* 16bit spid */
- *(uint16 *)&spi_outbuf[i * 4 + CMDLEN] =
- bcmswap16(data[i] & 0xffff);
- *(uint16 *)&spi_outbuf[i * 4 + CMDLEN + 2] =
- bcmswap16((data[i] & 0xffff0000) >> 16);
- }
- }
- }
- }
-
- /* Append resp-delay number of bytes and clock them out for F0/1/2 reads. */
- if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) {
- int func = GFIELD(cmd_arg, SPI_FUNCTION);
- switch (func) {
- case 0:
- resp_delay = sd->resp_delay_all ? F0_RESPONSE_DELAY : 0;
- break;
- case 1:
- resp_delay = F1_RESPONSE_DELAY;
- break;
- case 2:
- resp_delay = sd->resp_delay_all ? F2_RESPONSE_DELAY : 0;
- break;
- default:
- ASSERT(0);
- break;
- }
- /* Program response delay */
- bcmspi_prog_resp_delay(sd, func, resp_delay);
- }
-
- /* +4 for cmd and +4 for dstatus */
- hostlen = datalen + 8 + resp_delay;
- hostlen += dstatus_idx;
- hostlen += (4 - (hostlen & 0x3));
- spi_sendrecv(sd, spi_outbuf, spi_inbuf, hostlen);
-
- /* for Read, get the data into the input buffer */
- if (datalen != 0) {
- if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) { /* if read cmd */
- for (j = 0; j < datalen/4; j++) {
- if (sd->wordlen == 4) { /* 32bit spid */
- data[j] = bcmswap32(*(uint32 *)&spi_inbuf[j * 4 +
- CMDLEN + resp_delay]);
- } else if (sd->wordlen == 2) { /* 16bit spid */
- data[j] = (bcmswap16(*(uint16 *)&spi_inbuf[j * 4 +
- CMDLEN + resp_delay])) |
- ((bcmswap16(*(uint16 *)&spi_inbuf[j * 4 +
- CMDLEN + resp_delay + 2])) << 16);
- }
- }
-
- if ((DWORDMODE_ON) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
- ptr = (uint16 *)&data[0];
- templen = *ptr;
- buslen = len = ~(*(ptr + 1));
- buslen = ROUNDUP(buslen, 16);
- /* populate actual len in hw-header */
- if (templen == buslen)
- *ptr = len;
- }
- }
- }
-
- /* Restore back the len field of the hw header */
- if (DWORDMODE_ON) {
- if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
- (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
- ptr = (uint16 *)&data[0];
- *ptr = (uint16)(~*(ptr+1));
- }
- }
-
- dstatus_idx += (datalen + CMDLEN + resp_delay);
- /* Last 4bytes are dstatus. Device is configured to return status bits. */
- if (sd->wordlen == 4) { /* 32bit spid */
- sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf[dstatus_idx]);
- } else if (sd->wordlen == 2) { /* 16bit spid */
- sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx]) |
- (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx + 2]) << 16));
- } else {
- sd_err(("Host is %d bit machine, could not read SPI dstatus.\n",
- 8 * sd->wordlen));
- return ERROR;
- }
- if (sd->card_dstatus == 0xffffffff) {
- sd_err(("looks like not a GSPI device or device is not powered.\n"));
- }
-
- err = bcmspi_update_stats(sd, cmd_arg);
-
- return err;
-
-}
-
-static int
-bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
- uint32 addr, int nbytes, uint32 *data)
-{
- int status;
- uint32 cmd_arg;
- bool write = rw == SDIOH_READ ? 0 : 1;
- uint retries = 0;
-
- bool enable;
- uint32 spilen;
-
- cmd_arg = 0;
-
- ASSERT(nbytes);
- ASSERT(nbytes <= sd->client_block_size[func]);
-
- if (write) sd->t_cnt++; else sd->r_cnt++;
-
- if (func == 2) {
- /* Frame len check limited by gSPI. */
- if ((nbytes > 2000) && write) {
- sd_trace((">2KB write: F2 wr of %d bytes\n", nbytes));
- }
- /* ASSERT(nbytes <= 2048); Fix bigger len gspi issue and uncomment. */
- /* If F2 fifo on device is not ready to receive data, don't do F2 transfer */
- if (write) {
- uint32 dstatus;
- /* check F2 ready with cached one */
- bcmspi_cmd_getdstatus(sd, &dstatus);
- if ((dstatus & STATUS_F2_RX_READY) == 0) {
- retries = WAIT_F2RXFIFORDY;
- enable = 0;
- while (retries-- && !enable) {
- OSL_DELAY(WAIT_F2RXFIFORDY_DELAY * 1000);
- bcmspi_card_regread(sd, SPI_FUNC_0, SPID_STATUS_REG, 4,
- &dstatus);
- if (dstatus & STATUS_F2_RX_READY)
- enable = TRUE;
- }
- if (!enable) {
- struct spierrstats_t *spierrstats = &sd->spierrstats;
- spierrstats->f2rxnotready++;
- sd_err(("F2 FIFO is not ready to receive data.\n"));
- return ERROR;
- }
- sd_trace(("No of retries on F2 ready %d\n",
- (WAIT_F2RXFIFORDY - retries)));
- }
- }
- }
-
- /* F2 transfers happen on 0 addr */
- addr = (func == 2) ? 0 : addr;
-
- /* In pio mode buffer is read using fixed address fifo in func 1 */
- if ((func == 1) && (fifo))
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0);
- else
- cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);
-
- cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
- cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, addr);
- cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, write);
- spilen = sd->data_xfer_count = MIN(sd->client_block_size[func], nbytes);
- if ((sd->dwordmode == TRUE) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
- /* convert len to mod4 size */
- spilen = spilen + ((spilen & 0x3) ? (4 - (spilen & 0x3)): 0);
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
- } else
- cmd_arg = SFIELD(cmd_arg, SPI_LEN, spilen);
-
- if ((func == 2) && (fifo == 1)) {
- sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
- __FUNCTION__, write ? "Wr" : "Rd", func, "INCR",
- addr, nbytes, sd->r_cnt, sd->t_cnt));
- }
-
- sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
- sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
- __FUNCTION__, write ? "Wd" : "Rd", func, "INCR",
- addr, nbytes, sd->r_cnt, sd->t_cnt));
-
-
- if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg,
- data, nbytes)) != SUCCESS) {
- sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__,
- (write ? "write" : "read")));
- return status;
- }
-
- /* gSPI expects that hw-header-len is equal to spi-command-len */
- if ((func == 2) && (rw == SDIOH_WRITE) && (sd->dwordmode == FALSE)) {
- ASSERT((uint16)sd->data_xfer_count == (uint16)(*data & 0xffff));
- ASSERT((uint16)sd->data_xfer_count == (uint16)(~((*data & 0xffff0000) >> 16)));
- }
-
- if ((nbytes > 2000) && !write) {
- sd_trace((">2KB read: F2 rd of %d bytes\n", nbytes));
- }
-
- return SUCCESS;
-}
-
-/* Reset and re-initialize the device */
-int
-sdioh_sdio_reset(sdioh_info_t *si)
-{
- si->card_init_done = FALSE;
- return bcmspi_client_init(si);
-}
diff --git a/bcm4329/src/dhd/exe/GNUmakefile b/bcm4329/src/dhd/exe/GNUmakefile
index fec744d..240189b 100644
--- a/bcm4329/src/dhd/exe/GNUmakefile
+++ b/bcm4329/src/dhd/exe/GNUmakefile
@@ -49,7 +49,7 @@ CFLAGS += -DBCMSPI
#-----------------------------------------------------------
# Linux build
#
-ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le linuxarm_omap android"),)
+ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le android"),)
# $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files
DHD_OBJS := dhdu.o dhdu_linux.o bcmutils.o miniopt.o
@@ -63,10 +63,6 @@ endif
# extra warnings
CFLAGS += -Wextra $(CUSTOM_FLAGS)
-ifeq ($(TARGETENV), linuxarm_omap)
-CFLAGS += -DBGBRD
-endif
-
vpath %.c $(SRCBASE)/shared
all: $(DHD_EXE)
diff --git a/bcm4329/src/dhd/exe/dhdu.c b/bcm4329/src/dhd/exe/dhdu.c
index 6fc28b2..5ffd961 100644
--- a/bcm4329/src/dhd/exe/dhdu.c
+++ b/bcm4329/src/dhd/exe/dhdu.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhdu.c,v 1.52.2.10.2.6.2.10 2009/06/02 21:56:22 Exp $
+ * $Id: dhdu.c,v 1.52.2.10.2.6.2.11 2009/09/25 00:32:00 Exp $
*/
/* For backwards compatibility, the absense of the define 'BWL_NO_FILESYSTEM_SUPPORT'
@@ -406,6 +406,7 @@ dhd_list(void *dhd, cmd_t *garb, char **argv)
printf("%s\n", buf+row*80);
printf("\n");
+ free(buf);
return (0);
}
@@ -683,7 +684,7 @@ dhd_sd_blocksize(void *dhd, cmd_t *cmd, char **argv)
{
int ret;
int argc;
- char *endptr;
+ char *endptr = NULL;
void *ptr = NULL;
int func, size;
@@ -769,7 +770,7 @@ dhd_sdreg(void *dhd, cmd_t *cmd, char **argv)
int ret;
sdreg_t sdreg;
uint argc;
- char *ptr;
+ char *ptr = NULL;
UNUSED_PARAMETER(cmd);
@@ -991,7 +992,7 @@ static int
dhd_idletime(void *dhd, cmd_t *cmd, char **argv)
{
int32 idletime;
- char *endptr;
+ char *endptr = NULL;
int err = 0;
if (argv[1]) {
@@ -1040,7 +1041,7 @@ static int
dhd_idleclock(void *dhd, cmd_t *cmd, char **argv)
{
int32 idleclock;
- char *endptr;
+ char *endptr = NULL;
int err = 0;
if (argv[1]) {
@@ -1784,7 +1785,7 @@ static int
dhd_logstamp(void *dhd, cmd_t *cmd, char **argv)
{
int ret;
- char *endptr;
+ char *endptr = NULL;
uint argc;
int valn[2] = {0, 0};
@@ -1821,7 +1822,7 @@ dhd_sd_reg(void *dhd, cmd_t *cmd, char **argv)
{
int ret;
sdreg_t sdreg;
- char *endptr;
+ char *endptr = NULL;
uint argc;
void *ptr = NULL;
@@ -1911,8 +1912,8 @@ static int
dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg)
{
int ret, i;
- uint val, last_val = 0, msglevel, msglevel_add = 0, msglevel_del = 0;
- char *endptr;
+ uint val, last_val = 0, msglevel = 0, msglevel_add = 0, msglevel_del = 0;
+ char *endptr = NULL;
if ((ret = dhd_iovar_getint(dhd, cmd->name, (int*)&msglevel)) < 0)
return (ret);
@@ -2024,7 +2025,7 @@ dhd_var_setint(void *dhd, cmd_t *cmd, char **argv)
int32 val;
int len;
char *varname;
- char *endptr;
+ char *endptr = NULL;
char *p;
if (cmd->set == -1) {
diff --git a/bcm4329/src/dhd/linux/Makefile b/bcm4329/src/dhd/linux/Makefile
index df8f009..89300a1 100644
--- a/bcm4329/src/dhd/linux/Makefile
+++ b/bcm4329/src/dhd/linux/Makefile
@@ -21,7 +21,7 @@
# software in any way with any other Broadcom software provided under a license
# other than the GPL, without Broadcom's express prior written consent.
#
-# $Id: Makefile,v 1.55.2.6.2.10.6.18 2009/06/03 21:51:11 Exp $
+# $Id: Makefile,v 1.55.2.6.2.10.6.24 2009/10/22 18:40:45 Exp $
#
# Try a couple of places for LINUXDIR if not specified
@@ -54,6 +54,9 @@ ifeq ($(LINUXVER),)
$(error LINUXVER=$(LINUXVER) is empty)
endif # LINUXVER
+$(warning Found LINUXVER=$(LINUXVER))
+$(warning Found LINUXDIR=$(LINUXDIR))
+
# check if 2.4 kernel or 2.5+ kernel
BCM_KVER:=$(shell echo $(LINUXVER) | cut -c1-3 | sed 's/2\.[56]/2\.6/')
@@ -74,7 +77,7 @@ DFLAGS :=
# basic options (defines in DFLAGS, includes in IFLAGS)
-DFLAGS += -DLINUX -DSRCBASE=\"$(SRCBASE)\" -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2
+DFLAGS += -DLINUX -DSRCBASE=\"$(SRCBASE)\" -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 -DBCMWAPI_WPI
DFLAGS += -DUNRELEASEDCHIP
ifeq ($(BCMQT),1)
DFLAGS += -DBCMSLTGT -DBCMQT
@@ -85,7 +88,40 @@ ifeq ($(WLTEST),1)
endif
-IFLAGS := -I$(LINUXDIR)/include -I$(LINUXDIR)/include/asm/mach-default -I. -I$(SRCBASE)/include -I$(SRCBASE)/shared -I$(SRCBASE)/dhd/sys -I$(SRCBASE)/dongle -I$(SRCBASE)/wl/sys
+# Past 2.6.29 kernels, arch specific bits are re-organized in linux kernel. So
+# append new include paths to existing ones to get 2.6.29+ kernels compile
+
+# Default DHDARCH is x86
+ifdef ARCH
+ DHDARCH ?= $(ARCH)
+else
+ DHDARCH ?= x86
+endif
+
+ifneq ($(findstring native,$(TARGET)),)
+ DHDARCH = x86
+endif
+ifneq ($(findstring mips,$(TARGET)),)
+ DHDARCH = mips
+endif
+ifneq ($(findstring arm,$(TARGET)),)
+ DHDARCH = arm
+endif
+
+# First include from linux kernel dirs
+IFLAGS := -I$(LINUXDIR)/include
+IFLAGS += -I$(LINUXDIR)/include/asm/mach-default
+# Followed by 2.6.29+ specific paths
+IFLAGS += -I$(LINUXDIR)/arch/$(DHDARCH)/include
+IFLAGS += -I$(LINUXDIR)/arch/$(DHDARCH)/include/asm/mach-default
+
+# From current workspace
+IFLAGS += -I.
+IFLAGS += -I$(SRCBASE)/include
+IFLAGS += -I$(SRCBASE)/shared
+IFLAGS += -I$(SRCBASE)/dhd/sys
+IFLAGS += -I$(SRCBASE)/dongle
+IFLAGS += -I$(SRCBASE)/wl/sys
ifneq ($(wildcard $(LINUXDIR)/.config),)
include $(LINUXDIR)/.config
@@ -162,7 +198,7 @@ ifneq ($(findstring -rndis-,-$(TARGET)-),)
DFLAGS += -DRNDIS
CFILES += dhd_rndis.c
endif
-
+
ifneq ($(findstring -usb-,-$(TARGET)-),)
DFLAGS += -DBCMDHDUSB
CFILES += dhd_usb_linux.c
@@ -175,8 +211,15 @@ ifneq ($(findstring -sdstd-,$(TARGET)-),)
DFLAGS += -DBCMSDIO -DBCMSDIOH_STD
CFILES += dhd_sdio.c bcmsdh.c bcmsdstd.c bcmsdstd_linux.c bcmsdh_linux.c
endif
+ifneq ($(findstring -oob-,-$(TARGET)-),)
+DFLAGS += -DOOB_INTR_ONLY
+else
+ifneq ($(findstring -sdmmc-,-$(TARGET)-),)
+DFLAGS += -DSDIO_ISR_THREAD
+endif
+endif
ifneq ($(findstring -sdmmc-,-$(TARGET)-),)
-DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS -DSDIO_ISR_THREAD
+DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS
CFILES += dhd_sdio.c bcmsdh_sdmmc.c bcmsdh.c bcmsdh_linux.c bcmsdh_sdmmc_linux.c
endif
ifneq ($(findstring -sdspi-,$(TARGET)-),)
@@ -196,6 +239,8 @@ endif
CFLAGS += -fshort-wchar $(DFLAGS) $(WFLAGS) $(IFLAGS) $(CUSTOM_FLAGS)
+
+
LDFLAGS := -r
MODULES := dhd.o
ifeq ($(BCM_KVER), 2.6)
@@ -219,8 +264,9 @@ endif
TARGETS := \
dhd-cdc-usb dhd-cdc-sdstd \
- dhd-cdc-sdspi-pci dhd-cdc-sdmmc-gpl dhd-cdc-usb-apsta \
- dhd-cdc-usb-gpl
+ dhd-cdc-sdspi-pci dhd-cdc-sdmmc-gpl dhd-cdc-sdmmc-oob-gpl \
+ dhd-cdc-usb-apsta dhd-cdc-usb-gpl \
+ dhd-cdc-sdstd-apsta
TARGETS += \
diff --git a/bcm4329/src/dhd/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h
index 8f15106..004f7a3 100644
--- a/bcm4329/src/dhd/sys/dhd.h
+++ b/bcm4329/src/dhd/sys/dhd.h
@@ -24,7 +24,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd.h,v 1.32.4.7.2.4.14.22 2009/06/04 23:07:40 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.25 2009/10/27 04:41:56 Exp $
*/
/****************
@@ -46,6 +46,9 @@
#include <linux/ethtool.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+#include <linux/wakelock.h>
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
/* The kernel threading is sdio-specific */
#else /* LINUX */
#define ENOMEM 1
@@ -75,6 +78,26 @@ enum dhd_bus_state {
DHD_BUS_DATA /* Ready for frame transfers */
};
+enum dhd_bus_wake_state {
+ WAKE_LOCK_OFF,
+ WAKE_LOCK_PRIV,
+ WAKE_LOCK_DPC,
+ WAKE_LOCK_IOCTL,
+ WAKE_LOCK_DOWNLOAD,
+ WAKE_LOCK_TMOUT,
+ WAKE_LOCK_WATCHDOG,
+ WAKE_LOCK_LINK_DOWN_TMOUT,
+ WAKE_LOCK_MAX
+};
+enum dhd_prealloc_index {
+ DHD_PREALLOC_PROT = 0,
+ DHD_PREALLOC_RXBUF,
+ DHD_PREALLOC_DATABUF,
+ DHD_PREALLOC_OSL_BUF
+};
+#ifdef DHD_USE_STATIC_BUF
+extern void * dhd_os_prealloc(int section, unsigned long size);
+#endif
/* Common structure for module and instance linkage */
typedef struct dhd_pub {
/* Linkage ponters */
@@ -126,6 +149,9 @@ typedef struct dhd_pub {
int dongle_error;
uint8 country_code[WLC_CNTRY_BUF_SZ];
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+ struct wake_lock wakelock[WAKE_LOCK_MAX];
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
} dhd_pub_t;
#ifdef NDIS60
@@ -139,9 +165,90 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info)
#endif /* NDIS60 */
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+
+ #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+ #define _DHD_PM_RESUME_WAIT(a, b) do {\
+ int retry = 0; \
+ while (dhd_mmc_suspend && retry++ != b) { \
+ wait_event_timeout(a, FALSE, HZ/100); \
+ } \
+ } while (0)
+ #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30)
+ #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0)
+ #define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0)
+ #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0)
+
+ #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a);
+ #define SPINWAIT_SLEEP(a, exp, us) do { \
+ uint countdown = (us) + 9; \
+ while ((exp) && (countdown >= 10)) { \
+ wait_event_timeout(a, FALSE, HZ/100); \
+ countdown -= 10; \
+ } \
+ } while (0)
+
+ #else
+
+ #define DHD_PM_RESUME_WAIT_INIT(a)
+ #define DHD_PM_RESUME_WAIT(a)
+ #define DHD_PM_RESUME_WAIT_FOREVER(a)
+ #define DHD_PM_RESUME_RETURN_ERROR(a)
+ #define DHD_PM_RESUME_RETURN
+
+ #define DHD_SPINWAIT_SLEEP_INIT(a)
+ #define SPINWAIT_SLEEP(a, exp, us) do { \
+ uint countdown = (us) + 9; \
+ while ((exp) && (countdown >= 10)) { \
+ OSL_DELAY(10); \
+ countdown -= 10; \
+ } \
+ } while (0)
+
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
+
+inline static void WAKE_LOCK_INIT(dhd_pub_t * dhdp, int index, char * y)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock_init(&dhdp->wakelock[index], WAKE_LOCK_SUSPEND, y);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
+}
+
+inline static void WAKE_LOCK(dhd_pub_t * dhdp, int index)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock(&dhdp->wakelock[index]);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
+}
+
+inline static void WAKE_UNLOCK(dhd_pub_t * dhdp, int index)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+ wake_unlock(&dhdp->wakelock[index]);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
+}
+
+inline static void WAKE_LOCK_TIMEOUT(dhd_pub_t * dhdp, int index, long time)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock_timeout(&dhdp->wakelock[index], time);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
+}
+
+inline static void WAKE_LOCK_DESTROY(dhd_pub_t * dhdp, int index)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK)
+ wake_lock_destroy(&dhdp->wakelock[index]);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */
+}
+
+
typedef struct dhd_if_event {
uint8 ifidx;
uint8 action;
+ uint8 flags;
+ uint8 bssidx;
} dhd_if_event_t;
/*
@@ -201,15 +308,13 @@ extern void dhd_os_sdunlock_txq(dhd_pub_t * pub);
extern void dhd_os_sdlock_rxq(dhd_pub_t * pub);
extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub);
extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub);
+extern void dhd_customer_gpio_wlan_ctrl(int onoff);
extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub);
+#if defined(OOB_INTR_ONLY)
+extern int dhd_customer_oob_irq_map(void);
+#endif /* defined(OOB_INTR_ONLY) */
extern void dhd_os_sdtxlock(dhd_pub_t * pub);
extern void dhd_os_sdtxunlock(dhd_pub_t * pub);
-extern void dhd_os_set_irq(unsigned int irq, dhd_pub_t *pub);
-extern void dhd_os_enable_irq(dhd_pub_t *pub);
-extern void dhd_os_disable_irq(dhd_pub_t *pub);
-extern int dhd_os_wake_lock(dhd_pub_t *pub);
-extern int dhd_os_wake_unlock(dhd_pub_t *pub);
-extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub);
int setScheduler(struct task_struct *p, int policy, struct sched_param *param);
@@ -224,15 +329,24 @@ extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
extern int dhd_timeout_expired(dhd_timeout_t *tmo);
extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
+extern uint8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx);
extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata,
wl_event_msg_t *, void **data_ptr);
extern void wl_event_to_host_order(wl_event_msg_t * evt);
extern void dhd_common_init(void);
-extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, char *name, uint8 *mac_addr);
+extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle,
+ char *name, uint8 *mac_addr, uint32 flags, uint8 bssidx);
extern void dhd_del_if(struct dhd_info *dhd, int ifidx);
+extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name);
+extern void dhd_vif_del(struct dhd_info *dhd, int ifidx);
+
+extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx);
+extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len);
+
+
/* Send packet to dongle via data channel */
extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt);
@@ -244,6 +358,12 @@ extern int dhd_bus_start(dhd_pub_t *dhdp);
+typedef enum cust_gpio_modes {
+ WLAN_RESET_ON,
+ WLAN_RESET_OFF,
+ WLAN_POWER_ON,
+ WLAN_POWER_OFF
+} cust_gpio_modes_t;
/*
* Insmod parameters for debug/test
*/
diff --git a/bcm4329/src/dhd/sys/dhd_cdc.c b/bcm4329/src/dhd/sys/dhd_cdc.c
index b28d455..e503b50 100644
--- a/bcm4329/src/dhd/sys/dhd_cdc.c
+++ b/bcm4329/src/dhd/sys/dhd_cdc.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.18 2009/06/26 07:03:26 Exp $
+ * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.30 2009/10/28 21:38:04 Exp $
*
* BDC is like CDC, except it includes a header for data packets to convey
* packet priority over the bus, and flags (e.g. to indicate checksum status
@@ -41,11 +41,6 @@
#include <dhd_bus.h>
#include <dhd_dbg.h>
-#ifdef EXT_STA
-#include <siutils.h>
-#include <wlc_cfg.h>
-#include <wlc_pub.h>
-#endif /* EXT_STA */
/* Packet alignment for most efficient SDIO (can change based on platform) */
#ifndef DHD_SDALIGN
@@ -78,12 +73,9 @@ dhdcdc_msg(dhd_pub_t *dhd)
{
dhd_prot_t *prot = dhd->prot;
int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
- int ret;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
- dhd_os_wake_lock(dhd);
-
/* NOTE : cdc->msg.len holds the desired length of the buffer to be
* returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
* is actually sent to the dongle
@@ -92,10 +84,7 @@ dhdcdc_msg(dhd_pub_t *dhd)
len = CDC_MAX_MSG_SIZE;
/* Send request */
- ret = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
-
- dhd_os_wake_unlock(dhd);
- return ret;
+ return dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len);
}
static int
@@ -129,7 +118,7 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
/* Respond "bcmerror" and "bcmerrorstr" with local cache */
- if (cmd == WLC_GET_VAR)
+ if (cmd == WLC_GET_VAR && buf)
{
if (!strcmp((char *)buf, "bcmerrorstr"))
{
@@ -152,7 +141,7 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
CDC_SET_IF_IDX(msg, ifidx);
if (buf)
- memcpy((void *)(&msg[1]), buf, len);
+ memcpy(prot->buf, buf, len);
if ((ret = dhdcdc_msg(dhd)) < 0) {
DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret));
@@ -219,7 +208,7 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
CDC_SET_IF_IDX(msg, ifidx);
if (buf)
- memcpy((void *)(&msg[1]), buf, len);
+ memcpy(prot->buf, buf, len);
if ((ret = dhdcdc_msg(dhd)) < 0)
goto done;
@@ -256,6 +245,10 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
dhd_prot_t *prot = dhd->prot;
int ret = -1;
+ if (dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
+ return ret;
+ }
dhd_os_proto_block(dhd);
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@@ -361,11 +354,6 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf)
if (PKTSUMNEEDED(pktbuf))
h->flags |= BDC_FLAG_SUM_NEEDED;
-#ifdef EXT_STA
- /* save pkt encryption exemption info for dongle */
- h->flags &= ~BDC_FLAG_EXEMPT;
- h->flags |= (WLPKTFLAG_EXEMPT_GET(WLPKTTAG(pktbuf)) & BDC_FLAG_EXEMPT);
-#endif /* EXT_STA */
h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK);
h->flags2 = 0;
@@ -461,10 +449,17 @@ dhd_prot_attach(dhd_pub_t *dhd)
{
dhd_prot_t *cdc;
+#ifndef DHD_USE_STATIC_BUF
if (!(cdc = (dhd_prot_t *)MALLOC(dhd->osh, sizeof(dhd_prot_t)))) {
DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
goto fail;
}
+#else
+ if (!(cdc = (dhd_prot_t *)dhd_os_prealloc(DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) {
+ DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
+ goto fail;
+ }
+#endif /* DHD_USE_STATIC_BUF */
memset(cdc, 0, sizeof(dhd_prot_t));
/* ensure that the msg buf directly follows the cdc msg struct */
@@ -481,8 +476,10 @@ dhd_prot_attach(dhd_pub_t *dhd)
return 0;
fail:
+#ifndef DHD_USE_STATIC_BUF
if (cdc != NULL)
MFREE(dhd->osh, cdc, sizeof(dhd_prot_t));
+#endif
return BCME_NOMEM;
}
@@ -490,7 +487,9 @@ fail:
void
dhd_prot_detach(dhd_pub_t *dhd)
{
+#ifndef DHD_USE_STATIC_BUF
MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t));
+#endif
dhd->prot = NULL;
}
@@ -507,17 +506,120 @@ dhd_prot_dstats(dhd_pub_t *dhd)
return;
}
+int dhd_set_suspend(int value, dhd_pub_t *dhd)
+{
+ int power_mode = PM_MAX;
+ wl_pkt_filter_enable_t enable_parm;
+ char iovbuf[32];
+ int bcn_li_dtim = 3;
+#ifdef CUSTOMER_HW2
+ uint roamvar = 1;
+#endif /* CUSTOMER_HW2 */
+
+#define htod32(i) i
+
+ if (dhd && dhd->up) {
+ if (value) {
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM,
+ (char *)&power_mode, sizeof(power_mode));
+ /* Enable packet filter, only allow unicast packet to send up */
+ enable_parm.id = htod32(100);
+ enable_parm.enable = htod32(1);
+ bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
+ sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ /* set bcn_li_dtim */
+ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+ 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#ifdef CUSTOMER_HW2
+ /* Disable build-in roaming to allowed ext supplicant to take of romaing */
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#endif /* CUSTOMER_HW2 */
+ } else {
+ power_mode = PM_FAST;
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode,
+ sizeof(power_mode));
+ /* disable pkt filter */
+ enable_parm.id = htod32(100);
+ enable_parm.enable = htod32(0);
+ bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
+ sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ /* set bcn_li_dtim */
+ bcn_li_dtim = 0;
+ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
+ 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#ifdef CUSTOMER_HW2
+ roamvar = 0;
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+#endif /* CUSTOMER_HW2 */
+ }
+ }
+
+ return 0;
+}
+
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+
+/* Convert user's input in hex pattern to byte-size mask */
+static int
+wl_pattern_atoh(char *src, char *dst)
+{
+ int i;
+ if (strncmp(src, "0x", 2) != 0 &&
+ strncmp(src, "0X", 2) != 0) {
+ printf("Mask invalid format. Needs to start with 0x\n");
+ return -1;
+ }
+ src = src + 2; /* Skip past 0x */
+ if (strlen(src) % 2 != 0) {
+ printf("Mask invalid format. Needs to be of even length\n");
+ return -1;
+ }
+ for (i = 0; *src != '\0'; i++) {
+ char num[3];
+ strncpy(num, src, 2);
+ num[2] = '\0';
+ dst[i] = (uint8)strtoul(num, NULL, 16);
+ src += 2;
+ }
+ return i;
+}
+
int
dhd_preinit_ioctls(dhd_pub_t *dhd)
{
char eventmask[WL_EVENTING_MASK_LEN];
char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
-
+ int ret;
uint up = 0;
+#ifdef CUSTOMER_HW2
+ uint roamvar = 0;
+#else
uint roamvar = 1;
+#endif
uint power_mode = PM_FAST;
uint32 dongle_align = DHD_SDALIGN;
- int ret;
+ uint32 glom = 0;
+
+ uint bcn_timeout = 3;
+ int arpoe = 1;
+ int arp_ol = 0xf;
+ int scan_assoc_time = 40;
+ int scan_unassoc_time = 80;
+ const char *str;
+ wl_pkt_filter_t pkt_filter;
+ wl_pkt_filter_t *pkt_filterp;
+ int buf_len;
+ int str_len;
+ uint32 mask_size;
+ uint32 pattern_size;
+ char buf[256];
+ uint filter_mode = 1;
/* Get the device MAC address */
strcpy(iovbuf, "cur_etheraddr");
@@ -542,19 +644,27 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
- /* Force STA UP */
- dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+ /* disable glom option per default */
+ bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ /* Setup timeout if Beacons are lost and roam is off to report link down */
+ if (roamvar) {
+ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ }
- /* Disable build-in roaming to allowed ext supplicant to take of romaing */
+ /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */
bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ /* Force STA UP */
+ dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+
/* Setup event_msgs */
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
- /* Setup event_msgs */
setbit(eventmask, WLC_E_SET_SSID);
setbit(eventmask, WLC_E_PRUNE);
setbit(eventmask, WLC_E_AUTH);
@@ -576,6 +686,69 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
+ sizeof(scan_assoc_time));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
+ sizeof(scan_unassoc_time));
+
+ /* Set ARP offload */
+ bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+ bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+ /* add a default packet filter pattern */
+ str = "pkt_filter_add";
+ str_len = strlen(str);
+ strncpy(buf, str, str_len);
+ buf[ str_len ] = '\0';
+ buf_len = str_len + 1;
+
+ pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+
+ /* Parse packet filter id. */
+ pkt_filter.id = htod32(100);
+
+ /* Parse filter polarity. */
+ pkt_filter.negate_match = htod32(0);
+
+ /* Parse filter type. */
+ pkt_filter.type = htod32(0);
+
+ /* Parse pattern filter offset. */
+ pkt_filter.u.pattern.offset = htod32(0);
+
+ /* Parse pattern filter mask. */
+ mask_size = htod32(wl_pattern_atoh("0xff",
+ (char *) pkt_filterp->u.pattern.mask_and_pattern));
+
+ /* Parse pattern filter pattern. */
+ pattern_size = htod32(wl_pattern_atoh("0x00",
+ (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
+
+ if (mask_size != pattern_size) {
+ printk("Mask and pattern not the same size\n");
+ return -1;
+ }
+
+ pkt_filter.u.pattern.size_bytes = mask_size;
+ buf_len += WL_PKT_FILTER_FIXED_LEN;
+ buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
+
+ /* Keep-alive attributes are set in local variable (keep_alive_pkt), and
+ ** then memcpy'ed into buffer (keep_alive_pktp) since there is no
+ ** guarantee that the buffer is properly aligned.
+ */
+ memcpy((char *)pkt_filterp, &pkt_filter,
+ WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len);
+
+ /* set mode to allow pattern */
+ bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
return 0;
}
@@ -583,13 +756,8 @@ int
dhd_prot_init(dhd_pub_t *dhd)
{
int ret = 0;
- char buf[128];
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
- /* Get the device MAC address */
- strcpy(buf, "cur_etheraddr");
- dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
- memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
ret = dhd_preinit_ioctls(dhd);
diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c
index c96a0ac..eff07f2 100644
--- a/bcm4329/src/dhd/sys/dhd_common.c
+++ b/bcm4329/src/dhd/sys/dhd_common.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_common.c,v 1.5.6.8.2.6.6.32 2009/06/04 23:07:41 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.37 2009/10/22 14:47:18 Exp $
*/
#include <typedefs.h>
#include <osl.h>
@@ -90,6 +90,7 @@ const bcm_iovar_t dhd_iovars[] = {
{NULL, 0, 0, 0, 0 }
};
+
void
dhd_common_init(void)
{
@@ -100,16 +101,8 @@ dhd_common_init(void)
* first time that the driver is initialized vs subsequent initializations.
*/
dhd_msg_level = DHD_ERROR_VAL;
-#ifdef CONFIG_BCM4329_FW_PATH
- strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN-1);
-#else
fw_path[0] = '\0';
-#endif
-#ifdef CONFIG_BCM4329_NVRAM_PATH
- strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN-1);
-#else
nv_path[0] = '\0';
-#endif
}
static int
@@ -312,14 +305,21 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec)
return FALSE; /* refuse newer (incoming) packet */
/* Evict packet according to discard policy */
p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec);
- ASSERT(p);
+ if (p == NULL) {
+ DHD_ERROR(("%s: pktq_penq() failed, oldest %d.",
+ __FUNCTION__, discard_oldest));
+ ASSERT(p);
+ }
PKTFREE(dhdp->osh, p, TRUE);
}
/* Enqueue */
p = pktq_penq(q, prec, pkt);
- ASSERT(p);
+ if (p == NULL) {
+ DHD_ERROR(("%s: pktq_penq() failed.", __FUNCTION__));
+ ASSERT(p);
+ }
return TRUE;
}
@@ -382,6 +382,8 @@ dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ if (!buf) return BCME_BADARG;
+
switch (ioc->cmd) {
case DHD_GET_MAGIC:
if (buflen < sizeof(int))
@@ -451,7 +453,7 @@ dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
}
#ifdef APSTA_PINGTEST
-struct ether_addr guest_eas[MAX_GUEST] = {};
+struct ether_addr guest_eas[MAX_GUEST];
#endif
#ifdef SHOW_EVENTS
@@ -774,13 +776,18 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
char *event_data;
uint32 type, status;
uint16 flags;
+ int evlen;
- if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN))
+ if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) {
+ DHD_ERROR(("%s: mismatched OUI, bailing\n", __FUNCTION__));
return (BCME_ERROR);
+ }
/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
- if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT)
+ if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) {
+ DHD_ERROR(("%s: mismatched subtype, bailing\n", __FUNCTION__));
return (BCME_ERROR);
+ }
*data_ptr = &pvt_data[1];
event_data = *data_ptr;
@@ -791,17 +798,21 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
type = ntoh32_ua((void *)&event->event_type);
flags = ntoh16_ua((void *)&event->flags);
status = ntoh32_ua((void *)&event->status);
+ evlen = ntoh32_ua((void *)&event->datalen) + sizeof(bcm_event_t);
switch (type) {
case WLC_E_IF:
{
dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data;
+ DHD_TRACE(("%s: if event\n", __FUNCTION__));
if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS)
{
if (ifevent->action == WLC_E_IF_ADD)
dhd_add_if(dhd, ifevent->ifidx,
- NULL, event->ifname, pvt_data->eth.ether_dhost);
+ NULL, event->ifname,
+ pvt_data->eth.ether_dhost,
+ ifevent->flags, ifevent->bssidx);
else
dhd_del_if(dhd, ifevent->ifidx);
} else {
@@ -809,17 +820,44 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
__FUNCTION__, ifevent->ifidx, event->ifname));
}
}
+ /* send up the if event: btamp user needs it */
+ *ifidx = dhd_ifname2idx(dhd, event->ifname);
+ /* push up to external supp/auth */
+ dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
+ break;
+
+
+#ifdef P2P
+ case WLC_E_NDIS_LINK:
break;
+#endif
+ /* fall through */
+ /* These are what external supplicant/authenticator wants */
case WLC_E_LINK:
- case WLC_E_DEAUTH:
- case WLC_E_DEAUTH_IND:
- case WLC_E_DISASSOC:
+ case WLC_E_ASSOC_IND:
+ case WLC_E_REASSOC_IND:
case WLC_E_DISASSOC_IND:
- DHD_EVENT(("%s: Link event %d, flags %x, status %x\n",
- __FUNCTION__, type, flags, status));
+ case WLC_E_MIC_ERROR:
default:
+ /* Fall through: this should get _everything_ */
+
*ifidx = dhd_ifname2idx(dhd, event->ifname);
- DHD_EVENT(("%s: event %d, idx %d\n", __FUNCTION__, type, *ifidx));
+ /* push up to external supp/auth */
+ dhd_event(dhd, (char *)pvt_data, evlen, *ifidx);
+ DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n",
+ __FUNCTION__, type, flags, status));
+
+ /* put it back to WLC_E_NDIS_LINK */
+ if (type == WLC_E_NDIS_LINK) {
+ uint32 temp;
+
+ temp = ntoh32_ua((void *)&event->event_type);
+ DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp));
+
+ temp = ntoh32(WLC_E_NDIS_LINK);
+ memcpy((void *)(&pvt_data->event.event_type), &temp,
+ sizeof(pvt_data->event.event_type));
+ }
break;
}
diff --git a/bcm4329/src/dhd/sys/dhd_custom_gpio.c b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
index d0dc970..4da20ab 100644
--- a/bcm4329/src/dhd/sys/dhd_custom_gpio.c
+++ b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
@@ -20,7 +20,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
-* $Id: dhd_custom_gpio.c,v 1.1.4.2 2009/04/13 06:09:38 Exp $
+* $Id: dhd_custom_gpio.c,v 1.1.4.3 2009/10/14 04:29:34 Exp $
*/
@@ -28,193 +28,96 @@
#include <linuxver.h>
#include <osl.h>
#include <bcmutils.h>
+
#include <dngl_stats.h>
#include <dhd.h>
#include <wlioctl.h>
#include <wl_iw.h>
-#include <linux/platform_device.h>
-#include <linux/wifi_tiwlan.h>
-
-#include <linux/gpio.h>
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-
-static struct wifi_platform_data *wifi_control_data = NULL;
-static struct resource *wifi_irqres = NULL;
-static dhd_pub_t *wifi_dhd_pub = NULL;
-#ifdef MODULE
-DECLARE_COMPLETION(sdio_wait);
-#endif
-
-static int wifi_set_carddetect( int on )
-{
- printk("%s = %d\n", __FUNCTION__, on);
- if (wifi_control_data && wifi_control_data->set_carddetect) {
- wifi_control_data->set_carddetect(on);
- }
- return 0;
-}
-
-static int wifi_set_power( int on, unsigned long msec )
-{
- printk("%s = %d\n", __FUNCTION__, on);
- if (wifi_control_data && wifi_control_data->set_power) {
- wifi_control_data->set_power(on);
- }
- if (msec)
- mdelay(msec);
- return 0;
-}
-
-static int wifi_set_reset( int on, unsigned long msec )
-{
- printk("%s = %d\n", __FUNCTION__, on);
- if (wifi_control_data && wifi_control_data->set_reset) {
- wifi_control_data->set_reset(on);
- }
- if (msec)
- mdelay(msec);
- return 0;
-}
-
-irqreturn_t dhd_ext_irq_handler( int irq, void *pub, struct pt_regs *cpu_regs )
-{
- printk("%s\n", __FUNCTION__);
- dhd_os_disable_irq(pub);
- return IRQ_HANDLED;
-}
-
-static int wifi_probe( struct platform_device *pdev )
-{
- struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
-
- printk("%s\n", __FUNCTION__);
- wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
- if (wifi_irqres) {
- printk("wifi_irqres->start = %lu\n", (unsigned long)(wifi_irqres->start));
- printk("wifi_irqres->flags = %lx\n", wifi_irqres->flags);
- }
- wifi_control_data = wifi_ctrl;
- wifi_set_power(1, 0);
- wifi_set_reset(0, 0);
- wifi_set_carddetect(1);
- return 0;
-}
+#define WL_ERROR(x) printf x
+#define WL_TRACE(x)
-int dhdsdio_bussleep(struct dhd_bus *bus, bool sleep);
+#ifdef CUSTOMER_HW
+extern void bcm_wlan_power_off(int);
+extern void bcm_wlan_power_on(int);
+#endif /* CUSTOMER_HW */
-static int wifi_suspend( struct platform_device *pdev, pm_message_t state )
-{
- int rc = 0;
+#if defined(OOB_INTR_ONLY)
- printk("%s\n", __FUNCTION__);
- if (wifi_dhd_pub && !wifi_dhd_pub->dongle_reset) {
- rc = dhdsdio_bussleep(wifi_dhd_pub->bus, 1);
- if (!rc)
- dhd_os_enable_irq(wifi_dhd_pub);
- }
- return rc;
-}
+#if defined(BCMLXSDMMC)
+extern int sdioh_mmc_irq(int irq);
+#endif /* (BCMLXSDMMC) */
-static int wifi_resume( struct platform_device *pdev )
-{
- int rc = 0;
+/* Customer specific Host GPIO defintion */
+static int dhd_oob_gpio_num = -1; /* GG 19 */
- printk("%s\n", __FUNCTION__);
- if (wifi_dhd_pub && !wifi_dhd_pub->dongle_reset) {
- rc = dhdsdio_bussleep(wifi_dhd_pub->bus, 0);
- if (!rc)
- dhd_sched_dpc(wifi_dhd_pub);
- }
- return rc;
-}
-
-static int wifi_remove( struct platform_device *pdev )
-{
- struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
-
- printk("%s\n", __FUNCTION__);
- wifi_control_data = wifi_ctrl;
- wifi_set_carddetect(0);
- wifi_set_reset(1, 0);
- wifi_set_power(0, 0);
- return 0;
-}
+module_param(dhd_oob_gpio_num, int, 0644);
+MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
-static struct platform_driver bcm4329_wlan_device = {
- .probe = wifi_probe,
- .remove = wifi_remove,
- .suspend = wifi_suspend,
- .resume = wifi_resume,
- .driver = {
- .name = "bcm4329_wlan",
- },
-};
-
-int dhd_customer_wifi_complete( void *pub )
+int dhd_customer_oob_irq_map(void)
{
- int rc = -ENODEV;
-
- printk("%s\n", __FUNCTION__);
- if (!pub) {
- printk(KERN_WARNING "%s: No network device\n", __FUNCTION__);
- goto end;
- }
- if (!wifi_irqres || !(wifi_irqres->start)) {
- printk(KERN_WARNING "%s: No platform resources\n", __FUNCTION__);
- goto end;
+int host_oob_irq;
+#if defined(CUSTOM_OOB_GPIO_NUM)
+ if (dhd_oob_gpio_num < 0) {
+ dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
}
- wifi_dhd_pub = pub;
- if ((rc = request_irq(wifi_irqres->start, (irq_handler_t)dhd_ext_irq_handler, wifi_irqres->flags & IRQF_TRIGGER_MASK, wifi_irqres->name, pub))) {
- printk(KERN_ERR "%s: Failed to register interrupt handler\n", __FUNCTION__);
- goto end;
- }
- set_irq_wake(wifi_irqres->start, 1);
- dhd_os_set_irq(wifi_irqres->start, pub);
-end:
-#ifdef MODULE
- complete(&sdio_wait);
#endif
- return rc;
-}
-int dhd_customer_wifi_add_dev( void )
-{
- printk("%s\n", __FUNCTION__);
-
- if (platform_driver_register(&bcm4329_wlan_device))
- return -ENODEV;
-#ifdef MODULE
- if (!wait_for_completion_timeout(&sdio_wait, msecs_to_jiffies(10000))) {
- printk(KERN_ERR "%s: Timed out waiting for device detect\n", __FUNCTION__);
- return -ENODEV;
+ if (dhd_oob_gpio_num < 0) {
+ WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n", \
+ __FUNCTION__));
+ return (dhd_oob_gpio_num);
}
-#endif
- return 0;
-}
-void dhd_customer_wifi_del_dev( void )
-{
- printk("%s\n", __FUNCTION__);
- set_irq_wake(wifi_irqres->start, 0);
- free_irq(wifi_irqres->start, wifi_dhd_pub);
- platform_driver_unregister( &bcm4329_wlan_device );
+ WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n", \
+ __FUNCTION__, dhd_oob_gpio_num));
+
+ /* TODO : move it mmc specific code */
+ host_oob_irq = sdioh_mmc_irq(dhd_oob_gpio_num);
+ return (host_oob_irq);
}
+#endif /* defined(OOB_INTR_ONLY) */
-/* Customer specific function to insert/remove wlan reset gpio pin */
-void dhd_customer_gpio_wlan_reset( bool onoff )
+/* Customer function to control hw specific wlan gpios */
+void
+dhd_customer_gpio_wlan_ctrl(int onoff)
{
- if (onoff == G_WLAN_SET_OFF) {
- printk("%s: assert WLAN RESET\n", __FUNCTION__);
- wifi_set_reset(1, 0);
- wifi_set_power(0, 0);
- }
- else {
- printk("%s: remove WLAN RESET\n", __FUNCTION__);
- wifi_set_power(1, 0);
- wifi_set_reset(0, 0);
+ switch (onoff) {
+ case WLAN_RESET_OFF:
+ WL_TRACE(("%s: call customer specific GPIO to insert WLAN RESET\n",
+ __FUNCTION__));
+#ifdef CUSTOMER_HW
+ bcm_wlan_power_off(2);
+#endif /* CUSTOMER_HW */
+ WL_ERROR(("=========== WLAN placed in RESET ========\n"));
+ break;
+
+ case WLAN_RESET_ON:
+ WL_TRACE(("%s: callc customer specific GPIO to remove WLAN RESET\n",
+ __FUNCTION__));
+#ifdef CUSTOMER_HW
+ bcm_wlan_power_on(2);
+#endif /* CUSTOMER_HW */
+ WL_ERROR(("=========== WLAN going back to live ========\n"));
+ break;
+
+ case WLAN_POWER_OFF:
+ WL_TRACE(("%s: call customer specific GPIO to turn off WL_REG_ON\n",
+ __FUNCTION__));
+#ifdef CUSTOMER_HW
+ bcm_wlan_power_off(1);
+#endif /* CUSTOMER_HW */
+ break;
+
+ case WLAN_POWER_ON:
+ WL_TRACE(("%s: call customer specific GPIO to turn on WL_REG_ON\n",
+ __FUNCTION__));
+#ifdef CUSTOMER_HW
+ bcm_wlan_power_on(1);
+#endif /* CUSTOMER_HW */
+ /* Lets customer power to get stable */
+ OSL_DELAY(500);
+ break;
}
}
diff --git a/bcm4329/src/dhd/sys/dhd_dbg.h b/bcm4329/src/dhd/sys/dhd_dbg.h
index 8ec6d33..581b17d 100644
--- a/bcm4329/src/dhd/sys/dhd_dbg.h
+++ b/bcm4329/src/dhd/sys/dhd_dbg.h
@@ -1,6 +1,5 @@
/*
* Debug/trace/assert driver definitions for Dongle Host Driver.
- * basically copied from WL driver.
*
* Copyright (C) 1999-2009, Broadcom Corporation
*
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index aacc4fb..e5f84c0 100644
--- a/bcm4329/src/dhd/sys/dhd_linux.c
+++ b/bcm4329/src/dhd/sys/dhd_linux.c
@@ -22,9 +22,12 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.32 2009/06/26 07:03:26 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.46 2009/10/28 10:35:11 Exp $
*/
+#ifdef CONFIG_WIFI_CONTROL_FUNC
+#include <linux/platform_device.h>
+#endif
#include <typedefs.h>
#include <linuxver.h>
#include <osl.h>
@@ -54,12 +57,99 @@
#include <dhd_bus.h>
#include <dhd_proto.h>
#include <dhd_dbg.h>
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+/* To make sdio host driver ignore card insert/remove information */
+struct wifi_platform_data {
+ char *name;
+ int (*set_power)(int val);
+ int (*set_reset)(int val);
+ int (*set_carddetect)(int val);
+ void *(*mem_prealloc)(int section, unsigned long size);
+};
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-#include <linux/freezer.h>
+struct semaphore wifi_control_sem;
+
+struct dhd_bus *g_bus;
+
+static struct wifi_platform_data *wifi_control_data = NULL;
+
+static int wifi_probe(struct platform_device *pdev)
+{
+ struct wifi_platform_data *wifi_ctrl =
+ (struct wifi_platform_data *)(pdev->dev.platform_data);
+
+ DHD_TRACE(("## %s\n", __FUNCTION__));
+ if (wifi_ctrl) {
+ wifi_control_data = wifi_ctrl;
+ if (wifi_ctrl->set_power)
+ wifi_ctrl->set_power(1); /* Power On */
+ if (wifi_ctrl->set_carddetect)
+ wifi_ctrl->set_carddetect(1); /* CardDetect (0->1) */
+ }
+
+ up(&wifi_control_sem);
+ return 0;
+}
+
+static int wifi_remove(struct platform_device *pdev)
+{
+ struct wifi_platform_data *wifi_ctrl =
+ (struct wifi_platform_data *)(pdev->dev.platform_data);
+
+ DHD_TRACE(("## %s\n", __FUNCTION__));
+ if (wifi_ctrl) {
+ if (wifi_ctrl->set_carddetect)
+ wifi_ctrl->set_carddetect(0); /* CardDetect (1->0) */
+ if (wifi_ctrl->set_power)
+ wifi_ctrl->set_power(0); /* Power Off */
+ }
+ up(&wifi_control_sem);
+ return 0;
+}
+static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
+ return 0;
+}
+static int wifi_resume(struct platform_device *pdev)
+{
+ DHD_TRACE(("##> %s\n", __FUNCTION__));
+ return 0;
+}
+static struct platform_driver wifi_device = {
+ .probe = wifi_probe,
+ .remove = wifi_remove,
+ .suspend = wifi_suspend,
+ .resume = wifi_resume,
+ .driver = {
+ .name = "msm_wifi",
+ }
+};
+
+int wifi_add_dev(void)
+{
+ DHD_TRACE(("## Calling platform_driver_register\n"));
+ return platform_driver_register(&wifi_device);
+}
+
+void wifi_del_dev(void)
+{
+ DHD_TRACE(("## Unregister platform_driver_register\n"));
+ platform_driver_unregister(&wifi_device);
+}
+#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+#include <linux/suspend.h>
+volatile bool dhd_mmc_suspend = FALSE;
+DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+
+#if defined(OOB_INTR_ONLY)
+extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable);
+#endif /* defined(OOB_INTR_ONLY) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
MODULE_LICENSE("GPL v2");
#endif /* LinuxVer */
@@ -77,6 +167,10 @@ print_tainted()
#include <wl_iw.h>
#endif /* CONFIG_WIRELESS_EXT */
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+
/* Interface control information */
typedef struct dhd_if {
struct dhd_info *info; /* back pointer to dhd_info */
@@ -120,17 +214,6 @@ typedef struct dhd_info {
struct semaphore dpc_sem;
struct completion dpc_exited;
- /* Wakelocks */
-#ifdef CONFIG_HAS_WAKELOCK
- struct wake_lock wl_wifi; /* Wifi wakelock */
- struct wake_lock wl_rxwake; /* Wifi rx wakelock */
-#endif
- spinlock_t wl_lock;
- int wl_count;
- int wl_packet;
- unsigned int oob_irq;
- int oob_irq_flag;
-
/* Thread to issue ioctl for multicast */
long sysioc_pid;
struct semaphore sysioc_sem;
@@ -139,6 +222,11 @@ typedef struct dhd_info {
bool set_macaddress;
struct ether_addr macvalue;
wait_queue_head_t ctrl_wait;
+ atomic_t pend_8021x_cnt;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif /* CONFIG_HAS_EARLYSUSPEND */
} dhd_info_t;
/* Definitions to provide path to the firmware and nvram
@@ -147,6 +235,9 @@ typedef struct dhd_info {
char firmware_path[MOD_PARAM_PATHLEN];
char nvram_path[MOD_PARAM_PATHLEN];
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
+struct semaphore dhd_registration_sem;
+#endif
/* load firmware and/or nvram values from the filesystem */
module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
@@ -159,7 +250,7 @@ uint dhd_sysioc = TRUE;
module_param(dhd_sysioc, uint, 0);
/* Watchdog interval */
-uint dhd_watchdog_ms = 1000;
+uint dhd_watchdog_ms = 10;
module_param(dhd_watchdog_ms, uint, 0);
@@ -256,6 +347,8 @@ struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
#endif /* CONFIG_WIRELESS_EXT */
static void dhd_dpc(ulong data);
+/* forward decl */
+extern int dhd_wait_pend8021x(struct net_device *dev);
#ifdef TOE
#ifndef BDC
@@ -268,6 +361,55 @@ static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol);
static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
wl_event_msg_t *event_ptr, void **data_ptr);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored)
+{
+ switch (action)
+ {
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ dhd_mmc_suspend = TRUE;
+ return NOTIFY_OK;
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ dhd_mmc_suspend = FALSE;
+ return NOTIFY_OK;
+ }
+ return 0;
+}
+
+static struct notifier_block dhd_sleep_pm_notifier = {
+ .notifier_call = dhd_sleep_pm_callback,
+ .priority = 0
+};
+extern int register_pm_notifier(struct notifier_block *nb);
+extern int unregister_pm_notifier(struct notifier_block *nb);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+extern int dhd_set_suspend(int value, dhd_pub_t *dhd);
+
+static void dhd_early_suspend(struct early_suspend *h)
+{
+ struct dhd_info *dhdp;
+ dhdp = container_of(h, struct dhd_info, early_suspend);
+
+ DHD_TRACE(("%s: enter\n", __FUNCTION__));
+
+ dhd_set_suspend(1, &dhdp->pub);
+}
+
+static void dhd_late_resume(struct early_suspend *h)
+{
+ struct dhd_info *dhdp;
+ dhdp = container_of(h, struct dhd_info, early_suspend);
+
+ DHD_TRACE(("%s: enter\n", __FUNCTION__));
+
+ dhd_set_suspend(0, &dhdp->pub);
+}
+#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
/*
* Generalized timeout mechanism. Uses spin sleep with exponential back-off until
@@ -647,6 +789,7 @@ int
dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
{
int ret;
+ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
/* Reject if down */
if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) {
@@ -660,6 +803,8 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
if (ETHER_ISMULTI(eh->ether_dhost))
dhdp->tx_multicast++;
+ if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X)
+ atomic_inc(&dhd->pend_8021x_cnt);
}
/* Look into the packet and update the packet priority */
@@ -670,7 +815,12 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
dhd_prot_hdrpush(dhdp, ifidx, pktbuf);
/* Use bus module to send data frame */
+#ifdef BCMDBUS
+ ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */);
+#else
+ WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
ret = dhd_bus_txdata(dhdp->bus, pktbuf);
+#endif /* BCMDBUS */
return ret;
}
@@ -687,6 +837,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
/* Reject if down */
if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) {
+ DHD_ERROR(("%s: xmit rejected due to dhd bus down status \n", __FUNCTION__));
return -ENODEV;
}
@@ -763,7 +914,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt)
int i;
dhd_if_t *ifp;
wl_event_msg_t event;
- unsigned long flags;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@@ -819,10 +969,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt)
&data);
ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
- if (dhd->iflist[ifidx])
+ if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
ifp = dhd->iflist[ifidx];
- ifp->net->last_rx = jiffies;
+ if (ifp->net)
+ ifp->net->last_rx = jiffies;
+
dhdp->dstats.rx_bytes += skb->len;
dhdp->rx_packets++; /* Local count */
@@ -846,15 +998,20 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
}
}
- spin_lock_irqsave(&dhd->wl_lock, flags);
- dhd->wl_packet = 1;
- spin_unlock_irqrestore(&dhd->wl_lock, flags);
+}
+
+void
+dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx)
+{
+ /* Linux version has nothing to do */
+ return;
}
void
dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
{
- int ifidx;
+ uint ifidx;
+ dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
struct ether_header *eh;
uint16 type;
@@ -863,6 +1020,9 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
eh = (struct ether_header *)PKTDATA(dhdp->osh, txp);
type = ntoh16(eh->ether_type);
+ if (type == ETHER_TYPE_802_1X)
+ atomic_dec(&dhd->pend_8021x_cnt);
+
}
static struct net_device_stats *
@@ -904,6 +1064,7 @@ static int
dhd_watchdog_thread(void *data)
{
dhd_info_t *dhd = (dhd_info_t *)data;
+ WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_WATCHDOG, "dhd_watchdog_thread");
/* This thread doesn't need any user-level access,
* so get rid of all our resources
@@ -917,15 +1078,15 @@ dhd_watchdog_thread(void *data)
}
#endif /* DHD_SCHED */
- set_freezable();
-
DAEMONIZE("dhd_watchdog");
/* Run until signal received */
while (1) {
if (down_interruptible (&dhd->watchdog_sem) == 0) {
+ WAKE_LOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
/* Call the bus module watchdog */
dhd_bus_watchdog(&dhd->pub);
+ WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
/* Count the tick for reference */
dhd->pub.tickcnt++;
@@ -939,6 +1100,7 @@ dhd_watchdog_thread(void *data)
break;
}
+ WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_WATCHDOG);
complete_and_exit(&dhd->watchdog_exited, 0);
}
@@ -968,6 +1130,7 @@ dhd_dpc_thread(void *data)
{
dhd_info_t *dhd = (dhd_info_t *)data;
+ WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_DPC, "dhd_dpc_thread");
/* This thread doesn't need any user-level access,
* so get rid of all our resources
*/
@@ -980,8 +1143,6 @@ dhd_dpc_thread(void *data)
}
#endif /* DHD_SCHED */
- set_freezable();
-
DAEMONIZE("dhd_dpc");
/* Run until signal received */
@@ -989,19 +1150,22 @@ dhd_dpc_thread(void *data)
if (down_interruptible(&dhd->dpc_sem) == 0) {
/* Call bus dpc unless it indicated down (then clean stop) */
if (dhd->pub.busstate != DHD_BUS_DOWN) {
- if (dhd_bus_dpc(dhd->pub.bus))
+ WAKE_LOCK(&dhd->pub, WAKE_LOCK_DPC);
+ if (dhd_bus_dpc(dhd->pub.bus)) {
up(&dhd->dpc_sem);
- else
- dhd_os_wake_unlock(&dhd->pub);
+ WAKE_LOCK_TIMEOUT(&dhd->pub, WAKE_LOCK_TMOUT, 25);
+ }
+ WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_DPC);
} else {
dhd_bus_stop(dhd->pub.bus, TRUE);
- dhd_os_wake_unlock(&dhd->pub);
}
}
else
break;
}
+ WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_DPC);
+
complete_and_exit(&dhd->dpc_exited, 0);
}
@@ -1026,7 +1190,6 @@ dhd_sched_dpc(dhd_pub_t *dhdp)
{
dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
- dhd_os_wake_lock(dhdp);
if (dhd->dpc_pid >= 0) {
up(&dhd->dpc_sem);
return;
@@ -1151,6 +1314,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr)
if (copy_from_user(&info, uaddr, sizeof(info)))
return -EFAULT;
strncpy(drvname, info.driver, sizeof(info.driver));
+ drvname[sizeof(info.driver)-1] = '\0';
/* clear struct for return */
memset(&info, 0, sizeof(info));
@@ -1163,8 +1327,10 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr)
}
/* otherwise, require dongle to be up */
- else if (!dhd->pub.up)
+ else if (!dhd->pub.up) {
+ DHD_ERROR(("%s: dongle is not up\n", __FUNCTION__));
return -ENODEV;
+ }
/* finally, report dongle driver type */
else if (dhd->pub.iswl)
@@ -1244,6 +1410,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
void *buf = NULL;
uint driver = 0;
int ifidx;
+ bool is_set_key_cmd;
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
@@ -1327,10 +1494,26 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
goto done;
}
+ /* Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to
+ * prevent M4 encryption.
+ */
+ is_set_key_cmd = ((ioc.cmd == WLC_SET_KEY) ||
+ ((ioc.cmd == WLC_SET_VAR) &&
+ !(strncmp("wsec_key", ioc.buf, 9))) ||
+ ((ioc.cmd == WLC_SET_VAR) &&
+ !(strncmp("bsscfg:wsec_key", ioc.buf, 15))));
+ if (is_set_key_cmd) {
+ dhd_wait_pend8021x(net);
+ }
+ WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_IOCTL, "dhd_ioctl_entry");
+ WAKE_LOCK(&dhd->pub, WAKE_LOCK_IOCTL);
+
bcmerror = dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
+ WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_IOCTL);
+ WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_IOCTL);
done:
- if (!bcmerror && ioc.buf) {
+ if (!bcmerror && buf && ioc.buf) {
if (copy_to_user(ioc.buf, buf, buflen))
bcmerror = -EFAULT;
}
@@ -1344,13 +1527,21 @@ done:
static int
dhd_stop(struct net_device *net)
{
+#if !defined(IGNORE_ETH0_DOWN)
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ if (dhd->pub.up == 0) {
+ return 0;
+ }
+
/* Set state and stop OS transmissions */
dhd->pub.up = 0;
netif_stop_queue(net);
+#else
+ DHD_ERROR(("BYPASS %s:due to BRCM compilation : under investigation ...\n", __FUNCTION__));
+#endif /* !defined(IGNORE_ETH0_DOWN) */
OLD_MOD_DEC_USE_COUNT;
return 0;
@@ -1364,18 +1555,13 @@ dhd_open(struct net_device *net)
uint32 toe_ol;
#endif
int ifidx;
- int ret;
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
ASSERT(ifidx == 0);
- /* try to bring up bus */
- if ((ret = dhd_bus_start(&dhd->pub)) != 0) {
- DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
- return -1;
- }
+ atomic_set(&dhd->pend_8021x_cnt, 0);
memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN);
@@ -1408,10 +1594,14 @@ dhd_osl_detach(osl_t *osh)
DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh)));
}
osl_detach(osh);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
+ up(&dhd_registration_sem);
+#endif
}
int
-dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, uint8 *mac_addr)
+dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
+ uint8 *mac_addr, uint32 flags, uint8 bssidx)
{
dhd_if_t *ifp;
@@ -1491,9 +1681,13 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
memset(dhd, 0, sizeof(dhd_info_t));
+ /*
+ * Save the dhd_info into the priv
+ */
+ memcpy(netdev_priv(net), &dhd, sizeof(dhd));
dhd->pub.osh = osh;
- if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL) == DHD_BAD_IF)
+ if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF)
goto fail;
net->open = NULL;
@@ -1507,15 +1701,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
spin_lock_init(&dhd->sdlock);
spin_lock_init(&dhd->txqlock);
- /* Initialize Wakelock stuff */
- spin_lock_init(&dhd->wl_lock);
- dhd->wl_count = 0;
- dhd->wl_packet = 0;
-#ifdef CONFIG_HAS_WAKELOCK
- wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
- wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
-#endif
-
/* Link to info module */
dhd->pub.info = dhd;
@@ -1530,7 +1715,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
}
#ifdef CONFIG_WIRELESS_EXT
/* Attach and link in the iw */
- if (wl_iw_attach(net) != 0) {
+ if (wl_iw_attach(net, (void *)&dhd->pub) != 0) {
DHD_ERROR(("wl_iw_attach failed\n"));
goto fail;
}
@@ -1583,6 +1768,23 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
*/
memcpy(netdev_priv(net), &dhd, sizeof(dhd));
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+ g_bus = bus;
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+ register_pm_notifier(&dhd_sleep_pm_notifier);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+ /* Init lock suspend to prevent kernel going to suspend */
+ WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_TMOUT, "dhd_wake_lock");
+ WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_LINK_DOWN_TMOUT, "dhd_wake_lock_link_dw_event");
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
+ dhd->early_suspend.suspend = dhd_early_suspend;
+ dhd->early_suspend.resume = dhd_late_resume;
+ register_early_suspend(&dhd->early_suspend);
+#endif
+
return &dhd->pub;
fail:
@@ -1607,12 +1809,19 @@ dhd_bus_start(dhd_pub_t *dhdp)
/* try to download image and nvram to the dongle */
if (dhd->pub.busstate == DHD_BUS_DOWN) {
+ WAKE_LOCK_INIT(dhdp, WAKE_LOCK_DOWNLOAD, "dhd_bus_start");
+ WAKE_LOCK(dhdp, WAKE_LOCK_DOWNLOAD);
if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
fw_path, nv_path))) {
DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
__FUNCTION__, fw_path, nv_path));
+ WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
+ WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
return -1;
}
+
+ WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
+ WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
}
/* Start the watchdog timer */
@@ -1624,6 +1833,18 @@ dhd_bus_start(dhd_pub_t *dhdp)
DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret));
return ret;
}
+#if defined(OOB_INTR_ONLY)
+ /* Host registration for OOB interrupt */
+ if (bcmsdh_register_oob_intr(dhdp)) {
+ del_timer(&dhd->timer);
+ dhd->wd_timer_valid = FALSE;
+ DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__));
+ return -ENODEV;
+ }
+
+ /* Enable oob at firmware */
+ dhd_enable_oob_intr(dhd->pub.bus, TRUE);
+#endif /* defined(OOB_INTR_ONLY) */
/* If bus is not ready, can't come up */
if (dhd->pub.busstate != DHD_BUS_DATA) {
@@ -1634,7 +1855,8 @@ dhd_bus_start(dhd_pub_t *dhdp)
}
/* Bus is ready, do any protocol initialization */
- dhd_prot_init(&dhd->pub);
+ if ((ret = dhd_prot_init(&dhd->pub)) < 0)
+ return ret;
return 0;
}
@@ -1719,8 +1941,13 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
goto fail;
}
- printf("%s: Broadcom Dongle Host Driver\n", net->name);
+ printf("%s: Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", net->name,
+ dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
+ dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
+ up(&dhd_registration_sem);
+#endif
return 0;
fail:
@@ -1731,42 +1958,56 @@ fail:
void
dhd_bus_detach(dhd_pub_t *dhdp)
{
- dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+ dhd_info_t *dhd;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
- /* Stop the protocol module */
- dhd_prot_stop(&dhd->pub);
-
- /* Stop the bus module */
- dhd_bus_stop(dhd->pub.bus, TRUE);
-
- /* Clear the watchdog timer */
- del_timer(&dhd->timer);
- dhd->wd_timer_valid = FALSE;
+ if (dhdp) {
+ dhd = (dhd_info_t *)dhdp->info;
+ if (dhd) {
+ /* Stop the protocol module */
+ dhd_prot_stop(&dhd->pub);
+
+ /* Stop the bus module */
+ dhd_bus_stop(dhd->pub.bus, TRUE);
+#if defined(OOB_INTR_ONLY)
+ bcmsdh_unregister_oob_intr();
+#endif /* defined(OOB_INTR_ONLY) */
+
+ /* Clear the watchdog timer */
+ del_timer(&dhd->timer);
+ dhd->wd_timer_valid = FALSE;
+ }
+ }
}
void
dhd_detach(dhd_pub_t *dhdp)
{
- dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+ dhd_info_t *dhd;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
- if (dhd) {
- dhd_if_t *ifp;
- int i;
+ if (dhdp) {
+ dhd = (dhd_info_t *)dhdp->info;
+ if (dhd) {
+ dhd_if_t *ifp;
+ int i;
- for (i = 1; i < DHD_MAX_IFS; i++)
- if (dhd->iflist[i])
- dhd_del_if(dhd, i);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&dhd->early_suspend);
+#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
- ifp = dhd->iflist[0];
- ASSERT(ifp);
- if (ifp->net->open) {
- dhd_stop(ifp->net);
- unregister_netdev(ifp->net);
- }
+ for (i = 1; i < DHD_MAX_IFS; i++)
+ if (dhd->iflist[i])
+ dhd_del_if(dhd, i);
+
+ ifp = dhd->iflist[0];
+ ASSERT(ifp);
+ if (ifp->net->open) {
+ dhd_stop(ifp->net);
+ unregister_netdev(ifp->net);
+ }
if (dhd->watchdog_pid >= 0)
@@ -1798,18 +2039,17 @@ dhd_detach(dhd_pub_t *dhdp)
wl_iw_detach();
#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
+ unregister_pm_notifier(&dhd_sleep_pm_notifier);
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+ WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_TMOUT);
+ WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_LINK_DOWN_TMOUT);
free_netdev(ifp->net);
-#ifdef CONFIG_HAS_WAKELOCK
- wake_lock_destroy(&dhd->wl_wifi);
- wake_lock_destroy(&dhd->wl_rxwake);
-#endif
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
MFREE(dhd->pub.osh, dhd, sizeof(*dhd));
}
}
-
-int dhd_customer_wifi_add_dev(void);
-void dhd_customer_wifi_del_dev(void);
+}
static int __init
dhd_module_init(void)
@@ -1828,21 +2068,50 @@ dhd_module_init(void)
if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0) && dhd_deferred_tx)
break;
- printk("Invalid module parameters.\n");
+ DHD_ERROR(("Invalid module parameters.\n"));
return -EINVAL;
} while (0);
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+ sema_init(&wifi_control_sem, 0);
+ wifi_add_dev();
+
+ /* Waiting callback after platform_driver_register is done or exit with error */
+ if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
+ error = 1;
+ DHD_ERROR(("%s: platform_driver_register callback timeout\n", __FUNCTION__));
+ goto fail;
+ }
+#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+
+ /* Call customer gpio to turn on power with WL_REG_ON signal */
+ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
+ sema_init(&dhd_registration_sem, 0);
+#endif
+
error = dhd_bus_register();
- if (error)
- return error;
-
- error = dhd_customer_wifi_add_dev();
- if (error) {
- printk(KERN_ERR "%s: Fail to add wifi device\n", __func__);
- dhd_bus_unregister();
- }
- else
+
+ if (!error)
printf("\n%s\n", dhd_version);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
+ /*
+ * Wait till MMC sdio_register_driver callback called and made driver attach.
+ * It's needed to make sync up exit from dhd insmod and
+ * Kernel MMC sdio device callback registration
+ */
+ if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(3000)) != 0) {
+ error = 1;
+ DHD_ERROR(("%s: sdio_register_driver failed \n", __FUNCTION__));
+ }
+#endif
+
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+fail:
+#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+
return error;
}
@@ -1850,10 +2119,16 @@ static void __exit
dhd_module_cleanup(void)
{
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
dhd_bus_unregister();
- dhd_customer_wifi_del_dev();
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+ wifi_del_dev();
+#endif
+ /* Call customer gpio to turn off power with WL_REG_ON signal */
+ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
}
+
module_init(dhd_module_init);
module_exit(dhd_module_cleanup);
@@ -2007,7 +2282,7 @@ dhd_os_sdlock(dhd_pub_t *pub)
if (dhd->threads_only)
down(&dhd->sdsem);
else
- spin_lock_bh(&dhd->sdlock);
+ spin_lock_bh(&dhd->sdlock);
}
void
@@ -2020,7 +2295,7 @@ dhd_os_sdunlock(dhd_pub_t *pub)
if (dhd->threads_only)
up(&dhd->sdsem);
else
- spin_unlock_bh(&dhd->sdlock);
+ spin_unlock_bh(&dhd->sdlock);
}
void
@@ -2061,6 +2336,29 @@ dhd_os_sdtxunlock(dhd_pub_t *pub)
dhd_os_sdunlock(pub);
}
+#ifdef DHD_USE_STATIC_BUF
+void * dhd_os_prealloc(int section, unsigned long size)
+{
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+ void *alloc_ptr = NULL;
+ if (wifi_control_data && wifi_control_data->mem_prealloc)
+ {
+ alloc_ptr = wifi_control_data->mem_prealloc(section, size);
+ if (alloc_ptr)
+ {
+ DHD_INFO(("success alloc section %d\n", section));
+ bzero(alloc_ptr, size);
+ return alloc_ptr;
+ }
+ }
+
+ DHD_ERROR(("can't alloc section %d\n", section));
+ return 0;
+#else
+return MALLOC(0, size);
+#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
+}
+#endif /* DHD_USE_STATIC_BUF */
#ifdef CONFIG_WIRELESS_EXT
struct iw_statistics *
dhd_get_wireless_stats(struct net_device *dev)
@@ -2148,90 +2446,30 @@ dhd_dev_init_ioctl(struct net_device *dev)
dhd_preinit_ioctls(&dhd->pub);
}
-int dhd_os_wake_lock_timeout(dhd_pub_t *pub)
-{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&dhd->wl_lock, flags);
- if (dhd) {
-#ifdef CONFIG_HAS_WAKELOCK
- if (dhd->wl_packet)
- wake_lock_timeout(&dhd->wl_rxwake, (HZ >> 1));
-#endif
- dhd->wl_packet = 0;
- }
- ret = dhd->wl_packet;
- spin_unlock_irqrestore(&dhd->wl_lock, flags);
- /* printk("%s: %d\n", __FUNCTION__, ret); */
- return ret;
-}
-
-int dhd_os_wake_lock(dhd_pub_t *pub)
-{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&dhd->wl_lock, flags);
- if (dhd) {
-#ifdef CONFIG_HAS_WAKELOCK
- if (!dhd->wl_count)
- wake_lock(&dhd->wl_wifi);
-#endif
- dhd->wl_count++;
- ret = dhd->wl_count;
- }
- spin_unlock_irqrestore(&dhd->wl_lock, flags);
- if (ret > 2)
- printk("%s: Warning: %d\n", __FUNCTION__, ret);
- return ret;
-}
-
-int dhd_os_wake_unlock(dhd_pub_t *pub)
+static int
+dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&dhd->wl_lock, flags);
- if (dhd && dhd->wl_count) {
- dhd->wl_count--;
-#ifdef CONFIG_HAS_WAKELOCK
- if (!dhd->wl_count)
- wake_unlock(&dhd->wl_wifi);
-#endif
- ret = dhd->wl_count;
- }
- spin_unlock_irqrestore(&dhd->wl_lock, flags);
- /* printk("%s: %d\n", __FUNCTION__, ret); */
- return ret;
+ return (atomic_read(&dhd->pend_8021x_cnt));
}
-void dhd_os_set_irq(unsigned int irq, dhd_pub_t *pub)
-{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+#define MAX_WAIT_FOR_8021X_TX 10
- dhd->oob_irq = irq;
- disable_irq(irq);
- dhd->oob_irq_flag = 0;
-}
-
-void dhd_os_disable_irq(dhd_pub_t *pub)
-{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
- disable_irq_nosync(dhd->oob_irq);
- dhd->oob_irq_flag = 0;
-}
-
-void dhd_os_enable_irq(dhd_pub_t *pub)
+int
+dhd_wait_pend8021x(struct net_device *dev)
{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
-
- if (!(dhd->oob_irq_flag)) {
- dhd->oob_irq_flag = 1;
- enable_irq(dhd->oob_irq);
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int timeout = 10 * HZ / 1000;
+ int ntimes = MAX_WAIT_FOR_8021X_TX;
+ int pend = dhd_get_pend_8021x_cnt(dhd);
+
+ while (ntimes && pend) {
+ if (pend) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(timeout);
+ set_current_state(TASK_RUNNING);
+ ntimes--;
+ }
+ pend = dhd_get_pend_8021x_cnt(dhd);
}
+ return pend;
}
diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c
index ec4a9fa..6e43e43 100644
--- a/bcm4329/src/dhd/sys/dhd_sdio.c
+++ b/bcm4329/src/dhd/sys/dhd_sdio.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.77 2009/06/27 00:46:37 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.89 2009/10/28 05:49:40 Exp $
*/
#include <typedefs.h>
@@ -60,8 +60,6 @@
#include <dhdioctl.h>
#include <sdiovar.h>
-#include <linux/gpio.h>
-
#define QLEN 256 /* bulk rx and tx queue lengths */
#define FCHI (QLEN - 10)
#define FCLOW (FCHI / 2)
@@ -140,6 +138,8 @@
*/
#define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \
PKTFREE(bus->dhd->osh, pkt, FALSE);
+DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
+extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len);
/* Private data for SDIO bus interaction */
@@ -323,6 +323,13 @@ static bool forcealign;
#define ALIGNMENT 4
+#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
+extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
+#endif
+
+#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
+#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
+#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
#define PKTALIGN(osh, p, len, align) \
do { \
uint datalign; \
@@ -425,6 +432,7 @@ static int dhdsdio_download_nvram(struct dhd_bus *bus);
static int dhdsdio_download_code_array(struct dhd_bus *bus);
#endif
+
static void
dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size)
{
@@ -463,6 +471,9 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+#if defined(OOB_INTR_ONLY)
+ pendok = FALSE;
+#endif
clkctl = 0;
sdh = bus->sdh;
@@ -521,7 +532,8 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
/* Otherwise, wait here (polling) for HT Avail */
if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
- SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
+ SPINWAIT_SLEEP(sdioh_spinwait_sleep,
+ ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, &err)),
!SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
}
@@ -716,16 +728,8 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
return BCME_OK;
}
-int dhdsdio_oob(dhd_bus_t *bus)
-{
- sdpcmd_regs_t *regs = bus->regs;
- uint retries = 0;
-
- W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
- return 0;
-}
-
-int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
+int
+dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
{
bcmsdh_info_t *sdh = bus->sdh;
sdpcmd_regs_t *regs = bus->regs;
@@ -745,6 +749,7 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
return BCME_BUSY;
+
/* Disable SDIO interrupts (no longer interested) */
bcmsdh_intr_disable(bus->sdh);
@@ -763,21 +768,25 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
/* Isolate the bus */
-#if 0
- bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
- SBSDIO_DEVCTL_PADS_ISO, NULL);
-#endif
+ if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) {
+ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
+ SBSDIO_DEVCTL_PADS_ISO, NULL);
+ }
+
/* Change state */
bus->sleeping = TRUE;
} else {
/* Waking up: bus power up is ok, set local state */
+
bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
0, NULL);
+
/* Force pad isolation off if possible (in case power never toggled) */
if ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev >= 10))
bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
+
/* Make sure the controller has the bus up */
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
@@ -785,7 +794,8 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
W_SDREG(0, &regs->tosbmailboxdata, retries);
if (retries <= retry_limit)
W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
- else
+
+ if (retries > retry_limit)
DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
/* Make sure we have SD bus access */
@@ -800,8 +810,39 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
bcmsdh_intr_enable(bus->sdh);
}
}
+
return BCME_OK;
}
+#if defined(OOB_INTR_ONLY)
+void
+dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
+{
+#if defined(HW_OOB)
+ bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
+#else
+ sdpcmd_regs_t *regs = bus->regs;
+ uint retries = 0;
+
+ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+ if (enable == TRUE) {
+
+ /* Tell device to start using OOB wakeup */
+ W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
+ if (retries > retry_limit)
+ DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
+
+ } else {
+ /* Send misc interrupt to indicate OOB not needed */
+ W_SDREG(0, &regs->tosbmailboxdata, retries);
+ if (retries <= retry_limit)
+ W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
+ }
+
+ /* Turn off our contribution to the HT clock request */
+ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
+#endif /* defined(HW_OOB) */
+}
+#endif /* defined(OOB_INTR_ONLY) */
#define BUS_WAKE(bus) \
do { \
@@ -1466,7 +1507,7 @@ dhd_bus_clearcounts(dhd_pub_t *dhdp)
dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
- bus->rxrtx = bus->rx_toolong = bus->rx_toolong = bus->rxc_errors = 0;
+ bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
@@ -1538,6 +1579,11 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint s
uint32 sdaddr;
uint dsize;
+ if (size % 4) {
+ size += 3;
+ size &= 0xFFFFFFFC;
+ }
+
/* Determine initial transfer parameters */
sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
@@ -1910,11 +1956,11 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch
*(char *)arg = 0;
bcmstrcat(arg, "\nFunc 0\n");
- bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), 49 * 32);
+ bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
bcmstrcat(arg, "\nFunc 1\n");
- bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), 49 * 32);
+ bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
bcmstrcat(arg, "\nFunc 2\n");
- bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), 49 * 32);
+ bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
break;
}
@@ -2064,7 +2110,6 @@ dhdsdio_write_vars(dhd_bus_t *bus)
/* Compare the org NVRAM with the one read from RAM */
if (memcmp(vbuffer, nvram_ularray, varsize)) {
DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
- ASSERT(0);
} else
DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
__FUNCTION__));
@@ -3674,7 +3719,7 @@ dhdsdio_hostmail(dhd_bus_t *bus)
return intstatus;
}
-static bool
+bool
dhdsdio_dpc(dhd_bus_t *bus)
{
bcmsdh_info_t *sdh = bus->sdh;
@@ -3892,16 +3937,17 @@ clkwait:
resched = TRUE;
}
- dhd_os_sdunlock(bus->dhd);
bus->dpc_sched = resched;
/* If we're done for now, turn off clock request. */
- if (bus->idletime == DHD_IDLE_IMMEDIATE) {
+ if ((bus->clkstate != CLK_PENDING) && bus->idletime == DHD_IDLE_IMMEDIATE) {
bus->activity = FALSE;
dhdsdio_clkctl(bus, CLK_NONE, FALSE);
}
- dhd_os_wake_lock_timeout(bus->dhd); /* Keep wake lock for rx */
+
+ dhd_os_sdunlock(bus->dhd);
+
return resched;
}
@@ -3927,6 +3973,11 @@ dhdsdio_isr(void *arg)
dhd_bus_t *bus = (dhd_bus_t*)arg;
bcmsdh_info_t *sdh = bus->sdh;
+ if (bus->dhd->busstate == DHD_BUS_DOWN) {
+ DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
+ return;
+ }
+
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
/* Count the interrupt call */
@@ -3950,13 +4001,13 @@ dhdsdio_isr(void *arg)
bus->intdis = TRUE;
#if defined(SDIO_ISR_THREAD)
- dhd_os_wake_lock(bus->dhd);
+ DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
while (dhdsdio_dpc(bus));
- dhd_os_wake_unlock(bus->dhd);
#else
bus->dpc_sched = TRUE;
dhd_sched_dpc(bus->dhd);
#endif
+
}
#ifdef SDTEST
@@ -4326,8 +4377,6 @@ dhdsdio_chipmatch(uint16 chipid)
return FALSE;
}
-int dhd_customer_wifi_complete(void *);
-
static void *
dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
@@ -4480,11 +4529,9 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
goto fail;
}
- if (dhd_customer_wifi_complete(bus->dhd)) {
- DHD_ERROR(("%s: Platform resorce!!\n", __FUNCTION__));
- goto fail;
- }
+
return bus;
+
fail:
dhdsdio_release(bus, osh);
return NULL;
@@ -4645,6 +4692,7 @@ dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
{
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+#ifndef DHD_USE_STATIC_BUF
if (bus->dhd->maxctl) {
bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
if (!(bus->rxbuf = MALLOC(osh, bus->rxblen))) {
@@ -4662,6 +4710,22 @@ dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
if (!bus->rxblen) MFREE(osh, bus->rxbuf, bus->rxblen);
goto fail;
}
+#else
+ if (bus->dhd->maxctl) {
+ bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
+ if (!(bus->rxbuf = dhd_os_prealloc(DHD_PREALLOC_RXBUF, bus->rxblen))) {
+ DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
+ __FUNCTION__, bus->rxblen));
+ goto fail;
+ }
+ }
+ /* Allocate buffer to receive glomed packet */
+ if (!(bus->databuf = dhd_os_prealloc(DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
+ DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
+ __FUNCTION__, MAX_DATA_BUF));
+ goto fail;
+ }
+#endif /* DHD_USE_STATIC_BUF */
/* Align the buffer */
if ((uintptr)bus->databuf % DHD_SDALIGN)
@@ -4759,6 +4823,7 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
+
return ret;
}
@@ -4769,12 +4834,12 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
/* Download the firmware */
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
- dhd_os_wake_lock(bus->dhd);
- ret = _dhdsdio_download_firmware(bus);
- dhd_os_wake_unlock(bus->dhd);
+
+ ret = _dhdsdio_download_firmware(bus) == 0;
+
dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
- return !ret;
+ return ret;
}
/* Detach and free everything */
@@ -4818,13 +4883,17 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
return;
if (bus->rxbuf) {
+#ifndef DHD_USE_STATIC_BUF
MFREE(osh, bus->rxbuf, bus->rxblen);
+#endif
bus->rxctl = bus->rxbuf = NULL;
bus->rxlen = 0;
}
if (bus->databuf) {
+#ifndef DHD_USE_STATIC_BUF
MFREE(osh, bus->databuf, MAX_DATA_BUF);
+#endif
bus->databuf = NULL;
}
}
@@ -5066,7 +5135,7 @@ process_nvram_vars(char *varbuf, uint len)
return buf_len;
}
-/*
+/*
EXAMPLE: nvram_array
nvram_arry format:
name=value
@@ -5123,6 +5192,8 @@ dhdsdio_download_nvram(struct dhd_bus *bus)
else {
len = strlen(bus->nvram_params);
ASSERT(len <= MEMBLOCK);
+ if (len > MEMBLOCK)
+ len = MEMBLOCK;
memcpy(memblock, bus->nvram_params, len);
}
@@ -5283,6 +5354,10 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
if (flag == TRUE) {
if (!bus->dhd->dongle_reset) {
+#if !defined(IGNORE_ETH0_DOWN)
+ /* Force flow control as protection when stop come before ifconfig_down */
+ dhd_txflowcontrol(bus->dhd, 0, ON);
+#endif /* !defined(IGNORE_ETH0_DOWN) */
/* save country settinng if was pre-setup with priv ioctl */
dhdcdc_query_ioctl(bus->dhd, 0, WLC_GET_COUNTRY,
bus->dhd->country_code, sizeof(bus->dhd->country_code));
@@ -5321,8 +5396,18 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
/* Re-init bus, enable F2 transfer */
dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
+#if defined(OOB_INTR_ONLY)
+ dhd_enable_oob_intr(bus, TRUE);
+#endif /* defined(OOB_INTR_ONLY) */
+
bus->dhd->dongle_reset = FALSE;
bus->dhd->up = TRUE;
+
+#if !defined(IGNORE_ETH0_DOWN)
+ /* Restore flow control */
+ dhd_txflowcontrol(bus->dhd, 0, OFF);
+#endif
+
DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
} else
bcmerror = BCME_SDIO_ERROR;
diff --git a/bcm4329/src/include/bcmcdc.h b/bcm4329/src/include/bcmcdc.h
index 8cf50bc..641d755 100644
--- a/bcm4329/src/include/bcmcdc.h
+++ b/bcm4329/src/include/bcmcdc.h
@@ -74,11 +74,7 @@ typedef struct cdc_ioctl {
#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
-#ifndef EXT_STA
#define BDC_FLAG__UNUSED 0x03 /* Unassigned */
-#else
-#define BDC_FLAG_EXEMPT 0x03 /* Vista/EXT_STA: use for encryption exemption */
-#endif /* EXT_STA */
#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */
#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */
diff --git a/bcm4329/src/include/bcmdefs.h b/bcm4329/src/include/bcmdefs.h
index 2a494b9..ba7a9e4 100644
--- a/bcm4329/src/include/bcmdefs.h
+++ b/bcm4329/src/include/bcmdefs.h
@@ -20,38 +20,15 @@
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
- * $Id: bcmdefs.h,v 13.38.4.10.2.7.6.7 2009/05/21 06:48:31 Exp $
+ * $Id: bcmdefs.h,v 13.38.4.10.2.7.6.10 2009/07/03 08:20:51 Exp $
*/
#ifndef _bcmdefs_h_
#define _bcmdefs_h_
-
-
-
-
-
-
-#define bcmreclaimed 0
-#define r2_reclaimed 0
-#define _data _data
-#define _fn _fn
-#define _data _data
-#define _fn _fn
-#define _fn _fn
-#define BCMPREATTACHDATA(_data) _data
-#define BCMPREATTACHFN(_fn) _fn
-#define CONST const
-
-
-
-#define _data _data
-#define _fn _fn
-#define _fn _fn
#define STATIC static
-
#define SI_BUS 0
#define PCI_BUS 1
#define PCMCIA_BUS 2
diff --git a/bcm4329/src/include/bcmdevs.h b/bcm4329/src/include/bcmdevs.h
index 9c0891c..80b2ea8 100644
--- a/bcm4329/src/include/bcmdevs.h
+++ b/bcm4329/src/include/bcmdevs.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.14 2009/06/09 13:40:43 Exp $
+ * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.19 2009/09/18 23:51:17 Exp $
*/
diff --git a/bcm4329/src/include/bcmsdbus.h b/bcm4329/src/include/bcmsdbus.h
index c933bc1..0e629c0 100644
--- a/bcm4329/src/include/bcmsdbus.h
+++ b/bcm4329/src/include/bcmsdbus.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdbus.h,v 13.11.14.2.6.4 2009/04/13 19:00:01 Exp $
+ * $Id: bcmsdbus.h,v 13.11.14.2.6.6 2009/10/27 17:20:28 Exp $
*/
#ifndef _sdio_api_h_
@@ -74,11 +74,6 @@ extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
extern bool sdioh_interrupt_pending(sdioh_info_t *si);
#endif
-#ifdef BCMLXSDMMC
-extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
-extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
-#endif /* BCMLXSDMMC */
-
/* read or write one byte using cmd52 */
extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte);
diff --git a/bcm4329/src/include/bcmsdh.h b/bcm4329/src/include/bcmsdh.h
index 4bcc8bd..f8ab8ab 100644
--- a/bcm4329/src/include/bcmsdh.h
+++ b/bcm4329/src/include/bcmsdh.h
@@ -23,7 +23,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh.h,v 13.35.14.7.6.7 2009/06/03 18:25:31 Exp $
+ * $Id: bcmsdh.h,v 13.35.14.7.6.8 2009/10/14 04:22:25 Exp $
*/
#ifndef _bcmsdh_h_
@@ -190,6 +190,11 @@ extern void bcmsdh_unregister(void);
extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device);
extern void bcmsdh_device_remove(void * sdh);
+#if defined(OOB_INTR_ONLY)
+extern int bcmsdh_register_oob_intr(void * dhdp);
+extern void bcmsdh_unregister_oob_intr(void);
+extern void bcmsdh_oob_intr_set(bool enable);
+#endif /* defined(OOB_INTR_ONLY) */
/* Function to pass device-status bits to DHD. */
extern uint32 bcmsdh_get_dstatus(void *sdh);
diff --git a/bcm4329/src/include/bcmsdh_sdmmc.h b/bcm4329/src/include/bcmsdh_sdmmc.h
index 2333c74..b572f34 100644
--- a/bcm4329/src/include/bcmsdh_sdmmc.h
+++ b/bcm4329/src/include/bcmsdh_sdmmc.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc.h,v 13.1.2.1.8.5 2009/04/09 03:21:12 Exp $
+ * $Id: bcmsdh_sdmmc.h,v 13.1.2.1.8.7 2009/10/27 18:22:52 Exp $
*/
#ifndef __BCMSDH_SDMMC_H__
@@ -117,7 +117,6 @@ extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
typedef struct _BCMSDH_SDMMC_INSTANCE {
sdioh_info_t *sd;
struct sdio_func *func[SDIOD_MAX_IOFUNCS];
- uint32 host_claimed;
} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
#endif /* __BCMSDH_SDMMC_H__ */
diff --git a/bcm4329/src/include/bcmspibrcm.h b/bcm4329/src/include/bcmspibrcm.h
deleted file mode 100644
index a422373..0000000
--- a/bcm4329/src/include/bcmspibrcm.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
- *
- * Copyright (C) 2009, Broadcom Corporation
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
- * the contents of this file may not be disclosed to third parties, copied
- * or duplicated in any form, in whole or in part, without the prior
- * written permission of Broadcom Corporation.
- *
- * $Id: bcmspibrcm.h,v 1.4.4.1.4.3.6.1 2008/09/27 17:03:25 Exp $
- */
-
-/* global msglevel for debug messages - bitvals come from sdiovar.h */
-
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-
-#define sd_log(x)
-
-#define SDIOH_ASSERT(exp) \
- do { if (!(exp)) \
- printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
- } while (0)
-
-#define BLOCK_SIZE_F1 64
-#define BLOCK_SIZE_F2 2048
-#define BLOCK_SIZE_F3 2048
-
-/* internal return code */
-#define SUCCESS 0
-#undef ERROR
-#define ERROR 1
-#define ERROR_UF 2
-#define ERROR_OF 3
-
-/* private bus modes */
-#define SDIOH_MODE_SPI 0
-
-#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
-#define USE_MULTIBLOCK 0x4
-
-struct sdioh_info {
- uint cfg_bar; /* pci cfg address for bar */
- uint32 caps; /* cached value of capabilities reg */
- void *bar0; /* BAR0 for PCI Device */
- osl_t *osh; /* osh handler */
- void *controller; /* Pointer to SPI Controller's private data struct */
-
- uint lockcount; /* nest count of spi_lock() calls */
- bool client_intr_enabled; /* interrupt connnected flag */
- bool intr_handler_valid; /* client driver interrupt handler valid */
- sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
- void *intr_handler_arg; /* argument to call interrupt handler */
- bool initialized; /* card initialized */
- uint32 target_dev; /* Target device ID */
- uint32 intmask; /* Current active interrupts */
- void *sdos_info; /* Pointer to per-OS private data */
-
- uint32 controller_type; /* Host controller type */
- uint8 version; /* Host Controller Spec Compliance Version */
- uint irq; /* Client irq */
- uint32 intrcount; /* Client interrupts */
- uint32 local_intrcount; /* Controller interrupts */
- bool host_init_done; /* Controller initted */
- bool card_init_done; /* Client SDIO interface initted */
- bool polled_mode; /* polling for command completion */
-
- bool sd_use_dma; /* DMA on CMD53 */
- bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
- /* Must be on for sd_multiblock to be effective */
- bool use_client_ints; /* If this is false, make sure to restore */
- /* polling hack in wl_linux.c:wl_timer() */
- int adapter_slot; /* Maybe dealing with multiple slots/controllers */
- int sd_mode; /* SD1/SD4/SPI */
- int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */
- uint32 data_xfer_count; /* Current transfer */
- uint16 card_rca; /* Current Address */
- uint8 num_funcs; /* Supported funcs on client */
- uint32 card_dstatus; /* 32bit device status */
- uint32 com_cis_ptr;
- uint32 func_cis_ptr[SPI_MAX_IOFUNCS];
- void *dma_buf;
- ulong dma_phys;
- int r_cnt; /* rx count */
- int t_cnt; /* tx_count */
- uint32 wordlen; /* host processor 16/32bits */
- uint32 prev_fun;
- uint32 chip;
- uint32 chiprev;
- bool resp_delay_all;
- bool dwordmode;
-
- struct spierrstats_t spierrstats;
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmspibrcm.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/**************************************************************
- * Internal interfaces: bcmspibrcm.c references to per-port code
- */
-
-/* Interrupt (de)registration routines */
-extern int spi_register_irq(sdioh_info_t *sd, uint irq);
-extern void spi_free_irq(uint irq, sdioh_info_t *sd);
-
-/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
-extern void spi_lock(sdioh_info_t *sd);
-extern void spi_unlock(sdioh_info_t *sd);
-
-/* Allocate/init/free per-OS private data */
-extern int spi_osinit(sdioh_info_t *sd);
-extern void spi_osfree(sdioh_info_t *sd);
-
-#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */
-#define SPI_RW_FLAG_S 31
-#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */
-#define SPI_ACCESS_S 30
-#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */
-#define SPI_FUNCTION_S 28
-#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */
-#define SPI_REG_ADDR_S 11
-#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */
-#define SPI_LEN_S 0
diff --git a/bcm4329/src/include/bcmutils.h b/bcm4329/src/include/bcmutils.h
index b34550f..93bf25f 100644
--- a/bcm4329/src/include/bcmutils.h
+++ b/bcm4329/src/include/bcmutils.h
@@ -20,7 +20,7 @@
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
- * $Id: bcmutils.h,v 13.184.4.6.2.1.18.17 2009/06/18 02:31:37 Exp $
+ * $Id: bcmutils.h,v 13.184.4.6.2.1.18.22 2009/10/28 18:25:39 Exp $
*/
@@ -123,8 +123,12 @@ struct spktq {
+
struct ether_addr;
+extern int ether_isbcast(const void *ea);
+extern int ether_isnulladdr(const void *ea);
+
#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max))
diff --git a/bcm4329/src/include/bcmwifi.h b/bcm4329/src/include/bcmwifi.h
index f5a5874..8f5f3dc 100644
--- a/bcm4329/src/include/bcmwifi.h
+++ b/bcm4329/src/include/bcmwifi.h
@@ -22,7 +22,7 @@
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
- * $Id: bcmwifi.h,v 1.15 2007/11/19 22:23:04 Exp $
+ * $Id: bcmwifi.h,v 1.15.30.1 2009/08/15 00:51:27 Exp $
*/
@@ -84,17 +84,30 @@ typedef uint16 chanspec_t;
((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \
WL_CHANSPEC_BAND_5G))
#define CHSPEC_CHANNEL(chspec) ((uint8)(chspec & WL_CHANSPEC_CHAN_MASK))
-#define CHSPEC_CTL_SB(chspec) (chspec & WL_CHANSPEC_CTL_SB_MASK)
-#define CHSPEC_BW(chspec) (chspec & WL_CHANSPEC_BW_MASK)
#define CHSPEC_BAND(chspec) (chspec & WL_CHANSPEC_BAND_MASK)
+#ifdef WL20MHZ_ONLY
+
+#define CHSPEC_CTL_SB(chspec) WL_CHANSPEC_CTL_SB_NONE
+#define CHSPEC_BW(chspec) WL_CHANSPEC_BW_20
+#define CHSPEC_IS10(chspec) 0
+#define CHSPEC_IS20(chspec) 1
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec) 0
+#endif
+
+#else
+
+#define CHSPEC_CTL_SB(chspec) (chspec & WL_CHANSPEC_CTL_SB_MASK)
+#define CHSPEC_BW(chspec) (chspec & WL_CHANSPEC_BW_MASK)
#define CHSPEC_IS10(chspec) ((chspec & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10)
#define CHSPEC_IS20(chspec) ((chspec & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20)
-
#ifndef CHSPEC_IS40
#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40)
#endif
+#endif
+
#define CHSPEC_IS5G(chspec) ((chspec & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G)
#define CHSPEC_IS2G(chspec) ((chspec & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G)
#define CHSPEC_SB_NONE(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
diff --git a/bcm4329/src/include/dhdioctl.h b/bcm4329/src/include/dhdioctl.h
index 866c362..ee78c3d 100644
--- a/bcm4329/src/include/dhdioctl.h
+++ b/bcm4329/src/include/dhdioctl.h
@@ -25,7 +25,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.2 2009/02/03 18:36:10 Exp $
+ * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.4 2009/09/05 16:50:35 Exp $
*/
#ifndef _dhdioctl_h_
@@ -118,4 +118,5 @@ typedef struct dhd_pktgen {
/* require default structure packing */
#include <packed_section_end.h>
+
#endif /* _dhdioctl_h_ */
diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h
index bc5e933..e16e102 100644
--- a/bcm4329/src/include/epivers.h
+++ b/bcm4329/src/include/epivers.h
@@ -31,18 +31,18 @@
#define EPI_MINOR_VERSION 218
-#define EPI_RC_NUMBER 97
+#define EPI_RC_NUMBER 161
#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 218, 97, 0
+#define EPI_VERSION 4, 218, 161, 0
-#define EPI_VERSION_NUM 0x04da6100
+#define EPI_VERSION_NUM 0x04daa100
-#define EPI_VERSION_STR "4.218.97.0"
-#define EPI_ROUTER_VERSION_STR "4.219.97.0"
+#define EPI_VERSION_STR "4.218.161.0"
+#define EPI_ROUTER_VERSION_STR "4.219.161.0"
#endif
diff --git a/bcm4329/src/include/epivers.h.in b/bcm4329/src/include/epivers.h.in
deleted file mode 100644
index 8dc37fa..0000000
--- a/bcm4329/src/include/epivers.h.in
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 1999-2009, Broadcom Corporation
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- *
- * As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module. An independent module is a module which is not
- * derived from this software. The special exception does not apply to any
- * modifications of the software.
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- * $Id: epivers.h.in,v 13.25 2005/10/28 18:35:33 Exp $
- *
-*/
-
-
-#ifndef _epivers_h_
-#define _epivers_h_
-
-#define EPI_MAJOR_VERSION @EPI_MAJOR_VERSION@
-
-#define EPI_MINOR_VERSION @EPI_MINOR_VERSION@
-
-#define EPI_RC_NUMBER @EPI_RC_NUMBER@
-
-#define EPI_INCREMENTAL_NUMBER @EPI_INCREMENTAL_NUMBER@
-
-#define EPI_BUILD_NUMBER @EPI_BUILD_NUMBER@
-
-#define EPI_VERSION @EPI_VERSION@
-
-#define EPI_VERSION_NUM @EPI_VERSION_NUM@
-
-
-#define EPI_VERSION_STR "@EPI_VERSION_STR@"
-#define EPI_ROUTER_VERSION_STR "@EPI_ROUTER_VERSION_STR@"
-
-#endif
diff --git a/bcm4329/src/include/epivers.sh b/bcm4329/src/include/epivers.sh
deleted file mode 100644
index b0659e0..0000000
--- a/bcm4329/src/include/epivers.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#! /bin/bash
-#
-# Create the epivers.h file from epivers.h.in
-#
-# $Id: epivers.sh,v 13.19 2008/01/04 03:47:32 Exp $
-
-# Check for the in file, if not there we're probably in the wrong directory
-if [ ! -f epivers.h.in ]; then
- echo No epivers.h.in found
- exit 1
-fi
-
-if [ -f epivers.h ]; then
- # If the out file already exists, increment its build number
- build=`grep EPI_BUILD_NUMBER epivers.h | sed -e "s,.*BUILD_NUMBER[ ]*,,"`
- build=`expr ${build} + 1`
- echo build=${build}
- sed -e "s,.*_BUILD_NUMBER.*,#define EPI_BUILD_NUMBER ${build}," \
- < epivers.h > epivers.h.new
- mv epivers.h epivers.h.prev
- mv epivers.h.new epivers.h
-else
- # Otherwise create a new file.
-
- # CVS will insert the cvs tag name when this file is checked out.
- # If this is a tagged build, use the tag to supply the numbers
- # Tag should be in the form
- # <NAME>_REL_<MAJ>_<MINOR>
- # or
- # <NAME>_REL_<MAJ>_<MINOR>_RC<RCNUM>
- # or
- # <NAME>_REL_<MAJ>_<MINOR>_RC<RCNUM>_<INCREMENTAL>
- #
-
- CVSTAG="$Name: ROMTERM_REL_4_218_97 $"
-
- # Remove leading cvs "Name: " and trailing " $"
- CVSTAG=${CVSTAG/#*: /}
- CVSTAG=${CVSTAG/% $/}
-
- # TAG env var is supplied by calling makefile or build process
- #
- # If the checkout is from a branch tag, cvs checkout or export does
- # not replace rcs keywords. In such instances TAG env variable can
- # be used (by uncommenting following line). TAG env variable format
- # itself needs to be validated for number of fields before being used.
- # (e.g: HEAD is not a valid tag, which results in all '0' values below)
- #
- # TAG=${TAG:-${CVSTAG}}
-
- TAG=${CVSTAG/HEAD/}
-
- # Split the tag into an array on underbar or whitespace boundaries.
- IFS="_ " tag=(${TAG})
- unset IFS
-
- tagged=1
- if [ ${#tag[*]} -eq 0 ]; then
- tag=(`date '+TOT REL %Y %m %d 0 %y'`);
- tagged=0
- fi
-
- # Allow environment variable to override values.
- # Missing values default to 0
- #
- maj=${EPI_MAJOR_VERSION:-${tag[2]:-0}}
- min=${EPI_MINOR_VERSION:-${tag[3]:-0}}
- rcnum=${EPI_RC_NUMBER:-${tag[4]:-0}}
- incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}}
- build=${EPI_BUILD_NUMBER:-0}
-
- # Strip 'RC' from front of rcnum if present
- rcnum=${rcnum/#RC/}
-
- # strip leading zero off the number (otherwise they look like octal)
- maj=${maj/#0/}
- min=${min/#0/}
- min_router=${min}
- rcnum=${rcnum/#0/}
- incremental=${incremental/#0/}
- build=${build/#0/}
-
- # some numbers may now be null. replace with with zero.
- maj=${maj:-0}
- min=${min:-0}
- rcnum=${rcnum:-0}
- incremental=${incremental:-0}
- build=${build:-0}
-
- if [ ${tagged} -eq 1 ]; then
- vernum=`printf "0x%02x%02x%02x%02x" ${maj} ${min} ${rcnum} ${incremental}`
- else
- vernum=`printf "0x00%02x%02x%02x" ${tag[7]} ${min} ${rcnum}`
- fi
-
-
- # PR17029: increment minor number for tagged router builds
- # with an even minor revision
- if [ ${tagged} -eq 1 -a `expr \( \( ${min} + 1 \) % 2 \)` -eq 1 ]; then
- min_router=`expr ${min} + 1`
- fi
-
-
- # OK, go do it
-
- echo "maj=${maj}, min=${min}, rc=${rcnum}, inc=${incremental}, build=${build}"
- echo "Router maj=${maj}, min=${min_router}, rc=${rcnum}, inc=${incremental}, build=${build}"
-
- sed \
- -e "s;@EPI_MAJOR_VERSION@;${maj};" \
- -e "s;@EPI_MINOR_VERSION@;${min};" \
- -e "s;@EPI_RC_NUMBER@;${rcnum};" \
- -e "s;@EPI_INCREMENTAL_NUMBER@;${incremental};" \
- -e "s;@EPI_BUILD_NUMBER@;${build};" \
- -e "s;@EPI_VERSION@;${maj}, ${min}, ${rcnum}, ${incremental};" \
- -e "s;@EPI_VERSION_STR@;${maj}.${min}.${rcnum}.${incremental};" \
- -e "s;@EPI_ROUTER_VERSION_STR@;${maj}.${min_router}.${rcnum}.${incremental};" \
- -e "s;@EPI_VERSION_NUM@;${vernum};" \
- < epivers.h.in > epivers.h
-
-fi
diff --git a/bcm4329/src/include/hndpmu.h b/bcm4329/src/include/hndpmu.h
index f764881..afd78d7 100644
--- a/bcm4329/src/include/hndpmu.h
+++ b/bcm4329/src/include/hndpmu.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: hndpmu.h,v 13.14.4.3.4.3.8.5 2009/06/25 16:07:18 Exp $
+ * $Id: hndpmu.h,v 13.14.4.3.4.3.8.6 2009/09/14 09:21:45 Exp $
*/
#ifndef _hndpmu_h_
diff --git a/bcm4329/src/include/linux_osl.h b/bcm4329/src/include/linux_osl.h
index e7b23dd..98afe9c 100644
--- a/bcm4329/src/include/linux_osl.h
+++ b/bcm4329/src/include/linux_osl.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: linux_osl.h,v 13.131.30.1 2008/12/16 00:25:42 Exp $
+ * $Id: linux_osl.h,v 13.131.30.5 2009/10/27 04:42:45 Exp $
*/
@@ -108,7 +108,7 @@ extern uint osl_malloc_failed(osl_t *osh);
#define DMA_CONSISTENT_ALIGN PAGE_SIZE
-#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah) \
+#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah, alignbits) \
osl_dma_alloc_consistent((osh), (size), (pap))
#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
osl_dma_free_consistent((osh), (void*)(va), (size), (pa))
@@ -233,6 +233,10 @@ extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction);
#define PKTGET(osh, len, send) osl_pktget((osh), (len))
#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send))
+#ifdef DHD_USE_STATIC_BUF
+#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len))
+#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send))
+#endif
#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data)
#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len)
#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head))
@@ -245,10 +249,18 @@ extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction);
#define PKTDUP(osh, skb) osl_pktdup((osh), (skb))
#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb))
#define PKTALLOCED(osh) ((osl_pubinfo_t *)(osh))->pktalloced
+#define PKTSETPOOL(osh, skb, x, y) do {} while (0)
+#define PKTPOOL(osh, skb) FALSE
+#define PKTPOOLLEN(osh, pktp) (0)
+#define PKTPOOLAVAIL(osh, pktp) (0)
+#define PKTPOOLADD(osh, pktp, p) BCME_ERROR
+#define PKTPOOLGET(osh, pktp) NULL
#define PKTLIST_DUMP(osh, buf)
extern void *osl_pktget(osl_t *osh, uint len);
extern void osl_pktfree(osl_t *osh, void *skb, bool send);
+extern void *osl_pktget_static(osl_t *osh, uint len);
+extern void osl_pktfree_static(osl_t *osh, void *skb, bool send);
extern void *osl_pktdup(osl_t *osh, void *skb);
diff --git a/bcm4329/src/include/proto/802.11.h b/bcm4329/src/include/proto/802.11.h
index 364f725..217bd6c 100644
--- a/bcm4329/src/include/proto/802.11.h
+++ b/bcm4329/src/include/proto/802.11.h
@@ -21,7 +21,7 @@
*
* Fundamental types and constants relating to 802.11
*
- * $Id: 802.11.h,v 9.219.4.1.4.5.6.9 2009/05/21 05:54:11 Exp $
+ * $Id: 802.11.h,v 9.219.4.1.4.5.6.10 2009/07/09 10:15:09 Exp $
*/
diff --git a/bcm4329/src/include/proto/bcmevent.h b/bcm4329/src/include/proto/bcmevent.h
index ecccbe3..1791478 100644
--- a/bcm4329/src/include/proto/bcmevent.h
+++ b/bcm4329/src/include/proto/bcmevent.h
@@ -24,7 +24,7 @@
*
* Dependencies: proto/bcmeth.h
*
- * $Id: bcmevent.h,v 9.34.4.1.20.12 2009/05/24 17:00:58 Exp $
+ * $Id: bcmevent.h,v 9.34.4.1.20.16 2009/09/25 23:52:38 Exp $
*
*/
@@ -131,7 +131,9 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
#define WLC_E_ACTION_FRAME 58
#define WLC_E_ACTION_FRAME_COMPLETE 59
-#define WLC_E_LAST 60
+#define WLC_E_ESCAN_RESULT 69
+#define WLC_E_WAKE_EVENT 70
+#define WLC_E_LAST 71
diff --git a/bcm4329/src/include/proto/ethernet.h b/bcm4329/src/include/proto/ethernet.h
index ea4f233..05530d5 100644
--- a/bcm4329/src/include/proto/ethernet.h
+++ b/bcm4329/src/include/proto/ethernet.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: ethernet.h,v 9.45.56.1 2008/11/20 00:51:28 Exp $
+ * $Id: ethernet.h,v 9.45.56.3 2009/08/15 00:51:27 Exp $
*/
@@ -124,23 +124,21 @@ BWL_PRE_PACKED_STRUCT struct ether_addr {
((short*)d)[2] = ((short*)s)[2]; }
-#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \
- ((uint8 *)(ea))[1] & \
- ((uint8 *)(ea))[2] & \
- ((uint8 *)(ea))[3] & \
- ((uint8 *)(ea))[4] & \
- ((uint8 *)(ea))[5]) == 0xff)
-
static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}};
-
-#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \
- ((uint8 *)(ea))[1] | \
- ((uint8 *)(ea))[2] | \
- ((uint8 *)(ea))[3] | \
- ((uint8 *)(ea))[4] | \
- ((uint8 *)(ea))[5]) == 0)
+#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \
+ ((uint8 *)(ea))[1] & \
+ ((uint8 *)(ea))[2] & \
+ ((uint8 *)(ea))[3] & \
+ ((uint8 *)(ea))[4] & \
+ ((uint8 *)(ea))[5]) == 0xff)
+#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \
+ ((uint8 *)(ea))[1] | \
+ ((uint8 *)(ea))[2] | \
+ ((uint8 *)(ea))[3] | \
+ ((uint8 *)(ea))[4] | \
+ ((uint8 *)(ea))[5]) == 0)
diff --git a/bcm4329/src/include/sbchipc.h b/bcm4329/src/include/sbchipc.h
index 7427521..80e6e56 100644
--- a/bcm4329/src/include/sbchipc.h
+++ b/bcm4329/src/include/sbchipc.h
@@ -5,7 +5,7 @@
* jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer,
* gpio interface, extbus, and support for serial and parallel flashes.
*
- * $Id: sbchipc.h,v 13.103.2.5.4.5.2.8 2009/01/21 23:56:32 Exp $
+ * $Id: sbchipc.h,v 13.103.2.5.4.5.2.9 2009/07/03 14:23:21 Exp $
*
* Copyright (C) 1999-2009, Broadcom Corporation
*
@@ -823,54 +823,11 @@ typedef volatile struct {
-#define PMU1_PLL0_PLLCTL0 0
-#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000
-#define PMU1_PLL0_PC0_P1DIV_SHIFT 20
-#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000
-#define PMU1_PLL0_PC0_P2DIV_SHIFT 24
-
-
-#define PMU1_PLL0_PLLCTL1 1
-#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff
-#define PMU1_PLL0_PC1_M1DIV_SHIFT 0
-#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00
-#define PMU1_PLL0_PC1_M2DIV_SHIFT 8
-#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000
-#define PMU1_PLL0_PC1_M3DIV_SHIFT 16
-#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000
-#define PMU1_PLL0_PC1_M4DIV_SHIFT 24
-
#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8
#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
-#define PMU1_PLL0_PLLCTL2 2
-#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff
-#define PMU1_PLL0_PC2_M5DIV_SHIFT 0
-#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00
-#define PMU1_PLL0_PC2_M6DIV_SHIFT 8
-#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000
-#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17
-#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1
-#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2
-#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
-#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
-
-
-#define PMU1_PLL0_PLLCTL3 3
-#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff
-#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0
-
-
-#define PMU1_PLL0_PLLCTL4 4
-
-
-#define PMU1_PLL0_PLLCTL5 5
-#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
-#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
-
-
#define PMU2_PHY_PLL_PLLCTL 4
#define PMU2_SI_PLL_PLLCTL 10
@@ -1044,58 +1001,6 @@ typedef volatile struct {
#define CST4315_CBUCK_MODE_BURST 0x00000400
#define CST4315_CBUCK_MODE_LPBURST 0x00000c00
-
-#define RES4319_CBUCK_LPOM 1
-#define RES4319_CBUCK_BURST 2
-#define RES4319_CBUCK_PWM 3
-#define RES4319_CLDO_PU 4
-#define RES4319_PALDO_PU 5
-#define RES4319_ILP_REQUEST 6
-#define RES4319_LNLDO1_PU 9
-#define RES4319_OTP_PU 10
-#define RES4319_LNLDO2_PU 12
-#define RES4319_XTAL_PU 13
-#define RES4319_ALP_AVAIL 14
-#define RES4319_RX_PWRSW_PU 15
-#define RES4319_TX_PWRSW_PU 16
-#define RES4319_RFPLL_PWRSW_PU 17
-#define RES4319_LOGEN_PWRSW_PU 18
-#define RES4319_AFE_PWRSW_PU 19
-#define RES4319_BBPLL_PWRSW_PU 20
-#define RES4319_HT_AVAIL 21
-
-#define CST4319_SPI_CPULESSUSB 0x00000001
-#define CST4319_SPI_CLK_POL 0x00000002
-#define CST4319_SPI_CLK_PH 0x00000008
-#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0
-#define CST4319_SPROM_OTP_SEL_SHIFT 6
-#define CST4319_DEFCIS_SEL 0x00000000
-#define CST4319_SPROM_SEL 0x00000040
-#define CST4319_OTP_SEL 0x00000080
-#define CST4319_OTP_PWRDN 0x000000c0
-#define CST4319_SDIO_USB_MODE 0x00000100
-#define CST4319_REMAP_SEL_MASK 0x00000600
-#define CST4319_ILPDIV_EN 0x00000800
-#define CST4319_XTAL_PD_POL 0x00001000
-#define CST4319_LPO_SEL 0x00002000
-#define CST4319_RES_INIT_MODE 0x0000c000
-#define CST4319_PALDO_EXTPNP 0x00010000
-#define CST4319_CBUCK_MODE_MASK 0x00060000
-#define CST4319_CBUCK_MODE_BURST 0x00020000
-#define CST4319_CBUCK_MODE_LPBURST 0x00060000
-#define CST4319_RCAL_VALID 0x01000000
-#define CST4319_RCAL_VALUE_MASK 0x3e000000
-#define CST4319_RCAL_VALUE_SHIFT 25
-
-#define PMU1_PLL0_CHIPCTL0 0
-#define PMU1_PLL0_CHIPCTL1 1
-#define PMU1_PLL0_CHIPCTL2 2
-#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000
-#define CCTL_4319USB_XTAL_SEL_SHIFT 19
-#define CCTL_4319USB_48MHZ_PLL_SEL 1
-#define CCTL_4319USB_24MHZ_PLL_SEL 2
-
-
#define PMU_MAX_TRANSITION_DLY 15000
diff --git a/bcm4329/src/include/sbhnddma.h b/bcm4329/src/include/sbhnddma.h
index 4ccc36f..2aeee9e 100644
--- a/bcm4329/src/include/sbhnddma.h
+++ b/bcm4329/src/include/sbhnddma.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: sbhnddma.h,v 13.11.250.5 2008/05/07 20:23:46 Exp $
+ * $Id: sbhnddma.h,v 13.11.250.5.16.1 2009/07/21 14:04:51 Exp $
*/
@@ -61,8 +61,9 @@ typedef volatile struct {
} dma32dd_t;
-#define D32MAXRINGSZ 4096
-#define D32RINGALIGN 4096
+#define D32RINGALIGN_BITS 12
+#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS)
+#define D32RINGALIGN (1 << D32RINGALIGN_BITS)
#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t))
@@ -188,8 +189,9 @@ typedef volatile struct {
} dma64dd_t;
-#define D64MAXRINGSZ 8192
-#define D64RINGALIGN 8192
+#define D64RINGALIGN_BITS 13
+#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS)
+#define D64RINGALIGN (1 << D64RINGALIGN_BITS)
#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t))
diff --git a/bcm4329/src/include/sdio.h b/bcm4329/src/include/sdio.h
index e849267..d20d69c 100644
--- a/bcm4329/src/include/sdio.h
+++ b/bcm4329/src/include/sdio.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: sdio.h,v 13.24.4.1.4.1 2008/05/06 22:57:29 Exp $
+ * $Id: sdio.h,v 13.24.4.1.4.1.16.1 2009/08/12 01:08:02 Exp $
*/
#ifndef _SDIO_H
@@ -80,6 +80,9 @@ typedef volatile struct {
#define SDIOD_CCCR_POWER_CONTROL 0x12
#define SDIOD_CCCR_SPEED_CONTROL 0x13
+/* Broadcom extensions (corerev >= 1) */
+#define SDIOD_CCCR_BRCM_SEPINT 0xf2
+
/* cccr_sdio_rev */
#define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */
#define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */
@@ -134,6 +137,11 @@ typedef volatile struct {
#define SDIO_SPEED_SHS 0x01 /* supports high-speed [clocking] mode (RO) */
#define SDIO_SPEED_EHS 0x02 /* enable high-speed [clocking] mode (RW) */
+/* brcm sepint */
+#define SDIO_SEPINT_MASK 0x01 /* route sdpcmdev intr onto separate pad (chip-specific) */
+#define SDIO_SEPINT_OE 0x02 /* 1 asserts output enable for above pad */
+#define SDIO_SEPINT_ACT_HI 0x04 /* use active high interrupt level instead of active low */
+
/* FBR structure for function 1-7, FBR addresses and register offsets */
typedef volatile struct {
uint8 devctr; /* device interface, CSA control */
@@ -162,7 +170,7 @@ typedef volatile struct {
#define SDIOD_FBR_SIZE 0x100
/* Macro to calculate FBR register base */
-#define SDIOD_FBR_BASE(n) (n * 0x100)
+#define SDIOD_FBR_BASE(n) ((n) * 0x100)
/* Function register offsets */
#define SDIOD_FBR_DEVCTR 0x00 /* basic info for function */
@@ -282,13 +290,13 @@ typedef volatile struct {
/* build SD_CMD_IO_RW_DIRECT Argument */
#define SDIO_IO_RW_DIRECT_ARG(rw, raw, func, addr, data) \
- (((rw & 1) << 31) | ((func & 0x7) << 28) | ((raw & 1) << 27) | \
- ((addr & 0x1FFFF) << 9) | (data & 0xFF))
+ ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((raw) & 1) << 27) | \
+ (((addr) & 0x1FFFF) << 9) | ((data) & 0xFF))
/* build SD_CMD_IO_RW_EXTENDED Argument */
#define SDIO_IO_RW_EXTENDED_ARG(rw, blk, func, addr, inc_addr, count) \
- (((rw & 1) << 31) | ((func & 0x7) << 28) | ((blk & 1) << 27) | \
- ((inc_addr & 1) << 26) | ((addr & 0x1FFFF) << 9) | (count & 0x1FF))
+ ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((blk) & 1) << 27) | \
+ (((inc_addr) & 1) << 26) | (((addr) & 0x1FFFF) << 9) | ((count) & 0x1FF))
/* SDIO response parameters */
#define SD_RSP_NO_NONE 0
diff --git a/bcm4329/src/include/sdioh.h b/bcm4329/src/include/sdioh.h
index 6681c7c..960e30c 100644
--- a/bcm4329/src/include/sdioh.h
+++ b/bcm4329/src/include/sdioh.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: sdioh.h,v 13.13.18.1.16.1 2008/08/26 23:49:40 Exp $
+ * $Id: sdioh.h,v 13.13.18.1.16.2 2009/07/28 17:54:46 Exp $
*/
#ifndef _SDIOH_H
@@ -211,7 +211,7 @@
#define SW_RESET_DAT_M BITFIELD_MASK(1) /* Bit 2 DAT Line Reset */
#define SW_RESET_DAT_S 2
-/* SD_IntStatus: Offset 0x030, size = 2 bytes */
+/* SD_IntrStatus: Offset 0x030, size = 2 bytes */
/* Defs also serve SD_IntrStatusEnable and SD_IntrSignalEnable */
#define INTSTAT_CMD_COMPLETE_M BITFIELD_MASK(1) /* Bit 0 */
#define INTSTAT_CMD_COMPLETE_S 0
@@ -277,7 +277,7 @@
/* SD_WakeupCntr_BlockGapCntrl : Offset 0x02A , size = bytes */
/* SD_ClockCntrl : Offset 0x02C , size = bytes */
-/* SD_SoftwarewReset_TimeoutCntrl : Offset 0x02E , size = bytes */
+/* SD_SoftwareReset_TimeoutCntrl : Offset 0x02E , size = bytes */
/* SD_IntrStatus : Offset 0x030 , size = bytes */
/* SD_ErrorIntrStatus : Offset 0x032 , size = bytes */
/* SD_IntrStatusEnable : Offset 0x034 , size = bytes */
diff --git a/bcm4329/src/include/siutils.h b/bcm4329/src/include/siutils.h
index eae4895..7be09d5 100644
--- a/bcm4329/src/include/siutils.h
+++ b/bcm4329/src/include/siutils.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: siutils.h,v 13.197.4.2.4.3.8.8 2009/06/25 16:07:18 Exp $
+ * $Id: siutils.h,v 13.197.4.2.4.3.8.12 2009/09/22 13:28:16 Exp $
*/
@@ -132,6 +132,7 @@ extern void *si_osh(si_t *sih);
extern void si_setosh(si_t *sih, osl_t *osh);
extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val);
extern void *si_coreregs(si_t *sih);
+extern void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val);
extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val);
extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val);
extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val);
diff --git a/bcm4329/src/include/spid.h b/bcm4329/src/include/spid.h
deleted file mode 100644
index 0c04153..0000000
--- a/bcm4329/src/include/spid.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * SPI device spec header file
- *
- * Copyright (C) 2009, Broadcom Corporation
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
- * the contents of this file may not be disclosed to third parties, copied
- * or duplicated in any form, in whole or in part, without the prior
- * written permission of Broadcom Corporation.
- *
- * $Id: spid.h,v 1.7.10.1.16.3 2009/04/09 19:23:14 Exp $
- */
-
-#ifndef _SPI_H
-#define _SPI_H
-
-/*
- * Brcm SPI Device Register Map.
- *
- */
-
-typedef volatile struct {
- uint8 config; /* 0x00, len, endian, clock, speed, polarity, wakeup */
- uint8 response_delay; /* 0x01, read response delay in bytes (corerev < 3) */
- uint8 status_enable; /* 0x02, status-enable, intr with status, response_delay
- * function selection, command/data error check
- */
- uint8 reset_bp; /* 0x03, reset on wlan/bt backplane reset (corerev >= 1) */
- uint16 intr_reg; /* 0x04, Intr status register */
- uint16 intr_en_reg; /* 0x06, Intr mask register */
- uint32 status_reg; /* 0x08, RO, Status bits of last spi transfer */
- uint16 f1_info_reg; /* 0x0c, RO, enabled, ready for data transfer, blocksize */
- uint16 f2_info_reg; /* 0x0e, RO, enabled, ready for data transfer, blocksize */
- uint16 f3_info_reg; /* 0x10, RO, enabled, ready for data transfer, blocksize */
- uint32 test_read; /* 0x14, RO 0xfeedbead signature */
- uint32 test_rw; /* 0x18, RW */
- uint8 resp_delay_f0; /* 0x1c, read resp delay bytes for F0 (corerev >= 3) */
- uint8 resp_delay_f1; /* 0x1d, read resp delay bytes for F1 (corerev >= 3) */
- uint8 resp_delay_f2; /* 0x1e, read resp delay bytes for F2 (corerev >= 3) */
- uint8 resp_delay_f3; /* 0x1f, read resp delay bytes for F3 (corerev >= 3) */
-} spi_regs_t;
-
-/* SPI device register offsets */
-#define SPID_CONFIG 0x00
-#define SPID_RESPONSE_DELAY 0x01
-#define SPID_STATUS_ENABLE 0x02
-#define SPID_RESET_BP 0x03 /* (corerev >= 1) */
-#define SPID_INTR_REG 0x04 /* 16 bits - Interrupt status */
-#define SPID_INTR_EN_REG 0x06 /* 16 bits - Interrupt mask */
-#define SPID_STATUS_REG 0x08 /* 32 bits */
-#define SPID_F1_INFO_REG 0x0C /* 16 bits */
-#define SPID_F2_INFO_REG 0x0E /* 16 bits */
-#define SPID_F3_INFO_REG 0x10 /* 16 bits */
-#define SPID_TEST_READ 0x14 /* 32 bits */
-#define SPID_TEST_RW 0x18 /* 32 bits */
-#define SPID_RESP_DELAY_F0 0x1c /* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F1 0x1d /* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F2 0x1e /* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F3 0x1f /* 8 bits (corerev >= 3) */
-
-/* Bit masks for SPID_CONFIG device register */
-#define WORD_LENGTH_32 0x1 /* 0/1 16/32 bit word length */
-#define ENDIAN_BIG 0x2 /* 0/1 Little/Big Endian */
-#define CLOCK_PHASE 0x4 /* 0/1 clock phase delay */
-#define CLOCK_POLARITY 0x8 /* 0/1 Idle state clock polarity is low/high */
-#define HIGH_SPEED_MODE 0x10 /* 1/0 High Speed mode / Normal mode */
-#define INTR_POLARITY 0x20 /* 1/0 Interrupt active polarity is high/low */
-#define WAKE_UP 0x80 /* 0/1 Wake-up command from Host to WLAN */
-
-/* Bit mask for SPID_RESPONSE_DELAY device register */
-#define RESPONSE_DELAY_MASK 0xFF /* Configurable rd response delay in multiples of 8 bits */
-
-/* Bit mask for SPID_STATUS_ENABLE device register */
-#define STATUS_ENABLE 0x1 /* 1/0 Status sent/not sent to host after read/write */
-#define INTR_WITH_STATUS 0x2 /* 0/1 Do-not / do-interrupt if status is sent */
-#define RESP_DELAY_ALL 0x4 /* Applicability of resp delay to F1 or all func's read */
-#define DWORD_PKT_LEN_EN 0x8 /* Packet len denoted in dwords instead of bytes */
-#define CMD_ERR_CHK_EN 0x20 /* Command error check enable */
-#define DATA_ERR_CHK_EN 0x40 /* Data error check enable */
-
-/* Bit mask for SPID_RESET_BP device register */
-#define RESET_ON_WLAN_BP_RESET 0x4 /* enable reset for WLAN backplane */
-#define RESET_ON_BT_BP_RESET 0x8 /* enable reset for BT backplane */
-#define RESET_SPI 0x80 /* reset the above enabled logic */
-
-/* Bit mask for SPID_INTR_REG device register */
-#define DATA_UNAVAILABLE 0x0001 /* Requested data not available; Clear by writing a "1" */
-#define F2_F3_FIFO_RD_UNDERFLOW 0x0002
-#define F2_F3_FIFO_WR_OVERFLOW 0x0004
-#define COMMAND_ERROR 0x0008 /* Cleared by writing 1 */
-#define DATA_ERROR 0x0010 /* Cleared by writing 1 */
-#define F2_PACKET_AVAILABLE 0x0020
-#define F3_PACKET_AVAILABLE 0x0040
-#define F1_OVERFLOW 0x0080 /* Due to last write. Bkplane has pending write requests */
-#define MISC_INTR0 0x0100
-#define MISC_INTR1 0x0200
-#define MISC_INTR2 0x0400
-#define MISC_INTR3 0x0800
-#define MISC_INTR4 0x1000
-#define F1_INTR 0x2000
-#define F2_INTR 0x4000
-#define F3_INTR 0x8000
-
-/* Bit mask for 32bit SPID_STATUS_REG device register */
-#define STATUS_DATA_NOT_AVAILABLE 0x00000001
-#define STATUS_UNDERFLOW 0x00000002
-#define STATUS_OVERFLOW 0x00000004
-#define STATUS_F2_INTR 0x00000008
-#define STATUS_F3_INTR 0x00000010
-#define STATUS_F2_RX_READY 0x00000020
-#define STATUS_F3_RX_READY 0x00000040
-#define STATUS_HOST_CMD_DATA_ERR 0x00000080
-#define STATUS_F2_PKT_AVAILABLE 0x00000100
-#define STATUS_F2_PKT_LEN_MASK 0x000FFE00
-#define STATUS_F2_PKT_LEN_SHIFT 9
-#define STATUS_F3_PKT_AVAILABLE 0x00100000
-#define STATUS_F3_PKT_LEN_MASK 0xFFE00000
-#define STATUS_F3_PKT_LEN_SHIFT 21
-
-/* Bit mask for 16 bits SPID_F1_INFO_REG device register */
-#define F1_ENABLED 0x0001
-#define F1_RDY_FOR_DATA_TRANSFER 0x0002
-#define F1_MAX_PKT_SIZE 0x01FC
-
-/* Bit mask for 16 bits SPID_F2_INFO_REG device register */
-#define F2_ENABLED 0x0001
-#define F2_RDY_FOR_DATA_TRANSFER 0x0002
-#define F2_MAX_PKT_SIZE 0x3FFC
-
-/* Bit mask for 16 bits SPID_F3_INFO_REG device register */
-#define F3_ENABLED 0x0001
-#define F3_RDY_FOR_DATA_TRANSFER 0x0002
-#define F3_MAX_PKT_SIZE 0x3FFC
-
-/* Bit mask for 32 bits SPID_TEST_READ device register read in 16bit LE mode */
-#define TEST_RO_DATA_32BIT_LE 0xFEEDBEAD
-
-/* Maximum number of I/O funcs */
-#define SPI_MAX_IOFUNCS 4
-
-#define SPI_MAX_PKT_LEN (2048*4)
-
-/* Misc defines */
-#define SPI_FUNC_0 0
-#define SPI_FUNC_1 1
-#define SPI_FUNC_2 2
-#define SPI_FUNC_3 3
-
-#define WAIT_F2RXFIFORDY 100
-#define WAIT_F2RXFIFORDY_DELAY 20
-
-#endif /* _SPI_H */
diff --git a/bcm4329/src/include/wlioctl.h b/bcm4329/src/include/wlioctl.h
index 30564aa..751d5cd 100644
--- a/bcm4329/src/include/wlioctl.h
+++ b/bcm4329/src/include/wlioctl.h
@@ -24,7 +24,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wlioctl.h,v 1.601.4.15.2.14.2.37 2009/06/22 11:24:10 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.53 2009/10/27 06:18:20 Exp $
*/
@@ -133,11 +133,15 @@ typedef struct wlc_ssid {
#define WL_BSSTYPE_INDEP 0
#define WL_BSSTYPE_ANY 2
+
+#define WL_SCANFLAGS_PASSIVE 0x01
+#define WL_SCANFLAGS_PROHIBITED 0x04
+
typedef struct wl_scan_params {
wlc_ssid_t ssid;
struct ether_addr bssid;
int8 bss_type;
- int8 scan_type;
+ int8 scan_type;
int32 nprobes;
int32 active_time;
int32 passive_time;
@@ -154,6 +158,7 @@ typedef struct wl_scan_params {
#define WL_SCAN_ACTION_START 1
#define WL_SCAN_ACTION_CONTINUE 2
+#define WL_SCAN_ACTION_ABORT 3
#define ISCAN_REQ_VERSION 1
@@ -182,6 +187,27 @@ typedef struct wl_scan_results {
#define WL_SCAN_RESULTS_PENDING 2
#define WL_SCAN_RESULTS_ABORTED 3
+#define ESCAN_REQ_VERSION 1
+
+typedef struct wl_escan_params {
+ uint32 version;
+ uint16 action;
+ uint16 sync_id;
+ wl_scan_params_t params;
+} wl_escan_params_t;
+
+#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t))
+
+typedef struct wl_escan_result {
+ uint32 buflen;
+ uint32 version;
+ uint16 sync_id;
+ uint16 bss_count;
+ wl_bss_info_t bss_info[1];
+} wl_escan_result_t;
+
+#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t))
+
typedef struct wl_iscan_results {
uint32 status;
@@ -208,6 +234,7 @@ typedef struct wl_uint32_list {
typedef struct wl_assoc_params {
struct ether_addr bssid;
+ uint16 bssid_cnt;
int32 chanspec_num;
chanspec_t chanspec_list[1];
} wl_assoc_params_t;
@@ -322,6 +349,8 @@ typedef struct {
#define BRCM_AUTH_PSK 0x0100
#define BRCM_AUTH_DPT 0x0200
+#define WPA_AUTH_PFN_ANY 0xffffffff
+
#define MAXPMKID 16
@@ -762,6 +791,7 @@ typedef struct wl_ioctl {
#define WLC_PHY_TYPE_G 2
#define WLC_PHY_TYPE_N 4
#define WLC_PHY_TYPE_LP 5
+#define WLC_PHY_TYPE_SSN 6
#define WLC_PHY_TYPE_NULL 0xf
@@ -1156,7 +1186,6 @@ typedef struct {
uint32 pktengrxdmcast;
} wl_cnt_t;
-
typedef struct {
uint16 version;
uint16 length;
@@ -1173,6 +1202,7 @@ typedef struct {
uint32 rxmcs5_40M;
uint32 rxmcs6_40M;
uint32 rxmcs7_40M;
+ uint32 rxmcs32_40M;
uint32 txfrmsnt_20Mlo;
uint32 txfrmsnt_20Mup;
@@ -1181,6 +1211,14 @@ typedef struct {
uint32 rx_20ul;
} wl_cnt_ext_t;
+#define WL_RXDIV_STATS_T_VERSION 1
+typedef struct {
+ uint16 version;
+ uint16 length;
+
+ uint32 rxant[4];
+} wl_rxdiv_stats_t;
+
#define WL_DELTA_STATS_T_VERSION 1
typedef struct {
@@ -1291,10 +1329,12 @@ typedef struct wl_pfn {
int32 auth;
int32 wpa_auth;
int32 wsec;
+#ifdef WLPFN_AUTO_CONNECT
union {
wl_wsec_key_t sec_key;
wsec_pmk_t wpa_sec_key;
} pfn_security;
+#endif
} wl_pfn_t;
@@ -1468,10 +1508,15 @@ typedef struct wl_pkteng {
struct ether_addr src;
} wl_pkteng_t;
+#define NUM_80211b_RATES 4
+#define NUM_80211ag_RATES 8
+#define NUM_80211n_RATES 32
+#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES)
typedef struct wl_pkteng_stats {
uint32 lostfrmcnt;
int32 rssi;
int32 snr;
+ uint16 rxpktcnt[NUM_80211_RATES+1];
} wl_pkteng_stats_t;
#define WL_WOWL_MAGIC (1 << 0)
diff --git a/bcm4329/src/shared/aiutils.c b/bcm4329/src/shared/aiutils.c
index 00e96a8..1962711 100644
--- a/bcm4329/src/shared/aiutils.c
+++ b/bcm4329/src/shared/aiutils.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: aiutils.c,v 1.6.4.7.4.1 2008/11/03 15:16:48 Exp $
+ * $Id: aiutils.c,v 1.6.4.7.4.5 2009/09/25 00:32:01 Exp $
*/
#include <typedefs.h>
@@ -36,6 +36,11 @@
#include "siutils_priv.h"
+STATIC uint32
+get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st,
+ uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh);
+
+
/* EROM parsing */
static uint32
@@ -71,7 +76,7 @@ get_erom_ent(si_t *sih, uint32 *eromptr, uint32 mask, uint32 match)
return ent;
}
-static uint32
+STATIC uint32
get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st,
uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh)
{
@@ -422,6 +427,15 @@ ai_setint(si_t *sih, int siflag)
{
}
+void
+ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val)
+{
+ si_info_t *sii = SI_INFO(sih);
+ aidmp_t *ai = sii->curwrap;
+ W_REG(sii->osh, (uint32 *)((uint8 *)ai+offset), val);
+ return;
+}
+
uint
ai_corevendor(si_t *sih)
{
@@ -482,6 +496,9 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
ASSERT(regoff < SI_CORE_SIZE);
ASSERT((val & ~mask) == 0);
+ if (coreidx >= SI_MAXCORES)
+ return 0;
+
if (BUSTYPE(sih->bustype) == SI_BUS) {
/* If internal bus, we can always get at everything */
fast = TRUE;
diff --git a/bcm4329/src/shared/bcmutils.c b/bcm4329/src/shared/bcmutils.c
index 2741824..9805ee6 100644
--- a/bcm4329/src/shared/bcmutils.c
+++ b/bcm4329/src/shared/bcmutils.c
@@ -20,7 +20,7 @@
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
- * $Id: bcmutils.c,v 1.210.4.5.2.4.6.9 2009/05/22 20:49:24 Exp $
+ * $Id: bcmutils.c,v 1.210.4.5.2.4.6.16 2009/10/28 18:25:42 Exp $
*/
#include <typedefs.h>
@@ -45,6 +45,7 @@
#ifdef BCMDRIVER
+
/* copy a pkt buffer chain into a buffer */
uint
pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
@@ -665,7 +666,8 @@ bcmstrncat(char *dest, const char *src, uint size)
* Returns: Pointer to the next token found. NULL when no more tokens are found.
*****************************************************************************
*/
-char* bcmstrtok(char **string, const char *delimiters, char *tokdelim)
+char *
+bcmstrtok(char **string, const char *delimiters, char *tokdelim)
{
unsigned char *str;
unsigned long map[8];
@@ -742,7 +744,8 @@ char* bcmstrtok(char **string, const char *delimiters, char *tokdelim)
* t1 > t2, when ignoring case sensitivity.
*****************************************************************************
*/
-int bcmstricmp(const char *s1, const char *s2)
+int
+bcmstricmp(const char *s1, const char *s2)
{
char dc, sc;
@@ -775,7 +778,8 @@ int bcmstricmp(const char *s1, const char *s2)
* t1 > t2, when ignoring case sensitivity.
*****************************************************************************
*/
-int bcmstrnicmp(const char* s1, const char* s2, int cnt)
+int
+bcmstrnicmp(const char* s1, const char* s2, int cnt)
{
char dc, sc;
@@ -810,18 +814,14 @@ bcm_ether_atoe(char *p, struct ether_addr *ea)
return (i == 6);
}
+
#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
/* registry routine buffer preparation utility functions:
* parameter order is like strncpy, but returns count
* of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
*/
ulong
-wchar2ascii(
- char *abuf,
- ushort *wbuf,
- ushort wbuflen,
- ulong abuflen
-)
+wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen)
{
ulong copyct = 1;
ushort i;
diff --git a/bcm4329/src/shared/bcmwifi.c b/bcm4329/src/shared/bcmwifi.c
index b460d7f..641a4fd 100644
--- a/bcm4329/src/shared/bcmwifi.c
+++ b/bcm4329/src/shared/bcmwifi.c
@@ -22,7 +22,7 @@
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
- * $Id: bcmwifi.c,v 1.18.24.2 2008/08/01 21:52:06 Exp $
+ * $Id: bcmwifi.c,v 1.18.24.2.4.1 2009/09/25 00:32:01 Exp $
*/
@@ -83,7 +83,7 @@ wf_chspec_ntoa(chanspec_t chspec, char *buf)
chanspec_t
wf_chspec_aton(char *a)
{
- char *endp;
+ char *endp = NULL;
uint channel, band, bw, ctl_sb;
char c;
diff --git a/bcm4329/src/shared/hndpmu.c b/bcm4329/src/shared/hndpmu.c
index 90116de..25712ac 100644
--- a/bcm4329/src/shared/hndpmu.c
+++ b/bcm4329/src/shared/hndpmu.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: hndpmu.c,v 1.95.2.17.4.11.2.39 2009/06/25 16:07:18 Exp $
+ * $Id: hndpmu.c,v 1.95.2.17.4.11.2.50 2009/10/26 14:45:51 Exp $
*/
#include <typedefs.h>
@@ -70,7 +70,7 @@ void
si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
{
chipcregs_t *cc;
- uint origidx, intr_val;
+ uint origidx, intr_val = 0;
sdiod_drive_str_t *str_tab = NULL;
uint32 str_mask = 0;
uint32 str_shift = 0;
diff --git a/bcm4329/src/shared/linux_osl.c b/bcm4329/src/shared/linux_osl.c
index 7fb59e4..4cf658b 100644
--- a/bcm4329/src/shared/linux_osl.c
+++ b/bcm4329/src/shared/linux_osl.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: linux_osl.c,v 1.125.12.3.8.2 2009/06/18 02:31:41 Exp $
+ * $Id: linux_osl.c,v 1.125.12.3.8.5 2009/10/27 04:43:04 Exp $
*/
@@ -41,6 +41,28 @@
#define OS_HANDLE_MAGIC 0x1234abcd
#define BCM_MEM_FILENAME_LEN 24
+#ifdef DHD_USE_STATIC_BUF
+#define MAX_STATIC_BUF_NUM 16
+#define STATIC_BUF_SIZE (PAGE_SIZE*2)
+#define STATIC_BUF_TOTAL_LEN (MAX_STATIC_BUF_NUM*STATIC_BUF_SIZE)
+typedef struct bcm_static_buf {
+ struct semaphore static_sem;
+ unsigned char *buf_ptr;
+ unsigned char buf_use[MAX_STATIC_BUF_NUM];
+} bcm_static_buf_t;
+
+static bcm_static_buf_t *bcm_static_buf = 0;
+
+#define MAX_STATIC_PKT_NUM 8
+typedef struct bcm_static_pkt {
+ struct sk_buff *skb_4k[MAX_STATIC_PKT_NUM];
+ struct sk_buff *skb_8k[MAX_STATIC_PKT_NUM];
+ struct semaphore osl_pkt_sem;
+ unsigned char pkt_use[MAX_STATIC_PKT_NUM*2];
+} bcm_static_pkt_t;
+static bcm_static_pkt_t *bcm_static_skb = 0;
+
+#endif
typedef struct bcm_mem_link {
struct bcm_mem_link *prev;
struct bcm_mem_link *next;
@@ -121,6 +143,7 @@ osl_error(int bcmerror)
return linuxbcmerrormap[-bcmerror];
}
+void * dhd_os_prealloc(int section, unsigned long size);
osl_t *
osl_attach(void *pdev, uint bustype, bool pkttag)
{
@@ -159,6 +182,39 @@ osl_attach(void *pdev, uint bustype, bool pkttag)
break;
}
+#ifdef DHD_USE_STATIC_BUF
+
+
+ if (!bcm_static_buf) {
+ if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(3, STATIC_BUF_SIZE+
+ STATIC_BUF_TOTAL_LEN))) {
+ printk("can not alloc static buf!\n");
+ }
+ else
+ printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf);
+
+
+ init_MUTEX(&bcm_static_buf->static_sem);
+
+
+ bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
+
+ }
+
+ if (!bcm_static_skb)
+ {
+ int i;
+ void *skb_buff_ptr = 0;
+ bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
+ skb_buff_ptr = dhd_os_prealloc(4, 0);
+
+ bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16);
+ for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++)
+ bcm_static_skb->pkt_use[i] = 0;
+
+ init_MUTEX(&bcm_static_skb->osl_pkt_sem);
+ }
+#endif
return osh;
}
@@ -168,6 +224,14 @@ osl_detach(osl_t *osh)
if (osh == NULL)
return;
+#ifdef DHD_USE_STATIC_BUF
+ if (bcm_static_buf) {
+ bcm_static_buf = 0;
+ }
+ if (bcm_static_skb) {
+ bcm_static_skb = 0;
+ }
+#endif
ASSERT(osh->magic == OS_HANDLE_MAGIC);
kfree(osh);
}
@@ -220,6 +284,90 @@ osl_pktfree(osl_t *osh, void *p, bool send)
}
}
+#ifdef DHD_USE_STATIC_BUF
+void*
+osl_pktget_static(osl_t *osh, uint len)
+{
+ int i = 0;
+ struct sk_buff *skb;
+
+
+ if (len > (PAGE_SIZE*2))
+ {
+ printk("Do we really need this big skb??\n");
+ return osl_pktget(osh, len);
+ }
+
+
+ down(&bcm_static_skb->osl_pkt_sem);
+ if (len <= PAGE_SIZE)
+ {
+
+ for (i = 0; i < MAX_STATIC_PKT_NUM; i++)
+ {
+ if (bcm_static_skb->pkt_use[i] == 0)
+ break;
+ }
+
+ if (i != MAX_STATIC_PKT_NUM)
+ {
+ bcm_static_skb->pkt_use[i] = 1;
+ up(&bcm_static_skb->osl_pkt_sem);
+
+ skb = bcm_static_skb->skb_4k[i];
+ skb->tail = skb->data + len;
+ skb->len = len;
+
+ return skb;
+ }
+ }
+
+
+ for (i = 0; i < MAX_STATIC_PKT_NUM; i++)
+ {
+ if (bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] == 0)
+ break;
+ }
+
+ if (i != MAX_STATIC_PKT_NUM)
+ {
+ bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] = 1;
+ up(&bcm_static_skb->osl_pkt_sem);
+ skb = bcm_static_skb->skb_8k[i];
+ skb->tail = skb->data + len;
+ skb->len = len;
+
+ return skb;
+ }
+
+
+
+ up(&bcm_static_skb->osl_pkt_sem);
+ printk("all static pkt in use!\n");
+ return osl_pktget(osh, len);
+}
+
+
+void
+osl_pktfree_static(osl_t *osh, void *p, bool send)
+{
+ int i;
+
+ for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++)
+ {
+ if (p == bcm_static_skb->skb_4k[i])
+ {
+ down(&bcm_static_skb->osl_pkt_sem);
+ bcm_static_skb->pkt_use[i] = 0;
+ up(&bcm_static_skb->osl_pkt_sem);
+
+
+ return;
+ }
+ }
+ return osl_pktfree(osh, p, send);
+}
+#endif
uint32
osl_pci_read_config(osl_t *osh, uint offset, uint size)
{
@@ -307,6 +455,40 @@ osl_malloc(osl_t *osh, uint size)
if (osh)
ASSERT(osh->magic == OS_HANDLE_MAGIC);
+#ifdef DHD_USE_STATIC_BUF
+ if (bcm_static_buf)
+ {
+ int i = 0;
+ if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE))
+ {
+ down(&bcm_static_buf->static_sem);
+
+ for (i = 0; i < MAX_STATIC_BUF_NUM; i++)
+ {
+ if (bcm_static_buf->buf_use[i] == 0)
+ break;
+ }
+
+ if (i == MAX_STATIC_BUF_NUM)
+ {
+ up(&bcm_static_buf->static_sem);
+ printk("all static buff in use!\n");
+ goto original;
+ }
+
+ bcm_static_buf->buf_use[i] = 1;
+ up(&bcm_static_buf->static_sem);
+
+ bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size);
+ if (osh)
+ osh->malloced += size;
+
+ return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i));
+ }
+ }
+original:
+#endif
+
if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
if (osh)
osh->failed++;
@@ -321,6 +503,28 @@ osl_malloc(osl_t *osh, uint size)
void
osl_mfree(osl_t *osh, void *addr, uint size)
{
+#ifdef DHD_USE_STATIC_BUF
+ if (bcm_static_buf)
+ {
+ if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr \
+ <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN)))
+ {
+ int buf_idx = 0;
+
+ buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE;
+
+ down(&bcm_static_buf->static_sem);
+ bcm_static_buf->buf_use[buf_idx] = 0;
+ up(&bcm_static_buf->static_sem);
+
+ if (osh) {
+ ASSERT(osh->magic == OS_HANDLE_MAGIC);
+ osh->malloced -= size;
+ }
+ return;
+ }
+ }
+#endif
if (osh) {
ASSERT(osh->magic == OS_HANDLE_MAGIC);
osh->malloced -= size;
diff --git a/bcm4329/src/shared/miniopt.c b/bcm4329/src/shared/miniopt.c
index de00b6c..44199ea 100644
--- a/bcm4329/src/shared/miniopt.c
+++ b/bcm4329/src/shared/miniopt.c
@@ -20,7 +20,7 @@
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
- * $Id: miniopt.c,v 1.1.6.3 2009/01/14 23:52:06 Exp $
+ * $Id: miniopt.c,v 1.1.6.4 2009/09/25 00:32:01 Exp $
*/
/* ---- Include Files ---------------------------------------------------- */
@@ -62,7 +62,7 @@ int
miniopt(miniopt_t *t, char **argv)
{
int keylen;
- char *p, *eq, *valstr, *endptr;
+ char *p, *eq, *valstr, *endptr = NULL;
int err = 0;
t->consumed = 0;
diff --git a/bcm4329/src/shared/sbutils.c b/bcm4329/src/shared/sbutils.c
index cbe4438..567e94e 100644
--- a/bcm4329/src/shared/sbutils.c
+++ b/bcm4329/src/shared/sbutils.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: sbutils.c,v 1.662.4.10.2.7 2008/08/06 03:43:24 Exp $
+ * $Id: sbutils.c,v 1.662.4.10.2.7.4.1 2009/09/25 00:32:01 Exp $
*/
#include <typedefs.h>
@@ -363,6 +363,9 @@ sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
ASSERT(regoff < SI_CORE_SIZE);
ASSERT((val & ~mask) == 0);
+ if (coreidx >= SI_MAXCORES)
+ return 0;
+
if (BUSTYPE(sii->pub.bustype) == SI_BUS) {
/* If internal bus, we can always get at everything */
fast = TRUE;
diff --git a/bcm4329/src/shared/siutils.c b/bcm4329/src/shared/siutils.c
index 988dda1..df34986 100644
--- a/bcm4329/src/shared/siutils.c
+++ b/bcm4329/src/shared/siutils.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: siutils.c,v 1.662.4.4.4.16.4.20 2009/06/25 16:07:18 Exp $
+ * $Id: siutils.c,v 1.662.4.4.4.16.4.25 2009/09/22 13:32:03 Exp $
*/
#include <typedefs.h>
@@ -661,10 +661,6 @@ si_setcore(si_t *sih, uint coreid, uint coreunit)
{
uint idx;
- if (!sih) {
- printk("%s: Null, %u, %u\n", __func__, coreid, coreunit);
- return NULL;
- }
idx = si_findcoreidx(sih, coreid, coreunit);
if (!GOODIDX(idx))
return (NULL);
@@ -808,6 +804,19 @@ si_iscoreup(si_t *sih)
}
}
+void
+si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val)
+{
+ /* only for 4319, no requirement for SOCI_SB */
+ if (CHIPTYPE(sih->socitype) == SOCI_AI) {
+ ai_write_wrap_reg(sih, offset, val);
+ }
+ else
+ return;
+
+ return;
+}
+
uint
si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
{
@@ -1013,7 +1022,7 @@ si_sdio_init(si_t *sih)
{
si_info_t *sii = SI_INFO(sih);
- if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) || \
+ if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) ||
(sih->buscoretype == SDIOD_CORE_ID)) {
uint idx;
sdpcmd_regs_t *sdpregs;
diff --git a/bcm4329/src/shared/siutils_priv.h b/bcm4329/src/shared/siutils_priv.h
index 1192168..1ec59aa 100644
--- a/bcm4329/src/shared/siutils_priv.h
+++ b/bcm4329/src/shared/siutils_priv.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: siutils_priv.h,v 1.3.10.5 2008/08/06 06:28:10 Exp $
+ * $Id: siutils_priv.h,v 1.3.10.5.4.2 2009/09/22 13:28:16 Exp $
*/
#ifndef _siutils_priv_h_
@@ -207,6 +207,7 @@ extern void ai_core_disable(si_t *sih, uint32 bits);
extern int ai_numaddrspaces(si_t *sih);
extern uint32 ai_addrspace(si_t *sih, uint asidx);
extern uint32 ai_addrspacesize(si_t *sih, uint asidx);
+extern void ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val);
#endif /* _siutils_priv_h_ */
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index edca173..768373b 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.c,v 1.51.4.9.2.6.4.38 2009/06/29 18:54:46 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.57 2009/10/27 04:43:46 Exp $
*/
@@ -36,6 +36,8 @@
#include <linux/if_arp.h>
#include <asm/uaccess.h>
+#include <dngl_stats.h>
+#include <dhd.h>
#include <dhdioctl.h>
typedef void wlc_info_t;
@@ -43,6 +45,9 @@ typedef void wl_info_t;
typedef const struct si_pub si_t;
#include <wlioctl.h>
+#include <proto/ethernet.h>
+#include <dngl_stats.h>
+#include <dhd.h>
#define WL_ERROR(x)
#define WL_TRACE(x)
#define WL_ASSOC(x)
@@ -51,11 +56,13 @@ typedef const struct si_pub si_t;
#include <wl_iw.h>
+
#include <linux/rtnetlink.h>
#define WL_IW_USE_ISCAN 1
#define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1
+
#define WL_IW_IOCTL_CALL(func_call) \
do { \
func_call; \
@@ -66,7 +73,7 @@ static int g_onoff = G_WLAN_SET_ON;
extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
uint32 reason, char* stringBuf, uint buflen);
#include <bcmsdbus.h>
-extern void dhd_customer_gpio_wlan_reset(bool onoff);
+extern void dhd_customer_gpio_wlan_ctrl(int onoff);
extern uint dhd_dev_reset(struct net_device *dev, uint8 flag);
extern void dhd_dev_init_ioctl(struct net_device *dev);
@@ -154,6 +161,34 @@ typedef struct iscan_info {
char ioctlbuf[WLC_IOCTL_SMLEN];
} iscan_info_t;
+
+static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
+static void wl_iw_bt_release(void);
+
+typedef enum bt_coex_status {
+ BT_DHCP_IDLE = 0,
+ BT_DHCP_START,
+ BT_DHCP_OPPORTUNITY_WINDOW,
+ BT_DHCP_FLAG_FORCE_TIMEOUT
+} coex_status_t;
+#define BT_DHCP_OPPORTUNITY_WINDOW_TIEM 2500
+#define BT_DHCP_FLAG_FORCE_TIME 5500
+
+typedef struct bt_info {
+ struct net_device *dev;
+ struct timer_list timer;
+ uint32 timer_ms;
+ uint32 timer_on;
+ int bt_state;
+
+
+ long bt_pid;
+ struct semaphore bt_sem;
+ struct completion bt_exited;
+} bt_info_t;
+
+bt_info_t *g_bt = NULL;
+static void wl_iw_bt_timerfunc(ulong data);
iscan_info_t *g_iscan = NULL;
static void wl_iw_timerfunc(ulong data);
static void wl_iw_set_event_mask(struct net_device *dev);
@@ -243,6 +278,28 @@ dev_wlc_ioctl(
}
+static int
+dev_wlc_intvar_get_reg(
+ struct net_device *dev,
+ char *name,
+ uint reg,
+ int *retval)
+{
+ union {
+ char buf[WLC_IOCTL_SMLEN];
+ int val;
+ } var;
+ int error;
+
+ uint len;
+ len = bcm_mkiovar(name, (char *)(&reg), sizeof(reg), (char *)(&var), sizeof(var.buf));
+ ASSERT(len);
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
+
+ *retval = dtoh32(var.val);
+ return (error);
+}
+
@@ -306,7 +363,7 @@ dev_wlc_bufvar_set(
char *name,
char *buf, int len)
{
- char ioctlbuf[WLC_IOCTL_SMLEN];
+ char ioctlbuf[MAX_WLIW_IOCTL_LEN];
uint buflen;
buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
@@ -491,6 +548,103 @@ exit:
return error;
}
+static int
+wl_iw_set_btcoex_dhcp(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int error = 0;
+ char *p = extra;
+ uint val;
+#ifdef CUSTOMER_HW2
+ static int pm = PM_FAST;
+ int pm_local = PM_OFF;
+#endif
+ char powermode_val = 0;
+ char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
+ char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
+ char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
+
+ char buf_reg66val_defualt[8] = { 66, 00, 00, 00, 0x88, 0x13, 0x00, 0x00 };
+ char buf_reg41val_defualt[8] = { 41, 00, 00, 00, 0x13, 0x00, 0x00, 0x00 };
+ char buf_reg68val_defualt[8] = { 68, 00, 00, 00, 0x14, 0x00, 0x00, 0x00 };
+
+ char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
+
+
+ strncpy((char *)&powermode_val, extra + strlen("POWERMODE") +1, 1);
+
+
+ dev_wlc_intvar_get_reg(dev, "btc_params", 68, &val);
+
+ if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
+
+ WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__));
+
+#ifdef CUSTOMER_HW2
+
+ dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm));
+
+ dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local));
+#endif
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg66va_dhcp_on[0], sizeof(buf_reg66va_dhcp_on));
+
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg41va_dhcp_on[0], sizeof(buf_reg41va_dhcp_on));
+
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg68va_dhcp_on[0], sizeof(buf_reg68va_dhcp_on));
+
+
+ g_bt->bt_state = BT_DHCP_START;
+ g_bt->timer_on = 1;
+ add_timer(&g_bt->timer);
+ WL_TRACE(("%s enable BT DHCP Timer\n", __FUNCTION__));
+
+ }
+ else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) {
+
+ WL_TRACE(("%s: DHCP session done\n", __FUNCTION__));
+
+#ifdef CUSTOMER_HW2
+
+ dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+#endif
+
+ WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__));
+ if (g_bt->timer_on) {
+ del_timer(&g_bt->timer);
+ g_bt->timer_on = 0;
+ }
+
+
+ dev_wlc_bufvar_set(dev, "btc_flags", \
+ (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
+
+
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg66val_defualt[0], sizeof(buf_reg66val_defualt));
+
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg41val_defualt[0], sizeof(buf_reg41val_defualt));
+
+ dev_wlc_bufvar_set(dev, "btc_params", \
+ (char *)&buf_reg68val_defualt[0], sizeof(buf_reg68val_defualt));
+ }
+ else {
+ WL_ERROR(("Unkwown yet power setting, ignored\n"));
+ }
+
+ p += snprintf(p, MAX_WX_STRING, "OK");
+
+ wrqu->data.length = p - extra + 1;
+
+ return error;
+}
int
wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
@@ -558,6 +712,7 @@ wl_iw_get_rssi(
scb_val.val = 0;
+ bzero(&ssid, sizeof(ssid));
if (g_onoff == G_WLAN_SET_ON) {
error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
rssi = dtoh32(scb_val.val);
@@ -606,10 +761,13 @@ _wl_control_sysioc_thread_wl_off(void *data)
{
struct wl_ctrl *wl_ctl = (struct wl_ctrl *)data;
+ wl_iw_t *iw = *(wl_iw_t **)netdev_priv(wl_ctl->dev);
DAEMONIZE("wlcontrol_sysioc");
WL_TRACE(("%s Entered\n", __FUNCTION__));
+ WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_OFF, "sysioc_thread_wl_off");
+ WAKE_LOCK(iw->pub, WAKE_LOCK_OFF);
while (down_interruptible(&wl_ctl->timer_sem) == 0) {
WL_TRACE(("%s Turning off wifi dev\n", __FUNCTION__));
@@ -626,7 +784,7 @@ _wl_control_sysioc_thread_wl_off(void *data)
sdioh_stop(NULL);
#endif
- dhd_customer_gpio_wlan_reset(G_WLAN_SET_OFF);
+ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
wl_iw_send_priv_event(wl_ctl->dev, "STOP");
@@ -634,6 +792,8 @@ _wl_control_sysioc_thread_wl_off(void *data)
}
WL_TRACE(("%s Exited\n", __FUNCTION__));
+ WAKE_UNLOCK(iw->pub, WAKE_LOCK_OFF);
+ WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_OFF);
complete_and_exit(&wl_ctl->sysioc_exited, 0);
KILL_PROC(wl_ctl->sysioc_pid, SIGTERM);
@@ -695,7 +855,7 @@ wl_iw_control_wl_on(
WL_TRACE(("Enter %s \n", __FUNCTION__));
if (g_onoff == G_WLAN_SET_OFF) {
- dhd_customer_gpio_wlan_reset(G_WLAN_SET_ON);
+ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
#if defined(BCMLXSDMMC)
sdioh_start(NULL, 0);
@@ -915,9 +1075,18 @@ wl_iw_get_range(
int channels[MAXCHANNEL+1];
wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
wl_rateset_t rateset;
- int error, i;
+ int error, i, k;
uint sf, ch;
+ int phytype;
+ int bw_cap = 0, sgi_tx = 0, nmode = 0;
+ channel_info_t ci;
+ uint8 nrate_list2copy = 0;
+ uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130},
+ {14, 29, 43, 58, 87, 116, 130, 144},
+ {27, 54, 81, 108, 162, 216, 243, 270},
+ {30, 60, 90, 120, 180, 240, 270, 300}};
+
WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name));
if (!extra)
@@ -971,7 +1140,36 @@ wl_iw_get_range(
rateset.count = dtoh32(rateset.count);
range->num_bitrates = rateset.count;
for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
- range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000;
+ range->bitrate[i] = (rateset.rates[i]& 0x7f) * 500000;
+ dev_wlc_intvar_get(dev, "nmode", &nmode);
+ dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype));
+
+ if (nmode == 1 && phytype == WLC_PHY_TYPE_SSN) {
+ dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap);
+ dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
+ dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t));
+ ci.hw_channel = dtoh32(ci.hw_channel);
+
+ if (bw_cap == 0 ||
+ (bw_cap == 2 && ci.hw_channel <= 14)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 0;
+ else
+ nrate_list2copy = 1;
+ }
+ if (bw_cap == 1 ||
+ (bw_cap == 2 && ci.hw_channel >= 36)) {
+ if (sgi_tx == 0)
+ nrate_list2copy = 2;
+ else
+ nrate_list2copy = 3;
+ }
+ range->num_bitrates += 8;
+ for (k = 0; i < range->num_bitrates; k++, i++) {
+
+ range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000;
+ }
+ }
if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i))))
@@ -1036,6 +1234,17 @@ wl_iw_get_range(
#ifdef BCMWPA2
range->enc_capa |= IW_ENC_CAPA_WPA2;
#endif
+
+
+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
+
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE);
+#ifdef BCMWPA2
+ IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND);
+#endif
#endif
return 0;
@@ -1135,7 +1344,8 @@ wl_iw_set_wap(
scb_val_t scbval;
bzero(&scbval, sizeof(scb_val_t));
- dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
+
+ (void) dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
return 0;
}
@@ -1369,7 +1579,7 @@ wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
params->bss_type = DOT11_BSSTYPE_ANY;
- params->scan_type = -1;
+ params->scan_type = 0;
params->nprobes = -1;
params->active_time = -1;
params->passive_time = -1;
@@ -1423,10 +1633,12 @@ static void
wl_iw_timerfunc(ulong data)
{
iscan_info_t *iscan = (iscan_info_t *)data;
- iscan->timer_on = 0;
- if (iscan->iscan_state != ISCAN_STATE_IDLE) {
- WL_TRACE(("timer trigger\n"));
- up(&iscan->sysioc_sem);
+ if (iscan) {
+ iscan->timer_on = 0;
+ if (iscan->iscan_state != ISCAN_STATE_IDLE) {
+ WL_TRACE(("timer trigger\n"));
+ up(&iscan->sysioc_sem);
+ }
}
}
static void wl_iw_set_event_mask(struct net_device *dev)
@@ -1544,8 +1756,7 @@ _iscan_sysioc_thread(void *data)
rtnl_unlock();
#endif
- iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000;
- add_timer(&iscan->timer);
+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
iscan->timer_on = 1;
break;
case WL_SCAN_RESULTS_SUCCESS:
@@ -1556,8 +1767,7 @@ _iscan_sysioc_thread(void *data)
case WL_SCAN_RESULTS_PENDING:
WL_TRACE(("iscanresults pending\n"));
- iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000;
- add_timer(&iscan->timer);
+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
iscan->timer_on = 1;
break;
case WL_SCAN_RESULTS_ABORTED:
@@ -1570,6 +1780,11 @@ _iscan_sysioc_thread(void *data)
break;
}
}
+
+ if (iscan->timer_on) {
+ del_timer(&iscan->timer);
+ iscan->timer_on = 0;
+ }
complete_and_exit(&iscan->sysioc_exited, 0);
}
#endif
@@ -1899,7 +2114,7 @@ wl_iw_iscan_set_scan(
memcpy(ssid.SSID, req->essid, ssid.SSID_len);
ssid.SSID_len = htod32(ssid.SSID_len);
g_scan_specified_ssid = 1;
- dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
+ (void) dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
return wl_iw_set_scan(dev, info, wrqu, extra);
}
}
@@ -1907,9 +2122,11 @@ wl_iw_iscan_set_scan(
iscan->list_cur = iscan->list_hdr;
iscan->iscan_state = ISCAN_STATE_SCANING;
- dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
+ (void) dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN,
+ &iscan->scan_flag, sizeof(iscan->scan_flag));
wl_iw_set_event_mask(dev);
wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+ del_timer(&iscan->timer);
iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000;
add_timer(&iscan->timer);
iscan->timer_on = 1;
@@ -1964,6 +2181,59 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
}
#endif
+
+static int
+wl_iw_handle_scanresults_ies(char **event_p, char *end,
+ struct iw_request_info *info, wl_bss_info_t *bi)
+{
+#if WIRELESS_EXT > 17
+ struct iw_event iwe;
+ char *event;
+
+ event = *event_p;
+ if (bi->ie_length) {
+
+ bcm_tlv_t *ie;
+ uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ int ptr_len = bi->ie_length;
+
+#ifdef BCMWPA2
+ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ }
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+#endif
+
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+
+ if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ ptr_len = bi->ie_length;
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+ if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ *event_p = event;
+ }
+#endif
+
+ return 0;
+}
+
static uint
wl_iw_get_scan_prep(
wl_scan_results_t *list,
@@ -1975,7 +2245,7 @@ wl_iw_get_scan_prep(
struct iw_event iwe;
wl_bss_info_t *bi = NULL;
char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
- uint ret = 0;
+ int ret = 0;
ASSERT(list);
@@ -2023,45 +2293,9 @@ wl_iw_get_scan_prep(
iwe.u.qual.noise = 0x100 + bi->phy_noise;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
-#if WIRELESS_EXT > 17
- if (bi->ie_length) {
-
- bcm_tlv_t *ie;
- uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
- int ptr_len = bi->ie_length;
-#ifdef BCMWPA2
- if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie->len + 2;
- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
- }
- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
-#endif
- while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
-
- if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie->len + 2;
- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
- break;
- }
- }
+ wl_iw_handle_scanresults_ies(&event, end, info, bi);
- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
- ptr_len = bi->ie_length;
- while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
- if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie->len + 2;
- event = IWE_STREAM_ADD_POINT(info, event,
- end, &iwe, (char *)ie);
- goto done;
- }
- }
- }
-done:
-#endif
iwe.cmd = SIOCGIWENCODE;
if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
@@ -2091,8 +2325,7 @@ done:
ret = 0;
}
WL_TRACE(("%s: size=%d bytes prepared \n", __FUNCTION__, (unsigned int)(event - extra)));
- return ret;
-
+ return (uint)ret;
}
static int
@@ -2332,53 +2565,9 @@ wl_iw_iscan_get_scan(
iwe.u.qual.noise = 0x100 + bi->phy_noise;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
-#if WIRELESS_EXT > 17
- if (bi->ie_length) {
-
- bcm_tlv_t *ie;
- uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
- int ptr_len = bi->ie_length;
-#ifdef BCMWPA2
- if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
- if (event + ie->len + 2 >= end)
- return -E2BIG;
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie->len + 2;
- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
- }
- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
-#endif
- while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
-
- if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
- if (event + ie->len + 2 >= end)
- return -E2BIG;
+ wl_iw_handle_scanresults_ies(&event, end, info, bi);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie->len + 2;
- event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
- break;
- }
- }
-
- ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
- ptr_len = bi->ie_length;
- while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
- if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
- if (event + ie->len + 2 >= end)
- return -E2BIG;
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = ie->len + 2;
- event = IWE_STREAM_ADD_POINT(info,
- event,
- end, &iwe, (char *)ie);
- goto done;
- }
- }
- }
-done:
-#endif
iwe.cmd = SIOCGIWENCODE;
if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
@@ -2610,7 +2799,7 @@ static int wl_iw_get_rate(
if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate))))
return error;
rate = dtoh32(rate);
- vwrq->value = (rate & 0x7f) * 500000;
+ vwrq->value = rate * 500000;
return 0;
}
@@ -2795,20 +2984,31 @@ wl_iw_set_retry(
if (vwrq->flags & IW_RETRY_LIMIT) {
+
- if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) ||
+ !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) {
+#else
+ if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) {
+#endif
lrl = htod32(vwrq->value);
if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl))))
return error;
}
+
+#if WIRELESS_EXT > 20
+ if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) ||
+ !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) {
+#else
if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) {
+#endif
srl = htod32(vwrq->value);
if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl))))
return error;
}
}
-
return 0;
}
@@ -2991,7 +3191,7 @@ wl_iw_get_encode(
wsec = dtoh32(wsec);
auth = dtoh32(auth);
- dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len);
+ dwrq->length = MIN(DOT11_MAX_KEY_SIZE, key.len);
dwrq->flags = key.index + 1;
@@ -3063,8 +3263,8 @@ wl_iw_set_wpaie(
char *extra
)
{
- WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
- dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
+ dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
+
return 0;
}
@@ -3181,6 +3381,9 @@ wl_iw_set_encodeext(
break;
}
swap_key_from_BE(&key);
+
+ dhd_wait_pend8021x(dev);
+
error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
if (error)
return error;
@@ -3188,6 +3391,103 @@ wl_iw_set_encodeext(
return 0;
}
+#if WIRELESS_EXT > 17
+#ifdef BCMWPA2
+struct {
+ pmkid_list_t pmkids;
+ pmkid_t foo[MAXPMKID-1];
+} pmkid_list;
+
+static int
+wl_iw_set_pmksa(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra
+)
+{
+ struct iw_pmksa *iwpmksa;
+ uint i;
+ char eabuf[ETHER_ADDR_STR_LEN];
+
+ WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name));
+ iwpmksa = (struct iw_pmksa *)extra;
+ bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
+
+ if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
+ WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
+ bzero((char *)&pmkid_list, sizeof(pmkid_list));
+ }
+
+ if (iwpmksa->cmd == IW_PMKSA_REMOVE) {
+ pmkid_list_t pmkid, *pmkidptr;
+ pmkidptr = &pmkid;
+
+ bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
+ {
+ uint j;
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
+ if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
+ ETHER_ADDR_LEN))
+ break;
+
+ for (; i < pmkid_list.pmkids.npmkid; i++) {
+ bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID,
+ &pmkid_list.pmkids.pmkid[i].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID,
+ &pmkid_list.pmkids.pmkid[i].PMKID,
+ WPA2_PMKID_LEN);
+ }
+ pmkid_list.pmkids.npmkid--;
+ }
+
+ if (iwpmksa->cmd == IW_PMKSA_ADD) {
+ bcopy(&iwpmksa->bssid.sa_data[0],
+ &pmkid_list.pmkids.pmkid[pmkid_list.pmkids.npmkid].BSSID,
+ ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[pmkid_list.pmkids.npmkid].PMKID,
+ WPA2_PMKID_LEN);
+ {
+ uint j;
+ uint k;
+ k = pmkid_list.pmkids.npmkid;
+ WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
+ bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j]));
+ WL_TRACE(("\n"));
+ }
+ pmkid_list.pmkids.npmkid++;
+ }
+ WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid));
+ for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
+ uint j;
+ WL_TRACE(("PMKID[%d]: %s = ", i,
+ bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID,
+ eabuf)));
+ for (j = 0; j < WPA2_PMKID_LEN; j++)
+ WL_TRACE(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]));
+ printf("\n");
+ }
+ WL_TRACE(("\n"));
+
+ dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
+ return 0;
+}
+#endif
+#endif
+
static int
wl_iw_get_encodeext(
struct net_device *dev,
@@ -3219,6 +3519,9 @@ wl_iw_set_wpaauth(
paramid = vwrq->flags & IW_AUTH_INDEX;
paramval = vwrq->value;
+ WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n",
+ dev->name, paramid, paramval));
+
switch (paramid) {
case IW_AUTH_WPA_VERSION:
@@ -3230,7 +3533,7 @@ wl_iw_set_wpaauth(
else if (paramval & IW_AUTH_WPA_VERSION_WPA2)
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
#endif
- WL_ERROR(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val));
if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
return error;
break;
@@ -3277,7 +3580,7 @@ wl_iw_set_wpaauth(
val = WPA2_AUTH_UNSPECIFIED;
}
#endif
- WL_ERROR(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val)))
return error;
break;
@@ -3287,7 +3590,7 @@ wl_iw_set_wpaauth(
case IW_AUTH_80211_AUTH_ALG:
- WL_ERROR(("Setting the D11auth %d\n", paramval));
+ WL_INFORM(("Setting the D11auth %d\n", paramval));
if (paramval == IW_AUTH_ALG_OPEN_SYSTEM)
val = 0;
else if (paramval == IW_AUTH_ALG_SHARED_KEY)
@@ -3311,7 +3614,7 @@ wl_iw_set_wpaauth(
dev_wlc_intvar_set(dev, "wsec", val);
}
val = 0;
- WL_ERROR(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
+ WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val));
dev_wlc_intvar_set(dev, "wpa_auth", 0);
return error;
}
@@ -3329,11 +3632,11 @@ wl_iw_set_wpaauth(
#if WIRELESS_EXT > 17
case IW_AUTH_ROAMING_CONTROL:
- WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
+ WL_INFORM(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__));
break;
case IW_AUTH_PRIVACY_INVOKED:
- WL_ERROR(("%s: IW_AUTH_PRIVACY_INVOKED\n", __FUNCTION__));
+ WL_INFORM(("%s: IW_AUTH_PRIVACY_INVOKED\n", __FUNCTION__));
break;
#endif
default:
@@ -3452,6 +3755,8 @@ wl_iw_get_wpaauth(
}
#endif
+
+
static int
wl_iw_set_priv(
struct net_device *dev,
@@ -3463,6 +3768,7 @@ wl_iw_set_priv(
int ret = 0;
char * extra;
+ wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev);
if (!(extra = kmalloc(dwrq->length, GFP_KERNEL)))
return -ENOMEM;
@@ -3476,6 +3782,8 @@ wl_iw_set_priv(
if (dwrq->length && extra) {
+ WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_PRIV, "wl_iw_set_priv");
+ WAKE_LOCK(iw->pub, WAKE_LOCK_PRIV);
if (g_onoff == G_WLAN_SET_OFF) {
wl_iw_control_wl_on(dev, info);
@@ -3508,12 +3816,15 @@ wl_iw_set_priv(
ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
ret = wl_iw_control_wl_off(dev, info);
+ else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
+ ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
else {
snprintf(extra, MAX_WX_STRING, "OK");
dwrq->length = strlen("OK") + 1;
WL_TRACE(("Unkown PRIVATE command , ignored\n"));
}
-
+ WAKE_UNLOCK(iw->pub, WAKE_LOCK_PRIV);
+ WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_PRIV);
}
if (extra) {
@@ -3606,7 +3917,7 @@ static const iw_handler wl_iw_handler[] =
(iw_handler) wl_iw_set_encodeext,
(iw_handler) wl_iw_get_encodeext,
#ifdef BCMWPA2
- (iw_handler) NULL,
+ (iw_handler) wl_iw_set_pmksa,
#endif
#endif
};
@@ -3999,7 +4310,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
cmd = IWEVPMKIDCAND;
pmkcandlist = data;
- count = pmkcandlist->npmkid_cand;
+ count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand);
+ ASSERT(count >= 0);
wrqu.data.length = sizeof(struct iw_pmkid_cand);
pmkidcand = pmkcandlist->pmkid_cand;
while (count) {
@@ -4022,7 +4334,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
case WLC_E_SCAN_COMPLETE:
#if defined(WL_IW_USE_ISCAN)
- if ((g_iscan) && (g_iscan->sysioc_pid >= 0))
+ if ((g_iscan) && (g_iscan->sysioc_pid >= 0) &&
+ (g_iscan->iscan_state != ISCAN_STATE_IDLE))
up(&g_iscan->sysioc_sem);
#else
cmd = SIOCGIWSCAN;
@@ -4140,8 +4453,150 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
done:
return res;
}
-int wl_iw_attach(struct net_device *dev)
+static void
+wl_iw_bt_flag_set(
+ struct net_device *dev,
+ bool set)
{
+ char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
+ char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+
+ if (set == TRUE) {
+
+ dev_wlc_bufvar_set(dev, "btc_flags", \
+ (char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on));
+ }
+ else {
+
+ dev_wlc_bufvar_set(dev, "btc_flags", \
+ (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+}
+
+static void
+wl_iw_bt_timerfunc(ulong data)
+{
+ bt_info_t *bt_local = (bt_info_t *)data;
+ bt_local->timer_on = 0;
+ WL_TRACE(("%s\n", __FUNCTION__));
+
+ up(&bt_local->bt_sem);
+}
+
+static int
+_bt_dhcp_sysioc_thread(void *data)
+{
+ DAEMONIZE("dhcp_sysioc");
+
+ while (down_interruptible(&g_bt->bt_sem) == 0) {
+ if (g_bt->timer_on) {
+ del_timer(&g_bt->timer);
+ g_bt->timer_on = 0;
+ }
+
+ switch (g_bt->bt_state) {
+ case BT_DHCP_START:
+
+ g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW;
+ mod_timer(&g_bt->timer, jiffies + \
+ BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000);
+ g_bt->timer_on = 1;
+ break;
+ case BT_DHCP_OPPORTUNITY_WINDOW:
+
+ WL_TRACE(("%s waiting for %d msec expired, force bt flag\n", \
+ __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIEM));
+ if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE);
+ g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
+ mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000);
+ g_bt->timer_on = 1;
+ break;
+ case BT_DHCP_FLAG_FORCE_TIMEOUT:
+
+ WL_TRACE(("%s waiting for %d msec expired remove bt flag\n", \
+ __FUNCTION__, BT_DHCP_FLAG_FORCE_TIME));
+
+ if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
+ g_bt->bt_state = BT_DHCP_IDLE;
+ g_bt->timer_on = 0;
+ break;
+ default:
+ WL_ERROR(("%s error g_status=%d !!!\n", __FUNCTION__, \
+ g_bt->bt_state));
+ if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE);
+ g_bt->bt_state = BT_DHCP_IDLE;
+ g_bt->timer_on = 0;
+ break;
+ }
+ }
+
+ if (g_bt->timer_on) {
+ del_timer(&g_bt->timer);
+ g_bt->timer_on = 0;
+ }
+ complete_and_exit(&g_bt->bt_exited, 0);
+}
+
+static void
+wl_iw_bt_release(void)
+{
+ bt_info_t *bt_local = g_bt;
+
+ if (!bt_local) {
+ return;
+ }
+
+ if (bt_local->bt_pid >= 0) {
+ KILL_PROC(bt_local->bt_pid, SIGTERM);
+ wait_for_completion(&bt_local->bt_exited);
+ }
+ kfree(bt_local);
+ g_bt = NULL;
+}
+
+static int
+wl_iw_bt_init(struct net_device *dev)
+{
+ bt_info_t *bt_dhcp = NULL;
+
+ bt_dhcp = kmalloc(sizeof(bt_info_t), GFP_KERNEL);
+ if (!bt_dhcp)
+ return -ENOMEM;
+
+ memset(bt_dhcp, 0, sizeof(bt_info_t));
+ bt_dhcp->bt_pid = -1;
+ g_bt = bt_dhcp;
+ bt_dhcp->dev = dev;
+ bt_dhcp->bt_state = BT_DHCP_IDLE;
+
+
+ bt_dhcp->timer_ms = 10;
+ init_timer(&bt_dhcp->timer);
+ bt_dhcp->timer.data = (ulong)bt_dhcp;
+ bt_dhcp->timer.function = wl_iw_bt_timerfunc;
+
+ sema_init(&bt_dhcp->bt_sem, 0);
+ init_completion(&bt_dhcp->bt_exited);
+ bt_dhcp->bt_pid = kernel_thread(_bt_dhcp_sysioc_thread, bt_dhcp, 0);
+ if (bt_dhcp->bt_pid < 0) {
+ WL_ERROR(("Failed in %s\n", __FUNCTION__));
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+int wl_iw_attach(struct net_device *dev, void * dhdp)
+{
+ wl_iw_t *iw;
#if defined(WL_IW_USE_ISCAN)
iscan_info_t *iscan = NULL;
@@ -4172,6 +4627,8 @@ int wl_iw_attach(struct net_device *dev)
return -ENOMEM;
#endif
+ iw = *(wl_iw_t **)netdev_priv(dev);
+ iw->pub = (dhd_pub_t *)dhdp;
g_scan = NULL;
@@ -4184,6 +4641,10 @@ int wl_iw_attach(struct net_device *dev)
wl_iw_init_ss_cache_ctrl();
+
+ wl_iw_bt_init(dev);
+
+
return 0;
}
@@ -4215,5 +4676,7 @@ void wl_iw_detach(void)
g_scan = NULL;
wl_iw_release_ss_cache_ctrl();
+ wl_iw_bt_release();
+
}
diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h
index b19e22c..64d8fc2 100644
--- a/bcm4329/src/wl/sys/wl_iw.h
+++ b/bcm4329/src/wl/sys/wl_iw.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.h,v 1.5.34.1.6.8 2009/06/29 18:54:46 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.9 2009/10/14 04:27:31 Exp $
*/
@@ -71,6 +71,7 @@ typedef struct wl_iw {
struct ether_addr spy_addr[IW_MAX_SPY];
struct iw_quality spy_qual[IW_MAX_SPY];
void *wlinfo;
+ dhd_pub_t * pub;
} wl_iw_t;
struct wl_ctrl {
@@ -115,7 +116,7 @@ extern const struct iw_handler_def wl_iw_handler_def;
extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
-int wl_iw_attach(struct net_device *dev);
+int wl_iw_attach(struct net_device *dev, void * dhdp);
void wl_iw_detach(void);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)