增加所有文件
This commit is contained in:
555
middleware/disk/disk.c
Normal file
555
middleware/disk/disk.c
Normal file
@@ -0,0 +1,555 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include <armv7-r/atomic.h>
|
||||
#include <debug.h>
|
||||
#include <disk.h>
|
||||
#include <lib/list.h>
|
||||
#include <param.h>
|
||||
#include <semphr.h>
|
||||
|
||||
struct list_node g_disk_list;
|
||||
QueueHandle_t g_disk_mutex;
|
||||
|
||||
static struct disk_info *disk_get_info(const char *disk_name)
|
||||
{
|
||||
struct disk_info *info;
|
||||
|
||||
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
|
||||
/* matches nodes based on name */
|
||||
list_for_every_entry (&g_disk_list, info, struct disk_info, node) {
|
||||
if (!strcmp(disk_name, info->disk_name)) {
|
||||
xSemaphoreGive(g_disk_mutex);
|
||||
return info;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(g_disk_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int disk_open(const char *disk_name, struct disk_dev *dev)
|
||||
{
|
||||
struct disk_info *info;
|
||||
info = disk_get_info(disk_name);
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk devicve node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
if (NULL != dev->info) {
|
||||
ssdk_printf(SSDK_ERR, "disk device is open.\n");
|
||||
return -DISK_ERROR_BUSY;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk open:%s\n", info->disk_name);
|
||||
dev->info = info;
|
||||
dev->block_size = info->block_align_size;
|
||||
dev->flags = DISK_FLAGS_REWR;
|
||||
arch_atomic_add(&info->use_count, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int disk_close(struct disk_dev *dev)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk close:%s\n", info->disk_name);
|
||||
dev->info = NULL;
|
||||
arch_atomic_add(&info->use_count, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int disk_read(struct disk_dev *dev, disk_addr_t addr, uint8_t *dst,
|
||||
disk_size_t size)
|
||||
{
|
||||
if (!(dev->flags & DISK_FLAGS_READ)) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"disk device does not support read operations \n");
|
||||
return -DISK_ERROR_NO_PERMISSION;
|
||||
}
|
||||
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
/* size range judgment */
|
||||
if (addr + size > info->disk_size) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
|
||||
addr, size, info->disk_size);
|
||||
return -DISK_ERROR_OUT_RANGE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk read:%s addr:%lld size:%lld\n",
|
||||
info->disk_name, addr, size);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if ((info->cache) && !(dev->flags & DISK_FLAGS_DIRECT_IO)) {
|
||||
return disk_cache_read(info->cache, dst, addr, size);
|
||||
} else
|
||||
#endif
|
||||
if (info->disk_ops->disk_read)
|
||||
return info->disk_ops->disk_read(info, dst, addr, size);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_write(struct disk_dev *dev, disk_addr_t addr, const uint8_t *src,
|
||||
disk_size_t size)
|
||||
{
|
||||
if (!(dev->flags & DISK_FLAGS_WRITE)) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"disk device does not support write operations \n");
|
||||
return -DISK_ERROR_NO_PERMISSION;
|
||||
}
|
||||
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
/* size range judgment */
|
||||
if (addr + size > info->disk_size) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
|
||||
addr, size, info->disk_size);
|
||||
return -DISK_ERROR_OUT_RANGE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk write:%s addr:%lld size:%lld\n",
|
||||
info->disk_name, addr, size);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if (info->cache) {
|
||||
int ret = 0;
|
||||
ret |= disk_cache_write(info->cache, src, addr, size);
|
||||
|
||||
/* DIRECT_IO situation,TODO */
|
||||
if (dev->flags & DISK_FLAGS_DIRECT_IO)
|
||||
ret |= disk_cache_sync_addr(info->cache, addr, size);
|
||||
|
||||
return ret;
|
||||
} else
|
||||
#endif
|
||||
if (info->disk_ops->disk_write)
|
||||
return info->disk_ops->disk_write(info, src, addr, size);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_read_block(struct disk_dev *dev, block_t block, uint8_t *dst,
|
||||
block_count_t count)
|
||||
{
|
||||
if (!(dev->flags & DISK_FLAGS_READ)) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"disk device does not support read operations \n");
|
||||
return -DISK_ERROR_NO_PERMISSION;
|
||||
}
|
||||
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
/* size range judgment */
|
||||
if (block + count > info->disk_size / dev->block_size) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"out of disk range, block:%lld count:%d block_size:0x%x "
|
||||
"addr:%lld size:%lld disk_size:%lld\n",
|
||||
block, count, dev->block_size,
|
||||
(disk_addr_t)block * dev->block_size,
|
||||
(disk_addr_t)count * dev->block_size, info->disk_size);
|
||||
return -DISK_ERROR_OUT_RANGE;
|
||||
}
|
||||
|
||||
/* mem alignment judgment */
|
||||
if (!IS_ALIGNED(dst, info->mem_align_size)) {
|
||||
ssdk_printf(SSDK_ERR, "mem addresses 0x%p not aligned to 0x%x\n", dst,
|
||||
info->mem_align_size);
|
||||
return -DISK_ERROR_NO_ALIGNED;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG,
|
||||
"disk read block:%s block:%lld count:%d block_size:0x%x "
|
||||
"addr:%lld size:%lld\n",
|
||||
info->disk_name, block, count, dev->block_size,
|
||||
(disk_addr_t)block * dev->block_size,
|
||||
(disk_addr_t)count * dev->block_size);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if ((info->cache) && !(dev->flags & DISK_FLAGS_DIRECT_IO)) {
|
||||
return disk_cache_read(info->cache, dst, block * dev->block_size,
|
||||
count * dev->block_size);
|
||||
} else
|
||||
#endif
|
||||
if (info->disk_ops->disk_read_block)
|
||||
return info->disk_ops->disk_read_block(info, dst, block, count,
|
||||
dev->block_size);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_write_block(struct disk_dev *dev, block_t block, const uint8_t *src,
|
||||
block_count_t count)
|
||||
{
|
||||
if (!(dev->flags & DISK_FLAGS_WRITE)) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"disk device does not support write operations \n");
|
||||
return -DISK_ERROR_NO_PERMISSION;
|
||||
}
|
||||
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
/* size range judgment */
|
||||
if (block + count > info->disk_size / dev->block_size) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"out of disk range, block:%lld count:%d block_size:0x%x "
|
||||
"addr:%lld size:%lld disk_size:%lld\n",
|
||||
block, count, dev->block_size,
|
||||
(disk_addr_t)block * dev->block_size,
|
||||
(disk_addr_t)count * dev->block_size, info->disk_size);
|
||||
return -DISK_ERROR_OUT_RANGE;
|
||||
}
|
||||
|
||||
/* mem alignment judgment */
|
||||
if (!IS_ALIGNED(src, info->mem_align_size)) {
|
||||
ssdk_printf(SSDK_ERR, "mem addresses %p not aligned to %d\n", src,
|
||||
info->mem_align_size);
|
||||
return -DISK_ERROR_NO_ALIGNED;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG,
|
||||
"disk write block:%s block:%lld count:%d block_size:0x%x "
|
||||
"addr:%lld size:%lld\n",
|
||||
info->disk_name, block, count, dev->block_size,
|
||||
(disk_addr_t)block * dev->block_size,
|
||||
(disk_addr_t)count * dev->block_size);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if (info->cache) {
|
||||
int ret = 0;
|
||||
ret |= disk_cache_write(info->cache, src, block * dev->block_size,
|
||||
count * dev->block_size);
|
||||
|
||||
/* DIRECT_IO situation,TODO */
|
||||
if (dev->flags & DISK_FLAGS_DIRECT_IO)
|
||||
ret |= disk_cache_sync_addr(info->cache, block * dev->block_size,
|
||||
count * dev->block_size);
|
||||
|
||||
return ret;
|
||||
} else
|
||||
#endif
|
||||
if (info->disk_ops->disk_write_block)
|
||||
return info->disk_ops->disk_write_block(info, src, block, count,
|
||||
dev->block_size);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_erase(struct disk_dev *dev, disk_addr_t addr, disk_size_t size,
|
||||
disk_erase_flags flag)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
/* size range judgment */
|
||||
if (addr + size > info->disk_size) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
|
||||
addr, size, info->disk_size);
|
||||
return -DISK_ERROR_OUT_RANGE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk erase:%s addr:%lld size:%lld flag:%d\n",
|
||||
info->disk_name, addr, size, flag);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if (info->cache) {
|
||||
int ret = 0;
|
||||
ret |= disk_cache_erase(info->cache, addr, size, flag);
|
||||
|
||||
/* DIRECT_IO situation,TODO */
|
||||
if (dev->flags & DISK_FLAGS_DIRECT_IO)
|
||||
ret |= disk_cache_sync_addr(info->cache, addr, size);
|
||||
|
||||
return ret;
|
||||
} else
|
||||
#endif
|
||||
if (info->disk_ops->disk_erase)
|
||||
return info->disk_ops->disk_erase(info, addr, size, flag);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_erase_group(struct disk_dev *dev, uint32_t erase_block, uint32_t count,
|
||||
disk_erase_flags flag)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
/* size range judgment */
|
||||
if (erase_block + count > info->disk_size / info->erase_size) {
|
||||
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"out of disk range, erase_block:%d count:%d "
|
||||
"erase_size:0x%x addr:%lld size:%lld disk_size:%lld\n",
|
||||
erase_block, count, info->erase_size,
|
||||
(disk_addr_t)erase_block * info->erase_size,
|
||||
(disk_addr_t)count * info->erase_size, info->disk_size);
|
||||
return -DISK_ERROR_OUT_RANGE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG,
|
||||
"disk erase group:%s erase_block:%d count:%d erase_size:0x%x "
|
||||
"addr:%lld size:%lld flag:%d\n",
|
||||
info->disk_name, erase_block, count, info->erase_size,
|
||||
(disk_addr_t)erase_block * info->erase_size,
|
||||
(disk_addr_t)count * info->erase_size, flag);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if (info->cache) {
|
||||
int ret = 0;
|
||||
ret |= disk_cache_erase(info->cache, erase_block * info->erase_size,
|
||||
count * info->erase_size, flag);
|
||||
|
||||
/* DIRECT_IO situation,TODO */
|
||||
if (dev->flags & DISK_FLAGS_DIRECT_IO)
|
||||
ret |= disk_cache_sync_addr(info->cache,
|
||||
erase_block * info->erase_size,
|
||||
count * info->erase_size);
|
||||
|
||||
return ret;
|
||||
} else
|
||||
#endif
|
||||
if (info->disk_ops->disk_erase_group)
|
||||
return info->disk_ops->disk_erase_group(info, erase_block, count,
|
||||
info->erase_size, flag);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_sync(struct disk_dev *dev)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk sync:%s\n", info->disk_name);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if (info->cache)
|
||||
return disk_cache_sync(info->cache);
|
||||
else
|
||||
#endif
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_sync_addr(struct disk_dev *dev, disk_addr_t addr, disk_size_t size)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
/* size range judgment */
|
||||
if (addr + size > info->disk_size) {
|
||||
ssdk_printf(SSDK_ERR,
|
||||
"out of disk range, addr:%lld size:%lld disk_size:%lld\n",
|
||||
addr, size, info->disk_size);
|
||||
return -DISK_ERROR_OUT_RANGE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk sync addr:%s addr:%lld size:%lld\n",
|
||||
info->disk_name, addr, size);
|
||||
#ifdef CONFIG_DISK_CACHE
|
||||
|
||||
if (info->cache)
|
||||
return disk_cache_sync_addr(info->cache, addr, size);
|
||||
else
|
||||
#endif
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
disk_addr_t disk_size(struct disk_dev *dev)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk size:%s size:%lld\n", info->disk_name,
|
||||
info->disk_size);
|
||||
return info->disk_size;
|
||||
}
|
||||
|
||||
uint32_t disk_erase_size(struct disk_dev *dev)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk erase size:%s erase_size:0x%x\n",
|
||||
info->disk_name, info->erase_size);
|
||||
return info->erase_size;
|
||||
}
|
||||
|
||||
uint32_t disk_get_block_size(struct disk_dev *dev)
|
||||
{
|
||||
ssdk_printf(SSDK_DEBUG, "disk get block size:%s block_size:0x%x\n",
|
||||
dev->info->disk_name, dev->block_size);
|
||||
return dev->block_size;
|
||||
}
|
||||
|
||||
int disk_set_block_size(struct disk_dev *dev, uint32_t blk_sz)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
ssdk_printf(SSDK_DEBUG, "disk set block size:%s block_size:0x%x\n",
|
||||
dev->info->disk_name, blk_sz);
|
||||
|
||||
/* blk_sz alignment judgment */
|
||||
if (!IS_ALIGNED(blk_sz, info->block_align_size)) {
|
||||
ssdk_printf(SSDK_ERR, "blk_sz %d not aligned to 0x%x\n", blk_sz,
|
||||
info->block_align_size);
|
||||
return -DISK_ERROR_NO_ALIGNED;
|
||||
}
|
||||
|
||||
dev->block_size = blk_sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int disk_set_flags(struct disk_dev *dev, bool mode, uint32_t flags)
|
||||
{
|
||||
if (mode)
|
||||
dev->flags &= flags;
|
||||
else
|
||||
dev->flags |= ~flags;
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk set flags:%s flags:0x%x\n",
|
||||
dev->info->disk_name, dev->flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t disk_get_flags(struct disk_dev *dev)
|
||||
{
|
||||
ssdk_printf(SSDK_DEBUG, "disk get flags:%s flags:0x%x\n",
|
||||
dev->info->disk_name, dev->flags);
|
||||
return dev->flags;
|
||||
}
|
||||
|
||||
int disk_status(struct disk_dev *dev)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk status:%s\n", info->disk_name);
|
||||
|
||||
if (info->disk_ops->disk_status)
|
||||
return info->disk_ops->disk_status(info);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int disk_ioctl(struct disk_dev *dev, uint32_t cmd, void *buff)
|
||||
{
|
||||
struct disk_info *info = dev->info;
|
||||
|
||||
if (NULL == info) {
|
||||
ssdk_printf(SSDK_ERR, "no disk device node\n");
|
||||
return -DISK_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_DEBUG, "disk ioctl:%s\n", info->disk_name);
|
||||
|
||||
if (info->disk_ops->disk_ioctl)
|
||||
return info->disk_ops->disk_ioctl(info, cmd, buff);
|
||||
else
|
||||
return -DISK_ERROR_NO_FUN;
|
||||
}
|
||||
|
||||
int register_disk(struct disk_info *disk)
|
||||
{
|
||||
int ret = 0;
|
||||
ssdk_printf(SSDK_DEBUG,
|
||||
"register disk :%s disk_size:%lld erase_size:0x%x\n",
|
||||
disk->disk_name, disk->disk_size, disk->erase_size);
|
||||
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
|
||||
/* insert node */
|
||||
list_add_tail(&g_disk_list, &disk->node);
|
||||
disk->use_count = 0;
|
||||
xSemaphoreGive(g_disk_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int unregister_disk(struct disk_info *disk)
|
||||
{
|
||||
int ret = 0;
|
||||
ssdk_printf(SSDK_DEBUG, "unregiste disk :%s\n", disk->disk_name);
|
||||
xSemaphoreTake(g_disk_mutex, portMAX_DELAY);
|
||||
|
||||
if (disk->use_count) {
|
||||
xSemaphoreGive(g_disk_mutex);
|
||||
return -DISK_ERROR_BUSY;
|
||||
}
|
||||
|
||||
/* remove nodes */
|
||||
if (list_in_list(&disk->node))
|
||||
list_delete(&disk->node);
|
||||
|
||||
xSemaphoreGive(g_disk_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int disk_init(void)
|
||||
{
|
||||
ssdk_printf(SSDK_DEBUG, "disk init\n");
|
||||
/* disk list node init */
|
||||
list_initialize(&g_disk_list);
|
||||
g_disk_mutex = xSemaphoreCreateMutex();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int disk_exit(void)
|
||||
{
|
||||
ssdk_printf(SSDK_DEBUG, "disk exit\n");
|
||||
/* disk list node init */
|
||||
xSemaphoreGive(g_disk_mutex);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user