]>
git.zerfleddert.de Git - usb-driver/blob - jtagkey.c
c4f2beeb9679deb554d2c7e3496f8aaa680f07e7
6 #include "usb-driver.h"
11 #define USBBUFSIZE 1048576
12 #define JTAG_SPEED 100000
13 #define BULK_LATENCY 2
14 #define OTHER_LATENCY 1
16 static struct ftdi_context ftdic
;
18 static int jtagkey_latency(int latency
) {
19 static int current
= 0;
22 if (current
!= latency
) {
23 DPRINTF("switching latency\n");
24 if ((ret
= ftdi_set_latency_timer(&ftdic
, latency
)) != 0) {
25 fprintf(stderr
, "unable to set latency timer: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
35 static int jtagkey_init(unsigned short vid
, unsigned short pid
, unsigned short iface
) {
39 if ((ret
= ftdi_init(&ftdic
)) != 0) {
40 fprintf(stderr
, "unable to initialise libftdi: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
44 if ((ret
= ftdi_usb_open(&ftdic
, vid
, pid
)) != 0) {
45 fprintf(stderr
, "unable to open ftdi device: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
49 if ((ret
= ftdi_usb_reset(&ftdic
)) != 0) {
50 fprintf(stderr
, "unable reset device: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
54 if ((ret
= ftdi_set_interface(&ftdic
, iface
)) != 0) {
55 fprintf(stderr
, "unable to set interface: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
59 if ((ret
= ftdi_write_data_set_chunksize(&ftdic
, USBBUFSIZE
)) != 0) {
60 fprintf(stderr
, "unable to set write chunksize: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
64 if ((ret
= ftdi_read_data_set_chunksize(&ftdic
, USBBUFSIZE
)) != 0) {
65 fprintf(stderr
, "unable to set read chunksize: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
69 if ((ret
= jtagkey_latency(OTHER_LATENCY
)) != 0)
73 ftdi_write_data(&ftdic
, &c
, 1);
75 if ((ret
= ftdi_set_bitmode(&ftdic
, JTAGKEY_TCK
|JTAGKEY_TDI
|JTAGKEY_TMS
|JTAGKEY_OEn
, BITMODE_SYNCBB
)) != 0) {
76 fprintf(stderr
, "unable to enable bitbang mode: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
80 if ((ret
= ftdi_set_baudrate(&ftdic
, JTAG_SPEED
)) != 0) {
81 fprintf(stderr
, "unable to set baudrate: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
85 if ((ret
= ftdi_usb_purge_buffers(&ftdic
)) != 0) {
86 fprintf(stderr
, "unable to purge buffers: %d (%s)\n", ret
, ftdi_get_error_string(&ftdic
));
93 int jtagkey_open(int num
) {
96 ret
= jtagkey_init(config_usb_vid(num
), config_usb_pid(num
), config_usb_iface(num
));
104 void jtagkey_close(int handle
) {
105 if (handle
== 0xff) {
106 ftdi_disable_bitbang(&ftdic
);
107 ftdi_usb_close(&ftdic
);
113 static void jtagkey_state(unsigned char data
) {
114 fprintf(stderr
,"Pins high: ");
116 if (data
& JTAGKEY_TCK
)
117 fprintf(stderr
,"TCK ");
119 if (data
& JTAGKEY_TDI
)
120 fprintf(stderr
,"TDI ");
122 if (data
& JTAGKEY_TDO
)
123 fprintf(stderr
,"TDO ");
125 if (data
& JTAGKEY_TMS
)
126 fprintf(stderr
,"TMS ");
128 if (data
& JTAGKEY_VREF
)
129 fprintf(stderr
,"VREF ");
131 fprintf(stderr
,"\n");
135 struct jtagkey_reader_arg
{
140 static void *jtagkey_reader(void *thread_arg
) {
141 struct jtagkey_reader_arg
*arg
= (struct jtagkey_reader_arg
*)thread_arg
;
145 DPRINTF("reader for %d bytes\n", arg
->num
);
146 while (i
< arg
->num
) {
147 i
+= ftdi_read_data(&ftdic
, arg
->buf
+ i
, arg
->num
- i
);
153 /* TODO: Interpret JTAG commands and transfer in MPSSE mode */
154 int jtagkey_transfer(WD_TRANSFER
*tr
, int fd
, unsigned int request
, int ppbase
, int ecpbase
, int num
) {
160 static unsigned char last_data
= 0;
161 static unsigned char last_write
= 0x00;
162 static unsigned char writebuf
[USBBUFSIZE
], *writepos
= writebuf
;
163 static unsigned char readbuf
[USBBUFSIZE
], *readpos
;
164 unsigned char data
, prev_data
, last_cyc_write
;
165 struct jtagkey_reader_arg targ
;
166 pthread_t reader_thread
;
169 for (i
= 0; i
< num
; i
++)
170 if (tr
[i
].cmdTrans
== PP_READ
)
173 /* Write combining */
174 if ((writepos
-writebuf
> sizeof(writebuf
)-num
) || (nread
&& writepos
-writebuf
)) {
175 unsigned char *pos
= writebuf
;
178 DPRINTF("writing %zd bytes due to %d following reads in %d chunks or full buffer\n", writepos
-writebuf
, nread
, num
);
179 jtagkey_latency(BULK_LATENCY
);
181 targ
.num
= writepos
-pos
;
183 pthread_create(&reader_thread
, NULL
, &jtagkey_reader
, &targ
);
185 while (pos
< writepos
) {
188 if (len
> USBBUFSIZE
)
191 DPRINTF("combined write of %d/%zd\n",len
,writepos
-pos
);
192 ftdi_write_data(&ftdic
, pos
, len
);
195 pthread_join(reader_thread
, NULL
);
200 last_cyc_write
= last_write
;
202 for (i
= 0; i
< num
; i
++) {
203 DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
204 (unsigned long)tr
[i
].dwPort
, tr
[i
].cmdTrans
, tr
[i
].dwBytes
,
205 tr
[i
].fAutoinc
, tr
[i
].dwOptions
);
207 port
= (unsigned long)tr
[i
].dwPort
;
208 val
= tr
[i
].Data
.Byte
;
211 if (tr
[i
].cmdTrans
== 13)
212 DPRINTF("write byte: %d\n", val
);
214 if (tr
[i
].cmdTrans
== 13)
215 jtagmon(val
& PP_TCK
, val
& PP_TMS
, val
& PP_TDI
);
218 /* Pad writebuf for read-commands in stream */
219 *writepos
= last_data
;
220 prev_data
= last_data
;
222 if (port
== ppbase
+ PP_DATA
) {
223 DPRINTF("data port\n");
226 switch(tr
[i
].cmdTrans
) {
228 ret
= 0; /* We don't support reading of the data port */
270 fprintf(stderr
,"!!!Unsupported TRANSFER command: %lu!!!\n", tr
[i
].cmdTrans
);
276 if ((tr
[i
].cmdTrans
== PP_READ
) || (*writepos
!= prev_data
) || (i
== num
-1))
282 DPRINTF("writing %zd bytes\n", writepos
-writebuf
);
284 *writepos
= last_data
;
287 jtagkey_latency(OTHER_LATENCY
);
289 targ
.num
= writepos
-writebuf
;
291 pthread_create(&reader_thread
, NULL
, &jtagkey_reader
, &targ
);
292 ftdi_write_data(&ftdic
, writebuf
, writepos
-writebuf
);
293 pthread_join(reader_thread
, NULL
);
296 hexdump(writebuf
, writepos
-writebuf
, "->");
297 hexdump(readbuf
, i
, "<-");
306 last_write
= last_cyc_write
;
308 for (i
= 0; i
< num
; i
++) {
309 DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
310 (unsigned long)tr
[i
].dwPort
, tr
[i
].cmdTrans
, tr
[i
].dwBytes
,
311 tr
[i
].fAutoinc
, tr
[i
].dwOptions
);
313 port
= (unsigned long)tr
[i
].dwPort
;
314 val
= tr
[i
].Data
.Byte
;
316 if ((tr
[i
].cmdTrans
!= PP_READ
) && (val
== last_write
) && (i
!= num
-1))
321 if (port
== ppbase
+ PP_DATA
) {
322 if (tr
[i
].cmdTrans
== PP_WRITE
) {
325 } else if (port
== ppbase
+ PP_STATUS
) {
326 DPRINTF("status port (last write: 0x%x)\n", last_write
);
327 switch(tr
[i
].cmdTrans
) {
332 DPRINTF("READ: 0x%x\n", data
);
337 if ((data
& JTAGKEY_TDO
) && (last_write
& PP_PROG
))
340 if (~last_write
& PP_PROG
)
343 if (last_write
& 0x40)
350 ret
= 0; /* Status Port is readonly */
354 fprintf(stderr
,"!!!Unsupported TRANSFER command: %lu!!!\n", tr
[i
].cmdTrans
);
362 tr
[i
].Data
.Byte
= val
;
364 DPRINTF("dwPortReturn: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
365 (unsigned long)tr
[i
].dwPort
, tr
[i
].cmdTrans
, tr
[i
].dwBytes
,
366 tr
[i
].fAutoinc
, tr
[i
].dwOptions
);
368 if (tr
[i
].cmdTrans
== 10)
369 DPRINTF("read byte: %d\n", tr
[i
].Data
.Byte
);