drivers: ramdisk: use devicetree to instantiate RAM disk

Rework RAM disk driver to be configured using devicetree and
support multiple instances.

This patch also removes a copy of the RAM disk driver,
tests/subsys/fs/fat_fs_dual_drive/src/disk_access_test_drv.c,
that was there for testing multiple disk drivers support.

Bonus: one SYS_INIT() less and a memory region can be exported to the
host.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
This commit is contained in:
Johann Fischer 2023-07-07 00:30:04 +02:00 committed by Carles Cufí
commit f67dd39bb2
35 changed files with 298 additions and 173 deletions

View file

@ -3,6 +3,7 @@
config DISK_DRIVER_RAM
bool "RAM Disk"
default y if DT_HAS_ZEPHYR_RAM_DISK_ENABLED
help
RAM buffer used to emulate storage disk.
This option can be used to test the file
@ -10,18 +11,6 @@ config DISK_DRIVER_RAM
if DISK_DRIVER_RAM
config DISK_RAM_VOLUME_SIZE
int "RAM Disk size in kilobytes"
default 96
help
Size of the RAM Disk.
config DISK_RAM_VOLUME_NAME
string "RAM Disk mount point or drive name"
default "RAM"
help
Disk name as per file system naming guidelines.
module = RAMDISK
module-str = ramdisk
source "subsys/logging/Kconfig.template.log_config"

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016 Intel Corporation.
* Copyright (c) 2021, Nordic Semiconductor ASA
* Copyright (c) 2021,2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -15,15 +15,25 @@
LOG_MODULE_REGISTER(ramdisk, CONFIG_RAMDISK_LOG_LEVEL);
#define RAMDISK_SECTOR_SIZE 512
#define RAMDISK_VOLUME_SIZE (CONFIG_DISK_RAM_VOLUME_SIZE * 1024)
#define RAMDISK_SECTOR_COUNT (RAMDISK_VOLUME_SIZE / RAMDISK_SECTOR_SIZE)
struct ram_disk_data {
struct disk_info info;
const size_t sector_size;
const size_t sector_count;
uint8_t *const buf;
};
static uint8_t ramdisk_buf[RAMDISK_VOLUME_SIZE];
struct ram_disk_config {
const size_t sector_size;
const size_t sector_count;
const size_t size;
uint8_t *const buf;
};
static void *lba_to_address(uint32_t lba)
static void *lba_to_address(const struct device *dev, uint32_t lba)
{
return &ramdisk_buf[lba * RAMDISK_SECTOR_SIZE];
const struct ram_disk_config *config = dev->config;
return &config->buf[lba * config->sector_size];
}
static int disk_ram_access_status(struct disk_info *disk)
@ -39,15 +49,17 @@ static int disk_ram_access_init(struct disk_info *disk)
static int disk_ram_access_read(struct disk_info *disk, uint8_t *buff,
uint32_t sector, uint32_t count)
{
const struct device *dev = disk->dev;
const struct ram_disk_config *config = dev->config;
uint32_t last_sector = sector + count;
if (last_sector < sector || last_sector > RAMDISK_SECTOR_COUNT) {
LOG_ERR("Sector %" PRIu32 " is outside the range %u",
last_sector, RAMDISK_SECTOR_COUNT);
if (last_sector < sector || last_sector > config->sector_count) {
LOG_ERR("Sector %" PRIu32 " is outside the range %zu",
last_sector, config->sector_count);
return -EIO;
}
memcpy(buff, lba_to_address(sector), count * RAMDISK_SECTOR_SIZE);
memcpy(buff, lba_to_address(dev, sector), count * config->sector_size);
return 0;
}
@ -55,29 +67,33 @@ static int disk_ram_access_read(struct disk_info *disk, uint8_t *buff,
static int disk_ram_access_write(struct disk_info *disk, const uint8_t *buff,
uint32_t sector, uint32_t count)
{
const struct device *dev = disk->dev;
const struct ram_disk_config *config = dev->config;
uint32_t last_sector = sector + count;
if (last_sector < sector || last_sector > RAMDISK_SECTOR_COUNT) {
LOG_ERR("Sector %" PRIu32 " is outside the range %u",
last_sector, RAMDISK_SECTOR_COUNT);
if (last_sector < sector || last_sector > config->sector_count) {
LOG_ERR("Sector %" PRIu32 " is outside the range %zu",
last_sector, config->sector_count);
return -EIO;
}
memcpy(lba_to_address(sector), buff, count * RAMDISK_SECTOR_SIZE);
memcpy(lba_to_address(dev, sector), buff, count * config->sector_size);
return 0;
}
static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff)
{
const struct ram_disk_config *config = disk->dev->config;
switch (cmd) {
case DISK_IOCTL_CTRL_SYNC:
break;
case DISK_IOCTL_GET_SECTOR_COUNT:
*(uint32_t *)buff = RAMDISK_SECTOR_COUNT;
*(uint32_t *)buff = config->sector_count;
break;
case DISK_IOCTL_GET_SECTOR_SIZE:
*(uint32_t *)buff = RAMDISK_SECTOR_SIZE;
*(uint32_t *)buff = config->sector_size;
break;
case DISK_IOCTL_GET_ERASE_BLOCK_SZ:
*(uint32_t *)buff = 1U;
@ -89,6 +105,15 @@ static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff
return 0;
}
static int disk_ram_init(const struct device *dev)
{
struct disk_info *info = dev->data;
info->dev = dev;
return disk_access_register(info);
}
static const struct disk_operations ram_disk_ops = {
.init = disk_ram_access_init,
.status = disk_ram_access_status,
@ -97,15 +122,51 @@ static const struct disk_operations ram_disk_ops = {
.ioctl = disk_ram_access_ioctl,
};
static struct disk_info ram_disk = {
.name = CONFIG_DISK_RAM_VOLUME_NAME,
.ops = &ram_disk_ops,
};
#define DT_DRV_COMPAT zephyr_ram_disk
static int disk_ram_init(void)
{
#define RAMDISK_DEVICE_SIZE(n) \
(DT_INST_PROP(n, sector_size) * DT_INST_PROP(n, sector_count))
return disk_access_register(&ram_disk);
}
#define RAMDISK_DEVICE_CONFIG_DEFINE_MEMREG(n) \
BUILD_ASSERT(RAMDISK_DEVICE_SIZE(n) <= \
DT_REG_SIZE(DT_INST_PHANDLE(n, ram_region)), \
"Disk size is smaller than memory region"); \
\
static struct ram_disk_config disk_config_##n = { \
.sector_size = DT_INST_PROP(n, sector_size), \
.sector_count = DT_INST_PROP(n, sector_count), \
.size = RAMDISK_DEVICE_SIZE(n), \
.buf = UINT_TO_POINTER(DT_REG_ADDR(DT_INST_PHANDLE(n, ram_region))), \
}
SYS_INIT(disk_ram_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#define RAMDISK_DEVICE_CONFIG_DEFINE_LOCAL(n) \
static uint8_t disk_buf_##n[DT_INST_PROP(n, sector_size) * \
DT_INST_PROP(n, sector_count)]; \
\
static struct ram_disk_config disk_config_##n = { \
.sector_size = DT_INST_PROP(n, sector_size), \
.sector_count = DT_INST_PROP(n, sector_count), \
.size = RAMDISK_DEVICE_SIZE(n), \
.buf = disk_buf_##n, \
}
#define RAMDISK_DEVICE_CONFIG_DEFINE(n) \
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, ram_region), \
(RAMDISK_DEVICE_CONFIG_DEFINE_MEMREG(n)), \
(RAMDISK_DEVICE_CONFIG_DEFINE_LOCAL(n)))
#define RAMDISK_DEVICE_DEFINE(n) \
\
static struct disk_info disk_info_##n = { \
.name = DT_INST_PROP(n, disk_name), \
.ops = &ram_disk_ops, \
}; \
\
RAMDISK_DEVICE_CONFIG_DEFINE(n); \
\
DEVICE_DT_INST_DEFINE(n, disk_ram_init, NULL, \
&disk_info_##n, &disk_config_##n, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&ram_disk_ops);
DT_INST_FOREACH_STATUS_OKAY(RAMDISK_DEVICE_DEFINE)