OpenCores
URL https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [trunk/] [Software/] [adv_jtag_bridge/] [cable_xpc_dlc9.c] - Blame information for rev 55

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 nyawn
/* cable_xpc_dlc9.c - Xilinx Platform Cable (DLC9) driver for the Advanced JTAG Bridge
2 32 nyawn
   Copyright (C) 2008 - 2010 Nathan Yawn, nathan.yawn@opencores.org
3 4 nyawn
 
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
8
 
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
 
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
 
18
 
19
#include <stdio.h>
20
#include <sys/types.h>
21
#include <unistd.h>  // for usleep()
22
#include <stdlib.h>  // for sleep()
23
 
24 55 nyawn
#include "usb.h"  // libusb header
25 4 nyawn
 
26 55 nyawn
#include "cable_xpc_dlc9.h"
27 4 nyawn
#include "errcodes.h"
28
 
29 55 nyawn
jtag_cable_t dlc9_cable_driver = {
30
    .name ="xpc_usb" ,
31
    .inout_func = cable_xpcusb_inout,
32
    .out_func = cable_xpcusb_out,
33
    .init_func = cable_xpcusb_init,
34
    .opt_func = cable_xpcusb_opt,
35
    .bit_out_func = cable_common_write_bit,
36
    .bit_inout_func = cable_xpcusb_read_write_bit,
37
    .stream_out_func = cable_common_write_stream,
38
    .stream_inout_func = cable_common_read_stream,
39
    .flush_func = NULL,
40
    .opts = "",
41
    .help = "no options\n",
42
   };
43
 
44 4 nyawn
#define USB_TIMEOUT 500
45
 
46
// Note that this is based on the UrJTAG driver for the XPC-USB,
47
// which was 'experimental' at the time.
48
// It only supports bit-bang mode, and therefore will not be fast.
49
 
50
// USB constants for the DLC9
51
#define XPCUSB_VID  0x3fd
52
#define XPCUSB_PID  0x08
53
 
54
// Bit meanings in the command byte sent to the DLC9
55
// DLC9 has no TRST bit
56
#define XPCUSB_CMD_TDI 0x01
57
#define XPCUSB_CMD_TDO 0x01
58
#define XPCUSB_CMD_TMS 0x02
59
#define XPCUSB_CMD_TCK 0x04
60
#define XPCUSB_CMD_PROG 0x08
61
 
62
 
63
static struct usb_device *device;
64
 
65
 
66
///////////////////////////////////////////////////////////////////////////////
67
/*----- Functions for the Xilinx Platform Cable USB (Model DLC9)            */
68
/////////////////////////////////////////////////////////////////////////////
69
 
70
 
71
static int xpcu_request_28(struct usb_dev_handle *xpcu, int value)
72
{
73
  // Maybe clock speed setting?
74
  if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0028, value, NULL, 0, USB_TIMEOUT)<0)
75
    {
76
      fprintf(stderr, "Error sending usb_control_msg(0x28.x)\n");
77
      return APP_ERR_USB;
78
    }
79
 
80
  return APP_ERR_NONE;
81
}
82
 
83
 
84
static int xpcu_raise_ioa5(struct usb_dev_handle *xpcu)
85
{
86
  if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0018, 0x0000, NULL, 0, USB_TIMEOUT)<0)
87
    {
88
      fprintf(stderr, "Error sending usb_control_msg(0x18.0x00) (raise IOA.5{\n");
89
      return APP_ERR_USB;
90
    }
91
 
92
  return APP_ERR_NONE;
93
}
94
 
95
static int xpcu_select_gpio(struct usb_dev_handle *xpcu, int chain)
96
{
97
  if(usb_control_msg(xpcu, 0x40, 0xB0, 0x0052, chain, NULL, 0, USB_TIMEOUT)<0)
98
    {
99
      fprintf(stderr, "Error sending usb_control_msg(0x52.x) (select gpio)\n");
100
      return APP_ERR_USB;
101
    }
102
 
103
  return APP_ERR_NONE;
104
}
105
 
