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