tcl.c 44.2 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
6
 *   oyvind.harboe@zylin.com                                               *
ntfreak's avatar
ntfreak committed
7
8
 *                                                                         *
 *   Copyright (C) 2009 SoftPLC Corporation                                *
zwelch's avatar
zwelch committed
9
 *       http://softplc.com                                                *
ntfreak's avatar
ntfreak committed
10
 *   dick@softplc.com                                                      *
11
 *                                                                         *
12
13
14
 *   Copyright (C) 2009 Zachary T Welch                                    *
 *   zw@superlucidity.net                                                  *
 *                                                                         *
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "jtag.h"
zwelch's avatar
zwelch committed
35
#include "minidriver.h"
36
#include "interface.h"
37
#include "interfaces.h"
38

39
40
41
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
42

43
static const Jim_Nvp nvp_jtag_tap_event[] = {
44
45
	{ .value = JTAG_TRST_ASSERTED,		.name = "post-reset" },
	{ .value = JTAG_TAP_EVENT_SETUP,	.name = "setup" },
46
47
48
49
50
	{ .value = JTAG_TAP_EVENT_ENABLE,       .name = "tap-enable" },
	{ .value = JTAG_TAP_EVENT_DISABLE,      .name = "tap-disable" },

	{ .name = NULL, .value = -1 }
};
51

52
extern jtag_interface_t *jtag_interface;
53

54
55
56
57
58
59
/* jtag commands */
static int handle_interface_list_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc);
static int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_khz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
60
static int handle_jtag_rclk_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
61
62
63
64
static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
oharboe's avatar
oharboe committed
65
66
static int handle_jtag_nsrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_jtag_ntrst_assert_width_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
oharboe's avatar
oharboe committed
67

68
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
69

70
71
72
73
static int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
oharboe's avatar
oharboe committed
74
static int Jim_Command_pathmove(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
75
static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const *args);
76

77
78
79
static int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_verify_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int handle_tms_sequence_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
80

81

82
83
84
85
86
87
88
89
90
91
enum jtag_tap_cfg_param {
	JCFG_EVENT
};

static Jim_Nvp nvp_config_opts[] = {
	{ .name = "-event",      .value = JCFG_EVENT },

	{ .name = NULL,          .value = -1 }
};

92
static int jtag_tap_configure_cmd(Jim_GetOptInfo *goi, jtag_tap_t * tap)
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
{
	Jim_Nvp *n;
	Jim_Obj *o;
	int e;

	/* parse config or cget options */
	while (goi->argc > 0) {
		Jim_SetEmptyResult (goi->interp);

		e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
		if (e != JIM_OK) {
			Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
			return e;
		}

		switch (n->value) {
			case JCFG_EVENT:
				if (goi->argc == 0) {
111
					Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
112
113
114
					return JIM_ERR;
				}

115
				e = Jim_GetOpt_Nvp(goi, nvp_jtag_tap_event, &n);
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
				if (e != JIM_OK) {
					Jim_GetOpt_NvpUnknown(goi, nvp_jtag_tap_event, 1);
					return e;
				}

				if (goi->isconfigure) {
					if (goi->argc != 1) {
						Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
						return JIM_ERR;
					}
				} else {
					if (goi->argc != 0) {
						Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
						return JIM_ERR;
					}
				}

				{
					jtag_tap_event_action_t *jteap;

					jteap = tap->event_action;
					/* replace existing? */
					while (jteap) {
zwelch's avatar
zwelch committed
139
						if (jteap->event == (enum jtag_event)n->value) {
140
141
142
143
144
145
							break;
						}
						jteap = jteap->next;
					}

					if (goi->isconfigure) {
146
						bool replace = true;
147
148
149
						if (jteap == NULL) {
							/* create new */
							jteap = calloc(1, sizeof (*jteap));
150
							replace = false;
151
152
						}
						jteap->event = n->value;
153
						Jim_GetOpt_Obj(goi, &o);
154
155
156
157
158
159
						if (jteap->body) {
							Jim_DecrRefCount(interp, jteap->body);
						}
						jteap->body = Jim_DuplicateObj(goi->interp, o);
						Jim_IncrRefCount(jteap->body);

160
161
162
163
164
165
						if (!replace)
						{
							/* add to head of event list */
							jteap->next = tap->event_action;
							tap->event_action = jteap;
						}
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
						Jim_SetEmptyResult(goi->interp);
					} else {
						/* get */
						if (jteap == NULL) {
							Jim_SetEmptyResult(goi->interp);
						} else {
							Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, jteap->body));
						}
					}
				}
				/* loop for more */
				break;
		}
	} /* while (goi->argc) */

	return JIM_OK;
}
183

zwelch's avatar
zwelch committed
184
185
186
187
188
189
190
191
192
static int is_bad_irval(int ir_length, jim_wide w)
{
	jim_wide v = 1;

	v <<= ir_length;
	v -= 1;
	v = ~v;
	return (w & v) != 0;
}
193

