mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 19:36:35 +08:00
drivrs/mtd/filemtd.c: add block device MTD interface. Block MTD interface allows using block device directly as MTD instead of having to use file-system in between. NOTE that this provides the opposite capability of FTL which will let you use an MTD interface directly as a block device.
This commit is contained in:
committed by
Gregory Nutt
parent
0ef127e273
commit
5ef548677a
+85
-42
@@ -116,7 +116,7 @@ static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset,
|
|||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int filemtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
static int filemtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks);
|
size_t nblocks);
|
||||||
static ssize_t filemtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t filemtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf);
|
size_t nblocks, FAR uint8_t *buf);
|
||||||
@@ -128,7 +128,7 @@ static ssize_t filemtd_byteread(FAR struct mtd_dev_s *dev, off_t offset,
|
|||||||
static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
|
static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
|
||||||
size_t nbytes, FAR const uint8_t *buf);
|
size_t nbytes, FAR const uint8_t *buf);
|
||||||
#endif
|
#endif
|
||||||
static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
|
static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
|
||||||
unsigned long arg);
|
unsigned long arg);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -188,7 +188,7 @@ static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset,
|
|||||||
#ifdef CONFIG_DEBUG_FEATURES
|
#ifdef CONFIG_DEBUG_FEATURES
|
||||||
if (newvalue != srcvalue)
|
if (newvalue != srcvalue)
|
||||||
{
|
{
|
||||||
_err("ERROR: Bad write: source=%02x dest=%02x result=%02x\n",
|
ferr("ERROR: Bad write: source=%02x dest=%02x result=%02x\n",
|
||||||
srcvalue, oldvalue, newvalue);
|
srcvalue, oldvalue, newvalue);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -227,7 +227,7 @@ static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset,
|
|||||||
|
|
||||||
static ssize_t filemtd_read(FAR struct file_dev_s *priv,
|
static ssize_t filemtd_read(FAR struct file_dev_s *priv,
|
||||||
FAR unsigned char *buffer, size_t offsetbytes,
|
FAR unsigned char *buffer, size_t offsetbytes,
|
||||||
unsigned int nbytes)
|
unsigned int nbytes)
|
||||||
{
|
{
|
||||||
/* Set the starting location in the file */
|
/* Set the starting location in the file */
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ static ssize_t filemtd_read(FAR struct file_dev_s *priv,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int filemtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
static int filemtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks)
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
@@ -294,7 +294,7 @@ static int filemtd_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t filemtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t filemtd_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf)
|
size_t nblocks, FAR uint8_t *buf)
|
||||||
{
|
{
|
||||||
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
@@ -374,7 +374,7 @@ static ssize_t filemtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t filemtd_byteread(FAR struct mtd_dev_s *dev, off_t offset,
|
static ssize_t filemtd_byteread(FAR struct mtd_dev_s *dev, off_t offset,
|
||||||
size_t nbytes, FAR uint8_t *buf)
|
size_t nbytes, FAR uint8_t *buf)
|
||||||
{
|
{
|
||||||
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
||||||
|
|
||||||
@@ -423,7 +423,8 @@ static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
|
|||||||
* Name: filemtd_ioctl
|
* Name: filemtd_ioctl
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
|
||||||
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
|
||||||
int ret = -EINVAL; /* Assume good command with bad parameters */
|
int ret = -EINVAL; /* Assume good command with bad parameters */
|
||||||
@@ -475,24 +476,23 @@ static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: filemtd_initialize
|
* Name: blockmtd_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Create and initialize a FILE MTD device instance.
|
* Create and initialize a BLOCK MTD device instance.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* path - Path name of the file backing the MTD device
|
* path - Path name of the block device backing the MTD device
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
FAR struct mtd_dev_s *blockmtd_initialize(FAR const char *path, size_t offset,
|
||||||
int16_t sectsize, int32_t erasesize)
|
size_t mtdlen, int16_t sectsize,
|
||||||
|
int32_t erasesize)
|
||||||
{
|
{
|
||||||
FAR struct file_dev_s *priv;
|
FAR struct file_dev_s *priv;
|
||||||
struct stat sb;
|
|
||||||
size_t nblocks;
|
size_t nblocks;
|
||||||
size_t filelen;
|
int mode;
|
||||||
int mode, ret;
|
|
||||||
|
|
||||||
/* Create an instance of the FILE MTD device state structure */
|
/* Create an instance of the FILE MTD device state structure */
|
||||||
|
|
||||||
@@ -505,23 +505,14 @@ FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
|||||||
|
|
||||||
/* Determine the file open mode */
|
/* Determine the file open mode */
|
||||||
|
|
||||||
mode = O_RDOK;
|
mode = O_RDOK;
|
||||||
#ifdef CONFIG_FS_WRITABLE
|
#ifdef CONFIG_FS_WRITABLE
|
||||||
mode |= O_WROK;
|
mode |= O_WROK;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Stat the file */
|
/* Try to open the file. NOTE that block devices will use a character
|
||||||
|
* driver proxy.
|
||||||
ret = stat(path, &sb);
|
*/
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
_err("ERROR: Failed to stat %s: %d\n", path, get_errno());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
filelen = sb.st_size;
|
|
||||||
|
|
||||||
/* Try to open the file */
|
|
||||||
|
|
||||||
priv->fd = open(path, mode);
|
priv->fd = open(path, mode);
|
||||||
if (priv->fd == -1)
|
if (priv->fd == -1)
|
||||||
@@ -555,7 +546,7 @@ FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
|||||||
|
|
||||||
/* Force the size to be an even number of the erase block size */
|
/* Force the size to be an even number of the erase block size */
|
||||||
|
|
||||||
nblocks = (filelen - offset) / priv->erasesize;
|
nblocks = mtdlen / priv->erasesize;
|
||||||
if (nblocks < 3)
|
if (nblocks < 3)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Need to provide at least three full erase block\n");
|
ferr("ERROR: Need to provide at least three full erase block\n");
|
||||||
@@ -578,9 +569,9 @@ FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
|||||||
priv->offset = offset;
|
priv->offset = offset;
|
||||||
priv->nblocks = nblocks;
|
priv->nblocks = nblocks;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MTD_REGISTRATION
|
||||||
/* Register the MTD with the procfs system if enabled */
|
/* Register the MTD with the procfs system if enabled */
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_REGISTRATION
|
|
||||||
mtd_register(&priv->mtd, "filemtd");
|
mtd_register(&priv->mtd, "filemtd");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -588,17 +579,17 @@ FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: filemtd_teardown
|
* Name: blockmtd_teardown
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Teardown a previously created filemtd device.
|
* Teardown a previously created blockmtd device.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* path - Path name of the file backing the MTD device
|
* mtd - Pointer to the mtd.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void filemtd_teardown(FAR struct mtd_dev_s *dev)
|
void blockmtd_teardown(FAR struct mtd_dev_s *dev)
|
||||||
{
|
{
|
||||||
FAR struct file_dev_s *priv;
|
FAR struct file_dev_s *priv;
|
||||||
|
|
||||||
@@ -607,9 +598,9 @@ void filemtd_teardown(FAR struct mtd_dev_s *dev)
|
|||||||
priv = (FAR struct file_dev_s *) dev;
|
priv = (FAR struct file_dev_s *) dev;
|
||||||
close(priv->fd);
|
close(priv->fd);
|
||||||
|
|
||||||
/* Register the MTD with the procfs system if enabled */
|
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_REGISTRATION
|
#ifdef CONFIG_MTD_REGISTRATION
|
||||||
|
/* Un-register the MTD with the procfs system if enabled */
|
||||||
|
|
||||||
mtd_unregister(&priv->mtd);
|
mtd_unregister(&priv->mtd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -618,11 +609,66 @@ void filemtd_teardown(FAR struct mtd_dev_s *dev)
|
|||||||
kmm_free(priv);
|
kmm_free(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: filemtd_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Create and initialize a FILE MTD device instance.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* path - Path name of the file backing the MTD device
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
||||||
|
int16_t sectsize, int32_t erasesize)
|
||||||
|
{
|
||||||
|
size_t filelen;
|
||||||
|
struct stat sb;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Stat the file */
|
||||||
|
|
||||||
|
ret = stat(path, &sb);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
ferr("ERROR: Failed to stat %s: %d\n", path, get_errno());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
filelen = sb.st_size;
|
||||||
|
|
||||||
|
if (offset > filelen)
|
||||||
|
{
|
||||||
|
ferr("ERROR: Offset beyond end of file\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockmtd_initialize(path, offset, filelen - offset, sectsize,
|
||||||
|
erasesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: filemtd_teardown
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Teardown a previously created filemtd device.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* mtd - Pointer to the mtd.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void filemtd_teardown(FAR struct mtd_dev_s *dev)
|
||||||
|
{
|
||||||
|
blockmtd_teardown(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: filemtd_isfilemtd
|
* Name: filemtd_isfilemtd
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Tests if the provided mtd is a filemtd device.
|
* Tests if the provided mtd is a filemtd or blockmtd device.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* mtd - Pointer to the mtd.
|
* mtd - Pointer to the mtd.
|
||||||
@@ -633,8 +679,5 @@ bool filemtd_isfilemtd(FAR struct mtd_dev_s *dev)
|
|||||||
{
|
{
|
||||||
FAR struct file_dev_s *priv = (FAR struct file_dev_s *) dev;
|
FAR struct file_dev_s *priv = (FAR struct file_dev_s *) dev;
|
||||||
|
|
||||||
if (priv->mtd.erase == filemtd_erase)
|
return (priv->mtd.erase == filemtd_erase);
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-1
@@ -560,6 +560,28 @@ FAR struct mtd_dev_s *mx25rxx_initialize(FAR struct qspi_dev_s *qspi,
|
|||||||
FAR struct mtd_dev_s *n25qxxx_initialize(FAR struct qspi_dev_s *qspi,
|
FAR struct mtd_dev_s *n25qxxx_initialize(FAR struct qspi_dev_s *qspi,
|
||||||
bool unprotect);
|
bool unprotect);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: blockmtd_initialize
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Create a block device backed a MTD device.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct mtd_dev_s *blockmtd_initialize(FAR const char *path, size_t offset,
|
||||||
|
size_t mtdlen, int16_t sectsize,
|
||||||
|
int32_t erasesize);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: blockmtd_teardown
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Tear down a blockmtd device.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void blockmtd_teardown(FAR struct mtd_dev_s *dev);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: filemtd_initialize
|
* Name: filemtd_initialize
|
||||||
*
|
*
|
||||||
@@ -569,7 +591,7 @@ FAR struct mtd_dev_s *n25qxxx_initialize(FAR struct qspi_dev_s *qspi,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset,
|
||||||
int16_t sectsize, int32_t erasesize);
|
int16_t sectsize, int32_t erasesize);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: filemtd_teardown
|
* Name: filemtd_teardown
|
||||||
|
|||||||
Reference in New Issue
Block a user