wip
[fw/openocd] / src / ecosboard.c
index 7a8c6cb22da04423c40a11f8caa3ae897d72541e..b37e169d4ef91732ac9732ed87193626ce37aa1e 100644 (file)
@@ -59,6 +59,7 @@
 #include <cyg/athttpd/handler.h>
 #include <cyg/athttpd/cgi.h>
 #include <cyg/athttpd/forms.h>
+#include <cyg/discover/discover.h>
 #include <cyg/hal/hal_diag.h>
 #include <cyg/kernel/kapi.h>
 #include <cyg/io/serialio.h>
@@ -80,6 +81,7 @@
 #include <ifaddrs.h>
 #include <string.h>
 
+
 #include <unistd.h>
 #include <stdio.h>
 #define MAX_IFS 64
@@ -96,12 +98,12 @@ struct tftpd_fileops fileops =
 
 #endif
 
-#define ZYLIN_VERSION "1.44"
+#define ZYLIN_VERSION "1.47"
 #define ZYLIN_DATE __DATE__
 #define ZYLIN_TIME __TIME__
 /* hmmm....  we can't pick up the right # during build if we've checked this out
  * in Eclipse... arrggghh...*/
-#define ZYLIN_OPENOCD 1033
+#define ZYLIN_OPENOCD "$Revision$"
 #define ZYLIN_OPENOCD_VERSION "Zylin JTAG ZY1000 " ZYLIN_VERSION " " ZYLIN_DATE " " ZYLIN_TIME
 #define ZYLIN_CONFIG_DIR "/config/settings"
 
@@ -117,6 +119,7 @@ void diag_write(char *buf, int len)
 static bool serialLog = true;
 static bool writeLog = true;
 
+char hwaddr[512];
 
 struct FastLoad
 {
@@ -266,7 +269,8 @@ int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd,
        duration_stop_measure(&duration, &duration_text);
        if (retval==ERROR_OK)
        {
-               command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
+               command_print(cmd_ctx, "Loaded %u bytes in %s", image_size, duration_text);
+               command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
        }
        free(duration_text);
 
@@ -321,7 +325,9 @@ int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,
                command_print(cmd_ctx, ZYLIN_OPENOCD_VERSION);
        } else if (strcmp("openocd", args[0])==0)
        {
-               command_print(cmd_ctx, "%d", ZYLIN_OPENOCD);
+               int revision;
+               revision=atol(ZYLIN_OPENOCD+strlen("XRevision: "));
+               command_print(cmd_ctx, "%d", revision);
        } else if (strcmp("zy1000", args[0])==0)
        {
                command_print(cmd_ctx, "%s", ZYLIN_VERSION);
@@ -336,6 +342,9 @@ int handle_zy1000_version_command(struct command_context_s *cmd_ctx, char *cmd,
        return ERROR_OK;
 }
 
+
+
+
 extern flash_driver_t *flash_drivers[];
 extern target_type_t *target_types[];
 
@@ -537,10 +546,10 @@ static void setPower(bool power)
        savePower = power;
        if (power)
        {
-               HAL_WRITE_UINT32(0x08000014, 0x8);
+               HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x14, 0x8);
        } else
        {
-               HAL_WRITE_UINT32(0x08000010, 0x8);
+               HAL_WRITE_UINT32(ZY1000_JTAG_BASE+0x10, 0x8);
        }
 }
 
@@ -791,7 +800,9 @@ void _zylinjtag_diag_write_char(char c, void **param)
                HAL_DIAG_WRITE_CHAR(c);
        }
 
+#ifdef CYGPKG_HAL_ZYLIN_PHI
        printDccChar(c);
+#endif
 }
 
 #define SHOW_RESULT(a, b) diag_printf(#a " failed %d\n", (int)b)
@@ -837,12 +848,19 @@ static void copyfile(char *name2, char *name1)
     if( err < 0 ) SHOW_RESULT( close, err );
 
 }
