You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2016/06/15 22:03:46 UTC

[03/51] [partial] incubator-mynewt-site git commit: Fixed broken Quick Start link and added OpenOCD option for Arduino Primo debugging

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/jtag.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/jtag.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/jtag.c
new file mode 100755
index 0000000..9f45ea7
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/jtag.c
@@ -0,0 +1,723 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <ma...@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#include "jtag.h"
+
+#include "io.h"
+#include "msgtypes.h"
+#include "common.h"
+
+#include <stdbool.h>
+
+/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
+uint8_t delay_scan_in;
+
+/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
+uint8_t delay_scan_out;
+
+/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
+uint8_t delay_scan_io;
+
+/** Delay value for CLOCK_TCK operations with less than maximum frequency */
+uint8_t delay_tck;
+
+/** Delay value for CLOCK_TMS operations with less than maximum frequency */
+uint8_t delay_tms;
+
+/**
+ * Perform JTAG SCAN-IN operation at maximum TCK frequency.
+ *
+ * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
+ * stored in the EP2 IN buffer.
+ *
+ * Maximum achievable TCK frequency is 182 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
+{
+	uint8_t scan_size_bytes, bits_last_byte;
+	uint8_t tms_count_start, tms_count_end;
+	uint8_t tms_sequence_start, tms_sequence_end;
+	uint8_t tdo_data, i, j;
+
+	uint8_t outb_buffer;
+
+	/* Get parameters from OUT2BUF */
+	scan_size_bytes = OUT2BUF[out_offset];
+	bits_last_byte = OUT2BUF[out_offset + 1];
+	tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+	tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+	tms_sequence_start = OUT2BUF[out_offset + 3];
+	tms_sequence_end = OUT2BUF[out_offset + 4];
+
+	if (tms_count_start > 0)
+		jtag_clock_tms(tms_count_start, tms_sequence_start);
+
+	outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
+
+	/* Shift all bytes except the last byte */
+	for (i = 0; i < scan_size_bytes - 1; i++) {
+		tdo_data = 0;
+
+		for (j = 0; j < 8; j++) {
+			OUTB = outb_buffer;	/* TCK changes here */
+			tdo_data = tdo_data >> 1;
+			OUTB = (outb_buffer | PIN_TCK);
+
+			if (GET_TDO())
+				tdo_data |= 0x80;
+		}
+
+		/* Copy TDO data to IN2BUF */
+		IN2BUF[i + in_offset] = tdo_data;
+	}
+
+	tdo_data = 0;
+
+	/* Shift the last byte */
+	for (j = 0; j < bits_last_byte; j++) {
+		/* Assert TMS signal if requested and this is the last bit */
+		if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+			outb_buffer |= PIN_TMS;
+			tms_count_end--;
+			tms_sequence_end = tms_sequence_end >> 1;
+		}
+
+		OUTB = outb_buffer;	/* TCK changes here */
+		tdo_data = tdo_data >> 1;
+		OUTB = (outb_buffer | PIN_TCK);
+
+		if (GET_TDO())
+			tdo_data |= 0x80;
+	}
+	tdo_data = tdo_data >> (8 - bits_last_byte);
+
+	/* Copy TDO data to IN2BUF */
+	IN2BUF[i + in_offset] = tdo_data;
+
+	/* Move to correct end state */
+	if (tms_count_end > 0)
+		jtag_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Perform JTAG SCAN-IN operation at variable TCK frequency.
+ *
+ * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
+ * stored in the EP2 IN buffer.
+ *
+ * Maximum achievable TCK frequency is 113 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
+{
+	uint8_t scan_size_bytes, bits_last_byte;
+	uint8_t tms_count_start, tms_count_end;
+	uint8_t tms_sequence_start, tms_sequence_end;
+	uint8_t tdo_data, i, j, k;
+
+	uint8_t outb_buffer;
+
+	/* Get parameters from OUT2BUF */
+	scan_size_bytes = OUT2BUF[out_offset];
+	bits_last_byte = OUT2BUF[out_offset + 1];
+	tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+	tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+	tms_sequence_start = OUT2BUF[out_offset + 3];
+	tms_sequence_end = OUT2BUF[out_offset + 4];
+
+	if (tms_count_start > 0)
+		jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+
+	outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
+
+	/* Shift all bytes except the last byte */
+	for (i = 0; i < scan_size_bytes - 1; i++) {
+		tdo_data = 0;
+
+		for (j = 0; j < 8; j++) {
+			OUTB = outb_buffer;	/* TCK changes here */
+			for (k = 0; k < delay_scan_in; k++)
+				;
+			tdo_data = tdo_data >> 1;
+
+			OUTB = (outb_buffer | PIN_TCK);
+			for (k = 0; k < delay_scan_in; k++)
+				;
+
+			if (GET_TDO())
+				tdo_data |= 0x80;
+		}
+
+		/* Copy TDO data to IN2BUF */
+		IN2BUF[i + in_offset] = tdo_data;
+	}
+
+	tdo_data = 0;
+
+	/* Shift the last byte */
+	for (j = 0; j < bits_last_byte; j++) {
+		/* Assert TMS signal if requested and this is the last bit */
+		if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+			outb_buffer |= PIN_TMS;
+			tms_count_end--;
+			tms_sequence_end = tms_sequence_end >> 1;
+		}
+
+		OUTB = outb_buffer;	/* TCK changes here */
+		for (k = 0; k < delay_scan_in; k++)
+			;
+		tdo_data = tdo_data >> 1;
+
+		OUTB = (outb_buffer | PIN_TCK);
+		for (k = 0; k < delay_scan_in; k++)
+			;
+
+		if (GET_TDO())
+			tdo_data |= 0x80;
+	}
+	tdo_data = tdo_data >> (8 - bits_last_byte);
+
+	/* Copy TDO data to IN2BUF */
+	IN2BUF[i + in_offset] = tdo_data;
+
+	/* Move to correct end state */
+	if (tms_count_end > 0)
+		jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is not sampled.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 142 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_out(uint8_t out_offset)
+{
+	uint8_t scan_size_bytes, bits_last_byte;
+	uint8_t tms_count_start, tms_count_end;
+	uint8_t tms_sequence_start, tms_sequence_end;
+	uint8_t tdi_data, i, j;
+
+	uint8_t outb_buffer;
+
+	/* Get parameters from OUT2BUF */
+	scan_size_bytes = OUT2BUF[out_offset];
+	bits_last_byte = OUT2BUF[out_offset + 1];
+	tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+	tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+	tms_sequence_start = OUT2BUF[out_offset + 3];
+	tms_sequence_end = OUT2BUF[out_offset + 4];
+
+	if (tms_count_start > 0)
+		jtag_clock_tms(tms_count_start, tms_sequence_start);
+
+	outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+	/* Shift all bytes except the last byte */
+	for (i = 0; i < scan_size_bytes - 1; i++) {
+		tdi_data = OUT2BUF[i + out_offset + 5];
+
+		for (j = 0; j < 8; j++) {
+			if (tdi_data & 0x01)
+				outb_buffer |= PIN_TDI;
+			else
+				outb_buffer &= ~PIN_TDI;
+
+			OUTB = outb_buffer;	/* TDI and TCK change here */
+			tdi_data = tdi_data >> 1;
+			OUTB = (outb_buffer | PIN_TCK);
+		}
+	}
+
+	tdi_data = OUT2BUF[i + out_offset + 5];
+
+	/* Shift the last byte */
+	for (j = 0; j < bits_last_byte; j++) {
+		if (tdi_data & 0x01)
+			outb_buffer |= PIN_TDI;
+		else
+			outb_buffer &= ~PIN_TDI;
+
+		/* Assert TMS signal if requested and this is the last bit */
+		if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+			outb_buffer |= PIN_TMS;
+			tms_count_end--;
+			tms_sequence_end = tms_sequence_end >> 1;
+		}
+
+		OUTB = outb_buffer;	/* TDI and TCK change here */
+		tdi_data = tdi_data >> 1;
+		OUTB = (outb_buffer | PIN_TCK);
+	}
+
+	/* Move to correct end state */
+	if (tms_count_end > 0)
+		jtag_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is not sampled.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 97 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_out(uint8_t out_offset)
+{
+	uint8_t scan_size_bytes, bits_last_byte;
+	uint8_t tms_count_start, tms_count_end;
+	uint8_t tms_sequence_start, tms_sequence_end;
+	uint8_t tdi_data, i, j, k;
+
+	uint8_t outb_buffer;
+
+	/* Get parameters from OUT2BUF */
+	scan_size_bytes = OUT2BUF[out_offset];
+	bits_last_byte = OUT2BUF[out_offset + 1];
+	tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+	tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+	tms_sequence_start = OUT2BUF[out_offset + 3];
+	tms_sequence_end = OUT2BUF[out_offset + 4];
+
+	if (tms_count_start > 0)
+		jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+
+	outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+	/* Shift all bytes except the last byte */
+	for (i = 0; i < scan_size_bytes - 1; i++) {
+		tdi_data = OUT2BUF[i + out_offset + 5];
+
+		for (j = 0; j < 8; j++) {
+			if (tdi_data & 0x01)
+				outb_buffer |= PIN_TDI;
+			else
+				outb_buffer &= ~PIN_TDI;
+
+			OUTB = outb_buffer;	/* TDI and TCK change here */
+			for (k = 0; k < delay_scan_out; k++)
+				;
+			tdi_data = tdi_data >> 1;
+
+			OUTB = (outb_buffer | PIN_TCK);
+			for (k = 0; k < delay_scan_out; k++)
+				;
+		}
+	}
+
+	tdi_data = OUT2BUF[i + out_offset + 5];
+
+	/* Shift the last byte */
+	for (j = 0; j < bits_last_byte; j++) {
+		if (tdi_data & 0x01)
+			outb_buffer |= PIN_TDI;
+		else
+			outb_buffer &= ~PIN_TDI;
+
+		/* Assert TMS signal if requested and this is the last bit */
+		if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+			outb_buffer |= PIN_TMS;
+			tms_count_end--;
+			tms_sequence_end = tms_sequence_end >> 1;
+		}
+
+		OUTB = outb_buffer;	/* TDI and TCK change here */
+		for (k = 0; k < delay_scan_out; k++)
+			;
+		tdi_data = tdi_data >> 1;
+
+		OUTB = (outb_buffer | PIN_TCK);
+		for (k = 0; k < delay_scan_out; k++)
+			;
+	}
+
+	/* Move to correct end state */
+	if (tms_count_end > 0)
+		jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is sampled and stored in the EP2 IN buffer.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 100 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
+{
+	uint8_t scan_size_bytes, bits_last_byte;
+	uint8_t tms_count_start, tms_count_end;
+	uint8_t tms_sequence_start, tms_sequence_end;
+	uint8_t tdi_data, tdo_data, i, j;
+
+	uint8_t outb_buffer;
+
+	/* Get parameters from OUT2BUF */
+	scan_size_bytes = OUT2BUF[out_offset];
+	bits_last_byte = OUT2BUF[out_offset + 1];
+	tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+	tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+	tms_sequence_start = OUT2BUF[out_offset + 3];
+	tms_sequence_end = OUT2BUF[out_offset + 4];
+
+	if (tms_count_start > 0)
+		jtag_clock_tms(tms_count_start, tms_sequence_start);
+
+	outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+	/* Shift all bytes except the last byte */
+	for (i = 0; i < scan_size_bytes - 1; i++) {
+		tdi_data = OUT2BUF[i + out_offset + 5];
+		tdo_data = 0;
+
+		for (j = 0; j < 8; j++) {
+			if (tdi_data & 0x01)
+				outb_buffer |= PIN_TDI;
+			else
+				outb_buffer &= ~PIN_TDI;
+
+			OUTB = outb_buffer;	/* TDI and TCK change here */
+			tdi_data = tdi_data >> 1;
+			OUTB = (outb_buffer | PIN_TCK);
+			tdo_data = tdo_data >> 1;
+
+			if (GET_TDO())
+				tdo_data |= 0x80;
+		}
+
+		/* Copy TDO data to IN2BUF */
+		IN2BUF[i + in_offset] = tdo_data;
+	}
+
+	tdi_data = OUT2BUF[i + out_offset + 5];
+	tdo_data = 0;
+
+	/* Shift the last byte */
+	for (j = 0; j < bits_last_byte; j++) {
+		if (tdi_data & 0x01)
+			outb_buffer |= PIN_TDI;
+		else
+			outb_buffer &= ~PIN_TDI;
+
+		/* Assert TMS signal if requested and this is the last bit */
+		if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+			outb_buffer |= PIN_TMS;
+			tms_count_end--;
+			tms_sequence_end = tms_sequence_end >> 1;
+		}
+
+		OUTB = outb_buffer;	/* TDI and TCK change here */
+		tdi_data = tdi_data >> 1;
+		OUTB = (outb_buffer | PIN_TCK);
+		tdo_data = tdo_data >> 1;
+
+		if (GET_TDO())
+			tdo_data |= 0x80;
+	}
+	tdo_data = tdo_data >> (8 - bits_last_byte);
+
+	/* Copy TDO data to IN2BUF */
+	IN2BUF[i + in_offset] = tdo_data;
+
+	/* Move to correct end state */
+	if (tms_count_end > 0)
+		jtag_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is sampled and stored in the EP2 IN buffer.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 78 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
+{
+	uint8_t scan_size_bytes, bits_last_byte;
+	uint8_t tms_count_start, tms_count_end;
+	uint8_t tms_sequence_start, tms_sequence_end;
+	uint8_t tdi_data, tdo_data, i, j, k;
+
+	uint8_t outb_buffer;
+
+	/* Get parameters from OUT2BUF */
+	scan_size_bytes = OUT2BUF[out_offset];
+	bits_last_byte = OUT2BUF[out_offset + 1];
+	tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+	tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+	tms_sequence_start = OUT2BUF[out_offset + 3];
+	tms_sequence_end = OUT2BUF[out_offset + 4];
+
+	if (tms_count_start > 0)
+		jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+
+	outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+	/* Shift all bytes except the last byte */
+	for (i = 0; i < scan_size_bytes - 1; i++) {
+		tdi_data = OUT2BUF[i + out_offset + 5];
+		tdo_data = 0;
+
+		for (j = 0; j < 8; j++) {
+			if (tdi_data & 0x01)
+				outb_buffer |= PIN_TDI;
+			else
+				outb_buffer &= ~PIN_TDI;
+
+			OUTB = outb_buffer;	/* TDI and TCK change here */
+			for (k = 0; k < delay_scan_io; k++)
+				;
+			tdi_data = tdi_data >> 1;
+
+			OUTB = (outb_buffer | PIN_TCK);
+			for (k = 0; k < delay_scan_io; k++)
+				;
+			tdo_data = tdo_data >> 1;
+
+			if (GET_TDO())
+				tdo_data |= 0x80;
+		}
+
+		/* Copy TDO data to IN2BUF */
+		IN2BUF[i + in_offset] = tdo_data;
+	}
+
+	tdi_data = OUT2BUF[i + out_offset + 5];
+	tdo_data = 0;
+
+	/* Shift the last byte */
+	for (j = 0; j < bits_last_byte; j++) {
+		if (tdi_data & 0x01)
+			outb_buffer |= PIN_TDI;
+		else
+			outb_buffer &= ~PIN_TDI;
+
+		/* Assert TMS signal if requested and this is the last bit */
+		if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+			outb_buffer |= PIN_TMS;
+			tms_count_end--;
+			tms_sequence_end = tms_sequence_end >> 1;
+		}
+
+		OUTB = outb_buffer;	/* TDI and TCK change here */
+		for (k = 0; k < delay_scan_io; k++)
+			;
+		tdi_data = tdi_data >> 1;
+
+		OUTB = (outb_buffer | PIN_TCK);
+		for (k = 0; k < delay_scan_io; k++)
+			;
+		tdo_data = tdo_data >> 1;
+
+		if (GET_TDO())
+			tdo_data |= 0x80;
+	}
+	tdo_data = tdo_data >> (8 - bits_last_byte);
+
+	/* Copy TDO data to IN2BUF */
+	IN2BUF[i + in_offset] = tdo_data;
+
+	/* Move to correct end state */
+	if (tms_count_end > 0)
+		jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Generate TCK clock cycles.
+ *
+ * Maximum achievable TCK frequency is 375 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param count number of TCK clock cyclces to generate.
+ */
+void jtag_clock_tck(uint16_t count)
+{
+	uint16_t i;
+	uint8_t outb_buffer = OUTB & ~(PIN_TCK);
+
+	for (i = 0; i < count; i++) {
+		OUTB = outb_buffer;
+		OUTB = outb_buffer | PIN_TCK;
+	}
+}
+
+/**
+ * Generate TCK clock cycles at variable frequency.
+ *
+ * Maximum achieveable TCK frequency is 166.6 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param count number of TCK clock cyclces to generate.
+ */
+void jtag_slow_clock_tck(uint16_t count)
+{
+	uint16_t i;
+	uint8_t j;
+	uint8_t outb_buffer = OUTB & ~(PIN_TCK);
+
+	for (i = 0; i < count; i++) {
+		OUTB = outb_buffer;
+		for (j = 0; j < delay_tck; j++)
+			;
+		OUTB = outb_buffer | PIN_TCK;
+		for (j = 0; j < delay_tck; j++)
+			;
+	}
+}
+
+/**
+ * Perform TAP FSM state transitions at maximum TCK frequency.
+ *
+ * Maximum achievable TCK frequency is 176 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param count the number of state transitions to perform.
+ * @param sequence the TMS pin levels for each state transition, starting with
+ *  the least-significant bit.
+ */
+void jtag_clock_tms(uint8_t count, uint8_t sequence)
+{
+	uint8_t outb_buffer = OUTB & ~(PIN_TCK);
+	uint8_t i;
+
+	for (i = 0; i < count; i++) {
+		/* Set TMS pin according to sequence parameter */
+		if (sequence & 0x1)
+			outb_buffer |= PIN_TMS;
+		else
+			outb_buffer &= ~PIN_TMS;
+
+		OUTB = outb_buffer;
+		sequence = sequence >> 1;
+		OUTB = outb_buffer | PIN_TCK;
+	}
+}
+
+/**
+ * Perform TAP-FSM state transitions at less than maximum TCK frequency.
+ *
+ * Maximum achievable TCK frequency is 117 kHz for ULINK clocked at 24 MHz.
+ *
+ * @param count the number of state transitions to perform.
+ * @param sequence the TMS pin levels for each state transition, starting with
+ *  the least-significant bit.
+ */
+void jtag_slow_clock_tms(uint8_t count, uint8_t sequence)
+{
+	uint8_t outb_buffer = OUTB & ~(PIN_TCK);
+	uint8_t i, j;
+
+	for (i = 0; i < count; i++) {
+		/* Set TMS pin according to sequence parameter */
+		if (sequence & 0x1)
+			outb_buffer |= PIN_TMS;
+		else
+			outb_buffer &= ~PIN_TMS;
+
+		OUTB = outb_buffer;
+		for (j = 0; j < delay_tms; j++)
+			;
+		sequence = sequence >> 1;
+		OUTB = outb_buffer | PIN_TCK;
+		for (j = 0; j < delay_tms; j++)
+			;
+	}
+}
+
+/**
+ * Get current JTAG signal states.
+ *
+ * @return a 16-bit integer where the most-significant byte contains the state
+ *  of the JTAG input signals and the least-significant byte contains the state
+ *  of the JTAG output signals.
+ */
+uint16_t jtag_get_signals(void)
+{
+	uint8_t input_signal_state, output_signal_state;
+
+	input_signal_state = 0;
+	output_signal_state = 0;
+
+	/* Get states of input pins */
+	if (GET_TDO())
+		input_signal_state |= SIGNAL_TDO;
+	if (GET_BRKOUT())
+		input_signal_state |= SIGNAL_BRKOUT;
+	if (GET_TRAP())
+		input_signal_state |= SIGNAL_TRAP;
+	if (GET_RTCK()) {
+		/* Using RTCK this way would be extremely slow,
+		 * implemented only for the sake of completeness */
+		input_signal_state |= SIGNAL_RTCK;
+	}
+
+	/* Get states of output pins */
+	output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
+
+	return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state);
+}
+
+/**
+ * Set state of JTAG output signals.
+ *
+ * @param low signals which should be de-asserted.
+ * @param high signals which should be asserted.
+ */
+void jtag_set_signals(uint8_t low, uint8_t high)
+{
+	OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
+	OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
+}
+
+/**
+ * Configure TCK delay parameters.
+ *
+ * @param scan_in number of delay cycles in scan_in operations.
+ * @param scan_out number of delay cycles in scan_out operations.
+ * @param scan_io number of delay cycles in scan_io operations.
+ * @param tck number of delay cycles in clock_tck operations.
+ * @param tms number of delay cycles in clock_tms operations.
+ */
+void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
+	uint8_t scan_io, uint8_t tck, uint8_t tms)
+{
+	delay_scan_in = scan_in;
+	delay_scan_out = scan_out;
+	delay_scan_io = scan_io;
+	delay_tck = tck;
+	delay_tms = tms;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/main.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/main.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/main.c
new file mode 100755
index 0000000..e4865f8
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/main.c
@@ -0,0 +1,91 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <ma...@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#include "main.h"
+
+#include "io.h"
+#include "usb.h"
+#include "protocol.h"
+
+extern void sudav_isr(void)    __interrupt SUDAV_ISR;
+extern void sof_isr(void)      __interrupt;
+extern void sutok_isr(void)    __interrupt;
+extern void suspend_isr(void)  __interrupt;
+extern void usbreset_isr(void) __interrupt;
+extern void ibn_isr(void)      __interrupt;
+extern void ep0in_isr(void)    __interrupt;
+extern void ep0out_isr(void)   __interrupt;
+extern void ep1in_isr(void)    __interrupt;
+extern void ep1out_isr(void)   __interrupt;
+extern void ep2in_isr(void)    __interrupt;
+extern void ep2out_isr(void)   __interrupt;
+extern void ep3in_isr(void)    __interrupt;
+extern void ep3out_isr(void)   __interrupt;
+extern void ep4in_isr(void)    __interrupt;
+extern void ep4out_isr(void)   __interrupt;
+extern void ep5in_isr(void)    __interrupt;
+extern void ep5out_isr(void)   __interrupt;
+extern void ep6in_isr(void)    __interrupt;
+extern void ep6out_isr(void)   __interrupt;
+extern void ep7in_isr(void)    __interrupt;
+extern void ep7out_isr(void)   __interrupt;
+
+void io_init(void)
+{
+	/* PORTxCFG register bits select alternate functions (1 == alternate function,
+	 *                                                    0 == standard I/O)
+	 * OEx register bits turn on/off output buffer (1 == output, 0 == input)
+	 * OUTx register bits determine pin state of output
+	 * PINx register bits reflect pin state (high == 1, low == 0) */
+
+	/* PORT A */
+	PORTACFG = PIN_OE;
+	OEA = PIN_U_OE | PIN_OE | PIN_RUN_LED | PIN_COM_LED;
+	OUTA = PIN_RUN_LED | PIN_COM_LED;
+
+	/* PORT B */
+	PORTBCFG = 0x00;
+	OEB = PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET
+		| PIN_OCDSE;
+
+	/* TRST and RESET signals are low-active but inverted by hardware, so we clear
+	 * these signals here! */
+	OUTB = 0x00;
+
+	/* PORT C */
+	PORTCCFG = PIN_WR;
+	OEC = PIN_TXD0 | PIN_WR;
+	OUTC = 0x00;
+}
+
+int main(void)
+{
+	io_init();
+	usb_init();
+
+	/* Enable Interrupts */
+	EA = 1;
+
+	/* Begin executing command(s). This function never returns. */
+	command_loop();
+
+	/* Never reached, but SDCC complains about missing return statement */
+	return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/protocol.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/protocol.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/protocol.c
new file mode 100755
index 0000000..5f7f984
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/protocol.c
@@ -0,0 +1,240 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <ma...@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#include "protocol.h"
+#include "jtag.h"
+#include "delay.h"
+#include "usb.h"
+#include "io.h"
+#include "msgtypes.h"
+
+#include "reg_ezusb.h"
+
+/**
+ * @file
+ * Implementation of the OpenULINK communication protocol.
+ *
+ * The OpenULINK protocol uses one OUT and one IN endpoint. These two endpoints
+ * are configured to use the maximum packet size for full-speed transfers,
+ * 64 bytes. Commands always start with a command ID (see msgtypes.h for
+ * command ID definitions) and contain zero or more payload data bytes in both
+ * transfer directions (IN and OUT). The payload
+ *
+ * Almost all commands contain a fixed number of payload data bytes. The number
+ * of payload data bytes for the IN and OUT direction does not need to be the
+ * same.
+ *
+ * Multiple commands may be sent in one EP2 Bulk-OUT packet. Because the
+ * OpenULINK firmware does not perform bounds checking for EP2 Bulk-IN packets,
+ * the host MUST ensure that the commands sent in the OUT packet require a
+ * maximum of 64 bytes of IN data.
+ */
+
+/** Index in EP2 Bulk-OUT data buffer that contains the current command ID */
+volatile uint8_t cmd_id_index;
+
+/** Number of data bytes already in EP2 Bulk-IN buffer */
+volatile uint8_t payload_index_in;
+
+/**
+ * Execute a SET_LEDS command.
+ */
+void execute_set_led_command(void)
+{
+	uint8_t led_state = OUT2BUF[cmd_id_index + 1];
+
+	if (led_state & RUN_LED_ON)
+		SET_RUN_LED();
+
+	if (led_state & COM_LED_ON)
+		SET_COM_LED();
+
+	if (led_state & RUN_LED_OFF)
+		CLEAR_RUN_LED();
+
+	if (led_state & COM_LED_OFF)
+		CLEAR_COM_LED();
+}
+
+/**
+ * Executes one command and updates global command indexes.
+ *
+ * @return true if this command was the last command.
+ * @return false if there are more commands within the current contents of the
+ * Bulk EP2-OUT data buffer.
+ */
+bool execute_command(void)
+{
+	uint8_t usb_out_bytecount, usb_in_bytecount;
+	uint16_t signal_state;
+	uint16_t count;
+
+	/* Most commands do not transfer IN data. To save code space, we write 0 to
+	 * usb_in_bytecount here, then modify it in the switch statement below where
+	 * neccessary */
+	usb_in_bytecount = 0;
+
+	switch (OUT2BUF[cmd_id_index] /* Command ID */) {
+		case CMD_SCAN_IN:
+			usb_out_bytecount = 5;
+			usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+			jtag_scan_in(cmd_id_index + 1, payload_index_in);
+			break;
+		case CMD_SCAN_OUT:
+			usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
+			jtag_scan_out(cmd_id_index + 1);
+			break;
+		case CMD_SCAN_IO:
+			usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+			usb_out_bytecount = usb_in_bytecount + 5;
+			jtag_scan_io(cmd_id_index + 1, payload_index_in);
+			break;
+		case CMD_CLOCK_TMS:
+			usb_out_bytecount = 2;
+			jtag_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
+			break;
+		case CMD_CLOCK_TCK:
+			usb_out_bytecount = 2;
+			count = (uint16_t)OUT2BUF[cmd_id_index + 1];
+			count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
+			jtag_clock_tck(count);
+			break;
+		case CMD_SLOW_SCAN_IN:
+			usb_out_bytecount = 5;
+			usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+			jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
+			break;
+		case CMD_SLOW_SCAN_OUT:
+			usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
+			jtag_slow_scan_out(cmd_id_index + 1);
+			break;
+		case CMD_SLOW_SCAN_IO:
+			usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+			usb_out_bytecount = usb_in_bytecount + 5;
+			jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
+			break;
+		case CMD_SLOW_CLOCK_TMS:
+			usb_out_bytecount = 2;
+			jtag_slow_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
+			break;
+		case CMD_SLOW_CLOCK_TCK:
+			usb_out_bytecount = 2;
+			count = (uint16_t)OUT2BUF[cmd_id_index + 1];
+			count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
+			jtag_slow_clock_tck(count);
+			break;
+		case CMD_SLEEP_US:
+			usb_out_bytecount = 2;
+			count = (uint16_t)OUT2BUF[cmd_id_index + 1];
+			count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
+			delay_us(count);
+			break;
+		case CMD_SLEEP_MS:
+			usb_out_bytecount = 2;
+			count = (uint16_t)OUT2BUF[cmd_id_index + 1];
+			count |= ((uint16_t)OUT2BUF[cmd_id_index + 2]) << 8;
+			delay_ms(count);
+			break;
+		case CMD_GET_SIGNALS:
+			usb_out_bytecount = 0;
+			usb_in_bytecount = 2;
+			signal_state = jtag_get_signals();
+			IN2BUF[payload_index_in] = (signal_state >> 8) & 0x00FF;
+			IN2BUF[payload_index_in + 1] = signal_state & 0x00FF;
+			break;
+		case CMD_SET_SIGNALS:
+			usb_out_bytecount = 2;
+			jtag_set_signals(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
+			break;
+		case CMD_CONFIGURE_TCK_FREQ:
+			usb_out_bytecount = 5;
+			jtag_configure_tck_delay(
+			OUT2BUF[cmd_id_index + 1],	/* scan_in */
+			OUT2BUF[cmd_id_index + 2],	/* scan_out */
+			OUT2BUF[cmd_id_index + 3],	/* scan_io */
+			OUT2BUF[cmd_id_index + 4],	/* clock_tck */
+			OUT2BUF[cmd_id_index + 5]);	/* clock_tms */
+			break;
+		case CMD_SET_LEDS:
+			usb_out_bytecount = 1;
+			execute_set_led_command();
+			break;
+		case CMD_TEST:
+			usb_out_bytecount = 1;
+			/* Do nothing... This command is only used to test if the device is ready
+			 * to accept new commands */
+			break;
+		default:
+			/* Should never be reached */
+			usb_out_bytecount = 0;
+			break;
+	}
+
+	/* Update EP2 Bulk-IN data byte count */
+	payload_index_in += usb_in_bytecount;
+
+	/* Determine if this was the last command */
+	if ((cmd_id_index + usb_out_bytecount + 1) >= OUT2BC)
+		return true;
+	else {
+		/* Not the last command, update cmd_id_index */
+		cmd_id_index += (usb_out_bytecount + 1);
+		return false;
+	}
+}
+
+/**
+ * Forever wait for commands and execute them as they arrive.
+ */
+void command_loop(void)
+{
+	bool last_command;
+
+	while (1) {
+		cmd_id_index = 0;
+		payload_index_in = 0;
+
+		/* Wait until host sends EP2 Bulk-OUT packet */
+		while (!EP2_out)
+			;
+		EP2_out = 0;
+
+		/* Turn on COM LED to indicate command execution */
+		SET_COM_LED();
+
+		/* Execute the commands */
+		last_command = false;
+		while (last_command == false)
+			last_command = execute_command();
+
+		CLEAR_COM_LED();
+
+		/* Send back EP2 Bulk-IN packet if required */
+		if (payload_index_in > 0) {
+			IN2BC = payload_index_in;
+			while (!EP2_in)
+				;
+			EP2_in = 0;
+		}
+
+		/* Re-arm EP2-OUT after command execution */
+		OUT2BC = 0;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/usb.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/usb.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/usb.c
new file mode 100755
index 0000000..98ae67f
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/src/usb.c
@@ -0,0 +1,564 @@
+/***************************************************************************
+ *   Copyright (C) 2011-2013 by Martin Schmoelzer                          *
+ *   <ma...@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+/**
+ * @file
+ * Defines USB descriptors, interrupt routines and helper functions.
+ * To minimize code size, we make the following assumptions:
+ *  - The OpenULINK has exactly one configuration
+ *  - and exactly one alternate setting
+ *
+ * Therefore, we do not have to support the Set Configuration USB request.
+ */
+
+#include "usb.h"
+#include "delay.h"
+#include "io.h"
+
+/* Also update external declarations in "include/usb.h" if making changes to
+ * these variables! */
+volatile bool EP2_out;
+volatile bool EP2_in;
+
+volatile __xdata __at 0x7FE8 struct setup_data setup_data;
+
+/* Define number of endpoints (except Control Endpoint 0) in a central place.
+ * Be sure to include the neccessary endpoint descriptors! */
+#define NUM_ENDPOINTS 2
+
+__code struct usb_device_descriptor device_descriptor = {
+	.bLength =		sizeof(struct usb_device_descriptor),
+	.bDescriptorType =	DESCRIPTOR_TYPE_DEVICE,
+	.bcdUSB =		0x0110,	/* BCD: 01.00 (Version 1.0 USB spec) */
+	.bDeviceClass =		0xFF,	/* 0xFF = vendor-specific */
+	.bDeviceSubClass =	0xFF,
+	.bDeviceProtocol =	0xFF,
+	.bMaxPacketSize0 =	64,
+	.idVendor =		0xC251,
+	.idProduct =		0x2710,
+	.bcdDevice =		0x0100,
+	.iManufacturer =	1,
+	.iProduct =		2,
+	.iSerialNumber =	3,
+	.bNumConfigurations =	1
+};
+
+/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
+
+__code struct usb_config_descriptor config_descriptor = {
+	.bLength =		sizeof(struct usb_config_descriptor),
+	.bDescriptorType =	DESCRIPTOR_TYPE_CONFIGURATION,
+	.wTotalLength =		sizeof(struct usb_config_descriptor) +
+		sizeof(struct usb_interface_descriptor) +
+		(NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
+	.bNumInterfaces =	1,
+	.bConfigurationValue =	1,
+	.iConfiguration =	4,	/* String describing this configuration */
+	.bmAttributes =		0x80,	/* Only MSB set according to USB spec */
+	.MaxPower =		50	/* 100 mA */
+};
+
+__code struct usb_interface_descriptor interface_descriptor00 = {
+	.bLength = sizeof(struct usb_interface_descriptor),
+	.bDescriptorType =	DESCRIPTOR_TYPE_INTERFACE,
+	.bInterfaceNumber =	0,
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	NUM_ENDPOINTS,
+	.bInterfaceClass =	0xFF,
+	.bInterfaceSubclass =	0xFF,
+	.bInterfaceProtocol =	0xFF,
+	.iInterface =		0
+};
+
+__code struct usb_endpoint_descriptor Bulk_EP2_IN_Endpoint_Descriptor = {
+	.bLength =		sizeof(struct usb_endpoint_descriptor),
+	.bDescriptorType =	0x05,
+	.bEndpointAddress =	(2 | USB_DIR_IN),
+	.bmAttributes =		0x02,
+	.wMaxPacketSize =	64,
+	.bInterval =		0
+};
+
+__code struct usb_endpoint_descriptor Bulk_EP2_OUT_Endpoint_Descriptor = {
+	.bLength =		sizeof(struct usb_endpoint_descriptor),
+	.bDescriptorType =	0x05,
+	.bEndpointAddress =	(2 | USB_DIR_OUT),
+	.bmAttributes =		0x02,
+	.wMaxPacketSize =	64,
+	.bInterval =		0
+};
+
+__code struct usb_language_descriptor language_descriptor = {
+	.bLength =		4,
+	.bDescriptorType =	DESCRIPTOR_TYPE_STRING,
+	.wLANGID =		{0x0409 /* US English */}
+};
+
+__code struct usb_string_descriptor strManufacturer =
+	STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
+
+__code struct usb_string_descriptor strProduct =
+	STR_DESCR(9, 'O', 'p', 'e', 'n', 'U', 'L', 'I', 'N', 'K');
+
+__code struct usb_string_descriptor strSerialNumber =
+	STR_DESCR(6, '0', '0', '0', '0', '0', '1');
+
+__code struct usb_string_descriptor strConfigDescr  =
+	STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
+
+/* Table containing pointers to string descriptors */
+__code struct usb_string_descriptor *__code en_string_descriptors[4] = {
+	&strManufacturer,
+	&strProduct,
+	&strSerialNumber,
+	&strConfigDescr
+};
+
+void sudav_isr(void) __interrupt SUDAV_ISR
+{
+	CLEAR_IRQ();
+
+	usb_handle_setup_data();
+
+	USBIRQ = SUDAVIR;
+	EP0CS |= HSNAK;
+}
+
+void sof_isr(void)      __interrupt SOF_ISR
+{
+}
+void sutok_isr(void)    __interrupt SUTOK_ISR
+{
+}
+void suspend_isr(void)  __interrupt SUSPEND_ISR
+{
+}
+void usbreset_isr(void) __interrupt USBRESET_ISR
+{
+}
+void ibn_isr(void)      __interrupt IBN_ISR
+{
+}
+
+void ep0in_isr(void)    __interrupt EP0IN_ISR
+{
+}
+void ep0out_isr(void)   __interrupt EP0OUT_ISR
+{
+}
+void ep1in_isr(void)    __interrupt EP1IN_ISR
+{
+}
+void ep1out_isr(void)   __interrupt EP1OUT_ISR
+{
+}
+
+/**
+ * EP2 IN: called after the transfer from uC->Host has finished: we sent data
+ */
+void ep2in_isr(void)    __interrupt EP2IN_ISR
+{
+	EP2_in = 1;
+
+	CLEAR_IRQ();
+	IN07IRQ = IN2IR;/* Clear OUT2 IRQ */
+}
+
+/**
+ * EP2 OUT: called after the transfer from Host->uC has finished: we got data
+ */
+void ep2out_isr(void)   __interrupt EP2OUT_ISR
+{
+	EP2_out = 1;
+
+	CLEAR_IRQ();
+	OUT07IRQ = OUT2IR;	/* Clear OUT2 IRQ */
+}
+
+void ep3in_isr(void)    __interrupt EP3IN_ISR
+{
+}
+void ep3out_isr(void)   __interrupt EP3OUT_ISR
+{
+}
+void ep4in_isr(void)    __interrupt EP4IN_ISR
+{
+}
+void ep4out_isr(void)   __interrupt EP4OUT_ISR
+{
+}
+void ep5in_isr(void)    __interrupt EP5IN_ISR
+{
+}
+void ep5out_isr(void)   __interrupt EP5OUT_ISR
+{
+}
+void ep6in_isr(void)    __interrupt EP6IN_ISR
+{
+}
+void ep6out_isr(void)   __interrupt EP6OUT_ISR
+{
+}
+void ep7in_isr(void)    __interrupt EP7IN_ISR
+{
+}
+void ep7out_isr(void)   __interrupt EP7OUT_ISR
+{
+}
+
+/**
+ * Return the control/status register for an endpoint
+ *
+ * @param ep endpoint address
+ * @return on success: pointer to Control & Status register for endpoint
+ *  specified in \a ep
+ * @return on failure: NULL
+ */
+__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
+{
+	/* Mask direction bit */
+	uint8_t ep_num = ep & 0x7F;
+
+	switch (ep_num) {
+	    case 0:
+		    return &EP0CS;
+		    break;
+	    case 1:
+		    return ep & 0x80 ? &IN1CS : &OUT1CS;
+		    break;
+	    case 2:
+		    return ep & 0x80 ? &IN2CS : &OUT2CS;
+		    break;
+	    case 3:
+		    return ep & 0x80 ? &IN3CS : &OUT3CS;
+		    break;
+	    case 4:
+		    return ep & 0x80 ? &IN4CS : &OUT4CS;
+		    break;
+	    case 5:
+		    return ep & 0x80 ? &IN5CS : &OUT5CS;
+		    break;
+	    case 6:
+		    return ep & 0x80 ? &IN6CS : &OUT6CS;
+		    break;
+	    case 7:
+		    return ep & 0x80 ? &IN7CS : &OUT7CS;
+		    break;
+	}
+
+	return NULL;
+}
+
+void usb_reset_data_toggle(uint8_t ep)
+{
+	/* TOGCTL register:
+	   +----+-----+-----+------+-----+-------+-------+-------+
+	   | Q  |  S  |  R  |  IO  |  0  |  EP2  |  EP1  |  EP0  |
+	   +----+-----+-----+------+-----+-------+-------+-------+
+
+	   To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
+	   to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
+	   separate write cycle, the R bit needs to be set.
+	*/
+	uint8_t togctl_value = (ep & 0x80 >> 3) | (ep & 0x7);
+
+	/* First step: Write EP number and direction bit */
+	TOGCTL = togctl_value;
+
+	/* Second step: Set R bit */
+	togctl_value |= TOG_R;
+	TOGCTL = togctl_value;
+}
+
+/**
+ * Handle GET_STATUS request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_get_status(void)
+{
+	uint8_t *ep_cs;
+
+	switch (setup_data.bmRequestType) {
+	    case GS_DEVICE:
+			/* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
+			 *                    Byte 1: reserved, reset to zero */
+		    IN0BUF[0] = 0;
+		    IN0BUF[1] = 0;
+
+			/* Send response */
+		    IN0BC = 2;
+		    break;
+	    case GS_INTERFACE:
+			/* Always return two zero bytes according to USB 1.1 spec, p. 191 */
+		    IN0BUF[0] = 0;
+		    IN0BUF[1] = 0;
+
+			/* Send response */
+		    IN0BC = 2;
+		    break;
+	    case GS_ENDPOINT:
+			/* Get stall bit for endpoint specified in low byte of wIndex */
+		    ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex & 0xff);
+
+		    if (*ep_cs & EPSTALL)
+			    IN0BUF[0] = 0x01;
+		    else
+			    IN0BUF[0] = 0x00;
+
+			/* Second byte sent has to be always zero */
+		    IN0BUF[1] = 0;
+
+			/* Send response */
+		    IN0BC = 2;
+		    break;
+	    default:
+		    return false;
+		    break;
+	}
+
+	return true;
+}
+
+/**
+ * Handle CLEAR_FEATURE request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_clear_feature(void)
+{
+	__xdata uint8_t *ep_cs;
+
+	switch (setup_data.bmRequestType) {
+	    case CF_DEVICE:
+			/* Clear remote wakeup not supported: stall EP0 */
+		    STALL_EP0();
+		    break;
+	    case CF_ENDPOINT:
+		    if (setup_data.wValue == 0) {
+				/* Unstall the endpoint specified in wIndex */
+			    ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
+			    if (!ep_cs)
+				    return false;
+			    *ep_cs &= ~EPSTALL;
+		    } else {
+				/* Unsupported feature, stall EP0 */
+			    STALL_EP0();
+		    }
+		    break;
+	    default:
+			/* Vendor commands... */
+	}
+
+	return true;
+}
+
+/**
+ * Handle SET_FEATURE request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_set_feature(void)
+{
+	__xdata uint8_t *ep_cs;
+
+	switch (setup_data.bmRequestType) {
+	    case SF_DEVICE:
+		    if (setup_data.wValue == 2)
+			    return true;
+		    break;
+	    case SF_ENDPOINT:
+		    if (setup_data.wValue == 0) {
+				/* Stall the endpoint specified in wIndex */
+			    ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
+			    if (!ep_cs)
+				    return false;
+			    *ep_cs |= EPSTALL;
+		    } else {
+				/* Unsupported endpoint feature */
+			    return false;
+		    }
+		    break;
+	    default:
+			/* Vendor commands... */
+		    break;
+	}
+
+	return true;
+}
+
+/**
+ * Handle GET_DESCRIPTOR request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_get_descriptor(void)
+{
+	__xdata uint8_t descriptor_type;
+	__xdata uint8_t descriptor_index;
+
+	descriptor_type = (setup_data.wValue & 0xff00) >> 8;
+	descriptor_index = setup_data.wValue & 0x00ff;
+
+	switch (descriptor_type) {
+	    case DESCRIPTOR_TYPE_DEVICE:
+		    SUDPTRH = HI8(&device_descriptor);
+		    SUDPTRL = LO8(&device_descriptor);
+		    break;
+	    case DESCRIPTOR_TYPE_CONFIGURATION:
+		    SUDPTRH = HI8(&config_descriptor);
+		    SUDPTRL = LO8(&config_descriptor);
+		    break;
+	    case DESCRIPTOR_TYPE_STRING:
+		    if (setup_data.wIndex == 0) {
+				/* Supply language descriptor */
+			    SUDPTRH = HI8(&language_descriptor);
+			    SUDPTRL = LO8(&language_descriptor);
+		    } else if (setup_data.wIndex == 0x0409 /* US English */)   {
+				/* Supply string descriptor */
+			    SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
+			    SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
+		    } else
+			    return false;
+		    break;
+	    default:
+			/* Unsupported descriptor type */
+		    return false;
+		    break;
+	}
+
+	return true;
+}
+
+/**
+ * Handle SET_INTERFACE request.
+ */
+void usb_handle_set_interface(void)
+{
+	/* Reset Data Toggle */
+	usb_reset_data_toggle(USB_DIR_IN  | 2);
+	usb_reset_data_toggle(USB_DIR_OUT | 2);
+
+	/* Unstall & clear busy flag of all valid IN endpoints */
+	IN2CS = 0 | EPBSY;
+
+	/* Unstall all valid OUT endpoints, reset bytecounts */
+	OUT2CS = 0;
+	OUT2BC = 0;
+}
+
+/**
+ * Handle the arrival of a USB Control Setup Packet.
+ */
+void usb_handle_setup_data(void)
+{
+	switch (setup_data.bRequest) {
+	    case GET_STATUS:
+		    if (!usb_handle_get_status())
+			    STALL_EP0();
+		    break;
+	    case CLEAR_FEATURE:
+		    if (!usb_handle_clear_feature())
+			    STALL_EP0();
+		    break;
+	    case 2: case 4:
+			/* Reserved values */
+		    STALL_EP0();
+		    break;
+	    case SET_FEATURE:
+		    if (!usb_handle_set_feature())
+			    STALL_EP0();
+		    break;
+	    case SET_ADDRESS:
+			/* Handled by USB core */
+		    break;
+	    case SET_DESCRIPTOR:
+			/* Set Descriptor not supported. */
+		    STALL_EP0();
+		    break;
+	    case GET_DESCRIPTOR:
+		    if (!usb_handle_get_descriptor())
+			    STALL_EP0();
+		    break;
+	    case GET_CONFIGURATION:
+			/* OpenULINK has only one configuration, return its index */
+		    IN0BUF[0] = config_descriptor.bConfigurationValue;
+		    IN0BC = 1;
+		    break;
+	    case SET_CONFIGURATION:
+			/* OpenULINK has only one configuration -> nothing to do */
+		    break;
+	    case GET_INTERFACE:
+			/* OpenULINK only has one interface, return its number */
+		    IN0BUF[0] = interface_descriptor00.bInterfaceNumber;
+		    IN0BC = 1;
+		    break;
+	    case SET_INTERFACE:
+		    usb_handle_set_interface();
+		    break;
+	    case SYNCH_FRAME:
+			/* Isochronous endpoints not used -> nothing to do */
+		    break;
+	    default:
+			/* Any other requests: do nothing */
+		    break;
+	}
+}
+
+/**
+ * USB initialization. Configures USB interrupts, endpoints and performs
+ * ReNumeration.
+ */
+void usb_init(void)
+{
+	/* Mark endpoint 2 IN & OUT as valid */
+	IN07VAL  = IN2VAL;
+	OUT07VAL = OUT2VAL;
+
+	/* Make sure no isochronous endpoints are marked valid */
+	INISOVAL  = 0;
+	OUTISOVAL = 0;
+
+	/* Disable isochronous endpoints. This makes the isochronous data buffers
+	 * available as 8051 XDATA memory at address 0x2000 - 0x27FF */
+	ISOCTL = ISODISAB;
+
+	/* Enable USB Autovectoring */
+	USBBAV |= AVEN;
+
+	/* Enable SUDAV interrupt */
+	USBIEN |= SUDAVIE;
+
+	/* Enable EP2 OUT & IN interrupts */
+	OUT07IEN = OUT2IEN;
+	IN07IEN  = IN2IEN;
+
+	/* Enable USB interrupt (EIE register) */
+	EUSB = 1;
+
+	/* Perform ReNumeration */
+	USBCS = DISCON | RENUM;
+	delay_ms(200);
+	USBCS = DISCOE | RENUM;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/ulink_firmware.hex
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/ulink_firmware.hex b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/ulink_firmware.hex
new file mode 100755
index 0000000..efaea58
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/OpenULINK/ulink_firmware.hex
@@ -0,0 +1,347 @@
+:040000000200713257
+:01000B0032C2
+:0100130032BA
+:01001B0032B2
+:0100230032AA
+:01002B0032A2
+:01003300329A
+:01003B003292
+:01004300328A
+:01004B003282
+:01005300327A
+:01005B003272
+:01006300326A
+:03006B000201107F
+:0300CA0002006EC3
+:03006E000201018B
+:1000CD00907F937404F0907F9C7495F0907F96745C
+:1000DD0090F0907F94E4F0907F9D747FF0907F97E7
+:1000ED00E4F0907F957440F0907F9E7442F0907F85
+:1000FD0098E4F0221200CD1204ADD2AF1208E090B8
+:10010D00000022C021C0E0C0F0C082C083C007C083
+:10011D0006C005C004C003C002C001C000C0D07538
+:10012D00D000AF9174EF5FF59112040C907FAB741A
+:10013D0001F0907FB4E04402F0D0D0D000D001D0D7
+:10014D0002D003D004D005D006D007D083D082D002
+:10015D00F0D0E0D02132323232323232323232C04D
+:10016D00E0C082C083C007C0D075D000D201AF916E
+:10017D0074EF5FF591907FA97404F0D0D0D007D0C3
+:10018D0083D082D0E032C0E0C082C083C007C0D02F
+:10019D0075D000D200AF9174EF5FF591907FAA7486
+:1001AD0004F0D0D0D007D083D082D0E032323232BA
+:1001BD0032323232323232AF82747F5FFE24F850E7
+:1001CD0003020278EE240A83F582EE240C83F58374
+:1001DD00E473EFF306192C3F52650101020202028E
+:1001ED000202907FB422EF30E7067DB67E7F800459
+:1001FD007DC67E7F8D828E8322EF30E7067DB87EB1
+:10020D007F80047DC87E7F8D828E8322EF30E7064E
+:10021D007DBA7E7F80047DCA7E7F8D828E8322EFA4
+:10022D0030E7067DBC7E7F80047DCC7E7F8D828E07
+:10023D008322EF30E7067DBE7E7F80047DCE7E7FFC
+:10024D008D828E8322EF30E7067DC07E7F80047D18
+:10025D00D07E7F8D828E8322EF30E7067EC27F7F38
+:10026D0080047ED27F7F8E828F832290000022AF0A
+:10027D008274105FFE74075F4206907FD7EEF074B4
+:10028D00204EF022907FE8E0C322907FE8E0FF60EF
+:10029D0005BF0246800A907FB4E0FF4401F0803A2A
+:1002AD00907FEAE0FEA3E0FF4E7027907FECE0FE2A
+:1002BD00A3E08E821201C4AE82AF83EE4F7002C3F3
+:1002CD00228E828F83E0FD5305FE8E828F83EDF0AB
+:1002DD008008907FB4E0FF4401F0D322907FE8E0E6
+:1002ED00FF6005BF02468010907FEAE0FEA3E0FFAD
+:1002FD00BE0239BF0036D322907FEAE0FEA3E0FFB5
+:10030D004E7027907FECE0FEA3E08E821201C4AE0A
+:10031D0082AF83EE4F7002C3228E828F83E0FD4346
+:10032D0005018E828F83EDF08002C322D322907F50
+:10033D00EAE0A3E0FF907FEAE0FDA3E07E00BF01CD
+:10034D0002800DBF02028021BF030280340203EC44
+:10035D007ED37F138F06907FD4EEF07ED37F137FF5
+:10036D0000907FD5EEF00203EE7EE57F138F0690B1
+:10037D007FD4EEF07EE57F137F00907FD5EEF08089
+:10038D0060907FECE0FEA3E0FF4E70187E057F14B9
+:10039D008F06907FD4EEF07E057F147F00907FD581
+:1003AD00EEF0803D907FECE0FEA3E0FFBE092EBF96
+:1003BD00042BED1475F002A42459F582741435F054
+:1003CD00F583E493FEA3E493FF8E048F058D0490D3
+:1003DD007FD4ECF07F00907FD5EEF08004C322C374
+:1003ED0022D32275828212027C75820212027C90C7
+:1003FD007FB87402F0907FC8E4F0907FC9F022902E
+:10040D007FE9E0FF24F3500122EFF5F0240B83F593
+:10041D0082E5F0241183F583E473414F5D655D72D0
+:10042D007B73889899A9AC0404040404040404049F
+:10043D0004040404120291500122907FB4E044019F
+:10044D00F022120297500122907FB4E04401F02275
+:10045D00907FB4E04401F0221202E94042907FB453
+:10046D00E04401F02222907FB4E04401F022120317
+:10047D003B402C907FB4E04401F0229013EAE493CA
+:10048D00907F00F0907FB57401F022229013F0E47C
+:10049D0093907F00F0907FB57401F0221203F0224B
+:1004AD00907FDE7404F0907FDF7404F0907FE0E4C1
+:1004BD00F0907FE1F0907FA17401F0907FAFE04468
+:1004CD0001F0907FAEE04401F0907FAD7404F090A8
+:1004DD007FAC7404F0D2E8907FD6740AF09000C817
+:0A04ED0012137C907FD67406F022F3
+:1013D30012011001FFFFFF4051C21027000101025B
+:1013E3000301090220000101048032090400000204
+:1013F300FFFFFF00070582024000000705020240CD
+:1014030000000403090414034F00700065006E001C
+:1014130055004C0049004E004B0014034F00700070
+:1014230065006E0055004C0049004E004B000E0352
+:101433003000300030003000300031001A034A0021
+:101443005400410047002000410064006100700027
+:0E14530074006500720009141D1431143F145A
+:1004F700E5080424C0F582E4347DF583E0FF30E1AC
+:1005070008907F96E0FE54EFF08F06EE30E00890FB
+:100517007F96E0FE547FF0EF30E308907F96E0FE91
+:100527004410F0EF30E208907F96E0FF4480F0221D
+:100537007F00E50824C0F582E4347DF583E0FE24DE
+:10054700D550030208A6EE240A83F582EE242F83F2
+:10055700F583E473B18AD7B0FAD3A6A6A6A6A6A652
+:10056700A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A624
+:10057700A6A6A6A621FA512A639CD5053493A205FF
+:1005870006050605060808080808080808080808F0
+:1005970008080808080808080808080808080806D6
+:1005A700060607070707080808087E05E508042464
+:1005B700C0F582E4347DF583E0FFE50804F5828524
+:1005C7000927C007C00612091DD006D0070208A8D0
+:1005D700E5080424C0F582E4347DF583E02405FEB4
+:1005E700E50804F582C007C006120BDED006D00767
+:1005F7000208A8E5080424C0F582E4347DF583E009
+:10060700FF2405FEE50804F58285093CC007C006FE
+:10061700120E79D006D0070208A87E02E508042446
+:10062700C0F582E4347DF583E0FD7402250824C01B
+:10063700F582E4347DF583E0F50A8D82C007C006B4
+:1006470012124AD006D0070208A87E02E508042441
+:10065700C0F582E4347DF583E0FC7D007402250853
+:1006670024C0F582E4347DF583E0FAE44204EA42EB
+:10067700058C828D83C007C0061211DDD006D00716
+:100687000208A87E05E5080424C0F582E4347DF558
+:1006970083E0FFE50804F58285092DC007C006122F
+:1006A7000A67D006D0070208A8E5080424C0F58227
+:1006B700E4347DF583E02405FEE50804F582C007F0
+:1006C700C006120D14D006D0070208A8E5080424B6
+:1006D700C0F582E4347DF583E0FF2405FEE50804D8
+:1006E700F582850943C007C006121013D006D0074C
+:1006F7000208A87E02E5080424C0F582E4347DF5EB
+:1007070083E0FB7402250824C0F582E4347DF58379
+:10071700E0F50A8B82C007C006121281D006D00707
+:100727000208A87E02E5080424C0F582E4347DF5BA
+:1007370083E0FC7D007402250824C0F582E4347D43
+:10074700F583E0FAE44204EA42058C828D83C00710
+:10075700C006121207D006D0070208A87E02E508D5
+:100767000424C0F582E4347DF583E0FC7D00740247
+:10077700250824C0F582E4347DF583E0FAE44204D9
+:10078700EA42058C828D83C007C006121349D00642
+:10079700D0070208A87E02E5080424C0F582E434E5
+:1007A7007DF583E0FC7D007402250824C0F582E412
+:1007B700347DF583E0FAE44204EA42058C828D83B6
+:1007C700C007C00612137CD006D0070208A87E0017
+:1007D7007F02C007C0061212CEAC82AD83D006D00E
+:1007E7000785098275837E8D03EBF0E509042400F4
+:1007F700F582E4347EF5837D00ECF00208A87E02E2
+:10080700E5080424C0F582E4347DF583E0FD740235
+:10081700250824C0F582E4347DF583E0F50A8D824E
+:10082700C007C006121311D006D00780747E05E5F5
+:10083700080424C0F582E4347DF583E0FD740225C5
+:100847000824C0F582E4347DF583E0F50A740325B6
+:100857000824C0F582E4347DF583E0F50B740425A4
+:100867000824C0F582E4347DF583E0F50C74052592
+:100877000824C0F582E4347DF583E0F50D8D82C050
+:1008870007C006121329D006D00780157E01C007BE
+:10089700C0061204F7D006D00780067E0180027ECC
+:1008A70000EF2509F509AD087F008E037C00EB2DCD
+:1008B700FDEC3FFF0DBD00010F907FC9E0FC7B0001
+:1008C700C3ED9CEF64808BF063F08095F04002D31A
+:1008D70022EE042508F508C32275080075090010E3
+:1008E700000280FB907F96E0FF547FF0C202200257
+:1008F70007120537920280F6907F96E0FF4480F05A
+:10090700E509600B907FB9E509F010010280FB90C3
+:100917007FC9E4F080C3E582FF24C0F582E4347D1B
+:10092700F583E0F528EF0424C0F582E4347DF583F0
+:10093700E0F52974022FFC24C0F582E4347DF583A9
+:10094700E0C4540FFB53030FEC24C0F582E4347D5D
+:10095700F583E0FC740F5CF52A74032F24C0F5823D
+:10096700E4347DF583E0FA74042F24C0F582E4347F
+:100977007DF583E0F52BEB60078A0A8B8212124A1A
+:10098700907F97E0FB5303F874044BFA7900A8288B
+:100997007C0018B8FF011C89067F00C3EE98EF643E
+:1009A700808CF063F08095F050347F007E00907F5C
+:1009B70097EBF0EFC313FF907F97EAF0907F99E0F2
+:1009C700FC30E5034307800EBE080040E1E5272918
+:1009D7002400F582E4347EF583EFF00980B0892C9A
+:1009E7007F00AC2A7A00C3EA95295040A8297900EC
+:1009F70018B8FF01198A057E00EDB50011EEB501A3
+:100A07000DEC600A4303021CE52BC313F52B907F03
+:100A170097EBF0EFC313FF907F9774044BF0907F31
+:100A270099E0FE30E5034307800A80BAAD297E00CE
+:100A37007408C39DFDE49EFE8DF005F0EF8002C3B0
+:100A470013D5F0FBFFE527252C2400F582E4347E3F
+:100A5700F583EFF0EC6008852B0A8C8202124A229C
+:100A6700E582FF24C0F582E4347DF583E0F52EEFBF
+:100A77000424C0F582E4347DF583E0F52F74022F5A
+:100A8700FC24C0F582E4347DF583E0C4540FFB53A6
+:100A9700030FEC24C0F582E4347DF583E0FC740F8A
+:100AA7005CF53074032F24C0F582E4347DF583E0D0
+:100AB700FA74042F24C0F582E4347DF583E0F53120
+:100AC700EB60078A0A8B82121281907F97E0FB53B3
+:100AD70003F874044BFA753200A82E7C0018B8FF8F
+:100AE700011CA9327E00C3E998EE64808CF063F0A4
+:100AF7008095F0504C7E007C00907F97EBF079005A
+:100B0700C3E9952250030980F7EEC313FE907F9740
+:100B1700EAF07900C3E9952250030980F7907F999D
+:100B2700E0F930E5034306800CBC080040CBE52D17
+:100B370025322400F582E4347EF583EEF005328019
+:100B4700987E00AA307900C3E9952F5056A82F7CCC
+:100B57000018B8FF011C89057F00EDB50011EFB53E
+:100B6700040DEA600A4303021AE531C313F5319015
+:100B77007F97EBF07F00C3EF952250030F80F7EECE
+:100B8700C313FE907F9774044BF07F00C3EF952249
+:100B970050030F80F7907F99E0FF30E5034306800D
+:100BA7000980A4AD2F7F007408C39DFDE49FFF8DCE
+:100BB700F005F0EE8002C313D5F0FBFEE52D2532DC
+:100BC7002400F582E4347EF583EEF0EA600885318F
+:100BD7000A8A8202128122E582FF24C0F582E43468
+:100BE7007DF583E0F533EF0424C0F582E4347DF529
+:100BF70083E0F53474022FFC24C0F582E4347DF5DC
+:100C070083E0C4540FFB53030FEC24C0F582E43494
+:100C17007DF583E0FC740F5CF53574032F24C0F574
+:100C270082E4347DF583E0FA74042F24C0F582E46E
+:100C3700347DF583E0F536EB600B8A0A8B82C007BB
+:100C470012124AD007907F97E0FB5303F97A00A866
+:100C5700337C0018B8FF011C8A017E00C3E998EEB7
+:100C670064808CF063F08095F05039EF2A240524D6
+:100C7700C0F582E4347DF583E0FE7C00EE30E005CC
+:100C870043030180068B0174FE59FB907F97EBF0BD
+:100C9700EEC313FE907F9774044BF00CBC08004022
+:100CA700DB0A80ABEF2A240524C0F582E4347DF506
+:100CB70083E0FEAF357C00C3EC95345044EE30E062
+:100CC7000543030180068B0274FE5AFBA9347A00A0
+:100CD70019B9FF011A8C007D00E8B50111EDB502C5
+:100CE7000DEF600A4303021FE536C313F536907F05
+:100CF70097EBF0EEC313FE907F9774044BF00C80D4
+:100D0700B6EF600885360A8F8202124A22E582F51D
+:100D17003724C0F582E4347DF583E0F538E5370400
+:100D270024C0F582E4347DF583E0F5397402253774
+:100D3700FC24C0F582E4347DF583E0C4540FFB53F3
+:100D4700030FEC24C0F582E4347DF583E0FC740FD7
+:100D57005CF53A7403253724C0F582E4347DF583C6
+:100D6700E0FA7404253724C0F582E4347DF583E086
+:100D7700F53BEB60078A0A8B82121281907F97E01E
+:100D8700FB5303F97A00A8387C0018B8FF011C8AC6
+:100D9700067F00C3EE98EF64808CF063F08095F0D7
+:100DA7005050E5372A240524C0F582E4347DF583C5
+:100DB700E0FF7E00EF30E00543030180068B0474FB
+:100DC700FE5CFB907F97EBF07C00C3EC9523500310
+:100DD7000C80F7EFC313FF907F9774044BF07C00F0
+:100DE700C3EC952350030C80F70EBE080040C50ADC
+:100DF7008094E5372A240524C0F582E4347DF58301
+:100E0700E0FFAE3A7C00C3EC9539505AEF30E0056D
+:100E170043030180068B0274FE5AFBA8397A001837
+:100E2700B8FF011A8C017D00E9B50011EDB5020D7F
+:100E3700EE600A4303021EE53BC313F53B907F9721
+:100E4700EBF07D00C3ED952350030D80F7EFC3133F
+:100E5700FF907F9774044BF07D00C3ED95235003FB
+:100E67000D80F70C80A0EE6008853B0A8E82021287
+:100E77008122E582FF24C0F582E4347DF583E0F525
+:100E87003DEF0424C0F582E4347DF583E0F53E743C
+:100E9700022FFC24C0F582E4347DF583E0C4540FAF
+:100EA700FB53030FEC24C0F582E4347DF583E0FCAB
+:100EB700740F5CF53F74032F24C0F582E4347DF58D
+:100EC70083E0FA74042F24C0F582E4347DF583E0CF
+:100ED700F540EB600B8A0A8B82C00712124AD007D3
+:100EE700907F97E0FB5303F97A00A83D7C0018B880
+:100EF700FF011C8A017E00C3E998EE64808CF063D1
+:100F0700F08095F0505CEF2A240524C0F582E43484
+:100F17007DF583E0F5417C007900E54130E005434C
+:100F2700030180068B0074FE58FB907F97EBF0E57A
+:100F370041C313F541907F9774044BF0ECC313FC46
+:100F4700907F99E0F830E50343048009B908004031
+:100F5700C9E53C2A2400F582E4347EF583ECF00AE7
+:100F670080888A01EF2A240524C0F582E4347DF5C0
+:100F770083E0F5417C00AF3F754200C3E542953EF3
+:100F87005057E54130E00543030180068B0074FEAE
+:100F970058FBA83E7D0018B8FF011DAA427E00EA53
+:100FA700B50011EEB5050DEF600A4303021FE540DA
+:100FB700C313F540907F97EBF0E541C313F54190DC
+:100FC7007F9774044BF0ECC313FC907F99E0FE30DD
+:100FD700E503430480054280A2AD3E7E007408C34A
+:100FE7009DFDE49EFE8DF005F0EC8002C313D5F065
+:100FF700FBFCE53C292400F582E4347EF583ECF024
+:10100700EF600885400A8F8202124A22E582F54482
+:1010170024C0F582E4347DF583E0F545E5440424F6
+:10102700C0F582E4347DF583E0F54674022544FC7F
+:1010370024C0F582E4347DF583E0C4540FFB5303E9
+:101047000FEC24C0F582E4347DF583E0FC740F5C7B
+:10105700F5477403254424C0F582E4347DF583E025
+:10106700FA7404254424C0F582E4347DF583E0F561
+:1010770048EB60078A0A8B82121281907F97E0FB08
+:101087005303F97A00A8457C0018B8FF011C8A06AB
+:101097007F00C3EE98EF64808CF063F08095F0508A
+:1010A70074E5442A240524C0F582E4347DF583E001
+:1010B700F5497E007C00E54930E0054303018006E1
+:1010C7008B0074FE58FB907F97EBF07800C3E89590
+:1010D7002450030880F7E549C313F549907F9774B7
+:1010E700044BF07800C3E8952450030880F7EEC35B
+:1010F70013FE907F99E0F830E5034306800CBC08A7
+:101107000040B3E5432A2400F582E4347EF583EEFC
+:10111700F00A02108C8A04E5442A240524C0F582CB
+:10112700E4347DF583E0F5497E00AA47754A00C39C
+:10113700E54A9546506DE54930E0054303018006D1
+:101147008B0174FE59FBA9467D0019B9FF011DA843
+:101157004A7F00E8B50111EFB5050DEA600A4303C0
+:10116700021AE548C313F548907F97EBF07F00C359
+:10117700EF952450030F80F7E549C313F549907F96
+:101187009774044BF07F00C3EF952450030F80F74B
+:10119700EEC313FE907F99E0FF30E5034306800519
+:1011A7004A808CAD467F007408C39DFDE49FFF8D88
+:1011B700F005F0EE8002C313D5F0FBFEE5432C24C7
+:1011C70000F582E4347EF583EEF0EA600885480A8C
+:1011D7008A8202128122AE82AF83907F97E0FD530D
+:1011E70005FB74044DFC7A007B00C3EA9EEB9F501D
+:1011F7000E907F97EDF0ECF00ABA00EE0B80EB2231
+:10120700AE82AF83907F97E0FD5305FB74044DFCDE
+:101217007A007B00C3EA9EEB9F5027907F97EDF003
+:101227007900C3E9952550030980F7907F97ECF083
+:101237007900C3E9952550030980F70ABA00D50B51
+:1012470080D222AF82907F97E0FE5306FB7D00C3DA
+:10125700ED9F5025E50A30E00543060280068E041F
+:1012670074FD5CFE907F97EEF0E50AC313F50A90D4
+:101277007F9774044EF00D80D622AF82907F97E05F
+:10128700FE5306FB7D00C3ED9F503BE50A30E005AA
+:1012970043060280068E0474FD5CFE907F97EEF095
+:1012A7007C00C3EC952650030C80F7E50AC313F5C1
+:1012B7000A907F9774044EF07C00C3EC9526500388
+:1012C7000C80F70D80C0227F00907F99E0FE30E50B
+:1012D700027F01907F99E0FE30E603430702907F8B
+:1012E7009AE0FE30E703430704907F9BE0FE30E57A
+:1012F70003430708907F9AE0FE53067F8F05E4FFBC
+:10130700FCEE4FF582EC4DF58322E582547FF4FF26
+:10131700907F97E05FF0747F550AFF907F97E04FCB
+:10132700F022858222850A23850B24850C25850DCD
+:10133700262200227E567F021EBEFF011FEE4F703F
+:10134700F722750A05750B001213A6AE82AF837CD0
+:10135700007D00C3EC9EED9F501AC007C006C00574
+:10136700C004121339D004D005D006D0070CBC0036
+:10137700E20D80DF22AE82AF837C007D00C3EC9E4E
+:10138700ED9F501AC007C006C005C00412133BD01A
+:0F13970004D005D006D0070CBC00E20D80DF2289
+:03004300021B009D
+:101B0000020110000201630002016400020165008D
+:101B1000020166000201670002016800020169001B
+:101B200002016A0002016B0002016C0002019300D5
+:101B30000201BA000201BB000201BC000201BD00AB
+:101B40000201BE000201BF000201C0000201C1008B
+:081B50000201C2000201C30002
+:1013A6007A10E4FBFCE58225E0F582E58333F583DC
+:1013B600EB33FBEC33FCEB950AF5F0EC950B4006B2
+:0913C600FCABF0438201DADD22E8
+:0600A000E478FFF6D8FD34
+:10007E007900E94400601B7A009014617800759253
+:10008E0020E493F2A308B800020592D9F4DAF275CF
+:02009E0092FFCF
+:1000A6007800E84400600A7900759220E4F309D8E4
+:1000B600FC7800E84400600C7900902000E4F0A38E
+:0400C600D8FCD9FA8F
+:0D00710075814A1213CFE582600302006E14
+:0413CF007582002201
+:00000001FF

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/e302582d/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/amt_jtagaccel.c
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/amt_jtagaccel.c b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/amt_jtagaccel.c
new file mode 100755
index 0000000..5aacead
--- /dev/null
+++ b/docs/os/tutorials/downloads/openocd-code-89bf96ffe6ac66c80407af8383b9d5adc0dc35f4/src/jtag/drivers/amt_jtagaccel.c
@@ -0,0 +1,607 @@
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/interface.h>
+
+#if PARPORT_USE_PPDEV == 1
+#include <linux/parport.h>
+#include <linux/ppdev.h>
+#include <sys/ioctl.h>
+#else	/* not PARPORT_USE_PPDEV */
+#ifndef _WIN32
+#include <sys/io.h>
+#endif
+#endif
+
+#if PARPORT_USE_GIVEIO == 1
+#if IS_CYGWIN == 1
+#include <windows.h>
+#endif
+#endif
+
+/**
+ * @file
+ * Support the Amontec Chameleon POD with JTAG Accelerator support.
+ * This is a parallel port JTAG adapter with a CPLD between the
+ * parallel port and the JTAG connection.  VHDL code running in the
+ * CPLD significantly accelerates JTAG operations compared to the
+ * bitbanging "Wiggler" style of most parallel port adapters.
+ */
+
+/* configuration */
+static uint16_t amt_jtagaccel_port;
+
+/* interface variables
+ */
+static uint8_t aw_control_rst;
+static uint8_t aw_control_fsm = 0x10;
+static uint8_t aw_control_baudrate = 0x20;
+
+static int rtck_enabled;
+
+#if PARPORT_USE_PPDEV == 1
+static int device_handle;
+
+static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
+
+/* FIXME do something sane when these ioctl/read/write calls fail. */
+
+#define AMT_AW(val) \
+	do { \
+		int __retval; \
+		\
+		__retval = ioctl(device_handle, PPSETMODE, &addr_mode);	\
+		assert(__retval >= 0); \
+		__retval = write(device_handle, &val, 1); \
+		assert(__retval >= 0); \
+	} while (0)
+#define AMT_AR(val) \
+	do { \
+		int __retval; \
+		\
+		__retval = ioctl(device_handle, PPSETMODE, &addr_mode);	\
+		assert(__retval >= 0); \
+		__retval = read(device_handle, &val, 1); \
+		assert(__retval >= 0); \
+	} while (0)
+
+static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
+
+#define AMT_DW(val) \
+	do { \
+		int __retval; \
+		\
+		__retval = ioctl(device_handle, PPSETMODE, &data_mode);	\
+		assert(__retval >= 0); \
+		__retval = write(device_handle, &val, 1); \
+		assert(__retval >= 0); \
+	} while (0)
+#define AMT_DR(val) \
+	do { \
+		int __retval; \
+		\
+		__retval = ioctl(device_handle, PPSETMODE, &data_mode);	\
+		assert(__retval >= 0); \
+		__retval = read(device_handle, &val, 1); \
+		assert(__retval >= 0); \
+	} while (0)
+
+#else
+
+#define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
+#define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
+#define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
+#define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
+
+#endif	/* PARPORT_USE_PPDEV */
+
+/* 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
+ */
+static const uint8_t amt_jtagaccel_tap_move[6][6][2] = {
+	/*	   RESET         IDLE        DRSHIFT       DRPAUSE       IRSHIFT       IRPAUSE             */
+	{ {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} },	/* RESET */
+	{ {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} },	/* IDLE */
+	{ {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} },	/* DRSHIFT  */
+	{ {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} },	/* DRPAUSE  */
+	{ {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} },	/* IRSHIFT  */
+	{ {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} },	/* IRPAUSE  */
+};
+
+static void amt_jtagaccel_reset(int trst, int srst)
+{
+	if (trst == 1)
+		aw_control_rst |= 0x4;
+	else if (trst == 0)
+		aw_control_rst &= ~0x4;
+
+	if (srst == 1)
+		aw_control_rst |= 0x1;
+	else if (srst == 0)
+		aw_control_rst &= ~0x1;
+
+	AMT_AW(aw_control_rst);
+}
+
+static int amt_jtagaccel_speed(int speed)
+{
+	aw_control_baudrate &= 0xf0;
+	aw_control_baudrate |= speed & 0x0f;
+	AMT_AW(aw_control_baudrate);
+
+	return ERROR_OK;
+}
+
+static void amt_jtagaccel_end_state(tap_state_t state)
+{
+	if (tap_is_state_stable(state))
+		tap_set_end_state(state);
+	else {
+		LOG_ERROR("BUG: %i is not a valid end state", state);
+		exit(-1);
+	}
+}
+
+static void amt_wait_scan_busy(void)
+{
+	int timeout = 4096;
+	uint8_t ar_status;
+
+	AMT_AR(ar_status);
+	while (((ar_status) & 0x80) && (timeout-- > 0))
+		AMT_AR(ar_status);
+
+	if (ar_status & 0x80) {
+		LOG_ERROR(
+			"amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x",
+			(rtck_enabled) ? "enabled" : "disabled",
+			ar_status);
+		exit(-1);
+	}
+}
+
+static void amt_jtagaccel_state_move(void)
+{
+	uint8_t aw_scan_tms_5;
+	uint8_t tms_scan[2];
+
+	tap_state_t cur_state = tap_get_state();
+	tap_state_t end_state = tap_get_end_state();
+
+	tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0];
+	tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1];
+
+	aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
+	AMT_AW(aw_scan_tms_5);
+	int jtag_speed = 0;
+	int retval = jtag_get_speed(&jtag_speed);
+	assert(retval == ERROR_OK);
+	if (jtag_speed > 3 || rtck_enabled)
+		amt_wait_scan_busy();
+
+	if (tms_scan[0] & 0x80) {
+		aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
+		AMT_AW(aw_scan_tms_5);
+		if (jtag_speed > 3 || rtck_enabled)
+			amt_wait_scan_busy();
+	}
+
+	tap_set_state(end_state);
+}
+
+static void amt_jtagaccel_runtest(int num_cycles)
+{
+	int i = 0;
+	uint8_t aw_scan_tms_5;
+	uint8_t aw_scan_tms_1to4;
+
+	tap_state_t saved_end_state = tap_get_end_state();
+
+	/* only do a state_move when we're not already in IDLE */
+	if (tap_get_state() != TAP_IDLE) {
+		amt_jtagaccel_end_state(TAP_IDLE);
+		amt_jtagaccel_state_move();
+	}
+
+	while (num_cycles - i >= 5) {
+		aw_scan_tms_5 = 0x40;
+		AMT_AW(aw_scan_tms_5);
+		i += 5;
+	}
+
+	if (num_cycles - i > 0) {
+		aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
+		AMT_AW(aw_scan_tms_1to4);
+	}
+
+	amt_jtagaccel_end_state(saved_end_state);
+	if (tap_get_state() != tap_get_end_state())
+		amt_jtagaccel_state_move();
+}
+
+static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
+{
+	int bits_left = scan_size;
+	int bit_count = 0;
+	tap_state_t saved_end_state = tap_get_end_state();
+	uint8_t aw_tdi_option;
+	uint8_t dw_tdi_scan;
+	uint8_t dr_tdo;
+	uint8_t aw_tms_scan;
+	uint8_t tms_scan[2];
+	int jtag_speed_var;
+	int retval = jtag_get_speed(&jtag_speed_var);
+	assert(retval == ERROR_OK);
+
+	if (ir_scan)
+		amt_jtagaccel_end_state(TAP_IRSHIFT);
+	else
+		amt_jtagaccel_end_state(TAP_DRSHIFT);
+
+	/* Only move if we're not already there */
+	if (tap_get_state() != tap_get_end_state())
+		amt_jtagaccel_state_move();
+
+	amt_jtagaccel_end_state(saved_end_state);
+
+	/* handle unaligned bits at the beginning */
+	if ((scan_size - 1) % 8) {
+		aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
+		AMT_AW(aw_tdi_option);
+
+		dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
+		AMT_DW(dw_tdi_scan);
+		if (jtag_speed_var > 3 || rtck_enabled)
+			amt_wait_scan_busy();
+
+		if ((type == SCAN_IN) || (type == SCAN_IO)) {
+			AMT_DR(dr_tdo);
+			dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
+			buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
+		}
+
+		bit_count += (scan_size - 1) % 8;
+		bits_left -= (scan_size - 1) % 8;
+	}
+
+	while (bits_left - 1 >= 8) {
+		dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
+		AMT_DW(dw_tdi_scan);
+		if (jtag_speed_var > 3 || rtck_enabled)
+			amt_wait_scan_busy();
+
+		if ((type == SCAN_IN) || (type == SCAN_IO)) {
+			AMT_DR(dr_tdo);
+			buf_set_u32(buffer, bit_count, 8, dr_tdo);
+		}
+
+		bit_count += 8;
+		bits_left -= 8;
+	}
+
+	tms_scan[0] =
+		amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
+	tms_scan[1] =
+		amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
+	aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
+	AMT_AW(aw_tms_scan);
+	if (jtag_speed_var > 3 || rtck_enabled)
+		amt_wait_scan_busy();
+
+	if ((type == SCAN_IN) || (type == SCAN_IO)) {
+		AMT_DR(dr_tdo);
+		dr_tdo = dr_tdo >> 7;
+		buf_set_u32(buffer, bit_count, 1, dr_tdo);
+	}
+
+	if (tms_scan[0] & 0x80) {
+		aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
+		AMT_AW(aw_tms_scan);
+		if (jtag_speed_var > 3 || rtck_enabled)
+			amt_wait_scan_busy();
+	}
+	tap_set_state(tap_get_end_state());
+}
+
+static int amt_jtagaccel_execute_queue(void)
+{
+	struct jtag_command *cmd = jtag_command_queue;	/* currently processed command */
+	int scan_size;
+	enum scan_type type;
+	uint8_t *buffer;
+	int retval;
+
+	/* return ERROR_OK, unless a jtag_read_buffer returns a failed check
+	 * that wasn't handled by a caller-provided error handler
+	 */
+	retval = ERROR_OK;
+
+	while (cmd) {
+		switch (cmd->type) {
+			case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("reset trst: %i srst %i",
+				cmd->cmd.reset->trst,
+				cmd->cmd.reset->srst);
+#endif
+				if (cmd->cmd.reset->trst == 1)
+					tap_set_state(TAP_RESET);
+				amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+				break;
+			case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("runtest %i cycles, end in %i",
+				cmd->cmd.runtest->num_cycles,
+				cmd->cmd.runtest->end_state);
+#endif
+				amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
+				amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
+				break;
+			case JTAG_TLR_RESET:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
+#endif
+				amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
+				amt_jtagaccel_state_move();
+				break;
+			case JTAG_SCAN:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
+#endif
+				amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
+				scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+				type = jtag_scan_type(cmd->cmd.scan);
+				amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+				if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+					retval = ERROR_JTAG_QUEUE_FAILED;
+				if (buffer)
+					free(buffer);
+				break;
+			case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+				LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
+#endif
+				jtag_sleep(cmd->cmd.sleep->us);
+				break;
+			default:
+				LOG_ERROR("BUG: unknown JTAG command type encountered");
+				exit(-1);
+		}
+		cmd = cmd->next;
+	}
+
+	return retval;
+}
+
+#if PARPORT_USE_GIVEIO == 1
+int amt_jtagaccel_get_giveio_access(void)
+{
+	HANDLE h;
+	OSVERSIONINFO version;
+
+	version.dwOSVersionInfoSize = sizeof version;
+	if (!GetVersionEx(&version)) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
+		return 0;
+
+	h = CreateFile("\\\\.\\giveio",
+			GENERIC_READ,
+			0,
+			NULL,
+			OPEN_EXISTING,
+			FILE_ATTRIBUTE_NORMAL,
+			NULL);
+	if (h == INVALID_HANDLE_VALUE) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	CloseHandle(h);
+
+	return 0;
+}
+#endif
+
+static int amt_jtagaccel_init(void)
+{
+#if PARPORT_USE_PPDEV == 1
+	char buffer[256];
+	int i = 0;
+	uint8_t control_port;
+#else
+	uint8_t status_port;
+#endif
+	uint8_t ar_status;
+
+#if PARPORT_USE_PPDEV == 1
+	if (device_handle > 0) {
+		LOG_ERROR("device is already opened");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
+	device_handle = open(buffer, O_RDWR);
+
+	if (device_handle < 0) {
+		LOG_ERROR(
+			"cannot open device. check it exists and that user read and write rights are set");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	i = ioctl(device_handle, PPCLAIM);
+	if (i < 0) {
+		LOG_ERROR("cannot claim device");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	i = IEEE1284_MODE_EPP;
+	i = ioctl(device_handle, PPSETMODE, &i);
+	if (i < 0) {
+		LOG_ERROR(" cannot set compatible mode to device");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	control_port = 0x00;
+	i = ioctl(device_handle, PPWCONTROL, &control_port);
+
+	control_port = 0x04;
+	i = ioctl(device_handle, PPWCONTROL, &control_port);
+
+#else
+	if (amt_jtagaccel_port == 0) {
+		amt_jtagaccel_port = 0x378;
+		LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
+	}
+
+#if PARPORT_USE_GIVEIO == 1
+	if (amt_jtagaccel_get_giveio_access() != 0) {
+#else	/* PARPORT_USE_GIVEIO */
+	if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
+#endif	/* PARPORT_USE_GIVEIO */
+		LOG_ERROR("missing privileges for direct i/o");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+
+	/* prepare epp port
+	 * clear timeout */
+	status_port = inb(amt_jtagaccel_port + 1);
+	outb(status_port | 0x1, amt_jtagaccel_port + 1);
+
+	/* reset epp port */
+	outb(0x00, amt_jtagaccel_port + 2);
+	outb(0x04, amt_jtagaccel_port + 2);
+#endif
+
+	if (rtck_enabled) {
+		/* set RTCK enable bit */
+		aw_control_fsm |= 0x02;
+	}
+
+	/* enable JTAG port */
+	aw_control_fsm |= 0x04;
+	AMT_AW(aw_control_fsm);
+
+	enum reset_types jtag_reset_config = jtag_get_reset_config();
+	if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
+		aw_control_rst &= ~0x8;
+	else
+		aw_control_rst |= 0x8;
+
+	if (jtag_reset_config & RESET_SRST_PUSH_PULL)
+		aw_control_rst &= ~0x2;
+	else
+		aw_control_rst |= 0x2;
+
+	amt_jtagaccel_reset(0, 0);
+
+	/* read status register */
+	AMT_AR(ar_status);
+	LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
+
+	return ERROR_OK;
+}
+
+static int amt_jtagaccel_quit(void)
+{
+
+	return ERROR_OK;
+}
+
+COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command)
+{
+	if (CMD_ARGC == 1) {
+		/* only if the port wasn't overwritten by cmdline */
+		if (amt_jtagaccel_port == 0) {
+			uint16_t port;
+			COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
+			amt_jtagaccel_port = port;
+		} else {
+			LOG_ERROR("The parport port was already configured!");
+			return ERROR_FAIL;
+		}
+	}
+
+	command_print(CMD_CTX, "parport port = %u", amt_jtagaccel_port);
+
+	return ERROR_OK;
+}
+
+COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command)
+{
+	if (CMD_ARGC == 0) {
+		command_print(CMD_CTX,
+			"amt_jtagaccel RTCK feature %s",
+			(rtck_enabled) ? "enabled" : "disabled");
+		return ERROR_OK;
+	} else {
+		if (strcmp(CMD_ARGV[0], "enabled") == 0)
+			rtck_enabled = 1;
+		else
+			rtck_enabled = 0;
+	}
+
+	return ERROR_OK;
+}
+
+static const struct command_registration amtjtagaccel_command_handlers[] = {
+	{
+		.name = "parport_port",
+		.handler = &amt_jtagaccel_handle_parport_port_command,
+		.mode = COMMAND_CONFIG,
+		.help = "configure or display the parallel port to use",
+		.usage = "[port_num]",
+	},
+	{
+		/**
+		 * @todo Remove this "rtck" command; just use the standard
+		 * mechanism to enable/disable adaptive clocking.  First
+		 * implement the standard mechanism and deprecate "rtck";
+		 * after a year or so, it'll be safe to remove this.
+		 */
+		.name = "rtck",
+		.handler = &amt_jtagaccel_handle_rtck_command,
+		.mode = COMMAND_CONFIG,
+		.help = "configure or display RTCK support",
+		.usage = "[enable|disable]",
+	},
+	COMMAND_REGISTRATION_DONE
+};
+
+struct jtag_interface amt_jtagaccel_interface = {
+	.name = "amt_jtagaccel",
+	.commands = amtjtagaccel_command_handlers,
+
+	.init = amt_jtagaccel_init,
+	.quit = amt_jtagaccel_quit,
+	.speed = amt_jtagaccel_speed,
+	.execute_queue = amt_jtagaccel_execute_queue,
+};