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_parallel.c] - Blame information for rev 55

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

Line No. Rev Author Line
1 21 nyawn
/* cable_parallel.c - Parallel cable drivers (XPC3 and XESS) for the Advanced JTAG Bridge
2
   Copyright (C) 2001 Marko Mlinar, markom@opencores.org
3
   Copyright (C) 2004 György Jeney, nog@sdf.lonestar.org
4
 
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 2 of the License, or
9
   (at your option) any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
 
21
 
22
#include <stdio.h>
23
#include <sys/io.h>  // for inb(), outb()
24
#include <sys/types.h>
25 55 nyawn
#include <sys/time.h>
26 21 nyawn
#include <unistd.h>
27 55 nyawn
#include <time.h>
28 21 nyawn
 
29 55 nyawn
#include "cable_parallel.h"
30 21 nyawn
#include "errcodes.h"
31
 
32 55 nyawn
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
33
 #if ((_POSIX_TIMERS) && (_POSIX_CPUTIME))
34
 #define PARALLEL_USE_PROCESS_TIMER
35
 #endif
36
#endif
37 21 nyawn
 
38 55 nyawn
jtag_cable_t xpc3_cable_driver = {
39
    .name = "xpc3",
40
    .inout_func = cable_xpc3_inout,
41
    .out_func = cable_xpc3_out,
42
    .init_func = cable_parallel_init,
43
    .opt_func = cable_parallel_opt,
44
    .bit_out_func = cable_common_write_bit,
45
    .bit_inout_func = cable_common_read_write_bit,
46
    .stream_out_func = cable_common_write_stream,
47
    .stream_inout_func = cable_common_read_stream,
48
    .flush_func = NULL,
49
    .opts = "p:",
50
    .help = "-p [port] Which port to use when communicating with the parport hardware (eg. 0x378)\n"
51
    };
52
 
53
jtag_cable_t xess_cable_driver = {
54
    .name = "xess",
55
    .inout_func = cable_xess_inout,
56
    .out_func = cable_xess_out,
57
    .init_func = cable_parallel_init,
58
    .opt_func = cable_parallel_opt,
59
    .bit_out_func = cable_common_write_bit,
60
    .bit_inout_func = cable_common_read_write_bit,
61
    .stream_out_func = cable_common_write_stream,
62
    .stream_inout_func = cable_common_read_stream,
63
    .flush_func = NULL,
64
    .opts = "p:",
65
    .help = "-p [port] Which port to use when communicating with the parport hardware (eg. 0x378)\n",
66
    };
67
 
68 21 nyawn
#define LPT_READ (base+1)
69
#define LPT_WRITE base
70
 
71
// Common functions used by both cable types
72
static int cable_parallel_out(uint8_t value);
73
static int cable_parallel_inout(uint8_t value, uint8_t *inval);
74
 
75
 
76
static int base = 0x378;
77
 
78 55 nyawn
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
79
 #ifndef PARALLEL_USE_PROCESS_TIMER
80
 struct timeval last_tv;
81
 #endif
82
#endif
83 21 nyawn
 
84
/////////////////////////////////////////////////////////////////////////////////
85
/*-------------------------------------[ Parallel port specific functions ]---*/
86
///////////////////////////////////////////////////////////////////////////////
87
 
88
int cable_parallel_init()
89
{
90
  if (ioperm(base, 3, 1)) {
91
    fprintf(stderr, "Couldn't get the port at %x\n", base);
92
    perror("Root privileges are required.\n");
93
    return APP_ERR_INIT_FAILED;
94
  }
95
  printf("Connected to parallel port at %x\n", base);
96
  printf("Dropping root privileges.\n");
97
  setreuid(getuid(), getuid());
98
 
99 55 nyawn
#ifdef __PARALLEL_TIMER_BUSY_WAIT__
100
 #ifdef PARALLEL_USE_PROCESS_TIMER
101
  struct timespec ts;
102
  ts.tv_sec = 0;
103
  ts.tv_nsec = 0;
104
  clock_settime(CLOCK_PROCESS_CPUTIME_ID, &ts);
105
 #else
106
  gettimeofday(&last_tv, NULL);
107
 #endif
108
#endif
109
 
110 21 nyawn
  return APP_ERR_NONE;
111
}
112
 
113
 
