openocd: fix simple cases of NULL comparison
[fw/openocd] / src / jtag / aice / aice_transport.c
1 /***************************************************************************
2  *   Copyright (C) 2013 by Andes Technology                                *
3  *   Hsiangkai Wang <hkwang@andestech.com>                                 *
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, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 /* project specific includes */
24 #include <jtag/interface.h>
25 #include <jtag/tcl.h>
26 #include <transport/transport.h>
27 #include <target/target.h>
28 #include <jtag/aice/aice_interface.h>
29 #include <jtag/aice/aice_transport.h>
30 #include <string.h>
31
32 /* */
33 static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi,
34                 struct jtag_tap *tap)
35 {
36         jim_wide w;
37         int e = jim_getopt_wide(goi, &w);
38         if (e != JIM_OK) {
39                 Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
40                                 n->name);
41                 return e;
42         }
43
44         unsigned expected_len = sizeof(uint32_t) * tap->expected_ids_cnt;
45         uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
46         if (!new_expected_ids) {
47                 Jim_SetResultFormatted(goi->interp, "no memory");
48                 return JIM_ERR;
49         }
50
51         assert(tap->expected_ids);
52         memcpy(new_expected_ids, tap->expected_ids, expected_len);
53
54         new_expected_ids[tap->expected_ids_cnt] = w;
55
56         free(tap->expected_ids);
57         tap->expected_ids = new_expected_ids;
58         tap->expected_ids_cnt++;
59
60         return JIM_OK;
61 }
62
63 #define NTAP_OPT_EXPECTED_ID 0
64
65 /* */
66 static int jim_aice_newtap_cmd(struct jim_getopt_info *goi)
67 {
68         struct jtag_tap *tap;
69         int x;
70         int e;
71         struct jim_nvp *n;
72         char *cp;
73         const struct jim_nvp opts[] = {
74                 {.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID},
75                 {.name = NULL, .value = -1},
76         };
77
78         tap = calloc(1, sizeof(struct jtag_tap));
79         if (!tap) {
80                 Jim_SetResultFormatted(goi->interp, "no memory");
81                 return JIM_ERR;
82         }
83
84         /*
85          * we expect CHIP + TAP + OPTIONS
86          * */
87         if (goi->argc < 3) {
88                 Jim_SetResultFormatted(goi->interp,
89                                 "Missing CHIP TAP OPTIONS ....");
90                 free(tap);
91                 return JIM_ERR;
92         }
93
94         const char *tmp;
95         jim_getopt_string(goi, &tmp, NULL);
96         tap->chip = strdup(tmp);
97
98         jim_getopt_string(goi, &tmp, NULL);
99         tap->tapname = strdup(tmp);
100
101         /* name + dot + name + null */
102         x = strlen(tap->chip) + 1 + strlen(tap->tapname) + 1;
103         cp = malloc(x);
104         sprintf(cp, "%s.%s", tap->chip, tap->tapname);
105         tap->dotted_name = cp;
106
107         LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
108                         tap->chip, tap->tapname, tap->dotted_name, goi->argc);
109
110         while (goi->argc) {
111                 e = jim_getopt_nvp(goi, opts, &n);
112                 if (e != JIM_OK) {
113                         jim_getopt_nvp_unknown(goi, opts, 0);
114                         free(cp);
115                         free(tap);
116                         return e;
117                 }
118                 LOG_DEBUG("Processing option: %s", n->name);
119                 switch (n->value) {
120                         case NTAP_OPT_EXPECTED_ID:
121                                 e = jim_newtap_expected_id(n, goi, tap);
122                                 if (e != JIM_OK) {
123                                         free(cp);
124                                         free(tap);
125                                         return e;
126                                 }
127                                 break;
128                 }               /* switch (n->value) */
129         }                       /* while (goi->argc) */
130
131         /* default is enabled-after-reset */
132         tap->enabled = !tap->disabled_after_reset;
133
134         jtag_tap_init(tap);
135         return JIM_OK;
136 }
137
138 /* */
139 static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
140 {
141         struct jim_getopt_info goi;
142         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
143         return jim_aice_newtap_cmd(&goi);
144 }
145
146 /* */
147 COMMAND_HANDLER(handle_aice_init_command)
148 {
149         if (CMD_ARGC != 0)
150                 return ERROR_COMMAND_SYNTAX_ERROR;
151
152         static bool jtag_initialized;
153         if (jtag_initialized) {
154                 LOG_INFO("'jtag init' has already been called");
155                 return ERROR_OK;
156         }
157         jtag_initialized = true;
158
159         LOG_DEBUG("Initializing jtag devices...");
160         return jtag_init(CMD_CTX);
161 }
162
163 COMMAND_HANDLER(handle_scan_chain_command)
164 {
165         struct jtag_tap *tap;
166         char expected_id[12];
167
168         aice_scan_jtag_chain();
169         tap = jtag_all_taps();
170         command_print(CMD,
171                 "   TapName             Enabled  IdCode     Expected   IrLen IrCap IrMask");
172         command_print(CMD,
173                 "-- ------------------- -------- ---------- ---------- ----- ----- ------");
174
175         while (tap) {
176                 uint32_t expected, expected_mask, ii;
177
178                 snprintf(expected_id, sizeof(expected_id), "0x%08x",
179                         (unsigned)((tap->expected_ids_cnt > 0)
180                                    ? tap->expected_ids[0]
181                                    : 0));
182                 if (tap->ignore_version)
183                         expected_id[2] = '*';
184
185                 expected = buf_get_u32(tap->expected, 0, tap->ir_length);
186                 expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
187
188                 command_print(CMD,
189                         "%2d %-18s     %c     0x%08x %s %5d 0x%02x  0x%02x",
190                         tap->abs_chain_position,
191                         tap->dotted_name,
192                         tap->enabled ? 'Y' : 'n',
193                         (unsigned int)(tap->idcode),
194                         expected_id,
195                         (unsigned int)(tap->ir_length),
196                         (unsigned int)(expected),
197                         (unsigned int)(expected_mask));
198
199                 for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
200                         snprintf(expected_id, sizeof(expected_id), "0x%08x",
201                                 (unsigned) tap->expected_ids[ii]);
202                         if (tap->ignore_version)
203                                 expected_id[2] = '*';
204
205                         command_print(CMD,
206                                 "                                           %s",
207                                 expected_id);
208                 }
209
210                 tap = tap->next_tap;
211         }
212
213         return ERROR_OK;
214 }
215
216 static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
217 {
218         LOG_DEBUG("No implement: jim_aice_arp_init");
219
220         return JIM_OK;
221 }
222
223 /* */
224 static int aice_init_reset(struct command_context *cmd_ctx)
225 {
226         LOG_DEBUG("Initializing with hard TRST+SRST reset");
227
228         int retval;
229         enum reset_types jtag_reset_config = jtag_get_reset_config();
230
231         jtag_add_reset(1, 0);   /* TAP_RESET */
232         if (jtag_reset_config & RESET_HAS_SRST) {
233                 jtag_add_reset(1, 1);
234                 if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
235                         jtag_add_reset(0, 1);
236         }
237         jtag_add_reset(0, 0);
238         retval = jtag_execute_queue();
239         if (retval != ERROR_OK)
240                 return retval;
241
242         return ERROR_OK;
243 }
244
245 /* */
246 static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
247 {
248         int e = ERROR_OK;
249         struct jim_getopt_info goi;
250         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
251         if (goi.argc != 0) {
252                 Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
253                 return JIM_ERR;
254         }
255         struct command_context *context = current_command_context(interp);
256         e = aice_init_reset(context);
257
258         if (e != ERROR_OK) {
259                 Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
260                 Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
261                 return JIM_ERR;
262         }
263         return JIM_OK;
264 }
265
266 static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
267 {
268         struct jim_getopt_info goi;
269         jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
270         if (goi.argc != 0) {
271                 Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
272                 return JIM_ERR;
273         }
274         Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
275         struct jtag_tap *tap;
276
277         for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
278                 Jim_ListAppendElement(goi.interp,
279                                 Jim_GetResult(goi.interp),
280                                 Jim_NewStringObj(goi.interp,
281                                         tap->dotted_name, -1));
282
283         return JIM_OK;
284 }
285
286 /* */
287 static const struct command_registration
288 aice_transport_jtag_subcommand_handlers[] = {
289         {
290                 .name = "init",
291                 .mode = COMMAND_ANY,
292                 .handler = handle_aice_init_command,
293                 .help = "initialize jtag scan chain",
294                 .usage = ""
295         },
296         {
297                 .name = "arp_init",
298                 .mode = COMMAND_ANY,
299                 .jim_handler = jim_aice_arp_init,
300                 .help = "Validates JTAG scan chain against the list of "
301                         "declared TAPs.",
302         },
303         {
304                 .name = "arp_init-reset",
305                 .mode = COMMAND_ANY,
306                 .jim_handler = jim_aice_arp_init_reset,
307                 .help = "Uses TRST and SRST to try resetting everything on "
308                         "the JTAG scan chain, then performs 'jtag arp_init'."
309         },
310         {
311                 .name = "newtap",
312                 .mode = COMMAND_CONFIG,
313                 .jim_handler = jim_aice_newtap,
314                 .help = "Create a new TAP instance named basename.tap_type, "
315                         "and appends it to the scan chain.",
316                 .usage = "basename tap_type ['-expected_id' number]"
317         },
318         {
319                 .name = "tapisenabled",
320                 .mode = COMMAND_EXEC,
321                 .jim_handler = jim_jtag_tap_enabler,
322                 .help = "Returns a Tcl boolean (0/1) indicating whether "
323                         "the TAP is enabled (1) or not (0).",
324                 .usage = "tap_name",
325         },
326         {
327                 .name = "tapenable",
328                 .mode = COMMAND_EXEC,
329                 .jim_handler = jim_jtag_tap_enabler,
330                 .help = "Try to enable the specified TAP using the "
331                         "'tap-enable' TAP event.",
332                 .usage = "tap_name",
333         },
334         {
335                 .name = "tapdisable",
336                 .mode = COMMAND_EXEC,
337                 .jim_handler = jim_jtag_tap_enabler,
338                 .help = "Try to disable the specified TAP using the "
339                         "'tap-disable' TAP event.",
340                 .usage = "tap_name",
341         },
342         {
343                 .name = "configure",
344                 .mode = COMMAND_ANY,
345                 .jim_handler = jim_jtag_configure,
346                 .help = "Provide a Tcl handler for the specified "
347                         "TAP event.",
348                 .usage = "tap_name '-event' event_name handler",
349         },
350         {
351                 .name = "cget",
352                 .mode = COMMAND_EXEC,
353                 .jim_handler = jim_jtag_configure,
354                 .help = "Return any Tcl handler for the specified "
355                         "TAP event.",
356                 .usage = "tap_name '-event' event_name",
357         },
358         {
359                 .name = "names",
360                 .mode = COMMAND_ANY,
361                 .jim_handler = jim_aice_names,
362                 .help = "Returns list of all JTAG tap names.",
363         },
364         {
365                 .name = "scan_chain",
366                 .handler = handle_scan_chain_command,
367                 .mode = COMMAND_ANY,
368                 .help = "print current scan chain configuration",
369                 .usage = ""
370         },
371
372         COMMAND_REGISTRATION_DONE
373 };
374
375 /* */
376 static const struct command_registration aice_transport_command_handlers[] = {
377         {
378                 .name = "jtag",
379                 .mode = COMMAND_ANY,
380                 .usage = "",
381                 .chain = aice_transport_jtag_subcommand_handlers,
382         },
383         COMMAND_REGISTRATION_DONE
384
385 };
386
387 /* */
388 static int aice_transport_register_commands(struct command_context *cmd_ctx)
389 {
390         return register_commands(cmd_ctx, NULL,
391                         aice_transport_command_handlers);
392 }
393
394 /* */
395 static int aice_transport_init(struct command_context *cmd_ctx)
396 {
397         LOG_DEBUG("aice_transport_init");
398         struct target *t = get_current_target(cmd_ctx);
399         struct transport *transport;
400
401         if (!t) {
402                 LOG_ERROR("no current target");
403                 return ERROR_FAIL;
404         }
405
406         transport = get_current_transport();
407
408         if (!transport) {
409                 LOG_ERROR("no transport selected");
410                 return ERROR_FAIL;
411         }
412
413         LOG_DEBUG("current transport %s", transport->name);
414
415         return aice_init_targets();
416 }
417
418 /* */
419 static int aice_transport_select(struct command_context *ctx)
420 {
421         LOG_DEBUG("aice_transport_select");
422
423         int retval;
424
425         retval = aice_transport_register_commands(ctx);
426
427         if (retval != ERROR_OK)
428                 return retval;
429
430         return ERROR_OK;
431 }
432
433 static struct transport aice_jtag_transport = {
434         .name = "aice_jtag",
435         .select = aice_transport_select,
436         .init = aice_transport_init,
437 };
438
439 const char *aice_transports[] = { "aice_jtag", NULL };
440
441 static void aice_constructor(void) __attribute__((constructor));
442 static void aice_constructor(void)
443 {
444         transport_register(&aice_jtag_transport);
445 }