- added a PLD (programmable logic device) subsystem for FPGA, CPLD etc. configuration
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 22 Nov 2006 13:03:10 +0000 (13:03 +0000)
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 22 Nov 2006 13:03:10 +0000 (13:03 +0000)
- added support for loading .bit files into Xilinx Virtex-II devices
- added support for the Gateworks GW16012 JTAG dongle
- merged CFI fixes from XScale branch
- a few minor fixes

git-svn-id: svn://svn.berlios.de/openocd/trunk@116 b42882b7-edfa-0310-969c-e2dbd0fdcd60

16 files changed:
src/Makefile.am
src/flash/cfi.c
src/helper/binarybuffer.c
src/jtag/Makefile.am
src/jtag/ft2232.c
src/jtag/gw16012.c [new file with mode: 0644]
src/jtag/jtag.c
src/openocd.c
src/pld/Makefile.am [new file with mode: 0644]
src/pld/pld.c [new file with mode: 0644]
src/pld/pld.h [new file with mode: 0644]
src/pld/virtex2.c [new file with mode: 0644]
src/pld/virtex2.h [new file with mode: 0644]
src/pld/xilinx_bit.c [new file with mode: 0644]
src/pld/xilinx_bit.h [new file with mode: 0644]
src/target/armv4_5.c

index 208041f1095e557d8d58797f412021842434e1db..467149797fa0789738f1931896d3b28f44d46325 100644 (file)
@@ -4,11 +4,11 @@ openocd_SOURCES = openocd.c
 # set the include path found by configure
 INCLUDES = -I$(top_srcdir)/src/helper \
        -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target -I$(top_srcdir)/src/xsvf -I$(top_srcdir)/src/server \
-       -I$(top_srcdir)/src/flash $(all_includes)
+       -I$(top_srcdir)/src/flash -I$(top_srcdir)/src/pld $(all_includes)
 
 # the library search path.
 openocd_LDFLAGS = $(all_libraries) 
-SUBDIRS = helper jtag xsvf target server flash
+SUBDIRS = helper jtag xsvf target server flash pld
 
 if IS_MINGW
 MINGWLDADD = -lwsock32
@@ -43,4 +43,5 @@ openocd_LDADD = $(top_builddir)/src/xsvf/libxsvf.a \
        $(top_builddir)/src/helper/libhelper.a \
        $(top_builddir)/src/server/libserver.a $(top_builddir)/src/helper/libhelper.a \
        $(top_builddir)/src/flash/libflash.a $(top_builddir)/src/target/libtarget.a \
+       $(top_builddir)/src/pld/libpld.a \
        $(FTDI2232LIB) $(FTD2XXLIB) $(MINGWLDADD)
index bb548c22d1d51160312886ef67f995293f92a8b0..e91fcc7ed2ba0fdfb5ad46b094e046baad07d9c7 100644 (file)
@@ -208,8 +208,12 @@ u8 cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout)
        }
        
        DEBUG("status: 0x%x", status);
-
-       if (status != 0x80)
+       
+       if ((status & 0x80) != 0x80)
+       {
+               ERROR("timeout while waiting for WSM to become ready");
+       }
+       else if (status != 0x80)
        {
                ERROR("status register: 0x%x", status);
                if (status & 0x2)
@@ -352,6 +356,8 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **
                ERROR("no target '%i' configured", args[5]);
                exit(-1);
        }
+       
+       cfi_info->write_algorithm = NULL;
 
        /* bank wasn't probed yet */
        cfi_info->qry[0] = -1;
@@ -434,6 +440,9 @@ int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)
        u8 command[8];
        int i;
        
+       /* if the device supports neither legacy lock/unlock (bit 3) nor
+        * instant individual block locking (bit 5).
+        */
        if (!(pri_ext->feature_support & 0x28))
                return ERROR_FLASH_OPERATION_FAILED;
        
@@ -456,7 +465,8 @@ int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)
                        bank->sectors[i].is_protected = 0;
                }
                
-               cfi_intel_wait_status_busy(bank, 100);
+               /* Clear lock bits operation may take up to 1.4s */
+               cfi_intel_wait_status_busy(bank, 1400);
        }
        
        /* if the device doesn't support individual block lock bits set/clear,
@@ -544,27 +554,40 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
        cfi_flash_bank_t *cfi_info = bank->driver_priv;
        cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
        target_t *target = cfi_info->target;
-       reg_param_t reg_params[5];
+       reg_param_t reg_params[7];
        armv4_5_algorithm_t armv4_5_info;
        working_area_t *source;
        u32 buffer_size = 32768;
        u8 write_command[CFI_MAX_BUS_WIDTH];
+       u8 busy_pattern[CFI_MAX_BUS_WIDTH];
+       u8 error_pattern[CFI_MAX_BUS_WIDTH];
        int i;
        int retval;
        
+       /* algorithm register usage:
+        * r0: source address (in RAM)
+        * r1: target address (in Flash)
+        * r2: count
+        * r3: flash write command
+        * r4: status byte (returned to host)
+        * r5: busy test pattern
+        * r6: error test pattern
+        */
+        
        u32 word_32_code[] = {
                0xe4904004,   /* loop:  ldr r4, [r0], #4 */
                0xe5813000,   /*                str r3, [r1] */
                0xe5814000,   /*                str r4, [r1] */
-               0xe5914000,   /* busy   ldr r4, [r1] */
-               0xe3140080,   /*                tst r4, #0x80 */
-               0x0afffffc,   /*                beq busy */
-               0xe314007f,   /*                tst r4, #0x7f */
+               0xe5914000,   /* busy:  ldr r4, [r1] */
+               0xe0047005,   /*                and r7, r4, r5 */
+               0xe1570005,   /*                cmp r7, r5 */
+               0x1afffffb,   /*                bne busy */
+               0xe1140006,   /*                tst r4, r6 */
                0x1a000003,   /*                bne done */
                0xe2522001,   /*                subs r2, r2, #1 */
                0x0a000001,   /*                beq done */
                0xe2811004,   /*                add r1, r1 #4 */
-               0xeafffff3,   /*                b loop */
+               0xeafffff2,   /*                b loop */
                0xeafffffe,   /* done:  b -2 */
        };
        
@@ -573,14 +596,15 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
                0xe1c130b0,   /*                strh r3, [r1] */
                0xe1c140b0,   /*                strh r4, [r1] */
                0xe1d140b0,   /* busy   ldrh r4, [r1] */
-               0xe3140080,   /*                tst r4, #0x80 */
-               0x0afffffc,   /*                beq busy */
-               0xe314007f,   /*                tst r4, #0x7f */
+               0xe0047005,   /*                and r7, r4, r5 */
+               0xe1570005,   /*                cmp r7, r5 */
+               0x1afffffb,   /*                bne busy */
+               0xe1140006,   /*                tst r4, r6 */
                0x1a000003,   /*                bne done */
                0xe2522001,   /*                subs r2, r2, #1 */
                0x0a000001,   /*                beq done */
                0xe2811002,   /*                add r1, r1 #2 */
-               0xeafffff3,   /*                b loop */
+               0xeafffff2,   /*                b loop */
                0xeafffffe,   /* done:  b -2 */
        };
        
@@ -589,14 +613,15 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
                0xe5c13000,   /*                strb r3, [r1] */
                0xe5c14000,   /*                strb r4, [r1] */
                0xe5d14000,   /* busy   ldrb r4, [r1] */
-               0xe3140080,   /*                tst r4, #0x80 */
-               0x0afffffc,   /*                beq busy */
-               0xe314007f,   /*                tst r4, #0x7f */
+               0xe0047005,   /*                and r7, r4, r5 */
+               0xe1570005,   /*                cmp r7, r5 */
+               0x1afffffb,   /*                bne busy */
+               0xe1140006,   /*                tst r4, r6 */
                0x1a000003,   /*                bne done */
                0xe2522001,   /*                subs r2, r2, #1 */
                0x0a000001,   /*                beq done */
                0xe2811001,   /*                add r1, r1 #1 */
