[ECOS] Flash infrastructure rework

Andrew Lunn andrew@lunn.ch
Fri Jul 16 13:39:00 GMT 2004


Hi Folks

Ascom has recently required that Redboot run on a target board which
can be manufactured with two different FLASH devices which are pin
compatible and with two banks of flash in disjoint locations. We also
needed to support two jffs2 file systems simultaneously so allowing
fallback if one was corrupt. The client also wants one image to run on
both boards. The current flash infrastructure cannot support this. Due
to time pressures we have used Ian Campbells patches to get something
going quickly.

However in the background i took a step back and overhauled the whole
flash infrastructure in what i hope is a clean and consistent API with
all the features required:

        Multiple device drivers at the same time
        Multiple instantiations of the same driver
        Probing to detect what is actually on the board
        Support for boot block devices which have different size blocks
        Thread safe when used with the kernel
        Does not pollute the name space
        Optional backward compatible with old drivers
        Optional backward compatible with old API
        Able to support multiple JFFS2 filesystems
        Redboot to be able to access multiple devices
        Documentation!

Attached are the change. There are two .epk's. One is the new io/flash
code which uses v2 instead of current so you can have it in the
repository at the same time as the current code. The second is a flash
driver which uses the new API for the synthetic target. This installs
parallel the current synth flash driver which allows testing of legacy
and new drivers in the same system. There is also a patch to the rest
of eCos for redboot and jffs2.

Some screen shots....

RedBoot(tm) bootstrap and debug environment [ROM]
Non-certified release, version UNKNOWN - built 14:27:08, Jul 15 2004
 
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.
 
RAM: 0x02000000-0x02800000, [0x02006fd0-0x027e1000] available
FLASH: 0x40000000 - 0x400fffff 8 x 0x2000 blocks 15 x 0x10000 blocks 
FLASH: 0x40100000 - 0x401fffff 16 x 0x10000 blocks 

Here you can see two flash devices, the first one with boot blocks.
In this setup the first device is the new synthetic driver and the
second one is the legacy driver.

RedBoot> fis create -b 0x02000000 -l 0x10000 -f 0x40100000 junk
RedBoot> fis list
Name              FLASH addr  Mem addr    Length      Entry point
RedBoot           0x40000000  0x40000000  0x00020000  0x00000000
FIS directory     0x400EFFFF  0x400EFFFF  0x0000F000  0x00000000
RedBoot config    0x400FEFFF  0x400FEFFF  0x00001000  0x00000000
junk              0x40100000  0x40100000  0x00010000  0xFFFFFFFF
RedBoot> 

This creates an entry in the second flash device.

There are still some limitations. The FIS directory and RedBoot config
have to be in the lower device. Also they cannot yet make use of the
boot blocks, but that should be easy to add. 

The fileio1 test in the jffs2 package has been extended. If the flash
block io layer has been configured for two devices the second one is
also mounted:

