broadcast mac address in UDP hello message
[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         printDccChar(c);
801 }
802
803 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
804
805 #define IOSIZE 512
806 static void copyfile(char *name2, char *name1)
807 {
808
809         int err;
810         char buf[IOSIZE];
811         int fd1, fd2;
812         ssize_t done, wrote;
813
814         fd1 = open(name1, O_WRONLY | O_CREAT);
815         if (fd1 < 0)
816                 SHOW_RESULT( open, fd1 );
817
818         fd2 = open(name2, O_RDONLY);
819         if (fd2 < 0)
820                 SHOW_RESULT( open, fd2 );
821
822         for (;;)
823         {
824                 done = read(fd2, buf, IOSIZE );
825                 if (done < 0)
826                 {
827                         SHOW_RESULT( read, done );
828                         break;
829                 }
830
831         if( done == 0 ) break;
832
833                 wrote = write(fd1, buf, done);
834         if( wrote != done ) SHOW_RESULT( write, wrote );
835
836         if( wrote != done ) break;
837         }
838
839         err = close(fd1);
840     if( err < 0 ) SHOW_RESULT( close, err );
841
842         err = close(fd2);
843     if( err < 0 ) SHOW_RESULT( close, err );
844
845 }
846 static void copydir(char *name, char *destdir)
847 {
848         int err;
849         DIR *dirp;
850
851         dirp = opendir(destdir);
852         if (dirp==NULL)
853         {
854                 mkdir(destdir, 0777);
855         } else
856         {
857                 err = closedir(dirp);
858         }
859
860         dirp = opendir(name);
861     if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
862
863         for (;;)
864         {
865                 struct dirent *entry = readdir(dirp);
866
867                 if (entry == NULL)
868                         break;
869
870                 if (strcmp(entry->d_name, ".") == 0)
871                         continue;
872                 if (strcmp(entry->d_name, "..") == 0)
873                         continue;
874
875                 bool isDir = false;
876                 struct stat buf;
877                 char fullPath[PATH_MAX];
878                 strncpy(fullPath, name, PATH_MAX);
879                 strcat(fullPath, "/");
880                 strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
881
882                 if (stat(fullPath, &buf) == -1)
883                 {
884                         diag_printf("unable to read status from %s", fullPath);
885                         break;
886                 }
887                 isDir = S_ISDIR(buf.st_mode) != 0;
888
889                 if (isDir)
890                         continue;
891
892                 //        diag_printf("<INFO>: entry %14s",entry->d_name);
893                 char fullname[PATH_MAX];
894                 char fullname2[PATH_MAX];
895
896                 strcpy(fullname, name);
897                 strcat(fullname, "/");
898                 strcat(fullname, entry->d_name);
899
900                 strcpy(fullname2, destdir);
901                 strcat(fullname2, "/");
902                 strcat(fullname2, entry->d_name);
903                 //        diag_printf("from %s to %s\n", fullname, fullname2);
904                 copyfile(fullname, fullname2);
905
906                 //       diag_printf("\n");
907         }
908
909         err = closedir(dirp);
910     if( err < 0 ) SHOW_RESULT( stat, err );
911 }
912
913 #if 0
914 MTAB_ENTRY( romfs_mte1,
915                 "/rom",
916                 "romfs",
917                 "",
918                 (CYG_ADDRWORD) &filedata[0] );
919 #endif
920
921 void openocd_sleep_prelude()
922 {
923         cyg_mutex_unlock(&httpstate.jim_lock);
924 }
925
926 void openocd_sleep_postlude()
927 {
928         cyg_mutex_lock(&httpstate.jim_lock);
929 }
930
931 static int
932 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
933                                    int argc,
934                 Jim_Obj * const *argv)
935 {
936         int del;
937         if (argc != 2)
938         {
939                 Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
940                 return JIM_ERR;
941         }
942
943         del = 0;
944         if (unlink(Jim_GetString(argv[1], NULL)) == 0)
945                 del = 1;
946         if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
947                 del = 1;
948
949         return del ? JIM_OK : JIM_ERR;
950 }
951
952 static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
953                 Jim_Obj * const *argv)
954 {
955         cyg_handle_t thread = 0;
956         cyg_uint16 id = 0;
957         Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
958
959         /* Loop over the threads, and generate a table row for
960          * each.
961          */
962         while (cyg_thread_get_next(&thread, &id))
963         {
964                 Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
965
966                 cyg_thread_info info;
967                 char *state_string;
968
969                 cyg_thread_get_info(thread, id, &info);
970
971                 if (info.name == NULL)
972                         info.name = "<no name>";
973
974                 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
975                                 info.name, strlen(info.name)));
976
977                 /* Translate the state into a string.
978                  */
979                 if (info.state == 0)
980                         state_string = "RUN";
981                 else if (info.state & 0x04)
982                         state_string = "SUSP";
983                 else
984                         switch (info.state & 0x1b)
985                         {
986                         case 0x01:
987                                 state_string = "SLEEP";
988                                 break;
989                         case 0x02:
990                                 state_string = "CNTSLEEP";
991                                 break;
992                         case 0x08:
993                                 state_string = "CREATE";
994                                 break;
995                         case 0x10:
996                                 state_string = "EXIT";
997                                 break;
998                         default:
999                                 state_string = "????";
1000                                 break;
1001                         }
1002
1003                 Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
1004                                 state_string, strlen(state_string)));
1005
1006                 Jim_ListAppendElement   (interp, threadObj, Jim_NewIntObj(interp, id));
1007                 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.set_pri));
1008                 Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.cur_pri));
1009
1010                 Jim_ListAppendElement(interp, threads, threadObj);
1011         }
1012         Jim_SetResult( interp, threads);
1013
1014         return JIM_OK;
1015 }
1016
1017
1018 static int
1019 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
1020                                    int argc,
1021                 Jim_Obj * const *argv)
1022 {
1023         if (argc != 2)
1024         {
1025                 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
1026                 return JIM_ERR;
1027         }
1028
1029         char *name = (char*) Jim_GetString(argv[1], NULL);
1030
1031         DIR *dirp = NULL;
1032         dirp = opendir(name);
1033         if (dirp == NULL)
1034         {
1035                 return JIM_ERR;
1036         }
1037         Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
1038
1039         for (;;)
1040         {
1041                 struct dirent *entry = NULL;
1042                 entry = readdir(dirp);
1043                 if (entry == NULL)
1044                         break;
1045
1046                 if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
1047                         continue;
1048
1049         Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
1050         }
1051         closedir(dirp);
1052
1053         Jim_SetResult(interp, objPtr);
1054
1055         return JIM_OK;
1056 }
1057
1058
1059 static int
1060 zylinjtag_Jim_Command_getmem(Jim_Interp *interp,
1061                                    int argc,
1062                 Jim_Obj * const *argv)
1063 {
1064         if (argc != 3)
1065         {
1066                 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
1067                 return JIM_ERR;
1068         }
1069
1070         long address;
1071         long length;
1072         if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1073                 return JIM_ERR;
1074         if (Jim_GetLong(interp, argv[2], &length) != JIM_OK)
1075                 return JIM_ERR;
1076
1077         if (length < 0 && length > (4096 * 1024))
1078         {
1079                 Jim_WrongNumArgs(interp, 1, argv, "getmem ?dir?");
1080                 return JIM_ERR;
1081         }
1082
1083         void *mem = malloc(length);
1084         if (mem == NULL)
1085                 return JIM_ERR;
1086
1087         target_t *target = get_current_target(cmd_ctx);
1088
1089         int retval;
1090         int size = 1;
1091         int count = length;
1092         if ((address % 4 == 0) && (count % 4 == 0))
1093         {
1094                 size = 4;
1095                 count /= 4;
1096         }
1097
1098         if ((retval  = target->type->read_memory(target, address, size, count, mem)) != ERROR_OK)
1099         {
1100                 free(mem);
1101                 return JIM_ERR;
1102         }
1103
1104         Jim_Obj *objPtr = Jim_NewStringObj(interp, mem, length);
1105         Jim_SetResult(interp, objPtr);
1106
1107         free(mem);
1108
1109         return JIM_OK;
1110 }
1111
1112 static int
1113 zylinjtag_Jim_Command_peek(Jim_Interp *interp,
1114                                    int argc,
1115                 Jim_Obj * const *argv)
1116 {
1117         if (argc != 2)
1118         {
1119                 Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
1120                 return JIM_ERR;
1121         }
1122
1123         long address;
1124         if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1125                 return JIM_ERR;
1126
1127         int value = *((volatile int *) address);
1128
1129         Jim_SetResult(interp, Jim_NewIntObj(interp, value));
1130
1131         return JIM_OK;
1132 }
1133
1134 static int
1135 zylinjtag_Jim_Command_poke(Jim_Interp *interp,
1136                                    int argc,
1137                 Jim_Obj * const *argv)
1138 {
1139         if (argc != 3)
1140         {
1141                 Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
1142                 return JIM_ERR;
1143         }
1144
1145         long address;
1146         if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
1147                 return JIM_ERR;
1148         long value;
1149         if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
1150                 return JIM_ERR;
1151
1152         *((volatile int *) address) = value;
1153
1154         return JIM_OK;
1155 }
1156
1157
1158
1159 static int
1160 zylinjtag_Jim_Command_flash(Jim_Interp *interp,
1161                                    int argc,
1162                 Jim_Obj * const *argv)
1163 {
1164         int retval;
1165         u32 base = 0;
1166         flash_bank_t *t = get_flash_bank_by_num_noprobe(0);
1167         if (t != NULL)
1168         {
1169                 base = t->base;
1170                 retval = JIM_OK;
1171     } else
1172         {
1173                 retval = JIM_ERR;
1174         }
1175
1176         if (retval == JIM_OK)
1177         {
1178                 Jim_SetResult(interp, Jim_NewIntObj(interp, base));
1179         }
1180
1181         return retval;
1182 }
1183
1184
1185
1186
1187
1188 static int
1189 zylinjtag_Jim_Command_log(Jim_Interp *interp,
1190                                    int argc,
1191                 Jim_Obj * const *argv)
1192 {
1193         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1194
1195         if (logCount >= logSize)
1196         {
1197         Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer+logCount%logSize, logSize-logCount%logSize);
1198         }
1199         Jim_AppendString(httpstate.jim_interp, tclOutput, logBuffer, writePtr);
1200
1201         Jim_SetResult(interp, tclOutput);
1202         return JIM_OK;
1203 }
1204
1205 static int
1206 zylinjtag_Jim_Command_reboot(Jim_Interp *interp,
1207                                    int argc,
1208                 Jim_Obj * const *argv)
1209 {
1210         reboot();
1211         return JIM_OK;
1212 }
1213
1214 static int
1215 zylinjtag_Jim_Command_mac(Jim_Interp *interp,
1216                                    int argc,
1217                 Jim_Obj * const *argv)
1218 {
1219
1220         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1221
1222         Jim_AppendString(httpstate.jim_interp, tclOutput, hwaddr, strlen(hwaddr));
1223
1224         Jim_SetResult(interp, tclOutput);
1225
1226         return JIM_OK;
1227 }
1228
1229 static int
1230 zylinjtag_Jim_Command_ip(Jim_Interp *interp,
1231                                    int argc,
1232                 Jim_Obj * const *argv)
1233 {
1234         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
1235
1236         struct ifaddrs *ifa = NULL, *ifp = NULL;
1237
1238         if (getifaddrs(&ifp) < 0)
1239         {
1240                 return JIM_ERR;
1241         }
1242
1243         for (ifa = ifp; ifa; ifa = ifa->ifa_next)
1244         {
1245                 char ip[200];
1246                 socklen_t salen;
1247
1248                 if (ifa->ifa_addr->sa_family == AF_INET)
1249                         salen = sizeof(struct sockaddr_in);
1250                 else if (ifa->ifa_addr->sa_family == AF_INET6)
1251                         salen = sizeof(struct sockaddr_in6);
1252                 else
1253                         continue;
1254
1255                 if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
1256                                 NI_NUMERICHOST) < 0)
1257                 {
1258                         continue;
1259                 }
1260
1261                 Jim_AppendString(httpstate.jim_interp, tclOutput, ip, strlen(ip));
1262                 break;
1263
1264         }
1265
1266         freeifaddrs(ifp);
1267
1268         Jim_SetResult(interp, tclOutput);
1269
1270         return JIM_OK;
1271 }
1272
1273 extern Jim_Interp *interp;
1274
1275
1276 static void zylinjtag_startNetwork()
1277 {
1278         // Bring TCP/IP up immediately before we're ready to accept commands.
1279         //
1280         // That is as soon as a PING responds, we're accepting telnet sessions.
1281 #if defined(CYGPKG_NET_FREEBSD_STACK)
1282         phi_init_all_network_interfaces();
1283 #else
1284         lwip_init();
1285 #endif
1286         if (!eth0_up)
1287         {
1288                 diag_printf("Network not up and running\n");
1289                 exit(-1);
1290         }
1291 #if defined(CYGPKG_NET_FREEBSD_STACK)
1292         /*start TFTP*/
1293         tftpd_start(69, &fileops);
1294 #endif
1295
1296         cyg_httpd_init_tcl_interpreter();
1297
1298         interp = httpstate.jim_interp;
1299
1300     Jim_CreateCommand(httpstate.jim_interp, "log", zylinjtag_Jim_Command_log, NULL, NULL);
1301     Jim_CreateCommand(httpstate.jim_interp, "reboot", zylinjtag_Jim_Command_reboot, NULL, NULL);
1302     Jim_CreateCommand(httpstate.jim_interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
1303     Jim_CreateCommand(httpstate.jim_interp, "zy1000_flash", zylinjtag_Jim_Command_flash, NULL, NULL);
1304     Jim_CreateCommand(httpstate.jim_interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
1305     Jim_CreateCommand(httpstate.jim_interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
1306     Jim_CreateCommand(httpstate.jim_interp, "threads", zylinjtag_Jim_Command_threads, NULL, NULL);
1307     Jim_CreateCommand(httpstate.jim_interp, "getmem", zylinjtag_Jim_Command_getmem, NULL, NULL);
1308     Jim_CreateCommand(httpstate.jim_interp, "mac", zylinjtag_Jim_Command_mac, NULL, NULL);
1309     Jim_CreateCommand(httpstate.jim_interp, "ip", zylinjtag_Jim_Command_ip, NULL, NULL);
1310     Jim_CreateCommand(httpstate.jim_interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
1311
1312         cyg_httpd_start();
1313
1314         webRunning = true;
1315
1316         diag_printf("Web server running\n");
1317
1318         int s;
1319         struct ifreq ifr;
1320         s = socket(AF_INET, SOCK_DGRAM, 0);
1321         if (s >= 0)
1322         {
1323                 strcpy(ifr.ifr_name, "eth0");
1324                 int res;
1325                 res = ioctl(s, SIOCGIFHWADDR, &ifr);
1326                 close(s);
1327
1328                 if (res < 0)
1329                 {
1330                         diag_printf("Can't obtain MAC address\n");
1331                         reboot();
1332                 }
1333         }
1334
1335         sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
1336                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
1337                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
1338                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
1339                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
1340                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
1341                         (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
1342
1343
1344         discover_message=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
1345
1346         discover_launch();
1347 }
1348
1349
1350
1351
1352
1353 static void
1354 print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_t info)
1355 {
1356         writeLog = false;
1357         serialLog = true;
1358         char *infoStr = "unknown";
1359         switch (exception)
1360         {
1361         case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
1362                 infoStr = "undefined instruction";
1363                 break;
1364         case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
1365                 infoStr = "software interrupt";
1366                 break;
1367         case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
1368                 infoStr = "abort prefetch";
1369                 break;
1370         case CYGNUM_HAL_VECTOR_ABORT_DATA:
1371                 infoStr = "abort data";
1372                 break;
1373         default:
1374                 break;
1375         }
1376
1377         diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1378
1379         diag_printf("Dumping log\n---\n");
1380         if (logCount >= logSize)
1381         {
1382                 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
1383         }
1384         diag_write(logBuffer, writePtr);
1385
1386         diag_printf("---\nLogdump complete.\n");
1387         diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1388         diag_printf("\n---\nRebooting\n");
1389         HAL_PLATFORM_RESET();
1390
1391 }
1392
1393 static void setHandler(cyg_code_t exception)
1394 {
1395         cyg_exception_handler_t *old_handler;
1396         cyg_addrword_t old_data;
1397
1398         cyg_exception_set_handler(exception,
1399         print_exception_handler,
1400         0,
1401         &old_handler,
1402         &old_data);
1403 }
1404
1405 static cyg_thread zylinjtag_uart_thread_object;
1406 static cyg_handle_t zylinjtag_uart_thread_handle;
1407 static char uart_stack[4096];
1408
1409 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1410 static char backwardBuffer[1024];
1411
1412 static cyg_io_handle_t serial_handle;
1413
1414 void setNoDelay(int session, int flag)
1415 {
1416 #if 1
1417         // This decreases latency dramatically for e.g. GDB load which
1418         // does not have a sliding window protocol
1419         //
1420         // Can cause *lots* of TCP/IP packets to be sent and it would have
1421         // to be enabled/disabled on the fly to avoid the CPU being
1422         // overloaded...
1423         setsockopt(session, /* socket affected */
1424         IPPROTO_TCP, /* set option at TCP level */
1425         TCP_NODELAY, /* name of option */
1426         (char *) &flag, /* the cast is historical
1427          cruft */
1428         sizeof(int)); /* length of option value */
1429 #endif
1430 }
1431
1432 struct
1433 {
1434         int req;
1435         int actual;
1436         int req2;
1437         int actual2;
1438 } tcpipSent[512 * 1024];
1439 int cur;
1440
1441 static void
1442 zylinjtag_uart(cyg_addrword_t data)
1443 {
1444         int so_reuseaddr_option = 1;
1445
1446         int fd;
1447         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1448         {
1449                 LOG_ERROR("error creating socket: %s", strerror(errno));
1450                 exit(-1);
1451         }
1452
1453         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
1454
1455         struct sockaddr_in sin;
1456         unsigned int address_size;
1457         address_size = sizeof(sin);
1458         memset(&sin, 0, sizeof(sin));
1459         sin.sin_family = AF_INET;
1460         sin.sin_addr.s_addr = INADDR_ANY;
1461         sin.sin_port = htons(5555);
1462
1463         if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
1464         {
1465                 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
1466                 exit(-1);
1467         }
1468
1469         if (listen(fd, 1) == -1)
1470         {
1471                 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
1472                 exit(-1);
1473         }
1474         //      socket_nonblock(fd);
1475
1476
1477         for (;;)
1478         {
1479                 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
1480                 if (session < 0)
1481                 {
1482                         continue;
1483                 }
1484
1485                 setNoDelay(session, 1);
1486                 int oldopts = fcntl(session, F_GETFL, 0);
1487                 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
1488
1489                 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
1490                 if (serHandle < 0)
1491                 {
1492                         close(session);
1493                         continue;
1494                 }
1495
1496                 start_profile();
1497                 int actual = 0;
1498                 int actual2 = 0;
1499                 int pos, pos2;
1500                 pos = 0;
1501                 pos2 = 0;
1502                 cur = 0;
1503                 for (;;)
1504                 {
1505                         fd_set write_fds;
1506                         fd_set read_fds;
1507                         FD_ZERO(&write_fds);
1508                         FD_ZERO(&read_fds);
1509                         int fd_max = -1;
1510                         FD_SET(session, &read_fds);
1511                         fd_max = session;
1512                         FD_SET(serHandle, &read_fds);
1513                         if (serHandle > fd_max)
1514                         {
1515                                 fd_max = serHandle;
1516                         }
1517                         /* Wait... */
1518
1519                         cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1520                         if ((actual == 0) && (actual2 == 0))
1521                         {
1522                                 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
1523                                 if (retval <= 0)
1524                                 {
1525                                         break;
1526                                 }
1527                         }
1528
1529                         if (actual2 <= 0)
1530                         {
1531                                 memset(backwardBuffer, 's', sizeof(backwardBuffer));
1532                                 actual2=read(serHandle, backwardBuffer, sizeof(backwardBuffer));
1533                                 if (actual2 < 0)
1534                                 {
1535                                         if (errno != EAGAIN)
1536                                         {
1537                                                 goto closeSession;
1538                                         }
1539                                         actual2 = 0;
1540                                 }
1541                                 pos2 = 0;
1542                         }
1543
1544                         int x = actual2;
1545                         int y = 0;
1546                         if (actual2 > 0)
1547                         {
1548                                 int written = write(session, backwardBuffer + pos2, actual2);
1549                                 if (written <= 0)
1550                                         goto closeSession;
1551                                 actual2 -= written;
1552                                 pos2 += written;
1553                                 y = written;
1554                         }
1555
1556                         if (FD_ISSET(session, &read_fds)&&(sizeof(forwardBuffer)>actual))
1557                         {
1558                                 // NB! Here it is important that we empty the TCP/IP read buffer
1559                                 // to make transmission tick right
1560                                 memmove(forwardBuffer, forwardBuffer + pos, actual);
1561                                 pos = 0;
1562                                 int t;
1563                                 // this will block if there is no data at all
1564                                 t=read_socket(session, forwardBuffer+actual, sizeof(forwardBuffer)-actual);
1565                                 if (t <= 0)
1566                                 {
1567                                         goto closeSession;
1568                                 }
1569                                 actual += t;
1570                         }
1571
1572                         int x2 = actual;
1573                         int y2 = 0;
1574                         if (actual > 0)
1575                         {
1576                                 /* Do not put things into the serial buffer if it has something to send
1577                                  * as that can cause a single byte to be sent at the time.
1578                                  *
1579                                  *
1580                                  */
1581                                 int written = write(serHandle, forwardBuffer + pos, actual);
1582                                 if (written < 0)
1583                                 {
1584                                         if (errno != EAGAIN)
1585                                         {
1586                                                 goto closeSession;
1587                                         }
1588                                         // The serial buffer is full
1589                                         written = 0;
1590                                 } else
1591                                 {
1592                                         actual -= written;
1593                                         pos += written;
1594                                 }
1595                                 y2 = written;
1596                         }
1597                         if (cur < 1024)
1598                         {
1599                                 tcpipSent[cur].req = x;
1600                                 tcpipSent[cur].actual = y;
1601                                 tcpipSent[cur].req2 = x2;
1602                                 tcpipSent[cur].actual2 = y2;
1603                                 cur++;
1604                         }
1605
1606                 }
1607             closeSession:
1608             close(session);
1609                 close(serHandle);
1610
1611                 int i;
1612                 for (i = 0; i < 1024; i++)
1613                 {
1614                 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual, tcpipSent[i].req2, tcpipSent[i].actual2);
1615
1616                 }
1617         }
1618         close(fd);
1619
1620 }
1621
1622 void startUart(void)
1623 {
1624     cyg_thread_create(1,
1625                       zylinjtag_uart,
1626                       (cyg_addrword_t)0,
1627                       "uart thread",
1628                       (void *)uart_stack,
1629                       sizeof(uart_stack),
1630                       &zylinjtag_uart_thread_handle,
1631                       &zylinjtag_uart_thread_object);
1632         cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
1633         cyg_thread_resume(zylinjtag_uart_thread_handle);
1634 }
1635
1636
1637
1638 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1639 {
1640         static int current_baud = 38400;
1641         if (argc == 0)
1642         {
1643                 command_print(cmd_ctx, "%d", current_baud);
1644                 return ERROR_OK;
1645         } else if (argc != 1)
1646         {
1647                 return ERROR_INVALID_ARGUMENTS;
1648         }
1649
1650         current_baud = atol(args[0]);
1651
1652         int baud;
1653         switch (current_baud)
1654         {
1655         case 9600:
1656                 baud = CYGNUM_SERIAL_BAUD_9600;
1657                 break;
1658         case 19200:
1659                 baud = CYGNUM_SERIAL_BAUD_19200;
1660                 break;
1661         case 38400:
1662                 baud = CYGNUM_SERIAL_BAUD_38400;
1663                 break;
1664         case 57600:
1665                 baud = CYGNUM_SERIAL_BAUD_57600;
1666                 break;
1667         case 115200:
1668                 baud = CYGNUM_SERIAL_BAUD_115200;
1669                 break;
1670         case 230400:
1671                 baud = CYGNUM_SERIAL_BAUD_230400;
1672                 break;
1673         default:
1674                 command_print(cmd_ctx, "unsupported baudrate");
1675                 return ERROR_INVALID_ARGUMENTS;
1676         }
1677
1678         cyg_serial_info_t buf;
1679         cyg_uint32 len = 1;
1680         //get existing serial configuration
1681         len = sizeof(cyg_serial_info_t);
1682         int err;
1683         err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
1684         err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf, &len);
1685         if (err != ENOERR)
1686         {
1687                 command_print(cmd_ctx, "Failed to get serial port settings %d", err);
1688                 return ERROR_OK;
1689         }
1690         buf.baud = baud;
1691
1692         err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf, &len);
1693         if (err != ENOERR)
1694         {
1695                 command_print(cmd_ctx, "Failed to set serial port settings %d", err);
1696                 return ERROR_OK;
1697         }
1698
1699         return ERROR_OK;
1700 }
1701
1702 bool logAllToSerial = false;
1703
1704 /* boolean parameter stored on config */
1705 bool boolParam(char *var)
1706 {
1707         bool result = false;
1708         char *name = alloc_printf(ZYLIN_CONFIG_DIR "/%s", var);
1709         if (name == NULL)
1710                 return result;
1711
1712         void *data;
1713         int len;
1714         if (loadFile(name, &data, &len) == ERROR_OK)
1715         {
1716                 if (len > 1)
1717                         len = 1;
1718                 result = strncmp((char *) data, "1", len) == 0;
1719                 free(data);
1720         }
1721         free(name);
1722         return result;
1723 }
1724
1725 command_context_t *setup_command_handler();
1726
1727 int add_default_dirs(void)
1728 {
1729         add_script_search_dir(ZYLIN_CONFIG_DIR);
1730         add_script_search_dir("/rom/lib/openocd");
1731         add_script_search_dir("/rom");
1732         return ERROR_OK;
1733 }
1734
1735 static cyg_uint8 *ramblockdevice;
1736 static const int ramblockdevice_size=4096*1024;
1737 int main(int argc, char *argv[])
1738 {
1739         /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1740          * need to allocate towards the end of the heap.  */
1741
1742         ramblockdevice=(cyg_uint8 *)malloc(ramblockdevice_size);
1743         memset(ramblockdevice, 0xff, ramblockdevice_size);
1744
1745         setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
1746         setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
1747         setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
1748
1749         int err;
1750         err = cyg_io_lookup("/dev/ser0", &serial_handle);
1751         if (err != ENOERR)
1752         {
1753                 diag_printf("/dev/ser0 not found\n");
1754                 reboot();
1755         }
1756
1757         setPower(true); // on by default
1758
1759         atexit(keep_webserver);
1760
1761         err = mount("", "/ram", "ramfs");
1762         if (err < 0)
1763         {
1764                 diag_printf("unable to mount ramfs\n");
1765         }
1766         chdir("/ram");
1767
1768         char address[16];
1769         sprintf(address, "%p", &filedata[0]);
1770         err = mount(address, "/rom", "romfs");
1771         if (err < 0)
1772         {
1773                 diag_printf("unable to mount /rom\n");
1774         }
1775
1776         err = mount("", "/log", "logfs");
1777         if (err < 0)
1778         {
1779                 diag_printf("unable to mount logfs\n");
1780         }
1781
1782         err = mount("", "/tftp", "tftpfs");
1783         if (err < 0)
1784         {
1785                 diag_printf("unable to mount logfs\n");
1786         }
1787
1788         log = fopen("/log/log", "w");
1789         if (log == NULL)
1790         {
1791                 diag_printf("Could not open log file /ram/log\n");
1792                 exit(-1);
1793         }
1794
1795         diag_init_putc(_zylinjtag_diag_write_char);
1796
1797         // We want this in the log.
1798         diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1799         diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);
1800
1801         copydir("/rom", "/ram/cgi");
1802
1803         err = mount("/dev/flash1", "/config", "jffs2");
1804         if (err < 0)
1805         {
1806                 diag_printf("unable to mount jffs\n");
1807                 reboot();
1808         }
1809
1810         /* are we using a ram disk instead of a flash disk? This is used
1811          * for ZY1000 live demo...
1812          *
1813          * copy over flash disk to ram block device
1814          */
1815         if (boolParam("ramdisk"))
1816         {
1817                 diag_printf("Unmounting /config from flash and using ram instead\n");
1818                 err=umount("/config");
1819                 if (err < 0)
1820                 {
1821                         diag_printf("unable to unmount jffs\n");
1822                         reboot();
1823                 }
1824
1825                 err = mount("/dev/flash1", "/config2", "jffs2");
1826                 if (err < 0)
1827                 {
1828                         diag_printf("unable to mount jffs\n");
1829                         reboot();
1830                 }
1831
1832                 err = mount("/dev/ram", "/config", "jffs2");
1833                 if (err < 0)
1834                 {
1835                         diag_printf("unable to mount ram block device\n");
1836                         reboot();
1837                 }
1838
1839 //              copydir("/config2", "/config");
1840                 copyfile("/config2/ip", "/config/ip");
1841                 copydir("/config2/settings", "/config/settings");
1842
1843                 umount("/config2");
1844         } else
1845         {
1846                 /* we're not going to use a ram block disk */
1847                 free(ramblockdevice);
1848         }
1849
1850
1851         mkdir(ZYLIN_CONFIG_DIR, 0777);
1852         mkdir(ZYLIN_CONFIG_DIR "/target", 0777);
1853         mkdir(ZYLIN_CONFIG_DIR "/event", 0777);
1854
1855         logAllToSerial = boolParam("logserial");
1856
1857         // We need the network & web server in case there is something wrong with
1858         // the config files that invoke exit()
1859         zylinjtag_startNetwork();
1860
1861         /* we're going to access the jim interpreter from here on... */
1862         openocd_sleep_postlude();
1863         startUart();
1864
1865         add_default_dirs();
1866
1867         /* initialize commandline interface */
1868         command_context_t *cmd_ctx;
1869         cmd_ctx = setup_command_handler();
1870         command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1871         command_context_mode(cmd_ctx, COMMAND_CONFIG);
1872
1873
1874         register_command(cmd_ctx, NULL, "zy1000_version", handle_zy1000_version_command,
1875                         COMMAND_EXEC, "show zy1000 version numbers");
1876
1877         register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
1878                         "remove file");
1879
1880         register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,
1881                         "same args as load_image, image stored in memory");
1882
1883         register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY,
1884                         "loads active fast load image to current target");
1885
1886         register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
1887                         "display file content");
1888
1889         register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
1890                         "truncate a file to 0 size");
1891
1892         register_command(cmd_ctx, NULL, "append_file", handle_append_command,
1893                         COMMAND_ANY, "append a variable number of strings to a file");
1894
1895         register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,
1896                         "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1897
1898         register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
1899                         COMMAND_ANY, "display available ram memory");
1900
1901         register_command(cmd_ctx, NULL, "cp", handle_cp_command,
1902                                          COMMAND_ANY, "copy a file <from> <to>");
1903
1904 #ifdef CYGPKG_PROFILE_GPROF
1905         register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1906                         COMMAND_ANY, NULL);
1907 #endif
1908         register_command(cmd_ctx, NULL, "uart", handle_uart_command,
1909                                          COMMAND_ANY, "uart <baud>  - forward uart on port 5555");
1910
1911
1912         int errVal;
1913         errVal = log_init(cmd_ctx);
1914         if (errVal != ERROR_OK)
1915         {
1916                 diag_printf("log_init() failed %d\n", errVal);
1917                 exit(-1);
1918         }
1919
1920         set_log_output(cmd_ctx, log);
1921
1922         LOG_DEBUG("log init complete");
1923
1924         //      diag_printf("Executing config files\n");
1925
1926         if (logAllToSerial)
1927         {
1928                 diag_printf(ZYLIN_CONFIG_DIR "/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1929                 command_run_line(cmd_ctx, "debug_level 3");
1930         }
1931
1932         zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");
1933
1934         // FIX!!!  Yuk!
1935         // diag_printf() is really invoked from many more places than we trust it
1936         // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1937         //
1938         // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1939         // fingers that it doesn't cause any crashes.
1940         diag_printf("Init complete, GDB & telnet servers launched.\n");
1941         command_set_output_handler(cmd_ctx, zy1000_configuration_output_handler_log, NULL);
1942         if (!logAllToSerial)
1943         {
1944                 serialLog = false;
1945         }
1946
1947         /* handle network connections */
1948         server_loop(cmd_ctx);
1949         openocd_sleep_prelude();
1950
1951         /* shut server down */
1952         server_quit();
1953
1954         /* free commandline interface */
1955         command_done(cmd_ctx);
1956         umount("/config");
1957
1958         exit(0);
1959         for (;;);
1960 }
1961
1962
1963
1964 cyg_int32
1965 cyg_httpd_exec_cgi_tcl(char *file_name);
1966 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1967 {
1968         cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1969         return 0;
1970 }
1971
1972 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1973
1974 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1975 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1976
1977 #include <pkgconf/system.h>
1978 #include <pkgconf/hal.h>
1979 #include <pkgconf/kernel.h>
1980 #include <pkgconf/io_fileio.h>
1981 #include <pkgconf/fs_rom.h>
1982
1983 #include <cyg/kernel/ktypes.h>         // base kernel types
1984 #include <cyg/infra/cyg_trac.h>        // tracing macros
1985 #include <cyg/infra/cyg_ass.h>         // assertion macros
1986 #include <unistd.h>
1987 #include <sys/types.h>
1988 #include <fcntl.h>
1989 #include <sys/stat.h>
1990 #include <errno.h>
1991 #include <dirent.h>
1992
1993 #include <stdarg.h>
1994 #include <stdio.h>
1995 #include <stdlib.h>
1996 #include <string.h>
1997
1998 #include <cyg/fileio/fileio.h>
1999
2000 #include <cyg/kernel/kapi.h>
2001 #include <cyg/infra/diag.h>
2002
2003 //==========================================================================
2004 // Eventually we want to eXecute In Place from the ROM in a protected
2005 // environment, so we'll need executables to be aligned to a boundary
2006 // suitable for MMU protection. A suitable boundary would be the 4k
2007 // boundary in all the CPU architectures I am currently aware of.
2008
2009 // Forward definitions
2010
2011 // Filesystem operations
2012 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
2013 static int tftpfs_umount(cyg_mtab_entry *mte);
2014 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2015                 int mode, cyg_file *fte);
2016 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2017 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2018
2019 // File operations
2020 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2021 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
2022 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
2023
2024 //==========================================================================
2025 // Filesystem table entries
2026
2027 // -------------------------------------------------------------------------
2028 // Fstab entry.
2029 // This defines the entry in the filesystem table.
2030 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2031 // we should never block in any filesystem operations.
2032 #if 1
2033 FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,
2034                 CYG_SYNCMODE_NONE,
2035                 tftpfs_mount,
2036                 tftpfs_umount,
2037                 tftpfs_open,
2038                 (cyg_fsop_unlink *)cyg_fileio_erofs,
2039                 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2040                 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2041                 (cyg_fsop_rename *)cyg_fileio_erofs,
2042                 (cyg_fsop_link *)cyg_fileio_erofs,
2043                 (cyg_fsop_opendir *)cyg_fileio_erofs,
2044                 (cyg_fsop_chdir *)cyg_fileio_erofs,
2045                 (cyg_fsop_stat *)cyg_fileio_erofs,
2046                 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2047                 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2048 #endif
2049
2050 // -------------------------------------------------------------------------
2051 // mtab entry.
2052 // This defines a single ROMFS loaded into ROM at the configured address
2053 //
2054 // MTAB_ENTRY(  rom_mte,        // structure name
2055 //              "/rom",         // mount point
2056 //              "romfs",        // FIlesystem type
2057 //              "",             // hardware device
2058 //  (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS   // Address in ROM
2059 //           );
2060
2061
2062 // -------------------------------------------------------------------------
2063 // File operations.
2064 // This set of file operations are used for normal open files.
2065
2066 static cyg_fileops tftpfs_fileops =
2067 {
2068         tftpfs_fo_read,
2069         tftpfs_fo_write,
2070         tftpfs_fo_lseek,
2071         (cyg_fileop_ioctl *)cyg_fileio_erofs,
2072     cyg_fileio_seltrue,
2073     tftpfs_fo_fsync,
2074     tftpfs_fo_close,
2075                 (cyg_fileop_fstat *) cyg_fileio_erofs,
2076                 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2077         (cyg_fileop_setinfo *)cyg_fileio_erofs,
2078 };
2079
2080 // -------------------------------------------------------------------------
2081 // tftpfs_mount()
2082 // Process a mount request. This mainly finds root for the
2083 // filesystem.
2084
2085 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2086 {
2087         return ENOERR;
2088 }
2089
2090 static int tftpfs_umount(cyg_mtab_entry *mte)
2091 {
2092         return ENOERR;
2093 }
2094
2095 struct Tftp
2096 {
2097         int write;
2098         int readFile;
2099         cyg_uint8 *mem;
2100         int actual;
2101         char *server;
2102         char *file;
2103 };
2104
2105 static void freeTftp(struct Tftp *t)
2106 {
2107         if (t == NULL)
2108                 return;
2109         if (t->mem)
2110                 free(t->mem);
2111         if (t->server)
2112                 free(t->server);
2113         if (t->file)
2114                 free(t->file);
2115         free(t);
2116 }
2117
2118 static const int tftpMaxSize = 8192 * 1024;
2119 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2120                 int mode, cyg_file *file)
2121 {
2122         struct Tftp *tftp;
2123         tftp = malloc(sizeof(struct Tftp));
2124         if (tftp == NULL)
2125                 return EMFILE;
2126         memset(tftp, 0, sizeof(struct Tftp));
2127
2128         file->f_flag |= mode & CYG_FILE_MODE_MASK;
2129         file->f_type = CYG_FILE_TYPE_FILE;
2130         file->f_ops = &tftpfs_fileops;
2131         file->f_offset = 0;
2132         file->f_data = 0;
2133         file->f_xops = 0;
2134
2135         tftp->mem = malloc(tftpMaxSize);
2136         if (tftp->mem == NULL)
2137         {
2138                 freeTftp(tftp);
2139                 return EMFILE;
2140         }
2141
2142         char *server = strchr(name, '/');
2143         if (server == NULL)
2144         {
2145                 freeTftp(tftp);
2146                 return EMFILE;
2147         }
2148
2149         tftp->server = malloc(server - name + 1);
2150         if (tftp->server == NULL)
2151         {
2152                 freeTftp(tftp);
2153                 return EMFILE;
2154         }
2155         strncpy(tftp->server, name, server - name);
2156         tftp->server[server - name] = 0;
2157
2158         tftp->file = strdup(server + 1);
2159         if (tftp->file == NULL)
2160         {
2161                 freeTftp(tftp);
2162                 return EMFILE;
2163         }
2164
2165         file->f_data = (CYG_ADDRWORD) tftp;
2166
2167         return ENOERR;
2168 }
2169
2170 static int fetchTftp(struct Tftp *tftp)
2171 {
2172         if (!tftp->readFile)
2173         {
2174                 int err;
2175             tftp->actual = tftp_client_get( tftp->file, tftp->server, 0, tftp->mem, tftpMaxSize,   TFTP_OCTET, &err);
2176
2177                 if (tftp->actual < 0)
2178                 {
2179                         return EMFILE;
2180                 }
2181                 tftp->readFile = 1;
2182         }
2183         return ENOERR;
2184 }
2185
2186 // -------------------------------------------------------------------------
2187 // tftpfs_fo_write()
2188 // Read data from file.
2189
2190 static int
2191 tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2192 {
2193         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2194
2195         if (fetchTftp(tftp) != ENOERR)
2196                 return EMFILE;
2197
2198         int i;
2199         off_t pos = fp->f_offset;
2200         int resid = 0;
2201         for (i = 0; i < uio->uio_iovcnt; i++)
2202         {
2203                 cyg_iovec *iov = &uio->uio_iov[i];
2204                 char *buf = (char *) iov->iov_base;
2205                 off_t len = iov->iov_len;
2206
2207                 if (len + pos > tftp->actual)
2208                 {
2209                         len = tftp->actual - pos;
2210                 }
2211                 resid += iov->iov_len - len;
2212
2213                 memcpy(buf, tftp->mem + pos, len);
2214                 pos += len;
2215
2216         }
2217         uio->uio_resid = resid;
2218         fp->f_offset = pos;
2219
2220         return ENOERR;
2221 }
2222
2223
2224 static int
2225 tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2226 {
2227         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2228
2229         int i;
2230         off_t pos = fp->f_offset;
2231         int resid = 0;
2232         for (i = 0; i < uio->uio_iovcnt; i++)
2233         {
2234                 cyg_iovec *iov = &uio->uio_iov[i];
2235                 char *buf = (char *) iov->iov_base;
2236                 off_t len = iov->iov_len;
2237
2238                 if (len + pos > tftpMaxSize)
2239                 {
2240                         len = tftpMaxSize - pos;
2241                 }
2242                 resid += iov->iov_len - len;
2243
2244                 memcpy(tftp->mem + pos, buf, len);
2245                 pos += len;
2246
2247         }
2248         uio->uio_resid = resid;
2249         fp->f_offset = pos;
2250
2251         tftp->write = 1;
2252
2253         return ENOERR;
2254 }
2255
2256 static int
2257 tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2258 {
2259         int error = ENOERR;
2260         return error;
2261 }
2262
2263 // -------------------------------------------------------------------------
2264 // romfs_fo_close()
2265 // Close a file. We just clear out the data pointer.
2266
2267 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
2268 {
2269         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2270         int error = ENOERR;
2271
2272         if (tftp->write)
2273         {
2274             tftp_client_put( tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,   TFTP_OCTET, &error);
2275         }
2276
2277         freeTftp(tftp);
2278         fp->f_data = 0;
2279         return error;
2280 }
2281
2282 // -------------------------------------------------------------------------
2283 // romfs_fo_lseek()
2284 // Seek to a new file position.
2285
2286 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
2287 {
2288         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2289         off_t pos = *apos;
2290
2291         if (fetchTftp(tftp) != ENOERR)
2292                 return EMFILE;
2293
2294         switch (whence)
2295         {
2296         case SEEK_SET:
2297                 // Pos is already where we want to be.
2298                 break;
2299
2300         case SEEK_CUR:
2301                 // Add pos to current offset.
2302                 pos += fp->f_offset;
2303                 break;
2304
2305         case SEEK_END:
2306                 // Add pos to file size.
2307                 pos += tftp->actual;
2308                 break;
2309
2310         default:
2311                 return EINVAL;
2312         }
2313
2314         // Check that pos is still within current file size, or at the
2315         // very end.
2316         if (pos < 0 || pos > tftp->actual)
2317                 return EINVAL;
2318
2319         // All OK, set fp offset and return new position.
2320         *apos = fp->f_offset = pos;
2321
2322         return ENOERR;
2323 }
2324
2325 void usleep(int us)
2326 {
2327         if (us > 10000)
2328                 cyg_thread_delay(us / 10000 + 1);
2329         else
2330                 HAL_DELAY_US(us);
2331 }
2332
2333 // Chunked version.
2334 cyg_int32
2335 show_log_entry(CYG_HTTPD_STATE *phttpstate)
2336 {
2337         cyg_httpd_start_chunked("text");
2338         if (logCount >= logSize)
2339         {
2340         cyg_httpd_write_chunked(logBuffer+logCount%logSize, logSize-logCount%logSize);
2341         }
2342         cyg_httpd_write_chunked(logBuffer, writePtr);
2343         cyg_httpd_end_chunked();
2344         return -1;
2345 }
2346
2347 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
2348
2349 // Filesystem operations
2350 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
2351 static int logfs_umount(cyg_mtab_entry *mte);
2352 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2353                 int mode, cyg_file *fte);
2354 static int
2355 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2356
2357 // File operations
2358 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2359 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
2360
2361 #include <cyg/io/devtab.h>
2362
2363 //==========================================================================
2364 // Filesystem table entries
2365
2366 // -------------------------------------------------------------------------
2367 // Fstab entry.
2368 // This defines the entry in the filesystem table.
2369 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2370 // we should never block in any filesystem operations.
2371 FSTAB_ENTRY( logfs_fste, "logfs", 0,
2372                 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
2373                 logfs_mount,
2374                 logfs_umount,
2375                 logfs_open,
2376                 (cyg_fsop_unlink *)cyg_fileio_erofs,
2377                 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2378                 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2379                 (cyg_fsop_rename *)cyg_fileio_erofs,
2380                 (cyg_fsop_link *)cyg_fileio_erofs,
2381                 (cyg_fsop_opendir *)cyg_fileio_erofs,
2382                 (cyg_fsop_chdir *)cyg_fileio_erofs,
2383                 (cyg_fsop_stat *)cyg_fileio_erofs,
2384                 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2385                 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2386
2387 // -------------------------------------------------------------------------
2388 // File operations.
2389 // This set of file operations are used for normal open files.
2390
2391 static cyg_fileops logfs_fileops =
2392 {
2393         (cyg_fileop_read *)cyg_fileio_erofs,
2394     (cyg_fileop_write *)logfs_fo_write,
2395                 (cyg_fileop_lseek *) cyg_fileio_erofs,
2396         (cyg_fileop_ioctl *)cyg_fileio_erofs,
2397     cyg_fileio_seltrue,
2398     logfs_fo_fsync,
2399     logfs_fo_close,
2400         (cyg_fileop_fstat *)cyg_fileio_erofs,
2401                 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2402         (cyg_fileop_setinfo *)cyg_fileio_erofs,
2403 };
2404
2405 // -------------------------------------------------------------------------
2406 // logfs_mount()
2407 // Process a mount request. This mainly finds root for the
2408 // filesystem.
2409
2410 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2411 {
2412         return ENOERR;
2413 }
2414
2415 static int logfs_umount(cyg_mtab_entry *mte)
2416 {
2417         return ENOERR;
2418 }
2419
2420 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2421                 int mode, cyg_file *file)
2422 {
2423         file->f_flag |= mode & CYG_FILE_MODE_MASK;
2424         file->f_type = CYG_FILE_TYPE_FILE;
2425         file->f_ops = &logfs_fileops;
2426         file->f_offset = 0;
2427         file->f_data = 0;
2428         file->f_xops = 0;
2429         return ENOERR;
2430 }
2431
2432 // -------------------------------------------------------------------------
2433 // logfs_fo_write()
2434 // Write data to file.
2435
2436 static int
2437 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2438 {
2439         int i;
2440         for (i = 0; i < uio->uio_iovcnt; i++)
2441         {
2442                 cyg_iovec *iov = &uio->uio_iov[i];
2443                 char *buf = (char *) iov->iov_base;
2444                 off_t len = iov->iov_len;
2445
2446                 diag_write(buf, len);
2447         }
2448         uio->uio_resid = 0;
2449
2450         return ENOERR;
2451 }
2452 static int
2453 logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2454 {
2455         return ENOERR;
2456 }
2457
2458 // -------------------------------------------------------------------------
2459 // romfs_fo_close()
2460 // Close a file. We just clear out the data pointer.
2461
2462 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
2463 {
2464         return ENOERR;
2465 }
2466
2467 static bool
2468 ramiodev_init( struct cyg_devtab_entry *tab )
2469 {
2470         return true;
2471 }
2472
2473 static Cyg_ErrNo
2474 ramiodev_bread( cyg_io_handle_t handle, void *buf, cyg_uint32 *len,
2475                   cyg_uint32 pos)
2476 {
2477         if (*len+pos>ramblockdevice_size)
2478         {
2479                 *len=ramblockdevice_size-pos;
2480         }
2481         memcpy(buf, ramblockdevice+pos, *len);
2482         return ENOERR;
2483 }
2484
2485 static Cyg_ErrNo
2486 ramiodev_bwrite( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len,
2487                    cyg_uint32 pos )
2488 {
2489         if (((pos%4)!=0)||(((*len)%4)!=0))
2490         {
2491                 diag_printf("Unaligned write %d %d!", pos, *len);
2492         }
2493
2494         memcpy(ramblockdevice+pos, buf, *len);
2495         return ENOERR;
2496 }
2497
2498 static Cyg_ErrNo
2499 ramiodev_get_config( cyg_io_handle_t handle,
2500                        cyg_uint32 key,
2501                        void* buf,
2502                        cyg_uint32* len)
2503 {
2504     switch (key) {
2505     case CYG_IO_GET_CONFIG_FLASH_ERASE:
2506     {
2507         if ( *len != sizeof( cyg_io_flash_getconfig_erase_t ) )
2508              return -EINVAL;
2509         {
2510             cyg_io_flash_getconfig_erase_t *e = (cyg_io_flash_getconfig_erase_t *)buf;
2511             char *startpos = ramblockdevice + e->offset;
2512
2513             if (((e->offset%(64*1024))!=0)||((e->len%(64*1024))!=0))
2514             {
2515                 diag_printf("Erease is not aligned %d %d\n", e->offset, e->len);
2516             }
2517
2518             memset(startpos, 0xff, e->len);
2519
2520             e->flasherr = 0;
2521         }
2522         return ENOERR;
2523     }
2524     case CYG_IO_GET_CONFIG_FLASH_DEVSIZE:
2525     {
2526         if ( *len != sizeof( cyg_io_flash_getconfig_devsize_t ) )
2527              return -EINVAL;
2528         {
2529             cyg_io_flash_getconfig_devsize_t *d =
2530                 (cyg_io_flash_getconfig_devsize_t *)buf;
2531
2532                         d->dev_size = ramblockdevice_size;
2533         }
2534         return ENOERR;
2535     }
2536
2537     case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE:
2538     {
2539         cyg_io_flash_getconfig_blocksize_t *b =
2540             (cyg_io_flash_getconfig_blocksize_t *)buf;
2541         if ( *len != sizeof( cyg_io_flash_getconfig_blocksize_t ) )
2542              return -EINVAL;
2543
2544         // offset unused for now
2545                 b->block_size = 64*1024;
2546         return ENOERR;
2547     }
2548
2549     default:
2550         return -EINVAL;
2551     }
2552 }
2553
2554 static Cyg_ErrNo
2555 ramiodev_set_config( cyg_io_handle_t handle,
2556                        cyg_uint32 key,
2557                        const void* buf,
2558                        cyg_uint32* len)
2559 {
2560
2561     switch (key) {
2562     default:
2563         return -EINVAL;
2564     }
2565 } // ramiodev_set_config()
2566
2567 // get_config/set_config should be added later to provide the other flash
2568 // operations possible, like erase etc.
2569
2570 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops,
2571                    &ramiodev_bwrite,
2572                    &ramiodev_bread,
2573                    0, // no select
2574                    &ramiodev_get_config,
2575                    &ramiodev_set_config
2576     );
2577
2578
2579 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1,
2580                     "/dev/ram",
2581                     0,
2582                     &cyg_io_ramdev1_ops,
2583                     &ramiodev_init,
2584                     0, // No lookup required
2585                     NULL );