-               0xeafffff3,   /*                b loop */
+               0xeafffff2,   /*                b loop */
                0xeafffffe,   /* done:  b -2 */
        };
        
@@ -609,7 +634,7 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
        /* flash write code */
        if (!cfi_info->write_algorithm)
        {
-               if (target_alloc_working_area(target, 4 * 13, &cfi_info->write_algorithm) != ERROR_OK)
+               if (target_alloc_working_area(target, 4 * 14, &cfi_info->write_algorithm) != ERROR_OK)
                {
                        WARNING("no working area available, can't do block memory writes");
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -618,15 +643,15 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
                /* write algorithm code to working area */
                if (bank->bus_width == 1)
                {
-                       target_write_buffer(target, cfi_info->write_algorithm->address, 13 * 4, (u8*)word_8_code);
+                       target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_8_code);
                }
                else if (bank->bus_width == 2)
                {
-                       target_write_buffer(target, cfi_info->write_algorithm->address, 13 * 4, (u8*)word_16_code);
+                       target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_16_code);
                }       
                else if (bank->bus_width == 4)
                {
-                       target_write_buffer(target, cfi_info->write_algorithm->address, 13 * 4, (u8*)word_32_code);
+                       target_write_buffer(target, cfi_info->write_algorithm->address, 14 * 4, (u8*)word_32_code);
                }
                else
                {
@@ -653,6 +678,12 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
        init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
        init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
        init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
+       init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
+       init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);
+
+       cfi_command(bank, 0x40, write_command);
+       cfi_command(bank, 0x80, busy_pattern);
+       cfi_command(bank, 0x7f, error_pattern);
 
        while (count > 0)
        {
@@ -663,16 +694,17 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
                buf_set_u32(reg_params[0].value, 0, 32, source->address);
                buf_set_u32(reg_params[1].value, 0, 32, address);
                buf_set_u32(reg_params[2].value, 0, 32, thisrun_count / bank->bus_width);
-               cfi_command(bank, 0x40, write_command);
                buf_set_u32(reg_params[3].value, 0, 32, buf_get_u32(write_command, 0, 32));
+               buf_set_u32(reg_params[5].value, 0, 32, buf_get_u32(busy_pattern, 0, 32));
+               buf_set_u32(reg_params[6].value, 0, 32, buf_get_u32(error_pattern, 0, 32));
        
-               if ((retval = target->type->run_algorithm(target, 0, NULL, 5, reg_params, cfi_info->write_algorithm->address, cfi_info->write_algorithm->address + (12 * 4), 10000, &armv4_5_info)) != ERROR_OK)
+               if ((retval = target->type->run_algorithm(target, 0, NULL, 7, reg_params, cfi_info->write_algorithm->address, cfi_info->write_algorithm->address + (13 * 4), 10000, &armv4_5_info)) != ERROR_OK)
                {
                        cfi_intel_clear_status_register(bank);
                        return ERROR_FLASH_OPERATION_FAILED;
                }
        
-               if (buf_get_u32(reg_params[4].value, 0, 32) != 0x80)
+               if (buf_get_u32(reg_params[4].value, 0, 32) & target_buffer_get_u32(target, error_pattern))
                {
                        /* read status register (outputs debug inforation) */
                        cfi_intel_wait_status_busy(bank, 100);
@@ -692,7 +724,9 @@ int cfi_intel_write_block(struct flash_bank_s *bank, u8 *buffer, u32 address, u3
        destroy_reg_param(&reg_params[2]);
        destroy_reg_param(&reg_params[3]);
        destroy_reg_param(&reg_params[4]);
-
+       destroy_reg_param(&reg_params[5]);
+       destroy_reg_param(&reg_params[6]);
+       
        return ERROR_OK;
 }
 
@@ -932,9 +966,9 @@ int cfi_probe(struct flash_bank_s *bank)
        cfi_info->max_buf_write_size = cfi_query_u16(bank, 0, 0x2a);
        cfi_info->num_erase_regions = cfi_query_u8(bank, 0, 0x2c);
        
-       DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, cfi_info->max_buf_write_size);
+       DEBUG("size: 0x%x, interface desc: %i, max buffer write size: %x", 1 << cfi_info->dev_size, cfi_info->interface_desc, (1 << cfi_info->max_buf_write_size));
        
-       if (1 << cfi_info->dev_size != bank->size)
+       if (((1 << cfi_info->dev_size) * bank->bus_width / bank->chip_width) != bank->size)
        {
                WARNING("configuration specifies 0x%x size, but a 0x%x size flash was found", bank->size, 1 << cfi_info->dev_size);
        }
@@ -963,7 +997,7 @@ int cfi_probe(struct flash_bank_s *bank)
                        for (j = 0; j < (cfi_info->erase_region_info[i] & 0xffff) + 1; j++)
                        {
                                bank->sectors[sector].offset = offset;
-                               bank->sectors[sector].size = (cfi_info->erase_region_info[i] >> 16) * 256;
+                               bank->sectors[sector].size = ((cfi_info->erase_region_info[i] >> 16) * 256) * bank->bus_width / bank->chip_width;
                                offset += bank->sectors[sector].size;
                                bank->sectors[sector].is_erased = -1;
                                bank->sectors[sector].is_protected = -1;
@@ -1112,7 +1146,7 @@ int cfi_intel_protect_check(struct flash_bank_s *bank)
        cfi_flash_bank_t *cfi_info = bank->driver_priv;
        cfi_intel_pri_ext_t *pri_ext = cfi_info->pri_ext;
        target_t *target = cfi_info->target;
-       u8 command[8];
+       u8 command[CFI_MAX_BUS_WIDTH];
        int i;
        
        /* check if block lock bits are supported on this device */
index 6afd6e593c23902da97705de2f3f6b20172b1e17..7d41dc73a499efd6689fbcf1131addfa683353a6 100644 (file)
@@ -143,8 +143,8 @@ int buf_cmp_mask(u8 *buf1, u8 *buf2, u8 *mask, int size)
                /* mask out bits that don't really belong to the buffer if size isn't a multiple of 8 bits */
                if ((size % 8) && (i == num_bytes -1 ))
                {
-                       if (((buf1[i] & ((1 << (size % 8)) - 1)) & ((1 << (size % 8)) - 1)) != 
-                               ((buf2[i] & ((1 << (size % 8)) - 1)) & ((1 << (size % 8)) - 1)))
+                       if ((buf1[i] & ((1 << (size % 8)) - 1) & mask[i]) != 
+                               (buf2[i] & ((1 << (size % 8)) - 1) & mask[i]))
                                return 1;
                }
                else
index c63c734a7f3663fba6a1464687703e0050937ed0..d4812a468a846ae481654e0816e9be94e411d66a 100644 (file)
@@ -55,6 +55,12 @@ else
 AT91RM9200FILES =
 endif
 
-libjtag_a_SOURCES = jtag.c $(BITBANGFILES) $(PARPORTFILES) $(FT2232FILES) $(AMTJTAGACCELFILES) $(EP93XXFILES) $(AT91RM9200FILES)
+if GW16012
+GW16012FILES = gw16012.c
+else
+GW16012FILES =
+endif
+
+libjtag_a_SOURCES = jtag.c $(BITBANGFILES) $(PARPORTFILES) $(FT2232FILES) $(AMTJTAGACCELFILES) $(EP93XXFILES) $(AT91RM9200FILES) $(GW16012FILES)
 
 noinst_HEADERS = bitbang.h jtag.h
index 67167c78b167c9adb51b299081c5a10822f7e363..096111bc8e0fbcc123c41db7c7a93d290089d466 100644 (file)
 
 /* enable this to debug io latency
  */
-#if 0
+#if 1
 #define _DEBUG_USB_IO_
 #endif
 
 /* enable this to debug communication
  */
-#if 0
+#if 1
 #define _DEBUG_USB_COMMS_
 #endif
 
@@ -470,7 +470,7 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
        int cur_byte = 0;
        int last_bit;
 
-       if ((!ir_scan && (cur_state != TAP_SD)) || (ir_scan && (cur_state != TAP_SI)))
+       if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI))))
        {
                /* command "Clock Data to TMS/CS Pin (no Read)" */
                BUFFER_ADD = 0x4b;
@@ -491,8 +491,9 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
        }
        
        /* add command for complete bytes */
