You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

410 lines
12 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2005 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  5. * Copyright (C) 2007-2010 Øyvind Harboe *
  6. * oyvind.harboe@zylin.com *
  7. * *
  8. * Copyright (C) 2009 SoftPLC Corporation *
  9. * http://softplc.com *
  10. * dick@softplc.com *
  11. * *
  12. * Copyright (C) 2009 Zachary T Welch *
  13. * zw@superlucidity.net *
  14. * *
  15. * This program is free software; you can redistribute it and/or modify *
  16. * it under the terms of the GNU General Public License as published by *
  17. * the Free Software Foundation; either version 2 of the License, or *
  18. * (at your option) any later version. *
  19. * *
  20. * This program is distributed in the hope that it will be useful, *
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  23. * GNU General Public License for more details. *
  24. * *
  25. * You should have received a copy of the GNU General Public License *
  26. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  27. ***************************************************************************/
  28. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31. #include <jtag/jtag.h>
  32. #include <jtag/interface.h>
  33. #include <jtag/commands.h>
  34. #include <jtag/minidriver.h>
  35. #include <helper/command.h>
  36. struct jtag_callback_entry {
  37. struct jtag_callback_entry *next;
  38. jtag_callback_t callback;
  39. jtag_callback_data_t data0;
  40. jtag_callback_data_t data1;
  41. jtag_callback_data_t data2;
  42. jtag_callback_data_t data3;
  43. };
  44. static struct jtag_callback_entry *jtag_callback_queue_head;
  45. static struct jtag_callback_entry *jtag_callback_queue_tail;
  46. static void jtag_callback_queue_reset(void)
  47. {
  48. jtag_callback_queue_head = NULL;
  49. jtag_callback_queue_tail = NULL;
  50. }
  51. /**
  52. * see jtag_add_ir_scan()
  53. *
  54. */
  55. int interface_jtag_add_ir_scan(struct jtag_tap *active,
  56. const struct scan_field *in_fields, tap_state_t state)
  57. {
  58. size_t num_taps = jtag_tap_count_enabled();
  59. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  60. struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
  61. struct scan_field *out_fields = cmd_queue_alloc(num_taps * sizeof(struct scan_field));
  62. jtag_queue_command(cmd);
  63. cmd->type = JTAG_SCAN;
  64. cmd->cmd.scan = scan;
  65. scan->ir_scan = true;
  66. scan->num_fields = num_taps; /* one field per device */
  67. scan->fields = out_fields;
  68. scan->end_state = state;
  69. struct scan_field *field = out_fields; /* keep track where we insert data */
  70. /* loop over all enabled TAPs */
  71. for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
  72. /* search the input field list for fields for the current TAP */
  73. if (tap == active) {
  74. /* if TAP is listed in input fields, copy the value */
  75. tap->bypass = 0;
  76. jtag_scan_field_clone(field, in_fields);
  77. } else {
  78. /* if a TAP isn't listed in input fields, set it to BYPASS */
  79. tap->bypass = 1;
  80. field->num_bits = tap->ir_length;
  81. field->out_value = buf_set_ones(cmd_queue_alloc(DIV_ROUND_UP(tap->ir_length, 8)), tap->ir_length);
  82. field->in_value = NULL; /* do not collect input for tap's in bypass */
  83. }
  84. /* update device information */
  85. buf_cpy(field->out_value, tap->cur_instr, tap->ir_length);
  86. field++;
  87. }
  88. /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
  89. assert(field == out_fields + num_taps);
  90. return ERROR_OK;
  91. }
  92. /**
  93. * see jtag_add_dr_scan()
  94. *
  95. */
  96. int interface_jtag_add_dr_scan(struct jtag_tap *active, int in_num_fields,
  97. const struct scan_field *in_fields, tap_state_t state)
  98. {
  99. /* count devices in bypass */
  100. size_t bypass_devices = 0;
  101. for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
  102. if (tap->bypass)
  103. bypass_devices++;
  104. }
  105. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  106. struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
  107. struct scan_field *out_fields = cmd_queue_alloc((in_num_fields + bypass_devices) * sizeof(struct scan_field));
  108. jtag_queue_command(cmd);
  109. cmd->type = JTAG_SCAN;
  110. cmd->cmd.scan = scan;
  111. scan->ir_scan = false;
  112. scan->num_fields = in_num_fields + bypass_devices;
  113. scan->fields = out_fields;
  114. scan->end_state = state;
  115. struct scan_field *field = out_fields; /* keep track where we insert data */
  116. /* loop over all enabled TAPs */
  117. for (struct jtag_tap *tap = jtag_tap_next_enabled(NULL); tap; tap = jtag_tap_next_enabled(tap)) {
  118. /* if TAP is not bypassed insert matching input fields */
  119. if (!tap->bypass) {
  120. assert(active == tap);
  121. #ifndef NDEBUG
  122. /* remember initial position for assert() */
  123. struct scan_field *start_field = field;
  124. #endif /* NDEBUG */
  125. for (int j = 0; j < in_num_fields; j++) {
  126. jtag_scan_field_clone(field, in_fields + j);
  127. field++;
  128. }
  129. assert(field > start_field); /* must have at least one input field per not bypassed TAP */
  130. }
  131. /* if a TAP is bypassed, generated a dummy bit*/
  132. else {
  133. field->num_bits = 1;
  134. field->out_value = NULL;
  135. field->in_value = NULL;
  136. field++;
  137. }
  138. }
  139. assert(field == out_fields + scan->num_fields); /* no superfluous input fields permitted */
  140. return ERROR_OK;
  141. }
  142. static int jtag_add_plain_scan(int num_bits, const uint8_t *out_bits,
  143. uint8_t *in_bits, tap_state_t state, bool ir_scan)
  144. {
  145. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  146. struct scan_command *scan = cmd_queue_alloc(sizeof(struct scan_command));
  147. struct scan_field *out_fields = cmd_queue_alloc(sizeof(struct scan_field));
  148. jtag_queue_command(cmd);
  149. cmd->type = JTAG_SCAN;
  150. cmd->cmd.scan = scan;
  151. scan->ir_scan = ir_scan;
  152. scan->num_fields = 1;
  153. scan->fields = out_fields;
  154. scan->end_state = state;
  155. out_fields->num_bits = num_bits;
  156. out_fields->out_value = buf_cpy(out_bits, cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
  157. out_fields->in_value = in_bits;
  158. return ERROR_OK;
  159. }
  160. int interface_jtag_add_plain_dr_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
  161. {
  162. return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, false);
  163. }
  164. int interface_jtag_add_plain_ir_scan(int num_bits, const uint8_t *out_bits, uint8_t *in_bits, tap_state_t state)
  165. {
  166. return jtag_add_plain_scan(num_bits, out_bits, in_bits, state, true);
  167. }
  168. int interface_jtag_add_tlr(void)
  169. {
  170. tap_state_t state = TAP_RESET;
  171. /* allocate memory for a new list member */
  172. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  173. jtag_queue_command(cmd);
  174. cmd->type = JTAG_TLR_RESET;
  175. cmd->cmd.statemove = cmd_queue_alloc(sizeof(struct statemove_command));
  176. cmd->cmd.statemove->end_state = state;
  177. return ERROR_OK;
  178. }
  179. int interface_add_tms_seq(unsigned num_bits, const uint8_t *seq, enum tap_state state)
  180. {
  181. struct jtag_command *cmd;
  182. cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  183. if (!cmd)
  184. return ERROR_FAIL;
  185. cmd->type = JTAG_TMS;
  186. cmd->cmd.tms = cmd_queue_alloc(sizeof(*cmd->cmd.tms));
  187. if (!cmd->cmd.tms)
  188. return ERROR_FAIL;
  189. /* copy the bits; our caller doesn't guarantee they'll persist */
  190. cmd->cmd.tms->num_bits = num_bits;
  191. cmd->cmd.tms->bits = buf_cpy(seq,
  192. cmd_queue_alloc(DIV_ROUND_UP(num_bits, 8)), num_bits);
  193. if (!cmd->cmd.tms->bits)
  194. return ERROR_FAIL;
  195. jtag_queue_command(cmd);
  196. return ERROR_OK;
  197. }
  198. int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
  199. {
  200. /* allocate memory for a new list member */
  201. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  202. jtag_queue_command(cmd);
  203. cmd->type = JTAG_PATHMOVE;
  204. cmd->cmd.pathmove = cmd_queue_alloc(sizeof(struct pathmove_command));
  205. cmd->cmd.pathmove->num_states = num_states;
  206. cmd->cmd.pathmove->path = cmd_queue_alloc(sizeof(tap_state_t) * num_states);
  207. for (int i = 0; i < num_states; i++)
  208. cmd->cmd.pathmove->path[i] = path[i];
  209. return ERROR_OK;
  210. }
  211. int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
  212. {
  213. /* allocate memory for a new list member */
  214. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  215. jtag_queue_command(cmd);
  216. cmd->type = JTAG_RUNTEST;
  217. cmd->cmd.runtest = cmd_queue_alloc(sizeof(struct runtest_command));
  218. cmd->cmd.runtest->num_cycles = num_cycles;
  219. cmd->cmd.runtest->end_state = state;
  220. return ERROR_OK;
  221. }
  222. int interface_jtag_add_clocks(int num_cycles)
  223. {
  224. /* allocate memory for a new list member */
  225. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  226. jtag_queue_command(cmd);
  227. cmd->type = JTAG_STABLECLOCKS;
  228. cmd->cmd.stableclocks = cmd_queue_alloc(sizeof(struct stableclocks_command));
  229. cmd->cmd.stableclocks->num_cycles = num_cycles;
  230. return ERROR_OK;
  231. }
  232. int interface_jtag_add_reset(int req_trst, int req_srst)
  233. {
  234. /* allocate memory for a new list member */
  235. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  236. jtag_queue_command(cmd);
  237. cmd->type = JTAG_RESET;
  238. cmd->cmd.reset = cmd_queue_alloc(sizeof(struct reset_command));
  239. cmd->cmd.reset->trst = req_trst;
  240. cmd->cmd.reset->srst = req_srst;
  241. return ERROR_OK;
  242. }
  243. int interface_jtag_add_sleep(uint32_t us)
  244. {
  245. /* allocate memory for a new list member */
  246. struct jtag_command *cmd = cmd_queue_alloc(sizeof(struct jtag_command));
  247. jtag_queue_command(cmd);
  248. cmd->type = JTAG_SLEEP;
  249. cmd->cmd.sleep = cmd_queue_alloc(sizeof(struct sleep_command));
  250. cmd->cmd.sleep->us = us;
  251. return ERROR_OK;
  252. }
  253. /* add callback to end of queue */
  254. void interface_jtag_add_callback4(jtag_callback_t callback,
  255. jtag_callback_data_t data0, jtag_callback_data_t data1,
  256. jtag_callback_data_t data2, jtag_callback_data_t data3)
  257. {
  258. struct jtag_callback_entry *entry = cmd_queue_alloc(sizeof(struct jtag_callback_entry));
  259. entry->next = NULL;
  260. entry->callback = callback;
  261. entry->data0 = data0;
  262. entry->data1 = data1;
  263. entry->data2 = data2;
  264. entry->data3 = data3;
  265. if (!jtag_callback_queue_head) {
  266. jtag_callback_queue_head = entry;
  267. jtag_callback_queue_tail = entry;
  268. } else {
  269. jtag_callback_queue_tail->next = entry;
  270. jtag_callback_queue_tail = entry;
  271. }
  272. }
  273. int interface_jtag_execute_queue(void)
  274. {
  275. static int reentry;
  276. assert(reentry == 0);
  277. reentry++;
  278. int retval = default_interface_jtag_execute_queue();
  279. if (retval == ERROR_OK) {
  280. struct jtag_callback_entry *entry;
  281. for (entry = jtag_callback_queue_head; entry; entry = entry->next) {
  282. retval = entry->callback(entry->data0, entry->data1, entry->data2, entry->data3);
  283. if (retval != ERROR_OK)
  284. break;
  285. }
  286. }
  287. jtag_command_queue_reset();
  288. jtag_callback_queue_reset();
  289. reentry--;
  290. return retval;
  291. }
  292. static int jtag_convert_to_callback4(jtag_callback_data_t data0,
  293. jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3)
  294. {
  295. ((jtag_callback1_t)data1)(data0);
  296. return ERROR_OK;
  297. }
  298. void interface_jtag_add_callback(jtag_callback1_t callback, jtag_callback_data_t data0)
  299. {
  300. jtag_add_callback4(jtag_convert_to_callback4, data0, (jtag_callback_data_t)callback, 0, 0);
  301. }
  302. void jtag_add_callback(jtag_callback1_t f, jtag_callback_data_t data0)
  303. {
  304. interface_jtag_add_callback(f, data0);
  305. }
  306. void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0,
  307. jtag_callback_data_t data1, jtag_callback_data_t data2,
  308. jtag_callback_data_t data3)
  309. {
  310. interface_jtag_add_callback4(f, data0, data1, data2, data3);
  311. }