48ca0645484ae6937595ecc3be677403458886eb
[fw/openocd] / src / xsvf / xsvf.c
1 /***************************************************************************\r
2  *   Copyright (C) 2005 by Dominic Rath                                    *\r
3  *   Dominic.Rath@gmx.de                                                   *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include "xsvf.h"\r
25 \r
26 #include "jtag.h"\r
27 #include "command.h"\r
28 #include "log.h"\r
29 \r
30 #include <stdlib.h>\r
31 #include <unistd.h>\r
32 #include <sys/types.h>\r
33 #include <sys/stat.h>\r
34 #include <fcntl.h>\r
35 #include <string.h>\r
36 \r
37 #include <sys/time.h>\r
38 #include <time.h>\r
39 \r
40 #define XSTATE_MAX_PATH (12)\r
41 \r
42 int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);\r
43 \r
44 int xsvf_fd = 0;\r
45 \r
46 u8 *dr_out_buf; /* from host to device (TDI) */\r
47 u8 *dr_in_buf;  /* from device to host (TDO) */\r
48 u8 *dr_in_mask;\r
49 \r
50 int xsdrsize = 0;\r
51 int xruntest = 0;       /* number of TCK cycles / microseconds */\r
52 int xrepeat = 0x20; /* number of XC9500 retries */\r
53 \r
54 int xendir = 0;\r
55 int xenddr = 0;\r
56 \r
57 enum tap_state xsvf_to_tap[] =\r
58 {\r
59         TAP_TLR, TAP_RTI,\r
60         TAP_SDS, TAP_CD, TAP_SD, TAP_E1D, TAP_PD, TAP_E2D, TAP_UD,\r
61         TAP_SIS, TAP_CI, TAP_SI, TAP_E1I, TAP_PI, TAP_E2I, TAP_UI,\r
62 };\r
63 \r
64 int tap_to_xsvf[] =\r
65 {\r
66         0x0, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x1, 0x9, 0xa, 0xb, 0xc, 0xe, 0xf\r
67 };\r
68 \r
69 int xsvf_register_commands(struct command_context_s *cmd_ctx)\r
70 {\r
71         register_command(cmd_ctx, NULL, "xsvf", handle_xsvf_command,\r
72                 COMMAND_EXEC, "run xsvf <file>");\r
73 \r
74         return ERROR_OK;\r
75 }\r
76 \r
77 int xsvf_read_buffer(int num_bits, int fd, u8* buf)\r
78 {\r
79         int num_bytes;\r
80 \r
81         for (num_bytes = (num_bits + 7) / 8; num_bytes > 0; num_bytes--)\r
82         {\r
83                 if (read(fd, buf + num_bytes - 1, 1) < 0)\r
84                         return ERROR_XSVF_EOF;\r
85         }\r
86 \r
87         return ERROR_OK;\r
88 }\r
89 \r
90 int xsvf_read_xstates(int fd, enum tap_state *path, int max_path, int *path_len)\r
91 {\r
92         char c;\r
93         unsigned char uc;\r
94         \r
95         while ((read(fd, &c, 1) > 0) && (c == 0x12))\r
96         {\r
97                 if (*path_len > max_path)\r
98                 {\r
99                         WARNING("XSTATE path longer than max_path");\r
100                         break;\r
101                 }\r
102                 if (read(fd, &uc, 1) < 0)\r
103                 {\r
104                         return ERROR_XSVF_EOF;\r
105                 }\r
106                 path[(*path_len)++] = xsvf_to_tap[uc];\r
107         }\r
108         \r
109         lseek(fd, -1, SEEK_CUR);\r
110         \r
111         return ERROR_OK;\r
112 }\r
113 \r
114 int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
115 {\r
116         char c;\r
117         u8 buf4[4], buf2[2];\r
118         unsigned char uc, uc2;\r
119         unsigned int ui;\r
120         unsigned short us;\r
121 \r
122         int do_abort = 0;\r
123         int unsupported = 0;\r
124         int tdo_mismatch = 0;\r
125         \r
126         int runtest_requires_tck = 0;\r
127         \r
128         int device = -1;        /* use -1 to indicate a "plain" xsvf file which accounts for additional devices in the scan chain, otherwise the device that should be affected */\r
129 \r
130         if (argc < 2)\r
131         {\r
132                 command_print(cmd_ctx, "usage: xsvf <device#|plain> <file> <variant>");\r
133                 return ERROR_OK;\r
134         }\r
135 \r
136         if (strcmp(args[0], "plain") != 0)\r
137         {\r
138                 device = strtoul(args[0], NULL, 0);\r
139         }\r
140 \r
141         if ((xsvf_fd = open(args[1], O_RDONLY)) < 0)\r
142         {\r
143                 command_print(cmd_ctx, "file %s not found", args[0]);\r
144                 return ERROR_OK;\r
145         }\r
146         \r
147         if ((argc > 2) && (strcmp(args[2], "virt2") == 0))\r
148         {\r
149                 runtest_requires_tck = 1;\r
150         }\r
151 \r
152         while (read(xsvf_fd, &c, 1) > 0)\r
153         {\r
154                 switch (c)\r
155                 {\r
156                         case 0x00:      /* XCOMPLETE */\r
157                                 DEBUG("XCOMPLETE");\r
158                                 if (jtag_execute_queue() != ERROR_OK)\r
159                                 {\r
160                                         tdo_mismatch = 1;\r
161                                         break;  \r
162                                 }\r
163                                 break;\r
164                         case 0x01:      /* XTDOMASK */\r
165                                 DEBUG("XTDOMASK");\r
166                                 if (dr_in_mask && (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_mask) != ERROR_OK))\r
167                                         do_abort = 1;\r
168                                 break;\r
169                         case 0x02:      /* XSIR */\r
170                                 DEBUG("XSIR");\r
171                                 if (read(xsvf_fd, &c, 1) < 0)\r
172                                         do_abort = 1;\r
173                                 else\r
174                                 {\r
175                                         u8 *ir_buf = malloc((c + 7) / 8);\r
176                                         if (xsvf_read_buffer(c, xsvf_fd, ir_buf) != ERROR_OK)\r
177                                                 do_abort = 1;\r
178                                         else\r
179                                         {\r
180                                                 scan_field_t field;\r
181                                                 field.device = device;\r
182                                                 field.num_bits = c;\r
183                                                 field.out_value = ir_buf;\r
184                                                 field.out_mask = NULL;\r
185                                                 field.in_value = NULL;\r
186                                                 field.in_check_value = NULL;\r
187                                                 field.in_check_mask = NULL;\r
188                                                 field.in_handler = NULL;\r
189                                                 field.in_handler_priv = NULL;\r
190                                                 if (device == -1)\r
191                                                         jtag_add_plain_ir_scan(1, &field, TAP_PI, NULL);\r
192                                                 else\r
193                                                         jtag_add_ir_scan(1, &field, TAP_PI, NULL);\r
194                                                 if (jtag_execute_queue() != ERROR_OK)\r
195                                                 {\r
196                                                         tdo_mismatch = 1;\r
197                                                         free(ir_buf);\r
198                                                         break;\r
199                                                 }\r
200                                                 if (xruntest)\r
201                                                 {\r
202                                                         if (runtest_requires_tck)\r
203                                                                 jtag_add_runtest(xruntest, xsvf_to_tap[xendir]);\r
204                                                         else\r
205                                                         {\r
206                                                                 jtag_add_statemove(TAP_RTI);\r
207                                                                 jtag_add_sleep(xruntest);\r
208                                                                 jtag_add_statemove(xsvf_to_tap[xendir]);\r
209                                                         }\r
210                                                 }\r
211                                                 else if (xendir != 0xd) /* Pause-IR */\r
212                                                         jtag_add_statemove(xsvf_to_tap[xendir]);\r
213                                         }\r
214                                         free(ir_buf);\r
215                                 }\r
216                                 break;\r
217                         case 0x03:      /* XSDR */\r
218                                 DEBUG("XSDR");\r
219                                 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)\r
220                                         do_abort = 1;\r
221                                 else\r
222                                 {\r
223                                         scan_field_t field;\r
224                                         field.device = device;\r
225                                         field.num_bits = xsdrsize;\r
226                                         field.out_value = dr_out_buf;\r
227                                         field.out_mask = NULL;\r
228                                         field.in_value = NULL;\r
229                                         jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);\r
230                                         if (device == -1)\r
231                                                 jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL);\r
232                                         else\r
233                                                 jtag_add_dr_scan(1, &field, TAP_PD, NULL);\r
234                                         if (jtag_execute_queue() != ERROR_OK)\r
235                                         {\r
236                                                 tdo_mismatch = 1;\r
237                                                 break;  \r
238                                         }\r
239                                         if (xruntest)\r
240                                         {\r
241                                                 if (runtest_requires_tck)\r
242                                                         jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);\r
243                                                 else\r
244                                                 {\r
245                                                         jtag_add_statemove(TAP_RTI);\r
246                                                         jtag_add_sleep(xruntest);\r
247                                                         jtag_add_statemove(xsvf_to_tap[xenddr]);\r
248                                                 }\r
249                                         }\r
250                                         else if (xendir != 0x6) /* Pause-DR */\r
251                                                 jtag_add_statemove(xsvf_to_tap[xenddr]);\r
252                                 }\r
253                                 break;\r
254                         case 0x04:      /* XRUNTEST */\r
255                                 DEBUG("XRUNTEST");\r
256                                 if (read(xsvf_fd, buf4, 4) < 0)\r
257                                         do_abort = 1;\r
258                                 else\r
259                                 {\r
260                                         xruntest = be_to_h_u32(buf4);\r
261                                 }\r
262                                 break;\r
263                         case 0x07:      /* XREPEAT */\r
264                                 DEBUG("XREPEAT");\r
265                                 if (read(xsvf_fd, &c, 1) < 0)\r
266                                         do_abort = 1;\r
267                                 else\r
268                                 {\r
269                                         xrepeat = c;\r
270                                 }\r
271                                 break;\r
272                         case 0x08:      /* XSDRSIZE */\r
273                                 DEBUG("XSDRSIZE");\r
274                                 if (read(xsvf_fd, buf4, 4) < 0)\r
275                                         do_abort = 1;\r
276                                 else\r
277                                 {\r
278                                         xsdrsize = be_to_h_u32(buf4);\r
279                                         free(dr_out_buf);\r
280                                         free(dr_in_buf);\r
281                                         free(dr_in_mask);\r
282                                         dr_out_buf = malloc((xsdrsize + 7) / 8);\r
283                                         dr_in_buf = malloc((xsdrsize + 7) / 8);\r
284                                         dr_in_mask = malloc((xsdrsize + 7) / 8);\r
285                                 }\r
286                                 break;\r
287                         case 0x09:      /* XSDRTDO */\r
288                                 DEBUG("XSDRTDO");\r
289                                 if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_out_buf) != ERROR_OK)\r
290                                         do_abort = 1;\r
291                                 else\r
292                                 {\r
293                                         if (xsvf_read_buffer(xsdrsize, xsvf_fd, dr_in_buf) != ERROR_OK)\r
294                                                 do_abort = 1;\r
295                                         else\r
296                                         {\r
297                                                 scan_field_t field;\r
298                                                 field.device = device;\r
299                                                 field.num_bits = xsdrsize;\r
300                                                 field.out_value = dr_out_buf;\r
301                                                 field.out_mask = NULL;\r
302                                                 field.in_value = NULL;\r
303                                                 jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);\r
304                                                 if (device == -1)\r
305                                                         jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL);\r
306                                                 else\r
307                                                         jtag_add_dr_scan(1, &field, TAP_PD, NULL);\r
308                                                 if (jtag_execute_queue() != ERROR_OK)\r
309                                                 {\r
310                                                         tdo_mismatch = 1;\r
311                                                         break;  \r
312                                                 }\r
313                                                 if (xruntest)\r
314                                                 {\r
315                                                         if (runtest_requires_tck)\r
316                                                                 jtag_add_runtest(xruntest, xsvf_to_tap[xenddr]);\r
317                                                         else\r
318                                                         {\r
319                                                                 jtag_add_statemove(TAP_RTI);\r
320                                                                 jtag_add_sleep(xruntest);\r
321                                                                 jtag_add_statemove(xsvf_to_tap[xenddr]);\r
322                                                         }\r
323                                                 }\r
324                                                 else if (xendir != 0x6) /* Pause-DR */\r
325                                                         jtag_add_statemove(xsvf_to_tap[xenddr]);\r
326                                         }\r
327                                 }\r
328                                 break;\r
329                         case 0x0a:      /* XSETDRMASKS */\r
330                                 ERROR("unsupported XSETSDRMASKS\n");\r
331                                 unsupported = 1;\r
332                                 break;\r
333                         case 0x0b:      /* XSDRINC */\r
334                                 ERROR("unsupported XSDRINC\n");\r
335                                 unsupported = 1;\r
336                                 break;\r
337                         case 0x0c:      /* XSDRB */\r
338                                 unsupported = 1;\r
339                                 break;\r
340                         case 0x0d:      /* XSDRC */\r
341                                 unsupported = 1;\r
342                                 break;\r
343                         case 0x0e:      /* XSDRE */\r
344                                 unsupported = 1;\r
345                                 break;\r
346                         case 0x0f:      /* XSDRTDOB */\r
347                                 unsupported = 1;\r
348                                 break;\r
349                         case 0x10:      /* XSDRTDOB */\r
350                                 unsupported = 1;\r
351                                 break;\r
352                         case 0x11:      /* XSDRTDOB */\r
353                                 unsupported = 1;\r
354                                 break;\r
355                         case 0x12:      /* XSTATE */\r
356                                 DEBUG("XSTATE");\r
357                                 if (read(xsvf_fd, &uc, 1) < 0)\r
358                                         do_abort = 1;\r
359                                 else\r
360                                 {\r
361                                         enum tap_state *path = calloc(XSTATE_MAX_PATH, 4);\r
362                                         int path_len = 1;\r
363                                         path[0] = xsvf_to_tap[uc];\r
364                                         if (xsvf_read_xstates(xsvf_fd, path, XSTATE_MAX_PATH, &path_len) != ERROR_OK)\r
365                                                 do_abort = 1;\r
366                                         else\r
367                                         {\r
368                                                 jtag_add_pathmove(path_len, path);\r
369                                         }\r
370                                         free(path);\r
371                                 }\r
372                                 break;\r
373                         case 0x13:      /* XENDIR */\r
374                                 DEBUG("XENDIR");\r
375                                 if (read(xsvf_fd, &c, 1) < 0)\r
376                                         do_abort = 1;\r
377                                 else\r
378                                 {\r
379                                         if (c == 0)\r
380                                                 xendir = 1;\r
381                                         else if (c == 1)\r
382                                                 xendir = 0xd;\r
383                                         else\r
384                                         {\r
385                                                 ERROR("unknown XENDIR endstate");\r
386                                                 unsupported = 1;\r
387                                         }\r
388                                 }\r
389                                 break;\r
390                         case 0x14:      /* XENDDR */\r
391                                 DEBUG("XENDDR");\r
392                                 if (read(xsvf_fd, &c, 1) < 0)\r
393                                         do_abort = 1;\r
394                                 else\r
395                                 {\r
396                                         if (c == 0)\r
397                                                 xenddr = 1;\r
398                                         else if (c == 1)\r
399                                                 xenddr = 0x6;\r
400                                         else\r
401                                         {\r
402                                                 ERROR("unknown XENDDR endstate");\r
403                                                 unsupported = 1;\r
404                                         }\r
405                                 }\r
406                                 break;\r
407                         case 0x15:      /* XSIR2 */\r
408                                 DEBUG("XSIR2");\r
409                                 if (read(xsvf_fd, buf2, 2) < 0)\r
410                                         do_abort = 1;\r
411                                 else\r
412                                 {\r
413                                         u8 *ir_buf;\r
414                                         us = be_to_h_u16(buf2);\r
415                                         ir_buf = malloc((us + 7) / 8);\r
416                                         if (xsvf_read_buffer(us, xsvf_fd, ir_buf) != ERROR_OK)\r
417                                                 do_abort = 1;\r
418                                         else\r
419                                         {\r
420                                                 scan_field_t field;\r
421                                                 field.device = device;\r
422                                                 field.num_bits = us;\r
423                                                 field.out_value = ir_buf;\r
424                                                 field.out_mask = NULL;\r
425                                                 field.in_value = NULL;\r
426                                                 field.in_check_value = NULL;\r
427                                                 field.in_check_mask = NULL;\r
428                                                 field.in_handler = NULL;\r
429                                                 field.in_handler_priv = NULL;\r
430                                                 if (device == -1)\r
431                                                         jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir], NULL);\r
432                                                 else\r
433                                                         jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir], NULL);\r
434                                         }\r
435                                         free(ir_buf);\r
436                                 }\r
437                                 break;\r
438                         case 0x16:      /* XCOMMENT */\r
439                                 do\r
440                                 {\r
441                                         if (read(xsvf_fd, &c, 1) < 0)\r
442                                         {\r
443                                                 do_abort = 1;\r
444                                                 break;\r
445                                         }\r
446                                 } while (c != 0);\r
447                                 break;\r
448                         case 0x17:      /* XWAIT */\r
449                                 DEBUG("XWAIT");\r
450                                 if ((read(xsvf_fd, &uc, 1) < 0) || (read(xsvf_fd, &uc2, 1) < 0) || (read(xsvf_fd, buf4, 4) < 0))\r
451                                         do_abort = 1;\r
452                                 else\r
453                                 {\r
454                                         jtag_add_statemove(xsvf_to_tap[uc]);\r
455                                         ui = be_to_h_u32(buf4);\r
456                                         jtag_add_sleep(ui);\r
457                                         jtag_add_statemove(xsvf_to_tap[uc2]);\r
458                                 }\r
459                                 break;\r
460                         default:\r
461                                 ERROR("unknown xsvf command (0x%2.2x)\n", c);\r
462                                 unsupported = 1;\r
463                 }\r
464 \r
465                 if (do_abort || unsupported || tdo_mismatch)\r
466                         break;\r
467         }\r
468         \r
469         if (tdo_mismatch)\r
470         {\r
471                 command_print(cmd_ctx, "TDO mismatch, aborting");\r
472                 return ERROR_OK;\r
473         }\r
474 \r
475         if (unsupported)\r
476         {\r
477                 command_print(cmd_ctx, "unsupported xsvf command encountered, aborting");\r
478                 return ERROR_OK;\r
479         }\r
480 \r
481         if (do_abort)\r
482         {\r
483                 command_print(cmd_ctx, "premature end detected, aborting");\r
484                 return ERROR_OK;\r
485         }\r
486         \r
487         if (dr_out_buf)\r
488                 free(dr_out_buf);\r
489         \r
490         if (dr_in_buf)\r
491                 free(dr_in_buf);\r
492         \r
493         if (dr_in_mask)\r
494                 free(dr_in_mask);\r
495 \r
496         close(xsvf_fd);\r
497         \r
498         command_print(cmd_ctx, "XSVF file programmed successfully");\r
499 \r
500         return ERROR_OK;\r
501 }\r