diff options
Diffstat (limited to 'cpukit/libblock/src/bdbuf.c')
-rw-r--r-- | cpukit/libblock/src/bdbuf.c | 124 |
1 files changed, 73 insertions, 51 deletions
diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 5e135c44df..ad1112b517 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -822,22 +822,18 @@ rtems_bdbuf_set_state (rtems_bdbuf_buffer *bd, rtems_bdbuf_buf_state state) bd->state = state; } -/** - * Change the block number for the block size to the block number for the media - * block size. We have to use 64bit maths. There is no short cut here. - * - * @param block The logical block number in the block size terms. - * @param block_size The block size. - * @param media_block_size The block size of the media. - * @return rtems_blkdev_bnum The media block number. - */ static rtems_blkdev_bnum -rtems_bdbuf_media_block (rtems_blkdev_bnum block, - size_t block_size, - size_t media_block_size) +rtems_bdbuf_media_block (const rtems_disk_device *dd, rtems_blkdev_bnum block) { - return (rtems_blkdev_bnum) - ((((uint64_t) block) * block_size) / media_block_size); + if (dd->block_to_media_block_shift >= 0) + return block << dd->block_to_media_block_shift; + else + /* + * Change the block number for the block size to the block number for the media + * block size. We have to use 64bit maths. There is no short cut here. + */ + return (rtems_blkdev_bnum) + ((((uint64_t) block) * dd->block_size) / dd->media_block_size); } /** @@ -1743,40 +1739,22 @@ rtems_bdbuf_get_buffer_for_access (const rtems_disk_device *dd, } static rtems_status_code -rtems_bdbuf_obtain_disk (const rtems_disk_device *dd, - rtems_blkdev_bnum block, - rtems_blkdev_bnum *media_block_ptr, - size_t *bds_per_group_ptr) +rtems_bdbuf_get_media_block (const rtems_disk_device *dd, + rtems_blkdev_bnum block, + rtems_blkdev_bnum *media_block_ptr) { - if (media_block_ptr != NULL) + /* + * Compute the media block number. Drivers work with media block number not + * the block number a BD may have as this depends on the block size set by + * the user. + */ + rtems_blkdev_bnum mb = rtems_bdbuf_media_block (dd, block); + if (mb >= dd->size) { - /* - * Compute the media block number. Drivers work with media block number not - * the block number a BD may have as this depends on the block size set by - * the user. - */ - rtems_blkdev_bnum mb = rtems_bdbuf_media_block (block, - dd->block_size, - dd->media_block_size); - if (mb >= dd->size) - { - return RTEMS_INVALID_NUMBER; - } - - *media_block_ptr = mb + dd->start; + return RTEMS_INVALID_ID; } - if (bds_per_group_ptr != NULL) - { - size_t bds_per_group = rtems_bdbuf_bds_per_group (dd->block_size); - - if (bds_per_group == 0) - { - return RTEMS_INVALID_NUMBER; - } - - *bds_per_group_ptr = bds_per_group; - } + *media_block_ptr = mb + dd->start; return RTEMS_SUCCESSFUL; } @@ -1789,9 +1767,8 @@ rtems_bdbuf_get (const rtems_disk_device *dd, rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_bdbuf_buffer *bd = NULL; rtems_blkdev_bnum media_block = 0; - size_t bds_per_group = 0; - sc = rtems_bdbuf_obtain_disk (dd, block, &media_block, &bds_per_group); + sc = rtems_bdbuf_get_media_block (dd, block, &media_block); if (sc != RTEMS_SUCCESSFUL) return sc; @@ -1804,7 +1781,7 @@ rtems_bdbuf_get (const rtems_disk_device *dd, printf ("bdbuf:get: %" PRIu32 " (%" PRIu32 ") (dev = %08x)\n", media_block, block, (unsigned) dd->dev); - bd = rtems_bdbuf_get_buffer_for_access (dd, media_block, bds_per_group); + bd = rtems_bdbuf_get_buffer_for_access (dd, media_block, dd->bds_per_group); switch (bd->state) { @@ -1870,7 +1847,9 @@ rtems_bdbuf_create_read_request (const rtems_disk_device *dd, { rtems_bdbuf_buffer *bd = NULL; rtems_blkdev_bnum media_block_end = dd->start + dd->size; - rtems_blkdev_bnum media_block_count = dd->block_size / dd->media_block_size; + rtems_blkdev_bnum media_block_count = dd->block_to_media_block_shift >= 0 ? + dd->block_size >> dd->block_to_media_block_shift + : dd->block_size / dd->media_block_size; uint32_t block_size = dd->block_size; uint32_t transfer_index = 1; uint32_t transfer_count = bdbuf_config.max_read_ahead_blocks + 1; @@ -2007,9 +1986,8 @@ rtems_bdbuf_read (const rtems_disk_device *dd, rtems_blkdev_request *req = NULL; rtems_bdbuf_buffer *bd = NULL; rtems_blkdev_bnum media_block = 0; - size_t bds_per_group = 0; - sc = rtems_bdbuf_obtain_disk (dd, block, &media_block, &bds_per_group); + sc = rtems_bdbuf_get_media_block (dd, block, &media_block); if (sc != RTEMS_SUCCESSFUL) return sc; @@ -2027,7 +2005,7 @@ rtems_bdbuf_read (const rtems_disk_device *dd, media_block + dd->start, block, (unsigned) dd->dev); rtems_bdbuf_lock_cache (); - rtems_bdbuf_create_read_request (dd, media_block, bds_per_group, req, &bd); + rtems_bdbuf_create_read_request (dd, media_block, dd->bds_per_group, req, &bd); if (req->bufnum > 0) { @@ -2902,3 +2880,47 @@ rtems_bdbuf_purge_dev (const rtems_disk_device *dd) rtems_bdbuf_purge_list (&purge_list); rtems_bdbuf_unlock_cache (); } + +rtems_status_code +rtems_bdbuf_set_block_size (rtems_disk_device *dd, uint32_t block_size) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + rtems_bdbuf_lock_cache (); + + if (block_size > 0) + { + size_t bds_per_group = rtems_bdbuf_bds_per_group (block_size); + + if (bds_per_group != 0) + { + int block_to_media_block_shift = 0; + uint32_t media_blocks_per_block = block_size / dd->media_block_size; + uint32_t one = 1; + + while ((one << block_to_media_block_shift) < media_blocks_per_block) + { + ++block_to_media_block_shift; + } + + if ((dd->media_block_size << block_to_media_block_shift) != block_size) + block_to_media_block_shift = -1; + + dd->block_size = block_size; + dd->block_to_media_block_shift = block_to_media_block_shift; + dd->bds_per_group = bds_per_group; + } + else + { + sc = RTEMS_INVALID_NUMBER; + } + } + else + { + sc = RTEMS_INVALID_NUMBER; + } + + rtems_bdbuf_unlock_cache (); + + return sc; +} |