#ifndef JTAG_H
#define JTAG_H
-#include "types.h"
#include "binarybuffer.h"
#include "log.h"
-#include "command.h"
-
#ifdef _DEBUG_JTAG_IO_
#define DEBUG_JTAG_IO(expr ...) LOG_DEBUG(expr)
extern tap_state_t cmd_queue_end_state; /* finish DR scans in dr_end_state */
extern tap_state_t cmd_queue_cur_state; /* current TAP state */
-typedef void* error_handler_t; /* Later on we can delete error_handler_t, but keep it for now to make patches more readable */
-
-struct scan_field_s;
-typedef int (*in_handler_t)(u8* in_value, void* priv, struct scan_field_s* field);
-
typedef struct scan_field_s
{
jtag_tap_t* tap; /* tap pointer this instruction refers to */
int num_bits; /* number of bits this field specifies (up to 32) */
u8* out_value; /* value to be scanned into the device */
u8* in_value; /* pointer to a 32-bit memory location to take data scanned out */
- /* in_check_value/mask, in_handler_error_handler, in_handler_priv can be used by the in handler, otherwise they contain garbage */
- u8* in_check_value; /* deprecated! only used from jtag_set_check_value. used to validate scan results */
- u8* in_check_mask; /* deprecated! only used from jtag_set_check_value. check specified bits against check_value */
- in_handler_t in_handler; /* deprecated! SET TO NULL. DO NOT USE! process received buffer using this handler */
- void* in_handler_priv; /* deprecated! only used by obsolete in_handler implementations */
+
+ u8* check_value; /* Used together with jtag_add_dr_scan_check() to check data clocked
+ in */
+ u8* check_mask; /* mask to go with check_value */
+
+ /* internal work space */
+ int allocated; /* in_value has been allocated for the queue */
+ int modified; /* did we modify the in_value? */
+ u8 intmp[4]; /* temporary storage for checking synchronously */
} scan_field_t;
enum scan_type {
typedef struct scan_command_s
{
- int ir_scan; /* instruction/not data scan */
+ bool ir_scan; /* instruction/not data scan */
int num_fields; /* number of fields in *fields array */
scan_field_t* fields; /* pointer to an array of data scan fields */
tap_state_t end_state; /* TAP state in which JTAG commands should finish */
JTAG_STATEMOVE = 2,
JTAG_RUNTEST = 3,
JTAG_RESET = 4,
- JTAG_END_STATE = 5,
JTAG_PATHMOVE = 6,
JTAG_SLEEP = 7,
JTAG_STABLECLOCKS = 8
extern jtag_event_callback_t* jtag_event_callbacks;
-extern jtag_interface_t* jtag; /* global pointer to configured JTAG interface */
-
extern int jtag_speed;
extern int jtag_speed_post_reset;
*/
extern int jtag_interface_init(struct command_context_s* cmd_ctx);
+/// Shutdown the JTAG interface upon program exit.
+extern int jtag_interface_quit(void);
+
/* initialize JTAG chain using only a RESET reset. If init fails,
* try reset + init.
*/
*
*/
extern void jtag_add_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int interface_jtag_add_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-/* same as jtag_add_dr_scan but the scan is executed immediately. sets jtag_error if there
- * was a failure.
+/* same as jtag_add_ir_scan except no verify is performed */
+extern void jtag_add_ir_scan_noverify(int num_fields, const scan_field_t *fields, tap_state_t state);
+extern void jtag_add_dr_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+
+/* set in_value to point to 32 bits of memory to scan into. This function
+ * is a way to handle the case of synchronous and asynchronous
+ * JTAG queues.
+ *
+ * In the event of an asynchronous queue execution the queue buffer
+ * allocation method is used, for the synchronous case the temporary 32 bits come
+ * from the input field itself.
+ */
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+extern void jtag_alloc_in_value32(scan_field_t *field);
+#else
+static __inline__ void jtag_alloc_in_value32(scan_field_t *field)
+{
+ field->in_value=field->intmp;
+}
+#endif
+
+
+
+/* This version of jtag_add_dr_scan() uses the check_value/mask fields */
+extern void jtag_add_dr_scan_check(int num_fields, scan_field_t* fields, tap_state_t endstate);
+extern void jtag_add_plain_ir_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+extern void jtag_add_plain_dr_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+
+
+/* Simplest/typical callback - do some conversion on the data clocked in.
+ * This callback is for such conversion that can not fail.
+ * For conversion types or checks that can
+ * fail, use the jtag_callback_t variant */
+typedef void (*jtag_callback1_t)(u8 *in);
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+/* A simpler version of jtag_add_callback4 */
+extern void jtag_add_callback(jtag_callback1_t, u8 *in);
+#else
+/* implemented by minidriver */
+#endif
+
+
+/* This type can store an integer safely by a normal cast on 64 and
+ * 32 bit systems. */
+typedef intptr_t jtag_callback_data_t;
+
+/* The generic callback mechanism.
+ *
+ * The callback is invoked with three arguments. The first argument is
+ * the pointer to the data clocked in.
+ */
+typedef int (*jtag_callback_t)(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3);
+
+
+/* This callback can be executed immediately the queue has been flushed. Note that
+ * the JTAG queue can either be executed synchronously or asynchronously. Typically
+ * for USB the queue is executed asynchronously. For low latency interfaces, the
+ * queue may be executed synchronously.
+ *
+ * These callbacks are typically executed *after* the *entire* JTAG queue has been
+ * executed for e.g. USB interfaces.
+ *
+ * The callbacks are guaranteeed to be invoked in the order that they were queued.
+ *
+ * The strange name is due to C's lack of overloading using function arguments
+ *
+ * The callback mechansim is very general and does not really make any assumptions
+ * about what the callback does and what the arguments are.
+ *
+ * in - typically used to point to the data to operate on. More often than not
+ * this will be the data clocked in during a shift operation
+ *
+ * data1 - an integer that is big enough to be used either as an 'int' or
+ * cast to/from a pointer
+ *
+ * data2 - an integer that is big enough to be used either as an 'int' or
+ * cast to/from a pointer
+ *
+ * Why stop at 'data2' for arguments? Somewhat historical reasons. This is
+ * sufficient to implement the jtag_check_value_mask(), besides the
+ * line is best drawn somewhere...
+ *
+ * If the execution of the queue fails before the callbacks, then the
+ * callbacks may or may not be invoked depending on driver implementation.
*/
-extern void jtag_add_dr_scan_now(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int interface_jtag_add_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_plain_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int interface_jtag_add_plain_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_plain_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int interface_jtag_add_plain_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
+#ifndef HAVE_JTAG_MINIDRIVER_H
+extern void jtag_add_callback4(jtag_callback_t, u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3);
+#else
+/* implemented by minidriver */
+#endif
+
/* run a TAP_RESET reset. End state is TAP_RESET, regardless
* of start state.
*/
extern void jtag_add_tlr(void);
-extern int interface_jtag_add_tlr(void);
/* Application code *must* assume that interfaces will
* implement transitions between states with different
* a partial implementation of pathmove would have little practical
* application.
*/
-extern void jtag_add_pathmove(int num_states, tap_state_t* path);
-extern int interface_jtag_add_pathmove(int num_states, tap_state_t* path);
+extern void jtag_add_pathmove(int num_states, const tap_state_t* path);
/* go to TAP_IDLE, if we're not already there and cycle
* precisely num_cycles in the TAP_IDLE after which move
* to endstate via TAP_IDLE
*/
extern void jtag_add_runtest(int num_cycles, tap_state_t endstate);
-extern int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
/* A reset of the TAP state machine can be requested.
*
*/
extern void jtag_add_reset(int req_tlr_or_trst, int srst);
-/* this drives the actual srst and trst pins. srst will always be 0
- * if jtag_reset_config & RESET_SRST_PULLS_TRST != 0 and ditto for
- * trst.
- *
- * the higher level jtag_add_reset will invoke jtag_add_tlr() if
- * approperiate
- */
-extern int interface_jtag_add_reset(int trst, int srst);
extern void jtag_add_end_state(tap_state_t endstate);
-extern int interface_jtag_add_end_state(tap_state_t endstate);
extern void jtag_add_sleep(u32 us);
-extern int interface_jtag_add_sleep(u32 us);
/**
* stable, then queues up clock_count clocks for transmission.
*/
void jtag_add_clocks(int num_cycles);
-int interface_jtag_add_clocks(int num_cycles);
/*
/* can be implemented by hw+sw */
-extern int interface_jtag_execute_queue(void);
extern int jtag_power_dropout(int* dropout);
extern int jtag_srst_asserted(int* srst_asserted);
/* JTAG support functions */
struct invalidstruct
{
-
+
};
-extern void jtag_set_check_value(scan_field_t* field, u8* value, u8* mask, struct invalidstruct *obsolete);
-extern enum scan_type jtag_scan_type(scan_command_t* cmd);
-extern int jtag_scan_size(scan_command_t* cmd);
-extern int jtag_read_buffer(u8* buffer, scan_command_t* cmd);
-extern int jtag_build_buffer(scan_command_t* cmd, u8** buffer);
+/* execute jtag queue and check value and use mask if mask is != NULL. invokes
+ * jtag_set_error() with any error. */
+extern void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask);
+extern enum scan_type jtag_scan_type(const scan_command_t* cmd);
+extern int jtag_scan_size(const scan_command_t* cmd);
+extern int jtag_read_buffer(u8* buffer, const scan_command_t* cmd);
+extern int jtag_build_buffer(const scan_command_t* cmd, u8** buffer);
extern void jtag_sleep(u32 us);
extern int jtag_call_event_callbacks(enum jtag_event event);
#define ERROR_JTAG_NOT_STABLE_STATE (-105)
#define ERROR_JTAG_DEVICE_ERROR (-107)
+#ifdef INCLUDE_JTAG_MINIDRIVER_H
+
+extern int interface_jtag_add_ir_scan(
+ int num_fields, const scan_field_t* fields,
+ tap_state_t endstate);
+extern int interface_jtag_add_plain_ir_scan(
+ int num_fields, const scan_field_t* fields,
+ tap_state_t endstate);
+
+extern int interface_jtag_add_dr_scan(
+ int num_fields, const scan_field_t* fields,
+ tap_state_t endstate);
+extern int interface_jtag_add_plain_dr_scan(
+ int num_fields, const scan_field_t* fields,
+ tap_state_t endstate);
+
+extern int interface_jtag_add_tlr(void);
+extern int interface_jtag_add_pathmove(int num_states, const tap_state_t* path);
+extern int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
+
+/**
+ * This drives the actual srst and trst pins. srst will always be 0
+ * if jtag_reset_config & RESET_SRST_PULLS_TRST != 0 and ditto for
+ * trst.
+ *
+ * the higher level jtag_add_reset will invoke jtag_add_tlr() if
+ * approperiate
+ */
+extern int interface_jtag_add_reset(int trst, int srst);
+extern int interface_jtag_add_end_state(tap_state_t endstate);
+extern int interface_jtag_add_sleep(u32 us);
+extern int interface_jtag_add_clocks(int num_cycles);
+extern int interface_jtag_execute_queue(void);
+
+#endif // INCLUDE_JTAG_MINIDRIVER_H
/* this allows JTAG devices to implement the entire jtag_xxx() layer in hw/sw */
#ifdef HAVE_JTAG_MINIDRIVER_H
#define MINIDRIVER(a) notused ## a
#else
#define MINIDRIVER(a) a
+extern void interface_jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
+ tap_state_t end_state);
+
+#endif
-/* jtag_add_dr_out() is a faster version of jtag_add_dr_scan()
+/* jtag_add_dr_out() is a version of jtag_add_dr_scan() which
+ * only scans data out. It operates on 32 bit integers instead
+ * of 8 bit, which makes it a better impedance match with
+ * the calling code which often operate on 32 bit integers.
*
* Current or end_state can not be TAP_RESET. end_state can be TAP_INVALID
*
* return an error. There is no way to determine if there was a failure
* during this function call.
*
- * Note that this jtag_add_dr_out can be defined as an inline function.
+ * This is an inline fn to speed up embedded hosts. Also note that
+ * interface_jtag_add_dr_out() can be a *small* inline function for
+ * embedded hosts.
+ *
+ * There is no jtag_add_dr_outin() version of this fn that also allows
+ * clocking data back in. Patches gladly accepted!
*/
-extern void interface_jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
- tap_state_t end_state);
-
-#endif
-
static __inline__ void jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
tap_state_t end_state)
{
}
+
+
+/**
+ * Function jtag_add_statemove
+ * moves from the current state to the goal \a state. This needs
+ * to be handled according to the xsvf spec, see the XSTATE command
+ * description.
+ */
+extern int jtag_add_statemove(tap_state_t goal_state);
+
#endif /* JTAG_H */