194
static int jim_newtap_cmd(Jim_GetOptInfo *goi)
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
{
	jtag_tap_t *pTap;
	jim_wide w;
	int x;
	int e;
	Jim_Nvp *n;
	char *cp;
	const Jim_Nvp opts[] = {
#define NTAP_OPT_IRLEN     0
		{ .name = "-irlen"			,	.value = NTAP_OPT_IRLEN },
#define NTAP_OPT_IRMASK    1
		{ .name = "-irmask"			,	.value = NTAP_OPT_IRMASK },
#define NTAP_OPT_IRCAPTURE 2
		{ .name = "-ircapture"		,	.value = NTAP_OPT_IRCAPTURE },
#define NTAP_OPT_ENABLED   3
210
		{ .name = "-enable"			,	.value = NTAP_OPT_ENABLED },
211
#define NTAP_OPT_DISABLED  4
212
		{ .name = "-disable"		,	.value = NTAP_OPT_DISABLED },
213
#define NTAP_OPT_EXPECTED_ID 5
214
215
		{ .name = "-expected-id"	,	.value = NTAP_OPT_EXPECTED_ID },
		{ .name = NULL				,	.value = -1 },
216
217
	};

zwelch's avatar
zwelch committed
218
219
220
	pTap = calloc(1, sizeof(jtag_tap_t));
	if (!pTap) {
		Jim_SetResult_sprintf(goi->interp, "no memory");
221
222
		return JIM_ERR;
	}
zwelch's avatar
zwelch committed
223

224
225
226
	/*
	 * we expect CHIP + TAP + OPTIONS
	 * */
zwelch's avatar
zwelch committed
227
	if (goi->argc < 3) {
228
		Jim_SetResult_sprintf(goi->interp, "Missing CHIP TAP OPTIONS ....");
229
		free(pTap);
230
231
		return JIM_ERR;
	}
232
	Jim_GetOpt_String(goi, &cp, NULL);
233
234
	pTap->chip = strdup(cp);

235
	Jim_GetOpt_String(goi, &cp, NULL);
236
	pTap->tapname = strdup(cp);
oharboe's avatar
oharboe committed
237

238
	/* name + dot + name + null */
239
	x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
240
241
	cp = malloc(x);
	sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
242
243
	pTap->dotted_name = cp;

oharboe's avatar
oharboe committed
244
	LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
245
246
			  pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);

247
248
249
250
251
252
	/* IEEE specifies that the two LSBs of an IR scan are 01, so make
	 * that the default.  The "-irlen" and "-irmask" options are only
	 * needed to cope with nonstandard TAPs, or to specify more bits.
	 */
	pTap->ir_capture_mask = 0x03;
	pTap->ir_capture_value = 0x01;
253

zwelch's avatar
zwelch committed
254
	while (goi->argc) {
255
		e = Jim_GetOpt_Nvp(goi, opts, &n);
zwelch's avatar
zwelch committed
256
		if (e != JIM_OK) {
257
			Jim_GetOpt_NvpUnknown(goi, opts, 0);
258
259
			free((void *)pTap->dotted_name);
			free(pTap);
260
261
			return e;
		}
262
		LOG_DEBUG("Processing option: %s", n->name);
zwelch's avatar
zwelch committed
263
		switch (n->value) {
264
		case NTAP_OPT_ENABLED:
zwelch's avatar
zwelch committed
265
			pTap->disabled_after_reset = false;
266
267
			break;
		case NTAP_OPT_DISABLED:
zwelch's avatar
zwelch committed
268
			pTap->disabled_after_reset = true;
269
270
			break;
		case NTAP_OPT_EXPECTED_ID:
271
		{
272
			uint32_t *new_expected_ids;
273

274
			e = Jim_GetOpt_Wide(goi, &w);
275
			if (e != JIM_OK) {
276
				Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
277
278
				free((void *)pTap->dotted_name);
				free(pTap);
279
280
281
				return e;
			}

282
			new_expected_ids = malloc(sizeof(uint32_t) * (pTap->expected_ids_cnt + 1));
283
			if (new_expected_ids == NULL) {
284
				Jim_SetResult_sprintf(goi->interp, "no memory");
285
286
				free((void *)pTap->dotted_name);
				free(pTap);
287
288
289
				return JIM_ERR;
			}

290
			memcpy(new_expected_ids, pTap->expected_ids, sizeof(uint32_t) * pTap->expected_ids_cnt);
291
292

			new_expected_ids[pTap->expected_ids_cnt] = w;
293
294

			free(pTap->expected_ids);
295
296
			pTap->expected_ids = new_expected_ids;
			pTap->expected_ids_cnt++;
297
			break;
298
		}
299
300
301
		case NTAP_OPT_IRLEN:
		case NTAP_OPT_IRMASK:
		case NTAP_OPT_IRCAPTURE:
302
			e = Jim_GetOpt_Wide(goi, &w);
zwelch's avatar
zwelch committed
303
			if (e != JIM_OK) {
304
				Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
305
306
				free((void *)pTap->dotted_name);
				free(pTap);
307
308
				return e;
			}
zwelch's avatar
zwelch committed
309
			switch (n->value) {
310
			case NTAP_OPT_IRLEN:
zwelch's avatar
zwelch committed
311
				if (w > (jim_wide) (8 * sizeof(pTap->ir_capture_value)))
312
313
314
					LOG_WARNING("%s: huge IR length %d",
							pTap->dotted_name,
							(int) w);
315
316
317
				pTap->ir_length = w;
				break;
			case NTAP_OPT_IRMASK:
zwelch's avatar
zwelch committed
318
				if (is_bad_irval(pTap->ir_length, w)) {
319
320
					LOG_ERROR("%s: IR mask %x too big",
							pTap->dotted_name,
zwelch's avatar
zwelch committed
321
							(int) w);
322
323
					free((void *)pTap->dotted_name);
					free(pTap);
zwelch's avatar
zwelch committed
324
325
					return ERROR_FAIL;
				}
326
327
328
				if ((w & 3) != 3)
					LOG_WARNING("%s: nonstandard IR mask",
							pTap->dotted_name);
329
330
331
				pTap->ir_capture_mask = w;
				break;
			case NTAP_OPT_IRCAPTURE:
zwelch's avatar
zwelch committed
332
				if (is_bad_irval(pTap->ir_length, w)) {
333
334
					LOG_ERROR("%s: IR capture %x too big",
							pTap->dotted_name,
zwelch's avatar
zwelch committed
335
							(int) w);
336
337
					free((void *)pTap->dotted_name);
					free(pTap);
zwelch's avatar
zwelch committed
338
339
					return ERROR_FAIL;
				}
340
341
342
				if ((w & 3) != 1)
					LOG_WARNING("%s: nonstandard IR value",
							pTap->dotted_name);
343
344
345
				pTap->ir_capture_value = w;
				break;
			}
zwelch's avatar
zwelch committed
346
		} /* switch (n->value) */
347
	} /* while (goi->argc) */
