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