+ e = Jim_GetOpt_Wide( goi, &w );
+ if( e != JIM_OK) {
+ Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
+ return e;
+ }
+
+ new_expected_ids = malloc(sizeof(u32) * (pTap->expected_ids_cnt + 1));
+ if (new_expected_ids == NULL) {
+ Jim_SetResult_sprintf( goi->interp, "no memory");
+ return JIM_ERR;
+ }
+
+ memcpy(new_expected_ids, pTap->expected_ids, sizeof(u32) * pTap->expected_ids_cnt);
+
+ new_expected_ids[pTap->expected_ids_cnt] = w;
+
+ free(pTap->expected_ids);
+ pTap->expected_ids = new_expected_ids;
+ pTap->expected_ids_cnt++;
+ break;
+ }
+ case NTAP_OPT_IRLEN:
+ case NTAP_OPT_IRMASK:
+ case NTAP_OPT_IRCAPTURE:
+ e = Jim_GetOpt_Wide( goi, &w );
+ if( e != JIM_OK ){
+ Jim_SetResult_sprintf( goi->interp, "option: %s bad parameter", n->name );
+ return e;
+ }
+ if( (w < 0) || (w > 0xffff) ){
+ /* wacky value */
+ Jim_SetResult_sprintf( goi->interp, "option: %s - wacky value: %d (0x%x)",
+ n->name, (int)(w), (int)(w));
+ return JIM_ERR;
+ }
+ switch(n->value){
+ case NTAP_OPT_IRLEN:
+ pTap->ir_length = w;
+ reqbits &= (~(NTREQ_IRLEN));
+ break;
+ case NTAP_OPT_IRMASK:
+ pTap->ir_capture_mask = w;
+ reqbits &= (~(NTREQ_IRMASK));
+ break;
+ case NTAP_OPT_IRCAPTURE:
+ pTap->ir_capture_value = w;
+ reqbits &= (~(NTREQ_IRCAPTURE));
+ break;
+ }
+ } /* switch(n->value) */
+ } /* while( goi->argc ) */
+
+ /* Did we get all the options? */
+ if( reqbits ){
+ // no
+ Jim_SetResult_sprintf( goi->interp,
+ "newtap: %s missing required parameters",
+ pTap->dotted_name);
+ /* TODO: Tell user what is missing :-( */
+ /* no memory leaks pelase */
+ free(((void *)(pTap->expected_ids)));
+ free(((void *)(pTap->chip)));
+ free(((void *)(pTap->tapname)));
+ free(((void *)(pTap->dotted_name)));
+ free(((void *)(pTap)));
+ return JIM_ERR;
+ }
+
+ pTap->expected = malloc( pTap->ir_length );
+ pTap->expected_mask = malloc( pTap->ir_length );
+ pTap->cur_instr = malloc( pTap->ir_length );
+
+ buf_set_u32( pTap->expected,
+ 0,
+ pTap->ir_length,
+ pTap->ir_capture_value );
+ buf_set_u32( pTap->expected_mask,
+ 0,
+ pTap->ir_length,
+ pTap->ir_capture_mask );
+ buf_set_ones( pTap->cur_instr,
+ pTap->ir_length );
+
+ pTap->bypass = 1;
+
+ jtag_register_event_callback(jtag_reset_callback, pTap );
+
+ ppTap = &(jtag_all_taps);
+ while( (*ppTap) != NULL ){
+ ppTap = &((*ppTap)->next_tap);
+ }
+ *ppTap = pTap;
+ {
+ static int n_taps = 0;
+ pTap->abs_chain_position = n_taps++;
+ }
+ LOG_DEBUG( "Created Tap: %s @ abs position %d, irlen %d, capture: 0x%x mask: 0x%x",
+ (*ppTap)->dotted_name,
+ (*ppTap)->abs_chain_position,
+ (*ppTap)->ir_length,
+ (*ppTap)->ir_capture_value,
+ (*ppTap)->ir_capture_mask );
+
+ return ERROR_OK;
+}
+
+static int 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 {
+ JTAG_CMD_INTERFACE,
+ JTAG_CMD_INIT_RESET,
+ JTAG_CMD_NEWTAP,
+ JTAG_CMD_TAPENABLE,
+ JTAG_CMD_TAPDISABLE,
+ JTAG_CMD_TAPISENABLED,
+ JTAG_CMD_CONFIGURE,
+ JTAG_CMD_CGET
+ };
+
+ const Jim_Nvp jtag_cmds[] = {
+ { .name = "interface" , .value = JTAG_CMD_INTERFACE },
+ { .name = "arp_init-reset", .value = JTAG_CMD_INIT_RESET },
+ { .name = "newtap" , .value = JTAG_CMD_NEWTAP },
+ { .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 },
+ };
+
+ context = Jim_GetAssocData(interp, "context");
+ /* go past the command */
+ Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 );
+
+ e = Jim_GetOpt_Nvp( &goi, jtag_cmds, &n );
+ if( e != JIM_OK ){
+ Jim_GetOpt_NvpUnknown( &goi, jtag_cmds, 0 );
+ return e;
+ }
+ Jim_SetEmptyResult( goi.interp );
+ switch( n->value ){
+ case JTAG_CMD_INTERFACE:
+ /* 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. */
+ if( goi.argc != 0 ){
+ Jim_WrongNumArgs( goi.interp, 1, goi.argv-1, "(no params)");
+ return JIM_ERR;
+ }
+ Jim_SetResultString( goi.interp, jtag_interface->name, -1 );
+ return JIM_OK;
+ case JTAG_CMD_INIT_RESET:
+ if( goi.argc != 0 ){
+ Jim_WrongNumArgs( goi.interp, 1, goi.argv-1, "(no params)");
+ return JIM_ERR;
+ }
+ e = jtag_init_reset(context);
+ if( e != ERROR_OK ){
+ Jim_SetResult_sprintf( goi.interp, "error: %d", e);
+ return JIM_ERR;
+ }
+ return JIM_OK;
+ case JTAG_CMD_NEWTAP:
+ return jim_newtap_cmd( &goi );
+ break;
+ case JTAG_CMD_TAPISENABLED:
+ case JTAG_CMD_TAPENABLE:
+ case JTAG_CMD_TAPDISABLE:
+ if( goi.argc != 1 ){
+ Jim_SetResultString( goi.interp, "Too many parameters",-1 );
+ return JIM_ERR;
+ }
+
+ {
+ jtag_tap_t *t;
+ t = jtag_TapByJimObj( goi.interp, goi.argv[0] );
+ if( t == NULL ){
+ return JIM_ERR;
+ }
+ switch( n->value ){
+ case JTAG_CMD_TAPISENABLED:
+ e = t->enabled;
+ 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;
+ }
+ 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);
+ }
+ }
+
+ return JIM_ERR;
+}
+
+int jtag_register_commands(struct command_context_s *cmd_ctx)
+{
+ register_jim( cmd_ctx, "jtag", jim_jtag_command, "perform jtag tap actions");
+
+ register_command(cmd_ctx, NULL, "interface", handle_interface_command,
+ COMMAND_CONFIG, "try to configure interface");
+ register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
+ COMMAND_ANY, "set jtag speed (if supported)");
+ register_command(cmd_ctx, NULL, "jtag_khz", handle_jtag_khz_command,
+ COMMAND_ANY, "same as jtag_speed, except it takes maximum khz as arguments. 0 KHz = RTCK.");
+ register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
+ COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>");
+ register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
+ COMMAND_ANY,
+ "[none/trst_only/srst_only/trst_and_srst] [srst_pulls_trst/trst_pulls_srst] [combined/separate] [trst_push_pull/trst_open_drain] [srst_push_pull/srst_open_drain]");
+ register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
+ COMMAND_ANY, "jtag_nsrst_delay <ms> - delay after deasserting srst in ms");
+ register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
+ COMMAND_ANY, "jtag_ntrst_delay <ms> - delay after deasserting trst in ms");
+
+ register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
+ COMMAND_EXEC, "print current scan chain configuration");
+
+ register_command(cmd_ctx, NULL, "endstate", handle_endstate_command,
+ COMMAND_EXEC, "finish JTAG operations in <tap_state>");
+ 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] ...");
+ register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
+
+ register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
+ COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");
+ return ERROR_OK;
+}
+
+int jtag_interface_init(struct command_context_s *cmd_ctx)
+{
+ if (jtag)
+ return ERROR_OK;
+
+ if (!jtag_interface)
+ {
+ /* nothing was previously specified by "interface" command */
+ LOG_ERROR("JTAG interface has to be specified, see \"interface\" command");
+ return ERROR_JTAG_INVALID_INTERFACE;
+ }
+ if(hasKHz)
+ {
+ jtag_interface->khz(speed_khz, &jtag_speed);
+ hasKHz = 0;
+ }
+
+ if (jtag_interface->init() != ERROR_OK)
+ return ERROR_JTAG_INIT_FAILED;
+
+ jtag = jtag_interface;
+ return ERROR_OK;
+}
+
+static int jtag_init_inner(struct command_context_s *cmd_ctx)
+{
+ jtag_tap_t *tap;
+ int retval;
+
+ LOG_DEBUG("Init JTAG chain");
+
+ tap = jtag_NextEnabledTap(NULL);
+ if( tap == NULL ){
+ LOG_ERROR("There are no enabled taps?");
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+ jtag_add_tlr();
+ if ((retval=jtag_execute_queue())!=ERROR_OK)
+ return retval;
+
+ /* examine chain first, as this could discover the real chain layout */
+ if (jtag_examine_chain() != ERROR_OK)
+ {
+ LOG_ERROR("trying to validate configured JTAG chain anyway...");
+ }
+
+ if (jtag_validate_chain() != ERROR_OK)
+ {
+ LOG_WARNING("Could not validate JTAG chain, continuing anyway...");
+ }
+
+ return ERROR_OK;
+}
+
+int jtag_init_reset(struct command_context_s *cmd_ctx)
+{
+ int retval;
+
+ if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("Trying to bring the JTAG controller to life by asserting TRST / RESET");
+
+ /* Reset can happen after a power cycle.
+ *
+ * Ideally we would only assert TRST or run RESET before the target reset.
+ *
+ * However w/srst_pulls_trst, trst is asserted together with the target
+ * reset whether we want it or not.
+ *
+ * NB! Some targets have JTAG circuitry disabled until a
+ * trst & srst has been asserted.
+ *
+ * NB! here we assume nsrst/ntrst delay are sufficient!
+ *
+ * NB! order matters!!!! srst *can* disconnect JTAG circuitry
+ *
+ */
+ jtag_add_reset(1, 0); /* RESET or TRST */
+ if (jtag_reset_config & RESET_HAS_SRST)
+ {
+ jtag_add_reset(1, 1);
+ if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)
+ jtag_add_reset(0, 1);
+ }
+ jtag_add_reset(0, 0);
+ if ((retval = jtag_execute_queue()) != ERROR_OK)
+ return retval;
+
+ /* Check that we can communication on the JTAG chain + eventually we want to
+ * be able to perform enumeration only after OpenOCD has started
+ * telnet and GDB server
+ *
+ * That would allow users to more easily perform any magic they need to before
+ * reset happens.
+ */
+ return jtag_init_inner(cmd_ctx);
+}
+
+int jtag_init(struct command_context_s *cmd_ctx)
+{
+ int retval;
+ if ((retval=jtag_interface_init(cmd_ctx)) != ERROR_OK)
+ return retval;
+ if (jtag_init_inner(cmd_ctx)==ERROR_OK)
+ {
+ return ERROR_OK;
+ }
+ return jtag_init_reset(cmd_ctx);
+}
+
+static int default_khz(int khz, int *jtag_speed)
+{
+ LOG_ERROR("Translation from khz to jtag_speed not implemented");
+ return ERROR_FAIL;
+}
+
+static int default_speed_div(int speed, int *khz)
+{
+ LOG_ERROR("Translation from jtag_speed to khz not implemented");
+ return ERROR_FAIL;
+}
+
+static int default_power_dropout(int *dropout)
+{
+ *dropout=0; /* by default we can't detect power dropout */
+ return ERROR_OK;
+}
+
+static int default_srst_asserted(int *srst_asserted)
+{
+ *srst_asserted=0; /* by default we can't detect srst asserted */
+ return ERROR_OK;
+}
+
+int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ int i;
+ int retval;
+
+ /* check whether the interface is already configured */