flash/nor/at91samd: Use 32-bit register writes for ST-Link compat
[fw/openocd] / src / target / target_request.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2007 by Dominic Rath                                    *
5  *   Dominic.Rath@gmx.de                                                   *
6  *                                                                         *
7  *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *
8  *   oyvind.harboe@zylin.com                                               *
9  *                                                                         *
10  *   Copyright (C) 2008 by Spencer Oliver                                  *
11  *   spen@spen-soft.co.uk                                                  *
12  ***************************************************************************/
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include <helper/log.h>
19 #include <helper/binarybuffer.h>
20
21 #include "target.h"
22 #include "target_request.h"
23 #include "target_type.h"
24 #include "trace.h"
25
26 static bool got_message;
27
28 bool target_got_message(void)
29 {
30         bool t = got_message;
31         got_message = false;
32         return t;
33 }
34
35 static int charmsg_mode;
36
37 static int target_asciimsg(struct target *target, uint32_t length)
38 {
39         char *msg = malloc(DIV_ROUND_UP(length + 1, 4) * 4);
40         struct debug_msg_receiver *c = target->dbgmsg;
41
42         target->type->target_request_data(target, DIV_ROUND_UP(length, 4), (uint8_t *)msg);
43         msg[length] = 0;
44
45         LOG_DEBUG("%s", msg);
46
47         while (c) {
48                 command_output_text(c->cmd_ctx, msg);
49                 c = c->next;
50         }
51
52         return ERROR_OK;
53 }
54
55 static int target_charmsg(struct target *target, uint8_t msg)
56 {
57         LOG_USER_N("%c", msg);
58
59         return ERROR_OK;
60 }
61
62 static int target_hexmsg(struct target *target, int size, uint32_t length)
63 {
64         uint8_t *data = malloc(DIV_ROUND_UP(length * size, 4) * 4);
65         char line[128];
66         int line_len;
67         struct debug_msg_receiver *c = target->dbgmsg;
68         uint32_t i;
69
70         LOG_DEBUG("size: %i, length: %i", (int)size, (int)length);
71
72         target->type->target_request_data(target, DIV_ROUND_UP(length * size, 4), (uint8_t *)data);
73
74         line_len = 0;
75         for (i = 0; i < length; i++) {
76                 switch (size) {
77                         case 4:
78                                 line_len += snprintf(line + line_len, 128 - line_len, "%8.8" PRIx32 " ", le_to_h_u32(data + (4*i)));
79                                 break;
80                         case 2:
81                                 line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
82                                 break;
83                         case 1:
84                                 line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
85                                 break;
86                 }
87
88                 if ((i%8 == 7) || (i == length - 1)) {
89                         LOG_DEBUG("%s", line);
90
91                         while (c) {
92                                 command_output_text(c->cmd_ctx, line);
93                                 c = c->next;
94                         }
95                         c = target->dbgmsg;
96                         line_len = 0;
97                 }
98         }
99
100         free(data);
101
102         return ERROR_OK;
103 }
104
105 /* handle requests from the target received by a target specific
106  * side-band channel (e.g. ARM7/9 DCC)
107  */
108 int target_request(struct target *target, uint32_t request)
109 {
110         target_req_cmd_t target_req_cmd = request & 0xff;
111
112         assert(target->type->target_request_data);
113
114         /* Record that we got a target message for back-off algorithm */
115         got_message = true;
116
117         if (charmsg_mode) {
118                 target_charmsg(target, target_req_cmd);
119                 return ERROR_OK;
120         }
121
122         switch (target_req_cmd) {
123                 case TARGET_REQ_TRACEMSG:
124                         trace_point(target, (request & 0xffffff00) >> 8);
125                         break;
126                 case TARGET_REQ_DEBUGMSG:
127                         if (((request & 0xff00) >> 8) == 0)
128                                 target_asciimsg(target, (request & 0xffff0000) >> 16);
129                         else
130                                 target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
131                         break;
132                 case TARGET_REQ_DEBUGCHAR:
133                         target_charmsg(target, (request & 0x00ff0000) >> 16);
134                         break;
135 /*              case TARGET_REQ_SEMIHOSTING:
136  *                      break;
137  */
138                 default:
139                         LOG_ERROR("unknown target request: %2.2x", target_req_cmd);
140                         break;
141         }
142
143         return ERROR_OK;
144 }
145
146 static int add_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
147 {
148         struct debug_msg_receiver **p = &target->dbgmsg;
149
150         if (!target)
151                 return ERROR_COMMAND_SYNTAX_ERROR;
152
153         /* see if there's already a list */
154         if (*p) {
155                 /* find end of linked list */
156                 while ((*p)->next)
157                         p = &((*p)->next);
158                 p = &((*p)->next);
159         }
160
161         /* add new debug message receiver */
162         (*p) = malloc(sizeof(struct debug_msg_receiver));
163         (*p)->cmd_ctx = cmd_ctx;
164         (*p)->next = NULL;
165
166         /* enable callback */
167         target->dbg_msg_enabled = 1;
168
169         return ERROR_OK;
170 }
171
172 static struct debug_msg_receiver *find_debug_msg_receiver(struct command_context *cmd_ctx,
173                 struct target *target)
174 {
175         int do_all_targets = 0;
176
177         /* if no target has been specified search all of them */
178         if (!target) {
179                 /* if no targets haven been specified */
180                 if (!all_targets)
181                         return NULL;
182
183                 target = all_targets;
184                 do_all_targets = 1;
185         }
186
187         /* so we target != null */
188         struct debug_msg_receiver **p = &target->dbgmsg;
189         do {
190                 while (*p) {
191                         if ((*p)->cmd_ctx == cmd_ctx)
192                                 return *p;
193                         p = &((*p)->next);
194                 }
195
196                 target = target->next;
197         } while (target && do_all_targets);
198
199         return NULL;
200 }
201
202 int delete_debug_msg_receiver(struct command_context *cmd_ctx, struct target *target)
203 {
204         struct debug_msg_receiver **p;
205         struct debug_msg_receiver *c;
206         int do_all_targets = 0;
207
208         /* if no target has been specified search all of them */
209         if (!target) {
210                 /* if no targets haven been specified */
211                 if (!all_targets)
212                         return ERROR_OK;
213
214                 target = all_targets;
215                 do_all_targets = 1;
216         }
217
218         do {
219                 p = &target->dbgmsg;
220                 c = *p;
221                 while (c) {
222                         struct debug_msg_receiver *next = c->next;
223                         if (c->cmd_ctx == cmd_ctx) {
224                                 *p = next;
225                                 free(c);
226                                 if (!*p) {
227                                         /* disable callback */
228                                         target->dbg_msg_enabled = 0;
229                                 }
230                                 return ERROR_OK;
231                         } else
232                                 p = &(c->next);
233                         c = next;
234                 }
235
236                 target = target->next;
237         } while (target && do_all_targets);
238
239         return ERROR_OK;
240 }
241
242 COMMAND_HANDLER(handle_target_request_debugmsgs_command)
243 {
244         struct target *target = get_current_target(CMD_CTX);
245
246         int receiving = 0;
247
248         if (!target->type->target_request_data) {
249                 LOG_ERROR("Target %s does not support target requests", target_name(target));
250                 return ERROR_OK;
251         }
252
253         /* see if receiver is already registered */
254         if (find_debug_msg_receiver(CMD_CTX, target))
255                 receiving = 1;
256
257         if (CMD_ARGC > 0) {
258                 if (!strcmp(CMD_ARGV[0], "enable") || !strcmp(CMD_ARGV[0], "charmsg")) {
259                         /* don't register if this command context is already receiving */
260                         if (!receiving) {
261                                 receiving = 1;
262                                 add_debug_msg_receiver(CMD_CTX, target);
263                         }
264                         charmsg_mode = !strcmp(CMD_ARGV[0], "charmsg");
265                 } else if (!strcmp(CMD_ARGV[0], "disable")) {
266                         /* no need to delete a receiver if none is registered */
267                         if (receiving) {
268                                 receiving = 0;
269                                 delete_debug_msg_receiver(CMD_CTX, target);
270                         }
271                 } else
272                         return ERROR_COMMAND_SYNTAX_ERROR;
273         }
274
275         command_print(CMD, "receiving debug messages from current target %s",
276                         (receiving) ? (charmsg_mode ? "charmsg" : "enabled") : "disabled");
277         return ERROR_OK;
278 }
279
280 static const struct command_registration target_req_exec_command_handlers[] = {
281         {
282                 .name = "debugmsgs",
283                 .handler = handle_target_request_debugmsgs_command,
284                 .mode = COMMAND_EXEC,
285                 .help = "display and/or modify reception of debug messages from target",
286                 .usage = "['enable'|'charmsg'|'disable']",
287         },
288         COMMAND_REGISTRATION_DONE
289 };
290 static const struct command_registration target_req_command_handlers[] = {
291         {
292                 .name = "target_request",
293                 .mode = COMMAND_ANY,
294                 .help = "target request command group",
295                 .usage = "",
296                 .chain = target_req_exec_command_handlers,
297         },
298         COMMAND_REGISTRATION_DONE
299 };
300
301 int target_request_register_commands(struct command_context *cmd_ctx)
302 {
303         return register_commands(cmd_ctx, NULL, target_req_command_handlers);
304 }