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; }
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; }
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; }
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; }
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; }