/****************************************************************************/ /* */ /* 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 */ /* */ /****************************************************************************/ #include #include #include #include #include #include #define POINTER_ALIGNMENT sizeof(BYTE) #include "jbiexprt.h" /************************************************************************ * * Global variables */ unsigned char *file_buffer = NULL; long file_pointer = 0L; long file_length = 0L; /******************************************************************/ #include #include "ftd2xx.h" BOOL jtag_hardware_initialized = FALSE; BOOL verbose = FALSE; static FT_HANDLE ftdih = NULL; /******************************************************************/ int usb_blaster_buf_write(BYTE *buf, int size, DWORD* bytes_written) { FT_STATUS status; DWORD dw_bytes_written; if((size == 1) && (buf[0]&0x01)) printf("(tms tdi) -> (%d %d)\n", (buf[0]&0x02) >> 1, (buf[0]&0x10) >> 4); if ((status = FT_Write(ftdih, buf, size, &dw_bytes_written)) != FT_OK) { *bytes_written = dw_bytes_written; printf("FT_Write returned: %ld\n", status); return 0; } else { *bytes_written = dw_bytes_written; return 1; } } /******************************************************************/ int usb_blaster_buf_read(BYTE* buf, int size, DWORD* bytes_read) { DWORD dw_bytes_read; FT_STATUS status; if ((status = FT_Read(ftdih, buf, size, &dw_bytes_read)) != FT_OK) { *bytes_read = dw_bytes_read; printf("FT_Read returned: %ld", status); return 0; } *bytes_read = dw_bytes_read; return 1; } /******************************************************************/ int usb_blaster_init() { BYTE latency_timer; FT_STATUS status; if ((status = FT_OpenEx("USB-Blaster", FT_OPEN_BY_DESCRIPTION, &ftdih)) != FT_OK) { printf("unable to open ftdi device: %ld\n", status); return 0; } if ((status = FT_SetLatencyTimer(ftdih, 2)) != FT_OK) { printf("unable to set latency timer: %ld\n", status); return 0; } if ((status = FT_GetLatencyTimer(ftdih, &latency_timer)) != FT_OK) { printf("unable to get latency timer: %ld\n", status); return 0; } else { printf("current latency timer: %d\n", latency_timer); } if ((status = FT_SetBitMode(ftdih, 0x00, 0)) != FT_OK) { printf("unable to disable bit i/o mode: %ld\n", status); return 0; } return 1; } /******************************************************************/ int usb_blaster_quit() { FT_STATUS status; status = FT_Close(ftdih); return 1; } /******************************************************************/ void usb_blaster_wait(int count, int tms) { DWORD cnt; BYTE buf[64]; int i, len, extra; if (count <= 0) return; memset(buf, 0, 64); extra = (count & 7); buf[0] = 0x0C | (tms ? 0x02 : 0); usb_blaster_buf_write(buf, 1, &cnt); while (count > 0) { if (count > 504) { len = 63; count -= 504; } else { len = count >> 3; count = 0; } if (len > 0) { buf[0] = len | 0x80; usb_blaster_buf_write(buf, len + 1, &cnt); } } for (i = 0; i < extra; i++) { jbi_jtag_io(tms, 0, 0); } } /******************************************************************/ void usb_blaster_scan(int count, unsigned char *tdi, unsigned char *tdo) { DWORD cnt; BYTE buf[64]; unsigned char extra_bits; int i, len, pos, extra, tdo_bit, read_tdo; read_tdo = (tdo != NULL); if (count <= 0) return; pos = 0; extra = (count & 7); if (extra == 0) { count -= 8; extra = 8; } extra_bits = tdi[count >> 3]; while (count > 0) { if (count > 504) { len = 63; count -= 504; } else { len = count >> 3; count = 0; } if (len > 0) { buf[0] = len | 0x80 | (read_tdo ? 0x40 : 0); memcpy(buf + 1, tdi + pos, len); usb_blaster_buf_write(buf, len + 1, &cnt); if (read_tdo) { usb_blaster_buf_read(tdo + pos, len, &cnt); } pos += len; } } for (i = 0; i < extra; i++) { tdo_bit = jbi_jtag_io( (i == extra - 1), extra_bits & (1 << (i & 7)), read_tdo); if (read_tdo) { if (tdo_bit) { tdo[pos] |= (1 << (i & 7)); } else { tdo[pos] &= ~(unsigned int) (1 << (i & 7)); } } } } /************************************************************************ * * Customized interface functions for Jam STAPL ByteCode Player I/O: * * jbi_jtag_io() * jbi_message() * jbi_delay() */ int jbi_jtag_io(int tms, int tdi, int read_tdo) { BYTE buf[3]; DWORD count; int data = 0; int tdo = 0; if (!jtag_hardware_initialized) { usb_blaster_init(); jtag_hardware_initialized = TRUE; } data = (tdi ? 0x10 : 0) | (tms ? 0x02 : 0); buf[0] = data | 0x0C | (read_tdo ? 0x40 : 0); buf[1] = data | 0x0C | 0x01; buf[2] = data | 0x0C; usb_blaster_buf_write(buf, 3, &count); if (read_tdo) { usb_blaster_buf_read(buf, 1, &count); tdo = buf[0]&0x01; } return (tdo); } 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) { usleep(microseconds); } void *jbi_malloc(unsigned int size) { unsigned int n_bytes_to_allocate = (POINTER_ALIGNMENT * ((size + POINTER_ALIGNMENT - 1) / POINTER_ALIGNMENT)); unsigned char *ptr = 0; ptr = (unsigned char *) malloc(n_bytes_to_allocate); return ptr; } void jbi_free(void *ptr) { if (ptr != 0) { free(ptr); } } 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; 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 (argv[arg][0] == '-') { switch(toupper(argv[arg][1])) { case 'A': /* set action name */ if (action == NULL) { action = &argv[arg][2]; } else { error = TRUE; } break; 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; case 'R': /* don't reset the JTAG chain after use */ reset_jtag = 0; break; 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 (help || (filename == NULL)) { fprintf(stderr, "Usage: jbi [options] \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 : specify an action name (Jam STAPL)\n"); fprintf(stderr, " -d : initialize variable to specified value (Jam 1.1)\n"); fprintf(stderr, " -d : enable optional procedure (Jam STAPL)\n"); fprintf(stderr, " -d : disable recommended procedure (Jam STAPL)\n"); 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 */ file_buffer = (unsigned char *) jbi_malloc((size_t) file_length); if (file_buffer == NULL) { fprintf(stderr, "Error: can't allocate memory (%d Kbytes)\n", (int) (file_length / 1024L)); 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; } } fclose(fp); } if (exit_status == 0) { /* * 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); } procptr = procedure_list; while (procptr != NULL) { if (procptr->attributes != 0) { printf(" %s (%s)\n", procptr->name, (procptr->attributes == 1) ? "optional" : "recommended"); } 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 */ exec_result = jbi_execute(file_buffer, file_length, workspace, workspace_size, action, init_list, reset_jtag, &error_address, &exit_code, &format_version); 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 %d\n", exec_result); } } } } if (jtag_hardware_initialized) usb_blaster_quit(); if (workspace != NULL) jbi_free(workspace); if (file_buffer != NULL) jbi_free(file_buffer); return (exit_status); }