diff --git a/arch/arm/src/stm32/stm32_sdio.c b/arch/arm/src/stm32/stm32_sdio.c index f5f68f973a..b46147f041 100644 --- a/arch/arm/src/stm32/stm32_sdio.c +++ b/arch/arm/src/stm32/stm32_sdio.c @@ -93,21 +93,15 @@ #define SDIO_CLKCR_RISINGEDGE (0) #define SDIO_CLKCR_FALLINGEDGE SDIO_CLKCR_NEGEDGE -/* HCLK=72MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(178+2)=400 KHz */ +/* Mode dependent settings. These depend on clock devisor settings that must + * be defined in the board-specific board.h header file: SDIO_INIT_CLKDIV, + * SDIO_MMCXFR_CLKDIV, and SDIO_SDXFR_CLKDIV. + */ -#define SDIO_INIT_CLKDIV (178 << SDIO_CLKCR_CLKDIV_SHIFT) #define STM32_CLCKCR_INIT (SDIO_INIT_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ SDIO_CLKCR_WIDBUS_D1) - -/* HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(2+2)=18 MHz */ - -#define SDIO_MMCXFR_CLKDIV (2 << SDIO_CLKCR_CLKDIV_SHIFT) #define SDIO_CLKCR_MMCXFR (SDIO_MMCXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ SDIO_CLKCR_WIDBUS_D1) - -/* HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(1+2)=24 MHz */ - -#define SDIO_SDXFR_CLKDIV (1 << SDIO_CLKCR_CLKDIV_SHIFT) #define SDIO_CLCKR_SDXFR (SDIO_SDXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ SDIO_CLKCR_WIDBUS_D1) #define SDIO_CLCKR_SDWIDEXFR (SDIO_SDXFR_CLKDIV|SDIO_CLKCR_RISINGEDGE|\ @@ -198,7 +192,6 @@ struct stm32_dev_s uint32 *buffer; /* Address of current R/W buffer */ size_t remaining; /* Number of bytes remaining in the transfer */ - int result; /* Result of the transfer */ uint32 xfrmask; /* Interrupt enables for data transfer */ /* DMA data transfer support */ @@ -240,7 +233,7 @@ static void stm32_sendfifo(struct stm32_dev_s *priv); static void stm32_recvfifo(struct stm32_dev_s *priv); static void stm32_eventtimeout(int argc, uint32 arg); static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent); -static void stm32_endtransfer(struct stm32_dev_s *priv, int result); +static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent); /* Interrupt Handling *******************************************************/ @@ -790,8 +783,8 @@ static void stm32_eventtimeout(int argc, uint32 arg) * Wake up a waiting thread if the waited-for event has occurred. * * Input Parameters: - * priv - An instance of the SDIO device interface - * result - The result status of the transfer + * priv - An instance of the SDIO device interface + * wkupevent - The event that caused the wait to end * * Returned Value: * None @@ -824,7 +817,7 @@ static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent) * * Input Parameters: * priv - An instance of the SDIO device interface - * result - The result status of the transfer + * wkupevent - The event that caused the transfer to end * * Returned Value: * None @@ -834,7 +827,7 @@ static void stm32_endwait(struct stm32_dev_s *priv, sdio_eventset_t wkupevent) * ****************************************************************************/ -static void stm32_endtransfer(struct stm32_dev_s *priv, int result) +static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupevent) { /* Disable all transfer related interrupts */ @@ -843,15 +836,14 @@ static void stm32_endtransfer(struct stm32_dev_s *priv, int result) /* Mark the transfer finished with the provided status */ priv->remaining = 0; - priv->result = result; /* Is a data transfer complete event expected? */ - if ((priv->waitevents & SDIOWAIT_TRANSFERDONE) != 0) + if ((priv->waitevents & wkupevent) != 0) { /* Yes.. wake up any waiting threads */ - stm32_endwait(priv, SDIOWAIT_TRANSFERDONE); + stm32_endwait(priv, wkupevent); } } @@ -942,7 +934,7 @@ static int stm32_interrupt(int irq, void *context) /* Then terminate the transfer */ putreg32(SDIO_ICR_DATAENDC, STM32_SDIO_ICR); - stm32_endtransfer(priv, OK); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE); } /* Handle data block send/receive CRC failure */ @@ -953,7 +945,7 @@ static int stm32_interrupt(int irq, void *context) putreg32(SDIO_ICR_DCRCFAILC, STM32_SDIO_ICR); flldbg("ERROR: Data block CRC failure, remaining: %d\n", priv->remaining); - stm32_endtransfer(priv, -EIO); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); } /* Handle data timeout error */ @@ -964,7 +956,7 @@ static int stm32_interrupt(int irq, void *context) putreg32(SDIO_ICR_DTIMEOUTC, STM32_SDIO_ICR); flldbg("ERROR: Data timeout, remaining: %d\n", priv->remaining); - stm32_endtransfer(priv, -ETIMEDOUT); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); } /* Handle RX FIFO overrun error */ @@ -975,7 +967,7 @@ static int stm32_interrupt(int irq, void *context) putreg32(SDIO_ICR_RXOVERRC, STM32_SDIO_ICR); flldbg("ERROR: RX FIFO overrun, remaining: %d\n", priv->remaining); - stm32_endtransfer(priv, -EOVERFLOW); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); } /* Handle TX FIFO underrun error */ @@ -986,7 +978,7 @@ static int stm32_interrupt(int irq, void *context) putreg32(SDIO_ICR_TXUNDERRC, STM32_SDIO_ICR); flldbg("ERROR: TX FIFO underrun, remaining: %d\n", priv->remaining); - stm32_endtransfer(priv, -EOVERFLOW); + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); } /* Handle start bit error */ @@ -997,8 +989,8 @@ static int stm32_interrupt(int irq, void *context) putreg32(SDIO_ICR_STBITERRC, STM32_SDIO_ICR); flldbg("ERROR: Start bit, remaining: %d\n", priv->remaining); - stm32_endtransfer(priv, -EIO); - } + stm32_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR); + } } /* Handle wait events *************************************************/ @@ -1084,7 +1076,6 @@ static void stm32_reset(FAR struct sdio_dev_s *dev) priv->buffer = 0; /* Address of current R/W buffer */ priv->remaining = 0; /* Number of bytes remaining in the transfer */ - priv->result = 0; /* Result of the transfer */ priv->xfrmask = 0; /* Interrupt enables for data transfer */ /* DMA data transfer support */ @@ -1352,7 +1343,6 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer, priv->buffer = (uint32*)buffer; priv->remaining = nbytes; - priv->result = -EBUSY; #ifdef CONFIG_SDIO_DMA priv->dmamode = FALSE; #endif @@ -1404,7 +1394,6 @@ static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const ubyte *buffer, priv->buffer = (uint32*)buffer; priv->remaining = nbytes; - priv->result = -EBUSY; #ifdef CONFIG_SDIO_DMA priv->dmamode = FALSE; #endif @@ -1838,12 +1827,13 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, */ stm32_takesem(priv); - + wkupevent = priv->wkupevent; + /* Check if the event has occurred. When the event has occurred, then * evenset will be set to 0 and wkupevent will be set to a nonzero value. */ - if (priv->wkupevent != 0) + if (wkupevent != 0) { /* Yes... break out of the loop with wkupevent non-zero */ @@ -1992,7 +1982,6 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer, priv->buffer = (uint32*)buffer; priv->remaining = buflen; - priv->result = -EBUSY; priv->dmamode = TRUE; /* Then set up the SDIO data path */ @@ -2059,7 +2048,6 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev, priv->buffer = (uint32*)buffer; priv->remaining = buflen; - priv->result = -EBUSY; priv->dmamode = TRUE; /* Then set up the SDIO data path */ diff --git a/configs/stm3210e-eval/include/board.h b/configs/stm3210e-eval/include/board.h index c753d06505..4792ab6aff 100755 --- a/configs/stm3210e-eval/include/board.h +++ b/configs/stm3210e-eval/include/board.h @@ -45,6 +45,7 @@ # include #endif #include "stm32_rcc.h" +#include "stm32_sdio.h" #include "stm32_internal.h" /************************************************************************************ @@ -89,6 +90,36 @@ #define STM32_CFGR_USBPRE 0 +/* SDIO dividers. Note that slower clocking is required when DMA is disabled + * in order to avoid RX overrun/TX underrun errors due to delayed responses + * to service FIFOs in interrupt driven mode. These values have not been + * tuned!!! + * + * HCLK=72MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(178+2)=400 KHz + */ + +#define SDIO_INIT_CLKDIV (178 << SDIO_CLKCR_CLKDIV_SHIFT) + +/* DMA ON: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(2+2)=18 MHz + * DMA OFF: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(3+2)=14.4 MHz + */ + +#ifdef CONFIG_SDIO_DMA +# define SDIO_MMCXFR_CLKDIV (2 << SDIO_CLKCR_CLKDIV_SHIFT) +#else +# define SDIO_MMCXFR_CLKDIV (3 << SDIO_CLKCR_CLKDIV_SHIFT) +#endif + +/* DMA ON: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(1+2)=24 MHz + * DMA OFF: HCLK=72 MHz, SDIOCLK=72MHz, SDIO_CK=HCLK/(3+2)=14.4 MHz + */ + +#ifdef CONFIG_SDIO_DMA +# define SDIO_SDXFR_CLKDIV (1 << SDIO_CLKCR_CLKDIV_SHIFT) +#else +# define SDIO_SDXFR_CLKDIV (3 << SDIO_CLKCR_CLKDIV_SHIFT) +#endif + /* LED definitions ******************************************************************/ /* The STM3210E-EVAL board has 4 LEDs that we will encode as: */ diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c index 268b336d2a..a0db7d76cf 100644 --- a/drivers/mmcsd/mmcsd_sdio.c +++ b/drivers/mmcsd/mmcsd_sdio.c @@ -77,7 +77,14 @@ #define MMCSD_DSR_DELAY (100*1000) /* Time to wait after setting DSR */ #define MMCSD_CLK_DELAY (500*1000) /* Delay after changing clock speeds */ -/* Event delays (all in units of milliseconds) */ +/* Data delays (all in units of milliseconds). + * + * For MMC & SD V1.x, these should be based on Nac = TAAC + NSAC; The maximum + * value of TAAC is 80MS and the maximum value of NSAC is 25.5K clock cycle. + * For SD V2.x, a fixed delay of 100MS is recommend which is preety close to + * the worst case SD V1.x Nac. Here we just use 100MS delay for all data + * transfers. + */ #define MMCSD_SCR_DATADELAY (100) /* Wait up to 100MS to get SCR */ #define MMCSD_BLOCK_DATADELAY (100) /* Wait up to 100MS to get one data block */ @@ -446,7 +453,7 @@ static int mmcsd_getSCR(FAR struct mmcsd_state_s *priv, uint32 scr[2]) /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 to start data receipt */ - (void)SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); + (void)SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); mmcsd_sendcmdpoll(priv, SD_ACMD51, 0); ret = mmcsd_recvR1(priv, SD_ACMD51); if (ret != OK) @@ -457,10 +464,10 @@ static int mmcsd_getSCR(FAR struct mmcsd_state_s *priv, uint32 scr[2]) /* Wait for data to be transferred */ - ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, MMCSD_SCR_DATADELAY); + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, MMCSD_SCR_DATADELAY); if (ret != OK) { - fdbg("ERROR: EVENTWAIT for READ DATA failed: %d\n", ret); + fdbg("ERROR: mmcsd_eventwait for READ DATA failed: %d\n", ret); } return ret; } @@ -996,11 +1003,11 @@ static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv, { /* Yes.. the failure event is probably SDIOWAIT_TIMEOUT */ - fdbg("ERROR: Awakened with %02\n", wkupevent); + fdbg("ERROR: Awakened with %02x\n", wkupevent); return wkupevent & SDIOWAIT_TIMEOUT ? -ETIMEDOUT : -EIO; } - /* Since there are no failure events, we must have been awaked by one + /* Since there are no failure events, we must have been awakened by one * (or more) success events. */ @@ -1224,7 +1231,7 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, /* Configure SDIO controller hardware for the read transfer */ - SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); #ifdef CONFIG_SDIO_DMA if (priv->dma) { @@ -1252,12 +1259,16 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, /* Then wait for the data transfer to complete */ - ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, MMCSD_BLOCK_DATADELAY); + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, MMCSD_BLOCK_DATADELAY); if (ret != OK) { fdbg("ERROR: CMD17 transfer failed: %d\n", ret); + return ret; } - return ret; + + /* Return value: One sector read */ + + return 1; } /**************************************************************************** @@ -1327,7 +1338,7 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, /* Configure SDIO controller hardware for the read transfer */ - SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); #ifdef CONFIG_SDIO_DMA if (priv->dma) { @@ -1353,7 +1364,7 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, /* Wait for the transfer to complete */ - ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, nblocks * MMCSD_BLOCK_DATADELAY); + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, nblocks * MMCSD_BLOCK_DATADELAY); if (ret != OK) { fdbg("ERROR: CMD18 transfer failed: %d\n", ret); @@ -1367,7 +1378,10 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, { fdbg("ERROR: mmcsd_stoptransmission failed: %d\n", ret); } - return ret; + + /* On success, return the number of blocks read */ + + return nblocks; } /**************************************************************************** @@ -1396,6 +1410,9 @@ static ssize_t mmcsd_reload(FAR void *dev, FAR ubyte *buffer, { ret = mmcsd_readmultiple(priv, buffer, startblock, nblocks); } + + /* On success, return the number of blocks read */ + return ret; } #endif @@ -1476,7 +1493,7 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, /* Configure SDIO controller hardware for the write transfer */ - SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); #ifdef CONFIG_SDIO_DMA if (priv->dma) { @@ -1488,20 +1505,24 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, SDIO_SENDSETUP(priv->dev, buffer, priv->blocksize); } - /* Wait for the transfer to complete */ - - ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, MMCSD_BLOCK_DATADELAY); - if (ret != OK) - { - fdbg("ERROR: CMD24 transfer failed: %d\n", ret); - } - /* Flag that a write transfer is pending that we will have to check for * write complete at the beginning of the next transfer. */ priv->wrbusy = TRUE; - return ret; + + /* Wait for the transfer to complete */ + + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, MMCSD_BLOCK_DATADELAY); + if (ret != OK) + { + fdbg("ERROR: CMD24 transfer failed: %d\n", ret); + return ret; + } + + /* On success, return the number of blocks written */ + + return 1; } /**************************************************************************** @@ -1614,7 +1635,7 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, /* Configure SDIO controller hardware for the write transfer */ - SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); + SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR); #ifdef CONFIG_SDIO_DMA if (priv->dma) { @@ -1626,9 +1647,15 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, SDIO_SENDSETUP(priv->dev, buffer, nbytes); } + /* Flag that a write transfer is pending that we will have to check for + * write complete at the beginning of the next transfer. + */ + + priv->wrbusy = TRUE; + /* Wait for the transfer to complete */ - ret =mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, nblocks * MMCSD_BLOCK_DATADELAY); + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, nblocks * MMCSD_BLOCK_DATADELAY); if (ret != OK) { fdbg("ERROR: CMD18 transfer failed: %d\n", ret); @@ -1641,14 +1668,12 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, if (ret != OK) { fdbg("ERROR: mmcsd_stoptransmission failed: %d\n", ret); + return ret; } - /* Flag that a write transfer is pending that we will have to check for - * write complete at the beginning of the next transfer. - */ + /* On success, return the number of blocks read */ - priv->wrbusy = TRUE; - return ret; + return nblocks; } /**************************************************************************** @@ -1676,6 +1701,9 @@ static ssize_t mmcsd_flush(FAR void *dev, FAR const ubyte *buffer, { ret = mmcsd_writemultiple(priv, buffer, startblock, nblocks); } + + /* On success, return the number of blocks written */ + return ret; } #endif @@ -1768,6 +1796,9 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer, #endif mmcsd_givesem(priv); } + + /* On success, return the number of blocks read */ + return ret; } @@ -1805,6 +1836,9 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer, } #endif mmcsd_givesem(priv); + + /* On success, return the number of blocks written */ + return ret; } #endif diff --git a/drivers/rwbuffer.c b/drivers/rwbuffer.c index 59817f0baa..2d78f75aee 100644 --- a/drivers/rwbuffer.c +++ b/drivers/rwbuffer.c @@ -162,12 +162,15 @@ static void rwb_wrflush(struct rwbuffer_s *rwb) fvdbg("Flushing: blockstart=0x%08lx nblocks=%d from buffer=%p\n", (long)rwb->wrblockstart, rwb->wrnblocks, rwb->wrbuffer); - /* Flush cache */ + /* Flush cache. On success, the flush method will return the number + * of blocks written. Anything other than the number requested is + * an error. + */ ret = rwb->wrflush(rwb->dev, rwb->wrbuffer, rwb->wrblockstart, rwb->wrnblocks); - if (ret < 0) + if (ret != rwb->wrnblocks) { - fdbg("ERROR: Error flushing write buffer: %d\n", -ret); + fdbg("ERROR: Error flushing write buffer: %d\n", ret); } rwb_resetwrbuffer(rwb); @@ -281,7 +284,7 @@ static ssize_t rwb_writebuffer(FAR struct rwbuffer_s *rwb, #endif /**************************************************************************** - * Name: + * Name: rwb_resetrhbuffer ****************************************************************************/ #ifdef CONFIG_FS_READAHEAD @@ -295,7 +298,7 @@ static inline void rwb_resetrhbuffer(struct rwbuffer_s *rwb) #endif /**************************************************************************** - * Name: + * Name: rwb_bufferread ****************************************************************************/ #ifdef CONFIG_FS_READAHEAD @@ -329,7 +332,7 @@ rwb_bufferread(struct rwbuffer_s *rwb, off_t startblock, #endif /**************************************************************************** - * Name: + * Name: rwb_rhreload ****************************************************************************/ #ifdef CONFIG_FS_READAHEAD @@ -358,14 +361,19 @@ static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock) /* Now perform the read */ ret = rwb->rhreload(rwb->dev, rwb->rhbuffer, startblock, nblocks); - if (ret == 0) + 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 ret; + + return -EIO; } #endif @@ -481,12 +489,14 @@ void rwb_uninitialize(FAR struct rwbuffer_s *rwb) } /**************************************************************************** - * Name: + * Name: rwb_read ****************************************************************************/ int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32 nblocks, FAR ubyte *rdbuffer) { + uint32 remaining; + fvdbg("startblock=%ld nblocks=%ld rdbuffer=%p\n", (long)startblock, (long)nblocks, rdbuffer); @@ -516,17 +526,17 @@ int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32 nblocks, /* Loop until we have read all of the requested blocks */ rwb_semtake(&rwb->rhsem); - while (nblocks > 0) + for (remaining = nblocks; remaining > 0;) { /* Is there anything in the read-ahead buffer? */ if (rwb->rhnblocks > 0) { off_t startblock = startblock; - size_t nblocks = 0; + size_t nbufblocks = 0; off_t bufferend; - /* Loop for each block we find in the read-head buffer. Count the + /* Loop for each block we find in the read-head buffer. Count the * number of buffers that we can read from read-ahead buffer. */ @@ -534,28 +544,28 @@ int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32 nblocks, while ((startblock >= rwb->rhblockstart) && (startblock < bufferend) && - (nblocks > 0)) + (remaining > 0)) { /* This is one more that we will read from the read ahead buffer */ - nblocks++; + nbufblocks++; /* And one less that we will read from the media */ startblock++; - nblocks--; + remaining--; } /* Then read the data from the read-ahead buffer */ - rwb_bufferread(rwb, startblock, nblocks, &rdbuffer); + rwb_bufferread(rwb, startblock, nbufblocks, &rdbuffer); } /* If we did not get all of the data from the buffer, then we have to refill * the buffer and try again. */ - if (nblocks > 0) + if (remaining > 0) { int ret = rwb_rhreload(rwb, startblock); if (ret < 0) @@ -566,6 +576,11 @@ int rwb_read(FAR struct rwbuffer_s *rwb, off_t startblock, uint32 nblocks, } } + /* 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; #else @@ -620,6 +635,12 @@ int rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock, 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 + */ + return ret; #else diff --git a/include/nuttx/sdio.h b/include/nuttx/sdio.h index db0d0c001d..92a059abcf 100755 --- a/include/nuttx/sdio.h +++ b/include/nuttx/sdio.h @@ -57,8 +57,9 @@ #define SDIOWAIT_RESPONSEDONE (1 << 1) /* Bit 1: Response to command available */ #define SDIOWAIT_TRANSFERDONE (1 << 2) /* Bit 2: Data transfer/DMA done */ #define SDIOWAIT_TIMEOUT (1 << 3) /* Bit 3: Timeout */ +#define SDIOWAIT_ERROR (1 << 4) /* Bit 4: Some other error occurred */ -#define SDIOWAIT_ALLEVENTS 0x0f +#define SDIOWAIT_ALLEVENTS 0x1f /* Media events are used for enable/disable registered event callbacks */