<INFO>: mounting second JFFS2 filesystem on /mnt
<INFO>: reading directory /
<INFO>: entry              . [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry             .. [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry            etc [mode 016f0001 ino 00000002 nlink 1 size 0]
<INFO>: entry            dev<FAIL>: stat() returned -1 No such entity
 
<INFO>: entry            mnt [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry            var [mode 016f0001 ino 00000008 nlink 1 size 0]
<INFO>: entry            tmp [mode 016f0001 ino 00000007 nlink 1 size 0]
<INFO>: entry      jffs2.img [mode 004b0008 ino 00000009 nlink 1 size 2013]
<INFO>: reading directory /mnt
<INFO>: entry              . [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry             .. [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry            etc [mode 016f0001 ino 00000002 nlink 1 size 0]
<INFO>: entry            dev [mode 016f0001 ino 00000005 nlink 1 size 0]
<INFO>: entry            mnt [mode 016f0001 ino 00000006 nlink 1 size 0]
<INFO>: entry            var [mode 016f0001 ino 00000008 nlink 1 size 0]
<INFO>: entry            tmp [mode 016f0001 ino 00000007 nlink 1 size 0]
<INFO>: entry      jffs2.img [mode 004b0008 ino 00000009 nlink 1 size 2013]
<INFO>: umount /mnt
<INFO>: umount /

In this case the two filesystems are identical so its not the best of
tests. I also need to look into the /dev failure, but i don't think
that is related to the flashiodev code.

There is documentaion in SGML format which describes both the new
application and device API. Note that it might not be 100% correct. I
wrote the documentation first to get my ideas sorted out and then did
the implementation. There was some minor changes along the way which
might not of made it back into the documentation.

The new API is:

typedef int cyg_flash_printf(const char *fmt, ...);
__externC int cyg_flash_init( cyg_flash_printf *pf );
__externC int cyg_flash_get_info(cyg_uint32 devno, 
                                 cyg_flash_info_t * info);
__externC int cyg_flash_get_info_addr(cyg_flashaddr_t flash_base, 
                                      cyg_flash_info_t * info);
__externC int cyg_flash_verify_addr(const cyg_flashaddr_t address);
__externC bool cyg_flash_code_overlaps(const cyg_flashaddr_t start, 
                                       const cyg_flashaddr_t end);
__externC int cyg_flash_get_block_info(size_t *block_size, 
                                       cyg_uint32 *blocks);
__externC int cyg_flash_get_limits(cyg_flashaddr_t *start, 
                                   cyg_flashaddr_t *end);
__externC size_t cyg_flash_block_size(const cyg_flashaddr_t flash_base);
__externC int cyg_flash_read(cyg_flashaddr_t flash_base, 
                             const void *ram_base, 
                             const size_t len, 
                             cyg_flashaddr_t *err_address);
__externC int cyg_flash_erase(const cyg_flashaddr_t flash_base, 
                              const size_t len, 
                              cyg_flashaddr_t *err_address);
__externC int cyg_flash_program(const cyg_flashaddr_t flash_base, 
                                void *ram_base, 
                                const size_t len, 
                                cyg_flashaddr_t *err_address);
__externC int cyg_flash_lock(const cyg_flashaddr_t flash_base, 
                             const size_t len, 
                             cyg_flashaddr_t *err_address);
__externC int cyg_flash_unlock(const cyg_flashaddr_t flash_base, 
                               const size_t len, 
                               cyg_flashaddr_t *err_address);
__externC const char *cyg_flash_errmsg(const int err);
#ifdef CYGPKG_KERNEL
__externC int cyg_flash_mutex_lock(const cyg_flashaddr_t from, 
                                   const size_t len);
__externC int cyg_flash_mutex_unlock(const cyg_flashaddr_t from, 
#endif

and the device API is

// Structure of pointers to functions in the device driver
struct cyg_flash_dev_funs {
  int (*flash_init) (struct cyg_flash_dev *dev);
  size_t (*flash_query) (struct cyg_flash_dev *dev, void * data, 
                         const size_t len);
  int (*flash_erase_block) (struct cyg_flash_dev *dev, 
                            const cyg_flashaddr_t block_base);
  int (*flash_program) (struct cyg_flash_dev *dev, 
                        cyg_flashaddr_t base, 
                        const void* data, const size_t len);
  int (*flash_read) (struct cyg_flash_dev *dev, 
                     const cyg_flashaddr_t base, 
                     void* data, const size_t len);
  int (*flash_hwr_map_error) (struct cyg_flash_dev *dev, int err);
  int (*flash_block_lock) (struct cyg_flash_dev *dev, 
                           const cyg_flashaddr_t block_base);
  int (*flash_block_unlock) (struct cyg_flash_dev *dev, 
                             const cyg_flashaddr_t block_base);
};
 
// Structure each device places in the HAL table
struct cyg_flash_dev {
  struct cyg_flash_dev_funs   *funs;           // Function pointers
  cyg_flashaddr_t             start;           // First address
  cyg_flashaddr_t             end;             // Last address
  cyg_uint32                  num_block_infos; // Number of entries
  cyg_block_info_t            *block_info;     // Info about one block size
 
  void                        *priv;           // Devices private data
  void                        *config;         // Configuration info
 
// The following are only written to by the FLASH IO layer.
  cyg_flash_printf            *pf;             // Pointer to diagnostic printf
  bool                        init;            // Device has been initialised
#ifdef CYGPKG_KERNEL
  cyg_mutex_t                 mutex;           // Mutex for thread safeness
#endif
  struct cyg_flash_dev        *next;           // Pointer to next device
} CYG_HAL_TABLE_TYPE;

See the documentation for explanations of each function.

It needs some more device drivers. I plan to modify both the SST and
the Strata drivers to use the new API, but that work will not start
for another two weeks.

What i would like now is some feedback. Are there any missing
features? Does the APIs make sense. Reading the code do you see
obvious problems? 

Im on Holiday for the next two weeks so it would be nice to come back
to a few email of suggestions, improvements and bug fixes.

        Thanks
                Andrew
-------------- next part --------------
A non-text attachment was scrubbed...
Name: flashv2.epk
Type: application/octet-stream
Size: 24080 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/ecos-discuss/attachments/20040716/187da545/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: synthflashv2.epk
Type: application/octet-stream
Size: 7306 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/ecos-discuss/attachments/20040716/187da545/attachment-0001.obj>
-------------- next part --------------
? devs/flash/synth/current/tests/flash2.c
Index: devs/flash/synth/current/cdl/flash_synth.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/synth/current/cdl/flash_synth.cdl,v
retrieving revision 1.3
diff -u -r1.3 flash_synth.cdl
--- devs/flash/synth/current/cdl/flash_synth.cdl	23 May 2002 23:01:05 -0000	1.3
+++ devs/flash/synth/current/cdl/flash_synth.cdl	16 Jul 2004 11:21:02 -0000
@@ -56,7 +56,7 @@
     requires      CYGINT_ISO_ERRNO_CODES
 
     implements    CYGHWR_IO_FLASH_DEVICE
-
+    
     include_dir   .
     include_files ; # none _exported_ whatsoever
     description   "FLASH memory device support for Synthetic target"
@@ -121,7 +121,7 @@
         display "Synth flash tests"
         flavor  data
         no_define
-        calculated { "tests/flash1.c"}
+        calculated { "tests/flash1.c tests/flash2.c"}
             description   "
                 This option specifies the set of tests for the synth flash package."
     }
Index: devs/flash/synth/current/src/synth.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/synth/current/src/synth.c,v
retrieving revision 1.3
diff -u -r1.3 synth.c
--- devs/flash/synth/current/src/synth.c	23 May 2002 23:01:06 -0000	1.3
+++ devs/flash/synth/current/src/synth.c	16 Jul 2004 11:21:02 -0000
@@ -149,7 +149,7 @@
         return FLASH_ERR_HWR;
     }
     flash_info.start = cyg_dev_flash_synth_base;
-    flash_info.end = (void *)(((char *)cyg_dev_flash_synth_base) +
+    flash_info.end = (void *)(((char *)cyg_dev_flash_synth_base) -1 + 
         (CYGNUM_FLASH_SYNTH_BLOCKSIZE * CYGNUM_FLASH_SYNTH_NUMBLOCKS));
 
     return FLASH_ERR_OK;
Index: devs/flash/synth/current/tests/flash1.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/synth/current/tests/flash1.c,v
retrieving revision 1.4
diff -u -r1.4 flash1.c
--- devs/flash/synth/current/tests/flash1.c	24 Nov 2003 11:21:28 -0000	1.4
+++ devs/flash/synth/current/tests/flash1.c	16 Jul 2004 11:21:03 -0000
@@ -1,59 +1,59 @@
-/* Hay, the copyright is usefull for something! */
+/* Hey, the copyright is usefull for something! */
 
-static char copyright[] = "
-//==========================================================================
-//
-//      flash1.c
-//
-//      Test flash operations for the synth target synth flash driver
-//
-//==========================================================================
-//####ECOSGPLCOPYRIGHTBEGIN####
-// -------------------------------------------
-// This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-//
-// eCos is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 2 or (at your option) any later version.
-//
-// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-// for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with eCos; if not, write to the Free Software Foundation, Inc.,
-// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-//
-// As a special exception, if other files instantiate templates or use macros
-// or inline functions from this file, or you compile this file and link it
-// with other works to produce a work based on this file, this file does not
-// by itself cause the resulting work to be covered by the GNU General Public
-// License. However the source code for this file must still be made available
-// in accordance with section (3) of the GNU General Public License.
-//
-// This exception does not invalidate any other reasons why a work based on
-// this file might be covered by the GNU General Public License.
-//
-// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
-// at http://sources.redhat.com/ecos/ecos-license/
-// -------------------------------------------
-//####ECOSGPLCOPYRIGHTEND####
-//==========================================================================
-//#####DESCRIPTIONBEGIN####
-//
-// Author(s):           andrew.lunn@ascom.ch
-// Contributors:        andrew.lunn
-// Date:                2000-10-31
-// Purpose:             Test a flash driver
-// Description:         Try out a number of flash operations and make sure
-//                      what is in the flash is what we expeect.
-//                      
-//####DESCRIPTIONEND####
-//
-//==========================================================================
-";
+static char copyright[] = 
+"//=========================================================================="
+"//"
+"//      flash1.c"
+"//"
+"//      Test flash operations for the synth target synth flash driver"
+"//"
+"//=========================================================================="
+"//####ECOSGPLCOPYRIGHTBEGIN####"
+"// -------------------------------------------"
+"// This file is part of eCos, the Embedded Configurable Operating System."
+"// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc."
+"//"
+"// eCos is free software; you can redistribute it and/or modify it under"
+"// the terms of the GNU General Public License as published by the Free"
+"// Software Foundation; either version 2 or (at your option) any later version."
+"//"
+"// eCos is distributed in the hope that it will be useful, but WITHOUT ANY"
+"// WARRANTY; without even the implied warranty of MERCHANTABILITY or"
+"// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License"
+"// for more details."
+"//"
+"// You should have received a copy of the GNU General Public License along"
+"// with eCos; if not, write to the Free Software Foundation, Inc.,"
+"// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA."
+"//"
+"// As a special exception, if other files instantiate templates or use macros"
+"// or inline functions from this file, or you compile this file and link it"
+"// with other works to produce a work based on this file, this file does not"
+"// by itself cause the resulting work to be covered by the GNU General Public"
+"// License. However the source code for this file must still be made available"
+"// in accordance with section (3) of the GNU General Public License."
+"//"
+"// This exception does not invalidate any other reasons why a work based on"
+"// this file might be covered by the GNU General Public License."
+"//"
+"// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc."
+"// at http://sources.redhat.com/ecos/ecos-license/"
+"// -------------------------------------------"
+"//####ECOSGPLCOPYRIGHTEND####"
+"//=========================================================================="
+"//#####DESCRIPTIONBEGIN####"
+"//"
+"// Author(s):           andrew.lunn@ascom.ch"
+"// Contributors:        andrew.lunn"
+"// Date:                2000-10-31"
+"// Purpose:             Test a flash driver"
+"// Description:         Try out a number of flash operations and make sure"
+"//                      what is in the flash is what we expeect."
+"//                      "
+"//####DESCRIPTIONEND####"
+"//"
+"//=========================================================================="
+;
 
 #include <cyg/io/flash.h>
 #include <cyg/infra/testcase.h>
@@ -64,6 +64,9 @@
 #ifndef CYGINT_ISO_STRING_STRFUNCS
 # define NA_MSG "Need string functions for test"
 #endif
+#ifndef CYGSEM_IO_FLASH_LEGACY_API
+# define NA_MSG "Need legacy IO FLASH API for test"
+#endif
 
 #ifdef NA_MSG
 void cyg_user_start(void)
Index: redboot/current/src/flash.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/flash.c,v
retrieving revision 1.67
diff -u -r1.67 flash.c
--- redboot/current/src/flash.c	25 Jun 2004 15:49:43 -0000	1.67
+++ redboot/current/src/flash.c	16 Jul 2004 11:21:05 -0000
@@ -163,11 +163,12 @@
     );
 
 // Local data used by these routines
-void *flash_start, *flash_end;
-int flash_block_size, flash_num_blocks;
+cyg_flashaddr_t flash_start, flash_end;
+size_t flash_block_size;
+cyg_uint32 flash_num_blocks;
 #ifdef CYGOPT_REDBOOT_FIS
 void *fis_work_block;
-void *fis_addr;
+cyg_flashaddr_t fis_addr;
 int fisdir_size;  // Size of FIS directory.
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
@@ -186,8 +187,19 @@
 static void        
 _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
 {
-    diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
-    diag_printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
+    cyg_uint32 i=0;
+    cyg_flash_info_t info;
+    int ret;
+    
+    diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, 
+                cyg_flash_errmsg(stat));
+    do {
+      ret = cyg_flash_get_info(i, &info);
+      if (ret == CYG_FLASH_ERR_OK) {
+        diag_printf("   valid range is %p - %p\n", info.start, info.end);
+      }
+      i++;
+    } while (ret != CYG_FLASH_ERR_INVALID);
 }
 
 #ifdef CYGOPT_REDBOOT_FIS
@@ -196,9 +208,9 @@
 {
     int i;
     struct fis_image_desc *img;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 
-    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr);
     img = (struct fis_image_desc *)fis_work_block;
     for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
         if ((img->name[0] != (unsigned char)0xFF) && 
@@ -214,27 +226,27 @@
 fis_update_directory(void)
 {
     int stat;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 
 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
     memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
 #endif
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Ensure [quietly] that the directory is unlocked before trying to update
-    flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
+    cyg_flash_unlock((void *)fis_addr, flash_block_size, &err_addr);
 #endif
-    if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
-        diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_erase(fis_addr, flash_block_size, &err_addr)) != 0) {
+        diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, cyg_flash_errmsg(stat));
     } else {
-        if ((stat = flash_program(fis_addr, fis_work_block, flash_block_size,
-                                  (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_program(fis_addr, fis_work_block, flash_block_size,
+                                      &err_addr)) != 0) {
             diag_printf("Error writing FIS directory at %p: %s\n", 
-                        err_addr, flash_errmsg(stat));
+                        err_addr, cyg_flash_errmsg(stat));
         }
     }
 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
     // Ensure [quietly] that the directory is locked after the update
-    flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
+    cyg_flash_lock((void *)fis_addr, flash_block_size, &err_addr);
 #endif
 }
 
@@ -243,7 +255,7 @@
 {
     int stat;
     struct fis_image_desc *img;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     bool full_init = false;
     struct option_info opts[1];
     CYG_ADDRESS redboot_flash_start;
@@ -377,10 +389,10 @@
         erase_size =  (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
         if ( erase_size > erase_start ) {
             erase_size -= erase_start;
-            if ((stat = flash_erase((void *)erase_start, erase_size,
-                                    (void **)&err_addr)) != 0) {
+            if ((stat = cyg_flash_erase((void *)erase_start, erase_size,
+                                        &err_addr)) != 0) {
                 diag_printf("   initialization failed at %p: %s\n",
-                            err_addr, flash_errmsg(stat));
+                            err_addr, cyg_flash_errmsg(stat));
             }
         }
 #endif
@@ -396,10 +408,10 @@
         } else {
           erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
         }
-        if ((stat = flash_erase((void *)erase_start, erase_size,
-                                (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_erase((void *)erase_start, erase_size,
+                                    &err_addr)) != 0) {
           diag_printf("   initialization failed %p: %s\n",
-                 err_addr, flash_errmsg(stat));
+                 err_addr, cyg_flash_errmsg(stat));
         }
         erase_start += (erase_size + flash_block_size);
         if (fis_addr > cfg_base) {
@@ -407,27 +419,26 @@
         } else {
           erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data
         }
-        if ((stat = flash_erase((void *)erase_start, erase_size,
-                                (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_erase((void *)erase_start, erase_size,
+                                    &err_addr)) != 0) {
           diag_printf("   initialization failed %p: %s\n",
-                 err_addr, flash_errmsg(stat));
+                 err_addr, cyg_flash_errmsg(stat));
         }
         erase_start += (erase_size + flash_block_size);
 #else  // !CYGSEM_REDBOOT_FLASH_CONFIG        
         erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
-        if ((stat = flash_erase((void *)erase_start, erase_size,
-                                (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_erase(erase_start, erase_size,&err_addr)) != 0) {
           diag_printf("   initialization failed %p: %s\n",
-                 err_addr, flash_errmsg(stat));
+                      err_addr, cyg_flash_errmsg(stat));
         }
         erase_start += (erase_size + flash_block_size);          
 #endif
         // Lastly, anything at the end
         erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;
-        if ((stat = flash_erase((void *)erase_start, erase_size,
-                                (void **)&err_addr)) != 0) {
+        if ((stat = cyg_flash_erase(erase_start, erase_size,
+                                    &err_addr)) != 0) {
             diag_printf("   initialization failed at %p: %s\n",
-                        err_addr, flash_errmsg(stat));
+                        err_addr, cyg_flash_errmsg(stat));
         }
 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
     // In this case, 'fis free' works by scanning for erased blocks.  Since the
@@ -448,7 +459,7 @@
     bool show_cksums = false;
     bool show_datalen = false;
     struct option_info opts[2];
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     unsigned long last_addr, lowest_addr;
     bool image_found;
 
@@ -471,7 +482,7 @@
     if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) {
         return;
     }
-    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr);
     // Let diag_printf do the formatting in both cases, rather than counting
     // cols by hand....
     diag_printf("%-16s  %-10s  %-10s  %-10s  %-s\n",
@@ -520,20 +531,37 @@
 static int
 find_free(struct free_chunk *chunks)
 {
-    CYG_ADDRESS *fis_ptr, *fis_end;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
+    cyg_flash_info_t info;
     struct fis_image_desc *img;
-    int i, idx;
-    int num_chunks = 1;
-
-    // Do not search the area reserved for pre-RedBoot systems:
-    fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start + 
-                              CYGNUM_REDBOOT_FLASH_RESERVED_BASE + 
-                              CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
-    fis_end = (CYG_ADDRESS *)flash_end;
-    chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
-    chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
-    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    int i=0, idx;
+    int num_chunks = 0;
+    int ret;
+    
+    do {
+      ret = cyg_flash_get_info(i, &info);
+      if (ret == CYG_FLASH_ERR_OK) {
+        if (i == 0 ) {
+          // Do not search the area reserved for pre-RedBoot systems:
+          chunks[num_chunks].start = (info.start + 
+                                        CYGNUM_REDBOOT_FLASH_RESERVED_BASE + 
+                                        CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
+          chunks[num_chunks].end = info.end;
+          num_chunks++;
+        } else {   // Contiguous flash? If so collapse the chunks together.
+          if (chunks[num_chunks-1].end == (info.start -1)) {
+            chunks[num_chunks-1].end = info.end;
+          } else {
+            chunks[num_chunks].start = info.start;
+            chunks[num_chunks].end = info.end;
+            num_chunks++;
+          }
+        }
+      }
+      i++;
+    } while (ret != CYG_FLASH_ERR_INVALID);
+    
+    cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr);
     img = (struct fis_image_desc *) fis_work_block;
     for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
         if (img->name[0] != (unsigned char)0xFF) {
@@ -555,13 +583,11 @@
                         chunks[idx].end = img->flash_base;
                     } else {
                         // Split chunk into two parts
-                        if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) {
-                            chunks[idx+1].start = img->flash_base + img->size;
-                            chunks[idx+1].end = chunks[idx].end;
-                            if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) {
-                                diag_printf("Warning: too many free chunks\n");
-                                return num_chunks;
-                            }
+                        chunks[idx+1].start = img->flash_base + img->size;
+                        chunks[idx+1].end = chunks[idx].end;
+                        if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) {
+                          diag_printf("Warning: too many free chunks\n");
+                          return num_chunks;
                         }
                         chunks[idx].end = img->flash_base;
                     }
@@ -700,12 +726,13 @@
     bool length_set = false;
     bool img_size_set = false;
     bool no_copy = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct fis_image_desc *img = NULL;
     bool defaults_assumed;
     struct option_info opts[7];
     bool prog_ok = true;
-
+    size_t block_size;
+    
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
               (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
     init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, 
@@ -726,7 +753,7 @@
         return;
     }
 
-    flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+    cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr);
     defaults_assumed = false;
     if (name) {
         // Search existing files to acquire defaults for params not specified:
@@ -782,24 +809,6 @@
     }
     // 'length' is size of FLASH image, 'img_size' is actual data size
     // Round up length to FLASH block size
-#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
-    length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
-    if (length < img_size) {
-        diag_printf("Invalid FLASH image size/length combination\n");
-        return;
-    }
-#endif
-    if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
-        _show_invalid_flash_address(flash_addr, stat);
-        return;
-    }
-    if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) {
-        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
-        return;
-    }
     if (strlen(name) >= sizeof(img->name)) {
         diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
         return;
@@ -814,7 +823,30 @@
             diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);
             return;
         }
