File indexing completed on 2025-05-11 08:24:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #ifdef HAVE_CONFIG_H
0027 #include "config.h"
0028 #endif
0029
0030 #include <dev/flash/flashdev.h>
0031
0032 #include <rtems/imfs.h>
0033 #include <rtems/score/assert.h>
0034
0035 #include <errno.h>
0036 #include <fcntl.h>
0037 #include <stdlib.h>
0038 #include <string.h>
0039 #include <unistd.h>
0040 #include <assert.h>
0041
0042 #define RTEMS_FLASHDEV_REGION_ALLOC_FULL 0xFFFFFFFFUL
0043 #define RTEMS_FLASHDEV_REGION_UNDEFINED 0xFFFFFFFFUL
0044 #define RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH 32
0045
0046 #define RTEMS_FLASHDEV_BITALLOC_LENGTH(t) \
0047 (t->max_regions/RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH)
0048 #define RTEMS_FLASHDEV_BITALLOC_FINAL_BITS(t) \
0049 (t->max_regions%RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH)
0050
0051 static int rtems_flashdev_do_init(
0052 rtems_flashdev *flash,
0053 void ( *destroy )( rtems_flashdev *flash )
0054 );
0055
0056 static int rtems_flashdev_read_write(
0057 rtems_libio_t *iop,
0058 const void *write_buff,
0059 void *read_buff,
0060 size_t count
0061 );
0062
0063 static int rtems_flashdev_ioctl_erase(
0064 rtems_flashdev *flash,
0065 rtems_libio_t *iop,
0066 void *arg
0067 );
0068
0069 static off_t rtems_flashdev_get_region_offset(
0070 rtems_flashdev *flash,
0071 rtems_libio_t *iop
0072 );
0073
0074 static size_t rtems_flashdev_get_region_size(
0075 rtems_flashdev *flash,
0076 rtems_libio_t *iop
0077 );
0078
0079 static int rtems_flashdev_ioctl_set_region(
0080 rtems_flashdev *flash,
0081 rtems_libio_t *iop,
0082 void *arg
0083 );
0084
0085 static int rtems_flashdev_ioctl_create_region(
0086 rtems_flashdev *flash,
0087 rtems_libio_t *iop,
0088 rtems_flashdev_region *region_in
0089 );
0090
0091 static int rtems_flashdev_ioctl_update_region(
0092 rtems_flashdev *flash,
0093 rtems_libio_t *iop,
0094 rtems_flashdev_region *region_in
0095 );
0096
0097 static int rtems_flashdev_ioctl_clear_region(
0098 rtems_flashdev *flash,
0099 rtems_libio_t *iop
0100 );
0101
0102 static uint32_t rtems_flashdev_ioctl_jedec_id(
0103 rtems_flashdev *flash
0104 );
0105
0106 static uint32_t rtems_flashdev_ioctl_flash_type(
0107 rtems_flashdev *flash,
0108 void *arg
0109 );
0110
0111 static int rtems_flashdev_ioctl_pageinfo_offset(
0112 rtems_flashdev *flash,
0113 void *arg
0114 );
0115
0116 static int rtems_flashdev_ioctl_pageinfo_index(
0117 rtems_flashdev *flash,
0118 void *arg
0119 );
0120
0121 static int rtems_flashdev_ioctl_page_count(
0122 rtems_flashdev *flash,
0123 void *arg
0124 );
0125
0126 static int rtems_flashdev_ioctl_sectorinfo_offset(
0127 rtems_flashdev *flash,
0128 void *arg
0129 );
0130
0131 static int rtems_flashdev_ioctl_sector_count(
0132 rtems_flashdev *flash,
0133 void *arg
0134 );
0135
0136 static int rtems_flashdev_ioctl_write_block_size(
0137 rtems_flashdev *flash,
0138 void *arg
0139 );
0140
0141 static int rtems_flashdev_get_addr(
0142 rtems_flashdev *flash,
0143 rtems_libio_t *iop,
0144 size_t count,
0145 off_t *addr
0146 );
0147
0148 static int rtems_flashdev_get_abs_addr(
0149 rtems_flashdev *flash,
0150 rtems_libio_t *iop,
0151 size_t count,
0152 off_t *addr
0153 );
0154
0155 static int rtems_flashdev_update_and_return(
0156 rtems_libio_t *iop,
0157 int status,
0158 size_t count,
0159 off_t new_offset
0160 );
0161
0162 static uint32_t rtems_flashdev_find_unallocated_region(
0163 rtems_flashdev_region_table *region_table
0164 );
0165
0166 static uint32_t rtems_flashdev_set_region(
0167 rtems_flashdev_region_table *region_table,
0168 int index
0169 );
0170
0171 static uint32_t rtems_flashdev_unset_region(
0172 rtems_flashdev_region_table *region_table,
0173 int index
0174 );
0175
0176 static uint32_t rtems_flashdev_check_allocation(
0177 rtems_flashdev_region_table *region_table,
0178 int index
0179 );
0180
0181 static int rtems_flashdev_open(
0182 rtems_libio_t *iop,
0183 const char *path,
0184 int oflag,
0185 mode_t mode
0186 );
0187
0188 static int rtems_flashdev_close(
0189 rtems_libio_t *iop
0190 );
0191
0192 static ssize_t rtems_flashdev_read(
0193 rtems_libio_t *iop,
0194 void *buffer,
0195 size_t count
0196 );
0197
0198 static ssize_t rtems_flashdev_write(
0199 rtems_libio_t *iop,
0200 const void *buffer,
0201 size_t count
0202 );
0203
0204 static int rtems_flashdev_ioctl(
0205 rtems_libio_t *iop,
0206 ioctl_command_t command,
0207 void *arg
0208 );
0209
0210 static off_t rtems_flashdev_lseek(
0211 rtems_libio_t *iop,
0212 off_t offset,
0213 int whence
0214 );
0215
0216 static void rtems_flashdev_node_destroy(
0217 IMFS_jnode_t *node
0218 );
0219
0220 static const rtems_filesystem_file_handlers_r rtems_flashdev_handler = {
0221 .open_h = rtems_flashdev_open,
0222 .close_h = rtems_flashdev_close,
0223 .read_h = rtems_flashdev_read,
0224 .write_h = rtems_flashdev_write,
0225 .ioctl_h = rtems_flashdev_ioctl,
0226 .lseek_h = rtems_flashdev_lseek,
0227 .fstat_h = IMFS_stat,
0228 .ftruncate_h = rtems_filesystem_default_ftruncate,
0229 .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
0230 .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
0231 .fcntl_h = rtems_filesystem_default_fcntl,
0232 .kqfilter_h = rtems_filesystem_default_kqfilter,
0233 .mmap_h = rtems_filesystem_default_mmap,
0234 .poll_h = rtems_filesystem_default_poll,
0235 .readv_h = rtems_filesystem_default_readv,
0236 .writev_h = rtems_filesystem_default_writev };
0237
0238 static const IMFS_node_control
0239 rtems_flashdev_node_control = IMFS_GENERIC_INITIALIZER(
0240 &rtems_flashdev_handler,
0241 IMFS_node_initialize_generic,
0242 rtems_flashdev_node_destroy
0243 );
0244
0245 static void rtems_flashdev_node_destroy(
0246 IMFS_jnode_t *node
0247 )
0248 {
0249 rtems_flashdev *flash;
0250
0251 flash = IMFS_generic_get_context_by_node( node );
0252
0253 ( *flash->destroy )( flash );
0254
0255 IMFS_node_destroy_default( node );
0256 }
0257
0258 static uint32_t rtems_flashdev_get_region_index(
0259 rtems_libio_t *iop
0260 )
0261 {
0262 return (uint32_t)iop->data0;
0263 }
0264
0265 static int rtems_flashdev_is_region_defined(
0266 rtems_libio_t *iop
0267 )
0268 {
0269 return (rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED);
0270 }
0271
0272 static void rtems_flashdev_set_region_index(
0273 rtems_libio_t *iop,
0274 uint32_t index
0275 )
0276 {
0277 iop->data0 = index;
0278 }
0279
0280 static int rtems_flashdev_check_offset_region(
0281 rtems_flashdev *flash,
0282 rtems_libio_t *iop,
0283 off_t offset
0284 )
0285 {
0286 if ( ( rtems_flashdev_is_region_defined( iop ) ) &&
0287 ( offset > rtems_flashdev_get_region_size( flash, iop ) ) ) {
0288 rtems_set_errno_and_return_minus_one( EINVAL );
0289 }
0290 return 0;
0291 }
0292
0293 static void rtems_flashdev_obtain( rtems_flashdev *flash )
0294 {
0295 rtems_recursive_mutex_lock( &flash->mutex );
0296 }
0297
0298 static void rtems_flashdev_release( rtems_flashdev *flash )
0299 {
0300 rtems_recursive_mutex_unlock( &flash->mutex );
0301 }
0302
0303 static ssize_t rtems_flashdev_read(
0304 rtems_libio_t *iop,
0305 void *buffer,
0306 size_t count
0307 )
0308 {
0309 return rtems_flashdev_read_write( iop, NULL, buffer, count );
0310 }
0311
0312 static ssize_t rtems_flashdev_write(
0313 rtems_libio_t *iop,
0314 const void *buffer,
0315 size_t count
0316 )
0317 {
0318 return rtems_flashdev_read_write( iop, buffer, NULL, count);
0319 }
0320
0321 static int rtems_flashdev_read_write(
0322 rtems_libio_t *iop,
0323 const void *write_buff,
0324 void *read_buff,
0325 size_t count
0326 )
0327 {
0328 rtems_flashdev *flash = IMFS_generic_get_context_by_iop( iop );
0329 off_t addr;
0330 int status;
0331
0332 if ( read_buff == NULL && write_buff == NULL ) {
0333 rtems_set_errno_and_return_minus_one( EINVAL );
0334 }
0335
0336
0337 status = rtems_flashdev_get_addr( flash, iop, count, &addr );
0338 if ( status < 0 ) {
0339 return status;
0340 }
0341
0342
0343 rtems_flashdev_obtain( flash );
0344 if ( read_buff != NULL ) {
0345 status = ( *flash->read )( flash, addr, count, read_buff );
0346 } else if ( write_buff != NULL ) {
0347 status = ( *flash->write )( flash, addr, count, write_buff );
0348 }
0349 rtems_flashdev_release( flash );
0350
0351
0352 return rtems_flashdev_update_and_return( iop, status, count, addr + count );
0353 }
0354
0355 static int rtems_flashdev_ioctl(
0356 rtems_libio_t *iop,
0357 ioctl_command_t command,
0358 void *arg
0359 )
0360 {
0361 rtems_flashdev *flash = IMFS_generic_get_context_by_iop( iop );
0362 int err = 0;
0363
0364 rtems_flashdev_obtain( flash );
0365
0366 switch ( command ) {
0367 case RTEMS_FLASHDEV_IOCTL_OBTAIN:
0368 rtems_flashdev_obtain( flash );
0369 err = 0;
0370 break;
0371 case RTEMS_FLASHDEV_IOCTL_RELEASE:
0372 rtems_flashdev_release( flash );
0373 err = 0;
0374 break;
0375 case RTEMS_FLASHDEV_IOCTL_JEDEC_ID:
0376 *( (uint32_t *) arg ) = rtems_flashdev_ioctl_jedec_id( flash );
0377 err = 0;
0378 break;
0379 case RTEMS_FLASHDEV_IOCTL_ERASE:
0380 err = rtems_flashdev_ioctl_erase( flash, iop, arg );
0381 break;
0382 case RTEMS_FLASHDEV_IOCTL_REGION_SET:
0383 err = rtems_flashdev_ioctl_set_region( flash, iop, arg );
0384 break;
0385 case RTEMS_FLASHDEV_IOCTL_REGION_UNSET:
0386 err = rtems_flashdev_ioctl_clear_region( flash, iop );
0387 break;
0388 case RTEMS_FLASHDEV_IOCTL_TYPE:
0389 err = rtems_flashdev_ioctl_flash_type( flash, arg );
0390 break;
0391 case RTEMS_FLASHDEV_IOCTL_PAGEINFO_BY_OFFSET:
0392 err = rtems_flashdev_ioctl_pageinfo_offset( flash, arg );
0393 break;
0394 case RTEMS_FLASHDEV_IOCTL_PAGEINFO_BY_INDEX:
0395 err = rtems_flashdev_ioctl_pageinfo_index( flash, arg );
0396 break;
0397 case RTEMS_FLASHDEV_IOCTL_PAGE_COUNT:
0398 err = rtems_flashdev_ioctl_page_count( flash, arg );
0399 break;
0400 case RTEMS_FLASHDEV_IOCTL_SECTORINFO_BY_OFFSET:
0401 err = rtems_flashdev_ioctl_sectorinfo_offset( flash, arg );
0402 break;
0403 case RTEMS_FLASHDEV_IOCTL_SECTOR_COUNT:
0404 err = rtems_flashdev_ioctl_sector_count( flash, arg );
0405 break;
0406 case RTEMS_FLASHDEV_IOCTL_WRITE_BLOCK_SIZE:
0407 err = rtems_flashdev_ioctl_write_block_size( flash, arg );
0408 break;
0409 default:
0410 err = EINVAL;
0411 }
0412
0413 rtems_flashdev_release( flash );
0414 if ( err != 0 ) {
0415 rtems_set_errno_and_return_minus_one( err );
0416 } else {
0417 return 0;
0418 }
0419 }
0420
0421 static off_t rtems_flashdev_lseek(
0422 rtems_libio_t *iop,
0423 off_t offset,
0424 int whence
0425 )
0426 {
0427 off_t tmp_offset;
0428 rtems_flashdev *flash = IMFS_generic_get_context_by_iop( iop );
0429
0430 if ( offset < 0 ) {
0431 rtems_set_errno_and_return_minus_one( EINVAL );
0432 }
0433
0434 switch ( whence ) {
0435 case SEEK_CUR:
0436 tmp_offset = iop->offset + offset;
0437 break;
0438 case SEEK_SET:
0439 tmp_offset = offset;
0440 break;
0441 case SEEK_END:
0442 default:
0443 rtems_set_errno_and_return_minus_one( EINVAL );
0444 }
0445
0446 if ( ( rtems_flashdev_is_region_defined(iop) ) &&
0447 ( tmp_offset > rtems_flashdev_get_region_size( flash, iop ) ) ) {
0448 rtems_set_errno_and_return_minus_one( EINVAL );
0449 }
0450
0451 iop->offset = tmp_offset;
0452 return iop->offset;
0453 }
0454
0455 static int rtems_flashdev_close(
0456 rtems_libio_t *iop
0457 )
0458 {
0459 rtems_flashdev *flash = IMFS_generic_get_context_by_iop( iop );
0460 rtems_flashdev_ioctl_clear_region( flash, iop );
0461 return rtems_filesystem_default_close( iop );
0462 }
0463
0464 static int rtems_flashdev_open(
0465 rtems_libio_t *iop,
0466 const char *path,
0467 int oflag,
0468 mode_t mode
0469 )
0470 {
0471 int ret = rtems_filesystem_default_open( iop, path, oflag, mode );
0472 rtems_flashdev_set_region_index(iop, RTEMS_FLASHDEV_REGION_UNDEFINED);
0473 return ret;
0474 }
0475
0476 int rtems_flashdev_register(
0477 rtems_flashdev *flash,
0478 const char *flash_path
0479 )
0480 {
0481 int rv;
0482 rtems_flashdev_region_table *table = flash->region_table;
0483 int alloc_array_len;
0484
0485 rv = IMFS_make_generic_node(
0486 flash_path,
0487 S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0488 &rtems_flashdev_node_control,
0489 flash
0490 );
0491
0492 if ( rv != 0 ) {
0493 ( *flash->destroy )( flash );
0494 }
0495
0496 alloc_array_len = RTEMS_FLASHDEV_BITALLOC_LENGTH(table) +
0497 ((RTEMS_FLASHDEV_BITALLOC_FINAL_BITS(table)) != 0);
0498
0499 memset(table->bit_allocator, 0, alloc_array_len);
0500
0501 return rv;
0502 }
0503
0504 static int rtems_flashdev_do_init(
0505 rtems_flashdev *flash,
0506 void ( *destroy )( rtems_flashdev *flash )
0507 )
0508 {
0509 rtems_recursive_mutex_init( &flash->mutex, "RTEMS_FLASHDEV Flash" );
0510 flash->destroy = destroy;
0511 flash->read = NULL;
0512 flash->write = NULL;
0513 flash->erase = NULL;
0514 flash->jedec_id = NULL;
0515 flash->flash_type = NULL;
0516 flash->page_info_by_offset = NULL;
0517 flash->page_info_by_index = NULL;
0518 flash->page_count = NULL;
0519 flash->write_block_size = NULL;
0520 flash->region_table = NULL;
0521 return 0;
0522 }
0523
0524 void rtems_flashdev_destroy( rtems_flashdev *flash )
0525 {
0526 rtems_recursive_mutex_destroy( &flash->mutex );
0527 }
0528
0529 void rtems_flashdev_destroy_and_free( rtems_flashdev *flash )
0530 {
0531 if ( flash == NULL ) {
0532 return;
0533 }
0534 rtems_recursive_mutex_destroy( &( flash->mutex ) );
0535 free( flash );
0536 flash = NULL;
0537 return;
0538 }
0539
0540 int rtems_flashdev_init( rtems_flashdev *flash )
0541 {
0542 memset( flash, 0, sizeof( *flash ) );
0543
0544 return rtems_flashdev_do_init( flash, rtems_flashdev_destroy );
0545 }
0546
0547 rtems_flashdev *rtems_flashdev_alloc_and_init( size_t size )
0548 {
0549 rtems_flashdev *flash = NULL;
0550
0551 if ( size >= sizeof( *flash ) ) {
0552 flash = calloc( 1, size );
0553 if ( flash != NULL ) {
0554 int rv;
0555
0556 rv = rtems_flashdev_do_init( flash, rtems_flashdev_destroy_and_free );
0557 if ( rv != 0 ) {
0558 rtems_recursive_mutex_destroy( &flash->mutex );
0559 free( flash );
0560 return NULL;
0561 }
0562 }
0563 }
0564
0565 return flash;
0566 }
0567
0568 static int rtems_flashdev_get_addr(
0569 rtems_flashdev *flash,
0570 rtems_libio_t *iop,
0571 size_t count,
0572 off_t *addr
0573 )
0574 {
0575 off_t new_offset;
0576
0577
0578 new_offset = iop->offset + count;
0579
0580 if (rtems_flashdev_check_offset_region(flash, iop, new_offset)) {
0581 return -1;
0582 }
0583
0584
0585 if ( !rtems_flashdev_is_region_defined( iop ) ) {
0586 *addr = iop->offset;
0587 } else {
0588 *addr = ( iop->offset + rtems_flashdev_get_region_offset( flash, iop ) );
0589 }
0590 return 0;
0591 }
0592
0593 static int rtems_flashdev_get_abs_addr(
0594 rtems_flashdev *flash,
0595 rtems_libio_t *iop,
0596 size_t count,
0597 off_t *addr
0598 )
0599 {
0600 off_t new_offset;
0601
0602
0603 new_offset = *addr + count;
0604
0605 if (rtems_flashdev_check_offset_region(flash, iop, new_offset)) {
0606 return -1;
0607 }
0608
0609
0610 if ( rtems_flashdev_is_region_defined( iop ) ) {
0611 *addr = ( *addr + rtems_flashdev_get_region_offset( flash, iop ) );
0612 }
0613 return 0;
0614 }
0615 static int rtems_flashdev_update_and_return(
0616 rtems_libio_t *iop,
0617 int status,
0618 size_t count,
0619 off_t new_offset
0620 )
0621 {
0622
0623 if ( status == 0 ) {
0624 iop->offset = new_offset;
0625 return count;
0626 } else {
0627 rtems_set_errno_and_return_minus_one( status );
0628 }
0629 }
0630
0631 static int rtems_flashdev_ioctl_erase(
0632 rtems_flashdev *flash,
0633 rtems_libio_t *iop,
0634 void *arg
0635 )
0636 {
0637 rtems_flashdev_region *erase_args_1;
0638 off_t new_offset;
0639 int status;
0640
0641 if ( flash->erase == NULL ) {
0642 return 0;
0643 }
0644
0645 erase_args_1 = (rtems_flashdev_region *) arg;
0646
0647 new_offset = erase_args_1->offset;
0648 status = rtems_flashdev_get_abs_addr(flash, iop, erase_args_1->size, &new_offset);
0649 if ( status < 0 ) {
0650 return status;
0651 }
0652
0653
0654 status = ( *flash->erase )( flash, new_offset, erase_args_1->size );
0655 return status;
0656 }
0657
0658 static int rtems_flashdev_ioctl_set_region(
0659 rtems_flashdev *flash,
0660 rtems_libio_t *iop,
0661 void *arg
0662 )
0663 {
0664 rtems_flashdev_region *region_in;
0665 rtems_flashdev_region_table *table = flash->region_table;
0666 region_in = (rtems_flashdev_region *) arg;
0667
0668 if (flash->region_table == NULL) {
0669 rtems_set_errno_and_return_minus_one( ENOMEM );
0670 }
0671
0672 if ( !rtems_flashdev_is_region_defined( iop ) ) {
0673 if (
0674 rtems_flashdev_find_unallocated_region(table)
0675 == RTEMS_FLASHDEV_REGION_ALLOC_FULL
0676 )
0677 {
0678
0679 rtems_set_errno_and_return_minus_one( ENOMEM );
0680 } else {
0681
0682 return rtems_flashdev_ioctl_create_region( flash, iop, region_in );
0683 }
0684 } else {
0685
0686 return rtems_flashdev_ioctl_update_region( flash, iop, region_in );
0687 }
0688
0689 }
0690
0691 static int rtems_flashdev_ioctl_create_region(
0692 rtems_flashdev *flash,
0693 rtems_libio_t *iop,
0694 rtems_flashdev_region *region_in
0695 )
0696 {
0697 int i;
0698 rtems_flashdev_region_table *table = flash->region_table;
0699
0700
0701 i = rtems_flashdev_find_unallocated_region(flash->region_table);
0702 if (i == RTEMS_FLASHDEV_REGION_ALLOC_FULL) {
0703 rtems_set_errno_and_return_minus_one( ENOMEM );
0704 }
0705
0706
0707 table->regions[ i ].offset = region_in->offset;
0708 table->regions[ i ].size = region_in->size;
0709
0710
0711 rtems_flashdev_set_region(flash->region_table, i);
0712 rtems_flashdev_set_region_index( iop, i );
0713
0714 return 0;
0715 }
0716
0717 static int rtems_flashdev_ioctl_update_region(
0718 rtems_flashdev *flash,
0719 rtems_libio_t *iop,
0720 rtems_flashdev_region *region_in
0721 )
0722 {
0723 uint32_t region_index = rtems_flashdev_get_region_index( iop );
0724 rtems_flashdev_region_table *table = flash->region_table;
0725
0726
0727
0728
0729
0730 if (
0731 ( region_index >= flash->region_table->max_regions ) ||
0732 ( rtems_flashdev_check_allocation( table, region_index ) == 0)
0733 )
0734 {
0735 rtems_set_errno_and_return_minus_one( EINVAL );
0736 }
0737
0738
0739 table->regions[ region_index ].offset = region_in->offset;
0740 table->regions[ region_index ].size = region_in->size;
0741
0742 return 0;
0743 }
0744
0745 static int rtems_flashdev_ioctl_clear_region(
0746 rtems_flashdev *flash,
0747 rtems_libio_t *iop
0748 )
0749 {
0750 uint32_t region_index = rtems_flashdev_get_region_index( iop );
0751
0752 if (flash->region_table == NULL) {
0753 rtems_set_errno_and_return_minus_one( ENOMEM );
0754 }
0755
0756
0757 if ( region_index == RTEMS_FLASHDEV_REGION_UNDEFINED ) {
0758 rtems_set_errno_and_return_minus_one( EINVAL );
0759 }
0760
0761
0762 rtems_flashdev_unset_region( flash->region_table, region_index );
0763 rtems_flashdev_set_region_index( iop, RTEMS_FLASHDEV_REGION_UNDEFINED );
0764 return 0;
0765 }
0766
0767 static off_t rtems_flashdev_get_region_offset(
0768 rtems_flashdev *flash,
0769 rtems_libio_t *iop
0770 )
0771 {
0772
0773 assert( rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED );
0774 rtems_flashdev_region_table *table = flash->region_table;
0775 return table->regions[ rtems_flashdev_get_region_index( iop ) ].offset;
0776 }
0777
0778 static size_t rtems_flashdev_get_region_size(
0779 rtems_flashdev *flash,
0780 rtems_libio_t *iop
0781 )
0782 {
0783
0784 assert( rtems_flashdev_get_region_index( iop ) != RTEMS_FLASHDEV_REGION_UNDEFINED );
0785 rtems_flashdev_region_table *table = flash->region_table;
0786 return table->regions[ rtems_flashdev_get_region_index( iop ) ].size;
0787 }
0788
0789 static uint32_t rtems_flashdev_ioctl_jedec_id( rtems_flashdev *flash )
0790 {
0791 if ( flash->jedec_id == NULL ) {
0792 return 0;
0793 } else {
0794 return ( *flash->jedec_id )( flash );
0795 }
0796 }
0797
0798 static uint32_t rtems_flashdev_ioctl_flash_type(
0799 rtems_flashdev *flash,
0800 void *arg
0801 )
0802 {
0803 rtems_flashdev_flash_type *type = (rtems_flashdev_flash_type*)arg;
0804 if ( flash->flash_type == NULL ) {
0805 return 0;
0806 } else {
0807 return ( *flash->flash_type )( flash, type );
0808 }
0809 }
0810
0811 static int rtems_flashdev_ioctl_pageinfo_offset(
0812 rtems_flashdev *flash,
0813 void *arg
0814 )
0815 {
0816 rtems_flashdev_ioctl_page_info *page_info;
0817
0818 if ( arg == NULL ) {
0819 rtems_set_errno_and_return_minus_one( EINVAL );
0820 }
0821 if ( flash->page_info_by_offset == NULL ) {
0822 return 0;
0823 } else {
0824 page_info = (rtems_flashdev_ioctl_page_info *) arg;
0825 return ( *flash->page_info_by_offset )( flash,
0826 page_info->location,
0827 &page_info->page_info.offset,
0828 &page_info->page_info.size );
0829 }
0830 }
0831
0832 static int rtems_flashdev_ioctl_pageinfo_index( rtems_flashdev *flash,
0833 void *arg )
0834 {
0835 rtems_flashdev_ioctl_page_info *page_info;
0836
0837 if ( arg == NULL ) {
0838 rtems_set_errno_and_return_minus_one( EINVAL );
0839 }
0840 if ( flash->page_info_by_index == NULL ) {
0841 return 0;
0842 } else {
0843 page_info = (rtems_flashdev_ioctl_page_info *) arg;
0844 return ( *flash->page_info_by_index )( flash,
0845 page_info->location,
0846 &page_info->page_info.offset,
0847 &page_info->page_info.size );
0848 }
0849 }
0850
0851 static int rtems_flashdev_ioctl_page_count( rtems_flashdev *flash, void *arg )
0852 {
0853 if ( arg == NULL ) {
0854 rtems_set_errno_and_return_minus_one( EINVAL );
0855 }
0856 if ( flash->page_count == NULL ) {
0857 return 0;
0858 } else {
0859 return ( *flash->page_count )( flash, ( (int *) arg ) );
0860 }
0861 }
0862
0863 static int rtems_flashdev_ioctl_sectorinfo_offset(
0864 rtems_flashdev *flash,
0865 void *arg
0866 )
0867 {
0868 rtems_flashdev_ioctl_sector_info *sector_info;
0869
0870 if ( arg == NULL ) {
0871 rtems_set_errno_and_return_minus_one( EINVAL );
0872 }
0873 if ( flash->sector_info_by_offset == NULL ) {
0874 return 0;
0875 } else {
0876 sector_info = (rtems_flashdev_ioctl_sector_info *) arg;
0877 return ( *flash->sector_info_by_offset )( flash,
0878 sector_info->location,
0879 §or_info->sector_info.offset,
0880 §or_info->sector_info.size );
0881 }
0882 }
0883
0884 static int rtems_flashdev_ioctl_sector_count( rtems_flashdev *flash, void *arg )
0885 {
0886 if ( arg == NULL ) {
0887 rtems_set_errno_and_return_minus_one( EINVAL );
0888 }
0889 if ( flash->sector_count == NULL ) {
0890 return 0;
0891 } else {
0892 return ( *flash->sector_count )( flash, ( (int *) arg ) );
0893 }
0894 }
0895
0896 static int rtems_flashdev_ioctl_write_block_size(
0897 rtems_flashdev *flash,
0898 void *arg
0899 )
0900 {
0901 if ( arg == NULL ) {
0902 rtems_set_errno_and_return_minus_one( EINVAL );
0903 }
0904 if ( flash->write_block_size == NULL ) {
0905 return 0;
0906 } else {
0907 return ( *flash->write_block_size )( flash, ( (size_t *) arg ) );
0908 }
0909 }
0910
0911 static uint32_t rtems_flashdev_find_unallocated_region(
0912 rtems_flashdev_region_table *region_table
0913 )
0914 {
0915 int array_index = 0;
0916 int bit_index = 0;
0917 int shift;
0918
0919 while ( bit_index < region_table->max_regions) {
0920
0921 array_index = bit_index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0922 shift = bit_index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0923
0924
0925 if (
0926 (shift == 0) &&
0927 (region_table->bit_allocator[ array_index ] == RTEMS_FLASHDEV_REGION_ALLOC_FULL)
0928 )
0929 {
0930 bit_index = bit_index + RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0931 continue;
0932 }
0933
0934
0935 if ( ! ( ( ( region_table->bit_allocator[ array_index ] ) >> shift ) & 1UL ) ) {
0936 return bit_index;
0937 }
0938
0939 bit_index++;
0940 }
0941
0942 return RTEMS_FLASHDEV_REGION_ALLOC_FULL;
0943 }
0944
0945 static uint32_t rtems_flashdev_set_region(
0946 rtems_flashdev_region_table *region_table,
0947 int index
0948 )
0949 {
0950 int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0951 int shift = index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0952
0953 region_table->bit_allocator[ array_index ] |= 1UL << shift;
0954
0955 return index;
0956 }
0957
0958 static uint32_t rtems_flashdev_unset_region(
0959 rtems_flashdev_region_table *region_table,
0960 int index
0961 )
0962 {
0963 int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0964 int shift = index % RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0965
0966 region_table->bit_allocator[ array_index ] &= ~( 1UL << shift );
0967
0968 return index;
0969 }
0970
0971 static uint32_t rtems_flashdev_check_allocation(
0972 rtems_flashdev_region_table *region_table,
0973 int index
0974 )
0975 {
0976 int array_index = index / RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0977 int shift = index%RTEMS_FLASHDEV_REGION_BITALLOC_LENGTH;
0978
0979 return ( ( region_table->bit_allocator[ array_index ] >> shift ) & 1UL );
0980 }