target_request.c 7.84 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2007 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 yvind Harboe                                 *
6
7
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "replacements.h"
#include "log.h"
#include "target.h"
#include "target_request.h"
#include "binarybuffer.h"
#include "command.h"
36
#include "trace.h"
37
38
39
40
41

#include <stdlib.h>
#include <string.h>

command_t *target_request_cmd = NULL;
42
static int charmsg_mode = 0;
43
44
45
46
47
48
49
50
51

int target_asciimsg(target_t *target, u32 length)
{
	char *msg = malloc(CEIL(length + 1, 4) * 4);
	debug_msg_receiver_t *c = target->dbgmsg;
	
	target->type->target_request_data(target, CEIL(length, 4), (u8*)msg);
	msg[length] = 0;
	
52
	LOG_DEBUG("%s", msg);
53
54
55
56
57
58
59
60
61
62
	
	while (c)
	{
		command_print(c->cmd_ctx, "%s", msg);
		c = c->next;
	}
	
	return ERROR_OK;
}

63
64
int target_charmsg(target_t *target, u8 msg)
{
65
	LOG_USER_N("%c", msg);
66
67
68
69
	
	return ERROR_OK;
}

70
71
int target_hexmsg(target_t *target, int size, u32 length)
{
72
73
74
75
	u8 *data = malloc(CEIL(length * size, 4) * 4);
	char line[128];
	int line_len;
	debug_msg_receiver_t *c = target->dbgmsg;
76
	u32 i;
77
	
78
	LOG_DEBUG("size: %i, length: %i", size, length);
79

80
	target->type->target_request_data(target, CEIL(length * size, 4), (u8*)data);
81

82
83
	line_len = 0;
	for (i = 0; i < length; i++)
84
	{
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
		switch (size)
		{
			case 4:
				line_len += snprintf(line + line_len, 128 - line_len, "%8.8x ", le_to_h_u32(data + (4*i)));
				break;
			case 2:
				line_len += snprintf(line + line_len, 128 - line_len, "%4.4x ", le_to_h_u16(data + (2*i)));
				break;
			case 1:
				line_len += snprintf(line + line_len, 128 - line_len, "%2.2x ", data[i]);
				break;
		}
		
		if ((i%8 == 7) || (i == length - 1))
		{
100
			LOG_DEBUG("%s", line);
101
			
102
103
104
105
106
107
108
109
			while (c)
			{
				command_print(c->cmd_ctx, "%s", line);
				c = c->next;
			}
			c = target->dbgmsg;
			line_len = 0;
		}
110
111
	}
	
112
113
	free(data);

114
115
116
117
118
119
120
121
122
	return ERROR_OK;
}

/* handle requests from the target received by a target specific
 * side-band channel (e.g. ARM7/9 DCC)
 */
int target_request(target_t *target, u32 request)
{
	target_req_cmd_t target_req_cmd = request & 0xff;
123
124
125
126
127

	if ( charmsg_mode ) {
		target_charmsg(target, target_req_cmd );
		return ERROR_OK;
	}
128
129
130
	switch (target_req_cmd)
	{
		case TARGET_REQ_TRACEMSG:
131
			trace_point(target, (request & 0xffffff00) >> 8);
132
133
134
135
136
137
138
139
140
141
142
			break;
		case TARGET_REQ_DEBUGMSG:
			if (((request & 0xff00) >> 8) == 0)
			{
				target_asciimsg(target, (request & 0xffff0000) >> 16);
			}
			else
			{
				target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16);
			}
			break;
143
144
145
		case TARGET_REQ_DEBUGCHAR:
			target_charmsg(target, (request & 0x00ff0000) >> 16);
			break;
146
147
148
149
/*		case TARGET_REQ_SEMIHOSTING:
 *			break;
 */
 		default:
150
 			LOG_ERROR("unknown target request: %2.2x", target_req_cmd);
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 			break;
	}
	
	return ERROR_OK;
}

