diff packages/io/flash/current/src/flashiodev.c @ 1706:3845779eca10

* src/flash.c: Major rewrite to implement a new API * src/legacy_api.c: Support the legacy API * src/legacy_drv.c: Support the legacy driver API * src/flashiodev.c: Support the new API and multiple devices * include/flash_priv.h: Interface devices should use * cdl/io_flash.cdl: Updates for new interface and multiple devices.
author asl
date Thu, 05 Aug 2004 13:50:00 +0000
parents 5118f42e7e62
children 3bafac44ac03
line wrap: on
line diff
--- a/packages/io/flash/current/src/flashiodev.c
+++ b/packages/io/flash/current/src/flashiodev.c
@@ -9,6 +9,7 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2004 Andrew Lunn
 //
 // 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
@@ -41,7 +42,7 @@
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    jlarmour
-// Contributors: woehler
+// Contributors: woehler, Andrew Lunn
 // Date:         2002-01-16
 // Purpose:      
 // Description:  
@@ -62,110 +63,121 @@
 #include <cyg/hal/hal_if.h>
 
 #define MIN(x,y) ((x)<(y) ? (x) : (y))
+#define MAX(x,y) ((x)>(y) ? (x) : (y))
 
 struct flashiodev_priv_t{
-	char *start;
-	char *end;
+  cyg_flashaddr_t start;
+  cyg_flashaddr_t end;
+  cyg_bool        use_fis;
+  cyg_bool        use_absolute;
+  cyg_bool        use_offset;
+  char *          fis_name;
+  cyg_uint32      block_size;
 };
 
-static struct flashiodev_priv_t flashiodev_priv[1];
-
 static int dummy_printf( const char *fmt, ... ) {return 0;}
 
 static bool
 flashiodev_init( struct cyg_devtab_entry *tab )
 {
-    struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
-    int stat = flash_init( &dummy_printf );
-    if ( stat == 0 ) {
-#ifdef CYGNUM_IO_FLASH_BLOCK_CFG_FIS_1
-        CYG_ADDRESS		flash_base;
-        unsigned long	size;
+  struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
+  cyg_flash_info_t info;
+  cyg_uint32 i;
+  
+  int stat = cyg_flash_init( &dummy_printf );
+  if ( stat == 0 ) {
+    if (dev->use_fis) {
+      CYG_ADDRESS	flash_base;
+      unsigned long	size;
+    
+      if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE, 
+                                      dev->fis_name,
+                                      &flash_base))
+        return false;
+      if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE, 
+                                      dev->fis_name,
+                                      &size))
+        return false;
+    
+      dev->start = flash_base;
+      dev->end = flash_base + size;
+    }
+    if (dev->use_offset) {
+      // dev->start the contain the offset to the beginning of the block
+      // dev->end is the length of the block
+      cyg_flashaddr_t start, end;
+      cyg_flash_get_limits(&start, &end);
+      dev->start = dev->start + start;
+      dev->end = dev->start + dev->end;
+    }
+    if (dev->use_absolute) {
+      // dev->start is the absolute address of the start
+      // dev->end is the length;
+      dev->end = dev->start + dev->end;
+    }
 
-        if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE, 
-                                        CYGDAT_IO_FLASH_BLOCK_FIS_NAME_1,
-                                        &flash_base))
-            return false;
-        if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE, 
-                                        CYGDAT_IO_FLASH_BLOCK_FIS_NAME_1,
-                                        &size))
-            return false;
-			
-        dev->start = (char *)flash_base;
-        dev->end = (char *)flash_base + size;
-#else
-        dev->start = (char *)flash_info.start + CYGNUM_IO_FLASH_BLOCK_OFFSET_1;
-        dev->end = (char *)flash_info.start + CYGNUM_IO_FLASH_BLOCK_OFFSET_1 + 
-            CYGNUM_IO_FLASH_BLOCK_LENGTH_1;
-#endif
-        return true;
-    } else
-        return false;
+    stat = cyg_flash_get_info_addr(dev->start, &info);
+    if (stat != CYG_FLASH_ERR_OK) {
+      return false;
+    }
+    dev->block_size = 0;
+    for (i=0; i < info.num_block_infos; i++){
+      dev->block_size = MAX(dev->block_size, info.block_info[i].block_size);
+    }
+    
+    return true;
+  } else
+    return false;
 } // flashiodev_init()
 
-#if 0
-static Cyg_ErrNo
-flashiodev_lookup( struct cyg_devtab_entry **tab, 
-                   struct cyg_devtab_entry *sub_tab,
-                   const char *name)
-{   
-} // flashiodev_lookup()
-#endif
-
 static Cyg_ErrNo
 flashiodev_bread( cyg_io_handle_t handle, void *buf, cyg_uint32 *len,
                   cyg_uint32 pos)
 {
-	struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
-	struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
-
-	char *startpos = dev->start + pos;
-        void *erraddr;
-        Cyg_ErrNo err = ENOERR;
-        
-
+  struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
+  struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
+  
+  cyg_flashaddr_t startpos = dev->start + pos;
+  Cyg_ErrNo err;
+  
+  
 #ifdef CYGPKG_INFRA_DEBUG // don't bother checking this all the time
-    char *endpos = startpos + *len - 1;
-    char *flashend = MIN( (char *)flash_info.end - 1, dev->end - 1);
-    if ( startpos < dev->start )
-        return -EINVAL;
-    if ( endpos > flashend )
-        return -EINVAL;
+  cyg_flashaddr_t endpos = startpos + *len - 1;
+  if ( startpos < dev->start )
+    return -EINVAL;
+  if ( endpos > dev->end )
+    return -EINVAL;
 #endif
-    
-    err = flash_read( startpos,
-                      (void *)buf, *len, &erraddr );
-
-    if ( err )
-        err = -EIO; // just something sane
-    return err;
+  
+  err = cyg_flash_read( startpos,(void *)buf, *len, NULL );
+  
+  if ( err != CYG_FLASH_ERR_OK )
+    err = -EIO; // just something sane
+  return err;
 } // flashiodev_bread()
 
 static Cyg_ErrNo
 flashiodev_bwrite( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len,
                    cyg_uint32 pos )
-{   
-	struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
-	struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
-
-    Cyg_ErrNo err = ENOERR;
-    void *erraddr;
-    char *startpos = dev->start + pos;
-
+{
+  struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
+  struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
+  
+  Cyg_ErrNo err;
+  cyg_flashaddr_t startpos = dev->start + pos;
+  
 #ifdef CYGPKG_INFRA_DEBUG // don't bother checking this all the time
-    char *endpos = startpos + *len - 1;
-    char *flashend = MIN( (char *)flash_info.end - 1, dev->end - 1);
-    if ( startpos < dev->start )
-        return -EINVAL;
-    if ( endpos > flashend )
-        return -EINVAL;
+  cyg_flashaddr_t endpos = startpos + *len - 1;
+  if ( startpos < dev->start )
+    return -EINVAL;
+  if ( endpos > dev->end )
+    return -EINVAL;
 #endif
-    err = flash_program( startpos, 
-                         (void *)buf, *len, &erraddr );
-
-    if ( err )
-        err = -EIO; // just something sane
-    return err;
+  err = cyg_flash_program( startpos, (void *)buf, *len, NULL );
+  
+  if ( err )
+    err = -EIO; // just something sane
+  return err;
 } // flashiodev_bwrite()
 
 static Cyg_ErrNo
@@ -174,68 +186,65 @@ flashiodev_get_config( cyg_io_handle_t h
                        void* buf,
                        cyg_uint32* len)
 {
-	struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
-	struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
-
-    switch (key) {
-    case CYG_IO_GET_CONFIG_FLASH_ERASE:
+  struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
+  struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
+  
+  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 = dev->start + e->offset;
-
+      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;
+        cyg_flashaddr_t startpos = dev->start + e->offset;
+        
 #ifdef CYGPKG_INFRA_DEBUG // don't bother checking this all the time
-            char *endpos = startpos + e->len - 1;
-            char *flashend = MIN( (char *)flash_info.end - 1, dev->end - 1);
-            if ( startpos < dev->start )
-                return -EINVAL;
-            if ( endpos > flashend )
-                return -EINVAL;
+        cyg_flashaddr_t endpos = startpos + e->len - 1;
+        if ( startpos < dev->start )
+          return -EINVAL;
+        if ( endpos > dev->end )
+          return -EINVAL;
 #endif
-            e->flasherr = flash_erase( startpos, e->len, e->err_address );
-        }
-        return ENOERR;
+        e->flasherr = cyg_flash_erase( startpos, e->len, e->err_address );
+      }
+      return ENOERR;
     }
-    case CYG_IO_GET_CONFIG_FLASH_DEVSIZE:
+  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 = flash_info.blocks * flash_info.block_size;
-			d->dev_size = dev->end - dev->start;
-        }
-        return ENOERR;
+      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 = dev->end - dev->start;
+      }
+      return ENOERR;
     }
-
-    case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE:
+    
+  case CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE:
     {
-        cyg_io_flash_getconfig_blocksize_t *b =
-            (cyg_io_flash_getconfig_blocksize_t *)buf;
+      cyg_io_flash_getconfig_blocksize_t *b =
+        (cyg_io_flash_getconfig_blocksize_t *)buf;
 #ifdef CYGPKG_INFRA_DEBUG // don't bother checking this all the time
-       char *startpos = dev->start + b->offset;
-	    char *flashend = MIN( (char *)flash_info.end - 1, dev->end - 1);
-
-        if ( startpos < dev->start )
-            return -EINVAL;
-        if ( startpos > flashend )
-            return -EINVAL;
+      cyg_flashaddr_t startpos = dev->start + b->offset;
+      
+      if ( startpos < dev->start )
+        return -EINVAL;
+      if ( startpos > dev->end )
+        return -EINVAL;
 #endif  
-        if ( *len != sizeof( cyg_io_flash_getconfig_blocksize_t ) )
-             return -EINVAL;
-        
-        // offset unused for now
-		b->block_size = flash_info.block_size;
-        return ENOERR;
+      if ( *len != sizeof( cyg_io_flash_getconfig_blocksize_t ) )
+        return -EINVAL;
+      
+      // offset unused for now
+      b->block_size = dev->block_size;
+      return ENOERR;
     }
-
-    default:
-        return -EINVAL;
-    }
+    
+  default:
+    return -EINVAL;
+  }
 } // flashiodev_get_config()
 
 static Cyg_ErrNo
@@ -244,46 +253,88 @@ flashiodev_set_config( cyg_io_handle_t h
                        const void* buf,
                        cyg_uint32* len)
 {
-#ifdef CYGNUM_IO_FLASH_BLOCK_CFG_FIS_1
-	struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
-	struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
-#endif
-
-    switch (key) {
-#ifdef CYGNUM_IO_FLASH_BLOCK_CFG_FIS_1
-    case CYG_IO_SET_CONFIG_FLASH_FIS_NAME:
+  struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle;
+  struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv;
+  
+  switch (key) {
+  case CYG_IO_SET_CONFIG_FLASH_FIS_NAME:
     {
-        CYG_ADDRESS     flash_base;
-	unsigned long   size;
+      cyg_flashaddr_t flash_base;
+      unsigned long size;
+      cyg_flash_info_t info;
+      cyg_uint32 i;
+      int stat;
+      
+      if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE, 
+                                      (char *)buf, &flash_base))
+        return -ENOENT;
+      if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE, 
+                                      (char *)buf, &size))
+        return -ENOENT;
+      
+      dev->start = flash_base;
+      dev->end = flash_base + size;
 
-	if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE, 
-                                        (char *)buf, &flash_base))
-	    return -ENOENT;
-	if(!CYGACC_CALL_IF_FLASH_FIS_OP(CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE, 
-					(char *)buf, &size))
-	    return -ENOENT;
-			
-	dev->start = (char *)flash_base;
-	dev->end = (char *)flash_base + size;
-	return ENOERR;
+      stat = cyg_flash_get_info_addr(dev->start, &info);
+      if (stat != CYG_FLASH_ERR_OK) {
+        return -ENOENT;
+      }
+      dev->block_size = 0;
+      for (i=0; i < info.num_block_infos; i++){
+        dev->block_size = MAX(dev->block_size, info.block_info[i].block_size);
+      }
+      return ENOERR;
     }