-static void copydir(char *name)
+static void copydir(char *name, char *destdir)
 {
        int err;
        DIR *dirp;
 
-       mkdir("/ram/cgi", 0777);
+       dirp = opendir(destdir);
+       if (dirp==NULL)
+       {
+               mkdir(destdir, 0777);
+       } else
+       {
+               err = closedir(dirp);
+       }
 
        dirp = opendir(name);
     if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
@@ -881,9 +899,11 @@ static void copydir(char *name)
                char fullname2[PATH_MAX];
 
                strcpy(fullname, name);
+               strcat(fullname, "/");
                strcat(fullname, entry->d_name);
 
-               strcpy(fullname2, "/ram/cgi/");
+               strcpy(fullname2, destdir);
+               strcat(fullname2, "/");
                strcat(fullname2, entry->d_name);
                //        diag_printf("from %s to %s\n", fullname, fullname2);
                copyfile(fullname, fullname2);
@@ -913,6 +933,72 @@ void openocd_sleep_postlude()
        cyg_mutex_lock(&httpstate.jim_lock);
 }
 
+
+void format(void)
+{
+       diag_printf("Formatting JFFS2...\n");
+
+       cyg_io_handle_t handle;
+
+       Cyg_ErrNo err;
+       err = cyg_io_lookup(CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, &handle);
+       if (err != ENOERR)
+       {
+               diag_printf("Flash Error cyg_io_lookup: %d\n", err);
+               reboot();
+       }
+
+
+       cyg_uint32 len;
+       cyg_io_flash_getconfig_devsize_t ds;
+       len = sizeof (ds);
+       err = cyg_io_get_config(handle,
+                               CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &ds, &len);
+       if (err != ENOERR)
+       {
+               diag_printf("Flash error cyg_io_get_config %d\n", err);
+               reboot();
+       }
+
+       cyg_io_flash_getconfig_erase_t e;
+       void *err_addr;
+       len = sizeof (e);
+
+       e.offset = 0;
+       e.len = ds.dev_size;
+       e.err_address = &err_addr;
+
+       diag_printf("Formatting 0x%08x bytes\n", ds.dev_size);
+       err = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_FLASH_ERASE,
+                               &e, &len);
+       if (err != ENOERR)
+       {
+               diag_printf("Flash erase error %d offset 0x%p\n", err, err_addr);
+               reboot();
+       }
+
+       diag_printf("Flash formatted successfully\n");
+
+       reboot();
+}
+
+
+
+static int
+zylinjtag_Jim_Command_format_jffs2(Jim_Interp *interp,
+                                   int argc,
+               Jim_Obj * const *argv)
+{
+       int del;
+       if (argc != 1)
+       {
+               return JIM_ERR;
+       }
+
+       format();
+}
+
+
 static int
 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
                                    int argc,
@@ -934,6 +1020,72 @@ zylinjtag_Jim_Command_rm(Jim_Interp *interp,
        return del ? JIM_OK : JIM_ERR;
 }
 
+static int zylinjtag_Jim_Command_threads(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       cyg_handle_t thread = 0;
+       cyg_uint16 id = 0;
+       Jim_Obj *threads = Jim_NewListObj(interp, NULL, 0);
+
+       /* Loop over the threads, and generate a table row for
+        * each.
+        */
+       while (cyg_thread_get_next(&thread, &id))
+       {
+               Jim_Obj *threadObj = Jim_NewListObj(interp, NULL, 0);
+
+               cyg_thread_info info;
+               char *state_string;
+
+               cyg_thread_get_info(thread, id, &info);
+
+               if (info.name == NULL)
+                       info.name = "<no name>";
+
+               Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
+                               info.name, strlen(info.name)));
+
+               /* Translate the state into a string.
+                */
+               if (info.state == 0)
+                       state_string = "RUN";
+               else if (info.state & 0x04)
+                       state_string = "SUSP";
+               else
+                       switch (info.state & 0x1b)
+                       {
+                       case 0x01:
+                               state_string = "SLEEP";
+                               break;
+                       case 0x02:
+                               state_string = "CNTSLEEP";
+                               break;
+                       case 0x08:
+                               state_string = "CREATE";
+                               break;
+                       case 0x10:
+                               state_string = "EXIT";
+                               break;
+                       default:
+                               state_string = "????";
+                               break;
+                       }
+
+               Jim_ListAppendElement(interp, threadObj, Jim_NewStringObj(interp,
+                               state_string, strlen(state_string)));
+
+               Jim_ListAppendElement   (interp, threadObj, Jim_NewIntObj(interp, id));
+               Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.set_pri));
+               Jim_ListAppendElement(interp, threadObj, Jim_NewIntObj(interp, info.cur_pri));
+
+               Jim_ListAppendElement(interp, threads, threadObj);
+       }
+       Jim_SetResult( interp, threads);
+
+       return JIM_OK;
+}
+
+
 static int
 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
                                    int argc,
@@ -1135,33 +1287,9 @@ zylinjtag_Jim_Command_mac(Jim_Interp *interp,
                                    int argc,
                Jim_Obj * const *argv)
 {
-       int s;
-       struct ifreq ifr;
-       s = socket(AF_INET, SOCK_DGRAM, 0);
-       if (s >= 0)
-       {
-               strcpy(ifr.ifr_name, "eth0");
-               int res;
-               res = ioctl(s, SIOCGIFHWADDR, &ifr);
-               close(s);
-
-               if (res < 0)
-               {
-                       return JIM_OK;
-               }
-       }
 
        Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
 
-       char hwaddr[512];
-       sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
-                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
-
        Jim_AppendString(httpstate.jim_interp, tclOutput, hwaddr, strlen(hwaddr));
 
        Jim_SetResult(interp, tclOutput);
@@ -1215,6 +1343,7 @@ zylinjtag_Jim_Command_ip(Jim_Interp *interp,
 
 extern Jim_Interp *interp;
 
+
 static void zylinjtag_startNetwork()
 {
        // Bring TCP/IP up immediately before we're ready to accept commands.
@@ -1245,102 +1374,51 @@ static void zylinjtag_startNetwork()
     Jim_CreateCommand(httpstate.jim_interp, "zy1000_flash", zylinjtag_Jim_Command_flash, NULL, NULL);
     Jim_CreateCommand(httpstate.jim_interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
     Jim_CreateCommand(httpstate.jim_interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
+    Jim_CreateCommand(httpstate.jim_interp, "threads", zylinjtag_Jim_Command_threads, NULL, NULL);
     Jim_CreateCommand(httpstate.jim_interp, "getmem", zylinjtag_Jim_Command_getmem, NULL, NULL);
     Jim_CreateCommand(httpstate.jim_interp, "mac", zylinjtag_Jim_Command_mac, NULL, NULL);
     Jim_CreateCommand(httpstate.jim_interp, "ip", zylinjtag_Jim_Command_ip, NULL, NULL);
     Jim_CreateCommand(httpstate.jim_interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
+    Jim_CreateCommand(httpstate.jim_interp, "format_jffs2", zylinjtag_Jim_Command_format_jffs2, NULL, NULL);
 
        cyg_httpd_start();
 
        webRunning = true;
 
        diag_printf("Web server running\n");
-}
-
-static bool readPowerDropout()
-{
-       cyg_uint32 state;
-       // sample and clear power dropout
-       HAL_WRITE_UINT32(0x08000010, 0x80);
-       HAL_READ_UINT32(0x08000010, state);
-       bool powerDropout;
-       powerDropout = (state & 0x80) != 0;
-       return powerDropout;
-}
 
-bool readSRST()
-{
-       cyg_uint32 state;
-       // sample and clear SRST sensing
-       HAL_WRITE_UINT32(0x08000010, 0x00000040);
-       HAL_READ_UINT32(0x08000010, state);
-       bool srstAsserted;
-       srstAsserted = (state & 0x40) != 0;
-       return srstAsserted;
-}
-
-// every 300ms we check for reset & powerdropout and issue a "reset halt" if
-// so.
-
-
-static int sense_handler(void *priv)
-{
-       struct command_context_s *cmd_ctx;
-       cmd_ctx = (struct command_context_s *) priv;
-
-       static bool prevSrstAsserted = false;
-       static bool prevPowerdropout = false;
-
-       bool powerDropout;
-       powerDropout = readPowerDropout();
-
-       bool powerRestored;
-       powerRestored = prevPowerdropout && !powerDropout;
-       if (powerRestored)
+       int s;
+       struct ifreq ifr;
+       s = socket(AF_INET, SOCK_DGRAM, 0);
+       if (s >= 0)
        {
-               LOG_USER("Sensed power restore.");
-       }
+               strcpy(ifr.ifr_name, "eth0");
+               int res;
+               res = ioctl(s, SIOCGIFHWADDR, &ifr);
+               close(s);
 
-       cyg_tick_count_t current = cyg_current_time();
-       static cyg_tick_count_t lastPower = 0;
-       bool waitMore = lastPower + 200 > current;
-       if (powerDropout && !waitMore)
-       {
-               LOG_USER("Sensed power dropout.");
-               lastPower = current;
+               if (res < 0)
+               {
+                       diag_printf("Can't obtain MAC address\n");
+                       reboot();
+               }
        }
 
-       bool srstAsserted = readSRST();
-
-       bool srstDeasserted;
-       srstDeasserted = prevSrstAsserted && !srstAsserted;
+       sprintf(hwaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[0],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[1],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[2],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[3],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[4],
+                       (int) ((unsigned char *) &ifr.ifr_hwaddr.sa_data)[5]);
 
-       static cyg_tick_count_t lastSrst = 0;
-       waitMore = lastSrst + 200 > current;
-       if (srstDeasserted && !waitMore)
-       {
-               LOG_USER("Sensed nSRST deasserted");
-               lastSrst = current;
-       }
 
-       if (!prevSrstAsserted && srstAsserted)
-       {
-               LOG_USER("Sensed nSRST asserted");
-       }
+       discover_message=alloc_printf("ZY1000 Zylin JTAG debugger MAC %s", hwaddr);
 
-       prevSrstAsserted = srstAsserted;
-       prevPowerdropout = powerDropout;
+       discover_launch();
+}
 
-       if (srstDeasserted || powerRestored)
-       {
-               /* Other than logging the event we can't do anything here.
-                * Issuing a reset is a particularly bad idea as we might
-                * be inside a reset already.
-                */
-       }
 
-       return ERROR_OK;
-}
 
 
 
@@ -1352,6 +1430,7 @@ print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_
        char *infoStr = "unknown";
        switch (exception)
        {
+#ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
        case CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION:
                infoStr = "undefined instruction";
                break;
@@ -1364,6 +1443,7 @@ print_exception_handler(cyg_addrword_t data, cyg_code_t exception, cyg_addrword_
        case CYGNUM_HAL_VECTOR_ABORT_DATA:
                infoStr = "abort data";
                break;
+#endif
        default:
                break;
        }
@@ -1403,7 +1483,6 @@ static char uart_stack[4096];
 static char forwardBuffer[1024]; // NB! must be smaller than a TCP/IP packet!!!!!
 static char backwardBuffer[1024];
 
-static cyg_io_handle_t serial_handle;
 
 void setNoDelay(int session, int flag)
 {
@@ -1487,7 +1566,9 @@ zylinjtag_uart(cyg_addrword_t data)
                        continue;
                }
 
+#ifdef CYGPKG_PROFILE_GPROF
                start_profile();
+#endif
                int actual = 0;
                int actual2 = 0;
                int pos, pos2;
@@ -1631,15 +1712,20 @@ void startUart(void)
 
 int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       if (argc != 1)
+       static int current_baud = 38400;
+       if (argc == 0)
+       {
+               command_print(cmd_ctx, "%d", current_baud);
+               return ERROR_OK;
+       } else if (argc != 1)
        {
-               command_print(cmd_ctx, "usage: uart <baudrate>");
                return ERROR_INVALID_ARGUMENTS;
        }
 
-       int baud = atol(args[0]);
+       current_baud = atol(args[0]);
 
-       switch (baud)
+       int baud;
+       switch (current_baud)
        {
        case 9600:
                baud = CYGNUM_SERIAL_BAUD_9600;
@@ -1669,6 +1755,16 @@ int handle_uart_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
        //get existing serial configuration
        len = sizeof(cyg_serial_info_t);
        int err;
+       cyg_io_handle_t serial_handle;
+
+       err = cyg_io_lookup("/dev/ser0", &serial_handle);
+       if (err != ENOERR)
+       {
+               LOG_ERROR("/dev/ser0 not found\n");
+               return ERROR_FAIL;
+       }
+
+
        err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buf, &len);
        err = cyg_io_get_config(serial_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buf, &len);
        if (err != ENOERR)
@@ -1721,19 +1817,25 @@ int add_default_dirs(void)
        return ERROR_OK;
 }
 
+static cyg_uint8 *ramblockdevice;
+static const int ramblockdevice_size=4096*1024;
 int main(int argc, char *argv[])
 {
+       /* ramblockdevice will be the same address every time. The deflate app uses a buffer 16mBytes out, so we
+        * need to allocate towards the end of the heap.  */
+
+       ramblockdevice=(cyg_uint8 *)malloc(ramblockdevice_size);
+       memset(ramblockdevice, 0xff, ramblockdevice_size);
+
+
+
+#ifdef CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION
        setHandler(CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION);
        setHandler(CYGNUM_HAL_VECTOR_ABORT_PREFETCH);
        setHandler(CYGNUM_HAL_VECTOR_ABORT_DATA);
+#endif
 
        int err;
-       err = cyg_io_lookup("/dev/ser0", &serial_handle);
-       if (err != ENOERR)
-       {
-               diag_printf("/dev/ser0 not found\n");
-               reboot();
-       }
 
        setPower(true); // on by default
 
@@ -1779,12 +1881,59 @@ int main(int argc, char *argv[])
        diag_printf("Zylin ZY1000. Copyright Zylin AS 2007-2008.\n");
        diag_printf("%s\n", ZYLIN_OPENOCD_VERSION);
 
-       copydir("/rom/");
+       copydir("/rom", "/ram/cgi");
 
        err = mount("/dev/flash1", "/config", "jffs2");
        if (err < 0)
        {
-               diag_printf("unable to mount jffs\n");
+               diag_printf("unable to mount jffs2, falling back to ram disk..\n");
+               err = mount("", "/config", "ramfs");
+               if (err<0)
+               {
+                       diag_printf("unable to mount /config as ramdisk.\n");
+                       reboot();
+               }
+       } else
+       {
+               /* are we using a ram disk instead of a flash disk? This is used
+                * for ZY1000 live demo...
+                *
+                * copy over flash disk to ram block device
+                */
+               if (boolParam("ramdisk"))
+               {
+                       diag_printf("Unmounting /config from flash and using ram instead\n");
+                       err=umount("/config");
+                       if (err < 0)
+                       {
+                               diag_printf("unable to unmount jffs\n");
+                               reboot();
+                       }
+
+                       err = mount("/dev/flash1", "/config2", "jffs2");
+                       if (err < 0)
+                       {
+                               diag_printf("unable to mount jffs\n");
+                               reboot();
+                       }
+
+                       err = mount("/dev/ram", "/config", "jffs2");
+                       if (err < 0)
+                       {
+                               diag_printf("unable to mount ram block device\n");
+                               reboot();
+                       }
+
+       //              copydir("/config2", "/config");
+                       copyfile("/config2/ip", "/config/ip");
+                       copydir("/config2/settings", "/config/settings");
+
+                       umount("/config2");
+               } else
+               {
+                       /* we're not going to use a ram block disk */
+                       free(ramblockdevice);
+               }
        }
 
 
@@ -1815,7 +1964,7 @@ int main(int argc, char *argv[])
                        COMMAND_EXEC, "show zy1000 version numbers");
 
        register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
-                       "rm <filname>");
+                       "remove file");
 
        register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,
                        "same args as load_image, image stored in memory");
@@ -1824,22 +1973,22 @@ int main(int argc, char *argv[])
                        "loads active fast load image to current target");
 
        register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
-                       "cat <filname>");
+                       "display file content");
 
        register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
-                       "trunc <filname>");
+                       "truncate a file to 0 size");
 
        register_command(cmd_ctx, NULL, "append_file", handle_append_command,
-                       COMMAND_ANY, "append <filname>");
+                       COMMAND_ANY, "append a variable number of strings to a file");
 
        register_command(cmd_ctx, NULL, "power", handle_power_command, COMMAND_ANY,
                        "power <on/off> - turn power switch to target on/off. No arguments - print status.");
 
        register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
-                       COMMAND_ANY, "meminfo");
+                       COMMAND_ANY, "display available ram memory");
 
        register_command(cmd_ctx, NULL, "cp", handle_cp_command,
-                                        COMMAND_ANY, "cp <from> <to>");
+                                        COMMAND_ANY, "copy a file <from> <to>");
 
 #ifdef CYGPKG_PROFILE_GPROF
        register_command(cmd_ctx, NULL, "ecosboard_profile", eCosBoard_handle_eCosBoard_profile_command,
@@ -1871,8 +2020,6 @@ int main(int argc, char *argv[])
 
        zylinjtag_parse_config_file(cmd_ctx, "/rom/openocd.cfg");
 
-       target_register_timer_callback(sense_handler, 200, 1, cmd_ctx);
-
        // FIX!!!  Yuk!
        // diag_printf() is really invoked from many more places than we trust it
        // not to cause instabilities(e.g. invoking fputc() from an interrupt is *BAD*).
@@ -2300,6 +2447,8 @@ logfs_fo_write(struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
 static int logfs_fo_fsync(struct CYG_FILE_TAG *fp, int mode);
 static int logfs_fo_close(struct CYG_FILE_TAG *fp);
 
+#include <cyg/io/devtab.h>
+
 //==========================================================================
 // Filesystem table entries
 
@@ -2403,3 +2552,123 @@ static int logfs_fo_close(struct CYG_FILE_TAG *fp)
 {
        return ENOERR;
 }
+
+static bool
+ramiodev_init( struct cyg_devtab_entry *tab )
+{
+       return true;
+}
+
+static Cyg_ErrNo
+ramiodev_bread( cyg_io_handle_t handle, void *buf, cyg_uint32 *len,
+                  cyg_uint32 pos)
+{
+       if (*len+pos>ramblockdevice_size)
+       {
+               *len=ramblockdevice_size-pos;
+       }
+       memcpy(buf, ramblockdevice+pos, *len);
+       return ENOERR;
+}
+
+static Cyg_ErrNo
+ramiodev_bwrite( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len,
+                   cyg_uint32 pos )
+{
+       if (((pos%4)!=0)||(((*len)%4)!=0))
+       {
+               diag_printf("Unaligned write %d %d!", pos, *len);
+       }
+
+       memcpy(ramblockdevice+pos, buf, *len);
+       return ENOERR;
+}
+
+static Cyg_ErrNo
+ramiodev_get_config( cyg_io_handle_t handle,
+                       cyg_uint32 key,
+                       void* buf,
+                       cyg_uint32* len)
+{
+    switch (key) {
+    case CYG_IO_GET_CONFIG_FLASH_ERASE:
+    {
+        if ( *len != sizeof( cyg_io_flash_getconfig_erase_t ) )
+             return -EINVAL;
+        {
+            cyg_io_flash_getconfig_erase_t *e = (cyg_io_flash_getconfig_erase_t *)buf;
+            char *startpos = ramblockdevice + e->offset;
+
+            if (((e->offset%(64*1024))!=0)||((e->len%(64*1024))!=0))
+            {
+               diag_printf("Erease is not aligned %d %d\n", e->offset, e->len);
+            }
+
+            memset(startpos, 0xff, e->len);
+
+            e->flasherr = 0;
+        }
+        return ENOERR;
+    }
+    case CYG_IO_GET_CONFIG_FLASH_DEVSIZE:
+    {
+        if ( *len != sizeof( cyg_io_flash_getconfig_devsize_t ) )
+             return -EINVAL;
+        {
+            cyg_io_flash_getconfig_devsize_t *d =
+                (cyg_io_flash_getconfig_devsize_t *)buf;
+
+                       d->dev_size = ramblockdevice_size;
+        }
+        return ENOERR;
+    }
+
+    case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE:
+    {
+        cyg_io_flash_getconfig_blocksize_t *b =
+            (cyg_io_flash_getconfig_blocksize_t *)buf;
+        if ( *len != sizeof( cyg_io_flash_getconfig_blocksize_t ) )
+             return -EINVAL;
+
+        // offset unused for now
+               b->block_size = 64*1024;
+        return ENOERR;
+    }
+
+    default:
+        return -EINVAL;
+    }
+}
+
+static Cyg_ErrNo
+ramiodev_set_config( cyg_io_handle_t handle,
+                       cyg_uint32 key,
+                       const void* buf,
+                       cyg_uint32* len)
+{
+
+    switch (key) {
+    default:
+        return -EINVAL;
+    }
+} // ramiodev_set_config()
+
+// get_config/set_config should be added later to provide the other flash
+// operations possible, like erase etc.
+
+BLOCK_DEVIO_TABLE( cyg_io_ramdev1_ops,
+                   &ramiodev_bwrite,
+                   &ramiodev_bread,
+                   0, // no select
+                   &ramiodev_get_config,
+                   &ramiodev_set_config
+    );
+
+
+BLOCK_DEVTAB_ENTRY( cyg_io_ramdev1,
+                    "/dev/ram",
+                    0,
+                    &cyg_io_ramdev1_ops,
+                    &ramiodev_init,
+                    0, // No lookup required
+                    NULL );