nuttx/drivers/mtd/mtd_nandwrapper.c
Saurav Pal 0be6dfb552 fs/mnemofs: Refactor path logic, direntry size bug fix, open free bug fix
Refactoring path logic to prevent logic flaws, direntry size bug fix to allow proper direntry traversal, open free bug fix to prevent memory leak after close.

Signed-off-by: Saurav Pal <resyfer.dev@gmail.com>
2024-08-09 09:00:17 +02:00

419 lines
13 KiB
C

/****************************************************************************
* drivers/mtd/mtd_nandwrapper.c
* This deals with the wrapper over the upper half of the driver, to enable
* logging for debugging, and essentially passes the parameters right to the
* actual upper half of the NAND Flash device driver without changing them.
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <assert.h>
#include <stddef.h>
#include <nuttx/config.h>
#include <nuttx/mtd/nand.h>
#include <nuttx/mtd/nand_ram.h>
#include <nuttx/mtd/nand_scheme.h>
#include <nuttx/mtd/nand_wrapper.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define NAND_WRAPPER_DEBUG_1 1
#define NAND_WRAPPER_DEBUG_2 5
#define NAND_WRAPPER_DEBUG_3 10
#if CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL == 1
#define NAND_WRAPPER_DEBUG_LEVEL NAND_WRAPPER_DEBUG_1
#elif CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL == 2
#define NAND_WRAPPER_DEBUG_LEVEL NAND_WRAPPER_DEBUG_2
#elif CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL == 3
#define NAND_WRAPPER_DEBUG_LEVEL NAND_WRAPPER_DEBUG_3
#endif /* CONFIG_MTD_NAND_WRAPPER_DEBUG_LEVEL */
#define NAND_WRAPPER_LOG(str, ...) \
{ \
if(nand_wrapper_ins_i % NAND_WRAPPER_DEBUG_LEVEL == 0) \
{ \
syslog(LOG_DEBUG, "nand_wrapper: " str, __VA_ARGS__); \
} \
}
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static uint64_t nand_wrapper_ins_i = 0; /* Instruction counter */
static mutex_t nand_wrapper_dev_mut;
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nand_wrapper_erase
*
* Description:
* Wrapper for NAND MTD erase method.
*
* Input Parameters:
* dev: NAND MTD Device (with an actual type of `nand_wrapper_dev_s`
* startblock: Block number (0-indexing) to start erasing
* nblocks: Number of blocks to erase
*
* Returned Value:
* 0: Successful
* < 0: Error
*
* Assumptions/Limitations:
* This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
*
****************************************************************************/
int nand_wrapper_erase(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks)
{
int ret;
FAR struct nand_wrapper_dev_s *nand_dev;
nand_dev = (struct nand_wrapper_dev_s *)dev;
nxmutex_lock(&nand_wrapper_dev_mut);
nand_wrapper_ins_i++;
NAND_WRAPPER_LOG("[UPPER %lu | %s] Startblock: %d, N Blocks: %ld\n",
nand_wrapper_ins_i, "erase", startblock, nblocks);
DEBUGASSERT(nand_dev && nand_dev->under.mtd.erase);
ret = nand_dev->under.mtd.erase(dev, startblock, nblocks);
if (ret >= 0)
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
nand_wrapper_ins_i, "erase");
}
else
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
nand_wrapper_ins_i, "erase", ret);
}
nxmutex_unlock(&nand_wrapper_dev_mut);
return ret;
}
/****************************************************************************
* Name: nand_wrapper_bread
*
* Description:
* Wrapper for NAND MTD bread method.
*
* Input Parameters:
* dev: MTD Device
* startpage: Page number (0-indexing) to start reading
* npages: Number of pages to read.
* buffer: Preallocated memory where the data will be copied to
*
* Returned Value:
* 0: Successful
* < 0: Error
*
* Assumptions/Limitations:
* This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
*
****************************************************************************/
ssize_t nand_wrapper_bread(FAR struct mtd_dev_s *dev, off_t startpage,
size_t npages, FAR uint8_t *buffer)
{
int ret;
FAR struct nand_wrapper_dev_s *nand_dev;
nand_dev = (struct nand_wrapper_dev_s *)dev;
nxmutex_lock(&nand_wrapper_dev_mut);
nand_wrapper_ins_i++;
NAND_WRAPPER_LOG("[UPPER %lu | %s] "
"Startblock: %d, N Pages: %ld, Buffer: %p\n",
nand_wrapper_ins_i, "bread", startpage, npages, buffer);
DEBUGASSERT(nand_dev && nand_dev->under.mtd.bread);
ret = nand_dev->under.mtd.bread(dev, startpage, npages, buffer);
if (ret >= 0)
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
nand_wrapper_ins_i, "bread");
}
else
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
nand_wrapper_ins_i, "bread", ret);
}
nxmutex_unlock(&nand_wrapper_dev_mut);
return ret;
}
/****************************************************************************
* Name: nand_wrapper_bwrite
*
* Description:
* Wrapper for NAND MTD bwrite method.
*
* Input Parameters:
* dev: MTD Device
* startpage: Page number (0-indexing) to start reading
* npages: Number of pages to read.
* buffer: Data which will be written to the device
*
* Returned Value:
* 0: Successful
* < 0: Error
*
* Assumptions/Limitations:
* This assumes the length of `buffer` would be the same as the size of
* `npages * block_size`. This also assumes `dev` is specifically of
* type `struct nand_wrapper_dev_s *`
*
****************************************************************************/
ssize_t nand_wrapper_bwrite(FAR struct mtd_dev_s *dev, off_t startpage,
size_t npages, FAR const uint8_t *buffer)
{
int ret;
FAR struct nand_wrapper_dev_s *nand_dev;
nand_dev = (struct nand_wrapper_dev_s *)dev;
nxmutex_lock(&nand_wrapper_dev_mut);
nand_wrapper_ins_i++;
NAND_WRAPPER_LOG("[UPPER %lu | %s] "
"Startblock: %d, N Pages: %ld, Buffer: %p \n",
nand_wrapper_ins_i, "bwrite", startpage, npages, buffer);
DEBUGASSERT(nand_dev && nand_dev->under.mtd.bwrite);
ret = nand_dev->under.mtd.bwrite(dev, startpage, npages, buffer);
if (ret >= 0)
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
nand_wrapper_ins_i, "bwrite");
}
else
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
nand_wrapper_ins_i, "bwrite", ret);
}
nxmutex_unlock(&nand_wrapper_dev_mut);
return ret;
}
/****************************************************************************
* Name: nand_wrapper_ioctl
*
* Description:
* Wrapper for NAND MTD ioctl method.
*
* Input Parameters:
* dev: MTD Device
* cmd: Command for IOCTL
* arg: Any argument required by command
*
* Returned Value:
* 0: Successful
* < 0: Error
*
* Assumptions/Limitations:
* This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
*
****************************************************************************/
int nand_wrapper_ioctl(FAR struct mtd_dev_s *dev, int cmd,
unsigned long arg)
{
int ret;
FAR struct nand_wrapper_dev_s *nand_dev;
nand_dev = (struct nand_wrapper_dev_s *)dev;
nxmutex_lock(&nand_wrapper_dev_mut);
nand_wrapper_ins_i++;
NAND_WRAPPER_LOG("[UPPER %lu | %s] Command: %d, Arg : %ld\n",
nand_wrapper_ins_i, "ioctl", cmd, arg);
DEBUGASSERT(nand_dev && nand_dev->under.mtd.ioctl);
ret = nand_dev->under.mtd.ioctl(dev, cmd, arg);
if (ret >= 0)
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
nand_wrapper_ins_i, "ioctl");
}
else
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
nand_wrapper_ins_i, "ioctl", ret);
}
nxmutex_unlock(&nand_wrapper_dev_mut);
return ret;
}
/****************************************************************************
* Name: nand_wrapper_isbad
*
* Description:
* Wrapper for NAND MTD isbad method.
*
* Input Parameters:
* dev: MTD Device
* block: Block number (0-indexing) to check if it is bad
*
* Returned Value:
* 0: Successful
* < 0: Error
*
* Assumptions/Limitations:
* This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
*
****************************************************************************/
int nand_wrapper_isbad(FAR struct mtd_dev_s *dev, off_t block)
{
int ret;
FAR struct nand_wrapper_dev_s *nand_dev;
nand_dev = (struct nand_wrapper_dev_s *)dev;
nxmutex_lock(&nand_wrapper_dev_mut);
nand_wrapper_ins_i++;
NAND_WRAPPER_LOG("[UPPER %lu | %s] Block: %d\n",
nand_wrapper_ins_i, "isbad", block);
DEBUGASSERT(nand_dev && nand_dev->under.mtd.isbad);
ret = nand_dev->under.mtd.isbad(dev, block);
if (ret >= 0)
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Done %d\n",
nand_wrapper_ins_i, "isbad", ret);
}
else
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
nand_wrapper_ins_i, "isbad", ret);
}
nxmutex_unlock(&nand_wrapper_dev_mut);
return ret;
}
/****************************************************************************
* Name: nand_wrapper_markbad
*
* Description:
* Wrapper for NAND MTD markbad method.
*
* Input Parameters:
* dev: MTD Device
* block: Block number (0-indexing) to mark it as bad
*
* Returned Value:
* 0: Successful
* < 0: Error
*
* Assumptions/Limitations:
* This assumes `dev` is specifically of type `struct nand_wrapper_dev_s *`
*
****************************************************************************/
int nand_wrapper_markbad(FAR struct mtd_dev_s *dev, off_t block)
{
int ret;
FAR struct nand_wrapper_dev_s *nand_dev;
nand_dev = (struct nand_wrapper_dev_s *)dev;
nxmutex_lock(&nand_wrapper_dev_mut);
nand_wrapper_ins_i++;
NAND_WRAPPER_LOG("[UPPER %lu | %s] Blocks: %d\n",
nand_wrapper_ins_i, "markbad", block);
DEBUGASSERT(nand_dev && nand_dev->under.mtd.markbad);
ret = nand_dev->under.mtd.markbad(dev, block);
if (ret >= 0)
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Done\n",
nand_wrapper_ins_i, "markbad");
}
else
{
NAND_WRAPPER_LOG("[UPPER %lu | %s] Failed: %d!\n",
nand_wrapper_ins_i, "markbad", ret);
}
nxmutex_unlock(&nand_wrapper_dev_mut);
return ret;
}
/****************************************************************************
* Name: nand_wrapper_initialize
*
* Description:
* Initializes wrapper.
*
* Returned Value:
* 0: Successful
* < 0: Error
*
****************************************************************************/
void nand_wrapper_initialize(void)
{
nxmutex_init(&nand_wrapper_dev_mut);
}