1 /* JTAG low level functions and base class for cables
2
3 Copyright (C) 2004 Andrew Rogers
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Changes:
20 Sandro Amato [sdroamt@netscape.net] 26 Jun 2006 [applied 13 Jul 2006]:
21 Added a 'dotted' progress bar
22 Dmitry Teytelman [dimtey@gmail.com] 14 Jun 2006 [applied 13 Aug 2006]:
23 Code cleanup for clean -Wall compile.
24 Extensive changes to support FT2232 driver.
25 Moved progress bar to ioparport.cpp and ioftdi.cpp.
26 */
27
28
29
30 #include "iobase.h"
31
32 #include <unistd.h>
33 #include <stdio.h>
34
35 using namespace std;
36
IOBase()37 IOBase::IOBase()
38 {
39 verbose = false;
40 current_state=UNKNOWN;
41 }
42
shiftTDITDO(const unsigned char * tdi,unsigned char * tdo,int length,bool last)43 void IOBase::shiftTDITDO(const unsigned char *tdi, unsigned char *tdo, int length, bool last)
44 {
45 if(length==0) return;
46
47 int i=0;
48 int j=0;
49 unsigned char tdo_byte=0;
50 unsigned char tdi_byte=tdi[j];
51 while(i<length-1){
52 tdo_byte=tdo_byte+(txrx(false, (tdi_byte&1)==1)<<(i%8));
53 tdi_byte=tdi_byte>>1;
54 i++;
55 if((i%8)==0){ // Next byte
56 tdo[j]=tdo_byte; // Save the TDO byte
57 tdo_byte=0;
58 j++;
59 tdi_byte=tdi[j]; // Get the next TDI byte
60 }
61 };
62 tdo_byte=tdo_byte+(txrx(last, (tdi_byte&1)==1)<<(i%8)); // TMS set if last=true
63 tdo[j]=tdo_byte;
64 nextTapState(last); // If TMS is set the the state of the tap changes
65 return;
66 }
67
shiftTDI(const unsigned char * tdi,int length,bool last)68 void IOBase::shiftTDI(const unsigned char *tdi, int length, bool last)
69 {
70 unsigned char *buf = (unsigned char *)tdi;
71 int i, j, k, bytes = length / 8;
72
73 if (length==0) return;
74
75 if (bytes > 1)
76 {
77 for (k = 0; k < bytes/BLOCK_SIZE; k++)
78 tx_tdi_block(buf + k*BLOCK_SIZE, BLOCK_SIZE);
79
80 tx_tdi_block(buf + k*BLOCK_SIZE, bytes - 1 - k*BLOCK_SIZE);
81 j = bytes - 1;
82 i = (bytes - 1) * 8;
83 }
84 else
85 {
86 i = 0;
87 j = 0;
88 }
89 /*
90 for (; j < bytes - 1; j++, i += 8)
91 {
92 tx_tdi_byte(tdi[j]);
93 if (verbose && j != 0 && (j % TICK_COUNT == 0))
94 write(0, ".", 1);
95 }
96 */
97 unsigned char tdi_byte=tdi[j];
98 while(i<length-1){
99 tx(false, (tdi_byte&1)==1);
100 tdi_byte=tdi_byte>>1;
101 i++;
102 if((i%8)==0){ // Next byte
103 j++;
104 tdi_byte=tdi[j]; //Get the next TDI byte
105 }
106 };
107 tx(last, (tdi_byte&1)==1); // TMS set if last=true
108 nextTapState(last); // If TMS is set the the state of the tap changes
109 return;
110 }
111
112 // TDI gets a load of zeros, we just record TDO.
shiftTDO(unsigned char * tdo,int length,bool last)113 void IOBase::shiftTDO(unsigned char *tdo, int length, bool last)
114 {
115 if (length==0) return;
116 int i=0;
117 int j=0;
118 unsigned char tdo_byte=0;
119 while(i<length-1){
120 tdo_byte=tdo_byte+(txrx(false, false)<<(i%8));
121 i++;
122 if((i%8)==0){ // Next byte
123 tdo[j]=tdo_byte; // Save the TDO byte
124 tdo_byte=0;
125 j++;
126 }
127 };
128 tdo_byte=tdo_byte+(txrx(last, false)<<(i%8)); // TMS set if last=true
129 tdo[j]=tdo_byte;
130 nextTapState(last); // If TMS is set the the state of the tap changes
131 return;
132 }
133
134 // TDI gets a load of zeros or ones, and we ignore TDO
shift(bool tdi,int length,bool last)135 void IOBase::shift(bool tdi, int length, bool last)
136 {
137 if (length==0) return;
138 int i=0;
139 while(i<length-1){
140 tx(false, tdi);
141 i++;
142 };
143 tx(last, tdi); // TMS set if last=true
144 nextTapState(last); // If TMS is set the the state of the tap changes
145 return;
146 }
147
setTapState(tapState_t state)148 void IOBase::setTapState(tapState_t state)
149 {
150 bool tms;
151 while(current_state!=state){
152 switch(current_state){
153
154 case TEST_LOGIC_RESET:
155 switch(state){
156 case TEST_LOGIC_RESET:
157 tms=true;
158 break;
159 default:
160 tms=false;
161 current_state=RUN_TEST_IDLE;
162 };
163 break;
164
165 case RUN_TEST_IDLE:
166 switch(state){
167 case RUN_TEST_IDLE:
168 tms=false;
169 break;
170 default:
171 tms=true;
172 current_state=SELECT_DR_SCAN;
173 };
174 break;
175
176 case SELECT_DR_SCAN:
177 switch(state){
178 case CAPTURE_DR:
179 case SHIFT_DR:
180 case EXIT1_DR:
181 case PAUSE_DR:
182 case EXIT2_DR:
183 case UPDATE_DR:
184 tms=false;
185 current_state=CAPTURE_DR;
186 break;
187 default:
188 tms=true;
189 current_state=SELECT_IR_SCAN;
190 };
191 break;
192
193 case CAPTURE_DR:
194 switch(state){
195 case SHIFT_DR:
196 tms=false;
197 current_state=SHIFT_DR;
198 break;
199 default:
200 tms=true;
201 current_state=EXIT1_DR;
202 };
203 break;
204
205 case SHIFT_DR:
206 switch(state){
207 case SHIFT_DR:
208 tms=false;
209 break;
210 default:
211 tms=true;
212 current_state=EXIT1_DR;
213 };
214 break;
215
216 case EXIT1_DR:
217 switch(state){
218 case PAUSE_DR:
219 case EXIT2_DR:
220 case SHIFT_DR:
221 case EXIT1_DR:
222 tms=false;
223 current_state=PAUSE_DR;
224 break;
225 default:
226 tms=true;
227 current_state=UPDATE_DR;
228 };
229 break;
230
231 case PAUSE_DR:
232 switch(state){
233 case PAUSE_DR:
234 tms=false;
235 break;
236 default:
237 tms=true;
238 current_state=EXIT2_DR;
239 };
240 break;
241
242 case EXIT2_DR:
243 switch(state){
244 case SHIFT_DR:
245 case EXIT1_DR:
246 case PAUSE_DR:
247 tms=false;
248 current_state=SHIFT_DR;
249 break;
250 default:
251 tms=true;
252 current_state=UPDATE_DR;
253 };
254 break;
255
256 case UPDATE_DR:
257 switch(state){
258 case RUN_TEST_IDLE:
259 tms=false;
260 current_state=RUN_TEST_IDLE;
261 break;
262 default:
263 tms=true;
264 current_state=SELECT_DR_SCAN;
265 };
266 break;
267
268 case SELECT_IR_SCAN:
269 switch(state){
270 case CAPTURE_IR:
271 case SHIFT_IR:
272 case EXIT1_IR:
273 case PAUSE_IR:
274 case EXIT2_IR:
275 case UPDATE_IR:
276 tms=false;
277 current_state=CAPTURE_IR;
278 break;
279 default:
280 tms=true;
281 current_state=TEST_LOGIC_RESET;
282 };
283 break;
284
285 case CAPTURE_IR:
286 switch(state){
287 case SHIFT_IR:
288 tms=false;
289 current_state=SHIFT_IR;
290 break;
291 default:
292 tms=true;
293 current_state=EXIT1_IR;
294 };
295 break;
296
297 case SHIFT_IR:
298 switch(state){
299 case SHIFT_IR:
300 tms=false;
301 break;
302 default:
303 tms=true;
304 current_state=EXIT1_IR;
305 };
306 break;
307
308 case EXIT1_IR:
309 switch(state){
310 case PAUSE_IR:
311 case EXIT2_IR:
312 case SHIFT_IR:
313 case EXIT1_IR:
314 tms=false;
315 current_state=PAUSE_IR;
316 break;
317 default:
318 tms=true;
319 current_state=UPDATE_IR;
320 };
321 break;
322
323 case PAUSE_IR:
324 switch(state){
325 case PAUSE_IR:
326 tms=false;
327 break;
328 default:
329 tms=true;
330 current_state=EXIT2_IR;
331 };
332 break;
333
334 case EXIT2_IR:
335 switch(state){
336 case SHIFT_IR:
337 case EXIT1_IR:
338 case PAUSE_IR:
339 tms=false;
340 current_state=SHIFT_IR;
341 break;
342 default:
343 tms=true;
344 current_state=UPDATE_IR;
345 };
346 break;
347
348 case UPDATE_IR:
349 switch(state){
350 case RUN_TEST_IDLE:
351 tms=false;
352 current_state=RUN_TEST_IDLE;
353 break;
354 default:
355 tms=true;
356 current_state=SELECT_DR_SCAN;
357 };
358 break;
359
360 default:
361 tapTestLogicReset();
362 tms=true;
363 };
364 tx(tms,false);
365 };
366 }
367
368 // After shift data into the DR or IR we goto the next state
369 // This function should only be called from the end of a shift function
nextTapState(bool tms)370 void IOBase::nextTapState(bool tms)
371 {
372 if(current_state==SHIFT_DR){
373 if(tms)current_state=EXIT1_DR; // If TMS was set then goto next state
374 }
375 else if(current_state==SHIFT_IR){
376 if(tms)current_state=EXIT1_IR; // If TMS was set then goto next state
377 }
378 else tapTestLogicReset(); // We were in an unexpected state
379 }
380
tapTestLogicReset()381 void IOBase::tapTestLogicReset()
382 {
383 for(int i=0; i<5; i++)tx(true,false);
384 current_state=TEST_LOGIC_RESET;
385 }
386
cycleTCK(int n,bool tdi)387 void IOBase::cycleTCK(int n, bool tdi)
388 {
389 bool tms=false;
390 if(current_state==TEST_LOGIC_RESET)tms=true;
391 for(int i=0; i<n; i++)tx(tms,tdi);
392 }
393