view rvinterf/tmsh/tmcore.c @ 992:a7b0b426f9ca

target-utils: boot ROM UART autodetection revamped The new implementation should work with both the familiar Calypso C035 boot ROM version found in our regular targets as well as the older Calypso F741979B version found on the vintage D-Sample board.
author Mychaela Falconia <falcon@ivan.Harhan.ORG>
date Wed, 30 Dec 2015 21:28:41 +0000
parents c146f38d2b5f
children
line wrap: on
line source

/*
 * In this module we are going to implement commands which send requests
 * to ETM_CORE and the handling of responses from that target module.
 */

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "pktmux.h"
#include "limits.h"
#include "localtypes.h"
#include "etm.h"

extern u_char rvi_msg[];
extern int rvi_msg_len;

static void
rw8_response()
{
	char buf[MAX_PKT_FROM_TARGET*3+80], *dp;
	int num, i;

	if (rvi_msg[3]) {
		print_etm_pkt_raw("rw8 error");
		return;
	}
	num = rvi_msg_len - 7;
	if (!num) {
		async_msg_output("w8 OK");
		return;
	}
	strcpy(buf, "r8:");
	dp = buf + 3;
	for (i = 0; i < num; i++) {
		sprintf(dp, " %02X", rvi_msg[i+6]);
		dp += 3;
	}
	async_msg_output(buf);
}

static void
rw16_response()
{
	char buf[MAX_PKT_FROM_TARGET*3+80], *dp;
	int num, i, d, off;

	if (rvi_msg[3]) {
		print_etm_pkt_raw("rw16 error");
		return;
	}
	num = rvi_msg_len - 7;
	if (!num) {
		async_msg_output("w16 OK");
		return;
	}
	if (num & 1) {
		print_etm_pkt_raw("rw16 malformed resp");
		return;
	}
	num >>= 1;
	strcpy(buf, "r16:");
	dp = buf + 4;
	off = 6;
	for (i = 0; i < num; i++) {
		d = rvi_msg[off] | rvi_msg[off+1] << 8;
		off += 2;
		sprintf(dp, " %04X", d);
		dp += 5;
	}
	async_msg_output(buf);
}

static void
rw32_response()
{
	char buf[MAX_PKT_FROM_TARGET*3+80], *dp;
	int num, i, d, off;

	if (rvi_msg[3]) {
		print_etm_pkt_raw("rw32 error");
		return;
	}
	num = rvi_msg_len - 7;
	if (!num) {
		async_msg_output("w32 OK");
		return;
	}
	if (num & 3) {
		print_etm_pkt_raw("rw32 malformed resp");
		return;
	}
	num >>= 2;
	strcpy(buf, "r32:");
	dp = buf + 4;
	off = 6;
	for (i = 0; i < num; i++) {
		d = rvi_msg[off] | rvi_msg[off+1] << 8 | rvi_msg[off+2] << 16
			| rvi_msg[off+3] << 24;
		off += 4;
		sprintf(dp, " %08X", d);
		dp += 9;
	}
	async_msg_output(buf);
}

static void
dieid_response()
{
	char buf[MAX_PKT_FROM_TARGET*3+80], *dp;
	int num, i;

	if (rvi_msg[3]) {
		print_etm_pkt_raw("dieid error");
		return;
	}
	num = rvi_msg_len - 6;
	strcpy(buf, "dieid resp:");
	dp = buf + 11;
	for (i = 0; i < num; i++) {
		sprintf(dp, " %02X", rvi_msg[i+5]);
		dp += 3;
	}
	async_msg_output(buf);
}

static void
echo_response()
{
	if (rvi_msg[3])
		print_etm_pkt_raw("echo error");
	else
		print_etm_pkt_raw("echo resp");
}

