CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

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