]> git.zerfleddert.de Git - usb-driver/blob - jtagkey.c
41f0fd60723df3d2e472ada46b1a2cd8da1d0690
[usb-driver] / jtagkey.c
1 #include <stdio.h>
2 #include <ftdi.h>
3 #include <unistd.h>
4 #include "usb-driver.h"
5 #include "config.h"
6 #include "jtagkey.h"
7
8 #define USBBUFSIZE 4096
9 #define SLOW_AND_SAFE 1
10
11 static struct ftdi_context ftdic;
12 static unsigned int usb_maxlen = 0;
13 static unsigned char bitbang_mode;
14
15 static int jtagkey_init(unsigned short vid, unsigned short pid) {
16 int ret = 0;
17 unsigned char c;
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
39
40 #ifdef SLOW_AND_SAFE
41 usb_maxlen = 384;
42 #else
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));
45 return ret;
46 }
47 #endif
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
54 if ((ret = ftdi_set_baudrate(&ftdic, 500000)) != 0) {
55 fprintf(stderr, "unable to set baudrate: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
56 return ret;
57 }
58
59 c = 0x00;
60 ftdi_write_data(&ftdic, &c, 1);
61
62 if ((ret = ftdi_set_bitmode(&ftdic, JTAGKEY_TCK|JTAGKEY_TDI|JTAGKEY_TMS|JTAGKEY_OEn, BITMODE_SYNCBB)) != 0) {
63 fprintf(stderr, "unable to enable bitbang mode: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
64 return ret;
65 }
66
67 bitbang_mode = BITMODE_SYNCBB;
68
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
77 int 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
88 void jtagkey_close(int handle) {
89 if (handle == 0xff) {
90 ftdi_disable_bitbang(&ftdic);
91 ftdi_usb_close(&ftdic);
92 ftdi_deinit(&ftdic);
93 }
94 }
95
96 static int jtagkey_set_bbmode(unsigned char mode) {
97 int ret = 0;
98
99 if (bitbang_mode != mode) {
100 DPRINTF("switching bitbang-mode!\n");
101
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
121 void 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
142 int jtagkey_transfer(WD_TRANSFER *tr, int fd, unsigned int request, int ppbase, int ecpbase, int num) {
143 int ret = 0;
144 int i;
145 int nread = 0;
146 unsigned long port;
147 unsigned char val;
148 static unsigned char last_data = 0;
149 static unsigned char last_write = 0x00;
150 static unsigned char writebuf[USBBUFSIZE], *writepos = writebuf;
151 static unsigned char readbuf[USBBUFSIZE], *readpos;
152 unsigned char data, prev_data;
153
154 /* Count reads */
155 for (i = 0; i < num; i++)
156 if (tr[i].cmdTrans == PP_READ)
157 nread++;
158
159 /* Write combining */
160 if ((writepos-writebuf > sizeof(writebuf)-num) || (nread && writepos-writebuf)) {
161 unsigned char *pos = writebuf;
162 int len;
163 DPRINTF("writing %d bytes due to %d following reads in %d chunks or full buffer\n", writepos-writebuf, nread, num);
164
165 #ifndef SLOW_AND_SAFE
166 jtagkey_set_bbmode(BITMODE_BITBANG);
167 #endif
168 while (pos < writepos) {
169 len = writepos-pos;
170
171 if (len > usb_maxlen)
172 len = usb_maxlen;
173
174 DPRINTF("combined write of %d/%d\n",len,writepos-pos);
175 ftdi_write_data(&ftdic, pos, len);
176 #ifdef SLOW_AND_SAFE
177 i = 0;
178 while (i < len) {
179 i += ftdi_read_data(&ftdic, readbuf, sizeof(readbuf));
180 }
181 #endif
182 pos += len;
183 }
184
185 writepos = writebuf;
186 }
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
201 /* Pad writebuf for read-commands in stream */
202 *writepos = last_data;
203 prev_data = last_data;
204
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) {
234 data = JTAGKEY_OEn;
235 DPRINTF("CTRL\n");
236 } else {
237 DPRINTF("!CTRL\n");
238 }
239
240 if (val & PP_PROG) {
241 DPRINTF("PROG\n");
242 } else {
243 DPRINTF("!PROG\n");
244 }
245
246 *writepos = data;
247
248 last_data = data;
249 last_write = val;
250 break;
251
252 default:
253 fprintf(stderr,"!!!Unsupported TRANSFER command: %lu!!!\n", tr[i].cmdTrans);
254 ret = -1;
255 break;
256 }
257 }
258
259 if (nread || (*writepos != prev_data))
260 writepos++;
261 }
262
263 if (nread)
264 {
265 DPRINTF("writing %d bytes\n", writepos-writebuf);
266
267 *writepos = last_data;
268 writepos++;
269
270 jtagkey_set_bbmode(BITMODE_SYNCBB);
271 ftdi_write_data(&ftdic, writebuf, writepos-writebuf);
272
273 i = 0;
274 while (i < writepos-writebuf) {
275 i += ftdi_read_data(&ftdic, readbuf, sizeof(readbuf));
276 }
277
278 #ifdef DEBUG
279 DPRINTF("write: ");
280 hexdump(writebuf, writepos-writebuf);
281 DPRINTF("read: ");
282 hexdump(readbuf, i);
283 #endif
284
285 writepos = writebuf;
286 } else {
287 return ret;
288 }
289
290 readpos = readbuf;
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;
299 readpos++;
300
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);
307 switch(tr[i].cmdTrans) {
308 case PP_READ:
309 data = *readpos;
310
311 #ifdef DEBUG
312 DPRINTF("READ: 0x%x\n", data);
313 jtagkey_state(data);
314 #endif
315
316 val = 0x00;
317 if ((data & JTAGKEY_TDO) && (last_write & PP_PROG))
318 val |= PP_TDO;
319
320 if (!(last_write & PP_PROG))
321 val |= 0x08;
322
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 }
338 } else {
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