int add_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
{
	debug_msg_receiver_t **p = &target->dbgmsg;
	
	if (target == NULL)
		return ERROR_INVALID_ARGUMENTS;

	/* see if there's already a list */
	if (*p)
	{
		/* find end of linked list */
		p = &target->dbgmsg;
		while ((*p)->next)
			p = &((*p)->next);
		p = &((*p)->next);
	}

	/* add new debug message receiver */
	(*p) = malloc(sizeof(debug_msg_receiver_t));
	(*p)->cmd_ctx = cmd_ctx;
	(*p)->next = NULL;
	
179
180
181
	/* enable callback */
	target->dbg_msg_enabled = 1;
	
182
183
184
185
186
	return ERROR_OK;
}

debug_msg_receiver_t* find_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
{
187
	int do_all_targets = 0;
188
189
190
191
192
193
	debug_msg_receiver_t **p = &target->dbgmsg;
	
	/* if no target has been specified search all of them */
	if (target == NULL)
	{
		/* if no targets haven been specified */
194
		if (all_targets == NULL)
195
196
			return NULL;

197
198
		target = all_targets;
		do_all_targets = 1;
199
200
201
202
203
204
205
206
207
208
209
210
211
212
	}
	
	do
	{
		while (*p)
		{
			if ((*p)->cmd_ctx == cmd_ctx)
			{
				return *p;
			}
			p = &((*p)->next);
		}
		
		target = target->next;
213
	} while (target && do_all_targets);
214
215
216
217
218
219
220
221
	
	return NULL;
}

int delete_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target)
{
	debug_msg_receiver_t **p;
	debug_msg_receiver_t *c;
222
	int do_all_targets = 0;
223
224
225
226
227
	
	/* if no target has been specified search all of them */
	if (target == NULL)
	{
		/* if no targets haven been specified */
228
		if (all_targets == NULL)
229
230
			return ERROR_OK;
		
231
232
		target = all_targets;
		do_all_targets = 1;
233
234
235
236
	}

	do
	{
237
238
		p = &target->dbgmsg;
		c = *p;
239
240
241
242
243
244
245
		while (c)
		{
			debug_msg_receiver_t *next = c->next;
			if (c->cmd_ctx == cmd_ctx)
			{
				*p = next;
				free(c);
246
247
248
249
250
				if (*p == NULL)
				{
					/* disable callback */
					target->dbg_msg_enabled = 0;
				}
251
252
253
254
255
256
257
258
				return ERROR_OK;
			}
			else
				p = &(c->next);
			c = next;
		}
	
		target = target->next;
259
	} while (target && do_all_targets);
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
	
	return ERROR_OK;
}

int handle_target_request_debugmsgs_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
	target_t *target = get_current_target(cmd_ctx);

	int receiving = 0;
	
	/* see if reciever is already registered */
	if (find_debug_msg_receiver(cmd_ctx, target) != NULL)
		receiving = 1;

	if (argc > 0)
	{
276
		if (!strcmp(args[0], "enable") || !strcmp(args[0], "charmsg"))
277
278
279
280
281
282
283
		{
			/* don't register if this command context is already receiving */
			if (!receiving)
			{
				receiving = 1;
				add_debug_msg_receiver(cmd_ctx, target);
			}
284
			charmsg_mode = !strcmp(args[0], "charmsg");
285
286
287
288
289
290
291
292
293
294
295
296
		}
		else if (!strcmp(args[0], "disable"))
		{
			/* no need to delete a receiver if none is registered */
			if (receiving)
			{
				receiving = 0;
				delete_debug_msg_receiver(cmd_ctx, target);
			}
		}
		else
		{
297
			command_print(cmd_ctx, "usage: target_request debugmsgs ['enable'|'disable'|'charmsg']");
298
299
300
301
		}
	}
	
	command_print(cmd_ctx, "receiving debug messages from current target %s",
302
		      (receiving) ? (charmsg_mode?"charmsg":"enabled") : "disabled" );
303
304
305
306
307
308
309
310
311
	return ERROR_OK;
}

int target_request_register_commands(struct command_context_s *cmd_ctx)
{
	target_request_cmd =
		register_command(cmd_ctx, NULL, "target_request", NULL, COMMAND_ANY, "target_request commands");
	
	register_command(cmd_ctx, target_request_cmd, "debugmsgs", handle_target_request_debugmsgs_command,
oharboe's avatar
oharboe committed
312
		COMMAND_EXEC, "enable/disable reception of debug messages from target");
313
314
315

	return ERROR_OK;
}