-#endif
-    default:
-        return -EINVAL;
-    }
+  default:
+    return -EINVAL;
+  }
 } // flashiodev_set_config()
 
 // get_config/set_config should be added later to provide the other flash
 // operations possible, like erase etc.
 
+#ifdef CYGNUM_IO_FLASH_BLOCK_CFG_FIS_1
+static struct flashiodev_priv_t priv1 = {
+  0,       // start
+  0,       // end
+  1,       // use_fis
+  0,       // use_static
+  0.       // use_offset
+  CYGDAT_IO_FLASH_BLOCK_FIS_NAME_1,
+  0        // blocksize
+};
+
+#endif
+#ifdef CYGNUM_IO_FLASH_BLOCK_CFG_STATIC_ABSOLUTE_1 
+static struct flashiodev_priv_t priv1 = {
+  CYGNUM_IO_FLASH_BLOCK_ABSOLUTE_START_1,       // start
+  CYGNUM_IO_FLASH_BLOCK_ABSOLUTE_START_1 + CYGNUM_IO_FLASH_BLOCK_ABSOLUTE_LENGTH_1,
+  0,       // use_fis
+  1,       // use_static
+  0,       // use_offset
+  "",      // fis_name
+  0        // blocksize
+};
+#else
+static struct flashiodev_priv_t priv1 = {
+  CYGNUM_IO_FLASH_BLOCK_OFFSET_1,       // start
+  CYGNUM_IO_FLASH_BLOCK_LENGTH_1,       // end 
+  0,       // use_fis
+  0,       // use_static
+  1,       // use_offset
+  "",      // fis_name
+  0        // blocksize
+};
+#endif
+
 BLOCK_DEVIO_TABLE( cyg_io_flashdev1_ops,
                    &flashiodev_bwrite,
                    &flashiodev_bread,
                    0, // no select
                    &flashiodev_get_config,
                    &flashiodev_set_config
-    ); 
-                   
+                   ); 
+
 
 BLOCK_DEVTAB_ENTRY( cyg_io_flashdev1,
                     CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1,
@@ -291,6 +342,51 @@ BLOCK_DEVTAB_ENTRY( cyg_io_flashdev1,
                     &cyg_io_flashdev1_ops,
                     &flashiodev_init,
                     0, // No lookup required
-                    &flashiodev_priv[0] );
+                    &priv1 );
+
+
+#ifdef CYGSEM_IO_FLASH_BLOCK_DEVICE_2 
+#ifdef CYGNUM_IO_FLASH_BLOCK_CFG_FIS_2
+static struct flashiodev_priv_t priv2 = {
+  0,       // start
+  0,       // end
+  1,       // use_fis
+  0,       // use_static
+  0.       // use_offset
+  CYGDAT_IO_FLASH_BLOCK_FIS_NAME_2,
+  0        // blocksize
+};
+
+#endif
+#ifdef CYGNUM_IO_FLASH_BLOCK_CFG_STATIC_ABSOLUTE_2 
+static struct flashiodev_priv_t priv2 = {
+  CYGNUM_IO_FLASH_BLOCK_ABSOLUTE_START_2,       // start
+  CYGNUM_IO_FLASH_BLOCK_ABSOLUTE_START_2 + CYGNUM_IO_FLASH_BLOCK_ABSOLUTE_LENGTH_2,
+  0,       // use_fis
+  1,       // use_static
+  0,       // use_offset
+  "",      // fis_name
+  0        // blocksize
+};
+#else
+static struct flashiodev_priv_t priv2 = {
+  CYGNUM_IO_FLASH_BLOCK_OFFSET_2,       // start
+  CYGNUM_IO_FLASH_BLOCK_LENGTH_2,       // end 
+  0,       // use_fis
+  0,       // use_static
+  1,       // use_offset
+  "",      // fis_name
+  0        // blocksize
+};
+#endif
+
+BLOCK_DEVTAB_ENTRY( cyg_io_flashdev2,
+                    CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_2,
+                    0,
+                    &cyg_io_flashdev1_ops,
+                    &flashiodev_init,
+                    0, // No lookup required
+                    &priv2 );
+#endif
 
 // EOF flashiodev.c