+        flash_addr_set = true;
     }
+    if (flash_addr_set) {
+      block_size = cyg_flash_block_size(flash_addr + length);
+#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
+      length = ((length + block_size - 1) / block_size) * block_size;
+      if (length < img_size) {
+        diag_printf("Invalid FLASH image size/length combination\n");
+        return;
+      }
+#endif
+      if ((stat = cyg_flash_verify_addr(flash_addr)) ||
+          (stat = cyg_flash_verify_addr((flash_addr+length-1)))) {
+        _show_invalid_flash_address(flash_addr, stat);
+        return;
+      }
+      block_size = cyg_flash_block_size(flash_addr);
+      if ((flash_addr & (flash_block_size-1)) != 0) {
+        diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
+        diag_printf("   must be 0x%x aligned\n", flash_block_size);
+        return;
+      }
+    }
+    
     // First, see if the image by this name has agreable properties
     if (img) {
         if (flash_addr_set && (img->flash_base != flash_addr)) {
@@ -863,7 +895,7 @@
             }
         }
 #endif
-        // If not image by that name, try and find an empty slot
+        // If no image by that name, try and find an empty slot
         img = (struct fis_image_desc *)fis_work_block;
         for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
             if (img->name[0] == (unsigned char)0xFF) {
@@ -873,21 +905,23 @@
     }
     if (!no_copy) {
         // Safety check - make sure the address range is not within the code we're running
-        if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1))) {
+        if (cyg_flash_code_overlaps(flash_addr, (flash_addr+img_size-1))) {
             diag_printf("Can't program this region - contains code in use!\n");
             return;
         }
         if (prog_ok) {
             // Erase area to be programmed
-            if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-                diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
+            if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) {
+                diag_printf("Can't erase region at %p: %s\n", err_addr, cyg_flash_errmsg(stat));
                 prog_ok = false;
             }
         }
         if (prog_ok) {
             // Now program it
-            if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
-                diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
+            if ((stat = cyg_flash_program(flash_addr, (void *)mem_addr, img_size, 
+                                          &err_addr)) != 0) {
+                diag_printf("Can't program region at %p: %s\n", err_addr, 
+                            cyg_flash_errmsg(stat));
                 prog_ok = false;
             }
         }