348

zwelch's avatar
zwelch committed
349
350
351
	/* default is enabled-after-reset */
	pTap->enabled = !pTap->disabled_after_reset;

352
	/* Did all the required option bits get cleared? */
353
	if (pTap->ir_length != 0)
354
355
356
	{
		jtag_tap_init(pTap);
		return ERROR_OK;
357
358
	}

359
	Jim_SetResult_sprintf(goi->interp,
360
			"newtap: %s missing IR length",
361
			pTap->dotted_name);
362
	jtag_tap_free(pTap);
363
364
	return JIM_ERR;
}
365

zwelch's avatar
zwelch committed
366
static void jtag_tap_handle_event(jtag_tap_t *tap, enum jtag_event e)
367
368
369
{
	jtag_tap_event_action_t * jteap;

dbrownell's avatar
dbrownell committed
370
	for (jteap = tap->event_action; jteap != NULL; jteap = jteap->next) {
371
		if (jteap->event == e) {
372
			LOG_DEBUG("JTAG tap: %s event: %d (%s)\n\taction: %s",
373
374
375
					tap->dotted_name,
					e,
					Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name,
376
					Jim_GetString(jteap->body, NULL));
377
378
			if (Jim_EvalObj(interp, jteap->body) != JIM_OK) {
				Jim_PrintErrorMessage(interp);
379
380
381
			} else switch (e) {
			case JTAG_TAP_EVENT_ENABLE:
			case JTAG_TAP_EVENT_DISABLE:
zwelch's avatar
zwelch committed
382
				/* NOTE:  we currently assume the handlers
383
384
				 * can't fail.  Right here is where we should
				 * really be verifying the scan chains ...
zwelch's avatar
zwelch committed
385
				 */
386
				tap->enabled = (e == JTAG_TAP_EVENT_ENABLE);
387
388
				LOG_INFO("JTAG tap: %s %s", tap->dotted_name,
					tap->enabled ? "enabled" : "disabled");
389
390
391
				break;
			default:
				break;
392
393
394
395
396
397
			}
		}
	}
}


