예제 #1
0
int rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock, size_t nblocks, FAR const uint8_t *wrbuffer)
{
	int ret = OK;

#ifdef CONFIG_DRVR_READAHEAD
	if (rwb->rhmaxblocks > 0) {
		/* 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);
	}
#endif

#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 */

		if (nblocks > rwb->wrmaxblocks) {
			/* First flush the cache */

			rwb_semtake(&rwb->wrsem);
			rwb_wrflush(rwb);
			rwb_semgive(&rwb->wrsem);

			/* Then transfer the data directly to the media */

			ret = rwb->wrflush(rwb->dev, wrbuffer, startblock, nblocks);
		} 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
#endif
	{
		/* No write buffer.. just pass the write operation through via the
		 * flush callback.
		 */

		ret = rwb->wrflush(rwb->dev, wrbuffer, startblock, nblocks);
	}

	return ret;
}
예제 #2
0
static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock)
{
  off_t  endblock;
  size_t nblocks;
  int    ret;

  /* Check for attempts to read beyond the end of the media */

  if (startblock >= rwb->nblocks)
    {
      return -ESPIPE;
    }

  /* Get the block number +1 of the last block that will fit in the
   * read-ahead buffer
   */

  endblock = startblock + rwb->rhmaxblocks;

  /* Make sure that we don't read past the end of the device */

  if (endblock > rwb->nblocks)
    {
      endblock = rwb->nblocks;
    }

  nblocks = endblock - startblock;

  /* Reset the read buffer */

  rwb_resetrhbuffer(rwb);

  /* Now perform the read */

  ret = rwb->rhreload(rwb->dev, rwb->rhbuffer, startblock, nblocks);
  if (ret == nblocks)
    {
      /* Update information about what is in the read-ahead buffer */

      rwb->rhnblocks    = nblocks;
      rwb->rhblockstart = startblock;

      /* The return value is not the number of blocks we asked to be loaded. */

      return nblocks;
    }

  return -EIO;
}
예제 #3
0
int rwb_mediaremoved(FAR struct rwbuffer_s *rwb)
{
#ifdef CONFIG_FS_WRITEBUFFER
    rwb_semtake(&rwb->wrsem);
    rwb_resetwrbuffer(rwb);
    rwb_semgive(&rwb->wrsem);
#endif

#ifdef CONFIG_FS_READAHEAD
    rwb_semtake(&rwb->rhsem);
    rwb_resetrhbuffer(rwb);
    rwb_semgive(&rwb->rhsem);
#endif
    return 0;
}
예제 #4
0
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 (rwb->rhmaxblocks > 0) {
		rwb_semtake(&rwb->rhsem);
		rwb_resetrhbuffer(rwb);
		rwb_semgive(&rwb->rhsem);
	}
#endif

	return OK;
}
예제 #5
0
int rwb_initialize(FAR struct rwbuffer_s *rwb)
{
  uint32_t allocsize;

  /* Sanity checking */

  DEBUGASSERT(rwb != NULL);
  DEBUGASSERT(rwb->blocksize > 0);
  DEBUGASSERT(rwb->nblocks > 0);
  DEBUGASSERT(rwb->dev != NULL);

  /* Setup so that rwb_uninitialize can handle a failure */

#ifdef CONFIG_DRVR_WRITEBUFFER
  DEBUGASSERT(rwb->wrflush!= NULL);
  rwb->wrbuffer = NULL;
#endif
#ifdef CONFIG_DRVR_READAHEAD
  DEBUGASSERT(rwb->rhreload != NULL);
  rwb->rhbuffer = NULL;
#endif

#ifdef CONFIG_DRVR_WRITEBUFFER
  if (rwb->wrmaxblocks > 0)
    {
      fvdbg("Initialize the write buffer\n");

      /* Initialize the write buffer access semaphore */

      sem_init(&rwb->wrsem, 0, 1);

      /* Initialize write buffer parameters */

      rwb_resetwrbuffer(rwb);

      /* Allocate the write buffer */

      rwb->wrbuffer = NULL;
      if (rwb->wrmaxblocks > 0)
        {
          allocsize     = rwb->wrmaxblocks * rwb->blocksize;
          rwb->wrbuffer = kmm_malloc(allocsize);
          if (!rwb->wrbuffer)
            {
              fdbg("Write buffer kmm_malloc(%d) failed\n", allocsize);
              return -ENOMEM;
            }
        }

      fvdbg("Write buffer size: %d bytes\n", allocsize);
    }
#endif /* CONFIG_DRVR_WRITEBUFFER */

#ifdef CONFIG_DRVR_READAHEAD
  if (rhmaxblocks > 0)
    {
      fvdbg("Initialize the read-ahead buffer\n");

      /* Initialize the read-ahead buffer access semaphore */

      sem_init(&rwb->rhsem, 0, 1);

      /* Initialize read-ahead buffer parameters */

      rwb_resetrhbuffer(rwb);

      /* Allocate the read-ahead buffer */

      rwb->rhbuffer = NULL;
      if (rwb->rhmaxblocks > 0)
        {
          allocsize     = rwb->rhmaxblocks * rwb->blocksize;
          rwb->rhbuffer = kmm_malloc(allocsize);
          if (!rwb->rhbuffer)
            {
              fdbg("Read-ahead buffer kmm_malloc(%d) failed\n", allocsize);
              return -ENOMEM;
            }
        }

      fvdbg("Read-ahead buffer size: %d bytes\n", allocsize);
    }
#endif /* CONFIG_DRVR_READAHEAD */

  return OK;
}