├── .github └── FUNDING.yml ├── COPYING ├── Makefile ├── README.md ├── clujtag.c ├── clujtag.exe ├── defines.h ├── jtag_commands.h ├── libxsvf.h ├── memname.c ├── play.c ├── scan.c ├── statename.c ├── svf.c ├── tap.c └── xsvf.c /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [ClusterM] 2 | custom: ["https://www.buymeacoffee.com/cluster", "https://boosty.to/cluster"] 3 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | 4 | Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | Copyright (C) 2009 Clifford Wolf 6 | 7 | Permission to use, copy, modify, and/or distribute this software for any 8 | purpose with or without fee is hereby granted, provided that the above 9 | copyright notice and this permission notice appear in all copies. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-c -Wall -O2 3 | LDFLAGS= 4 | SOURCES=clujtag.c xsvf.c svf.c play.c memname.c scan.c statename.c tap.c 5 | OBJECTS=$(SOURCES:.c=.o) 6 | ifeq ($(OS),Windows_NT) 7 | EXECUTABLE=clujtag.exe 8 | else 9 | EXECUTABLE=clujtag 10 | endif 11 | 12 | all: $(SOURCES) $(EXECUTABLE) 13 | 14 | $(EXECUTABLE): $(OBJECTS) 15 | $(CC) $(LDFLAGS) $(OBJECTS) -o $@ 16 | 17 | .c.o: 18 | $(CC) $(CFLAGS) $< -o $@ 19 | 20 | clean: 21 | rm -rf *.o $(EXECUTABLE) 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | clujtag-client 2 | ============== 3 | 4 | Client for AVR-based JTAG programmer: https://github.com/ClusterM/clujtag-avr 5 | 6 | It's based on Lib(X)SVF (http://www.clifford.at/libxsvf/) so you can use it to flash SVF or XSVF files. Use MinGW (www.mingw.org) to compile it for Windows if need. Linux users are welome too. 7 | 8 | How to use: 9 | 10 | Usage: 11 | clujtag [ -v ... ] -p portname { -s svf-file | -x xsvf-file | -c } 12 | * -p portname - use specified serial port for communication with programmer (COM*xx* for Windows and /dev/tty*xxx* for Linux) 13 | * -v, -vv, -vvv, -vvvv - verbose, more verbose and even more verbose 14 | * -s svf-file - play the specified SVF file 15 | * -x xsvf-file - play the specified XSVF file 16 | * -c - list devices in JTAG chain 17 | 18 | 19 | Examples: 20 | 21 | >clujtag -p COM16 -c 22 | Scanning JTAG chain... 23 | Device found: idcode=0x170640dd, revision=0x1, part=0x7064, manufactor=0x06e 24 | 25 | 26 | >clujtag -v -p /dev/ttyACM0 -s MMC1.svf 27 | clujtag 28 | Copyright (C) 2009 RIEGL Research ForschungsGmbH 29 | Copyright (C) 2009 Clifford Wolf 30 | Copyright (C) 2014 Cluster 31 | Lib(X)SVF is free software licensed under the ISC license. 32 | Playing SVF file `MMC1.svf'. 33 | Done! 34 | -------------------------------------------------------------------------------- /clujtag.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * Copyright (C) 2014 Cluster 7 | * 8 | * Permission to use, copy, modify, and/or distribute this software for any 9 | * purpose with or without fee is hereby granted, provided that the above 10 | * copyright notice and this permission notice appear in all copies. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 | * 20 | */ 21 | #ifdef __MINGW32__ 22 | #define WINDOWS 23 | #endif 24 | 25 | #include "libxsvf.h" 26 | #include "defines.h" 27 | #include "jtag_commands.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #ifdef WINDOWS 39 | #include 40 | #else 41 | #include 42 | #endif 43 | 44 | char comPort[512]; 45 | #ifdef WINDOWS 46 | HANDLE portHandle; 47 | #else 48 | int portHandle; 49 | #endif 50 | FILE *f; 51 | int verbose; 52 | int tck_count; 53 | unsigned char tck_data[5096]; 54 | int write_buffer_count = 0; 55 | unsigned char write_buffer[ACK_STEP+16]; 56 | int byte_counter = 0; 57 | int scan_mode = 0; 58 | 59 | #ifdef WINDOWS 60 | static uint8_t read_port() 61 | { 62 | uint8_t buffer; 63 | DWORD read = 0; 64 | if (ReadFile(portHandle, &buffer, 1, &read, NULL) && (read == 1)) return buffer; 65 | fprintf(stderr, "Read error: %d\r\n", (int)GetLastError()); 66 | exit(1); 67 | } 68 | #else 69 | static uint8_t read_port() 70 | { 71 | uint8_t data; 72 | int res, t = 0; 73 | const int timeout = 5000; 74 | do 75 | { 76 | res = read(portHandle, &data, 1); 77 | t++; 78 | if (res == 0) usleep(10); 79 | } 80 | while ((res == 0) && (t < timeout)); 81 | if (t == timeout) 82 | { 83 | printf("Read timeout\n"); 84 | exit(1); 85 | } 86 | if (res == 1) return data; 87 | perror("Read error"); 88 | exit(1); 89 | } 90 | #endif 91 | 92 | void check_result() 93 | { 94 | uint8_t result = read_port(); 95 | if (verbose >= 4) { 96 | fprintf(stderr, "[RESULT: %d]\n", result); 97 | } 98 | 99 | if (!result) 100 | { 101 | fprintf(stderr, "JTAG error\r\n"); 102 | exit(2); 103 | } 104 | } 105 | 106 | #ifdef WINDOWS 107 | static void flush_data() 108 | { 109 | if (!write_buffer_count) return; 110 | DWORD writed = 0; 111 | if (WriteFile(portHandle, write_buffer, write_buffer_count, &writed, NULL) && (writed == write_buffer_count)) 112 | { 113 | if (verbose >= 4) { 114 | fprintf(stderr, "[WRITED: %d]\n", write_buffer_count); 115 | } 116 | write_buffer_count = 0; 117 | return; 118 | } 119 | int error = GetLastError(); 120 | fprintf(stderr, "Write error: %d\r\n", error); 121 | exit(1); 122 | } 123 | #else 124 | static void flush_data() 125 | { 126 | if (!write_buffer_count) return; 127 | int res; 128 | do 129 | { 130 | res = write(portHandle, write_buffer, write_buffer_count); 131 | if (res == -1) usleep(10); 132 | } while (res == -1 && errno == EAGAIN); 133 | if (res == -1) 134 | { 135 | perror("Write error"); 136 | exit(1); 137 | } 138 | if (verbose >= 4) { 139 | fprintf(stderr, "[WRITED: %d]\n", write_buffer_count); 140 | } 141 | write_buffer_count = 0; 142 | } 143 | #endif 144 | 145 | static void write_port(uint8_t data) 146 | { 147 | write_buffer[write_buffer_count++] = data; 148 | byte_counter++; 149 | if (byte_counter >= ACK_STEP) 150 | { 151 | flush_data(); 152 | check_result(); 153 | byte_counter = 0; 154 | } 155 | } 156 | 157 | static int h_setup(struct libxsvf_host *h) 158 | { 159 | if (verbose >= 1) { 160 | fprintf(stderr, "[SETUP]\n"); 161 | fflush(stderr); 162 | } 163 | 164 | if (!strlen(comPort)) 165 | { 166 | fprintf(stderr, "You '-p' parameter to specify the serial port\n"); 167 | return -1; 168 | } 169 | #ifdef WINDOWS 170 | 171 | char devicePath[50]; 172 | sprintf(devicePath, "\\\\.\\%s", comPort); 173 | 174 | HANDLE mHandle = CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,/* FILE_FLAG_OVERLAPPED*/0, NULL); 175 | if (mHandle == INVALID_HANDLE_VALUE) 176 | { 177 | fprintf(stderr, "Can't open serial port %s\r\n", comPort); 178 | return -1; 179 | } 180 | 181 | DCB dcb; 182 | FillMemory(&dcb, sizeof(dcb), 0); 183 | if (!GetCommState(mHandle, &dcb)) // get current DCB 184 | { 185 | fprintf(stderr, "Can't get serial port settings\r\n"); 186 | return -1; 187 | } 188 | dcb.BaudRate = CBR_256000; 189 | if (!SetCommState(mHandle, &dcb)) 190 | { 191 | fprintf(stderr, "Can't set serial port settings\r\n"); 192 | return -1; 193 | } 194 | 195 | COMMTIMEOUTS timeouts; 196 | FillMemory(&timeouts, sizeof(timeouts), 0); 197 | if (!GetCommTimeouts(mHandle, &timeouts)) 198 | { 199 | fprintf(stderr, "Can't get serial port timeouts\r\n"); 200 | return -1; 201 | } 202 | timeouts.ReadIntervalTimeout = 0; 203 | timeouts.ReadTotalTimeoutMultiplier = 0; 204 | timeouts.ReadTotalTimeoutMultiplier = 10000; 205 | timeouts.WriteTotalTimeoutConstant = 10000; 206 | timeouts.WriteTotalTimeoutMultiplier = 0; 207 | if (!SetCommTimeouts(mHandle, &timeouts)) 208 | { 209 | fprintf(stderr, "Can't set serial port timeouts\r\n"); 210 | return -1; 211 | } 212 | 213 | portHandle = mHandle; 214 | 215 | #else 216 | 217 | int fd; 218 | struct termios options; 219 | fd = open(comPort, O_RDWR | O_NOCTTY); 220 | if (fd == -1) 221 | { 222 | perror("Can't open serial port"); 223 | return -1; 224 | } 225 | 226 | fcntl(fd, F_SETFL, FNDELAY); 227 | 228 | bzero(&options, sizeof(options)); 229 | options.c_cflag = B230400 | CS8 | CLOCAL | CREAD; 230 | options.c_iflag = IGNPAR; 231 | options.c_oflag = 0; 232 | cfsetispeed(&options, B230400); 233 | cfsetospeed(&options, B230400); 234 | tcsetattr(fd, TCSANOW, &options); 235 | tcflush(fd, TCIFLUSH); 236 | portHandle = fd; 237 | 238 | #endif 239 | 240 | // Setup JTAG 241 | int i; 242 | byte_counter = 0; 243 | for (i = 0; i < 16; i++) 244 | write_port(JTAG_SETUP); 245 | byte_counter = 0; 246 | 247 | return 0; 248 | } 249 | 250 | static int h_shutdown(struct libxsvf_host *h) 251 | { 252 | if (verbose >= 1) { 253 | fprintf(stderr, "[SHUTDOWN]\n"); 254 | fflush(stderr); 255 | } 256 | 257 | if (portHandle) 258 | { 259 | write_port(JTAG_SHUTDOWN); 260 | flush_data(); 261 | check_result(portHandle); 262 | #ifdef WINDOWS 263 | CloseHandle(portHandle); 264 | #else 265 | close(portHandle); 266 | #endif 267 | } 268 | 269 | return 0; 270 | } 271 | 272 | static int h_pulse_tck_multi(struct libxsvf_host *h, unsigned char* data, unsigned int count) 273 | { 274 | write_port(JTAG_PULSE_TCK_MULTI); 275 | write_port(count & 0xff); 276 | write_port((count >> 8) & 0xff); 277 | int i; 278 | unsigned char r = 0; 279 | int last_v = data[0]; 280 | for (i = 0; i < count; i++) 281 | { 282 | if (data[i] != last_v || r == 0x7f) 283 | { 284 | if (r > 0) 285 | { 286 | if (r > 1) 287 | { 288 | write_port(r); 289 | write_port(last_v & 0xff); 290 | } else { 291 | write_port((last_v & 0xff) | 0x80); 292 | } 293 | } 294 | r = 0; 295 | last_v = data[i]; 296 | } 297 | r++; 298 | } 299 | 300 | if (r > 0) 301 | { 302 | if (r > 1) 303 | { 304 | write_port(r); 305 | write_port(last_v & 0xff); 306 | } else { 307 | write_port((last_v & 0xff) | 0x80); 308 | } 309 | } 310 | 311 | if (verbose >= 3) { 312 | fprintf(stderr, "[MULTI TCK: %d bits]\n", count); 313 | fprintf(stderr, "[TMS:%d, TDI:%d, TDO:%d]\n", data[i]&1, (data[i]>>1)&1 ? (data[i]>>2)&1 : -1, (data[i]>>3)&1 ? (data[i]>>4)&1 : -1); 314 | } 315 | return 0; 316 | } 317 | 318 | static void flush_tck(struct libxsvf_host *h) 319 | { 320 | if (tck_count > 0) 321 | h_pulse_tck_multi(h, tck_data, tck_count); 322 | tck_count = 0; 323 | } 324 | 325 | static void h_udelay(struct libxsvf_host *h, long usecs, int tms, long num_tck) 326 | { 327 | flush_tck(h); 328 | if (verbose >= 2) { 329 | fprintf(stderr, "[DELAY:%ld, TMS:%d, NUM_TCK:%ld]\n", usecs, tms, num_tck); 330 | } 331 | 332 | write_port(JTAG_PULSE_TCK_DELAY); 333 | write_port((tms&1) | ((num_tck > 0) ? 0b10 : 0) | ((usecs > 0) ? 0b100 : 0)); 334 | if (num_tck > 0) 335 | { 336 | write_port(num_tck & 0xff); 337 | write_port((num_tck >> 8) & 0xff); 338 | write_port((num_tck >> 16) & 0xff); 339 | write_port((num_tck >> 24) & 0xff); 340 | } 341 | 342 | if (usecs > 0) 343 | { 344 | write_port(usecs & 0xff); 345 | write_port((usecs >> 8) & 0xff); 346 | write_port((usecs >> 16) & 0xff); 347 | write_port((usecs >> 24) & 0xff); 348 | } 349 | } 350 | 351 | static int h_getbyte(struct libxsvf_host *h) 352 | { 353 | return fgetc(f); 354 | } 355 | 356 | static int h_pulse_tck(struct libxsvf_host *h, int tms, int tdi, int tdo, int rmask, int sync) 357 | { 358 | if (verbose >= 3) { 359 | fprintf(stderr, "[PULSE TCK TMS: %d, TDI: %d, TDO: %d]\n", tms, tdi, tdo); 360 | } 361 | 362 | uint8_t data = 0; 363 | if (tms) data |= 1; 364 | if (tdi) data |= (1<<1); 365 | if (tdo >= 0) 366 | { 367 | data |= (1<<2); // need check! 368 | data |= (tdo << 3); // must be same! 369 | } 370 | 371 | tck_data[tck_count] = data; 372 | tck_count++; 373 | if (tck_count == sizeof(tck_data) || (tdo < 0 && scan_mode)) 374 | flush_tck(h); 375 | 376 | if (tdo < 0 && scan_mode) 377 | { 378 | write_port(JTAG_TDO_REQUEST); 379 | flush_data(); 380 | byte_counter = 0; 381 | int res = read_port(); 382 | if (verbose >= 3) { 383 | fprintf(stderr, "[TDO STATE: %d]\n", res); 384 | } 385 | return res; 386 | } 387 | 388 | return 0; 389 | } 390 | 391 | static void h_report_device(struct libxsvf_host *h, unsigned long idcode) 392 | { 393 | printf("Device found: idcode=0x%08lx, revision=0x%01lx, part=0x%04lx, manufactor=0x%03lx\n", idcode, 394 | (idcode >> 28) & 0xf, (idcode >> 12) & 0xffff, (idcode >> 1) & 0x7ff); 395 | } 396 | 397 | 398 | static void h_report_status(struct libxsvf_host *h, const char *message) 399 | { 400 | if (verbose >= 1) { 401 | fprintf(stderr, "[STATUS] %s\n", message); 402 | } 403 | } 404 | 405 | static void h_report_error(struct libxsvf_host *h, const char *file, int line, const char *message) 406 | { 407 | fprintf(stderr, "[%s:%d] %s\n", file, line, message); 408 | } 409 | 410 | static void *h_realloc(struct libxsvf_host *h, void *ptr, int size, enum libxsvf_mem which) 411 | { 412 | if (verbose >= 2) { 413 | fprintf(stderr, "[REALLOC:%s:%d]\n", libxsvf_mem2str(which), size); 414 | } 415 | return realloc(ptr, size); 416 | } 417 | 418 | static struct libxsvf_host h = { 419 | .udelay = h_udelay, 420 | .setup = h_setup, 421 | .shutdown = h_shutdown, 422 | .getbyte = h_getbyte, 423 | .pulse_tck = h_pulse_tck, 424 | .pulse_sck = NULL, 425 | .set_trst = NULL, 426 | .set_frequency = NULL, 427 | .report_tapstate = NULL, 428 | .report_device = h_report_device, 429 | .report_status = h_report_status, 430 | .report_error = h_report_error, 431 | .realloc = h_realloc, 432 | }; 433 | 434 | const char *progname; 435 | 436 | static void copyleft() 437 | { 438 | static int already_printed = 0; 439 | if (already_printed) 440 | return; 441 | fprintf(stderr, "clujtag\n"); 442 | fprintf(stderr, "Copyright (C) 2009 RIEGL Research ForschungsGmbH\n"); 443 | fprintf(stderr, "Copyright (C) 2009 Clifford Wolf \n"); 444 | fprintf(stderr, "Copyright (C) 2015 Cluster \n"); 445 | fprintf(stderr, "Lib(X)SVF is free software licensed under the ISC license.\n"); 446 | already_printed = 1; 447 | } 448 | 449 | static void help() 450 | { 451 | copyleft(); 452 | fprintf(stderr, "\n"); 453 | fprintf(stderr, "Usage: %s [ -v ... ] -p portname { -s svf-file | -x xsvf-file | -c }\n", progname); 454 | fprintf(stderr, "\n"); 455 | fprintf(stderr, " -p portname\n"); 456 | fprintf(stderr, " Use specified serial port for communication with programmer (COMxx for Windows and /dev/ttyxxx for Linux)\n"); 457 | fprintf(stderr, "\n"); 458 | fprintf(stderr, " -v, -vv, -vvv, -vvvv\n"); 459 | fprintf(stderr, " Verbose, more verbose and even more verbose\n"); 460 | fprintf(stderr, "\n"); 461 | fprintf(stderr, "\n"); 462 | fprintf(stderr, " -s svf-file\n"); 463 | fprintf(stderr, " Play the specified SVF file\n"); 464 | fprintf(stderr, "\n"); 465 | fprintf(stderr, " -x xsvf-file\n"); 466 | fprintf(stderr, " Play the specified XSVF file\n"); 467 | fprintf(stderr, "\n"); 468 | fprintf(stderr, " -c\n"); 469 | fprintf(stderr, " List devices in JTAG chain\n"); 470 | fprintf(stderr, "\n"); 471 | exit(1); 472 | } 473 | 474 | int main(int argc, char **argv) 475 | { 476 | copyleft(); 477 | 478 | int rc = 0; 479 | int gotaction = 0; 480 | int opt; 481 | 482 | tck_count = 0; 483 | verbose = 0; 484 | comPort[0] = 0; 485 | portHandle = 0; 486 | char filename[1024]; 487 | 488 | progname = argc >= 1 ? argv[0] : "xvsftool"; 489 | while ((opt = getopt(argc, argv, "vp:x:s:c")) != -1) 490 | { 491 | switch (opt) 492 | { 493 | case 'v': 494 | verbose++; 495 | break; 496 | case 'p': 497 | strncpy(comPort, optarg, sizeof(comPort)-1); 498 | comPort[sizeof(comPort)-1] = 0; 499 | break; 500 | case 'x': 501 | case 's': 502 | gotaction = opt; 503 | strncpy(filename, optarg, sizeof(filename)); 504 | filename[sizeof(filename)-1] = 0; 505 | break; 506 | case 'c': 507 | gotaction = opt; 508 | break; 509 | default: 510 | help(); 511 | break; 512 | } 513 | } 514 | 515 | switch (gotaction) 516 | { 517 | case 'x': 518 | case 's': 519 | if (verbose) 520 | fprintf(stderr, "Playing %s file `%s'.\n", opt == 's' ? "SVF" : "XSVF", filename); 521 | if (!strcmp(filename, "-")) 522 | f = stdin; 523 | else 524 | f = fopen(filename, "rb"); 525 | if (f == NULL) { 526 | fprintf(stderr, "Can't open %s file `%s': %s\n", opt == 's' ? "SVF" : "XSVF", filename, strerror(errno)); 527 | rc = 1; 528 | } 529 | if (libxsvf_play(&h, gotaction == 's' ? LIBXSVF_MODE_SVF : LIBXSVF_MODE_XSVF) < 0) { 530 | fprintf(stderr, "Error while playing %s file `%s'.\n", opt == 's' ? "SVF" : "XSVF", filename); 531 | rc = 1; 532 | } 533 | if (strcmp(filename, "-")) 534 | fclose(f); 535 | break; 536 | 537 | case 'c': 538 | scan_mode = 1; 539 | if (libxsvf_play(&h, LIBXSVF_MODE_SCAN) < 0) { 540 | fprintf(stderr, "Error while scanning JTAG chain.\n"); 541 | rc = 1; 542 | } 543 | break; 544 | 545 | default: 546 | help(); 547 | break; 548 | } 549 | 550 | if (rc) 551 | { 552 | fprintf(stderr, "Finished with errors!\n"); 553 | } 554 | 555 | exit(rc); 556 | } 557 | 558 | -------------------------------------------------------------------------------- /clujtag.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ClusterM/clujtag-client/92938b0c11639398e63ce7f4bc5e3e67ceaeb332/clujtag.exe -------------------------------------------------------------------------------- /defines.h: -------------------------------------------------------------------------------- 1 | #define ACK_STEP 1024 2 | -------------------------------------------------------------------------------- /jtag_commands.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ClusterM/clujtag-client/92938b0c11639398e63ce7f4bc5e3e67ceaeb332/jtag_commands.h -------------------------------------------------------------------------------- /libxsvf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #ifndef LIBXSVF_H 22 | #define LIBXSVF_H 23 | 24 | enum libxsvf_mode { 25 | LIBXSVF_MODE_SVF = 1, 26 | LIBXSVF_MODE_XSVF = 2, 27 | LIBXSVF_MODE_SCAN = 3 28 | }; 29 | 30 | enum libxsvf_tap_state { 31 | /* Special States */ 32 | LIBXSVF_TAP_INIT = 0, 33 | LIBXSVF_TAP_RESET = 1, 34 | LIBXSVF_TAP_IDLE = 2, 35 | /* DR States */ 36 | LIBXSVF_TAP_DRSELECT = 3, 37 | LIBXSVF_TAP_DRCAPTURE = 4, 38 | LIBXSVF_TAP_DRSHIFT = 5, 39 | LIBXSVF_TAP_DREXIT1 = 6, 40 | LIBXSVF_TAP_DRPAUSE = 7, 41 | LIBXSVF_TAP_DREXIT2 = 8, 42 | LIBXSVF_TAP_DRUPDATE = 9, 43 | /* IR States */ 44 | LIBXSVF_TAP_IRSELECT = 10, 45 | LIBXSVF_TAP_IRCAPTURE = 11, 46 | LIBXSVF_TAP_IRSHIFT = 12, 47 | LIBXSVF_TAP_IREXIT1 = 13, 48 | LIBXSVF_TAP_IRPAUSE = 14, 49 | LIBXSVF_TAP_IREXIT2 = 15, 50 | LIBXSVF_TAP_IRUPDATE = 16 51 | }; 52 | 53 | enum libxsvf_mem { 54 | LIBXSVF_MEM_XSVF_TDI_DATA = 0, 55 | LIBXSVF_MEM_XSVF_TDO_DATA = 1, 56 | LIBXSVF_MEM_XSVF_TDO_MASK = 2, 57 | LIBXSVF_MEM_XSVF_ADDR_MASK = 3, 58 | LIBXSVF_MEM_XSVF_DATA_MASK = 4, 59 | LIBXSVF_MEM_SVF_COMMANDBUF = 5, 60 | LIBXSVF_MEM_SVF_SDR_TDI_DATA = 6, 61 | LIBXSVF_MEM_SVF_SDR_TDI_MASK = 7, 62 | LIBXSVF_MEM_SVF_SDR_TDO_DATA = 8, 63 | LIBXSVF_MEM_SVF_SDR_TDO_MASK = 9, 64 | LIBXSVF_MEM_SVF_SDR_RET_MASK = 10, 65 | LIBXSVF_MEM_SVF_SIR_TDI_DATA = 11, 66 | LIBXSVF_MEM_SVF_SIR_TDI_MASK = 12, 67 | LIBXSVF_MEM_SVF_SIR_TDO_DATA = 13, 68 | LIBXSVF_MEM_SVF_SIR_TDO_MASK = 14, 69 | LIBXSVF_MEM_SVF_SIR_RET_MASK = 15, 70 | LIBXSVF_MEM_SVF_HDR_TDI_DATA = 16, 71 | LIBXSVF_MEM_SVF_HDR_TDI_MASK = 17, 72 | LIBXSVF_MEM_SVF_HDR_TDO_DATA = 18, 73 | LIBXSVF_MEM_SVF_HDR_TDO_MASK = 19, 74 | LIBXSVF_MEM_SVF_HDR_RET_MASK = 20, 75 | LIBXSVF_MEM_SVF_HIR_TDI_DATA = 21, 76 | LIBXSVF_MEM_SVF_HIR_TDI_MASK = 22, 77 | LIBXSVF_MEM_SVF_HIR_TDO_DATA = 23, 78 | LIBXSVF_MEM_SVF_HIR_TDO_MASK = 24, 79 | LIBXSVF_MEM_SVF_HIR_RET_MASK = 25, 80 | LIBXSVF_MEM_SVF_TDR_TDI_DATA = 26, 81 | LIBXSVF_MEM_SVF_TDR_TDI_MASK = 27, 82 | LIBXSVF_MEM_SVF_TDR_TDO_DATA = 28, 83 | LIBXSVF_MEM_SVF_TDR_TDO_MASK = 29, 84 | LIBXSVF_MEM_SVF_TDR_RET_MASK = 30, 85 | LIBXSVF_MEM_SVF_TIR_TDI_DATA = 31, 86 | LIBXSVF_MEM_SVF_TIR_TDI_MASK = 32, 87 | LIBXSVF_MEM_SVF_TIR_TDO_DATA = 33, 88 | LIBXSVF_MEM_SVF_TIR_TDO_MASK = 34, 89 | LIBXSVF_MEM_SVF_TIR_RET_MASK = 35, 90 | LIBXSVF_MEM_NUM = 36 91 | }; 92 | 93 | struct libxsvf_host { 94 | int (*setup)(struct libxsvf_host *h); 95 | int (*shutdown)(struct libxsvf_host *h); 96 | void (*udelay)(struct libxsvf_host *h, long usecs, int tms, long num_tck); 97 | int (*getbyte)(struct libxsvf_host *h); 98 | int (*sync)(struct libxsvf_host *h); 99 | int (*pulse_tck)(struct libxsvf_host *h, int tms, int tdi, int tdo, int rmask, int sync); 100 | void (*pulse_sck)(struct libxsvf_host *h); 101 | void (*set_trst)(struct libxsvf_host *h, int v); 102 | int (*set_frequency)(struct libxsvf_host *h, int v); 103 | void (*report_tapstate)(struct libxsvf_host *h); 104 | void (*report_device)(struct libxsvf_host *h, unsigned long idcode); 105 | void (*report_status)(struct libxsvf_host *h, const char *message); 106 | void (*report_error)(struct libxsvf_host *h, const char *file, int line, const char *message); 107 | void *(*realloc)(struct libxsvf_host *h, void *ptr, int size, enum libxsvf_mem which); 108 | enum libxsvf_tap_state tap_state; 109 | void *user_data; 110 | }; 111 | 112 | int libxsvf_play(struct libxsvf_host *, enum libxsvf_mode mode); 113 | const char *libxsvf_state2str(enum libxsvf_tap_state tap_state); 114 | const char *libxsvf_mem2str(enum libxsvf_mem which); 115 | 116 | /* Internal API */ 117 | int libxsvf_svf(struct libxsvf_host *h); 118 | int libxsvf_xsvf(struct libxsvf_host *h); 119 | int libxsvf_scan(struct libxsvf_host *h); 120 | int libxsvf_tap_walk(struct libxsvf_host *, enum libxsvf_tap_state); 121 | 122 | /* Host accessor macros (see README) */ 123 | #define LIBXSVF_HOST_SETUP() h->setup(h) 124 | #define LIBXSVF_HOST_SHUTDOWN() h->shutdown(h) 125 | #define LIBXSVF_HOST_UDELAY(_usecs, _tms, _num_tck) h->udelay(h, _usecs, _tms, _num_tck) 126 | #define LIBXSVF_HOST_GETBYTE() h->getbyte(h) 127 | #define LIBXSVF_HOST_SYNC() (h->sync ? h->sync(h) : 0) 128 | #define LIBXSVF_HOST_PULSE_TCK(_tms, _tdi, _tdo, _rmask, _sync) h->pulse_tck(h, _tms, _tdi, _tdo, _rmask, _sync) 129 | #define LIBXSVF_HOST_PULSE_SCK() do { if (h->pulse_sck) h->pulse_sck(h); } while (0) 130 | #define LIBXSVF_HOST_SET_TRST(_v) do { if (h->set_trst) h->set_trst(h, _v); } while (0) 131 | #define LIBXSVF_HOST_SET_FREQUENCY(_v) (h->set_frequency ? h->set_frequency(h, _v) : -1) 132 | #define LIBXSVF_HOST_REPORT_TAPSTATE() do { if (h->report_tapstate) h->report_tapstate(h); } while (0) 133 | #define LIBXSVF_HOST_REPORT_DEVICE(_v) do { if (h->report_device) h->report_device(h, _v); } while (0) 134 | #define LIBXSVF_HOST_REPORT_STATUS(_msg) do { if (h->report_status) h->report_status(h, _msg); } while (0) 135 | #define LIBXSVF_HOST_REPORT_ERROR(_msg) h->report_error(h, __FILE__, __LINE__, _msg) 136 | #define LIBXSVF_HOST_REALLOC(_ptr, _size, _which) h->realloc(h, _ptr, _size, _which) 137 | 138 | #endif 139 | 140 | -------------------------------------------------------------------------------- /memname.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #include "libxsvf.h" 22 | 23 | const char *libxsvf_mem2str(enum libxsvf_mem which) 24 | { 25 | #define X(_w, _t) if (which == LIBXSVF_MEM_ ## _w) return #_t; 26 | X(XSVF_TDI_DATA, xsvf_tdi_data) 27 | X(XSVF_TDO_DATA, xsvf_tdo_data) 28 | X(XSVF_TDO_MASK, xsvf_tdo_mask) 29 | X(XSVF_ADDR_MASK, xsvf_addr_mask) 30 | X(XSVF_DATA_MASK, xsvf_data_mask) 31 | X(SVF_COMMANDBUF, svf_commandbuf) 32 | X(SVF_HDR_TDI_DATA, svf_hdr_tdi_data) 33 | X(SVF_HDR_TDI_MASK, svf_hdr_tdi_mask) 34 | X(SVF_HDR_TDO_DATA, svf_hdr_tdo_data) 35 | X(SVF_HDR_TDO_MASK, svf_hdr_tdo_mask) 36 | X(SVF_HDR_RET_MASK, svf_hdr_ret_mask) 37 | X(SVF_HIR_TDI_DATA, svf_hir_tdi_data) 38 | X(SVF_HIR_TDI_MASK, svf_hir_tdi_mask) 39 | X(SVF_HIR_TDO_DATA, svf_hir_tdo_data) 40 | X(SVF_HIR_TDO_MASK, svf_hir_tdo_mask) 41 | X(SVF_HIR_RET_MASK, svf_hir_ret_mask) 42 | X(SVF_TDR_TDI_DATA, svf_tdr_tdi_data) 43 | X(SVF_TDR_TDI_MASK, svf_tdr_tdi_mask) 44 | X(SVF_TDR_TDO_DATA, svf_tdr_tdo_data) 45 | X(SVF_TDR_TDO_MASK, svf_tdr_tdo_mask) 46 | X(SVF_TDR_RET_MASK, svf_tdr_ret_mask) 47 | X(SVF_TIR_TDI_DATA, svf_tir_tdi_data) 48 | X(SVF_TIR_TDI_MASK, svf_tir_tdi_mask) 49 | X(SVF_TIR_TDO_DATA, svf_tir_tdo_data) 50 | X(SVF_TIR_TDO_MASK, svf_tir_tdo_mask) 51 | X(SVF_TIR_RET_MASK, svf_tir_ret_mask) 52 | X(SVF_SDR_TDI_DATA, svf_sdr_tdi_data) 53 | X(SVF_SDR_TDI_MASK, svf_sdr_tdi_mask) 54 | X(SVF_SDR_TDO_DATA, svf_sdr_tdo_data) 55 | X(SVF_SDR_TDO_MASK, svf_sdr_tdo_mask) 56 | X(SVF_SDR_RET_MASK, svf_sdr_ret_mask) 57 | X(SVF_SIR_TDI_DATA, svf_sir_tdi_data) 58 | X(SVF_SIR_TDI_MASK, svf_sir_tdi_mask) 59 | X(SVF_SIR_TDO_DATA, svf_sir_tdo_data) 60 | X(SVF_SIR_TDO_MASK, svf_sir_tdo_mask) 61 | X(SVF_SIR_RET_MASK, svf_sir_ret_mask) 62 | #undef X 63 | return (void*)0; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /play.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #include "libxsvf.h" 22 | 23 | int libxsvf_play(struct libxsvf_host *h, enum libxsvf_mode mode) 24 | { 25 | int rc = -1; 26 | 27 | h->tap_state = LIBXSVF_TAP_INIT; 28 | if (LIBXSVF_HOST_SETUP() < 0) { 29 | LIBXSVF_HOST_REPORT_ERROR("Setup of JTAG interface failed."); 30 | return -1; 31 | } 32 | 33 | if (mode == LIBXSVF_MODE_SVF) { 34 | #ifdef LIBXSVF_WITHOUT_SVF 35 | LIBXSVF_HOST_REPORT_ERROR("SVF support in libxsvf is disabled."); 36 | #else 37 | rc = libxsvf_svf(h); 38 | #endif 39 | } 40 | 41 | if (mode == LIBXSVF_MODE_XSVF) { 42 | #ifdef LIBXSVF_WITHOUT_XSVF 43 | LIBXSVF_HOST_REPORT_ERROR("XSVF support in libxsvf is disabled."); 44 | #else 45 | rc = libxsvf_xsvf(h); 46 | #endif 47 | } 48 | 49 | if (mode == LIBXSVF_MODE_SCAN) { 50 | #ifdef LIBXSVF_WITHOUT_SCAN 51 | LIBXSVF_HOST_REPORT_ERROR("SCAN support in libxsvf is disabled."); 52 | #else 53 | rc = libxsvf_scan(h); 54 | #endif 55 | } 56 | 57 | libxsvf_tap_walk(h, LIBXSVF_TAP_RESET); 58 | if (LIBXSVF_HOST_SYNC() != 0 && rc >= 0 ) { 59 | LIBXSVF_HOST_REPORT_ERROR("TDO mismatch in TAP reset. (this is not possible!)"); 60 | rc = -1; 61 | } 62 | 63 | int shutdown_rc = LIBXSVF_HOST_SHUTDOWN(); 64 | 65 | if (shutdown_rc < 0) { 66 | LIBXSVF_HOST_REPORT_ERROR("Shutdown of JTAG interface failed."); 67 | rc = rc < 0 ? rc : shutdown_rc; 68 | } 69 | 70 | return rc; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /scan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #include "libxsvf.h" 22 | 23 | int libxsvf_scan(struct libxsvf_host *h) 24 | { 25 | int i, j; 26 | 27 | if (libxsvf_tap_walk(h, LIBXSVF_TAP_RESET) < 0) 28 | return -1; 29 | 30 | if (libxsvf_tap_walk(h, LIBXSVF_TAP_DRSHIFT) < 0) 31 | return -1; 32 | 33 | for (i=0; i<256; i++) 34 | { 35 | int bit = LIBXSVF_HOST_PULSE_TCK(0, 1, -1, 0, 1); 36 | 37 | if (bit < 0) 38 | return -1; 39 | 40 | if (bit == 0) { 41 | LIBXSVF_HOST_REPORT_DEVICE(0); 42 | } else { 43 | unsigned long idcode = 1; 44 | for (j=1; j<32; j++) { 45 | int bit = LIBXSVF_HOST_PULSE_TCK(0, 1, -1, 0, 1); 46 | if (bit < 0) 47 | return -1; 48 | idcode |= ((unsigned long)bit) << j; 49 | } 50 | if (idcode == 0xffffffff) 51 | break; 52 | LIBXSVF_HOST_REPORT_DEVICE(idcode); 53 | } 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /statename.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #include "libxsvf.h" 22 | 23 | const char *libxsvf_state2str(enum libxsvf_tap_state tap_state) 24 | { 25 | #define X(_s) if (tap_state == _s) return #_s; 26 | X(LIBXSVF_TAP_INIT) 27 | X(LIBXSVF_TAP_RESET) 28 | X(LIBXSVF_TAP_IDLE) 29 | X(LIBXSVF_TAP_DRSELECT) 30 | X(LIBXSVF_TAP_DRCAPTURE) 31 | X(LIBXSVF_TAP_DRSHIFT) 32 | X(LIBXSVF_TAP_DREXIT1) 33 | X(LIBXSVF_TAP_DRPAUSE) 34 | X(LIBXSVF_TAP_DREXIT2) 35 | X(LIBXSVF_TAP_DRUPDATE) 36 | X(LIBXSVF_TAP_IRSELECT) 37 | X(LIBXSVF_TAP_IRCAPTURE) 38 | X(LIBXSVF_TAP_IRSHIFT) 39 | X(LIBXSVF_TAP_IREXIT1) 40 | X(LIBXSVF_TAP_IRPAUSE) 41 | X(LIBXSVF_TAP_IREXIT2) 42 | X(LIBXSVF_TAP_IRUPDATE) 43 | #undef X 44 | return "UNKOWN_STATE"; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /svf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #include "libxsvf.h" 22 | 23 | static int read_command(struct libxsvf_host *h, char **buffer_p, int *len_p) 24 | { 25 | char *buffer = *buffer_p; 26 | int braket_mode = 0; 27 | int len = *len_p; 28 | int p = 0; 29 | 30 | while (1) 31 | { 32 | if (len < p+10) { 33 | len = len < 64 ? 96 : len*2; 34 | buffer = LIBXSVF_HOST_REALLOC(buffer, len, LIBXSVF_MEM_SVF_COMMANDBUF); 35 | *buffer_p = buffer; 36 | *len_p = len; 37 | if (!buffer) { 38 | LIBXSVF_HOST_REPORT_ERROR("Allocating memory failed."); 39 | return -1; 40 | } 41 | } 42 | buffer[p] = 0; 43 | 44 | int ch = LIBXSVF_HOST_GETBYTE(); 45 | if (ch < 0) { 46 | handle_eof: 47 | if (p == 0) 48 | return 0; 49 | LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF."); 50 | return -1; 51 | } 52 | if (ch <= ' ') { 53 | insert_eol: 54 | if (!braket_mode && p > 0 && buffer[p-1] != ' ') 55 | buffer[p++] = ' '; 56 | continue; 57 | } 58 | if (ch == '!') { 59 | skip_to_eol: 60 | while (1) { 61 | ch = LIBXSVF_HOST_GETBYTE(); 62 | if (ch < 0) 63 | goto handle_eof; 64 | if (ch < ' ' && ch != '\t') 65 | goto insert_eol; 66 | } 67 | } 68 | if (ch == '/' && p > 0 && buffer[p-1] == '/') { 69 | p--; 70 | goto skip_to_eol; 71 | } 72 | if (ch == ';') 73 | break; 74 | if (ch == '(') { 75 | if (!braket_mode && p > 0 && buffer[p-1] != ' ') 76 | buffer[p++] = ' '; 77 | braket_mode++; 78 | } 79 | if (ch >= 'a' && ch <= 'z') 80 | buffer[p++] = ch - ('a' - 'A'); 81 | else 82 | buffer[p++] = ch; 83 | if (ch == ')') { 84 | braket_mode--; 85 | if (!braket_mode) 86 | buffer[p++] = ' '; 87 | } 88 | } 89 | return 1; 90 | } 91 | 92 | static int strtokencmp(const char *str1, const char *str2) 93 | { 94 | int i = 0; 95 | while (1) { 96 | if ((str1[i] == ' ' || str1[i] == 0) && (str2[i] == ' ' || str2[i] == 0)) 97 | return 0; 98 | if (str1[i] < str2[i]) 99 | return -1; 100 | if (str1[i] > str2[i]) 101 | return +1; 102 | i++; 103 | } 104 | } 105 | 106 | static int strtokenskip(const char *str1) 107 | { 108 | int i = 0; 109 | while (str1[i] != 0 && str1[i] != ' ') i++; 110 | while (str1[i] == ' ') i++; 111 | return i; 112 | } 113 | 114 | static int token2tapstate(const char *str1) 115 | { 116 | #define X(_t) if (!strtokencmp(str1, #_t)) return LIBXSVF_TAP_ ## _t; 117 | X(RESET) 118 | X(IDLE) 119 | X(DRSELECT) 120 | X(DRCAPTURE) 121 | X(DRSHIFT) 122 | X(DREXIT1) 123 | X(DRPAUSE) 124 | X(DREXIT2) 125 | X(DRUPDATE) 126 | X(IRSELECT) 127 | X(IRCAPTURE) 128 | X(IRSHIFT) 129 | X(IREXIT1) 130 | X(IRPAUSE) 131 | X(IREXIT2) 132 | X(IRUPDATE) 133 | #undef X 134 | return -1; 135 | } 136 | 137 | struct bitdata_s { 138 | int len, alloced_len; 139 | int alloced_bytes; 140 | unsigned char *tdi_data; 141 | unsigned char *tdi_mask; 142 | unsigned char *tdo_data; 143 | unsigned char *tdo_mask; 144 | unsigned char *ret_mask; 145 | int has_tdo_data; 146 | }; 147 | 148 | static void bitdata_free(struct libxsvf_host *h, struct bitdata_s *bd, int offset) 149 | { 150 | LIBXSVF_HOST_REALLOC(bd->tdi_data, 0, offset+0); 151 | LIBXSVF_HOST_REALLOC(bd->tdi_mask, 0, offset+1); 152 | LIBXSVF_HOST_REALLOC(bd->tdo_data, 0, offset+2); 153 | LIBXSVF_HOST_REALLOC(bd->tdo_mask, 0, offset+3); 154 | LIBXSVF_HOST_REALLOC(bd->ret_mask, 0, offset+4); 155 | 156 | bd->tdi_data = (void*)0; 157 | bd->tdi_mask = (void*)0; 158 | bd->tdo_data = (void*)0; 159 | bd->tdo_mask = (void*)0; 160 | bd->ret_mask = (void*)0; 161 | } 162 | 163 | static int hex(char ch) 164 | { 165 | if (ch >= 'A' && ch <= 'Z') 166 | return (ch - 'A') + 10; 167 | if (ch >= '0' && ch <= '9') 168 | return ch - '0'; 169 | return 0; 170 | } 171 | 172 | static const char *bitdata_parse(struct libxsvf_host *h, const char *p, struct bitdata_s *bd, int offset) 173 | { 174 | int i, j; 175 | bd->len = 0; 176 | bd->has_tdo_data = 0; 177 | while (*p >= '0' && *p <= '9') { 178 | bd->len = bd->len * 10 + (*p - '0'); 179 | p++; 180 | } 181 | while (*p == ' ') { 182 | p++; 183 | } 184 | if (bd->len != bd->alloced_len) { 185 | bitdata_free(h, bd, offset); 186 | bd->alloced_len = bd->len; 187 | bd->alloced_bytes = (bd->len+7) / 8; 188 | } 189 | while (*p) 190 | { 191 | int memnum = 0; 192 | unsigned char **dp = (void*)0; 193 | if (!strtokencmp(p, "TDI")) { 194 | p += strtokenskip(p); 195 | dp = &bd->tdi_data; 196 | memnum = 0; 197 | } 198 | if (!strtokencmp(p, "TDO")) { 199 | p += strtokenskip(p); 200 | dp = &bd->tdo_data; 201 | bd->has_tdo_data = 1; 202 | memnum = 1; 203 | } 204 | if (!strtokencmp(p, "SMASK")) { 205 | p += strtokenskip(p); 206 | dp = &bd->tdi_mask; 207 | memnum = 2; 208 | } 209 | if (!strtokencmp(p, "MASK")) { 210 | p += strtokenskip(p); 211 | dp = &bd->tdo_mask; 212 | memnum = 3; 213 | } 214 | if (!strtokencmp(p, "RMASK")) { 215 | p += strtokenskip(p); 216 | dp = &bd->ret_mask; 217 | memnum = 4; 218 | } 219 | if (!dp) 220 | return (void*)0; 221 | if (*dp == (void*)0) { 222 | *dp = LIBXSVF_HOST_REALLOC(*dp, bd->alloced_bytes, offset+memnum); 223 | } 224 | if (*dp == (void*)0) { 225 | LIBXSVF_HOST_REPORT_ERROR("Allocating memory failed."); 226 | return (void*)0; 227 | } 228 | 229 | unsigned char *d = *dp; 230 | for (i=0; ialloced_bytes; i++) 231 | d[i] = 0; 232 | 233 | if (*p != '(') 234 | return (void*)0; 235 | p++; 236 | 237 | int hexdigits = 0; 238 | for (i=0; (p[i] >= 'A' && p[i] <= 'F') || (p[i] >= '0' && p[i] <= '9'); i++) 239 | hexdigits++; 240 | 241 | i = bd->alloced_bytes*2 - hexdigits; 242 | for (j=0; j */ 259 | printf("--- Parsed bitdata [%d] ---\n", bd->len); 260 | if (bd->tdi_data) { 261 | printf("TDI DATA:"); 262 | for (i=0; ialloced_bytes; i++) 263 | printf(" %02x", bd->tdi_data[i]); 264 | printf("\n"); 265 | } 266 | if (bd->tdo_data && has_tdo_data) { 267 | printf("TDO DATA:"); 268 | for (i=0; ialloced_bytes; i++) 269 | printf(" %02x", bd->tdo_data[i]); 270 | printf("\n"); 271 | } 272 | if (bd->tdi_mask) { 273 | printf("TDI MASK:"); 274 | for (i=0; ialloced_bytes; i++) 275 | printf(" %02x", bd->tdi_mask[i]); 276 | printf("\n"); 277 | } 278 | if (bd->tdo_mask) { 279 | printf("TDO MASK:"); 280 | for (i=0; ialloced_bytes; i++) 281 | printf(" %02x", bd->tdo_mask[i]); 282 | printf("\n"); 283 | } 284 | #endif 285 | return p; 286 | } 287 | 288 | static int getbit(unsigned char *data, int n) 289 | { 290 | return (data[n/8] & (1 << (7 - n%8))) ? 1 : 0; 291 | } 292 | 293 | static int bitdata_play(struct libxsvf_host *h, struct bitdata_s *bd, enum libxsvf_tap_state estate) 294 | { 295 | int left_padding = (8 - bd->len % 8) % 8; 296 | int tdo_error = 0; 297 | int tms = 0; 298 | int i; 299 | 300 | for (i=bd->len+left_padding-1; i >= left_padding; i--) { 301 | if (i == left_padding && h->tap_state != estate) { 302 | h->tap_state++; 303 | tms = 1; 304 | } 305 | int tdi = -1; 306 | if (bd->tdi_data) { 307 | if (!bd->tdi_mask || getbit(bd->tdi_mask, i)) 308 | tdi = getbit(bd->tdi_data, i); 309 | } 310 | int tdo = -1; 311 | if (bd->tdo_data && bd->has_tdo_data && (!bd->tdo_mask || getbit(bd->tdo_mask, i))) 312 | tdo = getbit(bd->tdo_data, i); 313 | int rmask = bd->ret_mask && getbit(bd->ret_mask, i); 314 | if (LIBXSVF_HOST_PULSE_TCK(tms, tdi, tdo, rmask, 0) < 0) 315 | tdo_error = 1; 316 | } 317 | 318 | if (tms) 319 | LIBXSVF_HOST_REPORT_TAPSTATE(); 320 | 321 | if (!tdo_error) 322 | return 0; 323 | 324 | LIBXSVF_HOST_REPORT_ERROR("TDO mismatch."); 325 | return -1; 326 | } 327 | 328 | int libxsvf_svf(struct libxsvf_host *h) 329 | { 330 | char *command_buffer = (void*)0; 331 | int command_buffer_len = 0; 332 | int rc, i; 333 | 334 | struct bitdata_s bd_hdr = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 }; 335 | struct bitdata_s bd_hir = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 }; 336 | struct bitdata_s bd_tdr = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 }; 337 | struct bitdata_s bd_tir = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 }; 338 | struct bitdata_s bd_sdr = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 }; 339 | struct bitdata_s bd_sir = { 0, 0, 0, (void*)0, (void*)0, (void*)0, (void*)0, (void*)0 }; 340 | 341 | int state_endir = LIBXSVF_TAP_IDLE; 342 | int state_enddr = LIBXSVF_TAP_IDLE; 343 | int state_run = LIBXSVF_TAP_IDLE; 344 | int state_endrun = LIBXSVF_TAP_IDLE; 345 | 346 | while (1) 347 | { 348 | rc = read_command(h, &command_buffer, &command_buffer_len); 349 | 350 | if (rc <= 0) 351 | break; 352 | 353 | const char *p = command_buffer; 354 | 355 | LIBXSVF_HOST_REPORT_STATUS(command_buffer); 356 | 357 | if (!strtokencmp(p, "ENDIR")) { 358 | p += strtokenskip(p); 359 | state_endir = token2tapstate(p); 360 | if (state_endir < 0) 361 | goto syntax_error; 362 | p += strtokenskip(p); 363 | goto eol_check; 364 | } 365 | 366 | if (!strtokencmp(p, "ENDDR")) { 367 | p += strtokenskip(p); 368 | state_enddr = token2tapstate(p); 369 | if (state_endir < 0) 370 | goto syntax_error; 371 | p += strtokenskip(p); 372 | goto eol_check; 373 | } 374 | 375 | if (!strtokencmp(p, "FREQUENCY")) { 376 | while (*p > 0 && *p >= ' ') { 377 | p++; 378 | } 379 | /* 380 | unsigned long number = 0; 381 | int exp = 0; 382 | p += strtokenskip(p); 383 | if (*p < '0' || *p > '9') 384 | goto syntax_error; 385 | while (*p >= '0' && *p <= '9') { 386 | number = number*10 + (*p - '0'); 387 | p++; 388 | } 389 | if(*p == 'E' || *p == 'e') { 390 | p++; 391 | while (*p >= '0' && *p <= '9') { 392 | exp = exp*10 + (*p - '0'); 393 | p++; 394 | } 395 | for(i=0; i= 0) { 449 | p += strtokenskip(p); 450 | if (got_endstate) 451 | state_endrun = st; 452 | else 453 | state_run = st; 454 | continue; 455 | } 456 | if (*p < '0' || *p > '9') 457 | goto syntax_error; 458 | int number = 0; 459 | int exp = 0, expsign = 1; 460 | int number_e6, exp_e6; 461 | while (*p >= '0' && *p <= '9') { 462 | number = number*10 + (*p - '0'); 463 | p++; 464 | } 465 | if(*p == 'E' || *p == 'e') { 466 | p++; 467 | if(*p == '-') { 468 | expsign = -1; 469 | p++; 470 | } 471 | while (*p >= '0' && *p <= '9') { 472 | exp = exp*10 + (*p - '0'); 473 | p++; 474 | } 475 | exp = exp * expsign; 476 | number_e6 = number; 477 | exp_e6 = exp + 6; 478 | while (exp < 0) { 479 | number /= 10; 480 | exp++; 481 | } 482 | while (exp > 0) { 483 | number *= 10; 484 | exp--; 485 | } 486 | while (exp_e6 < 0) { 487 | number_e6 /= 10; 488 | exp_e6++; 489 | } 490 | while (exp_e6 > 0) { 491 | number_e6 *= 10; 492 | exp_e6--; 493 | } 494 | } else { 495 | number_e6 = number * 1000000; 496 | } 497 | while (*p == ' ') { 498 | p++; 499 | } 500 | if (!strtokencmp(p, "SEC")) { 501 | p += strtokenskip(p); 502 | if (got_maximum) 503 | max_time = number_e6; 504 | else 505 | min_time = number_e6; 506 | continue; 507 | } 508 | if (!strtokencmp(p, "TCK")) { 509 | p += strtokenskip(p); 510 | tck_count = number; 511 | continue; 512 | } 513 | if (!strtokencmp(p, "SCK")) { 514 | p += strtokenskip(p); 515 | sck_count = number; 516 | continue; 517 | } 518 | goto syntax_error; 519 | } 520 | if (libxsvf_tap_walk(h, state_run) < 0) 521 | goto error; 522 | if (max_time >= 0) { 523 | LIBXSVF_HOST_REPORT_ERROR("WARNING: Maximum time in SVF RUNTEST command is ignored."); 524 | } 525 | if (sck_count >= 0) { 526 | for (i=0; i < sck_count; i++) { 527 | LIBXSVF_HOST_PULSE_SCK(); 528 | } 529 | } 530 | if (min_time >= 0 || tck_count >= 0) { 531 | LIBXSVF_HOST_UDELAY(min_time >= 0 ? min_time : 0, 0, tck_count >= 0 ? tck_count : 0); 532 | } 533 | if (libxsvf_tap_walk(h, state_endrun) < 0) 534 | goto error; 535 | goto eol_check; 536 | } 537 | 538 | if (!strtokencmp(p, "SDR")) { 539 | p += strtokenskip(p); 540 | p = bitdata_parse(h, p, &bd_sdr, LIBXSVF_MEM_SVF_SDR_TDI_DATA); 541 | if (!p) 542 | goto syntax_error; 543 | if (libxsvf_tap_walk(h, LIBXSVF_TAP_DRSHIFT) < 0) 544 | goto error; 545 | if (bitdata_play(h, &bd_hdr, bd_sdr.len+bd_tdr.len > 0 ? LIBXSVF_TAP_DRSHIFT : state_enddr) < 0) 546 | goto error; 547 | if (bitdata_play(h, &bd_sdr, bd_tdr.len > 0 ? LIBXSVF_TAP_DRSHIFT : state_enddr) < 0) 548 | goto error; 549 | if (bitdata_play(h, &bd_tdr, state_enddr) < 0) 550 | goto error; 551 | if (libxsvf_tap_walk(h, state_enddr) < 0) 552 | goto error; 553 | goto eol_check; 554 | } 555 | 556 | if (!strtokencmp(p, "SIR")) { 557 | p += strtokenskip(p); 558 | p = bitdata_parse(h, p, &bd_sir, LIBXSVF_MEM_SVF_SIR_TDI_DATA); 559 | if (!p) 560 | goto syntax_error; 561 | if (libxsvf_tap_walk(h, LIBXSVF_TAP_IRSHIFT) < 0) 562 | goto error; 563 | if (bitdata_play(h, &bd_hir, bd_sir.len+bd_tir.len > 0 ? LIBXSVF_TAP_IRSHIFT : state_endir) < 0) 564 | goto error; 565 | if (bitdata_play(h, &bd_sir, bd_tir.len > 0 ? LIBXSVF_TAP_IRSHIFT : state_endir) < 0) 566 | goto error; 567 | if (bitdata_play(h, &bd_tir, state_endir) < 0) 568 | goto error; 569 | if (libxsvf_tap_walk(h, state_endir) < 0) 570 | goto error; 571 | goto eol_check; 572 | } 573 | 574 | if (!strtokencmp(p, "STATE")) { 575 | p += strtokenskip(p); 576 | while (*p) { 577 | int st = token2tapstate(p); 578 | if (st < 0) 579 | goto syntax_error; 580 | if (libxsvf_tap_walk(h, st) < 0) 581 | goto error; 582 | p += strtokenskip(p); 583 | } 584 | goto eol_check; 585 | } 586 | 587 | if (!strtokencmp(p, "TDR")) { 588 | p += strtokenskip(p); 589 | p = bitdata_parse(h, p, &bd_tdr, LIBXSVF_MEM_SVF_TDR_TDI_DATA); 590 | if (!p) 591 | goto syntax_error; 592 | goto eol_check; 593 | } 594 | 595 | if (!strtokencmp(p, "TIR")) { 596 | p += strtokenskip(p); 597 | p = bitdata_parse(h, p, &bd_tir, LIBXSVF_MEM_SVF_TIR_TDI_DATA); 598 | if (!p) 599 | goto syntax_error; 600 | goto eol_check; 601 | } 602 | 603 | if (!strtokencmp(p, "TRST")) { 604 | p += strtokenskip(p); 605 | if (!strtokencmp(p, "ON")) { 606 | p += strtokenskip(p); 607 | LIBXSVF_HOST_SET_TRST(1); 608 | goto eol_check; 609 | } 610 | if (!strtokencmp(p, "OFF")) { 611 | p += strtokenskip(p); 612 | LIBXSVF_HOST_SET_TRST(0); 613 | goto eol_check; 614 | } 615 | if (!strtokencmp(p, "Z")) { 616 | p += strtokenskip(p); 617 | LIBXSVF_HOST_SET_TRST(-1); 618 | goto eol_check; 619 | } 620 | if (!strtokencmp(p, "ABSENT")) { 621 | p += strtokenskip(p); 622 | LIBXSVF_HOST_SET_TRST(-2); 623 | goto eol_check; 624 | } 625 | goto syntax_error; 626 | } 627 | 628 | eol_check: 629 | while (*p == ' ') 630 | p++; 631 | if (*p == 0) 632 | continue; 633 | 634 | syntax_error: 635 | LIBXSVF_HOST_REPORT_ERROR("SVF Syntax Error:"); 636 | if (0) { 637 | unsupported_error: 638 | LIBXSVF_HOST_REPORT_ERROR("Error in SVF input: unsupported command:"); 639 | } 640 | LIBXSVF_HOST_REPORT_ERROR(command_buffer); 641 | error: 642 | rc = -1; 643 | break; 644 | } 645 | 646 | if (LIBXSVF_HOST_SYNC() != 0 && rc >= 0 ) { 647 | LIBXSVF_HOST_REPORT_ERROR("TDO mismatch."); 648 | rc = -1; 649 | } 650 | 651 | bitdata_free(h, &bd_hdr, LIBXSVF_MEM_SVF_HDR_TDI_DATA); 652 | bitdata_free(h, &bd_hir, LIBXSVF_MEM_SVF_HIR_TDI_DATA); 653 | bitdata_free(h, &bd_tdr, LIBXSVF_MEM_SVF_TDR_TDI_DATA); 654 | bitdata_free(h, &bd_tir, LIBXSVF_MEM_SVF_TIR_TDI_DATA); 655 | bitdata_free(h, &bd_sdr, LIBXSVF_MEM_SVF_SDR_TDI_DATA); 656 | bitdata_free(h, &bd_sir, LIBXSVF_MEM_SVF_SIR_TDI_DATA); 657 | 658 | LIBXSVF_HOST_REALLOC(command_buffer, 0, LIBXSVF_MEM_SVF_COMMANDBUF); 659 | 660 | return rc; 661 | } 662 | 663 | -------------------------------------------------------------------------------- /tap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #include "libxsvf.h" 22 | 23 | static void tap_transition(struct libxsvf_host *h, int v) 24 | { 25 | LIBXSVF_HOST_PULSE_TCK(v, -1, -1, 0, 0); 26 | } 27 | 28 | int libxsvf_tap_walk(struct libxsvf_host *h, enum libxsvf_tap_state s) 29 | { 30 | int i, j; 31 | for (i=0; s != h->tap_state; i++) 32 | { 33 | switch (h->tap_state) 34 | { 35 | /* Special States */ 36 | case LIBXSVF_TAP_INIT: 37 | for (j = 0; j < 6; j++) 38 | tap_transition(h, 1); 39 | h->tap_state = LIBXSVF_TAP_RESET; 40 | break; 41 | case LIBXSVF_TAP_RESET: 42 | tap_transition(h, 0); 43 | h->tap_state = LIBXSVF_TAP_IDLE; 44 | break; 45 | case LIBXSVF_TAP_IDLE: 46 | tap_transition(h, 1); 47 | h->tap_state = LIBXSVF_TAP_DRSELECT; 48 | break; 49 | 50 | /* DR States */ 51 | case LIBXSVF_TAP_DRSELECT: 52 | if (s >= LIBXSVF_TAP_IRSELECT || s == LIBXSVF_TAP_RESET) { 53 | tap_transition(h, 1); 54 | h->tap_state = LIBXSVF_TAP_IRSELECT; 55 | } else { 56 | tap_transition(h, 0); 57 | h->tap_state = LIBXSVF_TAP_DRCAPTURE; 58 | } 59 | break; 60 | case LIBXSVF_TAP_DRCAPTURE: 61 | if (s == LIBXSVF_TAP_DRSHIFT) { 62 | tap_transition(h, 0); 63 | h->tap_state = LIBXSVF_TAP_DRSHIFT; 64 | } else { 65 | tap_transition(h, 1); 66 | h->tap_state = LIBXSVF_TAP_DREXIT1; 67 | } 68 | break; 69 | case LIBXSVF_TAP_DRSHIFT: 70 | tap_transition(h, 1); 71 | h->tap_state = LIBXSVF_TAP_DREXIT1; 72 | break; 73 | case LIBXSVF_TAP_DREXIT1: 74 | if (s == LIBXSVF_TAP_DRPAUSE) { 75 | tap_transition(h, 0); 76 | h->tap_state = LIBXSVF_TAP_DRPAUSE; 77 | } else { 78 | tap_transition(h, 1); 79 | h->tap_state = LIBXSVF_TAP_DRUPDATE; 80 | } 81 | break; 82 | case LIBXSVF_TAP_DRPAUSE: 83 | tap_transition(h, 1); 84 | h->tap_state = LIBXSVF_TAP_DREXIT2; 85 | break; 86 | case LIBXSVF_TAP_DREXIT2: 87 | if (s == LIBXSVF_TAP_DRSHIFT) { 88 | tap_transition(h, 0); 89 | h->tap_state = LIBXSVF_TAP_DRSHIFT; 90 | } else { 91 | tap_transition(h, 1); 92 | h->tap_state = LIBXSVF_TAP_DRUPDATE; 93 | } 94 | break; 95 | case LIBXSVF_TAP_DRUPDATE: 96 | if (s == LIBXSVF_TAP_IDLE) { 97 | tap_transition(h, 0); 98 | h->tap_state = LIBXSVF_TAP_IDLE; 99 | } else { 100 | tap_transition(h, 1); 101 | h->tap_state = LIBXSVF_TAP_DRSELECT; 102 | } 103 | break; 104 | 105 | /* IR States */ 106 | case LIBXSVF_TAP_IRSELECT: 107 | if (s == LIBXSVF_TAP_RESET) { 108 | tap_transition(h, 1); 109 | h->tap_state = LIBXSVF_TAP_RESET; 110 | } else { 111 | tap_transition(h, 0); 112 | h->tap_state = LIBXSVF_TAP_IRCAPTURE; 113 | } 114 | break; 115 | case LIBXSVF_TAP_IRCAPTURE: 116 | if (s == LIBXSVF_TAP_IRSHIFT) { 117 | tap_transition(h, 0); 118 | h->tap_state = LIBXSVF_TAP_IRSHIFT; 119 | } else { 120 | tap_transition(h, 1); 121 | h->tap_state = LIBXSVF_TAP_IREXIT1; 122 | } 123 | break; 124 | case LIBXSVF_TAP_IRSHIFT: 125 | tap_transition(h, 1); 126 | h->tap_state = LIBXSVF_TAP_IREXIT1; 127 | break; 128 | case LIBXSVF_TAP_IREXIT1: 129 | if (s == LIBXSVF_TAP_IRPAUSE) { 130 | tap_transition(h, 0); 131 | h->tap_state = LIBXSVF_TAP_IRPAUSE; 132 | } else { 133 | tap_transition(h, 1); 134 | h->tap_state = LIBXSVF_TAP_IRUPDATE; 135 | } 136 | break; 137 | case LIBXSVF_TAP_IRPAUSE: 138 | tap_transition(h, 1); 139 | h->tap_state = LIBXSVF_TAP_IREXIT2; 140 | break; 141 | case LIBXSVF_TAP_IREXIT2: 142 | if (s == LIBXSVF_TAP_IRSHIFT) { 143 | tap_transition(h, 0); 144 | h->tap_state = LIBXSVF_TAP_IRSHIFT; 145 | } else { 146 | tap_transition(h, 1); 147 | h->tap_state = LIBXSVF_TAP_IRUPDATE; 148 | } 149 | break; 150 | case LIBXSVF_TAP_IRUPDATE: 151 | if (s == LIBXSVF_TAP_IDLE) { 152 | tap_transition(h, 0); 153 | h->tap_state = LIBXSVF_TAP_IDLE; 154 | } else { 155 | tap_transition(h, 1); 156 | h->tap_state = LIBXSVF_TAP_DRSELECT; 157 | } 158 | break; 159 | 160 | default: 161 | LIBXSVF_HOST_REPORT_ERROR("Illegal tap state."); 162 | return -1; 163 | } 164 | if (h->report_tapstate) 165 | LIBXSVF_HOST_REPORT_TAPSTATE(); 166 | if (i>10) { 167 | LIBXSVF_HOST_REPORT_ERROR("Loop in tap walker."); 168 | return -1; 169 | } 170 | } 171 | 172 | return 0; 173 | } 174 | -------------------------------------------------------------------------------- /xsvf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Lib(X)SVF - A library for implementing SVF and XSVF JTAG players 3 | * 4 | * Copyright (C) 2009 RIEGL Research ForschungsGmbH 5 | * Copyright (C) 2009 Clifford Wolf 6 | * 7 | * Permission to use, copy, modify, and/or distribute this software for any 8 | * purpose with or without fee is hereby granted, provided that the above 9 | * copyright notice and this permission notice appear in all copies. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | * 19 | */ 20 | 21 | #include "libxsvf.h" 22 | 23 | /* command codes as defined in xilinx xapp503 */ 24 | enum xsvf_cmd { 25 | XCOMPLETE = 0x00, 26 | XTDOMASK = 0x01, 27 | XSIR = 0x02, 28 | XSDR = 0x03, 29 | XRUNTEST = 0x04, 30 | XREPEAT = 0x07, 31 | XSDRSIZE = 0x08, 32 | XSDRTDO = 0x09, 33 | XSETSDRMASKS = 0x0A, 34 | XSDRINC = 0x0B, 35 | XSDRB = 0x0C, 36 | XSDRC = 0x0D, 37 | XSDRE = 0x0E, 38 | XSDRTDOB = 0x0F, 39 | XSDRTDOC = 0x10, 40 | XSDRTDOE = 0x11, 41 | XSTATE = 0x12, 42 | XENDIR = 0x13, 43 | XENDDR = 0x14, 44 | XSIR2 = 0x15, 45 | XCOMMENT = 0x16, 46 | XWAIT = 0x17, 47 | /* Extensions used in svf2xsvf.py */ 48 | XWAITSTATE = 0x18, 49 | XTRST = 0x1c 50 | }; 51 | 52 | // This is to not confuse the VIM syntax highlighting 53 | #define VAL_OPEN ( 54 | #define VAL_CLOSE ) 55 | 56 | #define READ_BITS(_buf, _len) do { \ 57 | unsigned char *_p = _buf; int _i; \ 58 | for (_i=0; _i<(_len); _i+=8) { \ 59 | int tmp = LIBXSVF_HOST_GETBYTE(); \ 60 | if (tmp < 0) { \ 61 | LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF."); \ 62 | goto error; \ 63 | } \ 64 | *(_p++) = tmp; \ 65 | } \ 66 | } while (0) 67 | 68 | #define READ_LONG() VAL_OPEN{ \ 69 | long _buf = 0; int _i; \ 70 | for (_i=0; _i<4; _i++) { \ 71 | int tmp = LIBXSVF_HOST_GETBYTE(); \ 72 | if (tmp < 0) { \ 73 | LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF."); \ 74 | goto error; \ 75 | } \ 76 | _buf = _buf << 8 | tmp; \ 77 | } \ 78 | _buf; \ 79 | }VAL_CLOSE 80 | 81 | #define READ_BYTE() VAL_OPEN{ \ 82 | int _tmp = LIBXSVF_HOST_GETBYTE(); \ 83 | if (_tmp < 0) { \ 84 | LIBXSVF_HOST_REPORT_ERROR("Unexpected EOF."); \ 85 | goto error; \ 86 | } \ 87 | _tmp; \ 88 | }VAL_CLOSE 89 | 90 | #define SHIFT_DATA(_inp, _outp, _maskp, _len, _state, _estate, _edelay, _ret) do { \ 91 | if (shift_data(h, _inp, _outp, _maskp, _len, _state, _estate, _edelay, _ret) < 0) { \ 92 | goto error; \ 93 | } \ 94 | } while (0) 95 | 96 | #define TAP(_state) do { \ 97 | if (libxsvf_tap_walk(h, _state) < 0) \ 98 | goto error; \ 99 | } while (0) 100 | 101 | static int bits2bytes(int bits) 102 | { 103 | return (bits+7) / 8; 104 | } 105 | 106 | static int getbit(unsigned char *data, int n) 107 | { 108 | return (data[n/8] & (1 << (7 - n%8))) ? 1 : 0; 109 | } 110 | 111 | static void setbit(unsigned char *data, int n, int v) 112 | { 113 | unsigned char mask = 1 << (7 - n%8); 114 | if (v) 115 | data[n/8] |= mask; 116 | else 117 | data[n/8] &= ~mask; 118 | } 119 | 120 | static int xilinx_tap(int state) 121 | { 122 | /* state codes as defined in xilinx xapp503 */ 123 | switch (state) 124 | { 125 | case 0x00: 126 | return LIBXSVF_TAP_RESET; 127 | break; 128 | case 0x01: 129 | return LIBXSVF_TAP_IDLE; 130 | break; 131 | case 0x02: 132 | return LIBXSVF_TAP_DRSELECT; 133 | break; 134 | case 0x03: 135 | return LIBXSVF_TAP_DRCAPTURE; 136 | break; 137 | case 0x04: 138 | return LIBXSVF_TAP_DRSHIFT; 139 | break; 140 | case 0x05: 141 | return LIBXSVF_TAP_DREXIT1; 142 | break; 143 | case 0x06: 144 | return LIBXSVF_TAP_DRPAUSE; 145 | break; 146 | case 0x07: 147 | return LIBXSVF_TAP_DREXIT2; 148 | break; 149 | case 0x08: 150 | return LIBXSVF_TAP_DRUPDATE; 151 | break; 152 | case 0x09: 153 | return LIBXSVF_TAP_IRSELECT; 154 | break; 155 | case 0x0A: 156 | return LIBXSVF_TAP_IRCAPTURE; 157 | break; 158 | case 0x0B: 159 | return LIBXSVF_TAP_IRSHIFT; 160 | break; 161 | case 0x0C: 162 | return LIBXSVF_TAP_IREXIT1; 163 | break; 164 | case 0x0D: 165 | return LIBXSVF_TAP_IRPAUSE; 166 | break; 167 | case 0x0E: 168 | return LIBXSVF_TAP_IREXIT2; 169 | break; 170 | case 0x0F: 171 | return LIBXSVF_TAP_IRUPDATE; 172 | break; 173 | } 174 | return -1; 175 | } 176 | 177 | static int shift_data(struct libxsvf_host *h, unsigned char *inp, unsigned char *outp, unsigned char *maskp, int len, enum libxsvf_tap_state state, enum libxsvf_tap_state estate, int edelay, int retries) 178 | { 179 | int left_padding = (8 - len % 8) % 8; 180 | int with_retries = retries > 0; 181 | int i; 182 | 183 | if (with_retries && LIBXSVF_HOST_SYNC() < 0) { 184 | LIBXSVF_HOST_REPORT_ERROR("TDO mismatch."); 185 | return -1; 186 | } 187 | 188 | while (1) 189 | { 190 | int tdo_error = 0; 191 | int tms = 0; 192 | 193 | TAP(state); 194 | tms = 0; 195 | 196 | for (i=len+left_padding-1; i>=left_padding; i--) { 197 | if (i == left_padding && h->tap_state != estate) { 198 | h->tap_state++; 199 | tms = 1; 200 | } 201 | int tdi = getbit(inp, i); 202 | int tdo = -1; 203 | if (maskp && getbit(maskp, i)) 204 | tdo = outp && getbit(outp, i); 205 | int sync = with_retries && i == left_padding; 206 | if (LIBXSVF_HOST_PULSE_TCK(tms, tdi, tdo, 0, sync) < 0) 207 | tdo_error = 1; 208 | } 209 | 210 | if (tms) 211 | LIBXSVF_HOST_REPORT_TAPSTATE(); 212 | 213 | if (edelay) { 214 | TAP(LIBXSVF_TAP_IDLE); 215 | LIBXSVF_HOST_UDELAY(edelay, 0, edelay); 216 | } else { 217 | TAP(estate); 218 | } 219 | 220 | if (!tdo_error) 221 | return 0; 222 | 223 | if (retries <= 0) { 224 | LIBXSVF_HOST_REPORT_ERROR("TDO mismatch."); 225 | return -1; 226 | } 227 | 228 | retries--; 229 | } 230 | 231 | error: 232 | return -1; 233 | } 234 | 235 | int libxsvf_xsvf(struct libxsvf_host *h) 236 | { 237 | int rc = 0; 238 | int i, j; 239 | 240 | unsigned char *buf_tdi_data = (void*)0; 241 | unsigned char *buf_tdo_data = (void*)0; 242 | unsigned char *buf_tdo_mask = (void*)0; 243 | unsigned char *buf_addr_mask = (void*)0; 244 | unsigned char *buf_data_mask = (void*)0; 245 | 246 | long state_dr_size = 0; 247 | long state_data_size = 0; 248 | long state_runtest = 0; 249 | unsigned char state_xendir = 0; 250 | unsigned char state_xenddr = 0; 251 | unsigned char state_retries = 0; 252 | unsigned char cmd = 0; 253 | 254 | while (1) 255 | { 256 | unsigned char last_cmd = cmd; 257 | cmd = LIBXSVF_HOST_GETBYTE(); 258 | 259 | #define STATUS(_c) LIBXSVF_HOST_REPORT_STATUS("XSVF Command " #_c); 260 | 261 | switch (cmd) 262 | { 263 | case XCOMPLETE: { 264 | STATUS(XCOMPLETE); 265 | goto got_complete_command; 266 | } 267 | case XTDOMASK: { 268 | STATUS(XTDOMASK); 269 | READ_BITS(buf_tdo_mask, state_dr_size); 270 | break; 271 | } 272 | case XSIR: { 273 | STATUS(XSIR); 274 | int length = READ_BYTE(); 275 | unsigned char buf[bits2bytes(length)]; 276 | READ_BITS(buf, length); 277 | SHIFT_DATA(buf, (void*)0, (void*)0, length, LIBXSVF_TAP_IRSHIFT, 278 | state_xendir ? LIBXSVF_TAP_IRPAUSE : LIBXSVF_TAP_IDLE, 279 | state_runtest, state_retries); 280 | break; 281 | } 282 | case XSDR: { 283 | STATUS(XSDR); 284 | READ_BITS(buf_tdi_data, state_dr_size); 285 | SHIFT_DATA(buf_tdi_data, buf_tdo_data, buf_tdo_mask, state_dr_size, LIBXSVF_TAP_DRSHIFT, 286 | state_xenddr ? LIBXSVF_TAP_DRPAUSE : LIBXSVF_TAP_IDLE, 287 | state_runtest, state_retries); 288 | break; 289 | } 290 | case XRUNTEST: { 291 | STATUS(XRUNTEST); 292 | state_runtest = READ_LONG(); 293 | break; 294 | } 295 | case XREPEAT: { 296 | STATUS(XREPEAT); 297 | state_retries = READ_BYTE(); 298 | break; 299 | } 300 | case XSDRSIZE: { 301 | STATUS(XSDRSIZE); 302 | state_dr_size = READ_LONG(); 303 | buf_tdi_data = LIBXSVF_HOST_REALLOC(buf_tdi_data, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_TDI_DATA); 304 | buf_tdo_data = LIBXSVF_HOST_REALLOC(buf_tdo_data, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_TDO_DATA); 305 | buf_tdo_mask = LIBXSVF_HOST_REALLOC(buf_tdo_mask, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_TDO_MASK); 306 | buf_addr_mask = LIBXSVF_HOST_REALLOC(buf_addr_mask, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_ADDR_MASK); 307 | buf_data_mask = LIBXSVF_HOST_REALLOC(buf_data_mask, bits2bytes(state_dr_size), LIBXSVF_MEM_XSVF_DATA_MASK); 308 | if (!buf_tdi_data || !buf_tdo_data || !buf_tdo_mask || !buf_addr_mask || !buf_data_mask) { 309 | LIBXSVF_HOST_REPORT_ERROR("Allocating memory failed."); 310 | goto error; 311 | } 312 | break; 313 | } 314 | case XSDRTDO: { 315 | STATUS(XSDRTDO); 316 | READ_BITS(buf_tdi_data, state_dr_size); 317 | READ_BITS(buf_tdo_data, state_dr_size); 318 | SHIFT_DATA(buf_tdi_data, buf_tdo_data, buf_tdo_mask, state_dr_size, LIBXSVF_TAP_DRSHIFT, 319 | state_xenddr ? LIBXSVF_TAP_DRPAUSE : LIBXSVF_TAP_IDLE, 320 | state_runtest, state_retries); 321 | break; 322 | } 323 | case XSETSDRMASKS: { 324 | STATUS(XSETSDRMASKS); 325 | READ_BITS(buf_addr_mask, state_dr_size); 326 | READ_BITS(buf_data_mask, state_dr_size); 327 | state_data_size = 0; 328 | for (i=0; i=0; i--) { 344 | if (getbit(buf_addr_mask, i) == 0) 345 | continue; 346 | if (getbit(buf_tdi_data, i)) { 347 | setbit(buf_tdi_data, i, !carry); 348 | } else { 349 | setbit(buf_tdi_data, i, carry); 350 | carry = 0; 351 | } 352 | } 353 | unsigned char this_byte = 0; 354 | for (i=0, j=0; i= 0 ) { 474 | LIBXSVF_HOST_REPORT_ERROR("TDO mismatch."); 475 | rc = -1; 476 | } 477 | 478 | LIBXSVF_HOST_REALLOC(buf_tdi_data, 0, LIBXSVF_MEM_XSVF_TDI_DATA); 479 | LIBXSVF_HOST_REALLOC(buf_tdo_data, 0, LIBXSVF_MEM_XSVF_TDO_DATA); 480 | LIBXSVF_HOST_REALLOC(buf_tdo_mask, 0, LIBXSVF_MEM_XSVF_TDO_MASK); 481 | LIBXSVF_HOST_REALLOC(buf_addr_mask, 0, LIBXSVF_MEM_XSVF_ADDR_MASK); 482 | LIBXSVF_HOST_REALLOC(buf_data_mask, 0, LIBXSVF_MEM_XSVF_DATA_MASK); 483 | 484 | return rc; 485 | } 486 | 487 | --------------------------------------------------------------------------------