#include "config.h"
#endif
-#include "replacements.h"
-
#include "jtag.h"
-#include "command.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
-#include <assert.h>
+
int jtag_flush_queue_count; /* count # of flushes for profiling / debugging purposes */
+static void jtag_add_scan_check(void (*jtag_add_scan)(int num_fields, scan_field_t *fields, tap_state_t state),
+ int num_fields, scan_field_t *fields, tap_state_t state);
+
/* note that this is not marked as static as it must be available from outside jtag.c for those
that implement the jtag_xxx() minidriver layer
*/
int jtag_trst = 0;
int jtag_srst = 0;
+#ifndef HAVE_JTAG_MINIDRIVER_H
+struct jtag_callback_entry
+{
+ struct jtag_callback_entry *next;
+
+ jtag_callback_t callback;
+ u8 *in;
+ jtag_callback_data_t data1;
+ jtag_callback_data_t data2;
+ jtag_callback_data_t data3;
+};
+
+
+static struct jtag_callback_entry *jtag_callback_queue_head = NULL;
+static struct jtag_callback_entry *jtag_callback_queue_tail = NULL;
+#endif
+
+
jtag_command_t *jtag_command_queue = NULL;
jtag_command_t **last_comand_pointer = &jtag_command_queue;
static jtag_tap_t *jtag_all_taps = NULL;
void jtag_add_ir_scan(int num_fields, scan_field_t *fields, tap_state_t state)
{
/* 8 x 32 bit id's is enough for all invoations */
- u32 id[8];
- int modified[8];
-
-
- /* if we are to run a verification of the ir scan, we need to get the input back.
- * We may have to allocate space if the caller didn't ask for the input back.
- *
- */
- if (jtag_verify_capture_ir)
- {
- int j;
- for (j = 0; j < num_fields; j++)
- {
- modified[j]=0;
- if ((fields[j].in_value==NULL)&&(fields[j].num_bits<=32))
- {
- if (j<8)
- {
- modified[j]=1;
- fields[j].in_value=(u8 *)(id+j);
- } else
- {
- LOG_DEBUG("caller must provide in_value space for verify_capture_ir to work");
- }
- }
- }
- }
-
- jtag_add_ir_scan_noverify(num_fields, fields, state);
-
- if (jtag_verify_capture_ir)
+ int j;
+ for (j = 0; j < num_fields; j++)
{
- int j;
- for (j = 0; j < num_fields; j++)
+ fields[j].check_value=NULL;
+ fields[j].check_mask=NULL;
+ /* if we are to run a verification of the ir scan, we need to get the input back.
+ * We may have to allocate space if the caller didn't ask for the input back.
+ */
+ if (jtag_verify_capture_ir)
{
- jtag_tap_t *tap=fields[j].tap;
- jtag_check_value_mask(fields+j, tap->expected, tap->expected_mask);
-
- if (modified[j])
- {
- fields[j].in_value=NULL;
- }
+ fields[j].check_value=fields[j].tap->expected;
+ fields[j].check_mask=fields[j].tap->expected_mask;
}
}
+ jtag_add_scan_check(jtag_add_ir_scan_noverify, num_fields, fields, state);
}
int MINIDRIVER(interface_jtag_add_ir_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
break;
}
nth_tap++;
+
+ assert(nth_tap < x );
+
scan_size = tap->ir_length;
(*last_cmd)->cmd.scan->fields[nth_tap].tap = tap;
(*last_cmd)->cmd.scan->fields[nth_tap].num_bits = scan_size;
- (*last_cmd)->cmd.scan->fields[nth_tap].in_value = fields[nth_tap].in_value;
+ (*last_cmd)->cmd.scan->fields[nth_tap].in_value = NULL; /* do not collect input for tap's in bypass */
/* search the list */
for (j = 0; j < num_fields; j++)
if (tap == fields[j].tap)
{
found = 1;
+ (*last_cmd)->cmd.scan->fields[nth_tap].in_value = fields[j].in_value;
(*last_cmd)->cmd.scan->fields[nth_tap].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
tap->bypass = 0;
/* update device information */
buf_cpy((*last_cmd)->cmd.scan->fields[nth_tap].out_value, tap->cur_instr, scan_size);
}
+ assert(nth_tap == (x-1));
return ERROR_OK;
}
jtag_error=retval;
}
-void jtag_add_dr_scan_now(int num_fields, scan_field_t *fields, tap_state_t state)
+
+int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *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)
{
- jtag_add_dr_scan(num_fields, fields, state);
- jtag_execute_queue_noclear();
+ return jtag_check_value_inner(in, (u8 *)data1, (u8 *)data2, (int)data3);
}
+static void jtag_add_scan_check(void (*jtag_add_scan)(int num_fields, scan_field_t *fields, tap_state_t state),
+ int num_fields, scan_field_t *fields, tap_state_t state)
+{
+ for (int i=0; i<num_fields; i++)
+ {
+ fields[i].allocated=0;
+ fields[i].modified=0;
+ if ((fields[i].check_value!=NULL)&&(fields[i].in_value==NULL))
+ {
+ fields[i].modified=1;
+ /* we need storage space... */
+#ifdef HAVE_JTAG_MINIDRIVER_H
+ if (fields[i].num_bits<=32)
+ {
+ /* This is enough space and we're executing this synchronously */
+ fields[i].in_value=fields[i].intmp;
+ } else
+ {
+ fields[i].in_value=(u8 *)malloc(CEIL(fields[i].num_bits, 8));
+ fields[i].allocated=1;
+ }
+#else
+ fields[i].in_value=(u8 *)cmd_queue_alloc(CEIL(fields[i].num_bits, 8));
+#endif
+ }
+ }
+
+ jtag_add_scan(num_fields, fields, state);
+
+ for (int i=0; i<num_fields; i++)
+ {
+ if ((fields[i].check_value!=NULL)&&(fields[i].in_value!=NULL))
+ {
+ /* this is synchronous for a minidriver */
+ jtag_add_callback4(jtag_check_value_mask_callback, fields[i].in_value, (jtag_callback_data_t)fields[i].check_value, (jtag_callback_data_t)fields[i].check_mask, (jtag_callback_data_t)fields[i].num_bits);
+ }
+ if (fields[i].allocated)
+ {
+ free(fields[i].in_value);
+ }
+ if (fields[i].modified)
+ {
+ fields[i].in_value=NULL;
+ }
+ }
+}
+
+void jtag_add_dr_scan_check(int num_fields, scan_field_t *fields, tap_state_t state)
+{
+ jtag_add_scan_check(jtag_add_dr_scan, num_fields, fields, state);
+}
+
+
+
+
int MINIDRIVER(interface_jtag_add_dr_scan)(int num_fields, scan_field_t *fields, tap_state_t state)
{
int j;
return (tap == NULL) ? "(unknown)" : tap->dotted_name;
}
-int jtag_check_value_inner(u8 *captured, scan_field_t *field, u8 *in_check_value, u8 *in_check_mask)
+int jtag_check_value_inner(u8 *captured, u8 *in_check_value, u8 *in_check_mask, int num_bits)
{
int retval = ERROR_OK;
- int num_bits = field->num_bits;
int compare_failed = 0;
* only report a problem when there wasn't a handler, or if the handler
* acknowledged the error
*/
+ /*
LOG_WARNING("TAP %s:",
jtag_tap_name(field->tap));
+ */
if (compare_failed)
{
char *captured_char = buf_to_str(captured, (num_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : num_bits, 16);
jtag_execute_queue_noclear();
- int retval=jtag_check_value_inner(field->in_value, field, value, mask);
+ int retval=jtag_check_value_inner(field->in_value, value, mask, field->num_bits);
jtag_set_error(retval);
}
return type;
}
-int MINIDRIVER(interface_jtag_execute_queue)(void)
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+/* add callback to end of queue */
+void jtag_add_callback4(jtag_callback_t callback, u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
+{
+ struct jtag_callback_entry *entry=cmd_queue_alloc(sizeof(struct jtag_callback_entry));
+
+ entry->next=NULL;
+ entry->callback=callback;
+ entry->in=in;
+ entry->data1=data1;
+ entry->data2=data2;
+ entry->data3=data3;
+
+ if (jtag_callback_queue_head==NULL)
+ {
+ jtag_callback_queue_head=entry;
+ jtag_callback_queue_tail=entry;
+ } else
+ {
+ jtag_callback_queue_tail->next=entry;
+ jtag_callback_queue_tail=entry;
+ }
+}
+
+
+static int jtag_convert_to_callback4(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
+{
+ ((jtag_callback1_t)data1)(in);
+ return ERROR_OK;
+}
+
+void jtag_add_callback(jtag_callback1_t callback, u8 *in)
+{
+ jtag_add_callback4(jtag_convert_to_callback4, in, (jtag_callback_data_t)callback, 0, 0);
+}
+#endif
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+
+int interface_jtag_execute_queue(void)
{
int retval;
retval = jtag->execute_queue();
+ if (retval == ERROR_OK)
+ {
+ struct jtag_callback_entry *entry;
+ for (entry=jtag_callback_queue_head; entry!=NULL; entry=entry->next)
+ {
+ retval=entry->callback(entry->in, entry->data1, entry->data2, entry->data3);
+ if (retval!=ERROR_OK)
+ break;
+ }
+ }
+
cmd_queue_free();
+ jtag_callback_queue_head = NULL;
+ jtag_callback_queue_tail = NULL;
+
jtag_command_queue = NULL;
last_comand_pointer = &jtag_command_queue;
return retval;
}
+#endif
void jtag_execute_queue_noclear(void)
{
/* each flush can take as much as 1-2ms on high bandwidth low latency interfaces.
* E.g. a JTAG over TCP/IP or USB....
*/
- jtag_flush_queue_count++;
+ jtag_flush_queue_count++;
int retval=interface_jtag_execute_queue();
/* we keep the first error */
}
}
- fields = malloc(sizeof(scan_field_t) * argc / 2);
+ int num_fields= num_fields;
- for (i = 0; i < argc / 2; i++)
+ fields = malloc(sizeof(scan_field_t) * num_fields);
+
+ for (i = 0; i < num_fields; i++)
{
tap = jtag_TapByString( args[i*2] );
if (tap==NULL)
}
int field_size = tap->ir_length;
fields[i].tap = tap;
+ fields[i].num_bits = field_size;
fields[i].out_value = malloc(CEIL(field_size, 8));
buf_set_u32(fields[i].out_value, 0, field_size, strtoul(args[i*2+1], NULL, 0));
fields[i].in_value = NULL;
}
- jtag_add_ir_scan(argc / 2, fields, TAP_INVALID);
+ jtag_add_ir_scan(num_fields, fields, TAP_INVALID);
/* did we have an endstate? */
if (endstate != TAP_INVALID)
jtag_add_end_state(endstate);
jtag_execute_queue();
- for (i = 0; i < argc / 2; i++)
+ for (i = 0; i < num_fields; i++)
free(fields[i].out_value);
free (fields);
}
#endif // _DEBUG_JTAG_IO_
+#ifndef HAVE_JTAG_MINIDRIVER_H
+void jtag_alloc_in_value32(scan_field_t *field)
+{
+ field->in_value=(u8 *)cmd_queue_alloc(4);
+}
+#endif
+
+
/*-----</Cable Helper API>--------------------------------------*/