Home | History | Annotate | Download | only in dhdutil
      1 /*
      2  * Common code for DHD command-line utility
      3  *
      4  * Copyright (C) 1999-2013, Broadcom Corporation
      5  *
      6  * Permission to use, copy, modify, and/or distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     13  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     15  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     16  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  *
     18  * $Id: dhdu.c 385965 2013-02-19 04:33:34Z $
     19  */
     20 
     21 /* For backwards compatibility, the absence of the define 'BWL_NO_FILESYSTEM_SUPPORT'
     22  * implies that a filesystem is supported.
     23  */
     24 #if !defined(BWL_NO_FILESYSTEM_SUPPORT)
     25 #define BWL_FILESYSTEM_SUPPORT
     26 #endif
     27 
     28 #ifndef PROP_TXSTATUS
     29 #define PROP_TXSTATUS
     30 #endif
     31 
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <strings.h>
     36 #include <ctype.h>
     37 #include <assert.h>
     38 
     39 #include <typedefs.h>
     40 #include <epivers.h>
     41 #include <proto/ethernet.h>
     42 #include <dhdioctl.h>
     43 #include <sdiovar.h>
     44 #include <bcmutils.h>
     45 #include <bcmendian.h>
     46 #include "dhdu.h"
     47 #include "miniopt.h"
     48 #include <proto/bcmip.h>
     49 #include <hndrte_debug.h>
     50 #include <hndrte_armtrap.h>
     51 #include <hndrte_cons.h>
     52 #define IPV4_ADDR_LEN 4
     53 
     54 #include <errno.h>
     55 
     56 #include <trxhdr.h>
     57 #include "ucode_download.h"
     58 
     59 #define stricmp strcasecmp
     60 #define strnicmp strncasecmp
     61 
     62 
     63 static cmd_func_t dhd_var_void;
     64 static cmd_func_t dhd_varint, dhd_varstr;
     65 static cmd_func_t dhd_var_getandprintstr, dhd_var_getint, dhd_var_get;
     66 static cmd_func_t dhd_var_setint;
     67 
     68 static cmd_func_t dhd_version, dhd_list, dhd_msglevel;
     69 
     70 #ifdef SDTEST
     71 static cmd_func_t dhd_pktgen;
     72 #endif
     73 static cmd_func_t dhd_sprom;
     74 static cmd_func_t dhd_sdreg;
     75 static cmd_func_t dhd_sd_msglevel, dhd_sd_blocksize, dhd_sd_mode, dhd_sd_reg;
     76 static cmd_func_t dhd_dma_mode;
     77 static cmd_func_t dhd_membytes, dhd_download, dhd_dldn,
     78 	dhd_upload, dhd_coredump, dhd_consoledump, dhd_vars, dhd_idleclock, dhd_idletime;
     79 static cmd_func_t dhd_logstamp;
     80 
     81 static cmd_func_t dhd_hostreorder_flows;
     82 
     83 #ifdef PROP_TXSTATUS
     84 static cmd_func_t dhd_proptxstatusenable;
     85 static cmd_func_t dhd_proptxstatusmode;
     86 static cmd_func_t dhd_proptxopt;
     87 #endif
     88 static int dhd_var_getbuf(void *dhd, char *iovar, void *param, int param_len, void **bufptr);
     89 static int dhd_var_setbuf(void *dhd, char *iovar, void *param, int param_len);
     90 
     91 static uint dhd_iovar_mkbuf(char *name, char *data, uint datalen,
     92                             char *buf, uint buflen, int *perr);
     93 static int dhd_iovar_getint(void *dhd, char *name, int *var);
     94 static int dhd_iovar_setint(void *dhd, char *name, int var);
     95 
     96 #if defined(BWL_FILESYSTEM_SUPPORT)
     97 static int file_size(char *fname);
     98 static int read_vars(char *fname, char *buf, int buf_maxlen);
     99 #endif
    100 
    101 
    102 /* dword align allocation */
    103 static union {
    104 	char bufdata[DHD_IOCTL_MAXLEN];
    105 	uint32 alignme;
    106 } bufstruct_dhd;
    107 static char *buf = (char*) &bufstruct_dhd.bufdata;
    108 
    109 /* integer output format, default to signed integer */
    110 static uint8 int_fmt;
    111 
    112 #define DEBUG_INFO_PTRS_END 0xffffffff
    113 const uint32 debug_info_ptrs[] = {0xf8, 0x878, DEBUG_INFO_PTRS_END};
    114 
    115 typedef struct {
    116 	uint value;
    117 	char *string;
    118 } dbg_msg_t;
    119 
    120 static int dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg);
    121 
    122 /* Actual command table */
    123 cmd_t dhd_cmds[] = {
    124 	{ "cmds", dhd_list, -1, -1,
    125 	"generate a short list of available commands"},
    126 	{ "version", dhd_version, DHD_GET_VAR, -1,
    127 	"get version information" },
    128 	{ "msglevel", dhd_msglevel, DHD_GET_VAR, DHD_SET_VAR,
    129 	"get/set message bits" },
    130 	{ "bcmerrorstr", dhd_var_getandprintstr, DHD_GET_VAR, -1,
    131 	"errorstring"},
    132 	{ "wdtick", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    133 	"watchdog tick time (ms units)"},
    134 	{ "intr", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    135 	"use interrupts on the bus"},
    136 	{ "pollrate", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    137 	"number of ticks between bus polls (0 means no polling)"},
    138 	{ "idletime", dhd_idletime, DHD_GET_VAR, DHD_SET_VAR,
    139 	"number of ticks for activity timeout (-1: immediate, 0: never)"},
    140 	{ "idleclock", dhd_idleclock, DHD_GET_VAR, DHD_SET_VAR,
    141 	"idleclock active | stopped | <N>\n"
    142 	"\tactive (0)   - do not request any change to the SD clock\n"
    143 	"\tstopped (-1) - request SD clock be stopped on activity timeout\n"
    144 	"\t<N> (other)  - an sd_divisor value to request on activity timeout\n"},
    145 	{ "sd1idle", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    146 	"change mode to SD1 when turning off clock at idle"},
    147 	{ "forceeven", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    148 	"force SD tx/rx buffers to be even"},
    149 	{ "readahead", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    150 	"enable readahead feature (look for next frame len in headers)"},
    151 	{ "sdrxchain", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    152 	"enable packet chains to SDIO stack for glom receive"},
    153 	{ "alignctl", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    154 	"align control frames"},
    155 	{ "sdalign", dhd_varint, DHD_GET_VAR, -1,
    156 	"display the (compiled in) alignment target for sd requests"},
    157 	{ "txbound", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    158 	"get/set maximum number of tx frames per scheduling"},
    159 	{ "rxbound", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    160 	"get/set maximum number of rx frames per scheduling"},
    161 	{ "txminmax", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    162 	"get/set maximum number of tx frames per scheduling while rx frames outstanding"},
    163 	{ "dconpoll", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    164 	"g/set dongle console polling interval (ms)"},
    165 	{ "dump", dhd_varstr, DHD_GET_VAR, -1,
    166 	"dump information"},
    167 	{ "cons", dhd_varstr, -1, DHD_SET_VAR,
    168 	"send string to device console (sd only)"},
    169 	{ "clearcounts", dhd_var_void, -1, DHD_SET_VAR,
    170 	"reset the bus stats shown in the dhd dump"},
    171 	{ "logdump", dhd_varstr, DHD_GET_VAR, -1,
    172 	"dump the timestamp logging buffer"},
    173 	{ "logcal", dhd_varint, -1, DHD_SET_VAR,
    174 	"logcal <n>  -- log around an osl_delay of <n> usecs"},
    175 	{ "logstamp", dhd_logstamp, -1, DHD_SET_VAR,
    176 	"logstamp [<n1>] [<n2>]  -- add a message to the log"},
    177 	{ "ramstart", dhd_varint, DHD_GET_VAR, -1,
    178 	"display start address of onchip SOCRAM"},
    179 	{ "ramsize", dhd_varint, DHD_GET_VAR, -1,
    180 	"display size of onchip SOCRAM"},
    181 	{ "membytes", dhd_membytes, DHD_GET_VAR, DHD_SET_VAR,
    182 	"membytes [-h | -r | -i] <address> <length> [<data>]\n"
    183 	"\tread or write data in the dongle ram\n"
    184 	"\t-h   <data> is a sequence of hex digits rather than a char string\n"
    185 	"\t-r   output binary to stdout rather hex\n"},
    186 	{ "download", dhd_download, -1, DHD_SET_VAR,
    187 	"download [-a <address>] [--noreset] [--norun] [--verify] <binfile> [<varsfile>]\n"
    188 	"\tdownload file to specified dongle ram address and start CPU\n"
    189 	"\toptional vars file will replace vars parsed from the CIS\n"
    190 	"\t--noreset    do not reset SOCRAM core before download\n"
    191 	"\t--norun      do not start dongle CPU after download\n"
    192 	"\t--verify     do readback verify \n"
    193 	"\tdefault <address> is 0\n"},
    194 	{ "dldn", dhd_dldn, -1, DHD_SET_VAR,
    195 	"download <binfile>\n"
    196 	"\tdownload file to specified dongle ram address 0\n"},
    197 	{ "vars", dhd_vars, DHD_GET_VAR, DHD_SET_VAR,
    198 	"vars [<file>]\n"
    199 	"\toverride SPROM vars with <file> (before download)\n"},
    200 	{ "coredump", dhd_coredump, -1, -1,
    201 	"coredump <file>\n"
    202 	"\tdump dongle RAM content into a file in dumpfile format\n"
    203 	"\tfor use with ELF core generator"},
    204 	{ "consoledump", dhd_consoledump, -1, -1,
    205 	"consoledump\n"
    206 	"\tdump dongle debug console buffer"},
    207 	{ "upload", dhd_upload, -1, -1,
    208 	"upload [-a <address> ] <file> [<size>]\n"
    209 	"\tupload dongle RAM content into a file\n"
    210 	"\tdefault <address> is 0, default <size> is RAM size"},
    211 	{ "srdump", dhd_sprom, DHD_GET_VAR, -1,
    212 	"display SPROM content" },
    213 	{ "srwrite", dhd_sprom, -1, DHD_SET_VAR,
    214 	"write data or file content to SPROM\n"
    215 	"\tsrwrite <word-offset> <word-value> ...\n"
    216 	"\tsrwrite [-c] <srom-file-path>\n"
    217 	"\t  -c means write regardless of crc"},
    218 	{ "sleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    219 	"enter/exit simulated host sleep (bus powerdown w/OOB wakeup)"},
    220 	{ "kso", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    221 	"keep sdio on"},
    222 	{ "devcap", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    223 	"brcm device capabilities"},
    224 	{ "devsleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    225 	"Sleep CMD14"},
    226 #ifdef SDTEST
    227 	{ "extloop", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    228 	"external loopback: convert all tx data to echo test frames"},
    229 	{ "pktgen", dhd_pktgen, DHD_GET_VAR, DHD_SET_VAR,
    230 	"configure/report pktgen status (SDIO)\n"
    231 	"\t-f N     frequency: send/recv a burst every N ticks\n"
    232 	"\t-c N     count: send/recv N packets each burst\n"
    233 	"\t-t N     total: stop after a total of N packets\n"
    234 	"\t-p N     print: display counts on console every N bursts\n"
    235 	"\t-m N     min: set minimum length of packet data\n"
    236 	"\t-M N     Max: set maximum length of packet data\n"
    237 	"\t-l N     len: set fixed length of packet data\n"
    238 	"\t-s N     stop after N tx failures\n"
    239 	"\t-d dir   test direction/type:\n"
    240 	"\t            send -- send packets discarded by dongle\n"
    241 	"\t            echo -- send packets to be echoed by dongle\n"
    242 	"\t            burst -- request bursts (of size <-c>) from dongle\n"
    243 	"\t              one every <-f> ticks, until <-t> total requests\n"
    244 	"\t            recv -- request dongle enter continuous send mode,\n"
    245 	"\t              read up to <-c> pkts every <-f> ticks until <-t>\n"
    246 	"\t              total reads\n"},
    247 #endif /* SDTEST */
    248 	{ "dngl_isolation", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    249 	"g/set dongle isolation, so the dev could be disabled with out effecting the dongle state"},
    250 	{ "sdreg", dhd_sdreg, DHD_GET_VAR, DHD_SET_VAR,
    251 	"g/set sdpcmdev core register (f1) across SDIO (CMD53)"},
    252 	{ "sbreg", dhd_sdreg, DHD_GET_VAR, DHD_SET_VAR,
    253 	"g/set any backplane core register (f1) across SDIO (CMD53)"},
    254 	{ "sd_cis", dhd_var_getandprintstr, DHD_GET_VAR, -1,
    255 	"dump sdio CIS"},
    256 	{ "sd_devreg", dhd_sd_reg, DHD_GET_VAR, DHD_SET_VAR,
    257 	"g/set device register across SDIO bus (CMD52)"},
    258 	{ "sd_hostreg", dhd_sd_reg, DHD_GET_VAR, DHD_SET_VAR,
    259 	"g/set local controller register"},
    260 	{ "sd_blocksize", dhd_sd_blocksize, DHD_GET_VAR, DHD_SET_VAR,
    261 	"g/set block size for a function"},
    262 	{ "sd_blockmode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    263 	"g/set blockmode"},
    264 	{ "sd_ints", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    265 	"g/set client ints"},
    266 	{ "sd_dma", dhd_dma_mode, DHD_GET_VAR, DHD_SET_VAR,
    267 	"g/set dma usage: [PIO | SDMA | ADMA1 | ADMA2]"},
    268 	{ "sd_yieldcpu", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    269 	"allow blocking (yield of CPU) on data xfer"},
    270 	{ "sd_minyield", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    271 	"minimum xfer size to allow CPU yield"},
    272 	{ "sd_forcerb", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    273 	"force readback when changing local interrupt settings"},
    274 	{ "sd_numints", dhd_varint, DHD_GET_VAR, -1,
    275 	"number of device interrupts"},
    276 	{ "sd_numlocalints", dhd_varint, DHD_GET_VAR, -1,
    277 	"number of non-device interrupts"},
    278 	{ "sd_divisor", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    279 	"set the divisor for SDIO clock generation"},
    280 	{ "sd_power", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    281 	"set the SD Card slot power"},
    282 	{ "sd_power_save", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    283 	"set the SDIO3.0 power save value"},
    284 	{ "sd_clock", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    285 	"turn on/off the SD Clock"},
    286 	{ "sd_crc", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    287 	"turn on/off CRC checking in SPI mode"},
    288 	{ "sd_mode", dhd_sd_mode, DHD_GET_VAR, DHD_SET_VAR,
    289 	"g/set SDIO bus mode (spi, sd1, sd4)"},
    290 	{ "sd_highspeed", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    291 	"set the high-speed clocking mode"},
    292 	{ "sd_msglevel", dhd_sd_msglevel, DHD_GET_VAR, DHD_SET_VAR,
    293 	"g/set debug message level"},
    294 	{ "sd_hciregs", dhd_varstr, DHD_GET_VAR, -1,
    295 	"display host-controller interrupt registers"},
    296 	{ "sdiod_drive", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    297 	"SDIO Device drive strength in milliamps. (0=tri-state, 1-12mA)"},
    298 	{ "devreset", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    299 	"Move device into or out of reset state (1/reset, or 0/operational)"},
    300 	{ "ioctl_timeout", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    301 	"IOCTL response timeout (milliseconds)."},
    302 #ifdef PROP_TXSTATUS
    303 	{ "proptx", dhd_proptxstatusenable, DHD_GET_VAR, DHD_SET_VAR,
    304 	"enable/disable the proptxtstatus feature\n"
    305 	"0 - disabled\n"
    306 	"1 - enabled\n"},
    307 	{ "ptxmode", dhd_proptxstatusmode, DHD_GET_VAR, DHD_SET_VAR,
    308 	"set the proptxtstatus operation mode:\n"
    309 	"0 - Unsupported\n"
    310 	"1 - Use implied credit from a packet status\n"
    311 	"2 - Use explicit credit\n" },
    312 	{ "proptx_opt", dhd_proptxopt, DHD_GET_VAR, DHD_SET_VAR,
    313 	"enable/disable proptxtstatus optimizations to increase throughput:\n"
    314 	"0 - Unsupported\n"
    315 	"1 - Enable proptxstatus optimizations to increase throughput\n" },
    316 #endif
    317 	{ "sd_uhsimode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    318 	"g/set UHSI Mode"},
    319 	{ "host_reorder_flows", dhd_hostreorder_flows, DHD_GET_VAR, -1,
    320 	"get host reorder flows "},
    321 	{ "txglomsize", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    322 	"max glom size for sdio tx\n"},
    323 	{ "txglommode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    324 	"glom mode for sdio tx 0- copy, 1- multidescriptor\n"},
    325 	{ "fw_hang_report", dhd_varint, DHD_GET_VAR, DHD_SET_VAR,
    326 	"enable/disable report firmware hangs for firmware reload\n"
    327 	"0 - disabled (for testing)\n"
    328 	"1 - enabled (default)\n"},
    329 	{ NULL, NULL, 0, 0, NULL }
    330 };
    331 
    332 cmd_t dhd_varcmd = {"var", dhd_varint, -1, -1, "unrecognized name, type -h for help"};
    333 char *dhdu_av0;
    334 
    335 #if defined(BWL_FILESYSTEM_SUPPORT)
    336 static int
    337 file_size(char *fname)
    338 {
    339 	FILE *fp;
    340 	long size = -1;
    341 
    342 	/* Can't use stat() because of Win CE */
    343 
    344 	if ((fp = fopen(fname, "rb")) == NULL ||
    345 	    fseek(fp, 0, SEEK_END) < 0 ||
    346 	    (size = ftell(fp)) < 0)
    347 		fprintf(stderr, "Could not determine size of %s: %s\n",
    348 		        fname, strerror(errno));
    349 
    350 	if (fp != NULL)
    351 		fclose(fp);
    352 
    353 	return (int)size;
    354 }
    355 #endif   /* BWL_FILESYSTEM_SUPPORT */
    356 
    357 
    358 /* parse/validate the command line arguments */
    359 /*
    360 * pargv is updated upon return if the first argument is an option.
    361  * It remains intact otherwise.
    362  */
    363 int
    364 dhd_option(char ***pargv, char **pifname, int *phelp)
    365 {
    366 	char *ifname = NULL;
    367 	int help = FALSE;
    368 	int status = CMD_OPT;
    369 	char **argv = *pargv;
    370 
    371 	int_fmt = INT_FMT_DEC;
    372 
    373 	while (*argv) {
    374 		/* select different adapter */
    375 		if (!strcmp(*argv, "-a") || !strcmp(*argv, "-i")) {
    376 			char *opt = *argv++;
    377 			ifname = *argv;
    378 			if (!ifname) {
    379 				fprintf(stderr,
    380 					"error: expected interface name after option %s\n", opt);
    381 				status = CMD_ERR;
    382 				break;
    383 			}
    384 		}
    385 
    386 		/* integer output format */
    387 		else if (!strcmp(*argv, "-d"))
    388 			int_fmt = INT_FMT_DEC;
    389 		else if (!strcmp(*argv, "-u"))
    390 			int_fmt = INT_FMT_UINT;
    391 		else if (!strcmp(*argv, "-x"))
    392 			int_fmt = INT_FMT_HEX;
    393 
    394 		/* command usage */
    395 		else if (!strcmp(*argv, "-h"))
    396 			help = TRUE;
    397 
    398 		/* done with generic options */
    399 		else {
    400 			status = CMD_DHD;
    401 			break;
    402 		}
    403 
    404 		/* consume the argument */
    405 		argv ++;
    406 		break;
    407 	}
    408 
    409 	*phelp = help;
    410 	*pifname = ifname;
    411 	*pargv = argv;
    412 
    413 	return status;
    414 }
    415 
    416 void
    417 dhd_cmd_usage(cmd_t *cmd)
    418 {
    419 	if (strlen(cmd->name) >= 8)
    420 		fprintf(stderr, "%s\n\t%s\n\n", cmd->name, cmd->help);
    421 	else
    422 		fprintf(stderr, "%s\t%s\n\n", cmd->name, cmd->help);
    423 }
    424 
    425 /* Dump out short list of commands */
    426 static int
    427 dhd_list(void *dhd, cmd_t *garb, char **argv)
    428 {
    429 	cmd_t *cmd;
    430 	int nrows, i, len;
    431 	char *buf;
    432 	int letter, col, row, pad;
    433 
    434 	UNUSED_PARAMETER(dhd);
    435 	UNUSED_PARAMETER(garb);
    436 	UNUSED_PARAMETER(argv);
    437 
    438 	for (cmd = dhd_cmds, nrows = 0; cmd->name; cmd++)
    439 		    nrows++;
    440 
    441 	nrows /= 4;
    442 	nrows++;
    443 
    444 	len = nrows * 80 + 2;
    445 	buf = malloc(len);
    446 	if (buf == NULL) {
    447 		fprintf(stderr, "Failed to allocate buffer of %d bytes\n", len);
    448 		return BCME_NOMEM;
    449 	}
    450 	for (i = 0; i < len; i++)
    451 		*(buf+i) = 0;
    452 
    453 	row = col = 0;
    454 	for (letter = 'a'; letter < 'z'; letter++) {
    455 		for (cmd = dhd_cmds; cmd->name; cmd++) {
    456 			if (cmd->name[0] == letter || cmd->name[0] == letter - 0x20) {
    457 				strcat(buf+row*80, cmd->name);
    458 				pad = 18 * (col + 1) - strlen(buf+row*80);
    459 				if (pad < 1)
    460 					pad = 1;
    461 				for (; pad; pad--)
    462 					strcat(buf+row*80, " ");
    463 				row++;
    464 				if (row == nrows) {
    465 					col++; row = 0;
    466 				}
    467 			}
    468 		}
    469 	}
    470 	for (row = 0; row < nrows; row++)
    471 		printf("%s\n", buf+row*80);
    472 
    473 	printf("\n");
    474 	free(buf);
    475 	return (0);
    476 }
    477 
    478 void
    479 dhd_cmds_usage(cmd_t *port_cmds)
    480 {
    481 	cmd_t *port_cmd;
    482 	cmd_t *cmd;
    483 
    484 	/* print usage of port commands */
    485 	for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
    486 		/* Check for wc_cmd */
    487 		dhd_cmd_usage(port_cmd);
    488 
    489 	/* print usage of common commands without port counterparts */
    490 	for (cmd = dhd_cmds; cmd->name; cmd++) {
    491 		/* search if port counterpart exists */
    492 		for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
    493 			if (!strcmp(port_cmd->name, cmd->name))
    494 				break;
    495 		if (!port_cmd || !port_cmd->name)
    496 			dhd_cmd_usage(cmd);
    497 	}
    498 }
    499 
    500 void
    501 dhd_usage(cmd_t *port_cmds)
    502 {
    503 	fprintf(stderr,
    504 	        "Usage: %s [-a|i <adapter>] [-h] [-d|u|x] <command> [arguments]\n",
    505 		dhdu_av0);
    506 
    507 	fprintf(stderr, "\n");
    508 	fprintf(stderr, "  -h		this message\n");
    509 	fprintf(stderr, "  -a, -i	adapter name or number\n");
    510 	fprintf(stderr, "  -d		display values as signed integer\n");
    511 	fprintf(stderr, "  -u		display values as unsigned integer\n");
    512 	fprintf(stderr, "  -x		display values as hexdecimal\n");
    513 	fprintf(stderr, "\n");
    514 
    515 	dhd_cmds_usage(port_cmds);
    516 }
    517 
    518 int
    519 dhd_check(void *dhd)
    520 {
    521 	int ret;
    522 	int val;
    523 
    524 	if ((ret = dhd_get(dhd, DHD_GET_MAGIC, &val, sizeof(int))) < 0)
    525 		return ret;
    526 	if (val != DHD_IOCTL_MAGIC)
    527 		return -1;
    528 	if ((ret = dhd_get(dhd, DHD_GET_VERSION, &val, sizeof(int))) < 0)
    529 		return ret;
    530 	if (val > DHD_IOCTL_VERSION) {
    531 		fprintf(stderr, "Version mismatch, please upgrade\n");
    532 		return -1;
    533 	}
    534 	return 0;
    535 }
    536 
    537 void
    538 dhd_printint(int val)
    539 {
    540 	switch (int_fmt) {
    541 	case INT_FMT_UINT:
    542 		printf("%u\n", val);
    543 		break;
    544 	case INT_FMT_HEX:
    545 		printf("0x%x\n", val);
    546 		break;
    547 	case INT_FMT_DEC:
    548 	default:
    549 		printf("%d\n", val);
    550 		break;
    551 	}
    552 }
    553 
    554 /* pretty hex print a contiguous buffer (tweaked from wlu) */
    555 void
    556 dhd_hexdump(uchar *buf, uint nbytes, uint saddr)
    557 {
    558 	char line[256];
    559 	char* p;
    560 	uint i;
    561 
    562 	if (nbytes == 0) {
    563 		printf("\n");
    564 		return;
    565 	}
    566 
    567 	p = line;
    568 	for (i = 0; i < nbytes; i++) {
    569 		if (i % 16 == 0) {
    570 			p += sprintf(p, "%08x: ", saddr + i);	/* line prefix */
    571 		}
    572 		p += sprintf(p, "%02x ", buf[i]);
    573 		if (i % 16 == 15) {
    574 			uint j;
    575 			p += sprintf(p, "  ");
    576 			for (j = i-15; j <= i; j++)
    577 				p += sprintf(p, "%c",
    578 				             ((buf[j] >= 0x20 && buf[j] <= 0x7f) ? buf[j] : '.'));
    579 			printf("%s\n", line);		/* flush line */
    580 			p = line;
    581 		}
    582 	}
    583 
    584 	/* flush last partial line */
    585 	if (p != line)
    586 		printf("%s\n", line);
    587 }
    588 
    589 
    590 #ifdef SDTEST
    591 static int
    592 dhd_pktgen(void *dhd, cmd_t *cmd, char **argv)
    593 {
    594 	int ret = 0;
    595 	void *ptr = NULL;
    596 	dhd_pktgen_t pktgen;
    597 	char *str;
    598 
    599 	UNUSED_PARAMETER(dhd);
    600 	UNUSED_PARAMETER(cmd);
    601 
    602 	/* Get current settings */
    603 	if ((ret = dhd_var_getbuf(dhd, "pktgen", NULL, 0, &ptr)) != 0)
    604 		return ret;
    605 	memcpy(&pktgen, ptr, sizeof(pktgen));
    606 
    607 	if (pktgen.version != DHD_PKTGEN_VERSION) {
    608 		fprintf(stderr, "pktgen version mismatch (module %d app %d)\n",
    609 		        pktgen.version, DHD_PKTGEN_VERSION);
    610 		return BCME_ERROR;
    611 	}
    612 
    613 	/* Presence of args implies a set, else a get */
    614 	if (*++argv) {
    615 		miniopt_t opts;
    616 		int opt_err;
    617 
    618 		/* Initialize option parser */
    619 		miniopt_init(&opts, "pktgen", "", FALSE);
    620 
    621 		while ((opt_err = miniopt(&opts, argv)) != -1) {
    622 			if (opt_err == 1) {
    623 				fprintf(stderr, "pktgen options error\n");
    624 				ret = -1;
    625 				goto exit;
    626 			}
    627 			argv += opts.consumed;
    628 
    629 			if (!opts.good_int && opts.opt != 'd') {
    630 				fprintf(stderr, "invalid integer %s\n", opts.valstr);
    631 				ret = -1;
    632 				goto exit;
    633 			}
    634 
    635 			switch (opts.opt) {
    636 			case 'f':
    637 				pktgen.freq = opts.uval;
    638 				break;
    639 			case 'c':
    640 				pktgen.count = opts.uval;
    641 				break;
    642 			case 'p':
    643 				pktgen.print = opts.uval;
    644 				break;
    645 			case 't':
    646 				pktgen.total = opts.uval;
    647 				break;
    648 			case 's':
    649 				pktgen.stop = opts.uval;
    650 				break;
    651 			case 'm':
    652 				pktgen.minlen = opts.uval;
    653 				break;
    654 			case 'M':
    655 				pktgen.maxlen = opts.uval;
    656 				break;
    657 			case 'l': case 'L':
    658 				pktgen.minlen = pktgen.maxlen = opts.uval;
    659 				break;
    660 			case 'd':
    661 				if (!strcmp(opts.valstr, "send"))
    662 					pktgen.mode = DHD_PKTGEN_SEND;
    663 				else if (!strcmp(opts.valstr, "echo"))
    664 					pktgen.mode = DHD_PKTGEN_ECHO;
    665 				else if (!strcmp(opts.valstr, "burst"))
    666 					pktgen.mode = DHD_PKTGEN_RXBURST;
    667 				else if (!strcmp(opts.valstr, "recv"))
    668 					pktgen.mode = DHD_PKTGEN_RECV;
    669 				else {
    670 					fprintf(stderr, "unrecognized dir mode %s\n",
    671 					        opts.valstr);
    672 					return BCME_USAGE_ERROR;
    673 				}
    674 				break;
    675 
    676 			default:
    677 				fprintf(stderr, "option parsing error (key %s valstr %s)\n",
    678 				        opts.key, opts.valstr);
    679 				ret = BCME_USAGE_ERROR;
    680 				goto exit;
    681 			}
    682 		}
    683 
    684 		if (pktgen.maxlen < pktgen.minlen) {
    685 			fprintf(stderr, "min/max error (%d/%d)\n", pktgen.minlen, pktgen.maxlen);
    686 			ret = -1;
    687 			goto exit;
    688 		}
    689 
    690 		/* Set the new values */
    691 		ret = dhd_var_setbuf(dhd, "pktgen", &pktgen, sizeof(pktgen));
    692 	} else {
    693 		printf("Counts: %d send attempts, %d received, %d tx failures\n",
    694 		       pktgen.numsent, pktgen.numrcvd, pktgen.numfail);
    695 	}
    696 
    697 	/* Show configuration in either case */
    698 	switch (pktgen.mode) {
    699 	case DHD_PKTGEN_ECHO: str = "echo"; break;
    700 	case DHD_PKTGEN_SEND: str = "send"; break;
    701 	case DHD_PKTGEN_RECV: str = "recv"; break;
    702 	case DHD_PKTGEN_RXBURST: str = "burst"; break;
    703 	default: str = "UNKNOWN"; break;
    704 	}
    705 
    706 	printf("Config: mode %s %d pkts (len %d-%d) each %d ticks\n",
    707 	       str, pktgen.count, pktgen.minlen, pktgen.maxlen, pktgen.freq);
    708 
    709 	/* Second config line for optional items */
    710 	str = "        ";
    711 	if (pktgen.total) {
    712 		printf("%slimit %d", str, pktgen.total);
    713 		str = ", ";
    714 	}
    715 	if (pktgen.print) {
    716 		printf("%sprint every %d ticks", str, (pktgen.freq * pktgen.print));
    717 		str = ", ";
    718 	}
    719 	if (pktgen.stop) {
    720 		printf("%sstop after %d tx failures", str, pktgen.stop);
    721 		str = ", ";
    722 	}
    723 	if (str[0] == ',')
    724 		printf("\n");
    725 
    726 exit:
    727 	return ret;
    728 }
    729 #endif /* SDTEST */
    730 
    731 static dbg_msg_t dhd_sd_msgs[] = {
    732 	{SDH_ERROR_VAL,	"error"},
    733 	{SDH_TRACE_VAL,	"trace"},
    734 	{SDH_INFO_VAL,	"info"},
    735 	{SDH_DATA_VAL,	"data"},
    736 	{SDH_CTRL_VAL,	"control"},
    737 	{SDH_LOG_VAL,	"log"},
    738 	{SDH_DMA_VAL,	"dma"},
    739 	{0,		NULL}
    740 };
    741 
    742 static int
    743 dhd_sd_msglevel(void *dhd, cmd_t *cmd, char **argv)
    744 {
    745 	return dhd_do_msglevel(dhd, cmd, argv, dhd_sd_msgs);
    746 }
    747 
    748 static int
    749 dhd_sd_blocksize(void *dhd, cmd_t *cmd, char **argv)
    750 {
    751 	int ret;
    752 	int argc;
    753 	char *endptr = NULL;
    754 	void *ptr = NULL;
    755 	int func, size;
    756 
    757 	/* arg count */
    758 	for (argc = 0; argv[argc]; argc++);
    759 	argc--;
    760 
    761 	if (argc < 1 || argc > 2) {
    762 		printf("required args: function [size] (size 0 means max)\n");
    763 		return BCME_USAGE_ERROR;
    764 	}
    765 
    766 	func = strtol(argv[1], &endptr, 0);
    767 	if (*endptr != '\0') {
    768 		printf("Invalid function: %s\n", argv[1]);
    769 		return BCME_USAGE_ERROR;
    770 	}
    771 
    772 	if (argc > 1) {
    773 		size = strtol(argv[2], &endptr, 0);
    774 		if (*endptr != '\0') {
    775 			printf("Invalid size: %s\n", argv[1]);
    776 			return BCME_USAGE_ERROR;
    777 		}
    778 	}
    779 
    780 	if (argc == 1) {
    781 		if ((ret = dhd_var_getbuf(dhd, cmd->name, &func, sizeof(func), &ptr)) >= 0)
    782 			printf("Function %d block size: %d\n", func, *(int*)ptr);
    783 	} else {
    784 		printf("Setting function %d block size to %d\n", func, size);
    785 		size &= 0x0000ffff; size |= (func << 16);
    786 		ret = dhd_var_setbuf(dhd, cmd->name, &size, sizeof(size));
    787 	}
    788 
    789 	return (ret);
    790 }
    791 
    792 static int
    793 dhd_sd_mode(void *wl, cmd_t *cmd, char **argv)
    794 {
    795 	int ret;
    796 	int argc;
    797 	int sdmode;
    798 
    799 	/* arg count */
    800 	for (argc = 0; argv[argc]; argc++);
    801 	argc--;
    802 
    803 	if (argv[1]) {
    804 		if (!strcmp(argv[1], "spi")) {
    805 			strcpy(argv[1], "0");
    806 		} else if (!strcmp(argv[1], "sd1")) {
    807 			strcpy(argv[1], "1");
    808 		} else if (!strcmp(argv[1], "sd4")) {
    809 			strcpy(argv[1], "2");
    810 		} else {
    811 			return BCME_USAGE_ERROR;
    812 		}
    813 
    814 		ret = dhd_var_setint(wl, cmd, argv);
    815 
    816 	} else {
    817 		if ((ret = dhd_var_get(wl, cmd, argv))) {
    818 			return (ret);
    819 		} else {
    820 			sdmode = *(int32*)buf;
    821 
    822 			printf("SD Mode is: %s\n",
    823 			       sdmode == 0 ? "SPI"
    824 			       : sdmode == 1 ? "SD1"
    825 				   : sdmode == 2 ? "SD4" : "Unknown");
    826 		}
    827 	}
    828 
    829 	return (ret);
    830 }
    831 
    832 static int
    833 dhd_dma_mode(void *wl, cmd_t *cmd, char **argv)
    834 {
    835 	int ret;
    836 	int argc;
    837 	int dmamode;
    838 
    839 	/* arg count */
    840 	for (argc = 0; argv[argc]; argc++);
    841 	argc--;
    842 
    843 	if (argv[1]) {
    844 		if (!stricmp(argv[1], "pio")) {
    845 			strcpy(argv[1], "0");
    846 		} else if (!strcmp(argv[1], "0")) {
    847 		} else if (!stricmp(argv[1], "dma")) {
    848 			strcpy(argv[1], "1");
    849 		} else if (!stricmp(argv[1], "sdma")) {
    850 			strcpy(argv[1], "1");
    851 		} else if (!strcmp(argv[1], "1")) {
    852 		} else if (!stricmp(argv[1], "adma1")) {
    853 			strcpy(argv[1], "2");
    854 		} else if (!stricmp(argv[1], "adma")) {
    855 			strcpy(argv[1], "3");
    856 		} else if (!stricmp(argv[1], "adma2")) {
    857 			strcpy(argv[1], "3");
    858 		} else {
    859 			return BCME_USAGE_ERROR;
    860 		}
    861 
    862 		ret = dhd_var_setint(wl, cmd, argv);
    863 
    864 	} else {
    865 		if ((ret = dhd_var_get(wl, cmd, argv))) {
    866 			return (ret);
    867 		} else {
    868 			dmamode = *(int32*)buf;
    869 
    870 			printf("DMA Mode is: %s\n",
    871 			       dmamode == 0 ? "PIO"
    872 			       : dmamode == 1 ? "SDMA"
    873 			       : dmamode == 2 ? "ADMA1"
    874 			       : dmamode == 3 ? "ADMA2"
    875 			       : "Unknown");
    876 		}
    877 	}
    878 
    879 	return (ret);
    880 }
    881 
    882 
    883 static int
    884 dhd_sdreg(void *dhd, cmd_t *cmd, char **argv)
    885 {
    886 	int ret;
    887 	sdreg_t sdreg;
    888 	uint argc;
    889 	char *ptr = NULL;
    890 
    891 	UNUSED_PARAMETER(cmd);
    892 
    893 	bzero(&sdreg, sizeof(sdreg));
    894 
    895 	/* arg count */
    896 	for (argc = 0; argv[argc]; argc++);
    897 	argc--;
    898 
    899 	/* required args: offset (will default size) */
    900 	if (argc < 1) {
    901 		printf("required args: offset[/size] [value]\n");
    902 		return BCME_USAGE_ERROR;
    903 	}
    904 
    905 	sdreg.offset = strtoul(argv[1], &ptr, 0);
    906 	if (*ptr && *ptr != '/') {
    907 		printf("Bad arg: %s\n", argv[1]);
    908 		return BCME_USAGE_ERROR;
    909 	}
    910 
    911 	/* read optional /size */
    912 	if (*ptr == '/') {
    913 		sdreg.func = strtol((ptr+1), &ptr, 0);
    914 		if (*ptr || ((sdreg.func != 2) && sdreg.func != 4)) {
    915 			printf("Bad size option?\n");
    916 			return BCME_USAGE_ERROR;
    917 		}
    918 	}
    919 	else {
    920 		sdreg.func = 4;
    921 		printf("Defaulting to register size 4\n");
    922 	}
    923 
    924 	if (argc > 1) {
    925 		sdreg.value = strtoul(argv[2], &ptr, 0);
    926 		if (*ptr) {
    927 			printf("Bad value: %s\n", argv[2]);
    928 			return BCME_USAGE_ERROR;
    929 		}
    930 	}
    931 
    932 	if (argc <= 1) {
    933 		ret = dhd_var_getbuf(dhd, argv[0], &sdreg, sizeof(sdreg), (void**)&ptr);
    934 		if (ret >= 0)
    935 			printf("0x%0*x\n", (2 * sdreg.func), *(int *)ptr);
    936 	} else {
    937 		ret = dhd_var_setbuf(dhd, argv[0], &sdreg, sizeof(sdreg));
    938 	}
    939 
    940 	return (ret);
    941 }
    942 
    943 static int
    944 dhd_membytes(void *dhd, cmd_t *cmd, char **argv)
    945 {
    946 	int ret = -1;
    947 	uint argc;
    948 	char *ptr;
    949 	int params[2];
    950 	uint addr;
    951 	uint len;
    952 	int align;
    953 
    954 	int rawout, hexin;
    955 
    956 	miniopt_t opts;
    957 	int opt_err;
    958 
    959 	/* Parse command-line options */
    960 	miniopt_init(&opts, "membytes", "rh", FALSE);
    961 
    962 	rawout = hexin = 0;
    963 
    964 	argv++;
    965 	while ((opt_err = miniopt(&opts, argv)) != -1) {
    966 		if (opt_err == 1) {
    967 			fprintf(stderr, "membytes options error\n");
    968 			ret = -1;
    969 			goto exit;
    970 		}
    971 
    972 		if (opts.positional)
    973 			break;
    974 
    975 		argv += opts.consumed;
    976 
    977 		if (opts.opt == 'h') {
    978 			hexin = 1;
    979 		} else if (opts.opt == 'r') {
    980 			rawout = 1;
    981 		} else {
    982 			fprintf(stderr, "membytes command error\n");
    983 			ret = -1;
    984 			goto exit;
    985 		}
    986 	}
    987 
    988 	/* arg count */
    989 	for (argc = 0; argv[argc]; argc++);
    990 
    991 	/* required args: address size [<data>]] */
    992 	if (argc < 2) {
    993 		fprintf(stderr, "required args: address size [<data>]\n");
    994 		return BCME_USAGE_ERROR;
    995 	}
    996 
    997 	if (argc < 3 && hexin) {
    998 		fprintf(stderr, "missing <data> required by -h\n");
    999 		return BCME_USAGE_ERROR;
   1000 	}
   1001 	if ((argc > 2) && (rawout)) {
   1002 		fprintf(stderr, "can't have <data> arg with -r\n");
   1003 		return BCME_USAGE_ERROR;
   1004 	}
   1005 
   1006 	/* read address */
   1007 	addr = strtoul(argv[0], &ptr, 0);
   1008 	if (*ptr) {
   1009 		fprintf(stderr, "Bad arg: %s\n", argv[0]);
   1010 		return BCME_USAGE_ERROR;
   1011 	}
   1012 
   1013 	/* read size */
   1014 	len = strtoul(argv[1], &ptr, 0);
   1015 	if (*ptr) {
   1016 		fprintf(stderr, "Bad value: %s\n", argv[1]);
   1017 		return BCME_USAGE_ERROR;
   1018 	}
   1019 
   1020 	align = addr & 0x03;
   1021 	if (align && argc > 2) {
   1022 		fprintf(stderr, "Can only write starting at long-aligned addresses.\n");
   1023 		return BCME_USAGE_ERROR;
   1024 	}
   1025 
   1026 	/* get can just use utility function, set must copy custom buffer */
   1027 	if (argc == 2) {
   1028 		/* Read */
   1029 		uint chunk = DHD_IOCTL_MAXLEN;
   1030 		for (addr -= align, len += align; len; addr += chunk, len -= chunk, align = 0) {
   1031 			chunk = MIN(chunk, len);
   1032 			params[0] = addr;
   1033 			params[1] = ROUNDUP(chunk, 4);
   1034 			ret = dhd_var_getbuf(dhd, "membytes",
   1035 			                     params, (2 * sizeof(int)), (void**)&ptr);
   1036 			if (ret < 0)
   1037 				goto exit;
   1038 
   1039 			if (rawout) {
   1040 				fwrite(ptr + align, sizeof(char), chunk - align, stdout);
   1041 			} else {
   1042 				dhd_hexdump((uchar*)ptr + align, chunk - align, addr + align);
   1043 			}
   1044 		}
   1045 	} else {
   1046 		/* Write */
   1047 		uint patlen = strlen(argv[2]);
   1048 		uint chunk, maxchunk;
   1049 		char *sptr;
   1050 
   1051 		if (hexin) {
   1052 			char *inptr, *outptr;
   1053 			if (patlen & 1) {
   1054 				fprintf(stderr, "Hex (-h) must consist of whole bytes\n");
   1055 				ret = BCME_USAGE_ERROR;
   1056 				goto exit;
   1057 			}
   1058 
   1059 			for (inptr = outptr = argv[2]; patlen; patlen -= 2) {
   1060 				int n1, n2;
   1061 
   1062 				n1 = (int)((unsigned char)*inptr++);
   1063 				n2 = (int)((unsigned char)*inptr++);
   1064 				if (!isxdigit(n1) || !isxdigit(n2)) {
   1065 					fprintf(stderr, "invalid hex digit %c\n",
   1066 					        (isxdigit(n1) ? n2 : n1));
   1067 					ret = BCME_USAGE_ERROR;
   1068 					goto exit;
   1069 				}
   1070 				n1 = isdigit(n1) ? (n1 - '0')
   1071 				        : ((islower(n1) ? (toupper(n1)) : n1) - 'A' + 10);
   1072 				n2 = isdigit(n2) ? (n2 - '0')
   1073 				        : ((islower(n2) ? (toupper(n2)) : n2) - 'A' + 10);
   1074 				*outptr++ = (n1 * 16) + n2;
   1075 			}
   1076 
   1077 			patlen = outptr - argv[2];
   1078 		}
   1079 
   1080 		sptr = argv[2];
   1081 		maxchunk = DHD_IOCTL_MAXLEN - (strlen(cmd->name) + 1 + (2 * sizeof(int)));
   1082 
   1083 		while (len) {
   1084 			chunk = (len > maxchunk) ? (maxchunk & ~0x3) : len;
   1085 
   1086 			/* build the iovar command */
   1087 			memset(buf, 0, DHD_IOCTL_MAXLEN);
   1088 			strcpy(buf, cmd->name);
   1089 			ptr = buf + strlen(buf) + 1;
   1090 			params[0] = addr; params[1] = chunk;
   1091 			memcpy(ptr, params, (2 * sizeof(int)));
   1092 			ptr += (2 * sizeof(int));
   1093 			addr += chunk; len -= chunk;
   1094 
   1095 			while (chunk--) {
   1096 				*ptr++ = *sptr++;
   1097 				if (sptr >= (argv[2] + patlen))
   1098 					sptr = argv[2];
   1099 			}
   1100 
   1101 			ret = dhd_set(dhd, DHD_SET_VAR, &buf[0], (ptr - buf));
   1102 			if (ret < 0)
   1103 				goto exit;
   1104 		}
   1105 	}
   1106 
   1107 exit:
   1108 	return ret;
   1109 }
   1110 
   1111 static int
   1112 dhd_idletime(void *dhd, cmd_t *cmd, char **argv)
   1113 {
   1114 	int32 idletime;
   1115 	char *endptr = NULL;
   1116 	int err = 0;
   1117 
   1118 	if (argv[1]) {
   1119 		if (!strcmp(argv[1], "never")) {
   1120 			idletime = 0;
   1121 		} else if (!strcmp(argv[1], "immediate") || !strcmp(argv[1], "immed")) {
   1122 			idletime = DHD_IDLE_IMMEDIATE;
   1123 		} else {
   1124 			idletime = strtol(argv[1], &endptr, 0);
   1125 			if (*endptr != '\0') {
   1126 				fprintf(stderr, "invalid number %s\n", argv[1]);
   1127 				err = BCME_USAGE_ERROR;
   1128 			}
   1129 		}
   1130 		if ((idletime < 0) && (idletime != DHD_IDLE_IMMEDIATE)) {
   1131 			fprintf(stderr, "invalid value %s\n", argv[1]);
   1132 			err = -1;
   1133 		}
   1134 
   1135 		if (!err) {
   1136 			strcpy(buf, "idletime");
   1137 			endptr = buf + strlen(buf) + 1;
   1138 			memcpy(endptr, &idletime, sizeof(uint32));
   1139 			endptr += sizeof(uint32);
   1140 			err = dhd_set(dhd, DHD_SET_VAR, &buf[0], (endptr - buf));
   1141 		}
   1142 	} else {
   1143 		if ((err = dhd_var_get(dhd, cmd, argv))) {
   1144 			return err;
   1145 		} else {
   1146 			idletime = *(int32*)buf;
   1147 
   1148 			if (idletime == 0) {
   1149 				printf("0 (never)\n");
   1150 			} else if (idletime == DHD_IDLE_IMMEDIATE) {
   1151 				printf("-1 (immediate)\n");
   1152 			} else if (idletime > 0) {
   1153 				printf("%d\n", idletime);
   1154 			} else printf("%d (invalid)\n", idletime);
   1155 		}
   1156 	}
   1157 	return err;
   1158 }
   1159 
   1160 static int
   1161 dhd_idleclock(void *dhd, cmd_t *cmd, char **argv)
   1162 {
   1163 	int32 idleclock;
   1164 	char *endptr = NULL;
   1165 	int err = 0;
   1166 
   1167 	if (argv[1]) {
   1168 		if (!strcmp(argv[1], "active")) {
   1169 			idleclock = DHD_IDLE_ACTIVE;
   1170 		} else if (!strcmp(argv[1], "stopped")) {
   1171 			idleclock = DHD_IDLE_STOP;
   1172 		} else {
   1173 			idleclock = strtol(argv[1], &endptr, 0);
   1174 			if (*endptr != '\0') {
   1175 				fprintf(stderr, "invalid number %s\n", argv[1]);
   1176 				err = BCME_USAGE_ERROR;
   1177 			}
   1178 		}
   1179 
   1180 		if (!err) {
   1181 			strcpy(buf, "idleclock");
   1182 			endptr = buf + strlen(buf) + 1;
   1183 			memcpy(endptr, &idleclock, sizeof(int32));
   1184 			endptr += sizeof(int32);
   1185 			err = dhd_set(dhd, DHD_SET_VAR, &buf[0], (endptr - buf));
   1186 		}
   1187 	} else {
   1188 		if ((err = dhd_var_get(dhd, cmd, argv))) {
   1189 			return err;
   1190 		} else {
   1191 			idleclock = *(int32*)buf;
   1192 
   1193 			if (idleclock == DHD_IDLE_ACTIVE)
   1194 				printf("Idleclock %d (active)\n", idleclock);
   1195 			else if (idleclock == DHD_IDLE_STOP)
   1196 				printf("Idleclock %d (stopped)\n", idleclock);
   1197 			else
   1198 				printf("Idleclock divisor %d\n", idleclock);
   1199 		}
   1200 	}
   1201 	return err;
   1202 }
   1203 
   1204 /* Word count for a 4kb SPROM */
   1205 #define SPROM_WORDS 256
   1206 
   1207 static int
   1208 dhd_sprom(void *dhd, cmd_t *cmd, char **argv)
   1209 {
   1210 #if !defined(BWL_FILESYSTEM_SUPPORT)
   1211 	return (-1);
   1212 #else
   1213 	int ret, i;
   1214 	uint argc;
   1215 	char *endptr;
   1216 	char *bufp, *countptr;
   1217 	uint16 *wordptr;
   1218 	uint offset, words, bytes;
   1219 	bool nocrc = FALSE;
   1220 
   1221 	char *fname;
   1222 	FILE *fp;
   1223 
   1224 	UNUSED_PARAMETER(cmd);
   1225 
   1226 	/* arg count */
   1227 	for (argc = 0; argv[argc]; argc++);
   1228 	argc--;
   1229 
   1230 	/* init buffer */
   1231 	bufp = buf;
   1232 	memset(bufp, 0, DHD_IOCTL_MAXLEN);
   1233 	strcpy(bufp, "sprom");
   1234 	bufp += strlen("sprom") + 1;
   1235 
   1236 	if (strcmp(argv[0], "srdump") == 0) {
   1237 		if (argc) {
   1238 			fprintf(stderr, "Command srdump doesn't take args\n");
   1239 			return BCME_USAGE_ERROR;
   1240 		}
   1241 		offset = 0;
   1242 		words = SPROM_WORDS;
   1243 		bytes = 2 * words;
   1244 
   1245 		memcpy(bufp, &offset, sizeof(int));
   1246 		bufp += sizeof(int);
   1247 		memcpy(bufp, &bytes, sizeof(int));
   1248 		bufp += sizeof(int);
   1249 
   1250 		if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) {
   1251 			fprintf(stderr, "Internal error: unaligned word buffer\n");
   1252 			return BCME_ERROR;
   1253 		}
   1254 	} else {
   1255 		if (strcmp(argv[0], "srwrite") != 0) {
   1256 			fprintf(stderr, "Unimplemented sprom command: %s\n", argv[0]);
   1257 			return BCME_USAGE_ERROR;
   1258 		}
   1259 
   1260 		if (argc == 0) {
   1261 			return BCME_USAGE_ERROR;
   1262 		} else if ((argc == 1) ||
   1263 		           ((argc == 2) && ((nocrc = !strcmp(argv[1], "-c"))))) {
   1264 
   1265 			fname = nocrc ? argv[2] : argv[1];
   1266 
   1267 			/* determine and validate file size */
   1268 			if ((ret = file_size(fname)) < 0)
   1269 				return BCME_ERROR;
   1270 
   1271 			bytes = ret;
   1272 			offset = 0;
   1273 			words = bytes / 2;
   1274 
   1275 			if (bytes != 2 * SPROM_WORDS) {
   1276 				fprintf(stderr, "Bad file size\n");
   1277 				return BCME_ERROR;
   1278 			}
   1279 
   1280 			memcpy(bufp, &offset, sizeof(int));
   1281 			bufp += sizeof(int);
   1282 			memcpy(bufp, &bytes, sizeof(int));
   1283 			bufp += sizeof(int);
   1284 
   1285 			if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) {
   1286 				fprintf(stderr, "Internal error: unaligned word buffer\n");
   1287 				return BCME_ERROR;
   1288 			}
   1289 
   1290 			if ((fp = fopen(fname, "rb")) == NULL) {
   1291 				fprintf(stderr, "Could not open %s: %s\n",
   1292 				        fname, strerror(errno));
   1293 				return BCME_ERROR;
   1294 			}
   1295 
   1296 			if (fread((uint16*)bufp, sizeof(uint16), words, fp) != words) {
   1297 				fprintf(stderr, "Could not read %d bytes from %s\n",
   1298 				        words * 2, fname);
   1299 				fclose(fp);
   1300 				return BCME_ERROR;
   1301 			}
   1302 
   1303 			fclose(fp);
   1304 
   1305 			if (!nocrc &&
   1306 			    hndcrc8((uint8*)bufp, bytes, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
   1307 				fprintf(stderr, "CRC check failed: 0x%02x, should be 0x%02x.\n",
   1308 				        ((uint8*)bufp)[bytes-1],
   1309 				        ~hndcrc8((uint8*)bufp, bytes - 1, CRC8_INIT_VALUE) & 0xff);
   1310 				return BCME_ERROR;
   1311 			}
   1312 
   1313 			ltoh16_buf(bufp, bytes);
   1314 		} else {
   1315 			offset = strtoul(*++argv, &endptr, 0) * 2;
   1316 			if (*endptr != '\0') {
   1317 				fprintf(stderr, "offset %s is not an integer\n", *argv);
   1318 				return BCME_USAGE_ERROR;
   1319 			}
   1320 
   1321 			memcpy(bufp, &offset, sizeof(int));
   1322 			bufp += sizeof(int);
   1323 			countptr = bufp;
   1324 			bufp += sizeof(int);
   1325 
   1326 			if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) {
   1327 				fprintf(stderr, "Internal error: unaligned word buffer\n");
   1328 				return BCME_ERROR;
   1329 			}
   1330 
   1331 			for (words = 0, wordptr = (uint16*)bufp; *++argv; words++) {
   1332 				*wordptr++ = (uint16)strtoul(*argv, &endptr, 0);
   1333 				if (*endptr != '\0') {
   1334 					fprintf(stderr, "value %s is not an integer\n", *argv);
   1335 					return BCME_USAGE_ERROR;
   1336 				}
   1337 				if (words > SPROM_WORDS) {
   1338 					fprintf(stderr, "max of %d words\n", SPROM_WORDS);
   1339 					return BCME_USAGE_ERROR;
   1340 				}
   1341 			}
   1342 
   1343 			bytes = 2 * words;
   1344 			memcpy(countptr, &bytes, sizeof(int));
   1345 		}
   1346 	}
   1347 
   1348 	if (argc) {
   1349 		ret = dhd_set(dhd, DHD_SET_VAR, buf,
   1350 		              (strlen("sprom") + 1) + (2 * sizeof(int)) + bytes);
   1351 		return (ret);
   1352 	} else {
   1353 		ret = dhd_get(dhd, DHD_GET_VAR, buf,
   1354 		              (strlen("sprom") + 1) + (2 * sizeof(int)) + bytes);
   1355 		if (ret < 0) {
   1356 			return ret;
   1357 		}
   1358 
   1359 		for (i = 0; i < (int)words; i++) {
   1360 			if ((i % 8) == 0)
   1361 				printf("\n  srom[%03d]:  ", i);
   1362 			printf("0x%04x  ", ((uint16*)buf)[i]);
   1363 		}
   1364 		printf("\n");
   1365 	}
   1366 
   1367 	return 0;
   1368 #endif /* BWL_FILESYSTEM_SUPPORT */
   1369 }
   1370 
   1371 /*
   1372  * read_vars: reads an environment variables file into a buffer,
   1373  * reformatting them and returning the length (-1 on error).
   1374  *
   1375  * The input text file consists of lines of the form "<var>=<value>\n".
   1376  * CRs are ignored, as are blank lines and comments beginning with '#'.
   1377  *
   1378  * The output buffer consists of blocks of the form "<var>=<value>\0"
   1379  * (the newlines have been replaced by NULs)
   1380  *
   1381  * Todo: allow quoted variable names and quoted values.
   1382 */
   1383 
   1384 #if defined(BWL_FILESYSTEM_SUPPORT)
   1385 static int
   1386 read_vars(char *fname, char *buf, int buf_maxlen)
   1387 {
   1388 	FILE *fp;
   1389 	int buf_len, slen;
   1390 	char line[256], *s, *e;
   1391 	int line_no = 0;
   1392 
   1393 	if ((fp = fopen(fname, "rb")) == NULL) {
   1394 		fprintf(stderr, "Cannot open NVRAM file %s: %s\n",
   1395 		        fname, strerror(errno));
   1396 		exit(1);
   1397 	}
   1398 
   1399 	buf_len = 0;
   1400 
   1401 	while (fgets(line, sizeof(line), fp) != NULL) {
   1402 		bool found_eq = FALSE;
   1403 
   1404 		/* Ensure line length is limited */
   1405 		line[sizeof(line) - 1] = 0;
   1406 
   1407 		/* Skip any initial white space */
   1408 		for (s = line; *s == ' ' || *s == '\t'; s++)
   1409 			;
   1410 
   1411 		/* Determine end of string */
   1412 		for (e = s; *e != 0 && *e != '#' && *e != '\r' && *e != '\n'; e++)
   1413 			if (*e == '=')
   1414 				found_eq = TRUE;
   1415 
   1416 		/* Strip any white space from end of string */
   1417 		while (e > s && (e[-1] == ' ' || e[-1] == '\t'))
   1418 			e--;
   1419 
   1420 		slen = e - s;
   1421 
   1422 		/* Skip lines that end up blank */
   1423 		if (slen == 0)
   1424 			continue;
   1425 
   1426 		if (!found_eq) {
   1427 			fprintf(stderr, "Invalid line %d in NVRAM file %s\n", line_no, fname);
   1428 			fclose(fp);
   1429 			return -1;
   1430 		}
   1431 
   1432 		if (buf_len + slen + 1 > buf_maxlen) {
   1433 			fprintf(stderr, "NVRAM file %s too long\n", fname);
   1434 			fclose(fp);
   1435 			return -1;
   1436 		}
   1437 
   1438 		memcpy(buf + buf_len, s, slen);
   1439 		buf_len += slen;
   1440 		buf[buf_len++] = 0;
   1441 	}
   1442 
   1443 	fclose(fp);
   1444 
   1445 	return buf_len;
   1446 }
   1447 #endif   /* BWL_FILESYSTEM_SUPPORT */
   1448 
   1449 static int
   1450 dhd_vars(void *dhd, cmd_t *cmd, char **argv)
   1451 {
   1452 	int ret;
   1453 	uint argc;
   1454 	char *bufp;
   1455 
   1456 	UNUSED_PARAMETER(cmd);
   1457 
   1458 	/* arg count */
   1459 	for (argc = 0; argv[argc]; argc++);
   1460 	argc--;
   1461 
   1462 	switch (argc) {
   1463 	case 0: /* get */
   1464 	{
   1465 		if ((ret = dhd_var_getbuf(dhd, "vars", NULL, 0, (void**)&bufp)))
   1466 			break;
   1467 		while (*bufp) {
   1468 			printf("%s\n", bufp);
   1469 			bufp += strlen(bufp) + 1;
   1470 		}
   1471 	}
   1472 	break;
   1473 
   1474 #if defined(BWL_FILESYSTEM_SUPPORT)
   1475 	case 1: /* set */
   1476 	{
   1477 		char *vname;
   1478 		uint nvram_len;
   1479 
   1480 		vname = argv[1];
   1481 
   1482 		bufp = buf;
   1483 		strcpy(bufp, "vars");
   1484 		bufp += strlen("vars") + 1;
   1485 
   1486 		if ((ret = read_vars(vname, bufp,
   1487 		                           DHD_IOCTL_MAXLEN - (strlen("vars") + 3))) < 0) {
   1488 			ret = -1;
   1489 			break;
   1490 		}
   1491 
   1492 		nvram_len = ret;
   1493 		bufp += nvram_len;
   1494 		*bufp++ = 0;
   1495 
   1496 		ret = dhd_set(dhd, DHD_SET_VAR, buf, bufp - buf);
   1497 	}
   1498 	break;
   1499 #endif   /* BWL_FILESYSTEM_SUPPORT */
   1500 
   1501 	default:
   1502 		ret = -1;
   1503 		break;
   1504 	}
   1505 
   1506 	return ret;
   1507 }
   1508 
   1509 #define MEMBLOCK 2048
   1510 
   1511 /* Check that strlen("membytes")+1 + 2*sizeof(int32) + MEMBLOCK <= DHD_IOCTL_MAXLEN */
   1512 #if (MEMBLOCK + 17 > DHD_IOCTL_MAXLEN)
   1513 #error MEMBLOCK/DHD_IOCTL_MAXLEN sizing
   1514 #endif
   1515 
   1516 
   1517 #if defined(BWL_FILESYSTEM_SUPPORT)
   1518 static int
   1519 dhd_verify_file_bytes(void *dhd, uint8 *memblock, int start, uint len)
   1520 {
   1521 	int ret = 0;
   1522 	uint i = 0;
   1523 	char *ptr;
   1524 	int params[2];
   1525 	uint8 *src, *dst;
   1526 
   1527 	params[0] = start;
   1528 	params[1] = len;
   1529 	ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
   1530 	if (ret) {
   1531 		fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
   1532 		__FUNCTION__, len, start);
   1533 		return ret;
   1534 	}
   1535 
   1536 	src = (uint8 *)memblock;
   1537 	dst = (uint8 *)ptr;
   1538 	while (i < len) {
   1539 		if (src[i] != dst[i]) {
   1540 			fprintf(stderr, "   0x%x: exp[0x%02X] != got[0x%02X]\n",
   1541 				start+i, src[i], dst[i]);
   1542 			ret = -1;
   1543 		}
   1544 		i++;
   1545 	}
   1546 
   1547 	return ret;
   1548 }
   1549 
   1550 static int
   1551 dhd_load_file_bytes(void *dhd, cmd_t *cmd, FILE *fp, int fsize, int start, uint blk_sz, bool verify)
   1552 {
   1553 	int tot_len = 0;
   1554 	uint read_len;
   1555 	char *bufp;
   1556 	uint len;
   1557 	uint8 memblock[MEMBLOCK];
   1558 	int ret;
   1559 	int retry;
   1560 
   1561 	UNUSED_PARAMETER(cmd);
   1562 
   1563 	if (!fsize || !fp)
   1564 		return -1;
   1565 
   1566 	assert(blk_sz <= MEMBLOCK);
   1567 
   1568 	while (tot_len < fsize) {
   1569 		read_len = fsize - tot_len;
   1570 		if (read_len >= blk_sz) {
   1571 			read_len = blk_sz;
   1572 
   1573 			if (!ISALIGNED(start, MEMBLOCK))
   1574 				read_len = ROUNDUP(start, MEMBLOCK) - start;
   1575 		}
   1576 
   1577 		len = fread(memblock, sizeof(uint8), read_len, fp);
   1578 		if ((len < read_len) && !feof(fp)) {
   1579 			fprintf(stderr, "%s: error reading file\n", __FUNCTION__);
   1580 			return -1;
   1581 
   1582 		}
   1583 		retry = 0;
   1584 failed_retry:
   1585 
   1586 		bufp = buf;
   1587 		memset(bufp, 0, DHD_IOCTL_MAXLEN);
   1588 		strcpy(bufp, "membytes");
   1589 		bufp += strlen("membytes") + 1;
   1590 		memcpy(bufp, &start, sizeof(int));
   1591 		bufp += sizeof(int);
   1592 		memcpy(bufp, &len, sizeof(int));
   1593 		bufp += sizeof(int);
   1594 		memcpy(bufp, memblock, len);
   1595 
   1596 		ret = dhd_set(dhd, DHD_SET_VAR, &buf[0], (bufp - buf + len));
   1597 
   1598 		if (ret) {
   1599 			fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
   1600 			        __FUNCTION__, ret, len, start);
   1601 			return ret;
   1602 		}
   1603 
   1604 		if (verify == TRUE) {
   1605 			if (dhd_verify_file_bytes(dhd, memblock, start, len) != 0) {
   1606 				if (retry++ < 5000)
   1607 				{
   1608 					fprintf(stderr, "%s: verify failed %d membytes "
   1609 						"from 0x%08x\n", __FUNCTION__, len, start);
   1610 					goto failed_retry;
   1611 				}
   1612 			}
   1613 		}
   1614 
   1615 		start += len;
   1616 		tot_len += len;
   1617 	}
   1618 	return 0;
   1619 }
   1620 #endif   /* BWL_FILESYSTEM_SUPPORT */
   1621 
   1622 #ifdef PROP_TXSTATUS
   1623 static int
   1624 dhd_proptxstatusenable(void *dhd, cmd_t *cmd, char **argv)
   1625 {
   1626 	int flag = 0xdead;
   1627 	int ret;
   1628 
   1629 	if (argv[1]) {
   1630 		flag = atoi(argv[1]);
   1631 		ret = dhd_iovar_setint(dhd, cmd->name, flag);
   1632 	}
   1633 	else {
   1634 		ret = dhd_iovar_getint(dhd, cmd->name, &flag);
   1635 		if (ret >= 0)
   1636 			printf("proptxstatus: %d\n", flag);
   1637 	}
   1638 	return ret;
   1639 }
   1640 
   1641 static int
   1642 dhd_proptxstatusmode(void *dhd, cmd_t *cmd, char **argv)
   1643 {
   1644 	int mode = 0xdead;
   1645 	int ret;
   1646 
   1647 	if (argv[1]) {
   1648 		mode = atoi(argv[1]);
   1649 		ret = dhd_iovar_setint(dhd, cmd->name, mode);
   1650 	}
   1651 	else {
   1652 		ret = dhd_iovar_getint(dhd, cmd->name, &mode);
   1653 		if (ret >= 0)
   1654 			printf("proptxstatusmode: %d\n", mode);
   1655 	}
   1656 	return ret;
   1657 }
   1658 
   1659 static int
   1660 dhd_proptxopt(void *dhd, cmd_t *cmd, char **argv)
   1661 {
   1662 	int flag = 0xdead;
   1663 	int ret;
   1664 
   1665 	if (argv[1]) {
   1666 		flag = atoi(argv[1]);
   1667 		ret = dhd_iovar_setint(dhd, cmd->name, flag);
   1668 	}
   1669 	else {
   1670 		ret = dhd_iovar_getint(dhd, cmd->name, &flag);
   1671 		if (ret >= 0)
   1672 			printf("proptx_opt: %d\n", flag);
   1673 	}
   1674 	return ret;
   1675 }
   1676 
   1677 #endif /* PROP_TXSTATUS */
   1678 
   1679 static int
   1680 dhd_get_ramstart(void *dhd, uint32 *ramstart)
   1681 {
   1682 	int ret;
   1683 	char *ramstart_args[] = {"ramstart", NULL};
   1684 
   1685 	/* Read the bus type the DHD driver is associated to */
   1686 	if ((ret = dhd_var_get(dhd, NULL, ramstart_args)) != BCME_OK) {
   1687 		fprintf(stderr, "%s: error obtaining ramstart\n", __FUNCTION__);
   1688 
   1689 		return ret;
   1690 	}
   1691 
   1692 	*ramstart = *(uint32 *)buf;
   1693 
   1694 	return BCME_OK;
   1695 }
   1696 
   1697 static int
   1698 dhd_download(void *dhd, cmd_t *cmd, char **argv)
   1699 {
   1700 #if !defined(BWL_FILESYSTEM_SUPPORT)
   1701 	return (-1);
   1702 #else
   1703 	bool reset = TRUE;
   1704 	bool run = TRUE;
   1705 	bool verify = FALSE;
   1706 	char *fname = NULL;
   1707 	char *vname = NULL;
   1708 	uint32 start;
   1709 	int ret = 0;
   1710 	int fsize;
   1711 	uint32 bustype;
   1712 	long filepos;
   1713 
   1714 	FILE *fp = NULL;
   1715 	uint32 ramsize;
   1716 	char *memszargs[] = { "ramsize", NULL };
   1717 
   1718 	char *bufp;
   1719 
   1720 	miniopt_t opts;
   1721 	int opt_err;
   1722 	uint nvram_len;
   1723 	struct trx_header trx_hdr;
   1724 	uint32 trx_hdr_len;
   1725 	bool trx_file = FALSE;
   1726 	uint memblock_sz = MEMBLOCK;
   1727 	bool embedded_ucode = FALSE;
   1728 
   1729 	UNUSED_PARAMETER(cmd);
   1730 
   1731 	if ((ret = dhd_get_ramstart(dhd, &start)) != BCME_OK)
   1732 		goto exit;
   1733 
   1734 	/* Parse command-line options */
   1735 	miniopt_init(&opts, "download", "", TRUE);
   1736 
   1737 	argv++;
   1738 	while ((opt_err = miniopt(&opts, argv)) != -1) {
   1739 		if (opt_err == 1) {
   1740 			fprintf(stderr, "download options error\n");
   1741 			ret = -1;
   1742 			goto exit;
   1743 		}
   1744 		argv += opts.consumed;
   1745 
   1746 		if (opts.opt == 'a') {
   1747 			if (!opts.good_int) {
   1748 				fprintf(stderr, "invalid address %s\n", opts.valstr);
   1749 				ret = -1;
   1750 				goto exit;
   1751 			}
   1752 			start = (uint32)opts.uval;
   1753 		} else if (opts.positional) {
   1754 			if (fname && vname) {
   1755 				fprintf(stderr, "extra positional arg, %s\n",
   1756 				        opts.valstr);
   1757 				ret = -1;
   1758 				goto exit;
   1759 			}
   1760 			if (fname)
   1761 				vname = opts.valstr;
   1762 			else
   1763 				fname = opts.valstr;
   1764 		} else if (!opts.opt) {
   1765 			if (!strcmp(opts.key, "noreset")) {
   1766 				reset = FALSE;
   1767 			} else if (!strcmp(opts.key, "norun")) {
   1768 				run = FALSE;
   1769 			} else if (!strcmp(opts.key, "verify")) {
   1770 				verify = TRUE;
   1771 			} else {
   1772 				fprintf(stderr, "unrecognized option %s\n", opts.valstr);
   1773 				ret = -1;
   1774 				goto exit;
   1775 			}
   1776 		} else {
   1777 			fprintf(stderr, "unrecognized option %c\n", opts.opt);
   1778 			ret = -1;
   1779 			goto exit;
   1780 		}
   1781 	}
   1782 
   1783 	/* validate arguments */
   1784 	if (!fname) {
   1785 		fprintf(stderr, "filename required\n");
   1786 		ret = -1;
   1787 		goto exit;
   1788 	}
   1789 
   1790 	/* validate file size compared to memory size */
   1791 	if ((fsize = file_size(fname)) < 0) {
   1792 		ret = -1;
   1793 		goto exit;
   1794 	}
   1795 	/* read the file and push blocks down to memory */
   1796 	if ((fp = fopen(fname, "rb")) == NULL) {
   1797 		fprintf(stderr, "%s: unable to open %s: %s\n",
   1798 		        __FUNCTION__, fname, strerror(errno));
   1799 		ret = -1;
   1800 		goto exit;
   1801 	}
   1802 	/* Verify the file is a regular bin file or trx file */
   1803 	{
   1804 		uint32 tmp_len;
   1805 		trx_hdr_len = sizeof(struct trx_header);
   1806 		tmp_len = fread(&trx_hdr, sizeof(uint8), trx_hdr_len, fp);
   1807 		if (tmp_len == trx_hdr_len) {
   1808 			if (trx_hdr.magic == TRX_MAGIC) {
   1809 				trx_file = TRUE;
   1810 				if (trx_hdr.flag_version & TRX_EMBED_UCODE)
   1811 					embedded_ucode = TRUE;
   1812 			}
   1813 			else
   1814 				fseek(fp, 0, SEEK_SET);
   1815 		}
   1816 		else
   1817 			fseek(fp, 0, SEEK_SET);
   1818 	}
   1819 
   1820 	/* Check on which bus the dhd driver is sitting. Downloading methodology differs from
   1821 	 * USB to SDIO.
   1822 	 */
   1823 	{
   1824 		char* bustype_args[] = {"bustype", NULL};
   1825 
   1826 		/* Read the bus type the DHD driver is associated to */
   1827 		if ((ret = dhd_var_get(dhd, NULL, bustype_args))) {
   1828 			fprintf(stderr, "%s: error obtaining bustype\n", __FUNCTION__);
   1829 			goto exit;
   1830 		}
   1831 
   1832 		bustype = *(uint32*)buf;
   1833 	}
   1834 
   1835 	if (trx_file)
   1836 		fsize = (int)(trx_hdr.offsets[0]);
   1837 
   1838 	if (bustype == BUS_TYPE_SDIO) {
   1839 		if ((ret = dhd_var_get(dhd, NULL, memszargs))) {
   1840 			fprintf(stderr, "%s: error obtaining ramsize\n", __FUNCTION__);
   1841 			goto exit;
   1842 		}
   1843 		ramsize = *(uint32*)buf;
   1844 	}
   1845 
   1846 
   1847 	BCM_REFERENCE(ramsize);
   1848 
   1849 	/* do the download reset if not suppressed */
   1850 	if (reset) {
   1851 		if ((ret = dhd_iovar_setint(dhd, "dwnldstate", TRUE))) {
   1852 			fprintf(stderr, "%s: failed to put dongle in download mode\n",
   1853 			        __FUNCTION__);
   1854 			goto exit;
   1855 		}
   1856 	}
   1857 
   1858 #define RDL_CHUNK	1500  /* size of each dl transfer */
   1859 
   1860 	if (BUS_TYPE_USB == bustype) {
   1861 		/* store the cur pos pointing to base image which should be written */
   1862 		filepos = ftell(fp);
   1863 		if (filepos == -1) {
   1864 			fprintf(stderr, "%s: ftell failed.\n", __FUNCTION__);
   1865 		}
   1866 
   1867 		/* In case of USB, we need to write header information also to dongle. */
   1868 		fseek(fp, 0, SEEK_SET);
   1869 
   1870 		/* The file size is "base_image + TRX_Header_size" */
   1871 		fsize = (int)(trx_hdr.offsets[0] + sizeof(struct trx_header));
   1872 
   1873 		memblock_sz = RDL_CHUNK;
   1874 	}
   1875 
   1876 
   1877 	/* Load the ram image */
   1878 	if ((ret = dhd_load_file_bytes(dhd, cmd, fp, fsize, start, memblock_sz, verify))) {
   1879 		fprintf(stderr, "%s: error loading the ramimage at addr 0x%x\n",
   1880 		        __FUNCTION__, start);
   1881 		goto exit;
   1882 	}
   1883 
   1884 	if (trx_file) {
   1885 
   1886 		filepos = ftell(fp);
   1887 		if (filepos == -1) {
   1888 			fprintf(stderr, "%s: ftell failed.\n", __FUNCTION__);
   1889 		}
   1890 
   1891 		if (BUS_TYPE_SDIO == bustype) {
   1892 
   1893 		}
   1894 	}
   1895 
   1896 	fclose(fp);
   1897 	fp = NULL;
   1898 
   1899 	/* download the vars file if specified */
   1900 	if (vname) {
   1901 		bufp = buf;
   1902 		strcpy(bufp, "vars");
   1903 		bufp += strlen("vars") + 1;
   1904 
   1905 		if ((ret = read_vars(vname, bufp,
   1906 		                           DHD_IOCTL_MAXLEN - (strlen("vars") + 3))) < 0) {
   1907 			ret = -1;
   1908 			goto exit;
   1909 		}
   1910 
   1911 		nvram_len = ret;
   1912 		bufp += nvram_len;
   1913 		*bufp++ = 0;
   1914 
   1915 		ret = dhd_set(dhd, DHD_SET_VAR, buf, (bufp - buf));
   1916 		if (ret) {
   1917 			fprintf(stderr, "%s: error %d on delivering vars\n",
   1918 			        __FUNCTION__, ret);
   1919 			goto exit;
   1920 		}
   1921 	}
   1922 
   1923 	/* start running the downloaded code if not suppressed */
   1924 	if (run) {
   1925 		if ((ret = dhd_iovar_setint(dhd, "dwnldstate", FALSE))) {
   1926 
   1927 			fprintf(stderr, "%s: failed to take dongle out of download mode\n",
   1928 			        __FUNCTION__);
   1929 			/* USB Error return values */
   1930 			if (BUS_TYPE_USB == bustype) {
   1931 				if (ret == -1)
   1932 					fprintf(stderr, "%s: CPU is not in RUNNABLE State\n",
   1933 						__FUNCTION__);
   1934 				else
   1935 					fprintf(stderr, "%s: Error in setting CPU to RUN mode.\n",
   1936 						__FUNCTION__);
   1937 			}
   1938 			goto exit;
   1939 		}
   1940 	}
   1941 	if (embedded_ucode) {
   1942 	}
   1943 
   1944 exit:
   1945 	if (fp)
   1946 		fclose(fp);
   1947 
   1948 	return ret;
   1949 #endif /* BWL_FILESYSTEM_SUPPORT */
   1950 }
   1951 
   1952 static int
   1953 dhd_dldn(void *dhd, cmd_t *cmd, char **argv)
   1954 {
   1955 #if !defined(BWL_FILESYSTEM_SUPPORT)
   1956 	return (-1);
   1957 #else
   1958 	char *fname = NULL;
   1959 	uint32 start;
   1960 	int ret = 0;
   1961 	int fsize;
   1962 	int fd = 0;
   1963 
   1964 	FILE *fp = NULL;
   1965 	uint32 ramsize;
   1966 
   1967 	uint len;
   1968 	uint8 memblock[MEMBLOCK];
   1969 
   1970 	miniopt_t opts;
   1971 	int opt_err;
   1972 
   1973 	UNUSED_PARAMETER(cmd);
   1974 
   1975 	/* Parse command-line options */
   1976 	miniopt_init(&opts, "download", "", TRUE);
   1977 	argv++;
   1978 
   1979 	while ((opt_err = miniopt(&opts, argv)) != -1) {
   1980 		if (opt_err == 1) {
   1981 			fprintf(stderr, "download options error\n");
   1982 			ret = -1;
   1983 			goto exit;
   1984 		}
   1985 		argv += opts.consumed;
   1986 
   1987 		if (opts.positional) {
   1988 			if (fname) {
   1989 				fprintf(stderr, "extra positional arg, %s\n",
   1990 				        opts.valstr);
   1991 				ret = -1;
   1992 				goto exit;
   1993 			}
   1994 			if (!fname)
   1995 				fname = opts.valstr;
   1996 		} else {
   1997 			fprintf(stderr, "unrecognized option %c\n", opts.opt);
   1998 			ret = -1;
   1999 			goto exit;
   2000 		}
   2001 	}
   2002 
   2003 	fd = dhd_set(dhd, DHD_DLDN_ST, NULL, 0);
   2004 	if (fd < 0) {
   2005 		ret = -1;
   2006 		goto exit;
   2007 	}
   2008 
   2009 	/* validate arguments */
   2010 	if (!fname) {
   2011 		fprintf(stderr, "filename required\n");
   2012 		ret = -1;
   2013 		goto exit;
   2014 	}
   2015 
   2016 	/* validate file size compared to memory size */
   2017 	if ((fsize = file_size(fname)) < 0) {
   2018 		ret = -1;
   2019 		goto exit;
   2020 	}
   2021 
   2022 	ramsize = 393216;
   2023 
   2024 	if (ramsize && ((uint32)fsize > ramsize)) {
   2025 		fprintf(stderr, "%s: file %s too large (%d > %d)\n",
   2026 		        __FUNCTION__, fname, fsize, ramsize);
   2027 		ret = -1;
   2028 		goto exit;
   2029 	}
   2030 
   2031 	/* read the file and push blocks down to memory */
   2032 	if ((fp = fopen(fname, "rb")) == NULL) {
   2033 		fprintf(stderr, "%s: unable to open %s: %s\n",
   2034 		        __FUNCTION__, fname, strerror(errno));
   2035 		ret = -1;
   2036 		goto exit;
   2037 	}
   2038 
   2039 	if ((ret = dhd_get_ramstart(dhd, &start)) != BCME_OK)
   2040 		goto exit;
   2041 
   2042 	while ((len = fread(memblock, sizeof(uint8), MEMBLOCK, fp))) {
   2043 		if (len < MEMBLOCK && !feof(fp)) {
   2044 			fprintf(stderr, "%s: error reading file %s\n", __FUNCTION__, fname);
   2045 			ret = -1;
   2046 			goto exit;
   2047 		}
   2048 
   2049 		ret = dhd_set(dhd, DHD_DLDN_WRITE, memblock, len);
   2050 		if (ret) {
   2051 			fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
   2052 			        __FUNCTION__, ret, len, start);
   2053 			goto exit;
   2054 		}
   2055 
   2056 		start += len;
   2057 	}
   2058 
   2059 	if (!feof(fp)) {
   2060 		fprintf(stderr, "%s: error reading file %s\n", __FUNCTION__, fname);
   2061 		ret = -1;
   2062 		goto exit;
   2063 	}
   2064 	fclose(fp);
   2065 	fp = NULL;
   2066 
   2067 exit:
   2068 	if (fp)
   2069 		fclose(fp);
   2070 
   2071 	if (fd)
   2072 		ret = dhd_set(dhd, DHD_DLDN_END, NULL, 0);
   2073 
   2074 	return ret;
   2075 #endif /* BWL_FILESYSTEM_SUPPORT */
   2076 }
   2077 
   2078 static int
   2079 dhd_upload(void *dhd, cmd_t *cmd, char **argv)
   2080 {
   2081 #if !defined(BWL_FILESYSTEM_SUPPORT)
   2082 	return (-1);
   2083 #else
   2084 	char *fname = NULL;
   2085 	uint32 start;
   2086 	uint32 size = 0;
   2087 	int ret = 0;
   2088 
   2089 	FILE *fp;
   2090 	uint32 ramsize;
   2091 	char *memszargs[] = { "ramsize", NULL };
   2092 
   2093 	uint len;
   2094 
   2095 	miniopt_t opts;
   2096 	int opt_err;
   2097 
   2098 	UNUSED_PARAMETER(cmd);
   2099 	UNUSED_PARAMETER(argv);
   2100 
   2101 	if ((ret = dhd_get_ramstart(dhd, &start)) != BCME_OK)
   2102 		goto exit;
   2103 
   2104 	/* Parse command-line options */
   2105 	miniopt_init(&opts, "upload", "", TRUE);
   2106 
   2107 	argv++;
   2108 	while ((opt_err = miniopt(&opts, argv)) != -1) {
   2109 		if (opt_err == 1) {
   2110 			fprintf(stderr, "upload options error\n");
   2111 			ret = -1;
   2112 			goto exit;
   2113 		}
   2114 		argv += opts.consumed;
   2115 
   2116 		if (opts.opt == 'a') {
   2117 			if (!opts.good_int) {
   2118 				fprintf(stderr, "invalid address %s\n", opts.valstr);
   2119 				ret = -1;
   2120 				goto exit;
   2121 			}
   2122 			start = (uint32)opts.uval;
   2123 		} else if (opts.positional) {
   2124 			if (!fname) {
   2125 				fname = opts.valstr;
   2126 			} else if (opts.good_int) {
   2127 				size = (uint32)opts.uval;
   2128 			} else {
   2129 				fprintf(stderr, "upload options error\n");
   2130 				ret = -1;
   2131 				goto exit;
   2132 			}
   2133 		} else if (!opts.opt) {
   2134 			fprintf(stderr, "unrecognized option %s\n", opts.valstr);
   2135 			ret = -1;
   2136 			goto exit;
   2137 		} else {
   2138 			fprintf(stderr, "unrecognized option %c\n", opts.opt);
   2139 			ret = -1;
   2140 			goto exit;
   2141 		}
   2142 	}
   2143 
   2144 	/* validate arguments */
   2145 	if (!fname) {
   2146 		fprintf(stderr, "filename required\n");
   2147 		ret = -1;
   2148 		goto exit;
   2149 	}
   2150 
   2151 	if ((ret = dhd_var_get(dhd, NULL, memszargs))) {
   2152 		fprintf(stderr, "%s: error obtaining ramsize\n", __FUNCTION__);
   2153 		goto exit;
   2154 	}
   2155 	ramsize = *(uint32*)buf;
   2156 
   2157 	if (!ramsize)
   2158 		ramsize = size;
   2159 
   2160 	if ((fp = fopen(fname, "wb")) == NULL) {
   2161 		fprintf(stderr, "%s: Could not open %s: %s\n",
   2162 		        __FUNCTION__, fname, strerror(errno));
   2163 		ret = -1;
   2164 		goto exit;
   2165 	}
   2166 
   2167 	/* default size to full RAM */
   2168 	if (!size)
   2169 		size = ramsize;
   2170 
   2171 	/* read memory and write to file */
   2172 	while (size) {
   2173 		char *ptr;
   2174 		int params[2];
   2175 
   2176 		len = MIN(MEMBLOCK, size);
   2177 
   2178 		params[0] = start;
   2179 		params[1] = len;
   2180 		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
   2181 		if (ret) {
   2182 			fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
   2183 			        __FUNCTION__, len, start);
   2184 			break;
   2185 		}
   2186 
   2187 		if (fwrite(ptr, sizeof(char), len, fp) != len) {
   2188 			fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
   2189 			ret = -1;
   2190 			break;
   2191 		}
   2192 
   2193 		start += len;
   2194 		size -= len;
   2195 	}
   2196 
   2197 	fclose(fp);
   2198 exit:
   2199 	return ret;
   2200 #endif /* BWL_FILESYSTEM_SUPPORT */
   2201 }
   2202 
   2203 #ifdef BWL_FILESYSTEM_SUPPORT
   2204 static int
   2205 dhd_get_debug_info(void *dhd, hndrte_debug_t *debug_info)
   2206 {
   2207 	int i;
   2208 	int ret;
   2209 	int params[2];
   2210 
   2211 	uint32 *buffer;
   2212 	uint32 debug_info_ptr;
   2213 	uint32 ramstart;
   2214 
   2215 	if ((ret = dhd_get_ramstart(dhd, &ramstart)) != BCME_OK)
   2216 		return ret;
   2217 
   2218 	/*
   2219 	 * Different chips have different fixed debug_info_ptrs
   2220 	 * because of different ROM locations/uses.  Try them all looking
   2221 	 * for the magic number.
   2222 	 */
   2223 	for (i = 0; ; i++) {
   2224 		if (debug_info_ptrs[i] == DEBUG_INFO_PTRS_END) {
   2225 			fprintf(stderr, "Error: cannot find pointer to debug_info\n");
   2226 			return -1;
   2227 		}
   2228 
   2229 		params[0] = debug_info_ptrs[i] + ramstart;
   2230 		params[1] = 8;
   2231 		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&buffer);
   2232 		if ((ret == 0) &&
   2233 		    (*buffer == HNDRTE_DEBUG_PTR_PTR_MAGIC)) {
   2234 			break;
   2235 		}
   2236 	}
   2237 
   2238 	debug_info_ptr = *(buffer + 1);
   2239 	if (debug_info_ptr == 0) {
   2240 		fprintf(stderr, "Error: Debug info pointer is zero\n");
   2241 		return -1;
   2242 	}
   2243 
   2244 	/* Read the area the debuginfoptr points at */
   2245 	params[0] = debug_info_ptr;
   2246 	params[1] = sizeof(hndrte_debug_t);
   2247 	ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&buffer);
   2248 	if (ret) {
   2249 		fprintf(stderr, "%s: failed reading %lu membytes from 0x%08lx\n",
   2250 			__FUNCTION__, (long unsigned) params[1], (long unsigned) params[0]);
   2251 		return ret;
   2252 	}
   2253 
   2254 	memcpy((char *) debug_info, buffer, sizeof(hndrte_debug_t));
   2255 
   2256 	/* Sanity check the area */
   2257 	if ((debug_info->magic != HNDRTE_DEBUG_MAGIC) ||
   2258 	    (debug_info->version != HNDRTE_DEBUG_VERSION)) {
   2259 		fprintf(stderr, "Error: Invalid debug info area\n");
   2260 		return -1;
   2261 	}
   2262 
   2263 	return 0;
   2264 }
   2265 #endif /* BWL_FILESYSTEM_SUPPORT */
   2266 
   2267 static int
   2268 dhd_coredump(void *dhd, cmd_t *cmd, char **argv)
   2269 {
   2270 #if !defined(BWL_FILESYSTEM_SUPPORT)
   2271 	return (-1);
   2272 #else
   2273 	char *fname = NULL;
   2274 	int ret;
   2275 
   2276 	FILE *fp;
   2277 
   2278 	hndrte_debug_t debugInfo;
   2279 
   2280 	miniopt_t opts;
   2281 	int opt_err;
   2282 
   2283 	int params[2];
   2284 	char *ptr;
   2285 
   2286 	unsigned int start;
   2287 	unsigned int size;
   2288 
   2289 	prstatus_t prstatus;
   2290 
   2291 	UNUSED_PARAMETER(cmd);
   2292 	UNUSED_PARAMETER(argv);
   2293 
   2294 	/* Parse command-line options */
   2295 	miniopt_init(&opts, "dump", "", TRUE);
   2296 
   2297 	argv++;
   2298 	while ((opt_err = miniopt(&opts, argv)) != -1) {
   2299 		if (opt_err == 1) {
   2300 			fprintf(stderr, "dump options error\n");
   2301 			ret = -1;
   2302 			goto exit;
   2303 		}
   2304 		argv += opts.consumed;
   2305 
   2306 		if (opts.positional) {
   2307 			if (!fname) {
   2308 				fname = opts.valstr;
   2309 			} else {
   2310 				fprintf(stderr, "dump options error\n");
   2311 				ret = -1;
   2312 				goto exit;
   2313 			}
   2314 		} else if (!opts.opt) {
   2315 			fprintf(stderr, "unrecognized option %s\n", opts.valstr);
   2316 			ret = -1;
   2317 			goto exit;
   2318 		} else {
   2319 			fprintf(stderr, "unrecognized option %c\n", opts.opt);
   2320 			ret = -1;
   2321 			goto exit;
   2322 		}
   2323 	}
   2324 
   2325 	/* validate arguments */
   2326 	if (!fname) {
   2327 		fprintf(stderr, "filename required\n");
   2328 		ret = -1;
   2329 		goto exit;
   2330 	}
   2331 
   2332 	if ((ret = dhd_get_debug_info(dhd, &debugInfo)) < 0)
   2333 		goto exit;
   2334 
   2335 	/* Get the base and size to dump */
   2336 	start = debugInfo.ram_base;
   2337 	size = debugInfo.ram_size;
   2338 
   2339 	/* Get the arm trap area */
   2340 	bzero(&prstatus, sizeof(prstatus_t));
   2341 	if (debugInfo.trap_ptr != 0) {
   2342 		int i;
   2343 		trap_t armtrap;
   2344 		uint32 *reg;
   2345 
   2346 		params[0] = debugInfo.trap_ptr;
   2347 		params[1] = sizeof(trap_t);
   2348 		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
   2349 		if (ret) {
   2350 			fprintf(stderr, "%s: failed reading %lu membytes from 0x%08lx\n",
   2351 				__FUNCTION__, (long unsigned) params[1], (long unsigned) params[0]);
   2352 			goto exit;
   2353 		}
   2354 
   2355 		memcpy((char *) &armtrap, ptr, sizeof(trap_t));
   2356 
   2357 		/* Populate the prstatus */
   2358 		prstatus.si_signo = armtrap.type;
   2359 		reg = &armtrap.r0;
   2360 		for (i = 0; i < 15; i++, reg++) {
   2361 			prstatus.uregs[i] = *reg;
   2362 		}
   2363 		prstatus.uregs[15] = armtrap.epc;
   2364 	}
   2365 
   2366 	if ((fp = fopen(fname, "wb")) == NULL) {
   2367 		fprintf(stderr, "%s: Could not open %s: %s\n",
   2368 		        __FUNCTION__, fname, strerror(errno));
   2369 		ret = -1;
   2370 		goto exit;
   2371 	}
   2372 
   2373 	/* Write the preamble and debug header */
   2374 	fprintf(fp, "Dump starts for version %s FWID 01-%x\n", debugInfo.epivers, debugInfo.fwid);
   2375 	fprintf(fp, "XXXXXXXXXXXXXXXXXXXX");
   2376 	fprintf(fp, "%8.8lX", (long unsigned) sizeof(debugInfo));
   2377 	if (fwrite(&debugInfo, sizeof(unsigned char), sizeof(debugInfo), fp) != sizeof(debugInfo)) {
   2378 		fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
   2379 		ret = -1;
   2380 		fclose(fp);
   2381 		goto exit;
   2382 	}
   2383 
   2384 	/* Write the prstatus */
   2385 	if (fwrite(&prstatus, sizeof(unsigned char), sizeof(prstatus), fp) != sizeof(prstatus)) {
   2386 		fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
   2387 		ret = -1;
   2388 		fclose(fp);
   2389 		goto exit;
   2390 	}
   2391 
   2392 	/* Write the ram size as another sanity check */
   2393 	fprintf(fp, "%8.8X", size);
   2394 
   2395 	/* read memory and write to file */
   2396 	while (size) {
   2397 		int len;
   2398 		len = MIN(MEMBLOCK, size);
   2399 
   2400 		params[0] = start;
   2401 		params[1] = len;
   2402 		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
   2403 		if (ret) {
   2404 			fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
   2405 			        __FUNCTION__, len, start);
   2406 			break;
   2407 		}
   2408 
   2409 		if (fwrite(ptr, sizeof(char), len, fp) != (uint) len) {
   2410 			fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname);
   2411 			ret = -1;
   2412 			break;
   2413 		}
   2414 
   2415 		start += len;
   2416 		size -= len;
   2417 	}
   2418 
   2419 	fclose(fp);
   2420 exit:
   2421 	return ret;
   2422 #endif /* BWL_FILESYSTEM_SUPPORT */
   2423 }
   2424 
   2425 static int
   2426 dhd_consoledump(void *dhd, cmd_t *cmd, char **argv)
   2427 {
   2428 #if !defined(BWL_FILESYSTEM_SUPPORT)
   2429 	return (-1);
   2430 #else
   2431 	int ret;
   2432 
   2433 	hndrte_debug_t debugInfo;
   2434 
   2435 	miniopt_t opts;
   2436 	int opt_err;
   2437 
   2438 	int params[2];
   2439 	char *ptr;
   2440 
   2441 	unsigned int start;
   2442 	unsigned int size;
   2443 	int len;
   2444 
   2445 	UNUSED_PARAMETER(cmd);
   2446 	UNUSED_PARAMETER(argv);
   2447 
   2448 	/* Parse command-line options */
   2449 	miniopt_init(&opts, "consoledump", "", TRUE);
   2450 
   2451 	argv++;
   2452 	while ((opt_err = miniopt(&opts, argv)) != -1) {
   2453 		if (opt_err == 1) {
   2454 			fprintf(stderr, "dump options error\n");
   2455 			ret = -1;
   2456 			goto exit;
   2457 		}
   2458 		argv += opts.consumed;
   2459 
   2460 		if (!opts.opt) {
   2461 			fprintf(stderr, "unrecognized option %s\n", opts.valstr);
   2462 			ret = -1;
   2463 			goto exit;
   2464 		} else {
   2465 			fprintf(stderr, "unrecognized option %c\n", opts.opt);
   2466 			ret = -1;
   2467 			goto exit;
   2468 		}
   2469 	}
   2470 
   2471 	if ((ret = dhd_get_debug_info(dhd, &debugInfo)) < 0)
   2472 		goto exit;
   2473 
   2474 	if (debugInfo.console <= debugInfo.ram_base) {
   2475 		fprintf(stderr, "%s: console not found\n", __FUNCTION__);
   2476 		ret = -1;
   2477 		goto exit;
   2478 	}
   2479 
   2480 	/* Get the debug console area */
   2481 	params[0] = debugInfo.console;
   2482 	params[1] = sizeof(hndrte_cons_t);
   2483 	ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
   2484 	if (ret) {
   2485 		fprintf(stderr, "%s: failed reading %lu membytes from 0x%08lx\n",
   2486 			__FUNCTION__, (long unsigned) params[1], (long unsigned) params[0]);
   2487 		goto exit;
   2488 	}
   2489 
   2490 	if (ptr == NULL) {
   2491 		fprintf(stderr, "%s: console not initialised\n", __FUNCTION__);
   2492 		ret = -1;
   2493 		goto exit;
   2494 	}
   2495 
   2496 	start = (unsigned int)((hndrte_cons_t *)ptr)->log.buf;
   2497 	size = ((hndrte_cons_t *)ptr)->log.buf_size;
   2498 
   2499 	if (start <= debugInfo.ram_base) {
   2500 		fprintf(stderr, "%s: console buffer not initialised\n", __FUNCTION__);
   2501 		ret = -1;
   2502 		goto exit;
   2503 	}
   2504 
   2505 	/* read memory and write to file */
   2506 	while (size > 0) {
   2507 		len = MIN(MEMBLOCK, size);
   2508 
   2509 		params[0] = start;
   2510 		params[1] = len;
   2511 		ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr);
   2512 		if (ret) {
   2513 			fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n",
   2514 			        __FUNCTION__, len, start);
   2515 			break;
   2516 		}
   2517 
   2518 		printf("%s", ptr);
   2519 
   2520 		start += len;
   2521 		size -= len;
   2522 	}
   2523 
   2524 exit:
   2525 	return ret;
   2526 #endif /* BWL_FILESYSTEM_SUPPORT */
   2527 }
   2528 
   2529 static int
   2530 dhd_logstamp(void *dhd, cmd_t *cmd, char **argv)
   2531 {
   2532 	int ret;
   2533 	char *endptr = NULL;
   2534 	uint argc;
   2535 	int valn[2] = {0, 0};
   2536 
   2537 	/* arg count */
   2538 	for (argc = 0; argv[argc]; argc++);
   2539 	argc--; argv++;
   2540 
   2541 	if (argc > 2)
   2542 		return BCME_USAGE_ERROR;
   2543 
   2544 	if (argc) {
   2545 		valn[0] = strtol(argv[0], &endptr, 0);
   2546 		if (*endptr != '\0') {
   2547 			printf("bad val1: %s\n", argv[0]);
   2548 			return BCME_USAGE_ERROR;
   2549 		}
   2550 	}
   2551 
   2552 	if (argc > 1) {
   2553 		valn[1] = strtol(argv[1], &endptr, 0);
   2554 		if (*endptr != '\0') {
   2555 			printf("bad val2: %s\n", argv[1]);
   2556 			return BCME_USAGE_ERROR;
   2557 		}
   2558 	}
   2559 
   2560 	ret = dhd_var_setbuf(dhd, cmd->name, valn, argc * sizeof(int));
   2561 
   2562 	return (ret);
   2563 }
   2564 
   2565 static int
   2566 dhd_sd_reg(void *dhd, cmd_t *cmd, char **argv)
   2567 {
   2568 	int ret;
   2569 	sdreg_t sdreg;
   2570 	char *endptr = NULL;
   2571 	uint argc;
   2572 	void *ptr = NULL;
   2573 
   2574 	bzero(&sdreg, sizeof(sdreg));
   2575 
   2576 	/* arg count */
   2577 	for (argc = 0; argv[argc]; argc++);
   2578 	argc--;
   2579 
   2580 	/* hostreg: offset [value]; devreg: func offset [value] */
   2581 	if (!strcmp(cmd->name, "sd_hostreg")) {
   2582 		argv++;
   2583 		if (argc < 1) {
   2584 			printf("required args: offset [value]\n");
   2585 			return BCME_USAGE_ERROR;
   2586 		}
   2587 
   2588 	} else if (!strcmp(cmd->name, "sd_devreg")) {
   2589 		argv++;
   2590 		if (argc < 2) {
   2591 			printf("required args: func offset [value]\n");
   2592 			return BCME_USAGE_ERROR;
   2593 		}
   2594 
   2595 		sdreg.func = strtoul(*argv++, &endptr, 0);
   2596 		if (*endptr != '\0') {
   2597 			printf("Invalid function number\n");
   2598 			return BCME_USAGE_ERROR;
   2599 		}
   2600 	} else {
   2601 		return BCME_USAGE_ERROR;
   2602 	}
   2603 
   2604 	sdreg.offset = strtoul(*argv++, &endptr, 0);
   2605 	if (*endptr != '\0') {
   2606 		printf("Invalid offset value\n");
   2607 		return BCME_USAGE_ERROR;
   2608 	}
   2609 
   2610 	/* third arg: value */
   2611 	if (*argv) {
   2612 		sdreg.value = strtoul(*argv, &endptr, 0);
   2613 		if (*endptr != '\0') {
   2614 			printf("Invalid value\n");
   2615 			return BCME_USAGE_ERROR;
   2616 		}
   2617 	}
   2618 
   2619 	/* no third arg means get, otherwise set */
   2620 	if (!*argv) {
   2621 		if ((ret = dhd_var_getbuf(dhd, cmd->name, &sdreg, sizeof(sdreg), &ptr)) >= 0)
   2622 			printf("0x%x\n", *(int *)ptr);
   2623 	} else {
   2624 		ret = dhd_var_setbuf(dhd, cmd->name, &sdreg, sizeof(sdreg));
   2625 	}
   2626 
   2627 	return (ret);
   2628 }
   2629 
   2630 static dbg_msg_t dhd_msgs[] = {
   2631 	{DHD_ERROR_VAL,	"error"},
   2632 	{DHD_ERROR_VAL, "err"},
   2633 	{DHD_TRACE_VAL, "trace"},
   2634 	{DHD_INFO_VAL,	"inform"},
   2635 	{DHD_INFO_VAL,	"info"},
   2636 	{DHD_INFO_VAL,	"inf"},
   2637 	{DHD_DATA_VAL,	"data"},
   2638 	{DHD_CTL_VAL,	"ctl"},
   2639 	{DHD_TIMER_VAL,	"timer"},
   2640 	{DHD_HDRS_VAL,	"hdrs"},
   2641 	{DHD_BYTES_VAL,	"bytes"},
   2642 	{DHD_INTR_VAL,	"intr"},
   2643 	{DHD_LOG_VAL,	"log"},
   2644 	{DHD_GLOM_VAL,	"glom"},
   2645 	{DHD_EVENT_VAL,	"event"},
   2646 	{DHD_BTA_VAL,	"bta"},
   2647 	{DHD_ISCAN_VAL,	"iscan"},
   2648 	{DHD_ARPOE_VAL,	"arpoe"},
   2649 	{DHD_REORDER_VAL, "reorder"},
   2650 	{0,		NULL}
   2651 };
   2652 
   2653 static int
   2654 dhd_msglevel(void *dhd, cmd_t *cmd, char **argv)
   2655 {
   2656 	return dhd_do_msglevel(dhd, cmd, argv, dhd_msgs);
   2657 }
   2658 
   2659 static int
   2660 dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg)
   2661 {
   2662 	int ret, i;
   2663 	uint val, last_val = 0, msglevel = 0, msglevel_add = 0, msglevel_del = 0;
   2664 	char *endptr = NULL;
   2665 
   2666 	if ((ret = dhd_iovar_getint(dhd, cmd->name, (int*)&msglevel)) < 0)
   2667 		return (ret);
   2668 
   2669 	if (!*++argv) {
   2670 		printf("0x%x ", msglevel);
   2671 		for (i = 0; (val = dbg_msg[i].value); i++) {
   2672 			if ((msglevel & val) && (val != last_val))
   2673 				printf(" %s", dbg_msg[i].string);
   2674 			last_val = val;
   2675 		}
   2676 		printf("\n");
   2677 		return (0);
   2678 	}
   2679 
   2680 	while (*argv) {
   2681 		char *s = *argv;
   2682 		if (*s == '+' || *s == '-')
   2683 			s++;
   2684 		else
   2685 			msglevel_del = ~0;	/* make the whole list absolute */
   2686 		val = strtoul(s, &endptr, 0);
   2687 		/* not a plain integer if not all the string was parsed by strtoul */
   2688 		if (*endptr != '\0') {
   2689 			for (i = 0; (val = dbg_msg[i].value); i++)
   2690 				if (stricmp(dbg_msg[i].string, s) == 0)
   2691 					break;
   2692 			if (!val)
   2693 				goto usage;
   2694 		}
   2695 		if (**argv == '-')
   2696 			msglevel_del |= val;
   2697 		else
   2698 			msglevel_add |= val;
   2699 		++argv;
   2700 	}
   2701 
   2702 	msglevel &= ~msglevel_del;
   2703 	msglevel |= msglevel_add;
   2704 
   2705 	return (dhd_iovar_setint(dhd, cmd->name, msglevel));
   2706 
   2707 usage:
   2708 	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
   2709 	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
   2710 
   2711 	for (i = 0; (val = dbg_msg[i].value); i++) {
   2712 		if (val != last_val)
   2713 			fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string);
   2714 		else
   2715 			fprintf(stderr, ", %s", dbg_msg[i].string);
   2716 		last_val = val;
   2717 	}
   2718 	fprintf(stderr, "\n");
   2719 
   2720 	return 0;
   2721 }
   2722 
   2723 static char *
   2724 ver2str(unsigned int vms, unsigned int vls)
   2725 {
   2726 	static char verstr[100];
   2727 	unsigned int maj, year, month, day, build;
   2728 
   2729 	maj = (vms >> 16) & 0xFFFF;
   2730 	if (maj > 1000) {
   2731 		/* it is probably a date... */
   2732 		year = (vms >> 16) & 0xFFFF;
   2733 		month = vms & 0xFFFF;
   2734 		day = (vls >> 16) & 0xFFFF;
   2735 		build = vls & 0xFFFF;
   2736 		sprintf(verstr, "%d/%d/%d build %d",
   2737 			month, day, year, build);
   2738 	} else {
   2739 		/* it is a tagged release. */
   2740 		sprintf(verstr, "%d.%d RC%d.%d",
   2741 			(vms>>16)&0xFFFF, vms&0xFFFF,
   2742 			(vls>>16)&0xFFFF, vls&0xFFFF);
   2743 	}
   2744 	return verstr;
   2745 }
   2746 
   2747 static int
   2748 dhd_version(void *dhd, cmd_t *cmd, char **argv)
   2749 {
   2750 	int ret;
   2751 	char *ptr;
   2752 
   2753 	UNUSED_PARAMETER(cmd);
   2754 	UNUSED_PARAMETER(argv);
   2755 
   2756 	/* Display the application version info */
   2757 	printf("%s: %s\n", dhdu_av0,
   2758 		ver2str((EPI_MAJOR_VERSION << 16)| EPI_MINOR_VERSION,
   2759 		(EPI_RC_NUMBER << 16) | EPI_INCREMENTAL_NUMBER));
   2760 
   2761 	if ((ret = dhd_var_getbuf(dhd, cmd->name, NULL, 0, (void**)&ptr)) < 0)
   2762 		return ret;
   2763 
   2764 	/* Display the returned string */
   2765 	printf("%s\n", ptr);
   2766 
   2767 	return 0;
   2768 }
   2769 
   2770 static int
   2771 dhd_var_setint(void *dhd, cmd_t *cmd, char **argv)
   2772 {
   2773 	int32 val;
   2774 	int len;
   2775 	char *varname;
   2776 	char *endptr = NULL;
   2777 	char *p;
   2778 
   2779 	if (cmd->set == -1) {
   2780 		printf("set not defined for %s\n", cmd->name);
   2781 		return BCME_ERROR;
   2782 	}
   2783 
   2784 	if (!*argv) {
   2785 		printf("set: missing arguments\n");
   2786 		return BCME_USAGE_ERROR;
   2787 	}
   2788 
   2789 	varname = *argv++;
   2790 
   2791 	if (!*argv) {
   2792 		printf("set: missing value argument for set of \"%s\"\n", varname);
   2793 		return BCME_USAGE_ERROR;
   2794 	}
   2795 
   2796 	val = strtol(*argv, &endptr, 0);
   2797 	if (*endptr != '\0') {
   2798 		/* not all the value string was parsed by strtol */
   2799 		printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n",
   2800 			*argv, varname);
   2801 		return BCME_USAGE_ERROR;
   2802 	}
   2803 
   2804 	strcpy(buf, varname);
   2805 	p = buf;
   2806 	while (*p != '\0') {
   2807 		*p = tolower(*p);
   2808 		p++;
   2809 	}
   2810 
   2811 	/* skip the NUL */
   2812 	p++;
   2813 
   2814 	memcpy(p, &val, sizeof(uint));
   2815 	len = (p - buf) +  sizeof(uint);
   2816 
   2817 	return (dhd_set(dhd, DHD_SET_VAR, &buf[0], len));
   2818 }
   2819 
   2820 static int
   2821 dhd_var_get(void *dhd, cmd_t *cmd, char **argv)
   2822 {
   2823 	char *varname;
   2824 	char *p;
   2825 
   2826 	UNUSED_PARAMETER(cmd);
   2827 
   2828 	if (!*argv) {
   2829 		printf("get: missing arguments\n");
   2830 		return BCME_USAGE_ERROR;
   2831 	}
   2832 
   2833 	varname = *argv++;
   2834 
   2835 	if (*argv) {
   2836 		printf("get: error, extra arg \"%s\"\n", *argv);
   2837 		return BCME_USAGE_ERROR;
   2838 	}
   2839 
   2840 	strcpy(buf, varname);
   2841 	p = buf;
   2842 	while (*p != '\0') {
   2843 		*p = tolower(*p);
   2844 		p++;
   2845 	}
   2846 	return (dhd_get(dhd, DHD_GET_VAR, &buf[0], DHD_IOCTL_MAXLEN));
   2847 }
   2848 
   2849 static int
   2850 dhd_var_getint(void *dhd, cmd_t *cmd, char **argv)
   2851 {
   2852 	int err;
   2853 	int32 val;
   2854 	if (cmd->get == -1) {
   2855 		printf("get not defined for %s\n", cmd->name);
   2856 		return BCME_ERROR;
   2857 	}
   2858 
   2859 	if ((err = dhd_var_get(dhd, cmd, argv)))
   2860 		return (err);
   2861 
   2862 	val = *(int32*)buf;
   2863 
   2864 	if (val < 10)
   2865 		printf("%d\n", val);
   2866 	else
   2867 		printf("%d (0x%x)\n", val, val);
   2868 
   2869 	return (0);
   2870 }
   2871 
   2872 static int
   2873 dhd_var_getandprintstr(void *dhd, cmd_t *cmd, char **argv)
   2874 {
   2875 	int err;
   2876 
   2877 	if ((err = dhd_var_get(dhd, cmd, argv)))
   2878 		return (err);
   2879 
   2880 	printf("%s\n", buf);
   2881 	return (0);
   2882 }
   2883 
   2884 
   2885 void
   2886 dhd_printlasterror(void *dhd)
   2887 {
   2888 	char *cmd[2] = {"bcmerrorstr"};
   2889 
   2890 	if (dhd_var_get(dhd, NULL, cmd) != 0) {
   2891 		fprintf(stderr, "%s: \nError getting the last error\n", dhdu_av0);
   2892 	} else {
   2893 		fprintf(stderr, "%s: %s\n", dhdu_av0, buf);
   2894 	}
   2895 }
   2896 
   2897 static int
   2898 dhd_varint(void *dhd, cmd_t *cmd, char *argv[])
   2899 {
   2900 	if (argv[1])
   2901 		return (dhd_var_setint(dhd, cmd, argv));
   2902 	else
   2903 		return (dhd_var_getint(dhd, cmd, argv));
   2904 }
   2905 
   2906 static int
   2907 dhd_var_getbuf(void *dhd, char *iovar, void *param, int param_len, void **bufptr)
   2908 {
   2909 	int len;
   2910 
   2911 	memset(buf, 0, DHD_IOCTL_MAXLEN);
   2912 	strcpy(buf, iovar);
   2913 
   2914 	/* include the NUL */
   2915 	len = strlen(iovar) + 1;
   2916 
   2917 	if (param_len)
   2918 		memcpy(&buf[len], param, param_len);
   2919 
   2920 	*bufptr = buf;
   2921 
   2922 	return dhd_get(dhd, DHD_GET_VAR, &buf[0], DHD_IOCTL_MAXLEN);
   2923 }
   2924 
   2925 static int
   2926 dhd_var_setbuf(void *dhd, char *iovar, void *param, int param_len)
   2927 {
   2928 	int len;
   2929 
   2930 	memset(buf, 0, DHD_IOCTL_MAXLEN);
   2931 	strcpy(buf, iovar);
   2932 
   2933 	/* include the NUL */
   2934 	len = strlen(iovar) + 1;
   2935 
   2936 	if (param_len)
   2937 		memcpy(&buf[len], param, param_len);
   2938 
   2939 	len += param_len;
   2940 
   2941 	return dhd_set(dhd, DHD_SET_VAR, &buf[0], len);
   2942 }
   2943 
   2944 static int
   2945 dhd_var_void(void *dhd, cmd_t *cmd, char **argv)
   2946 {
   2947 	UNUSED_PARAMETER(argv);
   2948 
   2949 	if (cmd->set < 0)
   2950 		return BCME_ERROR;
   2951 
   2952 	return dhd_var_setbuf(dhd, cmd->name, NULL, 0);
   2953 }
   2954 
   2955 /*
   2956  * format an iovar buffer
   2957  */
   2958 static uint
   2959 dhd_iovar_mkbuf(char *name, char *data, uint datalen, char *buf, uint buflen, int *perr)
   2960 {
   2961 	uint len;
   2962 
   2963 	len = strlen(name) + 1;
   2964 
   2965 	/* check for overflow */
   2966 	if ((len + datalen) > buflen) {
   2967 		*perr = BCME_BUFTOOSHORT;
   2968 		return 0;
   2969 	}
   2970 
   2971 	strcpy(buf, name);
   2972 
   2973 	/* append data onto the end of the name string */
   2974 	if (datalen > 0)
   2975 		memcpy(&buf[len], data, datalen);
   2976 
   2977 	len += datalen;
   2978 
   2979 	*perr = 0;
   2980 	return len;
   2981 }
   2982 
   2983 static int
   2984 dhd_iovar_getint(void *dhd, char *name, int *var)
   2985 {
   2986 	char ibuf[DHD_IOCTL_SMLEN];
   2987 	int error;
   2988 
   2989 	dhd_iovar_mkbuf(name, NULL, 0, ibuf, sizeof(ibuf), &error);
   2990 	if (error)
   2991 		return error;
   2992 
   2993 	if ((error = dhd_get(dhd, DHD_GET_VAR, &ibuf, sizeof(ibuf))) < 0)
   2994 		return error;
   2995 
   2996 	memcpy(var, ibuf, sizeof(int));
   2997 
   2998 	return 0;
   2999 }
   3000 
   3001 static int
   3002 dhd_iovar_setint(void *dhd, char *name, int var)
   3003 {
   3004 	int len;
   3005 	char ibuf[DHD_IOCTL_SMLEN];
   3006 	int error;
   3007 
   3008 	len = dhd_iovar_mkbuf(name, (char *)&var, sizeof(var), ibuf, sizeof(ibuf), &error);
   3009 	if (error)
   3010 		return error;
   3011 
   3012 	if ((error = dhd_set(dhd, DHD_SET_VAR, &ibuf, len)) < 0)
   3013 		return error;
   3014 
   3015 	return 0;
   3016 }
   3017 
   3018 static int
   3019 dhd_varstr(void *dhd, cmd_t *cmd, char **argv)
   3020 {
   3021 	int error;
   3022 	char *str;
   3023 
   3024 	if (!*++argv) {
   3025 		void *ptr;
   3026 
   3027 		if ((error = dhd_var_getbuf(dhd, cmd->name, NULL, 0, &ptr)) < 0)
   3028 			return (error);
   3029 
   3030 		str = (char *)ptr;
   3031 		printf("%s\n", str);
   3032 		return (0);
   3033 	} else {
   3034 		str = *argv;
   3035 		/* iovar buffer length includes NUL */
   3036 		return dhd_var_setbuf(dhd, cmd->name, str, strlen(str) + 1);
   3037 	}
   3038 }
   3039 
   3040 
   3041 static int
   3042 dhd_hostreorder_flows(void *dhd, cmd_t *cmd, char **argv)
   3043 {
   3044 	int ret, count, i = 0;
   3045 	void *ptr;
   3046 	uint8 *flow_id;
   3047 
   3048 
   3049 	if ((ret = dhd_var_getbuf(dhd, cmd->name, NULL, 0, &ptr)) < 0) {
   3050 		printf("error getting reorder flows from the host\n");
   3051 		return ret;
   3052 	}
   3053 	flow_id = (uint8 *)ptr;
   3054 	count = *flow_id;
   3055 	if (!count)
   3056 		printf("there are no active flows\n");
   3057 	else {
   3058 		printf("flows(%d): \t", count);
   3059 		while (i++ < count)
   3060 			printf("%d  ", *flow_id++);
   3061 		printf("\n");
   3062 	}
   3063 	return 0;
   3064 }
   3065 
   3066 
   3067 
   3068 /* These two utility functions are used by dhdu_linux.c
   3069  * The code is taken from wlu.c.
   3070  */
   3071 int
   3072 dhd_atoip(const char *a, struct ipv4_addr *n)
   3073 {
   3074 	char *c;
   3075 	int i = 0;
   3076 
   3077 	for (;;) {
   3078 	        n->addr[i++] = (uint8)strtoul(a, &c, 0);
   3079 	        if (*c++ != '.' || i == IPV4_ADDR_LEN)
   3080 	                break;
   3081 	        a = c;
   3082 	}
   3083 	return (i == IPV4_ADDR_LEN);
   3084 }
   3085 
   3086 int
   3087 dhd_ether_atoe(const char *a, struct ether_addr *n)
   3088 {
   3089 	char *c;
   3090 	int i = 0;
   3091 
   3092 	memset(n, 0, ETHER_ADDR_LEN);
   3093 	for (;;) {
   3094 	        n->octet[i++] = (uint8)strtoul(a, &c, 16);
   3095 	        if (!*c++ || i == ETHER_ADDR_LEN)
   3096 	                break;
   3097 	        a = c;
   3098 	}
   3099 	return (i == ETHER_ADDR_LEN);
   3100 }
   3101