From 846a2589a4161dc1e8e3730c9510a54381c26a5e Mon Sep 17 00:00:00 2001
From: kc8apf <kc8apf@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Date: Sat, 13 Dec 2008 07:05:38 +0000
Subject: [PATCH] Add JTAG tap events for enable/disable

git-svn-id: svn://svn.berlios.de/openocd/trunk@1237 b42882b7-edfa-0310-969c-e2dbd0fdcd60
---
 src/jtag/jtag.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/jtag/jtag.h |  24 ++++++-
 2 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c
index 0b70c0f14..3c05592fa 100644
--- a/src/jtag/jtag.c
+++ b/src/jtag/jtag.c
@@ -110,6 +110,13 @@ char* jtag_event_strings[] =
 	"JTAG controller reset (RESET or TRST)"
 };
 
+const Jim_Nvp nvp_jtag_tap_event[] = {
+	{ .value = JTAG_TAP_EVENT_ENABLE,       .name = "tap-enable" },
+	{ .value = JTAG_TAP_EVENT_DISABLE,      .name = "tap-disable" },
+
+	{ .name = NULL, .value = -1 }
+};
+
 /* kludge!!!! these are just global variables that the
  * interface use internally. They really belong
  * inside the drivers, but we don't want to break
@@ -1699,6 +1706,104 @@ int jtag_validate_chain(void)
 	return ERROR_OK;
 }
 
+enum jtag_tap_cfg_param {
+	JCFG_EVENT
+};
+
+static Jim_Nvp nvp_config_opts[] = {
+	{ .name = "-event",      .value = JCFG_EVENT },
+
+	{ .name = NULL,          .value = -1 }
+};
+
+static int
+jtag_tap_configure_cmd( Jim_GetOptInfo *goi,
+		jtag_tap_t * tap)
+{
+	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) {
+					Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ..." );
+					return JIM_ERR;
+				}
+
+				e = Jim_GetOpt_Nvp( goi, nvp_jtag_tap_event, &n );
+				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) {
+						if (jteap->event == n->value) {
+							break;
+						}
+						jteap = jteap->next;
+					}
+
+					if (goi->isconfigure) {
+						if (jteap == NULL) {
+							/* create new */
+							jteap = calloc(1, sizeof (*jteap));
+						}
+						jteap->event = n->value;
+						Jim_GetOpt_Obj( goi, &o);
+						if (jteap->body) {
+							Jim_DecrRefCount(interp, jteap->body);
+						}
+						jteap->body = Jim_DuplicateObj(goi->interp, o);
+						Jim_IncrRefCount(jteap->body);
+
+						/* add to head of event list */
+						jteap->next = tap->event_action;
+						tap->event_action = jteap;
+						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;
+}
 
 static int
 jim_newtap_cmd( Jim_GetOptInfo *goi )
@@ -1901,6 +2006,7 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 	Jim_GetOptInfo goi;
 	int e;
 	Jim_Nvp *n;
+	Jim_Obj *o;
 	struct command_context_s *context;
 
 	enum {
@@ -1909,7 +2015,9 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 		JTAG_CMD_NEWTAP,
 		JTAG_CMD_TAPENABLE,
 		JTAG_CMD_TAPDISABLE,
-		JTAG_CMD_TAPISENABLED
+		JTAG_CMD_TAPISENABLED,
+		JTAG_CMD_CONFIGURE,
+		JTAG_CMD_CGET
 	};
 
 	const Jim_Nvp jtag_cmds[] = {
@@ -1919,6 +2027,8 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 		{ .name = "tapisenabled"     , .value = JTAG_CMD_TAPISENABLED },
 		{ .name = "tapenable"     , .value = JTAG_CMD_TAPENABLE },
 		{ .name = "tapdisable"    , .value = JTAG_CMD_TAPDISABLE },
+		{ .name = "configure"     , .value = JTAG_CMD_CONFIGURE },
+		{ .name = "cget"          , .value = JTAG_CMD_CGET },
 
 		{ .name = NULL, .value = -1 },
 	};
@@ -1977,10 +2087,12 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 				// below
 				break;
 			case JTAG_CMD_TAPENABLE:
+				jtag_tap_handle_event( t, JTAG_TAP_EVENT_ENABLE);
 				e = 1;
 				t->enabled = e;
 				break;
 			case JTAG_CMD_TAPDISABLE:
+				jtag_tap_handle_event( t, JTAG_TAP_EVENT_DISABLE);
 				e = 0;
 				t->enabled = e;
 				break;
