summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward Harte <hharte@broadcom.com>2009-03-30 17:09:32 -0700
committerHoward Harte <hharte@broadcom.com>2009-03-30 17:09:32 -0700
commitf42f81d9f222732884ecf14adfeaee6a58e8a534 (patch)
treed57463b317aa94b44441d2f9b7103c872c97a5ba
parent4d9cbf702872c23734edf9af540852330ca8590a (diff)
downloadbroadcom-f42f81d9f222732884ecf14adfeaee6a58e8a534.tar.gz
Updated support for Android.
-rw-r--r--src/bcmsdio/sys/bcmsdh.c26
-rw-r--r--src/bcmsdio/sys/bcmsdh_sdmmc.c263
-rw-r--r--src/bcmsdio/sys/bcmsdh_sdmmc_linux.c77
-rw-r--r--src/dhd/exe/GNUmakefile4
-rw-r--r--src/dhd/exe/dhdu.c4
-rwxr-xr-xsrc/dhd/linux/Makefile28
-rw-r--r--src/dhd/sys/dhd.h45
-rw-r--r--src/dhd/sys/dhd_bus.h31
-rw-r--r--src/dhd/sys/dhd_cdc.c73
-rw-r--r--src/dhd/sys/dhd_common.c69
-rw-r--r--src/dhd/sys/dhd_linux.c136
-rw-r--r--src/dhd/sys/dhd_proto.h32
-rw-r--r--src/dhd/sys/dhd_sdio.c163
-rw-r--r--src/include/bcmdefs.h28
-rw-r--r--src/include/bcmsdbus.h7
-rw-r--r--src/include/bcmsdh.h7
-rw-r--r--src/include/bcmsdh_sdmmc.h5
-rw-r--r--src/include/epivers.h38
-rw-r--r--src/include/linuxver.h4
-rw-r--r--src/include/proto/802.11.h32
-rw-r--r--src/include/proto/bcmevent.h31
-rw-r--r--src/include/proto/eapol.h4
-rw-r--r--src/include/sbchipc.h33
-rw-r--r--src/include/wlioctl.h96
-rw-r--r--src/wl/sys/wl_iw.c1428
-rw-r--r--src/wl/sys/wl_iw.h40
26 files changed, 2170 insertions, 534 deletions
diff --git a/src/bcmsdio/sys/bcmsdh.c b/src/bcmsdio/sys/bcmsdh.c
index f92da43..afbf5e0 100644
--- a/src/bcmsdio/sys/bcmsdh.c
+++ b/src/bcmsdio/sys/bcmsdh.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh.c,v 1.35.2.1.4.8.16.3 2008/12/17 04:22:21 Exp $
+ * $Id: bcmsdh.c,v 1.35.2.1.4.8.16.4 2009/03/19 04:09:04 Exp $
*/
/* ****************** BCMSDH Interface Functions *************************** */
@@ -182,6 +182,30 @@ bcmsdh_intr_pending(void *sdh)
}
#endif
+#ifdef BCMLXSDMMC
+int
+bcmsdh_claim_host_and_lock(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ ASSERT(bcmsdh);
+
+ status = sdioh_claim_host_and_lock(bcmsdh->sdioh);
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+
+int
+bcmsdh_release_host_and_unlock(void *sdh)
+{
+ bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh;
+ SDIOH_API_RC status;
+ ASSERT(bcmsdh);
+
+ status = sdioh_release_host_and_unlock(bcmsdh->sdioh);
+ return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR);
+}
+#endif /* BCMLXSDMMC */
+
int
bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
{
diff --git a/src/bcmsdio/sys/bcmsdh_sdmmc.c b/src/bcmsdio/sys/bcmsdh_sdmmc.c
index ef1a773..c6f5de2 100644
--- a/src/bcmsdio/sys/bcmsdh_sdmmc.c
+++ b/src/bcmsdio/sys/bcmsdh_sdmmc.c
@@ -3,27 +3,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc.c,v 1.1.2.8.6.4 2008/12/24 03:52:33 Exp $
+ * $Id: bcmsdh_sdmmc.c,v 1.1.2.8.6.10 2009/03/24 23:07:13 Exp $
*/
#include <typedefs.h>
@@ -49,10 +47,9 @@ extern void sdio_function_cleanup(void);
#endif /* BCMSDH_MODULE */
static void IRQHandler(struct sdio_func *func);
-#ifdef USE_STOCK_MMC_DRIVER /* Define to use unmodified Linux Kernel mmc driver. */
static void IRQHandlerF2(struct sdio_func *func);
-#endif /* USE_STOCK_MMC_DRIVER */
static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
+extern int sdio_reset_comm(struct mmc_card *card);
extern PBCMSDH_SDMMC_INSTANCE gInstance;
@@ -71,6 +68,35 @@ uint sd_use_dma = TRUE;
int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data);
+int sdioh_claim_host_and_lock(sdioh_info_t *sd)
+{
+ sdio_claim_host(gInstance->func[0]);
+ gInstance->host_claimed = 1;
+ return SDIOH_API_RC_SUCCESS;
+}
+
+int sdioh_release_host_and_unlock(sdioh_info_t *sd)
+{
+ gInstance->host_claimed = 0;
+ sdio_release_host(gInstance->func[0]);
+ return SDIOH_API_RC_SUCCESS;
+}
+
+
+void SDIO_CLAIM_HOST(uint32 func)
+{
+ if (gInstance->host_claimed == 0) {
+ sdio_claim_host(gInstance->func[func]);
+ }
+}
+
+void SDIO_RELEASE_HOST(uint32 func)
+{
+ if (gInstance->host_claimed == 0) {
+ sdio_release_host(gInstance->func[func]);
+ }
+}
+
static int
sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
{
@@ -97,9 +123,10 @@ sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr));
/* Enable Function 1 */
- sdio_claim_host(gInstance->func[1]);
+ gInstance->host_claimed = 0;
+ SDIO_CLAIM_HOST(1);
err_ret = sdio_enable_func(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
+ SDIO_RELEASE_HOST(1);
if (err_ret) {
sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret));
}
@@ -143,7 +170,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
gInstance->sd = sd;
/* Claim host controller */
- sdio_claim_host(gInstance->func[1]);
+ SDIO_CLAIM_HOST(1);
sd->client_block_size[1] = 64;
err_ret = sdio_set_block_size(gInstance->func[1], 64);
@@ -152,10 +179,11 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
}
/* Release host controller F1 */
- sdio_release_host(gInstance->func[1]);
+ SDIO_RELEASE_HOST(1);
+
if (gInstance->func[2]) {
/* Claim host controller F2 */
- sdio_claim_host(gInstance->func[2]);
+ SDIO_CLAIM_HOST(2);
sd->client_block_size[2] = sd_f2_blocksize;
err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize);
@@ -164,21 +192,12 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq)
sd_f2_blocksize));
}
-#ifdef USE_STOCK_MMC_DRIVER
- err_ret = sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
-#endif /* USE_STOCK_MMC_DRIVER */
-
/* Release host controller F2 */
- sdio_release_host(gInstance->func[2]);
+ SDIO_RELEASE_HOST(2);
}
sdioh_sdmmc_card_enablefuncs(sd);
- /* register and unmask irq */
- sdio_claim_host(gInstance->func[1]);
- err_ret = sdio_claim_irq(gInstance->func[1], IRQHandler);
- sdio_release_host(gInstance->func[1]);
-
sd_trace(("%s: Done\n", __FUNCTION__));
return sd;
}
@@ -191,6 +210,16 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd)
if (sd) {
+ /* Disable Function 2 */
+ SDIO_CLAIM_HOST(2);
+ sdio_disable_func(gInstance->func[2]);
+ SDIO_RELEASE_HOST(2);
+
+ /* Disable Function 1 */
+ SDIO_CLAIM_HOST(1);
+ sdio_disable_func(gInstance->func[1]);
+ SDIO_RELEASE_HOST(1);
+
/* deregister irq */
sdioh_sdmmc_osfree(sd);
@@ -204,9 +233,26 @@ extern SDIOH_API_RC
sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
{
sd_trace(("%s: Entering\n", __FUNCTION__));
+ if (fn == NULL) {
+ sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__));
+ return SDIOH_API_RC_FAIL;
+ }
sd->intr_handler = fn;
sd->intr_handler_arg = argh;
sd->intr_handler_valid = TRUE;
+
+ /* register and unmask irq */
+ if (gInstance->func[2]) {
+ SDIO_CLAIM_HOST(2);
+ sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
+ SDIO_RELEASE_HOST(2);
+ }
+
+ if (gInstance->func[1]) {
+ SDIO_CLAIM_HOST(1);
+ sdio_claim_irq(gInstance->func[1], IRQHandler);
+ SDIO_RELEASE_HOST(1);
+ }
return SDIOH_API_RC_SUCCESS;
}
@@ -214,6 +260,22 @@ extern SDIOH_API_RC
sdioh_interrupt_deregister(sdioh_info_t *sd)
{
sd_trace(("%s: Entering\n", __FUNCTION__));
+
+ if (gInstance->func[1]) {
+ /* register and unmask irq */
+ SDIO_CLAIM_HOST(1);
+ sdio_release_irq(gInstance->func[1]);
+ SDIO_RELEASE_HOST(1);
+ }
+
+ if (gInstance->func[2]) {
+ /* Claim host controller F2 */
+ SDIO_CLAIM_HOST(2);
+ sdio_release_irq(gInstance->func[2]);
+ /* Release host controller F2 */
+ SDIO_RELEASE_HOST(2);
+ }
+
sd->intr_handler_valid = FALSE;
sd->intr_handler = NULL;
sd->intr_handler_arg = NULL;
@@ -632,7 +694,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
*/
if (regaddr == SDIOD_CCCR_IOEN) {
if (gInstance->func[2]) {
- sdio_claim_host(gInstance->func[2]);
+ SDIO_CLAIM_HOST(2);
if (*byte & SDIO_FUNC_ENABLE_2) {
/* Enable Function 2 */
err_ret = sdio_enable_func(gInstance->func[2]);
@@ -648,25 +710,25 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
err_ret));
}
}
- sdio_release_host(gInstance->func[2]);
+ SDIO_RELEASE_HOST(2);
}
} else if (regaddr < 0xF0) {
sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr));
} else {
/* Claim host controller, perform F0 write, and release */
- sdio_claim_host(gInstance->func[func]);
+ SDIO_CLAIM_HOST(func);
sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
+ SDIO_RELEASE_HOST(func);
}
} else {
/* Claim host controller, perform Fn write, and release */
- sdio_claim_host(gInstance->func[func]);
+ SDIO_CLAIM_HOST(func);
sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret);
- sdio_release_host(gInstance->func[func]);
+ SDIO_RELEASE_HOST(func);
}
} else { /* CMD52 Read */
/* Claim host controller, perform Fn read, and release */
- sdio_claim_host(gInstance->func[func]);
+ SDIO_CLAIM_HOST(func);
if (func == 0) {
*byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret);
@@ -674,7 +736,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
*byte = sdio_readb(gInstance->func[func], regaddr, &err_ret);
}
- sdio_release_host(gInstance->func[func]);
+ SDIO_RELEASE_HOST(func);
}
if (err_ret) {
@@ -700,7 +762,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add
__FUNCTION__, cmd_type, rw, func, addr, nbytes));
/* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
+ SDIO_CLAIM_HOST(func);
if(rw) { /* CMD52 Write */
if (nbytes == 4) {
@@ -721,7 +783,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add
}
/* Release host controller */
- sdio_release_host(gInstance->func[func]);
+ SDIO_RELEASE_HOST(func);
if (err_ret) {
sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x",
@@ -746,7 +808,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
ASSERT(pkt);
/* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
+ SDIO_CLAIM_HOST(func);
for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) {
uint pkt_len = PKTLEN(sd->osh, pnext);
pkt_len += 3;
@@ -804,7 +866,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
}
/* Release host controller */
- sdio_release_host(gInstance->func[func]);
+ SDIO_RELEASE_HOST(func);
sd_trace(("%s: Exit\n", __FUNCTION__));
return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
@@ -838,6 +900,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) {
sd_err(("%s: PKTGET failed: len %d\n",
__FUNCTION__, buflen_u));
+ return SDIOH_API_RC_FAIL;
}
/* For a write, copy the buffer data into the packet. */
@@ -864,6 +927,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) {
sd_err(("%s: PKTGET failed: len %d\n",
__FUNCTION__, PKTLEN(sd->osh, pkt)));
+ return SDIOH_API_RC_FAIL;
}
/* For a write, copy the buffer data into the packet. */
@@ -897,15 +961,6 @@ sdioh_abort(sdioh_info_t *sd, uint func)
{
sd_trace(("%s: Enter\n", __FUNCTION__));
- /* Claim host controller */
- sdio_claim_host(gInstance->func[func]);
-
-#ifndef USE_STOCK_MMC_DRIVER
- sdio_abort(gInstance->func[func]);
-#endif /* USE_STOCK_MMC_DRIVER */
-
- /* Release host controller */
- sdio_release_host(gInstance->func[func]);
sd_trace(("%s: Exit\n", __FUNCTION__));
return SDIOH_API_RC_SUCCESS;
@@ -966,23 +1021,24 @@ static void IRQHandler(struct sdio_func *func)
sdioh_info_t *sd;
sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n"));
-
sd = gInstance->sd;
ASSERT(sd != NULL);
-
+ gInstance->host_claimed = 1;
if (sd->client_intr_enabled && sd->use_client_ints) {
sd->intrcount++;
ASSERT(sd->intr_handler);
ASSERT(sd->intr_handler_arg);
(sd->intr_handler)(sd->intr_handler_arg);
} else {
- sd_trace(("%s: Not ready for intr: enabled %d, handler %p\n",
+ sd_err(("bcmsdh_sdmmc: ***IRQHandler\n"));
+
+ sd_err(("%s: Not ready for intr: enabled %d, handler %p\n",
__FUNCTION__, sd->client_intr_enabled, sd->intr_handler));
}
+ gInstance->host_claimed = 0;
}
-#ifdef USE_STOCK_MMC_DRIVER
/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */
static void IRQHandlerF2(struct sdio_func *func)
{
@@ -994,7 +1050,6 @@ static void IRQHandlerF2(struct sdio_func *func)
ASSERT(sd != NULL);
}
-#endif /* USE_STOCK_MMC_DRIVER */
#ifdef NOTUSED
/* Write client card reg */
@@ -1022,3 +1077,93 @@ sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsiz
return SUCCESS;
}
#endif /* NOTUSED */
+
+
+void
+sdioh_start(int stage)
+{
+ int ret;
+ sdioh_info_t *sd = gInstance->sd;
+
+ /* Need to do this stages as we can't enable the interrupt till
+ downloading of the firmware is complete, other wise polling
+ sdio access will come in way
+ */
+ if (gInstance->func[0]) {
+ if (stage == 0) {
+
+ /* Since the power to the chip is killed, we will have
+ re enumerate the device again. Set the block size
+ and enable the fucntion 1 for in preparation for
+ downloading the code
+ */
+ /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux
+ 2.6.27. The implementation prior to that is buggy, and needs broadcom's
+ patch for it
+ */
+ if ((ret = sdio_reset_comm(gInstance->func[0]->card)))
+ sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret));
+ else {
+ sd->num_funcs = 2;
+ sd->sd_blockmode = TRUE;
+ sd->use_client_ints = TRUE;
+ sd->client_block_size[0] = 64;
+
+ /* Claim host controller */
+ SDIO_CLAIM_HOST(1);
+
+ sd->client_block_size[1] = 64;
+ if (sdio_set_block_size(gInstance->func[1], 64)) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n"));
+ }
+
+ /* Release host controller F1 */
+ SDIO_RELEASE_HOST(1);
+
+ if (gInstance->func[2]) {
+ /* Claim host controller F2 */
+ SDIO_CLAIM_HOST(2);
+
+ sd->client_block_size[2] = sd_f2_blocksize;
+ if (sdio_set_block_size(gInstance->func[2],
+ sd_f2_blocksize)) {
+ sd_err(("bcmsdh_sdmmc: Failed to set F2 "
+ "blocksize to %d\n", sd_f2_blocksize));
+ }
+
+ /* Release host controller F2 */
+ SDIO_RELEASE_HOST(2);
+ }
+
+ sdioh_sdmmc_card_enablefuncs(sd);
+ }
+ }
+ else if (stage == 1) {
+ SDIO_CLAIM_HOST(0);
+ sdio_claim_irq(gInstance->func[2], IRQHandlerF2);
+ sdio_claim_irq(gInstance->func[1], IRQHandler);
+ SDIO_RELEASE_HOST(0);
+ }
+ }
+ else
+ sd_err(("%s Failed\n", __FUNCTION__));
+}
+
+void
+sdioh_stop(void)
+{
+ /* MSM7201A Android sdio stack has bug with interrupt
+ So internaly within SDIO stack they are polling
+ which cause issue when device is turned off. So
+ unregister interrupt with SDIO stack to stop the
+ polling
+ */
+ if (gInstance->func[0]) {
+ SDIO_CLAIM_HOST(0);
+ sdio_release_irq(gInstance->func[1]);
+ sdio_release_irq(gInstance->func[2]);
+ SDIO_RELEASE_HOST(0);
+ }
+ else
+ sd_err(("%s Failed\n", __FUNCTION__));
+}
diff --git a/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
index cb307ff..b3b3bfc 100644
--- a/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
+++ b/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c
@@ -3,27 +3,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.20.3 2009/01/18 18:18:20 Exp $
+ * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.20.5 2009/03/03 08:55:39 Exp $
*/
#include <typedefs.h>
@@ -69,6 +67,7 @@ PBCMSDH_SDMMC_INSTANCE gInstance;
#define BCMSDH_SDMMC_MAX_DEVICES 1
extern int bcmsdh_probe(struct device *dev);
+extern int bcmsdh_remove(struct device *dev);
struct device sdmmc_dev;
static int bcmsdh_sdmmc_probe(struct sdio_func *func,
@@ -108,6 +107,11 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func)
sd_info(("sdio_vendor: 0x%04x\n", func->vendor));
sd_info(("sdio_device: 0x%04x\n", func->device));
sd_info(("Function#: 0x%04x\n", func->num));
+
+ if (func->num == 2) {
+ sd_trace(("F2 found, calling bcmsdh_probe...\n"));
+ bcmsdh_remove(&sdmmc_dev);
+ }
}
@@ -235,45 +239,10 @@ int sdio_function_init(void)
extern int bcmsdh_remove(struct device *dev);
void sdio_function_cleanup(void)
{
- int err_ret;
-
- bcmsdh_remove(&sdmmc_dev);
-
- sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__));
-
- if (gInstance->func[1]) {
- /* Disable Interrupt */
- sdio_claim_host(gInstance->func[1]);
- err_ret = sdio_release_irq(gInstance->func[1]);
- if (err_ret) {
- sd_err(("bcmsdh_sdmmc: Failed release of F1 IRQ, Err: 0x%08x", err_ret));
- }
-
- err_ret = sdio_disable_func(gInstance->func[1]);
- sdio_release_host(gInstance->func[1]);
- if (err_ret) {
- sd_err(("bcmsdh_sdmmc: Failed to disable F1, Err: 0x%08x", err_ret));
- }
- }
+ sd_trace(("%s Enter\n", __FUNCTION__));
- /* Disable Function 2 */
- if (gInstance->func[2]) {
- sdio_claim_host(gInstance->func[2]);
- err_ret = sdio_release_irq(gInstance->func[2]);
- if (err_ret) {
- sd_err(("bcmsdh_sdmmc: Failed to release IRQ for F2, Err: 0x%08x",
- err_ret));
- }
- err_ret = sdio_disable_func(gInstance->func[2]);
- sdio_release_host(gInstance->func[2]);
- if (err_ret) {
- sd_err(("bcmsdh_sdmmc: Failed to disable F2, Err: 0x%08x", err_ret));
- }
- }
+ sdio_unregister_driver(&bcmsdh_sdmmc_driver);
- if (gInstance) {
+ if (gInstance)
kfree(gInstance);
- }
-
- sdio_unregister_driver(&bcmsdh_sdmmc_driver);
}
diff --git a/src/dhd/exe/GNUmakefile b/src/dhd/exe/GNUmakefile
index f7dfa2e..0b90015 100644
--- a/src/dhd/exe/GNUmakefile
+++ b/src/dhd/exe/GNUmakefile
@@ -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: GNUmakefile,v 1.9.24.4.16.4 2008/12/20 01:35:34 Exp $
+# $Id: GNUmakefile,v 1.9.24.4.16.5 2009/03/03 08:51:47 Exp $
SRCBASE = ../..
@@ -61,7 +61,7 @@ ifneq ($(findstring x86,$(TARGETARCH)),x86)
endif
# extra warnings
-CFLAGS += -Wextra
+CFLAGS += -Wextra $(CUSTOM_FLAGS)
vpath %.c $(SRCBASE)/shared
diff --git a/src/dhd/exe/dhdu.c b/src/dhd/exe/dhdu.c
index cee5250..b4bcbdd 100644
--- a/src/dhd/exe/dhdu.c
+++ b/src/dhd/exe/dhdu.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhdu.c,v 1.52.2.10.2.6.16.7 2009/01/08 18:31:54 Exp $
+ * $Id: dhdu.c,v 1.52.2.10.2.6.16.9 2009/03/12 21:33:24 Exp $
*/
/* For backwards compatibility, the absense of the define 'BWL_NO_FILESYSTEM_SUPPORT'
@@ -159,6 +159,8 @@ cmd_t dhd_cmds[] = {
"get/set dhd tx dpc thread quantum"},
{ "senduptq", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
"get/set dhd sendup thread time quantum"},
+ { "rxflow", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+ "get/set dhd rx flow control enable flag"},
{ "dump", dhd_varstr, DHD_GET_VAR, -1,
"dump information"},
{ "clearcounts", dhd_var_void, -1, DHD_SET_VAR,
diff --git a/src/dhd/linux/Makefile b/src/dhd/linux/Makefile
index 323e8be..3418513 100755
--- a/src/dhd/linux/Makefile
+++ b/src/dhd/linux/Makefile
@@ -21,7 +21,7 @@
# software in any way with any other Broadcom software provided under a license
# other than the GPL, without Broadcom's express prior written consent.
#
-# $Id: Makefile,v 1.55.2.6.2.10.12.14 2009/02/20 17:56:01 Exp $
+# $Id: Makefile,v 1.55.2.6.2.10.12.20 2009/03/24 23:07:15 Exp $
#
# Try a couple of places for LINUXDIR if not specified
@@ -41,9 +41,18 @@ endif
endif
endif
-LINUXVER := $(shell { cat $(LINUXDIR)/Makefile; \
- echo "bcm$$$$:;@echo \$$(KERNELRELEASE)"; } | \
- $(MAKE) --no-print-directory $(if $(ARCH),ARCH=$(ARCH),) -C $(LINUXDIR) -f - bcm$$$$)
+# Derive LINUXVER from LINUXDIR
+MYKERNEL_RELEASE_KEYWORD:="KERNELRELEASE[[:space:]]*=.*kernel.release"
+MYKERNEL_DEFINITION:=$(if \
+ $(shell grep $(MYKERNEL_RELEASE_KEYWORD) $(LINUXDIR)/Makefile 2> /dev/null),\
+ grep $(MYKERNEL_RELEASE_KEYWORD) $(LINUXDIR)/Makefile,\
+ cat $(LINUXDIR)/Makefile)
+
+LINUXVER:=$(shell ($(MYKERNEL_DEFINITION); echo "show_kernel_version_number$$$$:;@echo \$$(KERNELRELEASE)") 2> /dev/null | $(MAKE) --no-print-directory -k -C $(LINUXDIR) MYUNAME="" -f - show_kernel_version_number$$$$ 2> /dev/null)
+
+ifeq ($(LINUXVER),)
+ $(error LINUXVER=$(LINUXVER) is empty)
+endif # LINUXVER
# check if 2.4 kernel or 2.5+ kernel
BCM_KVER:=$(shell echo $(LINUXVER) | cut -c1-3 | sed 's/2\.[56]/2\.6/')
@@ -67,14 +76,11 @@ DFLAGS :=
# basic options (defines in DFLAGS, includes in IFLAGS)
DFLAGS += -DLINUX -DSRCBASE=\"$(SRCBASE)\" -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2
DFLAGS += -DUNRELEASEDCHIP
-ifeq ($(USE_STOCK_MMC_DRIVER),1)
- DFLAGS += -DUSE_STOCK_MMC_DRIVER
-endif
ifeq ($(BCMQT),1)
DFLAGS += -DBCMSLTGT -DBCMQT
endif
ifeq ($(WLTEST),1)
- DFLAGS += -DWLTEST -DIOCTL_RESP_TIMEOUT=8000
+ DFLAGS += -DWLTEST -DIOCTL_RESP_TIMEOUT=20000
DFLAGS += -DDHD_SPROM
endif
@@ -90,7 +96,7 @@ DFLAGS += -DCONFIG_WIRELESS_EXT
endif
ifeq ($(CONFIG_MMC_MSM7X00A),y)
-DFLAGS += -Dlinux -DUSE_STOCK_MMC_DRIVER
+DFLAGS += -Dlinux
DFLAGS += -DDHD_SDALIGN=64 -DMAX_HDR_READ=64 -DDHD_FIRSTREAD=64
endif
@@ -170,7 +176,7 @@ DFLAGS += -DBCMSDIO -DBCMSDIOH_STD
CFILES += dhd_sdio.c bcmsdh.c bcmsdstd.c bcmsdstd_linux.c bcmsdh_linux.c
endif
ifneq ($(findstring -sdmmc-,-$(TARGET)-),)
-DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS
+DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS -DSDIO_ISR_THREAD
CFILES += dhd_sdio.c bcmsdh_sdmmc.c bcmsdh.c bcmsdh_linux.c bcmsdh_sdmmc_linux.c
endif
ifneq ($(findstring -sdspi-,$(TARGET)-),)
@@ -188,7 +194,7 @@ ifneq ($(findstring -intc1,$(shell echo $(LINUXVER))),)
DFLAGS += -DSANDGATE2G
endif
-CFLAGS += -fshort-wchar $(DFLAGS) $(WFLAGS) $(IFLAGS)
+CFLAGS += -fshort-wchar $(DFLAGS) $(WFLAGS) $(IFLAGS) $(CUSTOM_FLAGS)
LDFLAGS := -r
MODULES := dhd.o
diff --git a/src/dhd/sys/dhd.h b/src/dhd/sys/dhd.h
index 67d13ed..74c4ae1 100644
--- a/src/dhd/sys/dhd.h
+++ b/src/dhd/sys/dhd.h
@@ -6,27 +6,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd.h,v 1.32.4.7.2.4.28.14 2009/01/08 01:41:03 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.28.18 2009/03/06 21:20:39 Exp $
*/
/****************
@@ -113,6 +111,7 @@ typedef struct dhd_pub {
ulong rx_ctlpkts; /* Control frames processed from dongle */
ulong rx_ctlerrs; /* Errors in processing rx control frames */
ulong rx_dropped; /* Packets dropped locally (no memory) */
+ ulong rx_flushed; /* Packets flushed due to unscheduled sendup thread */
ulong rx_readahead_cnt; /* Number of packets where header read-ahead was used. */
ulong tx_realloc; /* Number of tx packets we had to realloc for headroom */
@@ -138,10 +137,10 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info)
#endif /* NDIS60 */
-typedef struct _dhd_if_event {
- char ifidx;
- char action;
-} dhd_if_event;
+typedef struct dhd_if_event {
+ uint8 ifidx;
+ uint8 action;
+} dhd_if_event_t;
/*
* Exported from dhd OS modules (dhd_linux/dhd_ndis)
@@ -204,14 +203,14 @@ extern void wl_event_to_host_order(wl_event_msg_t * evt);
extern void dhd_common_init(void);
-extern int dhd_add_if(struct dhd_info *dhd, uint ifidx, void *handle, char *name);
-extern void dhd_del_if(struct dhd_info *dhd, uint ifidx);
+extern int dhd_add_if(struct dhd_info *dhd, uint8 ifidx, void *handle, char *name);
+extern void dhd_del_if(struct dhd_info *dhd, uint8 ifidx);
/* Send pakcet to dongle via data channel */
extern int dhd_sendpkt(dhd_pub_t *dhdp, uint ifidx, void *pkt);
/* Send event to host */
-extern void dhd_sendup_event(dhd_pub_t *dhdp, void *pkt);
+extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data);
/*
diff --git a/src/dhd/sys/dhd_bus.h b/src/dhd/sys/dhd_bus.h
index a53d180..ebc508b 100644
--- a/src/dhd/sys/dhd_bus.h
+++ b/src/dhd/sys/dhd_bus.h
@@ -6,27 +6,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_bus.h,v 1.4.6.3.2.3.20.3 2009/01/08 01:30:43 Exp $
+ * $Id: dhd_bus.h,v 1.4.6.3.2.3.20.4 2009/02/03 21:40:44 Exp $
*/
#ifndef _dhd_bus_h_
@@ -85,5 +83,6 @@ extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_par
extern void *dhd_bus_pub(struct dhd_bus *bus);
extern void *dhd_bus_txq(struct dhd_bus *bus);
+extern uint dhd_bus_hdrlen(struct dhd_bus *bus);
#endif /* _dhd_bus_h_ */
diff --git a/src/dhd/sys/dhd_cdc.c b/src/dhd/sys/dhd_cdc.c
index bba3dbd..74a72a1 100644
--- a/src/dhd/sys/dhd_cdc.c
+++ b/src/dhd/sys/dhd_cdc.c
@@ -3,27 +3,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_cdc.c,v 1.22.4.2.4.8.2.6 2009/01/16 02:39:00 Exp $
+ * $Id: dhd_cdc.c,v 1.22.4.2.4.8.2.9 2009/02/25 07:27:58 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
@@ -480,10 +478,49 @@ dhd_prot_dstats(dhd_pub_t *dhd)
}
void
+dhd_preinit_ioctls(dhd_pub_t *dhd)
+{
+ uint up = 0;
+ uint roamvar = 1;
+ char eventmask[WL_EVENTING_MASK_LEN];
+ char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
+
+ /* Force STA UP */
+ dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up));
+
+ /* Disable build-in roaming to allowed ext supplicant to take of romaing */
+ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+
+ /* Setup event_msgs */
+ bzero(eventmask, sizeof(eventmask));
+ setbit(eventmask, WLC_E_SET_SSID);
+ setbit(eventmask, WLC_E_PRUNE);
+ setbit(eventmask, WLC_E_AUTH);
+ setbit(eventmask, WLC_E_REASSOC);
+ setbit(eventmask, WLC_E_REASSOC_IND);
+ setbit(eventmask, WLC_E_DEAUTH_IND);
+ setbit(eventmask, WLC_E_DISASSOC_IND);
+ setbit(eventmask, WLC_E_DISASSOC);
+ setbit(eventmask, WLC_E_JOIN);
+ setbit(eventmask, WLC_E_ASSOC_IND);
+ setbit(eventmask, WLC_E_PSK_SUP);
+ setbit(eventmask, WLC_E_LINK);
+ setbit(eventmask, WLC_E_NDIS_LINK);
+ setbit(eventmask, WLC_E_MIC_ERROR);
+ setbit(eventmask, WLC_E_PMKID_CACHE);
+ setbit(eventmask, WLC_E_TXFAIL);
+ setbit(eventmask, WLC_E_JOIN_START);
+ setbit(eventmask, WLC_E_SCAN_COMPLETE);
+
+ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
+ dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+}
+
+void
dhd_prot_init(dhd_pub_t *dhd)
{
char buf[128];
-
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
/* Get the device MAC address */
@@ -491,6 +528,8 @@ dhd_prot_init(dhd_pub_t *dhd)
dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf));
memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+ dhd_preinit_ioctls(dhd);
+
/* Always assumes wl for now */
dhd->iswl = TRUE;
diff --git a/src/dhd/sys/dhd_common.c b/src/dhd/sys/dhd_common.c
index 4538764..d6e2ee0 100644
--- a/src/dhd/sys/dhd_common.c
+++ b/src/dhd/sys/dhd_common.c
@@ -3,27 +3,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_common.c,v 1.5.6.8.2.8.2.18 2009/01/16 02:39:00 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.8.2.21 2009/02/11 01:23:12 Exp $
*/
#include <typedefs.h>
#include <osl.h>
@@ -41,6 +39,9 @@
int dhd_msg_level;
+ /* Definitions to provide path to the firmware and nvram
+ *example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt"
+ */
char firmware_path[MOD_PARAM_PATHLEN];
char nvram_path[MOD_PARAM_PATHLEN];
@@ -102,8 +103,6 @@ dhd_common_init(void)
* first time that the driver is initialized vs subsequent initializations.
*/
dhd_msg_level = DHD_ERROR_VAL;
- firmware_path[0] = '\0';
- nvram_path[0] = '\0';
}
static int
@@ -143,8 +142,8 @@ dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen)
dhdp->tx_ctlpkts, dhdp->tx_ctlerrs);
bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld \n",
dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors);
- bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld\n",
- dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped);
+ bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n",
+ dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped, dhdp->rx_flushed);
bcm_bprintf(strbuf, "rx_readahead_cnt %ld tx_realloc %ld\n",
dhdp->rx_readahead_cnt, dhdp->tx_realloc);
bcm_bprintf(strbuf, "\n");
@@ -224,6 +223,7 @@ dhd_doiovar(dhd_pub_t * dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const c
dhd_pub->rx_dropped = 0;
dhd_pub->rx_readahead_cnt = 0;
dhd_pub->tx_realloc = 0;
+ dhd_pub->rx_flushed = 0;
memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats));
dhd_bus_clearcounts(dhd_pub);
break;
@@ -719,7 +719,7 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
{
/* check whether packet is a BRCM event pkt */
bcm_event_t *pvt_data = (bcm_event_t *)pktdata;
- void *event_data;
+ char *event_data;
uint32 type, status;
uint16 flags;
@@ -737,18 +737,25 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
/* memcpy since BRCM event pkt may be unaligned. */
memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
- type = ntoh32(event->event_type);
- flags = ntoh16(event->flags);
- status = ntoh32(event->status);
+ type = ntoh32_ua((void *)&event->event_type);
+ flags = ntoh16_ua((void *)&event->flags);
+ status = ntoh32_ua((void *)&event->status);
switch (type) {
case WLC_E_IF:
{
- dhd_if_event *ifevent = (dhd_if_event *)event_data;
-
- if (ifevent->action == WLC_E_IF_ADD)
- dhd_add_if(dhd, ifevent->ifidx, NULL, event->ifname);
- else
- dhd_del_if(dhd, ifevent->ifidx);
+ dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data;
+
+ if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS)
+ {
+ if (ifevent->action == WLC_E_IF_ADD)
+ dhd_add_if(dhd, ifevent->ifidx,
+ NULL, event->ifname);
+ else
+ dhd_del_if(dhd, ifevent->ifidx);
+ } else {
+ DHD_ERROR(("%s: Invalid ifidx %d for %s\n",
+ __FUNCTION__, ifevent->ifidx, event->ifname));
+ }
}
break;
case WLC_E_LINK:
@@ -756,7 +763,7 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
case WLC_E_DEAUTH_IND:
case WLC_E_DISASSOC:
case WLC_E_DISASSOC_IND:
- DHD_EVENT(("%s: Link event %d, flags %x, status %x\n",
+ DHD_ERROR(("%s: Link event %d, flags %x, status %x\n",
__FUNCTION__, type, flags, status));
default:
*ifidx = dhd_ifname2idx(dhd, event->ifname);
diff --git a/src/dhd/sys/dhd_linux.c b/src/dhd/sys/dhd_linux.c
index 3efbeb1..968c474 100644
--- a/src/dhd/sys/dhd_linux.c
+++ b/src/dhd/sys/dhd_linux.c
@@ -4,27 +4,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c,v 1.65.4.9.2.13.6.22 2009/01/18 00:27:49 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.13.6.29 2009/02/11 23:00:23 Exp $
*/
#include <typedefs.h>
@@ -231,9 +229,6 @@ static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR
#ifdef CONFIG_WIRELESS_EXT
-#if WIRELESS_EXT < 21
-static
-#endif /* WIRELESS_EXT < 21 */
struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
#endif /* CONFIG_WIRELESS_EXT */
@@ -247,7 +242,7 @@ static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol);
static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol);
#endif /* TOE */
-static int iw_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
+static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
wl_event_msg_t *event_ptr, void **data_ptr);
int
@@ -445,6 +440,11 @@ dhd_op_if(dhd_if_t *ifp)
switch (ifp->state) {
case WLC_E_IF_ADD:
+ if (ifp->net != NULL) {
+ netif_stop_queue(ifp->net);
+ unregister_netdev(ifp->net);
+ free_netdev(ifp->net);
+ }
/* Allocate etherdev, including space for private structure */
if (!(ifp->net = alloc_etherdev(0))) {
DHD_ERROR(("%s: OOM - alloc_etherdev\n", __FUNCTION__));
@@ -461,9 +461,11 @@ dhd_op_if(dhd_if_t *ifp)
}
break;
case WLC_E_IF_DEL:
- netif_stop_queue(ifp->net);
- unregister_netdev(ifp->net);
- ret = DHD_DEL_IF;
+ if (ifp->net != NULL) {
+ netif_stop_queue(ifp->net);
+ unregister_netdev(ifp->net);
+ ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */
+ }
break;
default:
DHD_ERROR(("%s: bad op %d\n", __FUNCTION__, ifp->state));
@@ -608,7 +610,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
ifidx = dhd_net2idx(dhd, net);
if (ifidx == DHD_BAD_IF) {
- DHD_TRACE(("%s: bad ifidx %d\n", __FUNCTION__, ifidx));
+ DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx));
return -ENODEV;
}
@@ -724,7 +726,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt)
/* Process special event packets and then discard them */
if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM)
- iw_wl_host_event(dhd, &ifidx,
+ dhd_wl_host_event(dhd, &ifidx,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
skb->mac_header,
#else
@@ -764,17 +766,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt)
}
void
-dhd_sendup_event(dhd_pub_t *dhdp, void *pkt)
-{
- dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
- int ifidx;
- wl_event_msg_t event;
- void *data;
-
- iw_wl_host_event(dhd, &ifidx, PKTDATA(dhdp->osh, pkt), &event, &data);
-}
-
-void
dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
{
uint ifidx;
@@ -1298,8 +1289,8 @@ dhd_open(struct net_device *net)
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
- if (ifidx == DHD_BAD_IF)
- return -1;
+
+ ASSERT(ifidx == 0);
/* download image and nvram to the dongle */
if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
@@ -1362,7 +1353,7 @@ dhd_osl_detach(osl_t *osh)
}
int
-dhd_add_if(dhd_info_t *dhd, uint ifidx, void *handle, char *name)
+dhd_add_if(dhd_info_t *dhd, uint8 ifidx, void *handle, char *name)
{
dhd_if_t *ifp;
@@ -1398,7 +1389,7 @@ dhd_add_if(dhd_info_t *dhd, uint ifidx, void *handle, char *name)
}
void
-dhd_del_if(dhd_info_t *dhd, uint ifidx)
+dhd_del_if(dhd_info_t *dhd, uint8 ifidx)
{
dhd_if_t *ifp;
@@ -1465,6 +1456,14 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
goto fail;
}
+#ifdef CONFIG_WIRELESS_EXT
+ /* Attach and link in the iw */
+ if (wl_iw_attach(net) != 0) {
+ DHD_ERROR(("wl_iw_attach failed\n"));
+ goto fail;
+ }
+#endif
+
/* Set up the watchdog timer */
init_timer(&dhd->timer);
dhd->timer.data = (ulong)dhd;
@@ -1523,17 +1522,22 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
struct net_device *net;
uint8 temp_ethaddr[6] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 };
- DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+ DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
ASSERT(dhd && dhd->iflist[ifidx]);
ASSERT(dhd->iflist[ifidx]->net);
ASSERT(!dhd->iflist[ifidx]->net->open);
- *temp_ethaddr = ifidx;
/* Ok, link into the network layer... */
net = dhd->iflist[ifidx]->net;
- net->open = dhd_open;
- net->stop = dhd_stop;
+ if (ifidx == 0) {
+ /*
+ * device functions for the primary interface only
+ */
+ net->open = dhd_open;
+ net->stop = dhd_stop;
+ } else
+ net->open = net->stop = NULL;
net->get_stats = dhd_get_stats;
net->do_ioctl = dhd_ioctl_entry;
net->hard_start_xmit = dhd_start_xmit;
@@ -1545,9 +1549,9 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
#ifdef CONFIG_WIRELESS_EXT
-#if WIRELESS_EXT < 21
+#if WIRELESS_EXT < 19
net->get_wireless_stats = dhd_get_wireless_stats;
-#endif /* WIRELESS_EXT < 21 */
+#endif /* WIRELESS_EXT < 19 */
#if WIRELESS_EXT > 12
net->wireless_handlers = (struct iw_handler_def *) &wl_iw_handler_def;
#endif /* WIRELESS_EXT > 12 */
@@ -1571,19 +1575,6 @@ fail:
return BCME_ERROR;
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
-#define KILL_PROC(pid, sig) \
-{ \
- struct task_struct *tsk; \
- tsk = find_task_by_vpid(pid); \
- send_sig(sig, tsk, 1); \
-}
-#else
-#define KILL_PROC(pid, sig) \
-{ \
- kill_proc(pid, sig, 1); \
-}
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
void
dhd_detach(dhd_pub_t *dhdp)
{
@@ -1629,6 +1620,11 @@ dhd_detach(dhd_pub_t *dhdp)
if (dhdp->prot)
dhd_prot_detach(dhdp);
+#ifdef CONFIG_WIRELESS_EXT
+ /* Attach and link in the iw */
+ wl_iw_detach();
+#endif
+
free_netdev(ifp->net);
MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
}
@@ -1867,10 +1863,8 @@ void
dhd_os_sdunlock_rxq(dhd_pub_t * pub)
{
}
+
#ifdef CONFIG_WIRELESS_EXT
-#if WIRELESS_EXT < 21
-static
-#endif /* WIRELESS_EXT < 21 */
struct iw_statistics *
dhd_get_wireless_stats(struct net_device *dev)
{
@@ -1887,28 +1881,34 @@ dhd_get_wireless_stats(struct net_device *dev)
#endif /* CONFIG_WIRELESS_EXT */
static int
-iw_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, wl_event_msg_t *event, void **data_ptr)
+dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
+ wl_event_msg_t *event, void **data)
{
- int bcmerror;
+ int bcmerror = 0;
ASSERT(dhd != NULL);
- bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data_ptr);
+ bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data);
if (bcmerror != BCME_OK)
return (bcmerror);
#ifdef CONFIG_WIRELESS_EXT
ASSERT(dhd->iflist[*ifidx] != NULL);
- wl_iw_event(dhd->iflist[*ifidx]->net, event, NULL);
+ wl_iw_event(dhd->iflist[*ifidx]->net, event, *data);
#endif /* CONFIG_WIRELESS_EXT */
+ return (bcmerror);
+}
+
+/* send up locally generated event */
+void
+dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
+{
switch (ntoh32(event->event_type)) {
default:
break;
}
-
- return (bcmerror);
}
static int
diff --git a/src/dhd/sys/dhd_proto.h b/src/dhd/sys/dhd_proto.h
index c3b394a..e76788f 100644
--- a/src/dhd/sys/dhd_proto.h
+++ b/src/dhd/sys/dhd_proto.h
@@ -6,27 +6,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_proto.h,v 1.2.82.1.4.1.24.1 2008/10/31 23:21:16 Exp $
+ * $Id: dhd_proto.h,v 1.2.82.1.4.1.24.3 2009/03/10 19:11:47 Exp $
*/
#ifndef _dhd_proto_h_
@@ -80,6 +78,8 @@ extern void dhd_prot_dstats(dhd_pub_t *dhdp);
extern int dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen);
+extern void dhd_preinit_ioctls(dhd_pub_t *dhd);
+
/********************************
* For version-string expansion *
diff --git a/src/dhd/sys/dhd_sdio.c b/src/dhd/sys/dhd_sdio.c
index 6495944..73ae9cf 100644
--- a/src/dhd/sys/dhd_sdio.c
+++ b/src/dhd/sys/dhd_sdio.c
@@ -3,27 +3,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_sdio.c,v 1.157.2.27.2.36.4.24 2009/01/16 02:39:00 Exp $
+ * $Id: dhd_sdio.c,v 1.157.2.27.2.36.4.39 2009/03/24 22:37:18 Exp $
*/
#include <typedefs.h>
@@ -75,6 +73,7 @@
#endif /* defined(CONFIG_MACH_SANDGATE2G) */
#define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */
+
#define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */
#define MEMBLOCK 2048 /* Block size used for downloading of dongle image */
@@ -112,13 +111,14 @@
#if !ISPOWEROF2(MAX_HDR_READ)
#error MAX_HDR_READ is not a power of 2!
#endif
+
#define MAX_RX_DATASZ 2048
/* Maximum milliseconds to wait for F2 to come up */
#define DHD_WAIT_F2RDY 4000
/* Bump up limit on waiting for HT to account for first startup;
- * if the image is doing a CRC calcuation before programming the PMU
+ * if the image is doing a CRC calculation before programming the PMU
* for HT availability, it could take a couple hundred ms more, so
* max out at a half second (500000us).
*/
@@ -218,6 +218,9 @@ typedef struct dhd_bus {
uint32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
bool use_rxchain; /* If dhd should use PKT chains */
bool sleeping; /* Is SDIO bus sleeping? */
+ bool rxflow_enable; /* Is the rx flow control mechanism enable */
+ bool rxflow; /* Is rx flow control on */
+ uint prev_rxlim_hit; /* Is the previous rx limit exceeded (per dpc schedule) */
bool alp_only; /* Don't use HT clock (ALP only) */
/* Field to decide if rx of control frames happen in rxbuf or lb-pool */
bool usebufpool;
@@ -289,7 +292,7 @@ uint dhd_txbound;
uint dhd_rxbound;
uint dhd_txminmax = DHD_TXMINMAX;
-/* overrride the RAM size if possible */
+/* override the RAM size if possible */
#define DONGLE_MIN_MEMSIZE (128 *1024)
int dhd_dongle_memsize;
@@ -849,6 +852,8 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
} else {
PKTPUSH(osh, pkt, pad);
frame = (uint8*)PKTDATA(osh, pkt);
+
+ ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt));
bzero(frame, pad + SDPCM_HDRLEN);
}
}
@@ -1155,10 +1160,8 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
uint retries = 0;
bcmsdh_info_t *sdh = bus->sdh;
uint8 doff = 0;
- int ret = 0;
+ int ret = -1;
int i;
- uint16 pad;
-
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@@ -1183,7 +1186,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
/* Round send length to next SDIO block */
if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
- pad = bus->blocksize - (len % bus->blocksize);
+ uint16 pad = bus->blocksize - (len % bus->blocksize);
if ((pad <= bus->roundup) && (pad < bus->blocksize))
len += pad;
} else if (len % DHD_SDALIGN) {
@@ -1196,6 +1199,11 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
ASSERT(ISALIGNED((uintptr)frame, 2));
+#ifdef BCMLXSDMMC
+ /* Claim SD Host Controller and retain lock. */
+ bcmsdh_claim_host_and_lock(sdh);
+#endif /* BCMLXSDMMC */
+
/* Need to lock here to protect txseq and SDIO tx calls */
dhd_os_sdlock(bus->dhd);
@@ -1260,6 +1268,10 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
}
dhd_os_sdunlock(bus->dhd);
+#ifdef BCMLXSDMMC
+ /* Release SD Host Controller and unlock. */
+ bcmsdh_release_host_and_unlock(bus->sdh);
+#endif /* BCMLXSDMMC */
if (ret)
bus->dhd->tx_ctlerrs++;
@@ -1298,7 +1310,9 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
} else if (pending == TRUE) {
DHD_CTL(("%s: cancelled\n", __FUNCTION__));
return -ERESTARTSYS;
- } else DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
+ } else {
+ DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
+ }
if (rxlen)
bus->dhd->rx_ctlpkts++;
@@ -1636,7 +1650,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch
{
int bcmerror = 0;
int32 int_val = 0;
- bool bool_val;
+ bool bool_val = 0;
DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
__FUNCTION__, actionid, name, params, plen, arg, len, val_size));
@@ -2070,6 +2084,10 @@ exit:
}
dhd_os_sdunlock(bus->dhd);
+
+ if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == FALSE)
+ dhd_preinit_ioctls((dhd_pub_t *) bus->dhd);
+
return bcmerror;
}
@@ -2333,6 +2351,7 @@ void
dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
{
osl_t *osh = bus->dhd->osh;
+ uint32 local_hostintmask;
uint8 saveclk;
uint retries;
int err;
@@ -2347,9 +2366,9 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
/* Enable clock for device interrupts */
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
- /* Disable and clear interrupts at the chip level also */
+ /* Disable interrupts at the chip level also */
W_SDREG(0, &bus->regs->hostintmask, retries);
- W_SDREG(bus->hostintmask, &bus->regs->intstatus, retries);
+ local_hostintmask = bus->hostintmask;
bus->hostintmask = 0;
/* Change our idea of bus state */
@@ -2370,6 +2389,9 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
bcmsdh_intr_disable(bus->sdh);
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
+ /* Clear any pending interrupts now that F2 is disabled */
+ W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
+
/* Turn off the backplane clock (only) */
dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
@@ -2452,7 +2474,6 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
DHD_INFO(("%s: enable 0x%02x, ready 0x%02x\n", __FUNCTION__, enable, ready));
-
/* If F2 successfully enabled, set core and enable interrupts */
if (ready == enable) {
/* Make sure we're talking to the core. */
@@ -2709,7 +2730,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
break;
}
if (sublen % DHD_SDALIGN) {
- DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
+ DHD_GLOM(("%s: sublen %d not a multiple of %d\n",
__FUNCTION__, sublen, DHD_SDALIGN));
usechain = FALSE;
}
@@ -3063,6 +3084,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
uint8 *rxbuf;
int ifidx = 0;
+ uint rxcount = 0; /* Total frames read */
#if defined(DHD_DEBUG) || defined(SDTEST)
bool sdtest = FALSE; /* To limit message spew from test mode */
@@ -3607,20 +3629,20 @@ deliver:
dhd_rx_frame(bus->dhd, ifidx, pkt, 1);
dhd_os_sdlock(bus->dhd);
}
+ rxcount = maxframes - rxleft;
#ifdef DHD_DEBUG
/* Message if we hit the limit */
if (!rxleft && !sdtest)
DHD_ERROR(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
else
#endif /* DHD_DEBUG */
- DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, (maxframes - rxleft)));
-
- /* Back off rxseq if awaiting rtx, upate rx_seq */
+ DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
+ /* Back off rxseq if awaiting rtx, update rx_seq */
if (bus->rxskip)
rxseq--;
bus->rx_seq = rxseq;
- return (maxframes - rxleft);
+ return rxcount;
}
static uint32
@@ -3890,7 +3912,26 @@ clkwait:
bool
dhd_bus_dpc(struct dhd_bus *bus)
{
+#ifdef SDIO_ISR_THREAD
+ bool resched;
+
+#ifdef BCMLXSDMMC
+ /* Claim SD Host Controller and retain lock. */
+ bcmsdh_claim_host_and_lock(bus->sdh);
+#endif /* BCMLXSDMMC */
+
+ /* Call the DPC directly. */
+ DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
+ resched = dhdsdio_dpc(bus);
+
+#ifdef BCMLXSDMMC
+ /* Release SD Host Controller and unlock. */
+ bcmsdh_release_host_and_unlock(bus->sdh);
+#endif /* BCMLXSDMMC */
+ return resched;
+#else
return dhdsdio_dpc(bus);
+#endif /* SDIO_ISR_THREAD */
}
void
@@ -3922,8 +3963,13 @@ dhdsdio_isr(void *arg)
bcmsdh_intr_disable(sdh);
bus->intdis = TRUE;
+#if defined(SDIO_ISR_THREAD)
+ DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
+ while (dhdsdio_dpc(bus));
+#else
bus->dpc_sched = TRUE;
dhd_sched_dpc(bus->dhd);
+#endif
}
@@ -4178,10 +4224,18 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
bus = dhdp->bus;
+ if (bus->dhd->dongle_reset)
+ return FALSE;
+
/* Ignore the timer if simulating bus down */
if (bus->sleeping)
return FALSE;
+#ifdef BCMLXSDMMC
+ /* Claim SD Host Controller and retain lock. */
+ bcmsdh_claim_host_and_lock(bus->sdh);
+#endif /* BCMLXSDMMC */
+
dhd_os_sdlock(bus->dhd);
/* Poll period: check device if appropriate. */
@@ -4242,6 +4296,11 @@ dhd_bus_watchdog(dhd_pub_t *dhdp)
dhd_os_sdunlock(bus->dhd);
+#ifdef BCMLXSDMMC
+ /* Release SD Host Controller and unlock. */
+ bcmsdh_release_host_and_unlock(bus->sdh);
+#endif /* BCMLXSDMMC */
+
return bus->ipend;
}
@@ -4298,7 +4357,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
/* Init global variables at run-time, not as part of the declaration.
* This is required to support init/de-init of the driver. Initialization
* of globals as part of the declaration results in non-deterministic
- * behaviour since the value of the globals may be different on the
+ * behavior since the value of the globals may be different on the
* first time that the driver is initialized vs subsequent initializations.
*/
dhd_txbound = DHD_TXBOUND;
@@ -4445,7 +4504,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
#ifdef DHD_DEBUG
printf("F1 signature read @0x18000000=0x%4x\n",
bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
-#endif
+#endif /* DHD_DEBUG */
/* Force PLL off until si_attach() programs PLL control regs */
@@ -4518,9 +4577,6 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
goto fail;
}
- /* Let the layers below dhd know the chipid and chiprev for
- * controlling sw WAR's for hw PR's
- */
bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
@@ -4618,6 +4674,8 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
bus->dhd->busstate = DHD_BUS_DOWN;
bus->sleeping = FALSE;
+ bus->rxflow = FALSE;
+ bus->prev_rxlim_hit = 0;
/* Done with backplane-dependent accesses, can drop clock... */
@@ -4680,10 +4738,13 @@ bool
dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
char *firmware_path, char *nvram_path)
{
+ bool ret;
bus->firmware_path = firmware_path;
bus->nvram_path = nvram_path;
- return dhdsdio_download_firmware(bus, osh, bus->sdh);
+ ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
+
+ return ret;
}
static bool
@@ -4717,6 +4778,9 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
dhdsdio_release_dongle(bus, osh);
+ /* De-register interrupt handler */
+ bcmsdh_intr_dereg(bus->sdh);
+
MFREE(osh, bus, sizeof(dhd_bus_t));
}
@@ -4931,6 +4995,19 @@ process_nvram_vars(char *varbuf, uint len)
return buf_len;
}
+/*
+ EXAMPLE: nvram_array
+ nvram_arry format:
+ name=value
+ Use carriage return at the end of each assignment, and an empty string with
+ carriage return at the end of array.
+
+ For example:
+ unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"};
+ Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
+
+ Search "EXAMPLE: nvram_array" to see how the array is activated.
+*/
void
dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params)
@@ -5061,6 +5138,10 @@ _dhdsdio_download_firmware(struct dhd_bus *bus)
goto err;
}
+ /* EXAMPLE: nvram_array */
+ /* If a valid nvram_arry is specified as above, it can be passed down to dongle */
+ /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
+
/* External nvram takes precedence if specified */
if (dhdsdio_download_nvram(bus)) {
DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
@@ -5114,3 +5195,9 @@ dhd_bus_txq(struct dhd_bus *bus)
{
return &bus->txq;
}
+
+uint
+dhd_bus_hdrlen(struct dhd_bus *bus)
+{
+ return SDPCM_HDRLEN;
+}
diff --git a/src/include/bcmdefs.h b/src/include/bcmdefs.h
index 5ea3f7a..5c9dde9 100644
--- a/src/include/bcmdefs.h
+++ b/src/include/bcmdefs.h
@@ -3,25 +3,23 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
* $Id: bcmdefs.h,v 13.38.4.10.2.7 2008/07/01 00:53:19 Exp $
*/
diff --git a/src/include/bcmsdbus.h b/src/include/bcmsdbus.h
index 4c6ff9b..c649ba3 100644
--- a/src/include/bcmsdbus.h
+++ b/src/include/bcmsdbus.h
@@ -25,7 +25,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdbus.h,v 13.11.14.2.16.1 2008/12/17 05:02:20 Exp $
+ * $Id: bcmsdbus.h,v 13.11.14.2.16.2 2009/03/19 04:07:42 Exp $
*/
/*
@@ -79,6 +79,11 @@ extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
extern bool sdioh_interrupt_pending(sdioh_info_t *si);
#endif
+#ifdef BCMLXSDMMC
+extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
+extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
+#endif /* BCMLXSDMMC */
+
/* read or write one byte using cmd52 */
extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte);
diff --git a/src/include/bcmsdh.h b/src/include/bcmsdh.h
index 4165d71..c8f04b4 100644
--- a/src/include/bcmsdh.h
+++ b/src/include/bcmsdh.h
@@ -23,7 +23,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh.h,v 13.35.14.7.16.2 2008/12/17 04:33:18 Exp $
+ * $Id: bcmsdh.h,v 13.35.14.7.16.3 2009/03/19 04:07:42 Exp $
*/
#ifndef _bcmsdh_h_
@@ -69,6 +69,11 @@ extern int bcmsdh_intr_dereg(void *sdh);
extern bool bcmsdh_intr_pending(void *sdh);
#endif
+#ifdef BCMLXSDMMC
+extern int bcmsdh_claim_host_and_lock(void *sdh);
+extern int bcmsdh_release_host_and_unlock(void *sdh);
+#endif /* BCMLXSDMMC */
+
/* Register a callback to be called if and when bcmsdh detects
* device removal. No-op in the case of non-removable/hardwired devices.
*/
diff --git a/src/include/bcmsdh_sdmmc.h b/src/include/bcmsdh_sdmmc.h
index 2189239..e900971 100644
--- a/src/include/bcmsdh_sdmmc.h
+++ b/src/include/bcmsdh_sdmmc.h
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: bcmsdh_sdmmc.h,v 13.1.2.2 2008/09/03 00:22:37 Exp $
+ * $Id: bcmsdh_sdmmc.h,v 13.1.2.2.6.1 2009/03/19 04:07:42 Exp $
*/
#ifndef __BCMSDH_SDMMC_H__
@@ -116,6 +116,7 @@ extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
typedef struct _BCMSDH_SDMMC_INSTANCE {
sdioh_info_t *sd;
struct sdio_func *func[3];
-}BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
+ uint32 host_claimed;
+} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
#endif /* __BCMSDH_SDMMC_H__ */
diff --git a/src/include/epivers.h b/src/include/epivers.h
index b4a101e..1298982 100644
--- a/src/include/epivers.h
+++ b/src/include/epivers.h
@@ -1,25 +1,23 @@
/*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
* $Id: epivers.h.in,v 13.25 2005/10/28 18:35:33 Exp $
*
@@ -33,18 +31,18 @@
#define EPI_MINOR_VERSION 217
-#define EPI_RC_NUMBER 12
+#define EPI_RC_NUMBER 24
#define EPI_INCREMENTAL_NUMBER 0
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 217, 12, 0
+#define EPI_VERSION 4, 217, 24, 0
-#define EPI_VERSION_NUM 0x04d90c00
+#define EPI_VERSION_NUM 0x04d91800
-#define EPI_VERSION_STR "4.217.12.0"
-#define EPI_ROUTER_VERSION_STR "4.217.12.0"
+#define EPI_VERSION_STR "4.217.24.0"
+#define EPI_ROUTER_VERSION_STR "4.217.24.0"
#endif
diff --git a/src/include/linuxver.h b/src/include/linuxver.h
index bea6416..9883e6c 100644
--- a/src/include/linuxver.h
+++ b/src/include/linuxver.h
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: linuxver.h,v 13.38.8.1.22.1 2009/01/18 00:25:30 Exp $
+ * $Id: linuxver.h,v 13.38.8.1.22.2 2009/03/19 04:05:38 Exp $
*/
@@ -430,7 +430,7 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer)
{ \
struct task_struct *tsk; \
tsk = find_task_by_vpid(pid); \
- send_sig(sig, tsk, 1); \
+ if (tsk) send_sig(sig, tsk, 1); \
}
#else
#define KILL_PROC(pid, sig) \
diff --git a/src/include/proto/802.11.h b/src/include/proto/802.11.h
index 270601f..4d3562b 100644
--- a/src/include/proto/802.11.h
+++ b/src/include/proto/802.11.h
@@ -1,29 +1,27 @@
/*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
* Fundamental types and constants relating to 802.11
*
- * $Id: 802.11.h,v 9.219.4.1.4.5.20.3 2008/12/07 21:15:40 Exp $
+ * $Id: 802.11.h,v 9.219.4.1.4.5.20.6 2009/03/05 21:13:45 Exp $
*/
@@ -1008,6 +1006,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
#define DOT11_ACTION_CAT_BLOCKACK 3
#define DOT11_ACTION_CAT_PUBLIC 4
#define DOT11_ACTION_CAT_HT 7
+#define DOT11_ACTION_CAT_VS 127
#define DOT11_ACTION_NOTIFICATION 0x11
#define DOT11_ACTION_ID_M_REQ 0
@@ -1364,6 +1363,7 @@ typedef struct vndr_ie vndr_ie_t;
#define VNDR_IE_MAX_LEN 256
+
#define WPA_VERSION 1
#define WPA_OUI "\x00\x50\xF2"
diff --git a/src/include/proto/bcmevent.h b/src/include/proto/bcmevent.h
index 054b797..13d8210 100644
--- a/src/include/proto/bcmevent.h
+++ b/src/include/proto/bcmevent.h
@@ -3,30 +3,28 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
*
* Dependencies: proto/bcmeth.h
*
- * $Id: bcmevent.h,v 9.34.4.1.2.3.2.4 2008/12/11 00:12:47 Exp $
+ * $Id: bcmevent.h,v 9.34.4.1.2.3.2.5 2009/02/20 18:31:41 Exp $
*
*/
@@ -149,6 +147,7 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
#define WLC_E_STATUS_SUPPRESS 12
#define WLC_E_STATUS_NOCHANS 13
#define WLC_E_STATUS_CCXFASTRM 14
+#define WLC_E_STATUS_CS_ABORT 15
#define WLC_E_REASON_INITIAL_ASSOC 0
diff --git a/src/include/proto/eapol.h b/src/include/proto/eapol.h
index 6226191..bbc4172 100644
--- a/src/include/proto/eapol.h
+++ b/src/include/proto/eapol.h
@@ -7,7 +7,7 @@
*
* Copyright (C) 2002 Broadcom Corporation
*
- * $Id: eapol.h,v 9.18.260.1.2.1.20.3 2008/12/31 00:37:15 Exp $
+ * $Id: eapol.h,v 9.18.260.1.2.1.20.4 2009/02/03 01:26:12 Exp $
*/
#ifndef _eapol_h_
@@ -95,7 +95,7 @@ typedef BWL_PRE_PACKED_STRUCT struct {
unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */
unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */
unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */
- unsigned char rsc[DOT11_WPA_KEY_RSC_LEN]; /* Key RSC */
+ unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */
unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */
unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */
unsigned short data_len; /* Key Data Length */
diff --git a/src/include/sbchipc.h b/src/include/sbchipc.h
index 48a076b..f6456b9 100644
--- a/src/include/sbchipc.h
+++ b/src/include/sbchipc.h
@@ -5,29 +5,27 @@
* jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer,
* gpio interface, extbus, and support for serial and parallel flashes.
*
- * $Id: sbchipc.h,v 13.103.2.5.4.7 2008/10/08 21:58:33 Exp $
+ * $Id: sbchipc.h,v 13.103.2.5.4.7.4.1 2009/01/21 23:56:57 Exp $
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*/
@@ -707,6 +705,9 @@ typedef volatile struct {
#define PST_INTPEND 0x0040
#define PST_SBCLKST 0x0030
+#define PST_SBCLKST_ILP 0x0010
+#define PST_SBCLKST_ALP 0x0020
+#define PST_SBCLKST_HT 0x0030
#define PST_ALPAVAIL 0x0008
#define PST_HTAVAIL 0x0004
#define PST_RESINIT 0x0003
diff --git a/src/include/wlioctl.h b/src/include/wlioctl.h
index 3a7e4a0..9f9dd04 100644
--- a/src/include/wlioctl.h
+++ b/src/include/wlioctl.h
@@ -6,27 +6,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wlioctl.h,v 1.601.4.15.2.15.2.6 2009/01/13 01:12:41 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.15.2.10 2009/03/10 18:49:43 Exp $
*/
@@ -42,6 +40,17 @@
+#ifdef WIFI_ACT_FRAME
+typedef struct wl_action_frame {
+ struct ether_addr da;
+ uint16 len;
+ uint8 data[1040];
+} wl_action_frame_t;
+
+#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame)
+
+#endif
+
#define BWL_DEFAULT_PACKING
@@ -112,6 +121,39 @@ typedef struct wlc_ssid {
#define WL_BSSTYPE_INDEP 0
#define WL_BSSTYPE_ANY 2
+typedef struct wl_scan_params {
+ wlc_ssid_t ssid;
+ struct ether_addr bssid;
+ int8 bss_type;
+ int8 scan_type;
+ int32 nprobes;
+ int32 active_time;
+ int32 passive_time;
+ int32 home_time;
+ int32 channel_num;
+ uint16 channel_list[1];
+} wl_scan_params_t;
+
+#define WL_SCAN_PARAMS_FIXED_SIZE 64
+
+
+#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff
+#define WL_SCAN_PARAMS_NSSID_SHIFT 16
+
+#define WL_SCAN_ACTION_START 1
+#define WL_SCAN_ACTION_CONTINUE 2
+
+#define ISCAN_REQ_VERSION 1
+
+
+typedef struct wl_iscan_params {
+ uint32 version;
+ uint16 action;
+ uint16 scan_duration;
+ wl_scan_params_t params;
+} wl_iscan_params_t;
+
+#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t))
typedef struct wl_scan_results {
uint32 buflen;
@@ -152,6 +194,25 @@ typedef struct wl_uint32_list {
} wl_uint32_list_t;
+typedef struct wl_assoc_params {
+ struct ether_addr bssid;
+ int32 chanspec_num;
+ chanspec_t chanspec_list[1];
+} wl_assoc_params_t;
+#define WL_ASSOC_PARAMS_FIXED_SIZE (sizeof(wl_assoc_params_t) - sizeof(chanspec_t))
+
+
+typedef wl_assoc_params_t wl_reassoc_params_t;
+#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE
+
+
+typedef struct wl_join_params {
+ wlc_ssid_t ssid;
+ wl_assoc_params_t params;
+} wl_join_params_t;
+#define WL_JOIN_PARAMS_FIXED_SIZE (sizeof(wl_join_params_t) - sizeof(chanspec_t))
+
+
typedef enum sup_auth_status {
WLC_SUP_DISCONNECTED = 0,
@@ -1156,8 +1217,7 @@ typedef struct {
enum {
PFN_LIST_ORDER,
- PFN_RSSI,
- PFN_AUTO_CONNECT
+ PFN_RSSI
};
enum {
diff --git a/src/wl/sys/wl_iw.c b/src/wl/sys/wl_iw.c
index beffa24..51d5289 100644
--- a/src/wl/sys/wl_iw.c
+++ b/src/wl/sys/wl_iw.c
@@ -3,27 +3,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.c,v 1.51.4.9.2.8.6.3 2009/01/18 00:30:44 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.8.6.33 2009/03/12 17:56:57 Exp $
*/
@@ -38,6 +36,7 @@
#include <linux/if_arp.h>
#include <asm/uaccess.h>
+#include <dhdioctl.h>
typedef void wlc_info_t;
typedef void wl_info_t;
@@ -52,8 +51,20 @@ typedef const struct si_pub si_t;
#include <wl_iw.h>
+#include <linux/rtnetlink.h>
+
+#define WL_IW_USE_ISCAN 1
+
+#define WL_IW_IOCTL_CALL(func_call) \
+ do { \
+ func_call; \
+ } while (0)
+
extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
uint32 reason, char* stringBuf, uint buflen);
+static int dev_dhd_ioctl(struct net_device *dev, int cmd, void *arg, int len);
+extern void sdioh_start(int);
+extern void sdioh_stop(void);
uint wl_msg_level = WL_ERROR_VAL;
@@ -88,6 +99,79 @@ extern int dhd_wait_pend8021x(struct net_device *dev);
#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
#endif
+static void *g_scan = NULL;
+#define G_SCAN_RESULTS 8*1024
+#define WE_ADD_EVENT_FIX 0x80
+static uint g_scan_specified_ssid;
+
+
+static wlc_ssid_t g_ssid;
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
+#define DAEMONIZE(a) daemonize(a); \
+ allow_signal(SIGKILL); \
+ allow_signal(SIGTERM);
+#else
+#define RAISE_RX_SOFTIRQ() \
+ cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ)
+#define DAEMONIZE(a) daemonize(); \
+ do { if (a) \
+ strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \
+ } while (0);
+#endif
+
+#if defined(WL_IW_USE_ISCAN)
+
+#define ISCAN_STATE_IDLE 0
+#define ISCAN_STATE_SCANING 1
+
+
+#define WLC_IW_ISCAN_MAXLEN 2048
+typedef struct iscan_buf {
+ struct iscan_buf * next;
+ char iscan_buf[WLC_IW_ISCAN_MAXLEN];
+} iscan_buf_t;
+
+typedef struct iscan_info {
+ struct net_device *dev;
+ struct timer_list timer;
+ uint32 timer_ms;
+ uint32 timer_on;
+ int iscan_state;
+ iscan_buf_t * list_hdr;
+ iscan_buf_t * list_cur;
+
+
+ long sysioc_pid;
+ struct semaphore sysioc_sem;
+ struct completion sysioc_exited;
+
+ uint32 scan_flag;
+
+ char ioctlbuf[WLC_IOCTL_SMLEN];
+} iscan_info_t;
+iscan_info_t *g_iscan = NULL;
+static void wl_iw_timerfunc(ulong data);
+static void wl_iw_event_mask(struct net_device *dev, int set);
+static int
+wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action);
+#endif
+static int
+wl_iw_set_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+);
+static int
+wl_iw_get_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+);
+
static void swap_key_from_BE(
wl_wsec_key_t *key
)
@@ -146,6 +230,39 @@ dev_wlc_ioctl(
return ret;
}
+static int
+dev_dhd_ioctl(
+ struct net_device *dev,
+ int cmd,
+ void *arg,
+ int len
+)
+{
+ struct ifreq ifr;
+ dhd_ioctl_t ioc;
+ mm_segment_t fs;
+ int ret;
+
+ memset(&ioc, 0, sizeof(ioc));
+ ioc.cmd = cmd;
+ ioc.buf = arg;
+ ioc.len = len;
+ ioc.driver = DHD_IOCTL_MAGIC;
+
+ strcpy(ifr.ifr_name, dev->name);
+ ifr.ifr_data = (caddr_t) &ioc;
+
+
+ dev_open(dev);
+
+ fs = get_fs();
+ set_fs(get_ds());
+ ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+ set_fs(fs);
+
+ return ret;
+}
+
static int
@@ -164,6 +281,43 @@ dev_wlc_intvar_set(
return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
}
+#if defined(WL_IW_USE_ISCAN)
+static int
+dev_iw_iovar_setbuf(
+ struct net_device *dev,
+ char *iovar,
+ void *param,
+ int paramlen,
+ void *bufptr,
+ int buflen)
+{
+ int iolen;
+
+ iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ ASSERT(iolen);
+
+ return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen));
+}
+
+static int
+dev_iw_iovar_getbuf(
+ struct net_device *dev,
+ char *iovar,
+ void *param,
+ int paramlen,
+ void *bufptr,
+ int buflen)
+{
+ int iolen;
+
+ iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
+ ASSERT(iolen);
+
+ return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen));
+}
+#endif
+
+
#if WIRELESS_EXT > 17
static int
dev_wlc_bufvar_set(
@@ -229,6 +383,300 @@ dev_wlc_intvar_get(
}
+#if WIRELESS_EXT > 12
+static int
+wl_iw_set_active_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int as = 0;
+ int error = 0;
+ char *p = extra;
+
+#if defined(WL_IW_USE_ISCAN)
+ if (g_iscan->iscan_state == ISCAN_STATE_IDLE)
+#endif
+ error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
+#if defined(WL_IW_USE_ISCAN)
+ else
+ g_iscan->scan_flag = as;
+#endif
+ p += snprintf(p, MAX_WX_STRING, "OK");
+
+ wrqu->data.length = p - extra + 1;
+ return error;
+}
+
+static int
+wl_iw_set_passive_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int ps = 1;
+ int error = 0;
+ char *p = extra;
+
+#if defined(WL_IW_USE_ISCAN)
+ if (g_iscan->iscan_state == ISCAN_STATE_IDLE) {
+#endif
+
+
+ if (g_scan_specified_ssid == 0) {
+ error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &ps, sizeof(ps));
+ }
+#if defined(WL_IW_USE_ISCAN)
+ }
+ else
+ g_iscan->scan_flag = ps;
+#endif
+
+ p += snprintf(p, MAX_WX_STRING, "OK");
+
+ wrqu->data.length = p - extra + 1;
+ return error;
+}
+
+static int
+wl_iw_get_macaddr(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int error;
+ char buf[128];
+ struct ether_addr *id;
+ char *p = extra;
+
+
+ strcpy(buf, "cur_etheraddr");
+ error = dev_wlc_ioctl(dev, WLC_GET_VAR, buf, sizeof(buf));
+ id = (struct ether_addr *) buf;
+ p += snprintf(p, MAX_WX_STRING, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+ id->octet[0], id->octet[1], id->octet[2],
+ id->octet[3], id->octet[4], id->octet[5]);
+ wrqu->data.length = p - extra + 1;
+
+ return error;
+}
+
+
+int
+wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
+{
+ int i, c;
+ char *p = ssid_buf;
+
+ if (ssid_len > 32) ssid_len = 32;
+
+ for (i = 0; i < ssid_len; i++) {
+ c = (int)ssid[i];
+ if (c == '\\') {
+ *p++ = '\\';
+ *p++ = '\\';
+ } else if (isprint((uchar)c)) {
+ *p++ = (char)c;
+ } else {
+ p += sprintf(p, "\\x%02X", c);
+ }
+ }
+ *p = '\0';
+
+ return p - ssid_buf;
+}
+
+static int
+wl_iw_get_link_speed(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int link_speed;
+ int error;
+ char *p = extra;
+
+ error = dev_wlc_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed));
+
+ link_speed *= 500000;
+
+ p += snprintf(p, MAX_WX_STRING, "LinkSpeed %d", link_speed/1000000);
+
+ wrqu->data.length = p - extra + 1;
+
+ return error;
+}
+
+static int
+wl_iw_get_rssi(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ int rssi;
+ int error;
+ wlc_ssid_t ssid;
+ char *p = extra;
+ char ssidbuf[SSID_FMT_BUF_LEN];
+ scb_val_t scb_val;
+
+ scb_val.val = 0;
+ error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
+
+ rssi = dtoh32(scb_val.val);
+ error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid));
+
+ 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;
+
+ return error;
+}
+
+struct wl_ctrl {
+ struct timer_list *timer;
+ struct net_device *dev;
+ long sysioc_pid;
+ struct semaphore sysioc_sem;
+ struct completion sysioc_exited;
+};
+
+int g_onoff = 0;
+
+static int
+_wl_control_sysioc_thread(void *data)
+{
+ struct wl_ctrl *wl_ctl = (struct wl_ctrl *)data;
+ char buffer[20];
+ int len, onoff = 1;
+
+ DAEMONIZE("wlcontrol_sysioc");
+
+ WL_TRACE(("%s Entered\n", __FUNCTION__));
+
+ while (down_interruptible(&wl_ctl->sysioc_sem) == 0) {
+
+ WL_TRACE(("%s Turning off wifi dev = 0x%x\n", __FUNCTION__,
+ (unsigned int)wl_ctl->dev));
+
+ len = strlen("devreset") + 1;
+ strcpy(buffer, "devreset");
+ memcpy(&buffer[len], &onoff, sizeof(onoff));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+
+ dev_dhd_ioctl(wl_ctl->dev, DHD_SET_VAR, buffer, len + sizeof(onoff));
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+
+
+
+
+
+
+
+ g_onoff = 1;
+
+ break;
+ }
+ WL_TRACE(("%s Exited\n", __FUNCTION__));
+
+ complete_and_exit(&wl_ctl->sysioc_exited, 0);
+ KILL_PROC(wl_ctl->sysioc_pid, SIGTERM);
+}
+
+static void
+wl_iw_stop_timerfunc(ulong data)
+{
+ struct wl_ctrl * wl_ctl = (struct wl_ctrl *)data;
+
+ WL_TRACE(("%s\n", __FUNCTION__));
+
+ del_timer(wl_ctl->timer);
+
+ up(&wl_ctl->sysioc_sem);
+}
+
+static int
+wl_iw_control_wl(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra,
+ int onoff
+)
+{
+ char buffer[20];
+ static struct timer_list timer;
+ int len, ret = 0;
+ static struct wl_ctrl wl_ctl;
+
+ WL_TRACE(("%s -- onoff = %d, dev = 0x%x\n", __FUNCTION__, onoff, (unsigned int)dev));
+
+ if (onoff)
+ {
+
+
+ wl_ctl.timer = &timer;
+ wl_ctl.dev = dev;
+ sema_init(&wl_ctl.sysioc_sem, 0);
+ init_completion(&wl_ctl.sysioc_exited);
+
+
+ wl_ctl.sysioc_pid = kernel_thread(_wl_control_sysioc_thread, &wl_ctl, 0);
+
+ if (wl_ctl.sysioc_pid < 0)
+ return -ENOMEM;
+
+ timer.data = (ulong)&wl_ctl;
+ timer.function = wl_iw_stop_timerfunc;
+ init_timer(&timer);
+ timer.expires = jiffies + 2000 * HZ / 1000;
+ add_timer(&timer);
+ }
+ else
+ {
+
+
+
+
+
+
+
+ len = strlen("devreset") + 1;
+ strcpy(buffer, "devreset");
+ memcpy(&buffer[len], &onoff, sizeof(onoff));
+
+ ret = dev_dhd_ioctl(dev, DHD_SET_VAR, buffer, len + sizeof(onoff));
+
+
+
+
+ }
+
+ return ret;
+}
+#endif
+
#if WIRELESS_EXT < 13
struct iw_request_info
{
@@ -628,6 +1076,7 @@ wl_iw_set_wap(
)
{
int error = -EINVAL;
+ wl_join_params_t join_params;
WL_TRACE(("%s: SIOCSIWAP\n", dev->name));
@@ -644,13 +1093,22 @@ wl_iw_set_wap(
dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
return 0;
}
+
+
-
- if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) {
+ memset(&join_params, 0, sizeof(join_params));
+
+ memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
+ join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
+ memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN);
+
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, sizeof(join_params)))) {
WL_ERROR(("Invalid ioctl data.\n"));
return error;
}
+
+ memset(&g_ssid, 0, sizeof(g_ssid));
return 0;
}
@@ -728,6 +1186,7 @@ wl_iw_get_aplist(
struct iw_quality qual[IW_MAX_AP];
wl_bss_info_t *bi = NULL;
int error, i;
+ uint buflen = dwrq->length;
WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
@@ -735,12 +1194,12 @@ wl_iw_get_aplist(
return -EINVAL;
- list = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+ list = kmalloc(buflen, GFP_KERNEL);
if (!list)
return -ENOMEM;
- memset(list, 0, WLC_IOCTL_MAXLEN);
- list->buflen = htod32(WLC_IOCTL_MAXLEN);
- if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, WLC_IOCTL_MAXLEN))) {
+ memset(list, 0, buflen);
+ list->buflen = htod32(buflen);
+ if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) {
WL_ERROR(("%d: Scan results error %d\n", __LINE__, error));
kfree(list);
return error;
@@ -753,7 +1212,7 @@ wl_iw_get_aplist(
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;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
- WLC_IOCTL_MAXLEN));
+ buflen));
if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
@@ -787,12 +1246,298 @@ wl_iw_get_aplist(
return 0;
}
-#if WIRELESS_EXT > 13
+#ifdef WL_IW_USE_ISCAN
+static int
+wl_iw_iscan_get_aplist(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_scan_results_t *list;
+ iscan_buf_t * buf;
+ iscan_info_t *iscan = g_iscan;
+
+ struct sockaddr *addr = (struct sockaddr *) extra;
+ struct iw_quality qual[IW_MAX_AP];
+ wl_bss_info_t *bi = NULL;
+ int i;
+
+ WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
+
+ if (!extra)
+ return -EINVAL;
+
+ if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ return wl_iw_get_aplist(dev, info, dwrq, extra);
+ }
+
+ buf = iscan->list_hdr;
+
+ while (buf) {
+ list = &((wl_iscan_results_t*)buf->iscan_buf)->results;
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ bi = NULL;
+ 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;
+ ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
+ WLC_IW_ISCAN_MAXLEN));
+
+
+ if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+ continue;
+
+
+ memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ addr[dwrq->length].sa_family = ARPHRD_ETHER;
+ qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
+ qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+ qual[dwrq->length].noise = 0x100 + bi->phy_noise;
+
+
+#if WIRELESS_EXT > 18
+ qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+#else
+ qual[dwrq->length].updated = 7;
+#endif
+
+ dwrq->length++;
+ }
+ buf = buf->next;
+ }
+ if (dwrq->length) {
+ memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length);
+
+ dwrq->flags = 1;
+ }
+
+ return 0;
+}
+
+static int
+wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
+{
+ int err = 0;
+
+ memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
+ params->bss_type = DOT11_BSSTYPE_ANY;
+ params->scan_type = -1;
+ params->nprobes = -1;
+ params->active_time = -1;
+ params->passive_time = -1;
+ params->home_time = -1;
+ params->channel_num = 0;
+
+ params->nprobes = htod32(params->nprobes);
+ params->active_time = htod32(params->active_time);
+ params->passive_time = htod32(params->passive_time);
+ params->home_time = htod32(params->home_time);
+ if (ssid && ssid->SSID_len)
+ memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
+
+ return err;
+}
+
+static int
+wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action)
+{
+ int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
+ wl_iscan_params_t *params;
+ int err = 0;
+
+ if (ssid && ssid->SSID_len) {
+ params_size += sizeof(wlc_ssid_t);
+ }
+ params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL);
+ if (params == NULL) {
+ return -ENOMEM;
+ }
+ memset(params, 0, params_size);
+ ASSERT(params_size < WLC_IOCTL_SMLEN);
+
+ err = wl_iw_iscan_prep(&params->params, ssid);
+
+ if (!err) {
+ params->version = htod32(ISCAN_REQ_VERSION);
+ params->action = htod16(action);
+ params->scan_duration = htod16(0);
+
+
+ (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+ iscan->ioctlbuf, WLC_IOCTL_SMLEN);
+ }
+
+ kfree(params);
+ return err;
+}
+
+static void
+wl_iw_timerfunc(ulong data)
+{
+ iscan_info_t *iscan = (iscan_info_t *)data;
+ iscan->timer_on = 0;
+ if (iscan->iscan_state != ISCAN_STATE_IDLE) {
+ WL_TRACE(("timer trigger\n"));
+ up(&iscan->sysioc_sem);
+ }
+}
+static void wl_iw_event_mask(struct net_device *dev, int set)
+{
+ char eventmask[WL_EVENTING_MASK_LEN];
+ char iovbuf[WL_EVENTING_MASK_LEN + 12];
+
+ dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
+ bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
+ if (set)
+ setbit(eventmask, WLC_E_SCAN_COMPLETE);
+ else
+ clrbit(eventmask, WLC_E_SCAN_COMPLETE);
+ dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
+ iovbuf, sizeof(iovbuf));
+
+}
+
+static uint32
+wl_iw_iscan_get(iscan_info_t *iscan)
+{
+ iscan_buf_t * buf;
+ iscan_buf_t * ptr;
+ wl_iscan_results_t * list_buf;
+ wl_iscan_results_t list;
+ wl_scan_results_t *results;
+ uint32 status;
+
+
+ if (iscan->list_cur) {
+ buf = iscan->list_cur;
+ iscan->list_cur = buf->next;
+ }
+ else {
+ buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL);
+ if (!buf)
+ return WL_SCAN_RESULTS_ABORTED;
+ buf->next = NULL;
+ if (!iscan->list_hdr)
+ iscan->list_hdr = buf;
+ else {
+ ptr = iscan->list_hdr;
+ while (ptr->next) {
+ ptr = ptr->next;
+ }
+ ptr->next = buf;
+ }
+ }
+ memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN);
+ list_buf = (wl_iscan_results_t*)buf->iscan_buf;
+ results = &list_buf->results;
+ results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
+ results->version = 0;
+ results->count = 0;
+
+ memset(&list, 0, sizeof(list));
+ list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+ (void) dev_iw_iovar_getbuf(
+ iscan->dev,
+ "iscanresults",
+ &list,
+ WL_ISCAN_RESULTS_FIXED_SIZE,
+ buf->iscan_buf,
+ WLC_IW_ISCAN_MAXLEN);
+ results->buflen = dtoh32(results->buflen);
+ results->version = dtoh32(results->version);
+ results->count = dtoh32(results->count);
+ WL_TRACE(("results->count = %d\n", results->count));
+
+ WL_TRACE(("results->buflen = %d\n", results->buflen));
+ status = dtoh32(list_buf->status);
+ return status;
+}
+
+static int
+_iscan_sysioc_thread(void *data)
+{
+ uint32 status;
+ iscan_info_t *iscan = (iscan_info_t *)data;
+
+ DAEMONIZE("iscan_sysioc");
+
+ status = WL_SCAN_RESULTS_PARTIAL;
+ while (down_interruptible(&iscan->sysioc_sem) == 0) {
+ if (iscan->timer_on) {
+ del_timer(&iscan->timer);
+ iscan->timer_on = 0;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+ status = wl_iw_iscan_get(iscan);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+
+ switch (status) {
+ case WL_SCAN_RESULTS_PARTIAL:
+ WL_TRACE(("iscanresults incomplete\n"));
+#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
+
+ iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000;
+ add_timer(&iscan->timer);
+ iscan->timer_on = 1;
+ break;
+ case WL_SCAN_RESULTS_SUCCESS:
+ WL_TRACE(("iscanresults complete\n"));
+ iscan->iscan_state = ISCAN_STATE_IDLE;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+ wl_iw_event_mask(iscan->dev, 0);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+ break;
+ case WL_SCAN_RESULTS_PENDING:
+ WL_TRACE(("iscanresults pending\n"));
+
+ iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000;
+ add_timer(&iscan->timer);
+ iscan->timer_on = 1;
+ break;
+ case WL_SCAN_RESULTS_ABORTED:
+ WL_TRACE(("iscanresults aborted\n"));
+ iscan->iscan_state = ISCAN_STATE_IDLE;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_lock();
+#endif
+ wl_iw_event_mask(iscan->dev, 0);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ rtnl_unlock();
+#endif
+ break;
+ default:
+ WL_TRACE(("iscanresults returned unknown status %d\n", status));
+ break;
+ }
+ }
+ complete_and_exit(&iscan->sysioc_exited, 0);
+}
+#endif
+
static int
wl_iw_set_scan(
struct net_device *dev,
struct iw_request_info *info,
- struct iw_param *vwrq,
+ union iwreq_data *wrqu,
char *extra
)
{
@@ -801,14 +1546,83 @@ wl_iw_set_scan(
WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
- ssid.SSID_len = 0;
+ 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) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+ 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;
+ WL_TRACE(("Specific scan ssid=%s len=%d\n", ssid.SSID, ssid.SSID_len));
+ }
+ }
+#endif
(void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid));
return 0;
}
+#ifdef WL_IW_USE_ISCAN
+static int
+wl_iw_iscan_set_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra
+)
+{
+ wlc_ssid_t ssid;
+ iscan_info_t *iscan = g_iscan;
+
+ WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name));
+
+
+ if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ return wl_iw_set_scan(dev, info, wrqu, extra);
+ }
+ if (iscan->iscan_state == ISCAN_STATE_SCANING) {
+ return 0;
+ }
+
+
+ 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;
+ 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;
+ dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as));
+ return wl_iw_set_scan(dev, info, wrqu, extra);
+ }
+ }
+#endif
+
+ iscan->list_cur = iscan->list_hdr;
+ iscan->iscan_state = ISCAN_STATE_SCANING;
+ dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag));
+ wl_iw_event_mask(dev, 1);
+ wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
+ iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000;
+ add_timer(&iscan->timer);
+ iscan->timer_on = 1;
+
+ return 0;
+}
+#endif
+
#if WIRELESS_EXT > 17
static bool
ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len)
@@ -855,6 +1669,137 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
}
#endif
+static uint
+wl_iw_get_scan_prep(
+ wl_scan_results_t *list,
+ struct iw_request_info *info,
+ char *extra,
+ __u16 max_size)
+{
+ int i, j;
+ struct iw_event iwe;
+ wl_bss_info_t *bi = NULL;
+ char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
+ uint ret = 0;
+
+ ASSERT(list);
+
+
+
+ for (i = 0; i < list->count && i < IW_MAX_AP; i++)
+ {
+ ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
+
+
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
+
+ iwe.u.data.length = dtoh32(bi->SSID_len);
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
+
+
+ if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+ iwe.cmd = SIOCGIWMODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+ iwe.u.mode = IW_MODE_INFRA;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
+ }
+
+
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
+ CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ?
+ WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
+ iwe.u.freq.e = 6;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
+
+
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
+ iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+ iwe.u.qual.noise = 0x100 + bi->phy_noise;
+ event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
+
+#if WIRELESS_EXT > 17
+
+ if (bi->ie_length) {
+
+ bcm_tlv_t *ie;
+ uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ int ptr_len = bi->ie_length;
+#ifdef BCMWPA2
+ if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ }
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+#endif
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+
+ if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
+ break;
+ }
+ }
+
+ ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t);
+ ptr_len = bi->ie_length;
+ while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
+ if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = ie->len + 2;
+ event = IWE_STREAM_ADD_POINT(info, event,
+ end, &iwe, (char *)ie);
+ goto done;
+ }
+ }
+ }
+done:
+#endif
+
+ iwe.cmd = SIOCGIWENCODE;
+ if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
+
+
+ if (bi->rateset.count) {
+ 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;
+ value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
+ IW_EV_PARAM_LEN);
+ }
+ event = value;
+ }
+ }
+
+ if ((ret = (event - extra)) < 0) {
+ WL_ERROR(("==> Wrong size\n"));
+ ret = 0;
+ }
+ WL_TRACE(("%s: size=%d bytes prepared\n", __FUNCTION__, event - extra));
+ return ret;
+
+}
+
static int
wl_iw_get_scan(
struct net_device *dev,
@@ -864,16 +1809,24 @@ wl_iw_get_scan(
)
{
channel_info_t ci;
- wl_scan_results_t *list;
- struct iw_event iwe;
- wl_bss_info_t *bi = NULL;
- int error, i, j;
- char *event = extra, *end = extra + IW_SCAN_MAX_DATA, *value;
+ wl_scan_results_t *list_merge;
+ wl_scan_results_t *list = (wl_scan_results_t *) g_scan;
+ int error;
+ uint buflen_from_user = dwrq->length;
+ uint len = G_SCAN_RESULTS;
+ __u16 len_ret;
+#if defined(WL_IW_USE_ISCAN)
+ iscan_info_t *iscan = g_iscan;
+ iscan_buf_t * p_buf;
+#endif
- WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name));
+ WL_TRACE(("%s: wl_iw_get_scan\n", dev->name));
+ WL_TRACE(("%d: buflen_from_user\n", buflen_from_user));
- if (!extra)
+ if (!extra) {
+ WL_TRACE(("%s: wl_iw_get_scan return -EINVAL\n", dev->name));
return -EINVAL;
+ }
if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
@@ -883,27 +1836,127 @@ wl_iw_get_scan(
return -EAGAIN;
- list = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
- if (!list)
- return -ENOMEM;
- memset(list, 0, WLC_IOCTL_MAXLEN);
- list->buflen = htod32(WLC_IOCTL_MAXLEN);
- if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, WLC_IOCTL_MAXLEN))) {
- kfree(list);
- return error;
+ if (g_scan_specified_ssid) {
+
+ list = kmalloc(len, GFP_KERNEL);
+ if (!list) {
+ WL_TRACE(("%s: wl_iw_get_scan return -ENOMEM\n", dev->name));
+ return -ENOMEM;
+ }
+ }
+
+ 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));
+ dwrq->length = len;
+ if (g_scan_specified_ssid)
+ kfree(list);
+ return 0;
}
list->buflen = dtoh32(list->buflen);
list->version = dtoh32(list->version);
list->count = dtoh32(list->count);
- ASSERT(list->version == WL_BSS_INFO_VERSION);
+
+ if (g_scan_specified_ssid) {
+ WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count));
+ len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
+ kfree(list);
+
+#if defined(WL_IW_USE_ISCAN)
+ 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));
+ if (list_merge->count > 0)
+ len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info,
+ extra+len_ret, buflen_from_user -len_ret);
+ p_buf = p_buf->next;
+ }
+#else
+ list_merge = (wl_scan_results_t *) g_scan;
+ WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, 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);
+#endif
+ }
+ else {
+ list = (wl_scan_results_t *) g_scan;
+ len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user);
+ }
+
+
+ if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user)
+ len = len_ret;
+
+ dwrq->length = len;
+ dwrq->flags = 0;
+
+ WL_TRACE(("%s return to WE dwrq->length=%d bytes\n", __FUNCTION__, dwrq->length));
+ return 0;
+}
+
+#if defined(WL_IW_USE_ISCAN)
+static int
+wl_iw_iscan_get_scan(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra
+)
+{
+ wl_scan_results_t *list;
+ struct iw_event iwe;
+ wl_bss_info_t *bi = NULL;
+ int ii, j;
+ int apcnt;
+ char *event = extra, *end = extra + dwrq->length, *value;
+ iscan_info_t *iscan = g_iscan;
+ iscan_buf_t * p_buf;
+
+ WL_TRACE(("%s: SIOCGIWSCAN GET\n", dev->name));
+
+ if (!extra) {
+ WL_TRACE(("%s: SIOCGIWSCAN GET bad parameter\n", dev->name));
+ return -EINVAL;
+ }
+
+
+ if ((!iscan) || (iscan->sysioc_pid < 0)) {
+ return wl_iw_get_scan(dev, info, dwrq, extra);
+ }
+
+
+
+ if (g_scan_specified_ssid) {
+ return wl_iw_get_scan(dev, info, dwrq, extra);
+ }
+
+ WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name));
+ apcnt = 0;
+ p_buf = iscan->list_hdr;
+
+ while (p_buf != iscan->list_cur) {
+ list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
+
+ if (list->version != WL_BSS_INFO_VERSION) {
+ WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version));
+ }
- for (i = 0; i < list->count && i < IW_MAX_AP; i++) {
+ bi = NULL;
+ for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
- WLC_IOCTL_MAXLEN));
+ WLC_IW_ISCAN_MAXLEN));
+ if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
+ IW_EV_QUAL_LEN >= end)
+ return -E2BIG;
+
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
@@ -949,6 +2002,8 @@ wl_iw_get_scan(
int ptr_len = bi->ie_length;
#ifdef BCMWPA2
if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) {
+ if (event + ie->len + 2 >= end)
+ return -E2BIG;
iwe.cmd = IWEVGENIE;
iwe.u.data.length = ie->len + 2;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
@@ -958,6 +2013,9 @@ wl_iw_get_scan(
while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ if (event + ie->len + 2 >= end)
+ return -E2BIG;
+
iwe.cmd = IWEVGENIE;
iwe.u.data.length = ie->len + 2;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie);
@@ -969,6 +2027,8 @@ wl_iw_get_scan(
ptr_len = bi->ie_length;
while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) {
if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) {
+ if (event + ie->len + 2 >= end)
+ return -E2BIG;
iwe.cmd = IWEVGENIE;
iwe.u.data.length = ie->len + 2;
event = IWE_STREAM_ADD_POINT(info,
@@ -991,6 +2051,9 @@ done:
if (bi->rateset.count) {
+ if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
+ return -E2BIG;
+
value = event + IW_EV_LCP_LEN;
iwe.cmd = SIOCGIWRATE;
@@ -1002,12 +2065,13 @@ done:
}
event = value;
}
- }
-
- kfree(list);
+ }
+ p_buf = p_buf->next;
+ }
dwrq->length = event - extra;
dwrq->flags = 0;
+ WL_TRACE(("%s return to WE dwrq->length=%d bytes\n", __FUNCTION__, dwrq->length));
return 0;
}
@@ -1021,24 +2085,26 @@ wl_iw_set_essid(
char *extra
)
{
- wlc_ssid_t ssid;
int error;
WL_TRACE(("%s: SIOCSIWESSID\n", dev->name));
+
+ memset(&g_ssid, 0, sizeof(g_ssid));
+
if (dwrq->length && extra) {
#if WIRELESS_EXT > 20
- ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length);
+ g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length);
#else
- ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1);
+ g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length-1);
#endif
- memcpy(ssid.SSID, extra, ssid.SSID_len);
+ memcpy(g_ssid.SSID, extra, g_ssid.SSID_len);
} else {
- ssid.SSID_len = 0;
+ g_ssid.SSID_len = 0;
}
- ssid.SSID_len = htod32(ssid.SSID_len);
- if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))
+ g_ssid.SSID_len = htod32(g_ssid.SSID_len);
+ if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &g_ssid, sizeof(g_ssid))))
return error;
return 0;
@@ -1069,7 +2135,6 @@ wl_iw_get_essid(
memcpy(extra, ssid.SSID, ssid.SSID_len);
- extra[ssid.SSID_len] = '\0';
dwrq->length = ssid.SSID_len;
@@ -1831,16 +2896,20 @@ wl_iw_set_wpaauth(
if (paramval & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
- val |= WEP_ENABLED;
+ val = WEP_ENABLED;
if (paramval & IW_AUTH_CIPHER_TKIP)
- val |= TKIP_ENABLED;
+ val = TKIP_ENABLED;
if (paramval & IW_AUTH_CIPHER_CCMP)
- val |= AES_ENABLED;
+ val = AES_ENABLED;
- if (paramid == IW_AUTH_CIPHER_PAIRWISE)
- val |= iw->pwsec;
- else
+ if (paramid == IW_AUTH_CIPHER_PAIRWISE) {
+ iw->pwsec = val;
val |= iw->gwsec;
+ }
+ else {
+ iw->gwsec = val;
+ val |= iw->pwsec;
+ }
if ((error = dev_wlc_intvar_set(dev, "wsec", val)))
return error;
@@ -1876,10 +2945,12 @@ wl_iw_set_wpaauth(
case IW_AUTH_80211_AUTH_ALG:
WL_ERROR(("Setting the D11auth %d\n", paramval));
- if (paramval & IW_AUTH_ALG_OPEN_SYSTEM)
+ if (paramval == IW_AUTH_ALG_OPEN_SYSTEM)
val = 0;
- else if (paramval & IW_AUTH_ALG_SHARED_KEY)
+ else if (paramval == IW_AUTH_ALG_SHARED_KEY)
val = 1;
+ else if (paramval == (IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY))
+ val = 2;
else
error = 1;
if (!error && (error = dev_wlc_intvar_set(dev, "auth", val)))
@@ -1888,6 +2959,8 @@ wl_iw_set_wpaauth(
case IW_AUTH_WPA_ENABLED:
if (paramval == 0) {
+ iw->pwsec = 0;
+ iw->gwsec = 0;
if ((error = dev_wlc_intvar_get(dev, "wsec", &val)))
return error;
if (val & (TKIP_ENABLED | AES_ENABLED)) {
@@ -2036,6 +3109,62 @@ wl_iw_get_wpaauth(
}
#endif
+static int
+wl_iw_set_priv(
+ struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *ext
+)
+{
+ int ret = 0;
+ char * extra;
+
+ if (!(extra = kmalloc(dwrq->length, GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (copy_from_user(extra, dwrq->pointer, dwrq->length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ WL_TRACE(("%s: SIOCSIWPRIV, requst = %s ==> ",
+ dev->name, extra));
+
+
+ if (g_onoff) {
+ g_onoff = 0;
+ wl_iw_control_wl(dev, info, (union iwreq_data *)dwrq, extra, 0);
+ }
+
+ if (dwrq->length && extra) {
+ if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0)
+ ret = wl_iw_set_active_scan(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0)
+ ret = wl_iw_set_passive_scan(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, "RSSI", strlen("RSSI")) == 0)
+ ret = wl_iw_get_rssi(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, "LINKSPEED", strlen("LINKSPEED")) == 0)
+ ret = wl_iw_get_link_speed(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, "MACADDR", strlen("MACADDR")) == 0)
+ ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra);
+ else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
+ ret = wl_iw_control_wl(dev, info, (union iwreq_data *)dwrq, extra, 1);
+ }
+
+ if (extra) {
+ if (copy_to_user(dwrq->pointer, extra, dwrq->length)) {
+ kfree(extra);
+ return -EFAULT;
+ }
+
+ kfree(extra);
+ }
+ WL_TRACE(("\n"));
+
+ return ret;
+}
+
static const iw_handler wl_iw_handler[] =
{
(iw_handler) wl_iw_config_commit,
@@ -2050,7 +3179,7 @@ static const iw_handler wl_iw_handler[] =
(iw_handler) NULL,
(iw_handler) NULL,
(iw_handler) wl_iw_get_range,
- (iw_handler) NULL,
+ (iw_handler) wl_iw_set_priv,
(iw_handler) NULL,
(iw_handler) NULL,
(iw_handler) NULL,
@@ -2065,10 +3194,19 @@ static const iw_handler wl_iw_handler[] =
#else
(iw_handler) NULL,
#endif
+#if defined(WL_IW_USE_ISCAN)
+ (iw_handler) wl_iw_iscan_get_aplist,
+#else
(iw_handler) wl_iw_get_aplist,
+#endif
#if WIRELESS_EXT > 13
+#if defined(WL_IW_USE_ISCAN)
+ (iw_handler) wl_iw_iscan_set_scan,
+ (iw_handler) wl_iw_iscan_get_scan,
+#else
(iw_handler) wl_iw_set_scan,
(iw_handler) wl_iw_get_scan,
+#endif
#else
(iw_handler) NULL,
(iw_handler) NULL,
@@ -2111,14 +3249,61 @@ static const iw_handler wl_iw_handler[] =
};
#if WIRELESS_EXT > 12
+static const iw_handler wl_iw_priv_handler[] = {
+ NULL,
+ (iw_handler)wl_iw_set_active_scan,
+ NULL,
+ (iw_handler)wl_iw_get_rssi,
+ NULL,
+ (iw_handler)wl_iw_set_passive_scan,
+ NULL,
+ (iw_handler)wl_iw_get_link_speed,
+ NULL,
+ (iw_handler)wl_iw_get_macaddr
+};
+
+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,
+ "SCAN-ACTIVE"
+ },
+ {
+ WL_IW_GET_RSSI,
+ 0,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ "RSSI"
+ },
+ {
+ WL_IW_SET_PASSIVE_SCAN,
+ 0,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ "SCAN-PASSIVE"
+ },
+ {
+ WL_IW_GET_LINK_SPEED,
+ 0,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ "LINKSPEED"
+ },
+ {
+ WL_IW_GET_CURR_MACADDR,
+ 0,
+ IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
+ "Macaddr"
+ }
+};
+
const struct iw_handler_def wl_iw_handler_def =
{
.num_standard = ARRAYSIZE(wl_iw_handler),
- .num_private = 0,
- .num_private_args = 0,
.standard = (iw_handler *) wl_iw_handler,
- .private = NULL,
- .private_args = NULL,
+ .num_private = ARRAYSIZE(wl_iw_priv_handler),
+ .num_private_args = ARRAY_SIZE(wl_iw_priv_args),
+ .private = (iw_handler *)wl_iw_priv_handler,
+ .private_args = (void *) wl_iw_priv_args,
+
#if WIRELESS_EXT >= 19
get_wireless_stats: dhd_get_wireless_stats,
#endif
@@ -2172,6 +3357,11 @@ wl_iw_ioctl(
#if WIRELESS_EXT > 13
case SIOCGIWSCAN:
+#if defined(WL_IW_USE_ISCAN)
+ if (g_iscan)
+ max_tokens = wrq->u.data.length;
+ else
+#endif
max_tokens = IW_SCAN_MAX_DATA;
break;
#endif
@@ -2186,6 +3376,9 @@ wl_iw_ioctl(
max_tokens = IW_MAX_SPY;
break;
+ case SIOCSIWPRIV:
+ max_tokens = wrq->u.data.length;
+ break;
}
if (max_tokens && wrq->u.data.pointer) {
@@ -2332,34 +3525,42 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
memset(&wrqu, 0, sizeof(wrqu));
memset(extra, 0, sizeof(extra));
- memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
- wrqu.addr.sa_family = ARPHRD_ETHER;
+
switch (event_type) {
case WLC_E_TXFAIL:
cmd = IWEVTXDROP;
+ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
break;
#if WIRELESS_EXT > 14
case WLC_E_JOIN:
case WLC_E_ASSOC_IND:
case WLC_E_REASSOC_IND:
+ 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:
cmd = SIOCGIWAP;
- wrqu.data.length = strlen(extra);
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
bzero(&extra, ETHER_ADDR_LEN);
break;
case WLC_E_LINK:
case WLC_E_NDIS_LINK:
cmd = SIOCGIWAP;
- wrqu.data.length = strlen(extra);
if (!(flags & WLC_EVENT_MSG_LINK)) {
+
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
bzero(&extra, ETHER_ADDR_LEN);
}
+ else {
+
+ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ }
+ wrqu.addr.sa_family = ARPHRD_ETHER;
break;
#endif
#if WIRELESS_EXT > 17
@@ -2407,6 +3608,17 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
}
#endif
#endif
+
+#if defined(WL_IW_USE_ISCAN)
+ case WLC_E_SCAN_COMPLETE:
+ cmd = SIOCGIWSCAN;
+ WL_TRACE(("event WLC_E_SCAN_COMPLETE\n"));
+ if ((g_iscan) && (g_iscan->sysioc_pid >= 0))
+ up(&g_iscan->sysioc_sem);
+ break;
+
+#endif
+
default:
break;
@@ -2514,3 +3726,75 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
done:
return res;
}
+int wl_iw_attach(struct net_device *dev)
+{
+#if defined(WL_IW_USE_ISCAN)
+ iscan_info_t *iscan = NULL;
+
+ if (!dev)
+ return 0;
+
+ iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
+ if (!iscan)
+ return -ENOMEM;
+ memset(iscan, 0, sizeof(iscan_info_t));
+ iscan->sysioc_pid = -1;
+
+ g_iscan = iscan;
+ iscan->dev = dev;
+ iscan->iscan_state = ISCAN_STATE_IDLE;
+ g_iscan->scan_flag = 0;
+
+
+ iscan->timer_ms = 3000;
+ init_timer(&iscan->timer);
+ iscan->timer.data = (ulong)iscan;
+ iscan->timer.function = wl_iw_timerfunc;
+
+ sema_init(&iscan->sysioc_sem, 0);
+ init_completion(&iscan->sysioc_exited);
+ iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0);
+ if (iscan->sysioc_pid < 0)
+ return -ENOMEM;
+#endif
+
+ g_scan = NULL;
+
+
+ g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL);
+ if (!g_scan)
+ return -ENOMEM;
+
+ memset(g_scan, 0, G_SCAN_RESULTS);
+ g_scan_specified_ssid = 0;
+
+ return 0;
+}
+
+void wl_iw_detach(void)
+{
+#if defined(WL_IW_USE_ISCAN)
+ iscan_buf_t *buf;
+ iscan_info_t *iscan = g_iscan;
+
+ if (!iscan)
+ return;
+ if (iscan->sysioc_pid >= 0) {
+ KILL_PROC(iscan->sysioc_pid, SIGTERM);
+ wait_for_completion(&iscan->sysioc_exited);
+ }
+
+ while (iscan->list_hdr) {
+ buf = iscan->list_hdr->next;
+ kfree(iscan->list_hdr);
+ iscan->list_hdr = buf;
+ }
+ kfree(iscan);
+ g_iscan = NULL;
+#endif
+
+ if (g_scan)
+ kfree(g_scan);
+
+ g_scan = NULL;
+}
diff --git a/src/wl/sys/wl_iw.h b/src/wl/sys/wl_iw.h
index 15bb923..aff061c 100644
--- a/src/wl/sys/wl_iw.h
+++ b/src/wl/sys/wl_iw.h
@@ -3,27 +3,25 @@
*
* Copyright (C) 1999-2008, Broadcom Corporation
*
- * All Rights Reserved.
- *
- * Unless you and Broadcom execute a separate written software license
+ * Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2, available at
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the
+ * under the terms of the GNU General Public License version 2 (the “GPL”),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
+ *
* As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, regardless of the
- * license terms of these independent modules, and to copy and distribute the
- * resulting executable under terms of your choice, provided that you also meet,
- * for each linked independent module, the terms and conditions of the license
- * of that module. An independent module is a module which is not derived from
- * this software.
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
*
- * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
- * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
- * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.h,v 1.5.34.1.20.1 2009/01/18 00:30:44 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.20.4 2009/02/20 05:22:23 Exp $
*/
@@ -45,6 +43,14 @@
#define WL_IW_RSSI_VERY_GOOD -58
#define WL_IW_RSSI_EXCELLENT -57
#define WL_IW_RSSI_INVALID 0
+#define MAX_WX_STRING 80
+#define SSID_FMT_BUF_LEN ((4 * 32) + 1)
+#define isprint(c) bcm_isprint(c)
+#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1)
+#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3)
+#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5)
+#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7)
+#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9)
typedef struct wl_iw {
char nickname[IW_ESSID_MAX_SIZE];
@@ -68,6 +74,8 @@ extern const struct iw_handler_def wl_iw_handler_def;
extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
+int wl_iw_attach(struct net_device *dev);
+void wl_iw_detach(void);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \