Audit and eliminate redundant #include directives in main src/ files.
[openocd.git] / src / ecosboard.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
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "configuration.h"
25 #include "time_support.h"
26
27 #include "jtag.h"
28 #include "xsvf.h"
29 #include "svf.h"
30 #include "target.h"
31 #include "flash.h"
32 #include "nand.h"
33 #include "pld.h"
34 #include "rom.h"
35
36 #include "server.h"
37 #include "telnet_server.h"
38 #include "gdb_server.h"
39
40 #include <pkgconf/fs_jffs2.h> // Address of JFFS2
41 #include <network.h>
42
43 #include <arpa/inet.h>
44 #include <dirent.h>
45 #include <net/if.h>
46 #include <netdb.h>
47 #include <netinet/tcp.h>
48 #include <stdarg.h>
49 #include <sys/ioctl.h>
50 #include <sys/stat.h>
51
52 #include <cyg/athttpd/http.h>
53 #include <cyg/athttpd/socket.h>
54 #include <cyg/athttpd/handler.h>
55 #include <cyg/athttpd/cgi.h>
56 #include <cyg/athttpd/forms.h>
57 #include <cyg/discover/discover.h>
58 #include <cyg/fileio/fileio.h>
59 #include <cyg/hal/hal_diag.h>
60 #include <cyg/io/flash.h>
61 #include <cyg/io/serialio.h>
62 #include <cyg/io/io.h>
63 #include <cyg/kernel/kapi.h>
64
65 #ifdef HAVE_IFADDRS_H
66 #include <ifaddrs.h>
67 #endif
68 #ifdef HAVE_STRINGS_H
69 #include <strings.h>
70 #endif
71
72 #define MAX_IFS 64
73 #if defined(CYGPKG_NET_FREEBSD_STACK)
74 #include <tftp_support.h>
75 /* posix compatibility broken*/
76 struct tftpd_fileops fileops =
77 {
78 (int (*)(const char *, int))open,
79 close,
80 (int (*)(int, const void *, int))write,
81 ( int (*)(int, void *, int))read
82 };
83
84 #endif
85
86
87 void diag_write(char *buf, int len)
88 {
89 int j;
90 for (j = 0; j < len; j++)
91 {
92 diag_printf("%c", buf[j]);
93 }
94 }
95
96 static bool serialLog = true;
97 static bool writeLog = true;
98
99 char hwaddr[512];
100
101
102 extern flash_driver_t *flash_drivers[];
103 extern target_type_t *target_types[];
104
105 #ifdef CYGPKG_PROFILE_GPROF
106 #include <cyg/profile/profile.h>
107
108 extern char _stext, _etext; // Defined by the linker
109
110 static char *start_of_code=&_stext;
111 static char *end_of_code=&_etext;
112
113 void start_profile(void)
114 {
115 // This starts up the system-wide profiling, gathering
116 // profile information on all of the code, with a 16 byte
117 // "bucket" size, at a rate of 100us/profile hit.
118 // Note: a bucket size of 16 will give pretty good function
119 // resolution. Much smaller and the buffer becomes
120 // much too large for very little gain.
121 // Note: a timer period of 100us is also a reasonable
122 // compromise. Any smaller and the overhead of
123 // handling the timter (profile) interrupt could
124 // swamp the system. A fast processor might get
125 // by with a smaller value, but a slow one could
126 // even be swamped by this value. If the value is
127 // too large, the usefulness of the profile is reduced.
128
129 // no more interrupts than 1/10ms.
130 //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
131 // profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
132 profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
133 }
134 #endif
135
136 extern int eth0_up;
137 static FILE *log;
138
139 static char reboot_stack[2048];
140
141 static void zylinjtag_reboot(cyg_addrword_t data)
142 {
143 serialLog = true;
144 diag_printf("Rebooting in 100 ticks..\n");
145 cyg_thread_delay(100);
146 diag_printf("Unmounting /config..\n");
147 umount("/config");
148 diag_printf("Rebooting..\n");
149 HAL_PLATFORM_RESET();
150 }
151 static cyg_thread zylinjtag_thread_object;
152 static cyg_handle_t zylinjtag_thread_handle;
153
154 void reboot(void)
155 {
156 cyg_thread_create(1, zylinjtag_reboot, (cyg_addrword_t) 0, "reboot Thread",
157 (void *) reboot_stack, sizeof(reboot_stack),
158 &zylinjtag_thread_handle, &zylinjtag_thread_object);
159 cyg_thread_resume(zylinjtag_thread_handle);
160 }
161
162 int configuration_output_handler(struct command_context_s *context,
163 const char* line)
164 {
165 diag_printf("%s", line);
166
167 return ERROR_OK;
168 }
169
170 int zy1000_configuration_output_handler_log(struct command_context_s *context,
171 const char* line)
172 {
173 LOG_USER_N("%s", line);
174
175 return ERROR_OK;
176 }
177
178 #ifdef CYGPKG_PROFILE_GPROF
179 extern void start_profile(void);
180
181 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
182 {
183 command_print(cmd_ctx, "Profiling started");
184 start_profile();
185 return ERROR_OK;
186 }
187
188 #endif
189
190 externC void phi_init_all_network_interfaces(void);
191
192 command_context_t *cmd_ctx;
193
194 static bool webRunning = false;
195
196 void keep_webserver(void)
197 {
198 // Target initialisation is only attempted at startup, so we sleep forever and
199 // let the http server bail us out(i.e. get config files set up).
200 diag_printf("OpenOCD has invoked exit().\n"
201 "Use web server to correct any configuration settings and reboot.\n");
202 if (!webRunning)
203 reboot();
204
205 // exit() will terminate the current thread and we we'll then sleep eternally or
206 // we'll have a reboot scheduled.
207 }
208
209 extern void printDccChar(char c);
210
211 static char logBuffer[128 * 1024];
212 static const int logSize = sizeof(logBuffer);
213 int writePtr = 0;
214 int logCount = 0;
215
216 void _zylinjtag_diag_write_char(char c, void **param)
217 {
218 if (writeLog)
219 {
220 logBuffer[writePtr] = c;
221 writePtr = (writePtr + 1) % logSize;
222 logCount++;
223 }
224 if (serialLog)
225 {
226 if (c == '\n')
227 {
228 HAL_DIAG_WRITE_CHAR('\r');
229 }
230 HAL_DIAG_WRITE_CHAR(c);
231 }
232
233 #ifdef CYGPKG_HAL_ZYLIN_PHI
234 printDccChar(c);
235 #endif
236 }
237
238 void copyfile(char *name2, char *name1);
239
240 void copydir(char *name, char *destdir);
241
242 #if 0
243 MTAB_ENTRY( romfs_mte1,
244 "/rom",
245 "romfs",
246 "",
247 (CYG_ADDRWORD) &filedata[0] );
248 #endif
249
250 void openocd_sleep_prelude(void)
251 {
252 cyg_mutex_unlock(&httpstate.jim_lock);
253 }
254
255 void openocd_sleep_postlude(void)
256 {
257 cyg_mutex_lock(&httpstate.jim_lock);
258 }
259
260 void format(void)
261 {
262 diag_printf("Formatting JFFS2...\n");
263
264 cyg_io_handle_t handle;
265
266 Cyg_ErrNo err;
267 err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
268 if (err != ENOERR)
269 {
270 diag_printf("Flash Error cyg_io_lookup: %d\n", err);
271 reboot();
272 }
273
274 cyg_uint32 len;
275 cyg_io_flash_getconfig_devsize_t ds;
276 len = sizeof(ds);
277 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
278 if (err != ENOERR)
279 {
280 diag_printf("Flash error cyg_io_get_config %d\n", err);
281 reboot();
282 }
283
284 cyg_io_flash_getconfig_erase_t e;
285 void *err_addr;
286 len = sizeof(e);
287
288 e.offset = 0;
289 e.len = ds.dev_size;
290 e.err_address = &err_addr;
291
292 diag_printf("Formatting 0x%08x bytes\n", ds.dev_size);
293 err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len);
294 if (err != ENOERR)
295 {
296 diag_printf("Flash erase error %d offset 0x%p\n", err, err_addr);
297 reboot();
298 }
299
300 diag_printf("Flash formatted successfully\n");
301
302 reboot();
303 }
304
305 static int zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp, int argc,
306 Jim_Obj * const *argv)
307 {
308 if (argc != 1)
309 {
310 return JIM_ERR;
311 }
312
313 format();
314 for (;;)
315 ;
316 }
317
318 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
319 Jim_Obj * const *argv)
320 {
321 cyg_handle_t thread = 0;
322 cyg_uint16 id = 0;
323 Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
324
325 /* Loop over the threads, and generate a table row for
326 * each.
327 */
328 while (cyg_thread_get_next(&thread, &id))
329 {
330 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
331
332 cyg_thread_info info;
333 char *state_string;
334
335 cyg_thread_get_info(thread, id, &info);
336
337 if (info.name == NULL)
338 info.name = "<no name>";
339
340 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
341 info.name, strlen(info.name)));
342
343 /* Translate the state into a string.
344 */
345 if (info.state == 0)
346 state_string = "RUN";
347 else if (info.state & 0x04)
348 state_string = "SUSP";
349 else
350 switch (info.state & 0x1b)
351 {
352 case 0x01:
353 state_string = "SLEEP";
354 break;
355 case 0x02:
356 state_string = "CNTSLEEP";
357 break;
358 case 0x08:
359 state_string = "CREATE";
360 break;
361 case 0x10:
362 state_string = "EXIT";
363 break;
364 default:
365 state_string = "????";
366 break;
367 }
368
369 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
370 state_string, strlen(state_string)));
371
372 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, id));
373 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
374 info.set_pri));
375 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp,
376 info.cur_pri));
377
378 Jim_ListAppendElement(interp, threads, threadObj);
379 }
380 Jim_SetResult(interp, threads);
381
382 return JIM_OK;
383 }
384
385 static int zylinjtag_Jim_Command_log(Jim_Interp *interp, int argc,
386 Jim_Obj * const *argv)
387 {
388 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
389
390 if (logCount >= logSize)
391 {
392 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer + logCount
393 % logSize, logSize - logCount % logSize);
394 }
395 Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
396
397 Jim_SetResult(interp, tclOutput);
398 return JIM_OK;
399 }
400
401 static int zylinjtag_Jim_Command_reboot(Jim_Interp *interp, int argc,
402 Jim_Obj * const *argv)
403 {
404 reboot();
405 return JIM_OK;
406 }
407
408
409 extern Jim_Interp *interp;
410
411 static void zylinjtag_startNetwork(void)
412 {
413 // Bring TCP/IP up immediately before we're ready to accept commands.
414 //
415 // That is as soon as a PING responds, we're accepting telnet sessions.
416 #if defined(CYGPKG_NET_FREEBSD_STACK)
417 phi_init_all_network_interfaces();
418 #else
419 lwip_init();
420 #endif
421 if (!eth0_up)
422 {
423 diag_printf("Network not up and running\n");
424 exit(-1);
425 }
426 #if defined(CYGPKG_NET_FREEBSD_STACK)
427 /*start TFTP*/
428 tftpd_start(69, &fileops);
429 #endif
430
431 cyg_httpd_init_tcl_interpreter();
432
433 interp = httpstate.jim_interp;
434
435 Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log,
436 NULL, NULL);
437 Jim_CreateCommand(httpstate.jim_interp, "reboot",
438 zylinjtag_Jim_Command_reboot, NULL, NULL);
439 Jim_CreateCommand(httpstate.jim_interp, "threads",
440 zylinjtag_Jim_Command_threads, NULL, NULL);
441 Jim_CreateCommand(httpstate.jim_interp, "format_jffs2",
442 zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
443
444 cyg_httpd_start();
445
446 webRunning = true;
447
448 diag_printf("Web server running\n");
449
450 int s;
451 struct ifreq ifr;
452 s = socket(AF_INET, SOCK_DGRAM, 0);
453 if (s >= 0)
454 {
455 strcpy(ifr.ifr_name, "eth0");
456 int res;
457 res = ioctl(s, SIOCGIFHWADDR, &ifr);
458 close(s);
459
460 if (res < 0)
461 {
462 diag_printf("Can't obtain MAC address\n");
463 reboot();
464 }
465 }
466
467 sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
468 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
469 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
470 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
471 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
472 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
473 (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
474
475 discover_message
476 = alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
477
478 discover_launch();
479 }
480
481 static void print_exception_handler(cyg_addrword_t data, cyg_code_t exception,
482 cyg_addrword_t info)
483 {
484 writeLog = false;
485 serialLog = true;
486 char *infoStr = "unknown";
487 switch (exception)
488 {
489 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
490 case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
491 infoStr = "undefined instruction";
492 break;
493 case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
494 infoStr = "software interrupt";
495 break;
496 case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
497 infoStr = "abort prefetch";
498 break;
499 case CYGNUM_HAL_VECTOR_ABORT_DATA:
500 infoStr = "abort data";
501 break;
502 #endif
503 default:
504 break;
505 }
506
507 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
508
509 diag_printf("Dumping log\n---\n");
510 if (logCount >= logSize)
511 {
512 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
513 }
514 diag_write(logBuffer, writePtr);
515
516 diag_printf("---\nLogdump complete.\n");
517 diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
518 diag_printf("\n---\nRebooting\n");
519 HAL_PLATFORM_RESET();
520
521 }
522
523 static void setHandler(cyg_code_t exception)
524 {
525 cyg_exception_handler_t *old_handler;
526 cyg_addrword_t old_data;
527
528 cyg_exception_set_handler(exception, print_exception_handler, 0,
529 &old_handler, &old_data);
530 }
531
532 static cyg_thread zylinjtag_uart_thread_object;
533 static cyg_handle_t zylinjtag_uart_thread_handle;
534 static char uart_stack[4096];
535
536 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
537 static char backwardBuffer[1024];
538
539 void setNoDelay(int session, int flag)
540 {
541 #if 1
542 // This decreases latency dramatically for e.g. GDB load which
543 // does not have a sliding window protocol
544 //
545 // Can cause *lots* of TCP/IP packets to be sent and it would have
546 // to be enabled/disabled on the fly to avoid the CPU being
547 // overloaded...
548 setsockopt(session, /* socket affected */
549 IPPROTO_TCP, /* set option at TCP level */
550 TCP_NODELAY, /* name of option */
551 (char *) &flag, /* the cast is historical
552 cruft */
553 sizeof(int)); /* length of option value */
554 #endif
555 }
556
557 struct
558 {
559 int req;
560 int actual;
561 int req2;
562 int actual2;
563 } tcpipSent[512 * 1024];
564 int cur;
565
566 static void zylinjtag_uart(cyg_addrword_t data)
567 {
568 int so_reuseaddr_option = 1;
569
570 int fd;
571 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
572 {
573 LOG_ERROR("error creating socket: %s", strerror(errno));
574 exit(-1);
575 }
576
577 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &so_reuseaddr_option,
578 sizeof(int));
579
580 struct sockaddr_in sin;
581 unsigned int address_size;
582 address_size = sizeof(sin);
583 memset(&sin, 0, sizeof(sin));
584 sin.sin_family = AF_INET;
585 sin.sin_addr.s_addr = INADDR_ANY;
586 sin.sin_port = htons(5555);
587
588 if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
589 {
590 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
591 exit(-1);
592 }
593
594 if (listen(fd, 1) == -1)
595 {
596 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
597 exit(-1);
598 }
599 // socket_nonblock(fd);
600
601
602 for (;;)
603 {
604 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
605 if (session < 0)
606 {
607 continue;
608 }
609
610 setNoDelay(session, 1);
611 int oldopts = fcntl(session, F_GETFL, 0);
612 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
613
614 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
615 if (serHandle < 0)
616 {
617 close(session);
618 continue;
619 }
620
621 #ifdef CYGPKG_PROFILE_GPROF
622 start_profile();
623 #endif
624 int actual = 0;
625 int actual2 = 0;
626 int pos, pos2;
627 pos = 0;
628 pos2 = 0;
629 cur = 0;
630 for (;;)
631 {
632 fd_set write_fds;
633 fd_set read_fds;
634 FD_ZERO(&write_fds);
635 FD_ZERO(&read_fds);
636 int fd_max = -1;
637 FD_SET(session, &read_fds);
638 fd_max = session;
639 FD_SET(serHandle, &read_fds);
640 if (serHandle > fd_max)
641 {
642 fd_max = serHandle;
643 }
644 /* Wait... */
645
646 cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
647 if ((actual == 0) && (actual2 == 0))
648 {
649 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
650 if (retval <= 0)
651 {
652 break;
653 }
654 }
655
656 if (actual2 <= 0)
657 {
658 memset(backwardBuffer, 's', sizeof(backwardBuffer));
659 actual2 = read(serHandle, backwardBuffer,
660 sizeof(backwardBuffer));
661 if (actual2 < 0)
662 {
663 if (errno != EAGAIN)
664 {
665 goto closeSession;
666 }
667 actual2 = 0;
668 }
669 pos2 = 0;
670 }
671
672 int x = actual2;
673 int y = 0;
674 if (actual2 > 0)
675 {
676 int written = write(session, backwardBuffer + pos2, actual2);
677 if (written <= 0)
678 goto closeSession;
679 actual2 -= written;
680 pos2 += written;
681 y = written;
682 }
683
684 if (FD_ISSET(session, &read_fds)
685 && (sizeof(forwardBuffer) > actual))
686 {
687 // NB! Here it is important that we empty the TCP/IP read buffer
688 // to make transmission tick right
689 memmove(forwardBuffer, forwardBuffer + pos, actual);
690 pos = 0;
691 int t;
692 // this will block if there is no data at all
693 t = read_socket(session, forwardBuffer + actual,
694 sizeof(forwardBuffer) - actual);
695 if (t <= 0)
696 {
697 goto closeSession;
698 }
699 actual += t;
700 }
701
702 int x2 = actual;
703 int y2 = 0;
704 if (actual > 0)
705 {
706 /* Do not put things into the serial buffer if it has something to send
707 * as that can cause a single byte to be sent at the time.
708 *
709 *
710 */
711 int written = write(serHandle, forwardBuffer + pos, actual);
712 if (written < 0)
713 {
714 if (errno != EAGAIN)
715 {
716 goto closeSession;
717 }
718 // The serial buffer is full
719 written = 0;
720 }
721 else
722 {
723 actual -= written;
724 pos += written;
725 }
726 y2 = written;
727 }
728 if (cur < 1024)
729 {
730 tcpipSent[cur].req = x;
731 tcpipSent[cur].actual = y;
732 tcpipSent[cur].req2 = x2;
733 tcpipSent[cur].actual2 = y2;
734 cur++;
735 }
736
737 }
738 closeSession: close(session);
739 close(serHandle);
740
741 int i;
742 for (i = 0; i < 1024; i++)
743 {
744 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual,
745 tcpipSent[i].req2, tcpipSent[i].actual2);
746
747 }
748 }
749 close(fd);
750
751 }
752
753 void startUart(void)
754 {
755 cyg_thread_create(1, zylinjtag_uart, (cyg_addrword_t) 0, "uart thread",
756 (void *) uart_stack, sizeof(uart_stack),
757 &zylinjtag_uart_thread_handle, &zylinjtag_uart_thread_object);
758 cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
759 cyg_thread_resume(zylinjtag_uart_thread_handle);
760 }
761
762 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd,
763 char **args, int argc)
764 {
765 static int current_baud = 38400;
766 if (argc == 0)
767 {
768 command_print(cmd_ctx, "%d", current_baud);
769 return ERROR_OK;
770 }
771 else if (argc != 1)
772 {
773 return ERROR_INVALID_ARGUMENTS;
774 }
775
776 current_baud = atol(args[0]);
777
778 int baud;
779 switch (current_baud)
780 {
781 case 9600:
782 baud = CYGNUM_SERIAL_BAUD_9600;
783 break;
784 case 19200:
785 baud = CYGNUM_SERIAL_BAUD_19200;
786 break;
787 case 38400:
788 baud = CYGNUM_SERIAL_BAUD_38400;
789 break;
790 case 57600:
791 baud = CYGNUM_SERIAL_BAUD_57600;
792 break;
793 case 115200:
794 baud = CYGNUM_SERIAL_BAUD_115200;
795 break;
796 case 230400:
797 baud = CYGNUM_SERIAL_BAUD_230400;
798 break;
799 default:
800 command_print(cmd_ctx, "unsupported baudrate");
801 return ERROR_INVALID_ARGUMENTS;
802 }
803
804 cyg_serial_info_t buf;
805 cyg_uint32 len = 1;
806 //get existing serial configuration
807 len = sizeof(cyg_serial_info_t);
808 int err;
809 cyg_io_handle_t serial_handle;
810
811 err = cyg_io_lookup("/dev/ser0", &serial_handle);
812 if (err != ENOERR)
813 {
814 LOG_ERROR("/dev/ser0 not found\n");
815 return ERROR_FAIL;
816 }
817
818 err = cyg_io_get_config(serial_handle,
819 CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
820 err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf,
821 &len);
822 if (err != ENOERR)
823 {
824 command_print(cmd_ctx, "Failed to get serial port settings %d", err);
825 return ERROR_OK;
826 }
827 buf.baud = baud;
828
829 err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf,
830 &len);
831 if (err != ENOERR)
832 {
833 command_print(cmd_ctx, "Failed to set serial port settings %d", err);
834 return ERROR_OK;
835 }
836
837 return ERROR_OK;
838 }
839
840 bool logAllToSerial = false;
841
842
843 int boolParam(char *var);
844
845
846 command_context_t *setup_command_handler(void);
847
848 extern const char *zylin_config_dir;
849
850 int add_default_dirs(void)
851 {
852 add_script_search_dir(zylin_config_dir);
853 add_script_search_dir("/rom/lib/openocd");
854 add_script_search_dir("/rom");
855 return ERROR_OK;
856 }
857
858 int ioutil_init(struct command_context_s *cmd_ctx);
859
860 int main(int argc, char *argv[])
861 {
862 /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
863 * need to allocate towards the end of the heap. */
864
865 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
866 setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
867 setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
868 setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
869 #endif
870
871 int err;
872
873 atexit(keep_webserver);
874
875 diag_init_putc(_zylinjtag_diag_write_char);
876 // We want this in the log.
877 diag_printf("Zylin ZY1000.\n");
878
879 err = mount("", "/ram", "ramfs");
880 if (err < 0)
881 {
882 diag_printf("unable to mount ramfs\n");
883 }
884 chdir("/ram");
885
886 char address[16];
887 sprintf(address, "%p", &filedata[0]);
888 err = mount(address, "/rom", "romfs");
889 if (err < 0)
890 {
891 diag_printf("unable to mount /rom\n");
892 }
893
894 err = mount("", "/log", "logfs");
895 if (err < 0)
896 {
897 diag_printf("unable to mount logfs\n");
898 }
899
900 err = mount("", "/tftp", "tftpfs");
901 if (err < 0)
902 {
903 diag_printf("unable to mount logfs\n");
904 }
905
906 log = fopen("/log/log", "w");
907 if (log == NULL)
908 {
909 diag_printf("Could not open log file /ram/log\n");
910 exit(-1);
911 }
912
913
914 copydir("/rom", "/ram/cgi");
915
916 err = mount("/dev/flash1", "/config", "jffs2");
917 if (err < 0)
918 {
919 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
920 err = mount("", "/config", "ramfs");
921 if (err < 0)
922 {
923 diag_printf("unable to mount /config as ramdisk.\n");
924 reboot();
925 }
926 }
927 else
928 {
929 /* are we using a ram disk instead of a flash disk? This is used
930 * for ZY1000 live demo...
931 *
932 * copy over flash disk to ram block device
933 */
934 if (boolParam("ramdisk"))
935 {
936 diag_printf("Unmounting /config from flash and using ram instead\n");
937 err = umount("/config");
938 if (err < 0)
939 {
940 diag_printf("unable to unmount jffs\n");
941 reboot();
942 }
943
944 err = mount("/dev/flash1", "/config2", "jffs2");
945 if (err < 0)
946 {
947 diag_printf("unable to mount jffs\n");
948 reboot();
949 }
950
951 err = mount("", "/config", "ramfs");
952 if (err < 0)
953 {
954 diag_printf("unable to mount ram block device\n");
955 reboot();
956 }
957
958 // copydir("/config2", "/config");
959 copyfile("/config2/ip", "/config/ip");
960 copydir("/config2/settings", "/config/settings");
961
962 umount("/config2");
963 }
964 }
965
966 mkdir(zylin_config_dir, 0777);
967 char *dirname=alloc_printf("%s/target", zylin_config_dir);
968 mkdir(dirname, 0777);
969 free(dirname);
970 dirname=alloc_printf("%s/board", zylin_config_dir);
971 mkdir(dirname, 0777);
972 free(dirname);
973 dirname=alloc_printf("%s/event", zylin_config_dir);
974 mkdir(dirname, 0777);
975 free(dirname);
976
977 logAllToSerial = boolParam("logserial");
978
979 // We need the network & web server in case there is something wrong with
980 // the config files that invoke exit()
981 zylinjtag_startNetwork();
982
983 /* we're going to access the jim interpreter from here on... */
984 openocd_sleep_postlude();
985 startUart();
986
987 add_default_dirs();
988
989 /* initialize commandline interface */
990 command_context_t * cmd_ctx;
991 cmd_ctx = setup_command_handler();
992 command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
993 command_context_mode(cmd_ctx, COMMAND_CONFIG);
994
995 #if BUILD_IOUTIL
996 if (ioutil_init(cmd_ctx) != ERROR_OK)
997 {
998 return EXIT_FAILURE;
999 }
1000 #endif
1001
1002
1003 #ifdef CYGPKG_PROFILE_GPROF
1004 register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1005 COMMAND_ANY, NULL);
1006 #endif
1007
1008 register_command(cmd_ctx, NULL, "uart", handle_uart_command, COMMAND_ANY,
1009 "uart <baud> - forward uart on port 5555");
1010
1011 int errVal;
1012 errVal = log_init(cmd_ctx);
1013 if (errVal != ERROR_OK)
1014 {
1015 diag_printf("log_init() failed %d\n", errVal);
1016 exit(-1);
1017 }
1018
1019 set_log_output(cmd_ctx, log);
1020
1021 LOG_DEBUG("log init complete");
1022
1023 // diag_printf("Executing config files\n");
1024
1025 if (logAllToSerial)
1026 {
1027 diag_printf(
1028 "%s/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n", zylin_config_dir);
1029 command_run_line(cmd_ctx, "debug_level 3");
1030 }
1031
1032 command_run_linef(cmd_ctx, "script /rom/openocd.cfg");
1033
1034 // FIX!!! Yuk!
1035 // diag_printf() is really invoked from many more places than we trust it
1036 // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1037 //
1038 // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1039 // fingers that it doesn't cause any crashes.
1040 diag_printf("Init complete, GDB & telnet servers launched.\n");
1041 command_set_output_handler(cmd_ctx,
1042 zy1000_configuration_output_handler_log, NULL);
1043 if (!logAllToSerial)
1044 {
1045 serialLog = false;
1046 }
1047
1048 /* handle network connections */
1049 server_loop(cmd_ctx);
1050 openocd_sleep_prelude();
1051
1052 /* shut server down */
1053 server_quit();
1054
1055 /* free commandline interface */
1056 command_done(cmd_ctx);
1057 umount("/config");
1058
1059 exit(0);
1060 for (;;)
1061 ;
1062 }
1063
1064 cyg_int32 cyg_httpd_exec_cgi_tcl(char *file_name);
1065 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1066 {
1067 cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1068 return 0;
1069 }
1070
1071 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1072
1073 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1074 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1075
1076 #include <pkgconf/system.h>
1077 #include <pkgconf/hal.h>
1078 #include <pkgconf/kernel.h>
1079 #include <pkgconf/io_fileio.h>
1080 #include <pkgconf/fs_rom.h>
1081
1082 #include <cyg/kernel/ktypes.h> // base kernel types
1083 #include <cyg/infra/cyg_trac.h> // tracing macros
1084 #include <cyg/infra/cyg_ass.h> // assertion macros
1085 #include <cyg/fileio/fileio.h>
1086 #include <cyg/kernel/kapi.h>
1087 #include <cyg/infra/diag.h>
1088
1089 //==========================================================================
1090 // Eventually we want to eXecute In Place from the ROM in a protected
1091 // environment, so we'll need executables to be aligned to a boundary
1092 // suitable for MMU protection. A suitable boundary would be the 4k
1093 // boundary in all the CPU architectures I am currently aware of.
1094
1095 // Forward definitions
1096
1097 // Filesystem operations
1098 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1099 static int tftpfs_umount(cyg_mtab_entry *mte);
1100 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1101 int mode, cyg_file *fte);
1102 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1103 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1104
1105 // File operations
1106 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1107 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
1108 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
1109
1110 //==========================================================================
1111 // Filesystem table entries
1112
1113 // -------------------------------------------------------------------------
1114 // Fstab entry.
1115 // This defines the entry in the filesystem table.
1116 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1117 // we should never block in any filesystem operations.
1118 #if 1
1119 FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,
1120 CYG_SYNCMODE_NONE,
1121 tftpfs_mount,
1122 tftpfs_umount,
1123 tftpfs_open,
1124 (cyg_fsop_unlink *)cyg_fileio_erofs,
1125 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1126 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1127 (cyg_fsop_rename *)cyg_fileio_erofs,
1128 (cyg_fsop_link *)cyg_fileio_erofs,
1129 (cyg_fsop_opendir *)cyg_fileio_erofs,
1130 (cyg_fsop_chdir *)cyg_fileio_erofs,
1131 (cyg_fsop_stat *)cyg_fileio_erofs,
1132 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1133 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1134 #endif
1135
1136 // -------------------------------------------------------------------------
1137 // mtab entry.
1138 // This defines a single ROMFS loaded into ROM at the configured address
1139 //
1140 // MTAB_ENTRY( rom_mte, // structure name
1141 // "/rom", // mount point
1142 // "romfs", // FIlesystem type
1143 // "", // hardware device
1144 // (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS // Address in ROM
1145 // );
1146
1147
1148 // -------------------------------------------------------------------------
1149 // File operations.
1150 // This set of file operations are used for normal open files.
1151
1152 static cyg_fileops tftpfs_fileops =
1153 { tftpfs_fo_read, tftpfs_fo_write, tftpfs_fo_lseek,
1154 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1155 tftpfs_fo_fsync, tftpfs_fo_close,
1156 (cyg_fileop_fstat *) cyg_fileio_erofs,
1157 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1158 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1159
1160 // -------------------------------------------------------------------------
1161 // tftpfs_mount()
1162 // Process a mount request. This mainly finds root for the
1163 // filesystem.
1164
1165 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1166 {
1167 return ENOERR;
1168 }
1169
1170 static int tftpfs_umount(cyg_mtab_entry *mte)
1171 {
1172 return ENOERR;
1173 }
1174
1175 struct Tftp
1176 {
1177 int write;
1178 int readFile;
1179 cyg_uint8 *mem;
1180 int actual;
1181 char *server;
1182 char *file;
1183 };
1184
1185 static void freeTftp(struct Tftp *t)
1186 {
1187 if (t == NULL)
1188 return;
1189 if (t->mem)
1190 free(t->mem);
1191 if (t->server)
1192 free(t->server);
1193 if (t->file)
1194 free(t->file);
1195 free(t);
1196 }
1197
1198 static const int tftpMaxSize = 8192 * 1024;
1199 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1200 int mode, cyg_file *file)
1201 {
1202 struct Tftp *tftp;
1203 tftp = malloc(sizeof(struct Tftp));
1204 if (tftp == NULL)
1205 return EMFILE;
1206 memset(tftp, 0, sizeof(struct Tftp));
1207
1208 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1209 file->f_type = CYG_FILE_TYPE_FILE;
1210 file->f_ops = &tftpfs_fileops;
1211 file->f_offset = 0;
1212 file->f_data = 0;
1213 file->f_xops = 0;
1214
1215 tftp->mem = malloc(tftpMaxSize);
1216 if (tftp->mem == NULL)
1217 {
1218 freeTftp(tftp);
1219 return EMFILE;
1220 }
1221
1222 char *server = strchr(name, '/');
1223 if (server == NULL)
1224 {
1225 freeTftp(tftp);
1226 return EMFILE;
1227 }
1228
1229 tftp->server = malloc(server - name + 1);
1230 if (tftp->server == NULL)
1231 {
1232 freeTftp(tftp);
1233 return EMFILE;
1234 }
1235 strncpy(tftp->server, name, server - name);
1236 tftp->server[server - name] = 0;
1237
1238 tftp->file = strdup(server + 1);
1239 if (tftp->file == NULL)
1240 {
1241 freeTftp(tftp);
1242 return EMFILE;
1243 }
1244
1245 file->f_data = (CYG_ADDRWORD) tftp;
1246
1247 return ENOERR;
1248 }
1249
1250 static int fetchTftp(struct Tftp *tftp)
1251 {
1252 if (!tftp->readFile)
1253 {
1254 int err;
1255 tftp->actual = tftp_client_get(tftp->file, tftp->server, 0, tftp->mem,
1256 tftpMaxSize, TFTP_OCTET, &err);
1257
1258 if (tftp->actual < 0)
1259 {
1260 return EMFILE;
1261 }
1262 tftp->readFile = 1;
1263 }
1264 return ENOERR;
1265 }
1266
1267 // -------------------------------------------------------------------------
1268 // tftpfs_fo_write()
1269 // Read data from file.
1270
1271 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1272 {
1273 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1274
1275 if (fetchTftp(tftp) != ENOERR)
1276 return EMFILE;
1277
1278 int i;
1279 off_t pos = fp->f_offset;
1280 int resid = 0;
1281 for (i = 0; i < uio->uio_iovcnt; i++)
1282 {
1283 cyg_iovec *iov = &uio->uio_iov[i];
1284 char *buf = (char *) iov->iov_base;
1285 off_t len = iov->iov_len;
1286
1287 if (len + pos > tftp->actual)
1288 {
1289 len = tftp->actual - pos;
1290 }
1291 resid += iov->iov_len - len;
1292
1293 memcpy(buf, tftp->mem + pos, len);
1294 pos += len;
1295
1296 }
1297 uio->uio_resid = resid;
1298 fp->f_offset = pos;
1299
1300 return ENOERR;
1301 }
1302
1303 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1304 {
1305 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1306
1307 int i;
1308 off_t pos = fp->f_offset;
1309 int resid = 0;
1310 for (i = 0; i < uio->uio_iovcnt; i++)
1311 {
1312 cyg_iovec *iov = &uio->uio_iov[i];
1313 char *buf = (char *) iov->iov_base;
1314 off_t len = iov->iov_len;
1315
1316 if (len + pos > tftpMaxSize)
1317 {
1318 len = tftpMaxSize - pos;
1319 }
1320 resid += iov->iov_len - len;
1321
1322 memcpy(tftp->mem + pos, buf, len);
1323 pos += len;
1324
1325 }
1326 uio->uio_resid = resid;
1327 fp->f_offset = pos;
1328
1329 tftp->write = 1;
1330
1331 return ENOERR;
1332 }
1333
1334 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1335 {
1336 int error = ENOERR;
1337 return error;
1338 }
1339
1340 // -------------------------------------------------------------------------
1341 // romfs_fo_close()
1342 // Close a file. We just clear out the data pointer.
1343
1344 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
1345 {
1346 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1347 int error = ENOERR;
1348
1349 if (tftp->write)
1350 {
1351 tftp_client_put(tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,
1352 TFTP_OCTET, &error);
1353 }
1354
1355 freeTftp(tftp);
1356 fp->f_data = 0;
1357 return error;
1358 }
1359
1360 // -------------------------------------------------------------------------
1361 // romfs_fo_lseek()
1362 // Seek to a new file position.
1363
1364 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
1365 {
1366 struct Tftp *tftp = (struct Tftp *) fp->f_data;
1367 off_t pos = *apos;
1368
1369 if (fetchTftp(tftp) != ENOERR)
1370 return EMFILE;
1371
1372 switch (whence)
1373 {
1374 case SEEK_SET:
1375 // Pos is already where we want to be.
1376 break;
1377
1378 case SEEK_CUR:
1379 // Add pos to current offset.
1380 pos += fp->f_offset;
1381 break;
1382
1383 case SEEK_END:
1384 // Add pos to file size.
1385 pos += tftp->actual;
1386 break;
1387
1388 default:
1389 return EINVAL;
1390 }
1391
1392 // Check that pos is still within current file size, or at the
1393 // very end.
1394 if (pos < 0 || pos > tftp->actual)
1395 return EINVAL;
1396
1397 // All OK, set fp offset and return new position.
1398 *apos = fp->f_offset = pos;
1399
1400 return ENOERR;
1401 }
1402
1403 void usleep(int us)
1404 {
1405 if (us > 10000)
1406 cyg_thread_delay(us / 10000 + 1);
1407 else
1408 HAL_DELAY_US(us);
1409 }
1410
1411 // Chunked version.
1412 cyg_int32 show_log_entry(CYG_HTTPD_STATE *phttpstate)
1413 {
1414 cyg_httpd_start_chunked("text");
1415 if (logCount >= logSize)
1416 {
1417 cyg_httpd_write_chunked(logBuffer + logCount % logSize, logSize
1418 - logCount % logSize);
1419 }
1420 cyg_httpd_write_chunked(logBuffer, writePtr);
1421 cyg_httpd_end_chunked();
1422 return -1;
1423 }
1424
1425 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
1426
1427 // Filesystem operations
1428 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1429 static int logfs_umount(cyg_mtab_entry *mte);
1430 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1431 int mode, cyg_file *fte);
1432 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1433
1434 // File operations
1435 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1436 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
1437
1438 #include <cyg/io/devtab.h>
1439
1440 //==========================================================================
1441 // Filesystem table entries
1442
1443 // -------------------------------------------------------------------------
1444 // Fstab entry.
1445 // This defines the entry in the filesystem table.
1446 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1447 // we should never block in any filesystem operations.
1448 FSTAB_ENTRY( logfs_fste, "logfs", 0,
1449 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
1450 logfs_mount,
1451 logfs_umount,
1452 logfs_open,
1453 (cyg_fsop_unlink *)cyg_fileio_erofs,
1454 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1455 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1456 (cyg_fsop_rename *)cyg_fileio_erofs,
1457 (cyg_fsop_link *)cyg_fileio_erofs,
1458 (cyg_fsop_opendir *)cyg_fileio_erofs,
1459 (cyg_fsop_chdir *)cyg_fileio_erofs,
1460 (cyg_fsop_stat *)cyg_fileio_erofs,
1461 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1462 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1463
1464 // -------------------------------------------------------------------------
1465 // File operations.
1466 // This set of file operations are used for normal open files.
1467
1468 static cyg_fileops logfs_fileops =
1469 { (cyg_fileop_read *) cyg_fileio_erofs, (cyg_fileop_write *) logfs_fo_write,
1470 (cyg_fileop_lseek *) cyg_fileio_erofs,
1471 (cyg_fileop_ioctl *) cyg_fileio_erofs, cyg_fileio_seltrue,
1472 logfs_fo_fsync, logfs_fo_close, (cyg_fileop_fstat *) cyg_fileio_erofs,
1473 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1474 (cyg_fileop_setinfo *) cyg_fileio_erofs, };
1475
1476 // -------------------------------------------------------------------------
1477 // logfs_mount()
1478 // Process a mount request. This mainly finds root for the
1479 // filesystem.
1480
1481 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1482 {
1483 return ENOERR;
1484 }
1485
1486 static int logfs_umount(cyg_mtab_entry *mte)
1487 {
1488 return ENOERR;
1489 }
1490
1491 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1492 int mode, cyg_file *file)
1493 {
1494 file->f_flag |= mode & CYG_FILE_MODE_MASK;
1495 file->f_type = CYG_FILE_TYPE_FILE;
1496 file->f_ops = &logfs_fileops;
1497 file->f_offset = 0;
1498 file->f_data = 0;
1499 file->f_xops = 0;
1500 return ENOERR;
1501 }
1502
1503 // -------------------------------------------------------------------------
1504 // logfs_fo_write()
1505 // Write data to file.
1506
1507 static int logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
1508 {
1509 int i;
1510 for (i = 0; i < uio->uio_iovcnt; i++)
1511 {
1512 cyg_iovec *iov = &uio->uio_iov[i];
1513 char *buf = (char *) iov->iov_base;
1514 off_t len = iov->iov_len;
1515
1516 diag_write(buf, len);
1517 }
1518 uio->uio_resid = 0;
1519
1520 return ENOERR;
1521 }
1522 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
1523 {
1524 return ENOERR;
1525 }
1526
1527 // -------------------------------------------------------------------------
1528 // romfs_fo_close()
1529 // Close a file. We just clear out the data pointer.
1530
1531 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
1532 {
1533 return ENOERR;
1534 }
1535

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)