@@ -919,7 +953,7 @@
 {
     char *name;
     int num_reserved, i, stat;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct fis_image_desc *img;
 
     if (!scan_opts(argc, argv, 2, 0, 0, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
@@ -967,8 +1001,8 @@
         return;
     }
     // Erase Data blocks (free space)
-    if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
-        diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_erase(img->flash_base, img->size, &err_addr)) != 0) {
+        diag_printf("Error erasing at %p: %s\n", err_addr, cyg_flash_errmsg(stat));
     } else {
         img->name[0] = (unsigned char)0xFF;    
         fis_update_directory();
@@ -991,7 +1025,7 @@
 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) ||  defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
     bool decompress = false;
 #endif
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
               (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
@@ -1055,11 +1089,12 @@
         load_address_end = (unsigned long)p->out_buf;
 
     	// Reload fis directory
-        flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+        cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr);
     } else // dangling block
 #endif
     {
-        flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);
+        cyg_flash_read(img->flash_base, (void *)mem_addr, img->data_length, 
+                       &err_addr);
 
         // Set load address/top
         load_address = mem_addr;
@@ -1093,10 +1128,11 @@
     bool mem_addr_set = false;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[3];
     bool prog_ok;
-
+    size_t block_size;
+    
     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, 
               (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
     init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM, 
@@ -1115,18 +1151,20 @@
     }
 
     // Round up length to FLASH block size
