FreeCalypso > hg > freecalypso-sw
view rvinterf/tmsh/tmcore.c @ 923:10b4bed10192
gsm-fw/L1: fix for the DSP patch corruption bug
The L1 code we got from the LoCosto fw contains a feature for DSP CPU load
measurement. This feature is a LoCosto-ism, i.e., not applicable to earlier
DBB chips (Calypso) with their respective earlier DSP ROMs. Most of the
code dealing with that feature is conditionalized as #if (DSP >= 38),
but one spot was missed, and the MCU code was writing into an API word
dealing with this feature. In TCS211 this DSP API word happens to be
used by the DSP code patch, hence that write was corrupting the patched
DSP code.
author | Mychaela Falconia <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 19 Oct 2015 17:13:56 +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); }