398
static int jim_jtag_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
399
400
401
402
{
	Jim_GetOptInfo goi;
	int e;
	Jim_Nvp *n;
403
	Jim_Obj *o;
404
405
406
407
	struct command_context_s *context;

	enum {
		JTAG_CMD_INTERFACE,
408
		JTAG_CMD_INIT,
409
		JTAG_CMD_INIT_RESET,
410
411
412
		JTAG_CMD_NEWTAP,
		JTAG_CMD_TAPENABLE,
		JTAG_CMD_TAPDISABLE,
413
414
		JTAG_CMD_TAPISENABLED,
		JTAG_CMD_CONFIGURE,
zwelch's avatar
zwelch committed
415
416
		JTAG_CMD_CGET,
		JTAG_CMD_NAMES,
417
	};
418

419
420
	const Jim_Nvp jtag_cmds[] = {
		{ .name = "interface"     , .value = JTAG_CMD_INTERFACE },
421
		{ .name = "arp_init"      , .value = JTAG_CMD_INIT },
422
		{ .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET },
423
424
425
426
		{ .name = "newtap"        , .value = JTAG_CMD_NEWTAP },
		{ .name = "tapisenabled"     , .value = JTAG_CMD_TAPISENABLED },
		{ .name = "tapenable"     , .value = JTAG_CMD_TAPENABLE },
		{ .name = "tapdisable"    , .value = JTAG_CMD_TAPDISABLE },
427
428
		{ .name = "configure"     , .value = JTAG_CMD_CONFIGURE },
		{ .name = "cget"          , .value = JTAG_CMD_CGET },
zwelch's avatar
zwelch committed
429
		{ .name = "names"         , .value = JTAG_CMD_NAMES },
430

431
432
433
434
		{ .name = NULL, .value = -1 },
	};

	context = Jim_GetAssocData(interp, "context");
435
	/* go past the command */
436
	Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
437

438
	e = Jim_GetOpt_Nvp(&goi, jtag_cmds, &n);
zwelch's avatar
zwelch committed
439
	if (e != JIM_OK) {
440
		Jim_GetOpt_NvpUnknown(&goi, jtag_cmds, 0);
441
442
		return e;
	}
443
		Jim_SetEmptyResult(goi.interp);
zwelch's avatar
zwelch committed
444
	switch (n->value) {
445
	case JTAG_CMD_INTERFACE:
446
447
448
		/* return the name of the interface */
		/* TCL code might need to know the exact type... */
		/* FUTURE: we allow this as a means to "set" the interface. */
zwelch's avatar
zwelch committed
449
		if (goi.argc != 0) {
450
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
451
452
			return JIM_ERR;
		}
453
		Jim_SetResultString(goi.interp, jtag_interface->name, -1);
454
		return JIM_OK;
455
456
457
458
459
460
461
462
463
464
465
	case JTAG_CMD_INIT:
		if (goi.argc != 0) {
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
			return JIM_ERR;
		}
		e = jtag_init_inner(context);
		if (e != ERROR_OK) {
			Jim_SetResult_sprintf(goi.interp, "error: %d", e);
			return JIM_ERR;
		}
		return JIM_OK;
466
	case JTAG_CMD_INIT_RESET:
zwelch's avatar
zwelch committed
467
		if (goi.argc != 0) {
468
			Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
469
470
471
			return JIM_ERR;
		}
		e = jtag_init_reset(context);
zwelch's avatar
zwelch committed
472
		if (e != ERROR_OK) {
473
			Jim_SetResult_sprintf(goi.interp, "error: %d", e);
474
475
476
			return JIM_ERR;
		}
		return JIM_OK;
477
	case JTAG_CMD_NEWTAP:
478
		return jim_newtap_cmd(&goi);
479
480
481
482
		break;
	case JTAG_CMD_TAPISENABLED:
	case JTAG_CMD_TAPENABLE:
	case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
483
		if (goi.argc != 1) {
484
			Jim_SetResultString(goi.interp, "Too many parameters",-1);
485
486
			return JIM_ERR;
		}
oharboe's avatar
oharboe committed
487
488

		{
489
			jtag_tap_t *t;
zwelch's avatar
zwelch committed
490
491
492

			t = jtag_tap_by_jim_obj(goi.interp, goi.argv[0]);
			if (t == NULL)
493
				return JIM_ERR;
zwelch's avatar
zwelch committed
494
495

			switch (n->value) {
496
497
498
			case JTAG_CMD_TAPISENABLED:
				break;
			case JTAG_CMD_TAPENABLE:
zwelch's avatar
zwelch committed
499
500
501
502
503
504
505
506
507
508
				if (t->enabled)
					break;
				jtag_tap_handle_event(t, JTAG_TAP_EVENT_ENABLE);
				if (!t->enabled)
					break;

				/* FIXME add JTAG sanity checks, w/o TLR
				 *  - scan chain length grew by one (this)
				 *  - IDs and IR lengths are as expected
				 */
zwelch's avatar
zwelch committed
509
510

				jtag_call_event_callbacks(JTAG_TAP_EVENT_ENABLE);
511
512
				break;
			case JTAG_CMD_TAPDISABLE:
zwelch's avatar
zwelch committed
513
514
515
516
517
518
519
520
521
522
				if (!t->enabled)
					break;
				jtag_tap_handle_event(t, JTAG_TAP_EVENT_DISABLE);
				if (t->enabled)
					break;

				/* FIXME add JTAG sanity checks, w/o TLR
				 *  - scan chain length shrank by one (this)
				 *  - IDs and IR lengths are as expected
				 */
zwelch's avatar
zwelch committed
523
524

				jtag_call_event_callbacks(JTAG_TAP_EVENT_DISABLE);
525
526
				break;
			}
zwelch's avatar
zwelch committed
527
528
			e = t->enabled;
			Jim_SetResult(goi.interp, Jim_NewIntObj(goi.interp, e));
529
530
			return JIM_OK;
		}
531
532
533
		break;

	case JTAG_CMD_CGET:
zwelch's avatar
zwelch committed
534
		if (goi.argc < 2) {
zwelch's avatar
zwelch committed
535
536
			Jim_WrongNumArgs(goi.interp, 0, NULL,
					"cget tap_name queryparm");
537
538
539
540
541
542
543
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
544
			t = jtag_tap_by_jim_obj(goi.interp, o);
zwelch's avatar
zwelch committed
545
			if (t == NULL) {
546
547
548
549
				return JIM_ERR;
			}

			goi.isconfigure = 0;
550
			return jtag_tap_configure_cmd(&goi, t);
551
552
553
554
		}
		break;

	case JTAG_CMD_CONFIGURE:
zwelch's avatar
zwelch committed
555
		if (goi.argc < 3) {
zwelch's avatar
zwelch committed
556
557
			Jim_WrongNumArgs(goi.interp, 0, NULL,
					"configure tap_name attribute value ...");
558
559
560
561
562
563
564
			return JIM_ERR;
		}

		{
			jtag_tap_t *t;

			Jim_GetOpt_Obj(&goi, &o);
565
			t = jtag_tap_by_jim_obj(goi.interp, o);
zwelch's avatar
zwelch committed
566
			if (t == NULL) {
567
568
569
570
				return JIM_ERR;
			}

			goi.isconfigure = 1;
571
			return jtag_tap_configure_cmd(&goi, t);
572
		}
zwelch's avatar
zwelch committed
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
		break;

	case JTAG_CMD_NAMES:
		if (goi.argc != 0) {
			Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
			return JIM_ERR;
		}
		Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
		{
			jtag_tap_t *tap;

			for (tap = jtag_all_taps(); tap; tap = tap->next_tap) {
				Jim_ListAppendElement(goi.interp,
					Jim_GetResult(goi.interp),
					Jim_NewStringObj(goi.interp,
						tap->dotted_name, -1));
			}
			return JIM_OK;
		}
		break;

594
	}
595

596
597
598
	return JIM_ERR;
}

