|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <bitops.h>
|
|
|
|
#include <flash.h>
|
|
|
|
#include <ftl.h>
|
|
|
|
#include <macros.h>
|
|
|
|
|
|
|
|
static size_t ftl_flash_get_size(struct flash_dev *dev)
|
|
|
|
{
|
|
|
|
struct ftl_map *map = dev->priv;
|
|
|
|
|
|
|
|
return ftl_get_size(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t ftl_flash_get_capacity(struct flash_dev *dev)
|
|
|
|
{
|
|
|
|
struct ftl_map *map = dev->priv;
|
|
|
|
|
|
|
|
return ftl_get_capacity(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t ftl_flash_read(struct flash_dev *dev, uint32_t addr, void *data,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
struct ftl_map *map = dev->priv;
|
|
|
|
|
|
|
|
return ftl_read(map, data, len, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t ftl_flash_write(struct flash_dev *dev, uint32_t addr,
|
|
|
|
const void *data, size_t len)
|
|
|
|
{
|
|
|
|
struct ftl_map *map = dev->priv;
|
|
|
|
|
|
|
|
return ftl_write(map, addr, data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ftl_flash_sync(struct flash_dev *dev)
|
|
|
|
{
|
|
|
|
struct ftl_map *map = dev->priv;
|
|
|
|
|
|
|
|
return ftl_sync(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ftl_flash_erase(struct flash_dev *dev, uint32_t addr)
|
|
|
|
{
|
|
|
|
struct ftl_map *map = dev->priv;
|
|
|
|
|
|
|
|
return ftl_trim(map, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ftl_flash_release(struct flash_dev *dev)
|
|
|
|
{
|
|
|
|
struct ftl_map *map;
|
|
|
|
|
|
|
|
map = dev->priv;
|
|
|
|
|
|
|
|
flash_release(map->dev);
|
|
|
|
free(map);
|
|
|
|
free(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct flash_ops ftl_flash_ops = {
|
|
|
|
.release = ftl_flash_release,
|
|
|
|
.get_size = ftl_flash_get_size,
|
|
|
|
.get_capacity = ftl_flash_get_capacity,
|
|
|
|
.read = ftl_flash_read,
|
|
|
|
.write = ftl_flash_write,
|
|
|
|
/* TODO: implement default function to perform a copy. */
|
|
|
|
.copy = NULL,
|
|
|
|
.is_erased = default_flash_is_zero,
|
|
|
|
.erase = ftl_flash_erase,
|
|
|
|
.sync = ftl_flash_sync,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct flash_dev *ftl_mount(struct flash_dev *raw_dev)
|
|
|
|
{
|
|
|
|
struct flash_dev *dev;
|
|
|
|
struct ftl_map *map;
|
|
|
|
|
|
|
|
if (!(dev = malloc(sizeof *dev)))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!(map = malloc(sizeof *map)))
|
|
|
|
goto err_free_dev;
|
|
|
|
|
|
|
|
if (ftl_init_map(map, raw_dev) < 0)
|
|
|
|
goto err_free_map;
|
|
|
|
|
|
|
|
/* TODO: inspect return value? */
|
|
|
|
ftl_resume_map(map);
|
|
|
|
|
|
|
|
dev->ops = &ftl_flash_ops;
|
|
|
|
dev->priv = map;
|
|
|
|
dev->log2_block_size = map->log2_page_size;
|
|
|
|
|
|
|
|
return dev;
|
|
|
|
|
|
|
|
err_free_map:
|
|
|
|
free(map);
|
|
|
|
err_free_dev:
|
|
|
|
free(dev);
|
|
|
|
return NULL;
|
|
|
|
}
|