summaryrefslogtreecommitdiff
path: root/nuttx/drivers/rwbuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/drivers/rwbuffer.c')
-rw-r--r--nuttx/drivers/rwbuffer.c601
1 files changed, 452 insertions, 149 deletions
diff --git a/nuttx/drivers/rwbuffer.c b/nuttx/drivers/rwbuffer.c
index 0435440dd..c54277ddb 100644
--- a/nuttx/drivers/rwbuffer.c
+++ b/nuttx/drivers/rwbuffer.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/rwbuffer.c
*
- * Copyright (C) 2009, 2011, 2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2009, 2011, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,7 @@
#include <nuttx/wqueue.h>
#include <nuttx/rwbuffer.h>
-#if defined(CONFIG_FS_WRITEBUFFER) || defined(CONFIG_FS_READAHEAD)
+#if defined(CONFIG_DRVR_WRITEBUFFER) || defined(CONFIG_DRVR_READAHEAD)
/****************************************************************************
* Preprocessor Definitions
@@ -66,8 +66,8 @@
# error "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
#endif
-#ifndef CONFIG_FS_WRDELAY
-# define CONFIG_FS_WRDELAY 350
+#ifndef CONFIG_DRVR_WRDELAY
+# define CONFIG_DRVR_WRDELAY 350
#endif
/****************************************************************************
@@ -137,7 +137,7 @@ static inline bool rwb_overlap(off_t blockstart1, size_t nblocks1,
* Name: rwb_resetwrbuffer
****************************************************************************/
-#ifdef CONFIG_FS_WRITEBUFFER
+#ifdef CONFIG_DRVR_WRITEBUFFER
static inline void rwb_resetwrbuffer(struct rwbuffer_s *rwb)
{
/* We assume that the caller holds the wrsem */
@@ -152,7 +152,7 @@ static inline void rwb_resetwrbuffer(struct rwbuffer_s *rwb)
* Name: rwb_wrflush
****************************************************************************/
-#ifdef CONFIG_FS_WRITEBUFFER
+#ifdef CONFIG_DRVR_WRITEBUFFER
static void rwb_wrflush(struct rwbuffer_s *rwb)
{
int ret;
@@ -160,7 +160,7 @@ static void rwb_wrflush(struct rwbuffer_s *rwb)
fvdbg("Timeout!\n");
rwb_semtake(&rwb->wrsem);
- if (rwb->wrnblocks)
+ if (rwb->wrnblocks > 0)
{
fvdbg("Flushing: blockstart=0x%08lx nblocks=%d from buffer=%p\n",
(long)rwb->wrblockstart, rwb->wrnblocks, rwb->wrbuffer);
@@ -208,11 +208,11 @@ static void rwb_wrtimeout(FAR void *arg)
static void rwb_wrstarttimeout(FAR struct rwbuffer_s *rwb)
{
- /* CONFIG_FS_WRDELAY provides the delay period in milliseconds. CLK_TCK
+ /* CONFIG_DRVR_WRDELAY provides the delay period in milliseconds. CLK_TCK
* provides the clock tick of the system (frequency in Hz).
*/
- int ticks = (CONFIG_FS_WRDELAY + CLK_TCK/2) / CLK_TCK;
+ int ticks = (CONFIG_DRVR_WRDELAY + CLK_TCK/2) / CLK_TCK;
(void)work_queue(LPWORK, &rwb->work, rwb_wrtimeout, (FAR void *)rwb, ticks);
}
@@ -229,7 +229,7 @@ static inline void rwb_wrcanceltimeout(struct rwbuffer_s *rwb)
* Name: rwb_writebuffer
****************************************************************************/
-#ifdef CONFIG_FS_WRITEBUFFER
+#ifdef CONFIG_DRVR_WRITEBUFFER
static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb,
off_t startblock, uint32_t nblocks,
FAR const uint8_t *wrbuffer)
@@ -265,7 +265,7 @@ static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb,
/* writebuffer is empty? Then initialize it */
- if (!rwb->wrnblocks)
+ if (rwb->wrnblocks == 0)
{
fvdbg("Fresh cache starting at block: 0x%08x\n", startblock);
rwb->wrblockstart = startblock;
@@ -290,7 +290,7 @@ static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb,
* Name: rwb_resetrhbuffer
****************************************************************************/
-#ifdef CONFIG_FS_READAHEAD
+#ifdef CONFIG_DRVR_READAHEAD
static inline void rwb_resetrhbuffer(struct rwbuffer_s *rwb)
{
/* We assume that the caller holds the readAheadBufferSemphore */
@@ -304,7 +304,7 @@ static inline void rwb_resetrhbuffer(struct rwbuffer_s *rwb)
* Name: rwb_bufferread
****************************************************************************/
-#ifdef CONFIG_FS_READAHEAD
+#ifdef CONFIG_DRVR_READAHEAD
static inline void
rwb_bufferread(struct rwbuffer_s *rwb, off_t startblock,
size_t nblocks, uint8_t **rdbuffer)
@@ -338,7 +338,7 @@ rwb_bufferread(struct rwbuffer_s *rwb, off_t startblock,
* Name: rwb_rhreload
****************************************************************************/
-#ifdef CONFIG_FS_READAHEAD
+#ifdef CONFIG_DRVR_READAHEAD
static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock)
{
/* Get the block number +1 of the last block that will fit in the
@@ -382,6 +382,231 @@ static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock)
#endif
/****************************************************************************
+ * Name: rwb_invalidate_writebuffer
+ *
+ * Description:
+ * Invalidate a region of the write buffer
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DRVR_WRITEBUFFER
+int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb,
+ off_t startblock, size_t blockcount)
+{
+ int ret;
+
+ if (rwb->wrmaxblocks > 0 && wrnblocks > 0)
+ {
+ off_t wrbend;
+ off_t invend;
+
+ fvdbg("startblock=%d blockcount=%p\n", startblock, blockcount);
+
+ rwb_semtake(&rwb->wrsem);
+
+ /* Now there are five cases:
+ *
+ * 1. We invalidate nothing
+ */
+
+ wrbend = rwb->wrblockstart + rwb->wrnblocks;
+ invend = startblock + blockcount;
+
+ if (rwb->wrblockstart > invend || wrbend < startblock)
+ {
+ ret = OK;
+ }
+
+ /* 2. We invalidate the entire write buffer. */
+
+ else if (rwb->wrblockstart >= startblock && wrbend <= invend)
+ {
+ rwb->wrnblocks = 0;
+ ret = OK;
+ }
+
+ /* We are going to invalidate a subset of the write buffer. Three
+ * more cases to consider:
+ *
+ * 2. We invalidate a portion in the middle of the write buffer
+ */
+
+ else if (rwb->wrblockstart < startblock && wrbend > invend)
+ {
+ uint8_t *src;
+ off_t block;
+ off_t offset;
+ size_t nblocks;
+
+ /* Write the blocks at the end of the media to hardware */
+
+ nblocks = wrbend - invend;
+ block = invend;
+ offset = block - rwb->wrblockstart;
+ src = rwb->wrbuffer + offset * rwb->blocksize;
+
+ ret = rwb->wrflush(rwb->dev, block, nblocks, src);
+ if (ret < 0)
+ {
+ fdbg("ERROR: wrflush failed: %d\n", ret);
+ }
+
+ /* Keep the blocks at the beginning of the buffer up the
+ * start of the invalidated region.
+ */
+ else
+ {
+ rwb->wrnblocks = startblock - rwb->wrblockstart;
+ ret = OK;
+ }
+ }
+
+ /* 3. We invalidate a portion at the end of the write buffer */
+
+ else if (wrbend > startblock && wrbend <= invend)
+ {
+ rwb->wrnblocks = wrbend - startblock;
+ ret = OK;
+ }
+
+ /* 4. We invalidate a portion at the beginning of the write buffer */
+
+ else /* if (rwb->wrblockstart >= startblock && wrbend < invend) */
+ {
+ uint8_t *src;
+ size_t ninval;
+ size_t nkeep;
+
+ DEBUGASSERT(rwb->wrblockstart >= startblock && wrbend < invend);
+
+ /* Copy the data from the uninvalidated region to the beginning
+ * of the write buffer.
+ *
+ * First calculate the source and destination of the transfer.
+ */
+
+ ninval = invend - rwb->wrblockstart;
+ src = rwb->wrbuffer + ninval * rwb->blocksize;
+
+ /* Calculate the number of blocks we are keeping. We keep
+ * the ones that we don't invalidate.
+ */
+
+ nkeep = rwb->wrnblocks - ninval;
+
+ /* Then move the data that we are keeping to the beginning
+ * the write buffer.
+ */
+
+ memcpy(rwb->wrbuffer, src, nkeep * rwb->blocksize);
+
+ /* Update the block info. The first block is now the one just
+ * after the invalidation region and the number buffered blocks
+ * is the number that we kept.
+ */
+
+ rwb->wrblockstart = invend;
+ rwb->wrnblocks = nkeep;
+ ret = OK;
+ }
+
+ rwb_semgive(&rwb->wrsem);
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: rwb_invalidate_readahead
+ *
+ * Description:
+ * Invalidate a region of the read-ahead buffer
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DRVR_READAHEAD
+int rwb_invalidate_readahead(FAR struct rwbuffer_s *rwb,
+ off_t startblock, size_t blockcount)
+{
+ int ret;
+
+ if (rwb->rhmaxblocks > 0 && rhnblocks > 0)
+ {
+ off_t rhbend;
+ off_t invend;
+
+ fvdbg("startblock=%d blockcount=%p\n", startblock, blockcount);
+
+ rwb_semtake(&rwb->rhsem);
+
+ /* Now there are five cases:
+ *
+ * 1. We invalidate nothing
+ */
+
+ rhbend = rwb->rhblockstart + rwb->rhnblocks;
+ invend = startblock + blockcount;
+
+ if (rwb->rhblockstart > invend || rhbend < startblock)
+ {
+ ret = OK;
+ }
+
+ /* 2. We invalidate the entire read-ahead buffer. */
+
+ else if (rwb->rhblockstart >= startblock && rhbend <= invend)
+ {
+ rwb->rhnblocks = 0;
+ ret = OK;
+ }
+
+ /* We are going to invalidate a subset of the read-ahead buffer.
+ * Three more cases to consider:
+ *
+ * 2. We invalidate a portion in the middle of the write buffer
+ */
+
+ else if (rwb->rhblockstart < startblock && rhbend > invend)
+ {
+ /* Keep the blocks at the beginning of the buffer up the
+ * start of the invalidated region.
+ */
+
+ rwb->rhnblocks = startblock - rwb->rhblockstart;
+ ret = OK;
+ }
+
+ /* 3. We invalidate a portion at the end of the read-ahead buffer */
+
+ else if (rhbend > startblock && rhbend <= invend)
+ {
+ rwb->rhnblocks = rhbend - startblock;
+ ret = OK;
+ }
+
+ /* 4. We invalidate a portion at the beginning of the write buffer */
+
+ else /* if (rwb->rhblockstart >= startblock && rhbend < invend) */
+ {
+ /* Let's just force the whole read-ahead buffer to be reloaded.
+ * That might cost s small amount of performance, but well worth
+ * the lower complexity.
+ */
+
+ DEBUGASSERT(rwb->rhblockstart >= startblock && rhbend < invend);
+ rwb->rhnblocks = 0;
+ ret = OK;
+ }
+
+ rwb_semgive(&rwb->rhsem);
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
@@ -401,71 +626,78 @@ int rwb_initialize(FAR struct rwbuffer_s *rwb)
/* Setup so that rwb_uninitialize can handle a failure */
-#ifdef CONFIG_FS_WRITEBUFFER
+#ifdef CONFIG_DRVR_WRITEBUFFER
DEBUGASSERT(rwb->wrflush!= NULL);
rwb->wrbuffer = NULL;
#endif
-#ifdef CONFIG_FS_READAHEAD
+#ifdef CONFIG_DRVR_READAHEAD
DEBUGASSERT(rwb->rhreload != NULL);
rwb->rhbuffer = NULL;
#endif
-#ifdef CONFIG_FS_WRITEBUFFER
- fvdbg("Initialize the write buffer\n");
+#ifdef CONFIG_DRVR_WRITEBUFFER
+ if (rwb->wrmaxblocks > 0)
+ {
+ fvdbg("Initialize the write buffer\n");
- /* Initialize the write buffer access semaphore */
+ /* Initialize the write buffer access semaphore */
- sem_init(&rwb->wrsem, 0, 1);
+ sem_init(&rwb->wrsem, 0, 1);
- /* Initialize write buffer parameters */
+ /* Initialize write buffer parameters */
- rwb_resetwrbuffer(rwb);
+ rwb_resetwrbuffer(rwb);
- /* Allocate the write buffer */
+ /* Allocate the write buffer */
- rwb->wrbuffer = NULL;
- if (rwb->wrmaxblocks > 0)
- {
- allocsize = rwb->wrmaxblocks * rwb->blocksize;
- rwb->wrbuffer = kmalloc(allocsize);
- if (!rwb->wrbuffer)
+ rwb->wrbuffer = NULL;
+ if (rwb->wrmaxblocks > 0)
{
- fdbg("Write buffer kmalloc(%d) failed\n", allocsize);
- return -ENOMEM;
+ allocsize = rwb->wrmaxblocks * rwb->blocksize;
+ rwb->wrbuffer = kmalloc(allocsize);
+ if (!rwb->wrbuffer)
+ {
+ fdbg("Write buffer kmalloc(%d) failed\n", allocsize);
+ return -ENOMEM;
+ }
}
- }
- fvdbg("Write buffer size: %d bytes\n", allocsize);
-#endif /* CONFIG_FS_WRITEBUFFER */
+ fvdbg("Write buffer size: %d bytes\n", allocsize);
+ }
+#endif /* CONFIG_DRVR_WRITEBUFFER */
-#ifdef CONFIG_FS_READAHEAD
- fvdbg("Initialize the read-ahead buffer\n");
+#ifdef CONFIG_DRVR_READAHEAD
+ if (rhmaxblocks > 0)
+ {
+ fvdbg("Initialize the read-ahead buffer\n");
- /* Initialize the read-ahead buffer access semaphore */
+ /* Initialize the read-ahead buffer access semaphore */
- sem_init(&rwb->rhsem, 0, 1);
+ sem_init(&rwb->rhsem, 0, 1);
- /* Initialize read-ahead buffer parameters */
+ /* Initialize read-ahead buffer parameters */
- rwb_resetrhbuffer(rwb);
+ rwb_resetrhbuffer(rwb);
- /* Allocate the read-ahead buffer */
+ /* Allocate the read-ahead buffer */
- rwb->rhbuffer = NULL;
- if (rwb->rhmaxblocks > 0)
- {
- allocsize = rwb->rhmaxblocks * rwb->blocksize;
- rwb->rhbuffer = kmalloc(allocsize);
- if (!rwb->rhbuffer)
+ rwb->rhbuffer = NULL;
+ if (rwb->rhmaxblocks > 0)
{
- fdbg("Read-ahead buffer kmalloc(%d) failed\n", allocsize);
- return -ENOMEM;
+ allocsize = rwb->rhmaxblocks * rwb->blocksize;
+ rwb->rhbuffer = kmalloc(allocsize);
+ if (!rwb->rhbuffer)
+ {
+ fdbg("Read-ahead buffer kmalloc(%d) failed\n", allocsize);
+ return -ENOMEM;
+ }
}
+
+ fvdbg("Read-ahead buffer size: %d bytes\n", allocsize);
}
+#endif /* CONFIG_DRVR_READAHEAD */
- fvdbg("Read-ahead buffer size: %d bytes\n", allocsize);
-#endif /* CONFIG_FS_READAHEAD */
- return 0;
+ return OK;
}
/****************************************************************************
@@ -474,20 +706,26 @@ int rwb_initialize(FAR struct rwbuffer_s *rwb)
void rwb_uninitialize(FAR struct rwbuffer_s *rwb)
{
-#ifdef CONFIG_FS_WRITEBUFFER
- rwb_wrcanceltimeout(rwb);
- sem_destroy(&rwb->wrsem);
- if (rwb->wrbuffer)
+#ifdef CONFIG_DRVR_WRITEBUFFER
+ if (rwb->wrmaxblocks > 0)
{
- kfree(rwb->wrbuffer);
+ rwb_wrcanceltimeout(rwb);
+ sem_destroy(&rwb->wrsem);
+ if (rwb->wrbuffer)
+ {
+ kfree(rwb->wrbuffer);
+ }
}
#endif
-#ifdef CONFIG_FS_READAHEAD
- sem_destroy(&rwb->rhsem);
- if (rwb->rhbuffer)
+#ifdef CONFIG_DRVR_READAHEAD
+ if (rhmaxblocks > 0)
{
- kfree(rwb->rhbuffer);
+ sem_destroy(&rwb->rhsem);
+ if (rwb->rhbuffer)
+ {
+ kfree(rwb->rhbuffer);
+ }
}
#endif
}
@@ -504,7 +742,7 @@ int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32_t nblocks,
fvdbg("startblock=%ld nblocks=%ld rdbuffer=%p\n",
(long)startblock, (long)nblocks, rdbuffer);
-#ifdef CONFIG_FS_WRITEBUFFER
+#ifdef CONFIG_DRVR_WRITEBUFFER
/* If the new read data overlaps any part of the write buffer, then
* flush the write data onto the physical media before reading. We
* could attempt some more exotic handling -- but this simple logic
@@ -522,74 +760,86 @@ int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32_t nblocks,
{
rwb_wrflush(rwb);
}
+
rwb_semgive(&rwb->wrsem);
}
#endif
-#ifdef CONFIG_FS_READAHEAD
- /* Loop until we have read all of the requested blocks */
-
- rwb_semtake(&rwb->rhsem);
- for (remaining = nblocks; remaining > 0;)
+#ifdef CONFIG_DRVR_READAHEAD
+ if (rhmaxblocks > 0)
{
- /* Is there anything in the read-ahead buffer? */
+ /* Loop until we have read all of the requested blocks */
- if (rwb->rhnblocks > 0)
+ rwb_semtake(&rwb->rhsem);
+ for (remaining = nblocks; remaining > 0;)
{
- off_t startblock = startblock;
- size_t nbufblocks = 0;
- off_t bufferend;
+ /* Is there anything in the read-ahead buffer? */
- /* Loop for each block we find in the read-head buffer. Count the
- * number of buffers that we can read from read-ahead buffer.
- */
+ if (rwb->rhnblocks > 0)
+ {
+ off_t startblock = startblock;
+ size_t nbufblocks = 0;
+ off_t bufferend;
- bufferend = rwb->rhblockstart + rwb->rhnblocks;
+ /* Loop for each block we find in the read-head buffer. Count
+ * the number of buffers that we can read from read-ahead
+ * buffer.
+ */
- while ((startblock >= rwb->rhblockstart) &&
- (startblock < bufferend) &&
- (remaining > 0))
- {
- /* This is one more that we will read from the read ahead buffer */
+ bufferend = rwb->rhblockstart + rwb->rhnblocks;
- nbufblocks++;
+ while ((startblock >= rwb->rhblockstart) &&
+ (startblock < bufferend) &&
+ (remaining > 0))
+ {
+ /* This is one more that we will read from the read ahead
+ * buffer.
+ */
- /* And one less that we will read from the media */
+ nbufblocks++;
- startblock++;
- remaining--;
- }
+ /* And one less that we will read from the media */
- /* Then read the data from the read-ahead buffer */
+ startblock++;
+ remaining--;
+ }
- rwb_bufferread(rwb, startblock, nbufblocks, &rdbuffer);
- }
+ /* Then read the data from the read-ahead buffer */
- /* If we did not get all of the data from the buffer, then we have to refill
- * the buffer and try again.
- */
+ rwb_bufferread(rwb, startblock, nbufblocks, &rdbuffer);
+ }
- if (remaining > 0)
- {
- int ret = rwb_rhreload(rwb, startblock);
- if (ret < 0)
+ /* If we did not get all of the data from the buffer, then we have
+ * to refill the buffer and try again.
+ */
+
+ if (remaining > 0)
{
- fdbg("ERROR: Failed to fill the read-ahead buffer: %d\n", -ret);
- return ret;
+ int ret = rwb_rhreload(rwb, startblock);
+ if (ret < 0)
+ {
+ fdbg("ERROR: Failed to fill the read-ahead buffer: %d\n", ret);
+ return ret;
+ }
}
}
- }
- /* On success, return the number of blocks that we were requested to read.
- * This is for compatibility with the normal return of a block driver read
- * method
- */
+ /* On success, return the number of blocks that we were requested to
+ * read. This is for compatibility with the normal return of a block
+ * driver read method
+ */
- rwb_semgive(&rwb->rhsem);
- return 0;
+ rwb_semgive(&rwb->rhsem);
+ ret = nblocks;
+ }
+ else
#else
- return rwb->rhreload(rwb->dev, startblock, nblocks, rdbuffer);
+ {
+ ret = rwb->rhreload(rwb->dev, startblock, nblocks, rdbuffer);
+ }
#endif
+
+ return ret;
}
/****************************************************************************
@@ -601,82 +851,135 @@ int rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock,
{
int ret;
-#ifdef CONFIG_FS_READAHEAD
- /* If the new write data overlaps any part of the read buffer, then
- * flush the data from the read buffer. We could attempt some more
- * exotic handling -- but this simple logic is well-suited for simple
- * streaming applications.
- */
-
- rwb_semtake(&rwb->rhsem);
- if (rwb_overlap(rwb->rhblockstart, rwb->rhnblocks, startblock, nblocks))
+#ifdef CONFIG_DRVR_READAHEAD
+ if (rhmaxblocks > 0)
{
- rwb_resetrhbuffer(rwb);
+ /* If the new write data overlaps any part of the read buffer, then
+ * flush the data from the read buffer. We could attempt some more
+ * exotic handling -- but this simple logic is well-suited for simple
+ * streaming applications.
+ */
+
+ rwb_semtake(&rwb->rhsem);
+ if (rwb_overlap(rwb->rhblockstart, rwb->rhnblocks, startblock, nblocks))
+ {
+ rwb_resetrhbuffer(rwb);
+ }
+
+ rwb_semgive(&rwb->rhsem);
}
- rwb_semgive(&rwb->rhsem);
#endif
-#ifdef CONFIG_FS_WRITEBUFFER
- fvdbg("startblock=%d wrbuffer=%p\n", startblock, wrbuffer);
+#ifdef CONFIG_DRVR_WRITEBUFFER
+ if (rwb->wrmaxblocks > 0)
+ {
+ fvdbg("startblock=%d wrbuffer=%p\n", startblock, wrbuffer);
- /* Use the block cache unless the buffer size is bigger than block cache */
+ /* Use the block cache unless the buffer size is bigger than block cache */
- if (nblocks > rwb->wrmaxblocks)
- {
- /* First flush the cache */
+ if (nblocks > rwb->wrmaxblocks)
+ {
+ /* First flush the cache */
- rwb_semtake(&rwb->wrsem);
- rwb_wrflush(rwb);
- rwb_semgive(&rwb->wrsem);
+ rwb_semtake(&rwb->wrsem);
+ rwb_wrflush(rwb);
+ rwb_semgive(&rwb->wrsem);
- /* Then transfer the data directly to the media */
+ /* Then transfer the data directly to the media */
- ret = rwb->wrflush(rwb->dev, startblock, nblocks, wrbuffer);
+ ret = rwb->wrflush(rwb->dev, startblock, nblocks, wrbuffer);
+ }
+ else
+ {
+ /* Buffer the data in the write buffer */
+
+ ret = rwb_writebuffer(rwb, startblock, nblocks, wrbuffer);
+ }
+
+ /* On success, return the number of blocks that we were requested to
+ * write. This is for compatibility with the normal return of a block
+ * driver write method
+ */
}
else
+#else
{
- /* Buffer the data in the write buffer */
+ /* No write buffer.. just pass the write operation through via the
+ * flush callback.
+ */
- ret = rwb_writebuffer(rwb, startblock, nblocks, wrbuffer);
+ ret = rwb->wrflush(rwb->dev, startblock, nblocks, wrbuffer);
}
- /* On success, return the number of blocks that we were requested to write.
- * This is for compatibility with the normal return of a block driver write
- * method
- */
+#endif
return ret;
+}
-#else
+/****************************************************************************
+ * Name: rwb_mediaremoved
+ *
+ * Description:
+ * The following function is called when media is removed
+ *
+ ****************************************************************************/
- return rwb->wrflush(rwb->dev, startblock, nblocks, wrbuffer);
+int rwb_mediaremoved(FAR struct rwbuffer_s *rwb)
+{
+#ifdef CONFIG_DRVR_WRITEBUFFER
+ if (rwb->wrmaxblocks > 0)
+ {
+ rwb_semtake(&rwb->wrsem);
+ rwb_resetwrbuffer(rwb);
+ rwb_semgive(&rwb->wrsem);
+ }
+#endif
+#ifdef CONFIG_DRVR_READAHEAD
+ if (rhmaxblocks > 0)
+ {
+ rwb_semtake(&rwb->rhsem);
+ rwb_resetrhbuffer(rwb);
+ rwb_semgive(&rwb->rhsem);
+ }
#endif
+
+ return OK;
}
/****************************************************************************
- * Name: rwb_mediaremoved
+ * Name: rwb_invalidate
*
* Description:
- * The following function is called when media is removed
+ * Invalidate a region of the caches
*
****************************************************************************/
-int rwb_mediaremoved(FAR struct rwbuffer_s *rwb)
+int rwb_invalidate(FAR struct rwbuffer_s *rwb,
+ off_t startblock, size_t blockcount)
{
-#ifdef CONFIG_FS_WRITEBUFFER
- rwb_semtake(&rwb->wrsem);
- rwb_resetwrbuffer(rwb);
- rwb_semgive(&rwb->wrsem);
+ int ret;
+
+#ifdef CONFIG_DRVR_WRITEBUFFER
+ ret = rwb_invalidate_writebuffer(rwb, startblock, blockcount);
+ if (ret < 0)
+ {
+ fdbg("ERROR: rwb_invalidate_writebuffer failed: %d\n", ret);
+ return ret;
+ }
#endif
-#ifdef CONFIG_FS_READAHEAD
- rwb_semtake(&rwb->rhsem);
- rwb_resetrhbuffer(rwb);
- rwb_semgive(&rwb->rhsem);
+#ifdef CONFIG_DRVR_READAHEAD
+ ret = rwb_invalidate_readahead(rwb, startblock, blockcount);
+ if (ret < 0)
+ {
+ fdbg("ERROR: rwb_invalidate_readahead failed: %d\n", ret);
+ return ret;
+ }
#endif
- return 0;
+
+ return OK;
}
-#endif /* CONFIG_FS_WRITEBUFFER || CONFIG_FS_READAHEAD */
+#endif /* CONFIG_DRVR_WRITEBUFFER || CONFIG_DRVR_READAHEAD */