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

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)