OpenOCD
parport.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2005 by Dominic Rath *
5  * Dominic.Rath@gmx.de *
6  * *
7  * Copyright (C) 2008 by Spencer Oliver *
8  * spen@spen-soft.co.uk *
9  ***************************************************************************/
10 
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14 
15 #include <jtag/adapter.h>
16 #include <jtag/interface.h>
17 #include "bitbang.h"
18 
19 /* -ino: 060521-1036 */
20 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
21 #include <machine/sysarch.h>
22 #include <machine/cpufunc.h>
23 #define ioperm(startport, length, enable)\
24  i386_set_ioperm((startport), (length), (enable))
25 #endif /* __FreeBSD__ */
26 
27 #if PARPORT_USE_PPDEV == 1
28 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
29 #include <dev/ppbus/ppi.h>
30 #include <dev/ppbus/ppbconf.h>
31 #define PPRSTATUS PPIGSTATUS
32 #define PPWDATA PPISDATA
33 #else
34 #include <linux/parport.h>
35 #include <linux/ppdev.h>
36 #endif
37 #include <sys/ioctl.h>
38 #else /* not PARPORT_USE_PPDEV */
39 #ifndef _WIN32
40 #include <sys/io.h>
41 #endif
42 #endif
43 
44 #if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
45 #include <windows.h>
46 #endif
47 
48 // Parallel port cable description.
49 struct cable {
50  const char *name;
51  // Status port bit containing current TDO value.
52  uint8_t tdo_mask;
53  // Data port bit for TRST.
54  uint8_t trst_mask;
55  // Data port bit for TMD.
56  uint8_t tms_mask;
57  // Data port bit for TCK.
58  uint8_t tck_mask;
59  // Data port bit for TDI.
60  uint8_t tdi_mask;
61  // Data port bit for SRST.
62  uint8_t srst_mask;
63  // Data port bits that should be inverted.
64  uint8_t output_invert;
65  // Status port that should be inverted.
66  uint8_t input_invert;
67  // Initialize data port with this value.
68  uint8_t port_init;
69  // De-initialize data port with this value.
70  uint8_t port_exit;
71  // Data port bit for LED.
72  uint8_t led_mask;
73 };
74 
75 static const struct cable cables[] = {
76  /* name tdo trst tms tck tdi srst o_inv i_inv init exit led */
77  { "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 },
78  { "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 },
79  { "wiggler_ntrst_inverted", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
80  { "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
81  { "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 },
82  { "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
83  { "dlc5", 0x10, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00 },
84  { "triton", 0x80, 0x08, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
85  { "lattice", 0x40, 0x10, 0x04, 0x02, 0x01, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00 },
86  { "flashlink", 0x20, 0x10, 0x02, 0x01, 0x04, 0x20, 0x30, 0x20, 0x00, 0x00, 0x00 },
87 /* Altium Universal JTAG cable. Set the cable to Xilinx Mode and wire to target as follows:
88  HARD TCK - Target TCK
89  HARD TMS - Target TMS
90  HARD TDI - Target TDI
91  HARD TDO - Target TDO
92  SOFT TCK - Target TRST
93  SOFT TDI - Target SRST
94 */
95  { "altium", 0x10, 0x20, 0x04, 0x02, 0x01, 0x80, 0x00, 0x00, 0x10, 0x00, 0x08 },
96  { "aspo", 0x10, 0x01, 0x04, 0x08, 0x02, 0x10, 0x17, 0x00, 0x17, 0x17, 0x00 },
97  { NULL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
98 };
99 
100 // Configuration variables.
101 static char *parport_cable;
102 static uint16_t parport_port;
103 static bool parport_exit;
104 static uint32_t parport_toggling_time_ns = 1000;
105 static int wait_states;
106 
107 // Interface variables.
108 static const struct cable *cable;
109 static uint8_t dataport_value;
110 
111 #if PARPORT_USE_PPDEV == 1
112 static int device_handle;
113 #else
114 static unsigned long dataport;
115 static unsigned long statusport;
116 #endif
117 
119 {
120  int data = 0;
121 
122 #if PARPORT_USE_PPDEV == 1
123  ioctl(device_handle, PPRSTATUS, &data);
124 #else
125  data = inb(statusport);
126 #endif
127 
128  if ((data ^ cable->input_invert) & cable->tdo_mask)
129  return BB_HIGH;
130  else
131  return BB_LOW;
132 }
133 
134 static inline void parport_write_data(void)
135 {
136  uint8_t output;
138 
139 #if PARPORT_USE_PPDEV == 1
140  ioctl(device_handle, PPWDATA, &output);
141 #else
142 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
143  outb(dataport, output);
144 #else
145  outb(output, dataport);
146 #endif
147 #endif
148 }
149 
150 static int parport_write(int tck, int tms, int tdi)
151 {
152  int i = wait_states + 1;
153 
154  if (tck)
156  else
158 
159  if (tms)
161  else
163 
164  if (tdi)
166  else
168 
169  while (i-- > 0)
171 
172  return ERROR_OK;
173 }
174 
175 // (1) assert or (0) deassert reset lines.
176 static int parport_reset(int trst, int srst)
177 {
178  LOG_DEBUG("trst: %i, srst: %i", trst, srst);
179 
180  if (trst == 0)
182  else if (trst == 1)
184 
185  if (srst == 0)
187  else if (srst == 1)
189 
191 
192  return ERROR_OK;
193 }
194 
195 static int parport_led(bool on)
196 {
197  if (on)
199  else
201 
203 
204  return ERROR_OK;
205 }
206 
207 static int parport_speed(int speed)
208 {
209  wait_states = speed;
210  return ERROR_OK;
211 }
212 
213 static int parport_khz(int khz, int *jtag_speed)
214 {
215  if (!khz) {
216  LOG_DEBUG("RCLK not supported");
217  return ERROR_FAIL;
218  }
219 
220  *jtag_speed = 499999 / (khz * parport_toggling_time_ns);
221  return ERROR_OK;
222 }
223 
224 static int parport_speed_div(int speed, int *khz)
225 {
226  uint32_t denominator = (speed + 1) * parport_toggling_time_ns;
227 
228  *khz = (499999 + denominator) / denominator;
229  return ERROR_OK;
230 }
231 
232 #if PARPORT_USE_GIVEIO == 1
233 static int parport_get_giveio_access(void)
234 {
235  HANDLE h;
236  OSVERSIONINFO version;
237 
238  version.dwOSVersionInfoSize = sizeof(version);
239  if (!GetVersionEx(&version)) {
240  errno = EINVAL;
241  return -1;
242  }
243  if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
244  return 0;
245 
246  h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
247  if (h == INVALID_HANDLE_VALUE) {
248  errno = ENODEV;
249  return -1;
250  }
251 
252  CloseHandle(h);
253 
254  return 0;
255 }
256 #endif
257 
258 static struct bitbang_interface parport_bitbang = {
259  .read = &parport_read,
260  .write = &parport_write,
261  .blink = &parport_led,
262 };
263 
264 static int parport_init(void)
265 {
266  const struct cable *cur_cable;
267 #if PARPORT_USE_PPDEV == 1
268  char buffer[256];
269 #endif
270 
271  cur_cable = cables;
272 
273  if (!parport_cable) {
274  parport_cable = strdup("wiggler");
275  LOG_WARNING("No parport cable specified, using default 'wiggler'");
276  }
277 
278  while (cur_cable->name) {
279  if (!strcmp(cur_cable->name, parport_cable)) {
280  cable = cur_cable;
281  break;
282  }
283  cur_cable++;
284  }
285 
286  if (!cable) {
287  LOG_ERROR("No matching cable found for %s", parport_cable);
288  return ERROR_JTAG_INIT_FAILED;
289  }
290 
292 
293 #if PARPORT_USE_PPDEV == 1
294  if (device_handle > 0) {
295  LOG_ERROR("device is already opened");
296  return ERROR_JTAG_INIT_FAILED;
297  }
298 
299 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
300  LOG_DEBUG("opening /dev/ppi%d...", parport_port);
301 
302  snprintf(buffer, 256, "/dev/ppi%d", parport_port);
303  device_handle = open(buffer, O_WRONLY);
304 #else /* not __FreeBSD__, __FreeBSD_kernel__ */
305  LOG_DEBUG("opening /dev/parport%d...", parport_port);
306 
307  snprintf(buffer, 256, "/dev/parport%d", parport_port);
308  device_handle = open(buffer, O_WRONLY);
309 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
310 
311  if (device_handle < 0) {
312  int err = errno;
313  LOG_ERROR("cannot open device. check it exists and that user read and write rights are set. errno=%d", err);
314  return ERROR_JTAG_INIT_FAILED;
315  }
316 
317  LOG_DEBUG("...open");
318 
319 #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
320  int i = ioctl(device_handle, PPCLAIM);
321 
322  if (i < 0) {
323  LOG_ERROR("cannot claim device");
324  return ERROR_JTAG_INIT_FAILED;
325  }
326 
327  i = PARPORT_MODE_COMPAT;
328  i = ioctl(device_handle, PPSETMODE, &i);
329  if (i < 0) {
330  LOG_ERROR(" cannot set compatible mode to device");
331  return ERROR_JTAG_INIT_FAILED;
332  }
333 
334  i = IEEE1284_MODE_COMPAT;
335  i = ioctl(device_handle, PPNEGOT, &i);
336  if (i < 0) {
337  LOG_ERROR("cannot set compatible 1284 mode to device");
338  return ERROR_JTAG_INIT_FAILED;
339  }
340 #endif /* not __FreeBSD__, __FreeBSD_kernel__ */
341 
342 #else /* not PARPORT_USE_PPDEV */
343  if (!parport_port) {
344  parport_port = 0x378;
345  LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
346  }
347 
349  statusport = parport_port + 1;
350 
351  LOG_DEBUG("requesting privileges for parallel port 0x%lx...", dataport);
352 #if PARPORT_USE_GIVEIO == 1
353  if (parport_get_giveio_access() != 0) {
354 #else /* PARPORT_USE_GIVEIO */
355  if (ioperm(dataport, 3, 1) != 0) {
356 #endif /* PARPORT_USE_GIVEIO */
357  LOG_ERROR("missing privileges for direct i/o");
358  return ERROR_JTAG_INIT_FAILED;
359  }
360  LOG_DEBUG("...privileges granted");
361 
362  // Make sure parallel port is in right mode (clear tristate and interrupt.
363  #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
364  outb(parport_port + 2, 0x0);
365  #else
366  outb(0x0, parport_port + 2);
367  #endif
368 
369 #endif /* PARPORT_USE_PPDEV */
370 
371  if (parport_reset(0, 0) != ERROR_OK)
372  return ERROR_FAIL;
373  if (parport_write(0, 0, 0) != ERROR_OK)
374  return ERROR_FAIL;
375  if (parport_led(true) != ERROR_OK)
376  return ERROR_FAIL;
377 
379 
380  return ERROR_OK;
381 }
382 
383 static int parport_quit(void)
384 {
385  if (parport_led(false) != ERROR_OK)
386  return ERROR_FAIL;
387 
388  if (parport_exit) {
391  }
392 
393  free(parport_cable);
395 
396  return ERROR_OK;
397 }
398 
399 COMMAND_HANDLER(parport_handle_port_command)
400 {
401  if (CMD_ARGC == 1) {
402  // Only if the port wasn't overwritten by cmdline.
403  if (!parport_port) {
405  } else {
406  LOG_ERROR("The parport port was already configured!");
407  return ERROR_FAIL;
408  }
409  }
410 
411  command_print(CMD, "parport port = 0x%" PRIx16 "", parport_port);
412 
413  return ERROR_OK;
414 }
415 
416 COMMAND_HANDLER(parport_handle_cable_command)
417 {
418  if (!CMD_ARGC)
419  return ERROR_OK;
420 
421  // Only if the cable name wasn't overwritten by cmdline.
422  if (!parport_cable) {
423  // TODO: REVISIT first verify that it's listed in cables[].
424  parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
425  if (!parport_cable) {
426  LOG_ERROR("Out of memory");
427  return ERROR_FAIL;
428  }
429  strcpy(parport_cable, CMD_ARGV[0]);
430  }
431 
432  // TODO: REVISIT it's probably worth returning the current value.
433 
434  return ERROR_OK;
435 }
436 
437 COMMAND_HANDLER(parport_handle_write_on_exit_command)
438 {
439  if (CMD_ARGC != 1)
441 
443 
444  return ERROR_OK;
445 }
446 
447 COMMAND_HANDLER(parport_handle_toggling_time_command)
448 {
449  if (CMD_ARGC == 1) {
450  uint32_t ns;
451  int retval = parse_u32(CMD_ARGV[0], &ns);
452 
453  if (retval != ERROR_OK)
454  return retval;
455 
456  if (!ns) {
457  LOG_ERROR("0 ns is not a valid parport toggling time");
458  return ERROR_FAIL;
459  }
460 
462  retval = adapter_get_speed(&wait_states);
463  if (retval != ERROR_OK) {
464  /*
465  * If adapter_get_speed fails then the clock_mode has
466  * not been configured, this happens if toggling_time is
467  * called before the adapter speed is set.
468  */
469  LOG_INFO("no parport speed set - defaulting to zero wait states");
470  wait_states = 0;
471  }
472  }
473 
474  command_print(CMD, "parport toggling time = %" PRIu32 " ns",
476 
477  return ERROR_OK;
478 }
479 
480 static const struct command_registration parport_subcommand_handlers[] = {
481  {
482  .name = "port",
483  .handler = parport_handle_port_command,
484  .mode = COMMAND_CONFIG,
485  .help = "Display the address of the I/O port (e.g. 0x378) "
486  "or the number of the '/dev/parport' device used. "
487  "If a parameter is provided, first change that port.",
488  .usage = "[port_number]",
489  },
490  {
491  .name = "cable",
492  .handler = parport_handle_cable_command,
493  .mode = COMMAND_CONFIG,
494  .help = "Set the layout of the parallel port cable "
495  "used to connect to the target.",
496  // TODO: REVISIT there's no way to list layouts we know.
497  .usage = "[layout]",
498  },
499  {
500  .name = "write_on_exit",
501  .handler = parport_handle_write_on_exit_command,
502  .mode = COMMAND_CONFIG,
503  .help = "Configure the parallel driver to write "
504  "a known value to the parallel interface on exit.",
505  .usage = "('on'|'off')",
506  },
507  {
508  .name = "toggling_time",
509  .handler = parport_handle_toggling_time_command,
510  .mode = COMMAND_CONFIG,
511  .help = "Displays or assigns how many nanoseconds it "
512  "takes for the hardware to toggle TCK.",
513  .usage = "[nanoseconds]",
514  },
516 };
517 
518 static const struct command_registration parport_command_handlers[] = {
519  {
520  .name = "parport",
521  .mode = COMMAND_ANY,
522  .help = "perform parport management",
524  .usage = "",
525  },
527 };
528 
529 static struct jtag_interface parport_interface = {
531  .execute_queue = bitbang_execute_queue,
532 };
533 
535  .name = "parport",
536  .transports = jtag_only,
537  .commands = parport_command_handlers,
538 
539  .init = parport_init,
540  .quit = parport_quit,
541  .reset = parport_reset,
542  .speed = parport_speed,
543  .khz = parport_khz,
544  .speed_div = parport_speed_div,
545 
546  .jtag_ops = &parport_interface,
547 };
const char *const jtag_only[]
Definition: adapter.c:27
int adapter_get_speed(int *speed)
Definition: adapter.c:267
int bitbang_execute_queue(struct jtag_command *cmd_queue)
Definition: bitbang.c:293
bb_value_t
Definition: bitbang.h:17
@ BB_LOW
Definition: bitbang.h:18
@ BB_HIGH
Definition: bitbang.h:19
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:141
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define COMMAND_PARSE_ON_OFF(in, out)
parses an on/off command argument
Definition: command.h:530
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:442
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
static uint16_t output
Definition: ftdi.c:119
#define DEBUG_CAP_TMS_SEQ
Definition: interface.h:187
#define ERROR_JTAG_INIT_FAILED
Definition: jtag.h:553
#define LOG_WARNING(expr ...)
Definition: log.h:129
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
static int parport_reset(int trst, int srst)
Definition: parport.c:176
static const struct cable * cable
Definition: parport.c:108
static int parport_speed(int speed)
Definition: parport.c:207
static int wait_states
Definition: parport.c:105
static const struct command_registration parport_command_handlers[]
Definition: parport.c:518
static uint32_t parport_toggling_time_ns
Definition: parport.c:104
static int parport_write(int tck, int tms, int tdi)
Definition: parport.c:150
static const struct cable cables[]
Definition: parport.c:75
static unsigned long dataport
Definition: parport.c:114
static bb_value_t parport_read(void)
Definition: parport.c:118
static uint16_t parport_port
Definition: parport.c:102
static int parport_quit(void)
Definition: parport.c:383
static void parport_write_data(void)
Definition: parport.c:134
static struct jtag_interface parport_interface
Definition: parport.c:529
static struct bitbang_interface parport_bitbang
Definition: parport.c:258
static char * parport_cable
Definition: parport.c:101
static int parport_speed_div(int speed, int *khz)
Definition: parport.c:224
static const struct command_registration parport_subcommand_handlers[]
Definition: parport.c:480
static unsigned long statusport
Definition: parport.c:115
static int parport_khz(int khz, int *jtag_speed)
Definition: parport.c:213
static uint8_t dataport_value
Definition: parport.c:109
static int parport_init(void)
Definition: parport.c:264
static bool parport_exit
Definition: parport.c:103
COMMAND_HANDLER(parport_handle_port_command)
Definition: parport.c:399
struct adapter_driver parport_adapter_driver
Definition: parport.c:534
static int parport_led(bool on)
Definition: parport.c:195
Represents a driver for a debugging interface.
Definition: interface.h:207
const char *const name
The name of the interface driver.
Definition: interface.h:209
Low level callbacks (for bitbang).
Definition: bitbang.h:30
bb_value_t(* read)(void)
Sample TDO and return the value.
Definition: bitbang.h:32
Definition: parport.c:49
uint8_t trst_mask
Definition: parport.c:54
uint8_t srst_mask
Definition: parport.c:62
uint8_t input_invert
Definition: parport.c:66
uint8_t port_exit
Definition: parport.c:70
uint8_t tms_mask
Definition: parport.c:56
uint8_t led_mask
Definition: parport.c:72
uint8_t output_invert
Definition: parport.c:64
uint8_t tck_mask
Definition: parport.c:58
uint8_t tdo_mask
Definition: parport.c:52
uint8_t tdi_mask
Definition: parport.c:60
uint8_t port_init
Definition: parport.c:68
const char * name
Definition: parport.c:50
const char * name
Definition: command.h:235
const char * usage
a string listing the options and arguments, required or optional
Definition: command.h:241
Represents a driver for a debugging interface.
Definition: interface.h:182
unsigned int supported
Bit vector listing capabilities exposed by this driver.
Definition: interface.h:186
#define NULL
Definition: usb.h:16