]> git.zerfleddert.de Git - usb-driver/blame - jtagkey.c
only close the parallel port when it was really openend
[usb-driver] / jtagkey.c
CommitLineData
8121bc50 1#include <stdio.h>
2#include <ftdi.h>
9640dec9 3#include <unistd.h>
3cc5a0bc 4#include <pthread.h>
8121bc50 5#include "usb-driver.h"
5e3d963b 6#include "config.h"
8121bc50 7#include "jtagkey.h"
0a060ead 8#include "jtagmon.h"
8121bc50 9
3cc5a0bc 10#define USBBUFSIZE 1048576
66c1fd53 11#define JTAG_SPEED 100000
f9318fa1 12#define BULK_LATENCY 2
13#define OTHER_LATENCY 1
d0e2002d 14
8121bc50 15static struct ftdi_context ftdic;
f9318fa1 16
17static int jtagkey_latency(int latency) {
18 static int current = 0;
19 int ret;
20
21 if (current != latency) {
22 DPRINTF("switching latency\n");
23 if ((ret = ftdi_set_latency_timer(&ftdic, latency)) != 0) {
24 fprintf(stderr, "unable to set latency timer: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
25 return ret;
26 }
27
28 current = latency;
29 }
30
31 return ret;
32}
8121bc50 33
5e3d963b 34static int jtagkey_init(unsigned short vid, unsigned short pid) {
8121bc50 35 int ret = 0;
d0e2002d 36 unsigned char c;
8121bc50 37
38 if ((ret = ftdi_init(&ftdic)) != 0) {
39 fprintf(stderr, "unable to initialise libftdi: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
40 return ret;
41 }
42
43 if ((ret = ftdi_usb_open(&ftdic, vid, pid)) != 0) {
44 fprintf(stderr, "unable to open ftdi device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
45 return ret;
46 }
47
48 if ((ret = ftdi_usb_reset(&ftdic)) != 0) {
49 fprintf(stderr, "unable reset device: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
50 return ret;
51 }
52
53 if ((ret = ftdi_set_interface(&ftdic, INTERFACE_A)) != 0) {
54 fprintf(stderr, "unable to set interface: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
55 return ret;
56 }
57
3cc5a0bc 58 if ((ret = ftdi_write_data_set_chunksize(&ftdic, USBBUFSIZE)) != 0) {
59 fprintf(stderr, "unable to set write chunksize: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
60 return ret;
61 }
4af4753d 62
3cc5a0bc 63 if ((ret = ftdi_read_data_set_chunksize(&ftdic, USBBUFSIZE)) != 0) {
64 fprintf(stderr, "unable to set read chunksize: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
8121bc50 65 return ret;
66 }
67
f9318fa1 68 if ((ret = jtagkey_latency(OTHER_LATENCY)) != 0)
8121bc50 69 return ret;
8121bc50 70
d0e2002d 71 c = 0x00;
72 ftdi_write_data(&ftdic, &c, 1);
73
75417531 74 if ((ret = ftdi_set_bitmode(&ftdic, JTAGKEY_TCK|JTAGKEY_TDI|JTAGKEY_TMS|JTAGKEY_OEn, BITMODE_SYNCBB)) != 0) {
8121bc50 75 fprintf(stderr, "unable to enable bitbang mode: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
76 return ret;
77 }
78
66c1fd53 79 if ((ret = ftdi_set_baudrate(&ftdic, JTAG_SPEED)) != 0) {
80 fprintf(stderr, "unable to set baudrate: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
81 return ret;
82 }
83
8121bc50 84 if ((ret = ftdi_usb_purge_buffers(&ftdic)) != 0) {
85 fprintf(stderr, "unable to purge buffers: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
86 return ret;
87 }
88
89 return ret;
90}
91
5e3d963b 92int jtagkey_open(int num) {
93 int ret;
94
95 ret = jtagkey_init(config_usb_vid(num), config_usb_pid(num));
96
97 if (ret >= 0)
98 ret = 0xff;
99
100 return ret;
101}
102
103void jtagkey_close(int handle) {
104 if (handle == 0xff) {
105 ftdi_disable_bitbang(&ftdic);
106 ftdi_usb_close(&ftdic);
107 ftdi_deinit(&ftdic);
108 }
8121bc50 109}
110
111void jtagkey_state(unsigned char data) {
112 fprintf(stderr,"Pins high: ");
113
114 if (data & JTAGKEY_TCK)
115 fprintf(stderr,"TCK ");
116
117 if (data & JTAGKEY_TDI)
118 fprintf(stderr,"TDI ");
119
120 if (data & JTAGKEY_TDO)
121 fprintf(stderr,"TDO ");
122
123 if (data & JTAGKEY_TMS)
124 fprintf(stderr,"TMS ");
125
126 if (data & JTAGKEY_VREF)
127 fprintf(stderr,"VREF ");
128
129 fprintf(stderr,"\n");
130}
131
3cc5a0bc 132struct jtagkey_reader_arg {
133 int num;
134 unsigned char *buf;
135};
136
137static void *jtagkey_reader(void *thread_arg) {
138 struct jtagkey_reader_arg *arg = (struct jtagkey_reader_arg*)thread_arg;
3cc5a0bc 139 int i;
140
141 i = 0;
142 DPRINTF("reader for %d bytes\n", arg->num);
143 while (i < arg->num) {
144 i += ftdi_read_data(&ftdic, arg->buf + i, arg->num - i);
145 }
146
147 pthread_exit(NULL);
148}
149
617583d0 150/* TODO: Interpret JTAG commands and transfer in MPSSE mode */
8121bc50 151int jtagkey_transfer(WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num) {
152 int ret = 0;
153 int i;
d0e2002d 154 int nread = 0;
8121bc50 155 unsigned long port;
156 unsigned char val;
d0e2002d 157 static unsigned char last_data = 0;
e81047b8 158 static unsigned char last_write = 0x00;
d0e2002d 159 static unsigned char writebuf[USBBUFSIZE], *writepos = writebuf;
160 static unsigned char readbuf[USBBUFSIZE], *readpos;
617583d0 161 unsigned char data, prev_data, last_cyc_write;
3cc5a0bc 162 struct jtagkey_reader_arg targ;
163 pthread_t reader_thread;
d0e2002d 164
e81047b8 165 /* Count reads */
d0e2002d 166 for (i = 0; i < num; i++)
e81047b8 167 if (tr[i].cmdTrans == PP_READ)
d0e2002d 168 nread++;
169
170 /* Write combining */
171 if ((writepos-writebuf > sizeof(writebuf)-num) || (nread && writepos-writebuf)) {
4af4753d 172 unsigned char *pos = writebuf;
173 int len;
3cc5a0bc 174
d0e2002d 175 DPRINTF("writing %d bytes due to %d following reads in %d chunks or full buffer\n", writepos-writebuf, nread, num);
f9318fa1 176 jtagkey_latency(BULK_LATENCY);
d0e2002d 177
3cc5a0bc 178 targ.num = writepos-pos;
179 targ.buf = readbuf;
180 pthread_create(&reader_thread, NULL, &jtagkey_reader, &targ);
f9318fa1 181
4af4753d 182 while (pos < writepos) {
85690a3f 183 len = writepos-pos;
184
3cc5a0bc 185 if (len > USBBUFSIZE)
186 len = USBBUFSIZE;
d0e2002d 187
4af4753d 188 DPRINTF("combined write of %d/%d\n",len,writepos-pos);
189 ftdi_write_data(&ftdic, pos, len);
190 pos += len;
e81047b8 191 }
3cc5a0bc 192 pthread_join(reader_thread, NULL);
4af4753d 193
d0e2002d 194 writepos = writebuf;
195 }
8121bc50 196
617583d0 197 last_cyc_write = last_write;
198
8121bc50 199 for (i = 0; i < num; i++) {
200 DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
201 (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
202 tr[i].fAutoinc, tr[i].dwOptions);
203
204 port = (unsigned long)tr[i].dwPort;
205 val = tr[i].Data.Byte;
206
207#ifdef DEBUG
208 if (tr[i].cmdTrans == 13)
209 DPRINTF("write byte: %d\n", val);
0a060ead 210
211 if (tr[i].cmdTrans == 13)
084feb4b 212 jtagmon(val & PP_TCK, val & PP_TMS, val & PP_TDI);
8121bc50 213#endif
214
b122ac4b 215 /* Pad writebuf for read-commands in stream */
d0e2002d 216 *writepos = last_data;
e81047b8 217 prev_data = last_data;
b122ac4b 218
8121bc50 219 if (port == ppbase + PP_DATA) {
220 DPRINTF("data port\n");
221
222 data = 0x00;
223 switch(tr[i].cmdTrans) {
224 case PP_READ:
225 ret = 0; /* We don't support reading of the data port */
226 break;
227
228 case PP_WRITE:
229 if (val & PP_TDI) {
230 data |= JTAGKEY_TDI;
231 DPRINTF("TDI\n");
232 } else {
233 DPRINTF("!TDI\n");
234 }
235 if (val & PP_TCK) {
236 data |= JTAGKEY_TCK;
237 DPRINTF("TCK\n");
238 } else {
239 DPRINTF("!TCK\n");
240 }
241 if (val & PP_TMS) {
242 data |= JTAGKEY_TMS;
243 DPRINTF("TMS\n");
244 } else {
245 DPRINTF("!TMS\n");
246 }
247 if (val & PP_CTRL) {
d0e2002d 248 data = JTAGKEY_OEn;
8121bc50 249 DPRINTF("CTRL\n");
250 } else {
251 DPRINTF("!CTRL\n");
252 }
8121bc50 253
d0e2002d 254 if (val & PP_PROG) {
255 DPRINTF("PROG\n");
256 } else {
257 DPRINTF("!PROG\n");
258 }
259
260 *writepos = data;
261
b122ac4b 262 last_data = data;
d0e2002d 263 last_write = val;
8121bc50 264 break;
265
266 default:
267 fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
268 ret = -1;
269 break;
270 }
b122ac4b 271 }
e81047b8 272
617583d0 273 if ((tr[i].cmdTrans == PP_READ) || (*writepos != prev_data) || (i == num-1))
e81047b8 274 writepos++;
b122ac4b 275 }
276
d0e2002d 277 if (nread)
278 {
279 DPRINTF("writing %d bytes\n", writepos-writebuf);
59b06a85 280
281 *writepos = last_data;
282 writepos++;
283
f9318fa1 284 jtagkey_latency(OTHER_LATENCY);
285
3cc5a0bc 286 targ.num = writepos-writebuf;
287 targ.buf = readbuf;
288 pthread_create(&reader_thread, NULL, &jtagkey_reader, &targ);
9640dec9 289 ftdi_write_data(&ftdic, writebuf, writepos-writebuf);
3cc5a0bc 290 pthread_join(reader_thread, NULL);
b122ac4b 291
292#ifdef DEBUG
d0e2002d 293 DPRINTF("write: ");
294 hexdump(writebuf, writepos-writebuf);
295 DPRINTF("read: ");
296 hexdump(readbuf, i);
b122ac4b 297#endif
298
d0e2002d 299 writepos = writebuf;
300 } else {
301 return ret;
302 }
303
304 readpos = readbuf;
617583d0 305 last_write = last_cyc_write;
b122ac4b 306
307 for (i = 0; i < num; i++) {
308 DPRINTF("dwPort: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
309 (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
310 tr[i].fAutoinc, tr[i].dwOptions);
311
312 port = (unsigned long)tr[i].dwPort;
313 val = tr[i].Data.Byte;
617583d0 314
315 if ((tr[i].cmdTrans != PP_READ) && (val == last_write) && (i != num-1))
316 continue;
317
d0e2002d 318 readpos++;
b122ac4b 319
d0e2002d 320 if (port == ppbase + PP_DATA) {
321 if (tr[i].cmdTrans == PP_WRITE) {
322 last_write = val;
323 }
324 } else if (port == ppbase + PP_STATUS) {
325 DPRINTF("status port (last write: 0x%x)\n", last_write);
8121bc50 326 switch(tr[i].cmdTrans) {
327 case PP_READ:
d0e2002d 328 data = *readpos;
59b06a85 329
8121bc50 330#ifdef DEBUG
331 DPRINTF("READ: 0x%x\n", data);
332 jtagkey_state(data);
333#endif
334
335 val = 0x00;
d0e2002d 336 if ((data & JTAGKEY_TDO) && (last_write & PP_PROG))
8121bc50 337 val |= PP_TDO;
338
617583d0 339 if (~last_write & PP_PROG)
d0e2002d 340 val |= 0x08;
341
8121bc50 342 if (last_write & 0x40)
343 val |= 0x20;
344 else
345 val |= 0x80;
346 break;
347
348 case PP_WRITE:
349 ret = 0; /* Status Port is readonly */
350 break;
351
352 default:
353 fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
354 ret = -1;
355 break;
356 }
8121bc50 357 } else {
8121bc50 358 ret = 0;
359 }
360
361 tr[i].Data.Byte = val;
362
363 DPRINTF("dwPortReturn: 0x%lx, cmdTrans: %lu, dwbytes: %ld, fautoinc: %ld, dwoptions: %ld\n",
364 (unsigned long)tr[i].dwPort, tr[i].cmdTrans, tr[i].dwBytes,
365 tr[i].fAutoinc, tr[i].dwOptions);
366#ifdef DEBUG
367 if (tr[i].cmdTrans == 10)
368 DPRINTF("read byte: %d\n", tr[i].Data.Byte);
369#endif
370 }
371
372 return ret;
373}
Impressum, Datenschutz