You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

311 lines
8.3 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2007 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  5. * Copyright (C) 2007,2008 Øyvind Harboe *
  6. * oyvind.harboe@zylin.com *
  7. * *
  8. * Copyright (C) 2008 by Spencer Oliver *
  9. * spen@spen-soft.co.uk *
  10. * *
  11. * This program is free software; you can redistribute it and/or modify *
  12. * it under the terms of the GNU General Public License as published by *
  13. * the Free Software Foundation; either version 2 of the License, or *
  14. * (at your option) any later version. *
  15. * *
  16. * This program is distributed in the hope that it will be useful, *
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  19. * GNU General Public License for more details. *
  20. * *
  21. * You should have received a copy of the GNU General Public License *
  22. * along with this program; if not, write to the *
  23. * Free Software Foundation, Inc., *
  24. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  25. ***************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #endif
  29. #include <helper/log.h>
  30. #include <helper/binarybuffer.h>
  31. #include "target.h"
  32. #include "target_request.h"
  33. #include "target_type.h"
  34. #include "trace.h"
  35. static bool got_message;
  36. bool target_got_message(void)
  37. {
  38. bool t = got_message;
  39. got_message = false;
  40. return t;
  41. }
  42. static int charmsg_mode;
  43. static int target_asciimsg(struct target *target, uint32_t length)
  44. {
  45. char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4);
  46. struct debug_msg_receiver *c = target->dbgmsg;
  47. target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t *)msg);
  48. msg[length] = 0;
  49. LOG_DEBUG("%s", msg);
  50. while (c) {
  51. command_print(c->cmd_ctx, "%s", msg);
  52. c = c->next;
  53. }
  54. return ERROR_OK;
  55. }
  56. static int target_charmsg(struct target *target, uint8_t msg)
  57. {
  58. LOG_USER_N("%c", msg);
  59. return ERROR_OK;
  60. }
  61. static int target_hexmsg(struct target *target, int size, uint32_t length)
  62. {
  63. uint8_t *data = malloc(DIV_ROUND_UP(length * size, 4) * 4);
  64. char line[128];
  65. int line_len;
  66. struct debug_msg_receiver *c = target->dbgmsg;
  67. uint32_t i;
  68. LOG_DEBUG("size: %i, length: %i", (int)size, (int)length);
  69. target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t *)data);
  70. line_len = 0;
  71. for (i = 0; i < length; i++) {
  72. switch (size) {
  73. case 4:
  74. line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i)));
  75. break;
  76. case 2:
  77. line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
  78. break;
  79. case 1:
  80. line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
  81. break;
  82. }
  83. if ((i%8 == 7) || (i == length - 1)) {
  84. LOG_DEBUG("%s", line);
  85. while (c) {
  86. command_print(c->cmd_ctx, "%s", line);
  87. c = c->next;
  88. }
  89. c = target->dbgmsg;
  90. line_len = 0;
  91. }
  92. }
  93. free(data);
  94. return ERROR_OK;
  95. }
  96. /* handle requests from the target received by a target specific
  97. * side-band channel (e.g. ARM7/9 DCC)
  98. */
  99. int target_request(struct target *target, uint32_t request)
  100. {
  101. target_req_cmd_t target_req_cmd = request & 0xff;
  102. /* Record that we got a target message for back-off algorithm */
  103. got_message = true;
  104. if (charmsg_mode) {
  105. target_charmsg(target, target_req_cmd);
  106. return ERROR_OK;
  107. }
  108. switch (target_req_cmd) {
  109. case TARGET_REQ_TRACEMSG:
  110. trace_point(target, (request & 0xffffff00) >> 8);
  111. break;
  112. case TARGET_REQ_DEBUGMSG:
  113. if (((request & 0xff00) >> 8) == 0)
  114. target_asciimsg(target, (request & 0xffff0000) >> 16);
  115. else
  116. target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
  117. break;
  118. case TARGET_REQ_DEBUGCHAR:
  119. target_charmsg(target, (request & 0x00ff0000) >> 16);
  120. break;
  121. /* case TARGET_REQ_SEMIHOSTING:
  122. * break;
  123. */
  124. default:
  125. LOG_ERROR("unknown target request: %2.2x", target_req_cmd);
  126. break;
  127. }
  128. return ERROR_OK;
  129. }
  130. static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
  131. {
  132. struct debug_msg_receiver **p = &target->dbgmsg;
  133. if (target == NULL)
  134. return ERROR_COMMAND_SYNTAX_ERROR;
  135. /* see if there's already a list */
  136. if (*p) {
  137. /* find end of linked list */
  138. while ((*p)->next)
  139. p = &((*p)->next);
  140. p = &((*p)->next);
  141. }
  142. /* add new debug message receiver */
  143. (*p) = malloc(sizeof(struct debug_msg_receiver));
  144. (*p)->cmd_ctx = cmd_ctx;
  145. (*p)->next = NULL;
  146. /* enable callback */
  147. target->dbg_msg_enabled = 1;
  148. return ERROR_OK;
  149. }
  150. static struct debug_msg_receiver *find_debug_msg_receiver(struct command_context *cmd_ctx,
  151. struct target *target)
  152. {
  153. int do_all_targets = 0;
  154. /* if no target has been specified search all of them */
  155. if (target == NULL) {
  156. /* if no targets haven been specified */
  157. if (all_targets == NULL)
  158. return NULL;
  159. target = all_targets;
  160. do_all_targets = 1;
  161. }
  162. /* so we target != null */
  163. struct debug_msg_receiver **p = &target->dbgmsg;
  164. do {
  165. while (*p) {
  166. if ((*p)->cmd_ctx == cmd_ctx)
  167. return *p;
  168. p = &((*p)->next);
  169. }
  170. target = target->next;
  171. } while (target && do_all_targets);
  172. return NULL;
  173. }
  174. int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
  175. {
  176. struct debug_msg_receiver **p;
  177. struct debug_msg_receiver *c;
  178. int do_all_targets = 0;
  179. /* if no target has been specified search all of them */
  180. if (target == NULL) {
  181. /* if no targets haven been specified */
  182. if (all_targets == NULL)
  183. return ERROR_OK;
  184. target = all_targets;
  185. do_all_targets = 1;
  186. }
  187. do {
  188. p = &target->dbgmsg;
  189. c = *p;
  190. while (c) {
  191. struct debug_msg_receiver *next = c->next;
  192. if (c->cmd_ctx == cmd_ctx) {
  193. *p = next;
  194. free(c);
  195. if (*p == NULL) {
  196. /* disable callback */
  197. target->dbg_msg_enabled = 0;
  198. }
  199. return ERROR_OK;
  200. } else
  201. p = &(c->next);
  202. c = next;
  203. }
  204. target = target->next;
  205. } while (target && do_all_targets);
  206. return ERROR_OK;
  207. }
  208. COMMAND_HANDLER(handle_target_request_debugmsgs_command)
  209. {
  210. struct target *target = get_current_target(CMD_CTX);
  211. int receiving = 0;
  212. /* see if reciever is already registered */
  213. if (find_debug_msg_receiver(CMD_CTX, target) != NULL)
  214. receiving = 1;
  215. if (CMD_ARGC > 0) {
  216. if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg")) {
  217. /* don't register if this command context is already receiving */
  218. if (!receiving) {
  219. receiving = 1;
  220. add_debug_msg_receiver(CMD_CTX, target);
  221. }
  222. charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg");
  223. } else if (!strcmp(CMD_ARGV[0], "disable")) {
  224. /* no need to delete a receiver if none is registered */
  225. if (receiving) {
  226. receiving = 0;
  227. delete_debug_msg_receiver(CMD_CTX, target);
  228. }
  229. } else
  230. return ERROR_COMMAND_SYNTAX_ERROR;
  231. }
  232. command_print(CMD_CTX, "receiving debug messages from current target %s",
  233. (receiving) ? (charmsg_mode ? "charmsg" : "enabled") : "disabled");
  234. return ERROR_OK;
  235. }
  236. static const struct command_registration target_req_exec_command_handlers[] = {
  237. {
  238. .name = "debugmsgs",
  239. .handler = handle_target_request_debugmsgs_command,
  240. .mode = COMMAND_EXEC,
  241. .help = "display and/or modify reception of debug messages from target",
  242. .usage = "['enable'|'charmsg'|'disable']",
  243. },
  244. COMMAND_REGISTRATION_DONE
  245. };
  246. static const struct command_registration target_req_command_handlers[] = {
  247. {
  248. .name = "target_request",
  249. .mode = COMMAND_ANY,
  250. .help = "target request command group",
  251. .usage = "",
  252. .chain = target_req_exec_command_handlers,
  253. },
  254. COMMAND_REGISTRATION_DONE
  255. };
  256. int target_request_register_commands(struct command_context *cmd_ctx)
  257. {
  258. return register_commands(cmd_ctx, NULL, target_req_command_handlers);
  259. }