static void
version_response()
{
	char buf[80];

	if (rvi_msg[3]) {
		print_etm_pkt_raw("version error");
		return;
	}
	if (rvi_msg_len != 10) {
		print_etm_pkt_raw("version malformed resp");
		return;
	}
	sprintf(buf, "version resp: %02X%02X%02X%02X", rvi_msg[8], rvi_msg[7],
		rvi_msg[6], rvi_msg[5]);
	async_msg_output(buf);
}

void
tmcore_msg_rx()
{
	switch (rvi_msg[4]) {
	case TMCORE_OPC_MEM:
		if (rvi_msg_len < 7)
			goto unknown;
		switch (rvi_msg[5]) {
		case 0x00:
		case 0x04:
			rw32_response();
			return;
		case 0x01:
			rw8_response();
			return;
		case 0x02:
			rw16_response();
			return;
		default:
			goto unknown;
		}
	case TMCORE_OPC_ECHO:
		echo_response();
		return;
	case TMCORE_OPC_VERSION:
		version_response();
		return;
	case TMCORE_OPC_CODEC_RD:
		abbr_response();
		return;
	case TMCORE_OPC_CODEC_WR:
		abbw_response();
		return;
	case TMCORE_OPC_DIEID:
		dieid_response();
		return;
	default:
	unknown:
		print_etm_pkt_raw("ETM_CORE resp");
	}
}

void
cmd_r8(argc, argv)
	char **argv;
{
	u32 addr;
	int count;
	u_char cmdpkt[10];

	addr = strtoul(argv[1], 0, 16);
	if (argv[2])
		count = strtoul(argv[2], 0, 0);
	else
		count = 1;
	if (count < 1 || count > 253) {
		printf("error: count argument outside valid range\n");
		return;
	}
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_MEM;
	cmdpkt[3] = 0x01;
	cmdpkt[4] = count;
	cmdpkt[5] = addr;
	cmdpkt[6] = addr >> 8;
	cmdpkt[7] = addr >> 16;
	cmdpkt[8] = addr >> 24;
	send_etm_cmd(cmdpkt, 8);
}

void
cmd_r16(argc, argv)
	char **argv;
{
	u32 addr;
	int count;
	u_char cmdpkt[10];

	addr = strtoul(argv[1], 0, 16);
	if (argv[2])
		count = strtoul(argv[2], 0, 0);
	else
		count = 1;
	if (addr & 1) {
		printf("error: address not aligned\n");
		return;
	}
	if (count < 1 || count > 126) {
		printf("error: count argument outside valid range\n");
		return;
	}
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_MEM;
	cmdpkt[3] = 0x02;
	cmdpkt[4] = count;
	cmdpkt[5] = addr;
	cmdpkt[6] = addr >> 8;
	cmdpkt[7] = addr >> 16;
	cmdpkt[8] = addr >> 24;
	send_etm_cmd(cmdpkt, 8);
}

void
cmd_r32(argc, argv)
	char **argv;
{
	u32 addr;
	int count;
	u_char cmdpkt[10];

	addr = strtoul(argv[1], 0, 16);
	if (argv[2])
		count = strtoul(argv[2], 0, 0);
	else
		count = 1;
	if (addr & 3) {
		printf("error: address not aligned\n");
		return;
	}
	if (count < 1 || count > 63) {
		printf("error: count argument outside valid range\n");
		return;
	}
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_MEM;
	cmdpkt[3] = 0x04;
	cmdpkt[4] = count;
	cmdpkt[5] = addr;
	cmdpkt[6] = addr >> 8;
	cmdpkt[7] = addr >> 16;
	cmdpkt[8] = addr >> 24;
	send_etm_cmd(cmdpkt, 8);
}

