- Replace 'while(' with 'while ('.
[fw/openocd] / src / jtag / core.c
index 4c91abeeed7c8c40d653a60c1e48863b45c72e46..dd5c0a0e21b81133b673694debec364b92ef2615 100644 (file)
@@ -58,9 +58,11 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s
  */
 static int jtag_error = ERROR_OK;
 
-static char* jtag_event_strings[] =
+static const char *jtag_event_strings[] =
 {
-       "JTAG controller reset (RESET or TRST)"
+       [JTAG_TRST_ASSERTED] = "JTAG controller reset (RESET or TRST)",
+       [JTAG_TAP_EVENT_ENABLE] = "TAP enabled",
+       [JTAG_TAP_EVENT_DISABLE] = "TAP disabled",
 };
 
 static int jtag_trst = 0;
@@ -140,7 +142,7 @@ unsigned jtag_tap_count_enabled(void)
 {
        jtag_tap_t *t = jtag_all_taps();
        unsigned n = 0;
-       while(t)
+       while (t)
        {
                if (t->enabled)
                        n++;
@@ -155,7 +157,7 @@ void jtag_tap_add(struct jtag_tap_s *t)
        t->abs_chain_position = jtag_num_taps++;
 
        jtag_tap_t **tap = &__jtag_all_taps;
-       while(*tap != NULL)
+       while (*tap != NULL)
                tap = &(*tap)->next_tap;
        *tap = t;
 }
@@ -243,24 +245,30 @@ int jtag_register_event_callback(jtag_event_handler_t callback, void *priv)
        return ERROR_OK;
 }
 
-int jtag_unregister_event_callback(jtag_event_handler_t callback)
+int jtag_unregister_event_callback(jtag_event_handler_t callback, void *priv)
 {
-       jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
+       jtag_event_callback_t **callbacks_p;
+       jtag_event_callback_t **next;
 
        if (callback == NULL)
        {
                return ERROR_INVALID_ARGUMENTS;
        }
 
-       while (*callbacks_p)
+       for (callbacks_p = &jtag_event_callbacks;
+                       *callbacks_p != NULL;
+                       callbacks_p = next)
        {
-               jtag_event_callback_t **next = &((*callbacks_p)->next);
+               next = &((*callbacks_p)->next);
+
+               if ((*callbacks_p)->priv != priv)
+                       continue;
+
                if ((*callbacks_p)->callback == callback)
                {
                        free(*callbacks_p);
                        *callbacks_p = *next;
                }
-               callbacks_p = next;
        }
 
        return ERROR_OK;
@@ -274,8 +282,12 @@ int jtag_call_event_callbacks(enum jtag_event event)
 
        while (callback)
        {
+               jtag_event_callback_t *next;
+
+               /* callback may remove itself */
+               next = callback->next;
                callback->callback(event, callback->priv);
-               callback = callback->next;
+               callback = next;
        }
 
        return ERROR_OK;
@@ -341,23 +353,23 @@ void jtag_add_plain_ir_scan(int in_num_fields, const scan_field_t *in_fields,
        jtag_set_error(retval);
 }
 
-void jtag_add_callback(jtag_callback1_t f, u8 *in)
+void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
 {
-       interface_jtag_add_callback(f, in);
+       interface_jtag_add_callback(f, data0);
 }
 
-void jtag_add_callback4(jtag_callback_t f, u8 *in,
+void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
                jtag_callback_data_t data1, jtag_callback_data_t data2,
                jtag_callback_data_t data3)
 {
-       interface_jtag_add_callback4(f, in, data1, data2, data3);
+       interface_jtag_add_callback4(f, data0, data1, data2, data3);
 }
 
-int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits);
+int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits);
 
