+void tap_set_state_impl( tap_state_t new_state )
+{
+ /* this is the state we think the TAPs are in now, was cur_state */
+ state_follower = new_state;
+}
+
+tap_state_t tap_get_state()
+{
+ return state_follower;
+}
+
+/**
+ * @see tap_set_end_state() and tap_get_end_state() accessors.
+ * Actual name is not important because accessors hide it.
+ */
+static tap_state_t end_state_follower = TAP_RESET;
+
+void tap_set_end_state( tap_state_t new_end_state )
+{
+ /* this is the state we think the TAPs will be in at completion of the
+ current TAP operation, was end_state
+ */
+ end_state_follower = new_end_state;
+}
+
+tap_state_t tap_get_end_state()
+{
+ return end_state_follower;
+}
+
+
+int tap_move_ndx( tap_state_t astate )
+{
+ /* given a stable state, return the index into the tms_seqs[] array within tap_get_tms_path() */
+
+ int ndx;
+
+ switch( astate )
+ {
+ case TAP_RESET: ndx = 0; break;
+ case TAP_DRSHIFT: ndx = 2; break;
+ case TAP_DRPAUSE: ndx = 3; break;
+ case TAP_IDLE: ndx = 1; break;
+ case TAP_IRSHIFT: ndx = 4; break;
+ case TAP_IRPAUSE: ndx = 5; break;
+ default:
+ LOG_ERROR( "fatal: unstable state \"%s\" used in tap_move_ndx()", tap_state_name(astate) );
+ exit(1);
+ }
+
+ return ndx;
+}
+
+
+/* tap_move[i][j]: tap movement command to go from state i to state j
+ * 0: Test-Logic-Reset
+ * 1: Run-Test/Idle
+ * 2: Shift-DR
+ * 3: Pause-DR
+ * 4: Shift-IR
+ * 5: Pause-IR
+ *
+ * DRSHIFT->DRSHIFT and IRSHIFT->IRSHIFT have to be caught in interface specific code
+ */
+static struct
+{
+ u8 bits;
+ u8 bit_count;
+
+} tms_seqs[6][6] = /* [from_state_ndx][to_state_ndx] */
+{
+ /* value clocked to TMS to move from one of six stable states to another.
+ * N.B. OOCD clocks TMS from LSB first, so read these right-to-left.
+ * N.B. These values are tightly bound to the table in tap_get_tms_path_len().
+ * N.B. Reset only needs to be 0b11111, but in JLink an even byte of 1's is more stable.
+ * These extra ones cause no TAP state problem, because we go into reset and stay in reset.
+ */
+
+/*
+ * These macros allow us to specify TMS state transitions by bits rather than hex bytes.
+ * Read the bits from LSBit first to MSBit last (right-to-left).
+ */
+#define HEX__(n) 0x##n##LU
+
+#define B8__(x) \
+ (((x) & 0x0000000FLU)?(1<<0):0) \
+ +(((x) & 0x000000F0LU)?(1<<1):0) \
+ +(((x) & 0x00000F00LU)?(1<<2):0) \
+ +(((x) & 0x0000F000LU)?(1<<3):0) \
+ +(((x) & 0x000F0000LU)?(1<<4):0) \
+ +(((x) & 0x00F00000LU)?(1<<5):0) \
+ +(((x) & 0x0F000000LU)?(1<<6):0) \
+ +(((x) & 0xF0000000LU)?(1<<7):0)
+
+#define B8(bits,count) { ((u8)B8__(HEX__(bits))), (count) }
+
+#if 0 && ((BUILD_FT2232_FTD2XX==1) || (BUILD_FT2232_LIBFTDI==1))
+ /* this is the table submitted by Jeff Williams on 3/30/2009 with this comment:
+
+ OK, I added Peter's version of the state table, and it works OK for
+ me on MC1322x. I've recreated the jlink portion of patch with this
+ new state table. His changes to my state table are pretty minor in
+ terms of total transitions, but Peter feels that his version fixes
+ some long-standing problems.
+ Jeff
+
+ I added the bit count into the table
+ Dick
+ */
+
+ /* to state: */
+ /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
+ { B8(11111,5), B8(0,1), B8(0010,4), B8(01010,5), B8(00110,5), B8(010110,6) }, /* RESET */
+ { B8(11111,5), B8(0,1), B8(001,3), B8(0101,4), B8(0011,4), B8(01011,5) }, /* IDLE */
+ { B8(11111,5), B8(011,3), B8(00111,5), B8(01,2), B8(001111,6), B8(0101111,7) }, /* DRSHIFT */
+ { B8(11111,5), B8(011,3), B8(01,2), B8(0,1), B8(001111,6), B8(0101111,7) }, /* DRPAUSE */
+ { B8(11111,5), B8(011,3), B8(00111,5), B8(010111,6), B8(001111,6), B8(01,2) }, /* IRSHIFT */
+ { B8(11111,5), B8(011,3), B8(00111,5), B8(010111,6), B8(01,2), B8(0,1) } /* IRPAUSE */
+
+#else /* this is the old table, converted from hex and with the bit_count set to 7 for each combo, like before */
+
+ /* to state: */
+ /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */ /* from state: */
+ { B8(1111111,7), B8(0000000,7), B8(0010111,7), B8(0001010,7), B8(0011011,7), B8(0010110,7) }, /* RESET */
+ { B8(1111111,7), B8(0000000,7), B8(0100101,7), B8(0000101,7), B8(0101011,7), B8(0001011,7) }, /* IDLE */
+ { B8(1111111,7), B8(0110001,7), B8(0000000,7), B8(0000001,7), B8(0001111,7), B8(0101111,7) }, /* DRSHIFT */
+ { B8(1111111,7), B8(0110000,7), B8(0100000,7), B8(0010111,7), B8(0011110,7), B8(0101111,7) }, /* DRPAUSE */
+ { B8(1111111,7), B8(0110001,7), B8(0000111,7), B8(0010111,7), B8(0000000,7), B8(0000001,7) }, /* IRSHIFT */
+ { B8(1111111,7), B8(0110000,7), B8(0011100,7), B8(0010111,7), B8(0100000,7), B8(0101111,7) }, /* IRPAUSE */
+
+#endif
+
+#if 0 /* keeping old hex stuff for awhile, for reference */
+ /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
+ { 0x7f, 0x00, 0x17, 0x0a, 0x1b, 0x16 }, /* RESET */
+ { 0x7f, 0x00, 0x25, 0x05, 0x2b, 0x0b }, /* IDLE */
+ { 0x7f, 0x31, 0x00, 0x01, 0x0f, 0x2f }, /* DRSHIFT */
+ { 0x7f, 0x30, 0x20, 0x17, 0x1e, 0x2f }, /* DRPAUSE */
+ { 0x7f, 0x31, 0x07, 0x17, 0x00, 0x01 }, /* IRSHIFT */
+ { 0x7f, 0x30, 0x1c, 0x17, 0x20, 0x2f } /* IRPAUSE */
+#endif
+};
+
+
+int tap_get_tms_path( tap_state_t from, tap_state_t to )
+{
+ return tms_seqs[tap_move_ndx(from)][tap_move_ndx(to)].bits;
+}
+
+
+int tap_get_tms_path_len( tap_state_t from, tap_state_t to )
+{
+ return tms_seqs[tap_move_ndx(from)][tap_move_ndx(to)].bit_count;
+}
+
+
+bool tap_is_state_stable(tap_state_t astate)
+{
+ bool is_stable;
+
+ /* A switch() is used because it is symbol dependent
+ (not value dependent like an array), and can also check bounds.
+ */
+ switch( astate )
+ {
+ case TAP_RESET:
+ case TAP_IDLE:
+ case TAP_DRSHIFT:
+ case TAP_DRPAUSE:
+ case TAP_IRSHIFT:
+ case TAP_IRPAUSE:
+ is_stable = true;
+ break;
+ default:
+ is_stable = false;
+ }
+
+ return is_stable;
+}
+
+tap_state_t tap_state_transition(tap_state_t cur_state, bool tms)
+{
+ tap_state_t new_state;
+
+ /* A switch is used because it is symbol dependent and not value dependent
+ like an array. Also it can check for out of range conditions.
+ */
+
+ if (tms)
+ {
+ switch (cur_state)
+ {
+ case TAP_RESET:
+ new_state = cur_state;
+ break;
+ case TAP_IDLE:
+ case TAP_DRUPDATE:
+ case TAP_IRUPDATE:
+ new_state = TAP_DRSELECT;
+ break;
+ case TAP_DRSELECT:
+ new_state = TAP_IRSELECT;
+ break;
+ case TAP_DRCAPTURE:
+ case TAP_DRSHIFT:
+ new_state = TAP_DREXIT1;
+ break;
+ case TAP_DREXIT1:
+ case TAP_DREXIT2:
+ new_state = TAP_DRUPDATE;
+ break;
+ case TAP_DRPAUSE:
+ new_state = TAP_DREXIT2;
+ break;
+ case TAP_IRSELECT:
+ new_state = TAP_RESET;
+ break;
+ case TAP_IRCAPTURE:
+ case TAP_IRSHIFT:
+ new_state = TAP_IREXIT1;
+ break;
+ case TAP_IREXIT1:
+ case TAP_IREXIT2:
+ new_state = TAP_IRUPDATE;
+ break;
+ case TAP_IRPAUSE:
+ new_state = TAP_IREXIT2;
+ break;
+ default:
+ LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
+ exit(1);
+ break;
+ }
+ }
+ else
+ {
+ switch (cur_state)
+ {
+ case TAP_RESET:
+ case TAP_IDLE:
+ case TAP_DRUPDATE:
+ case TAP_IRUPDATE:
+ new_state = TAP_IDLE;
+ break;
+ case TAP_DRSELECT:
+ new_state = TAP_DRCAPTURE;
+ break;
+ case TAP_DRCAPTURE:
+ case TAP_DRSHIFT:
+ case TAP_DREXIT2:
+ new_state = TAP_DRSHIFT;
+ break;
+ case TAP_DREXIT1:
+ case TAP_DRPAUSE:
+ new_state = TAP_DRPAUSE;
+ break;
+ case TAP_IRSELECT:
+ new_state = TAP_IRCAPTURE;
+ break;
+ case TAP_IRCAPTURE:
+ case TAP_IRSHIFT:
+ case TAP_IREXIT2:
+ new_state = TAP_IRSHIFT;
+ break;
+ case TAP_IREXIT1:
+ case TAP_IRPAUSE:
+ new_state = TAP_IRPAUSE;
+ break;
+ default:
+ LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );
+ exit(1);
+ break;
+ }
+ }
+
+ return new_state;
+}
+
+const char* tap_state_name(tap_state_t state)