void
cmd_w8(argc, argv)
	char **argv;
{
	u32 addr, v;
	u_char cmdpkt[MAX_PKT_TO_TARGET];
	int di;
	char **ap;

	addr = strtoul(argv[1], 0, 16);
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_MEM;
	cmdpkt[3] = 0x11;
	cmdpkt[4] = argc - 2;
	cmdpkt[5] = addr;
	cmdpkt[6] = addr >> 8;
	cmdpkt[7] = addr >> 16;
	cmdpkt[8] = addr >> 24;
	di = 9;
	for (ap = argv + 2; *ap; ap++) {
		v = strtoul(*ap, 0, 16);
		cmdpkt[di++] = v;
	}
	send_etm_cmd(cmdpkt, di - 1);
}

void
cmd_w16(argc, argv)
	char **argv;
{
	u32 addr, v;
	u_char cmdpkt[MAX_PKT_TO_TARGET];
	int di;
	char **ap;

	addr = strtoul(argv[1], 0, 16);
	if (addr & 1) {
		printf("error: address not aligned\n");
		return;
	}
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_MEM;
	cmdpkt[3] = 0x12;
	cmdpkt[4] = argc - 2;
	cmdpkt[5] = addr;
	cmdpkt[6] = addr >> 8;
	cmdpkt[7] = addr >> 16;
	cmdpkt[8] = addr >> 24;
	di = 9;
	for (ap = argv + 2; *ap; ap++) {
		v = strtoul(*ap, 0, 16);
		cmdpkt[di++] = v;
		cmdpkt[di++] = v >> 8;
	}
	send_etm_cmd(cmdpkt, di - 1);
}

void
cmd_w32(argc, argv)
	char **argv;
{
	u32 addr, v;
	u_char cmdpkt[MAX_PKT_TO_TARGET];
	int di;
	char **ap;

	addr = strtoul(argv[1], 0, 16);
	if (addr & 3) {
		printf("error: address not aligned\n");
		return;
	}
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_MEM;
	cmdpkt[3] = 0x14;
	cmdpkt[4] = argc - 2;
	cmdpkt[5] = addr;
	cmdpkt[6] = addr >> 8;
	cmdpkt[7] = addr >> 16;
	cmdpkt[8] = addr >> 24;
	di = 9;
	for (ap = argv + 2; *ap; ap++) {
		v = strtoul(*ap, 0, 16);
		cmdpkt[di++] = v;
		cmdpkt[di++] = v >> 8;
		cmdpkt[di++] = v >> 16;
		cmdpkt[di++] = v >> 24;
	}
	send_etm_cmd(cmdpkt, di - 1);
}

void
cmd_dieid(argc, argv)
	char **argv;
{
	u_char cmdpkt[4];

	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_DIEID;
	send_etm_cmd(cmdpkt, 2);
}

void
cmd_ping(argc, argv)
	char **argv;
{
	int delay, size;
	u_char cmdpkt[8];

	if (argc > 1) {
		delay = strtoul(argv[1], 0, 0);
		if (delay > 65535) {
			printf("error: ping delay argument too big\n");
			return;
		}
	} else
		delay = 0;
	if (argc > 2) {
		size = strtoul(argv[2], 0, 0);
		if (size > 240) {
			printf("error: ping size argument too big\n");
			return;
		}
	} else
		size = 1;
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_ECHO;
	cmdpkt[3] = delay;
	cmdpkt[4] = delay >> 8;
	cmdpkt[5] = size;
	cmdpkt[6] = size >> 8;
	send_etm_cmd(cmdpkt, 6);
}

void
cmd_tgtreset(argc, argv)
	char **argv;
{
	u_char cmdpkt[4];

	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_RESET;
	send_etm_cmd(cmdpkt, 2);
}

void
cmd_version(argc, argv)
	char **argv;
{
	u32 arg;
	u_char cmdpkt[8];

	arg = strtoul(argv[1], 0, 16);
	cmdpkt[1] = ETM_CORE;
	cmdpkt[2] = TMCORE_OPC_VERSION;
	cmdpkt[3] = arg;
	cmdpkt[4] = arg >> 8;
	cmdpkt[5] = arg >> 16;
	cmdpkt[6] = arg >> 24;
	send_etm_cmd(cmdpkt, 6);
}