+    block_size = cyg_flash_block_size(flash_addr + length);
 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
-    length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
+    length = ((length + block_size - 1) / block_size) * block_size;
 #endif
-    if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+    if ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1)))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && flash_addr & (flash_block_size-1)) {
+
+    block_size = cyg_flash_block_size(flash_addr);
+    if (flash_addr & (block_size-1)) {
         diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
-        diag_printf("   must be 0x%x aligned\n", flash_block_size);
+        diag_printf("   must be 0x%x aligned\n", block_size);
         return;
     }
     if ((mem_addr < (CYG_ADDRESS)ram_start) ||
@@ -1135,7 +1173,7 @@
         diag_printf("   valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
     }
     // Safety check - make sure the address range is not within the code we're running
-    if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
+    if (cyg_flash_code_overlaps(flash_addr, (flash_addr+length-1))) {
         diag_printf("Can't program this region - contains code in use!\n");
         return;
     }
@@ -1147,15 +1185,18 @@
     prog_ok = true;
     if (prog_ok) {
         // Erase area to be programmed
-        if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-            diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
+        if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) {
+            diag_printf("Can't erase region at %p: %s\n", err_addr, 
+                        cyg_flash_errmsg(stat));
             prog_ok = false;
         }
     }
     if (prog_ok) {
         // Now program it
-        if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
-            diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
+        if ((stat = cyg_flash_program(flash_addr, (void *)mem_addr, length, 
+                                      &err_addr)) != 0) {
+            diag_printf("Can't program region at %p: %s\n", err_addr, 
+                        cyg_flash_errmsg(stat));
             prog_ok = false;
         }
     }
@@ -1169,7 +1210,7 @@
     CYG_ADDRESS flash_addr;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[2];
 
     init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 
@@ -1187,23 +1228,23 @@
         return;
     }
     if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+        ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if (flash_addr_set && flash_addr & (flash_block_size-1)) {
+    if (flash_addr_set && flash_addr & (cyg_flash_block_size(flash_addr)-1)) {
         diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
         diag_printf("   must be 0x%x aligned\n", flash_block_size);
         return;
     }
     // Safety check - make sure the address range is not within the code we're running
-    if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
+    if (cyg_flash_code_overlaps(flash_addr, (flash_addr+length-1))) {
         diag_printf("Can't erase this region - contains code in use!\n");
         return;
     }
-    if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_erase(flash_addr, length, &err_addr)) != 0) {
+        diag_printf("Error erasing at %p: %s\n", err_addr, cyg_flash_errmsg(stat));
     }
 }
 
