Storage: Last minute changes to the block device api

- Remove write set of functions
  - Caused confusion with small benefit
  - Trivial to add later
- Remove unused error codes
  - Initial expirementation indicates most of these may not be useful
  - Trivial to add later
- Removed bd_error_t
  - Carries to additional type information, int already carries
    sufficient connotation
  - Trivial to add later

per @c1728p9, @sg-
pull/3762/head
Christopher Haster 2017-02-22 18:37:50 -06:00 committed by Simon Hughes
parent 5a977eff30
commit ea5ac4bb4d
9 changed files with 97 additions and 209 deletions

View File

@ -1,75 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2017 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "BlockDevice.h"
// Writes by default perform an erase + program
bd_error_t BlockDevice::write(const void *buffer, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_write(addr, size)) {
return BD_ERROR_PARAMETER;
}
bd_error_t err = erase(addr, size);
if (err) {
return err;
}
return program(buffer, addr, size);
}
bd_size_t BlockDevice::get_write_size() const
{
return get_erase_size();
}
bool BlockDevice::is_valid_write(bd_addr_t addr, bd_size_t size)
{
return is_valid_erase(addr, size);
}
// Convenience functions for checking block validity
static bool is_aligned(uint64_t x, uint64_t alignment)
{
return (x / alignment) * alignment == x;
}
bool BlockDevice::is_valid_read(bd_addr_t addr, bd_size_t size)
{
return (
is_aligned(addr, get_read_size()) &&
is_aligned(size, get_read_size()) &&
addr + size <= this->size());
}
bool BlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size)
{
return (
is_aligned(addr, get_erase_size()) &&
is_aligned(size, get_erase_size()) &&
addr + size <= this->size());
}
bool BlockDevice::is_valid_program(bd_addr_t addr, bd_size_t size)
{
return (
is_aligned(addr, get_program_size()) &&
is_aligned(size, get_program_size()) &&
addr + size <= this->size());
}

View File

@ -22,23 +22,13 @@
/** Enum of standard error codes
*
* @enum bd_error_t
* @enum bd_error
*/
enum bd_error {
BD_ERROR_OK = 0, /*!< no error */
BD_ERROR_WOULD_BLOCK = -4001, /*!< operation would block */
BD_ERROR_UNSUPPORTED = -4002, /*!< unsupported operation */
BD_ERROR_PARAMETER = -4003, /*!< invalid parameter */
BD_ERROR_NO_INIT = -4004, /*!< uninitialized */
BD_ERROR_NO_DEVICE = -4005, /*!< device is missing or not connected */
BD_ERROR_WRITE_PROTECTED = -4006, /*!< write protected */
BD_ERROR_DEVICE_ERROR = -4007, /*!< device specific error */
BD_ERROR_DEVICE_ERROR = -4001, /*!< device specific error */
};
/** Type representing either 0 or a negative error code
*/
typedef int32_t bd_error_t;
/** Type representing the address of a specific block
*/
typedef uint64_t bd_addr_t;
@ -61,13 +51,13 @@ public:
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t init() = 0;
virtual int init() = 0;
/** Deinitialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t deinit() = 0;
virtual int deinit() = 0;
/** Read blocks from a block device
*
@ -78,20 +68,7 @@ public:
* @param size Size to read in bytes, must be a multiple of read block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t read(void *buffer, bd_addr_t addr, bd_size_t size) = 0;
/** Write blocks to a block device
*
* A write is equivalent to an erase followed by a program
*
* If a failure occurs, it is not possible to determine how many bytes succeeded
*
* @param buffer Buffer of data to write to blocks
* @param addr Address of block to begin writing to
* @param size Size to write in bytes, must be a multiple of write block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t write(const void *buffer, bd_addr_t addr, bd_size_t size);
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size) = 0;
/** Program blocks to a block device
*
@ -104,7 +81,7 @@ public:
* @param size Size to write in bytes, must be a multiple of program block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t program(const void *buffer, bd_addr_t addr, bd_size_t size) = 0;
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size) = 0;
/** Erase blocks on a block device
*
@ -114,7 +91,7 @@ public:
* @param size Size to erase in bytes, must be a multiple of erase block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t erase(bd_addr_t addr, bd_size_t size) = 0;
virtual int erase(bd_addr_t addr, bd_size_t size) = 0;
/** Get the size of a readable block
*
@ -122,14 +99,6 @@ public:
*/
virtual bd_size_t get_read_size() const = 0;
/** Get the size of a writeable block
*
* @return Size of a writeable block in bytes
* @note Must be a multiple of the read size, this is
* equivalent to the erase size of the device
*/
virtual bd_size_t get_write_size() const;
/** Get the size of a programable block
*
* @return Size of a programable block in bytes
@ -156,15 +125,13 @@ public:
* @param size Size to read in bytes
* @return True if read is valid for underlying block device
*/
bool is_valid_read(bd_addr_t addr, bd_size_t size);
/** Convenience function for checking block write validity
*
* @param addr Address of block to begin writing to
* @param size Size to write in bytes
* @return True if write is valid for underlying block device
*/
bool is_valid_write(bd_addr_t addr, bd_size_t size);
bool is_valid_read(bd_addr_t addr, bd_size_t size)
{
return (
addr % get_read_size() == 0 &&
size % get_read_size() == 0 &&
addr + size <= this->size());
}
/** Convenience function for checking block program validity
*
@ -172,7 +139,13 @@ public:
* @param size Size to write in bytes
* @return True if program is valid for underlying block device
*/
bool is_valid_program(bd_addr_t addr, bd_size_t size);
bool is_valid_program(bd_addr_t addr, bd_size_t size)
{
return (
addr % get_program_size() == 0 &&
size % get_program_size() == 0 &&
addr + size <= this->size());
}
/** Convenience function for checking block erase validity
*
@ -180,7 +153,13 @@ public:
* @param size Size to erase in bytes
* @return True if erase is valid for underlying block device
*/
bool is_valid_erase(bd_addr_t addr, bd_size_t size);
bool is_valid_erase(bd_addr_t addr, bd_size_t size)
{
return (
addr % get_erase_size() == 0 &&
size % get_erase_size() == 0 &&
addr + size <= this->size());
}
};

