- add support for cortex_m3 target_request debugmsgs
[fw/openocd] / src / target / target_request.c
1 /***************************************************************************
2  *   Copyright (C) 2007 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, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "replacements.h"
25 #include "log.h"
26 #include "target.h"
27 #include "target_request.h"
28 #include "binarybuffer.h"
29 #include "command.h"
30 #include "trace.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 command_t *target_request_cmd = NULL;
36
37 int target_asciimsg(target_t *target, u32 length)
38 {
39         char *msg = malloc(CEIL(length + 1, 4) * 4);
40         debug_msg_receiver_t *c = target->dbgmsg;
41         
42         target->type->target_request_data(target, CEIL(length, 4), (u8*)msg);
43         msg[length] = 0;
44         
45         DEBUG("%s", msg);
46         
47         while (c)
48         {
49                 command_print(c->cmd_ctx, "%s", msg);
50                 c = c->next;
51         }
52         
53         return ERROR_OK;
54 }
55
56 int target_hexmsg(target_t *target, int size, u32 length)
57 {
58         u8 *data = malloc(CEIL(length * size, 4) * 4);
59         char line[128];
60         int line_len;
61         debug_msg_receiver_t *c = target->dbgmsg;
62         int i;
63         
64         DEBUG("size: %i, length: %i", size, length);
65
66         target->type->target_request_data(target, CEIL(length * size, 4), (u8*)data);
67
68         line_len = 0;
69         for (i = 0; i < length; i++)
70         {
71                 switch (size)
72                 {
73                         case 4:
74                                 line_len += snprintf(line + line_len, 128 - line_len, "%8.8x ", 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                 
84                 if ((i%8 == 7) || (i == length - 1))
85                 {
86                         DEBUG("%s", line);
87                         
88                         while (c)
89                         {
90                                 command_print(c->cmd_ctx, "%s", line);
91                                 c = c->next;
92                         }
93                         c = target->dbgmsg;
94                         line_len = 0;
95                 }
96         }
97         
98         free(data);
99
100         return ERROR_OK;
101 }
102
103 /* handle requests from the target received by a target specific
104  * side-band channel (e.g. ARM7/9 DCC)
105  */
106 int target_request(target_t *target, u32 request)
107 {
108         target_req_cmd_t target_req_cmd = request & 0xff;
109         
110         switch (target_req_cmd)
111         {
112                 case TARGET_REQ_TRACEMSG:
113                         trace_point(target, (request & 0xffffff00) >> 8);
114                         break;
115                 case TARGET_REQ_DEBUGMSG:
116                         if (((request & 0xff00) >> 8) == 0)
117                         {
118                                 target_asciimsg(target, (request & 0xffff0000) >> 16);
119                         }
120                         else
121                         {
122                                 target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
123                         }
124                         break;
125 /*              case TARGET_REQ_SEMIHOSTING:
126  *                      break;
127  */
128                 default:
129                         ERROR("unknown target request: %2.2x", target_req_cmd);
130                         break;
131         }
132         
133         return ERROR_OK;
134 }
135
136 int add_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
137 {
138         debug_msg_receiver_t **p = &target->dbgmsg;
139         
140         if (target == NULL)
141                 return ERROR_INVALID_ARGUMENTS;
142
143         /* see if there's already a list */
144         if (*p)
145         {
146                 /* find end of linked list */
147                 p = &target->dbgmsg;
148                 while ((*p)->next)
149                         p = &((*p)->next);
150                 p = &((*p)->next);
151         }
152
153         /* add new debug message receiver */
154         (*p) = malloc(sizeof(debug_msg_receiver_t));
155         (*p)->cmd_ctx = cmd_ctx;
156         (*p)->next = NULL;
157         
158         /* enable callback */
159         target->dbg_msg_enabled = 1;
160         
161         return ERROR_OK;
162 }
163
164 debug_msg_receiver_t* find_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
165 {
166         int all_targets = 0;
167         debug_msg_receiver_t **p = &target->dbgmsg;
168         
169         /* if no target has been specified search all of them */
170         if (target == NULL)
171         {
172                 /* if no targets haven been specified */
173                 if (targets == NULL)
174                         return NULL;
175
176                 target = targets;
177                 all_targets = 1;
178         }
179         
180         do
181         {
182                 while (*p)
183                 {
184                         if ((*p)->cmd_ctx == cmd_ctx)
185                         {
186                                 return *p;
187                         }
188                         p = &((*p)->next);
189                 }
190                 
191                 target = target->next;
192         } while (target && all_targets);
193         
194         return NULL;
195 }
196
197 int delete_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
198 {
199         debug_msg_receiver_t **p;
200         debug_msg_receiver_t *c;
201         int all_targets = 0;
202         
203         /* if no target has been specified search all of them */
204         if (target == NULL)
205         {
206                 /* if no targets haven been specified */
207                 if (targets == NULL)
208                         return ERROR_OK;
209                 
210                 target = targets;
211                 all_targets = 1;
212         }
213
214         do
215         {
216                 p = &target->dbgmsg;
217                 c = *p;
218                 while (c)
219                 {
220                         debug_msg_receiver_t *next = c->next;
221                         if (c->cmd_ctx == cmd_ctx)
222                         {
223                                 *p = next;
224                                 free(c);
225                                 if (*p == NULL)
226                                 {
227                                         /* disable callback */
228                                         target->dbg_msg_enabled = 0;
229                                 }
230                                 return ERROR_OK;
231                         }
232                         else
233                                 p = &(c->next);
234                         c = next;
235                 }
236         
237                 target = target->next;
238         } while (target && all_targets);
239         
240         return ERROR_OK;
241 }
242
243 int handle_target_request_debugmsgs_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
244 {
245         target_t *target = get_current_target(cmd_ctx);
246
247         int receiving = 0;
248         
249         /* see if reciever is already registered */
250         if (find_debug_msg_receiver(cmd_ctx, target) != NULL)
251                 receiving = 1;
252
253         if (argc > 0)
254         {
255                 if (!strcmp(args[0], "enable"))
256                 {
257                         /* don't register if this command context is already receiving */
258                         if (!receiving)
259                         {
260                                 receiving = 1;
261                                 add_debug_msg_receiver(cmd_ctx, target);
262                         }
263                 }
264                 else if (!strcmp(args[0], "disable"))
265                 {
266                         /* no need to delete a receiver if none is registered */
267                         if (receiving)
268                         {
269                                 receiving = 0;
270                                 delete_debug_msg_receiver(cmd_ctx, target);
271                         }
272                 }
273                 else
274                 {
275                         command_print(cmd_ctx, "usage: target_request debugmsgs ['enable'|'disable']");
276                 }
277         }
278         
279         command_print(cmd_ctx, "receiving debug messages from current target %s",
280                         (receiving) ? "enabled" : "disabled");
281         
282         return ERROR_OK;
283 }
284
285 int target_request_register_commands(struct command_context_s *cmd_ctx)
286 {
287         target_request_cmd =
288                 register_command(cmd_ctx, NULL, "target_request", NULL, COMMAND_ANY, "target_request commands");
289         
290         register_command(cmd_ctx, target_request_cmd, "debugmsgs", handle_target_request_debugmsgs_command,
291                 COMMAND_EXEC, "enable/disable reception of debug messgages from target");
292
293         return ERROR_OK;
294 }