@@ -1988,6 +2100,46 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 			Jim_SetResult( goi.interp, Jim_NewIntObj( goi.interp, e ) );
 			return JIM_OK;
 		}
+		break;
+
+	case JTAG_CMD_CGET:
+		if( goi.argc < 2 ){
+			Jim_WrongNumArgs( goi.interp, 0, NULL, "?tap-name? -option ...");
+			return JIM_ERR;
+		}
+
+		{
+			jtag_tap_t *t;
+
+			Jim_GetOpt_Obj(&goi, &o);
+			t = jtag_TapByJimObj( goi.interp, o );
+			if( t == NULL ){
+				return JIM_ERR;
+			}
+
+			goi.isconfigure = 0;
+			return jtag_tap_configure_cmd( &goi, t);
+		}
+		break;
+
+	case JTAG_CMD_CONFIGURE:
+		if( goi.argc < 3 ){
+			Jim_WrongNumArgs( goi.interp, 0, NULL, "?tap-name? -option ?VALUE? ...");
+			return JIM_ERR;
+		}
+
+		{
+			jtag_tap_t *t;
+
+			Jim_GetOpt_Obj(&goi, &o);
+			t = jtag_TapByJimObj( goi.interp, o );
+			if( t == NULL ){
+				return JIM_ERR;
+			}
+
+			goi.isconfigure = 1;
+			return jtag_tap_configure_cmd( &goi, t);
+		}
 	}
 
 
@@ -2763,3 +2915,34 @@ int jtag_srst_asserted(int *srst_asserted)
 	return jtag->srst_asserted(srst_asserted);
 }
 
+void jtag_tap_handle_event( jtag_tap_t * tap, enum jtag_tap_event e)
+{
+	jtag_tap_event_action_t * jteap;
+	int done;
+
+	jteap = tap->event_action;
+
+	done = 0;
+	while (jteap) {
+		if (jteap->event == e) {
+			done = 1;
+			LOG_DEBUG( "JTAG tap: %s event: %d (%s) action: %s\n",
+					tap->dotted_name,
+					e,
+					Jim_Nvp_value2name_simple(nvp_jtag_tap_event, e)->name,
+					Jim_GetString(jteap->body, NULL) );
+			if (Jim_EvalObj(interp, jteap->body) != JIM_OK) {
+				Jim_PrintErrorMessage(interp);
+			}
+		}
+
+		jteap = jteap->next;
+	}
+
+	if (!done) {
+		LOG_DEBUG( "event %d %s - no action",
+				e,
+				Jim_Nvp_value2name_simple( nvp_jtag_tap_event, e)->name);
+	}
+}
+
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index 3ca084ac4..bd306abaf 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -158,6 +158,9 @@ typedef struct jtag_command_s
 
 extern jtag_command_t *jtag_command_queue;
 
+// forward declaration
+typedef struct jtag_tap_event_action_s jtag_tap_event_action_t;
+
 // this is really: typedef jtag_tap_t
 // But - the typedef is done in "types.h"
 // due to "forward decloration reasons"
@@ -178,6 +181,9 @@ struct jtag_tap_s
 	u8 expected_ids_cnt;/* Number of expected identification codes */
 	u8 *cur_instr;		/* current instruction */
 	int bypass;			/* bypass register selected */
+
+	jtag_tap_event_action_t *event_action;
+
 	jtag_tap_t *next_tap;
 };
 extern jtag_tap_t *jtag_AllTaps(void);
@@ -271,7 +277,21 @@ enum jtag_event
 	JTAG_TRST_ASSERTED
 };
 
-extern char* jtag_event_strings[];
+extern char * jtag_event_strings[];
+
+enum jtag_tap_event
+{
+	JTAG_TAP_EVENT_ENABLE,
+	JTAG_TAP_EVENT_DISABLE
+};
+
+extern const Jim_Nvp nvp_jtag_tap_event[];
+
+struct jtag_tap_event_action_s {
+	enum jtag_tap_event event;
+	Jim_Obj *body;
+	jtag_tap_event_action_t *next;
+};
 
 extern int jtag_trst;
 extern int jtag_srst;
@@ -462,6 +482,8 @@ extern int jtag_register_event_callback(int (*callback)(enum jtag_event event, v
 
 extern int jtag_verify_capture_ir;
 
+void jtag_tap_handle_event( jtag_tap_t * tap, enum jtag_tap_event e);
+
 /* error codes
  * JTAG subsystem uses codes between -100 and -199 */
 
-- 
GitLab