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