summaryrefslogtreecommitdiffstats
path: root/bcm4329/src
diff options
context:
space:
mode:
Diffstat (limited to 'bcm4329/src')
-rw-r--r--bcm4329/src/Makerules2
-rw-r--r--bcm4329/src/Makerules.env5
-rw-r--r--bcm4329/src/bcmsdio/linux/Makefile2
-rw-r--r--bcm4329/src/bcmsdio/linux/makefile.262
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmpcispi.c2
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh.c31
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_linux.c44
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c49
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c19
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdspi.c5
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c2
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdstd.c424
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c2
-rw-r--r--bcm4329/src/bcmsdio/sys/bcmspibrcm.c1726
-rw-r--r--bcm4329/src/branding.inc2
-rw-r--r--bcm4329/src/dhd/exe/GNUmakefile8
-rw-r--r--bcm4329/src/dhd/exe/dhdu.c62
-rw-r--r--bcm4329/src/dhd/exe/dhdu.h2
-rw-r--r--bcm4329/src/dhd/exe/dhdu_cmd.h2
-rw-r--r--bcm4329/src/dhd/exe/dhdu_linux.c2
-rw-r--r--bcm4329/src/dhd/linux/Makefile26
-rw-r--r--bcm4329/src/dhd/linux/makefile.262
-rw-r--r--bcm4329/src/dhd/sys/dhd.h77
-rw-r--r--bcm4329/src/dhd/sys/dhd_bus.h2
-rw-r--r--bcm4329/src/dhd/sys/dhd_cdc.c24
-rw-r--r--bcm4329/src/dhd/sys/dhd_common.c39
-rw-r--r--bcm4329/src/dhd/sys/dhd_custom_gpio.c33
-rw-r--r--bcm4329/src/dhd/sys/dhd_dbg.h9
-rw-r--r--bcm4329/src/dhd/sys/dhd_linux.c474
-rw-r--r--bcm4329/src/dhd/sys/dhd_linux_sched.c2
-rw-r--r--bcm4329/src/dhd/sys/dhd_proto.h2
-rw-r--r--bcm4329/src/dhd/sys/dhd_sdio.c72
-rw-r--r--bcm4329/src/dongle/dngl_stats.h2
-rw-r--r--bcm4329/src/include/aidmp.h2
-rw-r--r--bcm4329/src/include/bcmcdc.h2
-rw-r--r--bcm4329/src/include/bcmdefs.h27
-rw-r--r--bcm4329/src/include/bcmdevs.h6
-rw-r--r--bcm4329/src/include/bcmendian.h2
-rw-r--r--bcm4329/src/include/bcmpcispi.h2
-rw-r--r--bcm4329/src/include/bcmperf.h2
-rw-r--r--bcm4329/src/include/bcmsdbus.h2
-rw-r--r--bcm4329/src/include/bcmsdh.h2
-rw-r--r--bcm4329/src/include/bcmsdh_sdmmc.h2
-rw-r--r--bcm4329/src/include/bcmsdpcm.h2
-rw-r--r--bcm4329/src/include/bcmsdspi.h2
-rw-r--r--bcm4329/src/include/bcmsdstd.h61
-rw-r--r--bcm4329/src/include/bcmspi.h2
-rw-r--r--bcm4329/src/include/bcmspibrcm.h134
-rw-r--r--bcm4329/src/include/bcmutils.h18
-rw-r--r--bcm4329/src/include/bcmwifi.h10
-rw-r--r--bcm4329/src/include/dhdioctl.h2
-rw-r--r--bcm4329/src/include/epivers.h14
-rw-r--r--bcm4329/src/include/hndpmu.h2
-rw-r--r--bcm4329/src/include/hndsoc.h2
-rw-r--r--bcm4329/src/include/linux_osl.h2
-rw-r--r--bcm4329/src/include/linuxver.h20
-rw-r--r--bcm4329/src/include/miniopt.h2
-rw-r--r--bcm4329/src/include/msgtrace.h2
-rw-r--r--bcm4329/src/include/osl.h2
-rw-r--r--bcm4329/src/include/packed_section_end.h2
-rw-r--r--bcm4329/src/include/packed_section_start.h2
-rw-r--r--bcm4329/src/include/pcicfg.h2
-rw-r--r--bcm4329/src/include/proto/802.11.h25
-rw-r--r--bcm4329/src/include/proto/802.11e.h2
-rw-r--r--bcm4329/src/include/proto/802.1d.h2
-rw-r--r--bcm4329/src/include/proto/bcmeth.h2
-rw-r--r--bcm4329/src/include/proto/bcmevent.h2
-rw-r--r--bcm4329/src/include/proto/bcmip.h2
-rw-r--r--bcm4329/src/include/proto/ethernet.h4
-rw-r--r--bcm4329/src/include/proto/sdspi.h2
-rw-r--r--bcm4329/src/include/proto/vlan.h2
-rw-r--r--bcm4329/src/include/proto/wpa.h2
-rw-r--r--bcm4329/src/include/sbchipc.h113
-rw-r--r--bcm4329/src/include/sbconfig.h2
-rw-r--r--bcm4329/src/include/sbhnddma.h2
-rw-r--r--bcm4329/src/include/sbpcmcia.h2
-rw-r--r--bcm4329/src/include/sbsdio.h2
-rw-r--r--bcm4329/src/include/sbsdpcmdev.h2
-rw-r--r--bcm4329/src/include/sbsocram.h2
-rw-r--r--bcm4329/src/include/sdio.h2
-rw-r--r--bcm4329/src/include/sdioh.h9
-rw-r--r--bcm4329/src/include/sdiovar.h5
-rw-r--r--bcm4329/src/include/siutils.h5
-rw-r--r--bcm4329/src/include/spid.h153
-rw-r--r--bcm4329/src/include/trxhdr.h2
-rw-r--r--bcm4329/src/include/typedefs.h2
-rw-r--r--bcm4329/src/include/wlioctl.h44
-rw-r--r--bcm4329/src/shared/aiutils.c2
-rw-r--r--bcm4329/src/shared/bcmutils.c9
-rw-r--r--bcm4329/src/shared/bcmwifi.c2
-rw-r--r--bcm4329/src/shared/hndpmu.c4
-rw-r--r--bcm4329/src/shared/linux_osl.c35
-rw-r--r--bcm4329/src/shared/miniopt.c2
-rw-r--r--bcm4329/src/shared/sbutils.c2
-rw-r--r--bcm4329/src/shared/siutils.c6
-rw-r--r--bcm4329/src/shared/siutils_priv.h2
-rw-r--r--bcm4329/src/wl/sys/wl_iw.c2137
-rw-r--r--bcm4329/src/wl/sys/wl_iw.h61
98 files changed, 5198 insertions, 945 deletions
diff --git a/bcm4329/src/Makerules b/bcm4329/src/Makerules
index 511def2..06ee2fe 100644
--- a/bcm4329/src/Makerules
+++ b/bcm4329/src/Makerules
@@ -2,7 +2,7 @@
# Top level Makerules
# it uses Makerules.env for build env vars and optional branding.inc
#
-# Copyright (C) 1999-2009, Broadcom Corporation
+# Copyright (C) 1999-2010, Broadcom Corporation
#
# Unless you and Broadcom execute a separate written software license
# agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/Makerules.env b/bcm4329/src/Makerules.env
index 189f053..dbe4c39 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" "linuxmips" "sun4" "cygwin32" "win32" "macos"), )
+ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "linuxarm" "linuxarm_le" "android" "linuxarm_omap" "linuxmips" "sun4" "cygwin32" "win32" "macos"), )
TARGETOS = $(HOSTOS)
endif
ifeq ($(TARGETENV), bcmmips)
@@ -91,6 +91,9 @@ 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/linux/Makefile b/bcm4329/src/bcmsdio/linux/Makefile
index 9e265d4..41ed016 100644
--- a/bcm4329/src/bcmsdio/linux/Makefile
+++ b/bcm4329/src/bcmsdio/linux/Makefile
@@ -1,7 +1,7 @@
# GNU Makefile for Broadcom BCMSDH Lower-level Driver
#
-# Copyright (C) 1999-2009, Broadcom Corporation
+# Copyright (C) 1999-2010, Broadcom Corporation
#
# Unless you and Broadcom execute a separate written software license
# agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/bcmsdio/linux/makefile.26 b/bcm4329/src/bcmsdio/linux/makefile.26
index ffbde11..b1f13eb 100644
--- a/bcm4329/src/bcmsdio/linux/makefile.26
+++ b/bcm4329/src/bcmsdio/linux/makefile.26
@@ -2,7 +2,7 @@
# Makefile fragment for Linux 2.6
# Broadcom BCMSDH Driver
#
-# Copyright (C) 1999-2009, Broadcom Corporation
+# Copyright (C) 1999-2010, Broadcom Corporation
#
# Unless you and Broadcom execute a separate written software license
# agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/bcmsdio/sys/bcmpcispi.c b/bcm4329/src/bcmsdio/sys/bcmpcispi.c
index ba3e0c5..c0a66f1 100644
--- a/bcm4329/src/bcmsdio/sys/bcmpcispi.c
+++ b/bcm4329/src/bcmsdio/sys/bcmpcispi.c
@@ -1,7 +1,7 @@
/*
* Broadcom SPI over PCI-SPI Host Controller, low-level hardware driver
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh.c b/bcm4329/src/bcmsdio/sys/bcmsdh.c
index c9906e2..bb3608d 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh.c
@@ -2,7 +2,7 @@
* BCMSDH interface glue
* implement bcmsdh API for SDIOH driver
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.11 2009/10/20 09:48:20 Exp $
+ * $Id: bcmsdh.c,v 1.35.2.1.4.8.6.12 2009/11/04 20:36:52 Exp $
*/
/* ****************** BCMSDH Interface Functions *************************** */
@@ -40,9 +40,6 @@
#include <sdio.h> /* sdio spec */
-/* Defines number of access retries to configuration registers */
-#define SDIOH_API_ACCESS_RETRY_LIMIT 2
-
const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
@@ -59,7 +56,6 @@ struct bcmsdh_info
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);
@@ -68,7 +64,6 @@ bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
{
sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
}
-
#endif
bcmsdh_info_t *
@@ -210,9 +205,6 @@ bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- int32 retry = 0;
-#endif
uint8 data = 0;
if (!bcmsdh)
@@ -220,15 +212,7 @@ bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err)
ASSERT(bcmsdh->init_success);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- do {
- if (retry) /* wait for 1 ms till bus get settled down */
- OSL_DELAY(1000);
-#endif
status = sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
if (err)
*err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR);
@@ -243,24 +227,13 @@ bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err)
{
bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
SDIOH_API_RC status;
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- int32 retry = 0;
-#endif
if (!bcmsdh)
bcmsdh = l_bcmsdh;
ASSERT(bcmsdh->init_success);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- do {
- if (retry) /* wait for 1 ms till bus get settled down */
- OSL_DELAY(1000);
-#endif
status = sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data);
-#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
- } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
-#endif
if (err)
*err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR;
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
index 8787904..79d610b 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c
@@ -1,7 +1,7 @@
/*
* SDIO access interface for drivers - linux specific (pci only)
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.8 2009/10/15 22:48:28 Exp $
+ * $Id: bcmsdh_linux.c,v 1.42.10.10.2.12 2010/03/10 03:09:48 Exp $
*/
/**
@@ -75,7 +75,7 @@ struct bcmsdh_hc {
bcmsdh_info_t *sdh; /* SDIO Host Controller handle */
void *ch;
unsigned int oob_irq;
- unsigned long oob_flags;
+ unsigned long oob_flags; /* OOB Host specifiction as edge and etc */
};
static bcmsdh_hc_t *sdhcinfo = NULL;
@@ -176,7 +176,7 @@ int bcmsdh_probe(struct device *dev)
#endif /* BCMLXSDMMC */
int irq = 0;
uint32 vendevid;
- unsigned long irq_flags = IRQF_TRIGGER_FALLING;
+ unsigned long irq_flags = 0;
#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
pdev = to_platform_device(dev);
@@ -187,6 +187,7 @@ int bcmsdh_probe(struct device *dev)
#endif /* BCMLXSDMMC */
#if defined(OOB_INTR_ONLY)
+ irq_flags = IRQF_TRIGGER_FALLING;
irq = dhd_customer_oob_irq_map(&irq_flags);
if (irq < 0) {
SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__));
@@ -334,6 +335,18 @@ static struct pci_driver bcmsdh_pci_driver = {
};
+extern uint sd_pci_slot; /* Force detection to a particular PCI */
+ /* slot only . Allows for having multiple */
+ /* WL devices at once in a PC */
+ /* Only one instance of dhd will be */
+ /* useable at a time */
+ /* Upper word is bus number, */
+ /* lower word is slot number */
+ /* Default value of 0xFFFFffff turns this */
+ /* off */
+module_param(sd_pci_slot, uint, 0);
+
+
/**
* Detect supported SDIO Host Controller and attach if found.
*
@@ -349,6 +362,26 @@ bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
bcmsdh_info_t *sdh = NULL;
int rc;
+ if (sd_pci_slot != 0xFFFFffff) {
+ if (pdev->bus->number != (sd_pci_slot>>16) ||
+ PCI_SLOT(pdev->devfn) != (sd_pci_slot&0xffff)) {
+ SDLX_MSG(("%s: %s: bus %X, slot %X, vend %X, dev %X\n",
+ __FUNCTION__,
+ bcmsdh_chipmatch(pdev->vendor, pdev->device)
+ ?"Found compatible SDIOHC"
+ :"Probing unknown device",
+ pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor,
+ pdev->device));
+ return -ENODEV;
+ }
+ SDLX_MSG(("%s: %s: bus %X, slot %X, vendor %X, device %X (good PCI location)\n",
+ __FUNCTION__,
+ bcmsdh_chipmatch(pdev->vendor, pdev->device)
+ ?"Using compatible SDIOHC"
+ :"WARNING, forced use of unkown device",
+ pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device));
+ }
+
if ((pdev->vendor == VENDOR_TI) && ((pdev->device == PCIXX21_FLASHMEDIA_ID) ||
(pdev->device == PCIXX21_FLASHMEDIA0_ID))) {
uint32 config_reg;
@@ -547,6 +580,8 @@ static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+ WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
+
dhdsdio_isr((void *)dhdp->bus);
return IRQ_HANDLED;
@@ -560,6 +595,7 @@ int bcmsdh_register_oob_intr(void * dhdp)
dev_set_drvdata(sdhcinfo->dev, dhdp);
+
/* Refer to customer Host IRQ docs about proper irqflags definition */
error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, sdhcinfo->oob_flags,
"bcmsdh_sdmmc", NULL);
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
index d5da588..68b4b24 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c
@@ -1,7 +1,7 @@
/*
* BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.27 2009/10/28 19:42:29 Exp $
+ * $Id: bcmsdh_sdmmc.c,v 1.1.2.5.6.28 2009/11/04 20:36:52 Exp $
*/
#include <typedefs.h>
@@ -211,26 +211,30 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd)
}
#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)
+sdioh_enable_func_intr(void)
{
uint8 reg;
int err;
if (gInstance->func[0]) {
sdio_claim_host(gInstance->func[0]);
- reg = sdio_readb(gInstance->func[0], _SDIO_CCCR_IENx, &err);
+
+ reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &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);
+
+ reg |= 1 << 1; /* enable function-1 interrupt */
+ reg |= 2 << 1; /* enable function-2 interrupt */
+ reg |= 1; /* Master interrupt enable */
+
+ sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &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;
@@ -238,28 +242,30 @@ sdioh_enable_func_intr(uint32 func)
}
return SDIOH_API_RC_SUCCESS;
-
}
extern SDIOH_API_RC
-sdioh_disable_func_intr(uint32 func)
+sdioh_disable_func_intr(void)
{
uint8 reg;
int err;
if (gInstance->func[0]) {
sdio_claim_host(gInstance->func[0]);
- reg = sdio_readb(gInstance->func[0], _SDIO_CCCR_IENx, &err);
+ reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &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);
+
+ reg &= ~(1 << 1);
+ reg &= ~(1 << 2);
/* Disable master interrupt with the last function interrupt */
if (!(reg & 0xFE))
reg = 0;
- sdio_writeb(gInstance->func[0], reg, _SDIO_CCCR_IENx, &err);
+ sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err);
+
sdio_release_host(gInstance->func[0]);
if (err) {
sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err));
@@ -267,7 +273,6 @@ sdioh_disable_func_intr(uint32 func)
}
}
return SDIOH_API_RC_SUCCESS;
-
}
#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
@@ -298,7 +303,7 @@ sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
sdio_release_host(gInstance->func[1]);
}
#elif defined(HW_OOB)
- sdioh_enable_func_intr(2);
+ sdioh_enable_func_intr();
#endif /* defined(OOB_INTR_ONLY) */
return SDIOH_API_RC_SUCCESS;
}
@@ -328,7 +333,7 @@ sdioh_interrupt_deregister(sdioh_info_t *sd)
sd->intr_handler = NULL;
sd->intr_handler_arg = NULL;
#elif defined(HW_OOB)
- sdioh_disable_func_intr(2);
+ sdioh_disable_func_intr();
#endif /* !defined(OOB_INTR_ONLY) */
return SDIOH_API_RC_SUCCESS;
}
@@ -678,7 +683,6 @@ sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
}
#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)
{
@@ -794,8 +798,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
* depending upon MMC driver change.
* As of this time, this is temporaray one
*/
- sdio_f0_writeb(gInstance->func[func], *byte,
- regaddr, &err_ret);
+ sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
sdio_release_host(gInstance->func[func]);
}
#endif /* MMC_SDIO_ABORT */
@@ -1066,13 +1069,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
extern int
sdioh_abort(sdioh_info_t *sd, uint func)
{
- char t_func = (char) 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);
+ sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, (uint8 *)&func);
#endif /* defined(MMC_SDIO_ABORT) */
sd_trace(("%s: Exit\n", __FUNCTION__));
@@ -1260,7 +1261,7 @@ sdioh_start(sdioh_info_t *si, int stage)
sdio_release_host(gInstance->func[0]);
#else /* defined(OOB_INTR_ONLY) */
#if defined(HW_OOB)
- sdioh_enable_func_intr(2);
+ sdioh_enable_func_intr();
#endif
bcmsdh_oob_intr_set(TRUE);
#endif /* !defined(OOB_INTR_ONLY) */
@@ -1289,7 +1290,7 @@ sdioh_stop(sdioh_info_t *si)
sdio_release_host(gInstance->func[0]);
#else /* defined(OOB_INTR_ONLY) */
#if defined(HW_OOB)
- sdioh_disable_func_intr(2);
+ sdioh_disable_func_intr();
#endif
bcmsdh_oob_intr_set(FALSE);
#endif /* !defined(OOB_INTR_ONLY) */
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
index 3643d1c..871e8a9 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
@@ -1,7 +1,7 @@
/*
* BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.10 2009/10/14 04:32:13 Exp $
+ * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.6.11 2009/11/04 20:36:52 Exp $
*/
#include <typedefs.h>
@@ -51,7 +51,6 @@
#include <dhd_dbg.h>
-
extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
@@ -81,6 +80,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
int ret = 0;
+ static struct sdio_func sdio_func_0;
sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class));
sd_trace(("sdio_vendor: 0x%04x\n", func->vendor));
@@ -88,8 +88,9 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
sd_trace(("Function#: 0x%04x\n", func->num));
if (func->num == 1) {
- /* Keep a copy of F1's 'func' in F0, just in case... */
- gInstance->func[0] = func;
+ sdio_func_0.num = 0;
+ sdio_func_0.card = func->card;
+ gInstance->func[0] = &sdio_func_0;
if(func->device == 0x4) { /* 4318 */
gInstance->func[2] = NULL;
sd_trace(("NIC found, calling bcmsdh_probe...\n"));
@@ -121,7 +122,6 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func)
}
}
-
/* devices we support, null terminated */
static const struct sdio_device_id bcmsdh_sdmmc_ids[] = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) },
@@ -169,13 +169,6 @@ 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
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdspi.c b/bcm4329/src/bcmsdio/sys/bcmsdspi.c
index 206f34e..636539b 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdspi.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdspi.c
@@ -1,7 +1,7 @@
/*
* Broadcom BCMSDH to SPI Protocol Conversion Layer
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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: bcmsdspi.c,v 1.14.4.2.4.4.6.4 2009/04/13 19:18:36 Exp $
+ * $Id: bcmsdspi.c,v 1.14.4.2.4.4.6.5 2010/03/10 03:09:48 Exp $
*/
#include <typedefs.h>
@@ -57,6 +57,7 @@ uint sd_divisor = 2; /* Default 33MHz/2 = 16MHz for dongle */
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 */
+uint sd_pci_slot = 0xFFFFffff; /* Used to force selection of a particular PCI slot */
uint sd_toctl = 7;
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c
index 1046a17..e2e0ca6 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdspi_linux.c
@@ -1,7 +1,7 @@
/*
* Broadcom SPI Host Controller Driver - Linux Per-port
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdstd.c b/bcm4329/src/bcmsdio/sys/bcmsdstd.c
index 51ff4af..0b1b575 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdstd.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdstd.c
@@ -1,7 +1,7 @@
/*
* 'Standard' SDIO HOST CONTROLLER driver
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.14 2009/10/08 20:05:30 Exp $
+ * $Id: bcmsdstd.c,v 1.64.4.1.4.4.2.17 2010/03/10 03:09:48 Exp $
*/
#include <typedefs.h>
@@ -38,7 +38,8 @@
#include <pcicfg.h>
-#define SD_PAGE 4096
+#define SD_PAGE_BITS 12
+#define SD_PAGE (1 << SD_PAGE_BITS)
#include <bcmsdstd.h>
@@ -58,16 +59,21 @@ uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */
uint sd_power = 1; /* Default to SD Slot powered ON */
uint sd_clock = 1; /* Default to SD Clock turned ON */
+uint sd_pci_slot = 0xFFFFffff; /* Used to force selection of a particular PCI slot */
+uint8 sd_dma_mode = DMA_MODE_SDMA; /* Default to SDMA for now */
uint sd_toctl = 7;
static bool trap_errs = FALSE;
+static const char *dma_mode_description[] = { "PIO", "SDMA", "ADMA1", "32b ADMA2", "64b ADMA2" };
+
/* Prototypes */
static bool sdstd_start_clock(sdioh_info_t *sd, uint16 divisor);
static bool sdstd_start_power(sdioh_info_t *sd);
static bool sdstd_bus_width(sdioh_info_t *sd, int width);
static int sdstd_set_highspeed_mode(sdioh_info_t *sd, bool HSMode);
+static int sdstd_set_dma_mode(sdioh_info_t *sd, int8 dma_mode);
static int sdstd_card_enablefuncs(sdioh_info_t *sd);
static void sdstd_cmd_getrsp(sdioh_info_t *sd, uint32 *rsp_buffer, int count);
static int sdstd_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd, uint32 arg);
@@ -84,6 +90,14 @@ static int sdstd_check_errs(sdioh_info_t *sdioh_info, uint32 cmd, uint32 arg);
static int set_client_block_size(sdioh_info_t *sd, int func, int blocksize);
static void sd_map_dma(sdioh_info_t * sd);
static void sd_unmap_dma(sdioh_info_t * sd);
+static void sd_clear_adma_dscr_buf(sdioh_info_t *sd);
+static void sd_fill_dma_data_buf(sdioh_info_t *sd, uint8 data);
+static void sd_create_adma_descriptor(sdioh_info_t *sd,
+ uint32 index, uint32 addr_phys,
+ uint16 length, uint16 flags);
+static void sd_dump_adma_dscr(sdioh_info_t *sd);
+static void sdstd_dumpregs(sdioh_info_t *sd);
+
/*
* Private register access routines.
@@ -205,15 +219,10 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
/* Set defaults */
sd->sd_blockmode = TRUE;
sd->use_client_ints = TRUE;
- sd->sd_use_dma = TRUE;
+ sd->sd_dma_mode = sd_dma_mode;
if (!sd->sd_blockmode)
- sd->sd_use_dma = 0;
-
- if (sd->sd_use_dma) {
- OSL_DMADDRWIDTH(osh, 32);
- sd_map_dma(sd);
- }
+ sd->sd_dma_mode = DMA_MODE_NONE;
if (sdstd_driver_init(sd) != SUCCESS) {
/* If host CPU was reset without resetting SD bus or
@@ -234,6 +243,11 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
}
}
+ OSL_DMADDRWIDTH(osh, 32);
+
+ /* Always map DMA buffers, so we can switch between DMA modes. */
+ sd_map_dma(sd);
+
if (sdstd_register_irq(sd, irq) != SUCCESS) {
sd_err(("%s: sdstd_register_irq() failed for irq = %d\n", __FUNCTION__, irq));
sdstd_free_irq(sd->irq, sd);
@@ -344,7 +358,7 @@ const bcm_iovar_t sdioh_iovars[] = {
{"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
{"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 },
{"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */
- {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 },
+ {"sd_dma", IOV_DMA, 0, IOVT_UINT32, 0 },
#ifdef BCMSDYIELD
{"sd_yieldcpu", IOV_YIELDCPU, 0, IOVT_BOOL, 0 },
{"sd_minyield", IOV_MINYIELD, 0, IOVT_UINT32, 0 },
@@ -429,7 +443,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
si->sd_blockmode = (bool)int_val;
/* Haven't figured out how to make non-block mode with DMA */
if (!si->sd_blockmode)
- si->sd_use_dma = 0;
+ si->sd_dma_mode = DMA_MODE_NONE;
break;
#ifdef BCMSDYIELD
@@ -503,12 +517,13 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
}
case IOV_GVAL(IOV_DMA):
- int_val = (int32)si->sd_use_dma;
+ int_val = (int32)si->sd_dma_mode;
bcopy(&int_val, arg, val_size);
break;
case IOV_SVAL(IOV_DMA):
- si->sd_use_dma = (bool)int_val;
+ si->sd_dma_mode = (char)int_val;
+ sdstd_set_dma_mode(si, si->sd_dma_mode);
break;
case IOV_GVAL(IOV_USEINTS):
@@ -764,7 +779,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0);
cmd_arg = SFIELD(cmd_arg, CMD52_DATA, rw == SDIOH_READ ? 0 : *byte);
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_52, cmd_arg)) != SUCCESS) {
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_52, cmd_arg)) != SUCCESS) {
sdstd_unlock(sd);
return status;
}
@@ -821,6 +836,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint
bool fifo = (fix_inc == SDIOH_DATA_FIX);
uint8 *localbuf = NULL, *tmpbuf = NULL;
uint tmplen = 0;
+ bool local_blockmode = sd->sd_blockmode;
sdstd_lock(sd);
@@ -838,7 +854,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint
* Both: leftovers are handled last (will be sent via bytemode).
*/
while (buflen > 0) {
- if (sd->sd_blockmode) {
+ if (local_blockmode) {
/* Max xfer is Page size */
len = MIN(SD_PAGE, buflen);
@@ -870,7 +886,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint
return SDIOH_API_RC_FAIL;
}
- if (sd->sd_blockmode) {
+ if (local_blockmode) {
if ((func == SDIO_FUNC_1) && ((tmplen % 4) == 3) && (rw == SDIOH_WRITE)) {
if (localbuf)
MFREE(sd->osh, localbuf, len);
@@ -952,6 +968,11 @@ int sdstd_abort(sdioh_info_t *sd, uint func)
if (GFIELD(plain_intstatus, INTSTAT_CMD_COMPLETE)) {
sd_err(("SDSTD_ABORT: CMD COMPLETE SET BEFORE COMMAND GIVEN!!!\n"));
}
+ if (GFIELD(plain_intstatus, INTSTAT_CARD_REMOVAL)) {
+ sd_err(("SDSTD_ABORT: INTSTAT_CARD_REMOVAL\n"));
+ err = BCME_NODEVICE;
+ goto done;
+ }
}
/* Issue the command */
@@ -1060,6 +1081,9 @@ int sdstd_abort(sdioh_info_t *sd, uint func)
}
done:
+ if (err == BCME_NODEVICE)
+ return err;
+
sdstd_wreg8(sd, SD_SoftwareReset,
SFIELD(SFIELD(0, SW_RESET_DAT, 1), SW_RESET_CMD, 1));
@@ -1200,6 +1224,7 @@ sdstd_reset(sdioh_info_t *sd, bool host_reset, bool client_reset)
/* A reset should reset bus back to 1 bit mode */
sd->sd_mode = SDIOH_MODE_SD1;
+ sdstd_set_dma_mode(sd, sd->sd_dma_mode);
}
sdstd_unlock(sd);
return TRUE;
@@ -1324,7 +1349,8 @@ sdstd_host_init(sdioh_info_t *sd)
num_slots = 1;
first_bar = 0;
- sd->sd_blockmode = FALSE;
+ /* Controller supports ADMA2, so turn it on here. */
+ sd->sd_dma_mode = DMA_MODE_ADMA2;
}
/* Map in each slot on the board and query it to see if a
@@ -1401,22 +1427,17 @@ sdstd_host_init(sdioh_info_t *sd)
sd->caps = sdstd_rreg(sd, SD_Capabilities); /* Cache this for later use */
sd->curr_caps = sdstd_rreg(sd, SD_MaxCurCap);
- if (!GFIELD(sd->caps, CAP_DMA)) {
- sd_err(("SD HOST CAPS: No SDMA Support! Disabling DMA\n"));
- sd->sd_use_dma = FALSE;
- sd->sd_blockmode = FALSE;
- }
+ sdstd_set_dma_mode(sd, sd->sd_dma_mode);
sdstd_reset(sd, 1, 0);
/* Read SD4/SD1 mode */
if ((reg8 = sdstd_rreg8(sd, SD_HostCntrl))) {
- if (reg8 & SD4_MODE)
+ if (reg8 & SD4_MODE) {
sd_err(("%s: Host cntrlr already in 4 bit mode: 0x%x\n",
__FUNCTION__, reg8));
- else
- sd_err(("%s: Error! reg 0x28 should be 0 = 0x%x\n", __FUNCTION__, reg8));
+ }
}
/* Default power on mode is SD1 */
@@ -1440,7 +1461,7 @@ get_ocr(sdioh_info_t *sd, uint32 *cmd_arg, uint32 *cmd_rsp)
retries = CMD5_RETRIES;
do {
*cmd_rsp = 0;
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_5, *cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_5, *cmd_arg))
!= SUCCESS) {
sd_err(("%s: CMD5 failed\n", __FUNCTION__));
return status;
@@ -1496,7 +1517,7 @@ sdstd_client_init(sdioh_info_t *sd)
/* In SPI mode, issue CMD0 first */
if (sd->sd_mode == SDIOH_MODE_SPI) {
cmd_arg = 0;
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_0, cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_0, cmd_arg))
!= SUCCESS) {
sd_err(("BCMSDIOH: cardinit: CMD0 failed!\n"));
return status;
@@ -1508,7 +1529,7 @@ sdstd_client_init(sdioh_info_t *sd)
/* Card is operational. Ask it to send an RCA */
cmd_arg = 0;
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_3, cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_3, cmd_arg))
!= SUCCESS) {
sd_err(("%s: CMD3 failed!\n", __FUNCTION__));
return status;
@@ -1534,7 +1555,7 @@ sdstd_client_init(sdioh_info_t *sd)
/* Select the card */
cmd_arg = SFIELD(0, CMD7_RCA, sd->card_rca);
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_7, cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_7, cmd_arg))
!= SUCCESS) {
sd_err(("%s: CMD7 failed!\n", __FUNCTION__));
return status;
@@ -1656,6 +1677,86 @@ sdstd_set_highspeed_mode(sdioh_info_t *sd, bool HSMode)
return BCME_OK;
}
+/* Select DMA Mode:
+ * If dma_mode == DMA_MODE_AUTO, pick the "best" mode.
+ * Otherwise, pick the selected mode if supported.
+ * If not supported, use PIO mode.
+ */
+static int
+sdstd_set_dma_mode(sdioh_info_t *sd, int8 dma_mode)
+{
+ uint8 reg8, dma_sel_bits = SDIOH_SDMA_MODE;
+ int8 prev_dma_mode = sd->sd_dma_mode;
+
+ switch (prev_dma_mode) {
+ case DMA_MODE_AUTO:
+ sd_dma(("%s: Selecting best DMA mode supported by controller.\n",
+ __FUNCTION__));
+ if (GFIELD(sd->caps, CAP_ADMA2)) {
+ sd->sd_dma_mode = DMA_MODE_ADMA2;
+ dma_sel_bits = SDIOH_ADMA2_MODE;
+ } else if (GFIELD(sd->caps, CAP_ADMA1)) {
+ sd->sd_dma_mode = DMA_MODE_ADMA1;
+ dma_sel_bits = SDIOH_ADMA1_MODE;
+ } else if (GFIELD(sd->caps, CAP_DMA)) {
+ sd->sd_dma_mode = DMA_MODE_SDMA;
+ } else {
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ }
+ break;
+ case DMA_MODE_NONE:
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ break;
+ case DMA_MODE_SDMA:
+ if (GFIELD(sd->caps, CAP_DMA)) {
+ sd->sd_dma_mode = DMA_MODE_SDMA;
+ } else {
+ sd_err(("%s: SDMA not supported by controller.\n", __FUNCTION__));
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ }
+ break;
+ case DMA_MODE_ADMA1:
+ if (GFIELD(sd->caps, CAP_ADMA1)) {
+ sd->sd_dma_mode = DMA_MODE_ADMA1;
+ dma_sel_bits = SDIOH_ADMA1_MODE;
+ } else {
+ sd_err(("%s: ADMA1 not supported by controller.\n", __FUNCTION__));
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ }
+ break;
+ case DMA_MODE_ADMA2:
+ if (GFIELD(sd->caps, CAP_ADMA2)) {
+ sd->sd_dma_mode = DMA_MODE_ADMA2;
+ dma_sel_bits = SDIOH_ADMA2_MODE;
+ } else {
+ sd_err(("%s: ADMA2 not supported by controller.\n", __FUNCTION__));
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ }
+ break;
+ case DMA_MODE_ADMA2_64:
+ sd_err(("%s: 64b ADMA2 not supported by driver.\n", __FUNCTION__));
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ break;
+ default:
+ sd_err(("%s: Unsupported DMA Mode %d requested.\n", __FUNCTION__,
+ prev_dma_mode));
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ break;
+ }
+
+ /* clear SysAddr, only used for SDMA */
+ sdstd_wreg(sd, SD_SysAddr, 0);
+
+ sd_err(("%s: %s mode selected.\n", __FUNCTION__, dma_mode_description[sd->sd_dma_mode]));
+
+ reg8 = sdstd_rreg8(sd, SD_HostCntrl);
+ reg8 = SFIELD(reg8, HOST_DMA_SEL, dma_sel_bits);
+ sdstd_wreg8(sd, SD_HostCntrl, reg8);
+ sd_dma(("%s: SD_HostCntrl=0x%02x\n", __FUNCTION__, reg8));
+
+ return BCME_OK;
+}
+
bool
sdstd_start_clock(sdioh_info_t *sd, uint16 new_sd_divisor)
@@ -1942,7 +2043,7 @@ sdstd_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint
cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0);
cmd_arg = SFIELD(cmd_arg, CMD52_DATA, 0);
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_52, cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_52, cmd_arg))
!= SUCCESS)
return status;
@@ -1973,7 +2074,7 @@ sdstd_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint
/* sdstd_cmd_issue() returns with the command complete bit
* in the ISR already cleared
*/
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_53, cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_53, cmd_arg))
!= SUCCESS)
return status;
@@ -2115,7 +2216,7 @@ sdstd_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uin
cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SDIOH_XFER_TYPE_WRITE);
cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0);
cmd_arg = SFIELD(cmd_arg, CMD52_DATA, data & 0xff);
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_52, cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_52, cmd_arg))
!= SUCCESS)
return status;
@@ -2138,7 +2239,7 @@ sdstd_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uin
/* sdstd_cmd_issue() returns with the command complete bit
* in the ISR already cleared
*/
- if ((status = sdstd_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_53, cmd_arg))
+ if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_53, cmd_arg))
!= SUCCESS)
return status;
@@ -2338,7 +2439,7 @@ sdstd_cmd_issue(sdioh_info_t *sdioh_info, bool use_dma, uint32 cmd, uint32 arg)
cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL);
cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd);
- use_dma = sdioh_info->sd_use_dma && GFIELD(cmd_arg, CMD53_BLK_MODE);
+ use_dma = USE_DMA(sdioh_info) && GFIELD(cmd_arg, CMD53_BLK_MODE);
if (GFIELD(cmd_arg, CMD53_BLK_MODE)) {
uint16 blocksize;
@@ -2347,22 +2448,46 @@ sdstd_cmd_issue(sdioh_info_t *sdioh_info, bool use_dma, uint32 cmd, uint32 arg)
ASSERT(sdioh_info->sd_blockmode);
+ func = GFIELD(cmd_arg, CMD53_FUNCTION);
+ blocksize = MIN((int)sdioh_info->data_xfer_count,
+ sdioh_info->client_block_size[func]);
+ blockcount = GFIELD(cmd_arg, CMD53_BYTE_BLK_CNT);
+
/* data_xfer_cnt is already setup so that for multiblock mode,
* it is the entire buffer length. For non-block or single block,
* it is < 64 bytes
*/
if (use_dma) {
- sd_info(("%s: Previous SysAddr reg was 0x%x now 0x%x\n",
- __FUNCTION__, sdstd_rreg(sdioh_info, SD_SysAddr),
- (uint32)sdioh_info->dma_phys));
+ switch (sdioh_info->sd_dma_mode) {
+ case DMA_MODE_SDMA:
+ sd_dma(("%s: SDMA: SysAddr reg was 0x%x now 0x%x\n",
+ __FUNCTION__, sdstd_rreg(sdioh_info, SD_SysAddr),
+ (uint32)sdioh_info->dma_phys));
sdstd_wreg(sdioh_info, SD_SysAddr, sdioh_info->dma_phys);
+ break;
+ case DMA_MODE_ADMA1:
+ case DMA_MODE_ADMA2:
+ sd_dma(("%s: ADMA: Using ADMA\n", __FUNCTION__));
+ sd_create_adma_descriptor(sdioh_info, 0,
+ sdioh_info->dma_phys, blockcount*blocksize,
+ ADMA2_ATTRIBUTE_VALID | ADMA2_ATTRIBUTE_END |
+ ADMA2_ATTRIBUTE_INT | ADMA2_ATTRIBUTE_ACT_TRAN);
+ /* Dump descriptor if DMA debugging is enabled. */
+ if (sd_msglevel & SDH_DMA_VAL) {
+ sd_dump_adma_dscr(sdioh_info);
+ }
+
+ sdstd_wreg(sdioh_info, SD_ADMA_SysAddr,
+ sdioh_info->adma2_dscr_phys);
+ break;
+ default:
+ sd_err(("%s: unsupported DMA mode %d.\n",
+ __FUNCTION__, sdioh_info->sd_dma_mode));
+ break;
+ }
}
- func = GFIELD(cmd_arg, CMD53_FUNCTION);
- blocksize = MIN((int)sdioh_info->data_xfer_count,
- sdioh_info->client_block_size[func]);
- blockcount = GFIELD(cmd_arg, CMD53_BYTE_BLK_CNT);
- sd_trace(("%s: Writing Block count %d, block size %d bytes\n",
+ sd_trace(("%s: Setting block count %d, block size %d bytes\n",
__FUNCTION__, blockcount, blocksize));
sdstd_wreg16(sdioh_info, SD_BlockSize, blocksize);
sdstd_wreg16(sdioh_info, SD_BlockCount, blockcount);
@@ -2464,6 +2589,7 @@ sdstd_cmd_issue(sdioh_info_t *sdioh_info, bool use_dma, uint32 cmd, uint32 arg)
if (sdioh_info->polled_mode) {
uint16 int_reg = 0;
int retries = RETRIES_LARGE;
+
do {
int_reg = sdstd_rreg16(sdioh_info, SD_IntrStatus);
} while (--retries &&
@@ -2532,7 +2658,7 @@ sdstd_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, uint32 addr, int n
if (read) sd->r_cnt++; else sd->t_cnt++;
local_blockmode = sd->sd_blockmode;
- local_dma = sd->sd_use_dma;
+ local_dma = USE_DMA(sd);
/* Don't bother with block mode on small xfers */
if (nbytes < sd->client_block_size[func]) {
@@ -2635,6 +2761,7 @@ sdstd_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, uint32 addr, int n
__FUNCTION__, read ? "Read" : "Write", int_reg,
sdstd_rreg16(sd, SD_ErrorIntrStatus),
sdstd_rreg(sd, SD_PresentState)));
+ sdstd_dumpregs(sd);
sdstd_check_errs(sd, SDIOH_CMD_53, cmd_arg);
return (ERROR);
}
@@ -2723,6 +2850,7 @@ sdstd_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, uint32 addr, int n
sdstd_rreg(sd, SD_PresentState), int_reg,
sdstd_rreg16(sd, SD_ErrorIntrStatus), nbytes,
sd->r_cnt, sd->t_cnt));
+ sdstd_dumpregs(sd);
return ERROR;
}
@@ -2793,18 +2921,210 @@ int sdioh_sdio_reset(sdioh_info_t *si)
static void
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, 12)) == NULL) {
+
+ void *va;
+
+ if ((va = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE,
+ &sd->dma_start_phys, 0x12, 12)) == NULL) {
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ sd->dma_start_buf = 0;
+ sd->dma_buf = (void *)0;
+ sd->dma_phys = 0;
+ sd->alloced_dma_size = SD_PAGE;
sd_err(("%s: DMA_ALLOC failed. Disabling DMA support.\n", __FUNCTION__));
- sd->sd_use_dma = FALSE;
+ } else {
+ sd->dma_start_buf = va;
+ sd->dma_buf = (void *)ROUNDUP((uintptr)va, SD_PAGE);
+ sd->dma_phys = ROUNDUP((sd->dma_start_phys), SD_PAGE);
+ sd->alloced_dma_size = SD_PAGE;
+ sd_err(("%s: Mapped DMA Buffer %dbytes @virt/phys: %p/0x%lx\n",
+ __FUNCTION__, sd->alloced_dma_size, sd->dma_buf, sd->dma_phys));
+ sd_fill_dma_data_buf(sd, 0xA5);
+ }
+
+ if ((va = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE,
+ &sd->adma2_dscr_start_phys, 0x12, 12)) == NULL) {
+ sd->sd_dma_mode = DMA_MODE_NONE;
+ sd->adma2_dscr_start_buf = 0;
+ sd->adma2_dscr_buf = (void *)0;
+ sd->adma2_dscr_phys = 0;
+ sd->alloced_adma2_dscr_size = 0;
+ sd_err(("%s: DMA_ALLOC failed for descriptor buffer. "
+ "Disabling DMA support.\n", __FUNCTION__));
+ } else {
+ sd->adma2_dscr_start_buf = va;
+ sd->adma2_dscr_buf = (void *)ROUNDUP((uintptr)va, SD_PAGE);
+ sd->adma2_dscr_phys = ROUNDUP((sd->adma2_dscr_start_phys), SD_PAGE);
+ sd->alloced_adma2_dscr_size = SD_PAGE;
}
+
+ sd_err(("%s: Mapped ADMA2 Descriptor Buffer %dbytes @virt/phys: %p/0x%lx\n",
+ __FUNCTION__, sd->alloced_adma2_dscr_size, sd->adma2_dscr_buf,
+ sd->adma2_dscr_phys));
+ sd_clear_adma_dscr_buf(sd);
}
+
static void
sd_unmap_dma(sdioh_info_t * sd)
{
- if (sd->sd_use_dma == FALSE)
- return;
- DMA_FREE_CONSISTENT(sd->osh, sd->dma_buf, SD_PAGE, sd->dma_phys, 0x12);
+ if (sd->dma_start_buf) {
+ DMA_FREE_CONSISTENT(sd->osh, sd->dma_start_buf, sd->alloced_dma_size,
+ sd->dma_start_phys, 0x12);
+ }
+
+ if (sd->adma2_dscr_start_buf) {
+ DMA_FREE_CONSISTENT(sd->osh, sd->adma2_dscr_start_buf, sd->alloced_adma2_dscr_size,
+ sd->adma2_dscr_start_phys, 0x12);
+ }
+}
+
+static void sd_clear_adma_dscr_buf(sdioh_info_t *sd)
+{
+ bzero((char *)sd->adma2_dscr_buf, SD_PAGE);
+ sd_dump_adma_dscr(sd);
+}
+
+static void sd_fill_dma_data_buf(sdioh_info_t *sd, uint8 data)
+{
+ memset((char *)sd->dma_buf, data, SD_PAGE);
+}
+
+
+static void sd_create_adma_descriptor(sdioh_info_t *sd, uint32 index,
+ uint32 addr_phys, uint16 length, uint16 flags)
+{
+ adma2_dscr_32b_t *adma2_dscr_table;
+ adma1_dscr_t *adma1_dscr_table;
+
+ adma2_dscr_table = sd->adma2_dscr_buf;
+ adma1_dscr_table = sd->adma2_dscr_buf;
+
+ switch (sd->sd_dma_mode) {
+ case DMA_MODE_ADMA2:
+ sd_dma(("%s: creating ADMA2 descriptor for index %d\n",
+ __FUNCTION__, index));
+
+ adma2_dscr_table[index].phys_addr = addr_phys;
+ adma2_dscr_table[index].len_attr = length << 16;
+ adma2_dscr_table[index].len_attr |= flags;
+ break;
+ case DMA_MODE_ADMA1:
+ /* ADMA1 requires two descriptors, one for len
+ * and the other for data transfer
+ */
+ index <<= 1;
+
+ sd_dma(("%s: creating ADMA1 descriptor for index %d\n",
+ __FUNCTION__, index));
+
+ adma1_dscr_table[index].phys_addr_attr = length << 12;
+ adma1_dscr_table[index].phys_addr_attr |= (ADMA1_ATTRIBUTE_ACT_SET |
+ ADMA2_ATTRIBUTE_VALID);
+ adma1_dscr_table[index+1].phys_addr_attr = addr_phys & 0xFFFFF000;
+ adma1_dscr_table[index+1].phys_addr_attr |= (flags & 0x3f);
+ break;
+ default:
+ sd_err(("%s: cannot create ADMA descriptor for DMA mode %d\n",
+ __FUNCTION__, sd->sd_dma_mode));
+ break;
+ }
+}
+
+
+static void sd_dump_adma_dscr(sdioh_info_t *sd)
+{
+ adma2_dscr_32b_t *adma2_dscr_table;
+ adma1_dscr_t *adma1_dscr_table;
+ uint32 i = 0;
+ uint16 flags;
+ char flags_str[32];
+
+ ASSERT(sd->adma2_dscr_buf != NULL);
+
+ adma2_dscr_table = sd->adma2_dscr_buf;
+ adma1_dscr_table = sd->adma2_dscr_buf;
+
+ switch (sd->sd_dma_mode) {
+ case DMA_MODE_ADMA2:
+ sd_err(("ADMA2 Descriptor Table (%dbytes) @virt/phys: %p/0x%lx\n",
+ SD_PAGE, sd->adma2_dscr_buf, sd->adma2_dscr_phys));
+ sd_err((" #[Descr VA ] Buffer PA | Len | Flags (5:4 2 1 0)"
+ " |\n"));
+ while (adma2_dscr_table->len_attr & ADMA2_ATTRIBUTE_VALID) {
+ flags = adma2_dscr_table->len_attr & 0xFFFF;
+ sprintf(flags_str, "%s%s%s%s",
+ ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_LINK) ? "LINK " :
+ ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_TRAN) ? "TRAN " :
+ ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_NOP) ? "NOP " : "RSV ",
+ (flags & ADMA2_ATTRIBUTE_INT ? "INT " : " "),
+ (flags & ADMA2_ATTRIBUTE_END ? "END " : " "),
+ (flags & ADMA2_ATTRIBUTE_VALID ? "VALID" : ""));
+ sd_err(("%2d[0x%p]: 0x%08x | 0x%04x | 0x%04x (%s) |\n",
+ i, adma2_dscr_table, adma2_dscr_table->phys_addr,
+ adma2_dscr_table->len_attr >> 16, flags, flags_str));
+ i++;
+
+ /* Follow LINK descriptors or skip to next. */
+ if ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_LINK) {
+ adma2_dscr_table = phys_to_virt(
+ adma2_dscr_table->phys_addr);
+ } else {
+ adma2_dscr_table++;
+ }
+
+ }
+ break;
+ case DMA_MODE_ADMA1:
+ sd_err(("ADMA1 Descriptor Table (%dbytes) @virt/phys: %p/0x%lx\n",
+ SD_PAGE, sd->adma2_dscr_buf, sd->adma2_dscr_phys));
+ sd_err((" #[Descr VA ] Buffer PA | Flags (5:4 2 1 0) |\n"));
+
+ for (i = 0; adma1_dscr_table->phys_addr_attr & ADMA2_ATTRIBUTE_VALID; i++) {
+ flags = adma1_dscr_table->phys_addr_attr & 0x3F;
+ sprintf(flags_str, "%s%s%s%s",
+ ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_LINK) ? "LINK " :
+ ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_TRAN) ? "TRAN " :
+ ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_NOP) ? "NOP " : "SET ",
+ (flags & ADMA2_ATTRIBUTE_INT ? "INT " : " "),
+ (flags & ADMA2_ATTRIBUTE_END ? "END " : " "),
+ (flags & ADMA2_ATTRIBUTE_VALID ? "VALID" : ""));
+ sd_err(("%2d[0x%p]: 0x%08x | 0x%04x | (%s) |\n",
+ i, adma1_dscr_table,
+ adma1_dscr_table->phys_addr_attr & 0xFFFFF000,
+ flags, flags_str));
+
+ /* Follow LINK descriptors or skip to next. */
+ if ((flags & ADMA2_ATTRIBUTE_ACT_LINK) ==
+ ADMA2_ATTRIBUTE_ACT_LINK) {
+ adma1_dscr_table = phys_to_virt(
+ adma1_dscr_table->phys_addr_attr & 0xFFFFF000);
+ } else {
+ adma1_dscr_table++;
+ }
+ }
+ break;
+ default:
+ sd_err(("Unknown DMA Descriptor Table Format.\n"));
+ break;
+ }
+}
+
+static void sdstd_dumpregs(sdioh_info_t *sd)
+{
+ sd_err(("IntrStatus: 0x%04x ErrorIntrStatus 0x%04x\n",
+ sdstd_rreg16(sd, SD_IntrStatus),
+ sdstd_rreg16(sd, SD_ErrorIntrStatus)));
+ sd_err(("IntrStatusEnable: 0x%04x ErrorIntrStatusEnable 0x%04x\n",
+ sdstd_rreg16(sd, SD_IntrStatusEnable),
+ sdstd_rreg16(sd, SD_ErrorIntrStatusEnable)));
+ sd_err(("IntrSignalEnable: 0x%04x ErrorIntrSignalEnable 0x%04x\n",
+ sdstd_rreg16(sd, SD_IntrSignalEnable),
+ sdstd_rreg16(sd, SD_ErrorIntrSignalEnable)));
}
diff --git a/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c
index 5746b08..ad6d660 100644
--- a/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c
+++ b/bcm4329/src/bcmsdio/sys/bcmsdstd_linux.c
@@ -1,7 +1,7 @@
/*
* 'Standard' SDIO HOST CONTROLLER driver - linux portion
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/bcmsdio/sys/bcmspibrcm.c b/bcm4329/src/bcmsdio/sys/bcmspibrcm.c
new file mode 100644
index 0000000..0f131a4
--- /dev/null
+++ b/bcm4329/src/bcmsdio/sys/bcmspibrcm.c
@@ -0,0 +1,1726 @@
+/*
+ * Broadcom BCMSDH to gSPI Protocol Conversion Layer
+ *
+ * Copyright (C) 2010, 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/branding.inc b/bcm4329/src/branding.inc
index 8491edd..9633ac8 100644
--- a/bcm4329/src/branding.inc
+++ b/bcm4329/src/branding.inc
@@ -1,4 +1,4 @@
-# Copyright (C) 1999-2009, Broadcom Corporation
+# Copyright (C) 1999-2010, Broadcom Corporation
#
# Unless you and Broadcom execute a separate written software license
# agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/exe/GNUmakefile b/bcm4329/src/dhd/exe/GNUmakefile
index 240189b..901f2ca 100644
--- a/bcm4329/src/dhd/exe/GNUmakefile
+++ b/bcm4329/src/dhd/exe/GNUmakefile
@@ -2,7 +2,7 @@
# GNUmakefile for dhd/exe
# (Basically a copy of wl/exe linux portion.)
#
-# Copyright (C) 1999-2009, Broadcom Corporation
+# Copyright (C) 1999-2010, Broadcom Corporation
#
# Unless you and Broadcom execute a separate written software license
# agreement governing use of this software, this software is licensed to you
@@ -49,7 +49,7 @@ CFLAGS += -DBCMSPI
#-----------------------------------------------------------
# Linux build
#
-ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le android"),)
+ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le linuxarm_omap android"),)
# $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files
DHD_OBJS := dhdu.o dhdu_linux.o bcmutils.o miniopt.o
@@ -63,6 +63,10 @@ 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 372f732..afd8b61 100644
--- a/bcm4329/src/dhd/exe/dhdu.c
+++ b/bcm4329/src/dhd/exe/dhdu.c
@@ -1,7 +1,7 @@
/*
* Common code for dhd utility, hacked from wl utility
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.11 2009/09/25 00:32:00 Exp $
+ * $Id: dhdu.c,v 1.52.2.10.2.6.2.14 2010/01/19 07:24:15 Exp $
*/
/* For backwards compatibility, the absense of the define 'BWL_NO_FILESYSTEM_SUPPORT'
@@ -71,6 +71,7 @@ static cmd_func_t dhd_pktgen;
static cmd_func_t dhd_sprom;
static cmd_func_t dhd_sdreg;
static cmd_func_t dhd_sd_msglevel, dhd_sd_blocksize, dhd_sd_mode, dhd_sd_reg;
+static cmd_func_t dhd_dma_mode;
static cmd_func_t dhd_membytes, dhd_download, dhd_upload, dhd_vars, dhd_idleclock, dhd_idletime;
static cmd_func_t dhd_logstamp;
@@ -114,6 +115,8 @@ cmd_t dhd_cmds[] = {
"get version information" },
{ "msglevel", dhd_msglevel, DHD_GET_VAR, DHD_SET_VAR,
"get/set message bits" },
+ { "wlmsglevel", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+ "get/set wl message(in dhd) bits" },
{ "bcmerrorstr", dhd_var_getandprintstr, DHD_GET_VAR, -1,
"errorstring"},
{ "wdtick", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
@@ -225,8 +228,8 @@ cmd_t dhd_cmds[] = {
"g/set blockmode"},
{ "sd_ints", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
"g/set client ints"},
- { "sd_dma", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
- "g/set dma usage"},
+ { "sd_dma", dhd_dma_mode, DHD_GET_VAR, DHD_SET_VAR,
+ "g/set dma usage: [PIO | SDMA | ADMA1 | ADMA2]"},
{ "sd_yieldcpu", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
"allow blocking (yield of CPU) on data xfer"},
{ "sd_minyield", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
@@ -670,6 +673,7 @@ static dbg_msg_t dhd_sd_msgs[] = {
{SDH_DATA_VAL, "data"},
{SDH_CTRL_VAL, "control"},
{SDH_LOG_VAL, "log"},
+ {SDH_DMA_VAL, "dma"},
{0, NULL}
};
@@ -763,6 +767,56 @@ dhd_sd_mode(void *wl, cmd_t *cmd, char **argv)
return (ret);
}
+static int
+dhd_dma_mode(void *wl, cmd_t *cmd, char **argv)
+{
+ int ret;
+ int argc;
+ int dmamode;
+
+ /* arg count */
+ for (argc = 0; argv[argc]; argc++);
+ argc--;
+
+ if (argv[1]) {
+ if (!stricmp(argv[1], "pio")) {
+ strcpy(argv[1], "0");
+ } else if (!strcmp(argv[1], "0")) {
+ } else if (!stricmp(argv[1], "dma")) {
+ strcpy(argv[1], "1");
+ } else if (!stricmp(argv[1], "sdma")) {
+ strcpy(argv[1], "1");
+ } else if (!strcmp(argv[1], "1")) {
+ } else if (!stricmp(argv[1], "adma1")) {
+ strcpy(argv[1], "2");
+ } else if (!stricmp(argv[1], "adma")) {
+ strcpy(argv[1], "3");
+ } else if (!stricmp(argv[1], "adma2")) {
+ strcpy(argv[1], "3");
+ } else {
+ return USAGE_ERROR;
+ }
+
+ ret = dhd_var_setint(wl, cmd, argv);
+
+ } else {
+ if ((ret = dhd_var_get(wl, cmd, argv))) {
+ return (ret);
+ } else {
+ dmamode = *(int32*)buf;
+
+ printf("DMA Mode is: %s\n",
+ dmamode == 0 ? "PIO"
+ : dmamode == 1 ? "SDMA"
+ : dmamode == 2 ? "ADMA1"
+ : dmamode == 3 ? "ADMA2"
+ : "Unknown");
+ }
+ }
+
+ return (ret);
+}
+
static int
dhd_sdreg(void *dhd, cmd_t *cmd, char **argv)
diff --git a/bcm4329/src/dhd/exe/dhdu.h b/bcm4329/src/dhd/exe/dhdu.h
index 97a56d6..44f0368 100644
--- a/bcm4329/src/dhd/exe/dhdu.h
+++ b/bcm4329/src/dhd/exe/dhdu.h
@@ -1,7 +1,7 @@
/*
* Common code for dhd utility, hacked from wl utility
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/exe/dhdu_cmd.h b/bcm4329/src/dhd/exe/dhdu_cmd.h
index 8e1f642..220bbda 100644
--- a/bcm4329/src/dhd/exe/dhdu_cmd.h
+++ b/bcm4329/src/dhd/exe/dhdu_cmd.h
@@ -1,7 +1,7 @@
/*
* Command structure for dhd command line utility, copied from wl utility
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/exe/dhdu_linux.c b/bcm4329/src/dhd/exe/dhdu_linux.c
index b4dcbc7..e00c460 100644
--- a/bcm4329/src/dhd/exe/dhdu_linux.c
+++ b/bcm4329/src/dhd/exe/dhdu_linux.c
@@ -1,7 +1,7 @@
/*
* Linux port of dhd command line utility, hacked from wl utility.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/linux/Makefile b/bcm4329/src/dhd/linux/Makefile
index 89300a1..19d81d2 100644
--- a/bcm4329/src/dhd/linux/Makefile
+++ b/bcm4329/src/dhd/linux/Makefile
@@ -1,7 +1,7 @@
# GNU Makefile for Broadcom Dongle Host Driver
#
-# Copyright (C) 1999-2009, Broadcom Corporation
+# Copyright (C) 1999-2010, Broadcom Corporation
#
# Unless you and Broadcom execute a separate written software license
# agreement governing use of this software, this software is licensed to you
@@ -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.24 2009/10/22 18:40:45 Exp $
+# $Id: Makefile,v 1.55.2.6.2.10.6.27 2010/02/24 02:54:05 Exp $
#
# Try a couple of places for LINUXDIR if not specified
@@ -70,7 +70,7 @@ OBJCOPY := $(CROSS_COMPILE)objcopy
ifeq ($(SRCBASE),)
SRCBASE := $(shell /bin/pwd)/../..
endif
-vpath %.c $(SRCBASE)/dhd/sys $(SRCBASE)/shared $(SRCBASE)/bcmsdio/sys $(SRCBASE)/wl/sys
+vpath %.c $(SRCBASE)/dhd/sys $(SRCBASE)/shared $(SRCBASE)/bcmsdio/sys $(SRCBASE)/wl/sys $(SRCBASE)/crypto
## Initialize DFLAGS
DFLAGS :=
@@ -211,8 +211,14 @@ 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 -softap-,-$(TARGET)-),)
+DFLAGS += -DSOFTAP
+CFILES += sha1.c md5.c
+endif
ifneq ($(findstring -oob-,-$(TARGET)-),)
DFLAGS += -DOOB_INTR_ONLY
+DFLAGS += -DHW_OOB
+DFLAGS += -DMMC_SDIO_ABORT
else
ifneq ($(findstring -sdmmc-,-$(TARGET)-),)
DFLAGS += -DSDIO_ISR_THREAD
@@ -246,10 +252,14 @@ MODULES := dhd.o
ifeq ($(BCM_KVER), 2.6)
##Kernel module names in 2.6 kernel have .ko suffix
KMODULES:=dhd.ko
+ ifneq ($(findstring -nexus-,$(TARGET)-),)
+ KMODULES:=bcm4329.ko
+ endif
else
KMODULES:=$(MODULES)
endif
+
# host options
HOSTCC := $(CC)
ifneq ($(BCM_KVER), 2.6)
@@ -266,7 +276,9 @@ TARGETS := \
dhd-cdc-usb dhd-cdc-sdstd \
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
+ dhd-cdc-sdstd-apsta \
+ dhd-cdc-sdmmc-softap-gpl
+
TARGETS += \
@@ -311,9 +323,9 @@ ifneq ($(BCM_KVER), 2.6)
endif
$(MAKE) -C $(OBJDIR) -f $(SRCBASE)/dhd/linux/Makefile SRCBASE=$(SRCBASE) modules
ifeq ($(BCM_KVER), 2.6)
- $(OBJCOPY) --strip-unneeded $(OBJDIR)/dhd.ko $(OBJDIR)/dhd.ko.stripped
+ $(OBJCOPY) --strip-unneeded $(OBJDIR)/$(KMODULES) $(OBJDIR)/$(KMODULES).stripped
else
- $(OBJCOPY) --strip-unneeded $(OBJDIR)/dhd.o $(OBJDIR)/dhd.o.stripped
+ $(OBJCOPY) --strip-unneeded $(OBJDIR)/$(MODULES) $(OBJDIR)/$(MODULES).stripped
endif
dep: $(foreach file,$(CFILES),.$(file).depend)
@@ -330,7 +342,7 @@ else
modules: $(MODULES)
endif
-dhd.o: $(OFILES)
+$(MODULES): $(OFILES)
$(LD) $(LDFLAGS) -o $@ $^
ifeq ($(BCM_KVER), 2.6)
diff --git a/bcm4329/src/dhd/linux/makefile.26 b/bcm4329/src/dhd/linux/makefile.26
index 86c220b..eceee8e 100644
--- a/bcm4329/src/dhd/linux/makefile.26
+++ b/bcm4329/src/dhd/linux/makefile.26
@@ -2,7 +2,7 @@
# Makefile fragment for Linux 2.6
# Broadcom DHD Driver
#
-# Copyright (C) 1999-2009, Broadcom Corporation
+# Copyright (C) 1999-2010, Broadcom Corporation
#
# Unless you and Broadcom execute a separate written software license
# agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h
index 38baa8a..faf016f 100644
--- a/bcm4329/src/dhd/sys/dhd.h
+++ b/bcm4329/src/dhd/sys/dhd.h
@@ -4,7 +4,7 @@
* Provides type definitions and function prototypes used to link the
* DHD OS, bus, and protocol modules.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.25 2009/10/27 04:41:56 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.29 2010/02/23 06:58:21 Exp $
*/
/****************
@@ -46,23 +46,25 @@
#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
-#define EFAULT 2
+#define EFAULT 2
#define EINVAL 3
-#define EIO 4
+#define EIO 4
#define ETIMEDOUT 5
-#define ERESTARTSYS 6
+#define ERESTARTSYS 6
#endif /* LINUX */
#include <wlioctl.h>
-#ifdef NDIS60
+#if defined(NDIS60)
#include <wdf.h>
#include <WdfMiniport.h>
-#endif /* NDIS60 */
+#endif
/* Forward decls */
struct dhd_bus;
@@ -147,9 +149,12 @@ 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
+#if defined(NDIS60)
typedef struct _wdf_device_info {
dhd_pub_t *dhd;
@@ -158,7 +163,7 @@ typedef struct _wdf_device_info {
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info)
-#endif /* NDIS60 */
+#endif /* NDIS60 && !UNDERC_CE */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
@@ -166,7 +171,7 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info)
#define _DHD_PM_RESUME_WAIT(a, b) do {\
int retry = 0; \
while (dhd_mmc_suspend && retry++ != b) { \
- wait_event_interruptible_timeout(a, FALSE, HZ/100); \
+ wait_event_timeout(a, FALSE, HZ/100); \
} \
} while (0)
#define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30)
@@ -178,7 +183,7 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info)
#define SPINWAIT_SLEEP(a, exp, us) do { \
uint countdown = (us) + 9; \
while ((exp) && (countdown >= 10)) { \
- wait_event_interruptible_timeout(a, FALSE, HZ/100); \
+ wait_event_timeout(a, FALSE, HZ/100); \
countdown -= 10; \
} \
} while (0)
@@ -203,11 +208,41 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */
-/* Wakelock Functions */
-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);
-extern int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub);
+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;
@@ -275,6 +310,8 @@ 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);
+extern void dhd_os_sdlock_eventq(dhd_pub_t * pub);
+extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub);
#if defined(OOB_INTR_ONLY)
extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr);
#endif /* defined(OOB_INTR_ONLY) */
@@ -321,6 +358,7 @@ extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag);
extern uint dhd_bus_status(dhd_pub_t *dhdp);
extern int dhd_bus_start(dhd_pub_t *dhdp);
+extern void print_buf(void *pbuf, int len, int bytes_per_line);
typedef enum cust_gpio_modes {
@@ -329,6 +367,7 @@ typedef enum cust_gpio_modes {
WLAN_POWER_ON,
WLAN_POWER_OFF
} cust_gpio_modes_t;
+extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
/*
* Insmod parameters for debug/test
*/
@@ -337,6 +376,10 @@ typedef enum cust_gpio_modes {
extern uint dhd_watchdog_ms;
+#if defined(DHD_DEBUG)
+extern uint wl_msg_level;
+#endif /* DHD_DEBUG */
+
/* Use interrupts */
extern uint dhd_intr;
diff --git a/bcm4329/src/dhd/sys/dhd_bus.h b/bcm4329/src/dhd/sys/dhd_bus.h
index 93392f9..7156543 100644
--- a/bcm4329/src/dhd/sys/dhd_bus.h
+++ b/bcm4329/src/dhd/sys/dhd_bus.h
@@ -4,7 +4,7 @@
* Provides type definitions and function prototypes used to link the
* DHD OS, bus, and protocol modules.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/sys/dhd_cdc.c b/bcm4329/src/dhd/sys/dhd_cdc.c
index 935a766..77da0ea 100644
--- a/bcm4329/src/dhd/sys/dhd_cdc.c
+++ b/bcm4329/src/dhd/sys/dhd_cdc.c
@@ -1,7 +1,7 @@
/*
* DHD Protocol Module for CDC and BDC.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.30 2009/10/28 21:38:04 Exp $
+ * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.34 2010/01/21 22:08:34 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
@@ -73,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
@@ -87,9 +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
@@ -141,9 +136,9 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
msg->cmd = htol32(cmd);
msg->len = htol32(len);
- flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
- msg->flags = htol32(flags);
+ msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
CDC_SET_IF_IDX(msg, ifidx);
+ msg->flags = htol32(msg->flags);
if (buf)
memcpy(prot->buf, buf, len);
@@ -208,9 +203,9 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
msg->cmd = htol32(cmd);
msg->len = htol32(len);
- flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
- msg->flags |= htol32(flags);
+ msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
CDC_SET_IF_IDX(msg, ifidx);
+ msg->flags |= htol32(msg->flags);
if (buf)
memcpy(prot->buf, buf, len);
@@ -288,7 +283,6 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
ret = 0;
else {
cdc_ioctl_t *msg = &prot->msg;
- CDC_SET_IF_IDX(msg, ifidx);
ioc->needed = ltoh32(msg->len); /* len == needed when set/query fails from dongle */
}
@@ -634,7 +628,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
if ((ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
dhd_os_proto_unblock(dhd);
- return -BCME_NOTUP;
+ return BCME_NOTUP;
}
memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
@@ -737,7 +731,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
(char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
if (mask_size != pattern_size) {
- printk("Mask and pattern not the same size\n");
+ DHD_ERROR(("Mask and pattern not the same size\n"));
dhd_os_proto_unblock(dhd);
return -EINVAL;
}
diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c
index f840aba..ae0c3fb 100644
--- a/bcm4329/src/dhd/sys/dhd_common.c
+++ b/bcm4329/src/dhd/sys/dhd_common.c
@@ -1,7 +1,7 @@
/*
* Broadcom Dongle Host Driver (DHD), common DHD core.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.37 2009/10/22 14:47:18 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.41 2010/02/24 01:52:41 Exp $
*/
#include <typedefs.h>
#include <osl.h>
@@ -79,7 +79,7 @@ const bcm_iovar_t dhd_iovars[] = {
{"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) },
#ifdef DHD_DEBUG
{"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 },
-#endif
+#endif /* DHD_DEBUG */
{"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN },
{"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0 },
{"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0 },
@@ -101,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
@@ -197,6 +189,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
dhd_msg_level = int_val;
break;
+
case IOV_GVAL(IOV_BCMERRORSTR):
strncpy((char *)arg, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN);
((char *)arg)[BCME_STRLEN - 1] = 0x00;
@@ -553,6 +546,8 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data)
event_name = event_names[i].event_name;
}
+ DHD_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type));
+
if (flags & WLC_EVENT_MSG_LINK)
link = TRUE;
if (flags & WLC_EVENT_MSG_GROUP)
@@ -891,3 +886,25 @@ wl_event_to_host_order(wl_event_msg_t *evt)
evt->datalen = ntoh32(evt->datalen);
evt->version = ntoh16(evt->version);
}
+
+void print_buf(void *pbuf, int len, int bytes_per_line)
+{
+ int i, j = 0;
+ unsigned char *buf = pbuf;
+
+ if (bytes_per_line == 0) {
+ bytes_per_line = len;
+ }
+
+ for (i = 0; i < len; i++) {
+ printf("%2.2x", *buf++);
+ j++;
+ if (j == bytes_per_line) {
+ printf("\n");
+ j = 0;
+ } else {
+ printf(":");
+ }
+ }
+ printf("\n");
+}
diff --git a/bcm4329/src/dhd/sys/dhd_custom_gpio.c b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
index 9d655f9..cb67ae2 100644
--- a/bcm4329/src/dhd/sys/dhd_custom_gpio.c
+++ b/bcm4329/src/dhd/sys/dhd_custom_gpio.c
@@ -1,6 +1,6 @@
/*
* Customer code to add GPIO control during WLAN start/stop
-* Copyright (C) 1999-2009, Broadcom Corporation
+* Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.3 2009/10/14 04:29:34 Exp $
+* $Id: dhd_custom_gpio.c,v 1.1.4.6 2010/02/19 22:56:49 Exp $
*/
@@ -42,7 +42,6 @@
extern void bcm_wlan_power_off(int);
extern void bcm_wlan_power_on(int);
#endif /* CUSTOMER_HW */
-
#ifdef CUSTOMER_HW2
int wifi_set_carddetect(int on);
int wifi_set_power(int on, unsigned long msec);
@@ -55,6 +54,10 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr);
extern int sdioh_mmc_irq(int irq);
#endif /* (BCMLXSDMMC) */
+#ifdef CUSTOMER_HW3
+#include <mach/gpio.h>
+#endif
+
/* Customer specific Host GPIO defintion */
static int dhd_oob_gpio_num = -1; /* GG 19 */
@@ -63,10 +66,12 @@ MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number");
int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
{
- int host_oob_irq;
+ int host_oob_irq = 0;
+
#ifdef CUSTOMER_HW2
host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
-#else
+
+#else /* for NOT CUSTOMER_HW2 */
#if defined(CUSTOM_OOB_GPIO_NUM)
if (dhd_oob_gpio_num < 0) {
dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
@@ -74,17 +79,23 @@ int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
#endif
*irq_flags_ptr = IRQF_TRIGGER_FALLING;
if (dhd_oob_gpio_num < 0) {
- WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n", \
- __FUNCTION__));
+ WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
+ __FUNCTION__));
return (dhd_oob_gpio_num);
}
- WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n", \
+ 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);
-#endif
+#if defined CUSTOMER_HW
+ host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num);
+#elif defined CUSTOMER_HW3
+ gpio_request(dhd_oob_gpio_num, "oob irq");
+ host_oob_irq = gpio_to_irq(dhd_oob_gpio_num);
+ gpio_direction_input(dhd_oob_gpio_num);
+#endif /* CUSTOMER_HW */
+#endif /* CUSTOMER_HW2 */
+
return (host_oob_irq);
}
#endif /* defined(OOB_INTR_ONLY) */
diff --git a/bcm4329/src/dhd/sys/dhd_dbg.h b/bcm4329/src/dhd/sys/dhd_dbg.h
index f7f0c35..852f3c2 100644
--- a/bcm4329/src/dhd/sys/dhd_dbg.h
+++ b/bcm4329/src/dhd/sys/dhd_dbg.h
@@ -1,7 +1,7 @@
/*
* Debug/trace/assert driver definitions for Dongle Host Driver.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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_dbg.h,v 1.5.6.2.4.2.14.2 2009/05/20 19:41:53 Exp $
+ * $Id: dhd_dbg.h,v 1.5.6.2.4.2.14.6 2010/02/23 05:36:53 Exp $
*/
#ifndef _dhd_dbg_
@@ -29,7 +29,8 @@
#ifdef DHD_DEBUG
-#define DHD_ERROR(args) do {if (dhd_msg_level & DHD_ERROR_VAL) printf args;} while (0)
+#define DHD_ERROR(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
+ printf args;} while (0)
#define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0)
#define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0)
#define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0)
@@ -57,7 +58,7 @@
#else /* DHD_DEBUG */
-#define DHD_ERROR(args) printk args
+#define DHD_ERROR(args) do {if (net_ratelimit()) printf args;} while (0)
#define DHD_TRACE(args)
#define DHD_INFO(args)
#define DHD_DATA(args)
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index df46938..38a1a11 100644
--- a/bcm4329/src/dhd/sys/dhd_linux.c
+++ b/bcm4329/src/dhd/sys/dhd_linux.c
@@ -2,7 +2,7 @@
* Broadcom Dongle Host Driver (DHD), Linux-specific network interface
* Basically selected code segments from usb-cdc.c and usb-rndis.c
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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: dhd_linux.c,v 1.65.4.9.2.12.2.46 2009/10/28 10:35:11 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.60.4.1 2010/03/16 03:29:40 Exp $
*/
#ifdef CONFIG_WIFI_CONTROL_FUNC
@@ -57,11 +57,6 @@
#include <dhd_bus.h>
#include <dhd_proto.h>
#include <dhd_dbg.h>
-#include <wl_iw.h>
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-#include <linux/freezer.h>
#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
#include <linux/wifi_tiwlan.h>
@@ -115,13 +110,12 @@ int wifi_set_reset(int on, unsigned long msec)
mdelay(msec);
return 0;
}
-
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__));
+ printk("## %s\n", __FUNCTION__);
wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
wifi_control_data = wifi_ctrl;
@@ -137,7 +131,7 @@ 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__));
+ printk("## %s\n", __FUNCTION__);
wifi_control_data = wifi_ctrl;
wifi_set_carddetect(0); /* CardDetect (1->0) */
@@ -154,7 +148,7 @@ static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
static int wifi_resume(struct platform_device *pdev)
{
DHD_TRACE(("##> %s\n", __FUNCTION__));
- return 0;
+ return 0;
}
static struct platform_driver wifi_device = {
@@ -254,15 +248,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;
-
/* Thread to issue ioctl for multicast */
long sysioc_pid;
struct semaphore sysioc_sem;
@@ -286,6 +271,7 @@ char nvram_path[MOD_PARAM_PATHLEN];
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
struct semaphore dhd_registration_sem;
+#define DHD_REGISTRATION_TIMEOUT 8000 /* msec : allowed time to finished dhd registration */
#endif
/* load firmware and/or nvram values from the filesystem */
module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0);
@@ -315,6 +301,10 @@ module_param(dhd_dpc_prio, int, 0);
extern int dhd_dongle_memsize;
module_param(dhd_dongle_memsize, int, 0);
+/* Network inteface name */
+char iface_name[IFNAMSIZ];
+module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
#define DAEMONIZE(a) daemonize(a); \
allow_signal(SIGKILL); \
@@ -712,11 +702,15 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr)
return ret;
}
+#ifdef SOFTAP
+extern struct net_device *ap_net_dev;
+#endif
+
static void
dhd_op_if(dhd_if_t *ifp)
{
dhd_info_t *dhd;
- int ret = 0;
+ int ret = 0, err = 0;
ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */
@@ -743,15 +737,29 @@ dhd_op_if(dhd_if_t *ifp)
if (ret == 0) {
strcpy(ifp->net->name, ifp->name);
memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd));
- if (dhd_net_attach(&dhd->pub, ifp->idx) != 0) {
- DHD_ERROR(("%s: dhd_net_attach failed\n", __FUNCTION__));
+ if ((err = dhd_net_attach(&dhd->pub, ifp->idx)) != 0) {
+ DHD_ERROR(("%s: dhd_net_attach failed, err %d\n",
+ __FUNCTION__, err));
ret = -EOPNOTSUPP;
- } else
+ } else {
+#ifdef SOFTAP
+ /* semaphore that the soft AP CODE waits on */
+ extern struct semaphore ap_eth_sema;
+
+ /* save ptr to wl0.1 netdev for use in wl_iw.c */
+ ap_net_dev = ifp->net;
+ /* signal to the SOFTAP 'sleeper' thread, wl0.1 is ready */
+ up(&ap_eth_sema);
+#endif
+ DHD_TRACE(("\n ==== pid:%x, net_device for if:%s created ===\n\n",
+ current->pid, ifp->net->name));
ifp->state = 0;
+ }
}
break;
case WLC_E_IF_DEL:
if (ifp->net != NULL) {
+ DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n", __FUNCTION__));
netif_stop_queue(ifp->net);
unregister_netdev(ifp->net);
ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */
@@ -763,12 +771,23 @@ dhd_op_if(dhd_if_t *ifp)
break;
}
+
if (ret < 0) {
- if (ifp->net)
+
+ if (ifp->net) {
+
free_netdev(ifp->net);
+ }
+
dhd->iflist[ifp->idx] = NULL;
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
+
+#ifdef SOFTAP
+ if (ifp->net == ap_net_dev)
+ ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */
+#endif /* SOFTAP */
}
+
}
static int
@@ -777,12 +796,9 @@ _dhd_sysioc_thread(void *data)
dhd_info_t *dhd = (dhd_info_t *)data;
int i;
- set_freezable();
-
DAEMONIZE("dhd_sysioc");
while (down_interruptible(&dhd->sysioc_sem) == 0) {
- dhd_os_wake_lock(&dhd->pub);
for (i = 0; i < DHD_MAX_IFS; i++) {
if (dhd->iflist[i]) {
if (dhd->iflist[i]->state)
@@ -797,7 +813,6 @@ _dhd_sysioc_thread(void *data)
}
}
}
- dhd_os_wake_unlock(&dhd->pub);
}
complete_and_exit(&dhd->sysioc_exited, 0);
}
@@ -871,6 +886,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
#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 */
@@ -890,7 +906,6 @@ 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__));
- netif_stop_queue(net);
return -ENODEV;
}
@@ -1051,7 +1066,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
}
}
- dhd_os_wake_lock_timeout_enable(dhdp);
}
void
@@ -1118,6 +1132,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
@@ -1131,17 +1146,17 @@ 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) {
- dhd_os_wake_lock(&dhd->pub);
- /* Call the bus module watchdog */
- dhd_bus_watchdog(&dhd->pub);
-
+ if (dhd->pub.dongle_reset == FALSE) {
+ 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++;
@@ -1149,12 +1164,12 @@ dhd_watchdog_thread(void *data)
if (dhd->wd_timer_valid) {
mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
}
- dhd_os_wake_unlock(&dhd->pub);
}
else
break;
}
+ WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_WATCHDOG);
complete_and_exit(&dhd->watchdog_exited, 0);
}
@@ -1175,12 +1190,8 @@ dhd_watchdog(ulong data)
dhd->pub.tickcnt++;
/* Reschedule the watchdog */
-#if defined(CONTINUOUS_WATCHDOG)
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-#else
if (dhd->wd_timer_valid)
mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
-#endif /* defined(CONTINUOUS_WATCHDOG) */
}
static int
@@ -1188,6 +1199,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
*/
@@ -1200,8 +1212,6 @@ dhd_dpc_thread(void *data)
}
#endif /* DHD_SCHED */
- set_freezable();
-
DAEMONIZE("dhd_dpc");
/* Run until signal received */
@@ -1209,21 +1219,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) {
+ WAKE_LOCK(&dhd->pub, WAKE_LOCK_DPC);
if (dhd_bus_dpc(dhd->pub.bus)) {
up(&dhd->dpc_sem);
+ WAKE_LOCK_TIMEOUT(&dhd->pub, WAKE_LOCK_TMOUT, 25);
}
- else {
- dhd_os_wake_unlock(&dhd->pub);
- }
+ 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);
}
@@ -1248,7 +1259,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;
@@ -1473,6 +1483,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
+
if (ifidx == DHD_BAD_IF)
return -1;
@@ -1564,9 +1575,13 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
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 && buf && ioc.buf) {
if (copy_to_user(ioc.buf, buf, buflen))
@@ -1611,8 +1626,6 @@ dhd_open(struct net_device *net)
#endif
int ifidx;
- wl_control_wl_start(net); /* start if needed */
-
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
@@ -1744,15 +1757,26 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
memcpy(netdev_priv(net), &dhd, sizeof(dhd));
dhd->pub.osh = osh;
+ /* Set network interface name if it was provided as module parameter */
+ if (iface_name[0]) {
+ int len;
+ char ch;
+ strncpy(net->name, iface_name, IFNAMSIZ);
+ net->name[IFNAMSIZ - 1] = 0;
+ len = strlen(net->name);
+ ch = net->name[len - 1];
+ if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
+ strcat(net->name, "%d");
+ }
+
if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF)
goto fail;
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
net->open = NULL;
#else
net->netdev_ops = NULL;
#endif
-
init_MUTEX(&dhd->proto_sem);
/* Initialize other structure content */
init_waitqueue_head(&dhd->ioctl_resp_wait);
@@ -1762,15 +1786,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;
@@ -1844,6 +1859,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
#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;
@@ -1876,12 +1894,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 */
@@ -1896,7 +1921,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
#if defined(OOB_INTR_ONLY)
/* Host registration for OOB interrupt */
if (bcmsdh_register_oob_intr(dhdp)) {
- del_timer_sync(&dhd->timer);
+ del_timer(&dhd->timer);
dhd->wd_timer_valid = FALSE;
DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__));
return -ENODEV;
@@ -1908,7 +1933,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
/* If bus is not ready, can't come up */
if (dhd->pub.busstate != DHD_BUS_DATA) {
- del_timer_sync(&dhd->timer);
+ del_timer(&dhd->timer);
dhd->wd_timer_valid = FALSE;
DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
return -ENODEV;
@@ -1945,7 +1970,7 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, in
return ret;
}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
static struct net_device_ops dhd_ops_pri = {
.ndo_open = dhd_open,
.ndo_stop = dhd_stop,
@@ -1953,7 +1978,7 @@ static struct net_device_ops dhd_ops_pri = {
.ndo_do_ioctl = dhd_ioctl_entry,
.ndo_start_xmit = dhd_start_xmit,
.ndo_set_mac_address = dhd_set_mac_address,
- .ndo_set_multicast_list = dhd_set_multicast_list,
+ .ndo_set_multicast_list = dhd_set_multicast_list
};
static struct net_device_ops dhd_ops_virt = {
@@ -1961,10 +1986,9 @@ static struct net_device_ops dhd_ops_virt = {
.ndo_do_ioctl = dhd_ioctl_entry,
.ndo_start_xmit = dhd_start_xmit,
.ndo_set_mac_address = dhd_set_mac_address,
- .ndo_set_multicast_list = dhd_set_multicast_list,
+ .ndo_set_multicast_list = dhd_set_multicast_list
};
-#endif
-
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */
int
dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
{
@@ -1975,10 +1999,11 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
ASSERT(dhd && dhd->iflist[ifidx]);
- net = dhd->iflist[ifidx]->net;
+ net = dhd->iflist[ifidx]->net;
ASSERT(net);
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
ASSERT(!net->open);
net->get_stats = dhd_get_stats;
net->do_ioctl = dhd_ioctl_entry;
@@ -1996,7 +2021,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
/*
* device functions for the primary interface only
*/
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
net->open = dhd_open;
net->stop = dhd_stop;
#else
@@ -2022,6 +2047,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
#endif /* WIRELESS_EXT > 12 */
#endif /* CONFIG_WIRELESS_EXT */
+
dhd->pub.rxsz = net->mtu + net->hard_header_len + dhd->pub.hdrlen;
memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
@@ -2034,6 +2060,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
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]);
+ wl_iw_iscan_set_scan_broadcast_prep(net, 1);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
up(&dhd_registration_sem);
@@ -2041,7 +2068,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
return 0;
fail:
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
net->open = NULL;
#else
net->netdev_ops = NULL;
@@ -2069,7 +2096,7 @@ dhd_bus_detach(dhd_pub_t *dhdp)
#endif /* defined(OOB_INTR_ONLY) */
/* Clear the watchdog timer */
- del_timer_sync(&dhd->timer);
+ del_timer(&dhd->timer);
dhd->wd_timer_valid = FALSE;
}
}
@@ -2091,14 +2118,6 @@ dhd_detach(dhd_pub_t *dhdp)
#if defined(CONFIG_HAS_EARLYSUSPEND)
unregister_early_suspend(&dhd->early_suspend);
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
-#ifdef CONFIG_WIRELESS_EXT
- /* Attach and link in the iw */
- wl_iw_detach();
-#endif
- if (dhd->sysioc_pid >= 0) {
- KILL_PROC(dhd->sysioc_pid, SIGTERM);
- wait_for_completion(&dhd->sysioc_exited);
- }
for (i = 1; i < DHD_MAX_IFS; i++)
if (dhd->iflist[i])
@@ -2106,7 +2125,7 @@ dhd_detach(dhd_pub_t *dhdp)
ifp = dhd->iflist[0];
ASSERT(ifp);
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
if (ifp->net->open) {
#else
if (ifp->net->netdev_ops == &dhd_ops_pri) {
@@ -2115,38 +2134,60 @@ dhd_detach(dhd_pub_t *dhdp)
unregister_netdev(ifp->net);
}
- if (dhd->watchdog_pid >= 0)
- {
- KILL_PROC(dhd->watchdog_pid, SIGTERM);
- wait_for_completion(&dhd->watchdog_exited);
- }
- if (dhd->dpc_pid >= 0)
- {
- KILL_PROC(dhd->dpc_pid, SIGTERM);
- wait_for_completion(&dhd->dpc_exited);
- }
- else
- tasklet_kill(&dhd->tasklet);
+ if (dhd->watchdog_pid >= 0)
+ {
+ KILL_PROC(dhd->watchdog_pid, SIGTERM);
+ wait_for_completion(&dhd->watchdog_exited);
+ }
+
+ if (dhd->dpc_pid >= 0)
+ {
+ KILL_PROC(dhd->dpc_pid, SIGTERM);
+ wait_for_completion(&dhd->dpc_exited);
+ }
+ else
+ tasklet_kill(&dhd->tasklet);
- dhd_bus_detach(dhdp);
+ if (dhd->sysioc_pid >= 0) {
+ KILL_PROC(dhd->sysioc_pid, SIGTERM);
+ wait_for_completion(&dhd->sysioc_exited);
+ }
+
+ dhd_bus_detach(dhdp);
- if (dhdp->prot)
- dhd_prot_detach(dhdp);
+ if (dhdp->prot)
+ dhd_prot_detach(dhdp);
+
+#ifdef CONFIG_WIRELESS_EXT
+ /* Attach and link in the iw */
+ wl_iw_detach();
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
- unregister_pm_notifier(&dhd_sleep_pm_notifier);
+ unregister_pm_notifier(&dhd_sleep_pm_notifier);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
- 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));
- }
+ WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_TMOUT);
+ WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_LINK_DOWN_TMOUT);
+ free_netdev(ifp->net);
+ MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
+ MFREE(dhd->pub.osh, dhd, sizeof(*dhd));
}
}
+}
+static void __exit
+dhd_module_cleanup(void)
+{
+ DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+
+ dhd_bus_unregister();
+#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);
+}
+
static int __init
dhd_module_init(void)
@@ -2168,7 +2209,6 @@ dhd_module_init(void)
DHD_ERROR(("Invalid module parameters.\n"));
return -EINVAL;
} while (0);
-
/* Call customer gpio to turn on power with WL_REG_ON signal */
dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON);
@@ -2178,18 +2218,19 @@ dhd_module_init(void)
error = wifi_add_dev();
if (error) {
DHD_ERROR(("%s: platform_driver_register failed\n", __FUNCTION__));
- goto fail_0;
+ goto faild;
}
/* Waiting callback after platform_driver_register is done or exit with error */
- if (down_timeout(&wifi_control_sem, msecs_to_jiffies(5000)) != 0) {
- error = -EINVAL;
- DHD_ERROR(("%s: platform_driver_register timeout\n", __FUNCTION__));
- goto fail_1;
+ if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
+ printk("%s: platform_driver_register timeout\n", __FUNCTION__);
+ /* renove device */
+ wifi_del_dev();
+ goto faild;
}
#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1
sema_init(&dhd_registration_sem, 0);
#endif
@@ -2199,51 +2240,28 @@ dhd_module_init(void)
printf("\n%s\n", dhd_version);
else {
DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__));
- goto fail_1;
+ goto faild;
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+#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(10000)) != 0) {
+ if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) {
error = -EINVAL;
DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__));
- goto fail_2;
+ dhd_bus_unregister();
}
#endif
return error;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-fail_2:
- dhd_bus_unregister();
-#endif
-fail_1:
-#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
- wifi_del_dev();
-fail_0:
-#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
-
- /* Call customer gpio to turn off power with WL_REG_ON signal */
- dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
-
- return error;
-}
-
-static void __exit
-dhd_module_cleanup(void)
-{
- DHD_TRACE(("%s: Enter\n", __FUNCTION__));
- dhd_bus_unregister();
-#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 */
+faild:
+ /* turn off power and exit */
dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+ return -EINVAL;
}
-
module_init(dhd_module_init);
module_exit(dhd_module_cleanup);
@@ -2330,36 +2348,38 @@ void
dhd_os_wd_timer(void *bus, uint wdtick)
{
dhd_pub_t *pub = bus;
- dhd_info_t *dhd = (dhd_info_t *)pub->info;
-
-#if !defined(CONTINUOUS_WATCHDOG)
static uint save_dhd_watchdog_ms = 0;
-#endif /* !defined(CONTINUOUS_WATCHDOG) */
-
-#if defined(CONTINUOUS_WATCHDOG)
- dhd_watchdog_ms = (uint)wdtick;
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ dhd_info_t *dhd = (dhd_info_t *)pub->info;
- dhd->wd_timer_valid = TRUE;
-#else
/* Totally stop the timer */
if (!wdtick && dhd->wd_timer_valid == TRUE) {
- del_timer_sync(&dhd->timer);
+ del_timer(&dhd->timer);
dhd->wd_timer_valid = FALSE;
save_dhd_watchdog_ms = wdtick;
return;
}
if (wdtick) {
- dhd_watchdog_ms = (uint)wdtick;
-
- /* Re arm the timer, at last watchdog period */
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ dhd_watchdog_ms = (uint) wdtick;
+ if (save_dhd_watchdog_ms != dhd_watchdog_ms) {
+
+ if (dhd->wd_timer_valid == TRUE)
+ /* Stop timer and restart at new value */
+ del_timer(&dhd->timer);
+
+ /* Create timer again when watchdog period is
+ dynamically changed or in the first instance
+ */
+ dhd->timer.expires = jiffies + dhd_watchdog_ms * HZ / 1000;
+ add_timer(&dhd->timer);
+ }else {
+ /* Re arm the timer, at last watchdog period */
+ mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ }
dhd->wd_timer_valid = TRUE;
save_dhd_watchdog_ms = wdtick;
}
-#endif /* defined(CONTINUTOUS_WATCHDOG) */
}
void *
@@ -2414,7 +2434,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
@@ -2427,7 +2447,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
@@ -2563,16 +2583,15 @@ dhd_dev_reset(struct net_device *dev, uint8 flag)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- /* Turning off watchdog */
- if (flag)
- dhd_os_wd_timer(&dhd->pub, 0);
+ /* Turning off watchdog */
+ if (flag)
+ dhd_os_wd_timer(&dhd->pub, 0);
dhd_bus_devreset(&dhd->pub, flag);
- /* Turning on watchdog back */
- if (!flag)
- dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
-
+ /* Turning on watchdog back */
+ if (!flag)
+ dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__));
return 1;
@@ -2613,120 +2632,3 @@ dhd_wait_pend8021x(struct net_device *dev)
}
return pend;
}
-
-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;
-
- if (dhd) {
- spin_lock_irqsave(&dhd->wl_lock, flags);
- ret = dhd->wl_packet;
-#ifdef CONFIG_HAS_WAKELOCK
- if (dhd->wl_packet)
- wake_lock_timeout(&dhd->wl_rxwake, (HZ >> 1));
-#endif
- dhd->wl_packet = 0;
- spin_unlock_irqrestore(&dhd->wl_lock, flags);
- }
- /* printk("%s: %d\n", __FUNCTION__, ret); */
- return ret;
-}
-
-int net_os_wake_lock_timeout(struct net_device *dev)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int ret = 0;
-
- if (dhd)
- ret = dhd_os_wake_lock_timeout(&dhd->pub);
- return ret;
-}
-
-int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub)
-{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
- unsigned long flags;
-
- if (dhd) {
- spin_lock_irqsave(&dhd->wl_lock, flags);
- dhd->wl_packet = 1;
- spin_unlock_irqrestore(&dhd->wl_lock, flags);
- }
- /* printk("%s\n",__func__); */
- return 0;
-}
-
-int net_os_wake_lock_timeout_enable(struct net_device *dev)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int ret = 0;
-
- if (dhd)
- ret = dhd_os_wake_lock_timeout_enable(&dhd->pub);
- 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;
-
- if (dhd) {
- spin_lock_irqsave(&dhd->wl_lock, flags);
-#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);
- }
- /* printk("%s: %d\n", __FUNCTION__, ret); */
- return ret;
-}
-
-int net_os_wake_lock(struct net_device *dev)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int ret = 0;
-
- if (dhd)
- ret = dhd_os_wake_lock(&dhd->pub);
- return ret;
-}
-
-int dhd_os_wake_unlock(dhd_pub_t *pub)
-{
- dhd_info_t *dhd = (dhd_info_t *)(pub->info);
- unsigned long flags;
- int ret = 0;
-
- dhd_os_wake_lock_timeout(pub);
- if (dhd) {
- spin_lock_irqsave(&dhd->wl_lock, flags);
- if (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;
-}
-
-int net_os_wake_unlock(struct net_device *dev)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int ret = 0;
-
- if (dhd)
- ret = dhd_os_wake_unlock(&dhd->pub);
- return ret;
-}
diff --git a/bcm4329/src/dhd/sys/dhd_linux_sched.c b/bcm4329/src/dhd/sys/dhd_linux_sched.c
index 3189123..480b416 100644
--- a/bcm4329/src/dhd/sys/dhd_linux_sched.c
+++ b/bcm4329/src/dhd/sys/dhd_linux_sched.c
@@ -1,7 +1,7 @@
/*
* Expose some of the kernel scheduler routines
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/sys/dhd_proto.h b/bcm4329/src/dhd/sys/dhd_proto.h
index 1e2401a..79584d6 100644
--- a/bcm4329/src/dhd/sys/dhd_proto.h
+++ b/bcm4329/src/dhd/sys/dhd_proto.h
@@ -4,7 +4,7 @@
* Provides type definitions and function prototypes used to link the
* DHD OS, bus, and protocol modules.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c
index 427600f..b006623 100644
--- a/bcm4329/src/dhd/sys/dhd_sdio.c
+++ b/bcm4329/src/dhd/sys/dhd_sdio.c
@@ -1,7 +1,7 @@
/*
* DHD Bus Module for SDIO
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.89 2009/10/28 05:49:40 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.98 2010/02/01 05:22:19 Exp $
*/
#include <typedefs.h>
@@ -293,10 +293,8 @@ static int tx_packets[NUMPRIO];
/* Deferred transmit */
const uint dhd_deferred_tx = 1;
-#if !defined(CONTINUOUS_WATCHDOG)
extern uint dhd_watchdog_ms;
extern void dhd_os_wd_timer(void *bus, uint wdtick);
-#endif /* !defined(CONTINUOUS_WATCHDOG) */
/* Tx/Rx bounds */
uint dhd_txbound;
@@ -514,9 +512,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
/* Go to pending and await interrupt if appropriate */
if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
- DHD_INFO(("CLKCTL: set PENDING\n"));
- bus->clkstate = CLK_PENDING;
-
/* Allow only clock-available interrupt */
devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
if (err) {
@@ -527,6 +522,8 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
+ DHD_INFO(("CLKCTL: set PENDING\n"));
+ bus->clkstate = CLK_PENDING;
return BCME_OK;
} else if (bus->clkstate == CLK_PENDING) {
/* Cancel CA-only interrupt filter */
@@ -692,12 +689,9 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
/* Early exit if we're already there */
if (bus->clkstate == target) {
- if (target == CLK_AVAIL) {
-#if !defined(CONTINUOUS_WATCHDOG)
+ if (target == CLK_AVAIL)
dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
-#endif /* !defined(CONTINUOUS_WATCHDOG) */
bus->activity = TRUE;
- }
return BCME_OK;
}
@@ -708,9 +702,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
dhdsdio_sdclk(bus, TRUE);
/* Now request HT Avail on the backplane */
dhdsdio_htclk(bus, TRUE, pendok);
-#if !defined(CONTINUOUS_WATCHDOG)
dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
-#endif /* !defined(CONTINUOUS_WATCHDOG) */
bus->activity = TRUE;
break;
@@ -723,9 +715,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
else
DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
bus->clkstate, target));
-#if !defined(CONTINUOUS_WATCHDOG)
dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
-#endif /* !defined(CONTINUOUS_WATCHDOG) */
break;
case CLK_NONE:
@@ -734,9 +724,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
dhdsdio_htclk(bus, FALSE, FALSE);
/* Now remove the SD clock */
dhdsdio_sdclk(bus, FALSE);
-#if !defined(CONTINUOUS_WATCHDOG)
dhd_os_wd_timer(bus->dhd, 0);
-#endif /* !defined(CONTINUOUS_WATCHDOG) */
break;
}
#ifdef DHD_DEBUG
@@ -858,7 +846,7 @@ dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
/* Turn off our contribution to the HT clock request */
dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
-#endif /* defined(HW_OOB) */
+#endif /* !defined(HW_OOB) */
}
#endif /* defined(OOB_INTR_ONLY) */
@@ -1597,11 +1585,6 @@ 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)
@@ -3768,8 +3751,8 @@ dhdsdio_dpc(dhd_bus_t *bus)
if (err) {
DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
bus->dhd->busstate = DHD_BUS_DOWN;
- }
- ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
+ }else
+ ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
#endif /* DHD_DEBUG */
/* Read CSR, if clock on switch to AVAIL, else ignore */
@@ -3943,8 +3926,8 @@ clkwait:
/* Resched if events or tx frames are pending, else await next interrupt */
/* On failed register access, all bets are off: no resched or interrupts */
if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
- DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
- __FUNCTION__));
+ DHD_ERROR(("%s: failed backplane access over SDIO, halting operation %d \n",
+ __FUNCTION__, bcmsdh_regfail(sdh)));
bus->dhd->busstate = DHD_BUS_DOWN;
bus->intstatus = 0;
} else if (bus->clkstate == CLK_PENDING) {
@@ -3989,7 +3972,13 @@ void
dhdsdio_isr(void *arg)
{
dhd_bus_t *bus = (dhd_bus_t*)arg;
- bcmsdh_info_t *sdh = bus->sdh;
+ bcmsdh_info_t *sdh;
+
+ if (!bus) {
+ DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
+ return;
+ }
+ sdh = bus->sdh;
if (bus->dhd->busstate == DHD_BUS_DOWN) {
DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
@@ -4020,14 +4009,13 @@ dhdsdio_isr(void *arg)
#if defined(SDIO_ISR_THREAD)
DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
- dhd_os_wake_lock(bus->dhd);
while (dhdsdio_dpc(bus));
- dhd_os_wake_unlock(bus->dhd);
#else
bus->dpc_sched = TRUE;
dhd_sched_dpc(bus->dhd);
#endif
+
}
#ifdef SDTEST
@@ -4537,12 +4525,13 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
/* if firmware path present try to download and bring up bus */
- if ((ret = dhd_bus_start(bus->dhd)) == -1) {
- DHD_TRACE(("%s: warning : check if firmware was provided\n", __FUNCTION__));
- }
- else if (ret == BCME_NOTUP) {
- DHD_ERROR(("%s: dongle is not responding\n", __FUNCTION__));
+ if ((ret = dhd_bus_start(bus->dhd)) != 0) {
+ DHD_ERROR(("%s: failed\n", __FUNCTION__));
goto fail;
+ if (ret == BCME_NOTUP) {
+ DHD_ERROR(("%s: dongle is not responding\n", __FUNCTION__));
+ goto fail;
+ }
}
/* Ok, have the per-port tell the stack we're open for business */
if (dhd_net_attach(bus->dhd, 0) != 0) {
@@ -4843,6 +4832,7 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
+
return ret;
}
@@ -4852,13 +4842,12 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
bool ret;
/* Download the firmware */
- dhd_os_wake_lock(bus->dhd);
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
ret = _dhdsdio_download_firmware(bus) == 0;
dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
- dhd_os_wake_unlock(bus->dhd);
+
return ret;
}
@@ -4872,6 +4861,10 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
ASSERT(osh);
+ /* De-register interrupt handler */
+ bcmsdh_intr_disable(bus->sdh);
+ bcmsdh_intr_dereg(bus->sdh);
+
if (bus->dhd) {
dhdsdio_release_dongle(bus, osh);
@@ -4882,9 +4875,6 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
dhdsdio_release_malloc(bus, osh);
- /* De-register interrupt handler */
- bcmsdh_intr_dereg(bus->sdh);
-
MFREE(osh, bus, sizeof(dhd_bus_t));
}
@@ -5379,8 +5369,8 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
/* Force flow control as protection when stop come before ifconfig_down */
dhd_txflowcontrol(bus->dhd, 0, ON);
#endif /* !defined(IGNORE_ETH0_DOWN) */
- dhd_os_proto_block(dhdp);
/* save country settinng if was pre-setup with priv ioctl */
+ dhd_os_proto_block(dhdp);
dhdcdc_query_ioctl(bus->dhd, 0, WLC_GET_COUNTRY,
bus->dhd->country_code, sizeof(bus->dhd->country_code));
dhd_os_proto_unblock(dhdp);
diff --git a/bcm4329/src/dongle/dngl_stats.h b/bcm4329/src/dongle/dngl_stats.h
index c1776a8..e5db54e 100644
--- a/bcm4329/src/dongle/dngl_stats.h
+++ b/bcm4329/src/dongle/dngl_stats.h
@@ -2,7 +2,7 @@
* Common stats definitions for clients of dongle
* ports
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/aidmp.h b/bcm4329/src/include/aidmp.h
index 44b3de8..a927e5d 100644
--- a/bcm4329/src/include/aidmp.h
+++ b/bcm4329/src/include/aidmp.h
@@ -1,7 +1,7 @@
/*
* Broadcom AMBA Interconnect definitions.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmcdc.h b/bcm4329/src/include/bcmcdc.h
index 641d755..c2a860b 100644
--- a/bcm4329/src/include/bcmcdc.h
+++ b/bcm4329/src/include/bcmcdc.h
@@ -4,7 +4,7 @@
*
* Definitions subject to change without notice.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmdefs.h b/bcm4329/src/include/bcmdefs.h
index ba7a9e4..67d1158 100644
--- a/bcm4329/src/include/bcmdefs.h
+++ b/bcm4329/src/include/bcmdefs.h
@@ -1,7 +1,7 @@
/*
* Misc system wide definitions
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -20,15 +20,38 @@
* 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.10 2009/07/03 08:20:51 Exp $
+ * $Id: bcmdefs.h,v 13.38.4.10.2.7.6.11 2010/02/01 05:51:55 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 80b2ea8..910e246 100644
--- a/bcm4329/src/include/bcmdevs.h
+++ b/bcm4329/src/include/bcmdevs.h
@@ -1,7 +1,7 @@
/*
* Broadcom device-specific manifest constants.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.19 2009/09/18 23:51:17 Exp $
+ * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.29 2010/03/01 08:56:24 Exp $
*/
@@ -58,6 +58,7 @@
#define BCM4329_D11NDUAL_ID 0x432e
#define BCM4329_D11N2G_ID 0x432f
#define BCM4329_D11N5G_ID 0x4330
+#define BCM4336_D11N_ID 0x4343
#define BCM4315_D11DUAL_ID 0x4334
#define BCM4315_D11G_ID 0x4335
#define BCM4315_D11A_ID 0x4336
@@ -90,6 +91,7 @@
#define BCM4325_CHIP_ID 0x4325
#define BCM4328_CHIP_ID 0x4328
#define BCM4329_CHIP_ID 0x4329
+#define BCM4336_CHIP_ID 0x4336
#define BCM4402_CHIP_ID 0x4402
#define BCM4704_CHIP_ID 0x4704
#define BCM4710_CHIP_ID 0x4710
diff --git a/bcm4329/src/include/bcmendian.h b/bcm4329/src/include/bcmendian.h
index 38887df..ae46838 100644
--- a/bcm4329/src/include/bcmendian.h
+++ b/bcm4329/src/include/bcmendian.h
@@ -1,7 +1,7 @@
/*
* Byte order utilities
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmpcispi.h b/bcm4329/src/include/bcmpcispi.h
index e3be826..7d98fb7 100644
--- a/bcm4329/src/include/bcmpcispi.h
+++ b/bcm4329/src/include/bcmpcispi.h
@@ -1,7 +1,7 @@
/*
* Broadcom PCI-SPI Host Controller Register Definitions
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmperf.h b/bcm4329/src/include/bcmperf.h
index dfc3f44..2a78784 100644
--- a/bcm4329/src/include/bcmperf.h
+++ b/bcm4329/src/include/bcmperf.h
@@ -1,7 +1,7 @@
/*
* Performance counters software interface.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdbus.h b/bcm4329/src/include/bcmsdbus.h
index 0e629c0..b7b67bc 100644
--- a/bcm4329/src/include/bcmsdbus.h
+++ b/bcm4329/src/include/bcmsdbus.h
@@ -2,7 +2,7 @@
* Definitions for API from sdio common code (bcmsdh) to individual
* host controller drivers.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdh.h b/bcm4329/src/include/bcmsdh.h
index f8ab8ab..f5dee5c 100644
--- a/bcm4329/src/include/bcmsdh.h
+++ b/bcm4329/src/include/bcmsdh.h
@@ -3,7 +3,7 @@
* export functions to client drivers
* abstract OS and BUS specific details of SDIO
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdh_sdmmc.h b/bcm4329/src/include/bcmsdh_sdmmc.h
index b572f34..4e6d1b5 100644
--- a/bcm4329/src/include/bcmsdh_sdmmc.h
+++ b/bcm4329/src/include/bcmsdh_sdmmc.h
@@ -1,7 +1,7 @@
/*
* BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdpcm.h b/bcm4329/src/include/bcmsdpcm.h
index b63b1d3..450c9c3 100644
--- a/bcm4329/src/include/bcmsdpcm.h
+++ b/bcm4329/src/include/bcmsdpcm.h
@@ -2,7 +2,7 @@
* Broadcom SDIO/PCMCIA
* Software-specific definitions shared between device and host side
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdspi.h b/bcm4329/src/include/bcmsdspi.h
index b1e2be9..eaae10d 100644
--- a/bcm4329/src/include/bcmsdspi.h
+++ b/bcm4329/src/include/bcmsdspi.h
@@ -1,7 +1,7 @@
/*
* SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmsdstd.h b/bcm4329/src/include/bcmsdstd.h
index 7bffbad..974b3d4 100644
--- a/bcm4329/src/include/bcmsdstd.h
+++ b/bcm4329/src/include/bcmsdstd.h
@@ -1,7 +1,7 @@
/*
* 'Standard' SDIO HOST CONTROLLER driver
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -21,17 +21,18 @@
* 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.h,v 13.16.18.1.16.2 2008/09/30 17:14:16 Exp $
+ * $Id: bcmsdstd.h,v 13.16.18.1.16.3 2009/12/10 01:09:23 Exp $
*/
/* global msglevel for debug messages - bitvals come from sdiovar.h */
-#define sd_err(x)
+#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
#define sd_trace(x)
#define sd_info(x)
#define sd_debug(x)
#define sd_data(x)
#define sd_ctrl(x)
+#define sd_dma(x)
#define sd_sync_dma(sd, read, nbytes)
#define sd_init_dma(sd)
@@ -78,8 +79,6 @@ extern void sdstd_osfree(sdioh_info_t *sd);
#define RETRIES_LARGE 100000
#define RETRIES_SMALL 100
-#define USE_PIO 0x0 /* DMA or PIO */
-#define USE_DMA 0x1
#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
#define USE_MULTIBLOCK 0x4
@@ -115,7 +114,6 @@ struct sdioh_info {
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 */
@@ -125,17 +123,64 @@ struct sdioh_info {
int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */
uint32 data_xfer_count; /* Current transfer */
uint16 card_rca; /* Current Address */
+ int8 sd_dma_mode; /* DMA Mode (PIO, SDMA, ... ADMA2) on CMD53 */
uint8 num_funcs; /* Supported funcs on client */
uint32 com_cis_ptr;
uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
- void *dma_buf;
- ulong dma_phys;
+ void *dma_buf; /* DMA Buffer virtual address */
+ ulong dma_phys; /* DMA Buffer physical address */
+ void *adma2_dscr_buf; /* ADMA2 Descriptor Buffer virtual address */
+ ulong adma2_dscr_phys; /* ADMA2 Descriptor Buffer physical address */
+
+ /* adjustments needed to make the dma align properly */
+ void *dma_start_buf;
+ ulong dma_start_phys;
+ uint alloced_dma_size;
+ void *adma2_dscr_start_buf;
+ ulong adma2_dscr_start_phys;
+ uint alloced_adma2_dscr_size;
+
int r_cnt; /* rx count */
int t_cnt; /* tx_count */
bool got_hcint; /* local interrupt flag */
uint16 last_intrstatus; /* to cache intrstatus */
};
+#define DMA_MODE_NONE 0
+#define DMA_MODE_SDMA 1
+#define DMA_MODE_ADMA1 2
+#define DMA_MODE_ADMA2 3
+#define DMA_MODE_ADMA2_64 4
+#define DMA_MODE_AUTO -1
+
+#define USE_DMA(sd) ((bool)((sd->sd_dma_mode > 0) ? TRUE : FALSE))
+
+/* SDIO Host Control Register DMA Mode Definitions */
+#define SDIOH_SDMA_MODE 0
+#define SDIOH_ADMA1_MODE 1
+#define SDIOH_ADMA2_MODE 2
+#define SDIOH_ADMA2_64_MODE 3
+
+#define ADMA2_ATTRIBUTE_VALID (1 << 0) /* ADMA Descriptor line valid */
+#define ADMA2_ATTRIBUTE_END (1 << 1) /* End of Descriptor */
+#define ADMA2_ATTRIBUTE_INT (1 << 2) /* Interrupt when line is done */
+#define ADMA2_ATTRIBUTE_ACT_NOP (0 << 4) /* Skip current line, go to next. */
+#define ADMA2_ATTRIBUTE_ACT_RSV (1 << 4) /* Same as NOP */
+#define ADMA1_ATTRIBUTE_ACT_SET (1 << 4) /* ADMA1 Only - set transfer length */
+#define ADMA2_ATTRIBUTE_ACT_TRAN (2 << 4) /* Transfer Data of one descriptor line. */
+#define ADMA2_ATTRIBUTE_ACT_LINK (3 << 4) /* Link Descriptor */
+
+/* ADMA2 Descriptor Table Entry for 32-bit Address */
+typedef struct adma2_dscr_32b {
+ uint32 len_attr;
+ uint32 phys_addr;
+} adma2_dscr_32b_t;
+
+/* ADMA1 Descriptor Table Entry */
+typedef struct adma1_dscr {
+ uint32 phys_addr_attr;
+} adma1_dscr_t;
+
/************************************************************
* Internal interfaces: per-port references into bcmsdstd.c
*/
diff --git a/bcm4329/src/include/bcmspi.h b/bcm4329/src/include/bcmspi.h
index 0c46538..2e2bc93 100644
--- a/bcm4329/src/include/bcmspi.h
+++ b/bcm4329/src/include/bcmspi.h
@@ -1,7 +1,7 @@
/*
* Broadcom SPI Low-Level Hardware Driver API
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/bcmspibrcm.h b/bcm4329/src/include/bcmspibrcm.h
new file mode 100644
index 0000000..9dce878
--- /dev/null
+++ b/bcm4329/src/include/bcmspibrcm.h
@@ -0,0 +1,134 @@
+/*
+ * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
+ *
+ * Copyright (C) 2010, 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 93bf25f..7010838 100644
--- a/bcm4329/src/include/bcmutils.h
+++ b/bcm4329/src/include/bcmutils.h
@@ -1,7 +1,7 @@
/*
* Misc useful os-independent macros and functions.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.22 2009/10/28 18:25:39 Exp $
+ * $Id: bcmutils.h,v 13.184.4.6.2.1.18.24 2009/12/10 20:19:19 Exp $
*/
@@ -338,8 +338,11 @@ extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool
#define BCME_NOT_WME_ASSOCIATION -34
#define BCME_SDIO_ERROR -35
#define BCME_DONGLE_DOWN -36
-#define BCME_VERSION -37
-#define BCME_UNFINISHED -38
+#define BCME_VERSION -37
+#define BCME_TXFAIL -38
+#define BCME_RXFAIL -39
+#define BCME_NODEVICE -40
+#define BCME_UNFINISHED -41
#define BCME_LAST BCME_UNFINISHED
@@ -381,8 +384,11 @@ extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool
"Not WME Association", \
"SDIO Bus Error", \
"Dongle Not Accessible", \
- "Incorrect version", \
- "Command not finished" \
+ "Incorrect version", \
+ "TX Failure", \
+ "RX Failure", \
+ "Device Not Present", \
+ "Command not finished", \
}
#ifndef ABS
diff --git a/bcm4329/src/include/bcmwifi.h b/bcm4329/src/include/bcmwifi.h
index 8f5f3dc..038aedc 100644
--- a/bcm4329/src/include/bcmwifi.h
+++ b/bcm4329/src/include/bcmwifi.h
@@ -3,7 +3,7 @@
* This header file housing the define and function prototype use by
* both the wl driver, tools & Apps.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.30.1 2009/08/15 00:51:27 Exp $
+ * $Id: bcmwifi.h,v 1.15.30.4 2010/03/10 20:10:52 Exp $
*/
@@ -39,6 +39,7 @@ typedef uint16 chanspec_t;
#define CH_EWA_VALID 0x04
#define CH_20MHZ_APART 4
#define CH_10MHZ_APART 2
+#define CH_5MHZ_APART 1
#define CH_MAX_2G_CHANNEL 14
#define WLC_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL
#define MAXCHANNEL 224
@@ -113,6 +114,11 @@ typedef uint16 chanspec_t;
#define CHSPEC_SB_NONE(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE)
#define CHSPEC_SB_UPPER(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER)
#define CHSPEC_SB_LOWER(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER)
+#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \
+ (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \
+ (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))))
+
+#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G((chspec))? WLC_BAND_5G: WLC_BAND_2G)
#define CHANSPEC_STR_LEN 8
diff --git a/bcm4329/src/include/dhdioctl.h b/bcm4329/src/include/dhdioctl.h
index ee78c3d..706b4a8 100644
--- a/bcm4329/src/include/dhdioctl.h
+++ b/bcm4329/src/include/dhdioctl.h
@@ -5,7 +5,7 @@
*
* Definitions subject to change without notice.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h
index e16e102..8137f60 100644
--- a/bcm4329/src/include/epivers.h
+++ b/bcm4329/src/include/epivers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -31,18 +31,18 @@
#define EPI_MINOR_VERSION 218
-#define EPI_RC_NUMBER 161
+#define EPI_RC_NUMBER 204
-#define EPI_INCREMENTAL_NUMBER 0
+#define EPI_INCREMENTAL_NUMBER 1
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 218, 161, 0
+#define EPI_VERSION 4, 218, 204, 1
-#define EPI_VERSION_NUM 0x04daa100
+#define EPI_VERSION_NUM 0x04dacc01
-#define EPI_VERSION_STR "4.218.161.0"
-#define EPI_ROUTER_VERSION_STR "4.219.161.0"
+#define EPI_VERSION_STR "4.218.204.1"
+#define EPI_ROUTER_VERSION_STR "4.219.204.1"
#endif
diff --git a/bcm4329/src/include/hndpmu.h b/bcm4329/src/include/hndpmu.h
index afd78d7..e5568e7 100644
--- a/bcm4329/src/include/hndpmu.h
+++ b/bcm4329/src/include/hndpmu.h
@@ -1,7 +1,7 @@
/*
* HND SiliconBackplane PMU support.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/hndsoc.h b/bcm4329/src/include/hndsoc.h
index dcbab43..3542417 100644
--- a/bcm4329/src/include/hndsoc.h
+++ b/bcm4329/src/include/hndsoc.h
@@ -1,7 +1,7 @@
/*
* Broadcom HND chip & on-chip-interconnect-related definitions.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/linux_osl.h b/bcm4329/src/include/linux_osl.h
index 98afe9c..c8c658e 100644
--- a/bcm4329/src/include/linux_osl.h
+++ b/bcm4329/src/include/linux_osl.h
@@ -1,7 +1,7 @@
/*
* Linux OS Independent Layer
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/linuxver.h b/bcm4329/src/include/linuxver.h
index a36de95..c329ec2 100644
--- a/bcm4329/src/include/linuxver.h
+++ b/bcm4329/src/include/linuxver.h
@@ -2,7 +2,7 @@
* Linux-specific abstractions to gain some independence from linux kernel versions.
* Pave over some 2.2 versus 2.4 versus 2.6 kernel differences.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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: linuxver.h,v 13.38.8.1.8.3 2009/06/19 04:42:45 Exp $
+ * $Id: linuxver.h,v 13.38.8.1.8.5 2010/02/04 13:47:16 Exp $
*/
@@ -425,11 +425,22 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
#define CHECKSUM_HW CHECKSUM_PARTIAL
#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+#define KILL_PROC(nr, sig) \
+{ \
+struct task_struct *tsk; \
+struct pid *pid; \
+pid = find_get_pid((pid_t)nr); \
+tsk = pid_task(pid, PIDTYPE_PID); \
+if (tsk) send_sig(sig, tsk, 1); \
+}
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
+ KERNEL_VERSION(2, 6, 30))
#define KILL_PROC(pid, sig) \
{ \
struct task_struct *tsk; \
- tsk = pid_task(find_vpid(pid), PIDTYPE_PID); \
+ tsk = find_task_by_vpid(pid); \
if (tsk) send_sig(sig, tsk, 1); \
}
#else
@@ -438,6 +449,7 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
kill_proc(pid, sig, 1); \
}
#endif
+#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
#define netdev_priv(dev) dev->priv
diff --git a/bcm4329/src/include/miniopt.h b/bcm4329/src/include/miniopt.h
index 91e6603..3667fb1 100644
--- a/bcm4329/src/include/miniopt.h
+++ b/bcm4329/src/include/miniopt.h
@@ -1,7 +1,7 @@
/*
* Command line options parser.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/msgtrace.h b/bcm4329/src/include/msgtrace.h
index d79a89e..1479086 100644
--- a/bcm4329/src/include/msgtrace.h
+++ b/bcm4329/src/include/msgtrace.h
@@ -1,7 +1,7 @@
/*
* Trace messages sent over HBUS
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/osl.h b/bcm4329/src/include/osl.h
index 02b2b21..5599e53 100644
--- a/bcm4329/src/include/osl.h
+++ b/bcm4329/src/include/osl.h
@@ -1,7 +1,7 @@
/*
* OS Abstraction Layer
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/packed_section_end.h b/bcm4329/src/include/packed_section_end.h
index e455d69..5b61c18 100644
--- a/bcm4329/src/include/packed_section_end.h
+++ b/bcm4329/src/include/packed_section_end.h
@@ -15,7 +15,7 @@
* #include <packed_section_end.h>
*
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/packed_section_start.h b/bcm4329/src/include/packed_section_start.h
index a15562e..cb93aa6 100644
--- a/bcm4329/src/include/packed_section_start.h
+++ b/bcm4329/src/include/packed_section_start.h
@@ -15,7 +15,7 @@
* #include <packed_section_end.h>
*
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/pcicfg.h b/bcm4329/src/include/pcicfg.h
index 61c2f4a..898962c 100644
--- a/bcm4329/src/include/pcicfg.h
+++ b/bcm4329/src/include/pcicfg.h
@@ -1,7 +1,7 @@
/*
* pcicfg.h: PCI configuration constants and structures.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/802.11.h b/bcm4329/src/include/proto/802.11.h
index 217bd6c..3ef7de2 100644
--- a/bcm4329/src/include/proto/802.11.h
+++ b/bcm4329/src/include/proto/802.11.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -21,7 +21,7 @@
*
* Fundamental types and constants relating to 802.11
*
- * $Id: 802.11.h,v 9.219.4.1.4.5.6.10 2009/07/09 10:15:09 Exp $
+ * $Id: 802.11.h,v 9.219.4.1.4.5.6.11 2010/02/09 13:23:26 Exp $
*/
@@ -361,15 +361,25 @@ BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel {
dot11_brcm_extch_ie_t extch_ie;
} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct dot11_ext_csa {
- uint8 id;
- uint8 len;
+BWL_PRE_PACKED_STRUCT struct dot11_csa_body {
uint8 mode;
uint8 reg;
uint8 channel;
uint8 count;
} BWL_POST_PACKED_STRUCT;
+
+
+BWL_PRE_PACKED_STRUCT struct dot11_ext_csa {
+ uint8 id;
+ uint8 len;
+ struct dot11_csa_body b;
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa {
+ uint8 category;
+ uint8 action;
+ struct dot11_csa_body b;
+} BWL_POST_PACKED_STRUCT;
typedef struct dot11_ext_csa dot11_ext_csa_ie_t;
#define DOT11_EXT_CSA_IE_LEN 4
@@ -1025,7 +1035,8 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
#define DOT11_ACTION_ID_HT_MIMO_PS 1
-#define DOT11_ACTION_ID_BSS_COEX_MNG 0
+#define DOT11_PUB_ACTION_BSS_COEX_MNG 0
+#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4
#define DOT11_BA_ACTION_ADDBA_REQ 0
diff --git a/bcm4329/src/include/proto/802.11e.h b/bcm4329/src/include/proto/802.11e.h
index 0c53530..1dd6f45 100644
--- a/bcm4329/src/include/proto/802.11e.h
+++ b/bcm4329/src/include/proto/802.11e.h
@@ -1,7 +1,7 @@
/*
* 802.11e protocol header file
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/802.1d.h b/bcm4329/src/include/proto/802.1d.h
index efd7117..45c728b 100644
--- a/bcm4329/src/include/proto/802.1d.h
+++ b/bcm4329/src/include/proto/802.1d.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/bcmeth.h b/bcm4329/src/include/proto/bcmeth.h
index bd34a0b..fdb5a2a 100644
--- a/bcm4329/src/include/proto/bcmeth.h
+++ b/bcm4329/src/include/proto/bcmeth.h
@@ -1,7 +1,7 @@
/*
* Broadcom Ethernettype protocol definitions
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/bcmevent.h b/bcm4329/src/include/proto/bcmevent.h
index 1791478..46c04d3 100644
--- a/bcm4329/src/include/proto/bcmevent.h
+++ b/bcm4329/src/include/proto/bcmevent.h
@@ -1,7 +1,7 @@
/*
* Broadcom Event protocol definitions
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/bcmip.h b/bcm4329/src/include/proto/bcmip.h
index 9645016..9d2fd6f 100644
--- a/bcm4329/src/include/proto/bcmip.h
+++ b/bcm4329/src/include/proto/bcmip.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/ethernet.h b/bcm4329/src/include/proto/ethernet.h
index 05530d5..c2fc4bf 100644
--- a/bcm4329/src/include/proto/ethernet.h
+++ b/bcm4329/src/include/proto/ethernet.h
@@ -1,7 +1,7 @@
/*
* From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.3 2009/08/15 00:51:27 Exp $
+ * $Id: ethernet.h,v 9.45.56.5 2010/02/22 22:04:36 Exp $
*/
diff --git a/bcm4329/src/include/proto/sdspi.h b/bcm4329/src/include/proto/sdspi.h
index 3c7bcf3..7739e68 100644
--- a/bcm4329/src/include/proto/sdspi.h
+++ b/bcm4329/src/include/proto/sdspi.h
@@ -1,7 +1,7 @@
/*
* SD-SPI Protocol Standard
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/vlan.h b/bcm4329/src/include/proto/vlan.h
index 2dda4d5..670bc44 100644
--- a/bcm4329/src/include/proto/vlan.h
+++ b/bcm4329/src/include/proto/vlan.h
@@ -1,7 +1,7 @@
/*
* 802.1Q VLAN protocol definitions
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/proto/wpa.h b/bcm4329/src/include/proto/wpa.h
index 4c50125..f5d0cd5 100644
--- a/bcm4329/src/include/proto/wpa.h
+++ b/bcm4329/src/include/proto/wpa.h
@@ -1,7 +1,7 @@
/*
* Fundamental types and constants relating to WPA
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbchipc.h b/bcm4329/src/include/sbchipc.h
index 80e6e56..8c8be26 100644
--- a/bcm4329/src/include/sbchipc.h
+++ b/bcm4329/src/include/sbchipc.h
@@ -7,7 +7,7 @@
*
* $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
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -823,11 +823,70 @@ 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_PC0_BYPASS_SDMOD_MASK 0x10000000
+#define PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT 28
+
+
+
+#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_INT 0
+
+#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1
+#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2
+#define PMU1_PLL0_PC2_NDIV_MODE_MASH_1BY8 3
+#define PMU1_PLL0_PC2_NDIV_MODE_MFB_1BY8 4
+
+#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_PC4_KVCO_XS_MASK 0x38000000
+#define PMU1_PLL0_PC4_KVCO_XS_SHIFT 27
+
+
+
+#define PMU1_PLL0_PLLCTL5 5
+#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
+#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
+#define PMU1_PLL0_PC5_PLL_CTRL_37_32_MASK 0x0000003f
+#define PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT 0
+#define PMU1_PLL0_PC5_VCO_RNG_MASK 0x000000C0
+#define PMU1_PLL0_PC5_VCO_RNG_SHIFT 6
+
+
+
#define PMU2_PHY_PLL_PLLCTL 4
#define PMU2_SI_PLL_PLLCTL 10
@@ -1001,6 +1060,58 @@ 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/sbconfig.h b/bcm4329/src/include/sbconfig.h
index edf497c..da18ccb 100644
--- a/bcm4329/src/include/sbconfig.h
+++ b/bcm4329/src/include/sbconfig.h
@@ -1,7 +1,7 @@
/*
* Broadcom SiliconBackplane hardware register definitions.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbhnddma.h b/bcm4329/src/include/sbhnddma.h
index 2aeee9e..7681395 100644
--- a/bcm4329/src/include/sbhnddma.h
+++ b/bcm4329/src/include/sbhnddma.h
@@ -2,7 +2,7 @@
* Generic Broadcom Home Networking Division (HND) DMA engine HW interface
* This supports the following chips: BCM42xx, 44xx, 47xx .
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbpcmcia.h b/bcm4329/src/include/sbpcmcia.h
index 121b1a9..d6d8033 100644
--- a/bcm4329/src/include/sbpcmcia.h
+++ b/bcm4329/src/include/sbpcmcia.h
@@ -1,7 +1,7 @@
/*
* BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbsdio.h b/bcm4329/src/include/sbsdio.h
index 43ed6b5..75aaf4d 100644
--- a/bcm4329/src/include/sbsdio.h
+++ b/bcm4329/src/include/sbsdio.h
@@ -4,7 +4,7 @@
*
* SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbsdpcmdev.h b/bcm4329/src/include/sbsdpcmdev.h
index 57e832d..7c7c7e4 100644
--- a/bcm4329/src/include/sbsdpcmdev.h
+++ b/bcm4329/src/include/sbsdpcmdev.h
@@ -1,7 +1,7 @@
/*
* Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific device core support
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sbsocram.h b/bcm4329/src/include/sbsocram.h
index 170e8f2..5ede0b6 100644
--- a/bcm4329/src/include/sbsocram.h
+++ b/bcm4329/src/include/sbsocram.h
@@ -1,7 +1,7 @@
/*
* BCM47XX Sonics SiliconBackplane embedded ram core
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sdio.h b/bcm4329/src/include/sdio.h
index d20d69c..280cb84 100644
--- a/bcm4329/src/include/sdio.h
+++ b/bcm4329/src/include/sdio.h
@@ -2,7 +2,7 @@
* SDIO spec header file
* Protocol and standard (common) device definitions
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/sdioh.h b/bcm4329/src/include/sdioh.h
index 960e30c..8123452 100644
--- a/bcm4329/src/include/sdioh.h
+++ b/bcm4329/src/include/sdioh.h
@@ -2,7 +2,7 @@
* SDIO Host Controller Spec header file
* Register map and definitions for the Standard Host Controller
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.2 2009/07/28 17:54:46 Exp $
+ * $Id: sdioh.h,v 13.13.18.1.16.3 2009/12/08 22:34:21 Exp $
*/
#ifndef _SDIOH_H
@@ -64,6 +64,7 @@
#define SD_Capabilities_Reserved 0x044
#define SD_MaxCurCap 0x048
#define SD_MaxCurCap_Reserved 0x04C
+#define SD_ADMA_SysAddr 0x58
#define SD_SlotInterruptStatus 0x0FC
#define SD_HostControllerVersion 0x0FE
@@ -81,6 +82,8 @@
#define CAP_MAXBLOCK_S 16
#define CAP_ADMA2_M BITFIELD_MASK(1)
#define CAP_ADMA2_S 19
+#define CAP_ADMA1_M BITFIELD_MASK(1)
+#define CAP_ADMA1_S 20
#define CAP_HIGHSPEED_M BITFIELD_MASK(1)
#define CAP_HIGHSPEED_S 21
#define CAP_DMA_M BITFIELD_MASK(1)
@@ -191,6 +194,8 @@
#define HOST_DATA_WIDTH_M BITFIELD_MASK(1) /* Bit 1 4 bit enable */
#define HOST_DATA_WIDTH_S 1
#define HOST_HI_SPEED_EN_M BITFIELD_MASK(1) /* Bit 2 High speed vs low speed */
+#define HOST_DMA_SEL_S 3
+#define HOST_DMA_SEL_M BITFIELD_MASK(2) /* Bit 4:3 DMA Select */
#define HOST_HI_SPEED_EN_S 2
/* misc defines */
diff --git a/bcm4329/src/include/sdiovar.h b/bcm4329/src/include/sdiovar.h
index 3c5d512..0179d4c 100644
--- a/bcm4329/src/include/sdiovar.h
+++ b/bcm4329/src/include/sdiovar.h
@@ -2,7 +2,7 @@
* Structure used by apps whose drivers access SDIO drivers.
* Pulled out separately so dhdu and wlu can both use it.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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: sdiovar.h,v 13.5.14.2.16.1 2008/11/20 00:51:32 Exp $
+ * $Id: sdiovar.h,v 13.5.14.2.16.2 2009/12/08 22:34:21 Exp $
*/
#ifndef _sdiovar_h_
@@ -48,6 +48,7 @@ typedef struct sdreg {
#define SDH_DATA_VAL 0x0010 /* Data */
#define SDH_CTRL_VAL 0x0020 /* Control Regs */
#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */
+#define SDH_DMA_VAL 0x0080 /* DMA */
#define NUM_PREV_TRANSACTIONS 16
diff --git a/bcm4329/src/include/siutils.h b/bcm4329/src/include/siutils.h
index 7be09d5..b2a4ae3 100644
--- a/bcm4329/src/include/siutils.h
+++ b/bcm4329/src/include/siutils.h
@@ -2,7 +2,7 @@
* Misc utility routines for accessing the SOC Interconnects
* of Broadcom HNBU chips.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.12 2009/09/22 13:28:16 Exp $
+ * $Id: siutils.h,v 13.197.4.2.4.3.8.13 2010/03/10 21:34:34 Exp $
*/
@@ -225,6 +225,7 @@ extern void si_pci_up(si_t *sih);
extern void si_pcie_war_ovr_disable(si_t *sih);
extern void si_pcie_extendL1timer(si_t *sih, bool extend);
extern int si_pci_fixcfg(si_t *sih);
+void si_pmu_res_4319_swctrl_war(si_t *sih, osl_t *osh, bool enable);
diff --git a/bcm4329/src/include/spid.h b/bcm4329/src/include/spid.h
new file mode 100644
index 0000000..c740296
--- /dev/null
+++ b/bcm4329/src/include/spid.h
@@ -0,0 +1,153 @@
+/*
+ * SPI device spec header file
+ *
+ * Copyright (C) 2010, 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/trxhdr.h b/bcm4329/src/include/trxhdr.h
index b79ac35..8f5eed9 100644
--- a/bcm4329/src/include/trxhdr.h
+++ b/bcm4329/src/include/trxhdr.h
@@ -1,7 +1,7 @@
/*
* TRX image file header format.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/typedefs.h b/bcm4329/src/include/typedefs.h
index e4daeee..4d9dd76 100644
--- a/bcm4329/src/include/typedefs.h
+++ b/bcm4329/src/include/typedefs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/include/wlioctl.h b/bcm4329/src/include/wlioctl.h
index 751d5cd..6923555 100644
--- a/bcm4329/src/include/wlioctl.h
+++ b/bcm4329/src/include/wlioctl.h
@@ -4,7 +4,7 @@
*
* Definitions subject to change without notice.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.53 2009/10/27 06:18:20 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.59 2010/02/09 13:23:22 Exp $
*/
@@ -186,6 +186,7 @@ typedef struct wl_scan_results {
#define WL_SCAN_RESULTS_PARTIAL 1
#define WL_SCAN_RESULTS_PENDING 2
#define WL_SCAN_RESULTS_ABORTED 3
+#define WL_SCAN_RESULTS_NO_MEM 4
#define ESCAN_REQ_VERSION 1
@@ -1598,6 +1599,12 @@ typedef struct wl_obss_scan_arg {
#define WL_COEX_40MHZ_INTOLERANT 0x02
#define WL_COEX_WIDTH20 0x04
+typedef struct wl_action_obss_coex_req {
+ uint8 info;
+ uint8 num;
+ uint8 ch_list[1];
+} wl_action_obss_coex_req_t;
+
#define MAX_RSSI_LEVELS 8
@@ -1613,6 +1620,39 @@ typedef struct wl_rssi_event {
+#define WLFEATURE_DISABLE_11N 0x00000001
+#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002
+#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004
+#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008
+#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010
+#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020
+#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040
+#define WLFEATURE_DISABLE_11N_GF 0x00000080
+
+
+
+#include <packed_section_end.h>
+
+
+#include <packed_section_start.h>
+
+
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr {
+ struct ether_addr staAddr;
+ uint16 ieLen;
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data {
+ sta_prbreq_wps_ie_hdr_t hdr;
+ uint8 ieData[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list {
+ uint32 totLen;
+ uint8 ieDataList[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t;
+
+
#include <packed_section_end.h>
#endif
diff --git a/bcm4329/src/shared/aiutils.c b/bcm4329/src/shared/aiutils.c
index 1962711..a1d00ec 100644
--- a/bcm4329/src/shared/aiutils.c
+++ b/bcm4329/src/shared/aiutils.c
@@ -2,7 +2,7 @@
* Misc utility routines for accessing chip-specific features
* of the SiliconBackplane-based Broadcom chips.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/shared/bcmutils.c b/bcm4329/src/shared/bcmutils.c
index 9805ee6..c553d8e 100644
--- a/bcm4329/src/shared/bcmutils.c
+++ b/bcm4329/src/shared/bcmutils.c
@@ -1,7 +1,7 @@
/*
* Driver O/S-independent utility routines
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.16 2009/10/28 18:25:42 Exp $
+ * $Id: bcmutils.c,v 1.210.4.5.2.4.6.17 2009/11/17 02:20:12 Exp $
*/
#include <typedefs.h>
@@ -33,6 +33,11 @@
#else
#include <stdio.h>
#include <string.h>
+/* This case for external supplicant use */
+#if defined(BCMEXTSUP)
+#include <bcm_osl.h>
+#endif
+
#endif /* BCMDRIVER */
#include <bcmendian.h>
#include <bcmdevs.h>
diff --git a/bcm4329/src/shared/bcmwifi.c b/bcm4329/src/shared/bcmwifi.c
index 641a4fd..803acf8 100644
--- a/bcm4329/src/shared/bcmwifi.c
+++ b/bcm4329/src/shared/bcmwifi.c
@@ -3,7 +3,7 @@
* Contents are wifi-specific, used by any kernel or app-level
* software that might want wifi things as it grows.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/shared/hndpmu.c b/bcm4329/src/shared/hndpmu.c
index 25712ac..38d72b3 100644
--- a/bcm4329/src/shared/hndpmu.c
+++ b/bcm4329/src/shared/hndpmu.c
@@ -2,7 +2,7 @@
* Misc utility routines for accessing PMU corerev specific features
* of the SiliconBackplane-based Broadcom chips.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.50 2009/10/26 14:45:51 Exp $
+ * $Id: hndpmu.c,v 1.95.2.17.4.11.2.58 2010/03/10 21:36:44 Exp $
*/
#include <typedefs.h>
diff --git a/bcm4329/src/shared/linux_osl.c b/bcm4329/src/shared/linux_osl.c
index 9c100a4..c2f5682 100644
--- a/bcm4329/src/shared/linux_osl.c
+++ b/bcm4329/src/shared/linux_osl.c
@@ -1,7 +1,7 @@
/*
* Linux OS Independent Layer
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.5 2009/10/27 04:43:04 Exp $
+ * $Id: linux_osl.c,v 1.125.12.3.8.6 2009/12/09 01:29:03 Exp $
*/
@@ -81,7 +81,7 @@ struct osl_info {
bcm_mem_link_t *dbgmem_list;
};
-static int16 linuxbcmerrormap[] = \
+static int16 linuxbcmerrormap[] =
{ 0,
-EINVAL,
-EINVAL,
@@ -120,13 +120,16 @@ static int16 linuxbcmerrormap[] = \
-EIO,
-ENODEV,
-EINVAL,
- -EINVAL
+ -EIO,
+ -EIO,
+ -EINVAL,
+ -EINVAL,
-#if BCME_LAST != -38
+#if BCME_LAST != -41
#error "You need to add a OS error translation in the linuxbcmerrormap \
- for new error code defined in bcmuitls.h"
+ for new error code defined in bcmutils.h"
#endif
};
@@ -148,10 +151,8 @@ osl_t *
osl_attach(void *pdev, uint bustype, bool pkttag)
{
osl_t *osh;
- gfp_t flags;
- flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
- osh = kmalloc(sizeof(osl_t), flags);
+ osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
ASSERT(osh);
bzero(osh, sizeof(osl_t));
@@ -192,9 +193,9 @@ osl_attach(void *pdev, uint bustype, bool pkttag)
STATIC_BUF_TOTAL_LEN))) {
printk("can not alloc static buf!\n");
}
- else {
- /* printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); */
- }
+ else
+ printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf);
+
init_MUTEX(&bcm_static_buf->static_sem);
@@ -452,8 +453,8 @@ void*
osl_malloc(osl_t *osh, uint size)
{
void *addr;
- gfp_t flags;
+
if (osh)
ASSERT(osh->magic == OS_HANDLE_MAGIC);
@@ -490,8 +491,8 @@ osl_malloc(osl_t *osh, uint size)
}
original:
#endif
- flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
- if ((addr = kmalloc(size, flags)) == NULL) {
+
+ if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
if (osh)
osh->failed++;
return (NULL);
@@ -603,10 +604,8 @@ void *
osl_pktdup(osl_t *osh, void *skb)
{
void * p;
- gfp_t flags;
- flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
- if ((p = skb_clone((struct sk_buff*)skb, flags)) == NULL)
+ if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL)
return NULL;
diff --git a/bcm4329/src/shared/miniopt.c b/bcm4329/src/shared/miniopt.c
index 44199ea..6a184a7 100644
--- a/bcm4329/src/shared/miniopt.c
+++ b/bcm4329/src/shared/miniopt.c
@@ -1,7 +1,7 @@
/*
* Description.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/shared/sbutils.c b/bcm4329/src/shared/sbutils.c
index 567e94e..7500f14 100644
--- a/bcm4329/src/shared/sbutils.c
+++ b/bcm4329/src/shared/sbutils.c
@@ -2,7 +2,7 @@
* Misc utility routines for accessing chip-specific features
* of the SiliconBackplane-based Broadcom chips.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/shared/siutils.c b/bcm4329/src/shared/siutils.c
index df34986..6472a78 100644
--- a/bcm4329/src/shared/siutils.c
+++ b/bcm4329/src/shared/siutils.c
@@ -2,7 +2,7 @@
* Misc utility routines for accessing chip-specific features
* of the SiliconBackplane-based Broadcom chips.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.25 2009/09/22 13:32:03 Exp $
+ * $Id: siutils.c,v 1.662.4.4.4.16.4.26 2010/02/01 05:51:56 Exp $
*/
#include <typedefs.h>
@@ -1036,7 +1036,7 @@ si_sdio_init(si_t *sih)
sdpregs = (sdpcmd_regs_t *)si_setcore(sih, SDIOD_CORE_ID, 0);
ASSERT(sdpregs);
- SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " \
+ SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d "
"through SD core %d (%p)\n",
sih->buscorerev, idx, sii->curidx, sdpregs));
diff --git a/bcm4329/src/shared/siutils_priv.h b/bcm4329/src/shared/siutils_priv.h
index 1ec59aa..e8ad7e5 100644
--- a/bcm4329/src/shared/siutils_priv.h
+++ b/bcm4329/src/shared/siutils_priv.h
@@ -1,7 +1,7 @@
/*
* Include file private to the SOC Interconnect support files.
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index 0f04aab..d67daf3 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.c
@@ -1,7 +1,7 @@
/*
* Linux Wireless Extensions support
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.57 2009/10/27 04:43:46 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.84.2.3 2010/03/16 22:09:45 Exp $
*/
@@ -48,21 +48,27 @@ typedef const struct si_pub si_t;
#include <proto/ethernet.h>
#include <dngl_stats.h>
#include <dhd.h>
-#define WL_ERROR(x)
+#define WL_ERROR(x) printf x
#define WL_TRACE(x)
#define WL_ASSOC(x)
#define WL_INFORM(x)
#define WL_WSEC(x)
-#define WL_TRACE_PMK(x)
#include <wl_iw.h>
+
#include <linux/rtnetlink.h>
-#include <linux/mutex.h>
#define WL_IW_USE_ISCAN 1
#define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1
+#if defined(SOFTAP)
+#define WL_SOFTAP(x) printk x
+static struct net_device *priv_dev;
+static bool ap_cfg_running = FALSE;
+static bool ap_fw_loaded = FALSE;
+static int ap_mode = 0;
+#endif
#define WL_IW_IOCTL_CALL(func_call) \
do { \
@@ -70,7 +76,6 @@ typedef const struct si_pub si_t;
} while (0)
static int g_onoff = G_WLAN_SET_ON;
-static struct mutex wl_start_lock;
extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
uint32 reason, char* stringBuf, uint buflen);
@@ -113,11 +118,13 @@ extern int dhd_wait_pend8021x(struct net_device *dev);
#endif
static void *g_scan = NULL;
-static uint g_scan_specified_ssid;
+static volatile uint g_scan_specified_ssid;
+static wlc_ssid_t g_specific_ssid;
static wlc_ssid_t g_ssid;
-wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
+static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
+static volatile uint g_first_broadcast_scan;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
@@ -134,11 +141,13 @@ wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
#endif
#if defined(WL_IW_USE_ISCAN)
-
-static wlc_ssid_t g_specific_ssid; /* chache specific ssid request */
+static void wl_iw_free_ss_cache(void);
+static int wl_iw_run_ss_cache_timer(int kick_off);
+int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag);
#define ISCAN_STATE_IDLE 0
#define ISCAN_STATE_SCANING 1
+
#define WLC_IW_ISCAN_MAXLEN 2048
typedef struct iscan_buf {
struct iscan_buf * next;
@@ -163,7 +172,7 @@ typedef struct iscan_info {
char ioctlbuf[WLC_IOCTL_SMLEN];
} iscan_info_t;
-
+#define COEX_DHCP 1
static void wl_iw_bt_flag_set(struct net_device *dev, bool set);
static void wl_iw_bt_release(void);
@@ -258,35 +267,35 @@ dev_wlc_ioctl(
struct ifreq ifr;
wl_ioctl_t ioc;
mm_segment_t fs;
- int ret = -EINVAL;
+ int ret = -1;
- if (g_onoff == G_WLAN_SET_ON) {
- memset(&ioc, 0, sizeof(ioc));
- ioc.cmd = cmd;
- ioc.buf = arg;
- ioc.len = len;
+ if (!dev) {
+ WL_ERROR(("%s: dev is null\n", __FUNCTION__));
+ return ret;
+ }
- strcpy(ifr.ifr_name, dev->name);
- ifr.ifr_data = (caddr_t) &ioc;
+ WL_TRACE(("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n",
+ __FUNCTION__, current->pid, cmd, arg, len));
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
- ret = dev_open(dev);
- if (ret) {
- WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret));
- return ret;
- }
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t) &ioc;
+
+
+ dev_open(dev);
- fs = get_fs();
- set_fs(get_ds());
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
- ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+ fs = get_fs();
+ set_fs(get_ds());
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+ ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
#else
- ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#endif
- set_fs(fs);
- }
- else {
- WL_TRACE(("%s: call after driver stop\n", __FUNCTION__));
- }
+ ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif
+ set_fs(fs);
+
return ret;
}
@@ -376,7 +385,11 @@ dev_wlc_bufvar_set(
char *name,
char *buf, int len)
{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
char ioctlbuf[MAX_WLIW_IOCTL_LEN];
+#else
+ static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
+#endif
uint buflen;
buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf));
@@ -384,7 +397,7 @@ dev_wlc_bufvar_set(
return (dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen));
}
-#endif
+#endif
static int
@@ -393,9 +406,12 @@ dev_wlc_bufvar_get(
char *name,
char *buf, int buflen)
{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
char ioctlbuf[MAX_WLIW_IOCTL_LEN];
+#else
+ static char ioctlbuf[MAX_WLIW_IOCTL_LEN];
+#endif
int error;
-
uint len;
len = bcm_mkiovar(name, NULL, 0, ioctlbuf, sizeof(ioctlbuf));
@@ -533,9 +549,9 @@ wl_iw_set_country(
int country_offset;
int country_code_size;
- WL_TRACE(("%s\n", __FUNCTION__));
memset(country_code, 0, sizeof(country_code));
+
country_offset = strcspn(extra, " ");
country_code_size = strlen(extra) - country_offset;
@@ -717,15 +733,14 @@ wl_iw_get_rssi(
)
{
static int rssi = 0;
+ static wlc_ssid_t ssid = {0};
int error = 0;
- wlc_ssid_t ssid;
char *p = extra;
static char ssidbuf[SSID_FMT_BUF_LEN];
scb_val_t scb_val;
- scb_val.val = 0;
+ bzero(&scb_val, sizeof(scb_val_t));
- 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);
@@ -735,10 +750,6 @@ wl_iw_get_rssi(
ssid.SSID_len = dtoh32(ssid.SSID_len);
}
- if (!ssid.SSID_len) {
- return 0;
- }
-
wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi);
wrqu->data.length = p - extra + 1;
@@ -769,18 +780,18 @@ wl_iw_send_priv_event(
return 0;
}
-#ifdef WL_IW_USE_THREAD_WL_OFF
static int
_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__));
- net_os_wake_lock(wl_ctl->dev);
- mutex_lock(&wl_start_lock);
+ 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__));
@@ -793,6 +804,17 @@ _wl_control_sysioc_thread_wl_off(void *data)
dhd_dev_reset(wl_ctl->dev, 1);
+#if defined(WL_IW_USE_ISCAN)
+
+ wl_iw_free_ss_cache();
+ wl_iw_run_ss_cache_timer(0);
+ memset(g_scan, 0, G_SCAN_RESULTS);
+
+ g_ss_cache_ctrl.m_link_down = 1;
+ g_scan_specified_ssid = 0;
+
+ g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
+#endif
#if defined(BCMLXSDMMC)
sdioh_stop(NULL);
#endif
@@ -801,50 +823,17 @@ _wl_control_sysioc_thread_wl_off(void *data)
wl_iw_send_priv_event(wl_ctl->dev, "STOP");
- net_os_wake_lock_timeout_enable(wl_ctl->dev);
break;
}
- mutex_unlock(&wl_start_lock);
+
WL_TRACE(("%s Exited\n", __FUNCTION__));
- net_os_wake_unlock(wl_ctl->dev);
+ 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);
}
-#endif
-
-int
-wl_control_wl_start(struct net_device *dev)
-{
- int ret = 0;
-
- WL_TRACE(("Enter %s \n", __FUNCTION__));
-
- mutex_lock(&wl_start_lock);
- if (g_onoff == G_WLAN_SET_OFF) {
- dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
-
-#if defined(BCMLXSDMMC)
- sdioh_start(NULL, 0);
-#endif
-
- dhd_dev_reset(dev, 0);
-
-#if defined(BCMLXSDMMC)
- sdioh_start(NULL, 1);
-#endif
-
- dhd_dev_init_ioctl(dev);
-
- g_onoff = G_WLAN_SET_ON;
- }
- WL_TRACE(("Exited %s \n", __FUNCTION__));
-
- mutex_unlock(&wl_start_lock);
- return ret;
-}
-#ifdef WL_IW_USE_THREAD_WL_OFF
static void
wl_iw_stop_timerfunc(ulong data)
{
@@ -852,11 +841,10 @@ wl_iw_stop_timerfunc(ulong data)
WL_TRACE(("%s\n", __FUNCTION__));
- del_timer_sync(wl_ctl->timer);
+ del_timer(wl_ctl->timer);
up(&wl_ctl->timer_sem);
}
-#endif
static int
wl_iw_control_wl_off(
@@ -865,18 +853,24 @@ wl_iw_control_wl_off(
)
{
int ret = 0;
-#ifdef WL_IW_USE_THREAD_WL_OFF
static struct wl_ctrl ctl;
static struct timer_list timer;
-#endif
+
WL_TRACE(("Enter %s\n", __FUNCTION__));
-#ifdef WL_IW_USE_THREAD_WL_OFF
+#ifdef SOFTAP
+ ap_mode = 0;
+ ap_cfg_running = FALSE;
+#endif
+
+
+
ctl.timer = &timer;
ctl.dev = dev;
sema_init(&ctl.timer_sem, 0);
init_completion(&ctl.sysioc_exited);
+
ctl.sysioc_pid = kernel_thread(_wl_control_sysioc_thread_wl_off, &ctl, 0);
timer.data = (ulong)&ctl;
@@ -884,28 +878,7 @@ wl_iw_control_wl_off(
init_timer(&timer);
timer.expires = jiffies + 2000 * HZ / 1000;
add_timer(&timer);
-#else
- mutex_lock(&wl_start_lock);
- if (g_onoff == G_WLAN_SET_ON) {
- g_onoff = G_WLAN_SET_OFF;
-#if defined(WL_IW_USE_ISCAN)
- g_iscan->iscan_state = ISCAN_STATE_IDLE;
-#endif
- dhd_dev_reset(dev, 1);
-
-#if defined(BCMLXSDMMC)
- sdioh_stop(NULL);
-#endif
-
- dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
-
- wl_iw_send_priv_event(dev, "STOP");
-
- net_os_wake_lock_timeout_enable(dev);
- }
- mutex_unlock(&wl_start_lock);
-#endif
WL_TRACE(("Exited %s\n", __FUNCTION__));
return ret;
@@ -921,17 +894,347 @@ wl_iw_control_wl_on(
WL_TRACE(("Enter %s \n", __FUNCTION__));
- ret = wl_control_wl_start(dev);
+ if (g_onoff == G_WLAN_SET_OFF) {
+ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
+
+#if defined(BCMLXSDMMC)
+ sdioh_start(NULL, 0);
+#endif
+
+ dhd_dev_reset(dev, 0);
+
+#if defined(BCMLXSDMMC)
+ sdioh_start(NULL, 1);
+#endif
+
+ dhd_dev_init_ioctl(dev);
+
+ g_onoff = G_WLAN_SET_ON;
+ }
wl_iw_send_priv_event(dev, "START");
- net_os_wake_lock_timeout_enable(dev);
+#ifdef SOFTAP
+ if (!ap_fw_loaded) {
+ wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
+ }
+#else
+ wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
+#endif
+
WL_TRACE(("Exited %s \n", __FUNCTION__));
return ret;
}
+#ifdef SOFTAP
+static struct ap_profile my_ap;
+static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap);
+static int get_assoc_sta_list(struct net_device *dev, char *buf, int len);
+static int set_ap_mac_list(struct net_device *dev, char *buf);
+
+#define PTYPE_STRING 0
+#define PTYPE_INTDEC 1
+#define PTYPE_INTHEX 2
+#define PTYPE_STR_HEX 3
+int get_parmeter_from_string(
+ char **str_ptr, const char *token, int param_type, void *dst, int param_max_len);
+
+#endif
+
+int hex2num(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+int hex2byte(const char *hex)
+{
+ int a, b;
+ a = hex2num(*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+
+
+int hstr_2_buf(const char *txt, u8 *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ int a, b;
+
+ a = hex2num(*txt++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*txt++);
+ if (b < 0)
+ return -1;
+ *buf++ = (a << 4) | b;
+ }
+
+ return 0;
+}
+
+#ifdef SOFTAP
+int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
+{
+ char *str_ptr = param_str;
+ char sub_cmd[16];
+ int ret = 0;
+
+ memset(sub_cmd, 0, sizeof(sub_cmd));
+ memset(ap_cfg, 0, sizeof(struct ap_profile));
+
+
+ if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=",
+ PTYPE_STRING, sub_cmd, SSID_LEN) != 0) {
+ return -1;
+ }
+ if (strncmp(sub_cmd, "AP_CFG", 6)) {
+ WL_ERROR(("ERROR: sub_cmd:%s != 'AP_CFG'!\n", sub_cmd));
+ return -1;
+ }
+
+
+
+ ret = get_parmeter_from_string(&str_ptr, "SSID=", PTYPE_STRING, ap_cfg->ssid, SSID_LEN);
+
+ ret |= get_parmeter_from_string(&str_ptr, "SEC=", PTYPE_STRING, ap_cfg->sec, SEC_LEN);
+
+ ret |= get_parmeter_from_string(&str_ptr, "KEY=", PTYPE_STRING, ap_cfg->key, KEY_LEN);
+
+ ret |= get_parmeter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5);
+
+ ret |= get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5);
+
+ ret |= get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5);
+
+ return ret;
+}
+#endif
+
+
+
+#ifdef SOFTAP
+static int iwpriv_set_ap_config(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *ext)
+{
+ int res = 0;
+ char *extra = NULL;
+ struct ap_profile *ap_cfg = &my_ap;
+
+ WL_TRACE(("> Got IWPRIV SET_AP IOCTL: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
+ info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length));
+
+
+ if (wrqu->data.length != 0) {
+
+ char *str_ptr;
+
+ if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ extra[wrqu->data.length] = 0;
+ WL_SOFTAP((" Got str param in iw_point:\n %s\n", extra));
+
+ memset(ap_cfg, 0, sizeof(struct ap_profile));
+
+
+
+ str_ptr = extra;
+
+ init_ap_profile_from_string(extra, ap_cfg);
+
+ } else {
+
+ WL_ERROR(("IWPRIV argument len = 0 \n"));
+ return -1;
+ }
+
+
+ res |= set_ap_cfg(dev, ap_cfg);
+ kfree(extra);
+
+ return res;
+}
+#endif
+
+
+
+#ifdef SOFTAP
+static int iwpriv_get_assoc_list(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *p_iwrq,
+ char *extra)
+{
+ int i, ret = 0;
+ char mac_buf[256];
+ struct maclist *sta_maclist = (struct maclist *)mac_buf;
+
+ char mac_lst[256];
+ char *p_mac_str;
+
+ WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d, \
+ iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags, \
+ extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags));
+
+ WL_SOFTAP(("extra:%s\n", extra));
+ print_buf((u8 *)p_iwrq, 16, 0);
+
+ memset(sta_maclist, 0, sizeof(mac_buf));
+
+ sta_maclist->count = 8;
+
+ WL_TRACE((" net device:%s, buf_sz:%d\n", dev->name, sizeof(mac_buf)));
+ get_assoc_sta_list(dev, mac_buf, 256);
+ WL_TRACE((" got %d stations\n", sta_maclist->count));
+
+
+ memset(mac_lst, 0, sizeof(mac_lst));
+ p_mac_str = mac_lst;
+
+ for (i = 0; i < 8; i++) {
+ struct ether_addr * id = &sta_maclist->ea[i];
+
+ WL_SOFTAP(("dhd_drv>> sta_mac[%d] :", i));
+ print_buf((unsigned char *)&sta_maclist->ea[i], 6, 0);
+
+
+ p_mac_str += snprintf(p_mac_str, MAX_WX_STRING,
+ "Mac[%d]=%02X:%02X:%02X:%02X:%02X:%02X\n", i,
+ id->octet[0], id->octet[1], id->octet[2],
+ id->octet[3], id->octet[4], id->octet[5]);
+
+ }
+
+ p_iwrq->data.length = strlen(mac_lst);
+
+ WL_TRACE(("u.pointer:%p\n", p_iwrq->data.pointer));
+ WL_TRACE(("resulting str:\n%s \n len:%d\n\n", mac_lst, p_iwrq->data.length));
+
+ if (p_iwrq->data.length) {
+ if (copy_to_user(p_iwrq->data.pointer, mac_lst, p_iwrq->data.length)) {
+ WL_ERROR(("%s: Can't copy to user\n", __FUNCTION__));
+ return -EFAULT;
+ }
+ }
+
+ WL_TRACE(("Exited %s \n", __FUNCTION__));
+ return ret;
+}
+#endif
+
+
+#ifdef SOFTAP
+static int iwpriv_set_mac_filters(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *ext)
+{
+
+ int i, ret = -1;
+ char * extra = NULL;
+ u8 macfilt[8][6];
+ int mac_cnt = 0;
+ char sub_cmd[16];
+
+ WL_TRACE((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x, \
+ info->flags:%x, u.data:%p, u.len:%d\n",
+ info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length));
+
+ if (wrqu->data.length != 0) {
+
+ char *str_ptr;
+
+ if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ extra[wrqu->data.length] = 0;
+ WL_SOFTAP((" Got parameter string in iw_point:\n %s \n", extra));
+
+ memset(macfilt, 0, sizeof(macfilt));
+ memset(sub_cmd, 0, sizeof(sub_cmd));
+
+
+ str_ptr = extra;
+
+
+ if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=", PTYPE_STRING, sub_cmd, 15) != 0) {
+ goto exit_proc;
+ }
+
+#define MAC_FILT_MAX 8
+
+ if (strncmp(sub_cmd, "MAC_FLT_W", strlen("MAC_FLT_W"))) {
+ WL_ERROR(("ERROR: sub_cmd:%s != 'MAC_FLT_W'!\n", sub_cmd));
+ goto exit_proc;
+ }
+
+ if (get_parmeter_from_string(&str_ptr, "MAC_CNT=",
+ PTYPE_INTDEC, &mac_cnt, 4) != 0) {
+ WL_ERROR(("ERROR: MAC_CNT param is missing \n"));
+ goto exit_proc;
+ }
+
+ if (mac_cnt > MAC_FILT_MAX) {
+ WL_ERROR(("ERROR: number of MAC filters > MAX\n"));
+ goto exit_proc;
+ }
+
+ for (i=0; i< mac_cnt; i++)
+ if (get_parmeter_from_string(&str_ptr, "MAC=",
+ PTYPE_STR_HEX, macfilt[i], 12) != 0) {
+ WL_ERROR(("ERROR: MAC_filter[%d] is missing !\n", i));
+ goto exit_proc;
+ }
+
+ for (i = 0; i < mac_cnt; i++) {
+ WL_SOFTAP(("mac_filt[%d]:", i));
+ print_buf(macfilt[i], 6, 0);
+ }
+
+
+ wrqu->data.pointer = NULL;
+ wrqu->data.length = 0;
+ ret = 0;
+
+ } else {
+
+ WL_ERROR(("IWPRIV argument len is 0\n"));
+ return -1;
+ }
+
+ exit_proc:
+ kfree(extra);
+ return ret;
+}
+#endif
#endif
@@ -942,8 +1245,10 @@ struct iw_request_info
__u16 flags;
};
-typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
- void *wrqu, char *extra);
+typedef int (*iw_handler)(struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu,
+ char *extra);
#endif
static int
@@ -970,7 +1275,7 @@ wl_iw_config_commit(
bzero(&bssid, sizeof(struct sockaddr));
if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) {
- WL_ERROR(("Invalid ioctl data.\n"));
+ WL_ERROR(("%s: WLC_REASSOC to %s failed \n", __FUNCTION__, ssid.SSID));
return error;
}
@@ -1003,7 +1308,14 @@ wl_iw_set_freq(
int error, chan;
uint sf = 0;
- WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name));
+ WL_TRACE(("\n %s %s: SIOCSIWFREQ\n", __FUNCTION__, dev->name));
+
+#if defined(SOFTAP)
+ if (ap_cfg_running) {
+ WL_TRACE(("%s:>> not executed, 'SOFT_AP is active' \n", __FUNCTION__));
+ return 0;
+ }
+#endif
if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) {
@@ -1515,7 +1827,12 @@ wl_iw_get_aplist(
list->buflen = dtoh32(list->buflen);
list->version = dtoh32(list->version);
list->count = dtoh32(list->count);
- ASSERT(list->version == WL_BSS_INFO_VERSION);
+ if (list->version != WL_BSS_INFO_VERSION) {
+ WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
+ __FUNCTION__, list->version));
+ kfree(list);
+ return -EINVAL;
+ }
for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
@@ -1585,7 +1902,11 @@ wl_iw_iscan_get_aplist(
while (buf) {
list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
- ASSERT(list->version == WL_BSS_INFO_VERSION);
+ if (list->version != WL_BSS_INFO_VERSION) {
+ WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
+ __FUNCTION__, list->version));
+ return -EINVAL;
+ }
bi = NULL;
for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) {
@@ -1723,8 +2044,11 @@ wl_iw_iscan_get(iscan_info_t *iscan)
}
else {
buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
- if (!buf)
- return WL_SCAN_RESULTS_ABORTED;
+ if (!buf) {
+ WL_ERROR(("%s can't alloc iscan_buf_t : going to abort currect iscan\n", \
+ __FUNCTION__));
+ return WL_SCAN_RESULTS_NO_MEM;
+ }
buf->next = NULL;
if (!iscan->list_hdr)
iscan->list_hdr = buf;
@@ -1764,31 +2088,30 @@ wl_iw_iscan_get(iscan_info_t *iscan)
static void wl_iw_force_specific_scan(iscan_info_t *iscan)
{
- WL_TRACE(("### Force Specific SCAN for %s\n", g_specific_ssid.SSID));
+ WL_TRACE(("%s force Specific SCAN for %s\n", __FUNCTION__, g_specific_ssid.SSID));
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_lock();
#endif
+
(void) dev_wlc_ioctl(iscan->dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid));
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_unlock();
#endif
}
-
static void wl_iw_send_scan_complete(iscan_info_t *iscan)
{
#ifndef SANDGATE2G
union iwreq_data wrqu;
- char extra[IW_CUSTOM_MAX + 1];
memset(&wrqu, 0, sizeof(wrqu));
- memset(extra, 0, sizeof(extra));
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
- wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, extra);
-#else
+
+
wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL);
-#endif
- WL_TRACE(("Send Event SCAN complete\n"));
-#endif
+ if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED)
+ g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY;
+ WL_TRACE(("Send Event ISCAN complete\n"));
+#endif
}
static int
_iscan_sysioc_thread(void *data)
@@ -1796,17 +2119,21 @@ _iscan_sysioc_thread(void *data)
uint32 status;
iscan_info_t *iscan = (iscan_info_t *)data;
static bool iscan_pass_abort = FALSE;
-
DAEMONIZE("iscan_sysioc");
status = WL_SCAN_RESULTS_PARTIAL;
while (down_interruptible(&iscan->sysioc_sem) == 0) {
- net_os_wake_lock(iscan->dev);
-
+#if defined(SOFTAP)
+
+ if (ap_cfg_running) {
+ WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__));
+ continue;
+ }
+#endif
if (iscan->timer_on) {
+ del_timer(&iscan->timer);
iscan->timer_on = 0;
- del_timer_sync(&iscan->timer);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
@@ -1816,9 +2143,8 @@ _iscan_sysioc_thread(void *data)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_unlock();
#endif
-
- if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
- WL_TRACE(("%s Get results from specific scan sttaus=%d\n", __FUNCTION__, status));
+ if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) {
+ WL_TRACE(("%s Get results from specific scan status=%d\n", __FUNCTION__, status));
wl_iw_send_scan_complete(iscan);
iscan_pass_abort = FALSE;
status = -1;
@@ -1830,12 +2156,12 @@ _iscan_sysioc_thread(void *data)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_lock();
#endif
-
+
wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
rtnl_unlock();
#endif
-
+
mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
iscan->timer_on = 1;
break;
@@ -1846,7 +2172,7 @@ _iscan_sysioc_thread(void *data)
break;
case WL_SCAN_RESULTS_PENDING:
WL_TRACE(("iscanresults pending\n"));
-
+
mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
iscan->timer_on = 1;
break;
@@ -1860,35 +2186,51 @@ _iscan_sysioc_thread(void *data)
wl_iw_force_specific_scan(iscan);
}
break;
+ case WL_SCAN_RESULTS_NO_MEM:
+ WL_TRACE(("iscanresults can't alloc memory: skip\n"));
+ iscan->iscan_state = ISCAN_STATE_IDLE;
+ break;
default:
WL_TRACE(("iscanresults returned unknown status %d\n", status));
break;
- }
-
- net_os_wake_unlock(iscan->dev);
+ }
}
if (iscan->timer_on) {
+ del_timer(&iscan->timer);
iscan->timer_on = 0;
- del_timer_sync(&iscan->timer);
}
-
complete_and_exit(&iscan->sysioc_exited, 0);
}
#endif
+static void
+wl_iw_set_ss_cache_timer_flag(void)
+{
+ g_ss_cache_ctrl.m_timer_expired = 1;
+ WL_TRACE(("%s called\n", __FUNCTION__));
+}
-void
+static int
wl_iw_init_ss_cache_ctrl(void)
{
+ WL_TRACE(("%s :\n", __FUNCTION__));
g_ss_cache_ctrl.m_prev_scan_mode = 0;
g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
g_ss_cache_ctrl.m_cache_head = NULL;
g_ss_cache_ctrl.m_link_down = 0;
g_ss_cache_ctrl.m_timer_expired = 0;
- g_ss_cache_ctrl.m_timer = NULL;
memset(g_ss_cache_ctrl.m_active_bssid, 0, ETHER_ADDR_LEN);
+
+ g_ss_cache_ctrl.m_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+ if (!g_ss_cache_ctrl.m_timer) {
+ return -ENOMEM;
+ }
+ g_ss_cache_ctrl.m_timer->function = (void *)wl_iw_set_ss_cache_timer_flag;
+ init_timer(g_ss_cache_ctrl.m_timer);
+
+ return 0;
}
@@ -1913,12 +2255,6 @@ wl_iw_free_ss_cache(void)
*spec_scan_head = NULL;
}
-static void
-wl_iw_set_ss_cache_timer_flag(void)
-{
- g_ss_cache_ctrl.m_timer_expired = 1;
- WL_TRACE(("%s called\n", __FUNCTION__));
-}
static int
@@ -1928,24 +2264,15 @@ wl_iw_run_ss_cache_timer(int kick_off)
timer = &g_ss_cache_ctrl.m_timer;
- if (kick_off) {
- *timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
- if (!(*timer)) {
- return -ENOMEM;
- }
- (*timer)->function = (void *)wl_iw_set_ss_cache_timer_flag;
- init_timer(*timer);
- (*timer)->expires = jiffies + 30000 * HZ / 1000;
- add_timer(*timer);
- WL_TRACE(("%s : timer starts \n", __FUNCTION__));
- }
- else {
- if (*timer) {
+ if (*timer) {
+ if (kick_off) {
+ (*timer)->expires = jiffies + 30000 * HZ / 1000;
+ add_timer(*timer);
+ WL_TRACE(("%s : timer starts \n", __FUNCTION__));
+ } else {
del_timer_sync(*timer);
- kfree(*timer);
- *timer = NULL;
+ WL_TRACE(("%s : timer stops \n", __FUNCTION__));
}
- WL_TRACE(("%s : timer stops \n", __FUNCTION__));
}
return 0;
@@ -1955,8 +2282,12 @@ wl_iw_run_ss_cache_timer(int kick_off)
void
wl_iw_release_ss_cache_ctrl(void)
{
+ WL_TRACE(("%s :\n", __FUNCTION__));
wl_iw_free_ss_cache();
wl_iw_run_ss_cache_timer(0);
+ if (g_ss_cache_ctrl.m_timer) {
+ kfree(g_ss_cache_ctrl.m_timer);
+ }
}
@@ -2020,7 +2351,7 @@ wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list)
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
- WL_TRACE(("%s : %dth SSID %s\n", __FUNCTION__, i, bi->SSID));
+ WL_TRACE(("%s : find %d with specific SSID %s\n", __FUNCTION__, i, bi->SSID));
for (;node;) {
if (!memcmp(&node->bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
@@ -2074,12 +2405,13 @@ __u16 *merged_len)
node = g_ss_cache_ctrl.m_cache_head;
for (;node;) {
list_merge = (wl_scan_results_t *)node;
- WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
+ WL_TRACE(("%s: Cached Specific APs list=%d\n", __FUNCTION__, list_merge->count));
if (buflen_from_user - *merged_len > 0) {
*merged_len += (__u16) wl_iw_get_scan_prep(list_merge, info,
extra + *merged_len, buflen_from_user - *merged_len);
}
else {
+ WL_TRACE(("%s: exit with break\n", __FUNCTION__));
break;
}
node = node->next;
@@ -2131,7 +2463,16 @@ wl_iw_set_scan(
char *extra
)
{
- WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
+ int error;
+ WL_TRACE(("\n:%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name));
+
+#if defined(SOFTAP)
+
+ if (ap_cfg_running) {
+ WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
+ return 0;
+ }
+#endif
if (g_onoff == G_WLAN_SET_OFF)
@@ -2139,28 +2480,98 @@ wl_iw_set_scan(
memset(&g_specific_ssid, 0, sizeof(g_specific_ssid));
- g_scan_specified_ssid = 0;
+#ifndef WL_IW_USE_ISCAN
+
+ g_scan_specified_ssid = 0;
+#endif
#if WIRELESS_EXT > 17
if (wrqu->data.length == sizeof(struct iw_scan_req)) {
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
struct iw_scan_req *req = (struct iw_scan_req *)extra;
- g_specific_ssid.SSID_len = MIN(sizeof(g_specific_ssid.SSID), req->essid_len);
- memcpy(g_specific_ssid.SSID, req->essid, g_specific_ssid.SSID_len);
- g_specific_ssid.SSID_len = htod32(g_specific_ssid.SSID_len);
- g_scan_specified_ssid = 1;
- WL_TRACE(("Specific scan ssid=%s len=%d\n", g_specific_ssid.SSID, g_specific_ssid.SSID_len));
+ if (g_first_broadcast_scan != BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
+
+ WL_TRACE(("%s Ignoring SC %s first BC is not done = %d\n", \
+ __FUNCTION__, req->essid, \
+ g_first_broadcast_scan));
+ return -EBUSY;
+ }
+ if (g_scan_specified_ssid) {
+ WL_TRACE(("%s Specific SCAN is not done ignore scan for = %s \n", \
+ __FUNCTION__, req->essid));
+
+ return -EBUSY;
+ }
+ else {
+ g_specific_ssid.SSID_len = MIN(sizeof(g_specific_ssid.SSID), \
+ req->essid_len);
+ memcpy(g_specific_ssid.SSID, req->essid, g_specific_ssid.SSID_len);
+ g_specific_ssid.SSID_len = htod32(g_specific_ssid.SSID_len);
+ g_scan_specified_ssid = 1;
+ WL_TRACE(("### Specific scan ssid=%s len=%d\n", \
+ g_specific_ssid.SSID, g_specific_ssid.SSID_len));
+ }
}
}
-#endif
+#endif
- (void) dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid));
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)))) {
+ WL_TRACE(("#### Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error));
+
+ g_scan_specified_ssid = 0;
+ return -EBUSY;
+ }
return 0;
}
#ifdef WL_IW_USE_ISCAN
+int
+wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag)
+{
+ wlc_ssid_t ssid;
+ iscan_info_t *iscan = g_iscan;
+
+
+ if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) {
+ g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED;
+ WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__));
+ }
+ else if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) {
+ WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__));
+ return 0;
+ }
+
+
+ memset(&ssid, 0, sizeof(ssid));
+
+ iscan->list_cur = iscan->list_hdr;
+ iscan->iscan_state = ISCAN_STATE_SCANING;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ if (flag)
+ rtnl_lock();
+#endif
+
+ dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
+ wl_iw_set_event_mask(dev);
+
+ WL_TRACE(("+++: Set Broadcast ISCAN\n"));
+
+ wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ if (flag)
+ rtnl_unlock();
+#endif
+
+ mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
+
+ iscan->timer_on = 1;
+
+ return 0;
+}
static int
wl_iw_iscan_set_scan(
struct net_device *dev,
@@ -2172,48 +2583,68 @@ wl_iw_iscan_set_scan(
wlc_ssid_t ssid;
iscan_info_t *iscan = g_iscan;
- WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
+ WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name));
- if (g_onoff == G_WLAN_SET_OFF)
+#if defined(SOFTAP)
+ if (ap_cfg_running) {
+ WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
return 0;
+ }
+#endif
+
+ if (g_onoff == G_WLAN_SET_OFF) {
+ WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
+ return 0;
+ }
if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ WL_TRACE(("%s use backup if iscan thread is not successful\n", \
+ __FUNCTION__));
return wl_iw_set_scan(dev, info, wrqu, extra);
}
- if (iscan->iscan_state == ISCAN_STATE_SCANING) {
- return 0;
+
+ if (g_scan_specified_ssid) {
+ WL_TRACE(("%s Specific SCAN already running ignoring BC scan\n", \
+ __FUNCTION__));
+ return EBUSY;
}
memset(&ssid, 0, sizeof(ssid));
- g_scan_specified_ssid = 0;
#if WIRELESS_EXT > 17
if (wrqu->data.length == sizeof(struct iw_scan_req)) {
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
int as = 0;
struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) {
+
+ WL_TRACE(("%s First ISCAN in progress : ignoring SC = %s\n", \
+ __FUNCTION__, req->essid));
+ return -EBUSY;
+ }
ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len);
memcpy(ssid.SSID, req->essid, ssid.SSID_len);
ssid.SSID_len = htod32(ssid.SSID_len);
- g_scan_specified_ssid = 1;
- (void) dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
+ dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
+ wl_iw_set_event_mask(dev);
return wl_iw_set_scan(dev, info, wrqu, extra);
}
+ else {
+ g_scan_specified_ssid = 0;
+
+ if (iscan->iscan_state == ISCAN_STATE_SCANING) {
+ WL_TRACE(("%s ISCAN already in progress \n", __FUNCTION__));
+ return 0;
+ }
+ }
}
#endif
- iscan->list_cur = iscan->list_hdr;
- iscan->iscan_state = ISCAN_STATE_SCANING;
- (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);
- mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000);
- iscan->timer_on = 1;
+ wl_iw_iscan_set_scan_broadcast_prep(dev, 0);
return 0;
}
@@ -2337,10 +2768,16 @@ wl_iw_get_scan_prep(
for (i = 0; i < list->count && i < IW_MAX_AP; i++)
{
- ASSERT(list->version == WL_BSS_INFO_VERSION);
+ if (list->version != WL_BSS_INFO_VERSION) {
+ WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
+ __FUNCTION__, list->version));
+ return ret;
+ }
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+ WL_TRACE(("%s : %s\n", __FUNCTION__, bi->SSID));
+
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
@@ -2391,13 +2828,14 @@ wl_iw_get_scan_prep(
if (bi->rateset.count) {
- if (((event - extra) + IW_EV_LCP_LEN) <= (int)end) {
+ if (((event -extra) + IW_EV_LCP_LEN) <= (uintptr)end) {
value = event + IW_EV_LCP_LEN;
iwe.cmd = SIOCGIWRATE;
-
+
iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
- iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
+ iwe.u.bitrate.value =
+ (bi->rateset.rates[j] & 0x7f) * 500000;
value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
IW_EV_PARAM_LEN);
}
@@ -2433,7 +2871,8 @@ wl_iw_get_scan(
#if defined(WL_IW_USE_ISCAN)
iscan_info_t *iscan = g_iscan;
iscan_buf_t * p_buf;
-#endif
+ uint32 counter = 0;
+#endif
WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user));
@@ -2474,6 +2913,7 @@ wl_iw_get_scan(
list = kmalloc(len, GFP_KERNEL);
if (!list) {
WL_TRACE(("%s: wl_iw_get_scan return -ENOMEM\n", dev->name));
+ g_scan_specified_ssid = 0;
return -ENOMEM;
}
}
@@ -2481,7 +2921,7 @@ wl_iw_get_scan(
memset(list, 0, len);
list->buflen = htod32(len);
if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len))) {
- WL_TRACE(("%s: %s : Scan_results too big %d\n", dev->name, __FUNCTION__, len));
+ WL_TRACE(("%s: %s : Scan_results ERROR %d\n", dev->name, __FUNCTION__, len));
dwrq->length = len;
if (g_scan_specified_ssid)
kfree(list);
@@ -2491,11 +2931,14 @@ wl_iw_get_scan(
list->version = dtoh32(list->version);
list->count = dtoh32(list->count);
+
if (list->version != WL_BSS_INFO_VERSION) {
- WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n",
- __FUNCTION__, list->version));
- if (g_scan_specified_ssid)
+ WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
+ __FUNCTION__, list->version));
+ if (g_scan_specified_ssid) {
+ g_scan_specified_ssid = 0;
kfree(list);
+ }
return -EINVAL;
}
@@ -2506,20 +2949,24 @@ wl_iw_get_scan(
}
#if defined(WL_IW_USE_ISCAN)
+ if (g_scan_specified_ssid)
+ WL_TRACE(("%s: Specified scan APs from scan=%d\n", __FUNCTION__, list->count));
p_buf = iscan->list_hdr;
while (p_buf != iscan->list_cur) {
list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count));
+ counter += list_merge->count;
if (list_merge->count > 0)
len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
- extra+len_ret, buflen_from_user -len_ret);
+ extra+len_ret, buflen_from_user -len_ret);
p_buf = p_buf->next;
}
+ WL_TRACE(("%s merged with total Bcast APs=%d\n", __FUNCTION__, counter));
#else
list_merge = (wl_scan_results_t *) g_scan;
len_ret = (__u16) wl_iw_get_scan_prep(list_merge, info, extra, buflen_from_user);
-#endif
+#endif
if (g_ss_cache_ctrl.m_link_down) {
wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
@@ -2530,7 +2977,10 @@ wl_iw_get_scan(
wl_iw_run_ss_cache_timer(0);
wl_iw_run_ss_cache_timer(1);
-
+#if defined(WL_IW_USE_ISCAN)
+
+ g_scan_specified_ssid = 0;
+#endif
if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user)
len = len_ret;
@@ -2563,16 +3013,28 @@ wl_iw_iscan_get_scan(
__u16 merged_len = 0;
uint buflen_from_user = dwrq->length;
-
WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length));
+#if defined(SOFTAP)
+ if (ap_cfg_running) {
+ WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
+ return -EINVAL;
+ }
+#endif
+
if (!extra) {
- WL_TRACE(("%s: SIOCGIWSCAN GET bad parameter\n", dev->name));
+ WL_TRACE(("%s: INVALID SIOCGIWSCAN GET bad parameter\n", dev->name));
return -EINVAL;
}
+ if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) {
+ WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \
+ dev->name, __FUNCTION__));
+ return -EAGAIN;
+ }
if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ WL_TRACE(("%ssysioc_pid\n", __FUNCTION__));
return wl_iw_get_scan(dev, info, dwrq, extra);
}
@@ -2606,11 +3068,12 @@ wl_iw_iscan_get_scan(
while (p_buf != iscan->list_cur) {
list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
- counter += list->count;
+ counter += list->count;
if (list->version != WL_BSS_INFO_VERSION) {
- WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version));
- return -EINVAL; /* if WL_BSS_INFO_VERSION is corrupted iscan results are garbage */
+ WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \
+ __FUNCTION__, list->version));
+ return -EINVAL;
}
bi = NULL;
@@ -2700,9 +3163,15 @@ wl_iw_iscan_get_scan(
dwrq->length += merged_len;
wl_iw_run_ss_cache_timer(0);
wl_iw_run_ss_cache_timer(1);
+
+ g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED;
WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
+
+ if (!dwrq->length)
+ return -EAGAIN;
+
return 0;
}
#endif
@@ -2722,6 +3191,8 @@ wl_iw_set_essid(
memset(&g_ssid, 0, sizeof(g_ssid));
+ CHECK_EXTRA_FOR_NULL(extra);
+
if (dwrq->length && extra) {
#if WIRELESS_EXT > 20
g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length);
@@ -2737,6 +3208,7 @@ wl_iw_set_essid(
if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &g_ssid, sizeof(g_ssid))))
return error;
+ WL_TRACE(("%s: join SSID=%s\n", __FUNCTION__, g_ssid.SSID));
return 0;
}
@@ -3358,6 +3830,11 @@ wl_iw_set_wpaie(
char *extra
)
{
+
+ WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name));
+
+ CHECK_EXTRA_FOR_NULL(extra);
+
dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length);
return 0;
@@ -3391,6 +3868,8 @@ wl_iw_set_encodeext(
WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name));
+ CHECK_EXTRA_FOR_NULL(extra);
+
memset(&key, 0, sizeof(key));
iwe = (struct iw_encode_ext *)extra;
@@ -3506,12 +3985,15 @@ wl_iw_set_pmksa(
int ret = 0;
char eabuf[ETHER_ADDR_STR_LEN];
- WL_TRACE_PMK(("%s: SIOCSIWPMKSA\n", dev->name));
+ WL_WSEC(("%s: SIOCSIWPMKSA\n", dev->name));
+
+ CHECK_EXTRA_FOR_NULL(extra);
+
iwpmksa = (struct iw_pmksa *)extra;
bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
if (iwpmksa->cmd == IW_PMKSA_FLUSH) {
- WL_TRACE_PMK(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
+ WL_WSEC(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n"));
bzero((char *)&pmkid_list, sizeof(pmkid_list));
}
@@ -3521,15 +4003,16 @@ wl_iw_set_pmksa(
uint j;
pmkidptr = &pmkid;
- bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN);
+ bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, \
+ ETHER_ADDR_LEN);
bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN);
- WL_TRACE_PMK(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ",
+ WL_WSEC(("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_PMK(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
- WL_TRACE_PMK(("\n"));
+ WL_WSEC(("%02x ", pmkidptr->pmkid[0].PMKID[j]));
+ WL_WSEC(("\n"));
}
for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
@@ -3569,33 +4052,33 @@ wl_iw_set_pmksa(
}
else
ret = -EINVAL;
-
{
uint j;
uint k;
k = pmkid_list.pmkids.npmkid;
- WL_TRACE_PMK(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
+ WL_WSEC(("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_PMK(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j]));
- WL_TRACE_PMK(("\n"));
+ WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j]));
+ WL_WSEC(("\n"));
}
}
- WL_TRACE_PMK(("PRINTING pmkid LIST - No of elements %d, ret = %d\n", pmkid_list.pmkids.npmkid, ret));
+ WL_WSEC(("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_PMK(("PMKID[%d]: %s = ", i,
+ WL_WSEC(("PMKID[%d]: %s = ", i,
bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID,
eabuf)));
for (j = 0; j < WPA2_PMKID_LEN; j++)
- WL_TRACE_PMK(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]));
- WL_TRACE_PMK(("\n"));
+ WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]));
+ WL_WSEC(("\n"));
}
- WL_TRACE_PMK(("\n"));
+ WL_WSEC(("\n"));
if (!ret)
- ret = dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list));
+ ret = dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, \
+ sizeof(pmkid_list));
return ret;
}
#endif
@@ -3629,6 +4112,13 @@ wl_iw_set_wpaauth(
WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name));
+#if defined(SOFTAP)
+ if (ap_cfg_running) {
+ WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__));
+ return 0;
+ }
+#endif
+
paramid = vwrq->flags & IW_AUTH_INDEX;
paramval = vwrq->value;
@@ -3869,9 +4359,901 @@ wl_iw_get_wpaauth(
#endif
+#ifdef SOFTAP
+static int ap_macmode = MACLIST_MODE_DISABLED;
+static struct mflist ap_black_list;
static int
-wl_iw_set_priv(
+wl_iw_parse_wep(char *keystr, wl_wsec_key_t *key)
+{
+ char hex[] = "XX";
+ unsigned char *data = key->data;
+
+ switch (strlen(keystr)) {
+ case 5:
+ case 13:
+ case 16:
+ key->len = strlen(keystr);
+ memcpy(data, keystr, key->len + 1);
+ break;
+ case 12:
+ case 28:
+ case 34:
+ case 66:
+
+ if (!strnicmp(keystr, "0x", 2))
+ keystr += 2;
+ else
+ return -1;
+
+ case 10:
+ case 26:
+ case 32:
+ case 64:
+ key->len = strlen(keystr) / 2;
+ while (*keystr) {
+ strncpy(hex, keystr, 2);
+ *data++ = (char) bcm_strtoul(hex, NULL, 16);
+ keystr += 2;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ switch (key->len) {
+ case 5:
+ key->algo = CRYPTO_ALGO_WEP1;
+ break;
+ case 13:
+ key->algo = CRYPTO_ALGO_WEP128;
+ break;
+ case 16:
+
+ key->algo = CRYPTO_ALGO_AES_CCM;
+ break;
+ case 32:
+ key->algo = CRYPTO_ALGO_TKIP;
+ break;
+ default:
+ return -1;
+ }
+
+
+ key->flags |= WL_PRIMARY_KEY;
+
+ return 0;
+}
+
+#ifdef EXT_WPA_CRYPTO
+#define SHA1HashSize 20
+extern void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, \
+ int iterations, u8 *buf, size_t buflen);
+
+#else
+
+#define SHA1HashSize 20
+int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, \
+ int iterations, u8 *buf, size_t buflen)
+{
+ WL_ERROR(("WARNING: %s is not implemented !!!\n", __FUNCTION__));
+ return -1;
+}
+
+#endif
+
+int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val)
+{
+ struct {
+ int cfg;
+ int val;
+ } bss_setbuf;
+
+ int bss_set_res;
+ char smbuf[WLC_IOCTL_SMLEN];
+ memset(smbuf, 0, sizeof(smbuf));
+
+ bss_setbuf.cfg = 1;
+ bss_setbuf.val = val;
+
+ bss_set_res = dev_iw_iovar_setbuf(dev, "bss",
+ &bss_setbuf, sizeof(bss_setbuf), smbuf, sizeof(smbuf));
+ WL_TRACE(("\n:%s: bss_set_result:%d\n", __FUNCTION__, bss_set_res));
+
+ return bss_set_res;
+}
+
+static int wl_bssiovar_mkbuf(
+ const char *iovar,
+ int bssidx,
+ void *param,
+ int paramlen,
+ void *bufptr,
+ int buflen,
+ int *perr)
+{
+ const char *prefix = "bsscfg:";
+ int8* p;
+ uint prefixlen;
+ uint namelen;
+ uint iolen;
+
+ prefixlen = strlen(prefix);
+ namelen = strlen(iovar) + 1;
+ iolen = prefixlen + namelen + sizeof(int) + paramlen;
+
+
+ if (buflen < 0 || iolen > (uint)buflen) {
+ *perr = BCME_BUFTOOSHORT;
+ return 0;
+ }
+
+ p = (int8*)bufptr;
+
+
+ memcpy(p, prefix, prefixlen);
+ p += prefixlen;
+
+
+ memcpy(p, iovar, namelen);
+ p += namelen;
+
+
+ bssidx = htod32(bssidx);
+ memcpy(p, &bssidx, sizeof(int32));
+ p += sizeof(int32);
+
+
+ if (paramlen)
+ memcpy(p, param, paramlen);
+
+ *perr = 0;
+ return iolen;
+}
+
+
+
+
+int get_user_params(char *user_params, struct iw_point *dwrq)
+{
+ int ret = 0;
+
+ if (copy_from_user(user_params, dwrq->pointer, dwrq->length)) {
+ WL_ERROR(("\n%s: no user params: uptr:%p, ulen:%d\n",
+ __FUNCTION__, dwrq->pointer, dwrq->length));
+ return -EFAULT;
+ }
+
+ WL_TRACE(("\n%s: iwpriv user params:%s\n", __FUNCTION__, user_params));
+
+ return ret;
+}
+
+
+#ifdef SOFTAP
+
+struct net_device *ap_net_dev = NULL;
+struct semaphore ap_eth_sema;
+static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap);
+
+
+static int thr_wait_for_2nd_eth_dev(void *data)
+{
+
+ DAEMONIZE("wl0_eth_wthread");
+
+ WL_TRACE(("\n>%s threda started:, PID:%x\n", __FUNCTION__, current->pid));
+
+ if (down_timeout(&ap_eth_sema, msecs_to_jiffies(5000)) != 0) {
+ WL_ERROR(("\n%s: sap_eth_sema timeout \n", __FUNCTION__));
+ return -1;
+ }
+
+ if (!ap_net_dev) {
+ WL_ERROR((" ap_net_dev is null !!!"));
+ return -1;
+ }
+
+ WL_TRACE(("\n>%s: Thread:'softap ethdev IF:%s is detected !!!'\n\n",
+ __FUNCTION__, ap_net_dev->name));
+
+ ap_mode = 1;
+ ap_cfg_running = TRUE;
+
+ bcm_mdelay(500);
+
+
+ wl_iw_send_priv_event(priv_dev, "ASCII_CMD=AP_BSS_START");
+
+ WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__));
+
+ return 0;
+}
+
+
+static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
+{
+ int updown = 0;
+ int channel = 0;
+
+ wlc_ssid_t ap_ssid;
+ wlc_ssid_t null_ssid;
+ int max_assoc = 8;
+ int mpc = 0;
+
+ int res = 0;
+ int apsta_var = 0;
+ int iolen = 0;
+ int mkvar_err = 0;
+ int bsscfg_index = 1;
+ char buf[WLC_IOCTL_SMLEN];
+
+ ap_mode = 0;
+
+ memset(&null_ssid, 0, sizeof(wlc_ssid_t));
+ WL_SOFTAP(("wl_iw: set ap profile:\n"));
+ WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
+ WL_SOFTAP((" security = '%s'\n", ap->sec));
+ if (ap->key[0] != '\0')
+ WL_SOFTAP((" key = '%s'\n", ap->key));
+ WL_SOFTAP((" channel = %d\n", ap->channel));
+ WL_SOFTAP((" max scb = %d\n", ap->max_scb));
+
+
+ if (!ap_cfg_running) {
+
+
+ sema_init(&ap_eth_sema, 0);
+
+ mpc = 0;
+ res |= dev_wlc_intvar_set(dev, "mpc", mpc);
+
+ updown = 0;
+ res |= dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown));
+
+
+#ifdef AP_ONLY
+
+ apsta_var = 0;
+ res | = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var));
+
+ apsta_var = 1;
+ res |= dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var));
+ res |= dev_wlc_ioctl(dev, WLC_GET_AP, &apsta_var, sizeof(apsta_var));
+#else
+
+ apsta_var = 1;
+ iolen = wl_bssiovar_mkbuf("apsta",
+ bsscfg_index, &apsta_var, sizeof(apsta_var)+4,
+ buf, sizeof(buf), &mkvar_err);
+ ASSERT(iolen);
+ res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
+ WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res));
+#endif
+
+ updown = 1;
+ res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
+ WL_TRACE(("\n:%s >>>> dev_wlc_ioctl(WLC_UP) updown:%d, \n", __FUNCTION__, updown));
+
+ } else {
+
+ res |= dev_iw_write_cfg1_bss_var(dev, 0);
+ }
+
+
+ if (ap->channel == 0) {
+ int chosen = 0;
+ wl_uint32_list_t request;
+ int rescan = 0;
+ int retry = 0;
+ int ret = 0;
+ res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
+ res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid));
+
+ auto_channel_retry:
+ request.count = htod32(0);
+ ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
+ if (ret < 0) {
+ WL_ERROR(("can't start auto channel scan\n"));
+ return -1;
+ }
+
+ get_channel_retry:
+ bcm_mdelay(500);
+
+ ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
+ if (ret < 0 || dtoh32(chosen) == 0) {
+ if (retry++ < 3)
+ goto get_channel_retry;
+ else {
+ WL_ERROR(("can't get auto channel sel, err = %d, \
+ chosen = %d\n", ret, chosen));
+ return -1;
+ }
+ }
+ if ((chosen == 1) && (!rescan++))
+ goto auto_channel_retry;
+ WL_SOFTAP(("Set auto channel = %d\n", chosen));
+ ap->channel = chosen;
+ dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown));
+ }
+
+ channel = ap->channel;
+ res |= dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel));
+
+ if (!ap_cfg_running) {
+ updown = 0;
+ res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown));
+ }
+
+ max_assoc = ap->max_scb;
+ res |= dev_wlc_intvar_set(dev, "maxassoc", max_assoc);
+
+ ap_ssid.SSID_len = strlen(ap->ssid);
+ strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len);
+
+
+ iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid),
+ ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
+ ASSERT(iolen);
+ res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
+
+ if (!ap_cfg_running) {
+
+ kernel_thread(thr_wait_for_2nd_eth_dev, 0, 0);
+ } else {
+
+
+
+ WL_TRACE(("%s: Configure security & restart AP bss \n", __FUNCTION__));
+
+
+ res |= wl_iw_set_ap_security(dev, &my_ap);
+
+
+ res |= dev_iw_write_cfg1_bss_var(dev, 1);
+ }
+
+ return res;
+}
+#endif
+
+
+
+static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap)
+{
+ int wsec = 0;
+ int wpa_auth = 0;
+ int res = 0;
+ int i;
+ char *ptr;
+
+ WL_SOFTAP(("\nsetting SOFTAP security mode:\n"));
+ WL_SOFTAP(("wl_iw: set ap profile:\n"));
+ WL_SOFTAP((" ssid = '%s'\n", ap->ssid));
+ WL_SOFTAP((" security = '%s'\n", ap->sec));
+ if (ap->key[0] != '\0')
+ WL_SOFTAP((" key = '%s'\n", ap->key));
+ WL_SOFTAP((" channel = %d\n", ap->channel));
+ WL_SOFTAP((" max scb = %d\n", ap->max_scb));
+
+
+ if (strnicmp(ap->sec, "open", strlen("open")) == 0) {
+
+
+ wsec = 0;
+ res = dev_wlc_intvar_set(dev, "wsec", wsec);
+ wpa_auth = WPA_AUTH_DISABLED;
+ res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
+
+ WL_SOFTAP(("=====================\n"));
+ WL_SOFTAP((" wsec & wpa_auth set 'OPEN', result:&d %d\n", res));
+ WL_SOFTAP(("=====================\n"));
+
+ } else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) {
+
+
+ wl_wsec_key_t key;
+ memset(&key, 0, sizeof(key));
+
+ wsec = WEP_ENABLED;
+ res = dev_wlc_intvar_set(dev, "wsec", wsec);
+
+ key.index = 0;
+ if (wl_iw_parse_wep(ap->key, &key)) {
+ WL_SOFTAP(("wep key parse err!\n"));
+ return -1;
+ }
+
+ key.index = htod32(key.index);
+ key.len = htod32(key.len);
+ key.algo = htod32(key.algo);
+ key.flags = htod32(key.flags);
+
+ res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
+
+ wpa_auth = WPA_AUTH_DISABLED;
+ res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
+
+ WL_SOFTAP(("=====================\n"));
+ WL_SOFTAP((" wsec & auth set 'WEP', result:&d %d\n", res));
+ WL_SOFTAP(("=====================\n"));
+
+ } else if (strnicmp(ap->sec, "wpa2-psk", strlen("wpa2-psk")) == 0) {
+
+
+
+ wsec_pmk_t psk;
+ size_t key_len;
+
+ wsec = AES_ENABLED;
+ dev_wlc_intvar_set(dev, "wsec", wsec);
+
+ key_len = strlen(ap->key);
+ if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
+ WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
+ WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
+ return -1;
+ }
+
+
+ if (key_len < WSEC_MAX_PSK_LEN) {
+ unsigned char output[2*SHA1HashSize];
+ char key_str_buf[WSEC_MAX_PSK_LEN+1];
+
+
+ memset(output, 0, sizeof(output));
+ pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
+
+ ptr = key_str_buf;
+ for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
+
+ sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], \
+ (uint)output[i*4+1], (uint)output[i*4+2], \
+ (uint)output[i*4+3]);
+ ptr += 8;
+ }
+ WL_SOFTAP(("%s: passphase = %s\n", __FUNCTION__, key_str_buf));
+
+ psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
+ memcpy(psk.key, key_str_buf, psk.key_len);
+ } else {
+ psk.key_len = htod16((ushort) key_len);
+ memcpy(psk.key, ap->key, key_len);
+ }
+ psk.flags = htod16(WSEC_PASSPHRASE);
+ dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
+
+ wpa_auth = WPA2_AUTH_PSK;
+ dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
+
+ } else if (strnicmp(ap->sec, "wpa-psk", strlen("wpa-psk")) == 0) {
+
+
+ wsec_pmk_t psk;
+ size_t key_len;
+
+ wsec = TKIP_ENABLED;
+ res = dev_wlc_intvar_set(dev, "wsec", wsec);
+
+ key_len = strlen(ap->key);
+ if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
+ WL_SOFTAP(("passphrase must be between %d and %d characters long\n",
+ WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN));
+ return -1;
+ }
+
+
+ if (key_len < WSEC_MAX_PSK_LEN) {
+ unsigned char output[2*SHA1HashSize];
+ char key_str_buf[WSEC_MAX_PSK_LEN+1];
+
+ WL_SOFTAP(("%s: do passhash...\n", __FUNCTION__));
+
+ pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32);
+
+ ptr = key_str_buf;
+ for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) {
+ WL_SOFTAP(("[%02d]: %08x\n", i, *((unsigned int*)&output[i*4])));
+
+ sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], \
+ (uint)output[i*4+1], (uint)output[i*4+2], \
+ (uint)output[i*4+3]);
+ ptr += 8;
+ }
+ printk("%s: passphase = %s\n", __FUNCTION__, key_str_buf);
+
+ psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN);
+ memcpy(psk.key, key_str_buf, psk.key_len);
+ } else {
+ psk.key_len = htod16((ushort) key_len);
+ memcpy(psk.key, ap->key, key_len);
+ }
+
+ psk.flags = htod16(WSEC_PASSPHRASE);
+ res |= dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk));
+
+ wpa_auth = WPA_AUTH_PSK;
+ res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth);
+
+ WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res));
+ }
+
+ return res;
+}
+
+
+
+int get_parmeter_from_string(
+ char **str_ptr, const char *token,
+ int param_type, void *dst, int param_max_len)
+{
+ char int_str[7] = "0";
+ int parm_str_len;
+ char *param_str_begin;
+ char *param_str_end;
+ char *orig_str = *str_ptr;
+
+ if (!strncmp(*str_ptr, token, strlen(token))) {
+
+ strsep(str_ptr, "=,");
+ param_str_begin = *str_ptr;
+ strsep(str_ptr, "=,");
+
+ if (*str_ptr == NULL) {
+
+ parm_str_len = strlen(param_str_begin);
+ } else {
+ param_str_end = *str_ptr-1;
+ parm_str_len = param_str_end - param_str_begin;
+ }
+
+ WL_TRACE((" 'token:%s', len:%d, ", token, parm_str_len));
+
+ if (parm_str_len > param_max_len) {
+ WL_TRACE((" WARNING: extracted param len:%d is > MAX:%d\n",
+ parm_str_len, param_max_len));
+
+ parm_str_len = param_max_len;
+ }
+
+ switch (param_type) {
+
+ case PTYPE_INTDEC: {
+
+ int *pdst_int = dst;
+ char *eptr;
+ if (parm_str_len > sizeof(int_str))
+ parm_str_len = sizeof(int_str);
+
+ memcpy(int_str, param_str_begin, parm_str_len);
+
+ *pdst_int = simple_strtoul(int_str, &eptr, 10);
+
+ WL_TRACE((" written as integer:%d\n", *pdst_int));
+ }
+ break;
+ case PTYPE_STR_HEX: {
+ u8 *buf = dst;
+
+ param_max_len = param_max_len >> 1;
+ hstr_2_buf(param_str_begin, buf, param_max_len);
+ print_buf(buf, param_max_len, 0);
+ }
+ break;
+ default:
+
+ memcpy(dst, param_str_begin, parm_str_len);
+ *((char *)dst + parm_str_len) = 0;
+ WL_TRACE((" written as a string:%s\n", (char *)dst));
+ break;
+
+ }
+
+ return 0;
+ } else {
+ WL_ERROR(("\n %s: ERROR: can't find token:%s in str:%s \n",
+ __FUNCTION__, token, orig_str));
+
+ return -1;
+ }
+}
+
+
+static int iwpriv_softap_stop(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *ext)
+{
+ int res;
+
+ WL_SOFTAP((" iw_handler SOFTAP_STP \n"));
+
+
+ ap_mode = 0;
+ ap_cfg_running = FALSE;
+
+
+ res = dev_iw_write_cfg1_bss_var(dev, 2);
+
+ wrqu->data.length = 0;
+
+ return res;
+}
+
+
+
+static int iwpriv_fw_reload(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *ext)
+{
+
+ int ret = -1;
+ char extra[256];
+ char *fwstr = fw_path ;
+
+ WL_SOFTAP(("current firmware_path[]=%s\n", fwstr));
+
+ WL_TRACE((">Got FW_RELOAD cmd:"
+ "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d, \
+ fw_path:%p, len:%d \n",
+ info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length, fwstr, strlen(fwstr)));
+
+
+ if ((wrqu->data.length > 4) && (wrqu->data.length < sizeof(extra))) {
+
+ char *str_ptr;
+
+ if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
+ ret = -EFAULT;
+ goto exit_proc;
+ }
+
+
+ extra[wrqu->data.length] = 8;
+ str_ptr = extra;
+
+ if (get_parmeter_from_string(&str_ptr, "FW_PATH=", PTYPE_STRING, fwstr, 255) != 0) {
+ WL_ERROR(("Error: extracting FW_PATH='' string\n"));
+ goto exit_proc;
+ }
+
+ if (strstr(fwstr, "apsta") != NULL) {
+ WL_SOFTAP(("GOT APSTA FIRMWARE\n"));
+ ap_fw_loaded = TRUE;
+ } else {
+ WL_SOFTAP(("GOT STA FIRMWARE\n"));
+ ap_fw_loaded = FALSE;
+ }
+
+ WL_SOFTAP(("SET firmware_path[]=%s , str_p:%p\n", fwstr, fwstr));
+ ret = 0;
+ } else {
+ WL_ERROR(("Error: ivalid param len:%d\n", wrqu->data.length));
+ }
+
+exit_proc:
+ return ret;
+}
+#ifdef SOFTAP
+static int iwpriv_wpasupp_loop_tst(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *ext)
+{
+ int res = 0;
+ char *params = NULL;
+
+ WL_TRACE((">Got IWPRIV wp_supp loopback cmd test:"
+ "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n",
+ info->cmd, info->flags,
+ wrqu->data.pointer, wrqu->data.length));
+
+ if (wrqu->data.length != 0) {
+
+ if (!(params = kmalloc(wrqu->data.length+1, GFP_KERNEL)))
+ return -ENOMEM;
+
+
+ if (copy_from_user(params, wrqu->data.pointer, wrqu->data.length)) {
+ kfree(params);
+ return -EFAULT;
+ }
+
+ params[wrqu->data.length] = 0;
+ WL_SOFTAP(("\n>> copied from user:\n %s\n", params));
+ } else {
+ WL_ERROR(("ERROR param length is 0\n"));
+ return -EFAULT;
+ }
+
+
+ res = wl_iw_send_priv_event(dev, params);
+ kfree(params);
+
+ return res;
+}
+#endif
+
+
+static int
+ iwpriv_en_ap_bss(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ void *wrqu,
+ char *extra)
+{
+ int res = 0;
+ WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name));
+
+
+ if (wl_iw_set_ap_security(dev, &my_ap) != 0) {
+ WL_ERROR(("!!!!:ERROR setting SOFTAP security in :%s\n", __FUNCTION__));
+ };
+
+
+ dev_iw_write_cfg1_bss_var(dev, 1);
+ return res;
+}
+
+static int
+get_assoc_sta_list(struct net_device *dev, char *buf, int len)
+{
+
+ WL_TRACE(("calling dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n",
+ dev, WLC_GET_ASSOCLIST, buf, len));
+
+ dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len);
+
+ return 0;
+}
+
+
+static int
+set_ap_mac_list(struct net_device *dev, char *buf)
+{
+ struct mac_list_set *mac_list_set = (struct mac_list_set *)buf;
+ struct maclist *white_maclist = (struct maclist *)&mac_list_set->white_list;
+ struct maclist *black_maclist = (struct maclist *)&mac_list_set->black_list;
+ int mac_mode = mac_list_set->mode;
+ int length;
+ int i;
+
+ ap_macmode = mac_mode;
+ if (mac_mode == MACLIST_MODE_DISABLED) {
+
+ bzero(&ap_black_list, sizeof(struct mflist));
+
+
+ dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
+ } else {
+ scb_val_t scbval;
+ char mac_buf[256] = {0};
+ struct maclist *assoc_maclist = (struct maclist *) mac_buf;
+
+ mac_mode = MACLIST_MODE_ALLOW;
+
+ dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode));
+
+
+ length = sizeof(white_maclist->count)+white_maclist->count*ETHER_ADDR_LEN;
+ dev_wlc_ioctl(dev, WLC_SET_MACLIST, white_maclist, length);
+ WL_SOFTAP(("White List, length %d:\n", length));
+ for (i = 0; i < white_maclist->count; i++)
+ WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ i, white_maclist->ea[i].octet[0], white_maclist->ea[i].octet[1], \
+ white_maclist->ea[i].octet[2], \
+ white_maclist->ea[i].octet[3], white_maclist->ea[i].octet[4], \
+ white_maclist->ea[i].octet[5]));
+
+
+ bcopy(black_maclist, &ap_black_list, sizeof(ap_black_list));
+
+ WL_SOFTAP(("Black List, size %d:\n", sizeof(ap_black_list)));
+ for (i = 0; i < ap_black_list.count; i++)
+ WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ i, ap_black_list.ea[i].octet[0], ap_black_list.ea[i].octet[1], \
+ ap_black_list.ea[i].octet[2], \
+ ap_black_list.ea[i].octet[3], \
+ ap_black_list.ea[i].octet[4], ap_black_list.ea[i].octet[5]));
+
+
+ dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256);
+ if (assoc_maclist->count) {
+ int j;
+ for (i = 0; i < assoc_maclist->count; i++) {
+ for (j = 0; j < white_maclist->count; j++) {
+ if (!bcmp(&assoc_maclist->ea[i], &white_maclist->ea[j], \
+ ETHER_ADDR_LEN)) {
+ WL_SOFTAP(("match allow, let it be\n"));
+ break;
+ }
+ }
+ if (j == white_maclist->count) {
+ WL_SOFTAP(("match black, deauth it\n"));
+ scbval.val = htod32(1);
+ bcopy(&assoc_maclist->ea[i], &scbval.ea, \
+ ETHER_ADDR_LEN);
+ dev_wlc_ioctl(dev, \
+ WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval,
+ sizeof(scb_val_t));
+ }
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
+
+#ifdef SOFTAP
+int set_macfilt_from_string(struct mflist *pmflist, char **param_str)
+{
+ return 0;
+}
+#endif
+
+
+#ifdef SOFTAP
+#define PARAM_OFFSET PROFILE_OFFSET
+
+int wl_iw_process_private_ascii_cmd(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *dwrq,
+ char *cmd_str)
+{
+ int ret = 0;
+ char *sub_cmd = cmd_str + PROFILE_OFFSET + strlen("ASCII_CMD=");
+
+ WL_SOFTAP(("\n %s: ASCII_CMD: offs_0:%s, offset_32:\n'%s'\n",
+ __FUNCTION__, cmd_str, cmd_str + PROFILE_OFFSET));
+
+ if (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) {
+
+ WL_SOFTAP((" AP_CFG \n"));
+
+ ap_mode = 0;
+
+
+ if (init_ap_profile_from_string(cmd_str+PROFILE_OFFSET, &my_ap) != 0) {
+ WL_ERROR(("ERROR: SoftAP CFG prams !\n"));
+ ret = -1;
+ } else {
+ set_ap_cfg(dev, &my_ap);
+ }
+
+ } else if (strnicmp(sub_cmd, "AP_BSS_START", strlen("AP_BSS_START")) == 0) {
+
+ WL_SOFTAP(("\n SOFTAP - ENABLE BSS \n"));
+
+
+ WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name));
+
+ if (ap_net_dev == NULL) {
+ printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n");
+ } else {
+
+ iwpriv_en_ap_bss(ap_net_dev, info, dwrq, cmd_str);
+ }
+
+ } else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) {
+
+
+
+ } else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) {
+
+ WL_SOFTAP((" \n temp DOWN SOFTAP\n"));
+ ret = dev_iw_write_cfg1_bss_var(dev, 0);
+ }
+
+ return ret;
+
+}
+#endif
+static int wl_iw_set_priv(
struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
@@ -3881,6 +5263,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;
@@ -3889,34 +5272,38 @@ wl_iw_set_priv(
return -EFAULT;
}
- WL_TRACE(("%s: SIOCSIWPRIV requst = %s\n",
- dev->name, extra));
+ WL_TRACE(("%s: SIOCSIWPRIV request %s, info->cmd:%x, info->flags:%d\n dwrq->length:%d",
+ dev->name, extra, info->cmd, info->flags, dwrq->length));
- net_os_wake_lock(dev);
if (dwrq->length && extra) {
- if (strnicmp(extra, "START", strlen("START")) == 0) {
- wl_iw_control_wl_on(dev, info);
- WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
- }
+ 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_TRACE(("%s, missing START, Fail\n", __FUNCTION__));
- kfree(extra);
- net_os_wake_unlock(dev);
- return -EFAULT;
+ if (strnicmp(extra, "START", strlen("START")) != 0) {
+ WL_ERROR(("%s First IOCTL after stop is NOT START \n", \
+ __FUNCTION__));
+ WAKE_UNLOCK(iw->pub, WAKE_LOCK_PRIV);
+ WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_PRIV);
+ kfree(extra);
+ return -EFAULT;
+ } else {
+ wl_iw_control_wl_on(dev, info);
+ WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
+ }
}
if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) {
#ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
- WL_TRACE(("%s: active scan setting supppressed\n", dev->name));
+ WL_TRACE(("%s: active scan setting suppressed\n", dev->name));
#else
ret = wl_iw_set_active_scan(dev, info, (union iwreq_data *)dwrq, extra);
#endif
}
else if (strnicmp(extra, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0)
#ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS
- WL_TRACE(("%s: passive scan setting supppressed\n", dev->name));
+ WL_TRACE(("%s: passive scan setting suppressed\n", dev->name));
#else
ret = wl_iw_set_passive_scan(dev, info, (union iwreq_data *)dwrq, extra);
#endif
@@ -3932,15 +5319,25 @@ wl_iw_set_priv(
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);
+#ifdef SOFTAP
+ else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
+
+ wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
+ }
+ else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) {
+ WL_SOFTAP(("penguin, set AP_MAC_LIST_SET\n"));
+ set_ap_mac_list(dev, (extra + PROFILE_OFFSET));
+ }
+#endif
else {
snprintf(extra, MAX_WX_STRING, "OK");
dwrq->length = strlen("OK") + 1;
- WL_TRACE(("Unkown PRIVATE command , ignored\n"));
+ WL_ERROR(("Unkown PRIVATE command , ignored\n"));
}
+ WAKE_UNLOCK(iw->pub, WAKE_LOCK_PRIV);
+ WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_PRIV);
}
- net_os_wake_unlock(dev);
-
if (extra) {
if (copy_to_user(dwrq->pointer, extra, dwrq->length)) {
kfree(extra);
@@ -4051,11 +5448,41 @@ static const iw_handler wl_iw_priv_handler[] = {
NULL,
(iw_handler)wl_iw_control_wl_off,
NULL,
- (iw_handler)wl_iw_control_wl_on
+ (iw_handler)wl_iw_control_wl_on,
+#ifdef SOFTAP
+
+
+ NULL,
+ (iw_handler)iwpriv_set_ap_config,
+
+
+
+ NULL,
+ (iw_handler)iwpriv_get_assoc_list,
+
+
+ NULL,
+ (iw_handler)iwpriv_set_mac_filters,
+
+
+ NULL,
+ (iw_handler)iwpriv_en_ap_bss,
+
+
+ NULL,
+ (iw_handler)iwpriv_wpasupp_loop_tst,
+
+ NULL,
+ (iw_handler)iwpriv_softap_stop,
+
+ NULL,
+ (iw_handler)iwpriv_fw_reload
+#endif
};
-static const struct iw_priv_args wl_iw_priv_args[] = {
- {
+static const struct iw_priv_args wl_iw_priv_args[] =
+{
+ {
WL_IW_SET_ACTIVE_SCAN,
0,
IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
@@ -4096,8 +5523,60 @@ static const struct iw_priv_args wl_iw_priv_args[] = {
0,
IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
"START"
- }
-};
+ },
+
+#ifdef SOFTAP
+
+
+ {
+ WL_SET_AP_CFG,
+ IW_PRIV_TYPE_CHAR | 256,
+ 0,
+ "AP_SET_CFG"
+ },
+
+ {
+ WL_AP_STA_LIST,
+ 0,
+ IW_PRIV_TYPE_CHAR | 0,
+ "AP_GET_STA_LIST"
+ },
+
+ {
+ WL_AP_MAC_FLTR,
+ IW_PRIV_TYPE_CHAR | 256,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
+ "AP_SET_MAC_FLTR"
+ },
+
+ {
+ WL_AP_BSS_START,
+ 0,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ "AP_BSS_START"
+ },
+
+ {
+ AP_LPB_CMD,
+ IW_PRIV_TYPE_CHAR | 256,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
+ "AP_LPB_CMD"
+ },
+
+ {
+ WL_AP_STOP,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
+ "AP_BSS_STOP"
+ },
+ {
+ WL_FW_RELOAD,
+ IW_PRIV_TYPE_CHAR | 256,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0,
+ "WL_FW_RELOAD"
+ },
+#endif
+ };
const struct iw_handler_def wl_iw_handler_def =
{
@@ -4114,8 +5593,9 @@ const struct iw_handler_def wl_iw_handler_def =
};
#endif
-int
-wl_iw_ioctl(
+
+
+int wl_iw_ioctl(
struct net_device *dev,
struct ifreq *rq,
int cmd
@@ -4127,10 +5607,13 @@ wl_iw_ioctl(
char *extra = NULL;
int token_size = 1, max_tokens = 0, ret = 0;
+ WL_TRACE(("\n%s, cmd:%x alled via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd));
if (cmd < SIOCIWFIRST ||
IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) ||
- !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)]))
- return -EOPNOTSUPP;
+ !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) {
+ WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd));
+ return -EOPNOTSUPP;
+ }
switch (cmd) {
@@ -4147,11 +5630,12 @@ wl_iw_ioctl(
case SIOCSIWENCODEEXT:
case SIOCGIWENCODEEXT:
#endif
- max_tokens = IW_ENCODING_TOKEN_MAX;
+ max_tokens = wrq->u.data.length;
break;
case SIOCGIWRANGE:
- max_tokens = sizeof(struct iw_range);
+
+ max_tokens = sizeof(struct iw_range) + 500;
break;
case SIOCGIWAPLIST:
@@ -4180,15 +5664,21 @@ wl_iw_ioctl(
max_tokens = IW_MAX_SPY;
break;
+#if WIRELESS_EXT > 17
+ case SIOCSIWPMKSA:
+ case SIOCSIWGENIE:
+#endif
case SIOCSIWPRIV:
max_tokens = wrq->u.data.length;
break;
}
if (max_tokens && wrq->u.data.pointer) {
- if (wrq->u.data.length > max_tokens)
+ if (wrq->u.data.length > max_tokens) {
+ WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d > max_tokens=%d\n", \
+ __FUNCTION__, cmd, wrq->u.data.length, max_tokens));
return -E2BIG;
-
+ }
if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL)))
return -ENOMEM;
@@ -4327,12 +5817,56 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
uint16 flags = ntoh16(e->flags);
uint32 datalen = ntoh32(e->datalen);
uint32 status = ntoh32(e->status);
+ wl_iw_t *iw;
uint32 toto;
memset(&wrqu, 0, sizeof(wrqu));
memset(extra, 0, sizeof(extra));
+ iw = 0;
+
+ if (!dev) {
+ WL_ERROR(("%s: dev is null\n", __FUNCTION__));
+ return;
+ }
+ iw = *(wl_iw_t **)netdev_priv(dev);
+
+ WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type));
+
+
switch (event_type) {
+#if defined(SOFTAP)
+ case WLC_E_PRUNE:
+ if (ap_mode) {
+ char *macaddr = (char *)&e->addr;
+ WL_SOFTAP(("PRUNE received, %02X:%02X:%02X:%02X:%02X:%02X!\n",
+ macaddr[0], macaddr[1], macaddr[2], macaddr[3], \
+ macaddr[4], macaddr[5]));
+
+
+ if (ap_macmode)
+ {
+ int i;
+ for (i = 0; i < ap_black_list.count; i++) {
+ if (!bcmp(macaddr, &ap_black_list.ea[i], \
+ sizeof(struct ether_addr))) {
+ WL_SOFTAP(("mac in black list, ignore it\n"));
+ break;
+ }
+ }
+
+ if (i == ap_black_list.count) {
+
+ char mac_buf[32] = {0};
+ sprintf(mac_buf, "STA_BLOCK %02X:%02X:%02X:%02X:%02X:%02X",
+ macaddr[0], macaddr[1], macaddr[2],
+ macaddr[3], macaddr[4], macaddr[5]);
+ wl_iw_send_priv_event(priv_dev, mac_buf);
+ }
+ }
+ }
+ break;
+#endif
case WLC_E_TXFAIL:
cmd = IWEVTXDROP;
memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
@@ -4342,12 +5876,26 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
case WLC_E_JOIN:
case WLC_E_ASSOC_IND:
case WLC_E_REASSOC_IND:
+#if defined(SOFTAP)
+ WL_SOFTAP(("STA connect received %d\n", event_type));
+ if (ap_mode) {
+ wl_iw_send_priv_event(priv_dev, "STA_JOIN");
+ return;
+ }
+#endif
memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
wrqu.addr.sa_family = ARPHRD_ETHER;
cmd = IWEVREGISTERED;
break;
case WLC_E_DEAUTH_IND:
case WLC_E_DISASSOC_IND:
+#if defined(SOFTAP)
+ WL_SOFTAP(("STA disconnect received %d\n", event_type));
+ if (ap_mode) {
+ wl_iw_send_priv_event(priv_dev, "STA_LEAVE");
+ return;
+ }
+#endif
cmd = SIOCGIWAP;
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
wrqu.addr.sa_family = ARPHRD_ETHER;
@@ -4359,11 +5907,23 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
if (!(flags & WLC_EVENT_MSG_LINK)) {
+#ifdef SOFTAP
+ if (ap_mode && !strncmp(dev->name, "wl0.1", 5)) {
+
+ WL_SOFTAP(("AP DOWN %d\n", event_type));
+ wl_iw_send_priv_event(priv_dev, "AP_DOWN");
+ } else {
+ WL_TRACE(("STA_Link Down\n"));
g_ss_cache_ctrl.m_link_down = 1;
+ }
+#else
+ g_ss_cache_ctrl.m_link_down = 1;
+#endif
WL_TRACE(("Link Down\n"));
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
bzero(&extra, ETHER_ADDR_LEN);
+ WAKE_LOCK_TIMEOUT(iw->pub, WAKE_LOCK_LINK_DOWN_TMOUT, 20 * HZ);
}
else {
@@ -4371,6 +5931,17 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
g_ss_cache_ctrl.m_link_down = 0;
memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN);
+#ifdef SOFTAP
+
+ if (ap_mode && !strncmp(dev->name, "wl0.1", 5)) {
+
+ WL_SOFTAP(("AP UP %d\n", event_type));
+ wl_iw_send_priv_event(priv_dev, "AP_UP");
+ } else {
+ WL_TRACE(("STA_LINK_UP\n"));
+ }
+#else
+#endif
WL_TRACE(("Link UP\n"));
}
@@ -4382,7 +5953,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
wrqu.data.length = datalen + 1;
extra[0] = WLC_E_ACTION_FRAME;
memcpy(&extra[1], data, datalen);
- printf("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length);
+ WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length));
}
break;
@@ -4461,7 +6032,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
wrqu.data.length = strlen(extra);
WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n"));
#endif
- break;
+ break;
default:
@@ -4469,14 +6040,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
break;
}
#ifndef SANDGATE2G
- if (cmd) {
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
- if (cmd == SIOCGIWSCAN)
- wireless_send_event(dev, cmd, &wrqu, NULL);
- else
-#endif
- wireless_send_event(dev, cmd, &wrqu, extra);
- }
+ if (cmd)
+ wireless_send_event(dev, cmd, &wrqu, extra);
#endif
#if WIRELESS_EXT > 14
@@ -4507,14 +6072,14 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
goto done;
phy_noise = dtoh32(phy_noise);
- WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise));
+ WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise));
scb_val.val = 0;
if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
goto done;
rssi = dtoh32(scb_val.val);
- WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi));
+ WL_TRACE(("wl_iw_get_wireless_stats rssi=%d\n", rssi));
if (rssi <= WL_IW_RSSI_NO_SIGNAL)
wstats->qual.qual = 0;
else if (rssi <= WL_IW_RSSI_VERY_LOW)
@@ -4538,13 +6103,13 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
#endif
#if WIRELESS_EXT > 11
- WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n *****", (int)sizeof(wl_cnt_t)));
+ WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n", (int)sizeof(wl_cnt_t)));
memset(&cnt, 0, sizeof(wl_cnt_t));
res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
if (res)
{
- WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d ****** \n", res));
+ WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d\n", res));
goto done;
}
@@ -4621,19 +6186,17 @@ _bt_dhcp_sysioc_thread(void *data)
DAEMONIZE("dhcp_sysioc");
while (down_interruptible(&g_bt->bt_sem) == 0) {
-
- net_os_wake_lock(g_bt->dev);
-
if (g_bt->timer_on) {
+ del_timer(&g_bt->timer);
g_bt->timer_on = 0;
- del_timer_sync(&g_bt->timer);
}
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);
+ mod_timer(&g_bt->timer, jiffies + \
+ BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000);
g_bt->timer_on = 1;
break;
case BT_DHCP_OPPORTUNITY_WINDOW:
@@ -4662,15 +6225,12 @@ _bt_dhcp_sysioc_thread(void *data)
g_bt->timer_on = 0;
break;
}
-
- net_os_wake_unlock(g_bt->dev);
}
if (g_bt->timer_on) {
+ del_timer(&g_bt->timer);
g_bt->timer_on = 0;
- del_timer_sync(&g_bt->timer);
}
-
complete_and_exit(&g_bt->bt_exited, 0);
}
@@ -4741,6 +6301,7 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
g_iscan = iscan;
iscan->dev = dev;
iscan->iscan_state = ISCAN_STATE_IDLE;
+ g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
g_iscan->scan_flag = 0;
@@ -4755,7 +6316,6 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
if (iscan->sysioc_pid < 0)
return -ENOMEM;
#endif
- mutex_init(&wl_start_lock);
iw = *(wl_iw_t **)netdev_priv(dev);
iw->pub = (dhd_pub_t *)dhdp;
@@ -4769,10 +6329,16 @@ int wl_iw_attach(struct net_device *dev, void * dhdp)
memset(g_scan, 0, G_SCAN_RESULTS);
g_scan_specified_ssid = 0;
+
wl_iw_init_ss_cache_ctrl();
wl_iw_bt_init(dev);
+#ifdef SOFTAP
+ priv_dev = dev;
+#endif
+
+
return 0;
}
@@ -4805,5 +6371,12 @@ void wl_iw_detach(void)
wl_iw_release_ss_cache_ctrl();
wl_iw_bt_release();
+#ifdef SOFTAP
+ if (ap_mode) {
+ WL_TRACE(("\n%s AP is going down\n", __FUNCTION__));
+
+ wl_iw_send_priv_event(priv_dev, "AP_DOWN");
+ }
+#endif
}
diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h
index 0321964..7f770fd 100644
--- a/bcm4329/src/wl/sys/wl_iw.h
+++ b/bcm4329/src/wl/sys/wl_iw.h
@@ -1,7 +1,7 @@
/*
* Linux Wireless Extensions support
*
- * Copyright (C) 1999-2009, Broadcom Corporation
+ * Copyright (C) 1999-2010, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -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.9 2009/10/14 04:27:31 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.13.2.2 2010/03/16 22:09:45 Exp $
*/
@@ -35,6 +35,9 @@
#include <wlioctl.h>
+
+
+
#define WL_IW_RSSI_MINVAL -200
#define WL_IW_RSSI_NO_SIGNAL -91
#define WL_IW_RSSI_VERY_LOW -80
@@ -53,11 +56,26 @@
#define WL_IW_SET_STOP (SIOCIWFIRSTPRIV+11)
#define WL_IW_SET_START (SIOCIWFIRSTPRIV+13)
+
+#define WL_SET_AP_CFG (SIOCIWFIRSTPRIV+15)
+#define WL_AP_STA_LIST (SIOCIWFIRSTPRIV+17)
+#define WL_AP_MAC_FLTR (SIOCIWFIRSTPRIV+19)
+#define WL_AP_BSS_START (SIOCIWFIRSTPRIV+21)
+#define AP_LPB_CMD (SIOCIWFIRSTPRIV+23)
+#define WL_AP_STOP (SIOCIWFIRSTPRIV+25)
+#define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27)
+#define WL_AP_SPARE2 (SIOCIWFIRSTPRIV+29)
+#define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31)
#define G_SCAN_RESULTS 8*1024
#define WE_ADD_EVENT_FIX 0x80
#define G_WLAN_SET_ON 0
#define G_WLAN_SET_OFF 1
+#define CHECK_EXTRA_FOR_NULL(extra) \
+if (!extra) { \
+ WL_ERROR(("%s: error : extra is null pointer\n", __FUNCTION__)); \
+ return -EINVAL; \
+}
typedef struct wl_iw {
char nickname[IW_ESSID_MAX_SIZE];
@@ -106,8 +124,41 @@ typedef struct wl_iw_ss_cache_ctrl {
uint m_cons_br_scan_cnt;
struct timer_list *m_timer;
} wl_iw_ss_cache_ctrl_t;
+typedef enum broadcast_first_scan {
+ BROADCAST_SCAN_FIRST_IDLE = 0,
+ BROADCAST_SCAN_FIRST_STARTED,
+ BROADCAST_SCAN_FIRST_RESULT_READY,
+ BROADCAST_SCAN_FIRST_RESULT_CONSUMED
+} broadcast_first_scan_t;
+#ifdef SOFTAP
+#define SSID_LEN 33
+#define SEC_LEN 16
+#define KEY_LEN 65
+#define PROFILE_OFFSET 32
+struct ap_profile {
+ uint8 ssid[SSID_LEN];
+ uint8 sec[SEC_LEN];
+ uint8 key[KEY_LEN];
+ uint32 channel;
+ uint32 preamble;
+ uint32 max_scb;
+};
+#define MACLIST_MODE_DISABLED 0
+#define MACLIST_MODE_ENABLED 1
+#define MACLIST_MODE_ALLOW 2
+struct mflist {
+ uint count;
+ struct ether_addr ea[16];
+};
+struct mac_list_set {
+ uint32 mode;
+ struct mflist white_list;
+ struct mflist black_list;
+};
+#endif
+
#if WIRELESS_EXT > 12
#include <net/iw_handler.h>
extern const struct iw_handler_def wl_iw_handler_def;
@@ -118,12 +169,6 @@ 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, void * dhdp);
void wl_iw_detach(void);
-int wl_control_wl_start(struct net_device *dev);
-
-extern int net_os_wake_lock(struct net_device *dev);
-extern int net_os_wake_unlock(struct net_device *dev);
-extern int net_os_wake_lock_timeout(struct net_device *dev);
-extern int net_os_wake_lock_timeout_enable(struct net_device *dev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \