zy1000 1.46
[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.46"
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
1340
1341
1342
1343 static void
1344 print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_t info)
1345 {
1346         writeLog = false;
1347         serialLog = true;
1348         char *infoStr = "unknown";
1349         switch (exception)
1350         {
1351         case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
1352                 infoStr = "undefined instruction";
1353                 break;
1354         case CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT:
1355                 infoStr = "software interrupt";
1356                 break;
1357         case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:
1358                 infoStr = "abort prefetch";
1359                 break;
1360         case CYGNUM_HAL_VECTOR_ABORT_DATA:
1361                 infoStr = "abort data";
1362                 break;
1363         default:
1364                 break;
1365         }
1366
1367         diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1368
1369         diag_printf("Dumping log\n---\n");
1370         if (logCount >= logSize)
1371         {
1372                 diag_write(logBuffer + logCount % logSize, logSize - logCount % logSize);
1373         }
1374         diag_write(logBuffer, writePtr);
1375
1376         diag_printf("---\nLogdump complete.\n");
1377         diag_printf("Exception: %08x(%s) %08x\n", exception, infoStr, info);
1378         diag_printf("\n---\nRebooting\n");
1379         HAL_PLATFORM_RESET();
1380
1381 }
1382
1383 static void setHandler(cyg_code_t exception)
1384 {
1385         cyg_exception_handler_t *old_handler;
1386         cyg_addrword_t old_data;
1387
1388         cyg_exception_set_handler(exception,
1389         print_exception_handler,
1390         0,
1391         &old_handler,
1392         &old_data);
1393 }
1394
1395 static cyg_thread zylinjtag_uart_thread_object;
1396 static cyg_handle_t zylinjtag_uart_thread_handle;
1397 static char uart_stack[4096];
1398
1399 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
1400 static char backwardBuffer[1024];
1401
1402 static cyg_io_handle_t serial_handle;
1403
1404 void setNoDelay(int session, int flag)
1405 {
1406 #if 1
1407         // This decreases latency dramatically for e.g. GDB load which
1408         // does not have a sliding window protocol
1409         //
1410         // Can cause *lots* of TCP/IP packets to be sent and it would have
1411         // to be enabled/disabled on the fly to avoid the CPU being
1412         // overloaded...
1413         setsockopt(session, /* socket affected */
1414         IPPROTO_TCP, /* set option at TCP level */
1415         TCP_NODELAY, /* name of option */
1416         (char *) &flag, /* the cast is historical
1417          cruft */
1418         sizeof(int)); /* length of option value */
1419 #endif
1420 }
1421
1422 struct
1423 {
1424         int req;
1425         int actual;
1426         int req2;
1427         int actual2;
1428 } tcpipSent[512 * 1024];
1429 int cur;
1430
1431 static void
1432 zylinjtag_uart(cyg_addrword_t data)
1433 {
1434         int so_reuseaddr_option = 1;
1435
1436         int fd;
1437         if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
1438         {
1439                 LOG_ERROR("error creating socket: %s", strerror(errno));
1440                 exit(-1);
1441         }
1442
1443         setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&so_reuseaddr_option, sizeof(int));
1444
1445         struct sockaddr_in sin;
1446         unsigned int address_size;
1447         address_size = sizeof(sin);
1448         memset(&sin, 0, sizeof(sin));
1449         sin.sin_family = AF_INET;
1450         sin.sin_addr.s_addr = INADDR_ANY;
1451         sin.sin_port = htons(5555);
1452
1453         if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) == -1)
1454         {
1455                 LOG_ERROR("couldn't bind to socket: %s", strerror(errno));
1456                 exit(-1);
1457         }
1458
1459         if (listen(fd, 1) == -1)
1460         {
1461                 LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
1462                 exit(-1);
1463         }
1464         //      socket_nonblock(fd);
1465
1466
1467         for (;;)
1468         {
1469                 int session = accept(fd, (struct sockaddr *) &sin, &address_size);
1470                 if (session < 0)
1471                 {
1472                         continue;
1473                 }
1474
1475                 setNoDelay(session, 1);
1476                 int oldopts = fcntl(session, F_GETFL, 0);
1477                 fcntl(session, F_SETFL, oldopts | O_NONBLOCK); //
1478
1479                 int serHandle = open("/dev/ser0", O_RDWR | O_NONBLOCK);
1480                 if (serHandle < 0)
1481                 {
1482                         close(session);
1483                         continue;
1484                 }
1485
1486                 start_profile();
1487                 int actual = 0;
1488                 int actual2 = 0;
1489                 int pos, pos2;
1490                 pos = 0;
1491                 pos2 = 0;
1492                 cur = 0;
1493                 for (;;)
1494                 {
1495                         fd_set write_fds;
1496                         fd_set read_fds;
1497                         FD_ZERO(&write_fds);
1498                         FD_ZERO(&read_fds);
1499                         int fd_max = -1;
1500                         FD_SET(session, &read_fds);
1501                         fd_max = session;
1502                         FD_SET(serHandle, &read_fds);
1503                         if (serHandle > fd_max)
1504                         {
1505                                 fd_max = serHandle;
1506                         }
1507                         /* Wait... */
1508
1509                         cyg_thread_delay(5); // 50ms fixed delay to wait for data to be sent/received
1510                         if ((actual == 0) && (actual2 == 0))
1511                         {
1512                                 int retval = select(fd_max + 1, &read_fds, NULL, NULL, NULL);
1513                                 if (retval <= 0)
1514                                 {
1515                                         break;
1516                                 }
1517                         }
1518
1519                         if (actual2 <= 0)
1520                         {
1521                                 memset(backwardBuffer, 's', sizeof(backwardBuffer));
1522                                 actual2=read(serHandle, backwardBuffer, sizeof(backwardBuffer));
1523                                 if (actual2 < 0)
1524                                 {
1525                                         if (errno != EAGAIN)
1526                                         {
1527                                                 goto closeSession;
1528                                         }
1529                                         actual2 = 0;
1530                                 }
1531                                 pos2 = 0;
1532                         }
1533
1534                         int x = actual2;
1535                         int y = 0;
1536                         if (actual2 > 0)
1537                         {
1538                                 int written = write(session, backwardBuffer + pos2, actual2);
1539                                 if (written <= 0)
1540                                         goto closeSession;
1541                                 actual2 -= written;
1542                                 pos2 += written;
1543                                 y = written;
1544                         }
1545
1546                         if (FD_ISSET(session, &read_fds)&&(sizeof(forwardBuffer)>actual))
1547                         {
1548                                 // NB! Here it is important that we empty the TCP/IP read buffer
1549                                 // to make transmission tick right
1550                                 memmove(forwardBuffer, forwardBuffer + pos, actual);
1551                                 pos = 0;
1552                                 int t;
1553                                 // this will block if there is no data at all
1554                                 t=read_socket(session, forwardBuffer+actual, sizeof(forwardBuffer)-actual);
1555                                 if (t <= 0)
1556                                 {
1557                                         goto closeSession;
1558                                 }
1559                                 actual += t;
1560                         }
1561
1562                         int x2 = actual;
1563                         int y2 = 0;
1564                         if (actual > 0)
1565                         {
1566                                 /* Do not put things into the serial buffer if it has something to send
1567                                  * as that can cause a single byte to be sent at the time.
1568                                  *
1569                                  *
1570                                  */
1571                                 int written = write(serHandle, forwardBuffer + pos, actual);
1572                                 if (written < 0)
1573                                 {
1574                                         if (errno != EAGAIN)
1575                                         {
1576                                                 goto closeSession;
1577                                         }
1578                                         // The serial buffer is full
1579                                         written = 0;
1580                                 } else
1581                                 {
1582                                         actual -= written;
1583                                         pos += written;
1584                                 }
1585                                 y2 = written;
1586                         }
1587                         if (cur < 1024)
1588                         {
1589                                 tcpipSent[cur].req = x;
1590                                 tcpipSent[cur].actual = y;
1591                                 tcpipSent[cur].req2 = x2;
1592                                 tcpipSent[cur].actual2 = y2;
1593                                 cur++;
1594                         }
1595
1596                 }
1597             closeSession:
1598             close(session);
1599                 close(serHandle);
1600
1601                 int i;
1602                 for (i = 0; i < 1024; i++)
1603                 {
1604                 diag_printf("%d %d %d %d\n", tcpipSent[i].req, tcpipSent[i].actual, tcpipSent[i].req2, tcpipSent[i].actual2);
1605
1606                 }
1607         }
1608         close(fd);
1609
1610 }
1611
1612 void startUart(void)
1613 {
1614     cyg_thread_create(1,
1615                       zylinjtag_uart,
1616                       (cyg_addrword_t)0,
1617                       "uart thread",
1618                       (void *)uart_stack,
1619                       sizeof(uart_stack),
1620                       &zylinjtag_uart_thread_handle,
1621                       &zylinjtag_uart_thread_object);
1622         cyg_thread_set_priority(zylinjtag_uart_thread_handle, 1); // low priority as it sits in a busy loop
1623         cyg_thread_resume(zylinjtag_uart_thread_handle);
1624 }
1625
1626
1627
1628 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1629 {
1630         if (argc != 1)
1631         {
1632                 command_print(cmd_ctx, "usage: uart <baudrate>");
1633                 return ERROR_INVALID_ARGUMENTS;
1634         }
1635
1636         int baud = atol(args[0]);
1637
1638         switch (baud)
1639         {
1640         case 9600:
1641                 baud = CYGNUM_SERIAL_BAUD_9600;
1642                 break;
1643         case 19200:
1644                 baud = CYGNUM_SERIAL_BAUD_19200;
1645                 break;
1646         case 38400:
1647                 baud = CYGNUM_SERIAL_BAUD_38400;
1648                 break;
1649         case 57600:
1650                 baud = CYGNUM_SERIAL_BAUD_57600;
1651                 break;
1652         case 115200:
1653                 baud = CYGNUM_SERIAL_BAUD_115200;
1654                 break;
1655         case 230400:
1656                 baud = CYGNUM_SERIAL_BAUD_230400;
1657                 break;
1658         default:
1659                 command_print(cmd_ctx, "unsupported baudrate");
1660                 return ERROR_INVALID_ARGUMENTS;
1661         }
1662
1663         cyg_serial_info_t buf;
1664         cyg_uint32 len = 1;
1665         //get existing serial configuration
1666         len = sizeof(cyg_serial_info_t);
1667         int err;
1668         err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
1669         err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf, &len);
1670         if (err != ENOERR)
1671         {
1672                 command_print(cmd_ctx, "Failed to get serial port settings %d", err);
1673                 return ERROR_OK;
1674         }
1675         buf.baud = baud;
1676
1677         err = cyg_io_set_config(serial_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buf, &len);
1678         if (err != ENOERR)
1679         {
1680                 command_print(cmd_ctx, "Failed to set serial port settings %d", err);
1681                 return ERROR_OK;
1682         }
1683
1684         return ERROR_OK;
1685 }
1686
1687 bool logAllToSerial = false;
1688
1689 /* boolean parameter stored on config */
1690 bool boolParam(char *var)
1691 {
1692         bool result = false;
1693         char *name = alloc_printf(ZYLIN_CONFIG_DIR "/%s", var);
1694         if (name == NULL)
1695                 return result;
1696
1697         void *data;
1698         int len;
1699         if (loadFile(name, &data, &len) == ERROR_OK)
1700         {
1701                 if (len > 1)
1702                         len = 1;
1703                 result = strncmp((char *) data, "1", len) == 0;
1704                 free(data);
1705         }
1706         free(name);
1707         return result;
1708 }
1709
1710 command_context_t *setup_command_handler();
1711
1712 int add_default_dirs(void)
1713 {
1714         add_script_search_dir(ZYLIN_CONFIG_DIR);
1715         add_script_search_dir("/rom/lib/openocd");
1716         add_script_search_dir("/rom");
1717         return ERROR_OK;
1718 }
1719
1720 static cyg_uint8 *ramblockdevice;
1721 static const int ramblockdevice_size=4096*1024;
1722 int main(int argc, char *argv[])
1723 {
1724         /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
1725          * need to allocate towards the end of the heap.  */
1726
1727         ramblockdevice=(cyg_uint8 *)malloc(ramblockdevice_size);
1728         memset(ramblockdevice, 0xff, ramblockdevice_size);
1729
1730         setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
1731         setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
1732         setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
1733
1734         int err;
1735         err = cyg_io_lookup("/dev/ser0", &serial_handle);
1736         if (err != ENOERR)
1737         {
1738                 diag_printf("/dev/ser0 not found\n");
1739                 reboot();
1740         }
1741
1742         setPower(true); // on by default
1743
1744         atexit(keep_webserver);
1745
1746         err = mount("", "/ram", "ramfs");
1747         if (err < 0)
1748         {
1749                 diag_printf("unable to mount ramfs\n");
1750         }
1751         chdir("/ram");
1752
1753         char address[16];
1754         sprintf(address, "%p", &filedata[0]);
1755         err = mount(address, "/rom", "romfs");
1756         if (err < 0)
1757         {
1758                 diag_printf("unable to mount /rom\n");
1759         }
1760
1761         err = mount("", "/log", "logfs");
1762         if (err < 0)
1763         {
1764                 diag_printf("unable to mount logfs\n");
1765         }
1766
1767         err = mount("", "/tftp", "tftpfs");
1768         if (err < 0)
1769         {
1770                 diag_printf("unable to mount logfs\n");
1771         }
1772
1773         log = fopen("/log/log", "w");
1774         if (log == NULL)
1775         {
1776                 diag_printf("Could not open log file /ram/log\n");
1777                 exit(-1);
1778         }
1779
1780         diag_init_putc(_zylinjtag_diag_write_char);
1781
1782         // We want this in the log.
1783         diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
1784         diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);
1785
1786         copydir("/rom", "/ram/cgi");
1787
1788         err = mount("/dev/flash1", "/config", "jffs2");
1789         if (err < 0)
1790         {
1791                 diag_printf("unable to mount jffs\n");
1792                 reboot();
1793         }
1794
1795         /* are we using a ram disk instead of a flash disk? This is used
1796          * for ZY1000 live demo...
1797          *
1798          * copy over flash disk to ram block device
1799          */
1800         if (boolParam("ramdisk"))
1801         {
1802                 diag_printf("Unmounting /config from flash and using ram instead\n");
1803                 err=umount("/config");
1804                 if (err < 0)
1805                 {
1806                         diag_printf("unable to unmount jffs\n");
1807                         reboot();
1808                 }
1809
1810                 err = mount("/dev/flash1", "/config2", "jffs2");
1811                 if (err < 0)
1812                 {
1813                         diag_printf("unable to mount jffs\n");
1814                         reboot();
1815                 }
1816
1817                 err = mount("/dev/ram", "/config", "jffs2");
1818                 if (err < 0)
1819                 {
1820                         diag_printf("unable to mount ram block device\n");
1821                         reboot();
1822                 }
1823
1824 //              copydir("/config2", "/config");
1825                 copyfile("/config2/ip", "/config/ip");
1826                 copydir("/config2/settings", "/config/settings");
1827
1828                 umount("/config2");
1829         } else
1830         {
1831                 /* we're not going to use a ram block disk */
1832                 free(ramblockdevice);
1833         }
1834
1835
1836         mkdir(ZYLIN_CONFIG_DIR, 0777);
1837         mkdir(ZYLIN_CONFIG_DIR "/target", 0777);
1838         mkdir(ZYLIN_CONFIG_DIR "/event", 0777);
1839
1840         logAllToSerial = boolParam("logserial");
1841
1842         // We need the network & web server in case there is something wrong with
1843         // the config files that invoke exit()
1844         zylinjtag_startNetwork();
1845
1846         /* we're going to access the jim interpreter from here on... */
1847         openocd_sleep_postlude();
1848         startUart();
1849
1850         add_default_dirs();
1851
1852         /* initialize commandline interface */
1853         command_context_t *cmd_ctx;
1854         cmd_ctx = setup_command_handler();
1855         command_set_output_handler(cmd_ctx, configuration_output_handler, NULL);
1856         command_context_mode(cmd_ctx, COMMAND_CONFIG);
1857
1858
1859         register_command(cmd_ctx, NULL, "zy1000_version", handle_zy1000_version_command,
1860                         COMMAND_EXEC, "show zy1000 version numbers");
1861
1862         register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
1863                         "remove file");
1864
1865         register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,
1866                         "same args as load_image, image stored in memory");
1867
1868         register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY,
1869                         "loads active fast load image to current target");
1870
1871         register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
1872                         "display file content");
1873
1874         register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
1875                         "truncate a file to 0 size");
1876
1877         register_command(cmd_ctx, NULL, "append_file", handle_append_command,
1878                         COMMAND_ANY, "append a variable number of strings to a file");
1879
1880         register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,
1881                         "power <on/off> - turn power switch to target on/off. No arguments - print status.");
1882
1883         register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
1884                         COMMAND_ANY, "display available ram memory");
1885
1886         register_command(cmd_ctx, NULL, "cp", handle_cp_command,
1887                                          COMMAND_ANY, "copy a file <from> <to>");
1888
1889 #ifdef CYGPKG_PROFILE_GPROF
1890         register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
1891                         COMMAND_ANY, NULL);
1892 #endif
1893         register_command(cmd_ctx, NULL, "uart", handle_uart_command,
1894                                          COMMAND_ANY, "uart <baud>  - forward uart on port 5555");
1895
1896
1897         int errVal;
1898         errVal = log_init(cmd_ctx);
1899         if (errVal != ERROR_OK)
1900         {
1901                 diag_printf("log_init() failed %d\n", errVal);
1902                 exit(-1);
1903         }
1904
1905         set_log_output(cmd_ctx, log);
1906
1907         LOG_DEBUG("log init complete");
1908
1909         //      diag_printf("Executing config files\n");
1910
1911         if (logAllToSerial)
1912         {
1913                 diag_printf(ZYLIN_CONFIG_DIR "/logserial=1 => sending log output to serial port using \"debug_level 3\" as default.\n");
1914                 command_run_line(cmd_ctx, "debug_level 3");
1915         }
1916
1917         zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");
1918
1919         // FIX!!!  Yuk!
1920         // diag_printf() is really invoked from many more places than we trust it
1921         // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
1922         //
1923         // Disabling it here is safe and gives us enough logged debug output for now. Crossing
1924         // fingers that it doesn't cause any crashes.
1925         diag_printf("Init complete, GDB & telnet servers launched.\n");
1926         command_set_output_handler(cmd_ctx, zy1000_configuration_output_handler_log, NULL);
1927         if (!logAllToSerial)
1928         {
1929                 serialLog = false;
1930         }
1931
1932         /* handle network connections */
1933         server_loop(cmd_ctx);
1934         openocd_sleep_prelude();
1935
1936         /* shut server down */
1937         server_quit();
1938
1939         /* free commandline interface */
1940         command_done(cmd_ctx);
1941         umount("/config");
1942
1943         exit(0);
1944         for (;;);
1945 }
1946
1947
1948
1949 cyg_int32
1950 cyg_httpd_exec_cgi_tcl(char *file_name);
1951 cyg_int32 homeForm(CYG_HTTPD_STATE *p)
1952 {
1953         cyg_httpd_exec_cgi_tcl("/ram/cgi/index.tcl");
1954         return 0;
1955 }
1956
1957 CYG_HTTPD_HANDLER_TABLE_ENTRY(root_label, "/", homeForm);
1958
1959 CYG_HTTPD_MIME_TABLE_ENTRY(text_mime_label, "text", "text/plain");
1960 CYG_HTTPD_MIME_TABLE_ENTRY(bin_mime_label, "bin", "application/octet-stream");
1961
1962 #include <pkgconf/system.h>
1963 #include <pkgconf/hal.h>
1964 #include <pkgconf/kernel.h>
1965 #include <pkgconf/io_fileio.h>
1966 #include <pkgconf/fs_rom.h>
1967
1968 #include <cyg/kernel/ktypes.h>         // base kernel types
1969 #include <cyg/infra/cyg_trac.h>        // tracing macros
1970 #include <cyg/infra/cyg_ass.h>         // assertion macros
1971 #include <unistd.h>
1972 #include <sys/types.h>
1973 #include <fcntl.h>
1974 #include <sys/stat.h>
1975 #include <errno.h>
1976 #include <dirent.h>
1977
1978 #include <stdarg.h>
1979 #include <stdio.h>
1980 #include <stdlib.h>
1981 #include <string.h>
1982
1983 #include <cyg/fileio/fileio.h>
1984
1985 #include <cyg/kernel/kapi.h>
1986 #include <cyg/infra/diag.h>
1987
1988 //==========================================================================
1989 // Eventually we want to eXecute In Place from the ROM in a protected
1990 // environment, so we'll need executables to be aligned to a boundary
1991 // suitable for MMU protection. A suitable boundary would be the 4k
1992 // boundary in all the CPU architectures I am currently aware of.
1993
1994 // Forward definitions
1995
1996 // Filesystem operations
1997 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
1998 static int tftpfs_umount(cyg_mtab_entry *mte);
1999 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2000                 int mode, cyg_file *fte);
2001 static int tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2002 static int tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2003
2004 // File operations
2005 static int tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2006 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp);
2007 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence);
2008
2009 //==========================================================================
2010 // Filesystem table entries
2011
2012 // -------------------------------------------------------------------------
2013 // Fstab entry.
2014 // This defines the entry in the filesystem table.
2015 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2016 // we should never block in any filesystem operations.
2017 #if 1
2018 FSTAB_ENTRY( tftpfs_fste, "tftpfs", 0,
2019                 CYG_SYNCMODE_NONE,
2020                 tftpfs_mount,
2021                 tftpfs_umount,
2022                 tftpfs_open,
2023                 (cyg_fsop_unlink *)cyg_fileio_erofs,
2024                 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2025                 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2026                 (cyg_fsop_rename *)cyg_fileio_erofs,
2027                 (cyg_fsop_link *)cyg_fileio_erofs,
2028                 (cyg_fsop_opendir *)cyg_fileio_erofs,
2029                 (cyg_fsop_chdir *)cyg_fileio_erofs,
2030                 (cyg_fsop_stat *)cyg_fileio_erofs,
2031                 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2032                 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2033 #endif
2034
2035 // -------------------------------------------------------------------------
2036 // mtab entry.
2037 // This defines a single ROMFS loaded into ROM at the configured address
2038 //
2039 // MTAB_ENTRY(  rom_mte,        // structure name
2040 //              "/rom",         // mount point
2041 //              "romfs",        // FIlesystem type
2042 //              "",             // hardware device
2043 //  (CYG_ADDRWORD) CYGNUM_FS_ROM_BASE_ADDRESS   // Address in ROM
2044 //           );
2045
2046
2047 // -------------------------------------------------------------------------
2048 // File operations.
2049 // This set of file operations are used for normal open files.
2050
2051 static cyg_fileops tftpfs_fileops =
2052 {
2053         tftpfs_fo_read,
2054         tftpfs_fo_write,
2055         tftpfs_fo_lseek,
2056         (cyg_fileop_ioctl *)cyg_fileio_erofs,
2057     cyg_fileio_seltrue,
2058     tftpfs_fo_fsync,
2059     tftpfs_fo_close,
2060                 (cyg_fileop_fstat *) cyg_fileio_erofs,
2061                 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2062         (cyg_fileop_setinfo *)cyg_fileio_erofs,
2063 };
2064
2065 // -------------------------------------------------------------------------
2066 // tftpfs_mount()
2067 // Process a mount request. This mainly finds root for the
2068 // filesystem.
2069
2070 static int tftpfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2071 {
2072         return ENOERR;
2073 }
2074
2075 static int tftpfs_umount(cyg_mtab_entry *mte)
2076 {
2077         return ENOERR;
2078 }
2079
2080 struct Tftp
2081 {
2082         int write;
2083         int readFile;
2084         cyg_uint8 *mem;
2085         int actual;
2086         char *server;
2087         char *file;
2088 };
2089
2090 static void freeTftp(struct Tftp *t)
2091 {
2092         if (t == NULL)
2093                 return;
2094         if (t->mem)
2095                 free(t->mem);
2096         if (t->server)
2097                 free(t->server);
2098         if (t->file)
2099                 free(t->file);
2100         free(t);
2101 }
2102
2103 static const int tftpMaxSize = 8192 * 1024;
2104 static int tftpfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2105                 int mode, cyg_file *file)
2106 {
2107         struct Tftp *tftp;
2108         tftp = malloc(sizeof(struct Tftp));
2109         if (tftp == NULL)
2110                 return EMFILE;
2111         memset(tftp, 0, sizeof(struct Tftp));
2112
2113         file->f_flag |= mode & CYG_FILE_MODE_MASK;
2114         file->f_type = CYG_FILE_TYPE_FILE;
2115         file->f_ops = &tftpfs_fileops;
2116         file->f_offset = 0;
2117         file->f_data = 0;
2118         file->f_xops = 0;
2119
2120         tftp->mem = malloc(tftpMaxSize);
2121         if (tftp->mem == NULL)
2122         {
2123                 freeTftp(tftp);
2124                 return EMFILE;
2125         }
2126
2127         char *server = strchr(name, '/');
2128         if (server == NULL)
2129         {
2130                 freeTftp(tftp);
2131                 return EMFILE;
2132         }
2133
2134         tftp->server = malloc(server - name + 1);
2135         if (tftp->server == NULL)
2136         {
2137                 freeTftp(tftp);
2138                 return EMFILE;
2139         }
2140         strncpy(tftp->server, name, server - name);
2141         tftp->server[server - name] = 0;
2142
2143         tftp->file = strdup(server + 1);
2144         if (tftp->file == NULL)
2145         {
2146                 freeTftp(tftp);
2147                 return EMFILE;
2148         }
2149
2150         file->f_data = (CYG_ADDRWORD) tftp;
2151
2152         return ENOERR;
2153 }
2154
2155 static int fetchTftp(struct Tftp *tftp)
2156 {
2157         if (!tftp->readFile)
2158         {
2159                 int err;
2160             tftp->actual = tftp_client_get( tftp->file, tftp->server, 0, tftp->mem, tftpMaxSize,   TFTP_OCTET, &err);
2161
2162                 if (tftp->actual < 0)
2163                 {
2164                         return EMFILE;
2165                 }
2166                 tftp->readFile = 1;
2167         }
2168         return ENOERR;
2169 }
2170
2171 // -------------------------------------------------------------------------
2172 // tftpfs_fo_write()
2173 // Read data from file.
2174
2175 static int
2176 tftpfs_fo_read(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2177 {
2178         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2179
2180         if (fetchTftp(tftp) != ENOERR)
2181                 return EMFILE;
2182
2183         int i;
2184         off_t pos = fp->f_offset;
2185         int resid = 0;
2186         for (i = 0; i < uio->uio_iovcnt; i++)
2187         {
2188                 cyg_iovec *iov = &uio->uio_iov[i];
2189                 char *buf = (char *) iov->iov_base;
2190                 off_t len = iov->iov_len;
2191
2192                 if (len + pos > tftp->actual)
2193                 {
2194                         len = tftp->actual - pos;
2195                 }
2196                 resid += iov->iov_len - len;
2197
2198                 memcpy(buf, tftp->mem + pos, len);
2199                 pos += len;
2200
2201         }
2202         uio->uio_resid = resid;
2203         fp->f_offset = pos;
2204
2205         return ENOERR;
2206 }
2207
2208
2209 static int
2210 tftpfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2211 {
2212         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2213
2214         int i;
2215         off_t pos = fp->f_offset;
2216         int resid = 0;
2217         for (i = 0; i < uio->uio_iovcnt; i++)
2218         {
2219                 cyg_iovec *iov = &uio->uio_iov[i];
2220                 char *buf = (char *) iov->iov_base;
2221                 off_t len = iov->iov_len;
2222
2223                 if (len + pos > tftpMaxSize)
2224                 {
2225                         len = tftpMaxSize - pos;
2226                 }
2227                 resid += iov->iov_len - len;
2228
2229                 memcpy(tftp->mem + pos, buf, len);
2230                 pos += len;
2231
2232         }
2233         uio->uio_resid = resid;
2234         fp->f_offset = pos;
2235
2236         tftp->write = 1;
2237
2238         return ENOERR;
2239 }
2240
2241 static int
2242 tftpfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2243 {
2244         int error = ENOERR;
2245         return error;
2246 }
2247
2248 // -------------------------------------------------------------------------
2249 // romfs_fo_close()
2250 // Close a file. We just clear out the data pointer.
2251
2252 static int tftpfs_fo_close(struct CYG_FILE_TAG *fp)
2253 {
2254         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2255         int error = ENOERR;
2256
2257         if (tftp->write)
2258         {
2259             tftp_client_put( tftp->file, tftp->server, 0, tftp->mem, fp->f_offset,   TFTP_OCTET, &error);
2260         }
2261
2262         freeTftp(tftp);
2263         fp->f_data = 0;
2264         return error;
2265 }
2266
2267 // -------------------------------------------------------------------------
2268 // romfs_fo_lseek()
2269 // Seek to a new file position.
2270
2271 static int tftpfs_fo_lseek(struct CYG_FILE_TAG *fp, off_t *apos, int whence)
2272 {
2273         struct Tftp *tftp = (struct Tftp *) fp->f_data;
2274         off_t pos = *apos;
2275
2276         if (fetchTftp(tftp) != ENOERR)
2277                 return EMFILE;
2278
2279         switch (whence)
2280         {
2281         case SEEK_SET:
2282                 // Pos is already where we want to be.
2283                 break;
2284
2285         case SEEK_CUR:
2286                 // Add pos to current offset.
2287                 pos += fp->f_offset;
2288                 break;
2289
2290         case SEEK_END:
2291                 // Add pos to file size.
2292                 pos += tftp->actual;
2293                 break;
2294
2295         default:
2296                 return EINVAL;
2297         }
2298
2299         // Check that pos is still within current file size, or at the
2300         // very end.
2301         if (pos < 0 || pos > tftp->actual)
2302                 return EINVAL;
2303
2304         // All OK, set fp offset and return new position.
2305         *apos = fp->f_offset = pos;
2306
2307         return ENOERR;
2308 }
2309
2310 void usleep(int us)
2311 {
2312         if (us > 10000)
2313                 cyg_thread_delay(us / 10000 + 1);
2314         else
2315                 HAL_DELAY_US(us);
2316 }
2317
2318 // Chunked version.
2319 cyg_int32
2320 show_log_entry(CYG_HTTPD_STATE *phttpstate)
2321 {
2322         cyg_httpd_start_chunked("text");
2323         if (logCount >= logSize)
2324         {
2325         cyg_httpd_write_chunked(logBuffer+logCount%logSize, logSize-logCount%logSize);
2326         }
2327         cyg_httpd_write_chunked(logBuffer, writePtr);
2328         cyg_httpd_end_chunked();
2329         return -1;
2330 }
2331
2332 CYG_HTTPD_HANDLER_TABLE_ENTRY(show_log, "/ram/log", show_log_entry);
2333
2334 // Filesystem operations
2335 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte);
2336 static int logfs_umount(cyg_mtab_entry *mte);
2337 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2338                 int mode, cyg_file *fte);
2339 static int
2340 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
2341
2342 // File operations
2343 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
2344 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
2345
2346 #include <cyg/io/devtab.h>
2347
2348 //==========================================================================
2349 // Filesystem table entries
2350
2351 // -------------------------------------------------------------------------
2352 // Fstab entry.
2353 // This defines the entry in the filesystem table.
2354 // For simplicity we use _FILESYSTEM synchronization for all accesses since
2355 // we should never block in any filesystem operations.
2356 FSTAB_ENTRY( logfs_fste, "logfs", 0,
2357                 CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
2358                 logfs_mount,
2359                 logfs_umount,
2360                 logfs_open,
2361                 (cyg_fsop_unlink *)cyg_fileio_erofs,
2362                 (cyg_fsop_mkdir *)cyg_fileio_erofs,
2363                 (cyg_fsop_rmdir *)cyg_fileio_erofs,
2364                 (cyg_fsop_rename *)cyg_fileio_erofs,
2365                 (cyg_fsop_link *)cyg_fileio_erofs,
2366                 (cyg_fsop_opendir *)cyg_fileio_erofs,
2367                 (cyg_fsop_chdir *)cyg_fileio_erofs,
2368                 (cyg_fsop_stat *)cyg_fileio_erofs,
2369                 (cyg_fsop_getinfo *)cyg_fileio_erofs,
2370                 (cyg_fsop_setinfo *)cyg_fileio_erofs);
2371
2372 // -------------------------------------------------------------------------
2373 // File operations.
2374 // This set of file operations are used for normal open files.
2375
2376 static cyg_fileops logfs_fileops =
2377 {
2378         (cyg_fileop_read *)cyg_fileio_erofs,
2379     (cyg_fileop_write *)logfs_fo_write,
2380                 (cyg_fileop_lseek *) cyg_fileio_erofs,
2381         (cyg_fileop_ioctl *)cyg_fileio_erofs,
2382     cyg_fileio_seltrue,
2383     logfs_fo_fsync,
2384     logfs_fo_close,
2385         (cyg_fileop_fstat *)cyg_fileio_erofs,
2386                 (cyg_fileop_getinfo *) cyg_fileio_erofs,
2387         (cyg_fileop_setinfo *)cyg_fileio_erofs,
2388 };
2389
2390 // -------------------------------------------------------------------------
2391 // logfs_mount()
2392 // Process a mount request. This mainly finds root for the
2393 // filesystem.
2394
2395 static int logfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
2396 {
2397         return ENOERR;
2398 }
2399
2400 static int logfs_umount(cyg_mtab_entry *mte)
2401 {
2402         return ENOERR;
2403 }
2404
2405 static int logfs_open(cyg_mtab_entry *mte, cyg_dir dir, const char *name,
2406                 int mode, cyg_file *file)
2407 {
2408         file->f_flag |= mode & CYG_FILE_MODE_MASK;
2409         file->f_type = CYG_FILE_TYPE_FILE;
2410         file->f_ops = &logfs_fileops;
2411         file->f_offset = 0;
2412         file->f_data = 0;
2413         file->f_xops = 0;
2414         return ENOERR;
2415 }
2416
2417 // -------------------------------------------------------------------------
2418 // logfs_fo_write()
2419 // Write data to file.
2420
2421 static int
2422 logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio)
2423 {
2424         int i;
2425         for (i = 0; i < uio->uio_iovcnt; i++)
2426         {
2427                 cyg_iovec *iov = &uio->uio_iov[i];
2428                 char *buf = (char *) iov->iov_base;
2429                 off_t len = iov->iov_len;
2430
2431                 diag_write(buf, len);
2432         }
2433         uio->uio_resid = 0;
2434
2435         return ENOERR;
2436 }
2437 static int
2438 logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode)
2439 {
2440         return ENOERR;
2441 }
2442
2443 // -------------------------------------------------------------------------
2444 // romfs_fo_close()
2445 // Close a file. We just clear out the data pointer.
2446
2447 static int logfs_fo_close(struct CYG_FILE_TAG *fp)
2448 {
2449         return ENOERR;
2450 }
2451
2452 static bool
2453 ramiodev_init( struct cyg_devtab_entry *tab )
2454 {
2455         return true;
2456 }
2457
2458 static Cyg_ErrNo
2459 ramiodev_bread( cyg_io_handle_t handle, void *buf, cyg_uint32 *len,
2460                   cyg_uint32 pos)
2461 {
2462         if (*len+pos>ramblockdevice_size)
2463         {
2464                 *len=ramblockdevice_size-pos;
2465         }
2466         memcpy(buf, ramblockdevice+pos, *len);
2467         return ENOERR;
2468 }
2469
2470 static Cyg_ErrNo
2471 ramiodev_bwrite( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len,
2472                    cyg_uint32 pos )
2473 {
2474         if (((pos%4)!=0)||(((*len)%4)!=0))
2475         {
2476                 diag_printf("Unaligned write %d %d!", pos, *len);
2477         }
2478
2479         memcpy(ramblockdevice+pos, buf, *len);
2480         return ENOERR;
2481 }
2482
2483 static Cyg_ErrNo
2484 ramiodev_get_config( cyg_io_handle_t handle,
2485                        cyg_uint32 key,
2486                        void* buf,
2487                        cyg_uint32* len)
2488 {
2489     switch (key) {
2490     case CYG_IO_GET_CONFIG_FLASH_ERASE:
2491     {
2492         if ( *len != sizeof( cyg_io_flash_getconfig_erase_t ) )
2493              return -EINVAL;
2494         {
2495             cyg_io_flash_getconfig_erase_t *e = (cyg_io_flash_getconfig_erase_t *)buf;
2496             char *startpos = ramblockdevice + e->offset;
2497
2498             if (((e->offset%(64*1024))!=0)||((e->len%(64*1024))!=0))
2499             {
2500                 diag_printf("Erease is not aligned %d %d\n", e->offset, e->len);
2501             }
2502
2503             memset(startpos, 0xff, e->len);
2504
2505             e->flasherr = 0;
2506         }
2507         return ENOERR;
2508     }
2509     case CYG_IO_GET_CONFIG_FLASH_DEVSIZE:
2510     {
2511         if ( *len != sizeof( cyg_io_flash_getconfig_devsize_t ) )
2512              return -EINVAL;
2513         {
2514             cyg_io_flash_getconfig_devsize_t *d =
2515                 (cyg_io_flash_getconfig_devsize_t *)buf;
2516
2517                         d->dev_size = ramblockdevice_size;
2518         }
2519         return ENOERR;
2520     }
2521
2522     case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE:
2523     {
2524         cyg_io_flash_getconfig_blocksize_t *b =
2525             (cyg_io_flash_getconfig_blocksize_t *)buf;
2526         if ( *len != sizeof( cyg_io_flash_getconfig_blocksize_t ) )
2527              return -EINVAL;
2528
2529         // offset unused for now
2530                 b->block_size = 64*1024;
2531         return ENOERR;
2532     }
2533
2534     default:
2535         return -EINVAL;
2536     }
2537 }
2538
2539 static Cyg_ErrNo
2540 ramiodev_set_config( cyg_io_handle_t handle,
2541                        cyg_uint32 key,
2542                        const void* buf,
2543                        cyg_uint32* len)
2544 {
2545
2546     switch (key) {
2547     default:
2548         return -EINVAL;
2549     }
2550 } // ramiodev_set_config()
2551
2552 // get_config/set_config should be added later to provide the other flash
2553 // operations possible, like erase etc.
2554
2555 BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops,
2556                    &ramiodev_bwrite,
2557                    &ramiodev_bread,
2558                    0, // no select
2559                    &ramiodev_get_config,
2560                    &ramiodev_set_config
2561     );
2562
2563
2564 BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1,
2565                     "/dev/ram",
2566                     0,
2567                     &cyg_io_ramdev1_ops,
2568                     &ramiodev_init,
2569                     0, // No lookup required
2570                     NULL );