diff options
author | Ori Bernstein <orib@fb.com> | 2015-09-03 13:06:18 -0700 |
---|---|---|
committer | Ori Bernstein <orib@fb.com> | 2015-09-23 18:10:45 -0700 |
commit | 67f44805b41a532b7b440773f7ee6d17dc0e97f4 (patch) | |
tree | c21a66b12c4d92a765e1ee0d47b96e2a2b9cd0d2 /common/recipes-utils/jbi/files/code/jbistub.c | |
parent | 2a51b7c1c2165ddb188c511e192b75f0aa0fbead (diff) | |
download | ast2050-yocto-openbmc-67f44805b41a532b7b440773f7ee6d17dc0e97f4.zip ast2050-yocto-openbmc-67f44805b41a532b7b440773f7ee6d17dc0e97f4.tar.gz |
Openbmc dev snapshot.
Diffstat (limited to 'common/recipes-utils/jbi/files/code/jbistub.c')
-rw-r--r-- | common/recipes-utils/jbi/files/code/jbistub.c | 2222 |
1 files changed, 2222 insertions, 0 deletions
diff --git a/common/recipes-utils/jbi/files/code/jbistub.c b/common/recipes-utils/jbi/files/code/jbistub.c new file mode 100644 index 0000000..87e9066 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbistub.c @@ -0,0 +1,2222 @@ +/****************************************************************************/ +/* */ +/* 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/gpio.h> +#include <openbmc/log.h> +#include <errno.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 +int g_tck = -1; +int g_tms = -1; +int g_tdo = -1; +int g_tdi = -1; +gpio_st g_gpio_tck; +gpio_st g_gpio_tms; +gpio_st g_gpio_tdo; +gpio_st g_gpio_tdi; +#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 + +/* + * The threshold (ns) to use spin instead of nanosleep(). + * Before adding the high resolution timer support, either spin or nanosleep() + * will not bring the process wakeup within 10ms. It turns out the system time + * update is also controlled by HZ (100). + * After I added the high resolution timer support, the spin works as the + * system time is updated more frequently. However, nanosleep() solution is + * still noticable slower comparing with spin. There could be some kernel + * scheduling tweak missing. Did not get time on that yet. + * For now, use 10ms as the threshold to determine if spin or nanosleep() + * is used. + */ +#define SPIN_THRESHOLD (10 * 1000 * 1000) +#define NANOSEC_IN_SEC (1000 * 1000 * 1000) + +static int sleep_ns(unsigned long clk) +{ + struct timespec req, rem; + int rc = 0; + if (clk <= SPIN_THRESHOLD) { + struct timespec orig; + rc = clock_gettime(CLOCK_MONOTONIC, &req); + orig = req; + while (!rc && clk) { + unsigned long tmp; + rc = clock_gettime(CLOCK_MONOTONIC, &rem); + tmp = (rem.tv_sec - req.tv_sec) * NANOSEC_IN_SEC; + if (rem.tv_nsec >= req.tv_nsec) { + tmp += rem.tv_nsec - req.tv_nsec; + } else { + tmp -= req.tv_nsec - rem.tv_nsec; + } + if (tmp >= clk) { + break; + } + clk -= tmp; + req = rem; + } + } else { + req.tv_sec = 0; + req.tv_nsec = clk; + while ((rc = nanosleep(&req, &rem)) == -1 && errno == EINTR) { + req = rem; + } + } + if (rc == -1) { + rc = errno; + LOG_ERR(rc, "Failed to sleep %u nanoseconds", clk); + } + return rc; +} + +int initialize_jtag_gpios() +{ + if (gpio_open(&g_gpio_tck, g_tck) || gpio_open(&g_gpio_tms, g_tms) + || gpio_open(&g_gpio_tdo, g_tdo) || gpio_open(&g_gpio_tdi, g_tdi)) { + return -1; + } + + /* change GPIO directions, only TDO is input, all others are output */ + if (gpio_change_direction(&g_gpio_tck, GPIO_DIRECTION_OUT) + || gpio_change_direction(&g_gpio_tms, GPIO_DIRECTION_OUT) + || gpio_change_direction(&g_gpio_tdo, GPIO_DIRECTION_IN) + || gpio_change_direction(&g_gpio_tdi, GPIO_DIRECTION_OUT)) { + return -1; + } + + /* set tck, tms, tdi to low */ + gpio_write(&g_gpio_tck, GPIO_VALUE_LOW); + gpio_write(&g_gpio_tms, GPIO_VALUE_LOW); + gpio_write(&g_gpio_tdi, GPIO_VALUE_LOW); + + jbi_delay(1); + + LOG_DBG("Opened TCK(GPIO %d), TMS(GPIO %d), TDI(GPIO %d), and TDO(GPIO %d)", + g_tck, g_tms, g_tdi, g_tdo); + + return 0; +} + +int jbi_jtag_io(int tms, int tdi, int read_tdo) +{ + int tdo = 0; + + if (!jtag_hardware_initialized) { + initialize_jtag_gpios(); + jtag_hardware_initialized = TRUE; + } + + gpio_write(&g_gpio_tms, tms ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); + gpio_write(&g_gpio_tdi, tdi ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); + + /* sleep 500ns to make sure the signal shows up on wire */ + sleep_ns(500); + /* + * if we need to read data, the data should be ready from the + * previous clock falling edge. Read it now. + */ + if (read_tdo) { + tdo = gpio_read(&g_gpio_tdo) == GPIO_VALUE_HIGH ? 1 : 0; + } + + /* do rising edge to clock out the data */ + gpio_write(&g_gpio_tck, GPIO_VALUE_HIGH); + sleep_ns(500); + /* do falling edge clocking */ + gpio_write(&g_gpio_tck, GPIO_VALUE_LOW); + + LOG_VER("tms=%d tdi=%d do_read=%d tdo=%d", tms, tdi, read_tdo, tdo); + + return 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 + sleep_ns(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; + + 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 = atoi(&argv[arg][3]); + break; + case 'S': + g_tms = atoi(&argv[arg][3]); + break; + case 'I': + g_tdi = atoi(&argv[arg][3]); + break; + case 'O': + g_tdo = atoi(&argv[arg][3]); + break; + } + 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) { + if (g_tck == -1 || g_tms == -1 || g_tdo == -1 || g_tdi == -1) { + 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 + } +} + +#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--; +} |