@@ -1218,7 +1259,7 @@
     CYG_ADDRESS flash_addr;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[2];
 
     init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 
@@ -1246,13 +1287,13 @@
         return;
     }
     if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+        ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
-    if ((stat = flash_lock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        diag_printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_lock(flash_addr, length, &err_addr)) != 0) {
+        diag_printf("Error locking at %p: %s\n", err_addr, cyg_flash_errmsg(stat));
     }
 }
 
@@ -1265,7 +1306,7 @@
     CYG_ADDRESS flash_addr;
     bool flash_addr_set = false;
     bool length_set = false;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
     struct option_info opts[2];
 
     init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 
@@ -1292,14 +1333,14 @@
         return;
     }
     if (flash_addr_set &&
-        ((stat = flash_verify_addr((void *)flash_addr)) ||
-         (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
+        ((stat = cyg_flash_verify_addr(flash_addr)) ||
+         (stat = cyg_flash_verify_addr((flash_addr+length-1))))) {
         _show_invalid_flash_address(flash_addr, stat);
         return;
     }
 
-    if ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
-        diag_printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat));
+    if ((stat = cyg_flash_unlock(flash_addr, length, &err_addr)) != 0) {
+        diag_printf("Error unlocking at %p: %s\n", err_addr, cyg_flash_errmsg(stat));
     }
 }
 #endif
