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