114
int cable_parallel_opt(int c, char *str)
115
{
116
  switch(c) {
117
  case 'p':
118
    if(!sscanf(str, "%x", &base)) {
119
      fprintf(stderr, "p parameter must have a hex number as parameter\n");
120
      return APP_ERR_BAD_PARAM;
121
    }
122
    break;
123
  default:
124
    fprintf(stderr, "Unknown parameter '%c'\n", c);
125
    return APP_ERR_BAD_PARAM;
126
  }
127
  return APP_ERR_NONE;
128
}
129
 
130
/*-----------------------------------------[ Physical board wait function ]---*/
131 55 nyawn
 
132
/* Multiple users have reported poor performance of parallel cables,
133
 * which has been traced to various sleep functions sleeping much longer than
134
 * microseconds.  The same users have reported error-free functionality
135
 * and an order of magnitude improvement in upload speed.
136
 * Other users have reported errors when running without a wait.
137
 * Impact apparently limits the frequency of parallel JTAG cables
138
 * to 200 kHz, and some clones fail at higher speeds.
139
 */
140
 
141
 
142
 
143
#ifdef __PARALLEL_SLEEP_WAIT__
144 21 nyawn
void cable_parallel_phys_wait()
145
{
146 55 nyawn
  struct timespec ts;
147
  ts.tv_sec = 0;
148
  ts.tv_nsec = 2500;
149
  nanosleep(&ts, NULL);
150 21 nyawn
}
151 55 nyawn
#else
152 21 nyawn
 
153 55 nyawn
 #ifdef __PARALLEL_TIMER_BUSY_WAIT__
154
 
155
  #ifndef PARALLEL_USE_PROCESS_TIMER
156
 
157
/* Helper function needed if process timer isn't implemented */
158
/* do x-y */
159
int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
160
{
161
  /* Perform the carry for the later subtraction by updating y. */
162
  if (x->tv_usec < y->tv_usec) {
163
    int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
164
    y->tv_usec -= 1000000 * nsec;
165
    y->tv_sec += nsec;
166
  }
167
  if (x->tv_usec - y->tv_usec > 1000000) {
168
    int nsec = (x->tv_usec - y->tv_usec) / 1000000;
169
    y->tv_usec += 1000000 * nsec;
170
    y->tv_sec -= nsec;
171
  }
172
 
173
  /* Compute the time remaining to wait.
174
     tv_usec is certainly positive. */
175
  result->tv_sec = x->tv_sec - y->tv_sec;
176
  result->tv_usec = x->tv_usec - y->tv_usec;
177
 
178
  /* Return 1 if result is negative. */
179
  return x->tv_sec < y->tv_sec;
180
}
181
  #endif
182
 
183
 
184
void cable_parallel_phys_wait()
185
{
186
  /* This busy wait attempts to make the frequency exactly 200kHz,
187
   * including the processing time between ticks.
188
   * This means a period of 5us, or half a period of 2.5us.
189
   */
190
  #ifdef PARALLEL_USE_PROCESS_TIMER
191
  struct timespec ts;
192
  do
193
    {
194
      clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
195
    } while((ts.tv_sec == 0) && (ts.tv_nsec < 2500));
196
 
197
  /* Doing the set after the check means that processing time
198
   * is not added to the wait. */
199
  ts.tv_sec = 0;
200
  ts.tv_nsec = 0;
201
  clock_settime(CLOCK_PROCESS_CPUTIME_ID, &ts);
202
  #else
203
  struct timeval now_tv;
204
  struct timeval results_tv;
205
  do
206
    {
207
      gettimeofday(&now_tv, NULL);
208
      timeval_subtract (&results_tv, &now_tv, &last_tv);
209
    } while((results_tv.tv_sec == 0) && (results_tv.tv_usec < 3));
210
  last_tv = now_tv;
211
  #endif
212
}
213
 
214
 #else  // NO WAIT
215
 
216
void cable_parallel_phys_wait()
217
{
218
  // No wait, run max speed
219
}
220
 
221
 #endif
222
#endif
223
 
224
 
225 21 nyawn
/*----------------------------------------------[ xpc3 specific functions ]---*/
226 55 nyawn
jtag_cable_t *cable_xpc3_get_driver(void)
227
{
228
  return &xpc3_cable_driver;
229
}
230
 