-static int jtag_check_value_mask_callback(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
+static int jtag_check_value_mask_callback(jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
 {
-       return jtag_check_value_inner(in, (u8 *)data1, (u8 *)data2, (int)data3);
+       return jtag_check_value_inner((uint8_t *)data0, (uint8_t *)data1, (uint8_t *)data2, (int)data3);
 }
 
 static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const scan_field_t *in_fields, tap_state_t state),
@@ -381,7 +393,7 @@ static void jtag_add_scan_check(void (*jtag_add_scan)(int in_num_fields, const s
                if ((in_fields[i].check_value != NULL) && (in_fields[i].in_value != NULL))
                {
                        /* this is synchronous for a minidriver */
-                       jtag_add_callback4(jtag_check_value_mask_callback, in_fields[i].in_value,
+                       jtag_add_callback4(jtag_check_value_mask_callback, (jtag_callback_data_t)in_fields[i].in_value,
                                (jtag_callback_data_t)in_fields[i].check_value,
                                (jtag_callback_data_t)in_fields[i].check_mask,
                                (jtag_callback_data_t)in_fields[i].num_bits);
@@ -430,7 +442,7 @@ void jtag_add_plain_dr_scan(int in_num_fields, const scan_field_t *in_fields,
 }
 
 void jtag_add_dr_out(jtag_tap_t* tap,
-               int num_fields, const int* num_bits, const u32* value,
+               int num_fields, const int* num_bits, const uint32_t* value,
                tap_state_t end_state)
 {
        assert(end_state != TAP_INVALID);
@@ -498,11 +510,11 @@ int jtag_add_statemove(tap_state_t goal_state)
 
        if (goal_state==cur_state )
                ;       /* nothing to do */
-       else if( goal_state==TAP_RESET )
+       else if ( goal_state==TAP_RESET )
        {
                jtag_add_tlr();
        }
-       else if( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) )
+       else if ( tap_is_state_stable(cur_state) && tap_is_state_stable(goal_state) )
        {
                unsigned tms_bits  = tap_get_tms_path(cur_state, goal_state);
                unsigned tms_count = tap_get_tms_path_len(cur_state, goal_state);
@@ -519,7 +531,7 @@ int jtag_add_statemove(tap_state_t goal_state)
 
                jtag_add_pathmove(tms_count, moves);
        }
-       else if( tap_state_transition(cur_state, true)  == goal_state
+       else if ( tap_state_transition(cur_state, true)  == goal_state
                ||   tap_state_transition(cur_state, false) == goal_state )
        {
                jtag_add_pathmove(1, &goal_state);
@@ -674,14 +686,14 @@ tap_state_t jtag_get_end_state(void)
        return cmd_queue_end_state;
 }
 
-void jtag_add_sleep(u32 us)
+void jtag_add_sleep(uint32_t us)
 {
        /// @todo Here, keep_alive() appears to be a layering violation!!!
        keep_alive();
        jtag_set_error(interface_jtag_add_sleep(us));
 }
 
-int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits)
+int jtag_check_value_inner(uint8_t *captured, uint8_t *in_check_value, uint8_t *in_check_mask, int num_bits)
 {
        int retval = ERROR_OK;
 
@@ -730,7 +742,7 @@ int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask,
        return retval;
 }
 
-void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask)
+void jtag_check_value_mask(scan_field_t *field, uint8_t *value, uint8_t *mask)
 {
        assert(field->in_value != NULL);
 
@@ -786,6 +798,8 @@ static int jtag_reset_callback(enum jtag_event event, void *priv)
 
        if (event == JTAG_TRST_ASSERTED)
        {
+               tap->enabled = !tap->disabled_after_reset;
+
                buf_set_ones(tap->cur_instr, tap->ir_length);
                tap->bypass = 1;
        }
@@ -793,7 +807,7 @@ static int jtag_reset_callback(enum jtag_event event, void *priv)
        return ERROR_OK;
 }
 
-void jtag_sleep(u32 us)
+void jtag_sleep(uint32_t us)
 {
        alive_sleep(us/1000);
 }
@@ -805,7 +819,7 @@ void jtag_sleep(u32 us)
 #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12)
 #define EXTRACT_VER(X)  (((X) & 0xf0000000) >> 28)
 
-static int jtag_examine_chain_execute(u8 *idcode_buffer, unsigned num_idcode)
+static int jtag_examine_chain_execute(uint8_t *idcode_buffer, unsigned num_idcode)
 {
        scan_field_t field = {
                        .tap = NULL,
@@ -822,10 +836,10 @@ static int jtag_examine_chain_execute(u8 *idcode_buffer, unsigned num_idcode)
        return jtag_execute_queue();
 }
 
-static bool jtag_examine_chain_check(u8 *idcodes, unsigned count)
+static bool jtag_examine_chain_check(uint8_t *idcodes, unsigned count)
 {
-       u8 zero_check = 0x0;
-       u8 one_check = 0xff;
+       uint8_t zero_check = 0x0;
+       uint8_t one_check = 0xff;
 
        for (unsigned i = 0; i < count * 4; i++)
        {
@@ -845,16 +859,19 @@ static bool jtag_examine_chain_check(u8 *idcodes, unsigned count)
 }
 
 static void jtag_examine_chain_display(enum log_levels level, const char *msg,
-               const char *name, u32 idcode)
+               const char *name, uint32_t idcode)
 {
        log_printf_lf(level, __FILE__, __LINE__, __FUNCTION__,
-                       "JTAG tap: %s %16.16s: 0x%08x "
-                       "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
-               name, msg, idcode,
-               EXTRACT_MFG(idcode), EXTRACT_PART(idcode), EXTRACT_VER(idcode) );
+                                 "JTAG tap: %s %16.16s: 0x%08x "
+                                 "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
+                                 name, msg, 
+                                 (unsigned int)idcode,
+                                 (unsigned int)EXTRACT_MFG(idcode), 
+                                 (unsigned int)EXTRACT_PART(idcode), 
+                                 (unsigned int)EXTRACT_VER(idcode) );
 }
 
-static bool jtag_idcode_is_final(u32 idcode)
+static bool jtag_idcode_is_final(uint32_t idcode)
 {
                return idcode == 0x000000FF || idcode == 0xFFFFFFFF;
 }
@@ -865,17 +882,17 @@ static bool jtag_idcode_is_final(u32 idcode)
  * read back correctly.  This can help identify and diagnose problems
  * with the JTAG chain earlier, gives more helpful/explicit error messages.
  */
-static void jtag_examine_chain_end(u8 *idcodes, unsigned count, unsigned max)
+static void jtag_examine_chain_end(uint8_t *idcodes, unsigned count, unsigned max)
 {
        bool triggered = false;
        for ( ; count < max - 31; count += 32)
        {
-               u32 idcode = buf_get_u32(idcodes, count, 32);
+               uint32_t idcode = buf_get_u32(idcodes, count, 32);
                // do not trigger the warning if the data looks good
                if (!triggered && jtag_idcode_is_final(idcode))
                        continue;
                LOG_WARNING("Unexpected idcode after end of chain: %d 0x%08x",
-                               count, idcode);
+                                       count, (unsigned int)idcode);
                triggered = true;
        }
 }
@@ -893,7 +910,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
        }
 
        /* Loop over the expected identification codes and test for a match */
-       u8 ii;
+       uint8_t ii;
        for (ii = 0; ii < tap->expected_ids_cnt; ii++)
        {
                if (tap->idcode == tap->expected_ids[ii])
@@ -923,7 +940,7 @@ static bool jtag_examine_chain_match_tap(const struct jtag_tap_s *tap)
  */
 int jtag_examine_chain(void)
 {
-       u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+       uint8_t idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
        unsigned device_count = 0;
 
        jtag_examine_chain_execute(idcode_buffer, JTAG_MAX_CHAIN_SIZE);
@@ -941,7 +958,7 @@ int jtag_examine_chain(void)
 
        for (unsigned bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
        {
-               u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
+               uint32_t idcode = buf_get_u32(idcode_buffer, bit_count, 32);
                if ((idcode & 1) == 0)
                {
                        /* LSB must not be 0, this indicates a device in bypass */
@@ -1001,7 +1018,7 @@ int jtag_validate_chain(void)
 {
        jtag_tap_t *tap;
        int total_ir_length = 0;
-       u8 *ir_test = NULL;
+       uint8_t *ir_test = NULL;
        scan_field_t field;
        int chain_pos = 0;
 
@@ -1009,7 +1026,7 @@ int jtag_validate_chain(void)
        total_ir_length = 0;
        for(;;){
                tap = jtag_tap_next_enabled(tap);
-               if( tap == NULL ){
+               if ( tap == NULL ){
                        break;
                }
                total_ir_length += tap->ir_length;
@@ -1033,7 +1050,7 @@ int jtag_validate_chain(void)
        int val;
        for(;;){
                tap = jtag_tap_next_enabled(tap);
-               if( tap == NULL ){
+               if ( tap == NULL ){
                        break;
                }
 
@@ -1073,6 +1090,7 @@ void jtag_tap_init(jtag_tap_t *tap)
        tap->expected_mask = malloc(tap->ir_length);
        tap->cur_instr = malloc(tap->ir_length);
 
+       /// @todo cope sanely with ir_length bigger than 32 bits
        buf_set_u32(tap->expected, 0, tap->ir_length, tap->ir_capture_value);
        buf_set_u32(tap->expected_mask, 0, tap->ir_length, tap->ir_capture_mask);
        buf_set_ones(tap->cur_instr, tap->ir_length);
@@ -1085,12 +1103,14 @@ void jtag_tap_init(jtag_tap_t *tap)
        LOG_DEBUG("Created Tap: %s @ abs position %d, "
                        "irlen %d, capture: 0x%x mask: 0x%x", tap->dotted_name,
                                tap->abs_chain_position, tap->ir_length,
-                               tap->ir_capture_value, tap->ir_capture_mask);
+                         (unsigned int)(tap->ir_capture_value), (unsigned int)(tap->ir_capture_mask));
        jtag_tap_add(tap);
 }
 
 void jtag_tap_free(jtag_tap_t *tap)
 {
+       jtag_unregister_event_callback(&jtag_reset_callback, tap);
+
        /// @todo is anything missing? no memory leaks please 
        free((void *)tap->expected_ids);
        free((void *)tap->chip);
@@ -1110,7 +1130,7 @@ int jtag_interface_init(struct command_context_s *cmd_ctx)
                LOG_ERROR("JTAG interface has to be specified, see \"interface\" command");
                return ERROR_JTAG_INVALID_INTERFACE;
        }
-       if(hasKHz)
+       if (hasKHz)
        {
                jtag_interface->khz(jtag_get_speed_khz(), &jtag_speed);
                hasKHz = false;
@@ -1131,7 +1151,7 @@ static int jtag_init_inner(struct command_context_s *cmd_ctx)
        LOG_DEBUG("Init JTAG chain");
 
        tap = jtag_tap_next_enabled(NULL);
-       if( tap == NULL ){
+       if ( tap == NULL ){
                LOG_ERROR("There are no enabled taps?");
                return ERROR_JTAG_INIT_FAILED;
        }