1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
8 * Copyright (C) 2009 SoftPLC Corporation *
12 * Copyright (C) 2009 Zachary T Welch *
13 * zw@superlucidity.net *
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. *
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. *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program; if not, write to the *
27 * Free Software Foundation, Inc., *
28 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
29 ***************************************************************************/
34 #include "interface.h"
35 #include "minidriver.h"
38 struct jtag_callback_entry
40 struct jtag_callback_entry
*next
;
42 jtag_callback_t callback
;
44 jtag_callback_data_t data1
;
45 jtag_callback_data_t data2
;
46 jtag_callback_data_t data3
;
49 static struct jtag_callback_entry
*jtag_callback_queue_head
= NULL
;
50 static struct jtag_callback_entry
*jtag_callback_queue_tail
= NULL
;
52 static void jtag_callback_queue_reset(void)
54 jtag_callback_queue_head
= NULL
;
55 jtag_callback_queue_tail
= NULL
;
59 * Copy a scan_field_t for insertion into the queue.
61 * This allocates a new copy of out_value using cmd_queue_alloc.
63 static void cmd_queue_scan_field_clone(scan_field_t
* dst
, const scan_field_t
* src
)
66 dst
->num_bits
= src
->num_bits
;
67 dst
->out_value
= buf_cpy(src
->out_value
, cmd_queue_alloc(CEIL(src
->num_bits
, 8)), src
->num_bits
);
68 dst
->in_value
= src
->in_value
;
73 * see jtag_add_ir_scan()
76 int interface_jtag_add_ir_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
78 size_t num_taps
= jtag_tap_count_enabled();
80 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
81 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
82 scan_field_t
* out_fields
= cmd_queue_alloc(num_taps
* sizeof(scan_field_t
));
84 jtag_queue_command(cmd
);
86 cmd
->type
= JTAG_SCAN
;
90 scan
->num_fields
= num_taps
; /* one field per device */
91 scan
->fields
= out_fields
;
92 scan
->end_state
= state
;
95 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
97 /* loop over all enabled TAPs */
99 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
101 /* search the input field list for fields for the current TAP */
105 for (int j
= 0; j
< in_num_fields
; j
++)
107 if (tap
!= in_fields
[j
].tap
)
110 /* if TAP is listed in input fields, copy the value */
116 assert(in_fields
[j
].num_bits
== tap
->ir_length
); /* input fields must have the same length as the TAP's IR */
118 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
125 /* if a TAP isn't listed in input fields, set it to BYPASS */
130 field
->num_bits
= tap
->ir_length
;
131 field
->out_value
= buf_set_ones(cmd_queue_alloc(CEIL(tap
->ir_length
, 8)), tap
->ir_length
);
132 field
->in_value
= NULL
; /* do not collect input for tap's in bypass */
135 /* update device information */
136 buf_cpy(field
->out_value
, tap
->cur_instr
, tap
->ir_length
);
141 assert(field
== out_fields
+ num_taps
); /* paranoia: jtag_tap_count_enabled() and jtag_tap_next_enabled() not in sync */
147 * see jtag_add_plain_ir_scan()
150 int interface_jtag_add_plain_ir_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
153 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
154 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
155 scan_field_t
* out_fields
= cmd_queue_alloc(in_num_fields
* sizeof(scan_field_t
));
157 jtag_queue_command(cmd
);
159 cmd
->type
= JTAG_SCAN
;
160 cmd
->cmd
.scan
= scan
;
162 scan
->ir_scan
= true;
163 scan
->num_fields
= in_num_fields
;
164 scan
->fields
= out_fields
;
165 scan
->end_state
= state
;
167 for (int i
= 0; i
< in_num_fields
; i
++)
168 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
176 * see jtag_add_dr_scan()
179 int interface_jtag_add_dr_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
181 /* count devices in bypass */
183 size_t bypass_devices
= 0;
185 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
191 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
192 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
193 scan_field_t
* out_fields
= cmd_queue_alloc((in_num_fields
+ bypass_devices
) * sizeof(scan_field_t
));
195 jtag_queue_command(cmd
);
197 cmd
->type
= JTAG_SCAN
;
198 cmd
->cmd
.scan
= scan
;
200 scan
->ir_scan
= false;
201 scan
->num_fields
= in_num_fields
+ bypass_devices
;
202 scan
->fields
= out_fields
;
203 scan
->end_state
= state
;
206 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
208 /* loop over all enabled TAPs */
210 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
212 /* if TAP is not bypassed insert matching input fields */
216 scan_field_t
* start_field
= field
; /* keep initial position for assert() */
218 for (int j
= 0; j
< in_num_fields
; j
++)
220 if (tap
!= in_fields
[j
].tap
)
223 cmd_queue_scan_field_clone(field
, in_fields
+ j
);
228 assert(field
> start_field
); /* must have at least one input field per not bypassed TAP */
231 /* if a TAP is bypassed, generated a dummy bit*/
236 field
->out_value
= NULL
;
237 field
->in_value
= NULL
;
243 assert(field
== out_fields
+ scan
->num_fields
); /* no superfluous input fields permitted */
251 * Generate a DR SCAN using the array of output values passed to the function
253 * This function assumes that the parameter target_tap specifies the one TAP
254 * that is not bypassed. All other TAPs must be bypassed and the function will
255 * generate a dummy 1bit field for them.
257 * For the target_tap a sequence of output-only fields will be generated where
258 * each field has the size num_bits and the field's values are taken from
261 * The bypass status of TAPs is set by jtag_add_ir_scan().
264 void interface_jtag_add_dr_out(jtag_tap_t
*target_tap
,
268 tap_state_t end_state
)
270 /* count devices in bypass */
272 size_t bypass_devices
= 0;
274 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
281 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
282 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
283 scan_field_t
* out_fields
= cmd_queue_alloc((in_num_fields
+ bypass_devices
) * sizeof(scan_field_t
));
285 jtag_queue_command(cmd
);
287 cmd
->type
= JTAG_SCAN
;
288 cmd
->cmd
.scan
= scan
;
290 scan
->ir_scan
= false;
291 scan
->num_fields
= in_num_fields
+ bypass_devices
;
292 scan
->fields
= out_fields
;
293 scan
->end_state
= end_state
;
296 bool target_tap_match
= false;
298 scan_field_t
* field
= out_fields
; /* keep track where we insert data */
300 /* loop over all enabled TAPs */
302 for (jtag_tap_t
* tap
= jtag_tap_next_enabled(NULL
); tap
!= NULL
; tap
= jtag_tap_next_enabled(tap
))
304 /* if TAP is not bypassed insert matching input fields */
308 assert(tap
== target_tap
); /* target_tap must match the one not bypassed TAP */
310 target_tap_match
= true;
312 for (int j
= 0; j
< in_num_fields
; j
++)
315 size_t scan_size
= num_bits
[j
];
316 buf_set_u32(out_value
, 0, scan_size
, value
[j
]);
319 field
->num_bits
= scan_size
;
320 field
->out_value
= buf_cpy(out_value
, cmd_queue_alloc(CEIL(scan_size
, 8)), scan_size
);
321 field
->in_value
= NULL
;
327 /* if a TAP is bypassed, generated a dummy bit*/
333 field
->out_value
= NULL
;
334 field
->in_value
= NULL
;
340 assert(target_tap_match
); /* target_tap should be enabled and not bypassed */
344 * see jtag_add_plain_dr_scan()
347 int interface_jtag_add_plain_dr_scan(int in_num_fields
, const scan_field_t
*in_fields
, tap_state_t state
)
349 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
350 scan_command_t
* scan
= cmd_queue_alloc(sizeof(scan_command_t
));
351 scan_field_t
* out_fields
= cmd_queue_alloc(in_num_fields
* sizeof(scan_field_t
));
353 jtag_queue_command(cmd
);
355 cmd
->type
= JTAG_SCAN
;
356 cmd
->cmd
.scan
= scan
;
358 scan
->ir_scan
= false;
359 scan
->num_fields
= in_num_fields
;
360 scan
->fields
= out_fields
;
361 scan
->end_state
= state
;
363 for (int i
= 0; i
< in_num_fields
; i
++)
364 cmd_queue_scan_field_clone(out_fields
+ i
, in_fields
+ i
);
369 int interface_jtag_add_tlr(void)
371 tap_state_t state
= TAP_RESET
;
373 /* allocate memory for a new list member */
374 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
376 jtag_queue_command(cmd
);
378 cmd
->type
= JTAG_STATEMOVE
;
380 cmd
->cmd
.statemove
= cmd_queue_alloc(sizeof(statemove_command_t
));
381 cmd
->cmd
.statemove
->end_state
= state
;
386 int interface_jtag_add_pathmove(int num_states
, const tap_state_t
*path
)
388 /* allocate memory for a new list member */
389 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
391 jtag_queue_command(cmd
);
393 cmd
->type
= JTAG_PATHMOVE
;
395 cmd
->cmd
.pathmove
= cmd_queue_alloc(sizeof(pathmove_command_t
));
396 cmd
->cmd
.pathmove
->num_states
= num_states
;
397 cmd
->cmd
.pathmove
->path
= cmd_queue_alloc(sizeof(tap_state_t
) * num_states
);
399 for (int i
= 0; i
< num_states
; i
++)
400 cmd
->cmd
.pathmove
->path
[i
] = path
[i
];
405 int interface_jtag_add_runtest(int num_cycles
, tap_state_t state
)
407 /* allocate memory for a new list member */
408 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
410 jtag_queue_command(cmd
);
412 cmd
->type
= JTAG_RUNTEST
;
414 cmd
->cmd
.runtest
= cmd_queue_alloc(sizeof(runtest_command_t
));
415 cmd
->cmd
.runtest
->num_cycles
= num_cycles
;
416 cmd
->cmd
.runtest
->end_state
= state
;
421 int interface_jtag_add_clocks( int num_cycles
)
423 /* allocate memory for a new list member */
424 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
426 jtag_queue_command(cmd
);
428 cmd
->type
= JTAG_STABLECLOCKS
;
430 cmd
->cmd
.stableclocks
= cmd_queue_alloc(sizeof(stableclocks_command_t
));
431 cmd
->cmd
.stableclocks
->num_cycles
= num_cycles
;
436 int interface_jtag_add_reset(int req_trst
, int req_srst
)
438 /* allocate memory for a new list member */
439 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
441 jtag_queue_command(cmd
);
443 cmd
->type
= JTAG_RESET
;
445 cmd
->cmd
.reset
= cmd_queue_alloc(sizeof(reset_command_t
));
446 cmd
->cmd
.reset
->trst
= req_trst
;
447 cmd
->cmd
.reset
->srst
= req_srst
;
452 int interface_jtag_add_sleep(u32 us
)
454 /* allocate memory for a new list member */
455 jtag_command_t
* cmd
= cmd_queue_alloc(sizeof(jtag_command_t
));
457 jtag_queue_command(cmd
);
459 cmd
->type
= JTAG_SLEEP
;
461 cmd
->cmd
.sleep
= cmd_queue_alloc(sizeof(sleep_command_t
));
462 cmd
->cmd
.sleep
->us
= us
;
467 /* add callback to end of queue */
468 void interface_jtag_add_callback4(jtag_callback_t callback
, u8
*in
, jtag_callback_data_t data1
, jtag_callback_data_t data2
, jtag_callback_data_t data3
)
470 struct jtag_callback_entry
*entry
=cmd_queue_alloc(sizeof(struct jtag_callback_entry
));
473 entry
->callback
=callback
;
479 if (jtag_callback_queue_head
==NULL
)
481 jtag_callback_queue_head
=entry
;
482 jtag_callback_queue_tail
=entry
;
485 jtag_callback_queue_tail
->next
=entry
;
486 jtag_callback_queue_tail
=entry
;
490 int interface_jtag_execute_queue(void)
492 int retval
= default_interface_jtag_execute_queue();
493 if (retval
== ERROR_OK
)
495 struct jtag_callback_entry
*entry
;
496 for (entry
=jtag_callback_queue_head
; entry
!=NULL
; entry
=entry
->next
)
498 retval
=entry
->callback(entry
->in
, entry
->data1
, entry
->data2
, entry
->data3
);
499 if (retval
!=ERROR_OK
)
504 jtag_command_queue_reset();
505 jtag_callback_queue_reset();
510 static int jtag_convert_to_callback4(u8
*in
, jtag_callback_data_t data1
, jtag_callback_data_t data2
, jtag_callback_data_t data3
)
512 ((jtag_callback1_t
)data1
)(in
);
516 void interface_jtag_add_callback(jtag_callback1_t callback
, u8
*in
)
518 jtag_add_callback4(jtag_convert_to_callback4
, in
, (jtag_callback_data_t
)callback
, 0, 0);