599

600
void jtag_notify_event(enum jtag_event event)
601
602
{
	jtag_tap_t *tap;
603

604
	for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
605
		jtag_tap_handle_event(tap, event);
606
607
608
}


609
610
int jtag_register_commands(struct command_context_s *cmd_ctx)
{
611
	register_jim(cmd_ctx, "jtag", jim_jtag_command, "perform jtag tap actions");
612

613
	register_command(cmd_ctx, NULL, "interface", handle_interface_command,
oharboe's avatar
oharboe committed
614
		COMMAND_CONFIG, "try to configure interface");
615
616
617
	register_command(cmd_ctx, NULL,
		"interface_list", &handle_interface_list_command,
		COMMAND_ANY, "list all built-in interfaces");
618
	register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
zwelch's avatar
zwelch committed
619
		COMMAND_ANY, "(DEPRECATED) set jtag speed (if supported)");
620
	register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
zwelch's avatar
zwelch committed
621
622
		COMMAND_ANY, "set maximum jtag speed (if supported); "
		"parameter is maximum khz, or 0 for adaptive clocking (RTCK).");
623
624
	register_command(cmd_ctx, NULL, "jtag_rclk", handle_jtag_rclk_command,
		COMMAND_ANY, "fallback_speed_khz - set JTAG speed to RCLK or use fallback speed");
625
	register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
zwelch's avatar
zwelch committed
626
		COMMAND_CONFIG, "(DEPRECATED) jtag_device <ir_length> <ir_expected> <ir_mask>");
627
	register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
628
		COMMAND_ANY,
dbrownell's avatar
dbrownell committed
629
630
631
632
633
634
		"reset_config "
		"[none|trst_only|srst_only|trst_and_srst] "
		"[srst_pulls_trst|trst_pulls_srst|combined|separate] "
		"[srst_gates_jtag|srst_nogate] "
		"[trst_push_pull|trst_open_drain] "
		"[srst_push_pull|srst_open_drain]");
635
	register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
636
		COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms");
637
	register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
638
		COMMAND_ANY, "jtag_ntrst_delay <ms> - delay after deasserting trst in ms");
oharboe's avatar
oharboe committed
639
640
641
642
	register_command(cmd_ctx, NULL, "jtag_nsrst_assert_width", handle_jtag_nsrst_assert_width_command,
		COMMAND_ANY, "jtag_nsrst_assert_width <ms> - delay after asserting srst in ms");
	register_command(cmd_ctx, NULL, "jtag_ntrst_assert_width", handle_jtag_ntrst_assert_width_command,
		COMMAND_ANY, "jtag_ntrst_assert_width <ms> - delay after asserting trst in ms");
643

644
645
646
647
648
649
650
651
652
	register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
		COMMAND_EXEC, "print current scan chain configuration");

	register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
		COMMAND_EXEC, "toggle reset lines <trst> <srst>");
	register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
		COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");
	register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
		COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
