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