common/recipes-utils/jbi/files/code/jbistub.c (1,911 lines of code) (raw):

/****************************************************************************/ /* */ /* Module: jbistub.c */ /* */ /* Copyright (C) Altera Corporation 1997-2001 */ /* */ /* Description: Jam STAPL ByteCode Player main source file */ /* */ /* Supports Altera ByteBlaster hardware download cable */ /* on Windows 95 and Windows NT operating systems. */ /* (A device driver is required for Windows NT.) */ /* */ /* Also supports BitBlaster hardware download cable on */ /* Windows 95, Windows NT, and UNIX platforms. */ /* */ /* Revisions: 1.1 fixed control port initialization for ByteBlaster */ /* 2.0 added support for STAPL bytecode format, added code */ /* to get printer port address from Windows registry */ /* 2.1 improved messages, fixed delay-calibration bug in */ /* 16-bit DOS port, added support for "alternative */ /* cable X", added option to control whether to reset */ /* the TAP after execution, moved porting macros into */ /* jbiport.h */ /* 2.2 added support for static memory */ /* fixed /W4 warnings */ /* */ /****************************************************************************/ #ifndef NO_ALTERA_STDIO #define NO_ALTERA_STDIO #endif #if ( _MSC_VER >= 800 ) #pragma warning(disable:4115) #pragma warning(disable:4201) #pragma warning(disable:4214) #pragma warning(disable:4514) #endif #include "jbiport.h" #if PORT == WINDOWS #include <windows.h> #else typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; #define TRUE 1 #define FALSE 0 #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifndef OPENBMC #include <io.h> #endif #include <fcntl.h> #ifndef OPENBMC #include <process.h> #endif #if defined(USE_STATIC_MEMORY) #define N_STATIC_MEMORY_KBYTES ((unsigned int) USE_STATIC_MEMORY) #define N_STATIC_MEMORY_BYTES (N_STATIC_MEMORY_KBYTES * 1024) #define POINTER_ALIGNMENT sizeof(DWORD) #else /* USE_STATIC_MEMORY */ #include <malloc.h> #define POINTER_ALIGNMENT sizeof(BYTE) #endif /* USE_STATIC_MEMORY */ #include <time.h> #ifndef OPENBMC #include <conio.h> #endif #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #ifdef OPENBMC //#define VERBOSE //#define DEBUG #include <openbmc/libgpio.h> #include <openbmc/hr_nanosleep.h> #include <openbmc/log.h> #include <errno.h> #include <sys/ioctl.h> #endif #if PORT == DOS #include <bios.h> #endif #include "jbiexprt.h" #if PORT == WINDOWS #define PGDC_IOCTL_GET_DEVICE_INFO_PP 0x00166A00L #define PGDC_IOCTL_READ_PORT_PP 0x00166A04L #define PGDC_IOCTL_WRITE_PORT_PP 0x0016AA08L #define PGDC_IOCTL_PROCESS_LIST_PP 0x0016AA1CL #define PGDC_READ_INFO 0x0a80 #define PGDC_READ_PORT 0x0a81 #define PGDC_WRITE_PORT 0x0a82 #define PGDC_PROCESS_LIST 0x0a87 #define PGDC_HDLC_NTDRIVER_VERSION 2 #define PORT_IO_BUFFER_SIZE 256 #endif #if PORT == WINDOWS #ifdef __BORLANDC__ /* create dummy inp() and outp() functions for Borland 32-bit compile */ WORD inp(WORD address) { address = address; return(0); } void outp(WORD address, WORD data) { address = address; data = data; } #else #pragma intrinsic (inp, outp) #endif #endif /* * For Borland C compiler (16-bit), set the stack size */ #if PORT == DOS #ifdef __BORLANDC__ extern unsigned int _stklen = 50000; #endif #endif /************************************************************************ * * Global variables */ /* file buffer for Jam STAPL ByteCode input file */ #if PORT == DOS unsigned char **file_buffer = NULL; #else unsigned char *file_buffer = NULL; #endif long file_pointer = 0L; long file_length = 0L; /* delay count for one millisecond delay */ long one_ms_delay = 0L; /* serial port interface available on all platforms */ BOOL jtag_hardware_initialized = FALSE; char *serial_port_name = NULL; BOOL specified_com_port = FALSE; int com_port = -1; void initialize_jtag_hardware(void); void close_jtag_hardware(void); #ifdef OPENBMC static int g_swio = 0; static int g_tck_offset = -1; static int g_tms_offset = -1; static int g_tdo_offset = -1; static int g_tdi_offset = -1; static const char *g_tck_shadow; static const char *g_tms_shadow; static const char *g_tdo_shadow; static const char *g_tdi_shadow; static int g_jtag_dev = -1; static gpio_desc_t *g_gpio_tck; static gpio_desc_t *g_gpio_tms; static gpio_desc_t *g_gpio_tdo; static gpio_desc_t *g_gpio_tdi; static int g_sysfs_tck_fd = -1; static int g_sysfs_tms_fd = -1; static int g_sysfs_tdi_fd = -1; static int g_sysfs_tdo_fd = -1; static int (*jtag_io_func)(int, int, int); #endif #if defined(USE_STATIC_MEMORY) unsigned char static_memory_heap[N_STATIC_MEMORY_BYTES] = { 0 }; #endif /* USE_STATIC_MEMORY */ #if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) unsigned int n_bytes_allocated = 0; #endif /* USE_STATIC_MEMORY || MEM_TRACKER */ #if defined(MEM_TRACKER) unsigned int peak_memory_usage = 0; unsigned int peak_allocations = 0; unsigned int n_allocations = 0; #if defined(USE_STATIC_MEMORY) unsigned int n_bytes_not_recovered = 0; #endif /* USE_STATIC_MEMORY */ const DWORD BEGIN_GUARD = 0x01234567; const DWORD END_GUARD = 0x76543210; #endif /* MEM_TRACKER */ #if PORT == WINDOWS || PORT == DOS /* parallel port interface available on PC only */ BOOL specified_lpt_port = FALSE; BOOL specified_lpt_addr = FALSE; int lpt_port = 1; int initial_lpt_ctrl = 0; WORD lpt_addr = 0x3bc; WORD lpt_addr_table[3] = { 0x3bc, 0x378, 0x278 }; BOOL alternative_cable_l = FALSE; BOOL alternative_cable_x = FALSE; void write_byteblaster(int port, int data); int read_byteblaster(int port); #endif #if PORT==WINDOWS #ifndef __BORLANDC__ WORD lpt_addresses_from_registry[4] = { 0 }; #endif #endif #if PORT == WINDOWS /* variables to manage cached I/O under Windows NT */ BOOL windows_nt = FALSE; int port_io_count = 0; HANDLE nt_device_handle = INVALID_HANDLE_VALUE; struct PORT_IO_LIST_STRUCT { USHORT command; USHORT data; } port_io_buffer[PORT_IO_BUFFER_SIZE]; extern void flush_ports(void); BOOL initialize_nt_driver(void); #endif /* function prototypes to allow forward reference */ extern void delay_loop(long count); /* * This structure stores information about each available vector signal */ struct VECTOR_LIST_STRUCT { char *signal_name; int hardware_bit; int vector_index; }; struct VECTOR_LIST_STRUCT vector_list[] = { /* add a record here for each vector signal */ { "", 0, -1 } }; #define VECTOR_SIGNAL_COUNT ((int)(sizeof(vector_list)/sizeof(vector_list[0]))) BOOL verbose = FALSE; /************************************************************************ * * Customized interface functions for Jam STAPL ByteCode Player I/O: * * jbi_jtag_io() * jbi_message() * jbi_delay() */ #ifdef OPENBMC #define JTAG_CHAR_DEV "/dev/jtag0" #ifndef JTAG_SYSFS_DIR #define JTAG_SYSFS_DIR "/sys/devices/platform/ahb/ahb:apb/1e6e4000.jtag/" #endif #define JTAG_SYSFS_TDI JTAG_SYSFS_DIR "tdi" #define JTAG_SYSFS_TDO JTAG_SYSFS_DIR "tdo" #define JTAG_SYSFS_TMS JTAG_SYSFS_DIR "tms" #define JTAG_SYSFS_TCK JTAG_SYSFS_DIR "tck" #define __JTAG_IOCTL_MAGIC 0xb2 #define JTAG_IOCBITBANG _IOW(__JTAG_IOCTL_MAGIC, 6, unsigned int) struct tck_bitbang { unsigned char tms; unsigned char tdi; unsigned char tdo; } __attribute__((__packed__)); static void jtag_swio_write(int fd, int value) { if (lseek(fd, 0, SEEK_SET) < 0) { fprintf(stderr, "%s: lseek failed\n", __func__); return; } if (write(fd, (value) ? "1" : "0", 1) != 1) { fprintf(stderr, "%s: write failed\n", __func__); } return; } static int jtag_swio_read(int fd) { char buf[8] = {0}; if (lseek(fd, 0, SEEK_SET) < 0) { fprintf(stderr, "%s: lseek failed\n", __func__); return -1; } if (read(fd, buf, sizeof(buf) - 1) < 1) { fprintf(stderr, "%s: read failed\n", __func__); return -1; } return (atoi(buf) ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); } #ifndef ARRAY_SIZE #define ARRAY_SIZE(_a) (sizeof(_a) / sizeof((_a)[0])) #endif static int initialize_jtag_swio(void) { int i, fd; struct { const char *path; int flags; int *fd; } jtag_fds[4] = { {JTAG_SYSFS_TDI, O_WRONLY, &g_sysfs_tdi_fd}, {JTAG_SYSFS_TCK, O_WRONLY, &g_sysfs_tck_fd}, {JTAG_SYSFS_TMS, O_WRONLY, &g_sysfs_tms_fd}, {JTAG_SYSFS_TDO, O_RDONLY, &g_sysfs_tdo_fd}, }; if ((g_jtag_dev = open(JTAG_CHAR_DEV, O_RDWR)) < 0) { OBMC_ERROR(errno, "failed to open jtag device %s", JTAG_CHAR_DEV); } else { /* Use ioctl(JTAG_IOCBITBANG) if successfully open Kernel 5.6 JTAG driver */ return 0; } for (i = 0; i < ARRAY_SIZE(jtag_fds); i++) { fd = open(jtag_fds[i].path, jtag_fds[i].flags); if (fd < 0) { fprintf(stderr, "failed to open %s: %s\n", jtag_fds[i].path, strerror(errno)); goto error; } *(jtag_fds[i].fd) = fd; } /* set tck, tms, tdi to low */ jtag_swio_write(g_sysfs_tck_fd, GPIO_VALUE_LOW); jtag_swio_write(g_sysfs_tms_fd, GPIO_VALUE_LOW); jtag_swio_write(g_sysfs_tdi_fd, GPIO_VALUE_LOW); jbi_delay(1); return 0; error: for (i = 0; i < ARRAY_SIZE(jtag_fds); i++) { fd = *(jtag_fds[i].fd); if (fd >= 0) close(fd); } return -1; } static int jbi_jtag_swio(int tms, int tdi, int read_tdo) { int tdo = 0; struct tck_bitbang bitbang; if (!jtag_hardware_initialized) { if (initialize_jtag_swio()) { fprintf(stderr, "%s: initialize_jtag_swio() failed\n", __func__); return -1; } jtag_hardware_initialized = TRUE; } if (g_jtag_dev >= 0) { bitbang.tms = tms ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW; bitbang.tdi = tdi ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW; bitbang.tdo = 0; if (ioctl(g_jtag_dev, JTAG_IOCBITBANG, &bitbang) < 0) { fprintf(stderr, "%s: ioctl(JTAG_IOCBITBANG) failed\n", __func__); return -1; } if (read_tdo) { tdo = bitbang.tdo; } } else { jtag_swio_write(g_sysfs_tms_fd, tms ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); jtag_swio_write(g_sysfs_tdi_fd, tdi ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); /* * if we need to read data, the data should be ready from the * previous clock falling edge. Read it now. */ if (read_tdo && ((tdo = jtag_swio_read(g_sysfs_tdo_fd)) < 0)) { fprintf(stderr, "%s: jtag_swio_read() failed\n", __func__); return -1; } /* do rising edge to clock out the data */ jtag_swio_write(g_sysfs_tck_fd, GPIO_VALUE_HIGH); /* do falling edge clocking */ jtag_swio_write(g_sysfs_tck_fd, GPIO_VALUE_LOW); } OBMC_DEBUG("tms=%d tdi=%d do_read=%d tdo=%d", tms, tdi, read_tdo, tdo); return tdo; } static int initialize_jtag_gpios() { int i; gpio_desc_t *desc; struct { const char *shadow; int offset; gpio_desc_t **desc; } jtag_pins[4] = { {g_tck_shadow, g_tck_offset, &g_gpio_tck}, {g_tms_shadow, g_tms_offset, &g_gpio_tms}, {g_tdi_shadow, g_tdi_offset, &g_gpio_tdi}, {g_tdo_shadow, g_tdo_offset, &g_gpio_tdo}, }; for (i = 0; i < ARRAY_SIZE(jtag_pins); i++) { if (jtag_pins[i].shadow != NULL) desc = gpio_open_by_shadow(jtag_pins[i].shadow); else if (jtag_pins[i].offset >= 0) desc = gpio_open_by_offset(GPIO_CHIP_ASPEED, jtag_pins[i].offset); else goto error; if (desc == NULL) goto error; *(jtag_pins[i].desc) = desc; } /* change GPIO directions, only TDO is input, all others are output */ if (gpio_set_direction(g_gpio_tck, GPIO_DIRECTION_OUT) || gpio_set_direction(g_gpio_tms, GPIO_DIRECTION_OUT) || gpio_set_direction(g_gpio_tdo, GPIO_DIRECTION_IN) || gpio_set_direction(g_gpio_tdi, GPIO_DIRECTION_OUT)) { goto error; } /* set tck, tms, tdi to low */ gpio_set_value(g_gpio_tck, GPIO_VALUE_LOW); gpio_set_value(g_gpio_tms, GPIO_VALUE_LOW); gpio_set_value(g_gpio_tdi, GPIO_VALUE_LOW); jbi_delay(1); OBMC_DEBUG("Opened TCK(GPIO %d), TMS(GPIO %d), " "TDI(GPIO %d), and TDO(GPIO %d)", g_tck_offset, g_tms_offset, g_tdi_offset, g_tdo_offset); return 0; error: for (i = 0; i < ARRAY_SIZE(jtag_pins); i++) { desc = *(jtag_pins[i].desc); if (desc != NULL) gpio_close(desc); } } static int jbi_jtag_gpio(int tms, int tdi, int read_tdo) { int tdo = 0; if (!jtag_hardware_initialized) { if (initialize_jtag_gpios()) { fprintf(stderr, "%s: initialize_jtag_gpios() failed\n", __func__); return -1; } jtag_hardware_initialized = TRUE; } gpio_set_value(g_gpio_tms, tms ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); gpio_set_value(g_gpio_tdi, tdi ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); /* * if we need to read data, the data should be ready from the * previous clock falling edge. Read it now. */ if (read_tdo) { gpio_value_t val; gpio_get_value(g_gpio_tdo, &val); tdo = (val == GPIO_VALUE_HIGH ? 1 : 0); } /* do rising edge to clock out the data */ gpio_set_value(g_gpio_tck, GPIO_VALUE_HIGH); /* do falling edge clocking */ gpio_set_value(g_gpio_tck, GPIO_VALUE_LOW); OBMC_DEBUG("tms=%d tdi=%d do_read=%d tdo=%d", tms, tdi, read_tdo, tdo); return tdo; } int jbi_jtag_io(int tms, int tdi, int read_tdo) { return jtag_io_func(tms, tdi, read_tdo); } #else int jbi_jtag_io(int tms, int tdi, int read_tdo) { int data = 0; int tdo = 0; int i = 0; int result = 0; char ch_data = 0; if (!jtag_hardware_initialized) { initialize_jtag_hardware(); jtag_hardware_initialized = TRUE; } if (specified_com_port) { ch_data = (char) ((tdi ? 0x01 : 0) | (tms ? 0x02 : 0) | 0x60); write(com_port, &ch_data, 1); if (read_tdo) { ch_data = 0x7e; write(com_port, &ch_data, 1); for (i = 0; (i < 100) && (result != 1); ++i) { result = read(com_port, &ch_data, 1); } if (result == 1) { tdo = ch_data & 0x01; } else { fprintf(stderr, "Error: BitBlaster not responding\n"); } } ch_data = (char) ((tdi ? 0x01 : 0) | (tms ? 0x02 : 0) | 0x64); write(com_port, &ch_data, 1); } else { #if PORT == WINDOWS || PORT == DOS data = (alternative_cable_l ? ((tdi ? 0x01 : 0) | (tms ? 0x04 : 0)) : (alternative_cable_x ? ((tdi ? 0x01 : 0) | (tms ? 0x04 : 0) | 0x10) : ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0)))); write_byteblaster(0, data); if (read_tdo) { tdo = read_byteblaster(1); tdo = (alternative_cable_l ? ((tdo & 0x40) ? 1 : 0) : (alternative_cable_x ? ((tdo & 0x10) ? 1 : 0) : ((tdo & 0x80) ? 0 : 1))); } write_byteblaster(0, data | (alternative_cable_l ? 0x02 : (alternative_cable_x ? 0x02: 0x01))); write_byteblaster(0, data); #else /* parallel port interface not available */ tdo = 0; #endif } return (tdo); } #endif void jbi_message(char *message_text) { puts(message_text); fflush(stdout); } void jbi_export_integer(char *key, long value) { if (verbose) { printf("Export: key = \"%s\", value = %ld\n", key, value); fflush(stdout); } } #define HEX_LINE_CHARS 72 #define HEX_LINE_BITS (HEX_LINE_CHARS * 4) char conv_to_hex(unsigned long value) { char c; if (value > 9) { c = (char) (value + ('A' - 10)); } else { c = (char) (value + '0'); } return (c); } void jbi_export_boolean_array(char *key, unsigned char *data, long count) { char string[HEX_LINE_CHARS + 1]; long i, offset; unsigned long size, line, lines, linebits, value, j, k; if (verbose) { if (count > HEX_LINE_BITS) { printf("Export: key = \"%s\", %ld bits, value = HEX\n", key, count); lines = (count + (HEX_LINE_BITS - 1)) / HEX_LINE_BITS; for (line = 0; line < lines; ++line) { if (line < (lines - 1)) { linebits = HEX_LINE_BITS; size = HEX_LINE_CHARS; offset = count - ((line + 1) * HEX_LINE_BITS); } else { linebits = count - ((lines - 1) * HEX_LINE_BITS); size = (linebits + 3) / 4; offset = 0L; } string[size] = '\0'; j = size - 1; value = 0; for (k = 0; k < linebits; ++k) { i = k + offset; if (data[i >> 3] & (1 << (i & 7))) value |= (1 << (i & 3)); if ((i & 3) == 3) { string[j] = conv_to_hex(value); value = 0; --j; } } if ((k & 3) > 0) string[j] = conv_to_hex(value); printf("%s\n", string); } fflush(stdout); } else { size = (count + 3) / 4; string[size] = '\0'; j = size - 1; value = 0; for (i = 0; i < count; ++i) { if (data[i >> 3] & (1 << (i & 7))) value |= (1 << (i & 3)); if ((i & 3) == 3) { string[j] = conv_to_hex(value); value = 0; --j; } } if ((i & 3) > 0) string[j] = conv_to_hex(value); printf("Export: key = \"%s\", %ld bits, value = HEX %s\n", key, count, string); fflush(stdout); } } } void jbi_delay(long microseconds) { #if PORT == WINDOWS /* if Windows NT, flush I/O cache buffer before delay loop */ if (windows_nt && (port_io_count > 0)) flush_ports(); #endif #ifdef OPENBMC hr_nanosleep(microseconds * 1000); #else delay_loop(microseconds * ((one_ms_delay / 1000L) + ((one_ms_delay % 1000L) ? 1 : 0))); #endif } int jbi_vector_map ( int signal_count, char **signals ) { int signal, vector, ch_index, diff; int matched_count = 0; char l, r; for (vector = 0; (vector < VECTOR_SIGNAL_COUNT); ++vector) { vector_list[vector].vector_index = -1; } for (signal = 0; signal < signal_count; ++signal) { diff = 1; for (vector = 0; (diff != 0) && (vector < VECTOR_SIGNAL_COUNT); ++vector) { if (vector_list[vector].vector_index == -1) { ch_index = 0; do { l = signals[signal][ch_index]; r = vector_list[vector].signal_name[ch_index]; diff = (((l >= 'a') && (l <= 'z')) ? (l - ('a' - 'A')) : l) - (((r >= 'a') && (r <= 'z')) ? (r - ('a' - 'A')) : r); ++ch_index; } while ((diff == 0) && (l != '\0') && (r != '\0')); if (diff == 0) { vector_list[vector].vector_index = signal; ++matched_count; } } } } return (matched_count); } int jbi_vector_io ( int signal_count, long *dir_vect, long *data_vect, long *capture_vect ) { int signal, vector, bit; int matched_count = 0; int data = 0; int mask = 0; int dir = 0; int i = 0; int result = 0; char ch_data = 0; if (!jtag_hardware_initialized) { initialize_jtag_hardware(); jtag_hardware_initialized = TRUE; } /* * Collect information about output signals */ for (vector = 0; vector < VECTOR_SIGNAL_COUNT; ++vector) { signal = vector_list[vector].vector_index; if ((signal >= 0) && (signal < signal_count)) { bit = (1 << vector_list[vector].hardware_bit); mask |= bit; if (data_vect[signal >> 5] & (1L << (signal & 0x1f))) data |= bit; if (dir_vect[signal >> 5] & (1L << (signal & 0x1f))) dir |= bit; ++matched_count; } } /* * Write outputs to hardware interface, if any */ if (dir != 0) { if (specified_com_port) { ch_data = (char) (((data >> 6) & 0x01) | (data & 0x02) | ((data << 2) & 0x04) | ((data << 3) & 0x08) | 0x60); write(com_port, &ch_data, 1); } else { #if PORT == WINDOWS || PORT == DOS write_byteblaster(0, data); #endif } } /* * Read the input signals and save information in capture_vect[] */ if ((dir != mask) && (capture_vect != NULL)) { if (specified_com_port) { ch_data = 0x7e; write(com_port, &ch_data, 1); for (i = 0; (i < 100) && (result != 1); ++i) { result = read(com_port, &ch_data, 1); } if (result == 1) { data = ((ch_data << 7) & 0x80) | ((ch_data << 3) & 0x10); } else { fprintf(stderr, "Error: BitBlaster not responding\n"); } } else { #if PORT == WINDOWS || PORT == DOS data = read_byteblaster(1) ^ 0x80; /* parallel port inverts bit 7 */ #endif } for (vector = 0; vector < VECTOR_SIGNAL_COUNT; ++vector) { signal = vector_list[vector].vector_index; if ((signal >= 0) && (signal < signal_count)) { bit = (1 << vector_list[vector].hardware_bit); if ((dir & bit) == 0) /* if it is an input signal... */ { if (data & bit) { capture_vect[signal >> 5] |= (1L << (signal & 0x1f)); } else { capture_vect[signal >> 5] &= ~(unsigned long) (1L << (signal & 0x1f)); } } } } } return (matched_count); } void *jbi_malloc(unsigned int size) { unsigned int n_bytes_to_allocate = #if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) sizeof(unsigned int) + #endif /* USE_STATIC_MEMORY || MEM_TRACKER */ #if defined(MEM_TRACKER) (2 * sizeof(DWORD)) + #endif /* MEM_TRACKER */ (POINTER_ALIGNMENT * ((size + POINTER_ALIGNMENT - 1) / POINTER_ALIGNMENT)); unsigned char *ptr = 0; #if defined(MEM_TRACKER) if ((n_bytes_allocated + n_bytes_to_allocate) > peak_memory_usage) { peak_memory_usage = n_bytes_allocated + n_bytes_to_allocate; } if ((n_allocations + 1) > peak_allocations) { peak_allocations = n_allocations + 1; } #endif /* MEM_TRACKER */ #if defined(USE_STATIC_MEMORY) if ((n_bytes_allocated + n_bytes_to_allocate) <= N_STATIC_MEMORY_BYTES) { ptr = (&(static_memory_heap[n_bytes_allocated])); } #else /* USE_STATIC_MEMORY */ ptr = (unsigned char *) malloc(n_bytes_to_allocate); #endif /* USE_STATIC_MEMORY */ #if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) if (ptr != 0) { unsigned int i = 0; #if defined(MEM_TRACKER) for (i = 0; i < sizeof(DWORD); ++i) { *ptr = (unsigned char) (BEGIN_GUARD >> (8 * i)); ++ptr; } #endif /* MEM_TRACKER */ for (i = 0; i < sizeof(unsigned int); ++i) { *ptr = (unsigned char) (size >> (8 * i)); ++ptr; } #if defined(MEM_TRACKER) for (i = 0; i < sizeof(DWORD); ++i) { *(ptr + size + i) = (unsigned char) (END_GUARD >> (8 * i)); /* don't increment ptr */ } ++n_allocations; #endif /* MEM_TRACKER */ n_bytes_allocated += n_bytes_to_allocate; } #endif /* USE_STATIC_MEMORY || MEM_TRACKER */ return ptr; } void jbi_free(void *ptr) { if ( #if defined(MEM_TRACKER) (n_allocations > 0) && #endif /* MEM_TRACKER */ (ptr != 0) ) { unsigned char *tmp_ptr = (unsigned char *) ptr; #if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) unsigned int n_bytes_to_free = 0; unsigned int i = 0; unsigned int size = 0; #endif /* USE_STATIC_MEMORY || MEM_TRACKER */ #if defined(MEM_TRACKER) DWORD begin_guard = 0; DWORD end_guard = 0; tmp_ptr -= sizeof(DWORD); #endif /* MEM_TRACKER */ #if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) tmp_ptr -= sizeof(unsigned int); #endif /* USE_STATIC_MEMORY || MEM_TRACKER */ ptr = tmp_ptr; #if defined(MEM_TRACKER) for (i = 0; i < sizeof(DWORD); ++i) { begin_guard |= (((DWORD)(*tmp_ptr)) << (8 * i)); ++tmp_ptr; } #endif /* MEM_TRACKER */ #if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) for (i = 0; i < sizeof(unsigned int); ++i) { size |= (((unsigned int)(*tmp_ptr)) << (8 * i)); ++tmp_ptr; } #endif /* USE_STATIC_MEMORY || MEM_TRACKER */ #if defined(MEM_TRACKER) tmp_ptr += size; for (i = 0; i < sizeof(DWORD); ++i) { end_guard |= (((DWORD)(*tmp_ptr)) << (8 * i)); ++tmp_ptr; } if ((begin_guard != BEGIN_GUARD) || (end_guard != END_GUARD)) { fprintf(stderr, "Error: memory corruption detected for allocation #%d... bad %s guard\n", n_allocations, (begin_guard != BEGIN_GUARD) ? "begin" : "end"); } --n_allocations; #endif /* MEM_TRACKER */ #if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) n_bytes_to_free = #if defined(MEM_TRACKER) (2 * sizeof(DWORD)) + #endif /* MEM_TRACKER */ sizeof(unsigned int) + (POINTER_ALIGNMENT * ((size + POINTER_ALIGNMENT - 1) / POINTER_ALIGNMENT)); #endif /* USE_STATIC_MEMORY || MEM_TRACKER */ #if defined(USE_STATIC_MEMORY) if ((((unsigned long) ptr - (unsigned long) static_memory_heap) + n_bytes_to_free) == (unsigned long) n_bytes_allocated) { n_bytes_allocated -= n_bytes_to_free; } #if defined(MEM_TRACKER) else { n_bytes_not_recovered += n_bytes_to_free; } #endif /* MEM_TRACKER */ #else /* USE_STATIC_MEMORY */ #if defined(MEM_TRACKER) n_bytes_allocated -= n_bytes_to_free; #endif /* MEM_TRACKER */ free(ptr); #endif /* USE_STATIC_MEMORY */ } #if defined(MEM_TRACKER) else { if (ptr != 0) { fprintf(stderr, "Error: attempt to free unallocated memory\n"); } } #endif /* MEM_TRACKER */ } /************************************************************************ * * get_tick_count() -- Get system tick count in milliseconds * * for DOS, use BIOS function _bios_timeofday() * for WINDOWS use GetTickCount() function * for UNIX use clock() system function */ DWORD get_tick_count(void) { DWORD tick_count = 0L; #if PORT == WINDOWS tick_count = GetTickCount(); #elif PORT == DOS _bios_timeofday(_TIME_GETCLOCK, (long *)&tick_count); tick_count *= 55L; /* convert to milliseconds */ #else /* assume clock() function returns microseconds */ tick_count = (DWORD) (clock() / 1000L); #endif return (tick_count); } #define DELAY_SAMPLES 10 #define DELAY_CHECK_LOOPS 10000 void calibrate_delay(void) { int sample = 0; int count = 0; DWORD tick_count1 = 0L; DWORD tick_count2 = 0L; one_ms_delay = 0L; #if PORT == WINDOWS || PORT == DOS || defined(OPENBMC) for (sample = 0; sample < DELAY_SAMPLES; ++sample) { count = 0; tick_count1 = get_tick_count(); while ((tick_count2 = get_tick_count()) == tick_count1) {}; do { delay_loop(DELAY_CHECK_LOOPS); count++; } while ((tick_count1 = get_tick_count()) == tick_count2); one_ms_delay += ((DELAY_CHECK_LOOPS * (DWORD)count) / (tick_count1 - tick_count2)); } one_ms_delay /= DELAY_SAMPLES; #else /* This is system-dependent! Update this number for target system */ one_ms_delay = 1000L; #endif } char *error_text[] = { /* JBIC_SUCCESS 0 */ "success", /* JBIC_OUT_OF_MEMORY 1 */ "out of memory", /* JBIC_IO_ERROR 2 */ "file access error", /* JAMC_SYNTAX_ERROR 3 */ "syntax error", /* JBIC_UNEXPECTED_END 4 */ "unexpected end of file", /* JBIC_UNDEFINED_SYMBOL 5 */ "undefined symbol", /* JAMC_REDEFINED_SYMBOL 6 */ "redefined symbol", /* JBIC_INTEGER_OVERFLOW 7 */ "integer overflow", /* JBIC_DIVIDE_BY_ZERO 8 */ "divide by zero", /* JBIC_CRC_ERROR 9 */ "CRC mismatch", /* JBIC_INTERNAL_ERROR 10 */ "internal error", /* JBIC_BOUNDS_ERROR 11 */ "bounds error", /* JAMC_TYPE_MISMATCH 12 */ "type mismatch", /* JAMC_ASSIGN_TO_CONST 13 */ "assignment to constant", /* JAMC_NEXT_UNEXPECTED 14 */ "NEXT unexpected", /* JAMC_POP_UNEXPECTED 15 */ "POP unexpected", /* JAMC_RETURN_UNEXPECTED 16 */ "RETURN unexpected", /* JAMC_ILLEGAL_SYMBOL 17 */ "illegal symbol name", /* JBIC_VECTOR_MAP_FAILED 18 */ "vector signal name not found", /* JBIC_USER_ABORT 19 */ "execution cancelled", /* JBIC_STACK_OVERFLOW 20 */ "stack overflow", /* JBIC_ILLEGAL_OPCODE 21 */ "illegal instruction code", /* JAMC_PHASE_ERROR 22 */ "phase error", /* JAMC_SCOPE_ERROR 23 */ "scope error", /* JBIC_ACTION_NOT_FOUND 24 */ "action not found", }; #define MAX_ERROR_CODE (int)((sizeof(error_text)/sizeof(error_text[0]))+1) /************************************************************************/ int main(int argc, char **argv) { BOOL help = FALSE; BOOL error = FALSE; char *filename = NULL; long offset = 0L; long error_address = 0L; JBI_RETURN_TYPE crc_result = JBIC_SUCCESS; JBI_RETURN_TYPE exec_result = JBIC_SUCCESS; unsigned short expected_crc = 0; unsigned short actual_crc = 0; char key[33] = {0}; char value[257] = {0}; int exit_status = 0; int arg = 0; int exit_code = 0; int format_version = 0; time_t start_time = 0; time_t end_time = 0; int time_delta = 0; char *workspace = NULL; char *action = NULL; char *init_list[10]; int init_count = 0; FILE *fp = NULL; struct stat sbuf; long workspace_size = 0; char *exit_string = NULL; int reset_jtag = 1; int execute_program = 1; int action_count = 0; int procedure_count = 0; int index = 0; char *action_name = NULL; char *description = NULL; JBI_PROCINFO *procedure_list = NULL; JBI_PROCINFO *procptr = NULL; char *endptr; verbose = FALSE; init_list[0] = NULL; /* print out the version string and copyright message */ fprintf(stderr, "Jam STAPL ByteCode Player Version 2.2\nCopyright (C) 1998-2001 Altera Corporation\n\n"); for (arg = 1; arg < argc; arg++) { #if PORT == UNIX if (argv[arg][0] == '-') #else if ((argv[arg][0] == '-') || (argv[arg][0] == '/')) #endif { switch(toupper(argv[arg][1])) { case 'A': /* set action name */ if (action == NULL) { action = &argv[arg][2]; } else { error = TRUE; } break; #if PORT == WINDOWS || PORT == DOS case 'C': /* Use alternative ISP download cable */ if(toupper(argv[arg][2]) == 'L') alternative_cable_l = TRUE; else if(toupper(argv[arg][2]) == 'X') alternative_cable_x = TRUE; break; #endif case 'D': /* initialization list */ if (argv[arg][2] == '"') { init_list[init_count] = &argv[arg][3]; } else { init_list[init_count] = &argv[arg][2]; } init_list[++init_count] = NULL; break; #if PORT == WINDOWS || PORT == DOS case 'P': /* set LPT port address */ specified_lpt_port = TRUE; if (sscanf(&argv[arg][2], "%d", &lpt_port) != 1) error = TRUE; if ((lpt_port < 1) || (lpt_port > 3)) error = TRUE; if (error) { if (sscanf(&argv[arg][2], "%x", &lpt_port) == 1) { if ((lpt_port == 0x3bc) || (lpt_port == 0x378) || (lpt_port == 0x278)) { error = FALSE; specified_lpt_addr = TRUE; lpt_addr = (WORD) lpt_port; lpt_port = 1; } } } break; #endif case 'R': /* don't reset the JTAG chain after use */ reset_jtag = 0; break; #ifdef OPENBMC case 'G': /* GPIO directory */ switch (toupper(argv[arg][2])) { case 'C': g_tck_offset = strtol(&argv[arg][3], &endptr, 0); if (endptr == &argv[arg][3]) g_tck_shadow = &argv[arg][3]; break; case 'S': g_tms_offset = strtol(&argv[arg][3], &endptr, 0); if (endptr == &argv[arg][3]) g_tms_shadow = &argv[arg][3]; break; case 'I': g_tdi_offset = strtol(&argv[arg][3], &endptr, 0); if (endptr == &argv[arg][3]) g_tdi_shadow = &argv[arg][3]; break; case 'O': g_tdo_offset = strtol(&argv[arg][3], &endptr, 0); if (endptr == &argv[arg][3]) g_tdo_shadow = &argv[arg][3]; break; } jtag_io_func = jbi_jtag_gpio; break; case 'W': /* use software mode to control jtag pins */ g_swio = 1; jtag_io_func = jbi_jtag_swio; break; #else case 'S': /* set serial port address */ serial_port_name = &argv[arg][2]; specified_com_port = TRUE; break; #endif case 'M': /* set memory size */ if (sscanf(&argv[arg][2], "%ld", &workspace_size) != 1) error = TRUE; if (workspace_size == 0) error = TRUE; break; case 'H': /* help */ help = TRUE; break; case 'V': /* verbose */ verbose = TRUE; break; case 'I': /* show info only, do not execute */ verbose = TRUE; execute_program = 0; break; default: error = TRUE; break; } } else { /* it's a filename */ if (filename == NULL) { filename = argv[arg]; } else { /* error -- we already found a filename */ error = TRUE; } } if (error) { fprintf(stderr, "Illegal argument: \"%s\"\n", argv[arg]); help = TRUE; error = FALSE; } } #if PORT == WINDOWS || PORT == DOS if (specified_lpt_port && specified_com_port) { fprintf(stderr, "Error: -s and -p options may not be used together\n\n"); help = TRUE; } #endif #ifdef OPENBMC if (execute_program) { int pins = 0; if (g_tck_shadow != NULL || g_tck_offset >= 0) pins++; if (g_tms_shadow != NULL || g_tms_offset >= 0) pins++; if (g_tdi_shadow != NULL || g_tdi_offset >= 0) pins++; if (g_tdo_shadow != NULL || g_tdo_offset >= 0) pins++; if (!g_swio && (pins < 4)) { fprintf(stderr, "Error: -gc, -gs, -gi, and -go must be specified\n"); help = TRUE; } } #endif if (help || (filename == NULL)) { fprintf(stderr, "Usage: jbi [options] <filename>\n"); fprintf(stderr, "\nAvailable options:\n"); fprintf(stderr, " -h : show help message\n"); fprintf(stderr, " -v : show verbose messages\n"); fprintf(stderr, " -i : show file info only - does not execute any action\n"); fprintf(stderr, " -a<action> : specify an action name (Jam STAPL)\n"); fprintf(stderr, " -d<var=val> : initialize variable to specified value (Jam 1.1)\n"); fprintf(stderr, " -d<proc=1> : enable optional procedure (Jam STAPL)\n"); fprintf(stderr, " -d<proc=0> : disable recommended procedure (Jam STAPL)\n"); #if PORT == WINDOWS || PORT == DOS fprintf(stderr, " -p<port> : parallel port number or address (for ByteBlaster)\n"); fprintf(stderr, " -c<cable> : alternative download cable compatibility: -cl or -cx\n"); #endif #ifdef OPENBMC fprintf(stderr, " -gc<clock> : GPIO directory for TCK\n"); fprintf(stderr, " -gs<clock> : GPIO directory for TMS\n"); fprintf(stderr, " -gi<clock> : GPIO directory for TDI\n"); fprintf(stderr, " -go<clock> : GPIO directory for TDO\n"); #else fprintf(stderr, " -s<port> : serial port name (for BitBlaster)\n"); #endif fprintf(stderr, " -r : don't reset JTAG TAP after use\n"); exit_status = 1; } else if ((workspace_size > 0) && ((workspace = (char *) jbi_malloc((size_t) workspace_size)) == NULL)) { fprintf(stderr, "Error: can't allocate memory (%d Kbytes)\n", (int) (workspace_size / 1024L)); exit_status = 1; } else if (access(filename, 0) != 0) { fprintf(stderr, "Error: can't access file \"%s\"\n", filename); exit_status = 1; } else { /* get length of file */ if (stat(filename, &sbuf) == 0) file_length = sbuf.st_size; if ((fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "Error: can't open file \"%s\"\n", filename); exit_status = 1; } else { /* * Read entire file into a buffer */ #if PORT == DOS int pages = 1 + (int) (file_length >> 14L); int page; file_buffer = (unsigned char **) jbi_malloc( (size_t) (pages * sizeof(char *))); for (page = 0; page < pages; ++page) { /* allocate enough 16K blocks to store the file */ file_buffer[page] = (unsigned char *) jbi_malloc (0x4000); if (file_buffer[page] == NULL) { /* flag error and break out of loop */ file_buffer = NULL; page = pages; } } #else file_buffer = (unsigned char *) jbi_malloc((size_t) file_length); #endif if (file_buffer == NULL) { fprintf(stderr, "Error: can't allocate memory (%d Kbytes)\n", (int) (file_length / 1024L)); exit_status = 1; } else { #if PORT == DOS int pages = 1 + (int) (file_length >> 14L); int page; size_t page_size = 0x4000; for (page = 0; (page < pages) && (exit_status == 0); ++page) { if (page == (pages - 1)) { /* last page may not be full 16K bytes */ page_size = (size_t) (file_length & 0x3fffL); } if (fread(file_buffer[page], 1, page_size, fp) != page_size) { fprintf(stderr, "Error reading file \"%s\"\n", filename); exit_status = 1; } } #else if (fread(file_buffer, 1, (size_t) file_length, fp) != (size_t) file_length) { fprintf(stderr, "Error reading file \"%s\"\n", filename); exit_status = 1; } #endif } fclose(fp); } if (exit_status == 0) { /* * Get Operating System type */ #if PORT == WINDOWS windows_nt = !(GetVersion() & 0x80000000); #endif /* * Calibrate the delay loop function */ calibrate_delay(); /* * Check CRC */ crc_result = jbi_check_crc(file_buffer, file_length, &expected_crc, &actual_crc); if (verbose || (crc_result == JBIC_CRC_ERROR)) { switch (crc_result) { case JBIC_SUCCESS: printf("CRC matched: CRC value = %04X\n", actual_crc); break; case JBIC_CRC_ERROR: printf("CRC mismatch: expected %04X, actual %04X\n", expected_crc, actual_crc); break; case JBIC_UNEXPECTED_END: printf("Expected CRC not found, actual CRC value = %04X\n", actual_crc); break; case JBIC_IO_ERROR: printf("Error: File format is not recognized.\n"); exit(1); break; default: printf("CRC function returned error code %d\n", crc_result); break; } } if (verbose) { /* * Display file format version */ jbi_get_file_info(file_buffer, file_length, &format_version, &action_count, &procedure_count); printf("File format is %s ByteCode format\n", (format_version == 2) ? "Jam STAPL" : "pre-standardized Jam 1.1"); /* * Dump out NOTE fields */ while (jbi_get_note(file_buffer, file_length, &offset, key, value, 256) == 0) { printf("NOTE \"%s\" = \"%s\"\n", key, value); } /* * Dump the action table */ if ((format_version == 2) && (action_count > 0)) { printf("\nActions available in this file:\n"); for (index = 0; index < action_count; ++index) { jbi_get_action_info(file_buffer, file_length, index, &action_name, &description, &procedure_list); if (description == NULL) { printf("%s\n", action_name); } else { printf("%s \"%s\"\n", action_name, description); } #if PORT == DOS if (action_name != NULL) jbi_free(action_name); if (description != NULL) jbi_free(description); #endif procptr = procedure_list; while (procptr != NULL) { if (procptr->attributes != 0) { printf(" %s (%s)\n", procptr->name, (procptr->attributes == 1) ? "optional" : "recommended"); } #if PORT == DOS if (procptr->name != NULL) jbi_free(procptr->name); #endif procedure_list = procptr->next; jbi_free(procptr); procptr = procedure_list; } } /* add a blank line before execution messages */ if (execute_program) printf("\n"); } } if (execute_program) { /* * Execute the Jam STAPL ByteCode program */ time(&start_time); exec_result = jbi_execute(file_buffer, file_length, workspace, workspace_size, action, init_list, reset_jtag, &error_address, &exit_code, &format_version); time(&end_time); if (exec_result == JBIC_SUCCESS) { if (format_version == 2) { switch (exit_code) { case 0: exit_string = "Success"; break; case 1: exit_string = "Checking chain failure"; break; case 2: exit_string = "Reading IDCODE failure"; break; case 3: exit_string = "Reading USERCODE failure"; break; case 4: exit_string = "Reading UESCODE failure"; break; case 5: exit_string = "Entering ISP failure"; break; case 6: exit_string = "Unrecognized device"; break; case 7: exit_string = "Device revision is not supported"; break; case 8: exit_string = "Erase failure"; break; case 9: exit_string = "Device is not blank"; break; case 10: exit_string = "Device programming failure"; break; case 11: exit_string = "Device verify failure"; break; case 12: exit_string = "Read failure"; break; case 13: exit_string = "Calculating checksum failure"; break; case 14: exit_string = "Setting security bit failure"; break; case 15: exit_string = "Querying security bit failure"; break; case 16: exit_string = "Exiting ISP failure"; break; case 17: exit_string = "Performing system test failure"; break; default: exit_string = "Unknown exit code"; break; } } else { switch (exit_code) { case 0: exit_string = "Success"; break; case 1: exit_string = "Illegal initialization values"; break; case 2: exit_string = "Unrecognized device"; break; case 3: exit_string = "Device revision is not supported"; break; case 4: exit_string = "Device programming failure"; break; case 5: exit_string = "Device is not blank"; break; case 6: exit_string = "Device verify failure"; break; case 7: exit_string = "SRAM configuration failure"; break; default: exit_string = "Unknown exit code"; break; } } printf("Exit code = %d... %s\n", exit_code, exit_string); } else if ((format_version == 2) && (exec_result == JBIC_ACTION_NOT_FOUND)) { if ((action == NULL) || (*action == '\0')) { printf("Error: no action specified for Jam STAPL file.\nProgram terminated.\n"); } else { printf("Error: action \"%s\" is not supported for this Jam STAPL file.\nProgram terminated.\n", action); } } else if (exec_result < MAX_ERROR_CODE) { printf("Error at address %ld: %s.\nProgram terminated.\n", error_address, error_text[exec_result]); } else { printf("Unknown error code %ld\n", exec_result); } /* * Print out elapsed time */ if (verbose) { time_delta = (int) (end_time - start_time); printf("Elapsed time = %02u:%02u:%02u\n", time_delta / 3600, /* hours */ (time_delta % 3600) / 60, /* minutes */ time_delta % 60); /* seconds */ } } } } if (jtag_hardware_initialized) close_jtag_hardware(); if (workspace != NULL) jbi_free(workspace); if (file_buffer != NULL) jbi_free(file_buffer); #if defined(MEM_TRACKER) if (verbose) { #if defined(USE_STATIC_MEMORY) fprintf(stdout, "Memory Usage Info: static memory size = %ud (%dKB)\n", N_STATIC_MEMORY_BYTES, N_STATIC_MEMORY_KBYTES); #endif /* USE_STATIC_MEMORY */ fprintf(stdout, "Memory Usage Info: peak memory usage = %ud (%dKB)\n", peak_memory_usage, (peak_memory_usage + 1023) / 1024); fprintf(stdout, "Memory Usage Info: peak allocations = %d\n", peak_allocations); #if defined(USE_STATIC_MEMORY) if ((n_bytes_allocated - n_bytes_not_recovered) != 0) { fprintf(stdout, "Memory Usage Info: bytes still allocated = %d (%dKB)\n", (n_bytes_allocated - n_bytes_not_recovered), ((n_bytes_allocated - n_bytes_not_recovered) + 1023) / 1024); } #else /* USE_STATIC_MEMORY */ if (n_bytes_allocated != 0) { fprintf(stdout, "Memory Usage Info: bytes still allocated = %d (%dKB)\n", n_bytes_allocated, (n_bytes_allocated + 1023) / 1024); } #endif /* USE_STATIC_MEMORY */ if (n_allocations != 0) { fprintf(stdout, "Memory Usage Info: allocations not freed = %d\n", n_allocations); } } #endif /* MEM_TRACKER */ return (exit_status); } #if PORT==WINDOWS #ifndef __BORLANDC__ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SEARCH_DYN_DATA * * Searches recursively in Windows 95/98 Registry for parallel port info * under HKEY_DYN_DATA registry key. Called by search_local_machine(). */ void search_dyn_data ( char *dd_path, char *hardware_key, int lpt ) { DWORD index; DWORD size; DWORD type; LONG result; HKEY key; int length; WORD address; char buffer[1024]; FILETIME last_write = {0}; WORD *word_ptr; int i; length = strlen(dd_path); if (RegOpenKeyEx( HKEY_DYN_DATA, dd_path, 0L, KEY_READ, &key) == ERROR_SUCCESS) { size = 1023; if (RegQueryValueEx( key, "HardWareKey", NULL, &type, (unsigned char *) buffer, &size) == ERROR_SUCCESS) { if ((type == REG_SZ) && (stricmp(buffer, hardware_key) == 0)) { size = 1023; if (RegQueryValueEx( key, "Allocation", NULL, &type, (unsigned char *) buffer, &size) == ERROR_SUCCESS) { /* * By "inspection", I have found five cases: size 32, 48, * 56, 60, and 80 bytes. The port address seems to be * located at different offsets in the buffer for these * five cases, as shown below. If a valid port address * is not found, or the size is not one of these known * sizes, then I search through the entire buffer and * look for a value which is a valid port address. */ word_ptr = (WORD *) buffer; if ((type == REG_BINARY) && (size == 32)) { address = word_ptr[10]; } else if ((type == REG_BINARY) && (size == 48)) { address = word_ptr[18]; } else if ((type == REG_BINARY) && (size == 56)) { address = word_ptr[22]; } else if ((type == REG_BINARY) && (size == 60)) { address = word_ptr[24]; } else if ((type == REG_BINARY) && (size == 80)) { address = word_ptr[24]; } else address = 0; /* if not found, search through entire buffer */ i = 0; while ((i < (int) (size / 2)) && (address != 0x278) && (address != 0x27C) && (address != 0x378) && (address != 0x37C) && (address != 0x3B8) && (address != 0x3BC)) { if ((word_ptr[i] == 0x278) || (word_ptr[i] == 0x27C) || (word_ptr[i] == 0x378) || (word_ptr[i] == 0x37C) || (word_ptr[i] == 0x3B8) || (word_ptr[i] == 0x3BC)) { address = word_ptr[i]; } ++i; } if ((address == 0x278) || (address == 0x27C) || (address == 0x378) || (address == 0x37C) || (address == 0x3B8) || (address == 0x3BC)) { lpt_addresses_from_registry[lpt] = address; } } } } index = 0; do { size = 1023; result = RegEnumKeyEx( key, index++, buffer, &size, NULL, NULL, NULL, &last_write); if (result == ERROR_SUCCESS) { dd_path[length] = '\\'; dd_path[length + 1] = '\0'; strcpy(&dd_path[length + 1], buffer); search_dyn_data(dd_path, hardware_key, lpt); dd_path[length] = '\0'; } } while (result == ERROR_SUCCESS); RegCloseKey(key); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * SEARCH_LOCAL_MACHINE * * Searches recursively in Windows 95/98 Registry for parallel port info * under HKEY_LOCAL_MACHINE\Enum. When parallel port is found, calls * search_dyn_data() to get the port address. */ void search_local_machine ( char *lm_path, char *dd_path ) { DWORD index; DWORD size; DWORD type; LONG result; HKEY key; int length; char buffer[1024]; FILETIME last_write = {0}; length = strlen(lm_path); if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, lm_path, 0L, KEY_READ, &key) == ERROR_SUCCESS) { size = 1023; if (RegQueryValueEx( key, "PortName", NULL, &type, (unsigned char *) buffer, &size) == ERROR_SUCCESS) { if ((type == REG_SZ) && (size == 5) && (buffer[0] == 'L') && (buffer[1] == 'P') && (buffer[2] == 'T') && (buffer[3] >= '1') && (buffer[3] <= '4') && (buffer[4] == '\0')) { /* we found the entry in HKEY_LOCAL_MACHINE, now we need to */ /* find the corresponding entry under HKEY_DYN_DATA. */ /* add 5 to lm_path to skip over "Enum" and backslash */ search_dyn_data(dd_path, &lm_path[5], (buffer[3] - '1')); } } index = 0; do { size = 1023; result = RegEnumKeyEx( key, index++, buffer, &size, NULL, NULL, NULL, &last_write); if (result == ERROR_SUCCESS) { lm_path[length] = '\\'; lm_path[length + 1] = '\0'; strcpy(&lm_path[length + 1], buffer); search_local_machine(lm_path, dd_path); lm_path[length] = '\0'; } } while (result == ERROR_SUCCESS); RegCloseKey(key); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * GET_LPT_ADDRESSES_FROM_REGISTRY * * Searches Win95/98 registry recursively to get I/O port addresses for * parallel ports. */ void get_lpt_addresses_from_registry() { char lm_path[1024]; char dd_path[1024]; strcpy(lm_path, "Enum"); strcpy(dd_path, "Config Manager"); search_local_machine(lm_path, dd_path); } #endif #endif void initialize_jtag_hardware() { if (specified_com_port) { com_port = open(serial_port_name, O_RDWR); if (com_port == -1) { fprintf(stderr, "Error: can't open serial port \"%s\"\n", serial_port_name); } else { int i = 0, result = 0; char data = 0; data = 0x7e; write(com_port, &data, 1); for (i = 0; (i < 100) && (result != 1); ++i) { result = read(com_port, &data, 1); } if (result == 1) { data = 0x70; write(com_port, &data, 1); /* TDO echo off */ data = 0x72; write(com_port, &data, 1); /* auto LEDs off */ data = 0x74; write(com_port, &data, 1); /* ERROR LED off */ data = 0x76; write(com_port, &data, 1); /* DONE LED off */ data = 0x60; write(com_port, &data, 1); /* signals low */ } else { fprintf(stderr, "Error: BitBlaster is not responding on %s\n", serial_port_name); close(com_port); com_port = -1; } } } else { #if PORT == WINDOWS || PORT == DOS #if PORT == WINDOWS if (windows_nt) { initialize_nt_driver(); } else { #ifdef __BORLANDC__ fprintf(stderr, "Error: parallel port access is not available\n"); #else if (!specified_lpt_addr) { get_lpt_addresses_from_registry(); lpt_addr = 0; if (specified_lpt_port) { lpt_addr = lpt_addresses_from_registry[lpt_port - 1]; } if (lpt_addr == 0) { if (lpt_addresses_from_registry[3] != 0) lpt_addr = lpt_addresses_from_registry[3]; if (lpt_addresses_from_registry[2] != 0) lpt_addr = lpt_addresses_from_registry[2]; if (lpt_addresses_from_registry[1] != 0) lpt_addr = lpt_addresses_from_registry[1]; if (lpt_addresses_from_registry[0] != 0) lpt_addr = lpt_addresses_from_registry[0]; } if (lpt_addr == 0) { if (specified_lpt_port) { lpt_addr = lpt_addr_table[lpt_port - 1]; } else { lpt_addr = lpt_addr_table[0]; } } } initial_lpt_ctrl = windows_nt ? 0x0c : read_byteblaster(2); #endif } #endif #if PORT == DOS /* * Read word at specific memory address to get the LPT port address */ WORD *bios_address = (WORD *) 0x00400008; if (!specified_lpt_addr) { lpt_addr = bios_address[lpt_port - 1]; if ((lpt_addr != 0x278) && (lpt_addr != 0x27c) && (lpt_addr != 0x378) && (lpt_addr != 0x37c) && (lpt_addr != 0x3b8) && (lpt_addr != 0x3bc)) { lpt_addr = lpt_addr_table[lpt_port - 1]; } } initial_lpt_ctrl = read_byteblaster(2); #endif /* set AUTO-FEED low to enable ByteBlaster (value to port inverted) */ /* set DIRECTION low for data output from parallel port */ write_byteblaster(2, (initial_lpt_ctrl | 0x02) & 0xDF); #endif } } void close_jtag_hardware() { if (specified_com_port) { if (com_port != -1) close(com_port); } else { #if PORT == WINDOWS || PORT == DOS /* set AUTO-FEED high to disable ByteBlaster */ write_byteblaster(2, initial_lpt_ctrl & 0xfd); #if PORT == WINDOWS if (windows_nt && (nt_device_handle != INVALID_HANDLE_VALUE)) { if (port_io_count > 0) flush_ports(); CloseHandle(nt_device_handle); } #endif #endif #ifdef OPENBMC if (g_sysfs_tck_fd >= 0) close(g_sysfs_tck_fd); if (g_sysfs_tms_fd >= 0) close(g_sysfs_tms_fd); if (g_sysfs_tdo_fd >= 0) close(g_sysfs_tdo_fd); if (g_sysfs_tdi_fd >= 0) close(g_sysfs_tdi_fd); if (g_jtag_dev >= 0) close(g_jtag_dev); #endif } } #if PORT == WINDOWS /**************************************************************************/ /* */ BOOL initialize_nt_driver() /* */ /* Uses CreateFile() to open a connection to the Windows NT device */ /* driver. */ /* */ /**************************************************************************/ { BOOL status = FALSE; ULONG buffer[1]; ULONG returned_length = 0; char nt_lpt_str[] = { '\\', '\\', '.', '\\', 'A', 'L', 'T', 'L', 'P', 'T', '1', '\0' }; nt_lpt_str[10] = (char) ('1' + (lpt_port - 1)); nt_device_handle = CreateFile( nt_lpt_str, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (nt_device_handle == INVALID_HANDLE_VALUE) { fprintf(stderr, "I/O error: cannot open device %s\nCheck port number and device driver installation", nt_lpt_str); } else { if (DeviceIoControl( nt_device_handle, /* Handle to device */ PGDC_IOCTL_GET_DEVICE_INFO_PP, /* IO Control code */ (ULONG *)NULL, /* Buffer to driver. */ 0, /* Length of buffer in bytes. */ &buffer, /* Buffer from driver. */ sizeof(ULONG), /* Length of buffer in bytes. */ &returned_length, /* Bytes placed in data_buffer. */ NULL)) /* Wait for operation to complete */ { if (returned_length == sizeof(ULONG)) { if (buffer[0] == PGDC_HDLC_NTDRIVER_VERSION) { status = TRUE; } else { fprintf(stderr, "I/O error: device driver %s is not compatible\n(Driver version is %lu, expected version %lu.\n", nt_lpt_str, (unsigned long) buffer[0], (unsigned long) PGDC_HDLC_NTDRIVER_VERSION); } } else { fprintf(stderr, "I/O error: device driver %s is not compatible.\n", nt_lpt_str); } } if (!status) { CloseHandle(nt_device_handle); nt_device_handle = INVALID_HANDLE_VALUE; } } if (!status) { /* error message already given */ exit(1); } return (status); } #endif #if PORT == WINDOWS || PORT == DOS /**************************************************************************/ /* */ void write_byteblaster ( int port, int data ) /* */ /**************************************************************************/ { #if PORT == WINDOWS BOOL status = FALSE; int returned_length = 0; int buffer[2]; if (windows_nt) { /* * On Windows NT, access hardware through device driver */ if (port == 0) { port_io_buffer[port_io_count].data = (USHORT) data; port_io_buffer[port_io_count].command = PGDC_WRITE_PORT; ++port_io_count; if (port_io_count >= PORT_IO_BUFFER_SIZE) flush_ports(); } else { if (port_io_count > 0) flush_ports(); buffer[0] = port; buffer[1] = data; status = DeviceIoControl( nt_device_handle, /* Handle to device */ PGDC_IOCTL_WRITE_PORT_PP, /* IO Control code for write */ (ULONG *)&buffer, /* Buffer to driver. */ 2 * sizeof(int), /* Length of buffer in bytes. */ (ULONG *)NULL, /* Buffer from driver. Not used. */ 0, /* Length of buffer in bytes. */ (ULONG *)&returned_length, /* Bytes returned. Should be zero. */ NULL); /* Wait for operation to complete */ if ((!status) || (returned_length != 0)) { fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n"); CloseHandle(nt_device_handle); exit(1); } } } else #endif { /* * On Windows 95, access hardware directly */ outp((WORD)(port + lpt_addr), (WORD)data); } } /**************************************************************************/ /* */ int read_byteblaster ( int port ) /* */ /**************************************************************************/ { int data = 0; #if PORT == WINDOWS BOOL status = FALSE; int returned_length = 0; if (windows_nt) { /* flush output cache buffer before reading from device */ if (port_io_count > 0) flush_ports(); /* * On Windows NT, access hardware through device driver */ status = DeviceIoControl( nt_device_handle, /* Handle to device */ PGDC_IOCTL_READ_PORT_PP, /* IO Control code for Read */ (ULONG *)&port, /* Buffer to driver. */ sizeof(int), /* Length of buffer in bytes. */ (ULONG *)&data, /* Buffer from driver. */ sizeof(int), /* Length of buffer in bytes. */ (ULONG *)&returned_length, /* Bytes placed in data_buffer. */ NULL); /* Wait for operation to complete */ if ((!status) || (returned_length != sizeof(int))) { fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n"); CloseHandle(nt_device_handle); exit(1); } } else #endif { /* * On Windows 95, access hardware directly */ data = inp((WORD)(port + lpt_addr)); } return (data & 0xff); } #if PORT == WINDOWS void flush_ports(void) { ULONG n_writes = 0L; BOOL status; status = DeviceIoControl( nt_device_handle, /* handle to device */ PGDC_IOCTL_PROCESS_LIST_PP, /* IO control code */ (LPVOID)port_io_buffer, /* IN buffer (list buffer) */ port_io_count * sizeof(struct PORT_IO_LIST_STRUCT),/* length of IN buffer in bytes */ (LPVOID)port_io_buffer, /* OUT buffer (list buffer) */ port_io_count * sizeof(struct PORT_IO_LIST_STRUCT),/* length of OUT buffer in bytes */ &n_writes, /* number of writes performed */ 0); /* wait for operation to complete */ if ((!status) || ((port_io_count * sizeof(struct PORT_IO_LIST_STRUCT)) != n_writes)) { fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n"); CloseHandle(nt_device_handle); exit(1); } port_io_count = 0; } #endif /* PORT == WINDOWS */ #endif /* PORT == WINDOWS || PORT == DOS */ #if !defined (DEBUG) #pragma optimize ("ceglt", off) #endif void delay_loop(long count) { while (count != 0L) count--; }