106
static int xpcu_read_firmware_version(struct usb_dev_handle *xpcu, uint16_t *buf)
107
{
108
  if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0000, (char*)buf, 2, USB_TIMEOUT)<0)
109
    {
110
      fprintf(stderr,"Error sending usb_control_msg(0x50.0) (read_firmware_version)\n");
111
      return APP_ERR_USB;
112
    }
113
  return APP_ERR_NONE;
114
}
115
 
116
static int xpcu_read_cpld_version(struct usb_dev_handle *xpcu, uint16_t *buf)
117
{
118
  if(usb_control_msg(xpcu, 0xC0, 0xB0, 0x0050, 0x0001, (char*)buf, 2, USB_TIMEOUT)<0)
119
    {
120
      fprintf(stderr, "Error sending usb_control_msg(0x50.1) (read_cpld_version)\n");
121
      return APP_ERR_USB;
122
    }
123
  return APP_ERR_NONE;
124
}
125
 
126
 
127
static int xpcusb_enumerate_bus(void)
128
{
129
  int             flag;  // for USB bus scanning stop condition
130
  struct usb_bus *bus;   // pointer on the USB bus
131
 
132
  // board detection
133
  usb_init();
134
  usb_find_busses();
135
  usb_find_devices();
136
 
137
  flag = 0;
138
 
139
  for (bus = usb_get_busses(); bus; bus = bus->next)
140
  {
141
    for (device = bus->devices; device; device = device->next)
142
    {
143
      if (device->descriptor.idVendor  == XPCUSB_VID &&
144
          device->descriptor.idProduct == XPCUSB_PID)
145
      {
146
              flag = 1;
147
              fprintf(stderr, "Found Xilinx Platform Cable USB (DLC9)\n");
148
              return APP_ERR_NONE;
149
      }
150
    }
151
    if (flag)
152
      break;
153
  }
154
 
155
  fprintf(stderr, "Failed to find Xilinx Platform Cable USB\n");
156
  return APP_ERR_CABLENOTFOUND;
157
}
158
 
159
 
160
int cable_xpcusb_init()
161
{
162
  int err = APP_ERR_NONE;
163
 
164
  // Process to reset the XPC USB (DLC9)
165
  if(err |= xpcusb_enumerate_bus()) {
166
    return err;
167
  }
168
 
169
  usb_dev_handle *h_device = usb_open(device);
170
 
171
  if(h_device == NULL)
172
    {
173
      fprintf(stderr, "Init failed to open USB device for reset\n");
174
      return APP_ERR_USB;
175
    }
176
 
177
  if(usb_reset(h_device) != APP_ERR_NONE)
178
    fprintf(stderr, "Failed to reset XPC-USB\n");
179
 
180
  usb_close(h_device);
181
 
182
  // Wait for reset!!!
183
  sleep(1);
184
 
185
  // Do device initialization
186
  if(err |= xpcusb_enumerate_bus())
187
    return err;
188
 
189
  h_device = usb_open(device);
190
  if(h_device == NULL)
191
    {
192
      fprintf(stderr, "Init failed to open USB device for initialization\n");
193
      return APP_ERR_USB;
194
    }
195
 
196
  // set the configuration
197
  if (usb_set_configuration(h_device, device->config->bConfigurationValue))
198
    {
199
      usb_close(h_device);
200
      fprintf(stderr, "USB-reset failed to set configuration\n");
201
      return APP_ERR_USB;
202
    }
203
 
204
  while (usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber));
205
 
206
  // DO DEVICE-SPECIFIC INIT HERE
207
  // Don't mess with the order here, it's easy to break.
208
 
209
  // Maybe set the clock speed?
210
  if(xpcu_request_28(h_device, 0x11) != APP_ERR_NONE)   {
211
    fprintf(stderr, "Request 28 (set clock speed?) failed.\n");
212
  }
213
 
214
  // Set internal TCK,TMS,TDO to 0
215
  if(usb_control_msg(h_device, 0x40, 0xB0, 0x0030, 0x08, NULL, 0, USB_TIMEOUT)!= APP_ERR_NONE) {
216
    fprintf(stderr, "usb_control_msg(0x30.0x00) (write port E) failed\n");
217
  }
