From: Bernd Moessner <berndmoessne...@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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel