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