1 /* JTAG routines
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 #include "config.h"
20 
21 #include "jtag.h"
22 #include <unistd.h>
23 #include <stdio.h>
24 
25 #ifdef WINDOWS
26 	#include <windows.h>
27 	#define usleep(x) Sleep((x+999)/1000)
28 #endif
29 
Jtag(IOBase * iob)30 Jtag::Jtag(IOBase *iob)
31 {
32   io=iob;
33   postDRState=IOBase::RUN_TEST_IDLE;
34   postIRState=IOBase::RUN_TEST_IDLE;
35   deviceIndex=-1;
36   shiftDRincomplete=false;
37 }
38 
getChain()39 int Jtag::getChain()
40 {
41   io->tapTestLogicReset();
42   io->setTapState(IOBase::SHIFT_DR);
43   byte idx[4];
44   byte zero[4];
45   numDevices=0;
46   for(int i=0; i<4; i++)zero[i]=0;
47   do{
48     io->shiftTDITDO(zero,idx,32,false);
49     unsigned long id=byteArrayToLong(idx);
50     if(id!=0 && id !=0xffffffff){
51       numDevices++;
52       chainParam_t dev;
53       dev.idcode=id;
54       devices.insert(devices.begin(),dev);
55     }
56     else{
57       if (id == 0xffffffff && numDevices >0)
58        {
59          fprintf(stderr,"You probably have a broken Atmel device in your chain!\n");
60          fprintf(stderr,"No succeeding device can be identified\n");
61        }
62       break;
63     }
64   }while(numDevices<MAXNUMDEVICES);
65   io->setTapState(IOBase::TEST_LOGIC_RESET);
66   return numDevices;
67 }
68 
selectDevice(int dev)69 int Jtag::selectDevice(int dev)
70 {
71   if(dev>=numDevices)deviceIndex=-1;
72   else deviceIndex=dev;
73   return deviceIndex;
74 }
75 
Usleep(unsigned int usec)76 void Jtag::Usleep(unsigned int usec)
77 {
78   io->flush_tms();
79   io->flush();
80   usleep(usec);
81 }
82 
setDeviceIRLength(int dev,int len)83 int Jtag::setDeviceIRLength(int dev, int len)
84 {
85   if(dev>=numDevices||dev<0)return -1;
86   devices[dev].irlen=len;
87   return dev;
88 }
89 
shiftDR(const byte * tdi,byte * tdo,int length,int align,bool exit)90 void Jtag::shiftDR(const byte *tdi, byte *tdo, int length, int align, bool exit)
91 {
92   if(deviceIndex<0)return;
93   int post=deviceIndex;
94   if(!shiftDRincomplete){
95     int pre=numDevices-deviceIndex-1;
96     if(align){
97       pre=-post;
98       while(pre<=0)pre+=align;
99     }
100     /* We can combine the pre bits to reach the target device with
101      the TMS bits to reach the SHIFT-DR state, as the pre bit can be '0'*/
102     io->setTapState(IOBase::SHIFT_DR,pre);
103   }
104   if(tdi!=0&&tdo!=0)io->shiftTDITDO(tdi,tdo,length,post==0&&exit);
105   else if(tdi!=0&&tdo==0)io->shiftTDI(tdi,length,post==0&&exit);
106   else if(tdi==0&&tdo!=0)io->shiftTDO(tdo,length,post==0&&exit);
107   else io->shift(false,length,post==0&&exit);
108   if(exit){
109     io->shift(false,post);
110     io->setTapState(postDRState);
111     shiftDRincomplete=false;
112   }
113   else shiftDRincomplete=true;
114 }
115 
shiftIR(const byte * tdi,byte * tdo)116 void Jtag::shiftIR(const byte *tdi, byte *tdo)
117 {
118 	int dev;
119 
120   if(deviceIndex<0)return;
121   io->setTapState(IOBase::SHIFT_IR);
122   int pre=0;
123   for(dev=deviceIndex+1; dev<numDevices; dev++)pre+=devices[dev].irlen; // Calculate number of pre BYPASS bits.
124   int post=0;
125   for(dev=0; dev<deviceIndex; dev++)post+=devices[dev].irlen; // Calculate number of post BYPASS bits.
126   io->shift(true,pre,false);
127   if(tdo!=0)io->shiftTDITDO(tdi,tdo,devices[deviceIndex].irlen,post==0);
128   else if(tdo==0)io->shiftTDI(tdi,devices[deviceIndex].irlen,post==0);
129   io->shift(true,post);
130   io->setTapState(postIRState);
131 }
132