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

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)