218
 
219
  // Read firmware version (constant embedded in firmware)
220
  uint16_t buf;
221
 
222
  if(xpcu_read_firmware_version(h_device, &buf) != APP_ERR_NONE)        {
223
    fprintf(stderr, "Failed to read firmware version.\n");
224
  }
225
  else  {
226
    printf("firmware version = 0x%04X (%u)\n", buf, buf);
227
  }
228
 
229
  // Read CPLD version (uses the internal GPIF interface)
230
  if(xpcu_read_cpld_version(h_device, &buf) != APP_ERR_NONE) {
231
    fprintf(stderr, "Failed to read CPLD version.\n");
232
  }
233
  else
234
    {
235
      printf("cable CPLD version = 0x%04X (%u)\n", buf, buf);
236
      if(buf == 0)               {
237
        printf("Warning: version '0' can't be correct. Please try resetting the cable\n");
238
      }
239
    }
240
 
241
  // Set IOA bit 5, which enables output buffers
242
  if(xpcu_raise_ioa5(h_device) != APP_ERR_NONE) {
243
    fprintf(stderr, "Failed to enable XPC output buffers\n");
244
  }
245
 
246
  // access external chain for normal operation
247
  if(xpcu_select_gpio(h_device, 0) != APP_ERR_NONE) {
248
    fprintf(stderr, "Failed to select external JTAG chain\n");
249
  }
250
 
251
  // Init all done, release cable
252
  if (usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)){
253
    usb_close(h_device);
254
    fprintf(stderr, "USB-out failed to release interface\n");
255
    return APP_ERR_USB;
256
  }
257
 
258
  usb_close(h_device);
259
 
260
  return APP_ERR_NONE;
261
}
262
 
263
 
264
int cable_xpcusb_out(uint8_t value)
265
{
266
  int             rv;                  // to catch return values of functions
267
  usb_dev_handle *h_device;            // handle on the ubs device
268
  uint8_t out;
269
 
270
  // open the device
271
  h_device = usb_open(device);
272
  if (h_device == NULL){
273
    usb_close(h_device);
274
    fprintf(stderr, "USB-out failed to open device\n");
275
    return APP_ERR_USB;
276
  }
277
 
278
  // set the configuration
279
  if (usb_set_configuration(h_device, device->config->bConfigurationValue))
280
    {
281
      usb_close(h_device);
282
      fprintf(stderr, "USB-out failed to set configuration\n");
283
      return APP_ERR_USB;
284
    }
285
 
286
  // wait until device is ready
287
  while (usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber));
288
 
289
  // send the buffer
290
  // Translate to USB blaster protocol
291
  out = 0;
292
  if(value & TCLK_BIT)
293
    out |= XPCUSB_CMD_TCK;
294
  if(value & TDI_BIT)
295
    out |= XPCUSB_CMD_TDI;
296
  if(value & TMS_BIT)
297
    out |= XPCUSB_CMD_TMS;
298
 
299
  out |= XPCUSB_CMD_PROG;  // Set output PROG (always necessary)
300
 
301
  /* debug
302
  if(value & TDI_BIT)
303
    printf("Write 1\n");
304
  else
305
    printf("Write 0\n");
306
  */
307
 
308
  rv = usb_control_msg(h_device, 0x40, 0xB0, 0x0030, out, NULL, 0, USB_TIMEOUT);
309
  if (rv < 0){
310
    fprintf(stderr, "\nFailed to send a write control message (rv = %d):\n%s\n", rv, usb_strerror());
311
  }
312
 
313
  // release the interface cleanly
314
  if (usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)){
315
    fprintf(stderr, "Warning: failed to release usb interface after write\n");
316
  }
317
 
318
  // close the device
319
  usb_close(h_device);
320
  return APP_ERR_NONE;
321
}
322
 
323
 