653
	register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
654
	register_jim(cmd_ctx, "flush_count", Jim_Command_flush_count, "returns number of times the JTAG queue has been flushed");
oharboe's avatar
oharboe committed
655
	register_jim(cmd_ctx, "pathmove", Jim_Command_pathmove, "move JTAG to state1 then to state2, state3, etc. <state1>,<state2>,<stat3>...");
656
657

	register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
zwelch's avatar
zwelch committed
658
		COMMAND_ANY, "verify value captured during Capture-IR <enable | disable>");
oharboe's avatar
oharboe committed
659
	register_command(cmd_ctx, NULL, "verify_jtag", handle_verify_jtag_command,
zwelch's avatar
zwelch committed
660
		COMMAND_ANY, "verify value capture <enable | disable>");
661
	register_command(cmd_ctx, NULL, "tms_sequence", handle_tms_sequence_command,
zwelch's avatar
zwelch committed
662
		COMMAND_ANY, "choose short(default) or long tms_sequence <short | long>");
663
664
665
	return ERROR_OK;
}

666
667
static int default_khz(int khz, int *jtag_speed)
{
668
	LOG_ERROR("Translation from khz to jtag_speed not implemented");
669
670
671
	return ERROR_FAIL;
}

oharboe's avatar
oharboe committed
672
static int default_speed_div(int speed, int *khz)
673
{
674
	LOG_ERROR("Translation from jtag_speed to khz not implemented");
675
676
677
678
679
	return ERROR_FAIL;
}

static int default_power_dropout(int *dropout)
{
zwelch's avatar
zwelch committed
680
	*dropout = 0; /* by default we can't detect power dropout */
681
682
683
684
685
	return ERROR_OK;
}

static int default_srst_asserted(int *srst_asserted)
{
zwelch's avatar
zwelch committed
686
	*srst_asserted = 0; /* by default we can't detect srst asserted */
687
	return ERROR_OK;
688
689
}

690
691
static int handle_interface_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
692
693
694
695
{
	/* check whether the interface is already configured */
	if (jtag_interface)
	{
696
		LOG_WARNING("Interface already configured, ignoring");
697
698
699
700
		return ERROR_OK;
	}

	/* interface name is a mandatory argument */
701
	if (argc != 1 || args[0][0] == '\0')
702
703
		return ERROR_COMMAND_SYNTAX_ERROR;

704
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
705
	{
706
707
708
709
710
		if (strcmp(args[0], jtag_interfaces[i]->name) != 0)
			continue;

		int retval = jtag_interfaces[i]->register_commands(cmd_ctx);
		if (ERROR_OK != retval)
711
				return retval;
712

713
		jtag_interface = jtag_interfaces[i];
714

715
716
717
718
719
720
721
722
		if (jtag_interface->khz == NULL)
			jtag_interface->khz = default_khz;
		if (jtag_interface->speed_div == NULL)
			jtag_interface->speed_div = default_speed_div;
		if (jtag_interface->power_dropout == NULL)
			jtag_interface->power_dropout = default_power_dropout;
		if (jtag_interface->srst_asserted == NULL)
			jtag_interface->srst_asserted = default_srst_asserted;
723

724
		return ERROR_OK;
725
726
727
728
729
	}

	/* no valid interface was found (i.e. the configuration option,
	 * didn't match one of the compiled-in interfaces
	 */
730
	LOG_ERROR("The specified JTAG interface was not found (%s)", args[0]);
731
732
733
734
735
736
737
738
739
740
741
	handle_interface_list_command(cmd_ctx, cmd, args, argc);
	return ERROR_JTAG_INVALID_INTERFACE;
}

static int handle_interface_list_command(struct command_context_s *cmd_ctx,
		char *cmd, char **args, int argc)
{
	if (strcmp(cmd, "interface_list") == 0 && argc > 0)
		return ERROR_COMMAND_SYNTAX_ERROR;

	command_print(cmd_ctx, "The following JTAG interfaces are available:");
742
	for (unsigned i = 0; NULL != jtag_interfaces[i]; i++)
743
744
745
746
	{
		const char *name = jtag_interfaces[i]->name;
		command_print(cmd_ctx, "%u: %s", i + 1, name);
	}
747

748
	return ERROR_OK;
749
750
}