-       if (num_bytes > 1)
+       while (num_bytes > 1)
        {
+               int thisrun_bytes;
                if (type == SCAN_IO)
                {
                        /* Clock Data Bytes In and Out LSB First */
@@ -511,24 +512,206 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
                        BUFFER_ADD = 0x28;
                        //DEBUG("added TDI bytes (i %i)", num_bytes);
                }
-               BUFFER_ADD = (num_bytes-2) & 0xff;
-               BUFFER_ADD = ((num_bytes-2) >> 8) & 0xff;
+               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+               num_bytes -= thisrun_bytes;
+               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;
+               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;
+               if (type != SCAN_IN)
+               {
+                       /* add complete bytes */
+                       while(thisrun_bytes-- > 0)
+                       {
+                               BUFFER_ADD = buffer[cur_byte];
+                               cur_byte++;
+                               bits_left -= 8;
+                       }
+               }
+               else /* (type == SCAN_IN) */
+               {
+                       bits_left -= 8 * (thisrun_bytes);
+               }
        }
+       
+       /* the most signifcant bit is scanned during TAP movement */
        if (type != SCAN_IN)
+               last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
+       else
+               last_bit = 0;
+
+       /* process remaining bits but the last one */
+       if (bits_left > 1)
        {
-               /* add complete bytes */
-               while(num_bytes-- > 1)
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
                {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = bits_left - 2;
+               if (type != SCAN_IN)
                        BUFFER_ADD = buffer[cur_byte];
-                       cur_byte++;
-                       bits_left -= 8;
+       }
+
+       if ((ir_scan && (end_state == TAP_SI)) ||
+               (!ir_scan && (end_state == TAP_SD)))
+       {
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
                }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = 0x0;
+               BUFFER_ADD = last_bit;
        }
-       if (type == SCAN_IN)
+       else
+       {
+               /* move from Shift-IR/DR to end state */
+               if (type != SCAN_OUT)
+               {
+                       /* Clock Data to TMS/CS Pin with Read */
+                       BUFFER_ADD = 0x6b;
+                       //DEBUG("added TMS scan (read)");
+               }
+               else
+               {
+                       /* Clock Data to TMS/CS Pin (no Read) */
+                       BUFFER_ADD = 0x4b;
+                       //DEBUG("added TMS scan (no read)");
+               }
+               BUFFER_ADD = 0x6;
+               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
+               cur_state = end_state;
+       }
+}
+
+int ft2232_large_scan(scan_command_t *cmd, enum scan_type type, u8 *buffer, int scan_size)
+{
+       int num_bytes = (scan_size + 7) / 8;
+       int bits_left = scan_size;
+       int cur_byte = 0;
+       int last_bit;
+       u8 *receive_buffer = malloc(CEIL(scan_size, 8));
+       u8 *receive_pointer = receive_buffer;
+       u32 bytes_written;
+       u32 bytes_read;
+       int retval;
+       int thisrun_read = 0;
+       
+       if (cmd->ir_scan)
        {
-               bits_left -= 8 * (num_bytes - 1);
+               ERROR("BUG: large IR scans are not supported");
+               exit(-1);
        }
 
+       if (cur_state != TAP_SD)
+       {
+               /* command "Clock Data to TMS/CS Pin (no Read)" */
+               BUFFER_ADD = 0x4b;
+               /* scan 7 bit */
+               BUFFER_ADD = 0x6;
+               /* TMS data bits */
+               BUFFER_ADD = TAP_MOVE(cur_state, TAP_SD);
+               cur_state = TAP_SD;
+       }
+       
+       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+       {
+               ERROR("couldn't write MPSSE commands to FT2232");
+               exit(-1);
+       }
+       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+       ft2232_buffer_size = 0;
+       
+       /* add command for complete bytes */
+       while (num_bytes > 1)
+       {
+               int thisrun_bytes;
+               
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bytes In and Out LSB First */
+                       BUFFER_ADD = 0x39;
+                       //DEBUG("added TDI bytes (io %i)", num_bytes);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x19;
+                       //DEBUG("added TDI bytes (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x28;
+                       //DEBUG("added TDI bytes (i %i)", num_bytes);
+               }
+               thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1);
+               thisrun_read = thisrun_bytes;
+               num_bytes -= thisrun_bytes;
+               BUFFER_ADD = (thisrun_bytes - 1) & 0xff;
+               BUFFER_ADD = ((thisrun_bytes - 1) >> 8) & 0xff;
+               if (type != SCAN_IN)
+               {
+                       /* add complete bytes */
+                       while(thisrun_bytes-- > 0)
+                       {
+                               BUFFER_ADD = buffer[cur_byte];
+                               cur_byte++;
+                               bits_left -= 8;
+                       }
+               }
+               else /* (type == SCAN_IN) */
+               {
+                       bits_left -= 8 * (thisrun_bytes);
+               }
+
+               if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+               {
+                       ERROR("couldn't write MPSSE commands to FT2232");
+                       exit(-1);
+               }
+               DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+               ft2232_buffer_size = 0;
+               
+               if (type != SCAN_OUT)
+               {
+                       if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)
+                       {
+                               ERROR("couldn't read from FT2232");
+                               exit(-1);
+                       }
+                       DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);
+                       receive_pointer += bytes_read;
+               }
+       }
+       
+       thisrun_read = 0;
+       
        /* the most signifcant bit is scanned during TAP movement */
        if (type != SCAN_IN)
                last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1;
@@ -559,30 +742,83 @@ void ft2232_add_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size
                BUFFER_ADD = bits_left - 2;
                if (type != SCAN_IN)
                        BUFFER_ADD = buffer[cur_byte];
+                       
+               if (type != SCAN_OUT)
+                       thisrun_read += 2;
        }
 
-       /* move from Shift-IR/DR to end state */
-       if (type != SCAN_OUT)
+       if (end_state == TAP_SD)
        {
-               /* Clock Data to TMS/CS Pin with Read */
-               BUFFER_ADD = 0x6b;
-               //DEBUG("added TMS scan (read)");
+               if (type == SCAN_IO)
+               {
+                       /* Clock Data Bits In and Out LSB First */
+                       BUFFER_ADD = 0x3b;
+                       //DEBUG("added TDI bits (io) %i", bits_left - 1);
+               }
+               else if (type == SCAN_OUT)
+               {
+                       /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */
+                       BUFFER_ADD = 0x1b;
+                       //DEBUG("added TDI bits (o)");
+               }
+               else if (type == SCAN_IN)
+               {
+                       /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */
+                       BUFFER_ADD = 0x2a;
+                       //DEBUG("added TDI bits (i %i)", bits_left - 1);
+               }
+               BUFFER_ADD = 0x0;
+               BUFFER_ADD = last_bit;
        }
        else
        {
-               /* Clock Data to TMS/CS Pin (no Read) */
-               BUFFER_ADD = 0x4b;
-               //DEBUG("added TMS scan (no read)");
+               /* move from Shift-IR/DR to end state */
+               if (type != SCAN_OUT)
+               {
+                       /* Clock Data to TMS/CS Pin with Read */
+                       BUFFER_ADD = 0x6b;
+                       //DEBUG("added TMS scan (read)");
+               }
+               else
+               {
+                       /* Clock Data to TMS/CS Pin (no Read) */
+                       BUFFER_ADD = 0x4b;
+                       //DEBUG("added TMS scan (no read)");
+               }
+               BUFFER_ADD = 0x6;
+               BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
+               cur_state = end_state;
        }
