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

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)