summaryrefslogtreecommitdiffstats
path: root/bcmdhd/dhdutil/dhdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'bcmdhd/dhdutil/dhdu.c')
-rw-r--r--bcmdhd/dhdutil/dhdu.c279
1 files changed, 221 insertions, 58 deletions
diff --git a/bcmdhd/dhdutil/dhdu.c b/bcmdhd/dhdutil/dhdu.c
index c20cef0..5de111a 100644
--- a/bcmdhd/dhdutil/dhdu.c
+++ b/bcmdhd/dhdutil/dhdu.c
@@ -1,7 +1,7 @@
/*
* Common code for DHD command-line utility
*
- * Copyright (C) 1999-2011, Broadcom Corporation
+ * Copyright (C) 1999-2012, Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,7 +15,7 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: dhdu.c,v 1.88.2.19 2011-01-19 23:47:10 Exp $
+ * $Id: dhdu.c 355225 2012-09-05 22:35:10Z $
*/
/* For backwards compatibility, the absence of the define 'BWL_NO_FILESYSTEM_SUPPORT'
@@ -25,7 +25,9 @@
#define BWL_FILESYSTEM_SUPPORT
#endif
+#ifndef PROP_TXSTATUS
#define PROP_TXSTATUS
+#endif
#include <stdio.h>
#include <stdlib.h>
@@ -42,17 +44,24 @@
#include <bcmendian.h>
#include "dhdu.h"
#include "miniopt.h"
+/* #include <usbrdl.h> */
#include <proto/bcmip.h>
#define IPV4_ADDR_LEN 4
+#ifdef WLBTAMP
#include <proto/bt_amp_hci.h>
+#endif
#include <errno.h>
#include <trxhdr.h>
+/* #include "ucode_download.h" Greg */
#define stricmp strcasecmp
#define strnicmp strncasecmp
+#ifndef RDL_CHUNK
+#define RDL_CHUNK 1500
+#endif
static cmd_func_t dhd_var_void;
static cmd_func_t dhd_varint, dhd_varstr;
@@ -72,6 +81,8 @@ static cmd_func_t dhd_membytes, dhd_download, dhd_dldn,
dhd_upload, dhd_vars, dhd_idleclock, dhd_idletime;
static cmd_func_t dhd_logstamp;
+static cmd_func_t dhd_hostreorder_flows;
+
#ifdef PROP_TXSTATUS
static cmd_func_t dhd_proptxstatusenable;
static cmd_func_t dhd_proptxstatusmode;
@@ -89,8 +100,10 @@ static int file_size(char *fname);
static int read_vars(char *fname, char *buf, int buf_maxlen);
#endif
+#ifdef WLBTAMP
static cmd_func_t wl_HCI_cmd;
static cmd_func_t wl_HCI_ACL_data;
+#endif
/* dword align allocation */
static union {
@@ -167,16 +180,17 @@ cmd_t dhd_cmds[] = {
{ "memsize", dhd_varint, DHD_GET_VAR, -1,
"display size of onchip SOCRAM"},
{ "membytes", dhd_membytes, DHD_GET_VAR, DHD_SET_VAR,
- "membytes [-h | -r | -i] <address> <length> [<bytes>]\n"
+ "membytes [-h | -r | -i] <address> <length> [<data>]\n"
"\tread or write data in the dongle ram\n"
- "\t-h <bytes> is a sequence of hex digits, else a char string\n"
- "\t-r output as a raw write rather than hexdump display\n"},
+ "\t-h <data> is a sequence of hex digits rather than a char string\n"
+ "\t-r output binary to stdout rather hex\n"},
{ "download", dhd_download, -1, DHD_SET_VAR,
- "download [-a <address>] [--noreset] [--norun] <binfile> [<varsfile>]\n"
+ "download [-a <address>] [--noreset] [--norun] [--verify] <binfile> [<varsfile>]\n"
"\tdownload file to specified dongle ram address and start CPU\n"
"\toptional vars file will replace vars parsed from the CIS\n"
"\t--noreset do not reset SOCRAM core before download\n"
"\t--norun do not start dongle CPU after download\n"
+ "\t--verify do readback verify \n"
"\tdefault <address> is 0\n"},
{ "dldn", dhd_dldn, -1, DHD_SET_VAR,
"download <binfile>\n"
@@ -197,6 +211,12 @@ cmd_t dhd_cmds[] = {
"\t -c means write regardless of crc"},
{ "sleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
"enter/exit simulated host sleep (bus powerdown w/OOB wakeup)"},
+ { "kso", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+ "keep sdio on"},
+ { "devcap", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+ "brcm device capabilities"},
+ { "devsleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+ "Sleep CMD14"},
#ifdef SDTEST
{ "extloop", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
"external loopback: convert all tx data to echo test frames"},
@@ -271,12 +291,14 @@ cmd_t dhd_cmds[] = {
"Move device into or out of reset state (1/reset, or 0/operational)"},
{ "ioctl_timeout", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
"IOCTL response timeout (milliseconds)."},
+#ifdef WLBTAMP
{ "HCI_cmd", wl_HCI_cmd, -1, DHD_SET_VAR,
"carries HCI commands to the driver\n"
"\tusage: dhd HCI_cmd <command> <args>\n" },
{ "HCI_ACL_data", wl_HCI_ACL_data, -1, DHD_SET_VAR,
"carries HCI ACL data packet to the driver\n"
"\tusage: dhd HCI_ACL_data <logical link handle> <data>\n" },
+#endif
#ifdef PROP_TXSTATUS
{ "proptx", dhd_proptxstatusenable, DHD_GET_VAR, DHD_SET_VAR,
"enable/disable the proptxtstatus feature\n"
@@ -290,17 +312,12 @@ cmd_t dhd_cmds[] = {
#endif
{ "sd_uhsimode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
"g/set UHSI Mode"},
-#ifdef WLMEDIA_HTSF
- { "pktdlystatsz", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
- "Specify the size of the delay statistics buffer\n"
- "0 - disable"},
-#endif
- { "hsicsleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
- "sleep/wake HSIC bus"},
- { "changemtu", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
- "change the size of the mtu during runtime <1500-1752> Bytes\n"},
- { "hsicautosleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
- "Enable/Disable HSIC bus automatic sleep/resume feature"},
+ { "host_reorder_flows", dhd_hostreorder_flows, DHD_GET_VAR, -1,
+ "get host reorder flows "},
+ { "txglomsize", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+ "max glom size for sdio tx\n"},
+ { "txglommode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
+ "glom mode for sdio tx 0- copy, 1- multidescriptor\n"},
{ NULL, NULL, 0, 0, NULL }
};
@@ -963,17 +980,18 @@ dhd_membytes(void *dhd, cmd_t *cmd, char **argv)
/* arg count */
for (argc = 0; argv[argc]; argc++);
- /* required args: address size [<bytes>]] */
+ /* required args: address size [<data>]] */
if (argc < 2) {
- fprintf(stderr, "required args: address size [<bytes>]\n");
+ fprintf(stderr, "required args: address size [<data>]\n");
return USAGE_ERROR;
}
+
if (argc < 3 && hexin) {
- fprintf(stderr, "missing <bytes> arg implies by -h\n");
+ fprintf(stderr, "missing <data> required by -h\n");
return USAGE_ERROR;
}
if ((argc > 2) && (rawout)) {
- fprintf(stderr, "can't have input <bytes> arg with -r or -i\n");
+ fprintf(stderr, "can't have <data> arg with -r\n");
return USAGE_ERROR;
}
@@ -999,10 +1017,12 @@ dhd_membytes(void *dhd, cmd_t *cmd, char **argv)
/* get can just use utility function, set must copy custom buffer */
if (argc == 2) {
+ /* Read */
uint chunk = DHD_IOCTL_MAXLEN;
for (addr -= align, len += align; len; addr += chunk, len -= chunk, align = 0) {
chunk = MIN(chunk, len);
- params[0] = addr; params[1] = ROUNDUP(chunk, 4);
+ params[0] = addr;
+ params[1] = ROUNDUP(chunk, 4);
ret = dhd_var_getbuf(dhd, "membytes",
params, (2 * sizeof(int)), (void**)&ptr);
if (ret < 0)
@@ -1015,6 +1035,7 @@ dhd_membytes(void *dhd, cmd_t *cmd, char **argv)
}
}
} else {
+ /* Write */
uint patlen = strlen(argv[2]);
uint chunk, maxchunk;
char *sptr;
@@ -1487,7 +1508,39 @@ dhd_vars(void *dhd, cmd_t *cmd, char **argv)
#if defined(BWL_FILESYSTEM_SUPPORT)
static int
-dhd_load_file_bytes(void *dhd, cmd_t *cmd, FILE *fp, int fsize, int start)
+dhd_verify_file_bytes(void *dhd, uint8 *memblock, int start, uint len)
+{
+ int ret = 0;
+ uint i = 0;
+ char *ptr;
+ int params[2];
+ uint8 *src, *dst;
+
+ params[0] = start;
+ params[1] = len;
+ ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
+ if (ret) {
+ fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
+ __FUNCTION__, len, start);
+ return -1;
+ }
+
+ src = (uint8 *)memblock;
+ dst = (uint8 *)ptr;
+ while (i < len) {
+ if (src[i] != dst[i]) {
+ fprintf(stderr, " 0x%x: exp[0x%02X] != got[0x%02X]\n",
+ start+i, src[i], dst[i]);
+ ret = -1;
+ }
+ i++;
+ }
+
+ return ret;
+}
+
+static int
+dhd_load_file_bytes(void *dhd, cmd_t *cmd, FILE *fp, int fsize, int start, uint blk_sz, bool verify)
{
int tot_len = 0;
uint read_len;
@@ -1495,19 +1548,32 @@ dhd_load_file_bytes(void *dhd, cmd_t *cmd, FILE *fp, int fsize, int start)
uint len;
uint8 memblock[MEMBLOCK];
int ret;
+ int retry;
UNUSED_PARAMETER(cmd);
+ if (!fsize || !fp)
+ return -1;
+
+ assert(blk_sz <= MEMBLOCK);
+
while (tot_len < fsize) {
read_len = fsize - tot_len;
- if (read_len >= MEMBLOCK)
- read_len = MEMBLOCK;
+ if (read_len >= blk_sz) {
+ read_len = blk_sz;
+
+ if (!ISALIGNED(start, MEMBLOCK))
+ read_len = ROUNDUP(start, MEMBLOCK) - start;
+ }
+
len = fread(memblock, sizeof(uint8), read_len, fp);
if ((len < read_len) && !feof(fp)) {
fprintf(stderr, "%s: error reading file\n", __FUNCTION__);
return -1;
}
+ retry = 0;
+failed_retry:
bufp = buf;
memset(bufp, 0, DHD_IOCTL_MAXLEN);
@@ -1526,6 +1592,21 @@ dhd_load_file_bytes(void *dhd, cmd_t *cmd, FILE *fp, int fsize, int start)
__FUNCTION__, ret, len, start);
return -1;
}
+
+ if (verify == TRUE) {
+ if (len & 1)
+ len = ROUNDUP(len, 2);
+
+ if (dhd_verify_file_bytes(dhd, memblock, start, len) != 0) {
+ if (retry++ < 5000)
+ {
+ fprintf(stderr, "%s: verify failed %d membytes "
+ "from 0x%08x\n", __FUNCTION__, len, start);
+ goto failed_retry;
+ }
+ }
+ }
+
start += len;
tot_len += len;
}
@@ -1575,21 +1656,29 @@ dhd_download(void *dhd, cmd_t *cmd, char **argv)
#else
bool reset = TRUE;
bool run = TRUE;
+ bool verify = FALSE;
char *fname = NULL;
char *vname = NULL;
uint32 start = 0;
int ret = 0;
int fsize;
+ uint32 bustype;
+ long filepos;
+
FILE *fp = NULL;
uint32 memsize;
char *memszargs[] = { "memsize", NULL };
+
char *bufp;
+
miniopt_t opts;
int opt_err;
uint nvram_len;
struct trx_header trx_hdr;
+ uint32 trx_hdr_len;
bool trx_file = FALSE;
- bool overlays = FALSE;
+ uint memblock_sz = MEMBLOCK;
+ bool embedded_ucode = FALSE;
UNUSED_PARAMETER(cmd);
@@ -1628,6 +1717,8 @@ dhd_download(void *dhd, cmd_t *cmd, char **argv)
reset = FALSE;
} else if (!strcmp(opts.key, "norun")) {
run = FALSE;
+ } else if (!strcmp(opts.key, "verify")) {
+ verify = TRUE;
} else {
fprintf(stderr, "unrecognized option %s\n", opts.valstr);
ret = -1;
@@ -1662,18 +1753,13 @@ dhd_download(void *dhd, cmd_t *cmd, char **argv)
/* Verify the file is a regular bin file or trx file */
{
uint32 tmp_len;
- uint32 trx_hdr_len = sizeof(struct trx_header);
+ trx_hdr_len = sizeof(struct trx_header);
tmp_len = fread(&trx_hdr, sizeof(uint8), trx_hdr_len, fp);
if (tmp_len == trx_hdr_len) {
if (trx_hdr.magic == TRX_MAGIC) {
trx_file = TRUE;
- if (trx_hdr.flag_version & TRX_OVERLAYS) {
- fprintf(stderr, "Image contains overlays but overlays "
- "not supported by this command\n");
- ret = BCME_UNSUPPORTED;
- goto exit;
- } else {
- }
+ if (trx_hdr.flag_version & TRX_EMBED_UCODE)
+ embedded_ucode = TRUE;
}
else
fseek(fp, 0, SEEK_SET);
@@ -1682,37 +1768,63 @@ dhd_download(void *dhd, cmd_t *cmd, char **argv)
fseek(fp, 0, SEEK_SET);
}
- if ((ret = dhd_var_get(dhd, NULL, memszargs))) {
- fprintf(stderr, "%s: error obtaining memsize\n", __FUNCTION__);
- goto exit;
+ /* Check on which bus the dhd driver is sitting. Downloading methodology differs from
+ * USB to SDIO.
+ */
+ {
+ char* bustype_args[] = {"bustype", NULL};
+
+ /* Read the bus type the DHD driver is associated to */
+ if ((ret = dhd_var_get(dhd, NULL, bustype_args))) {
+ fprintf(stderr, "%s: error obtaining bustype\n", __FUNCTION__);
+ goto exit;
+ }
+
+ bustype = *(uint32*)buf;
}
- memsize = *(uint32*)buf;
+ if (trx_file)
+ fsize = (int)(trx_hdr.offsets[0]);
-#ifdef PART_OF_RAM_AS_ROMSIM
- /* only useful for cases where you want to sim some RAM as ROM */
- if (memsize && ((uint32)fsize > memsize)) {
- fprintf(stderr, "%s: file %s too large (%d > %d)\n",
- __FUNCTION__, fname, fsize, memsize);
- ret = -1;
- goto exit;
+ if (bustype == BUS_TYPE_SDIO) {
+ if ((ret = dhd_var_get(dhd, NULL, memszargs))) {
+ fprintf(stderr, "%s: error obtaining memsize\n", __FUNCTION__);
+ goto exit;
+ }
+ memsize = *(uint32*)buf;
}
-#endif /* PART_OF_RAM_AS_ROMSIM */
+
+
+ BCM_REFERENCE(memsize);
/* do the download reset if not suppressed */
if (reset) {
- if ((ret = dhd_iovar_setint(dhd, "download", TRUE))) {
+ if ((ret = dhd_iovar_setint(dhd, "dwnldstate", TRUE))) {
fprintf(stderr, "%s: failed to put dongle in download mode\n",
__FUNCTION__);
goto exit;
}
}
- if (trx_file)
- fsize = trx_hdr.offsets[0];
+ if (BUS_TYPE_USB == bustype) {
+ /* store the cur pos pointing to base image which should be written */
+ filepos = ftell(fp);
+ if (filepos == -1) {
+ fprintf(stderr, "%s: ftell failed.\n", __FUNCTION__);
+ }
+
+ /* In case of USB, we need to write header information also to dongle. */
+ fseek(fp, 0, SEEK_SET);
+
+ /* The file size is "base_image + TRX_Header_size" */
+ fsize = (int)(trx_hdr.offsets[0] + sizeof(struct trx_header));
+
+ memblock_sz = RDL_CHUNK;
+ }
+
/* Load the ram image */
- if (dhd_load_file_bytes(dhd, cmd, fp, fsize, start)) {
+ if (dhd_load_file_bytes(dhd, cmd, fp, fsize, start, memblock_sz, verify)) {
fprintf(stderr, "%s: error loading the ramimage at addr 0x%x\n",
__FUNCTION__, start);
ret = -1;
@@ -1720,8 +1832,14 @@ dhd_download(void *dhd, cmd_t *cmd, char **argv)
}
if (trx_file) {
- if (overlays) {
- } else {
+
+ filepos = ftell(fp);
+ if (filepos == -1) {
+ fprintf(stderr, "%s: ftell failed.\n", __FUNCTION__);
+ }
+
+ if (BUS_TYPE_SDIO == bustype) {
+
}
}
@@ -1754,18 +1872,30 @@ dhd_download(void *dhd, cmd_t *cmd, char **argv)
/* start running the downloaded code if not suppressed */
if (run) {
- if ((ret = dhd_iovar_setint(dhd, "download", FALSE))) {
+ if ((ret = dhd_iovar_setint(dhd, "dwnldstate", FALSE))) {
+
fprintf(stderr, "%s: failed to take dongle out of download mode\n",
__FUNCTION__);
+ /* USB Error return values */
+ if (BUS_TYPE_USB == bustype) {
+ if (ret == -1)
+ fprintf(stderr, "%s: CPU is not in RUNNABLE State\n",
+ __FUNCTION__);
+ else
+ fprintf(stderr, "%s: Error in setting CPU to RUN mode.\n",
+ __FUNCTION__);
+ }
goto exit;
}
}
+ if (embedded_ucode) {
+/* GREG remove */
+ }
exit:
if (fp)
fclose(fp);
-
return ret;
#endif /* BWL_FILESYSTEM_SUPPORT */
}
@@ -2140,6 +2270,9 @@ static dbg_msg_t dhd_msgs[] = {
{DHD_GLOM_VAL, "glom"},
{DHD_EVENT_VAL, "event"},
{DHD_BTA_VAL, "bta"},
+ {DHD_ISCAN_VAL, "iscan"},
+ {DHD_ARPOE_VAL, "arpoe"},
+ {DHD_REORDER_VAL, "reorder"},
{0, NULL}
};
@@ -2531,6 +2664,33 @@ dhd_varstr(void *dhd, cmd_t *cmd, char **argv)
}
+static int
+dhd_hostreorder_flows(void *dhd, cmd_t *cmd, char **argv)
+{
+ int ret, count, i = 0;
+ void *ptr;
+ uint8 *flow_id;
+
+
+ if ((ret = dhd_var_getbuf(dhd, cmd->name, NULL, 0, &ptr)) < 0) {
+ printf("error getting reorder flows from the host\n");
+ return ret;
+ }
+ flow_id = (uint8 *)ptr;
+ count = *flow_id;
+ if (!count)
+ printf("there are no active flows\n");
+ else {
+ printf("flows(%d): \t", count);
+ while (i++ < count)
+ printf("%d ", *flow_id++);
+ printf("\n");
+ }
+ return 0;
+}
+
+
+#ifdef WLBTAMP
#define MATCH_OP(op, opstr) (strlen(op) == strlen(opstr) && strncmp(op, opstr, strlen(op)) == 0)
@@ -2627,16 +2787,18 @@ wl_HCI_cmd(void *wl, cmd_t *cmd, char **argv)
return dhd_var_setbuf(wl, cmd->name, cpkt, HCI_CMD_PREAMBLE_SIZE + plen);
}
+typedef union {
+ uint8 buf[HCI_ACL_DATA_PREAMBLE_SIZE + 2048];
+ uint32 alignme;
+} g_hci_dbuf_t;
+
static int
wl_HCI_ACL_data(void *wl, cmd_t *cmd, char **argv)
{
/* Align struct. Also declare static so that large array isn't allocated
* from the stack.
*/
- static union {
- uint8 buf[HCI_ACL_DATA_PREAMBLE_SIZE + 2048];
- uint32 alignme;
- } g_hci_dbuf;
+ static g_hci_dbuf_t g_hci_dbuf;
amp_hci_ACL_data_t *dpkt = (amp_hci_ACL_data_t *)&g_hci_dbuf.buf[0];
uint16 dlen;
@@ -2657,6 +2819,7 @@ wl_HCI_ACL_data(void *wl, cmd_t *cmd, char **argv)
return dhd_var_setbuf(wl, cmd->name, dpkt, HCI_ACL_DATA_PREAMBLE_SIZE + dlen);
}
+#endif /* WLBTAMP */
/* These two utility functions are used by dhdu_linux.c
* The code is taken from wlu.c.