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