1 /***************************************************************************
2  *   Copyright (C) 2006 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include <jtag/interface.h>
24 #include <jtag/commands.h>
25 
26 #if 1
27 #define _DEBUG_GW16012_IO_
28 #endif
29 
30 /* system includes */
31 /*  -ino: 060521-1036 */
32 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
33 
34 #include <machine/sysarch.h>
35 #include <machine/cpufunc.h>
36 #define ioperm(startport, length, enable) \
37 	386_set_ioperm((startport), (length), (enable))
38 
39 #else
40 
41 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
42 
43 #if PARPORT_USE_PPDEV == 1
44 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
45 #include <dev/ppbus/ppi.h>
46 #include <dev/ppbus/ppbconf.h>
47 #define PPRSTATUS	PPIGSTATUS
48 #define PPWDATA		PPISDATA
49 #else
50 #include <linux/parport.h>
51 #include <linux/ppdev.h>
52 #endif
53 #include <fcntl.h>
54 #include <sys/ioctl.h>
55 #else /* not PARPORT_USE_PPDEV */
56 #ifndef _WIN32
57 #include <sys/io.h>
58 #endif
59 #endif
60 
61 #if PARPORT_USE_GIVEIO == 1 && IS_CYGWIN == 1
62 #include <windows.h>
63 #endif
64 
65 /* configuration */
66 static uint16_t gw16012_port;
67 
68 /* interface variables
69  */
70 static uint8_t gw16012_msb;
71 static uint8_t gw16012_control_value;
72 
73 #if PARPORT_USE_PPDEV == 1
74 static int device_handle;
75 #endif
76 
gw16012_data(uint8_t value)77 static void gw16012_data(uint8_t value)
78 {
79 	value = (value & 0x7f) | gw16012_msb;
80 	gw16012_msb ^= 0x80; /* toggle MSB */
81 
82 #ifdef _DEBUG_GW16012_IO_
83 	LOG_DEBUG("%2.2x", value);
84 #endif
85 
86 	#if PARPORT_USE_PPDEV == 1
87 		ioctl(device_handle, PPWDATA, &value);
88 	#else
89 		#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
90 			outb(gw16012_port, value);
91 		#else
92 			outb(value, gw16012_port);
93 		#endif
94 	#endif
95 }
96 
gw16012_control(uint8_t value)97 static void gw16012_control(uint8_t value)
98 {
99 	if (value != gw16012_control_value) {
100 		gw16012_control_value = value;
101 
102 #ifdef _DEBUG_GW16012_IO_
103 		LOG_DEBUG("%2.2x", gw16012_control_value);
104 #endif
105 
106 		#if PARPORT_USE_PPDEV == 1
107 			ioctl(device_handle, PPWCONTROL, &gw16012_control_value);
108 		#else
109 			#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
110 				outb(gw16012_port + 2, gw16012_control_value);
111 			#else
112 				outb(gw16012_control_value, gw16012_port + 2);
113 			#endif
114 		#endif
115 	}
116 }
117 
gw16012_input(uint8_t * value)118 static void gw16012_input(uint8_t *value)
119 {
120 	#if PARPORT_USE_PPDEV == 1
121 		ioctl(device_handle, PPRSTATUS, value);
122 	#else
123 		*value = inb(gw16012_port + 1);
124 	#endif
125 
126 #ifdef _DEBUG_GW16012_IO_
127 	LOG_DEBUG("%2.2x", *value);
128 #endif
129 }
130 
131 /* (1) assert or (0) deassert reset lines */
gw16012_reset(int trst,int srst)132 static void gw16012_reset(int trst, int srst)
133 {
134 	LOG_DEBUG("trst: %i, srst: %i", trst, srst);
135 
136 	if (trst == 0)
137 		gw16012_control(0x0d);
138 	else if (trst == 1)
139 		gw16012_control(0x0c);
140 
141 	if (srst == 0)
142 		gw16012_control(0x0a);
143 	else if (srst == 1)
144 		gw16012_control(0x0b);
145 }
146 
gw16012_end_state(tap_state_t state)147 static void gw16012_end_state(tap_state_t state)
148 {
149 	if (tap_is_state_stable(state))
150 		tap_set_end_state(state);
151 	else {
152 		LOG_ERROR("BUG: %i is not a valid end state", state);
153 		exit(-1);
154 	}
155 }
156 
gw16012_state_move(void)157 static void gw16012_state_move(void)
158 {
159 	int i = 0, tms = 0;
160 	uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
161 	int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
162 
163 	gw16012_control(0x0); /* single-bit mode */
164 
165 	for (i = 0; i < tms_count; i++) {
166 		tms = (tms_scan >> i) & 1;
167 		gw16012_data(tms << 1); /* output next TMS bit */
168 	}
169 
170 	tap_set_state(tap_get_end_state());
171 }
172 
gw16012_path_move(struct pathmove_command * cmd)173 static void gw16012_path_move(struct pathmove_command *cmd)
174 {
175 	int num_states = cmd->num_states;
176 	int state_count;
177 
178 	state_count = 0;
179 	while (num_states) {
180 		gw16012_control(0x0); /* single-bit mode */
181 		if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
182 			gw16012_data(0x0); /* TCK cycle with TMS low */
183 		else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
184 			gw16012_data(0x2); /* TCK cycle with TMS high */
185 		else {
186 			LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition",
187 					tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
188 			exit(-1);
189 		}
190 
191 		tap_set_state(cmd->path[state_count]);
192 		state_count++;
193 		num_states--;
194 	}
195 
196 	tap_set_end_state(tap_get_state());
197 }
198 
gw16012_runtest(int num_cycles)199 static void gw16012_runtest(int num_cycles)
200 {
201 	tap_state_t saved_end_state = tap_get_end_state();
202 	int i;
203 
204 	/* only do a state_move when we're not already in IDLE */
205 	if (tap_get_state() != TAP_IDLE) {
206 		gw16012_end_state(TAP_IDLE);
207 		gw16012_state_move();
208 	}
209 
210 	for (i = 0; i < num_cycles; i++) {
211 		gw16012_control(0x0); /* single-bit mode */
212 		gw16012_data(0x0); /* TMS cycle with TMS low */
213 	}
214 
215 	gw16012_end_state(saved_end_state);
216 	if (tap_get_state() != tap_get_end_state())
217 		gw16012_state_move();
218 }
219 
gw16012_scan(bool ir_scan,enum scan_type type,uint8_t * buffer,int scan_size)220 static void gw16012_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
221 {
222 	int bits_left = scan_size;
223 	int bit_count = 0;
224 	tap_state_t saved_end_state = tap_get_end_state();
225 	uint8_t scan_out, scan_in;
226 
227 	/* only if we're not already in the correct Shift state */
228 	if (!((!ir_scan && (tap_get_state() == TAP_DRSHIFT)) ||
229 			(ir_scan && (tap_get_state() == TAP_IRSHIFT)))) {
230 		if (ir_scan)
231 			gw16012_end_state(TAP_IRSHIFT);
232 		else
233 			gw16012_end_state(TAP_DRSHIFT);
234 
235 		gw16012_state_move();
236 		gw16012_end_state(saved_end_state);
237 	}
238 
239 	while (type == SCAN_OUT && ((bits_left - 1) > 7)) {
240 		gw16012_control(0x2); /* seven-bit mode */
241 		scan_out = buf_get_u32(buffer, bit_count, 7);
242 		gw16012_data(scan_out);
243 		bit_count += 7;
244 		bits_left -= 7;
245 	}
246 
247 	gw16012_control(0x0); /* single-bit mode */
248 	while (bits_left-- > 0) {
249 		uint8_t tms = 0;
250 
251 		scan_out = buf_get_u32(buffer, bit_count, 1);
252 
253 		if (bits_left == 0) /* last bit */ {
254 			if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT))
255 				|| (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))
256 				tms = 0;
257 			else
258 				tms = 2;
259 		}
260 
261 		gw16012_data(scan_out | tms);
262 
263 		if (type != SCAN_OUT) {
264 			gw16012_input(&scan_in);
265 			buf_set_u32(buffer, bit_count, 1, ((scan_in & 0x08) >> 3));
266 		}
267 
268 		bit_count++;
269 	}
270 
271 	if (!((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) ||
272 		(!ir_scan && (tap_get_end_state() == TAP_DRSHIFT)))) {
273 		gw16012_data(0x0);
274 		if (ir_scan)
275 			tap_set_state(TAP_IRPAUSE);
276 		else
277 			tap_set_state(TAP_DRPAUSE);
278 
279 		if (tap_get_state() != tap_get_end_state())
280 			gw16012_state_move();
281 	}
282 }
283 
gw16012_execute_queue(void)284 static int gw16012_execute_queue(void)
285 {
286 	struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
287 	int scan_size;
288 	enum scan_type type;
289 	uint8_t *buffer;
290 	int retval;
291 
292 	/* return ERROR_OK, unless a jtag_read_buffer returns a failed check
293 	 * that wasn't handled by a caller-provided error handler
294 	 */
295 	retval = ERROR_OK;
296 
297 	while (cmd) {
298 		switch (cmd->type) {
299 			case JTAG_RESET:
300 				LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
301 				if (cmd->cmd.reset->trst == 1)
302 					tap_set_state(TAP_RESET);
303 				gw16012_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
304 				break;
305 			case JTAG_RUNTEST:
306 				LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
307 						cmd->cmd.runtest->end_state);
308 				gw16012_end_state(cmd->cmd.runtest->end_state);
309 				gw16012_runtest(cmd->cmd.runtest->num_cycles);
310 				break;
311 			case JTAG_TLR_RESET:
312 				LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
313 				gw16012_end_state(cmd->cmd.statemove->end_state);
314 				gw16012_state_move();
315 				break;
316 			case JTAG_PATHMOVE:
317 				LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
318 						cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
319 				gw16012_path_move(cmd->cmd.pathmove);
320 				break;
321 			case JTAG_SCAN:
322 				gw16012_end_state(cmd->cmd.scan->end_state);
323 				scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
324 				type = jtag_scan_type(cmd->cmd.scan);
325 				LOG_DEBUG_IO("%s scan (%i) %i bit end in %i", (cmd->cmd.scan->ir_scan) ? "ir" : "dr",
326 					type, scan_size, cmd->cmd.scan->end_state);
327 				gw16012_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
328 				if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
329 					retval = ERROR_JTAG_QUEUE_FAILED;
330 				free(buffer);
331 				break;
332 			case JTAG_SLEEP:
333 				LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
334 				jtag_sleep(cmd->cmd.sleep->us);
335 				break;
336 			default:
337 				LOG_ERROR("BUG: unknown JTAG command type encountered");
338 				exit(-1);
339 		}
340 		cmd = cmd->next;
341 	}
342 
343 	return retval;
344 }
345 
346 #if PARPORT_USE_GIVEIO == 1
gw16012_get_giveio_access(void)347 static int gw16012_get_giveio_access(void)
348 {
349 	HANDLE h;
350 	OSVERSIONINFO version;
351 
352 	version.dwOSVersionInfoSize = sizeof(version);
353 	if (!GetVersionEx(&version)) {
354 		errno = EINVAL;
355 		return -1;
356 	}
357 	if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
358 		return 0;
359 
360 	h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING,
361 			FILE_ATTRIBUTE_NORMAL, NULL);
362 	if (h == INVALID_HANDLE_VALUE) {
363 		errno = ENODEV;
364 		return -1;
365 	}
366 
367 	CloseHandle(h);
368 
369 	return 0;
370 }
371 #endif
372 
373 #if PARPORT_USE_PPDEV == 1
374 
375 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
376 
377 #define GW16012_PPDEV_NAME	"ppi"
378 
gw16012_init_ioctls(void)379 static int gw16012_init_ioctls(void)
380 {
381 	int temp = 0;
382 	temp = ioctl(device_handle, PPCLAIM);
383 	if (temp < 0) {
384 		LOG_ERROR("cannot claim device");
385 		return ERROR_JTAG_INIT_FAILED;
386 	}
387 
388 	temp = PARPORT_MODE_COMPAT;
389 	temp = ioctl(device_handle, PPSETMODE, &temp);
390 	if (temp < 0) {
391 		LOG_ERROR(" cannot set compatible mode to device");
392 		return ERROR_JTAG_INIT_FAILED;
393 	}
394 
395 	temp = IEEE1284_MODE_COMPAT;
396 	temp = ioctl(device_handle, PPNEGOT, &temp);
397 	if (temp < 0) {
398 		LOG_ERROR("cannot set compatible 1284 mode to device");
399 		return ERROR_JTAG_INIT_FAILED;
400 	}
401 	return ERROR_OK;
402 }
403 #else
404 
405 #define GW16012_PPDEV_NAME	"parport"
406 
gw16012_init_ioctls(void)407 static int gw16012_init_ioctls(void)
408 {
409 	return ERROR_OK;
410 }
411 
412 #endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
413 
gw16012_init_device(void)414 static int gw16012_init_device(void)
415 {
416 	const char *device_name = GW16012_PPDEV_NAME;
417 	char buffer[256];
418 
419 	if (device_handle > 0) {
420 		LOG_ERROR("device is already opened");
421 		return ERROR_JTAG_INIT_FAILED;
422 	}
423 
424 	snprintf(buffer, 256, "/dev/%s%d", device_name, gw16012_port);
425 	LOG_DEBUG("opening %s...", buffer);
426 
427 	device_handle = open(buffer, O_WRONLY);
428 	if (device_handle < 0) {
429 		LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
430 		return ERROR_JTAG_INIT_FAILED;
431 	}
432 
433 	LOG_DEBUG("...open");
434 
435 	if (gw16012_init_ioctls() != ERROR_OK)
436 		return ERROR_JTAG_INIT_FAILED;
437 
438 	return ERROR_OK;
439 }
440 
441 #else /* PARPORT_USE_PPDEV */
442 
gw16012_init_device(void)443 static int gw16012_init_device(void)
444 {
445 	if (gw16012_port == 0) {
446 		gw16012_port = 0x378;
447 		LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
448 	}
449 
450 	LOG_DEBUG("requesting privileges for parallel port 0x%" PRIx16 "...", gw16012_port);
451 #if PARPORT_USE_GIVEIO == 1
452 	if (gw16012_get_giveio_access() != 0) {
453 #else /* PARPORT_USE_GIVEIO */
454 	if (ioperm(gw16012_port, 3, 1) != 0) {
455 #endif /* PARPORT_USE_GIVEIO */
456 		LOG_ERROR("missing privileges for direct i/o");
457 		return ERROR_JTAG_INIT_FAILED;
458 	}
459 	LOG_DEBUG("...privileges granted");
460 
461 	/* make sure parallel port is in right mode (clear tristate and interrupt */
462 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
463 	outb(gw16012_port + 2, 0x0);
464 #else
465 	outb(0x0, gw16012_port + 2);
466 #endif
467 	return ERROR_OK;
468 }
469 
470 #endif /* PARPORT_USE_PPDEV */
471 
472 static int gw16012_init(void)
473 {
474 	uint8_t status_port;
475 
476 	if (gw16012_init_device() != ERROR_OK)
477 		return ERROR_JTAG_INIT_FAILED;
478 
479 	gw16012_input(&status_port);
480 	gw16012_msb = (status_port & 0x80) ^ 0x80;
481 
482 	gw16012_reset(0, 0);
483 
484 	return ERROR_OK;
485 }
486 
487 static int gw16012_quit(void)
488 {
489 
490 	return ERROR_OK;
491 }
492 
493 COMMAND_HANDLER(gw16012_handle_parport_port_command)
494 {
495 	if (CMD_ARGC == 1) {
496 		/* only if the port wasn't overwritten by cmdline */
497 		if (gw16012_port == 0)
498 			COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], gw16012_port);
499 		else {
500 			LOG_ERROR("The parport port was already configured!");
501 			return ERROR_FAIL;
502 		}
503 	}
504 
505 	command_print(CMD, "parport port = %u", gw16012_port);
506 
507 	return ERROR_OK;
508 }
509 
510 static const struct command_registration gw16012_command_handlers[] = {
511 	{
512 		.name = "parport_port",
513 		.handler = gw16012_handle_parport_port_command,
514 		.mode = COMMAND_CONFIG,
515 		.help = "Display the address of the I/O port (e.g. 0x378) "
516 			"or the number of the '/dev/parport' device used.  "
517 			"If a parameter is provided, first change that port.",
518 		.usage = "[port_number]",
519 	},
520 	COMMAND_REGISTRATION_DONE
521 };
522 
523 static struct jtag_interface gw16012_interface = {
524 	.execute_queue = gw16012_execute_queue,
525 };
526 
527 struct adapter_driver gw16012_adapter_driver = {
528 	.name = "gw16012",
529 	.transports = jtag_only,
530 	.commands = gw16012_command_handlers,
531 
532 	.init = gw16012_init,
533 	.quit = gw16012_quit,
534 
535 	.jtag_ops = &gw16012_interface,
536 };
537