751
static int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
752
{
753
754
755
	int e;
	char buf[1024];
	Jim_Obj *newargs[ 10 ];
756
757
758
759
760
761
762
763
	/*
	 * CONVERT SYNTAX
	 * argv[-1] = command
	 * argv[ 0] = ir length
	 * argv[ 1] = ir capture
	 * argv[ 2] = ir mask
	 * argv[ 3] = not actually used by anything but in the docs
	 */
oharboe's avatar
oharboe committed
764

zwelch's avatar
zwelch committed
765
	if (argc < 4) {
766
		command_print(cmd_ctx, "OLD DEPRECATED SYNTAX: Please use the NEW syntax");
767
		return ERROR_OK;
768
	}
769
770
	command_print(cmd_ctx, "OLD SYNTAX: DEPRECATED - translating to new syntax");
	command_print(cmd_ctx, "jtag newtap CHIP TAP -irlen %s -ircapture %s -irvalue %s",
771
772
				   args[0],
				   args[1],
773
				   args[2]);
774
775
776
777
778
	command_print(cmd_ctx, "Example: STM32 has 2 taps, the cortexM3(len4) + boundaryscan(len5)");
	command_print(cmd_ctx, "jtag newtap stm32 cortexm3 ....., thus creating the tap: \"stm32.cortexm3\"");
	command_print(cmd_ctx, "jtag newtap stm32 boundary ....., and the tap: \"stm32.boundary\"");
	command_print(cmd_ctx, "And then refer to the taps by the dotted name.");

779
780
781
782
783
784
785
786
787
788
789
790
	newargs[0] = Jim_NewStringObj(interp, "jtag", -1);
	newargs[1] = Jim_NewStringObj(interp, "newtap", -1);
	sprintf(buf, "chip%d", jtag_tap_count());
	newargs[2] = Jim_NewStringObj(interp, buf, -1);
	sprintf(buf, "tap%d", jtag_tap_count());
	newargs[3] = Jim_NewStringObj(interp, buf, -1);
	newargs[4] = Jim_NewStringObj(interp, "-irlen", -1);
	newargs[5] = Jim_NewStringObj(interp, args[0], -1);
	newargs[6] = Jim_NewStringObj(interp, "-ircapture", -1);
	newargs[7] = Jim_NewStringObj(interp, args[1], -1);
	newargs[8] = Jim_NewStringObj(interp, "-irmask", -1);
	newargs[9] = Jim_NewStringObj(interp, args[2], -1);
791
792
793

	command_print(cmd_ctx, "NEW COMMAND:");
	sprintf(buf, "%s %s %s %s %s %s %s %s %s %s",
794
795
796
797
798
799
800
801
802
803
804
805
			 Jim_GetString(newargs[0], NULL),
			 Jim_GetString(newargs[1], NULL),
			 Jim_GetString(newargs[2], NULL),
			 Jim_GetString(newargs[3], NULL),
			 Jim_GetString(newargs[4], NULL),
			 Jim_GetString(newargs[5], NULL),
			 Jim_GetString(newargs[6], NULL),
			 Jim_GetString(newargs[7], NULL),
			 Jim_GetString(newargs[8], NULL),
			 Jim_GetString(newargs[9], NULL));

	e = jim_jtag_command(interp, 10, newargs);
zwelch's avatar
zwelch committed
806
	if (e != JIM_OK) {
807
		command_print(cmd_ctx, "%s", Jim_GetString(Jim_GetResult(interp), NULL));
808
809
	}
	return e;
810
811
}

812
static int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
813
{
814
	jtag_tap_t *tap;
815

816
	tap = jtag_all_taps();
817
818
819
	command_print(cmd_ctx, "     TapName            | Enabled |   IdCode      Expected    IrLen IrCap  IrMask Instr     ");
	command_print(cmd_ctx, "---|--------------------|---------|------------|------------|------|------|------|---------");

zwelch's avatar
zwelch committed
820
	while (tap) {
821
		uint32_t expected, expected_mask, cur_instr, ii;
822
823
824
		expected = buf_get_u32(tap->expected, 0, tap->ir_length);
		expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
		cur_instr = buf_get_u32(tap->cur_instr, 0, tap->ir_length);
825

826
827
828
829
830
		command_print(cmd_ctx,
					  "%2d | %-18s |    %c    | 0x%08x | 0x%08x | 0x%02x | 0x%02x | 0x%02x | 0x%02x",
					  tap->abs_chain_position,
					  tap->dotted_name,
					  tap->enabled ? 'Y' : 'n',
831
832
833
834
835
836
					  (unsigned int)(tap->idcode),
					  (unsigned int)(tap->expected_ids_cnt > 0 ? tap->expected_ids[0] : 0),
					  (unsigned int)(tap->ir_length),
					  (unsigned int)(expected),
					  (unsigned int)(expected_mask),
					  (unsigned int)(cur_instr));
837
838
839

		for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
			command_print(cmd_ctx, "   |                    |         |            | 0x%08x |      |      |      |         ",
840
						  (unsigned int)(tap->expected_ids[ii]));
841
842
		}

843
		tap = tap->next_tap;
844
845
846
847
848
	}

	return ERROR_OK;
}

