[PATCH rtems 10/14] Flashdev: Refactoring, replace region with partition jargon and allow IOTCLs to return a value
berndmoessner80 at gmail.com
berndmoessner80 at gmail.com
Tue Jan 2 20:45:31 UTC 2024
From: Bernd Moessner <berndmoessner80 at gmail.com>
---
cpukit/dev/flash/flashdev.c | 1051 +++++++++--------
cpukit/include/dev/flash/flashdev.h | 250 ++--
cpukit/libmisc/shell/main_flashdev.c | 2 +-
testsuites/libtests/flashdev01/init.c | 97 +-
.../libtests/flashdev01/test_flashdev.c | 16 +-
5 files changed, 794 insertions(+), 622 deletions(-)
diff --git a/cpukit/dev/flash/flashdev.c b/cpukit/dev/flash/flashdev.c
index 363d12e3ff..de6556c19a 100644
--- a/cpukit/dev/flash/flashdev.c
+++ b/cpukit/dev/flash/flashdev.c
@@ -40,25 +40,25 @@
#include <unistd.h>
#include <assert.h>
-#define RTEMS_FLASHDEV_REGION_ALLOC_FULL 0xFFFFFFFFUL
-#define RTEMS_FLASHDEV_REGION_UNDEFINED 0xFFFFFFFFUL
-#define RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH 32
+#define RTEMS_FLASHDEV_MAX_PARTITIONS 16
+#define RTEMS_FLASHDEV_PARTITION_ALLOC_FULL 0xFFFFFFFFUL
+#define RTEMS_FLASHDEV_PARTITION_UNDEFINED 0xFFFFFFFFUL
-#define RTEMS_FLASHDEV_BITALLOC_LENGTH(t) \
- (t->max_regions/RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH)
-#define RTEMS_FLASHDEV_BITALLOC_FINAL_BITS(t) \
- (t->max_regions%RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH)
-static int rtems_flashdev_do_init(
- rtems_flashdev *flash,
- void ( *destroy )( rtems_flashdev *flash )
-);
+static inline uint32_t set_bit(uint32_t in, uint32_t bit_idx)
+{
+ return in | ( 1 << bit_idx );
+}
-static int rtems_flashdev_read_write(
- rtems_libio_t *iop,
- const void *write_buff,
- void *read_buff,
- size_t count
+static inline uint32_t clear_bit(uint32_t in, uint32_t bit_idx)
+{
+ return in & ~( 1 << (bit_idx) );
+}
+
+
+/* IOCTL Functions*/
+static uint32_t rtems_flashdev_ioctl_get_jedec_id(
+ rtems_flashdev *flash
);
static int rtems_flashdev_ioctl_erase(
@@ -67,41 +67,34 @@ static int rtems_flashdev_ioctl_erase(
void *arg
);
-static off_t rtems_flashdev_get_region_offset(
- rtems_flashdev *flash,
- rtems_libio_t *iop
-);
-
-static size_t rtems_flashdev_get_region_size(
+static int rtems_flashdev_ioctl_create_partition(
rtems_flashdev *flash,
- rtems_libio_t *iop
+ rtems_libio_t *iop,
+ void *arg
);
-static int rtems_flashdev_ioctl_set_region(
+static int rtems_flashdev_ioctl_delete_partition(
rtems_flashdev *flash,
rtems_libio_t *iop,
void *arg
);
-static int rtems_flashdev_ioctl_create_region(
+static int rtems_flashdev_ioctl_resize_partition(
rtems_flashdev *flash,
rtems_libio_t *iop,
- rtems_flashdev_region *region_in
+ void *arg
);
-static int rtems_flashdev_ioctl_update_region(
+static int rtems_flashdev_ioctl_activate_partition(
rtems_flashdev *flash,
rtems_libio_t *iop,
- rtems_flashdev_region *region_in
+ void *arg
);
-static int rtems_flashdev_ioctl_clear_region(
+static int rtems_flashdev_ioctl_deactivate_partition(
rtems_flashdev *flash,
- rtems_libio_t *iop
-);
-
-static uint32_t rtems_flashdev_ioctl_get_jedec_id(
- rtems_flashdev *flash
+ rtems_libio_t *iop,
+ void *arg
);
static uint32_t rtems_flashdev_ioctl_get_flash_type(
@@ -109,12 +102,12 @@ static uint32_t rtems_flashdev_ioctl_get_flash_type(
void *arg
);
-static int rtems_flashdev_ioctl_get_pageinfo_offset(
+static int rtems_flashdev_ioctl_get_pageinfo_by_offset(
rtems_flashdev *flash,
void *arg
);
-static int rtems_flashdev_ioctl_get_pageinfo_index(
+static int rtems_flashdev_ioctl_get_pageinfo_by_index(
rtems_flashdev *flash,
void *arg
);
@@ -134,6 +127,49 @@ static int rtems_flashdev_ioctl_get_erase_size(
void *arg
);
+
+static int rtems_flashdev_do_init(
+ rtems_flashdev *flash,
+ void ( *destroy )( rtems_flashdev *flash )
+);
+
+static int rtems_flashdev_read_write(
+ rtems_libio_t *iop,
+ const void *write_buff,
+ void *read_buff,
+ size_t count
+);
+
+static ssize_t rtems_flashdev_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ size_t count
+);
+
+static ssize_t rtems_flashdev_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ size_t count
+);
+
+static off_t rtems_flashdev_get_partition_offset(
+ rtems_flashdev *flash,
+ rtems_libio_t *iop
+);
+
+static size_t rtems_flashdev_get_partition_size(
+ rtems_flashdev *flash,
+ rtems_libio_t *iop
+);
+
+static int rtems_flashdev_create_partition(
+ rtems_libio_t *iop,
+ rtems_flashdev_partition *partition_table,
+ uint32_t partition_idx,
+ rtems_flashdev_partition *region_in
+);
+
+
static int rtems_flashdev_get_addr(
rtems_flashdev *flash,
rtems_libio_t *iop,
@@ -154,28 +190,13 @@ static int rtems_flashdev_update_and_return(
size_t count
);
-static int rtems_flashdev_check_region_valid(
+static int rtems_flashdev_check_partition_valid(
rtems_flashdev *flash,
- rtems_flashdev_region * region
-);
-
-static uint32_t rtems_flashdev_find_unallocated_region(
- rtems_flashdev_region_table *region_table
+ rtems_flashdev_partition * region
);
-static uint32_t rtems_flashdev_set_region(
- rtems_flashdev_region_table *region_table,
- int index
-);
-
-static uint32_t rtems_flashdev_unset_region(
- rtems_flashdev_region_table *region_table,
- int index
-);
-
-static uint32_t rtems_flashdev_check_allocation(
- rtems_flashdev_region_table *region_table,
- int index
+static uint32_t rtems_flashdev_find_unallocated_partition(
+ rtems_libio_t *iop
);
static int rtems_flashdev_open(
@@ -189,18 +210,6 @@ static int rtems_flashdev_close(
rtems_libio_t *iop
);
-static ssize_t rtems_flashdev_read(
- rtems_libio_t *iop,
- void *buffer,
- size_t count
-);
-
-static ssize_t rtems_flashdev_write(
- rtems_libio_t *iop,
- const void *buffer,
- size_t count
-);
-
static int rtems_flashdev_ioctl(
rtems_libio_t *iop,
ioctl_command_t command,
@@ -217,6 +226,59 @@ static void rtems_flashdev_node_destroy(
IMFS_jnode_t *node
);
+static uint32_t rtems_flashdev_get_defined_partitions(
+ rtems_libio_t *iop
+);
+
+static bool rtems_flashdev_is_a_partition_active(
+ rtems_libio_t *iop
+);
+
+static bool rtems_flashdev_is_partition_defined(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+);
+
+static int rtems_flashdev_activate_partition(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+);
+
+static int rtems_flashdev_deactivate_partition(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+);
+
+static void rtems_flashdev_mark_partition_defined(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+);
+
+static void rtems_flashdev_mark_partition_undefined(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+);
+
+static bool rtems_flashdev_check_partition_overlap(
+ rtems_libio_t *iop,
+ rtems_flashdev_partition *partition_table,
+ rtems_flashdev_partition *region_in
+);
+
+static int rtems_flashdev_check_partition_offset(
+ rtems_flashdev *flash,
+ rtems_libio_t *iop,
+ off_t offset
+);
+
+static uint32_t rtems_flashdev_get_active_partition_index(
+ rtems_libio_t *iop
+);
+
+static void rtems_flashdev_obtain( rtems_flashdev *flash );
+
+static void rtems_flashdev_release( rtems_flashdev *flash );
+
static const rtems_filesystem_file_handlers_r rtems_flashdev_handler = {
.open_h = rtems_flashdev_open,
.close_h = rtems_flashdev_close,
@@ -234,97 +296,37 @@ static const rtems_filesystem_file_handlers_r rtems_flashdev_handler = {
.poll_h = rtems_filesystem_default_poll,
.readv_h = rtems_filesystem_default_readv,
.writev_h = rtems_filesystem_default_writev };
-/*
+
static const IMFS_node_control
rtems_flashdev_node_control = IMFS_GENERIC_INITIALIZER(
&rtems_flashdev_handler,
IMFS_node_initialize_generic,
rtems_flashdev_node_destroy
);
-*/
-static const IMFS_node_control rtems_flashdev_node_control = {
- .handlers = &rtems_flashdev_handler,
- .node_initialize = IMFS_node_initialize_generic,
- .node_remove = IMFS_node_remove_default,
- .node_destroy = rtems_flashdev_node_destroy
-};
-
-static void rtems_flashdev_node_destroy(
- IMFS_jnode_t *node
-)
-{
- rtems_flashdev *flash;
- flash = IMFS_generic_get_context_by_node( node );
-
- ( *flash->destroy )( flash );
-
- IMFS_node_destroy_default( node );
-}
-
-static uint32_t rtems_flashdev_get_region_index(
- rtems_libio_t *iop
-)
-{
- return (uint32_t)iop->data0;
-}
-
-static int rtems_flashdev_is_region_defined(
- rtems_libio_t *iop
-)
-{
- return (rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED);
-}
-
-static void rtems_flashdev_set_region_index(
- rtems_libio_t *iop,
- uint32_t index
-)
-{
- iop->data0 = index;
-}
-
-static int rtems_flashdev_check_offset_region(
+static int rtems_flashdev_do_init(
rtems_flashdev *flash,
- rtems_libio_t *iop,
- off_t offset
+ void ( *destroy )( rtems_flashdev *flash )
)
{
- if ( ( rtems_flashdev_is_region_defined( iop ) ) &&
- ( offset > rtems_flashdev_get_region_size( flash, iop ) ) ) {
- rtems_set_errno_and_return_minus_one( EINVAL );
- }
+ char mtx_name[19];
+ sprintf(mtx_name, "FDEV_MTX_%08x", (unsigned int) flash);
+ rtems_recursive_mutex_init( &flash->mutex, (const char*) &mtx_name);
+ flash->destroy = destroy;
+ flash->read = NULL;
+ flash->write = NULL;
+ flash->erase = NULL;
+ flash->get_jedec_id = NULL;
+ flash->get_flash_type = NULL;
+ flash->get_page_info_by_offset = NULL;
+ flash->get_page_info_by_index = NULL;
+ flash->get_page_count = NULL;
+ flash->get_min_write_size = NULL;
+ flash->get_erase_size = NULL;
+ flash->partition_table = NULL;
return 0;
}
-static void rtems_flashdev_obtain( rtems_flashdev *flash )
-{
- rtems_recursive_mutex_lock( &flash->mutex );
-}
-
-static void rtems_flashdev_release( rtems_flashdev *flash )
-{
- rtems_recursive_mutex_unlock( &flash->mutex );
-}
-
-static ssize_t rtems_flashdev_read(
- rtems_libio_t *iop,
- void *buffer,
- size_t count
-)
-{
- return rtems_flashdev_read_write( iop, NULL, buffer, count );
-}
-
-static ssize_t rtems_flashdev_write(
- rtems_libio_t *iop,
- const void *buffer,
- size_t count
-)
-{
- return rtems_flashdev_read_write( iop, buffer, NULL, count);
-}
-
static int rtems_flashdev_read_write(
rtems_libio_t *iop,
const void *write_buff,
@@ -337,7 +339,7 @@ static int rtems_flashdev_read_write(
int status;
if ( read_buff == NULL && write_buff == NULL ) {
- return EINVAL;
+ rtems_set_errno_and_return_minus_one( EINVAL );
}
/* Get flash address */
@@ -382,6 +384,183 @@ static int rtems_flashdev_read_write(
return rtems_flashdev_update_and_return( iop, status, count );
}
+static ssize_t rtems_flashdev_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ size_t count
+)
+{
+ return rtems_flashdev_read_write( iop, NULL, buffer, count );
+}
+
+static ssize_t rtems_flashdev_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ size_t count
+)
+{
+ return rtems_flashdev_read_write( iop, buffer, NULL, count);
+}
+
+static off_t rtems_flashdev_get_partition_offset(
+ rtems_flashdev *flash,
+ rtems_libio_t *iop
+)
+{
+ /* Region is already checked to be defined */
+ assert( rtems_flashdev_get_active_partition_index( iop ) != RTEMS_FLASHDEV_PARTITION_UNDEFINED );
+ rtems_flashdev_partition *table = flash->partition_table;
+ return table[ rtems_flashdev_get_active_partition_index( iop ) ].offset;
+}
+
+static size_t rtems_flashdev_get_partition_size(
+ rtems_flashdev *flash,
+ rtems_libio_t *iop
+)
+{
+ /* Region is already checked to be defined */
+ assert( rtems_flashdev_get_active_partition_index( iop ) != RTEMS_FLASHDEV_PARTITION_UNDEFINED );
+ rtems_flashdev_partition *table = flash->partition_table;
+ return table[ rtems_flashdev_get_active_partition_index( iop ) ].size;
+}
+
+static int rtems_flashdev_get_addr(
+ rtems_flashdev *flash,
+ rtems_libio_t *iop,
+ size_t count,
+ off_t *addr
+)
+{
+ off_t new_offset;
+
+ /* Check address is in valid partition */
+ new_offset = iop->offset + count;
+
+ if (rtems_flashdev_check_partition_offset(flash, iop, new_offset)) {
+ return -1;
+ }
+
+ /* Get address for operation */
+ if ( !rtems_flashdev_is_a_partition_active( iop ) ) {
+ *addr = iop->offset;
+ } else {
+ *addr = ( iop->offset + rtems_flashdev_get_partition_offset( flash, iop ) );
+ }
+ return 0;
+}
+
+static int rtems_flashdev_get_abs_addr(
+ rtems_flashdev *flash,
+ rtems_libio_t *iop,
+ size_t count,
+ off_t *addr
+)
+{
+ off_t new_offset;
+
+ /* Check address is in valid partition */
+ new_offset = *addr + count;
+
+ if (rtems_flashdev_check_partition_offset(flash, iop, new_offset)) {
+ return -1;
+ }
+
+ /* Get address for operation */
+ if ( rtems_flashdev_is_a_partition_active( iop ) ) {
+ *addr = ( *addr + rtems_flashdev_get_partition_offset( flash, iop ) );
+ }
+ return 0;
+}
+
+static int rtems_flashdev_update_and_return(
+ rtems_libio_t *iop,
+ int status,
+ size_t count
+)
+{
+ /* Update offset and return */
+ if ( status == 0 ) {
+ iop->offset += count;
+ return count;
+ } else {
+ rtems_set_errno_and_return_minus_one( status );
+ }
+}
+
+static int rtems_flashdev_create_partition(
+ rtems_libio_t *iop,
+ rtems_flashdev_partition *partition_table,
+ uint32_t partition_idx,
+ rtems_flashdev_partition *partition_in
+)
+{
+ int i = 0x0000FFFF & partition_idx;
+
+ /* Set partitions values */
+ partition_table[ i ].offset = partition_in->offset;
+ partition_table[ i ].size = partition_in->size;
+
+ rtems_flashdev_mark_partition_defined( iop, i );
+
+ return i;
+}
+
+static int rtems_flashdev_check_partition_valid(
+ rtems_flashdev *flash,
+ rtems_flashdev_partition * region
+)
+{
+ size_t erase_size = 0;
+ int status = (flash)->get_erase_size(flash, &erase_size);
+
+ if (0 != status)
+ {
+ return status;
+ }
+ if (region->offset % erase_size || region->size % erase_size)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static uint32_t rtems_flashdev_find_unallocated_partition(
+ rtems_libio_t *iop
+)
+{
+ uint16_t defined_partitions = rtems_flashdev_get_defined_partitions(iop);
+
+ for (uint32_t idx = 0; idx < RTEMS_FLASHDEV_MAX_PARTITIONS; ++idx)
+ {
+ if (!(defined_partitions & ( 1 << idx )))
+ {
+ return idx;
+ }
+ }
+
+ return RTEMS_FLASHDEV_PARTITION_ALLOC_FULL;
+}
+
+static int rtems_flashdev_open(
+ rtems_libio_t *iop,
+ const char *path,
+ int oflag,
+ mode_t mode
+)
+{
+ int ret = rtems_filesystem_default_open( iop, path, oflag, mode );
+ rtems_flashdev_mark_partition_defined(iop, RTEMS_FLASHDEV_PARTITION_UNDEFINED);
+ return ret;
+}
+
+static int rtems_flashdev_close(
+ rtems_libio_t *iop
+)
+{
+ return rtems_filesystem_default_close( iop );
+}
+
static int rtems_flashdev_ioctl(
rtems_libio_t *iop,
ioctl_command_t command,
@@ -409,20 +588,28 @@ static int rtems_flashdev_ioctl(
case RTEMS_FLASHDEV_IOCTL_ERASE:
err = rtems_flashdev_ioctl_erase( flash, iop, arg );
break;
- case RTEMS_FLASHDEV_IOCTL_SET_REGION:
- err = rtems_flashdev_ioctl_set_region( flash, iop, arg );
+ case RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION:
+ err = rtems_flashdev_ioctl_create_partition( flash, iop, arg );
+ break;
+ case RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION:
+ err = rtems_flashdev_ioctl_delete_partition( flash, iop, arg );
+ break;
+ case RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION:
+ err = rtems_flashdev_ioctl_resize_partition( flash, iop, arg );
+ case RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION:
+ err = rtems_flashdev_ioctl_activate_partition( flash, iop, arg );
break;
- case RTEMS_FLASHDEV_IOCTL_UNSET_REGION:
- err = rtems_flashdev_ioctl_clear_region( flash, iop );
+ case RTEMS_FLASHDEV_IOCTL_DEACTIVATE_PARTITION:
+ err = rtems_flashdev_ioctl_deactivate_partition( flash, iop, arg );
break;
case RTEMS_FLASHDEV_IOCTL_GET_TYPE:
err = rtems_flashdev_ioctl_get_flash_type( flash, arg );
break;
case RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_OFFSET:
- err = rtems_flashdev_ioctl_get_pageinfo_offset( flash, arg );
+ err = rtems_flashdev_ioctl_get_pageinfo_by_offset( flash, arg );
break;
case RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_INDEX:
- err = rtems_flashdev_ioctl_get_pageinfo_index( flash, arg );
+ err = rtems_flashdev_ioctl_get_pageinfo_by_index( flash, arg );
break;
case RTEMS_FLASHDEV_IOCTL_GET_PAGE_COUNT:
err = rtems_flashdev_ioctl_get_page_count( flash, arg );
@@ -434,15 +621,15 @@ static int rtems_flashdev_ioctl(
err = rtems_flashdev_ioctl_get_erase_size( flash, arg );
break;
default:
- err = EINVAL;
+ err = -EINVAL;
}
rtems_flashdev_release( flash );
- if ( err != 0 ) {
+ if ( err < 0 ) {
rtems_set_errno_and_return_minus_one( err );
- } else {
- return 0;
}
+
+ return err;
}
static off_t rtems_flashdev_lseek(
@@ -470,8 +657,8 @@ static off_t rtems_flashdev_lseek(
rtems_set_errno_and_return_minus_one( EINVAL );
}
- if ( ( rtems_flashdev_is_region_defined(iop) ) &&
- ( tmp_offset > rtems_flashdev_get_region_size( flash, iop ) ) ) {
+ if ( ( rtems_flashdev_is_a_partition_active(iop) ) &&
+ ( tmp_offset > rtems_flashdev_get_partition_size( flash, iop ) ) ) {
rtems_set_errno_and_return_minus_one( EINVAL );
}
@@ -479,192 +666,248 @@ static off_t rtems_flashdev_lseek(
return iop->offset;
}
-static int rtems_flashdev_close(
- rtems_libio_t *iop
+static void rtems_flashdev_node_destroy(
+ IMFS_jnode_t *node
)
{
- rtems_flashdev *flash = IMFS_generic_get_context_by_iop( iop );
- rtems_flashdev_ioctl_clear_region( flash, iop );
- return rtems_filesystem_default_close( iop );
+ rtems_flashdev *flash;
+
+ flash = IMFS_generic_get_context_by_node( node );
+
+ ( *flash->destroy )( flash );
+
+ IMFS_node_destroy_default( node );
}
-static int rtems_flashdev_open(
- rtems_libio_t *iop,
- const char *path,
- int oflag,
- mode_t mode
+static uint32_t rtems_flashdev_get_defined_partitions(
+ rtems_libio_t *iop
)
{
- int ret = rtems_filesystem_default_open( iop, path, oflag, mode );
- rtems_flashdev_set_region_index(iop, RTEMS_FLASHDEV_REGION_UNDEFINED);
- return ret;
+ return 0x0000FFFF & ((uint32_t) iop->data0);
}
-int rtems_flashdev_register(
- rtems_flashdev *flash,
- const char *flash_path
+static bool rtems_flashdev_is_a_partition_active(
+ rtems_libio_t *iop
)
{
- int rv;
- rtems_flashdev_region_table *table = flash->region_table;
- int alloc_array_len;
+ return (rtems_flashdev_get_active_partition_index( iop )
+ != RTEMS_FLASHDEV_PARTITION_UNDEFINED);
+}
- rv = IMFS_make_generic_node(
- flash_path,
- S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
- &rtems_flashdev_node_control,
- flash
- );
+static bool rtems_flashdev_is_partition_defined(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+)
+{
+ uint32_t defined_partitions = rtems_flashdev_get_defined_partitions(iop);
+ return (defined_partitions & ( 1 << partition_idx ));
+}
- if ( rv != 0 ) {
- ( *flash->destroy )( flash );
- }
+static int rtems_flashdev_activate_partition(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+)
+{
+ if(!rtems_flashdev_is_partition_defined(iop, partition_idx)){return -1;}
+ iop->data0 = set_bit(iop->data0, partition_idx + RTEMS_FLASHDEV_MAX_PARTITIONS);
+ return 0;
+}
- alloc_array_len = RTEMS_FLASHDEV_BITALLOC_LENGTH(table) +
- ((RTEMS_FLASHDEV_BITALLOC_FINAL_BITS(table)) != 0);
+static int rtems_flashdev_deactivate_partition(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+)
+{
+ if(!rtems_flashdev_is_partition_defined(iop, partition_idx)){return -1;}
+ iop->data0 = clear_bit(iop->data0, partition_idx + RTEMS_FLASHDEV_MAX_PARTITIONS);
+ return 0;
+}
- memset(table->bit_allocator, 0, alloc_array_len);
+static void rtems_flashdev_mark_partition_defined(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+)
+{
+ iop->data0 = set_bit(iop->data0, partition_idx);
+}
- return rv;
+static void rtems_flashdev_mark_partition_undefined(
+ rtems_libio_t *iop,
+ uint32_t partition_idx
+)
+{
+ if (rtems_flashdev_is_a_partition_active( iop ))
+ {
+ if( partition_idx == rtems_flashdev_get_active_partition_index( iop ) )
+ {
+ rtems_flashdev_deactivate_partition(iop, partition_idx);
+ }
+ }
+ iop->data0 = clear_bit(iop->data0, partition_idx);
}
-int rtems_flashdev_deregister(
- const char *flash_path
+static bool rtems_flashdev_check_partition_overlap(
+ rtems_libio_t *iop,
+ rtems_flashdev_partition *partition_table,
+ rtems_flashdev_partition *partition_in
)
{
- rtems_filesystem_eval_path_context_t ctx;
- int eval_flags = RTEMS_FS_FOLLOW_LINK;
- const rtems_filesystem_location_info_t *currentloc =
- rtems_filesystem_eval_path_start( &ctx , flash_path, eval_flags );
+ off_t cp_start;
+ off_t cp_end;
+ off_t partition_in_start = partition_in->offset;
+ off_t partition_in_end = partition_in->offset + partition_in->size;
+ uint16_t defined_partitions = rtems_flashdev_get_defined_partitions(iop);
- return IMFS_rmnod(NULL, currentloc);
+ for (uint16_t idx = 0; idx < RTEMS_FLASHDEV_MAX_PARTITIONS; ++idx)
+ {
+ if (defined_partitions & ( 1 << idx ))
+ {
+ cp_start = partition_table[ idx ].offset;
+ cp_end = partition_table[ idx ].offset
+ + partition_table[ idx ].size;
+
+ if( (partition_in_start < cp_end) && (partition_in_end > cp_start) )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
}
-static int rtems_flashdev_do_init(
+static int rtems_flashdev_check_partition_offset(
rtems_flashdev *flash,
- void ( *destroy )( rtems_flashdev *flash )
+ rtems_libio_t *iop,
+ off_t offset
)
{
- char mtx_name[19];
- sprintf(mtx_name, "FDEV_MTX_%08x", (unsigned int) flash);
- rtems_recursive_mutex_init( &flash->mutex, (const char*) &mtx_name);
- flash->destroy = destroy;
- flash->read = NULL;
- flash->write = NULL;
- flash->erase = NULL;
- flash->get_jedec_id = NULL;
- flash->get_flash_type = NULL;
- flash->get_page_info_by_offset = NULL;
- flash->get_page_info_by_index = NULL;
- flash->get_page_count = NULL;
- flash->get_min_write_size = NULL;
- flash->get_erase_size = NULL;
- flash->region_table = NULL;
+ if ( ( rtems_flashdev_is_a_partition_active( iop ) ) &&
+ ( offset > rtems_flashdev_get_partition_size( flash, iop ) ) ) {
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
return 0;
}
-void rtems_flashdev_destroy( rtems_flashdev *flash )
+static uint32_t rtems_flashdev_get_active_partition_index(
+ rtems_libio_t *iop
+)
{
- rtems_recursive_mutex_destroy( &flash->mutex );
-}
+ uint32_t active = ((uint32_t)iop->data0) >> RTEMS_FLASHDEV_MAX_PARTITIONS;
-void rtems_flashdev_destroy_and_free( rtems_flashdev *flash )
-{
- if ( flash == NULL ) {
- return;
+ for (uint32_t idx = 0; idx < RTEMS_FLASHDEV_MAX_PARTITIONS; idx++)
+ {
+ if (active & ( 1 << idx ))
+ {
+ return 0x0000FFFF & idx;
+ }
}
- rtems_recursive_mutex_destroy( &( flash->mutex ) );
- free( flash );
- return;
+
+ return RTEMS_FLASHDEV_PARTITION_UNDEFINED;
}
-int rtems_flashdev_init( rtems_flashdev *flash )
+static void rtems_flashdev_obtain( rtems_flashdev *flash )
{
- memset( flash, 0, sizeof( *flash ) );
+ rtems_recursive_mutex_lock( &flash->mutex );
+}
- return rtems_flashdev_do_init( flash, rtems_flashdev_destroy );
+static void rtems_flashdev_release( rtems_flashdev *flash )
+{
+ rtems_recursive_mutex_unlock( &flash->mutex );
}
+/* API Implementation*/
rtems_flashdev *rtems_flashdev_alloc_and_init( size_t size )
{
rtems_flashdev *flash = NULL;
if ( size >= sizeof( *flash ) ) {
flash = calloc( 1, size );
- if ( flash != NULL ) {
+ if ( NULL != flash ) {
int rv;
-
+ rtems_flashdev_partition * table = calloc( RTEMS_FLASHDEV_MAX_PARTITIONS, sizeof(rtems_flashdev_partition));
rv = rtems_flashdev_do_init( flash, rtems_flashdev_destroy_and_free );
- if ( rv != 0 ) {
+ if ( (rv != 0) || (table == NULL) ) {
rtems_recursive_mutex_destroy( &flash->mutex );
free( flash );
+ if (NULL != table)
+ {
+ free( table );
+ }
return NULL;
}
+ flash->partition_table = table;
}
}
return flash;
}
-static int rtems_flashdev_get_addr(
+int rtems_flashdev_init( rtems_flashdev *flash )
+{
+ memset( flash, 0, sizeof( *flash ) );
+ return rtems_flashdev_do_init( flash, rtems_flashdev_destroy );
+}
+
+int rtems_flashdev_register(
rtems_flashdev *flash,
- rtems_libio_t *iop,
- size_t count,
- off_t *addr
+ const char *flash_path
)
{
- off_t new_offset;
+ int rv;
- /* Check address is in valid region */
- new_offset = iop->offset + count;
+ rv = IMFS_make_generic_node(
+ flash_path,
+ S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
+ &rtems_flashdev_node_control,
+ flash
+ );
- if (rtems_flashdev_check_offset_region(flash, iop, new_offset)) {
- return -1;
+ if ( rv != 0 ) {
+ ( *flash->destroy )( flash );
}
- /* Get address for operation */
- if ( !rtems_flashdev_is_region_defined( iop ) ) {
- *addr = iop->offset;
- } else {
- *addr = ( iop->offset + rtems_flashdev_get_region_offset( flash, iop ) );
- }
- return 0;
+ return rv;
}
-static int rtems_flashdev_get_abs_addr(
- rtems_flashdev *flash,
- rtems_libio_t *iop,
- size_t count,
- off_t *addr
+int rtems_flashdev_deregister(
+ const char *flash_path
)
{
- off_t new_offset;
+ rtems_filesystem_eval_path_context_t ctx;
+ int eval_flags = RTEMS_FS_FOLLOW_LINK;
+ const rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_start( &ctx , flash_path, eval_flags );
- /* Check address is in valid region */
- new_offset = *addr + count;
+ return IMFS_rmnod(NULL, currentloc);
+}
- if (rtems_flashdev_check_offset_region(flash, iop, new_offset)) {
- return -1;
+void rtems_flashdev_destroy( rtems_flashdev *flash )
+{
+ rtems_recursive_mutex_destroy( &flash->mutex );
+}
+
+void rtems_flashdev_destroy_and_free( rtems_flashdev *flash )
+{
+ if ( NULL == flash ) {
+ return;
}
- /* Get address for operation */
- if ( rtems_flashdev_is_region_defined( iop ) ) {
- *addr = ( *addr + rtems_flashdev_get_region_offset( flash, iop ) );
+ if (NULL != flash->partition_table )
+ {
+ free( flash->partition_table );
}
- return 0;
+
+ rtems_recursive_mutex_destroy( &( flash->mutex ) );
+ free( flash );
+ return;
}
-static int rtems_flashdev_update_and_return(
- rtems_libio_t *iop,
- int status,
- size_t count
-)
+
+static uint32_t rtems_flashdev_ioctl_get_jedec_id( rtems_flashdev *flash )
{
- /* Update offset and return */
- if ( status == 0 ) {
- iop->offset += count;
- return count;
+ if ( flash->get_jedec_id == NULL ) {
+ return 0;
} else {
- rtems_set_errno_and_return_minus_one( status );
+ return ( *flash->get_jedec_id )( flash );
}
}
@@ -674,7 +917,7 @@ static int rtems_flashdev_ioctl_erase(
void *arg
)
{
- rtems_flashdev_region *erase_args_1;
+ rtems_flashdev_partition *erase_args_1;
off_t new_offset;
int status;
@@ -682,9 +925,9 @@ static int rtems_flashdev_ioctl_erase(
return 0;
}
- erase_args_1 = (rtems_flashdev_region *) arg;
- /* Check erasing valid region */
- if ( 0 != rtems_flashdev_check_region_valid(flash, erase_args_1))
+ erase_args_1 = (rtems_flashdev_partition *) arg;
+ /* Check erasing valid partition */
+ if ( 0 != rtems_flashdev_check_partition_valid(flash, erase_args_1))
{
return EINVAL;
}
@@ -700,149 +943,122 @@ static int rtems_flashdev_ioctl_erase(
return status;
}
-static int rtems_flashdev_ioctl_set_region(
+
+static int rtems_flashdev_ioctl_create_partition(
rtems_flashdev *flash,
rtems_libio_t *iop,
void *arg
)
{
- rtems_flashdev_region *region_in;
- rtems_flashdev_region_table *table = flash->region_table;
- region_in = (rtems_flashdev_region *) arg;
+ rtems_flashdev_partition *partition_in;
+ rtems_flashdev_partition *table = flash->partition_table;
+ partition_in = (rtems_flashdev_partition *) arg;
+ uint32_t partition_idx = 0;
- if (flash->region_table == NULL) {
+ if (table == NULL) {
rtems_set_errno_and_return_minus_one( ENOMEM );
}
- if ( 0 != rtems_flashdev_check_region_valid(flash, region_in))
+ if ( 0 != rtems_flashdev_check_partition_valid(flash, partition_in))
{
- return EINVAL;
+ rtems_set_errno_and_return_minus_one( EINVAL );
}
- if ( !rtems_flashdev_is_region_defined( iop ) ) {
- if (
- rtems_flashdev_find_unallocated_region(table)
- == RTEMS_FLASHDEV_REGION_ALLOC_FULL
- )
- {
- /* New region to allocate and all regions allocated */
- rtems_set_errno_and_return_minus_one( ENOMEM );
- } else {
- /* New region to allocate and space to allocate region */
- return rtems_flashdev_ioctl_create_region( flash, iop, region_in );
- }
- } else {
- /* Updating existing region */
- return rtems_flashdev_ioctl_update_region( flash, iop, region_in );
+ if (rtems_flashdev_check_partition_overlap(iop, table, partition_in)) {
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+ partition_idx = rtems_flashdev_find_unallocated_partition(iop);
+
+ if (RTEMS_FLASHDEV_PARTITION_ALLOC_FULL == partition_idx)
+ {
+ /* New partition to allocate and all partitions allocated */
+ rtems_set_errno_and_return_minus_one( ENOMEM );
}
+ /* New partition to allocate and space to allocate partition */
+ return rtems_flashdev_create_partition( iop, table, partition_idx, partition_in );
}
-static int rtems_flashdev_ioctl_create_region(
+static int rtems_flashdev_ioctl_delete_partition(
rtems_flashdev *flash,
rtems_libio_t *iop,
- rtems_flashdev_region *region_in
+ void *arg
)
{
- int i;
- rtems_flashdev_region_table *table = flash->region_table;
+ uint32_t *partition_idx = (uint32_t*) arg;
- /* Find unallocated region slot */
- i = rtems_flashdev_find_unallocated_region(flash->region_table);
- if (i == RTEMS_FLASHDEV_REGION_ALLOC_FULL) {
+ if (flash->partition_table == NULL) {
rtems_set_errno_and_return_minus_one( ENOMEM );
}
- /* Set region values */
- table->regions[ i ].offset = region_in->offset;
- table->regions[ i ].size = region_in->size;
-
- /* Set region as allocated and link iop */
- rtems_flashdev_set_region(flash->region_table, i);
- rtems_flashdev_set_region_index( iop, i );
-
- return 0;
-}
-
-static int rtems_flashdev_ioctl_update_region(
- rtems_flashdev *flash,
- rtems_libio_t *iop,
- rtems_flashdev_region *region_in
-)
-{
- uint32_t region_index = rtems_flashdev_get_region_index( iop );
- rtems_flashdev_region_table *table = flash->region_table;
-
- /**
- * If region index is larger then maximum region index or region
- * index at given index is undefined return an error.
- */
- if (
- ( region_index >= flash->region_table->max_regions ) ||
- ( rtems_flashdev_check_allocation( table, region_index ) == 0)
- )
- {
+ /* Check partition to clear */
+ if ( *partition_idx >= RTEMS_FLASHDEV_MAX_PARTITIONS ) {
rtems_set_errno_and_return_minus_one( EINVAL );
}
- /* Set region values */
- table->regions[ region_index ].offset = region_in->offset;
- table->regions[ region_index ].size = region_in->size;
-
+ /* Clear partition */
+ rtems_flashdev_mark_partition_undefined( iop, *partition_idx );
return 0;
}
-static int rtems_flashdev_ioctl_clear_region(
+static int rtems_flashdev_ioctl_resize_partition(
rtems_flashdev *flash,
- rtems_libio_t *iop
+ rtems_libio_t *iop,
+ void *arg
)
{
- uint32_t region_index = rtems_flashdev_get_region_index( iop );
+ rtems_flashdev_partition storage;
- if (flash->region_table == NULL) {
- rtems_set_errno_and_return_minus_one( ENOMEM );
+ uint32_t partition_idx = 0;
+ int ret = -1;
+ if ( !rtems_flashdev_is_a_partition_active( iop ) ) {
+ return -1;
}
- /* Check region to clear */
- if ( region_index == RTEMS_FLASHDEV_REGION_UNDEFINED ) {
- rtems_set_errno_and_return_minus_one( EINVAL );
+ partition_idx = rtems_flashdev_get_active_partition_index( iop );
+ storage = flash->partition_table[ partition_idx ];
+
+ if ( 0 == rtems_flashdev_ioctl_delete_partition( flash, iop, &partition_idx ))
+ {
+ ret = rtems_flashdev_ioctl_create_partition( flash, iop, arg);
+
+ if (ret >= 0)
+ {
+ rtems_flashdev_activate_partition(iop, (uint32_t) ret);
+ return ret;
+ }
+ else
+ {
+ ret = rtems_flashdev_create_partition( iop, flash->partition_table, partition_idx, &storage);
+ if (ret >= 0)
+ {
+ rtems_flashdev_activate_partition(iop, partition_idx);
+ return -1;
+ }
+ }
}
- /* Clear region */
- rtems_flashdev_unset_region( flash->region_table, region_index );
- rtems_flashdev_set_region_index( iop, RTEMS_FLASHDEV_REGION_UNDEFINED );
- return 0;
+ return -1;
}
-static off_t rtems_flashdev_get_region_offset(
+static int rtems_flashdev_ioctl_activate_partition(
rtems_flashdev *flash,
- rtems_libio_t *iop
+ rtems_libio_t *iop,
+ void *arg
)
{
- /* Region is already checked to be defined */
- assert( rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED );
- rtems_flashdev_region_table *table = flash->region_table;
- return table->regions[ rtems_flashdev_get_region_index( iop ) ].offset;
+ uint32_t *partition_idx = (uint32_t*) arg;
+ return rtems_flashdev_activate_partition(iop, *partition_idx);
}
-static size_t rtems_flashdev_get_region_size(
+static int rtems_flashdev_ioctl_deactivate_partition(
rtems_flashdev *flash,
- rtems_libio_t *iop
+ rtems_libio_t *iop,
+ void *arg
)
{
- /* Region is already checked to be defined */
- assert( rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED );
- rtems_flashdev_region_table *table = flash->region_table;
- return table->regions[ rtems_flashdev_get_region_index( iop ) ].size;
-}
-
-static uint32_t rtems_flashdev_ioctl_get_jedec_id( rtems_flashdev *flash )
-{
- if ( flash->get_jedec_id == NULL ) {
- return 0;
- } else {
- return ( *flash->get_jedec_id )( flash );
- }
+ uint32_t *partition_idx = (uint32_t*) arg;
+ return rtems_flashdev_deactivate_partition(iop, *partition_idx);
}
static uint32_t rtems_flashdev_ioctl_get_flash_type(
@@ -858,7 +1074,7 @@ static uint32_t rtems_flashdev_ioctl_get_flash_type(
}
}
-static int rtems_flashdev_ioctl_get_pageinfo_offset(
+static int rtems_flashdev_ioctl_get_pageinfo_by_offset(
rtems_flashdev *flash,
void *arg
)
@@ -879,7 +1095,7 @@ static int rtems_flashdev_ioctl_get_pageinfo_offset(
}
}
-static int rtems_flashdev_ioctl_get_pageinfo_index( rtems_flashdev *flash,
+static int rtems_flashdev_ioctl_get_pageinfo_by_index( rtems_flashdev *flash,
void *arg )
{
rtems_flashdev_ioctl_page_info *page_info;
@@ -938,95 +1154,4 @@ static int rtems_flashdev_ioctl_get_erase_size(
} else {
return ( *flash->get_erase_size )( flash, ( (size_t *) arg ) );
}
-}
-
-static int rtems_flashdev_check_region_valid(
- rtems_flashdev *flash,
- rtems_flashdev_region * region
-)
-{
- size_t erase_size = 0;
- int status = (flash)->get_erase_size(flash, &erase_size);
-
- if (0 != status)
- {
- return status;
- }
- if (region->offset % erase_size || region->size % erase_size)
- {
- return -1;
- }
-
- return 0;
-}
-
-static uint32_t rtems_flashdev_find_unallocated_region(
- rtems_flashdev_region_table *region_table
-)
-{
- int array_index = 0;
- int bit_index = 0;
- int shift;
-
- while ( bit_index < region_table->max_regions) {
- /* Get uint32_t holding the ith bit */
- array_index = bit_index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
- shift = bit_index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
- /* Check if region available in next BITALLOC_LENGTH regions */
- if (
- (shift == 0) &&
- (region_table->bit_allocator[ array_index ] == RTEMS_FLASHDEV_REGION_ALLOC_FULL)
- )
- {
- bit_index = bit_index + RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
- continue;
- }
-
- /* Check individual bit */
- if ( ! ( ( ( region_table->bit_allocator[ array_index ] ) >> shift ) & 1UL ) ) {
- return bit_index;
- }
-
- bit_index++;
- }
-
- return RTEMS_FLASHDEV_REGION_ALLOC_FULL;
-}
-
-static uint32_t rtems_flashdev_set_region(
- rtems_flashdev_region_table *region_table,
- int index
-)
-{
- int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
- int shift = index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
- region_table->bit_allocator[ array_index ] |= 1UL << shift;
-
- return index;
-}
-
-static uint32_t rtems_flashdev_unset_region(
- rtems_flashdev_region_table *region_table,
- int index
-)
-{
- int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
- int shift = index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
- region_table->bit_allocator[ array_index ] &= ~( 1UL << shift );
-
- return index;
-}
-
-static uint32_t rtems_flashdev_check_allocation(
- rtems_flashdev_region_table *region_table,
- int index
-)
-{
- int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
- int shift = index%RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
-
- return ( ( region_table->bit_allocator[ array_index ] >> shift ) & 1UL );
-}
+}
\ No newline at end of file
diff --git a/cpukit/include/dev/flash/flashdev.h b/cpukit/include/dev/flash/flashdev.h
index 0b54fcc71e..91a189ff6f 100644
--- a/cpukit/include/dev/flash/flashdev.h
+++ b/cpukit/include/dev/flash/flashdev.h
@@ -57,105 +57,135 @@ typedef struct rtems_flashdev rtems_flashdev;
*/
/* IOCTL Calls */
+typedef enum {
+ /**
+ * @brief Obtains the flash device.
+ *
+ * This command has no argument.
+ */
+ RTEMS_FLASHDEV_IOCTL_OBTAIN = 0,
-/**
- * @brief Obtains the flash device.
- *
- * This command has no argument.
- */
-#define RTEMS_FLASHDEV_IOCTL_OBTAIN 0
-/**
- * @brief Releases the flash device.
- *
- * This command has no argument.
- */
-#define RTEMS_FLASHDEV_IOCTL_RELEASE 1
-/**
- * @brief Returns the JEDEC ID of the flash device. This IOCTL call
- * is informational only.
- *
- * @param[out] jedec_id Pointer to uint32_t in which the JEDEC ID is
- * returned in.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_JEDEC_ID 2
-/**
- * @brief Erases flash device.
- *
- * @param[in] erase_args Pointer to rtems_flashdev_region struct
- * containing offset and size of erase to be performed.
- */
-#define RTEMS_FLASHDEV_IOCTL_ERASE 3
-/**
- * @brief Set a region that limits read, write and erase calls to within it.
- * Regions are file descriptor specific and limited to a single region per
- * file descriptor and 32 regions total per flash device. Regions can be
- * changed or updated by calling this IOCTL again.
- *
- * @param[in] region Pointer to rtems_flashdev_region struct containing
- * base and length of defined region.
- */
-#define RTEMS_FLASHDEV_IOCTL_SET_REGION 4
-/**
- * @brief Removes the set region on the file descriptor.
- *
- * This command has no argument.
- */
-#define RTEMS_FLASHDEV_IOCTL_UNSET_REGION 5
-/**
- * @brief Returns the type of flash device (e.g. NOR or NAND).
- *
- * @param[out] flash_type Pointer to integer which is set to the flash
- * type macro value.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_TYPE 6
+ /**
+ * @brief Releases the flash device.
+ *
+ * This command has no argument.
+ */
+ RTEMS_FLASHDEV_IOCTL_RELEASE,
-/**
- * @brief Get the size and address of flash page at given offset
- *
- * The offset ignores the region limiting. To find page of region
- * limited offset add the base of the region to the desired offset.
- *
- * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
- * with offset and space for return values.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_OFFSET 7
+ /**
+ * @brief Returns the JEDEC ID of the flash device. This IOCTL call
+ * is informational only.
+ *
+ * @param[out] jedec_id Pointer to uint32_t in which the JEDEC ID is
+ * returned in.
+ */
+ RTEMS_FLASHDEV_IOCTL_GET_JEDEC_ID,
-/**
- * @brief Get the size and address of nth flash page where n is index passed in.
- *
- * The index ignores the region limiting.
- *
- * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
- * with index and space for return values.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_INDEX 8
+ /**
+ * @brief Erases flash device.
+ *
+ * @param[in] erase_args Pointer to rtems_flashdev_partition struct
+ * containing offset and size of erase to be performed.
+ */
+ RTEMS_FLASHDEV_IOCTL_ERASE,
-/**
- * @brief Get the number of pages in flash device.
- *
- * @param[out] count Integer containing the number of pages.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_PAGE_COUNT 9
+ /**
+ * @brief Create a partition that limits read, write and erase calls to
+ * within it. Partitions are file descriptor specific and limited to a
+ * single partition per file descriptor and 32 partitions total per
+ * flash device.
+ *
+ * @param[in] partition Pointer to rtems_flashdev_partition struct containing
+ * base and length of defined partition.
+ *
+ * @return partition_idx Integer containing the partition index or error
+ */
+ RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION,
-/**
- * @brief Get the minimum write size supported by the driver.
- *
- * @param[out] count Integer containing the minimum write size.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_MIN_WRITE_SIZE 10
+ /**
+ * @brief Delete a partition
+ *
+ * @param[in] partition_idx Integer containing the partition index
+ *
+ */
+ RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION,
-/**
- * @brief Get the erase size supported by the driver.
- *
- * @param[out] count Integer containing the erase size.
- */
-#define RTEMS_FLASHDEV_IOCTL_GET_ERASE_SIZE 11
+ /**
+ * @brief Resize active partition
+ *
+ * @param[in] partition Pointer to rtems_flashdev_partition struct containing
+ * base and length of defined partition.
+ *
+ */
+ RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION,
-/**
- * @brief The maximum number of region limited file descriptors
- * allowed to be open at once.
- */
-#define RTEMS_FLASHDEV_MAX_REGIONS 32
+ /**
+ * @brief Activate a partition
+ *
+ * @param[in] partition_idx Integer containing the partition index
+ *
+ */
+ RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION,
+
+ /**
+ * @brief Deactivate a partition
+ *
+ * @param[in] partition_idx Integer containing the partition index
+ *
+ */
+ RTEMS_FLASHDEV_IOCTL_DEACTIVATE_PARTITION,
+
+ /**
+ * @brief Returns the type of flash device (e.g. NOR or NAND).
+ *
+ * @param[out] flash_type Pointer to integer which is set to the flash
+ * type macro value.
+ */
+ RTEMS_FLASHDEV_IOCTL_GET_TYPE,
+
+ /**
+ * @brief Get the size and address of flash page at given offset
+ *
+ * The offset ignores the region limiting. To find page of region
+ * limited offset add the base of the region to the desired offset.
+ *
+ * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
+ * with offset and space for return values.
+ */
+ RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_OFFSET,
+
+ /**
+ * @brief Get the size and address of nth flash page where n is index passed in.
+ *
+ * The index ignores the region limiting.
+ *
+ * @param[in,out] rtems_flashdev_ioctl_page_info arg Pointer to struct
+ * with index and space for return values.
+ */
+ RTEMS_FLASHDEV_IOCTL_GET_PAGEINFO_BY_INDEX,
+
+ /**
+ * @brief Get the number of pages in flash device.
+ *
+ * @param[out] count Integer containing the number of pages.
+ */
+ RTEMS_FLASHDEV_IOCTL_GET_PAGE_COUNT,
+
+ /**
+ * @brief Get the minimum write size supported by the driver.
+ *
+ * @param[out] count Integer containing the minimum write size.
+ */
+ RTEMS_FLASHDEV_IOCTL_GET_MIN_WRITE_SIZE,
+
+ /**
+ * @brief Get the erase size supported by the driver.
+ *
+ * @param[out] count Integer containing the erase size.
+ */
+ RTEMS_FLASHDEV_IOCTL_GET_ERASE_SIZE
+
+} rtems_flashdev_ioctl_token;
/**
* @brief Enum for flash type returned from IOCTL call.
@@ -174,38 +204,16 @@ typedef enum rtems_flashdev_flash_type {
/**
* @brief General definition for on flash device.
*/
-typedef struct rtems_flashdev_region {
+typedef struct rtems_flashdev_partition {
/**
- * @brief Base of region.
+ * @brief Base of partition.
*/
off_t offset;
/**
- * @brief Length of region.
+ * @brief Length of partition.
*/
size_t size;
-} rtems_flashdev_region;
-
-/**
- * @brief Struct holding region definitions
- */
-typedef struct rtems_flashdev_region_table {
- /**
- * @brief The maximum regions that can be defined at once.
- */
- int max_regions;
-
- /**
- * @brief Pointer to array of rtems_flashdev_region of length
- * max_regions
- */
- rtems_flashdev_region* regions;
-
- /**
- * @brief Array of uint32_t acting as bit allocator
- * for regions array.
- */
- uint32_t *bit_allocator;
-} rtems_flashdev_region_table;
+} rtems_flashdev_partition;
/**
* @brief Page information returned from IOCTL calls.
@@ -220,7 +228,7 @@ typedef struct rtems_flashdev_ioctl_page_info {
* @brief Information returned about the page. Including the
* base offset and size of page.
*/
- rtems_flashdev_region page_info;
+ rtems_flashdev_partition page_info;
} rtems_flashdev_ioctl_page_info;
/**
@@ -405,9 +413,9 @@ struct rtems_flashdev {
rtems_recursive_mutex mutex;
/**
- * @brief Region table defining size and memory for region allocations
+ * @brief Partition table
*/
- rtems_flashdev_region_table *region_table;
+ rtems_flashdev_partition *partition_table;
};
/**
diff --git a/cpukit/libmisc/shell/main_flashdev.c b/cpukit/libmisc/shell/main_flashdev.c
index e070642cca..2b703a88ec 100644
--- a/cpukit/libmisc/shell/main_flashdev.c
+++ b/cpukit/libmisc/shell/main_flashdev.c
@@ -337,7 +337,7 @@ int flashdev_shell_erase(
uint32_t bytes;
int fd;
int status;
- rtems_flashdev_region args;
+ rtems_flashdev_partition args;
/* Check arguments */
if (argc < 5) {
diff --git a/testsuites/libtests/flashdev01/init.c b/testsuites/libtests/flashdev01/init.c
index 118367a62f..a6f7251496 100644
--- a/testsuites/libtests/flashdev01/init.c
+++ b/testsuites/libtests/flashdev01/init.c
@@ -55,9 +55,9 @@ static void run_test(void) {
int status;
char* read_data;
size_t bytes_read;
- rtems_flashdev_region e_args;
+ rtems_flashdev_partition e_args;
rtems_flashdev_ioctl_page_info pg_info;
- rtems_flashdev_region region;
+ rtems_flashdev_partition partition;
uint32_t jedec;
int page_count;
int type;
@@ -133,7 +133,6 @@ static void run_test(void) {
status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ERASE, &e_args);
rtems_test_assert(!status);
-
fseek(file, 0x0, SEEK_SET);
fgets(buff, TEST_DATA_SIZE, file);
rtems_test_assert(buff[0] == 0);
@@ -215,53 +214,107 @@ static void run_test(void) {
rtems_test_assert(bytes_read == TEST_DATA_SIZE);
memset(buff,0x00,TEST_DATA_SIZE);
- /* Test Regions - this one must fail */
- region.offset = ERASE_SIZE;
- region.size = 0x200;
- status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_SET_REGION, ®ion);
+ /* Test Partitions - this one must fail */
+ partition.offset = ERASE_SIZE;
+ partition.size = 0x200;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
+ rtems_test_assert(status);
+
+ /* Test Partitions - this one must fail*/
+ partition.offset = 0x200;
+ partition.size = ERASE_SIZE;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
rtems_test_assert(status);
- /* Test Regions - this one must fail*/
- region.offset = 0x200;
- region.size = ERASE_SIZE;
- status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_SET_REGION, ®ion);
+ /* Test Partitions - create partition 0*/
+ partition.offset = 0;
+ partition.size = ERASE_SIZE;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
+ rtems_test_assert(status == 0);
+
+ /* Activate Partition 0*/
+ status = 0;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION, &status);
+ rtems_test_assert(!status);
+
+ /* Try to resize partition 0 above limit*/
+ partition.offset = 1;
+ partition.size = ERASE_SIZE;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION, &partition);
rtems_test_assert(status);
- /* Test Regions */
- region.offset = ERASE_SIZE;
- region.size = ERASE_SIZE;
- status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_SET_REGION, ®ion);
+ /* Try to resize partition 0 within limit*/
+ partition.offset = 0;
+ partition.size = 2*ERASE_SIZE;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION, &partition);
+ rtems_test_assert(status == 0);
+
+ /* Try to resize partition 0 to original size*/
+ partition.size = ERASE_SIZE;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_RESIZE_PARTITION, &partition);
+ rtems_test_assert(status == 0);
+
+ /* Deactivate Partition 0*/
+ status = 0;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_DEACTIVATE_PARTITION, &status);
rtems_test_assert(!status);
- /* Test Erasing*/
+ /* Test Partitions - ioctl returns partition idx*/
+ partition.offset = ERASE_SIZE;
+ partition.size = ERASE_SIZE;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_CREATE_PARTITION, &partition);
+ rtems_test_assert(status == 1);
+
+ /* Activate Partition - wrong partion idx*/
+ status = 3;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION, &status);
+ rtems_test_assert(status);
+
+ /* Activate Partition - ioctl returns partition idx*/
+ status = 1;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ACTIVATE_PARTITION, &status);
+ rtems_test_assert(!status);
+
+ /* Test Erasing - ioctl returns partition idx*/
e_args.offset = 0x0;
e_args.size = ERASE_SIZE;
status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_ERASE, &e_args);
rtems_test_assert(!status);
- /* Test read within then region */
+ /* Test read within then partition */
status = fseek(file, 0x0, SEEK_SET);
rtems_test_assert(!status);
bytes_read = fread(buff, 1, 0x200, file);
rtems_test_assert(bytes_read == 0x200);
- /* Test read to larger then region */
+ /* Test read to larger then partition */
fseek(file, 0x0, SEEK_SET);
rtems_test_assert(!status);
read_data = fgets(buff, 2048, file);
rtems_test_assert(buff[0] == 0);
- /* Test fseek outside of region */
+ /* Test fseek outside of partition */
fseek(file, 0x0, SEEK_SET);
rtems_test_assert(!status);
status = fseek(file, ERASE_SIZE+1, SEEK_SET);
rtems_test_assert(status);
- /* Write to base unset region and check the writes location */
+ /* Write to base unset partition and check the writes location */
fseek(file, 0x0, SEEK_SET);
fwrite("HELLO WORLD!!!!!", 1, 16, file);
- ioctl(fd, RTEMS_FLASHDEV_IOCTL_UNSET_REGION, NULL);
- /* Test read within then region */
+
+ /* delete partition 0 */
+ status = 0;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION, &status);
+ rtems_test_assert(!status);
+
+ /* delete partition 1 */
+ status = 1;
+ status = ioctl(fd, RTEMS_FLASHDEV_IOCTL_DELETE_PARTITION, &status);
+ rtems_test_assert(!status);
+
+
+ /* Test read within then partition */
status = fseek(file, 0x0, SEEK_SET);
rtems_test_assert(!status);
bytes_read = fread(buff, 1, 0x200, file);
diff --git a/testsuites/libtests/flashdev01/test_flashdev.c b/testsuites/libtests/flashdev01/test_flashdev.c
index 9b8d1dbba5..012e1ed152 100644
--- a/testsuites/libtests/flashdev01/test_flashdev.c
+++ b/testsuites/libtests/flashdev01/test_flashdev.c
@@ -33,9 +33,7 @@
#define TEST_DATA_SIZE (PAGE_SIZE * PAGE_COUNT)
#define PAGE_COUNT 16
#define PAGE_SIZE 128
-#define MAX_NUM_REGIONS 48
-#define BITALLOC_SIZE 32
-#define NUM_BITALLOC ((MAX_NUM_REGIONS + BITALLOC_SIZE - 1) / BITALLOC_SIZE)
+#define MAX_NUM_PARTITIONS 16
static size_t g_min_write_size = 0;
static size_t g_erase_size = 0;
@@ -47,8 +45,6 @@ static size_t g_erase_size = 0;
typedef struct test_flashdev {
char* data;
uint32_t jedec_id;
- uint32_t bit_allocator[NUM_BITALLOC];
- rtems_flashdev_region regions[MAX_NUM_REGIONS];
} test_flashdev;
int test_flashdev_get_page_by_off(
@@ -287,11 +283,6 @@ rtems_flashdev* test_flashdev_init(size_t min_write_size, size_t erase_size)
flash_driver->jedec_id = 0x00ABCDEF;
- rtems_flashdev_region_table *ftable = calloc(1, sizeof(rtems_flashdev_region_table));
- ftable->max_regions = MAX_NUM_REGIONS;
- ftable->regions = flash_driver->regions;
- ftable->bit_allocator = flash_driver->bit_allocator;
-
flash->driver = flash_driver;
flash->read = &test_flashdev_read;
flash->write = &test_flashdev_write;
@@ -303,7 +294,6 @@ rtems_flashdev* test_flashdev_init(size_t min_write_size, size_t erase_size)
flash->get_page_count = &test_flashdev_get_page_count;
flash->get_min_write_size = &test_flashdev_get_min_write_size;
flash->get_erase_size = &test_flashdev_get_erase_size;
- flash->region_table = ftable;
return flash;
}
@@ -315,10 +305,6 @@ void test_flashdev_deinit(
{
if (NULL != flash)
{
- if (NULL != flash->driver)
- {
- free(flash->region_table);
- }
if (NULL != flash->driver)
{
test_flashdev* flash_driver = (test_flashdev*) flash->driver;
--
2.34.1
More information about the devel
mailing list