324
int cable_xpcusb_inout(uint8_t value, uint8_t *inval)
325
{
326
  int rv;                  // to catch return values of functions
327
  usb_dev_handle *h_device;            // handle on the usb device
328
  char ret = 0;
329
  uint8_t out;
330
 
331
  // Translate to USB blaster protocol
332
  out = 0;
333
  if(value & TCLK_BIT)
334
    out |= XPCUSB_CMD_TCK;
335
  if(value & TDI_BIT)
336
    out |= XPCUSB_CMD_TDI;
337
  if(value & TMS_BIT)
338
    out |= XPCUSB_CMD_TMS;
339
 
340
  out |= XPCUSB_CMD_PROG;  // Set output PROG (always necessary)
341
 
342
  // open the device
343
  h_device = usb_open(device);
344
  if (h_device == NULL){
345
    usb_close(h_device);
346
    return APP_ERR_USB;
347
  }
348
 
349
  // set the configuration
350
  if (usb_set_configuration(h_device, device->config->bConfigurationValue)){
351
    usb_close(h_device);
352
    return APP_ERR_USB;
353
  }
354
 
355
  // wait until device is ready
356
  while (usb_claim_interface(h_device, device->config->interface->altsetting->bInterfaceNumber));
357
 
358
  // Send the output
359
  rv = usb_control_msg(h_device, 0x40, 0xB0, 0x0030, out, NULL, 0, USB_TIMEOUT);
360
  if (rv < 0){
361
    fprintf(stderr, "\nFailed to send a write control message (rv = %x):\n%s\n", rv, usb_strerror());
362
    goto usbblaster_in_fail;
363
  }
364
 
365
 
366
  // receive the response
367
  rv = usb_control_msg(h_device, 0xC0, 0xB0, 0x0038, 0, (char*)&ret, 1, USB_TIMEOUT);
368
  if (rv < 0){
369
    fprintf(stderr, "\nFailed to execute a read control message:\n%s\n", usb_strerror());
370
    goto usbblaster_in_fail;
371
  }
372
 
373
 
374
  // release the interface cleanly
375
  if (usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber)){
376
    fprintf(stderr, "Warning: failed to release USB interface after read\n");
377
    usb_close(h_device);
378
    return APP_ERR_USB;
379
  }
380
 
381
  // close the device
382
  usb_close(h_device);
383
 
384
  /* debug
385
  if(value & TDI_BIT)
386
    printf("Write 1, ");
387
  else
388
    printf("Write 0, ");
389
  */
390
 
391
  if(ret & XPCUSB_CMD_TDO)
392
    *inval = 1;
393
  else
394
    *inval = 0;
395
 
396
  //printf("Read 0\n");
397
  return APP_ERR_NONE;
398
 
399
usbblaster_in_fail:
400
  usb_release_interface(h_device, device->config->interface->altsetting->bInterfaceNumber);
401
  usb_close(h_device);
402
  return APP_ERR_USB;
403
}
404
 
405
 
406
// Xilinx couldn't be like everyone else.  Oh, no.
407
// For some reason, "set data/drop TCK" then "read data/raise TCK" won't work.
408
// So we have our very own bit read/write function.  @whee.
409
int cable_xpcusb_read_write_bit(uint8_t packet_out, uint8_t *bit_in) {
410
  uint8_t data = TRST_BIT;  //  TRST is active low, don't clear unless /set/ in 'packet'
411
  int err = APP_ERR_NONE;
412
 
413
  /* Write data, drop clock */
414
  if(packet_out & TDO) data |= TDI_BIT;
415
  if(packet_out & TMS) data |= TMS_BIT;
416
  if(packet_out & TRST) data &= ~TRST_BIT;
417
 
418
  err |= cable_xpcusb_inout(data, bit_in);  // read in bit, set data, drop clock
419
  err |= cable_xpcusb_out(data|TCLK_BIT);  // clk hi
420
 
421
  return err;
422
}
423
 
424
 
425
int cable_xpcusb_opt(int c, char *str)
426
{
427
    fprintf(stderr, "Unknown parameter '%c'\n", c);
428
    return APP_ERR_BAD_PARAM;
429
}
430
 
431 55 nyawn
jtag_cable_t *cable_xpcusb_get_driver(void)
432
{
433
  return &dlc9_cable_driver;
434
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.