1/* 2 * Common code for dhd utility, hacked from wl utility 3 * 4 * Copyright (C) 1999-2010, Broadcom Corporation 5 * 6 * Unless you and Broadcom execute a separate written software license 7 * agreement governing use of this software, this software is licensed to you 8 * under the terms of the GNU General Public License version 2 (the "GPL"), 9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 * following added to such license: 11 * 12 * As a special exception, the copyright holders of this software give you 13 * permission to link this software with independent modules, and to copy and 14 * distribute the resulting executable under terms of your choice, provided that 15 * you also meet, for each linked independent module, the terms and conditions of 16 * the license of that module. An independent module is a module which is not 17 * derived from this software. The special exception does not apply to any 18 * modifications of the software. 19 * 20 * Notwithstanding the above, under no circumstances may you combine this 21 * software in any way with any other Broadcom software provided under a license 22 * other than the GPL, without Broadcom's express prior written consent. 23 * 24 * $Id: dhdu.c,v 1.52.2.10.2.6.2.14 2010/01/19 07:24:15 Exp $ 25 */ 26 27/* For backwards compatibility, the absense of the define 'BWL_NO_FILESYSTEM_SUPPORT' 28 * implies that a filesystem is supported. 29 */ 30#if !defined(BWL_NO_FILESYSTEM_SUPPORT) 31#define BWL_FILESYSTEM_SUPPORT 32#endif 33 34 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <ctype.h> 39#include <assert.h> 40 41#include <typedefs.h> 42#include <epivers.h> 43#include <proto/ethernet.h> 44#include <dhdioctl.h> 45#include <sdiovar.h> 46#include <bcmutils.h> 47#include <bcmendian.h> 48#include "dhdu.h" 49 50 51#include "miniopt.h" 52 53#include <errno.h> 54 55#include <trxhdr.h> 56 57#define stricmp strcasecmp 58#define strnicmp strncasecmp 59 60 61static cmd_func_t dhd_var_void; 62static cmd_func_t dhd_varint, dhd_varstr; 63static cmd_func_t dhd_var_getandprintstr, dhd_var_getint, dhd_var_get; 64static cmd_func_t dhd_var_setint; 65 66static cmd_func_t dhd_version, dhd_list, dhd_msglevel; 67 68#ifdef SDTEST 69static cmd_func_t dhd_pktgen; 70#endif 71static cmd_func_t dhd_sprom; 72static cmd_func_t dhd_sdreg; 73static cmd_func_t dhd_sd_msglevel, dhd_sd_blocksize, dhd_sd_mode, dhd_sd_reg; 74static cmd_func_t dhd_dma_mode; 75static cmd_func_t dhd_membytes, dhd_download, dhd_upload, dhd_vars, dhd_idleclock, dhd_idletime; 76static cmd_func_t dhd_logstamp; 77 78static int dhd_var_getbuf(void *dhd, char *iovar, void *param, int param_len, void **bufptr); 79static int dhd_var_setbuf(void *dhd, char *iovar, void *param, int param_len); 80 81static uint dhd_iovar_mkbuf(char *name, char *data, uint datalen, 82 char *buf, uint buflen, int *perr); 83static int dhd_iovar_getint(void *dhd, char *name, int *var); 84static int dhd_iovar_setint(void *dhd, char *name, int var); 85 86#if defined(BWL_FILESYSTEM_SUPPORT) 87static int file_size(char *fname); 88static int read_vars(char *fname, char *buf, int buf_maxlen); 89#endif 90 91 92 93/* dword align allocation */ 94static union { 95 char bufdata[DHD_IOCTL_MAXLEN]; 96 uint32 alignme; 97} bufstruct_dhd; 98static char *buf = (char*) &bufstruct_dhd.bufdata; 99 100/* integer output format, default to signed integer */ 101static uint8 int_fmt; 102 103typedef struct { 104 uint value; 105 char *string; 106} dbg_msg_t; 107 108static int dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg); 109 110/* Actual command table */ 111cmd_t dhd_cmds[] = { 112 { "cmds", dhd_list, -1, -1, 113 "generate a short list of available commands"}, 114 { "version", dhd_version, DHD_GET_VAR, -1, 115 "get version information" }, 116 { "msglevel", dhd_msglevel, DHD_GET_VAR, DHD_SET_VAR, 117 "get/set message bits" }, 118 { "wlmsglevel", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 119 "get/set wl message(in dhd) bits" }, 120 { "bcmerrorstr", dhd_var_getandprintstr, DHD_GET_VAR, -1, 121 "errorstring"}, 122 { "wdtick", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 123 "watchdog tick time (ms units)"}, 124 { "intr", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 125 "use interrupts on the bus"}, 126 { "pollrate", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 127 "number of ticks between bus polls (0 means no polling)"}, 128 { "idletime", dhd_idletime, DHD_GET_VAR, DHD_SET_VAR, 129 "number of ticks for activity timeout (-1: immediate, 0: never)"}, 130 { "idleclock", dhd_idleclock, DHD_GET_VAR, DHD_SET_VAR, 131 "idleclock active | stopped | <N>\n" 132 "\tactive (0) - do not request any change to the SD clock\n" 133 "\tstopped (-1) - request SD clock be stopped on activity timeout\n" 134 "\t<N> (other) - an sd_divisor value to request on activity timeout\n"}, 135 { "sd1idle", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 136 "change mode to SD1 when turning off clock at idle"}, 137 { "forceeven", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 138 "force SD tx/rx buffers to be even"}, 139 { "readahead", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 140 "enable readahead feature (look for next frame len in headers)"}, 141 { "sdrxchain", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 142 "enable packet chains to SDIO stack for glom receive"}, 143 { "alignctl", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 144 "align control frames"}, 145 { "sdalign", dhd_varint, DHD_GET_VAR, -1, 146 "display the (compiled in) alignment target for sd requests"}, 147 { "txbound", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 148 "get/set maximum number of tx frames per scheduling"}, 149 { "rxbound", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 150 "get/set maximum number of rx frames per scheduling"}, 151 { "txminmax", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 152 "get/set maximum number of tx frames per scheduling while rx frames outstanding"}, 153 { "dump", dhd_varstr, DHD_GET_VAR, -1, 154 "dump information"}, 155 { "clearcounts", dhd_var_void, -1, DHD_SET_VAR, 156 "reset the bus stats shown in the dhd dump"}, 157 { "logdump", dhd_varstr, DHD_GET_VAR, -1, 158 "dump the timestamp logging buffer"}, 159 { "logcal", dhd_varint, -1, DHD_SET_VAR, 160 "logcal <n> -- log around an osl_delay of <n> usecs"}, 161 { "logstamp", dhd_logstamp, -1, DHD_SET_VAR, 162 "logstamp [<n1>] [<n2>] -- add a message to the log"}, 163 { "memsize", dhd_varint, DHD_GET_VAR, -1, 164 "display size of onchip SOCRAM"}, 165 { "membytes", dhd_membytes, DHD_GET_VAR, DHD_SET_VAR, 166 "membytes [-h | -r | -i] <address> <length> [<bytes>]\n" 167 "\tread or write data in the dongle ram\n" 168 "\t-h <bytes> is a sequence of hex digits, else a char string\n" 169 "\t-r output as a raw write rather than hexdump display\n"}, 170 { "download", dhd_download, -1, DHD_SET_VAR, 171 "download [-a <address>] [--noreset] [--norun] <binfile> [<varsfile>]\n" 172 "\tdownload file to specified dongle ram address and start CPU\n" 173 "\toptional vars file will replace vars parsed from the CIS\n" 174 "\t--noreset do not reset SOCRAM core before download\n" 175 "\t--norun do not start dongle CPU after download\n" 176 "\tdefault <address> is 0\n"}, 177 { "vars", dhd_vars, DHD_GET_VAR, DHD_SET_VAR, 178 "vars [<file>]\n" 179 "\toverride SPROM vars with <file> (before download)\n"}, 180 { "upload", dhd_upload, -1, -1, 181 "upload [-a <address> ] <file> [<size>]\n" 182 "\tupload dongle RAM content into a file\n" 183 "\tdefault <address> is 0, default <size> is RAM size"}, 184 { "srdump", dhd_sprom, DHD_GET_VAR, -1, 185 "display SPROM content" }, 186 { "srwrite", dhd_sprom, -1, DHD_SET_VAR, 187 "write data or file content to SPROM\n" 188 "\tsrwrite <word-offset> <word-value> ...\n" 189 "\tsrwrite [-c] <srom-file-path>\n" 190 "\t -c means write regardless of crc"}, 191 { "sleep", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 192 "enter/exit simulated host sleep (bus powerdown w/OOB wakeup)"}, 193#ifdef SDTEST 194 { "extloop", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 195 "external loopback: convert all tx data to echo test frames"}, 196 { "pktgen", dhd_pktgen, DHD_GET_VAR, DHD_SET_VAR, 197 "configure/report pktgen status (SDIO)\n" 198 "\t-f N frequency: send/recv a burst every N ticks\n" 199 "\t-c N count: send/recv N packets each burst\n" 200 "\t-t N total: stop after a total of N packets\n" 201 "\t-p N print: display counts on console every N bursts\n" 202 "\t-m N min: set minimum length of packet data\n" 203 "\t-M N Max: set maximum length of packet data\n" 204 "\t-l N len: set fixed length of packet data\n" 205 "\t-s N stop after N tx failures\n" 206 "\t-d dir test direction/type:\n" 207 "\t send -- send packets discarded by dongle\n" 208 "\t echo -- send packets to be echoed by dongle\n" 209 "\t burst -- request bursts (of size <-c>) from dongle\n" 210 "\t one every <-f> ticks, until <-t> total requests\n" 211 "\t recv -- request dongle enter continuous send mode,\n" 212 "\t read up to <-c> pkts every <-f> ticks until <-t>\n" 213 "\t total reads\n"}, 214#endif /* SDTEST */ 215 { "sdreg", dhd_sdreg, DHD_GET_VAR, DHD_SET_VAR, 216 "g/set sdpcmdev core register (f1) across SDIO (CMD53)"}, 217 { "sbreg", dhd_sdreg, DHD_GET_VAR, DHD_SET_VAR, 218 "g/set any backplane core register (f1) across SDIO (CMD53)"}, 219 { "sd_cis", dhd_var_getandprintstr, DHD_GET_VAR, -1, 220 "dump sdio CIS"}, 221 { "sd_devreg", dhd_sd_reg, DHD_GET_VAR, DHD_SET_VAR, 222 "g/set device register across SDIO bus (CMD52)"}, 223 { "sd_hostreg", dhd_sd_reg, DHD_GET_VAR, DHD_SET_VAR, 224 "g/set local controller register"}, 225 { "sd_blocksize", dhd_sd_blocksize, DHD_GET_VAR, DHD_SET_VAR, 226 "g/set block size for a function"}, 227 { "sd_blockmode", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 228 "g/set blockmode"}, 229 { "sd_ints", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 230 "g/set client ints"}, 231 { "sd_dma", dhd_dma_mode, DHD_GET_VAR, DHD_SET_VAR, 232 "g/set dma usage: [PIO | SDMA | ADMA1 | ADMA2]"}, 233 { "sd_yieldcpu", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 234 "allow blocking (yield of CPU) on data xfer"}, 235 { "sd_minyield", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 236 "minimum xfer size to allow CPU yield"}, 237 { "sd_forcerb", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 238 "force readback when changing local interrupt settings"}, 239 { "sd_numints", dhd_varint, DHD_GET_VAR, -1, 240 "number of device interrupts"}, 241 { "sd_numlocalints", dhd_varint, DHD_GET_VAR, -1, 242 "number of non-device interrupts"}, 243 { "sd_divisor", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 244 "set the divisor for SDIO clock generation"}, 245 { "sd_power", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 246 "set the SD Card slot power"}, 247 { "sd_clock", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 248 "turn on/off the SD Clock"}, 249 { "sd_crc", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 250 "turn on/off CRC checking in SPI mode"}, 251 { "sd_mode", dhd_sd_mode, DHD_GET_VAR, DHD_SET_VAR, 252 "g/set SDIO bus mode (spi, sd1, sd4)"}, 253 { "sd_highspeed", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 254 "set the high-speed clocking mode"}, 255 { "sd_msglevel", dhd_sd_msglevel, DHD_GET_VAR, DHD_SET_VAR, 256 "g/set debug message level"}, 257 { "sd_hciregs", dhd_varstr, DHD_GET_VAR, -1, 258 "display host-controller interrupt registers"}, 259 { "sdiod_drive", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 260 "SDIO Device drive strength in milliamps. (0=tri-state, 1-12mA)"}, 261 { "devreset", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 262 "Move device into or out of reset state (1/reset, or 0/operational)"}, 263 { "connstatus", dhd_varstr, DHD_GET_VAR, -1, 264 "get status of last connection attempt" }, 265 { "ioctl_timeout", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, 266 "IOCTL response timeout (milliseconds)."}, 267 { NULL, NULL, 0, 0, NULL } 268}; 269 270cmd_t dhd_varcmd = {"var", dhd_varint, -1, -1, "unrecognized name, type -h for help"}; 271char *dhdu_av0; 272 273#if defined(BWL_FILESYSTEM_SUPPORT) 274static int 275file_size(char *fname) 276{ 277 FILE *fp; 278 long size = -1; 279 280 /* Can't use stat() because of Win CE */ 281 282 if ((fp = fopen(fname, "rb")) == NULL || 283 fseek(fp, 0, SEEK_END) < 0 || 284 (size = ftell(fp)) < 0) 285 fprintf(stderr, "Could not determine size of %s: %s\n", 286 fname, strerror(errno)); 287 288 if (fp != NULL) 289 fclose(fp); 290 291 return (int)size; 292} 293#endif /* BWL_FILESYSTEM_SUPPORT */ 294 295 296/* parse/validate the command line arguments */ 297/* 298* pargv is updated upon return if the first argument is an option. 299 * It remains intact otherwise. 300 */ 301int 302dhd_option(char ***pargv, char **pifname, int *phelp) 303{ 304 char *ifname = NULL; 305 int help = FALSE; 306 int status = CMD_OPT; 307 char **argv = *pargv; 308 309 int_fmt = INT_FMT_DEC; 310 311 while (*argv) { 312 /* select different adapter */ 313 if (!strcmp(*argv, "-a") || !strcmp(*argv, "-i")) { 314 char *opt = *argv++; 315 ifname = *argv; 316 if (!ifname) { 317 fprintf(stderr, 318 "error: expected interface name after option %s\n", opt); 319 status = CMD_ERR; 320 break; 321 } 322 } 323 324 /* integer output format */ 325 else if (!strcmp(*argv, "-d")) 326 int_fmt = INT_FMT_DEC; 327 else if (!strcmp(*argv, "-u")) 328 int_fmt = INT_FMT_UINT; 329 else if (!strcmp(*argv, "-x")) 330 int_fmt = INT_FMT_HEX; 331 332 /* command usage */ 333 else if (!strcmp(*argv, "-h")) 334 help = TRUE; 335 336 /* done with generic options */ 337 else { 338 status = CMD_DHD; 339 break; 340 } 341 342 /* consume the argument */ 343 argv ++; 344 break; 345 } 346 347 *phelp = help; 348 *pifname = ifname; 349 *pargv = argv; 350 351 return status; 352} 353 354void 355dhd_cmd_usage(cmd_t *cmd) 356{ 357 if (strlen(cmd->name) >= 8) 358 fprintf(stderr, "%s\n\t%s\n\n", cmd->name, cmd->help); 359 else 360 fprintf(stderr, "%s\t%s\n\n", cmd->name, cmd->help); 361} 362 363/* Dump out short list of commands */ 364static int 365dhd_list(void *dhd, cmd_t *garb, char **argv) 366{ 367 cmd_t *cmd; 368 int nrows, i, len; 369 char *buf; 370 int letter, col, row, pad; 371 372 UNUSED_PARAMETER(dhd); 373 UNUSED_PARAMETER(garb); 374 UNUSED_PARAMETER(argv); 375 376 for (cmd = dhd_cmds, nrows = 0; cmd->name; cmd++) 377 nrows++; 378 379 nrows /= 4; 380 nrows++; 381 382 len = nrows * 80 + 2; 383 buf = malloc(len); 384 if (buf == NULL) { 385 fprintf(stderr, "Failed to allocate buffer of %d bytes\n", len); 386 return COMMAND_ERROR; 387 } 388 for (i = 0; i < len; i++) 389 *(buf+i) = 0; 390 391 row = col = 0; 392 for (letter = 'a'; letter < 'z'; letter++) { 393 for (cmd = dhd_cmds; cmd->name; cmd++) { 394 if (cmd->name[0] == letter || cmd->name[0] == letter - 0x20) { 395 strcat(buf+row*80, cmd->name); 396 pad = 18 * (col + 1) - strlen(buf+row*80); 397 if (pad < 1) 398 pad = 1; 399 for (; pad; pad--) 400 strcat(buf+row*80, " "); 401 row++; 402 if (row == nrows) { 403 col++; row = 0; 404 } 405 } 406 } 407 } 408 for (row = 0; row < nrows; row++) 409 printf("%s\n", buf+row*80); 410 411 printf("\n"); 412 free(buf); 413 return (0); 414} 415 416void 417dhd_cmds_usage(cmd_t *port_cmds) 418{ 419 cmd_t *port_cmd; 420 cmd_t *cmd; 421 422 /* print usage of port commands */ 423 for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++) 424 /* Check for wc_cmd */ 425 dhd_cmd_usage(port_cmd); 426 427 /* print usage of common commands without port counterparts */ 428 for (cmd = dhd_cmds; cmd->name; cmd++) { 429 /* search if port counterpart exists */ 430 for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++) 431 if (!strcmp(port_cmd->name, cmd->name)) 432 break; 433 if (!port_cmd || !port_cmd->name) 434 dhd_cmd_usage(cmd); 435 } 436} 437 438void 439dhd_usage(cmd_t *port_cmds) 440{ 441 fprintf(stderr, 442 "Usage: %s [-a|i <adapter>] [-h] [-d|u|x] <command> [arguments]\n", 443 dhdu_av0); 444 445 fprintf(stderr, "\n"); 446 fprintf(stderr, " -h this message\n"); 447 fprintf(stderr, " -a, -i adapter name or number\n"); 448 fprintf(stderr, " -d display values as signed integer\n"); 449 fprintf(stderr, " -u display values as unsigned integer\n"); 450 fprintf(stderr, " -x display values as hexdecimal\n"); 451 fprintf(stderr, "\n"); 452 453 dhd_cmds_usage(port_cmds); 454} 455 456int 457dhd_check(void *dhd) 458{ 459 int ret; 460 int val; 461 462 if ((ret = dhd_get(dhd, DHD_GET_MAGIC, &val, sizeof(int)) < 0)) 463 return ret; 464 if (val != DHD_IOCTL_MAGIC) 465 return -1; 466 if ((ret = dhd_get(dhd, DHD_GET_VERSION, &val, sizeof(int)) < 0)) 467 return ret; 468 if (val > DHD_IOCTL_VERSION) { 469 fprintf(stderr, "Version mismatch, please upgrade\n"); 470 return -1; 471 } 472 return 0; 473} 474 475void 476dhd_printint(int val) 477{ 478 switch (int_fmt) { 479 case INT_FMT_UINT: 480 printf("%u\n", val); 481 break; 482 case INT_FMT_HEX: 483 printf("0x%x\n", val); 484 break; 485 case INT_FMT_DEC: 486 default: 487 printf("%d\n", val); 488 break; 489 } 490} 491 492/* pretty hex print a contiguous buffer (tweaked from wlu) */ 493void 494dhd_hexdump(uchar *buf, uint nbytes, uint saddr) 495{ 496 char line[256]; 497 char* p; 498 uint i; 499 500 if (nbytes == 0) { 501 printf("\n"); 502 return; 503 } 504 505 p = line; 506 for (i = 0; i < nbytes; i++) { 507 if (i % 16 == 0) { 508 p += sprintf(p, "%08x: ", saddr + i); /* line prefix */ 509 } 510 p += sprintf(p, "%02x ", buf[i]); 511 if (i % 16 == 15) { 512 uint j; 513 p += sprintf(p, " "); 514 for (j = i-15; j <= i; j++) 515 p += sprintf(p, "%c", 516 ((buf[j] >= 0x20 && buf[j] <= 0x7f) ? buf[j] : '.')); 517 printf("%s\n", line); /* flush line */ 518 p = line; 519 } 520 } 521 522 /* flush last partial line */ 523 if (p != line) 524 printf("%s\n", line); 525} 526 527 528#ifdef SDTEST 529static int 530dhd_pktgen(void *dhd, cmd_t *cmd, char **argv) 531{ 532 int ret = 0; 533 void *ptr = NULL; 534 dhd_pktgen_t pktgen; 535 char *str; 536 537 UNUSED_PARAMETER(dhd); 538 UNUSED_PARAMETER(cmd); 539 540 /* Get current settings */ 541 if ((ret = dhd_var_getbuf(dhd, "pktgen", NULL, 0, &ptr)) != 0) 542 return ret; 543 memcpy(&pktgen, ptr, sizeof(pktgen)); 544 545 if (pktgen.version != DHD_PKTGEN_VERSION) { 546 fprintf(stderr, "pktgen version mismatch (module %d app %d)\n", 547 pktgen.version, DHD_PKTGEN_VERSION); 548 return COMMAND_ERROR; 549 } 550 551 /* Presence of args implies a set, else a get */ 552 if (*++argv) { 553 miniopt_t opts; 554 int opt_err; 555 556 /* Initialize option parser */ 557 miniopt_init(&opts, "pktgen", "", FALSE); 558 559 while ((opt_err = miniopt(&opts, argv)) != -1) { 560 if (opt_err == 1) { 561 fprintf(stderr, "pktgen options error\n"); 562 ret = -1; 563 goto exit; 564 } 565 argv += opts.consumed; 566 567 if (!opts.good_int && opts.opt != 'd') { 568 fprintf(stderr, "invalid integer %s\n", opts.valstr); 569 ret = -1; 570 goto exit; 571 } 572 573 switch (opts.opt) { 574 case 'f': 575 pktgen.freq = opts.uval; 576 break; 577 case 'c': 578 pktgen.count = opts.uval; 579 break; 580 case 'p': 581 pktgen.print = opts.uval; 582 break; 583 case 't': 584 pktgen.total = opts.uval; 585 break; 586 case 's': 587 pktgen.stop = opts.uval; 588 break; 589 case 'm': 590 pktgen.minlen = opts.uval; 591 break; 592 case 'M': 593 pktgen.maxlen = opts.uval; 594 break; 595 case 'l': case 'L': 596 pktgen.minlen = pktgen.maxlen = opts.uval; 597 break; 598 case 'd': 599 if (!strcmp(opts.valstr, "send")) 600 pktgen.mode = DHD_PKTGEN_SEND; 601 else if (!strcmp(opts.valstr, "echo")) 602 pktgen.mode = DHD_PKTGEN_ECHO; 603 else if (!strcmp(opts.valstr, "burst")) 604 pktgen.mode = DHD_PKTGEN_RXBURST; 605 else if (!strcmp(opts.valstr, "recv")) 606 pktgen.mode = DHD_PKTGEN_RECV; 607 else { 608 fprintf(stderr, "unrecognized dir mode %s\n", 609 opts.valstr); 610 return USAGE_ERROR; 611 } 612 break; 613 614 default: 615 fprintf(stderr, "option parsing error (key %s valstr %s)\n", 616 opts.key, opts.valstr); 617 ret = USAGE_ERROR; 618 goto exit; 619 } 620 } 621 622 if (pktgen.maxlen < pktgen.minlen) { 623 fprintf(stderr, "min/max error (%d/%d)\n", pktgen.minlen, pktgen.maxlen); 624 ret = -1; 625 goto exit; 626 } 627 628 /* Set the new values */ 629 ret = dhd_var_setbuf(dhd, "pktgen", &pktgen, sizeof(pktgen)); 630 } else { 631 printf("Counts: %d send attempts, %d received, %d tx failures\n", 632 pktgen.numsent, pktgen.numrcvd, pktgen.numfail); 633 } 634 635 /* Show configuration in either case */ 636 switch (pktgen.mode) { 637 case DHD_PKTGEN_ECHO: str = "echo"; break; 638 case DHD_PKTGEN_SEND: str = "send"; break; 639 case DHD_PKTGEN_RECV: str = "recv"; break; 640 case DHD_PKTGEN_RXBURST: str = "burst"; break; 641 default: str = "UNKNOWN"; break; 642 } 643 644 printf("Config: mode %s %d pkts (len %d-%d) each %d ticks\n", 645 str, pktgen.count, pktgen.minlen, pktgen.maxlen, pktgen.freq); 646 647 /* Second config line for optional items */ 648 str = " "; 649 if (pktgen.total) { 650 printf("%slimit %d", str, pktgen.total); 651 str = ", "; 652 } 653 if (pktgen.print) { 654 printf("%sprint every %d ticks", str, (pktgen.freq * pktgen.print)); 655 str = ", "; 656 } 657 if (pktgen.stop) { 658 printf("%sstop after %d tx failures", str, pktgen.stop); 659 str = ", "; 660 } 661 if (str[0] == ',') 662 printf("\n"); 663 664exit: 665 return ret; 666} 667#endif /* SDTEST */ 668 669static dbg_msg_t dhd_sd_msgs[] = { 670 {SDH_ERROR_VAL, "error"}, 671 {SDH_TRACE_VAL, "trace"}, 672 {SDH_INFO_VAL, "info"}, 673 {SDH_DATA_VAL, "data"}, 674 {SDH_CTRL_VAL, "control"}, 675 {SDH_LOG_VAL, "log"}, 676 {SDH_DMA_VAL, "dma"}, 677 {0, NULL} 678}; 679 680static int 681dhd_sd_msglevel(void *dhd, cmd_t *cmd, char **argv) 682{ 683 return dhd_do_msglevel(dhd, cmd, argv, dhd_sd_msgs); 684} 685 686static int 687dhd_sd_blocksize(void *dhd, cmd_t *cmd, char **argv) 688{ 689 int ret; 690 int argc; 691 char *endptr = NULL; 692 void *ptr = NULL; 693 int func, size; 694 695 /* arg count */ 696 for (argc = 0; argv[argc]; argc++); 697 argc--; 698 699 if (argc < 1 || argc > 2) { 700 printf("required args: function [size] (size 0 means max)\n"); 701 return USAGE_ERROR; 702 } 703 704 func = strtol(argv[1], &endptr, 0); 705 if (*endptr != '\0') { 706 printf("Invaild function: %s\n", argv[1]); 707 return USAGE_ERROR; 708 } 709 710 if (argc > 1) { 711 size = strtol(argv[2], &endptr, 0); 712 if (*endptr != '\0') { 713 printf("Invalid size: %s\n", argv[1]); 714 return USAGE_ERROR; 715 } 716 } 717 718 if (argc == 1) { 719 if ((ret = dhd_var_getbuf(dhd, cmd->name, &func, sizeof(func), &ptr)) >= 0) 720 printf("Function %d block size: %d\n", func, *(int*)ptr); 721 } else { 722 printf("Setting function %d block size to %d\n", func, size); 723 size &= 0x0000ffff; size |= (func << 16); 724 ret = dhd_var_setbuf(dhd, cmd->name, &size, sizeof(size)); 725 } 726 727 return (ret); 728} 729 730static int 731dhd_sd_mode(void *wl, cmd_t *cmd, char **argv) 732{ 733 int ret; 734 int argc; 735 int sdmode; 736 737 /* arg count */ 738 for (argc = 0; argv[argc]; argc++); 739 argc--; 740 741 if (argv[1]) { 742 if (!strcmp(argv[1], "spi")) { 743 strcpy(argv[1], "0"); 744 } else if (!strcmp(argv[1], "sd1")) { 745 strcpy(argv[1], "1"); 746 } else if (!strcmp(argv[1], "sd4")) { 747 strcpy(argv[1], "2"); 748 } else { 749 return USAGE_ERROR; 750 } 751 752 ret = dhd_var_setint(wl, cmd, argv); 753 754 } else { 755 if ((ret = dhd_var_get(wl, cmd, argv))) { 756 return (ret); 757 } else { 758 sdmode = *(int32*)buf; 759 760 printf("SD Mode is: %s\n", 761 sdmode == 0 ? "SPI" 762 : sdmode == 1 ? "SD1" 763 : sdmode == 2 ? "SD4" : "Unknown"); 764 } 765 } 766 767 return (ret); 768} 769 770static int 771dhd_dma_mode(void *wl, cmd_t *cmd, char **argv) 772{ 773 int ret; 774 int argc; 775 int dmamode; 776 777 /* arg count */ 778 for (argc = 0; argv[argc]; argc++); 779 argc--; 780 781 if (argv[1]) { 782 if (!stricmp(argv[1], "pio")) { 783 strcpy(argv[1], "0"); 784 } else if (!strcmp(argv[1], "0")) { 785 } else if (!stricmp(argv[1], "dma")) { 786 strcpy(argv[1], "1"); 787 } else if (!stricmp(argv[1], "sdma")) { 788 strcpy(argv[1], "1"); 789 } else if (!strcmp(argv[1], "1")) { 790 } else if (!stricmp(argv[1], "adma1")) { 791 strcpy(argv[1], "2"); 792 } else if (!stricmp(argv[1], "adma")) { 793 strcpy(argv[1], "3"); 794 } else if (!stricmp(argv[1], "adma2")) { 795 strcpy(argv[1], "3"); 796 } else { 797 return USAGE_ERROR; 798 } 799 800 ret = dhd_var_setint(wl, cmd, argv); 801 802 } else { 803 if ((ret = dhd_var_get(wl, cmd, argv))) { 804 return (ret); 805 } else { 806 dmamode = *(int32*)buf; 807 808 printf("DMA Mode is: %s\n", 809 dmamode == 0 ? "PIO" 810 : dmamode == 1 ? "SDMA" 811 : dmamode == 2 ? "ADMA1" 812 : dmamode == 3 ? "ADMA2" 813 : "Unknown"); 814 } 815 } 816 817 return (ret); 818} 819 820 821static int 822dhd_sdreg(void *dhd, cmd_t *cmd, char **argv) 823{ 824 int ret; 825 sdreg_t sdreg; 826 uint argc; 827 char *ptr = NULL; 828 829 UNUSED_PARAMETER(cmd); 830 831 bzero(&sdreg, sizeof(sdreg)); 832 833 /* arg count */ 834 for (argc = 0; argv[argc]; argc++); 835 argc--; 836 837 /* required args: offset (will default size) */ 838 if (argc < 1) { 839 printf("required args: offset[/size] [value]\n"); 840 return USAGE_ERROR; 841 } 842 843 sdreg.offset = strtoul(argv[1], &ptr, 0); 844 if (*ptr && *ptr != '/') { 845 printf("Bad arg: %s\n", argv[1]); 846 return USAGE_ERROR; 847 } 848 849 /* read optional /size */ 850 if (*ptr == '/') { 851 sdreg.func = strtol((ptr+1), &ptr, 0); 852 if (*ptr || ((sdreg.func != 2) && sdreg.func != 4)) { 853 printf("Bad size option?\n"); 854 return USAGE_ERROR; 855 } 856 } 857 else { 858 sdreg.func = 4; 859 printf("Defaulting to register size 4\n"); 860 } 861 862 if (argc > 1) { 863 sdreg.value = strtoul(argv[2], &ptr, 0); 864 if (*ptr) { 865 printf("Bad value: %s\n", argv[2]); 866 return USAGE_ERROR; 867 } 868 } 869 870 if (argc <= 1) { 871 ret = dhd_var_getbuf(dhd, argv[0], &sdreg, sizeof(sdreg), (void**)&ptr); 872 if (ret >= 0) 873 printf("0x%0*x\n", (2 * sdreg.func), *(int *)ptr); 874 } else { 875 ret = dhd_var_setbuf(dhd, argv[0], &sdreg, sizeof(sdreg)); 876 } 877 878 return (ret); 879} 880 881static int 882dhd_membytes(void *dhd, cmd_t *cmd, char **argv) 883{ 884 int ret = -1; 885 uint argc; 886 char *ptr; 887 int params[2]; 888 uint addr; 889 uint len; 890 int align; 891 892 int rawout, hexin; 893 894 miniopt_t opts; 895 int opt_err; 896 897 /* Parse command-line options */ 898 miniopt_init(&opts, "membytes", "rh", FALSE); 899 900 rawout = hexin = 0; 901 902 argv++; 903 while ((opt_err = miniopt(&opts, argv)) != -1) { 904 if (opt_err == 1) { 905 fprintf(stderr, "membytes options error\n"); 906 ret = -1; 907 goto exit; 908 } 909 910 if (opts.positional) 911 break; 912 913 argv += opts.consumed; 914 915 if (opts.opt == 'h') { 916 hexin = 1; 917 } else if (opts.opt == 'r') { 918 rawout = 1; 919 } else { 920 fprintf(stderr, "membytes command error\n"); 921 ret = -1; 922 goto exit; 923 } 924 } 925 926 /* arg count */ 927 for (argc = 0; argv[argc]; argc++); 928 929 /* required args: address size [<bytes>]] */ 930 if (argc < 2) { 931 fprintf(stderr, "required args: address size [<bytes>]\n"); 932 return USAGE_ERROR; 933 } 934 if (argc < 3 && hexin) { 935 fprintf(stderr, "missing <bytes> arg implies by -h\n"); 936 return USAGE_ERROR; 937 } 938 if ((argc > 2) && (rawout)) { 939 fprintf(stderr, "can't have input <bytes> arg with -r or -i\n"); 940 return USAGE_ERROR; 941 } 942 943 /* read address */ 944 addr = strtoul(argv[0], &ptr, 0); 945 if (*ptr) { 946 fprintf(stderr, "Bad arg: %s\n", argv[0]); 947 return USAGE_ERROR; 948 } 949 950 /* read size */ 951 len = strtoul(argv[1], &ptr, 0); 952 if (*ptr) { 953 fprintf(stderr, "Bad value: %s\n", argv[1]); 954 return USAGE_ERROR; 955 } 956 957 align = addr & 0x03; 958 if (align && argc > 2) { 959 fprintf(stderr, "Can only write starting at long-aligned addresses.\n"); 960 return USAGE_ERROR; 961 } 962 963 /* get can just use utility function, set must copy custom buffer */ 964 if (argc == 2) { 965 uint chunk = DHD_IOCTL_MAXLEN; 966 for (addr -= align, len += align; len; addr += chunk, len -= chunk, align = 0) { 967 chunk = MIN(chunk, len); 968 params[0] = addr; params[1] = ROUNDUP(chunk, 4); 969 ret = dhd_var_getbuf(dhd, "membytes", 970 params, (2 * sizeof(int)), (void**)&ptr); 971 if (ret < 0) 972 goto exit; 973 974 if (rawout) { 975 fwrite(ptr + align, sizeof(char), chunk - align, stdout); 976 } else { 977 dhd_hexdump((uchar*)ptr + align, chunk - align, addr + align); 978 } 979 } 980 } else { 981 uint patlen = strlen(argv[2]); 982 uint chunk, maxchunk; 983 char *sptr; 984 985 if (hexin) { 986 char *inptr, *outptr; 987 if (patlen & 1) { 988 fprintf(stderr, "Hex (-h) must consist of whole bytes\n"); 989 ret = USAGE_ERROR; 990 goto exit; 991 } 992 993 for (inptr = outptr = argv[2]; patlen; patlen -= 2) { 994 int n1, n2; 995 996 n1 = (int)((unsigned char)*inptr++); 997 n2 = (int)((unsigned char)*inptr++); 998 if (!isxdigit(n1) || !isxdigit(n2)) { 999 fprintf(stderr, "invalid hex digit %c\n", 1000 (isxdigit(n1) ? n2 : n1)); 1001 ret = USAGE_ERROR; 1002 goto exit; 1003 } 1004 n1 = isdigit(n1) ? (n1 - '0') 1005 : ((islower(n1) ? (toupper(n1)) : n1) - 'A' + 10); 1006 n2 = isdigit(n2) ? (n2 - '0') 1007 : ((islower(n2) ? (toupper(n2)) : n2) - 'A' + 10); 1008 *outptr++ = (n1 * 16) + n2; 1009 } 1010 1011 patlen = outptr - argv[2]; 1012 } 1013 1014 sptr = argv[2]; 1015 maxchunk = DHD_IOCTL_MAXLEN - (strlen(cmd->name) + 1 + (2 * sizeof(int))); 1016 1017 while (len) { 1018 chunk = (len > maxchunk) ? (maxchunk & ~0x3) : len; 1019 1020 /* build the iovar command */ 1021 memset(buf, 0, DHD_IOCTL_MAXLEN); 1022 strcpy(buf, cmd->name); 1023 ptr = buf + strlen(buf) + 1; 1024 params[0] = addr; params[1] = chunk; 1025 memcpy(ptr, params, (2 * sizeof(int))); 1026 ptr += (2 * sizeof(int)); 1027 addr += chunk; len -= chunk; 1028 1029 while (chunk--) { 1030 *ptr++ = *sptr++; 1031 if (sptr >= (argv[2] + patlen)) 1032 sptr = argv[2]; 1033 } 1034 1035 ret = dhd_set(dhd, DHD_SET_VAR, &buf[0], (ptr - buf)); 1036 if (ret < 0) 1037 goto exit; 1038 } 1039 } 1040 1041exit: 1042 return ret; 1043} 1044 1045static int 1046dhd_idletime(void *dhd, cmd_t *cmd, char **argv) 1047{ 1048 int32 idletime; 1049 char *endptr = NULL; 1050 int err = 0; 1051 1052 if (argv[1]) { 1053 if (!strcmp(argv[1], "never")) { 1054 idletime = 0; 1055 } else if (!strcmp(argv[1], "immediate") || !strcmp(argv[1], "immed")) { 1056 idletime = DHD_IDLE_IMMEDIATE; 1057 } else { 1058 idletime = strtol(argv[1], &endptr, 0); 1059 if (*endptr != '\0') { 1060 fprintf(stderr, "invalid number %s\n", argv[1]); 1061 err = -1; 1062 } 1063 } 1064 if ((idletime < 0) && (idletime != DHD_IDLE_IMMEDIATE)) { 1065 fprintf(stderr, "invalid value %s\n", argv[1]); 1066 err = -1; 1067 } 1068 1069 if (!err) { 1070 strcpy(buf, "idletime"); 1071 endptr = buf + strlen(buf) + 1; 1072 memcpy(endptr, &idletime, sizeof(uint32)); 1073 endptr += sizeof(uint32); 1074 err = dhd_set(dhd, DHD_SET_VAR, &buf[0], (endptr - buf)); 1075 } 1076 } else { 1077 if ((err = dhd_var_get(dhd, cmd, argv))) { 1078 return err; 1079 } else { 1080 idletime = *(int32*)buf; 1081 1082 if (idletime == 0) { 1083 printf("0 (never)\n"); 1084 } else if (idletime == DHD_IDLE_IMMEDIATE) { 1085 printf("-1 (immediate)\n"); 1086 } else if (idletime > 0) { 1087 printf("%d\n", idletime); 1088 } else printf("%d (invalid)\n", idletime); 1089 } 1090 } 1091 return err; 1092} 1093 1094static int 1095dhd_idleclock(void *dhd, cmd_t *cmd, char **argv) 1096{ 1097 int32 idleclock; 1098 char *endptr = NULL; 1099 int err = 0; 1100 1101 if (argv[1]) { 1102 if (!strcmp(argv[1], "active")) { 1103 idleclock = DHD_IDLE_ACTIVE; 1104 } else if (!strcmp(argv[1], "stopped")) { 1105 idleclock = DHD_IDLE_STOP; 1106 } else { 1107 idleclock = strtol(argv[1], &endptr, 0); 1108 if (*endptr != '\0') { 1109 fprintf(stderr, "invalid number %s\n", argv[1]); 1110 err = USAGE_ERROR; 1111 } 1112 } 1113 1114 if (!err) { 1115 strcpy(buf, "idleclock"); 1116 endptr = buf + strlen(buf) + 1; 1117 memcpy(endptr, &idleclock, sizeof(int32)); 1118 endptr += sizeof(int32); 1119 err = dhd_set(dhd, DHD_SET_VAR, &buf[0], (endptr - buf)); 1120 } 1121 } else { 1122 if ((err = dhd_var_get(dhd, cmd, argv))) { 1123 return err; 1124 } else { 1125 idleclock = *(int32*)buf; 1126 1127 if (idleclock == DHD_IDLE_ACTIVE) 1128 printf("Idleclock %d (active)\n", idleclock); 1129 else if (idleclock == DHD_IDLE_STOP) 1130 printf("Idleclock %d (stopped)\n", idleclock); 1131 else 1132 printf("Idleclock divisor %d\n", idleclock); 1133 } 1134 } 1135 return err; 1136} 1137 1138/* Word count for a 4kb SPROM */ 1139#define SPROM_WORDS 256 1140 1141static int 1142dhd_sprom(void *dhd, cmd_t *cmd, char **argv) 1143{ 1144#if !defined(BWL_FILESYSTEM_SUPPORT) 1145 return (-1); 1146#else 1147 int ret, i; 1148 uint argc; 1149 char *endptr; 1150 char *bufp, *countptr; 1151 uint16 *wordptr; 1152 uint offset, words, bytes; 1153 bool nocrc = FALSE; 1154 1155 char *fname; 1156 FILE *fp; 1157 1158 UNUSED_PARAMETER(cmd); 1159 1160 /* arg count */ 1161 for (argc = 0; argv[argc]; argc++); 1162 argc--; 1163 1164 /* init buffer */ 1165 bufp = buf; 1166 memset(bufp, 0, DHD_IOCTL_MAXLEN); 1167 strcpy(bufp, "sprom"); 1168 bufp += strlen("sprom") + 1; 1169 1170 if (strcmp(argv[0], "srdump") == 0) { 1171 if (argc) { 1172 fprintf(stderr, "Command srdump doesn't take args\n"); 1173 return USAGE_ERROR; 1174 } 1175 offset = 0; 1176 words = SPROM_WORDS; 1177 bytes = 2 * words; 1178 1179 memcpy(bufp, &offset, sizeof(int)); 1180 bufp += sizeof(int); 1181 memcpy(bufp, &bytes, sizeof(int)); 1182 bufp += sizeof(int); 1183 1184 if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) { 1185 fprintf(stderr, "Internal error: unaligned word buffer\n"); 1186 return COMMAND_ERROR; 1187 } 1188 } else { 1189 if (strcmp(argv[0], "srwrite") != 0) { 1190 fprintf(stderr, "Unimplemented sprom command: %s\n", argv[0]); 1191 return USAGE_ERROR; 1192 } 1193 1194 if (argc == 0) { 1195 return USAGE_ERROR; 1196 } else if ((argc == 1) || 1197 ((argc == 2) && ((nocrc = !strcmp(argv[1], "-c"))))) { 1198 1199 fname = nocrc ? argv[2] : argv[1]; 1200 1201 /* determine and validate file size */ 1202 if ((ret = file_size(fname)) < 0) 1203 return COMMAND_ERROR; 1204 1205 bytes = ret; 1206 offset = 0; 1207 words = bytes / 2; 1208 1209 if (bytes != 2 * SPROM_WORDS) { 1210 fprintf(stderr, "Bad file size\n"); 1211 return COMMAND_ERROR; 1212 } 1213 1214 memcpy(bufp, &offset, sizeof(int)); 1215 bufp += sizeof(int); 1216 memcpy(bufp, &bytes, sizeof(int)); 1217 bufp += sizeof(int); 1218 1219 if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) { 1220 fprintf(stderr, "Internal error: unaligned word buffer\n"); 1221 return COMMAND_ERROR; 1222 } 1223 1224 if ((fp = fopen(fname, "rb")) == NULL) { 1225 fprintf(stderr, "Could not open %s: %s\n", 1226 fname, strerror(errno)); 1227 return COMMAND_ERROR; 1228 } 1229 1230 if (fread((uint16*)bufp, sizeof(uint16), words, fp) != words) { 1231 fprintf(stderr, "Could not read %d bytes from %s\n", 1232 words * 2, fname); 1233 fclose(fp); 1234 return COMMAND_ERROR; 1235 } 1236 1237 fclose(fp); 1238 1239 if (!nocrc && 1240 hndcrc8((uint8*)bufp, bytes, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { 1241 fprintf(stderr, "CRC check failed: 0x%02x, should be 0x%02x.\n", 1242 ((uint8*)bufp)[bytes-1], 1243 ~hndcrc8((uint8*)bufp, bytes - 1, CRC8_INIT_VALUE) & 0xff); 1244 return COMMAND_ERROR; 1245 } 1246 1247 ltoh16_buf(bufp, bytes); 1248 } else { 1249 offset = strtoul(*++argv, &endptr, 0) * 2; 1250 if (*endptr != '\0') { 1251 fprintf(stderr, "offset %s is not an integer\n", *argv); 1252 return USAGE_ERROR; 1253 } 1254 1255 memcpy(bufp, &offset, sizeof(int)); 1256 bufp += sizeof(int); 1257 countptr = bufp; 1258 bufp += sizeof(int); 1259 1260 if (!ISALIGNED((uintptr)bufp, sizeof(uint16))) { 1261 fprintf(stderr, "Internal error: unaligned word buffer\n"); 1262 return COMMAND_ERROR; 1263 } 1264 1265 for (words = 0, wordptr = (uint16*)bufp; *++argv; words++) { 1266 *wordptr++ = (uint16)strtoul(*argv, &endptr, 0); 1267 if (*endptr != '\0') { 1268 fprintf(stderr, "value %s is not an integer\n", *argv); 1269 return USAGE_ERROR; 1270 } 1271 if (words > SPROM_WORDS) { 1272 fprintf(stderr, "max of %d words\n", SPROM_WORDS); 1273 return USAGE_ERROR; 1274 } 1275 } 1276 1277 bytes = 2 * words; 1278 memcpy(countptr, &bytes, sizeof(int)); 1279 } 1280 } 1281 1282 if (argc) { 1283 ret = dhd_set(dhd, DHD_SET_VAR, buf, 1284 (strlen("sprom") + 1) + (2 * sizeof(int)) + bytes); 1285 return (ret); 1286 } else { 1287 ret = dhd_get(dhd, DHD_GET_VAR, buf, 1288 (strlen("sprom") + 1) + (2 * sizeof(int)) + bytes); 1289 if (ret < 0) { 1290 return ret; 1291 } 1292 1293 for (i = 0; i < (int)words; i++) { 1294 if ((i % 8) == 0) 1295 printf("\n srom[%03d]: ", i); 1296 printf("0x%04x ", ((uint16*)buf)[i]); 1297 } 1298 printf("\n"); 1299 } 1300 1301 return 0; 1302#endif /* BWL_FILESYSTEM_SUPPORT */ 1303} 1304 1305/* 1306 * read_vars: reads an environment variables file into a buffer, 1307 * reformatting them and returning the length (-1 on error). 1308 * 1309 * The input text file consists of lines of the form "<var>=<value>\n". 1310 * CRs are ignored, as are blank lines and comments beginning with '#'. 1311 * 1312 * The output buffer consists of blocks of the form "<var>=<value>\0" 1313 * (the newlines have been replaced by NULs) 1314 * 1315 * Todo: allow quoted variable names and quoted values. 1316*/ 1317 1318#if defined(BWL_FILESYSTEM_SUPPORT) 1319static int 1320read_vars(char *fname, char *buf, int buf_maxlen) 1321{ 1322 FILE *fp; 1323 int buf_len, slen; 1324 char line[256], *s, *e; 1325 int line_no = 0; 1326 1327 if ((fp = fopen(fname, "rb")) == NULL) { 1328 fprintf(stderr, "Cannot open NVRAM file %s: %s\n", 1329 fname, strerror(errno)); 1330 exit(1); 1331 } 1332 1333 buf_len = 0; 1334 1335 while (fgets(line, sizeof(line), fp) != NULL) { 1336 bool found_eq = FALSE; 1337 1338 /* Ensure line length is limited */ 1339 line[sizeof(line) - 1] = 0; 1340 1341 /* Skip any initial white space */ 1342 for (s = line; *s == ' ' || *s == '\t'; s++) 1343 ; 1344 1345 /* Determine end of string */ 1346 for (e = s; *e != 0 && *e != '#' && *e != '\r' && *e != '\n'; e++) 1347 if (*e == '=') 1348 found_eq = TRUE; 1349 1350 /* Strip any white space from end of string */ 1351 while (e > s && (e[-1] == ' ' || e[-1] == '\t')) 1352 e--; 1353 1354 slen = e - s; 1355 1356 /* Skip lines that end up blank */ 1357 if (slen == 0) 1358 continue; 1359 1360 if (!found_eq) { 1361 fprintf(stderr, "Invalid line %d in NVRAM file %s\n", line_no, fname); 1362 fclose(fp); 1363 return -1; 1364 } 1365 1366 if (buf_len + slen + 1 > buf_maxlen) { 1367 fprintf(stderr, "NVRAM file %s too long\n", fname); 1368 fclose(fp); 1369 return -1; 1370 } 1371 1372 memcpy(buf + buf_len, s, slen); 1373 buf_len += slen; 1374 buf[buf_len++] = 0; 1375 } 1376 1377 fclose(fp); 1378 1379 return buf_len; 1380} 1381#endif /* BWL_FILESYSTEM_SUPPORT */ 1382 1383static int 1384dhd_vars(void *dhd, cmd_t *cmd, char **argv) 1385{ 1386 int ret; 1387 uint argc; 1388 char *bufp; 1389 char *vname; 1390 1391 UNUSED_PARAMETER(cmd); 1392 1393 /* arg count */ 1394 for (argc = 0; argv[argc]; argc++); 1395 argc--; 1396 1397 switch (argc) { 1398 case 0: /* get */ 1399 { 1400 if ((ret = dhd_var_getbuf(dhd, "vars", NULL, 0, (void**)&bufp))) 1401 break; 1402 while (*bufp) { 1403 printf("%s\n", bufp); 1404 bufp += strlen(bufp) + 1; 1405 } 1406 } 1407 break; 1408 1409#if defined(BWL_FILESYSTEM_SUPPORT) 1410 case 1: /* set */ 1411 { 1412 uint nvram_len; 1413 vname = argv[1]; 1414 1415 bufp = buf; 1416 strcpy(bufp, "vars"); 1417 bufp += strlen("vars") + 1; 1418 1419 if ((ret = read_vars(vname, bufp, 1420 DHD_IOCTL_MAXLEN - (strlen("vars") + 3))) < 0) { 1421 ret = -1; 1422 break; 1423 } 1424 1425 nvram_len = ret; 1426 bufp += nvram_len; 1427 *bufp++ = 0; 1428 1429 ret = dhd_set(dhd, DHD_SET_VAR, buf, bufp - buf); 1430 } 1431 break; 1432#endif /* BWL_FILESYSTEM_SUPPORT */ 1433 1434 default: 1435 ret = -1; 1436 break; 1437 } 1438 1439 return ret; 1440} 1441 1442#define MEMBLOCK 2048 1443 1444/* Check that strlen("membytes")+1 + 2*sizeof(int32) + MEMBLOCK <= DHD_IOCTL_MAXLEN */ 1445#if (MEMBLOCK + 17 > DHD_IOCTL_MAXLEN) 1446#error MEMBLOCK/DHD_IOCTL_MAXLEN sizing 1447#endif 1448 1449 1450#if defined(BWL_FILESYSTEM_SUPPORT) 1451static int 1452dhd_load_file_bytes(void *dhd, cmd_t *cmd, FILE *fp, int fsize, int start) 1453{ 1454 int tot_len = 0; 1455 uint read_len; 1456 char *bufp; 1457 uint len; 1458 uint8 memblock[MEMBLOCK]; 1459 int ret; 1460 1461 UNUSED_PARAMETER(cmd); 1462 1463 while (tot_len < fsize) { 1464 read_len = fsize - tot_len; 1465 if (read_len >= MEMBLOCK) 1466 read_len = MEMBLOCK; 1467 len = fread(memblock, sizeof(uint8), read_len, fp); 1468 if ((len < read_len) && !feof(fp)) { 1469 fprintf(stderr, "%s: error reading file\n", __FUNCTION__); 1470 return -1; 1471 1472 } 1473 1474 bufp = buf; 1475 memset(bufp, 0, DHD_IOCTL_MAXLEN); 1476 strcpy(bufp, "membytes"); 1477 bufp += strlen("membytes") + 1; 1478 memcpy(bufp, &start, sizeof(int)); 1479 bufp += sizeof(int); 1480 memcpy(bufp, &len, sizeof(int)); 1481 bufp += sizeof(int); 1482 memcpy(bufp, memblock, len); 1483 1484 ret = dhd_set(dhd, DHD_SET_VAR, &buf[0], (bufp - buf + len)); 1485 1486 if (ret) { 1487 fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n", 1488 __FUNCTION__, ret, len, start); 1489 return -1; 1490 } 1491 start += len; 1492 tot_len += len; 1493 } 1494 return 0; 1495} 1496#endif /* BWL_FILESYSTEM_SUPPORT */ 1497 1498static int 1499dhd_download(void *dhd, cmd_t *cmd, char **argv) 1500{ 1501#if !defined(BWL_FILESYSTEM_SUPPORT) 1502 return (-1); 1503#else 1504 bool reset = TRUE; 1505 bool run = TRUE; 1506 char *fname = NULL; 1507 char *vname = NULL; 1508 uint32 start = 0; 1509 int ret = 0; 1510 int fsize; 1511 1512 FILE *fp = NULL; 1513 uint32 memsize; 1514 char *memszargs[] = { "memsize", NULL }; 1515 1516 char *bufp; 1517 1518 miniopt_t opts; 1519 int opt_err; 1520 uint nvram_len; 1521 struct trx_header trx_hdr; 1522 bool trx_file = FALSE; 1523 1524 /* Parse command-line options */ 1525 miniopt_init(&opts, "download", "", TRUE); 1526 1527 argv++; 1528 while ((opt_err = miniopt(&opts, argv)) != -1) { 1529 if (opt_err == 1) { 1530 fprintf(stderr, "download options error\n"); 1531 ret = -1; 1532 goto exit; 1533 } 1534 argv += opts.consumed; 1535 1536 if (opts.opt == 'a') { 1537 if (!opts.good_int) { 1538 fprintf(stderr, "invalid address %s\n", opts.valstr); 1539 ret = -1; 1540 goto exit; 1541 } 1542 start = (uint32)opts.uval; 1543 } else if (opts.positional) { 1544 if (fname && vname) { 1545 fprintf(stderr, "extra positional arg, %s\n", 1546 opts.valstr); 1547 ret = -1; 1548 goto exit; 1549 } 1550 if (fname) 1551 vname = opts.valstr; 1552 else 1553 fname = opts.valstr; 1554 } else if (!opts.opt) { 1555 if (!strcmp(opts.key, "noreset")) { 1556 reset = FALSE; 1557 } else if (!strcmp(opts.key, "norun")) { 1558 run = FALSE; 1559 } else { 1560 fprintf(stderr, "unrecognized option %s\n", opts.valstr); 1561 ret = -1; 1562 goto exit; 1563 } 1564 } else { 1565 fprintf(stderr, "unrecognized option %c\n", opts.opt); 1566 ret = -1; 1567 goto exit; 1568 } 1569 } 1570 1571 /* validate arguments */ 1572 if (!fname) { 1573 fprintf(stderr, "filename required\n"); 1574 ret = -1; 1575 goto exit; 1576 } 1577 1578 1579 /* validate file size compared to memory size */ 1580 if ((fsize = file_size(fname)) < 0) { 1581 ret = -1; 1582 goto exit; 1583 } 1584 /* read the file and push blocks down to memory */ 1585 if ((fp = fopen(fname, "rb")) == NULL) { 1586 fprintf(stderr, "%s: unable to open %s: %s\n", 1587 __FUNCTION__, fname, strerror(errno)); 1588 ret = -1; 1589 goto exit; 1590 } 1591 /* Verify the file is a regular bin file or trx file */ 1592 { 1593 uint32 tmp_len; 1594 uint32 trx_hdr_len = sizeof(struct trx_header); 1595 tmp_len = fread(&trx_hdr, sizeof(uint8), trx_hdr_len, fp); 1596 if (tmp_len == trx_hdr_len) { 1597 if (trx_hdr.magic == TRX_MAGIC) { 1598 fprintf(stderr, "TRX file\n"); 1599 trx_file = TRUE; 1600 /* trx header file format: image_size, rom_img_size, rom_load_adr */ 1601 fprintf(stderr, "dongle RAM Image size %d\n", trx_hdr.offsets[0]); 1602 fprintf(stderr, "dongle ROM Image size %d\n", trx_hdr.offsets[1]); 1603 fprintf(stderr, "dongle ROM Loadaddr 0x%x\n", trx_hdr.offsets[2]); 1604 fsize = trx_hdr.offsets[0] + trx_hdr.offsets[1]; 1605 fprintf(stderr, "filesize is %d\n", fsize); 1606 } 1607 else 1608 fseek(fp, 0, SEEK_SET); 1609 } 1610 else 1611 fseek(fp, 0, SEEK_SET); 1612 } 1613 1614 if ((ret = dhd_var_get(dhd, NULL, memszargs))) { 1615 fprintf(stderr, "%s: error obtaining memsize\n", __FUNCTION__); 1616 goto exit; 1617 } 1618 1619 memsize = *(uint32*)buf; 1620 1621 if (memsize && ((uint32)fsize > memsize)) { 1622 fprintf(stderr, "%s: file %s too large (%d > %d)\n", 1623 __FUNCTION__, fname, fsize, memsize); 1624 ret = -1; 1625 goto exit; 1626 } 1627 1628 /* do the download reset if not suppressed */ 1629 if (reset) { 1630 if ((ret = dhd_iovar_setint(dhd, "download", TRUE))) { 1631 fprintf(stderr, "%s: failed to put dongle in download mode\n", 1632 __FUNCTION__); 1633 goto exit; 1634 } 1635 } 1636 if (trx_file) 1637 fsize = trx_hdr.offsets[0]; 1638 /* Load the ram image */ 1639 if (dhd_load_file_bytes(dhd, cmd, fp, fsize, start)) { 1640 fprintf(stderr, "%s: error loading the ramimage at addr 0x%x\n", 1641 __FUNCTION__, start); 1642 ret = -1; 1643 goto exit; 1644 } 1645 if (trx_file) { 1646 /* Load the rom library */ 1647 start = trx_hdr.offsets[2]; 1648 fsize = trx_hdr.offsets[1]; 1649 1650 fprintf(stderr, "setting the maxsocram value 0x%x \n", start); 1651 if (dhd_iovar_setint(dhd, "maxsocram", start)) { 1652 fprintf(stderr, "%s: setting the maxram size to %d failed\n", 1653 __FUNCTION__, start); 1654 goto exit; 1655 } 1656 1657 if (dhd_load_file_bytes(dhd, cmd, fp, fsize, start)) { 1658 fprintf(stderr, "%s: error loading the rom library at addr 0x%x\n", 1659 __FUNCTION__, start); 1660 goto exit; 1661 } 1662 1663 } 1664 1665 fclose(fp); 1666 fp = NULL; 1667 1668 /* download the vars file if specified */ 1669 if (vname) { 1670 bufp = buf; 1671 strcpy(bufp, "vars"); 1672 bufp += strlen("vars") + 1; 1673 1674 if ((ret = read_vars(vname, bufp, 1675 DHD_IOCTL_MAXLEN - (strlen("vars") + 3))) < 0) { 1676 ret = -1; 1677 goto exit; 1678 } 1679 1680 nvram_len = ret; 1681 bufp += nvram_len; 1682 *bufp++ = 0; 1683 1684 ret = dhd_set(dhd, DHD_SET_VAR, buf, (bufp - buf)); 1685 if (ret) { 1686 fprintf(stderr, "%s: error %d on delivering vars\n", 1687 __FUNCTION__, ret); 1688 goto exit; 1689 } 1690 } 1691 1692 /* start running the downloaded code if not suppressed */ 1693 if (run) { 1694 if ((ret = dhd_iovar_setint(dhd, "download", FALSE))) { 1695 fprintf(stderr, "%s: failed to take dongle out of download mode\n", 1696 __FUNCTION__); 1697 goto exit; 1698 } 1699 } 1700 1701exit: 1702 if (fp) 1703 fclose(fp); 1704 1705 return ret; 1706#endif /* BWL_FILESYSTEM_SUPPORT */ 1707} 1708 1709static int 1710dhd_upload(void *dhd, cmd_t *cmd, char **argv) 1711{ 1712#if !defined(BWL_FILESYSTEM_SUPPORT) 1713 return (-1); 1714#else 1715 char *fname = NULL; 1716 uint32 start = 0; 1717 uint32 size = 0; 1718 int ret = 0; 1719 1720 FILE *fp; 1721 uint32 memsize; 1722 char *memszargs[] = { "memsize", NULL }; 1723 1724 uint len; 1725 1726 miniopt_t opts; 1727 int opt_err; 1728 1729 UNUSED_PARAMETER(cmd); 1730 UNUSED_PARAMETER(argv); 1731 1732 /* Parse command-line options */ 1733 miniopt_init(&opts, "upload", "", TRUE); 1734 1735 argv++; 1736 while ((opt_err = miniopt(&opts, argv)) != -1) { 1737 if (opt_err == 1) { 1738 fprintf(stderr, "upload options error\n"); 1739 ret = -1; 1740 goto exit; 1741 } 1742 argv += opts.consumed; 1743 1744 if (opts.opt == 'a') { 1745 if (!opts.good_int) { 1746 fprintf(stderr, "invalid address %s\n", opts.valstr); 1747 ret = -1; 1748 goto exit; 1749 } 1750 start = (uint32)opts.uval; 1751 } else if (opts.positional) { 1752 if (!fname) { 1753 fname = opts.valstr; 1754 } else if (opts.good_int) { 1755 size = (uint32)opts.uval; 1756 } else { 1757 fprintf(stderr, "upload options error\n"); 1758 ret = -1; 1759 goto exit; 1760 } 1761 } else if (!opts.opt) { 1762 fprintf(stderr, "unrecognized option %s\n", opts.valstr); 1763 ret = -1; 1764 goto exit; 1765 } else { 1766 fprintf(stderr, "unrecognized option %c\n", opts.opt); 1767 ret = -1; 1768 goto exit; 1769 } 1770 } 1771 1772 /* validate arguments */ 1773 if (!fname) { 1774 fprintf(stderr, "filename required\n"); 1775 ret = -1; 1776 goto exit; 1777 } 1778 1779 if ((ret = dhd_var_get(dhd, NULL, memszargs))) { 1780 fprintf(stderr, "%s: error obtaining memsize\n", __FUNCTION__); 1781 goto exit; 1782 } 1783 memsize = *(uint32*)buf; 1784 1785 if (!memsize) 1786 memsize = start + size; 1787 1788 if (start + size > memsize) { 1789 fprintf(stderr, "%s: %d bytes at 0x%x exceeds ramsize 0x%x\n", 1790 __FUNCTION__, size, start, memsize); 1791 ret = -1; 1792 goto exit; 1793 } 1794 1795 if ((fp = fopen(fname, "wb")) == NULL) { 1796 fprintf(stderr, "%s: Could not open %s: %s\n", 1797 __FUNCTION__, fname, strerror(errno)); 1798 ret = -1; 1799 goto exit; 1800 } 1801 1802 /* default size to full RAM */ 1803 if (!size) 1804 size = memsize - start; 1805 1806 /* read memory and write to file */ 1807 while (size) { 1808 char *ptr; 1809 int params[2]; 1810 1811 len = MIN(MEMBLOCK, size); 1812 1813 params[0] = start; 1814 params[1] = len; 1815 ret = dhd_var_getbuf(dhd, "membytes", params, 2 * sizeof(int), (void**)&ptr); 1816 if (ret) { 1817 fprintf(stderr, "%s: failed reading %d membytes from 0x%08x\n", 1818 __FUNCTION__, len, start); 1819 break; 1820 } 1821 1822 if (fwrite(ptr, sizeof(*ptr), len, fp) != len) { 1823 fprintf(stderr, "%s: error writing to file %s\n", __FUNCTION__, fname); 1824 ret = -1; 1825 break; 1826 } 1827 1828 start += len; 1829 size -= len; 1830 } 1831 1832 fclose(fp); 1833exit: 1834 return ret; 1835#endif /* BWL_FILESYSTEM_SUPPORT */ 1836} 1837 1838static int 1839dhd_logstamp(void *dhd, cmd_t *cmd, char **argv) 1840{ 1841 int ret; 1842 char *endptr = NULL; 1843 uint argc; 1844 int valn[2] = {0, 0}; 1845 1846 /* arg count */ 1847 for (argc = 0; argv[argc]; argc++); 1848 argc--; argv++; 1849 1850 if (argc > 2) 1851 return USAGE_ERROR; 1852 1853 if (argc) { 1854 valn[0] = strtol(argv[0], &endptr, 0); 1855 if (*endptr != '\0') { 1856 printf("bad val1: %s\n", argv[0]); 1857 return USAGE_ERROR; 1858 } 1859 } 1860 1861 if (argc > 1) { 1862 valn[1] = strtol(argv[1], &endptr, 0); 1863 if (*endptr != '\0') { 1864 printf("bad val2: %s\n", argv[1]); 1865 return USAGE_ERROR; 1866 } 1867 } 1868 1869 ret = dhd_var_setbuf(dhd, cmd->name, valn, argc * sizeof(int)); 1870 1871 return (ret); 1872} 1873 1874static int 1875dhd_sd_reg(void *dhd, cmd_t *cmd, char **argv) 1876{ 1877 int ret; 1878 sdreg_t sdreg; 1879 char *endptr = NULL; 1880 uint argc; 1881 void *ptr = NULL; 1882 1883 bzero(&sdreg, sizeof(sdreg)); 1884 1885 /* arg count */ 1886 for (argc = 0; argv[argc]; argc++); 1887 argc--; 1888 1889 /* hostreg: offset [value]; devreg: func offset [value] */ 1890 if (!strcmp(cmd->name, "sd_hostreg")) { 1891 argv++; 1892 if (argc < 1) { 1893 printf("required args: offset [value]\n"); 1894 return USAGE_ERROR; 1895 } 1896 1897 } else if (!strcmp(cmd->name, "sd_devreg")) { 1898 argv++; 1899 if (argc < 2) { 1900 printf("required args: func offset [value]\n"); 1901 return USAGE_ERROR; 1902 } 1903 1904 sdreg.func = strtoul(*argv++, &endptr, 0); 1905 if (*endptr != '\0') { 1906 printf("Invalid function number\n"); 1907 return USAGE_ERROR; 1908 } 1909 } else { 1910 return USAGE_ERROR; 1911 } 1912 1913 sdreg.offset = strtoul(*argv++, &endptr, 0); 1914 if (*endptr != '\0') { 1915 printf("Invalid offset value\n"); 1916 return USAGE_ERROR; 1917 } 1918 1919 /* third arg: value */ 1920 if (*argv) { 1921 sdreg.value = strtoul(*argv, &endptr, 0); 1922 if (*endptr != '\0') { 1923 printf("Invalid value\n"); 1924 return USAGE_ERROR; 1925 } 1926 } 1927 1928 /* no third arg means get, otherwise set */ 1929 if (!*argv) { 1930 if ((ret = dhd_var_getbuf(dhd, cmd->name, &sdreg, sizeof(sdreg), &ptr)) >= 0) 1931 printf("0x%x\n", *(int *)ptr); 1932 } else { 1933 ret = dhd_var_setbuf(dhd, cmd->name, &sdreg, sizeof(sdreg)); 1934 } 1935 1936 return (ret); 1937} 1938 1939static dbg_msg_t dhd_msgs[] = { 1940 {DHD_ERROR_VAL, "error"}, 1941 {DHD_ERROR_VAL, "err"}, 1942 {DHD_TRACE_VAL, "trace"}, 1943 {DHD_INFO_VAL, "inform"}, 1944 {DHD_INFO_VAL, "info"}, 1945 {DHD_INFO_VAL, "inf"}, 1946 {DHD_DATA_VAL, "data"}, 1947 {DHD_CTL_VAL, "ctl"}, 1948 {DHD_TIMER_VAL, "timer"}, 1949 {DHD_HDRS_VAL, "hdrs"}, 1950 {DHD_BYTES_VAL, "bytes"}, 1951 {DHD_INTR_VAL, "intr"}, 1952 {DHD_LOG_VAL, "log"}, 1953 {DHD_GLOM_VAL, "glom"}, 1954 {DHD_EVENT_VAL, "event"}, 1955 {DHD_BTA_VAL, "bta"}, 1956 {0, NULL} 1957}; 1958 1959static int 1960dhd_msglevel(void *dhd, cmd_t *cmd, char **argv) 1961{ 1962 return dhd_do_msglevel(dhd, cmd, argv, dhd_msgs); 1963} 1964 1965static int 1966dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg) 1967{ 1968 int ret, i; 1969 uint val, last_val = 0, msglevel = 0, msglevel_add = 0, msglevel_del = 0; 1970 char *endptr = NULL; 1971 1972 if ((ret = dhd_iovar_getint(dhd, cmd->name, (int*)&msglevel)) < 0) 1973 return (ret); 1974 1975 if (!*++argv) { 1976 printf("0x%x ", msglevel); 1977 for (i = 0; (val = dbg_msg[i].value); i++) { 1978 if ((msglevel & val) && (val != last_val)) 1979 printf(" %s", dbg_msg[i].string); 1980 last_val = val; 1981 } 1982 printf("\n"); 1983 return (0); 1984 } 1985 1986 while (*argv) { 1987 char *s = *argv; 1988 if (*s == '+' || *s == '-') 1989 s++; 1990 else 1991 msglevel_del = ~0; /* make the whole list absolute */ 1992 val = strtoul(s, &endptr, 0); 1993 /* not a plain integer if not all the string was parsed by strtoul */ 1994 if (*endptr != '\0') { 1995 for (i = 0; (val = dbg_msg[i].value); i++) 1996 if (stricmp(dbg_msg[i].string, s) == 0) 1997 break; 1998 if (!val) 1999 goto usage; 2000 } 2001 if (**argv == '-') 2002 msglevel_del |= val; 2003 else 2004 msglevel_add |= val; 2005 ++argv; 2006 } 2007 2008 msglevel &= ~msglevel_del; 2009 msglevel |= msglevel_add; 2010 2011 return (dhd_iovar_setint(dhd, cmd->name, msglevel)); 2012 2013usage: 2014 fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n"); 2015 fprintf(stderr, "Use a + or - prefix to make an incremental change."); 2016 2017 for (i = 0; (val = dbg_msg[i].value); i++) { 2018 if (val != last_val) 2019 fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string); 2020 else 2021 fprintf(stderr, ", %s", dbg_msg[i].string); 2022 last_val = val; 2023 } 2024 fprintf(stderr, "\n"); 2025 2026 return 0; 2027} 2028 2029static char * 2030ver2str(unsigned int vms, unsigned int vls) 2031{ 2032 static char verstr[100]; 2033 unsigned int maj, year, month, day, build; 2034 2035 maj = (vms >> 16) & 0xFFFF; 2036 if (maj > 1000) { 2037 /* it is probably a date... */ 2038 year = (vms >> 16) & 0xFFFF; 2039 month = vms & 0xFFFF; 2040 day = (vls >> 16) & 0xFFFF; 2041 build = vls & 0xFFFF; 2042 sprintf(verstr, "%d/%d/%d build %d", 2043 month, day, year, build); 2044 } else { 2045 /* it is a tagged release. */ 2046 sprintf(verstr, "%d.%d RC%d.%d", 2047 (vms>>16)&0xFFFF, vms&0xFFFF, 2048 (vls>>16)&0xFFFF, vls&0xFFFF); 2049 } 2050 return verstr; 2051} 2052 2053static int 2054dhd_version(void *dhd, cmd_t *cmd, char **argv) 2055{ 2056 int ret; 2057 char *ptr; 2058 2059 UNUSED_PARAMETER(cmd); 2060 UNUSED_PARAMETER(argv); 2061 2062 /* Display the application version info */ 2063 printf("%s: %s\n", dhdu_av0, 2064 ver2str((EPI_MAJOR_VERSION << 16)| EPI_MINOR_VERSION, 2065 (EPI_RC_NUMBER << 16) | EPI_INCREMENTAL_NUMBER)); 2066 2067 if ((ret = dhd_var_getbuf(dhd, cmd->name, NULL, 0, (void**)&ptr)) < 0) 2068 return ret; 2069 2070 /* Display the returned string */ 2071 printf("%s\n", ptr); 2072 2073 return 0; 2074} 2075 2076static int 2077dhd_var_setint(void *dhd, cmd_t *cmd, char **argv) 2078{ 2079 int32 val; 2080 int len; 2081 char *varname; 2082 char *endptr = NULL; 2083 char *p; 2084 2085 if (cmd->set == -1) { 2086 printf("set not defined for %s\n", cmd->name); 2087 return COMMAND_ERROR; 2088 } 2089 2090 if (!*argv) { 2091 printf("set: missing arguments\n"); 2092 return USAGE_ERROR; 2093 } 2094 2095 varname = *argv++; 2096 2097 if (!*argv) { 2098 printf("set: missing value argument for set of \"%s\"\n", varname); 2099 return USAGE_ERROR; 2100 } 2101 2102 val = strtol(*argv, &endptr, 0); 2103 if (*endptr != '\0') { 2104 /* not all the value string was parsed by strtol */ 2105 printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n", 2106 *argv, varname); 2107 return USAGE_ERROR; 2108 } 2109 2110 strcpy(buf, varname); 2111 p = buf; 2112 while (*p != '\0') { 2113 *p = tolower(*p); 2114 p++; 2115 } 2116 2117 /* skip the NUL */ 2118 p++; 2119 2120 memcpy(p, &val, sizeof(uint)); 2121 len = (p - buf) + sizeof(uint); 2122 2123 return (dhd_set(dhd, DHD_SET_VAR, &buf[0], len)); 2124} 2125 2126static int 2127dhd_var_get(void *dhd, cmd_t *cmd, char **argv) 2128{ 2129 char *varname; 2130 char *p; 2131 2132 UNUSED_PARAMETER(cmd); 2133 2134 if (!*argv) { 2135 printf("get: missing arguments\n"); 2136 return USAGE_ERROR; 2137 } 2138 2139 varname = *argv++; 2140 2141 if (*argv) { 2142 printf("get: error, extra arg \"%s\"\n", *argv); 2143 return USAGE_ERROR; 2144 } 2145 2146 strcpy(buf, varname); 2147 p = buf; 2148 while (*p != '\0') { 2149 *p = tolower(*p); 2150 p++; 2151 } 2152 return (dhd_get(dhd, DHD_GET_VAR, &buf[0], DHD_IOCTL_MAXLEN)); 2153} 2154 2155static int 2156dhd_var_getint(void *dhd, cmd_t *cmd, char **argv) 2157{ 2158 int err; 2159 int32 val; 2160 2161 if (cmd->get == -1) { 2162 printf("get not defined for %s\n", cmd->name); 2163 return COMMAND_ERROR; 2164 } 2165 2166 if ((err = dhd_var_get(dhd, cmd, argv))) 2167 return (err); 2168 2169 val = *(int32*)buf; 2170 2171 if (val < 10) 2172 printf("%d\n", val); 2173 else 2174 printf("%d (0x%x)\n", val, val); 2175 2176 return (0); 2177} 2178 2179static int 2180dhd_var_getandprintstr(void *dhd, cmd_t *cmd, char **argv) 2181{ 2182 int err; 2183 2184 if ((err = dhd_var_get(dhd, cmd, argv))) 2185 return (err); 2186 2187 printf("%s\n", buf); 2188 return (0); 2189} 2190 2191 2192void 2193dhd_printlasterror(void *dhd) 2194{ 2195 char *cmd[2] = {"bcmerrorstr"}; 2196 2197 if (dhd_var_get(dhd, NULL, cmd) != 0) { 2198 fprintf(stderr, "%s: \nError getting the last error\n", dhdu_av0); 2199 } else { 2200 fprintf(stderr, "%s: %s\n", dhdu_av0, buf); 2201 } 2202} 2203 2204static int 2205dhd_varint(void *dhd, cmd_t *cmd, char *argv[]) 2206{ 2207 if (argv[1]) 2208 return (dhd_var_setint(dhd, cmd, argv)); 2209 else 2210 return (dhd_var_getint(dhd, cmd, argv)); 2211} 2212 2213static int 2214dhd_var_getbuf(void *dhd, char *iovar, void *param, int param_len, void **bufptr) 2215{ 2216 int len; 2217 2218 memset(buf, 0, DHD_IOCTL_MAXLEN); 2219 strcpy(buf, iovar); 2220 2221 /* include the NUL */ 2222 len = strlen(iovar) + 1; 2223 2224 if (param_len) 2225 memcpy(&buf[len], param, param_len); 2226 2227 *bufptr = buf; 2228 2229 return dhd_get(dhd, DHD_GET_VAR, &buf[0], DHD_IOCTL_MAXLEN); 2230} 2231 2232static int 2233dhd_var_setbuf(void *dhd, char *iovar, void *param, int param_len) 2234{ 2235 int len; 2236 2237 memset(buf, 0, DHD_IOCTL_MAXLEN); 2238 strcpy(buf, iovar); 2239 2240 /* include the NUL */ 2241 len = strlen(iovar) + 1; 2242 2243 if (param_len) 2244 memcpy(&buf[len], param, param_len); 2245 2246 len += param_len; 2247 return dhd_set(dhd, DHD_SET_VAR, &buf[0], len); 2248} 2249 2250static int 2251dhd_var_void(void *dhd, cmd_t *cmd, char **argv) 2252{ 2253 UNUSED_PARAMETER(argv); 2254 2255 if (cmd->set < 0) 2256 return USAGE_ERROR; 2257 2258 return dhd_var_setbuf(dhd, cmd->name, NULL, 0); 2259} 2260 2261/* 2262 * format an iovar buffer 2263 */ 2264static uint 2265dhd_iovar_mkbuf(char *name, char *data, uint datalen, char *buf, uint buflen, int *perr) 2266{ 2267 uint len; 2268 2269 len = strlen(name) + 1; 2270 2271 /* check for overflow */ 2272 if ((len + datalen) > buflen) { 2273 *perr = BCME_BUFTOOSHORT; 2274 return 0; 2275 } 2276 2277 strcpy(buf, name); 2278 2279 /* append data onto the end of the name string */ 2280 if (datalen > 0) 2281 memcpy(&buf[len], data, datalen); 2282 2283 len += datalen; 2284 2285 *perr = 0; 2286 return len; 2287} 2288 2289static int 2290dhd_iovar_getint(void *dhd, char *name, int *var) 2291{ 2292 char ibuf[DHD_IOCTL_SMLEN]; 2293 int error; 2294 2295 dhd_iovar_mkbuf(name, NULL, 0, ibuf, sizeof(ibuf), &error); 2296 if (error) 2297 return error; 2298 2299 if ((error = dhd_get(dhd, DHD_GET_VAR, &ibuf, sizeof(ibuf))) < 0) 2300 return error; 2301 2302 memcpy(var, ibuf, sizeof(int)); 2303 2304 return 0; 2305} 2306 2307static int 2308dhd_iovar_setint(void *dhd, char *name, int var) 2309{ 2310 int len; 2311 char ibuf[DHD_IOCTL_SMLEN]; 2312 int error; 2313 2314 len = dhd_iovar_mkbuf(name, (char *)&var, sizeof(var), ibuf, sizeof(ibuf), &error); 2315 if (error) 2316 return error; 2317 2318 if ((error = dhd_set(dhd, DHD_SET_VAR, &ibuf, len)) < 0) 2319 return error; 2320 2321 return 0; 2322} 2323 2324static int 2325dhd_varstr(void *dhd, cmd_t *cmd, char **argv) 2326{ 2327 int error; 2328 char *str; 2329 2330 if (!*++argv) { 2331 void *ptr; 2332 if ((error = dhd_var_getbuf(dhd, cmd->name, NULL, 0, &ptr)) < 0) 2333 return (error); 2334 2335 str = (char *)ptr; 2336 printf("%s\n", str); 2337 return (0); 2338 } else { 2339 str = *argv; 2340 /* iovar buffer length includes NUL */ 2341 return dhd_var_setbuf(dhd, cmd->name, str, strlen(str) + 1); 2342 } 2343} 2344