231 21 nyawn
int cable_xpc3_out(uint8_t value)
232
{
233
  uint8_t out = 0;
234
 
235 55 nyawn
  cable_parallel_phys_wait();  // Limit the max clock rate if necessary
236
 
237 21 nyawn
  /* First convert the bits in value byte to the ones that the cable wants */
238
  if(value & TCLK_BIT)
239
    out |= 0x02; /* D1 pin 3 */
240
  if(value & TRST_BIT)
241
    out |= 0x10; /* Not used */
242
  if(value & TDI_BIT)
243
    out |= 0x01; /* D0 pin 2 */
244
  if(value & TMS_BIT)
245
    out |= 0x04; /* D2 pin 4 */
246
 
247
  return cable_parallel_out(out);
248
}
249
 
250
int cable_xpc3_inout(uint8_t value, uint8_t *inval)
251
{
252
  uint8_t in;
253
  int retval;
254
  uint8_t out = 0;
255
 
256 55 nyawn
  cable_parallel_phys_wait();  // Limit the max clock rate if necessary
257
 
258 21 nyawn
  /* First convert the bits in value byte to the ones that the cable wants */
259
  if(value & TCLK_BIT)
260
    out |= 0x02; /* D1 pin 3 */
261
  if(value & TRST_BIT)
262
    out |= 0x10; /* Not used */
263
  if(value & TDI_BIT)
264
    out |= 0x01; /* D0 pin 2 */
265
  if(value & TMS_BIT)
266
    out |= 0x04; /* D2 pin 4 */
267
 
268
  retval = cable_parallel_inout(out, &in);
269
 
270
  if(in & 0x10) /* S6 pin 13 */
271
    *inval = 1;
272
  else
273
    *inval = 0;
274
 
275
  return retval;
276
}
277
 
278
/*----------------------------------------------[ xess specific functions ]---*/
279 55 nyawn
jtag_cable_t *cable_xess_get_driver(void)
280
{
281
  return &xess_cable_driver;
282
}
283
 
284 21 nyawn
int cable_xess_out(uint8_t value)
285
{
286
  uint8_t out = 0;
287
 
288 55 nyawn
  cable_parallel_phys_wait();  // Limit the max clock rate if necessary
289
 
290 21 nyawn
  /* First convert the bits in value byte to the ones that the cable wants */
291
  if(value & TCLK_BIT)
292
    out |= 0x04; /* D2 pin 4 */
293
  if(value & TRST_BIT)
294
    out |= 0x08; /* D3 pin 5 */
295
  if(value & TDI_BIT)
296
    out |= 0x10; /* D4 pin 6 */
297
  if(value & TMS_BIT)
298
    out |= 0x20; /* D3 pin 5 */
299
 
300
  return cable_parallel_out(out);
301
}
302
 
303 55 nyawn
int cable_xess_inout(uint8_t value, uint8_t *inval)
304 21 nyawn
{
305
  uint8_t in;
306
  int retval;
307 22 nyawn
  uint8_t out = 0;
308 21 nyawn
 
309 55 nyawn
  cable_parallel_phys_wait();  // Limit the max clock rate if necessary
310
 
311 22 nyawn
  /* First convert the bits in value byte to the ones that the cable wants */
312
  if(value & TCLK_BIT)
313
    out |= 0x04; /* D2 pin 4 */
314
  if(value & TRST_BIT)
315
    out |= 0x08; /* D3 pin 5 */
316
  if(value & TDI_BIT)
317
    out |= 0x10; /* D4 pin 6 */
318
  if(value & TMS_BIT)
319
    out |= 0x20; /* D3 pin 5 */
320 21 nyawn
 
321 22 nyawn
  retval = cable_parallel_inout(out, &in);
322
 
323 21 nyawn
  if(in & 0x20) /* S5 pin 12*/
324
    *inval = 1;
325
  else
326
    *inval = 0;
327
 
328
  return retval;
329
}
330
 
331
 
332
/*----------------------------------------------[ common helper functions ]---*/
333
// 'static' for internal access only
334
 
335
static int cable_parallel_out(uint8_t value)
336
{
337
  outb(value, LPT_WRITE);
338
  return APP_ERR_NONE;
339
}
340
 
341
static int cable_parallel_inout(uint8_t value, uint8_t *inval)
342
{
343
  *inval = inb(LPT_READ);
344
  outb(value, LPT_WRITE);
345
 
346
  return APP_ERR_NONE;
347
}

powered by: WebSVN 2.1.0

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