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