+/**
+ * Function buffer_write
+ * writes a byte into the byte buffer, "ft2232_buffer", which must be sent later.
+ * @param val is the byte to send.
+ */
+static inline void buffer_write( u8 val )
+{
+ assert( ft2232_buffer );
+ assert( (unsigned) ft2232_buffer_size < (unsigned) FT2232_BUFFER_SIZE );
+ ft2232_buffer[ft2232_buffer_size++] = val;
+}
+
+/**
+ * Function buffer_read
+ * returns a byte from the byte buffer.
+ */
+static inline u8 buffer_read(void)
+{
+ assert( ft2232_buffer );
+ assert( ft2232_read_pointer < ft2232_buffer_size );
+ return ft2232_buffer[ft2232_read_pointer++];
+}
+
+
+/**
+ * Function clock_tms
+ * clocks out \a bit_count bits on the TMS line, starting with the least
+ * significant bit of tms_bits and progressing to more significant bits.
+ * Rigorous state transition logging is done here via tap_set_state().
+ *
+ * @param pmsse_cmd is one of the MPSSE TMS oriented commands such as 0x4b or 0x6b. See
+ * the MPSSE spec referenced above for their functionality. The MPSSE command
+ * "Clock Data to TMS/CS Pin (no Read)" is often used for this, 0x4b.
+ *
+ * @param tms_bits holds the sequence of bits to send.
+ * @param tms_count tells how many bits in the sequence.
+ * @param tdi_bit is a single bit which is passed on to TDI before the first TCK cycle
+ * and is held static for the duration of TMS clocking. See the MPSSE spec referenced above.
+ */
+static void clock_tms( u8 mpsse_cmd, int tms_bits, int tms_count, bool tdi_bit )
+{
+ u8 tms_byte;
+ int i;
+ int tms_ndx; /* bit index into tms_byte */
+
+ assert( tms_count > 0 );
+
+// LOG_DEBUG("mpsse cmd=%02x, tms_bits=0x%08x, bit_count=%d", mpsse_cmd, tms_bits, tms_count );
+
+ for (tms_byte = tms_ndx = i = 0; i < tms_count; ++i, tms_bits>>=1)
+ {
+ bool bit = tms_bits & 1;
+
+ if(bit)
+ tms_byte |= (1<<tms_ndx);
+
+ /* always do state transitions in public view */
+ tap_set_state( tap_state_transition(tap_get_state(), bit) );
+
+ /* we wrote a bit to tms_byte just above, increment bit index. if bit was zero
+ also increment.
+ */
+ ++tms_ndx;
+
+ if( tms_ndx==7 || i==tms_count-1 )
+ {
+ buffer_write( mpsse_cmd );
+ buffer_write( tms_ndx - 1 );
+
+ /* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of
+ TMS/CS and is held static for the duration of TMS/CS clocking.
+ */
+ buffer_write( tms_byte | (tdi_bit << 7) );
+ }
+ }
+}
+
+
+/**
+ * Function get_tms_buffer_requirements
+ * returns what clock_tms() will consume if called with
+ * same \a bit_count.
+ */
+static inline int get_tms_buffer_requirements( int bit_count )
+{
+ return ((bit_count + 6)/7) * 3;
+}
+
+
+/**
+ * Function move_to_state
+ * moves the TAP controller from the current state to a
+ * \a goal_state through a path given by tap_get_tms_path(). State transition
+ * logging is performed by delegation to clock_tms().
+ *
+ * @param goal_state is the destination state for the move.
+ */
+static void move_to_state( tap_state_t goal_state )
+{
+ tap_state_t start_state = tap_get_state();
+
+ /* goal_state is 1/2 of a tuple/pair of states which allow convenient
+ lookup of the required TMS pattern to move to this state from the
+ start state.
+ */
+
+ /* do the 2 lookups */
+ int tms_bits = tap_get_tms_path(start_state, goal_state);
+ int tms_count = tap_get_tms_path_len(start_state, goal_state);
+
+ DEBUG_JTAG_IO( "start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state) );
+
+ clock_tms( 0x4b, tms_bits, tms_count, 0 );
+}
+