@@ -1309,28 +1350,44 @@
 
 void
 _flash_info(void)
-{
+{   
+    cyg_uint32 i=0,j;
+    cyg_flash_info_t info;
+    int ret;
+    
     if (!__flash_init) return;
-    diag_printf("FLASH: %p - %p, %d blocks of %p bytes each.\n", 
-           flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
+
+    do {
+      ret = cyg_flash_get_info(i, &info);
+      if (ret == CYG_FLASH_ERR_OK) {
+        diag_printf("FLASH: %p - %p ", info.start, info.end);
+        for (j=0;j < info.num_block_infos; j++) {
+          diag_printf("%d x 0x%x blocks ",
+                      info.block_info[j].blocks,
+                      info.block_info[j].block_size);
+        }
+        diag_printf("\n");
+      }
+      i++;
+    } while (ret != CYG_FLASH_ERR_INVALID);
 }
 
 bool
 do_flash_init(void)
 {
     int stat;
-    void *err_addr;
+    cyg_flashaddr_t err_addr;
 
     if (!__flash_init) {
         __flash_init = 1;
-        if ((stat = flash_init(diag_printf)) != 0) {
-            diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
+        if ((stat = cyg_flash_init(diag_printf)) != 0) {
+            diag_printf("FLASH: driver init failed: %s\n", cyg_flash_errmsg(stat));
             return false;
         }
-        flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
+        cyg_flash_get_limits(&flash_start, &flash_end);
         // Keep 'end' address as last valid location, to avoid wrap around problems
-        flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
-        flash_get_block_info(&flash_block_size, &flash_num_blocks);
+        flash_end = ((CYG_ADDRESS)flash_end - 1);
+        cyg_flash_get_block_info(&flash_block_size, &flash_num_blocks);
 #ifdef CYGOPT_REDBOOT_FIS
         fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
         fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
@@ -1345,17 +1402,17 @@
         fis_work_block = workspace_end;
 # endif
         if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
-            fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
-                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
+            fis_addr = ((CYG_ADDRESS)flash_end + 1 +
+                        (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
         } else {
-            fis_addr = (void *)((CYG_ADDRESS)flash_start + 
-                                (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
+            fis_addr = ((CYG_ADDRESS)flash_start + 
+                        (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
         }
         if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
             diag_printf("FIS directory doesn't fit\n");
             return false;
         }
-        flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
+        cyg_flash_read(fis_addr, fis_work_block, fisdir_size, &err_addr);
 #endif
     }
     return true;
Index: redboot/current/src/io.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/redboot/current/src/io.c,v
retrieving revision 1.32
diff -u -r1.32 io.c
--- redboot/current/src/io.c	5 Dec 2003 12:51:55 -0000	1.32
+++ redboot/current/src/io.c	16 Jul 2004 11:21:06 -0000
@@ -387,6 +387,7 @@
             mon_read_char(&c);
         }
         *eol = '\0';
+        
         switch (c) {
 #define CTRL(c) ((c)&0x1F)
 #if CYGNUM_REDBOOT_CMD_LINE_EDITING != 0
Index: fs/jffs2/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/ChangeLog,v
retrieving revision 1.34
diff -u -r1.34 ChangeLog
--- fs/jffs2/current/ChangeLog	29 Apr 2004 07:16:10 -0000	1.34
+++ fs/jffs2/current/ChangeLog	16 Jul 2004 11:21:07 -0000
@@ -1,3 +1,27 @@
+2004-07-14  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* tests/fileio1.c (main): If we have two filesystem configured
+	mount the second one on /mnt and list the root of it.
+	* src/fs-ecos.c (jffs2_fo_write): Fixed a typo in a debug print 
+	which is normally disabled.
+
+2004-07-12  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/fs-ecos.c (jffs2_fo_lseek): Put back part of the fix for
+	lseeking past the end of the file which was removed during the last
+	merge with MTD.
+
+2004-07-10  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/flashio.c (jffs2_flash_erase): Minor update for new
+	flash API.
+
+2004-06-21  Dirk Eibach  <eibach@gdsys.de>
+2004-06-21  Andrew Lunn  <andrew.lunn@ascom.ch>
+
+	* src/fs-ecos.c (jffs2_getinfo): Added support for
+	FS_INFO_{FREE|USED} on a filesystem.
+
 2004-04-19  Oyvind Harboe <oyvind.harboe@zylin.com>
 	
 	* src/build.c: JFFS2 can now be used as a write-once, read many mode
Index: fs/jffs2/current/src/flashio.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/flashio.c,v
retrieving revision 1.1
diff -u -r1.1 flashio.c
--- fs/jffs2/current/src/flashio.c	11 Dec 2003 23:38:21 -0000	1.1
+++ fs/jffs2/current/src/flashio.c	16 Jul 2004 11:21:07 -0000
@@ -144,7 +144,7 @@
 			   struct jffs2_eraseblock * jeb)
 {
 	cyg_io_flash_getconfig_erase_t e;
-	void *err_addr;
+	cyg_flashaddr_t err_addr;
 	Cyg_ErrNo err;
 	cyg_uint32 len = sizeof (e);
 	struct super_block *sb = OFNI_BS_2SFFJ(c);
Index: fs/jffs2/current/src/fs-ecos.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/fs-ecos.c,v
retrieving revision 1.27
diff -u -r1.27 fs-ecos.c
--- fs/jffs2/current/src/fs-ecos.c	21 Apr 2004 18:51:21 -0000	1.27
+++ fs/jffs2/current/src/fs-ecos.c	16 Jul 2004 11:21:08 -0000
@@ -1360,7 +1360,7 @@
 		int err;
 
 		D2(printf("jffs2_fo_write page_start_pos %d\n", pos));
-		D2(printf("jffs2_fo_write transfer size %d\n", l));
+		D2(printf("jffs2_fo_write transfer size %d\n", len));
 
 		err = jffs2_write_inode_range(c, f, &ri, buf,
 					      pos, len, &writtenlen);
@@ -1420,7 +1420,7 @@
 
         // Check that pos is still within current file size, or at the
         // very end.
-        if (pos < 0 || pos > node->i_size)
+        if (pos < 0 )
                 return EINVAL;
 
 	// All OK, set fp offset and return new position.
Index: fs/jffs2/current/tests/fileio1.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/tests/fileio1.c,v
retrieving revision 1.3
diff -u -r1.3 fileio1.c
--- fs/jffs2/current/tests/fileio1.c	11 Dec 2003 23:33:55 -0000	1.3
+++ fs/jffs2/current/tests/fileio1.c	16 Jul 2004 11:21:09 -0000
@@ -73,6 +73,8 @@
 #include <string.h>
 #include <dirent.h>
 
+#include <stdlib.h>
+
 #include <cyg/fileio/fileio.h>
 
 #include <cyg/infra/testcase.h>
@@ -416,6 +418,14 @@
     //int i;
     int existingdirents=-1;
 
+    struct mallinfo info;
+
+    info =  mallinfo();
+    diag_printf("arenasize %d, freeblocks %d, totalallocated %d, totalfree %d, maxfree %d\n",
+                info.arena, info.ordblks, info.uordblks, info.fordblks, info.maxfree);
+    
+    
+
     CYG_TEST_INIT();
 
     // --------------------------------------------------------------
@@ -658,9 +668,33 @@
     err = umount( "/jffs2" );
     if( err < 0 ) SHOW_RESULT( umount, err );    
     
+#ifdef CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_2
+    diag_printf("<INFO>: mounting second JFFS2 filesystem on /mnt\n");
+    
+    err = mount( CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1, "/mnt", "jffs2" );
+    if( err < 0 ) SHOW_RESULT( mount, err );    
+
+    err = chdir( "/" );
+    if( err < 0 ) SHOW_RESULT( chdir, err );
+
+    checkcwd( "/" );
+    
+    listdir( "/", true, -1, &existingdirents );
+    if ( existingdirents < 2 )
+        CYG_TEST_FAIL("Not enough dir entries\n");
+
+    listdir( "/mnt", true, -1, &existingdirents );
+    if ( existingdirents < 2 )
+        CYG_TEST_FAIL("Not enough dir entries\n");
+
+    diag_printf("<INFO>: umount /mnt\n");    
+    err = umount( "/mnt" );
+#endif
+
     diag_printf("<INFO>: umount /\n");    
     err = umount( "/" );
     if( err < 0 ) SHOW_RESULT( umount, err );    
+
     
     CYG_TEST_PASS_FINISH("fileio1");
 }

-------------- next part --------------
-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


More information about the Ecos-discuss mailing list