some trivial minidriver fixes
[openocd.git] / src / jtag / zy1000.c
1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #define INCLUDE_JTAG_MINIDRIVER_H
24 #define INCLUDE_JTAG_INTERFACE_H
25 #include "embeddedice.h"
26 #include "bitbang.h"
27
28 #include <cyg/hal/hal_io.h> // low level i/o
29 #include <cyg/hal/hal_diag.h>
30
31
32 #define ZYLIN_VERSION "1.52"
33 #define ZYLIN_DATE __DATE__
34 #define ZYLIN_TIME __TIME__
35 #define ZYLIN_OPENOCD "$Revision$"
36 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
37 const char *zylin_config_dir="/config/settings";
38
39 /* low level command set
40 */
41 int zy1000_read(void);
42 static void zy1000_write(int tck, int tms, int tdi);
43 void zy1000_reset(int trst, int srst);
44
45
46 int zy1000_speed(int speed);
47 int zy1000_register_commands(struct command_context_s *cmd_ctx);
48 int zy1000_init(void);
49 int zy1000_quit(void);
50
51 /* interface commands */
52 int zy1000_handle_zy1000_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
53
54 static int zy1000_khz(int khz, int *jtag_speed)
55 {
56 if (khz==0)
57 {
58 *jtag_speed=0;
59 }
60 else
61 {
62 *jtag_speed=64000/khz;
63 }
64 return ERROR_OK;
65 }
66
67 static int zy1000_speed_div(int speed, int *khz)
68 {
69 if (speed==0)
70 {
71 *khz = 0;
72 }
73 else
74 {
75 *khz=64000/speed;
76 }
77
78 return ERROR_OK;
79 }
80
81 static bool readPowerDropout(void)
82 {
83 cyg_uint32 state;
84 // sample and clear power dropout
85 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x10, 0x80);
86 HAL_READ_UINT32(ZY1000_JTAG_BASE+0x10, state);
87 bool powerDropout;
88 powerDropout = (state & 0x80) != 0;
89 return powerDropout;
90 }
91
92
93 static bool readSRST(void)
94 {
95 cyg_uint32 state;
96 // sample and clear SRST sensing
97 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x10, 0x00000040);
98 HAL_READ_UINT32(ZY1000_JTAG_BASE+0x10, state);
99 bool srstAsserted;
100 srstAsserted = (state & 0x40) != 0;
101 return srstAsserted;
102 }
103
104 static int zy1000_srst_asserted(int *srst_asserted)
105 {
106 *srst_asserted=readSRST();
107 return ERROR_OK;
108 }
109
110 static int zy1000_power_dropout(int *dropout)
111 {
112 *dropout=readPowerDropout();
113 return ERROR_OK;
114 }
115
116
117 jtag_interface_t zy1000_interface =
118 {
119 .name = "ZY1000",
120 .execute_queue = bitbang_execute_queue,
121 .speed = zy1000_speed,
122 .register_commands = zy1000_register_commands,
123 .init = zy1000_init,
124 .quit = zy1000_quit,
125 .khz = zy1000_khz,
126 .speed_div = zy1000_speed_div,
127 .power_dropout = zy1000_power_dropout,
128 .srst_asserted = zy1000_srst_asserted,
129 };
130
131 bitbang_interface_t zy1000_bitbang =
132 {
133 .read = zy1000_read,
134 .write = zy1000_write,
135 .reset = zy1000_reset
136 };
137
138
139
140 static void zy1000_write(int tck, int tms, int tdi)
141 {
142
143 }
144
145 int zy1000_read(void)
146 {
147 return -1;
148 }
149
150 extern bool readSRST(void);
151
152 void zy1000_reset(int trst, int srst)
153 {
154 LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst);
155 if(!srst)
156 {
157 ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x00000001);
158 }
159 else
160 {
161 /* Danger!!! if clk!=0 when in
162 * idle in TAP_IDLE, reset halt on str912 will fail.
163 */
164 ZY1000_POKE(ZY1000_JTAG_BASE+0x10, 0x00000001);
165 }
166
167 if(!trst)
168 {
169 ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x00000002);
170 }
171 else
172 {
173 /* assert reset */
174 ZY1000_POKE(ZY1000_JTAG_BASE+0x10, 0x00000002);
175 }
176
177 if (trst||(srst&&(jtag_reset_config & RESET_SRST_PULLS_TRST)))
178 {
179 waitIdle();
180 /* we're now in the RESET state until trst is deasserted */
181 ZY1000_POKE(ZY1000_JTAG_BASE+0x20, TAP_RESET);
182 } else
183 {
184 /* We'll get RCLK failure when we assert TRST, so clear any false positives here */
185 ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x400);
186 }
187
188 /* wait for srst to float back up */
189 if (!srst)
190 {
191 int i;
192 for (i=0; i<1000; i++)
193 {
194 // We don't want to sense our own reset, so we clear here.
195 // There is of course a timing hole where we could loose
196 // a "real" reset.
197 if (!readSRST())
198 break;
199
200 /* wait 1ms */
201 alive_sleep(1);
202 }
203
204 if (i==1000)
205 {
206 LOG_USER("SRST didn't deassert after %dms", i);
207 } else if (i>1)
208 {
209 LOG_USER("SRST took %dms to deassert", i);
210 }
211 }
212 }
213
214 int zy1000_speed(int speed)
215 {
216 if(speed == 0)
217 {
218 /*0 means RCLK*/
219 speed = 0;
220 ZY1000_POKE(ZY1000_JTAG_BASE+0x10, 0x100);
221 LOG_DEBUG("jtag_speed using RCLK");
222 }
223 else
224 {
225 if(speed > 8190 || speed < 2)
226 {
227 LOG_USER("valid ZY1000 jtag_speed=[8190,2]. Divisor is 64MHz / even values between 8190-2, i.e. min 7814Hz, max 32MHz");
228 return ERROR_INVALID_ARGUMENTS;
229 }
230
231 LOG_USER("jtag_speed %d => JTAG clk=%f", speed, 64.0/(float)speed);
232 ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x100);
233 ZY1000_POKE(ZY1000_JTAG_BASE+0x1c, speed&~1);
234 }
235 return ERROR_OK;
236 }
237
238 static bool savePower;
239
240
241 static void setPower(bool power)
242 {
243 savePower = power;
244 if (power)
245 {
246 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x14, 0x8);
247 } else
248 {
249 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x10, 0x8);
250 }
251 }
252
253 int handle_power_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
254 {
255 if (argc > 1)
256 {
257 return ERROR_INVALID_ARGUMENTS;
258 }
259
260 if (argc == 1)
261 {
262 if (strcmp(args[0], "on") == 0)
263 {
264 setPower(1);
265 }
266 else if (strcmp(args[0], "off") == 0)
267 {
268 setPower(0);
269 } else
270 {
271 command_print(cmd_ctx, "arg is \"on\" or \"off\"");
272 return ERROR_INVALID_ARGUMENTS;
273 }
274 }
275
276 command_print(cmd_ctx, "Target power %s", savePower ? "on" : "off");
277
278 return ERROR_OK;
279 }
280
281
282 /* Give TELNET a way to find out what version this is */
283 static int jim_zy1000_version(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
284 {
285 if ((argc < 1) || (argc > 2))
286 return JIM_ERR;
287 char buff[128];
288 const char *version_str=NULL;
289
290 if (argc == 1)
291 {
292 version_str=ZYLIN_OPENOCD_VERSION;
293 } else
294 {
295 const char *str = Jim_GetString(argv[1], NULL);
296 if (strcmp("openocd", str) == 0)
297 {
298 int revision;
299 revision = atol(ZYLIN_OPENOCD+strlen("XRevision: "));
300 sprintf(buff, "%d", revision);
301 version_str=buff;
302 }
303 else if (strcmp("zy1000", str) == 0)
304 {
305 version_str=ZYLIN_VERSION;
306 }
307 else if (strcmp("date", str) == 0)
308 {
309 version_str=ZYLIN_DATE;
310 }
311 else
312 {
313 return JIM_ERR;
314 }
315 }
316
317 Jim_SetResult(interp, Jim_NewStringObj(interp, version_str, -1));
318
319 return JIM_OK;
320 }
321
322
323 static int
324 zylinjtag_Jim_Command_powerstatus(Jim_Interp *interp,
325 int argc,
326 Jim_Obj * const *argv)
327 {
328 if (argc != 1)
329 {
330 Jim_WrongNumArgs(interp, 1, argv, "powerstatus");
331 return JIM_ERR;
332 }
333
334 cyg_uint32 status;
335 ZY1000_PEEK(ZY1000_JTAG_BASE+0x10, status);
336
337 Jim_SetResult(interp, Jim_NewIntObj(interp, (status&0x80)!=0));
338
339 return JIM_OK;
340 }
341
342 int zy1000_register_commands(struct command_context_s *cmd_ctx)
343 {
344 register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,
345 "power <on/off> - turn power switch to target on/off. No arguments - print status.");
346
347 Jim_CreateCommand(interp, "zy1000_version", jim_zy1000_version, NULL, NULL);
348
349
350 Jim_CreateCommand(interp, "powerstatus", zylinjtag_Jim_Command_powerstatus, NULL, NULL);
351
352 return ERROR_OK;
353 }
354
355
356
357
358 int zy1000_init(void)
359 {
360 LOG_USER("%s", ZYLIN_OPENOCD_VERSION);
361
362 ZY1000_POKE(ZY1000_JTAG_BASE+0x10, 0x30); // Turn on LED1 & LED2
363
364 setPower(true); // on by default
365
366
367 /* deassert resets. Important to avoid infinite loop waiting for SRST to deassert */
368 zy1000_reset(0, 0);
369 zy1000_speed(jtag_speed);
370
371 bitbang_interface = &zy1000_bitbang;
372
373 return ERROR_OK;
374 }
375
376 int zy1000_quit(void)
377 {
378
379 return ERROR_OK;
380 }
381
382
383 void interface_jtag_add_scan_check_alloc(scan_field_t *field)
384 {
385 /* We're executing this synchronously, so try to use local storage. */
386 if (field->num_bits > 32)
387 {
388 unsigned num_bytes = TAP_SCAN_BYTES(field->num_bits);
389 field->in_value = (u8 *)malloc(num_bytes);
390 field->allocated = 1;
391 }
392 else
393 field->in_value = field->intmp;
394 }
395
396
397 int interface_jtag_execute_queue(void)
398 {
399 cyg_uint32 empty;
400
401 waitIdle();
402 ZY1000_PEEK(ZY1000_JTAG_BASE+0x10, empty);
403 /* clear JTAG error register */
404 ZY1000_POKE(ZY1000_JTAG_BASE+0x14, 0x400);
405
406 if ((empty&0x400)!=0)
407 {
408 LOG_WARNING("RCLK timeout");
409 /* the error is informative only as we don't want to break the firmware if there
410 * is a false positive.
411 */
412 // return ERROR_FAIL;
413 }
414 return ERROR_OK;
415 }
416
417
418
419
420
421 static cyg_uint32 getShiftValue(void)
422 {
423 cyg_uint32 value;
424 waitIdle();
425 ZY1000_PEEK(ZY1000_JTAG_BASE+0xc, value);
426 VERBOSE(LOG_INFO("getShiftValue %08x", value));
427 return value;
428 }
429 #if 0
430 static cyg_uint32 getShiftValueFlip(void)
431 {
432 cyg_uint32 value;
433 waitIdle();
434 ZY1000_PEEK(ZY1000_JTAG_BASE+0x18, value);
435 VERBOSE(LOG_INFO("getShiftValue %08x (flipped)", value));
436 return value;
437 }
438 #endif
439
440 #if 0
441 static void shiftValueInnerFlip(const tap_state_t state, const tap_state_t endState, int repeat, cyg_uint32 value)
442 {
443 VERBOSE(LOG_INFO("shiftValueInner %s %s %d %08x (flipped)", tap_state_name(state), tap_state_name(endState), repeat, value));
444 cyg_uint32 a,b;
445 a=state;
446 b=endState;
447 ZY1000_POKE(ZY1000_JTAG_BASE+0xc, value);
448 ZY1000_POKE(ZY1000_JTAG_BASE+0x8, (1<<15)|(repeat<<8)|(a<<4)|b);
449 VERBOSE(getShiftValueFlip());
450 }
451 #endif
452
453 extern int jtag_check_value(u8 *captured, void *priv);
454
455 static void gotoEndState(void)
456 {
457 setCurrentState(cmd_queue_end_state);
458 }
459
460 static __inline void scanFields(int num_fields, scan_field_t *fields, tap_state_t shiftState, tap_state_t end_state)
461 {
462 int i;
463 int j;
464 int k;
465
466 for (i = 0; i < num_fields; i++)
467 {
468 cyg_uint32 value;
469
470 static u8 *in_buff=NULL; /* pointer to buffer for scanned data */
471 static int in_buff_size=0;
472 u8 *inBuffer=NULL;
473
474
475 // figure out where to store the input data
476 int num_bits=fields[i].num_bits;
477 if (fields[i].in_value!=NULL)
478 {
479 inBuffer=fields[i].in_value;
480 }
481
482 // here we shuffle N bits out/in
483 j=0;
484 while (j<num_bits)
485 {
486 tap_state_t pause_state;
487 int l;
488 k=num_bits-j;
489 pause_state=(shiftState==TAP_DRSHIFT)?TAP_DRSHIFT:TAP_IRSHIFT;
490 if (k>32)
491 {
492 k=32;
493 /* we have more to shift out */
494 } else if (i == num_fields-1)
495 {
496 /* this was the last to shift out this time */
497 pause_state=end_state;
498 }
499
500 // we have (num_bits+7)/8 bytes of bits to toggle out.
501 // bits are pushed out LSB to MSB
502 value=0;
503 if (fields[i].out_value!=NULL)
504 {
505 for (l=0; l<k; l+=8)
506 {
507 value|=fields[i].out_value[(j+l)/8]<<l;
508 }
509 }
510 /* mask away unused bits for easier debugging */
511 value&=~(((u32)0xffffffff)<<k);
512
513 shiftValueInner(shiftState, pause_state, k, value);
514
515 if (inBuffer!=NULL)
516 {
517 // data in, LSB to MSB
518 value=getShiftValue();
519 // we're shifting in data to MSB, shift data to be aligned for returning the value
520 value >>= 32-k;
521
522 for (l=0; l<k; l+=8)
523 {
524 inBuffer[(j+l)/8]=(value>>l)&0xff;
525 }
526 }
527 j+=k;
528 }
529 }
530 }
531
532 int interface_jtag_add_end_state(tap_state_t state)
533 {
534 return ERROR_OK;
535 }
536
537
538 int interface_jtag_add_ir_scan(int num_fields, const scan_field_t *fields, tap_state_t state)
539 {
540
541 int j;
542 int scan_size = 0;
543 jtag_tap_t *tap, *nextTap;
544 for(tap = jtag_NextEnabledTap(NULL); tap!= NULL; tap=nextTap)
545 {
546 nextTap=jtag_NextEnabledTap(tap);
547 tap_state_t end_state;
548 if (nextTap==NULL)
549 {
550 end_state = cmd_queue_end_state;
551 } else
552 {
553 end_state = TAP_IRSHIFT;
554 }
555
556 int found = 0;
557
558 scan_size = tap->ir_length;
559
560 /* search the list */
561 for (j=0; j < num_fields; j++)
562 {
563 if (tap == fields[j].tap)
564 {
565 found = 1;
566
567 scanFields(1, fields+j, TAP_IRSHIFT, end_state);
568 /* update device information */
569 buf_cpy(fields[j].out_value, tap->cur_instr, scan_size);
570
571 tap->bypass = 0;
572 break;
573 }
574 }
575
576 if (!found)
577 {
578 /* if a device isn't listed, set it to BYPASS */
579 u8 ones[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
580
581 scan_field_t tmp;
582 memset(&tmp, 0, sizeof(tmp));
583 tmp.out_value = ones;
584 tmp.num_bits = scan_size;
585 scanFields(1, &tmp, TAP_IRSHIFT, end_state);
586 /* update device information */
587 buf_cpy(tmp.out_value, tap->cur_instr, scan_size);
588 tap->bypass = 1;
589 }
590 }
591
592 return ERROR_OK;
593 }
594
595
596
597
598
599 int interface_jtag_add_plain_ir_scan(int num_fields, const scan_field_t *fields, tap_state_t state)
600 {
601 scanFields(num_fields, fields, TAP_IRSHIFT, cmd_queue_end_state);
602
603 return ERROR_OK;
604 }
605
606 /*extern jtag_command_t **jtag_get_last_command_p(void);*/
607
608 int interface_jtag_add_dr_scan(int num_fields, const scan_field_t *fields, tap_state_t state)
609 {
610
611 int j;
612 jtag_tap_t *tap, *nextTap;
613 for(tap = jtag_NextEnabledTap(NULL); tap!= NULL; tap=nextTap)
614 {
615 nextTap=jtag_NextEnabledTap(tap);
616 int found=0;
617 tap_state_t end_state;
618 if (nextTap==NULL)
619 {
620 end_state = cmd_queue_end_state;
621 } else
622 {
623 end_state = TAP_DRSHIFT;
624 }
625
626 for (j=0; j < num_fields; j++)
627 {
628 if (tap == fields[j].tap)
629 {
630 found = 1;
631
632 scanFields(1, fields+j, TAP_DRSHIFT, end_state);
633 }
634 }
635 if (!found)
636 {
637 scan_field_t tmp;
638 /* program the scan field to 1 bit length, and ignore it's value */
639 tmp.num_bits = 1;
640 tmp.out_value = NULL;
641 tmp.in_value = NULL;
642
643 scanFields(1, &tmp, TAP_DRSHIFT, end_state);
644 }
645 else
646 {
647 }
648 }
649 return ERROR_OK;
650 }
651
652 int interface_jtag_add_plain_dr_scan(int num_fields, const scan_field_t *fields, tap_state_t state)
653 {
654 scanFields(num_fields, fields, TAP_DRSHIFT, cmd_queue_end_state);
655 return ERROR_OK;
656 }
657
658
659 int interface_jtag_add_tlr()
660 {
661 setCurrentState(TAP_RESET);
662 return ERROR_OK;
663 }
664
665
666
667
668 extern int jtag_nsrst_delay;
669 extern int jtag_ntrst_delay;
670
671 int interface_jtag_add_reset(int req_trst, int req_srst)
672 {
673 zy1000_reset(req_trst, req_srst);
674 return ERROR_OK;
675 }
676
677 static int zy1000_jtag_add_clocks(int num_cycles, tap_state_t state, tap_state_t clockstate)
678 {
679 /* num_cycles can be 0 */
680 setCurrentState(clockstate);
681
682 /* execute num_cycles, 32 at the time. */
683 int i;
684 for (i=0; i<num_cycles; i+=32)
685 {
686 int num;
687 num=32;
688 if (num_cycles-i<num)
689 {
690 num=num_cycles-i;
691 }
692 shiftValueInner(clockstate, clockstate, num, 0);
693 }
694
695 #if !TEST_MANUAL()
696 /* finish in end_state */
697 setCurrentState(state);
698 #else
699 tap_state_t t=TAP_IDLE;
700 /* test manual drive code on any target */
701 int tms;
702 u8 tms_scan = tap_get_tms_path(t, state);
703 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
704
705 for (i = 0; i < tms_count; i++)
706 {
707 tms = (tms_scan >> i) & 1;
708 waitIdle();
709 ZY1000_POKE(ZY1000_JTAG_BASE+0x28, tms);
710 }
711 waitIdle();
712 ZY1000_POKE(ZY1000_JTAG_BASE+0x20, state);
713 #endif
714
715
716 return ERROR_OK;
717 }
718
719 int interface_jtag_add_runtest(int num_cycles, tap_state_t state)
720 {
721 return zy1000_jtag_add_clocks(num_cycles, state, TAP_IDLE);
722 }
723
724 int interface_jtag_add_clocks(int num_cycles)
725 {
726 return zy1000_jtag_add_clocks(num_cycles, cmd_queue_cur_state, cmd_queue_end_state);
727 }
728
729 int interface_jtag_add_sleep(u32 us)
730 {
731 jtag_sleep(us);
732 return ERROR_OK;
733 }
734
735 int interface_jtag_add_pathmove(int num_states, const tap_state_t *path)
736 {
737 int state_count;
738 int tms = 0;
739
740 /*wait for the fifo to be empty*/
741 waitIdle();
742
743 state_count = 0;
744
745 tap_state_t cur_state=cmd_queue_cur_state;
746
747 while (num_states)
748 {
749 if (tap_state_transition(cur_state, false) == path[state_count])
750 {
751 tms = 0;
752 }
753 else if (tap_state_transition(cur_state, true) == path[state_count])
754 {
755 tms = 1;
756 }
757 else
758 {
759 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(cur_state), tap_state_name(path[state_count]));
760 exit(-1);
761 }
762
763 waitIdle();
764 ZY1000_POKE(ZY1000_JTAG_BASE+0x28, tms);
765
766 cur_state = path[state_count];
767 state_count++;
768 num_states--;
769 }
770
771 waitIdle();
772 ZY1000_POKE(ZY1000_JTAG_BASE+0x20, cur_state);
773 return ERROR_OK;
774 }
775
776
777
778 void embeddedice_write_dcc(jtag_tap_t *tap, int reg_addr, u8 *buffer, int little, int count)
779 {
780 // static int const reg_addr=0x5;
781 tap_state_t end_state=cmd_queue_end_state;
782 if (jtag_NextEnabledTap(jtag_NextEnabledTap(NULL))==NULL)
783 {
784 /* better performance via code duplication */
785 if (little)
786 {
787 int i;
788 for (i = 0; i < count; i++)
789 {
790 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, fast_target_buffer_get_u32(buffer, 1));
791 shiftValueInner(TAP_DRSHIFT, end_state, 6, reg_addr|(1<<5));
792 buffer+=4;
793 }
794 } else
795 {
796 int i;
797 for (i = 0; i < count; i++)
798 {
799 shiftValueInner(TAP_DRSHIFT, TAP_DRSHIFT, 32, fast_target_buffer_get_u32(buffer, 0));
800 shiftValueInner(TAP_DRSHIFT, end_state, 6, reg_addr|(1<<5));
801 buffer+=4;
802 }
803 }
804 }
805 else
806 {
807 int i;
808 for (i = 0; i < count; i++)
809 {
810 embeddedice_write_reg_inner(tap, reg_addr, fast_target_buffer_get_u32(buffer, little));
811 buffer += 4;
812 }
813 }
814 }
815
816 int loadFile(const char *fileName, void **data, int *len);
817
818 /* boolean parameter stored on config */
819 int boolParam(char *var)
820 {
821 bool result = false;
822 char *name = alloc_printf("%s/%s", zylin_config_dir, var);
823 if (name == NULL)
824 return result;
825
826 void *data;
827 int len;
828 if (loadFile(name, &data, &len) == ERROR_OK)
829 {
830 if (len > 1)
831 len = 1;
832 result = strncmp((char *) data, "1", len) == 0;
833 free(data);
834 }
835 free(name);
836 return result;
837 }
838
839

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)