first commit for chrg
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-08-08 GuEe-GUI first version
|
||||
*/
|
||||
|
||||
#include "blk_dfs.h"
|
||||
|
||||
#include <dfs_file.h>
|
||||
#include <drivers/classes/block.h>
|
||||
|
||||
#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_DFS_V2)
|
||||
struct blk_fops_data
|
||||
{
|
||||
struct rt_device_blk_geometry geometry;
|
||||
};
|
||||
|
||||
static int blk_fops_open(struct dfs_file *file)
|
||||
{
|
||||
struct rt_device *dev = file->vnode->data;
|
||||
struct blk_fops_data *data = rt_malloc(sizeof(*data));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
return (int)-RT_ENOMEM;
|
||||
}
|
||||
|
||||
dev->user_data = data;
|
||||
rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &data->geometry);
|
||||
rt_device_control(dev, RT_DEVICE_CTRL_ALL_BLK_SSIZEGET, &file->vnode->size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blk_fops_close(struct dfs_file *file)
|
||||
{
|
||||
struct rt_device *dev = file->vnode->data;
|
||||
|
||||
rt_free(dev->user_data);
|
||||
dev->user_data = RT_NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blk_fops_ioctl(struct dfs_file *file, int cmd, void *arg)
|
||||
{
|
||||
struct rt_device *dev = file->vnode->data;
|
||||
|
||||
return (int)rt_device_control(dev, cmd, arg);
|
||||
}
|
||||
|
||||
static ssize_t blk_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
void *rbuf;
|
||||
rt_ssize_t res = 0;
|
||||
int bytes_per_sector, blk_pos, first_offs, rsize = 0;
|
||||
struct rt_device *dev = file->vnode->data;
|
||||
struct blk_fops_data *data = dev->user_data;
|
||||
|
||||
bytes_per_sector = data->geometry.bytes_per_sector;
|
||||
blk_pos = *pos / bytes_per_sector;
|
||||
first_offs = *pos % bytes_per_sector;
|
||||
|
||||
if ((rbuf = rt_malloc(bytes_per_sector)))
|
||||
{
|
||||
/*
|
||||
** #1: read first unalign block size.
|
||||
*/
|
||||
res = rt_device_read(dev, blk_pos, rbuf, 1);
|
||||
|
||||
if (res == 1)
|
||||
{
|
||||
if (count > bytes_per_sector - first_offs)
|
||||
{
|
||||
rsize = bytes_per_sector - first_offs;
|
||||
}
|
||||
else
|
||||
{
|
||||
rsize = count;
|
||||
}
|
||||
rt_memcpy(buf, rbuf + first_offs, rsize);
|
||||
++blk_pos;
|
||||
|
||||
/*
|
||||
** #2: read continuous block size.
|
||||
*/
|
||||
while (rsize < count)
|
||||
{
|
||||
res = rt_device_read(dev, blk_pos++, rbuf, 1);
|
||||
|
||||
if (res != 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (count - rsize >= bytes_per_sector)
|
||||
{
|
||||
rt_memcpy(buf + rsize, rbuf, bytes_per_sector);
|
||||
rsize += bytes_per_sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_memcpy(buf + rsize, rbuf, count - rsize);
|
||||
rsize = count;
|
||||
}
|
||||
}
|
||||
|
||||
*pos += rsize;
|
||||
}
|
||||
|
||||
rt_free(rbuf);
|
||||
}
|
||||
|
||||
return rsize;
|
||||
}
|
||||
|
||||
static ssize_t blk_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
void *rbuf;
|
||||
rt_ssize_t res = 0;
|
||||
int bytes_per_sector, blk_pos, first_offs, wsize = 0;
|
||||
struct rt_device *dev = file->vnode->data;
|
||||
struct blk_fops_data *data = dev->user_data;
|
||||
|
||||
bytes_per_sector = data->geometry.bytes_per_sector;
|
||||
blk_pos = *pos / bytes_per_sector;
|
||||
first_offs = *pos % bytes_per_sector;
|
||||
|
||||
/*
|
||||
** #1: write first unalign block size.
|
||||
*/
|
||||
if (first_offs != 0)
|
||||
{
|
||||
if (count > bytes_per_sector - first_offs)
|
||||
{
|
||||
wsize = bytes_per_sector - first_offs;
|
||||
}
|
||||
else
|
||||
{
|
||||
wsize = count;
|
||||
}
|
||||
|
||||
if ((rbuf = rt_malloc(bytes_per_sector)))
|
||||
{
|
||||
res = rt_device_read(dev, blk_pos, rbuf, 1);
|
||||
|
||||
if (res == 1)
|
||||
{
|
||||
rt_memcpy(rbuf + first_offs, buf, wsize);
|
||||
res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1);
|
||||
|
||||
if (res == 1)
|
||||
{
|
||||
blk_pos += 1;
|
||||
rt_free(rbuf);
|
||||
|
||||
goto _goon;
|
||||
}
|
||||
}
|
||||
|
||||
rt_free(rbuf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_goon:
|
||||
/*
|
||||
** #2: write continuous block size.
|
||||
*/
|
||||
if ((count - wsize) / bytes_per_sector != 0)
|
||||
{
|
||||
res = rt_device_write(dev, blk_pos, buf + wsize, (count - wsize) / bytes_per_sector);
|
||||
wsize += res * bytes_per_sector;
|
||||
blk_pos += res;
|
||||
|
||||
if (res != (count - wsize) / bytes_per_sector)
|
||||
{
|
||||
*pos += wsize;
|
||||
return wsize;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** # 3: write last unalign block size.
|
||||
*/
|
||||
if ((count - wsize) != 0)
|
||||
{
|
||||
if ((rbuf = rt_malloc(bytes_per_sector)))
|
||||
{
|
||||
res = rt_device_read(dev, blk_pos, rbuf, 1);
|
||||
|
||||
if (res == 1)
|
||||
{
|
||||
rt_memcpy(rbuf, buf + wsize, count - wsize);
|
||||
res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1);
|
||||
|
||||
if (res == 1)
|
||||
{
|
||||
wsize += count - wsize;
|
||||
}
|
||||
}
|
||||
|
||||
rt_free(rbuf);
|
||||
}
|
||||
}
|
||||
|
||||
*pos += wsize;
|
||||
return wsize;
|
||||
}
|
||||
|
||||
static int blk_fops_flush(struct dfs_file *file)
|
||||
{
|
||||
struct rt_device *dev = file->vnode->data;
|
||||
|
||||
return (int)rt_device_control(dev, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL);
|
||||
}
|
||||
|
||||
static int blk_fops_poll(struct dfs_file *file, struct rt_pollreq *req)
|
||||
{
|
||||
int mask = 0;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
const static struct dfs_file_ops blk_fops =
|
||||
{
|
||||
.open = blk_fops_open,
|
||||
.close = blk_fops_close,
|
||||
.ioctl = blk_fops_ioctl,
|
||||
.read = blk_fops_read,
|
||||
.write = blk_fops_write,
|
||||
.flush = blk_fops_flush,
|
||||
.lseek = generic_dfs_lseek,
|
||||
.poll = blk_fops_poll
|
||||
};
|
||||
|
||||
void device_set_blk_fops(struct rt_device *dev)
|
||||
{
|
||||
dev->fops = &blk_fops;
|
||||
}
|
||||
#else
|
||||
void device_set_blk_fops(struct rt_device *dev)
|
||||
{
|
||||
}
|
||||
#endif /* RT_USING_POSIX_DEVIO && RT_USING_DFS_V2 */
|
||||
|
||||
void device_get_blk_ssize(struct rt_device *dev, void *args)
|
||||
{
|
||||
rt_uint32_t bytes_per_sector;
|
||||
struct rt_device_blk_geometry geometry;
|
||||
|
||||
rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
|
||||
bytes_per_sector = geometry.bytes_per_sector;
|
||||
|
||||
RT_ASSERT(sizeof(bytes_per_sector) == sizeof(geometry.bytes_per_sector));
|
||||
|
||||
rt_memcpy(args, &bytes_per_sector, sizeof(bytes_per_sector));
|
||||
}
|
||||
|
||||
void device_get_all_blk_ssize(struct rt_device *dev, void *args)
|
||||
{
|
||||
rt_uint64_t count_mul_per;
|
||||
struct rt_device_blk_geometry geometry;
|
||||
|
||||
rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
|
||||
count_mul_per = geometry.bytes_per_sector * geometry.sector_count;
|
||||
|
||||
rt_memcpy(args, &count_mul_per, sizeof(count_mul_per));
|
||||
}
|
||||
Reference in New Issue
Block a user