]> git.sur5r.net Git - openocd/blob - src/ecosboard.c
6326b9873dad52dd726041e35107721e41aa1083
[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 "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
85 #include <unistd.h>
86 #include <stdio.h>
87 #define MAX_IFS 64
88 #if defined(CYGPKG_NET_FREEBSD_STACK)
89 #include <tftp_support.h>
90 /* posix compatibility broken*/
91 struct tftpd_fileops fileops =
92 {
93         (int (*)(const char *, int))open,
94         close,
95         (int (*)(int, const void *, int))write,
96         ( int (*)(int, void *, int))read
97 };
98
99 #endif
100
101 #define ZYLIN_VERSION "1.48"
102 #define ZYLIN_DATE __DATE__
103 #define ZYLIN_TIME __TIME__
104 /* hmmm....  we can't pick up the right # during build if we've checked this out
105  * in Eclipse... arrggghh...*/
106 #define ZYLIN_OPENOCD "$Revision$"
107 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
108 #define ZYLIN_CONFIG_DIR "/config/settings"
109
110 void diag_write(char *buf, int len)
111 {
112         int j;
113         for (j = 0; j < len; j++)
114         {
115                 diag_printf("%c", buf[j]);
116         }
117 }
118
119 static bool serialLog = true;
120 static bool writeLog = true;
121
122 char hwaddr[512];
123
124
125 /* Give TELNET a way to find out what version this is */
126 int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,
127                 char **args, int argc)
128 {
129         if (argc > 1)
130         {
131                 return ERROR_COMMAND_SYNTAX_ERROR;
132         }
133         if (argc == 0)
134         {
135                 command_print(cmd_ctx, ZYLIN_OPENOCD_VERSION);
136         } else if (strcmp("openocd", args[0])==0)
137         {
138                 int revision;
139                 revision=atol(ZYLIN_OPENOCD+strlen("XRevision: "));
140                 command_print(cmd_ctx, "%d", revision);
141         } else if (strcmp("zy1000", args[0])==0)
142         {
143                 command_print(cmd_ctx, "%s", ZYLIN_VERSION);
144         } else if (strcmp("date", args[0])==0)
145         {
146                 command_print(cmd_ctx, "%s", ZYLIN_DATE);
147         } else
148         {
149                 return ERROR_COMMAND_SYNTAX_ERROR;
150         }
151
152         return ERROR_OK;
153 }
154
155
156
157
158 extern flash_driver_t *flash_drivers[];
159 extern target_type_t *target_types[];
160
161 #ifdef CYGPKG_PROFILE_GPROF
162 #include <cyg/profile/profile.h>
163
164 extern char _stext, _etext; // Defined by the linker
165
166 static char *start_of_code=&_stext;
167 static char *end_of_code=&_etext;
168
169 void start_profile(void)
170 {
171         // This starts up the system-wide profiling, gathering
172         // profile information on all of the code, with a 16 byte
173         // "bucket" size, at a rate of 100us/profile hit.
174         // Note: a bucket size of 16 will give pretty good function
175         //       resolution.  Much smaller and the buffer becomes
176         //       much too large for very little gain.
177         // Note: a timer period of 100us is also a reasonable
178         //       compromise.  Any smaller and the overhead of
179         //       handling the timter (profile) interrupt could
180         //       swamp the system.  A fast processor might get
181         //       by with a smaller value, but a slow one could
182         //       even be swamped by this value.  If the value is
183         //       too large, the usefulness of the profile is reduced.
184
185         // no more interrupts than 1/10ms.
186         //profile_on((void *)0, (void *)0x40000, 16, 10000); // SRAM
187 //      profile_on(0, &_etext, 16, 10000); // SRAM & DRAM
188         profile_on(start_of_code, end_of_code, 16, 10000); // Nios DRAM
189 }
190 #endif
191
192 // launch GDB server if a config file exists
193 bool zylinjtag_parse_config_file(struct command_context_s *cmd_ctx, const char *config_file_name)
194 {
195         bool foundFile = false;
196         FILE *config_file = NULL;
197         command_print(cmd_ctx, "executing config file %s", config_file_name);
198         config_file = fopen(config_file_name, "r");
199         if (config_file)
200         {
201                 fclose(config_file);
202                 int retval;
203                 retval = command_run_linef(cmd_ctx, "script %s", config_file_name);
204                 if (retval == ERROR_OK)
205                 {
206                         foundFile = true;
207                 }
208                 else
209                 {
210                         command_print(cmd_ctx, "Failed executing %s %d", config_file_name, retval);
211                 }
212         }
213         else
214         {
215                 command_print(cmd_ctx, "No %s found", config_file_name);
216         }
217
218         return foundFile;
219 }
220
221 extern int eth0_up;
222 static FILE *log;
223
224 static char reboot_stack[2048];
225
226
227 static void
228 zylinjtag_reboot(cyg_addrword_t data)
229 {
230         serialLog = true;
231         diag_printf("Rebooting in 100 ticks..\n");
232         cyg_thread_delay(100);
233         diag_printf("Unmounting /config..\n");
234         umount("/config");
235         diag_printf("Rebooting..\n");
236         HAL_PLATFORM_RESET();
237 }
238 static cyg_thread zylinjtag_thread_object;
239 static cyg_handle_t zylinjtag_thread_handle;
240
241 void reboot(void)
242 {
243     cyg_thread_create(1,
244                       zylinjtag_reboot,
245                       (cyg_addrword_t)0,
246                       "reboot Thread",
247                       (void *)reboot_stack,
248                       sizeof(reboot_stack),
249                       &zylinjtag_thread_handle,
250                       &zylinjtag_thread_object);
251         cyg_thread_resume(zylinjtag_thread_handle);
252 }
253
254 int configuration_output_handler(struct command_context_s *context, const char* line)
255 {
256         diag_printf("%s", line);
257
258         return ERROR_OK;
259 }
260
261 int zy1000_configuration_output_handler_log(struct command_context_s *context, const char* line)
262 {
263         LOG_USER_N("%s", line);
264
265         return ERROR_OK;
266 }
267
268 int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
269                 char **args, int argc)
270 {
271         if (argc != 1)
272         {
273                 command_print(cmd_ctx, "rm <filename>");
274                 return ERROR_INVALID_ARGUMENTS;
275         }
276
277         if (unlink(args[0]) != 0)
278         {
279                 command_print(cmd_ctx, "failed: %d", errno);
280         }
281
282         return ERROR_OK;
283 }
284
285 int loadFile(const char *fileName, void **data, int *len);
286
287 int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
288                 char **args, int argc)
289 {
290         if (argc != 1)
291         {
292                 command_print(cmd_ctx, "cat <filename>");
293                 return ERROR_INVALID_ARGUMENTS;
294         }
295
296         // NOTE!!! we only have line printing capability so we print the entire file as a single line.
297         void *data;
298         int len;
299
300         int retval = loadFile(args[0], &data, &len);
301         if (retval == ERROR_OK)
302         {
303                 command_print(cmd_ctx, "%s", data);
304                 free(data);
305         }
306         else
307         {
308                 command_print(cmd_ctx, "%s not found %d", args[0], retval);
309         }
310
311         return ERROR_OK;
312 }
313 int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
314                 char **args, int argc)
315 {
316         if (argc != 1)
317         {
318                 command_print(cmd_ctx, "trunc <filename>");
319                 return ERROR_INVALID_ARGUMENTS;
320         }
321
322         FILE *config_file = NULL;
323         config_file = fopen(args[0], "w");
324         if (config_file != NULL)
325                 fclose(config_file);
326
327         return ERROR_OK;
328 }
329
330
331 int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
332 {
333         static int prev = 0;
334         struct mallinfo info;
335
336         if (argc != 0)
337         {
338                 command_print(cmd_ctx, "meminfo");
339                 return ERROR_INVALID_ARGUMENTS;
340         }
341
342         info = mallinfo();
343
344         if (prev > 0)
345         {
346                 command_print(cmd_ctx, "Diff:            %d", prev - info.fordblks);
347         }
348         prev = info.fordblks;
349
350         command_print(cmd_ctx, "Available ram:   %d", info.fordblks );
351
352         return ERROR_OK;
353 }
354
355 static bool savePower;
356
357 static void setPower(bool power)
358 {
359         savePower = power;
360         if (power)
361         {
362                 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x14, 0x8);
363         } else
364         {
365                 HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x10, 0x8);
366         }
367 }
368
369 int handle_power_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
370 {
371         if (argc > 1)
372         {
373                 return ERROR_INVALID_ARGUMENTS;
374         }
375
376         if (argc == 1)
377         {
378                 if (strcmp(args[0], "on") == 0)
379                 {
380                         setPower(1);
381                 }
382                 else if (strcmp(args[0], "off") == 0)
383                 {
384                         setPower(0);
385                 } else
386                 {
387                         command_print(cmd_ctx, "arg is \"on\" or \"off\"");
388                         return ERROR_INVALID_ARGUMENTS;
389                 }
390         }
391
392         command_print(cmd_ctx, "Target power %s", savePower ? "on" : "off");
393
394         return ERROR_OK;
395 }
396
397 int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
398                 char **args, int argc)
399 {
400         if (argc < 1)
401         {
402                 command_print(cmd_ctx,
403                                 "append <filename> [<string1>, [<string2>, ...]]");
404                 return ERROR_INVALID_ARGUMENTS;
405         }
406
407         FILE *config_file = NULL;
408         config_file = fopen(args[0], "a");
409         if (config_file != NULL)
410         {
411                 int i;
412                 fseek(config_file, 0, SEEK_END);
413
414                 for (i = 1; i < argc; i++)
415                 {
416                         fwrite(args[i], strlen(args[i]), 1, config_file);
417                         if (i != argc - 1)
418                         {
419                                 fwrite(" ", 1, 1, config_file);
420                         }
421                 }
422                 fwrite("\n", 1, 1, config_file);
423                 fclose(config_file);
424         }
425
426         return ERROR_OK;
427 }
428
429 extern int telnet_socket;
430
431 int readMore(int fd, void *data, int length)
432 {
433         /* used in select() */
434         fd_set read_fds;
435
436         /* monitor sockets for acitvity */
437         int fd_max = 1;
438         FD_ZERO(&read_fds);
439         /* listen for new connections */
440         FD_SET(fd, &read_fds);
441
442         // Maximum 5 seconds.
443         struct timeval tv;
444         tv.tv_sec = 5;
445         tv.tv_usec = 0;
446
447         int retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
448         if (retval == 0)
449         {
450                 diag_printf("Timed out waiting for binary payload\n");
451                 return -1;
452         }
453         if (retval != 1)
454                 return -1;
455
456         return read_socket(fd, data, length);
457 }
458
459 int readAll(int fd, void *data, int length)
460 {
461         int pos = 0;
462         for (;;)
463         {
464                 int actual = readMore(fd, ((char *) data) + pos, length - pos);
465                 //              diag_printf("Read %d bytes(pos=%d, length=%d)\n", actual, pos, length);
466                 if (actual <= 0)
467                         return -1;
468                 pos += actual;
469                 if (pos == length)
470                         break;
471         }
472         return length;
473 }
474
475 int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
476 {
477         cyg_uint32 value;
478         if (argc != 1)
479         {
480                 return ERROR_INVALID_ARGUMENTS;
481         }
482         HAL_READ_UINT32(strtoul(args[0], NULL, 0), value);
483         command_print(cmd_ctx, "0x%x : 0x%x", strtoul(args[0], NULL, 0), value);
484         return ERROR_OK;
485 }
486
487 int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
488 {
489         if (argc != 2)
490         {
491                 return ERROR_INVALID_ARGUMENTS;
492         }
493         HAL_WRITE_UINT32(strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0));
494         return ERROR_OK;
495 }
496
497 int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
498 {
499         if (argc != 2)
500         {
501                 return ERROR_INVALID_ARGUMENTS;
502         }
503
504         // NOTE!!! we only have line printing capability so we print the entire file as a single line.
505         void *data;
506         int len;
507
508         int retval = loadFile(args[0], &data, &len);
509         if (retval != ERROR_OK)
510                 return retval;
511
512         FILE *f = fopen(args[1], "wb");
513         if (f == NULL)
514                 retval = ERROR_INVALID_ARGUMENTS;
515
516         int pos = 0;
517         for (;;)
518         {
519                 int chunk = len - pos;
520                 static const int maxChunk = 512 * 1024; // ~1/sec
521                 if (chunk > maxChunk)
522                 {
523                         chunk = maxChunk;
524                 }
525
526                 if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
527                         retval = ERROR_INVALID_ARGUMENTS;
528
529                 if (retval != ERROR_OK)
530                 {
531                         break;
532                 }
533
534                 command_print(cmd_ctx, "%d", len - pos);
535
536                 pos += chunk;
537
538                 if (pos == len)
539                         break;
540         }
541
542         if (retval == ERROR_OK)
543         {
544                 command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
545         } else
546         {
547                 command_print(cmd_ctx, "Failed: %d", retval);
548         }
549
550         if (data != NULL)
551                 free(data);
552         if (f != NULL)
553                 fclose(f);
554
555         if (retval != ERROR_OK)
556                 unlink(args[1]);
557
558         return retval;
559 }
560
561 #ifdef CYGPKG_PROFILE_GPROF
562 extern void start_profile();
563
564 int eCosBoard_handle_eCosBoard_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
565 {
566         command_print(cmd_ctx, "Profiling started");
567         start_profile();
568         return ERROR_OK;
569 }
570
571 #endif
572
573 externC void phi_init_all_network_interfaces();
574
575 command_context_t *cmd_ctx;
576
577 static bool webRunning = false;
578
579 void keep_webserver()
580 {
581         // Target initialisation is only attempted at startup, so we sleep forever and
582         // let the http server bail us out(i.e. get config files set up).
583         diag_printf("OpenOCD has invoked exit().\n"
584                 "Use web server to correct any configuration settings and reboot.\n");
585         if (!webRunning)
586                 reboot();
587
588         // exit() will terminate the current thread and we we'll then sleep eternally or
589         // we'll have a reboot scheduled.
590 }
591
592 extern void printDccChar(char c);
593
594 static char logBuffer[128 * 1024];
595 static const int logSize = sizeof(logBuffer);
596 int writePtr = 0;
597 int logCount = 0;
598
599 void _zylinjtag_diag_write_char(char c, void **param)
600 {
601         if (writeLog)
602         {
603                 logBuffer[writePtr] = c;
604                 writePtr = (writePtr + 1) % logSize;
605                 logCount++;
606         }
607         if (serialLog)
608         {
609                 if (c == '\n')
610                 {
611                         HAL_DIAG_WRITE_CHAR('\r');
612                 }
613                 HAL_DIAG_WRITE_CHAR(c);
614         }
615
616 #ifdef CYGPKG_HAL_ZYLIN_PHI
617         printDccChar(c);
618 #endif
619 }
620
621 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
622
623 #define IOSIZE 512
624 static void copyfile(char *name2, char *name1)
625 {
626
627         int err;
628         char buf[IOSIZE];
629         int fd1, fd2;
630         ssize_t done, wrote;
631
632         fd1 = open(name1, O_WRONLY | O_CREAT);
633         if (fd1 < 0)
634                 SHOW_RESULT( open, fd1 );
635
636         fd2 = open(name2, O_RDONLY);
637         if (fd2 < 0)
638                 SHOW_RESULT( open, fd2 );
639
640         for (;;)
641         {
642                 done = read(fd2, buf, IOSIZE );
643                 if (done < 0)
644                 {
645                         SHOW_RESULT( read, done );
646                         break;
647                 }
648
649         if( done == 0 ) break;
650
651                 wrote = write(fd1, buf, done);
652         if( wrote != done ) SHOW_RESULT( write, wrote );
653
654         if( wrote != done ) break;
655         }
656
657         err = close(fd1);
658     if( err < 0 ) SHOW_RESULT( close, err );
659
660         err = close(fd2);
661     if( err < 0 ) SHOW_RESULT( close, err );
662
663 }
664 static void copydir(char *name, char *destdir)
665 {
666         int err;
667         DIR *dirp;
668
669         dirp = opendir(destdir);
670         if (dirp==NULL)
671         {
672                 mkdir(destdir, 0777);
673         } else
674         {
675                 err = closedir(dirp);
676         }
677
678         dirp = opendir(name);
679     if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
680
681         for (;;)
682         {
683                 struct dirent *entry = readdir(dirp);
684
685                 if (entry == NULL)
686                         break;
687
688                 if (strcmp(entry->d_name, ".") == 0)
689                         continue;
690                 if (strcmp(entry->d_name, "..") == 0)
691                         continue;
692
693                 bool isDir = false;
694                 struct stat buf;
695                 char fullPath[PATH_MAX];
696                 strncpy(fullPath, name, PATH_MAX);
697                 strcat(fullPath, "/");
698                 strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
699
700                 if (stat(fullPath, &buf) == -1)
701                 {
702                         diag_printf("unable to read status from %s", fullPath);
703                         break;
704                 }
705                 isDir = S_ISDIR(buf.st_mode) != 0;
706
707                 if (isDir)
708                         continue;
709
710                 //        diag_printf("<INFO>: entry %14s",entry->d_name);
711                 char fullname[PATH_MAX];
712                 char fullname2[PATH_MAX];
713
714                 strcpy(fullname, name);
715                 strcat(fullname, "/");
716                 strcat(fullname, entry->d_name);
717
718                 strcpy(fullname2, destdir);
719                 strcat(fullname2, "/");
720                 strcat(fullname2, entry->d_name);
721                 //        diag_printf("from %s to %s\n", fullname, fullname2);
722                 copyfile(fullname, fullname2);
723
724                 //       diag_printf("\n");
725         }
726
727         err = closedir(dirp);
728     if( err < 0 ) SHOW_RESULT( stat, err );
729 }
730
731 #if 0
732 MTAB_ENTRY( romfs_mte1,
733                 "/rom",
734                 "romfs",
735                 "",
736                 (CYG_ADDRWORD) &filedata[0] );
737 #endif
738
739 void openocd_sleep_prelude()
740 {
741         cyg_mutex_unlock(&httpstate.jim_lock);
742 }
743
744 void openocd_sleep_postlude()
745 {
746         cyg_mutex_lock(&httpstate.jim_lock);
747 }
748
749
750 void format(void)
751 {
752         diag_printf("Formatting JFFS2...\n");
753
754         cyg_io_handle_t handle;
755
756         Cyg_ErrNo err;
757         err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
758         if (err != ENOERR)
759         {
760                 diag_printf("Flash Error cyg_io_lookup: %d\n", err);
761                 reboot();
762         }
763
764
765         cyg_uint32 len;
766         cyg_io_flash_getconfig_devsize_t ds;
767         len = sizeof (ds);
768         err = cyg_io_get_config(handle,
769                                 CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
770         if (err != ENOERR)
771         {
772                 diag_printf("Flash error cyg_io_get_config %d\n", err);
773                 reboot();
774         }
775
776         cyg_io_flash_getconfig_erase_t e;
777         void *err_addr;
778         len = sizeof (e);
779
780         e.offset = 0;
781         e.len = ds.dev_size;
782         e.err_address = &err_addr;
783
784         diag_printf("Formatting 0x%08x bytes\n", ds.dev_size);
785         err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE,
786                                 &e, &len);
787         if (err != ENOERR)
788         {
789                 diag_printf("Flash erase error %d offset 0x%p\n", err, err_addr);
790                 reboot();
791         }
792
793         diag_printf("Flash formatted successfully\n");
794
795         reboot();
796 }
797
798
799
800 static int
801 zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp,
802                                    int argc,
803                 Jim_Obj * const *argv)
804 {
805         if (argc != 1)
806         {
807                 return JIM_ERR;
808         }
809
810         format();
811         for(;;);
812 }
813
814
815 static int
816 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
817                                    int argc,
818                 Jim_Obj * const *argv)
819 {
820         int del;
821         if (argc != 2)
822         {
823                 Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
824                 return JIM_ERR;
825         }
826
827         del = 0;
828         if (unlink(Jim_GetString(argv[1], NULL)) == 0)
829                 del = 1;
830         if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
831                 del = 1;
832
833         return del ? JIM_OK : JIM_ERR;
834 }
835
836 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
837                 Jim_Obj * const *argv)
838 {
839         cyg_handle_t thread = 0;
840         cyg_uint16 id = 0;
841         Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
842
843         /* Loop over the threads, and generate a table row for
844          * each.
845          */
846         while (cyg_thread_get_next(&thread, &id))
847         {
848                 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
849
850                 cyg_thread_info info;
851                 char *state_string;
852
853                 cyg_thread_get_info(thread, id, &info);
854
855                 if (info.name == NULL)
856                         info.name = "<no name>";
857
858                 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
859                                 info.name, strlen(info.name)));
860
861                 /* Translate the state into a string.
862                  */
863                 if (info.state == 0)
864                         state_string = "RUN";
865                 else if (info.state & 0x04)
866                         state_string = "SUSP";
867                 else
868                         switch (info.state & 0x1b)
869                         {
870                         case 0x01:
871                                 state_string = "SLEEP";
872                                 break;
873                         case 0x02:
874                                 state_string = "CNTSLEEP";
875                                 break;
876                         case 0x08:
877                                 state_string = "CREATE";
878                                 break;
879                         case 0x10:
880                                 state_string = "EXIT";
881                                 break;
882                         default:
883                                 state_string = "????";
884                                 break;
885                         }
886
887                 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
888                                 state_string, strlen(state_string)));
889
890                 Jim_ListAppendElement   (interp, threadObj, Jim_NewIntObj(interp, id));
891                 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.set_pri));
892                 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.cur_pri));
893
894                 Jim_ListAppendElement(interp, threads, threadObj);
895         }
896         Jim_SetResult( interp, threads);
897
898         return JIM_OK;
899 }
900
901
902 static int
903 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
904                                    int argc,
905                 Jim_Obj * const *argv)
906 {
907         if (argc != 2)
908         {
909                 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
910                 return JIM_ERR;
911         }
912
913         char *name = (char*) Jim_GetString(argv[1], NULL);
914
915         DIR *dirp = NULL;
916         dirp = opendir(name);
917         if (dirp == NULL)
918         {
919                 return JIM_ERR;
920         }
921         Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
922
923         for (;;)
924         {
925                 struct dirent *entry = NULL;
926                 entry = readdir(dirp);
927                 if (entry == NULL)
928                         break;
929
930                 if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
931                         continue;
932
933         Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
934         }
935         closedir(dirp);
936
937         Jim_SetResult(interp, objPtr);
938
939         return JIM_OK;
940 }
941
942
943 static int
944 zylinjtag_Jim_Command_getmem(Jim_Interp *interp,
945                                    int argc,
946                 Jim_Obj * const *argv)
947 {
948         if (argc != 3)
949         {
950                 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
951                 return JIM_ERR;
952         }
953
954         long address;
955         long length;
956         if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
957                 return JIM_ERR;
958         if (Jim_GetLong(interp, argv[2], &length) != JIM_OK)
959                 return JIM_ERR;
960
961         if (length < 0 && length > (4096 * 1024))
962         {
963                 Jim_WrongNumArgs(interp, 1, argv, "getmem ?dir?");
964                 return JIM_ERR;
965         }
966
967         void *mem = malloc(length);
968         if (mem == NULL)
969                 return JIM_ERR;
970
971         target_t *target = get_current_target(cmd_ctx);
972
973         int retval;
974         int size = 1;
975         int count = length;
976         if ((address % 4 == 0) && (count % 4 == 0))
977         {
978                 size = 4;
979                 count /= 4;
980         }
981
982         if ((retval  = target->type->read_memory(target, address, size, count, mem)) != ERROR_OK)
983         {
984                 free(mem);
985                 return JIM_ERR;
986         }
987
988         Jim_Obj *objPtr = Jim_NewStringObj(interp, mem, length);
989         Jim_SetResult(interp, objPtr);
990
991         free(mem);
992
993         return JIM_OK;
994 }
995
996 static int
997 zylinjtag_Jim_Command_peek(Jim_Interp *interp,
998                                    int argc,
999                 Jim_Obj * const *argv)
1000 {
1001         if (argc != 2)
1002         {
1003                 Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
1004                 return JIM_ERR;
1005         }
1006
1007         long address;
1008         if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1009                 return JIM_ERR;
1010
1011         int value = *((volatile int *) address);
1012
1013         Jim_SetResult(interp, Jim_NewIntObj(interp, value));
1014
1015         return JIM_OK;
1016 }
1017
1018 static int
1019 zylinjtag_Jim_Command_poke(Jim_Interp *interp,
1020                                    int argc,
1021                 Jim_Obj * const *argv)
1022 {
1023         if (argc != 3)
1024         {
1025                 Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
1026                 return JIM_ERR;
1027         }
1028
1029         long address;
1030         if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1031                 return JIM_ERR;
1032         long value;
1033         if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
1034                 return JIM_ERR;
1035
1036         *((volatile int *) address) = value;
1037
1038         return JIM_OK;
1039 }
1040
1041
1042
1043 static int
1044 zylinjtag_Jim_Command_flash(Jim_Interp *interp,
1045                                    int argc,
1046                 Jim_Obj * const *argv)
1047 {
1048         int retval;
1049         u32 base = 0;
1050         flash_bank_t *t = get_flash_bank_by_num_noprobe(0);
1051         if (t != NULL)
1052         {
1053                 base = t->base;
1054                 retval = JIM_OK;
1055     } else
1056         {
1057                 retval = JIM_ERR;
1058         }
1059
1060         if (retval == JIM_OK)
1061         {
1062                 Jim_SetResult(interp, Jim_NewIntObj(interp, base));
1063         }
1064
1065         return retval;
1066 }
1067
1068
1069
1070
1071
1072 static int
1073 zylinjtag_Jim_Command_log(Jim_Interp *interp,
1074                                    int argc,
1075                 Jim_Obj * const *argv)
1076 {
1077         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1078
1079         if (logCount >= logSize)
1080         {
1081         Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer+logCount%logSize, logSize-logCount%logSize);
1082         }
1083         Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
1084
1085         Jim_SetResult(interp, tclOutput);
1086         return JIM_OK;
1087 }
1088
1089 static int
1090 zylinjtag_Jim_Command_reboot(Jim_Interp *interp,
1091                                    int argc,
1092                 Jim_Obj * const *argv)
1093 {
1094         reboot();
1095         return JIM_OK;
1096 }
1097
1098 static int
1099 zylinjtag_Jim_Command_mac(Jim_Interp *interp,
1100                                    int argc,
1101                 Jim_Obj * const *argv)
1102 {
1103
1104         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1105
1106         Jim_AppendString(httpstate.jim_interp, tclOutput, hwaddr, strlen(hwaddr));
1107
1108         Jim_SetResult(interp, tclOutput);
1109
1110         return JIM_OK;
1111 }
1112
1113 static int
1114 zylinjtag_Jim_Command_ip(Jim_Interp *interp,
1115                                    int argc,
1116                 Jim_Obj * const *argv)
1117 {
1118         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1119
1120         struct ifaddrs *ifa = NULL, *ifp = NULL;
1121
1122         if (getifaddrs(&ifp) < 0)
1123         {
1124                 return JIM_ERR;
1125         }
1126
1127         for (ifa = ifp; ifa; ifa = ifa->ifa_next)
1128         {
1129                 char ip[200];
1130                 socklen_t salen;
1131
1132                 if (ifa->ifa_addr->sa_family == AF_INET)
1133                         salen = sizeof(struct sockaddr_in);
1134                 else if (ifa->ifa_addr->sa_family == AF_INET6)
1135                         salen = sizeof(struct sockaddr_in6);
1136                 else
1137                         continue;
1138
1139                 if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
1140                                 NI_NUMERICHOST) < 0)
1141                 {
1142                         continue;
1143                 }
1144
1145                 Jim_AppendString(httpstate.jim_interp, tclOutput, ip, strlen(ip));
1146                 break;
1147
1148         }
1149
1150         freeifaddrs(ifp);
1151
1152         Jim_SetResult(interp, tclOutput);
1153
1154         return JIM_OK;
1155 }
1156
1157 extern Jim_Interp *interp;
1158
1159
1160 static void zylinjtag_startNetwork()
1161 {
1162         // Bring TCP/IP up immediately before we're ready to accept commands.
1163         //
1164         // That is as soon as a PING responds, we're accepting telnet sessions.
1165 #if defined(CYGPKG_NET_FREEBSD_STACK)
1166         phi_init_all_network_interfaces();
1167 #else
1168         lwip_init();
1169 #endif
1170         if (!eth0_up)
1171         {
1172                 diag_printf("Network not up and running\n");
1173                 exit(-1);
1174         }
1175 #if defined(CYGPKG_NET_FREEBSD_STACK)
1176         /*start TFTP*/
1177         tftpd_start(69, &fileops);
1178 #endif
1179
1180         cyg_httpd_init_tcl_interpreter();
1181
1182         interp = httpstate.jim_interp;
1183
1184     Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log, NULL, NULL);
1185     Jim_CreateCommand(httpstate.jim_interp, "reboot", zylinjtag_Jim_Command_reboot, NULL, NULL);
1186     Jim_CreateCommand(httpstate.jim_interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
1187     Jim_CreateCommand(httpstate.jim_interp, "zy1000_flash", zylinjtag_Jim_Command_flash, NULL, NULL);
1188     Jim_CreateCommand(httpstate.jim_interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
1189     Jim_CreateCommand(httpstate.jim_interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
1190     Jim_CreateCommand(httpstate.jim_interp, "threads", zylinjtag_Jim_Command_threads, NULL, NULL);
1191     Jim_CreateCommand(httpstate.jim_interp, "getmem", zylinjtag_Jim_Command_getmem, NULL, NULL);
1192     Jim_CreateCommand(httpstate.jim_interp, "mac", zylinjtag_Jim_Command_mac, NULL, NULL);
1193     Jim_CreateCommand(httpstate.jim_interp, "ip", zylinjtag_Jim_Command_ip, NULL, NULL);
1194     Jim_CreateCommand(httpstate.jim_interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
1195     Jim_CreateCommand(httpstate.jim_interp, "format_jffs2", zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
1196
1197         cyg_httpd_start();
1198
1199         webRunning = true;
1200
1201         diag_printf("Web server running\n");
1202
1203         int s;
1204         struct ifreq ifr;
1205         s = socket(AF_INET, SOCK_DGRAM, 0);
1206         if (s >= 0)
1207         {
1208                 strcpy(ifr.ifr_name, "eth0");
1209                 int res;
1210                 res = ioctl(s, SIOCGIFHWADDR, &ifr);
1211                 close(s);
1212
1213                 if (res < 0)
1214                 {
1215                         diag_printf("Can't obtain MAC address\n");
1216                         reboot();
1217                 }
1218         }
1219
1220         sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
1221                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
1222                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
1223                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
1224                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
1225                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
1226                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
1227
1228
1229         discover_message=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
1230
1231         discover_launch();
1232 }
1233
1234
1235
1236
1237
1238 static void
1239 print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_t info)
1240 {
1241         writeLog = false;
1242         serialLog = true;
1243         char *infoStr = "unknown";
1244         switch (exception)
1245         {
1246 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1247         case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
1248                 infoStr = "undefined instruction";
1249                 break;
1250         case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
1251                 infoStr = "software interrupt";
1252                 break;
1253         case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
1254                 infoStr = "abort prefetch";
1255                 break;
1256         case CYGNUM_HAL_VECTOR_ABORT_DATA:
1257                 infoStr = "abort data";
1258                 break;
1259 #endif
1260         default:
1261                 break;
1262         }
1263
1264         diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1265
1266         diag_printf("Dumping log\n---\n");
1267         if (logCount >= logSize)
1268         {
1269                 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
1270         }
1271         diag_write(logBuffer, writePtr);
1272
1273         diag_printf("---\nLogdump complete.\n");
1274         diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1275         diag_printf("\n---\nRebooting\n");
1276         HAL_PLATFORM_RESET();
1277
1278 }
1279
1280 static void setHandler(cyg_code_t exception)
1281 {
1282         cyg_exception_handler_t *old_handler;
1283         cyg_addrword_t old_data;
1284
1285         cyg_exception_set_handler(exception,
1286         print_exception_handler,
1287         0,
1288         &old_handler,
1289         &old_data);
1290 }
1291
1292 static cyg_thread zylinjtag_uart_thread_object;
1293 static cyg_handle_t zylinjtag_uart_thread_handle;
1294 static char uart_stack[4096];
1295
1296 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1297 static char backwardBuffer[1024];
1298
1299
1300 void setNoDelay(int session, int flag)
1301 {
1302 #if 1
1303         // This decreases latency dramatically for e.g. GDB load which
1304         // does not have a sliding window protocol
1305         //
1306         // Can cause *lots* of TCP/IP packets to be sent and it would have
1307         // to be enabled/disabled on the fly to avoid the CPU being
1308         // overloaded...
1309         setsockopt(session, /* socket affected */
1310         IPPROTO_TCP, /* set option at TCP level */
1311         TCP_NODELAY, /* name of option */
1312         (char *) &flag, /* the cast is historical
1313          cruft */
1314         sizeof(int)); /* length of option value */
1315 #endif
1316 }
1317
1318 struct
1319 {
1320         int req;
1321         int actual;
1322         int req2;
1323         int actual2;
1324 } tcpipSent[512 * 1024];
1325 int cur;
1326
1327 static void
1328 zylinjtag_uart(cyg_addrword_t data)
1329 {
1330         int so_reuseaddr_option = 1;
1331
1332         int fd;
1333         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1334         {
1335                 LOG_ERROR("error creating socket: %s", strerror(errno));
1336                 exit(-1);
1337         }
1338
1339         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
1340
1341         struct sockaddr_in sin;
1342         unsigned int address_size;
1343         address_size = sizeof(sin);
1344         memset(&sin, 0, sizeof(sin));
1345         sin.sin_family = AF_INET;
1346         sin.sin_addr.s_addr = INADDR_ANY;
1347         sin.sin_port = htons(5555);
1348
1349         if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
1350         {
1351                 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
1352                 exit(-1);
1353         }
1354
1355         if (listen(fd, 1) == -1)
1356         {
1357                 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
1358                 exit(-1);
1359         }
1360         //      socket_nonblock(fd);
1361
1362
1363         for (;;)
1364         {
1365                 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
1366                 if (session < 0)
1367                 {
1368                         continue;
1369                 }
1370
1371                 setNoDelay(session, 1);
1372                 int oldopts = fcntl(session, F_GETFL, 0);
1373                 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
1374
1375                 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
1376                 if (serHandle < 0)
1377                 {
1378                         close(session);
1379                         continue;
1380                 }
1381
1382 #ifdef CYGPKG_PROFILE_GPROF
1383                 start_profile();
1384 #endif
1385                 int actual = 0;
1386                 int actual2 = 0;
1387                 int pos, pos2;
1388                 pos = 0;
1389                 pos2 = 0;
1390                 cur = 0;
1391                 for (;;)
1392                 {
1393                         fd_set write_fds;
1394                         fd_set read_fds;
1395                         FD_ZERO(&write_fds);
1396                         FD_ZERO(&read_fds);
1397                         int fd_max = -1;
1398                         FD_SET(session, &read_fds);
1399                         fd_max = session;
1400                         FD_SET(serHandle, &read_fds);
1401                         if (serHandle > fd_max)
1402                         {
1403                                 fd_max = serHandle;
1404                         }
1405                         /* Wait... */
1406
1407                         cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1408                         if ((actual == 0) && (actual2 == 0))
1409                         {
1410                                 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
1411                                 if (retval <= 0)
1412                                 {
1413                                         break;
1414                                 }
1415                         }
1416
1417                         if (actual2 <= 0)
1418                         {
1419                                 memset(backwardBuffer, 's', sizeof(backwardBuffer));
1420                                 actual2=read(serHandle, backwardBuffer, sizeof(backwardBuffer));
1421                                 if (actual2 < 0)
1422                                 {
1423                                         if (errno != EAGAIN)
1424                                         {
1425                                                 goto closeSession;
1426                                         }
1427                                         actual2 = 0;
1428                                 }
1429                                 pos2 = 0;
1430                         }
1431
1432                         int x = actual2;
1433                         int y = 0;
1434                         if (actual2 > 0)
1435                         {
1436                                 int written = write(session, backwardBuffer + pos2, actual2);
1437                                 if (written <= 0)
1438                                         goto closeSession;
1439                                 actual2 -= written;
1440                                 pos2 += written;
1441                                 y = written;
1442                         }
1443
1444                         if (FD_ISSET(session, &read_fds)&&(sizeof(forwardBuffer)>actual))
1445                         {
1446                                 // NB! Here it is important that we empty the TCP/IP read buffer
1447                                 // to make transmission tick right
1448                                 memmove(forwardBuffer, forwardBuffer + pos, actual);
1449                                 pos = 0;
1450                                 int t;
1451                                 // this will block if there is no data at all
1452                                 t=read_socket(session, forwardBuffer+actual, sizeof(forwardBuffer)-actual);
1453                                 if (t <= 0)
1454                                 {
1455                                         goto closeSession;
1456                                 }
1457                                 actual += t;
1458                         }
1459
1460                         int x2 = actual;
1461                         int y2 = 0;
1462                         if (actual > 0)
1463                         {
1464                                 /* Do not put things into the serial buffer if it has something to send
1465                                  * as that can cause a single byte to be sent at the time.
1466                                  *
1467                                  *
1468                                  */
1469                                 int written = write(serHandle, forwardBuffer + pos, actual);
1470                                 if (written < 0)
1471                                 {
1472                                         if (errno != EAGAIN)
1473                                         {
1474                                                 goto closeSession;
1475                                         }
1476                                         // The serial buffer is full
1477                                         written = 0;
1478                                 } else
1479                                 {
1480                                         actual -= written;
1481                                         pos += written;
1482                                 }
1483                                 y2 = written;
1484                         }
1485                         if (cur < 1024)
1486                         {
1487                                 tcpipSent[cur].req = x;
1488                                 tcpipSent[cur].actual = y;
1489                                 tcpipSent[cur].req2 = x2;
1490                                 tcpipSent[cur].actual2 = y2;
1491                                 cur++;
1492                         }
1493
1494                 }
1495             closeSession:
1496             close(session);
1497                 close(serHandle);
1498
1499                 int i;
1500                 for (i = 0; i < 1024; i++)
1501                 {
1502                 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual, tcpipSent[i].req2, tcpipSent[i].actual2);
1503
1504                 }
1505         }
1506         close(fd);
1507
1508 }
1509
1510 void startUart(void)
1511 {
1512     cyg_thread_create(1,
1513                       zylinjtag_uart,
1514                       (cyg_addrword_t)0,
1515                       "uart thread",
1516                       (void *)uart_stack,
1517                       sizeof(uart_stack),
1518                       &zylinjtag_uart_thread_handle,
1519                       &zylinjtag_uart_thread_object);
1520         cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
1521         cyg_thread_resume(zylinjtag_uart_thread_handle);
1522 }
1523
1524
1525
1526 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1527 {
1528         static int current_baud = 38400;
1529         if (argc == 0)
1530         {
1531                 command_print(cmd_ctx, "%d", current_baud);
1532                 return ERROR_OK;
1533         } else if (argc != 1)
1534         {
1535                 return ERROR_INVALID_ARGUMENTS;
1536         }
1537
1538         current_baud = atol(args[0]);
1539
1540         int baud;
1541         switch (current_baud)
1542         {
1543         case 9600:
1544                 baud = CYGNUM_SERIAL_BAUD_9600;
1545                 break;
1546         case 19200:
1547                 baud = CYGNUM_SERIAL_BAUD_19200;
1548                 break;
1549         case 38400:
1550                 baud = CYGNUM_SERIAL_BAUD_38400;
1551                 break;
1552         case 57600:
1553                 baud = CYGNUM_SERIAL_BAUD_57600;
1554                 break;
1555         case 115200:
1556                 baud = CYGNUM_SERIAL_BAUD_115200;
1557                 break;
1558         case 230400:
1559                 baud = CYGNUM_SERIAL_BAUD_230400;
1560                 break;
1561         default:
1562                 command_print(cmd_ctx, "unsupported baudrate");
1563                 return ERROR_INVALID_ARGUMENTS;
1564         }
1565
1566         cyg_serial_info_t buf;
1567         cyg_uint32 len = 1;
1568         //get existing serial configuration
1569         len = sizeof(cyg_serial_info_t);
1570         int err;
1571         cyg_io_handle_t serial_handle;
1572
1573         err = cyg_io_lookup("/dev/ser0", &serial_handle);
1574         if (err != ENOERR)
1575         {
1576                 LOG_ERROR("/dev/ser0 not found\n");
1577                 return ERROR_FAIL;
1578         }
1579
1580
1581         err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
1582         err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf, &len);
1583         if (err != ENOERR)
1584         {
1585                 command_print(cmd_ctx, "Failed to get serial port settings %d", err);
1586                 return ERROR_OK;
1587         }
1588         buf.baud = baud;
1589
1590         err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf, &len);
1591         if (err != ENOERR)
1592         {
1593                 command_print(cmd_ctx, "Failed to set serial port settings %d", err);
1594                 return ERROR_OK;
1595         }
1596
1597         return ERROR_OK;
1598 }
1599
1600 bool logAllToSerial = false;
1601
1602 /* boolean parameter stored on config */
1603 bool boolParam(char *var)
1604 {
1605         bool result = false;
1606         char *name = alloc_printf(ZYLIN_CONFIG_DIR "/%s", var);
1607         if (name == NULL)
1608                 return result;
1609
1610         void *data;
1611         int len;
1612         if (loadFile(name, &data, &len) == ERROR_OK)
1613         {
1614                 if (len > 1)
1615                         len = 1;
1616                 result = strncmp((char *) data, "1", len) == 0;
1617                 free(data);
1618         }
1619         free(name);
1620         return result;
1621 }
1622
1623 command_context_t *setup_command_handler();
1624
1625 int add_default_dirs(void)
1626 {
1627         add_script_search_dir(ZYLIN_CONFIG_DIR);
1628         add_script_search_dir("/rom/lib/openocd");
1629         add_script_search_dir("/rom");
1630         return ERROR_OK;
1631 }
1632
1633 static cyg_uint8 *ramblockdevice;
1634 static const int ramblockdevice_size=4096*1024;
1635 int main(int argc, char *argv[])
1636 {
1637         /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1638          * need to allocate towards the end of the heap.  */
1639
1640         ramblockdevice=(cyg_uint8 *)malloc(ramblockdevice_size);
1641         memset(ramblockdevice, 0xff, ramblockdevice_size);
1642
1643
1644
1645 #ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
1646         setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
1647         setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
1648         setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
1649 #endif
1650
1651         int err;
1652
1653         setPower(true); // on by default
1654
1655         atexit(keep_webserver);
1656
1657         err = mount("", "/ram", "ramfs");
1658         if (err < 0)
1659         {
1660                 diag_printf("unable to mount ramfs\n");
1661         }
1662         chdir("/ram");
1663
1664         char address[16];
1665         sprintf(address, "%p", &filedata[0]);
1666         err = mount(address, "/rom", "romfs");
1667         if (err < 0)
1668         {
1669                 diag_printf("unable to mount /rom\n");
1670         }
1671
1672         err = mount("", "/log", "logfs");
1673         if (err < 0)
1674         {
1675                 diag_printf("unable to mount logfs\n");
1676         }
1677
1678         err = mount("", "/tftp", "tftpfs");
1679         if (err < 0)
1680         {
1681                 diag_printf("unable to mount logfs\n");
1682         }
1683
1684         log = fopen("/log/log", "w");
1685         if (log == NULL)
1686         {
1687                 diag_printf("Could not open log file /ram/log\n");
1688                 exit(-1);
1689         }
1690
1691         diag_init_putc(_zylinjtag_diag_write_char);
1692
1693         // We want this in the log.
1694         diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1695         diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);
1696
1697         copydir("/rom", "/ram/cgi");
1698
1699         err = mount("/dev/flash1", "/config", "jffs2");
1700         if (err < 0)
1701         {
1702                 diag_printf("unable to mount jffs2, falling back to ram disk..\n");
1703                 err = mount("", "/config", "ramfs");
1704                 if (err<0)
1705                 {
1706                         diag_printf("unable to mount /config as ramdisk.\n");
1707                         reboot();
1708                 }
1709         } else
1710         {
1711                 /* are we using a ram disk instead of a flash disk? This is used
1712                  * for ZY1000 live demo...
1713                  *
1714                  * copy over flash disk to ram block device
1715                  */
1716                 if (boolParam("ramdisk"))
1717                 {
1718                         diag_printf("Unmounting /config from flash and using ram instead\n");
1719                         err=umount("/config");
1720                         if (err < 0)
1721                         {
1722                                 diag_printf("unable to unmount jffs\n");
1723                                 reboot();
1724                         }
1725
1726                         err = mount("/dev/flash1", "/config2", "jffs2");
1727                         if (err < 0)
1728                         {
1729                                 diag_printf("unable to mount jffs\n");
1730                                 reboot();
1731                         }
1732
1733                         err = mount("", "/config", "ramfs");
1734                         if (err < 0)
1735                         {
1736                                 diag_printf("unable to mount ram block device\n");
1737                                 reboot();
1738                         }
1739
1740         //              copydir("/config2", "/config");
1741                         copyfile("/config2/ip", "/config/ip");
1742                         copydir("/config2/settings", "/config/settings");
1743
1744                         umount("/config2");
1745                 } else
1746                 {
1747                         /* we're not going to use a ram block disk */
1748                         free(ramblockdevice);
1749                 }
1750         }
1751
1752
1753         mkdir(ZYLIN_CONFIG_DIR, 0777);
1754         mkdir(ZYLIN_CONFIG_DIR "/target", 0777);
1755         mkdir(ZYLIN_CONFIG_DIR "/event", 0777);
1756
1757         logAllToSerial = boolParam("logserial");
1758
1759         // We need the network & web server in case there is something wrong with
1760         // the config files that invoke exit()
1761         zylinjtag_startNetwork();
1762
1763         /* we're going to access the jim interpreter from here on... */
1764         openocd_sleep_postlude();
1765         startUart();
1766
1767         add_default_dirs();
1768
1769         /* initialize commandline interface */
1770         command_context_t *cmd_ctx;
1771         cmd_ctx = setup_command_handler();
1772         command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1773         command_context_mode(cmd_ctx, COMMAND_CONFIG);
1774
1775
1776         register_command(cmd_ctx, NULL, "zy1000_version", handle_zy1000_version_command,
1777                         COMMAND_EXEC, "show zy1000 version numbers");
1778
1779         register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
1780                         "remove file");
1781
1782         register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
1783                         "display file content");
1784
1785         register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
1786                         "truncate a file to 0 size");
1787
1788         register_command(cmd_ctx, NULL, "append_file", handle_append_command,
1789                         COMMAND_ANY, "append a variable number of strings to a file");
1790
1791         register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,
1792                         "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1793
1794         register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
1795                         COMMAND_ANY, "display available ram memory");
1796
1797         register_command(cmd_ctx, NULL, "cp", handle_cp_command,
1798                                          COMMAND_ANY, "copy a file <from> <to>");
1799
1800 #ifdef CYGPKG_PROFILE_GPROF
1801         register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1802                         COMMAND_ANY, NULL);
1803 #endif
1804         register_command(cmd_ctx, NULL, "uart", handle_uart_command,
1805                                          COMMAND_ANY, "uart <baud>  - forward uart on port 5555");
1806
1807
1808         int errVal;
1809         errVal = log_init(cmd_ctx);
1810         if (errVal != ERROR_OK)
1811         {
1812                 diag_printf("log_init() failed %d\n", errVal);
1813                 exit(-1);
1814         }
1815
1816         set_log_output(cmd_ctx, log);
1817
1818         LOG_DEBUG("log init complete");
1819
1820         //      diag_printf("Executing config files\n");
1821
1822         if (logAllToSerial)
1823         {
1824                 diag_printf(ZYLIN_CONFIG_DIR "/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1825                 command_run_line(cmd_ctx, "debug_level 3");
1826         }
1827
1828         zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");
1829
1830         // FIX!!!  Yuk!
1831         // diag_printf() is really invoked from many more places than we trust it
1832         // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1833         //
1834         // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1835         // fingers that it doesn't cause any crashes.
1836         diag_printf("Init complete, GDB & telnet servers launched.\n");
1837         command_set_output_handler(cmd_ctx, zy1000_configuration_output_handler_log, NULL);
1838         if (!logAllToSerial)
1839         {
1840                 serialLog = false;
1841         }
1842
1843         /* handle network connections */
1844         server_loop(cmd_ctx);
1845         openocd_sleep_prelude();
1846
1847         /* shut server down */
1848         server_quit();
1849
1850         /* free commandline interface */
1851         command_done(cmd_ctx);
1852         umount("/config");
1853
1854         exit(0);
1855         for (;;);
1856 }
1857
1858
1859
1860 cyg_int32
1861 cyg_httpd_exec_cgi_tcl(char *file_name);
1862 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1863 {
1864         cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1865         return 0;
1866 }
1867
1868 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1869
1870 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1871 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1872
1873 #include <pkgconf/system.h>
1874 #include <pkgconf/hal.h>
1875 #include <pkgconf/kernel.h>
1876 #include <pkgconf/io_fileio.h>
1877 #include <pkgconf/fs_rom.h>
1878
1879 #include <cyg/kernel/ktypes.h>         // base kernel types
1880 #include <cyg/infra/cyg_trac.h>        // tracing macros
1881 #include <cyg/infra/cyg_ass.h>         // assertion macros
1882 #include <unistd.h>
1883 #include <sys/types.h>
1884 #include <fcntl.h>
1885 #include <sys/stat.h>
1886 #include <errno.h>
1887 #include <dirent.h>
1888
1889 #include <stdarg.h>
1890 #include <stdio.h>
1891 #include <stdlib.h>
1892 #include <string.h>
1893
1894 #include <cyg/fileio/fileio.h>
1895
1896 #include <cyg/kernel/kapi.h>
1897 #include <cyg/infra/diag.h>
1898
1899 //==========================================================================
1900 // Eventually we want to eXecute In Place from the ROM in a protected
1901 // environment, so we'll need executables to be aligned to a boundary
1902 // suitable for MMU protection. A suitable boundary would be the 4k
1903 // boundary in all the CPU architectures I am currently aware of.
1904
1905 // Forward definitions
1906
1907 // Filesystem operations
1908 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1909 static int tftpfs_umount(cyg_mtab_entry *mte);
1910 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
1911                 int mode, cyg_file *fte);
1912 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1913 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
1914
1915 // File operations
1916 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
1917 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
1918 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
1919
1920 //==========================================================================
1921 // Filesystem table entries
1922
1923 // -------------------------------------------------------------------------
1924 // Fstab entry.
1925 // This defines the entry in the filesystem table.
1926 // For simplicity we use _FILESYSTEM synchronization for all accesses since
1927 // we should never block in any filesystem operations.
1928 #if 1
1929 FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,
1930                 CYG_SYNCMODE_NONE,
1931                 tftpfs_mount,
1932                 tftpfs_umount,
1933                 tftpfs_open,
1934                 (cyg_fsop_unlink *)cyg_fileio_erofs,
1935                 (cyg_fsop_mkdir *)cyg_fileio_erofs,
1936                 (cyg_fsop_rmdir *)cyg_fileio_erofs,
1937                 (cyg_fsop_rename *)cyg_fileio_erofs,
1938                 (cyg_fsop_link *)cyg_fileio_erofs,
1939                 (cyg_fsop_opendir *)cyg_fileio_erofs,
1940                 (cyg_fsop_chdir *)cyg_fileio_erofs,
1941                 (cyg_fsop_stat *)cyg_fileio_erofs,
1942                 (cyg_fsop_getinfo *)cyg_fileio_erofs,
1943                 (cyg_fsop_setinfo *)cyg_fileio_erofs);
1944 #endif
1945
1946 // -------------------------------------------------------------------------
1947 // mtab entry.
1948 // This defines a single ROMFS loaded into ROM at the configured address
1949 //
1950 // MTAB_ENTRY(  rom_mte,        // structure name
1951 //              "/rom",         // mount point
1952 //              "romfs",        // FIlesystem type
1953 //              "",             // hardware device
1954 //  (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS   // Address in ROM
1955 //           );
1956
1957
1958 // -------------------------------------------------------------------------
1959 // File operations.
1960 // This set of file operations are used for normal open files.
1961
1962 static cyg_fileops tftpfs_fileops =
1963 {
1964         tftpfs_fo_read,
1965         tftpfs_fo_write,
1966         tftpfs_fo_lseek,
1967         (cyg_fileop_ioctl *)cyg_fileio_erofs,
1968     cyg_fileio_seltrue,
1969     tftpfs_fo_fsync,
1970     tftpfs_fo_close,
1971                 (cyg_fileop_fstat *) cyg_fileio_erofs,
1972                 (cyg_fileop_getinfo *) cyg_fileio_erofs,
1973         (cyg_fileop_setinfo *)cyg_fileio_erofs,
1974 };
1975
1976 // -------------------------------------------------------------------------
1977 // tftpfs_mount()
1978 // Process a mount request. This mainly finds root for the
1979 // filesystem.
1980
1981 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
1982 {
1983         return ENOERR;
1984 }
1985
1986 static int tftpfs_umount(cyg_mtab_entry *mte)
1987 {
1988         return ENOERR;
1989 }
1990
1991 struct Tftp
1992 {
1993         int write;
1994         int readFile;
1995         cyg_uint8 *mem;
1996         int actual;
1997         char *server;
1998         char *file;
1999 };
2000
2001 static void freeTftp(struct Tftp *t)
2002 {
2003         if (t == NULL)
2004                 return;
2005         if (t->mem)
2006                 free(t->mem);
2007         if (t->server)
2008                 free(t->server);
2009         if (t->file)
2010                 free(t->file);
2011         free(t);
2012 }
2013
2014 static const int tftpMaxSize = 8192 * 1024;
2015 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2016                 int mode, cyg_file *file)
2017 {
2018         struct Tftp *tftp;
2019         tftp = malloc(sizeof(struct Tftp));
2020         if (tftp == NULL)
2021                 return EMFILE;
2022         memset(tftp, 0, sizeof(struct Tftp));
2023
2024         file->f_flag |= mode & CYG_FILE_MODE_MASK;
2025         file->f_type = CYG_FILE_TYPE_FILE;
2026         file->f_ops = &tftpfs_fileops;
2027         file->f_offset = 0;
2028         file->f_data = 0;
2029         file->f_xops = 0;
2030
2031         tftp->mem = malloc(tftpMaxSize);
2032         if (tftp->mem == NULL)
2033         {
2034                 freeTftp(tftp);
2035                 return EMFILE;
2036         }
2037
2038         char *server = strchr(name, '/');
2039         if (server == NULL)
2040         {
2041                 freeTftp(tftp);
2042                 return EMFILE;
2043         }
2044
2045         tftp->server = malloc(server - name + 1);
2046         if (tftp->server == NULL)
2047         {
2048                 freeTftp(tftp);
2049                 return EMFILE;
2050         }
2051         strncpy(tftp->server, name, server - name);
2052         tftp->server[server - name] = 0;
2053
2054         tftp->file = strdup(server + 1);
2055         if (tftp->file == NULL)
2056         {
2057                 freeTftp(tftp);
2058                 return EMFILE;
2059         }
2060
2061         file->f_data = (CYG_ADDRWORD) tftp;
2062
2063         return ENOERR;
2064 }
2065
2066 static int fetchTftp(struct Tftp *tftp)
2067 {
2068         if (!tftp->readFile)
2069         {
2070                 int err;
2071             tftp->actual = tftp_client_get( tftp->file, tftp->server, 0, tftp->mem, tftpMaxSize,   TFTP_OCTET, &err);
2072
2073                 if (tftp->actual < 0)
2074                 {
2075                         return EMFILE;
2076                 }
2077                 tftp->readFile = 1;
2078         }
2079         return ENOERR;
2080 }
2081
2082 // -------------------------------------------------------------------------
2083 // tftpfs_fo_write()
2084 // Read data from file.
2085
2086 static int
2087 tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2088 {
2089         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2090
2091         if (fetchTftp(tftp) != ENOERR)
2092                 return EMFILE;
2093
2094         int i;
2095         off_t pos = fp->f_offset;
2096         int resid = 0;
2097         for (i = 0; i < uio->uio_iovcnt; i++)
2098         {
2099                 cyg_iovec *iov = &uio->uio_iov[i];
2100                 char *buf = (char *) iov->iov_base;
2101                 off_t len = iov->iov_len;
2102
2103                 if (len + pos > tftp->actual)
2104                 {
2105                         len = tftp->actual - pos;
2106                 }
2107                 resid += iov->iov_len - len;
2108
2109                 memcpy(buf, tftp->mem + pos, len);
2110                 pos += len;
2111
2112         }
2113         uio->uio_resid = resid;
2114         fp->f_offset = pos;
2115
2116         return ENOERR;
2117 }
2118
2119
2120 static int
2121 tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2122 {
2123         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2124
2125         int i;
2126         off_t pos = fp->f_offset;
2127         int resid = 0;
2128         for (i = 0; i < uio->uio_iovcnt; i++)
2129         {
2130                 cyg_iovec *iov = &uio->uio_iov[i];
2131                 char *buf = (char *) iov->iov_base;
2132                 off_t len = iov->iov_len;
2133
2134                 if (len + pos > tftpMaxSize)
2135                 {
2136                         len = tftpMaxSize - pos;
2137                 }
2138                 resid += iov->iov_len - len;
2139
2140                 memcpy(tftp->mem + pos, buf, len);
2141                 pos += len;
2142
2143         }
2144         uio->uio_resid = resid;
2145         fp->f_offset = pos;
2146
2147         tftp->write = 1;
2148
2149         return ENOERR;
2150 }
2151
2152 static int
2153 tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2154 {
2155         int error = ENOERR;
2156         return error;
2157 }
2158
2159 // -------------------------------------------------------------------------
2160 // romfs_fo_close()
2161 // Close a file. We just clear out the data pointer.
2162
2163 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
2164 {
2165         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2166         int error = ENOERR;
2167
2168         if (tftp->write)
2169         {
2170             tftp_client_put( tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,   TFTP_OCTET, &error);
2171         }
2172
2173         freeTftp(tftp);
2174         fp->f_data = 0;
2175         return error;
2176 }
2177
2178 // -------------------------------------------------------------------------
2179 // romfs_fo_lseek()
2180 // Seek to a new file position.
2181
2182 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
2183 {
2184         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2185         off_t pos = *apos;
2186
2187         if (fetchTftp(tftp) != ENOERR)
2188                 return EMFILE;
2189
2190         switch (whence)
2191         {
2192         case SEEK_SET:
2193                 // Pos is already where we want to be.
2194                 break;
2195
2196         case SEEK_CUR:
2197                 // Add pos to current offset.
2198                 pos += fp->f_offset;
2199                 break;
2200
2201         case SEEK_END:
2202                 // Add pos to file size.
2203                 pos += tftp->actual;
2204                 break;
2205
2206         default:
2207                 return EINVAL;
2208         }
2209
2210         // Check that pos is still within current file size, or at the
2211         // very end.
2212         if (pos < 0 || pos > tftp->actual)
2213                 return EINVAL;
2214
2215         // All OK, set fp offset and return new position.
2216         *apos = fp->f_offset = pos;
2217
2218         return ENOERR;
2219 }
2220
2221 void usleep(int us)
2222 {
2223         if (us > 10000)
2224                 cyg_thread_delay(us / 10000 + 1);
2225         else
2226                 HAL_DELAY_US(us);
2227 }
2228
2229 // Chunked version.
2230 cyg_int32
2231 show_log_entry(CYG_HTTPD_STATE *phttpstate)
2232 {
2233         cyg_httpd_start_chunked("text");
2234         if (logCount >= logSize)
2235         {
2236         cyg_httpd_write_chunked(logBuffer+logCount%logSize, logSize-logCount%logSize);
2237         }
2238         cyg_httpd_write_chunked(logBuffer, writePtr);
2239         cyg_httpd_end_chunked();
2240         return -1;
2241 }
2242
2243 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
2244
2245 // Filesystem operations
2246 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
2247 static int logfs_umount(cyg_mtab_entry *mte);
2248 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2249                 int mode, cyg_file *fte);
2250 static int
2251 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2252
2253 // File operations
2254 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2255 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
2256
2257 #include <cyg/io/devtab.h>
2258
2259 //==========================================================================
2260 // Filesystem table entries
2261
2262 // -------------------------------------------------------------------------
2263 // Fstab entry.
2264 // This defines the entry in the filesystem table.
2265 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2266 // we should never block in any filesystem operations.
2267 FSTAB_ENTRY( logfs_fste, "logfs", 0,
2268                 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
2269                 logfs_mount,
2270                 logfs_umount,
2271                 logfs_open,
2272                 (cyg_fsop_unlink *)cyg_fileio_erofs,
2273                 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2274                 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2275                 (cyg_fsop_rename *)cyg_fileio_erofs,
2276                 (cyg_fsop_link *)cyg_fileio_erofs,
2277                 (cyg_fsop_opendir *)cyg_fileio_erofs,
2278                 (cyg_fsop_chdir *)cyg_fileio_erofs,
2279                 (cyg_fsop_stat *)cyg_fileio_erofs,
2280                 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2281                 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2282
2283 // -------------------------------------------------------------------------
2284 // File operations.
2285 // This set of file operations are used for normal open files.
2286
2287 static cyg_fileops logfs_fileops =
2288 {
2289         (cyg_fileop_read *)cyg_fileio_erofs,
2290     (cyg_fileop_write *)logfs_fo_write,
2291                 (cyg_fileop_lseek *) cyg_fileio_erofs,
2292         (cyg_fileop_ioctl *)cyg_fileio_erofs,
2293     cyg_fileio_seltrue,
2294     logfs_fo_fsync,
2295     logfs_fo_close,
2296         (cyg_fileop_fstat *)cyg_fileio_erofs,
2297                 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2298         (cyg_fileop_setinfo *)cyg_fileio_erofs,
2299 };
2300
2301 // -------------------------------------------------------------------------
2302 // logfs_mount()
2303 // Process a mount request. This mainly finds root for the
2304 // filesystem.
2305
2306 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2307 {
2308         return ENOERR;
2309 }
2310
2311 static int logfs_umount(cyg_mtab_entry *mte)
2312 {
2313         return ENOERR;
2314 }
2315
2316 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2317                 int mode, cyg_file *file)
2318 {
2319         file->f_flag |= mode & CYG_FILE_MODE_MASK;
2320         file->f_type = CYG_FILE_TYPE_FILE;
2321         file->f_ops = &logfs_fileops;
2322         file->f_offset = 0;
2323         file->f_data = 0;
2324         file->f_xops = 0;
2325         return ENOERR;
2326 }
2327
2328 // -------------------------------------------------------------------------
2329 // logfs_fo_write()
2330 // Write data to file.
2331
2332 static int
2333 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2334 {
2335         int i;
2336         for (i = 0; i < uio->uio_iovcnt; i++)
2337         {
2338                 cyg_iovec *iov = &uio->uio_iov[i];
2339                 char *buf = (char *) iov->iov_base;
2340                 off_t len = iov->iov_len;
2341
2342                 diag_write(buf, len);
2343         }
2344         uio->uio_resid = 0;
2345
2346         return ENOERR;
2347 }
2348 static int
2349 logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2350 {
2351         return ENOERR;
2352 }
2353
2354 // -------------------------------------------------------------------------
2355 // romfs_fo_close()
2356 // Close a file. We just clear out the data pointer.
2357
2358 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
2359 {
2360         return ENOERR;
2361 }
2362