849
static int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
850
{
zwelch's avatar
zwelch committed
851
852
853
854
855
856
857
858
859
860
861
862
863
864
	int new_cfg = 0;
	int mask = 0;

	/* Original versions cared about the order of these tokens:
	 *   reset_config signals [combination [trst_type [srst_type]]]
	 * They also clobbered the previous configuration even on error.
	 *
	 * Here we don't care about the order, and only change values
	 * which have been explicitly specified.
	 */
	for (; argc; argc--, args++) {
		int tmp = 0;
		int m;

dbrownell's avatar
dbrownell committed
865
866
		/* gating */
		m = RESET_SRST_NO_GATING;
867
		if (strcmp(*args, "srst_gates_jtag") == 0)
dbrownell's avatar
dbrownell committed
868
869
870
871
872
873
874
875
876
			/* default: don't use JTAG while SRST asserted */;
		else if (strcmp(*args, "srst_nogate") == 0)
			tmp = RESET_SRST_NO_GATING;
		else
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"gating", *args);
			return ERROR_INVALID_ARGUMENTS;
877
		}
dbrownell's avatar
dbrownell committed
878
879
		if (m)
			goto next;
880

zwelch's avatar
zwelch committed
881
882
883
884
885
886
887
888
889
890
		/* signals */
		m = RESET_HAS_TRST | RESET_HAS_SRST;
		if (strcmp(*args, "none") == 0)
			tmp = RESET_NONE;
		else if (strcmp(*args, "trst_only") == 0)
			tmp = RESET_HAS_TRST;
		else if (strcmp(*args, "srst_only") == 0)
			tmp = RESET_HAS_SRST;
		else if (strcmp(*args, "trst_and_srst") == 0)
			tmp = RESET_HAS_TRST | RESET_HAS_SRST;
891
		else
zwelch's avatar
zwelch committed
892
893
894
895
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"signal", *args);
896
897
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
		if (m)
			goto next;

		/* combination (options for broken wiring) */
		m = RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
		if (strcmp(*args, "separate") == 0)
			/* separate reset lines - default */;
		else if (strcmp(*args, "srst_pulls_trst") == 0)
			tmp |= RESET_SRST_PULLS_TRST;
		else if (strcmp(*args, "trst_pulls_srst") == 0)
			tmp |= RESET_TRST_PULLS_SRST;
		else if (strcmp(*args, "combined") == 0)
			tmp |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
		else
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"combination", *args);
			return ERROR_INVALID_ARGUMENTS;
917
		}
zwelch's avatar
zwelch committed
918
919
920
921
922
923
924
925
926
		if (m)
			goto next;

		/* trst_type (NOP without HAS_TRST) */
		m = RESET_TRST_OPEN_DRAIN;
		if (strcmp(*args, "trst_open_drain") == 0)
			tmp |= RESET_TRST_OPEN_DRAIN;
		else if (strcmp(*args, "trst_push_pull") == 0)
			/* push/pull from adapter - default */;
927
		else
zwelch's avatar
zwelch committed
928
929
930
931
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"trst_type", *args);
932
933
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
934
935
936
937
938
939
940
941
942
		if (m)
			goto next;

		/* srst_type (NOP without HAS_SRST) */
		m |= RESET_SRST_PUSH_PULL;
		if (strcmp(*args, "srst_push_pull") == 0)
			tmp |= RESET_SRST_PUSH_PULL;
		else if (strcmp(*args, "srst_open_drain") == 0)
			/* open drain from adapter - default */;
943
		else
zwelch's avatar
zwelch committed
944
945
946
947
			m = 0;
		if (mask & m) {
			LOG_ERROR("extra reset_config %s spec (%s)",
					"srst_type", *args);
948
949
			return ERROR_INVALID_ARGUMENTS;
		}
zwelch's avatar
zwelch committed
950
951
952
953
954
955
956
957
958
959
960
961
962
		if (m)
			goto next;

		/* caller provided nonsense; fail */
		LOG_ERROR("unknown reset_config flag (%s)", *args);
		return ERROR_INVALID_ARGUMENTS;

next:
		/* Remember the bits which were specified (mask)
		 * and their new values (new_cfg).
		 */
		mask |= m;
		new_cfg |= tmp;
963
	}
964

zwelch's avatar
zwelch committed
965
	/* clear previous values of those bits, save new values */
dbrownell's avatar
dbrownell committed
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
	if (mask) {
		int old_cfg = jtag_get_reset_config();

		old_cfg &= ~mask;
		new_cfg |= old_cfg;
		jtag_set_reset_config(new_cfg);
	} else
		new_cfg = jtag_get_reset_config();


	/*
	 * Display the (now-)current reset mode
	 */
	char *modes[5];

	/* minimal JTAG has neither SRST nor TRST (so that's the default) */
	switch (new_cfg & (RESET_HAS_TRST | RESET_HAS_SRST)) {
	case RESET_HAS_SRST:
		modes[0] = "srst_only";
		break;
	case RESET_HAS_TRST:
		modes[0] = "trst_only";
		break;
	case RESET_TRST_AND_SRST:
		modes[0] = "trst_and_srst";
		break;
	default:
		modes[0] = "none";
		break;
	}

	/* normally SRST and TRST are decoupled; but bugs happen ... */
	switch (new_cfg & (RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST)) {
	case RESET_SRST_PULLS_TRST:
		modes[1] = "srst_pulls_trst";
For faster browsing, not all history is shown. View entire blame