-       BUFFER_ADD = 0x6;
-       BUFFER_ADD = TAP_MOVE(cur_state, end_state) | (last_bit << 7);
-       cur_state = end_state;
-
+       
+       if (type != SCAN_OUT)
+               thisrun_read += 1;
+       
+       if ((retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written)) != ERROR_OK)
+       {
+               ERROR("couldn't write MPSSE commands to FT2232");
+               exit(-1);
+       }
+       DEBUG("ft2232_buffer_size: %i, bytes_written: %i", ft2232_buffer_size, bytes_written);
+       ft2232_buffer_size = 0;
+       
+       if (type != SCAN_OUT)
+       {
+               if ((retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read)) != ERROR_OK)
+               {
+                       ERROR("couldn't read from FT2232");
+                       exit(-1);
+               }
+               DEBUG("thisrun_read: %i, bytes_read: %i", thisrun_read, bytes_read);
+               receive_pointer += bytes_read;
+       }
+       
+       return ERROR_OK;
 }
 
 int ft2232_predict_scan_out(int scan_size, enum scan_type type)
 {
        int predicted_size = 3;
+       int num_bytes = (scan_size - 1) / 8;
        
        if (cur_state != TAP_SD)
                predicted_size += 3;
@@ -590,14 +826,14 @@ int ft2232_predict_scan_out(int scan_size, enum scan_type type)
        if (type == SCAN_IN)    /* only from device to host */
        {
                /* complete bytes */
-               predicted_size += (CEIL(scan_size, 8) > 1) ? 3 : 0;
+               predicted_size += (CEIL(num_bytes, 65536)) * 3;
                /* remaining bits - 1 (up to 7) */
                predicted_size += ((scan_size - 1) % 8) ? 2 : 0;
        }
        else                                    /* host to device, or bidirectional */
        {
                /* complete bytes */
-               predicted_size += (CEIL(scan_size, 8) > 1) ? (CEIL(scan_size, 8) + 3 - 1) : 0;
+               predicted_size += num_bytes + (CEIL(num_bytes, 65536)) * 3;
                /* remaining bits -1 (up to 7) */
                predicted_size += ((scan_size - 1) % 8) ? 3 : 0;
        }
@@ -910,9 +1146,26 @@ int ft2232_execute_queue()
                                scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
                                type = jtag_scan_type(cmd->cmd.scan);
                                predicted_size = ft2232_predict_scan_out(scan_size, type);
-                               if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
+                               if ((predicted_size + 1) > FT2232_BUFFER_SIZE)
+                               {
+                                       DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)");
+                                       /* unsent commands before this */
+                                       if (first_unsent != cmd)
+                                               ft2232_send_and_recv(first_unsent, cmd);
+                                       
+                                       /* current command */
+                                       if (cmd->cmd.scan->end_state != -1)
+                                               ft2232_end_state(cmd->cmd.scan->end_state);
+                                       ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size);
+                                       require_send = 0;
+                                       first_unsent = cmd->next;
+                                       if (buffer)
+                                               free(buffer);
+                                       break;
+                               }
+                               else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE)
                                {
-                                       DEBUG("ftd2xx buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd);
+                                       DEBUG("ft2232 buffer size reached, sending queued commands (first_unsent: %x, cmd: %x)", first_unsent, cmd);
                                        ft2232_send_and_recv(first_unsent, cmd);
                                        require_send = 0;
                                        first_unsent = cmd;
diff --git a/src/jtag/gw16012.c b/src/jtag/gw16012.c
new file mode 100644 (file)
index 0000000..6210a52
--- /dev/null
@@ -0,0 +1,507 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "jtag.h"
+
+/* system includes */
+
+/* system includes */
+// -ino: 060521-1036
+#ifdef __FreeBSD__
+
+#include <sys/types.h>
+#include <machine/sysarch.h>
+#include <machine/cpufunc.h>
+#define ioperm(startport,length,enable)\
+  i386_set_ioperm((startport), (length), (enable))
+
+#else
+
+#ifndef _WIN32
+#include <sys/io.h>
+#else
+#include "errno.h"
+#endif /* _WIN32 */
+
+#endif /* __FreeBSD__ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#if PARPORT_USE_PPDEV == 1
+#ifdef __FreeBSD__
+#include <dev/ppbus/ppi.h>
+#include <dev/ppbus/ppbconf.h>
+#define PPRSTATUS      PPIGSTATUS
+#define PPWDATA                PPISDATA
+#else
+#include <linux/parport.h>
+#include <linux/ppdev.h>
+#endif
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#endif
+
+#if PARPORT_USE_GIVEIO == 1
+#if IS_CYGWIN == 1
+#include <windows.h>
+#include <errno.h>
+#undef ERROR
+#endif
+#endif
+
+#include "log.h"
+
+/* configuration */
+unsigned long gw16012_port;
+
+/* interface variables
+ */
+static u8 gw16012_msb = 0x0;
+static u8 gw16012_control_value = 0x0;
+
+#if PARPORT_USE_PPDEV == 1
+static int device_handle;
+#endif
+
+int gw16012_execute_queue(void);
+int gw16012_register_commands(struct command_context_s *cmd_ctx);
+int gw16012_speed(int speed);
+int gw16012_init(void);
+int gw16012_quit(void);
+
+int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+jtag_interface_t gw16012_interface = 
+{
+       .name = "gw16012",
+       
+       .execute_queue = gw16012_execute_queue,
+
+       .support_pathmove = 0,
+
+       .speed = gw16012_speed, 
+       .register_commands = gw16012_register_commands,
+       .init = gw16012_init,
+       .quit = gw16012_quit,
+};
+
+int gw16012_register_commands(struct command_context_s *cmd_ctx)
+{
+       register_command(cmd_ctx, NULL, "parport_port", gw16012_handle_parport_port_command,
+                                        COMMAND_CONFIG, NULL);
+       
+       return ERROR_OK;
+}
+
+void gw16012_data(u8 value)
+{
+       value = (value & 0x7f) | gw16012_msb;
+       gw16012_msb ^= 0x80; /* toggle MSB */
+       
+       #if PARPORT_USE_PPDEV == 1
+               ioctl(device_handle, PPWDATA, &value);
+       #else
+               #ifdef __FreeBSD__
+                       outb(gw16012_port, value);
+               #else
+                       outb(value, gw16012_port);
+               #endif
+       #endif  
+}
+
+void gw16012_control(u8 value)
+{
+       if (value != gw16012_control_value)
+       {
+               gw16012_control_value = value;
+
+               #if PARPORT_USE_PPDEV == 1
+                       ioctl(device_handle, PPWCONTROL, &gw16012_control_value);
+               #else
+                       #ifdef __FreeBSD__
+                               outb(gw16012_port + 2, gw16012_control_value);
+                       #else
+                               outb(gw16012_control_value, gw16012_port + 2);
+                       #endif
+               #endif
+       }
+}
+
+void gw16012_input(u8 *value)
+{
+       #if PARPORT_USE_PPDEV == 1
+               ioctl(device_handle, PPRSTATUS, value);
+       #else
+               *value = inb(gw16012_port + 1);
+       #endif
+}
+
+/* (1) assert or (0) deassert reset lines */
+void gw16012_reset(int trst, int srst)
+{
+       DEBUG("trst: %i, srst: %i", trst, srst);
+
+       if (trst == 0)
+               gw16012_control(0x0d);
+       else if (trst == 1)
+               gw16012_control(0x0c);
+
+       if (srst == 0)
+               gw16012_control(0x0a);
+       else if (srst == 1)
+               gw16012_control(0x0b);
+}
+
+int gw16012_speed(int speed)
+{
+
+       return ERROR_OK;
+}
+
+void gw16012_end_state(state)
+{
+       if (tap_move_map[state] != -1)
+               end_state = state;
+       else
+       {
+               ERROR("BUG: %i is not a valid end state", state);
+               exit(-1);
+       }
+}
+
+void gw16012_state_move(void)
+{
+       int i=0, tms=0;
+       u8 tms_scan = TAP_MOVE(cur_state, end_state);
+       
+       gw16012_control(0x0); /* single-bit mode */
+       
+       for (i = 0; i < 7; i++)
+       {
+               tms = (tms_scan >> i) & 1;
+               gw16012_data(tms << 1); /* output next TMS bit */
+       }
+       
+       cur_state = end_state;
+}
+
+void gw16012_runtest(int num_cycles)
+{
+       enum tap_state saved_end_state = end_state;
+       int i;
+       
+       /* only do a state_move when we're not already in RTI */
+       if (cur_state != TAP_RTI)
+       {
+               gw16012_end_state(TAP_RTI);
+               gw16012_state_move();
+       }
+       
+       for (i = 0; i < num_cycles; i++)
+       {
+               gw16012_control(0x0); /* single-bit mode */
+               gw16012_data(0x0); /* TMS cycle with TMS low */
+       }
+       
+       gw16012_end_state(saved_end_state);
+       if (cur_state != end_state)
+               gw16012_state_move();
+}
+
+void gw16012_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
+{
+       int bits_left = scan_size;
+       int bit_count = 0;
+       enum tap_state saved_end_state = end_state;
+       u8 scan_out, scan_in;
+
+       if (ir_scan)
+               gw16012_end_state(TAP_SI);
+       else
+               gw16012_end_state(TAP_SD);
+
+       gw16012_state_move();
+       gw16012_end_state(saved_end_state);
+
+       while (type == SCAN_OUT && ((bits_left - 1) > 7))
+       {
+               gw16012_control(0x2); /* seven-bit mode */
+               scan_out = buf_get_u32(buffer, bit_count, 7);
+               gw16012_data(scan_out);
+               bit_count += 7;
+               bits_left -= 7;
+       }
+       
+       gw16012_control(0x0); /* single-bit mode */
+       while (bits_left-- > 0)
+       {
+               u8 tms = 0;
+               if (bits_left == 0) /* last bit */
+               {
+                       if ((ir_scan && (end_state == TAP_SI))
+                               || (!ir_scan && (end_state == TAP_SD)))
+                       {
+                               tms = 0; 
+                       }
+                       else
+                       {
+                               tms = 2;
+                       }
+               }
+               
+               scan_out = buf_get_u32(buffer, bit_count, 1);
+               gw16012_data(scan_out | tms);
+               if (type != SCAN_OUT)
+               {
+                       gw16012_input(&scan_in);
+                       buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
+               }
+               bit_count++;
+       }
+
+       if (!((ir_scan && (end_state == TAP_SI)) ||
+               (!ir_scan && (end_state == TAP_SD))))
+       {
+               gw16012_data(0x0);
+               if (ir_scan)
+                       cur_state = TAP_PI;
+               else
+                       cur_state = TAP_PD;
+                       
+               if (cur_state != end_state)
+                       gw16012_state_move();
+       }
+}
+
+int gw16012_execute_queue(void)
+{
+       jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
+       int scan_size;
+       enum scan_type type;
+       u8 *buffer;
+               
+       while (cmd)
+       {
+               switch (cmd->type)
+               {
+                       case JTAG_END_STATE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
+#endif
+                               if (cmd->cmd.end_state->end_state != -1)
+                                       gw16012_end_state(cmd->cmd.end_state->end_state);
+                               break;
+                       case JTAG_RESET:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+#endif
+                               if (cmd->cmd.reset->trst == 1)
+                               {
+                                       cur_state = TAP_TLR;
+                               }
+                               gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
+                               break;
+                       case JTAG_RUNTEST:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
+#endif
+                               if (cmd->cmd.runtest->end_state != -1)
+                                       gw16012_end_state(cmd->cmd.runtest->end_state);
+                               gw16012_runtest(cmd->cmd.runtest->num_cycles);
+                               break;
+                       case JTAG_STATEMOVE:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
+#endif
+                               if (cmd->cmd.statemove->end_state != -1)
+                                       gw16012_end_state(cmd->cmd.statemove->end_state);
+                               gw16012_state_move();
+                               break;
+                       case JTAG_SCAN:
+                               if (cmd->cmd.scan->end_state != -1)
+                                       gw16012_end_state(cmd->cmd.scan->end_state);
+                               scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
+                               type = jtag_scan_type(cmd->cmd.scan);
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr", 
+                                       type, scan_size, cmd->cmd.scan->end_state);
+#endif
+                               gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
+                               if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
+                                       return ERROR_JTAG_QUEUE_FAILED;
+                               if (buffer)
+                                       free(buffer);
+                               break;
+                       case JTAG_SLEEP:
+#ifdef _DEBUG_JTAG_IO_
+                               DEBUG("sleep", cmd->cmd.sleep->us);
+#endif
+                               jtag_sleep(cmd->cmd.sleep->us);
+                               break;
+                       default:
+                               ERROR("BUG: unknown JTAG command type encountered");
+                               exit(-1);
+               }
+               cmd = cmd->next;
+       }
+       
+       return ERROR_OK;
+}
+
+#if PARPORT_USE_GIVEIO == 1
+int gw16012_get_giveio_access()
+{
+    HANDLE h;
+    OSVERSIONINFO version;
+
+    version.dwOSVersionInfoSize = sizeof version;
+    if (!GetVersionEx( &version )) {
+        errno = EINVAL;
+        return -1;
+    }
+    if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
+        return 0;
+
+    h = CreateFile( "\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+    if (h == INVALID_HANDLE_VALUE) {
+        errno = ENODEV;
+        return -1;
+    }
+
+    CloseHandle( h );
+
+    return 0;
+}
+#endif
+
+int gw16012_init(void)
+{
+#if PARPORT_USE_PPDEV == 1
+       char buffer[256];
+       int i = 0;
+       u8 control_port;
+#endif
+       u8 status_port;
+       
+#if PARPORT_USE_PPDEV == 1
+       if (device_handle>0)
+       {
+               ERROR("device is already opened");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+#ifdef __FreeBSD__
+       DEBUG("opening /dev/ppi%d...", gw16012_port);
+
+       snprintf(buffer, 256, "/dev/ppi%d", gw16012_port);
+       device_handle = open(buffer, O_WRONLY);
+#else
+       DEBUG("opening /dev/parport%d...", gw16012_port);
+
+       snprintf(buffer, 256, "/dev/parport%d", gw16012_port);
+       device_handle = open(buffer, O_WRONLY);
+#endif 
+       if (device_handle<0)
+       {
+               ERROR("cannot open device. check it exists and that user read and write rights are set");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       DEBUG("...open");
+
+#ifndef __FreeBSD__
+       i=ioctl(device_handle, PPCLAIM);
+       if (i<0)
+       {
+               ERROR("cannot claim device");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       i = PARPORT_MODE_COMPAT;
+       i= ioctl(device_handle, PPSETMODE, & i);
+       if (i<0)
+       {
+               ERROR(" cannot set compatible mode to device");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       i = IEEE1284_MODE_COMPAT;
+       i = ioctl(device_handle, PPNEGOT, & i);
+       if (i<0)
+       {
+               ERROR("cannot set compatible 1284 mode to device");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+#endif
+#else
+       if (gw16012_port == 0)
+       {
+               gw16012_port = 0x378;
+               WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
+       }
+       
+       DEBUG("requesting privileges for parallel port 0x%x...", gw16012_port);
+#if PARPORT_USE_GIVEIO == 1
+       if (gw16012_get_giveio_access() != 0)
+#else /* PARPORT_USE_GIVEIO */
+       if (ioperm(gw16012_port, 3, 1) != 0)
+#endif /* PARPORT_USE_GIVEIO */
+       {
+               ERROR("missing privileges for direct i/o");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       DEBUG("...privileges granted");
+#endif /* PARPORT_USE_PPDEV */
+       
+       gw16012_input(&status_port);
+       gw16012_msb = (status_port & 0x80) ^ 0x80;
+       
+       gw16012_speed(jtag_speed);
+       gw16012_reset(0, 0);
+       
+       return ERROR_OK;
+}
+
+int gw16012_quit(void)
+{
+       
+       return ERROR_OK;
+}
+
+int gw16012_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc == 0)
+               return ERROR_OK;
+
+       /* only if the port wasn't overwritten by cmdline */
+       if (gw16012_port == 0)
+               gw16012_port = strtoul(args[0], NULL, 0);
+
+       return ERROR_OK;
+}
index 4ba227c09b39b1d3480625609ac66e7c6b4ed1e4..259a327dd87eb71424c9706ca3218aef95707523 100644 (file)
@@ -144,6 +144,10 @@ jtag_event_callback_t *jtag_event_callbacks;
        extern jtag_interface_t at91rm9200_interface;
 #endif
 
+#if BUILD_GW16012 == 1
+       extern jtag_interface_t gw16012_interface;
+#endif
+
 jtag_interface_t *jtag_interfaces[] = {
 #if BUILD_PARPORT == 1
        &parport_interface,
@@ -162,6 +166,9 @@ jtag_interface_t *jtag_interfaces[] = {
 #endif
 #if BUILD_AT91RM9200 == 1
        &at91rm9200_interface,
+#endif
+#if BUILD_GW16012 == 1
+       &gw16012_interface,
 #endif
        NULL,
 };
@@ -959,7 +966,7 @@ int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
                if (cmd->fields[i].out_value)
                {
 #ifdef _DEBUG_JTAG_IO_
-                       char* char_buf = buf_to_str(cmd->fields[i].out_value, cmd->fields[i].num_bits, 16);
+                       char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16);
 #endif
                        buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);
 #ifdef _DEBUG_JTAG_IO_
@@ -993,7 +1000,7 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
                        #ifdef _DEBUG_JTAG_IO_
                                char *char_buf;
 
-                               char_buf = buf_to_str(captured, num_bits, 16);
+                               char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
                                DEBUG("fields[%i].in_value: 0x%s", i, char_buf);
                                free(char_buf);
                        #endif
@@ -1031,9 +1038,9 @@ int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
                                if ((cmd->fields[i].in_check_mask && buf_cmp_mask(captured, cmd->fields[i].in_check_value, cmd->fields[i].in_check_mask, num_bits))
                                        || (!cmd->fields[i].in_check_mask && buf_cmp(captured, cmd->fields[i].in_check_mask, num_bits)))
                                {
-                                       char *captured_char = buf_to_str(captured, num_bits, 16);
-                                       char *in_check_value_char = buf_to_str(cmd->fields[i].in_check_value, num_bits, 16);
-                                       char *in_check_mask_char = buf_to_str(cmd->fields[i].in_check_mask, num_bits, 16);
+                                       char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
+                                       char *in_check_value_char = buf_to_str(cmd->fields[i].in_check_value, (num_bits > 64) ? 64 : num_bits, 16);
+                                       char *in_check_mask_char = buf_to_str(cmd->fields[i].in_check_mask, (num_bits > 64) ? 64 : num_bits, 16);
                                        /* TODO: error reporting */
                                        WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char);
                                        retval = ERROR_JTAG_QUEUE_FAILED;
index 4df416e8f221ee4232fa3cda639efe83da9f0ae1..3abc609e1438f838252e7c0373bd2bd2f865c125 100644 (file)
@@ -18,7 +18,7 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#define OPENOCD_VERSION "Open On-Chip Debugger (2006-10-12 18:00 CEST)"
+#define OPENOCD_VERSION "Open On-Chip Debugger (2006-11-22 14:00 CEST)"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -32,6 +32,7 @@
 #include "xsvf.h"
 #include "target.h"
 #include "flash.h"
+#include "pld.h"
 
 #include "command.h"
 #include "server.h"
@@ -74,6 +75,7 @@ int main(int argc, char *argv[])
        xsvf_register_commands(cmd_ctx);
        target_register_commands(cmd_ctx);
        flash_register_commands(cmd_ctx);
+       pld_register_commands(cmd_ctx);
        
        if (log_init(cmd_ctx) != ERROR_OK)
                return EXIT_FAILURE;
@@ -107,6 +109,10 @@ int main(int argc, char *argv[])
                return EXIT_FAILURE;
        DEBUG("flash init complete");
 
+       if (pld_init(cmd_ctx) != ERROR_OK)
+               return EXIT_FAILURE;
+       DEBUG("pld init complete");
+
        /* initialize tcp server */
        server_init();
        
diff --git a/src/pld/Makefile.am b/src/pld/Makefile.am
new file mode 100644 (file)
index 0000000..e338625
--- /dev/null
@@ -0,0 +1,5 @@
+INCLUDES = -I$(top_srcdir)/src/server -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag $(all_includes)
+METASOURCES = AUTO
+noinst_LIBRARIES = libpld.a
+noinst_HEADERS = pld.h xilinx_bit.h virtex2.h
+libpld_a_SOURCES = pld.c xilinx_bit.c virtex2.c
diff --git a/src/pld/pld.c b/src/pld/pld.c
new file mode 100644 (file)
index 0000000..a20f9d9
--- /dev/null
@@ -0,0 +1,218 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pld.h"
+
+#include "jtag.h"
+#include "command.h"
+#include "log.h"
+#include "time_support.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+/* pld drivers
+ */
+extern pld_driver_t virtex2_pld;
+
+pld_driver_t *pld_drivers[] =
+{
+       &virtex2_pld,
+       NULL,
+};
+
+pld_device_t *pld_devices;
+static command_t *pld_cmd;
+
+int handle_pld_devices_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_pld_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int pld_init(struct command_context_s *cmd_ctx)
+{
+       if (pld_devices)
+       {
+               register_command(cmd_ctx, pld_cmd, "devices", handle_pld_devices_command, COMMAND_EXEC,
+                                               "list configured pld devices");
+               register_command(cmd_ctx, pld_cmd, "load", handle_pld_load_command, COMMAND_EXEC,
+                                               "load configuration <file> into programmable logic device");
+       }
+       
+       return ERROR_OK;
+}
+
+pld_device_t *get_pld_device_by_num(int num)
+{
+       pld_device_t *p;
+       int i = 0;
+
+       for (p = pld_devices; p; p = p->next)
+       {
+               if (i++ == num)
+               {
+                       return p;
+               }
+       }
+       
+       return NULL;
+}
+
+/* pld device <driver> [driver_options ...]
+ */
+int handle_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int i;
+       int found = 0;
+               
+       if (argc < 1)
+       {
+               WARNING("incomplete 'pld bank' configuration");
+               return ERROR_OK;
+       }
+       
+       for (i = 0; pld_drivers[i]; i++)
+       {
+               if (strcmp(args[0], pld_drivers[i]->name) == 0)
+               {
+                       pld_device_t *p, *c;
+                       
+                       /* register pld specific commands */
+                       if (pld_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)
+                       {
+                               ERROR("couldn't register '%s' commands", args[0]);
+                               exit(-1);
+                       }
+                       
+                       c = malloc(sizeof(pld_device_t));
+                       c->driver = pld_drivers[i];
+                       c->next = NULL;
+                       
+                       if (pld_drivers[i]->pld_device_command(cmd_ctx, cmd, args, argc, c) != ERROR_OK)
+                       {
+                               ERROR("'%s' driver rejected pld device", args[0]);
+                               free(c);
+                               return ERROR_OK;
+                       }
+                       
+                       /* put pld device in linked list */
+                       if (pld_devices)
+                       {
+                               /* find last pld device */
+                               for (p = pld_devices; p && p->next; p = p->next);
+                               if (p)
+                                       p->next = c;
+                       }
+                       else
+                       {
+                               pld_devices = c;
+                       }
+                       
+                       found = 1;
+               }
+       }
+               
+       /* no matching pld driver found */
+       if (!found)
+       {
+               ERROR("pld driver '%s' not found", args[0]);
+               exit(-1);
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_pld_devices_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       pld_device_t *p;
+       int i = 0;
+       
+       if (!pld_devices)
+       {
+               command_print(cmd_ctx, "no pld devices configured");
+               return ERROR_OK;
+       }
+       
+       for (p = pld_devices; p; p = p->next)
+       {
+               command_print(cmd_ctx, "#%i: %s", i++, p->driver->name);
+       }
+       
+       return ERROR_OK;
+}
+
+int handle_pld_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       int retval;
+       struct timeval start, end, duration;
+       pld_device_t *p;
+       
+       gettimeofday(&start, NULL);
+               
+       if (argc < 2)
+       {
+               command_print(cmd_ctx, "usage: pld load <device#> <file>");
+               return ERROR_OK;
+       }
+       
+       p = get_pld_device_by_num(strtoul(args[0], NULL, 0));
+       if (!p)
+       {
+               command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+       
+       if ((retval = p->driver->load(p, args[1])) != ERROR_OK)
+       {
+               command_print(cmd_ctx, "failed loading file %s to pld device %i",
+                       args[1], strtoul(args[0], NULL, 0));
+               switch (retval)
+               {
+               }
+       }
+       else
+       {
+               gettimeofday(&end, NULL);       
+               timeval_subtract(&duration, &end, &start);
+               
+               command_print(cmd_ctx, "loaded file %s to pld device %i in %is %ius", 
+                       args[1], strtoul(args[0], NULL, 0), duration.tv_sec, duration.tv_usec);
+       }
+       
+       return ERROR_OK;
+}
+
+int pld_register_commands(struct command_context_s *cmd_ctx)
+{
+       pld_cmd = register_command(cmd_ctx, NULL, "pld", NULL, COMMAND_ANY, "programmable logic device commands");
+       
+       register_command(cmd_ctx, pld_cmd, "device", handle_pld_device_command, COMMAND_CONFIG, NULL);
+       
+       return ERROR_OK;
+}
diff --git a/src/pld/pld.h b/src/pld/pld.h
new file mode 100644 (file)
index 0000000..e4cfc07
--- /dev/null
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef PLD_H
+#define PLD_H
+
+#include "command.h"
+
+struct pld_device_s;
+
+typedef struct pld_driver_s
+{
+       char *name;
+       int (*register_commands)(struct command_context_s *cmd_ctx);
+       int (*pld_device_command)(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);
+       int (*load)(struct pld_device_s *pld_device, char *filename);
+} pld_driver_t;
+
+typedef struct pld_device_s
+{
+       pld_driver_t *driver;
+       void *driver_priv;
+       struct pld_device_s *next;
+} pld_device_t;
+
+extern int pld_register_commands(struct command_context_s *cmd_ctx);
+extern int pld_init(struct command_context_s *cmd_ctx);
+extern pld_device_t *get_pld_device_by_num(int num);
+
+#define ERROR_PLD_DEVICE_INVALID       (-1000)
+#define ERROR_PLD_FILE_LOAD_FAILED     (-1001)
+
+#endif /* PLD_H */
diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c
new file mode 100644 (file)
index 0000000..8624367
--- /dev/null
@@ -0,0 +1,264 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "virtex2.h"
+
+#include "pld.h"
+#include "xilinx_bit.h"
+#include "command.h"
+#include "log.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+int virtex2_register_commands(struct command_context_s *cmd_ctx);
+int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);
+int virtex2_load(struct pld_device_s *pld_device, char *filename);
+
+pld_driver_t virtex2_pld =
+{
+       .name = "virtex2",
+       .register_commands = virtex2_register_commands,
+       .pld_device_command = virtex2_pld_device_command,
+       .load = virtex2_load,
+};
+
+int virtex2_set_instr(int chain_pos, u32 new_instr)
+{
+       jtag_device_t *device = jtag_get_device(chain_pos);
+       
+       if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+       {
+               scan_field_t field;
+       
+               field.device = chain_pos;
+               field.num_bits = device->ir_length;
+               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               field.out_mask = NULL;
+               field.in_value = NULL;
+               field.in_check_value = NULL;
+               field.in_check_mask = NULL;
+               field.in_handler = NULL;
+               field.in_handler_priv = NULL;
+               
+               jtag_add_ir_scan(1, &field, TAP_RTI);
+               
+               free(field.out_value);
+       }
+       
+       return ERROR_OK;
+}
+
+int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)
+{
+       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+       scan_field_t scan_field;
+       u8 *values;
+       int i;
+       
+       values = malloc(num_words * 4);
+
+       scan_field.device = virtex2_info->chain_pos;
+       scan_field.num_bits = num_words * 32;
+       scan_field.out_value = values;
+       scan_field.out_mask = NULL;
+       scan_field.in_value = NULL;
+       scan_field.in_check_value = NULL;
+       scan_field.in_check_mask = NULL;
+       scan_field.in_handler = NULL;
+       scan_field.in_handler_priv = NULL;
+       
+       for (i = 0; i < num_words; i++)
+               buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
+       
+       virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
+       
+       jtag_add_dr_scan(1, &scan_field, TAP_PD);
+       
+       free(values);
+       
+       return ERROR_OK;
+}
+
+int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv)
+{
+       u32 *dest = priv;
+       *dest = flip_u32(le_to_h_u32(in_buf), 32);
+       return ERROR_OK;
+}
+
+int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)
+{
+       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+       scan_field_t scan_field;
+       
+       scan_field.device = virtex2_info->chain_pos;
+       scan_field.num_bits = 32;
+       scan_field.out_value = NULL;
+       scan_field.out_mask = NULL;
+       scan_field.in_value = NULL;
+       scan_field.in_check_value = NULL;
+       scan_field.in_check_mask = NULL;
+       scan_field.in_handler = virtex2_jtag_buf_to_u32;
+       
+       virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */
+       
+       while (num_words--)
+       {
+               scan_field.in_handler_priv = words++;
+               jtag_add_dr_scan(1, &scan_field, TAP_PD);
+       }
+       
+       return ERROR_OK;
+}
+
+int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)
+{
+       u32 data[5];
+       
+       jtag_add_statemove(TAP_TLR);
+       
+       data[0] = 0xaa995566; /* synch word */
+       data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
+       data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
+       data[3] = 0x20000000; /* NOOP */
+       data[4] = 0x20000000; /* NOOP */
+       virtex2_send_32(pld_device, 5, data);
+       
+       virtex2_receive_32(pld_device, 1, status);
+       
+       jtag_execute_queue();
+       
+       DEBUG("status: 0x%8.8x", *status);
+       
+       return ERROR_OK;
+}
+
+int virtex2_load(struct pld_device_s *pld_device, char *filename)
+{
+       virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+       xilinx_bit_file_t bit_file;
+       int retval;
+       int i;
+
+       scan_field_t field;
+
+       field.device = virtex2_info->chain_pos;
+       field.out_mask = NULL;
+       field.in_value = NULL;
+       field.in_check_value = NULL;
+       field.in_check_mask = NULL;
+       field.in_handler = NULL;
+       field.in_handler_priv = NULL;
+       
+       if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)
+               return retval;
+       
+       jtag_add_end_state(TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */
+       jtag_execute_queue();
+       jtag_add_sleep(1000);
+       
+       virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
+       jtag_execute_queue();
+       
+       for (i = 0; i < bit_file.length; i++)
+               bit_file.data[i] = flip_u32(bit_file.data[i], 8);
+       
+       field.num_bits = bit_file.length * 8;
+       field.out_value = bit_file.data;
+
+       jtag_add_dr_scan(1, &field, TAP_PD);
+       jtag_execute_queue();
+       
+       jtag_add_statemove(TAP_TLR);
+       
+       jtag_add_end_state(TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
+       jtag_add_runtest(13, TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+       virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
+       jtag_add_runtest(13, TAP_RTI);
+       virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+       jtag_execute_queue();
+
+       return ERROR_OK;
+}
+
+int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       pld_device_t *device;
+       virtex2_pld_device_t *virtex2_info;
+       u32 status;
+       
+       if (argc < 1)
+       {
+               command_print(cmd_ctx, "usage: virtex2 read_stat <num>");
+               return ERROR_OK;
+       }
+       
+       device = get_pld_device_by_num(strtoul(args[0], NULL, 0));
+       if (!device)
+       {
+               command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);
+               return ERROR_OK;
+       }
+
+       virtex2_info = device->driver_priv;
+       
+       virtex2_read_stat(device, &status);
+       
+       command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);
+       
+       return ERROR_OK;
+}
+
+int virtex2_register_commands(struct command_context_s *cmd_ctx)
+{
+       command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");
+
+       register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,
+                                        "read Virtex-II status register");
+
+       return ERROR_OK;
+}
+
+int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)
+{
+       virtex2_pld_device_t *virtex2_info;
+       
+       if (argc < 2)
+       {
+               WARNING("incomplete pld device 'virtex2' configuration");
+               return ERROR_PLD_DEVICE_INVALID;
+       }
+       
+       virtex2_info = malloc(sizeof(virtex2_pld_device_t));
+       pld_device->driver_priv = virtex2_info;
+       
+       virtex2_info->chain_pos = strtoul(args[1], NULL, 0);
+       
+       return ERROR_OK;
+}
diff --git a/src/pld/virtex2.h b/src/pld/virtex2.h
new file mode 100644 (file)
index 0000000..1b5865d
--- /dev/null
@@ -0,0 +1,31 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef VIRTEX2_H
+#define VIRTEX2_H
+
+#include "pld.h"
+#include "xilinx_bit.h"
+
+typedef struct virtex2_pld_device_s
+{
+       int chain_pos;
+} virtex2_pld_device_t;
+
+#endif /* VIRTEX2_H */
diff --git a/src/pld/xilinx_bit.c b/src/pld/xilinx_bit.c
new file mode 100644 (file)
index 0000000..7bf72b2
--- /dev/null
@@ -0,0 +1,146 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xilinx_bit.h"
+
+#include "pld.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+int read_section(FILE *input_file, int length_size, char section, u32 *buffer_length, u8 **buffer) 
+{
+       u8 length_buffer[4];
+       u32 length;
+       char section_char;
+       int read_count;
+       
+       if ((length_size != 2) && (length_size != 4))
+       {
+               ERROR("BUG: length_size neither 2 nor 4");
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       if ((read_count = fread(&section_char, 1, 1, input_file)) != 1)
+       {
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+       
+       if (section_char != section)
+       {
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       if ((read_count = fread(length_buffer, 1, length_size, input_file)) != length_size)
+       {
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+       
+       if (length_size == 4)
+               length = be_to_h_u32(length_buffer);
+
+       if (length_size == 2)
+               length = be_to_h_u16(length_buffer);
+               
+       if (buffer_length)
+               *buffer_length = length;
+       
+       *buffer = malloc(length);
+       
+       if ((read_count = fread(*buffer, 1, length, input_file)) != length)
+       {
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+       
+       return ERROR_OK;
+}
+
+int xilinx_read_bit_file(xilinx_bit_file_t *bit_file, char *filename)
+{
+       FILE *input_file;
+       struct stat input_stat;
+       int read_count;
+       
+       if (!filename || !bit_file)
+               return ERROR_INVALID_ARGUMENTS;
+       
+       if (stat(filename, &input_stat) == -1)
+       {
+               ERROR("couldn't stat() %s: %s", filename, strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+
+       if (S_ISDIR(input_stat.st_mode))
+       {
+               ERROR("%s is a directory", filename);
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+               
+       if (input_stat.st_size == 0){
+               ERROR("Empty file %s", filename);
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+               
+       if (!(input_file = fopen(filename, "rb")))
+       {
+               ERROR("couldn't open %s: %s", filename, strerror(errno));
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+       
+       if ((read_count = fread(bit_file->unknown_header, 1, 13, input_file)) != 13)
+       {
+               ERROR("couldn't read unknown_header from file '%s'", filename);
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       }
+       
+       if (read_section(input_file, 2, 'a', NULL, &bit_file->source_file) != ERROR_OK)
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       
+       if (read_section(input_file, 2, 'b', NULL, &bit_file->part_name) != ERROR_OK)
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       
+       if (read_section(input_file, 2, 'c', NULL, &bit_file->date) != ERROR_OK)
+               return ERROR_PLD_FILE_LOAD_FAILED;
+
+       if (read_section(input_file, 2, 'd', NULL, &bit_file->time) != ERROR_OK)
+               return ERROR_PLD_FILE_LOAD_FAILED;
+
+       if (read_section(input_file, 4, 'e', &bit_file->length, &bit_file->data) != ERROR_OK)
+               return ERROR_PLD_FILE_LOAD_FAILED;
+       
+       DEBUG("bit_file: %s %s %s,%s %i", bit_file->source_file, bit_file->part_name,
+               bit_file->date, bit_file->time, bit_file->length);
+       
+       fclose(input_file);
+       
+       return ERROR_OK;
+}
diff --git a/src/pld/xilinx_bit.h b/src/pld/xilinx_bit.h
new file mode 100644 (file)
index 0000000..505957a
--- /dev/null
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef XILINX_BIT_H
+#define XILINX_BIT_H
+
+#include "types.h"
+
+typedef struct xilinx_bit_file_s
+{
+       u8 unknown_header[13];
+       u8 *source_file;
+       u8 *part_name;
+       u8 *date;
+       u8 *time;
+       u32 length;
+       u8 *data;
+} xilinx_bit_file_t;
+
+int xilinx_read_bit_file(xilinx_bit_file_t *bit_file, char *filename);
+
+#endif /* XILINX_BIT_H */
index 00fb2f07856fe0c3d300990a87ceecde212e09a3..3eab03354bc6ceb3386f5a74d4aad0ef9fe1a27f 100644 (file)
@@ -285,7 +285,7 @@ reg_cache_t* armv4_5_build_reg_cache(target_t *target, armv4_5_common_t *armv4_5
        int num_regs = 37;
        reg_cache_t *cache = malloc(sizeof(reg_cache_t));
        reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
-       armv4_5_core_reg_t *arch_info = malloc(sizeof(reg_t) * num_regs);
+       armv4_5_core_reg_t *arch_info = malloc(sizeof(armv4_5_core_reg_t) * num_regs);
        int i;
        
        cache->name = "arm v4/5 registers";
@@ -630,7 +630,7 @@ int armv4_5_run_algorithm(struct target_s *target, int num_mem_params, mem_param
        
        for (i = 0; i <= 16; i++)
        {
-               DEBUG("restoring register %s with value 0x%8.8x", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32));
+               DEBUG("restoring register %s with value 0x%8.8x", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, context[i]);
                buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]);
                ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1;
                ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)