View File

@ -28,7 +28,7 @@ static bool is_aligned(uint64_t x, uint64_t alignment)
return (x / alignment) * alignment == x;
}
bd_error_t ChainingBlockDevice::init()
int ChainingBlockDevice::init()
{
_read_size = 0;
_program_size = 0;
@ -40,7 +40,7 @@ bd_error_t ChainingBlockDevice::init()
// the constructor since some block devices may need to be
// initialized before they know their block size/count
for (size_t i = 0; i < _bd_count; i++) {
bd_error_t err = _bds[i]->init();
int err = _bds[i]->init();
if (err) {
return err;
}
@ -48,22 +48,22 @@ bd_error_t ChainingBlockDevice::init()
bd_size_t read = _bds[i]->get_read_size();
if (i == 0 || (read >= _read_size && is_aligned(read, _read_size))) {
_read_size = read;
} else if (!(_read_size > read && is_aligned(_read_size, read))) {
return BD_ERROR_PARAMETER;
} else {
MBED_ASSERT(_read_size > read && is_aligned(_read_size, read));
}
bd_size_t program = _bds[i]->get_program_size();
if (i == 0 || (program >= _program_size && is_aligned(program, _program_size))) {
_program_size = program;
} else if (!(_program_size > program && is_aligned(_program_size, program))) {
return BD_ERROR_PARAMETER;
} else {
MBED_ASSERT(_program_size > program && is_aligned(_program_size, program));
}
bd_size_t erase = _bds[i]->get_erase_size();
if (i == 0 || (erase >= _erase_size && is_aligned(erase, _erase_size))) {
_erase_size = erase;
} else if (!(_erase_size > erase && is_aligned(_erase_size, erase))) {
return BD_ERROR_PARAMETER;
} else {
MBED_ASSERT(_erase_size > erase && is_aligned(_erase_size, erase));
}
_size += _bds[i]->size();
@ -72,10 +72,10 @@ bd_error_t ChainingBlockDevice::init()
return 0;
}
bd_error_t ChainingBlockDevice::deinit()
int ChainingBlockDevice::deinit()
{
for (size_t i = 0; i < _bd_count; i++) {
bd_error_t err = _bds[i]->deinit();
int err = _bds[i]->deinit();
if (err) {
return err;
}
@ -84,12 +84,9 @@ bd_error_t ChainingBlockDevice::deinit()
return 0;
}
bd_error_t ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
int ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_read(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_read(addr, size));
uint8_t *buffer = static_cast<uint8_t*>(b);
// Find block devices containing blocks, may span multiple block devices
@ -102,7 +99,7 @@ bd_error_t ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
read = bdsize - addr;
}
bd_error_t err = _bds[i]->read(buffer, addr, read);
int err = _bds[i]->read(buffer, addr, read);
if (err) {
return err;
}
@ -118,12 +115,9 @@ bd_error_t ChainingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
return 0;
}
bd_error_t ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
int ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_program(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_program(addr, size));
const uint8_t *buffer = static_cast<const uint8_t*>(b);
// Find block devices containing blocks, may span multiple block devices
@ -136,7 +130,7 @@ bd_error_t ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t
program = bdsize - addr;
}
bd_error_t err = _bds[i]->program(buffer, addr, program);
int err = _bds[i]->program(buffer, addr, program);
if (err) {
return err;
}
@ -152,11 +146,9 @@ bd_error_t ChainingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t
return 0;
}
bd_error_t ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
int ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
if (!is_valid_erase(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_erase(addr, size));
// Find block devices containing blocks, may span multiple block devices
for (size_t i = 0; i < _bd_count && size > 0; i++) {
@ -168,7 +160,7 @@ bd_error_t ChainingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
erase = bdsize - addr;
}
bd_error_t err = _bds[i]->erase(addr, erase);
int err = _bds[i]->erase(addr, erase);
if (err) {
return err;
}

View File

@ -78,13 +78,13 @@ public:
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t init();
virtual int init();
/** Deinitialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t deinit();
virtual int deinit();
/** Read blocks from a block device
*
@ -93,7 +93,7 @@ public:
* @param size Size to read in bytes, must be a multiple of read block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t read(void *buffer, bd_addr_t addr, bd_size_t size);
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
/** Program blocks to a block device
*
@ -104,7 +104,7 @@ public:
* @param size Size to write in bytes, must be a multiple of program block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t program(const void *buffer, bd_addr_t addr, bd_size_t size);
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
/** Erase blocks on a block device
*
@ -114,7 +114,7 @@ public:
* @param size Size to erase in bytes, must be a multiple of erase block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t erase(bd_addr_t addr, bd_size_t size);
virtual int erase(bd_addr_t addr, bd_size_t size);
/** Get the size of a readable block
*

View File

@ -43,7 +43,7 @@ HeapBlockDevice::~HeapBlockDevice()
}
}
bd_error_t HeapBlockDevice::init()
int HeapBlockDevice::init()
{
if (!_blocks) {
_blocks = new uint8_t*[_count];
@ -55,7 +55,7 @@ bd_error_t HeapBlockDevice::init()
return BD_ERROR_OK;
}
bd_error_t HeapBlockDevice::deinit()
int HeapBlockDevice::deinit()
{
// Heapory is lazily cleaned up in destructor to allow
// data to live across de/reinitialization
@ -82,13 +82,11 @@ bd_size_t HeapBlockDevice::size()
return _count * _erase_size;
}
bd_error_t HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
int HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_read(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_read(addr, size));
uint8_t *buffer = static_cast<uint8_t*>(b);
while (size > 0) {
bd_addr_t hi = addr / _erase_size;
bd_addr_t lo = addr % _erase_size;
@ -107,13 +105,11 @@ bd_error_t HeapBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
return 0;
}
bd_error_t HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
int HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_program(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_program(addr, size));
const uint8_t *buffer = static_cast<const uint8_t*>(b);
while (size > 0) {
bd_addr_t hi = addr / _erase_size;
bd_addr_t lo = addr % _erase_size;
@ -135,11 +131,9 @@ bd_error_t HeapBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t siz
return 0;
}
bd_error_t HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
int HeapBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
if (!is_valid_erase(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_erase(addr, size));
while (size > 0) {
bd_addr_t hi = addr / _erase_size;

View File

@ -59,13 +59,13 @@ public:
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t init();
virtual int init();
/** Deinitialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t deinit();
virtual int deinit();
/** Read blocks from a block device
*
@ -74,7 +74,7 @@ public:
* @param size Size to read in bytes, must be a multiple of read block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t read(void *buffer, bd_addr_t addr, bd_size_t size);
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
/** Program blocks to a block device
*
@ -85,7 +85,7 @@ public:
* @param size Size to write in bytes, must be a multiple of program block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t program(const void *buffer, bd_addr_t addr, bd_size_t size);
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
/** Erase blocks on a block device
*
@ -95,7 +95,7 @@ public:
* @param size Size to erase in bytes, must be a multiple of erase block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t erase(bd_addr_t addr, bd_size_t size);
virtual int erase(bd_addr_t addr, bd_size_t size);
/** Get the size of a readable block
*

View File

@ -44,9 +44,9 @@ SlicingBlockDevice::SlicingBlockDevice(BlockDevice *bd, bd_addr_t start, bd_addr
}
}
bd_error_t SlicingBlockDevice::init()
int SlicingBlockDevice::init()
{
bd_error_t err = _bd->init();
int err = _bd->init();
if (err) {
return err;
}
@ -65,42 +65,31 @@ bd_error_t SlicingBlockDevice::init()
}
// Check that block addresses are valid
if (!_bd->is_valid_write(_start, _stop - _start)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(_bd->is_valid_erase(_start, _stop - _start));
return 0;
}
bd_error_t SlicingBlockDevice::deinit()
int SlicingBlockDevice::deinit()
{
return _bd->deinit();
}
bd_error_t SlicingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
int SlicingBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_read(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_read(addr, size));
return _bd->read(b, addr + _start, size);
}
bd_error_t SlicingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
int SlicingBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_program(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_program(addr, size));
return _bd->program(b, addr + _start, size);
}
bd_error_t SlicingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
int SlicingBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
if (!is_valid_erase(addr, size)) {
return BD_ERROR_PARAMETER;
}
MBED_ASSERT(is_valid_erase(addr, size));
return _bd->erase(addr + _start, size);
}

View File

@ -76,13 +76,13 @@ public:
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t init();
virtual int init();
/** Deinitialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t deinit();
virtual int deinit();
/** Read blocks from a block device
*
@ -91,7 +91,7 @@ public:
* @param size Size to read in bytes, must be a multiple of read block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t read(void *buffer, bd_addr_t addr, bd_size_t size);
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
/** Program blocks to a block device
*
@ -102,7 +102,7 @@ public:
* @param size Size to write in bytes, must be a multiple of program block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t program(const void *buffer, bd_addr_t addr, bd_size_t size);
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
/** Erase blocks on a block device
*
@ -112,7 +112,7 @@ public:
* @param size Size to erase in bytes, must be a multiple of erase block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t erase(bd_addr_t addr, bd_size_t size);
virtual int erase(bd_addr_t addr, bd_size_t size);
/** Get the size of a readable block
*

View File

@ -91,7 +91,7 @@ DSTATUS disk_initialize(BYTE pdrv)
DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
debug_if(FFS_DBG, "disk_read(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
bd_size_t ssize = _ffs[pdrv]->get_write_size();
bd_size_t ssize = _ffs[pdrv]->get_erase_size();
int err = _ffs[pdrv]->read(buff, sector*ssize, count*ssize);
return err ? RES_PARERR : RES_OK;
}
@ -99,9 +99,18 @@ DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
debug_if(FFS_DBG, "disk_write(sector %d, count %d) on pdrv [%d]\n", sector, count, pdrv);
bd_size_t ssize = _ffs[pdrv]->get_write_size();
int err = _ffs[pdrv]->write(buff, sector*ssize, count*ssize);
return err ? RES_PARERR : RES_OK;
bd_size_t ssize = _ffs[pdrv]->get_erase_size();
int err = _ffs[pdrv]->erase(sector*ssize, count*ssize);
if (err) {
return RES_PARERR;
}
err = _ffs[pdrv]->program(buff, sector*ssize, count*ssize);
if (err) {
return RES_PARERR;
}
return RES_OK;
}
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
@ -118,7 +127,7 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
if (_ffs[pdrv] == NULL) {
return RES_NOTRDY;
} else {
DWORD count = _ffs[pdrv]->size() / _ffs[pdrv]->get_write_size();
DWORD count = _ffs[pdrv]->size() / _ffs[pdrv]->get_erase_size();
*((DWORD*)buff) = count;
return RES_OK;
}
@ -126,7 +135,7 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
if (_ffs[pdrv] == NULL) {
return RES_NOTRDY;
} else {
DWORD size = _ffs[pdrv]->get_write_size();
DWORD size = _ffs[pdrv]->get_erase_size();
*((DWORD*)buff) = size;
return RES_OK;
}