]> git.sur5r.net Git - openocd/commitdiff
Add OpenULINK firmware
authorMartin Schmölzer <martin.schmoelzer@student.tuwien.ac.at>
Mon, 20 Jun 2011 17:49:49 +0000 (19:49 +0200)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Sun, 26 Jun 2011 15:43:51 +0000 (17:43 +0200)
Build requires SDCC, the Small Device C Compiler.

19 files changed:
src/jtag/drivers/OpenULINK/Makefile [new file with mode: 0644]
src/jtag/drivers/OpenULINK/README [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/common.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/delay.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/io.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/jtag.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/main.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/msgtypes.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/protocol.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/reg_ezusb.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/shorttypes.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/usb.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/delay.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/jtag.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/main.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/protocol.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/usb.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/ulink_firmware.hex [new file with mode: 0644]

diff --git a/src/jtag/drivers/OpenULINK/Makefile b/src/jtag/drivers/OpenULINK/Makefile
new file mode 100644 (file)
index 0000000..c0e3435
--- /dev/null
@@ -0,0 +1,90 @@
+############################################################################
+#    Copyright (C) 2011 by Martin Schmoelzer                               #
+#    <martin.schmoelzer@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.,                                       #
+#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
+############################################################################
+
+# Define the name of our tools. Some distributions (e. g. Fedora) prefix
+# the SDCC executables, change this accordingly!
+PREFIX =
+
+# Small Device C Compiler: http://sdcc.sourceforge.net/
+CC = $(PREFIX)-sdcc
+
+# 8051 assembler, part of the SDCC software package.
+AS = $(PREFIX)-sdas8051
+
+# SDCC produces quite messy Intel HEX files. This tool is be used to re-format
+# those files. It is not required for the firmware download functionality in
+# the OpenOCD driver, but the resulting file is smaller.
+PACKIHX = $(PREFIX)-packihx
+
+# GNU binutils size. Used to print the size of the IHX file generated by SDCC.
+SIZE = size
+
+# Source and header directories.
+SRC_DIR     = src
+INCLUDE_DIR = include
+
+CODE_SIZE = 0x1B00
+
+# Starting address of __xdata variables. Since the OpenULINK firmware does not
+# use any of the isochronous interrupts, we can use the isochronous buffer space
+# as XDATA memory.
+XRAM_LOC  = 0x2000
+XRAM_SIZE = 0x0800
+
+CFLAGS  = --std-sdcc99 --opt-code-size --model-small
+LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \
+          --xram-size $(XRAM_SIZE) --iram-size 256 --model-small
+
+# list of base object files
+OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel
+HEADERS = $(INCLUDE_DIR)/main.h         \
+          $(INCLUDE_DIR)/usb.h          \
+          $(INCLUDE_DIR)/protocol.h     \
+          $(INCLUDE_DIR)/jtag.h         \
+          $(INCLUDE_DIR)/delay.h        \
+          $(INCLUDE_DIR)/reg_ezusb.h    \
+          $(INCLUDE_DIR)/io.h           \
+          $(INCLUDE_DIR)/msgtypes.h     \
+          $(INCLUDE_DIR)/shorttypes.h
+
+# Disable all built-in rules.
+.SUFFIXES:
+
+# Targets which are executed even when identically named file is present.
+.PHONY: all, clean
+
+all: ulink_firmware.ihx
+       $(SIZE) ulink_firmware.ihx
+
+ulink_firmware.ihx: $(OBJECTS)
+       $(CC) -mmcs51 $(LDFLAGS) -o $@ $^
+
+# Rebuild every C module (there are only 5 of them) if any header changes.
+%.rel: $(SRC_DIR)/%.c $(HEADERS)
+       $(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
+
+%.rel: $(SRC_DIR)/%.a51
+       $(AS) -lsgo $@ $<
+
+clean:
+       rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lnk *.map *.mem
+
+hex: ulink_firmware.ihx
+       $(PACKIHX) ulink_firmware.ihx > ulink_firmware.hex
diff --git a/src/jtag/drivers/OpenULINK/README b/src/jtag/drivers/OpenULINK/README
new file mode 100644 (file)
index 0000000..445d770
--- /dev/null
@@ -0,0 +1,34 @@
+This is the OpenULINK firmware for the Keil ULINK JTAG adapter.
+
+The main components of the Keil ULINK adapter are:
+- Cypress EZ-USB microcontroller: enhanced 8051 CPU + USB core (1.1 Full-Speed)
+- SRAM memory chip
+- Level shifters to support different JTAG signal voltage levels
+- Pin headers for various JTAG pin assignments
+
+This firmware can only be run on the ORIGINAL Keil ULINK adapter, not on the
+newer ULINK2, ULINK-ME or ULINK-PRO, as these adapters are based on different
+hardware.
+
+To compile the firmware, the SDCC compiler package is required. Most Linux
+distributions include SDCC in their official package repositories. The SDCC
+source code can be found at http://sdcc.sourceforge.net/
+Simply type "make hex" in the OpenULINK directory to compile the firmware.
+"make clean" will remove all generated files except the Intel HEX file required
+for downloading the firmware to the ULINK adapter.
+
+Note that the EZ-USB microcontroller does not have on-chip flash, nor does the
+Keil ULINK include on-board memory to store the firmware program of the EZ-USB.
+Instead, upon initial connection of the ULINK adapter to the host PC via USB,
+the EZ-USB core has enough intelligence to act as a stand-alone USB device,
+responding to USB control requests and allowing firmware download via a special
+VENDOR-type control request. Then, the EZ-USB microcontroller simulates a
+disconnect and re-connect to the USB bus. It may take up to two seconds for the
+host to recognize the newly connected device before OpenOCD can proceed to
+execute JTAG commands. This delay is only visible when OpenOCD first uses a
+blank (unconfigured) ULINK device.
+
+Once the user disconnects the ULINK adapter, all its memory contents are lost
+and the firmware download process has to be executed again. This also maintains
+compatibility with the original Keil uVision IDE, which will happily download
+its own firmware image to a blank ULINK adapter.
diff --git a/src/jtag/drivers/OpenULINK/include/common.h b/src/jtag/drivers/OpenULINK/include/common.h
new file mode 100644 (file)
index 0000000..f4c966c
--- /dev/null
@@ -0,0 +1,26 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __COMMON_H
+#define __COMMON_H
+
+#define DIV_ROUND_UP(m, n)  (((m) + (n) - 1) / (n))
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/delay.h b/src/jtag/drivers/OpenULINK/include/delay.h
new file mode 100644 (file)
index 0000000..3dfaf35
--- /dev/null
@@ -0,0 +1,34 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __DELAY_H
+#define __DELAY_H
+
+#include "shorttypes.h"
+
+#define NOP  {__asm nop __endasm;}
+
+void delay_5us(void);
+void delay_1ms(void);
+
+void delay_us(u16 delay);
+void delay_ms(u16 delay);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/io.h b/src/jtag/drivers/OpenULINK/include/io.h
new file mode 100644 (file)
index 0000000..f7119b9
--- /dev/null
@@ -0,0 +1,125 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __IO_H
+#define __IO_H
+
+#include "reg_ezusb.h"
+
+/***************************************************************************
+ *  JTAG Signals:                                                          *
+ ***************************************************************************
+ * TMS ....... Test Mode Select                                            *
+ * TCK ....... Test Clock                                                  *
+ * TDI ....... Test Data Input  (from device point of view, not JTAG       *
+ *             adapter point of view!)                                     *
+ * TDO ....... Test Data Output (from device point of view, not JTAG       *
+ *             adapter point of view!)                                     *
+ * TRST ...... Test Reset: Used to reset the TAP Finite State Machine      *
+ *             into the Test Logic Reset state                             *
+ * RTCK ...... Return Test Clock                                           *
+ * OCDSE ..... Enable/Disable OCDS interface (Infineon specific) - shared  *
+ *             with /JEN                                                   *
+ * TRAP ...... Trap Condition (Infineon specific) - shared with TSTAT      *
+ * BRKIN ..... Hardware Break-In (Infineon specific)                       *
+ * BRKOUT .... Hardware Break-Out (Infineon specific)                      *
+ * /JEN ...... JTAG-Enable (STMicroelectronics specific) - shared          *
+ *             with OCDSE                                                  *
+ * TSTAT ..... JTAG ISP Status (STMicroelectronics specific) - shared      *
+ *             with TRAP                                                   *
+ * RESET ..... Chip Reset (STMicroelectronics specific)                    *
+ * /TERR ..... JTAG ISP Error (STMicroelectronics specific) - shared       *
+ *             with BRKOUT                                                 *
+ ***************************************************************************/
+
+/* PORT A */
+#define PIN_U_OE      OUTA0
+// PA1 Not Connected
+#define PIN_OE        OUTA2
+// PA3 Not Connected
+#define PIN_RUN_LED   OUTA4
+#define PIN_TDO       PINA5
+#define PIN_BRKOUT    PINA6
+#define PIN_COM_LED   OUTA7
+
+
+/* PORT B */
+#define PIN_TDI       OUTB0
+#define PIN_TMS       OUTB1
+#define PIN_TCK       OUTB2
+#define PIN_TRST      OUTB3
+#define PIN_BRKIN     OUTB4
+#define PIN_RESET     OUTB5
+#define PIN_OCDSE     OUTB6
+#define PIN_TRAP      PINB7
+
+/* JTAG Signals with direction 'OUT' on port B */
+#define MASK_PORTB_DIRECTION_OUT (PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET | PIN_OCDSE)
+
+/* PORT C */
+#define PIN_RXD0      PINC0
+#define PIN_TXD0      OUTC1
+#define PIN_RESET_2   PINC2
+// PC3 Not Connected
+// PC4 Not Connected
+#define PIN_RTCK      PINC5
+#define PIN_WR        OUTC6
+// PC7 Not Connected
+
+/* LED Macros */
+#define SET_RUN_LED()     OUTA &= ~PIN_RUN_LED
+#define CLEAR_RUN_LED()   OUTA |=  PIN_RUN_LED
+
+#define SET_COM_LED()     OUTA &= ~PIN_COM_LED
+#define CLEAR_COM_LED()   OUTA |=  PIN_COM_LED
+
+/* JTAG Pin Macros */
+#define GET_TMS()         (PINSB & PIN_TMS)
+#define GET_TCK()         (PINSB & PIN_TCK)
+
+#define GET_TDO()         (PINSA & PIN_TDO)
+#define GET_BRKOUT()      (PINSA & PIN_BRKOUT)
+#define GET_TRAP()        (PINSB & PIN_TRAP)
+#define GET_RTCK()        (PINSC & PIN_RTCK)
+
+#define SET_TMS_HIGH()    OUTB |=  PIN_TMS
+#define SET_TMS_LOW()     OUTB &= ~PIN_TMS
+
+#define SET_TCK_HIGH()    OUTB |=  PIN_TCK
+#define SET_TCK_LOW()     OUTB &= ~PIN_TCK
+
+#define SET_TDI_HIGH()    OUTB |=  PIN_TDI
+#define SET_TDI_LOW()     OUTB &= ~PIN_TDI
+
+/* TRST and RESET are low-active and inverted by hardware. SET_HIGH de-asserts
+ * the signal (enabling reset), SET_LOW asserts the signal (disabling reset) */
+#define SET_TRST_HIGH()   OUTB |=  PIN_TRST
+#define SET_TRST_LOW()    OUTB &= ~PIN_TRST
+
+#define SET_RESET_HIGH()  OUTB |=  PIN_RESET
+#define SET_RESET_LOW()   OUTB &= ~PIN_RESET
+
+#define SET_OCDSE_HIGH()  OUTB |=  PIN_OCDSE
+#define SET_OCDSE_LOW()   OUTB &= ~PIN_OCDSE
+
+#define SET_BRKIN_HIGH()  OUTB |=  PIN_BRKIN
+#define SET_BRKIN_LOW()   OUTB &= ~PIN_BRKIN
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/jtag.h b/src/jtag/drivers/OpenULINK/include/jtag.h
new file mode 100644 (file)
index 0000000..93ecfb0
--- /dev/null
@@ -0,0 +1,46 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __JTAG_H
+#define __JTAG_H
+
+#include "shorttypes.h"
+
+#define NOP {__asm nop __endasm;}
+
+void jtag_scan_in(u8 out_offset, u8 in_offset);
+void jtag_scan_out(u8 out_offset);
+void jtag_scan_io(u8 out_offset, u8 in_offset);
+
+void jtag_slow_scan_in(u8 scan_size_bytes, u8 tdo_index, u8 scan_options);
+void jtag_slow_scan_out(u8 scan_size_bytes, u8 tdi_index, u8 scan_options);
+void jtag_slow_scan_io(u8 scan_size_bytes, u8 tdi_index, u8 tdo_index,
+    u8 scan_options);
+
+void jtag_clock_tck(u16 count);
+void jtag_clock_tms(u8 count, u8 sequence);
+void jtag_slow_clock_tms(u8 count, u8 sequence);
+
+u16  jtag_get_signals(void);
+void jtag_set_signals(u8 low, u8 high);
+
+void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/main.h b/src/jtag/drivers/OpenULINK/include/main.h
new file mode 100644 (file)
index 0000000..08d748c
--- /dev/null
@@ -0,0 +1,26 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __MAIN_H
+#define __MAIN_H
+
+void io_init(void);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/msgtypes.h b/src/jtag/drivers/OpenULINK/include/msgtypes.h
new file mode 100644 (file)
index 0000000..e3afb67
--- /dev/null
@@ -0,0 +1,187 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+/**
+ * @file Definition of the commands supported by the OpenULINK firmware.
+ *
+ * Basically, two types of commands can be distinguished:
+ *  - Commands with fixed payload size
+ *  - Commands with variable payload size
+ *
+ * SCAN commands (in all variations) carry payloads of variable size, all
+ * other commands carry payloads of fixed size.
+ *
+ * In the case of SCAN commands, the payload size (n) is calculated by
+ * dividing the scan_size_bits variable by 8, rounding up the result.
+ *
+ * Offset zero always contains the command ID.
+ *
+ ****************************************************************************
+ * CMD_SCAN_IN, CMD_SLOW_SCAN_IN:                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0..n: TDO data                                                    *
+ ****************************************************************************
+ * CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT:                                         *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ * offset 6..x: TDI data                                                    *
+ ****************************************************************************
+ * CMD_SCAN_IO, CMD_SLOW_SCAN_IO:                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ * offset 6..x: TDI data                                                    *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0..n: TDO data                                                    *
+ ****************************************************************************
+ * CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS:                                       *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: tms_count                                                      *
+ * offset 2: tms_sequence                                                   *
+ ****************************************************************************
+ * CMD_CLOCK_TCK:                                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of tck_count                                          *
+ * offset 2: high byte of tck_count                                         *
+ ****************************************************************************
+ * CMD_CLOCK_SLEEP_US:                                                      *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of sleep_us                                           *
+ * offset 2: high byte of sleep_us                                          *
+ ****************************************************************************
+ * CMD_CLOCK_SLEEP_MS:                                                      *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of sleep_ms                                           *
+ * offset 2: high byte of sleep_ms                                          *
+ ****************************************************************************
+ * CMD_GET_SIGNALS:                                                         *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0: current state of input signals                                 *
+ * offset 1: current state of output signals                                *
+ ****************************************************************************
+ * CMD_SET_SIGNALS:                                                         *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: signals that should be de-asserted                             *
+ * offset 2: signals that should be asserted                                *
+ ****************************************************************************
+ * CMD_CONFIGURE_TCK_FREQ:                                                  *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: delay value for scan functions                                 *
+ * offset 2: delay value for clock_tck function                             *
+ * offset 3: delay value for clock_tms function                             *
+ ****************************************************************************
+ * CMD_SET_LEDS:                                                            *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: LED states:                                                    *
+ *           Bit 0: turn COM LED on                                         *
+ *           Bit 1: turn RUN LED on                                         *
+ *           Bit 2: turn COM LED off                                        *
+ *           Bit 3: turn RUN LED off                                        *
+ *           Bits 7..4: Reserved                                            *
+ ****************************************************************************
+ * CMD_TEST:                                                                *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: unused dummy value                                             *
+ ****************************************************************************
+ */
+
+#ifndef __MSGTYPES_H
+#define __MSGTYPES_H
+
+/*
+ * Command IDs:
+ *
+ * Bits 7..6: Reserved, should always be zero
+ * Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
+ *            the IDs 0x00..0x1F are commands with variable payload size,
+ *            the IDs 0x20..0x3F are commands with fixed payload size.
+ */
+
+#define CMD_ID_MASK             0x3F
+
+/* Commands with variable payload size */
+#define CMD_SCAN_IN             0x00
+#define CMD_SLOW_SCAN_IN        0x01
+#define CMD_SCAN_OUT            0x02
+#define CMD_SLOW_SCAN_OUT       0x03
+#define CMD_SCAN_IO             0x04
+#define CMD_SLOW_SCAN_IO        0x05
+
+/* Commands with fixed payload size */
+#define CMD_CLOCK_TMS           0x20
+#define CMD_SLOW_CLOCK_TMS      0x21
+#define CMD_CLOCK_TCK           0x22
+#define CMD_SLEEP_US            0x23
+#define CMD_SLEEP_MS            0x24
+#define CMD_GET_SIGNALS         0x25
+#define CMD_SET_SIGNALS         0x26
+#define CMD_CONFIGURE_TCK_FREQ  0x27
+#define CMD_SET_LEDS            0x28
+#define CMD_TEST                0x29
+
+/* JTAG signal definition for jtag_get_signals() -- Input signals! */
+#define SIGNAL_TDO      (1<<0)
+#define SIGNAL_BRKOUT   (1<<1)
+#define SIGNAL_TRAP     (1<<2)
+#define SIGNAL_RTCK     (1<<3)
+
+/* JTAG signal definition for jtag_get_signals() -- Output signals! */
+#define SIGNAL_TDI      (1<<0)
+#define SIGNAL_TMS      (1<<1)
+#define SIGNAL_TCK      (1<<2)
+#define SIGNAL_TRST     (1<<3)
+#define SIGNAL_BRKIN    (1<<4)
+#define SIGNAL_RESET    (1<<5)
+#define SIGNAL_OCDSE    (1<<6)
+
+/* LED definitions for CMD_SET_LEDS and CMD_CLEAR_LEDS commands */
+#define COM_LED_ON      (1<<0)
+#define RUN_LED_ON      (1<<1)
+#define COM_LED_OFF     (1<<2)
+#define RUN_LED_OFF     (1<<3)
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/protocol.h b/src/jtag/drivers/OpenULINK/include/protocol.h
new file mode 100644 (file)
index 0000000..2129fc8
--- /dev/null
@@ -0,0 +1,33 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __PROTOCOL_H
+#define __PROTOCOL_H
+
+#include "shorttypes.h"
+#include "common.h"
+#include <stdbool.h>
+
+void execute_set_led_command(void);
+
+bool execute_command(void);
+void command_loop(void);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/reg_ezusb.h b/src/jtag/drivers/OpenULINK/include/reg_ezusb.h
new file mode 100644 (file)
index 0000000..26ee018
--- /dev/null
@@ -0,0 +1,742 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef REG_EZUSB_H
+#define REG_EZUSB_H
+
+/**
+ * @file All information in this file was taken from the EZ-USB Technical
+ * Reference Manual, Cypress Semiconductor, 3901 North First Street
+ * San Jose, CA 95134 (www.cypress.com).
+ *
+ * The EZ-USB Technical Reference Manual is called "EZ-USB TRM" hereafter.
+ *
+ * The following bit name  definitions differ from those in the EZ-USB TRM:
+ * - All lowercase characters in the EZ-USB TRM bit names have been converted
+ *   to capitals (e. g. "WakeSRC" converted to "WAKESRC").
+ * - CPUCS:  8051RES is named "RES8051".
+ * - ISOCTL: Two MBZ ("Must Be Zero") bits are named "MBZ0" and "MBZ1".
+ * - I2CS: STOP and START bits are preceded by "I2C_"
+ * - INxCS, OUTxCS: the busy and stall bits are named "EPBSY" and "EPSTALL".
+ * - TOGCTL: EZ-USB TRM bit names are preceded by "TOG_".
+ */
+
+/* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */
+#include <mcs51/compiler.h>
+
+/* Bit vectors */
+#define bmBit0      0x01
+#define bmBit1      0x02
+#define bmBit2      0x04
+#define bmBit3      0x08
+#define bmBit4      0x10
+#define bmBit5      0x20
+#define bmBit6      0x40
+#define bmBit7      0x80
+
+/***************************************************************************/
+/************************ Special Function Registers ***********************/
+/***************************************************************************/
+
+/* See EZ-USB TRM, pp. A-9 - A-10 */
+
+SFR(SP,             0x81);
+SFR(DPL0,           0x82);
+SFR(DPH0,           0x83);
+SFR(DPL1,           0x84);
+SFR(DPL2,           0x85);
+
+SFR(DPS,            0x86);
+  #define SEL       bmBit0
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '0'
+  // Bit 4 read-only, always reads '0'
+  // Bit 5 read-only, always reads '0'
+  // Bit 6 read-only, always reads '0'
+  // Bit 7 read-only, always reads '0'
+
+SFR(PCON,           0x87);
+  #define IDLE      bmBit0
+  #define STOP      bmBit1
+  #define GF0       bmBit2
+  #define GF1       bmBit3
+  // Bit 4 read-only, always reads '1'
+  // Bit 5 read-only, always reads '1'
+  // Bit 6 unused
+  #define SMOD0     bmBit7
+
+SFR(TCON,           0x88);
+  SBIT(IT0,         0x88, 0);
+  SBIT(IE0,         0x88, 1);
+  SBIT(IT1,         0x88, 2);
+  SBIT(IE1,         0x88, 3);
+  SBIT(TR0,         0x88, 4);
+  SBIT(TF0,         0x88, 5);
+  SBIT(TR1,         0x88, 6);
+  SBIT(TF1,         0x88, 7);
+
+SFR(TMOD,           0x89);
+/* Some bits in this register share the same name in the EZ-USB TRM. Therefore,
+ * we add a '0'/'1' to distinguish them */
+  #define M00       bmBit0
+  #define M01       bmBit1
+  #define CT0       bmBit2
+  #define GATE0     bmBit3
+  #define M10       bmBit4
+  #define M11       bmBit5
+  #define CT1       bmBit6
+  #define GATE1     bmBit7
+
+SFR(TL0,            0x8A);
+SFR(TL1,            0x8B);
+SFR(TH0,            0x8C);
+SFR(TH1,            0x8D);
+
+SFR(CKCON,          0x8E);
+  #define MD0       bmBit0
+  #define MD1       bmBit1
+  #define MD2       bmBit2
+  #define T0M       bmBit3
+  #define T1M       bmBit4
+  #define T2M       bmBit5
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFR(SPC_FNC,        0x8D);
+  #define bmWRS     bmBit0
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '0'
+  // Bit 4 read-only, always reads '0'
+  // Bit 5 read-only, always reads '0'
+  // Bit 6 read-only, always reads '0'
+  // Bit 7 read-only, always reads '0'
+
+SFR(EXIF,           0x91);
+  // Bit 0 read-only, always reads '0'
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '1'
+  #define USBINT    bmBit4
+  #define I2CINT    bmBit5
+  #define IE4       bmBit6
+  #define IE5       bmBit7
+
+/* Definition of the _XPAGE register, according to SDCC Compiler User Guide,
+ * Version 3.0.1, Chapter 4, p. 61. Also see EZ-USB TRM, p. 2-4. */
+SFR(MPAGE,          0x92);
+SFR(_XPAGE,         0x92);
+
+SFR(SCON0,          0x98);
+  SBIT(RI_0,        0x98, 0);
+  SBIT(TI_0,        0x98, 1);
+  SBIT(RB8_0,       0x98, 2);
+  SBIT(TB8_0,       0x98, 3);
+  SBIT(REN_0,       0x98, 4);
+  SBIT(SM2_0,       0x98, 5);
+  SBIT(SM1_0,       0x98, 6);
+  SBIT(SM0_0,       0x98, 7);
+
+SFR(SBUF0,          0x99);
+
+SFR(IE,             0xA8);
+  SBIT(EX0,         0xA8, 0);
+  SBIT(ET0,         0xA8, 1);
+  SBIT(EX1,         0xA8, 2);
+  SBIT(ET1,         0xA8, 3);
+  SBIT(ES0,         0xA8, 4);
+  SBIT(ET2,         0xA8, 5);
+  SBIT(ES1,         0xA8, 6);
+  SBIT(EA,          0xA8, 7);
+
+SFR(IP,             0xB8);
+  SBIT(PX0,         0xB8, 0);
+  SBIT(PT0,         0xB8, 1);
+  SBIT(PX1,         0xB8, 2);
+  SBIT(PT1,         0xB8, 3);
+  SBIT(PS0,         0xB8, 4);
+  SBIT(PT2,         0xB8, 5);
+  SBIT(PS1,         0xB8, 6);
+  // Bit 7 read-only, always reads '1'
+
+SFR(SCON1,          0xC0);
+  SBIT(RI_1,        0xC0, 0);
+  SBIT(TI_1,        0xC0, 1);
+  SBIT(RB8_1,       0xC0, 2);
+  SBIT(TB8_1,       0xC0, 3);
+  SBIT(REN_1,       0xC0, 4);
+  SBIT(SM2_1,       0xC0, 5);
+  SBIT(SM1_1,       0xC0, 6);
+  SBIT(SM0_1,       0xC0, 7);
+
+SFR(SBUF1,          0xC1);
+
+SFR(T2CON,          0xC8);
+  SBIT(CPRL2,       0xC8, 0);
+  SBIT(CT2,         0xC8, 1);
+  SBIT(TR2,         0xC8, 2);
+  SBIT(EXEN2,       0xC8, 3);
+  SBIT(TCLK,        0xC8, 4);
+  SBIT(RCLK,        0xC8, 5);
+  SBIT(EXF2,        0xC8, 6);
+  SBIT(TF2,         0xC8, 7);
+
+SFR(RCAP2L,         0xCA);
+SFR(RCAP2H,         0xCB);
+SFR(TL2,            0xCC);
+SFR(TH2,            0xCD);
+
+SFR(PSW,            0xD0);
+  SBIT(P,           0xD0, 0);
+  SBIT(F1,          0xD0, 1);
+  SBIT(OV,          0xD0, 2);
+  SBIT(RS0,         0xD0, 3);
+  SBIT(RS1,         0xD0, 4);
+  SBIT(F0,          0xD0, 5);
+  SBIT(AC,          0xD0, 6);
+  SBIT(CY,          0xD0, 7);
+
+SFR(EICON,          0xD8);
+  // Bit 0 read-only, always reads '0'
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  SBIT(INT6,        0xD8, 3);
+  SBIT(RESI,        0xD8, 4);
+  SBIT(ERESI,       0xD8, 5);
+  // Bit 6 read-only, always reads '1'
+  SBIT(SMOD1,       0xD8, 7);
+
+SFR(ACC,            0xE0);
+
+SFR(EIE,            0xE8);
+  SBIT(EUSB,        0xE8, 0);
+  SBIT(EI2C,        0xE8, 1);
+  SBIT(EX4,         0xE8, 2);
+  SBIT(EX5,         0xE8, 3);
+  SBIT(EWDI,        0xE8, 4);
+  // Bit 5 read-only, always reads '1'
+  // Bit 6 read-only, always reads '1'
+  // Bit 7 read-only, always reads '1'
+
+SFR(B,              0xF0);
+
+SFR(EIP,            0xF8);
+  SBIT(PUSB,        0xF8, 0);
+  SBIT(PI2C,        0xF8, 1);
+  SBIT(PX4,         0xF8, 2);
+  SBIT(PX5,         0xF8, 3);
+  SBIT(PX6,         0xF8, 4);
+  // Bit 5 read-only, always reads '1'
+  // Bit 6 read-only, always reads '1'
+  // Bit 7 read-only, always reads '1'
+
+/***************************************************************************/
+/***************************** XDATA Registers *****************************/
+/***************************************************************************/
+
+/************************ Endpoint 0-7 Data Buffers ************************/
+SFRX(OUT7BUF[64],   0x7B40);
+SFRX(IN7BUF[64],    0x7B80);
+SFRX(OUT6BUF[64],   0x7BC0);
+SFRX(IN6BUF[64],    0x7C00);
+SFRX(OUT5BUF[64],   0x7C40);
+SFRX(IN5BUF[64],    0x7C80);
+SFRX(OUT4BUF[64],   0x7CC0);
+SFRX(IN4BUF[64],    0x7D00);
+SFRX(OUT3BUF[64],   0x7D40);
+SFRX(IN3BUF[64],    0x7D80);
+SFRX(OUT2BUF[64],   0x7DC0);
+SFRX(IN2BUF[64],    0x7E00);
+SFRX(OUT1BUF[64],   0x7E40);
+SFRX(IN1BUF[64],    0x7E80);
+SFRX(OUT0BUF[64],   0x7EC0);
+SFRX(IN0BUF[64],    0x7F00);
+// 0x7F40 - 0x7F5F reserved
+
+/**************************** Isochronous Data *****************************/
+SFRX(OUT8DATA,      0x7F60);
+SFRX(OUT9DATA,      0x7F61);
+SFRX(OUT10DATA,     0x7F62);
+SFRX(OUT11DATA,     0x7F63);
+SFRX(OUT12DATA,     0x7F64);
+SFRX(OUT13DATA,     0x7F65);
+SFRX(OUT14DATA,     0x7F66);
+SFRX(OUT15DATA,     0x7F67);
+
+SFRX(IN8DATA,       0x7F68);
+SFRX(IN9DATA,       0x7F69);
+SFRX(IN10DATA,      0x7F6A);
+SFRX(IN11DATA,      0x7F6B);
+SFRX(IN12DATA,      0x7F6C);
+SFRX(IN13DATA,      0x7F6D);
+SFRX(IN14DATA,      0x7F6E);
+SFRX(IN15DATA,      0x7F6F);
+
+/************************* Isochronous Byte Counts *************************/
+SFRX(OUT8BCH,       0x7F70);
+SFRX(OUT8BCL,       0x7F71);
+SFRX(OUT9BCH,       0x7F72);
+SFRX(OUT9BCL,       0x7F73);
+SFRX(OUT10BCH,      0x7F74);
+SFRX(OUT10BCL,      0x7F75);
+SFRX(OUT11BCH,      0x7F76);
+SFRX(OUT11BCL,      0x7F77);
+SFRX(OUT12BCH,      0x7F78);
+SFRX(OUT12BCL,      0x7F79);
+SFRX(OUT13BCH,      0x7F7A);
+SFRX(OUT13BCL,      0x7F7B);
+SFRX(OUT14BCH,      0x7F7C);
+SFRX(OUT14BCL,      0x7F7D);
+SFRX(OUT15BCH,      0x7F7E);
+SFRX(OUT16BCL,      0x7F7F);
+
+/****************************** CPU Registers ******************************/
+SFRX(CPUCS,         0x7F92);
+  #define RES8051   bmBit0
+  #define CLK24OE   bmBit1
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '0'
+  // Bits 4...7: Chip Revision
+
+SFRX(PORTACFG,      0x7F93);
+  #define T0OUT     bmBit0
+  #define T1OUT     bmBit1
+  #define OE        bmBit2
+  #define CS        bmBit3
+  #define FWR       bmBit4
+  #define FRD       bmBit5
+  #define RXD0OUT   bmBit6
+  #define RXD1OUT   bmBit7
+
+SFRX(PORTBCFG,      0x7F94);
+  #define T2        bmBit0
+  #define T2EX      bmBit1
+  #define RXD1      bmBit2
+  #define TXD1      bmBit3
+  #define INT4      bmBit4
+  #define INT5      bmBit5
+  #define INT6      bmBit6
+  #define T2OUT     bmBit7
+
+SFRX(PORTCCFG,      0x7F95);
+  #define RXD0      bmBit0
+  #define TXD0      bmBit1
+  #define INT0      bmBit2
+  #define INT1      bmBit3
+  #define T0        bmBit4
+  #define T1        bmBit5
+  #define WR        bmBit6
+  #define RD        bmBit7
+
+/*********************** Input-Output Port Registers ***********************/
+SFRX(OUTA,          0x7F96);
+  #define OUTA0     bmBit0
+  #define OUTA1     bmBit1
+  #define OUTA2     bmBit2
+  #define OUTA3     bmBit3
+  #define OUTA4     bmBit4
+  #define OUTA5     bmBit5
+  #define OUTA6     bmBit6
+  #define OUTA7     bmBit7
+
+SFRX(OUTB,          0x7F97);
+  #define OUTB0     bmBit0
+  #define OUTB1     bmBit1
+  #define OUTB2     bmBit2
+  #define OUTB3     bmBit3
+  #define OUTB4     bmBit4
+  #define OUTB5     bmBit5
+  #define OUTB6     bmBit6
+  #define OUTB7     bmBit7
+
+SFRX(OUTC,          0x7F98);
+  #define OUTC0     bmBit0
+  #define OUTC1     bmBit1
+  #define OUTC2     bmBit2
+  #define OUTC3     bmBit3
+  #define OUTC4     bmBit4
+  #define OUTC5     bmBit5
+  #define OUTC6     bmBit6
+  #define OUTC7     bmBit7
+
+SFRX(PINSA,         0x7F99);
+  #define PINA0     bmBit0
+  #define PINA1     bmBit1
+  #define PINA2     bmBit2
+  #define PINA3     bmBit3
+  #define PINA4     bmBit4
+  #define PINA5     bmBit5
+  #define PINA6     bmBit6
+  #define PINA7     bmBit7
+
+SFRX(PINSB,         0x7F9A);
+  #define PINB0     bmBit0
+  #define PINB1     bmBit1
+  #define PINB2     bmBit2
+  #define PINB3     bmBit3
+  #define PINB4     bmBit4
+  #define PINB5     bmBit5
+  #define PINB6     bmBit6
+  #define PINB7     bmBit7
+
+SFRX(PINSC,         0x7F9B);
+  #define PINC0     bmBit0
+  #define PINC1     bmBit1
+  #define PINC2     bmBit2
+  #define PINC3     bmBit3
+  #define PINC4     bmBit4
+  #define PINC5     bmBit5
+  #define PINC6     bmBit6
+  #define PINC7     bmBit7
+
+SFRX(OEA,           0x7F9C);
+  #define OEA0      bmBit0
+  #define OEA1      bmBit1
+  #define OEA2      bmBit2
+  #define OEA3      bmBit3
+  #define OEA4      bmBit4
+  #define OEA5      bmBit5
+  #define OEA6      bmBit6
+  #define OEA7      bmBit7
+
+SFRX(OEB,           0x7F9D);
+  #define OEB0      bmBit0
+  #define OEB1      bmBit1
+  #define OEB2      bmBit2
+  #define OEB3      bmBit3
+  #define OEB4      bmBit4
+  #define OEB5      bmBit5
+  #define OEB6      bmBit6
+  #define OEB7      bmBit7
+
+SFRX(OEC,           0x7F9E);
+  #define OEC0      bmBit0
+  #define OEC1      bmBit1
+  #define OEC2      bmBit2
+  #define OEC3      bmBit3
+  #define OEC4      bmBit4
+  #define OEC5      bmBit5
+  #define OEC6      bmBit6
+  #define OEC7      bmBit7
+
+// 0x7F9F reserved
+
+/****************** Isochronous Control/Status Registers *******************/
+SFRX(ISOERR,        0x7FA0);
+  #define ISO8ERR   bmBit0
+  #define ISO9ERR   bmBit1
+  #define ISO10ERR  bmBit2
+  #define ISO11ERR  bmBit3
+  #define ISO12ERR  bmBit4
+  #define ISO13ERR  bmBit5
+  #define ISO14ERR  bmBit6
+  #define ISO15ERR  bmBit7
+
+SFRX(ISOCTL,        0x7FA1);
+  #define ISODISAB  bmBit0
+  #define MBZ0      bmBit1
+  #define MBZ1      bmBit2
+  #define PPSTAT    bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(ZBCOUT,        0x7FA2);
+  #define EP8       bmBit0
+  #define EP9       bmBit1
+  #define EP10      bmBit2
+  #define EP11      bmBit3
+  #define EP12      bmBit4
+  #define EP13      bmBit5
+  #define EP14      bmBit6
+  #define EP15      bmBit7
+
+// 0x7FA3 reserved
+// 0x7FA4 reserved
+
+/****************************** I2C Registers ******************************/
+SFRX(I2CS,          0x7FA5);
+  #define DONE      bmBit0
+  #define ACK       bmBit1
+  #define BERR      bmBit2
+  #define ID0       bmBit3
+  #define ID1       bmBit4
+  #define LASTRD    bmBit5
+  #define I2C_STOP  bmBit6
+  #define I2C_START bmBit7
+
+SFRX(I2DAT,         0x7FA6);
+// 0x7FA7 reserved
+
+/******************************* Interrupts ********************************/
+SFRX(IVEC,          0x7FA8);
+  // Bit 0 read-only, always reads '0'
+  // Bit 1 read-only, always reads '0'
+  #define IV0       bmBit2
+  #define IV1       bmBit3
+  #define IV2       bmBit4
+  #define IV3       bmBit5
+  #define IV4       bmBit6
+  // Bit 7 read-only, always reads '0'
+
+SFRX(IN07IRQ,       0x7FA9);
+  #define IN0IR     bmBit0
+  #define IN1IR     bmBit1
+  #define IN2IR     bmBit2
+  #define IN3IR     bmBit3
+  #define IN4IR     bmBit4
+  #define IN5IR     bmBit5
+  #define IN6IR     bmBit6
+  #define IN7IR     bmBit7
+
+SFRX(OUT07IRQ,      0x7FAA);
+  #define OUT0IR    bmBit0
+  #define OUT1IR    bmBit1
+  #define OUT2IR    bmBit2
+  #define OUT3IR    bmBit3
+  #define OUT4IR    bmBit4
+  #define OUT5IR    bmBit5
+  #define OUT6IR    bmBit6
+  #define OUT7IR    bmBit7
+
+SFRX(USBIRQ,        0x7FAB);
+  #define SUDAVIR   bmBit0
+  #define SOFIR     bmBit1
+  #define SUTOKIR   bmBit2
+  #define SUSPIR    bmBit3
+  #define URESIR    bmBit4
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(IN07IEN,       0x7FAC);
+  #define IN0IEN    bmBit0
+  #define IN1IEN    bmBit1
+  #define IN2IEN    bmBit2
+  #define IN3IEN    bmBit3
+  #define IN4IEN    bmBit4
+  #define IN5IEN    bmBit5
+  #define IN6IEN    bmBit6
+  #define IN7IEN    bmBit7
+
+SFRX(OUT07IEN,      0x7FAD);
+  #define OUT0IEN   bmBit0
+  #define OUT1IEN   bmBit1
+  #define OUT2IEN   bmBit2
+  #define OUT3IEN   bmBit3
+  #define OUT4IEN   bmBit4
+  #define OUT5IEN   bmBit5
+  #define OUT6IEN   bmBit6
+  #define OUT7IEN   bmBit7
+
+SFRX(USBIEN,        0x7FAE);
+  #define SUDAVIE   bmBit0
+  #define SOFIE     bmBit1
+  #define SUTOKIE   bmBit2
+  #define SUSPIE    bmBit3
+  #define URESIE    bmBit4
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(USBBAV,        0x7FAF);
+  #define AVEN      bmBit0
+  #define BPEN      bmBit1
+  #define BPPULSE   bmBit2
+  #define BREAK     bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+// 0x7FB0 reserved
+// 0x7FB1 reserved
+SFRX(BPADDRH,       0x7FB2);
+SFRX(BPADDRL,       0x7FB3);
+
+/****************************** Endpoints 0-7 ******************************/
+SFRX(EP0CS,         0x7FB4);
+  #define EP0STALL  bmBit0
+  #define HSNAK     bmBit1
+  #define IN0BSY    bmBit2
+  #define OUT0BSY   bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(IN0BC,         0x7FB5);
+SFRX(IN1CS,         0x7FB6);
+SFRX(IN1BC,         0x7FB7);
+SFRX(IN2CS,         0x7FB8);
+SFRX(IN2BC,         0x7FB9);
+SFRX(IN3CS,         0x7FBA);
+SFRX(IN3BC,         0x7FBB);
+SFRX(IN4CS,         0x7FBC);
+SFRX(IN4BC,         0x7FBD);
+SFRX(IN5CS,         0x7FBE);
+SFRX(IN5BC,         0x7FBF);
+SFRX(IN6CS,         0x7FC0);
+SFRX(IN6BC,         0x7FC1);
+SFRX(IN7CS,         0x7FC2);
+SFRX(IN7BC,         0x7FC3);
+// 0x7FC4 reserved
+SFRX(OUT0BC,        0x7FC5);
+SFRX(OUT1CS,        0x7FC6);
+SFRX(OUT1BC,        0x7FC7);
+SFRX(OUT2CS,        0x7FC8);
+SFRX(OUT2BC,        0x7FC9);
+SFRX(OUT3CS,        0x7FCA);
+SFRX(OUT3BC,        0x7FCB);
+SFRX(OUT4CS,        0x7FCC);
+SFRX(OUT4BC,        0x7FCD);
+SFRX(OUT5CS,        0x7FCE);
+SFRX(OUT5BC,        0x7FCF);
+SFRX(OUT6CS,        0x7FD0);
+SFRX(OUT6BC,        0x7FD1);
+SFRX(OUT7CS,        0x7FD2);
+SFRX(OUT7BC,        0x7FD3);
+
+/* The INxSTALL, OUTxSTALL, INxBSY and OUTxBSY bits are the same for all
+ * INxCS/OUTxCS registers. For better readability, we define them only once */
+#define EPSTALL     bmBit0
+#define EPBSY       bmBit1
+
+/************************** Global USB Registers ***************************/
+SFRX(SUDPTRH,       0x7FD4);
+SFRX(SUDPTRL,       0x7FD5);
+
+SFRX(USBCS,         0x7FD6);
+  #define SIGRSUME  bmBit0
+  #define RENUM     bmBit1
+  #define DISCOE    bmBit2
+  #define DISCON    bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  #define WAKESRC   bmBit7
+
+SFRX(TOGCTL,        0x7FD7);
+  #define TOG_EP0   bmBit0
+  #define TOG_EP1   bmBit1
+  #define TOG_EP2   bmBit2
+  // Bit 3 is read-only, always reads '0'
+  #define TOG_IO    bmBit4
+  #define TOG_R     bmBit5
+  #define TOG_S     bmBit6
+  #define TOG_Q     bmBit7
+
+SFRX(USBFRAMEL,     0x7FD8);
+SFRX(USBFRAMEH,     0x7FD9);
+// 0x7FDA reserved
+SFRX(FNADDR,        0x7FDB);
+// 0x7FDC reserved
+
+SFRX(USBPAIR,       0x7FDD);
+  #define PR2IN     bmBit0
+  #define PR4IN     bmBit1
+  #define PR6IN     bmBit2
+  #define PR2OUT    bmBit3
+  #define PR4OUT    bmBit4
+  #define PR6OUT    bmBit5
+  // Bit 6 unused
+  #define ISOSEND0  bmBit7
+
+SFRX(IN07VAL,       0x7FDE);
+  // Bit 0 is read-only, always reads '1'
+  #define IN1VAL    bmBit1
+  #define IN2VAL    bmBit2
+  #define IN3VAL    bmBit3
+  #define IN4VAL    bmBit4
+  #define IN5VAL    bmBit5
+  #define IN6VAL    bmBit6
+  #define IN7VAL    bmBit7
+
+SFRX(OUT07VAL,      0x7FDF);
+  // Bit 0 is read-only, always reads '1'
+  #define OUT1VAL   bmBit1
+  #define OUT2VAL   bmBit2
+  #define OUT3VAL   bmBit3
+  #define OUT4VAL   bmBit4
+  #define OUT5VAL   bmBit5
+  #define OUT6VAL   bmBit6
+  #define OUT7VAL   bmBit7
+
+SFRX(INISOVAL,      0x7FE0);
+  #define IN8VAL    bmBit0
+  #define IN9VAL    bmBit1
+  #define IN10VAL   bmBit2
+  #define IN11VAL   bmBit3
+  #define IN12VAL   bmBit4
+  #define IN13VAL   bmBit5
+  #define IN14VAL   bmBit6
+  #define IN15VAL   bmBit7
+
+SFRX(OUTISOVAL,     0x7FE1);
+  #define OUT8VAL   bmBit0
+  #define OUT9VAL   bmBit1
+  #define OUT10VAL  bmBit2
+  #define OUT11VAL  bmBit3
+  #define OUT12VAL  bmBit4
+  #define OUT13VAL  bmBit5
+  #define OUT14VAL  bmBit6
+  #define OUT15VAL  bmBit7
+
+SFRX(FASTXFR,       0x7FE2);
+  #define WMOD0     bmBit0
+  #define WMOD1     bmBit1
+  #define WPOL      bmBit2
+  #define RMOD0     bmBit3
+  #define RMOD1     bmBit4
+  #define RPOL      bmBit5
+  #define FBLK      bmBit6
+  #define FISO      bmBit7
+
+SFRX(AUTOPTRH,      0x7FE3);
+SFRX(AUTOPTRL,      0x7FE4);
+SFRX(AUTODATA,      0x7FE5);
+// 0x7FE6 reserved
+// 0x7FE7 reserved
+
+/******************************* Setup Data ********************************/
+SFRX(SETUPDAT[8],   0x7FE8);
+
+/************************* Isochronous FIFO sizes **************************/
+SFRX(OUT8ADDR,      0x7FF0);
+SFRX(OUT9ADDR,      0x7FF1);
+SFRX(OUT10ADDR,     0x7FF2);
+SFRX(OUT11ADDR,     0x7FF3);
+SFRX(OUT12ADDR,     0x7FF4);
+SFRX(OUT13ADDR,     0x7FF5);
+SFRX(OUT14ADDR,     0x7FF6);
+SFRX(OUT15ADDR,     0x7FF7);
+
+SFRX(IN8ADDR,       0x7FF8);
+SFRX(IN9ADDR,       0x7FF9);
+SFRX(IN10ADDR,      0x7FFA);
+SFRX(IN11ADDR,      0x7FFB);
+SFRX(IN12ADDR,      0x7FFC);
+SFRX(IN13ADDR,      0x7FFD);
+SFRX(IN14ADDR,      0x7FFE);
+SFRX(IN15ADDR,      0x7FFF);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/shorttypes.h b/src/jtag/drivers/OpenULINK/include/shorttypes.h
new file mode 100644 (file)
index 0000000..60b37df
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __SHORTTYPES_H
+#define __SHORTTYPES_H
+
+#include <stdint.h>
+
+/**
+ * @file Integer type definitions for shorter code (easier to stay within 80
+ * character maximum line length).
+ */
+
+/* Signed integers */
+typedef int8_t   s8;
+typedef int16_t  s16;
+typedef int32_t  s32;
+
+/* Unsigned integers */
+typedef uint8_t  u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/usb.h b/src/jtag/drivers/OpenULINK/include/usb.h
new file mode 100644 (file)
index 0000000..f70819e
--- /dev/null
@@ -0,0 +1,267 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef __USB_H
+#define __USB_H
+
+#include "shorttypes.h"
+#include "reg_ezusb.h"
+
+#include <stdbool.h>
+
+#define NULL        (void*)0;
+
+/* High and Low byte of a word (u16) */
+#define HI8(word)   (u8)(((u16)word >> 8) & 0xff)
+#define LO8(word)   (u8)((u16)word & 0xff)
+
+/* Convenience functions */
+#define STALL_EP0()   EP0CS |= EP0STALL
+#define CLEAR_IRQ()   EXIF &= ~USBINT
+
+/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/
+
+/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */
+#define DESCRIPTOR_TYPE_DEVICE         0x01
+#define DESCRIPTOR_TYPE_CONFIGURATION  0x02
+#define DESCRIPTOR_TYPE_STRING         0x03
+#define DESCRIPTOR_TYPE_INTERFACE      0x04
+#define DESCRIPTOR_TYPE_ENDPOINT       0x05
+
+#define STR_DESCR(len,...) { len*2+2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } }
+
+/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< DEVICE Descriptor Type.
+  u16 bcdUSB;              ///< USB specification release number (BCD).
+  u8  bDeviceClass;        ///< Class code.
+  u8  bDeviceSubClass;     ///< Subclass code.
+  u8  bDeviceProtocol;     ///< Protocol code.
+  u8  bMaxPacketSize0;     ///< Maximum packet size for EP0 (8, 16, 32, 64).
+  u16 idVendor;            ///< USB Vendor ID.
+  u16 idProduct;           ///< USB Product ID.
+  u16 bcdDevice;           ///< Device Release Number (BCD).
+  u8  iManufacturer;       ///< Index of manufacturer string descriptor.
+  u8  iProduct;            ///< Index of product string descriptor.
+  u8  iSerialNumber;       ///< Index of string descriptor containing serial #.
+  u8  bNumConfigurations;  ///< Number of possible configurations.
+} usb_device_descriptor_t;
+
+/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< CONFIGURATION descriptor type.
+  u16 wTotalLength;        ///< Combined total length of all descriptors.
+  u8  bNumInterfaces;      ///< Number of interfaces in this configuration.
+  u8  bConfigurationValue; ///< Value used to select this configuration.
+  u8  iConfiguration;      ///< Index of configuration string descriptor.
+  u8  bmAttributes;        ///< Configuration characteristics.
+  u8  MaxPower;            ///< Maximum power consumption in 2 mA units.
+} usb_config_descriptor_t;
+
+/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< INTERFACE descriptor type.
+  u8  bInterfaceNumber;    ///< Interface number.
+  u8  bAlternateSetting;   ///< Value used to select alternate setting.
+  u8  bNumEndpoints;       ///< Number of endpoints used by this interface.
+  u8  bInterfaceClass;     ///< Class code.
+  u8  bInterfaceSubclass;  ///< Subclass code.
+  u8  bInterfaceProtocol;  ///< Protocol code.
+  u8  iInterface;          ///< Index of interface string descriptor.
+} usb_interface_descriptor_t;
+
+/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< ENDPOINT descriptor type.
+  u8  bEndpointAddress;    ///< Endpoint Address: USB 1.1 spec, table 9-10.
+  u8  bmAttributes;        ///< Endpoint Attributes: USB 1.1 spec, table 9-10.
+  u16 wMaxPacketSize;      ///< Maximum packet size for this endpoint.
+  u8  bInterval;           ///< Polling interval (in ms) for this endpoint.
+} usb_endpoint_descriptor_t;
+
+/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< STRING descriptor type.
+  u16 wLANGID[];           ///< LANGID codes.
+} usb_language_descriptor_t;
+
+/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< STRING descriptor type.
+  u16 bString[];           ///< UNICODE encoded string.
+} usb_string_descriptor_t;
+
+/********************** USB Control Endpoint 0 related *********************/
+
+/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */
+typedef struct {
+  u8  bmRequestType;       ///< Characteristics of a request.
+  u8  bRequest;            ///< Specific request.
+  u16 wValue;              ///< Field that varies according to request.
+  u16 wIndex;              ///< Field that varies according to request.
+  u16 wLength;             ///< Number of bytes to transfer in data stage.
+} setup_data_t;
+
+/* External declarations for variables that need to be accessed outside of
+ * the USB module */
+extern volatile bool EP2_out;
+extern volatile bool EP2_in;
+extern volatile __xdata __at 0x7FE8 setup_data_t setup_data;
+
+/*
+ * USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2
+ *
+ * Bit 7: Data transfer direction
+ *    0 = Host-to-device
+ *    1 = Device-to-host
+ * Bit 6...5: Type
+ *    0 = Standard
+ *    1 = Class
+ *    2 = Vendor
+ *    3 = Reserved
+ * Bit 4...0: Recipient
+ *    0 = Device
+ *    1 = Interface
+ *    2 = Endpoint
+ *    3 = Other
+ *    4...31 = Reserved
+ */
+
+#define USB_DIR_OUT             0x00
+#define USB_DIR_IN              0x80
+
+#define USB_REQ_TYPE_STANDARD   (0x00 << 5)
+#define USB_REQ_TYPE_CLASS      (0x01 << 5)
+#define USB_REQ_TYPE_VENDOR     (0x02 << 5)
+#define USB_REQ_TYPE_RESERVED   (0x03 << 5)
+
+#define USB_RECIP_DEVICE        0x00
+#define USB_RECIP_INTERFACE     0x01
+#define USB_RECIP_ENDPOINT      0x02
+#define USB_RECIP_OTHER         0x03
+
+/* bmRequestType for USB Standard Requests */
+
+/* Clear Interface Request */
+#define CF_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define CF_ENDPOINT  (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Get Configuration Request */
+#define GC_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Get Descriptor Request */
+#define GD_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Get Interface Request */
+#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+
+/* Get Status Request: See USB 1.1 spec, page 190 */
+#define GS_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define GS_ENDPOINT  (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Set Address Request is handled by EZ-USB core */
+
+/* Set Configuration Request */
+#define SC_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Set Descriptor Request */
+#define SD_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Set Feature Request */
+#define SF_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define SF_ENDPOINT  (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Set Interface Request */
+#define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+
+/* Synch Frame Request */
+#define SY_ENDPOINT  (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */
+#define GET_STATUS               0
+#define CLEAR_FEATURE            1
+// Value '2' is reserved for future use
+#define SET_FEATURE              3
+// Value '4' is reserved for future use
+#define SET_ADDRESS              5
+#define GET_DESCRIPTOR           6
+#define SET_DESCRIPTOR           7
+#define GET_CONFIGURATION        8
+#define SET_CONFIGURATION        9
+#define GET_INTERFACE           10
+#define SET_INTERFACE           11
+#define SYNCH_FRAME             12
+
+/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */
+#define DEVICE_REMOTE_WAKEUP     1
+#define ENDPOINT_HALT            0
+
+/************************** EZ-USB specific stuff **************************/
+
+/** USB Interrupts. See AN2131-TRM, page 9-4 for details */
+typedef enum {
+  SUDAV_ISR = 13,
+  SOF_ISR,
+  SUTOK_ISR,
+  SUSPEND_ISR,
+  USBRESET_ISR,
+  IBN_ISR,
+  EP0IN_ISR,
+  EP0OUT_ISR,
+  EP1IN_ISR,
+  EP1OUT_ISR,
+  EP2IN_ISR,
+  EP2OUT_ISR,
+  EP3IN_ISR,
+  EP3OUT_ISR,
+  EP4IN_ISR,
+  EP4OUT_ISR,
+  EP5IN_ISR,
+  EP5OUT_ISR,
+  EP6IN_ISR,
+  EP6OUT_ISR,
+  EP7IN_ISR,
+  EP7OUT_ISR
+} USB_ISR;
+
+/*************************** Function Prototypes ***************************/
+
+__xdata u8* usb_get_endpoint_cs_reg(u8 ep);
+void usb_reset_data_toggle(u8 ep);
+
+bool usb_handle_get_status(void);
+bool usb_handle_clear_feature(void);
+bool usb_handle_set_feature(void);
+bool usb_handle_get_descriptor(void);
+void usb_handle_set_interface(void);
+
+void usb_handle_setup_data(void);
+void usb_init(void);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 b/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51
new file mode 100644 (file)
index 0000000..6f774dd
--- /dev/null
@@ -0,0 +1,83 @@
+;--------------------------------------------------------------------------;
+;    Copyright (C) 2011 by Martin Schmoelzer                               ;
+;    <martin.schmoelzer@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.,                                       ;
+;    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             ;
+;--------------------------------------------------------------------------;
+
+.module JUMPTABLE
+.globl USB_AutoVector
+.globl USB_Jump_Table
+
+;--------------------------------------------------------------------------;
+; Interrupt Vectors                                                        ;
+;--------------------------------------------------------------------------;
+.area   USB_JV (ABS,OVR)   ; Absolute, Overlay
+.org    0x43               ; USB interrupt (INT2) jumps here
+USB_AutoVector = #. + 2
+    ljmp  USB_jump_table
+
+;--------------------------------------------------------------------------;
+; USB Jump Table                                                           ;
+;--------------------------------------------------------------------------;
+.area  USB_JT (ABS)        ; Absolute placement
+.org   0x1B00              ; Place jump table at 0x1B00
+
+USB_jump_table:            ; autovector jump table
+    ljmp  _sudav_isr       ; Setup Data Available
+    .db 0
+    ljmp  _sof_isr         ; Start of Frame
+    .db 0
+    ljmp  _sutok_isr       ; Setup Data Loading
+    .db 0
+    ljmp  _suspend_isr     ; Global Suspend
+    .db 0
+    ljmp  _usbreset_isr    ; USB Reset
+    .db 0
+    ljmp  _ibn_isr         ; IN Bulk NAK interrupt
+    .db 0
+    ljmp  _ep0in_isr       ; Endpoint 0 IN
+    .db 0
+    ljmp  _ep0out_isr      ; Endpoint 0 OUT
+    .db 0
+    ljmp  _ep1in_isr       ; Endpoint 1 IN
+    .db 0
+    ljmp  _ep1out_isr      ; Endpoint 1 OUT
+    .db 0
+    ljmp  _ep2in_isr       ; Endpoint 2 IN
+    .db 0
+    ljmp  _ep2out_isr      ; Endpoint 2 OUT
+    .db 0
+    ljmp  _ep3in_isr       ; Endpoint 3 IN
+    .db 0
+    ljmp  _ep3out_isr      ; Endpoint 3 OUT
+    .db 0
+    ljmp  _ep4in_isr       ; Endpoint 4 IN
+    .db 0
+    ljmp  _ep4out_isr      ; Endpoint 4 OUT
+    .db 0
+    ljmp  _ep5in_isr       ; Endpoint 5 IN
+    .db 0
+    ljmp  _ep5out_isr      ; Endpoint 5 OUT
+    .db 0
+    ljmp  _ep6in_isr       ; Endpoint 6 IN
+    .db 0
+    ljmp  _ep6out_isr      ; Endpoint 6 OUT
+    .db 0
+    ljmp  _ep7in_isr       ; Endpoint 7 IN
+    .db 0
+    ljmp  _ep7out_isr      ; Endpoint 7 OUT
+    .db 0
diff --git a/src/jtag/drivers/OpenULINK/src/delay.c b/src/jtag/drivers/OpenULINK/src/delay.c
new file mode 100644 (file)
index 0000000..5b7d0eb
--- /dev/null
@@ -0,0 +1,51 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "delay.h"
+
+void delay_5us(void)
+{
+  NOP;
+}
+
+void delay_1ms(void) {
+  u16 i;
+
+  for (i = 0; i < 598; i++);
+}
+
+void delay_us(u16 delay)
+{
+  u16 i;
+  u16 maxcount = (delay / 5);
+
+  for (i = 0; i < maxcount; i++) {
+    delay_5us();
+  }
+}
+
+void delay_ms(u16 delay)
+{
+  u16 i;
+
+  for (i = 0; i < delay; i++) {
+    delay_1ms();
+  }
+}
diff --git a/src/jtag/drivers/OpenULINK/src/jtag.c b/src/jtag/drivers/OpenULINK/src/jtag.c
new file mode 100644 (file)
index 0000000..cf126ed
--- /dev/null
@@ -0,0 +1,414 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "jtag.h"
+
+#include "io.h"
+#include "msgtypes.h"
+#include "common.h"
+
+#include <stdbool.h>
+
+/** Delay value for SCAN operations with less than maximum TCK frequency */
+u8 delay_scan = 0;
+
+/** Delay value for CLOCK_TCK operations */
+u8 delay_tck = 0;
+
+/** Delay value for CLOCK_TMS operations with less than maximum frequency */
+u8 delay_tms = 0;
+
+/**
+ * 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.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_in(u8 out_offset, u8 in_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdo_data, i, j;
+
+  u8 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 */
+      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;
+  }
+
+  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 change here */
+    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 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.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_out(u8 out_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdi_data, i, j;
+
+  u8 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 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.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_io(u8 out_offset, u8 in_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdi_data, tdo_data, i, j;
+
+  u8 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);
+  }
+}
+
+/**
+ * Generate TCK clock cycles.
+ *
+ * @param count number of TCK clock cyclces to generate.
+ */
+void jtag_clock_tck(u16 count)
+{
+  u16 i;
+  u8 j;
+
+  for ( i = 0; i < count; i++ ) {
+    SET_TCK_LOW();
+    for(j = 0; j < delay_tck; j++);
+
+    SET_TCK_HIGH();
+    for(j = 0; j < delay_tck; j++);
+  }
+}
+
+/**
+ * Perform TAP-FSM state transitions at maximum TCK frequency.
+ *
+ * @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(u8 count, u8 sequence)
+{
+  volatile u8 outb_buffer;
+  u8 i;
+
+  outb_buffer = OUTB & ~(PIN_TCK);
+
+  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.
+ *
+ * @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(u8 count, u8 sequence)
+{
+
+}
+
+/**
+ * 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 cotains the state
+ *  of the JTAG output signals.
+ */
+u16 jtag_get_signals(void)
+{
+  u8 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 ((u16)input_signal_state << 8) | ((u16)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(u8 low, u8 high)
+{
+  OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
+  OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
+}
+
+/**
+ * Configure TCK delay parameters.
+ *
+ * @param scan number of delay cycles in shift 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(u8 scan, u8 tck, u8 tms)
+{
+  delay_scan = scan;
+  delay_tck = tck;
+  delay_tms = tms;
+}
diff --git a/src/jtag/drivers/OpenULINK/src/main.c b/src/jtag/drivers/OpenULINK/src/main.c
new file mode 100644 (file)
index 0000000..3ea3fff
--- /dev/null
@@ -0,0 +1,92 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "main.h"
+
+#include "shorttypes.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;
+}
diff --git a/src/jtag/drivers/OpenULINK/src/protocol.c b/src/jtag/drivers/OpenULINK/src/protocol.c
new file mode 100644 (file)
index 0000000..05929d0
--- /dev/null
@@ -0,0 +1,212 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 u8 cmd_id_index;
+
+/** Number of data bytes already in EP2 Bulk-IN buffer */
+volatile u8 payload_index_in;
+
+/**
+ * Execute a SET_LEDS command.
+ */
+void execute_set_led_command(void)
+{
+  u8 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.
+ *
+ * @param index the index of the Bulk EP2-OUT data buffer at which the
+ *  command ID is stored.
+ * @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)
+{
+  u8 usb_out_bytecount, usb_in_bytecount;
+  u16 signal_state;
+  u16 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 = (u16)OUT2BUF[cmd_id_index + 1];
+    count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8;
+    jtag_clock_tck(count);
+    break;
+  case CMD_SLEEP_US:
+    usb_out_bytecount = 2;
+    count = (u16)OUT2BUF[cmd_id_index + 1];
+    count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8;
+    delay_us(count);
+    break;
+  case CMD_SLEEP_MS:
+    usb_out_bytecount = 2;
+    count = (u16)OUT2BUF[cmd_id_index + 1];
+    count |= ((u16)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_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;
+  }
+}
diff --git a/src/jtag/drivers/OpenULINK/src/usb.c b/src/jtag/drivers/OpenULINK/src/usb.c
new file mode 100644 (file)
index 0000000..b74b3a2
--- /dev/null
@@ -0,0 +1,543 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 = 0;
+volatile bool EP2_in  = 0;
+
+volatile __xdata __at 0x7FE8 setup_data_t 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
+
+/*
+ * Normally, we would initialize the descriptor structures in C99 style:
+ *
+ * __code usb_device_descriptor_t device_descriptor = {
+ *   .bLength = foo,
+ *   .bDescriptorType = bar,
+ *   .bcdUSB = 0xABCD,
+ *   ...
+ * };
+ *
+ * But SDCC currently does not support this, so we have to do it the
+ * old-fashioned way...
+ */
+
+__code usb_device_descriptor_t device_descriptor = {
+  /* .bLength = */            sizeof(usb_device_descriptor_t),
+  /* .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 usb_config_descriptor_t config_descriptor = {
+  /* .bLength = */             sizeof(usb_config_descriptor_t),
+  /* .bDescriptorType = */     DESCRIPTOR_TYPE_CONFIGURATION,
+  /* .wTotalLength = */        sizeof(usb_config_descriptor_t) +
+                               sizeof(usb_interface_descriptor_t) + 
+                               NUM_ENDPOINTS * sizeof(usb_endpoint_descriptor_t),
+  /* .bNumInterfaces = */      1,
+  /* .bConfigurationValue = */ 1,
+  /* .iConfiguration = */      4,     /* String describing this configuration */
+  /* .bmAttributes = */        0x80,  /* Only MSB set according to USB spec */
+  /* .MaxPower = */            50     /* 100 mA */
+};
+
+__code usb_interface_descriptor_t interface_descriptor00 = {
+  /* .bLength = */             sizeof(usb_interface_descriptor_t),
+  /* .bDescriptorType = */     DESCRIPTOR_TYPE_INTERFACE,
+  /* .bInterfaceNumber = */    0,
+  /* .bAlternateSetting = */   0,
+  /* .bNumEndpoints = */       NUM_ENDPOINTS,
+  /* .bInterfaceClass = */     0xFF,
+  /* .bInterfaceSubclass = */  0xFF,
+  /* .bInterfaceProtocol = */  0xFF,
+  /* .iInterface = */          0
+};
+
+__code usb_endpoint_descriptor_t Bulk_EP2_IN_Endpoint_Descriptor = {
+  /* .bLength = */             sizeof(usb_endpoint_descriptor_t),
+  /* .bDescriptorType = */     0x05,
+  /* .bEndpointAddress = */    2 | USB_DIR_IN,
+  /* .bmAttributes = */        0x02,
+  /* .wMaxPacketSize = */      64,
+  /* .bInterval = */           0
+};
+
+__code usb_endpoint_descriptor_t Bulk_EP2_OUT_Endpoint_Descriptor = {
+  /* .bLength = */             sizeof(usb_endpoint_descriptor_t),
+  /* .bDescriptorType = */     0x05,
+  /* .bEndpointAddress = */    2 | USB_DIR_OUT,
+  /* .bmAttributes = */        0x02,
+  /* .wMaxPacketSize = */      64,
+  /* .bInterval = */           0
+};
+
+__code usb_language_descriptor_t language_descriptor = {
+  /* .bLength =  */            4,
+  /* .bDescriptorType = */     DESCRIPTOR_TYPE_STRING,
+  /* .wLANGID = */             {0x0409 /* US English */}
+};
+
+__code usb_string_descriptor_t strManufacturer = STR_DESCR(9,'O','p','e','n','U','L','I','N','K');
+__code usb_string_descriptor_t strProduct      = STR_DESCR(9,'O','p','e','n','U','L','I','N','K');
+__code usb_string_descriptor_t strSerialNumber = STR_DESCR(6, '0','0','0','0','0','1');
+__code usb_string_descriptor_t strConfigDescr  = STR_DESCR(12, 'J','T','A','G',' ','A','d','a','p','t','e','r');
+
+/* Table containing pointers to string descriptors */
+__code usb_string_descriptor_t* __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 u8* usb_get_endpoint_cs_reg(u8 ep)
+{
+  /* Mask direction bit */
+  u8 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(u8 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.
+  */
+  u8 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)
+{
+  u8 *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 u8 *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 u8 *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 u8 descriptor_type;
+  __xdata u8 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;
+}
diff --git a/src/jtag/drivers/OpenULINK/ulink_firmware.hex b/src/jtag/drivers/OpenULINK/ulink_firmware.hex
new file mode 100644 (file)
index 0000000..9e74423
--- /dev/null
@@ -0,0 +1,251 @@
+:040000000200733255
+:01000B0032C2
+:0100130032BA
+:01001B0032B2
+:0100230032AA
+:01002B0032A2
+:01003300329A
+:01003B003292
+:01004300328A
+:01004B003282
+:01005300327A
+:01005B003272
+:01006300326A
+:03006B0002011F70
+:0300D90002006EB4
+:05006E0012011080FEEC
+:1000DC00907F937404F0907F9C7495F0907F96744D
+:1000EC0090F0907F94E4F0907F9D747FF0907F97D8
+:1000FC00E4F0907F957440F0907F9E7442F0907F76
+:10010C0098E4F0221200DC1204FCD2AF1207C89063
+:03011C00000022BE
+:0400CC00C200C201AB
+:10011F00C021C0E0C0F0C082C083C002C003C004D1
+:10012F00C005C006C007C000C001C0D075D00053C5
+:10013F0091EF120455907FAB7401F0907FB4E044BF
+:10014F0002F0D0D0D001D000D007D006D005D00417
+:10015F00D003D002D083D082D0F0D0E0D021323281
+:10016F003232323232323232C0E0C082C083D201F8
+:10017F005391EF907FA97404F0D083D082D0E032F6
+:10018F00C0E0C082C083D2005391EF907FAA740465
+:10019F00F0D083D082D0E032323232323232323249
+:1001AF003232AA82747F5AFB7407B50300500302E0
+:1001BF000269EB2B2B9001C8730201E00201E402EC
+:1001CF0001F702020A02021D02023002024302027A
+:1001DF0056907FB422EA30E7067BB67C7F80047BA3
+:1001EF00C67C7F8B828C8322EA30E7067BB87C7FCC
+:1001FF0080047BC87C7F8B828C8322EA30E7067B6E
+:10020F00BA7C7F80047BCA7C7F8B828C8322EA300E
+:10021F00E7067BBC7C7F80047BCC7C7F8B828C83CE
+:10022F0022EA30E7067BBE7C7F80047BCE7C7F8B0F
+:10023F00828C8322EA30E7067BC07C7F80047BD0F0
+:10024F007C7F8B828C8322EA30E7067AC27B7F80A9
+:10025F00047AD27B7F8A828B832290000022AA822B
+:10026F0074105AFB74075A4203907FD7EBF0742037
+:10027F004BF022907FE8E0FABA8002800ABA81023E
+:10028F008016BA825D8022907F00E4F0907F01F0AB
+:10029F00907FB57402F0804C907F00E4F0907F0166
+:1002AF00F0907FB57402F0803B907FECE0FAA3E012
+:1002BF008A821201B1AA82AB837C008A828B838CE3
+:1002CF00F0120D90FA30E008907F007401F0800575
+:1002DF00907F00E4F0907F01E4F0907FB57402F01E
+:1002EF008002C322D322907FE8E0FA6005BA02466B
+:1002FF00800A907FB4E0FA4401F0803A907FEAE000
+:10030F00FAA3E0FB4A7027907FECE0FAA3E08A8221
+:10031F001201B1AA82AB83EA4B7002C3228A828B8D
+:10032F0083E0FC5304FE8A828B83ECF08008907F7D
+:10033F00B4E0FA4401F0D322907FE8E0FA6005BA06
+:10034F0002468010907FEAE0FAA3E0FBBA0239BBC5
+:10035F000036D322907FEAE0FAA3E0FB4A702790A1
+:10036F007FECE0FAA3E08A821201B1AA82AB83EAA2
+:10037F004B7002C3228A828B83E0FC4304018A8282
+:10038F008B83ECF08002C322D322907FEAE0A3E0BC
+:10039F00FA907FEAE0FBA3E07C00BA0102800CBA7E
+:1003AF000202801DBA0302802E807B7AB07C0D90F2
+:1003BF007FD4ECF07AB07C0D7C00907FD5EAF08092
+:1003CF00677AC27C0D907FD4ECF07AC27C0D7C00F2
+:1003DF00907FD5EAF08051907FECE0FAA3E0FC4AE1
+:1003EF0070167AE27C0D907FD4ECF07AE27C0D7C73
+:1003FF0000907FD5EAF08030907FECE0FAA3E0FC2C
+:10040F00BA0921BC041E1BEB2BFA900E3693CAA31C
+:10041F0093FB8A048B05907FD4EDF07B00907FD502
+:10042F00EAF08004C322C322D32275828212026DA6
+:10043F0075820212026D907FB87402F0907FC8E44B
+:10044F00F0907FC9F022907FE9E0FA740CB50200BA
+:10045F00500122EA2A2A9004697302049002049E32
+:10046F000204AC0204B40204AC0204C10204CA02C6
+:10047F0004C20204D70204E70204E80204F80204EB
+:10048F00FB120282500122907FB4E04401F022124D
+:10049F0002F5500122907FB4E04401F022907FB426
+:1004AF00E04401F0221203474042907FB4E0440140
+:1004BF00F02222907FB4E04401F022120399402CE5
+:1004CF00907FB4E04401F022900DC7E493907F0039
+:1004DF00F0907FB57401F02222900DCDE493907FC0
+:1004EF0000F0907FB57401F02212043922907FDE64
+:1004FF007404F0907FDF7404F0907FE0E4F0907F5D
+:10050F00E1F0907FA17401F0907FAFE04401F09093
+:10051F007FAEE04401F0907FAD7404F0907FAC7437
+:10052F0004F0D2E8907FD6740AF09000C8120D3D07
+:07053F00907FD67406F02244
+:100DB00012011001FFFFFF4051C210270001010284
+:100DC000030109022000010104803209040000022D
+:100DD000FFFFFF00070582024000000705020240F6
+:100DE00000000403090414034F00700065006E0046
+:100DF00055004C0049004E004B0014034F0070009A
+:100E000065006E0055004C0049004E004B000E037B
+:100E10003000300030003000300031001A034A004A
+:100E20005400410047002000410064006100700050
+:0E0E3000740065007200E60DFA0D0E0E1C0E29
+:10054600E5080424C0F582E4347DF583E0FA30E161
+:1005560008907F96E0FB54EFF0EA30E008907F9633
+:10056600E0FB547FF0EA30E308907F96E0FB44100E
+:10057600F0EA30E208907F96E0FA4480F0227A00B2
+:10058600E50824C0F582E4347DF583E0FB603EBBDC
+:100596000202805FBB040302061CBB200302064363
+:1005A600BB2203020673BB23030206ACBB24030271
+:1005B60006E5BB250302071DBB260302074CBB2825
+:1005C6000302077BBB290302078A02078E7B05E528
+:1005D600080424C0F582E4347DF583E0FAE50804D6
+:1005E600F58285090DC002C003120805D003D002AA
+:1005F600020790E5080424C0F582E4347DF583E023
+:100606002405FBE50804F582C002C003120951D097
+:1006160003D002020790E5080424C0F582E4347D85
+:10062600F583E0FA2405FBE50804F582850917C081
+:1006360002C003120A83D003D0020207907B02E5B0
+:10064600080424C0F582E4347DF583E0FC740225B9
+:100656000824C0F582E4347DF583E0F5228C82C05F
+:1006660002C003120C5BD003D0020207907B02E5A6
+:10067600080424C0F582E4347DF583E0FC7D007433
+:1006860002250824C0F582E4347DF583E0FFE442C8
+:1006960004EF42058C828D83C002C003120C20D069
+:1006A60003D0020207907B02E5080424C0F582E429
+:1006B600347DF583E0FC7D007402250824C0F582B4
+:1006C600E4347DF583E0FFE44204EF42058C828D3D
+:1006D60083C002C003120D0AD003D0020207907B2A
+:1006E60002E5080424C0F582E4347DF583E0FC7D50
+:1006F600007402250824C0F582E4347DF583E0FF0A
+:10070600E44204EF42058C828D83C002C003120DC1
+:100716003DD003D00280737B007A02C002C0031270
+:100726000C95AC82AD83D003D00285098275837E99
+:100736008D06EEF0E509042400F582E4347EF583A7
+:100746007D00ECF080447B02E5080424C0F582E4D9
+:10075600347DF583E0FC7402250824C0F582E43478
+:100766007DF583E0F5228C82C002C003120CD8D03E
+:1007760003D00280157B01C002C003120546D003D8
+:10078600D00280067B0180027B00EA2509F509AAD2
+:10079600087C008B057E00ED2AFAEE3CFC0ABA00C6
+:1007A600010C907FC9E0FD7E00C3EA9DEC64808E5B
+:1007B600F063F08095F04002D322EB042508F5089B
+:1007C600C32275080075090010000280FB907F9611
+:1007D600E0FA547FF0C202200207120584920280DA
+:1007E600F6907F96E0FA4480F0E509600B907FB9B9
+:0F07F600E509F010010280FB907FC9E4F080C399
+:0900D000750A00750B00750C00A7
+:10080500E582FA24C0F582E4347DF583E0F50EEA4D
+:100815000424C0F582E4347DF583E0F50F74022AE3
+:10082500FD24C0F582E4347DF583E0C4540FFE5306
+:10083500060FED24C0F582E4347DF583E0FD740FE9
+:100845005DF51074032A24C0F582E4347DF583E058
+:10085500FF74042A24C0F582E4347DF583E0F511A4
+:10086500EE60078F228E82120C5B907F97E0FE531D
+:1008750006F87F0074044EF87900AD0E7B001DBDAF
+:10088500FF011B89027C00C3EA9DEC64808BF06349
+:10089500F08095F050357A007B00BB080050199028
+:1008A5007F97EEF0E8F0EAC313FA907F99E0FC3009
+:1008B500E5034302800B80E2E50D292400F582E47F
+:1008C500347EF583EAF009890780AF89077A00ABA2
+:1008D50010751200E512B50F00503EAD0F78001DE2
+:1008E500BDFF0118A9127C00E9B50511ECB5000D95
+:1008F500EB600A4306021BE511C313F511907F97C0
+:10090500EEF074044EF0EAC313FA907F99E0FC30E0
+:10091500E503430280051280BBAC0F7D007408C35C
+:100925009CFCE49DFD8CF005F0EA8002C313D5F034
+:10093500FBFAE50D2F2400F582E4347EF583EAF019
+:10094500EB60088511228B82020C5B22E582FA247A
+:10095500C0F582E4347DF583E0F513EA0424C0F59F
+:1009650082E4347DF583E0F51474022AFD24C0F594
+:1009750082E4347DF583E0C4540FFE53060FED2465
+:10098500C0F582E4347DF583E0FD740F5DF51574E3
+:10099500032A24C0F582E4347DF583E0FF74042A3C
+:1009A50024C0F582E4347DF583E0F516EE600B8F07
+:1009B500228E82C002120C5BD002907F97E0FE531C
+:1009C50006F97F00A9137D0019B9FF011D8F037872
+:1009D50000C3EB99E864808DF063F08095F05038A2
+:1009E500EA2F240524C0F582E4347DF583E0FB7D00
+:1009F50000BD0800501FEB30E0054306018003539E
+:100A050006FE907F97EEF0EBC313FB907F9774047F
+:100A15004EF00D80DC0F80ACEA2F240524C0F58252
+:100A2500E4347DF583E0FBAA157D00EDB514005097
+:100A350041EB30E00543060180035306FEAF147811
+:100A4500001FBFFF01188D017C00E9B50711ECB54A
+:100A5500000DEA600A4306021AE516C313F516905F
+:100A65007F97EEF0EBC313FB907F9774044EF00D68
+:100A750080B9EA60088516228A82020C5B22E5822B
+:100A8500F51824C0F582E4347DF583E0F519E51801
+:100A95000424C0F582E4347DF583E0F51A7402255B
+:100AA50018FD24C0F582E4347DF583E0C4540FFEBF
+:100AB50053060FED24C0F582E4347DF583E0FD7423
+:100AC5000F5DF51B7403251824C0F582E4347DF50C
+:100AD50083E0FF7404251824C0F582E4347DF58392
+:100AE500E0F51CEE60078F228E82120C5B907F97DB
+:100AF500E0FE5306F97F007900AD197B001DBDFFAF
+:100B0500011B89007A00C3E89DEA64808BF063F0DD
+:100B15008095F0505EE51829240524C0F582E4345B
+:100B25007DF583E0F51D7B007D00BD08005031E5B6
+:100B35001D30E00543060180035306FE907F97EEC6
+:100B4500F0E51DC313F51D907F9774044EF0EBC3BC
+:100B550013FB907F99E0F830E5034303800D80CACD
+:100B6500E517292400F582E4347EF583EBF0098945
+:100B75000780868907E51829240524C0F582E43411
+:100B85007DF583E0F51D7B00AD1B751E00E51EB5EB
+:100B95001A005054E51D30E0054306018003530655
+:100BA500FEA91A7C0019B9FF011CA81E7A00E8B538
+:100BB5000111EAB5040DED600A4306021DE51CC3EB
+:100BC50013F51C907F97EEF0E51DC313F51D907F7F
+:100BD5009774044EF0EBC313FB907F99E0FA30E570
+:100BE50003430380051E80A5AC1A7A007408C39CD4
+:100BF500FCE49AFA8CF005F0EB8002C313D5F0FB08
+:100C0500FBE5172F2400F582E4347EF583EBF0ED48
+:100C15006008851C228D82020C5B22AA82AB837C34
+:100C2500007D00C3EC9AED9B502B907F97E054FB21
+:100C3500F07E00EEB50B0050030E80F7907F97E035
+:100C45004404F07E00EEB50B0050030E80F70CBC9B
+:100C550000D10D80CE22AA82907F97E0FB74FB5BCA
+:100C6500F5237B00EBB502005024E52230E0054377
+:100C7500230280035323FD907F97E523F0E522C3EC
+:100C850013F522907F9774044523F00B80D622221A
+:100C95007A00907F99E0FB30E5027A01907F99E038
+:100CA500FB30E603430202907F9AE0FB30E7034303
+:100CB5000204907F9BE0FB30E503430208907F9A96
+:100CC500E0FB53037F8A04E4FAFDEB4AF582ED4C21
+:100CD500F58322E582547FF4FA907F97E05AF07409
+:100CE5007F5522FA907F97E04AF02285820A852275
+:100CF5000B85230C2200227A567B021ABAFF011BB0
+:100D0500EA4B70F722752205752300120D67AA823A
+:100D1500AB837C007D00C3EC9AED9B501AC002C0EA
+:100D250003C004C005120CFAD005D004D003D002CC
+:100D35000CBC00E20D80DF22AA82AB837C007D0023
+:100D4500C3EC9AED9B501AC002C003C004C0051243
+:100D55000CFCD005D004D003D0020CBC00E20D8001
+:020D6500DF228B
+:03004300021B009D
+:101B000002011F0002016E0002016F00020170005D
+:101B100002017100020172000201730002017400EF
+:101B200002017500020176000201770002018F00B8
+:101B30000201A7000201A8000201A9000201AA00F7
+:101B40000201AB000201AC000201AD000201AE00D7
+:081B50000201AF000201B00028
+:100D67007A10E4FBFCE58225E0F582E58333F58321
+:100D7700EB33FBEC33FCEB9522F5F0EC95234006C7
+:090D8700FCABF0438201DADD222D
+:0600A200E478FFF6D8FD32
+:100080007900E94400601B7A00900E3E780075927A
+:1000900020E493F2A308B800020592D9F4DAF275CD
+:0200A00092FFCD
+:1000A8007800E84400600A7900759220E4F309D8E2
+:1000B800FC7800E84400600C7900902000E4F0A38C
+:0400C800D8FCD9FA8D
+:0D007300758123120DACE582600302006E62
+:100D900020F71430F6148883A88220F507E6A8838C
+:100DA00075830022E280F7E49322E022758200221C
+:00000001FF