/** @brief Read sectors from a disk. @param bVolNum The volume number of the volume whose block device is being read from. @param ullSectorStart The starting sector number. @param ulSectorCount The number of sectors to read. @param pBuffer The buffer into which to read the sector data. @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. */ static REDSTATUS DiskRead( uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer) { REDSTATUS ret = 0; uint32_t ulSectorIdx = 0U; uint32_t ulSectorSize = gaRedVolConf[bVolNum].ulSectorSize; uint8_t *pbBuffer = CAST_VOID_PTR_TO_UINT8_PTR(pBuffer); while(ulSectorIdx < ulSectorCount) { uint32_t ulTransfer = REDMIN(ulSectorCount - ulSectorIdx, MAX_SECTOR_TRANSFER); Ctrl_status cs; cs = sd_mmc_mem_2_ram_multi(bVolNum, (uint32_t)(ullSectorStart + ulSectorIdx), (uint16_t)ulTransfer, &pbBuffer[ulSectorIdx * ulSectorSize]); if(cs != CTRL_GOOD) { ret = -RED_EIO; break; } ulSectorIdx += ulTransfer; } return ret; }
/** @brief Read sectors from a disk. @param bVolNum The volume number of the volume whose block device is being read from. @param ullSectorStart The starting sector number. @param ulSectorCount The number of sectors to read. @param pBuffer The buffer into which to read the sector data. @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. @retval -RED_EIO A disk I/O error occurred. */ static REDSTATUS DiskRead( uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer) { REDSTATUS ret = 0; uint32_t ulSectorIdx = 0U; uint32_t ulSectorSize = gaRedVolConf[bVolNum].ulSectorSize; uint8_t *pbBuffer = CAST_VOID_PTR_TO_UINT8_PTR(pBuffer); while(ulSectorIdx < ulSectorCount) { uint32_t ulTransfer = REDMIN(ulSectorCount - ulSectorIdx, MAX_SECTOR_TRANSFER); DRESULT result; result = disk_read(bVolNum, &pbBuffer[ulSectorIdx * ulSectorSize], (DWORD)(ullSectorStart + ulSectorIdx), (BYTE)ulTransfer); if(result != RES_OK) { ret = -RED_EIO; break; } ulSectorIdx += ulTransfer; } return ret; }
/** @brief Read sectors from a disk. @param bVolNum The volume number of the volume whose block device is being read from. @param ullSectorStart The starting sector number. @param ulSectorCount The number of sectors to read. @param pBuffer The buffer into which to read the sector data. @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. @retval -RED_EIO A disk I/O error occurred. */ static REDSTATUS DiskRead( uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, void *pBuffer) { REDSTATUS ret = 0; F_DRIVER *pDriver = gapFDriver[bVolNum]; if(pDriver == NULL) { ret = -RED_EINVAL; } else { uint8_t *pbBuffer = CAST_VOID_PTR_TO_UINT8_PTR(pBuffer); uint32_t ulSectorSize = gaRedVolConf[bVolNum].ulSectorSize; uint32_t ulSectorIdx; int iErr; for(ulSectorIdx = 0U; ulSectorIdx < ulSectorCount; ulSectorIdx++) { iErr = pDriver->readsector(pDriver, &pbBuffer[ulSectorIdx * ulSectorSize], CAST_ULONG(ullSectorStart + ulSectorCount)); if(iErr != 0) { ret = -RED_EIO; break; } } } return ret; }
/** @brief Initialize a buffer with the specified byte value. This function should only be called from RedMemSet(). @param pDest The buffer to initialize. @param bVal The byte value with which to initialize @p pDest. @param ulLen The number of bytes to initialize. */ static void RedMemSetUnchecked( void *pDest, uint8_t bVal, uint32_t ulLen) { uint8_t *pbDest = CAST_VOID_PTR_TO_UINT8_PTR(pDest); uint32_t ulIdx; for(ulIdx = 0U; ulIdx < ulLen; ulIdx++) { pbDest[ulIdx] = bVal; } }
/** @brief Copy memory from one address to another. This function should only be called from RedMemCpy(). @param pDest The destination buffer. @param pSrc The source buffer. @param ulLen The number of bytes to copy. */ static void RedMemCpyUnchecked( void *pDest, const void *pSrc, uint32_t ulLen) { uint8_t *pbDest = CAST_VOID_PTR_TO_UINT8_PTR(pDest); const uint8_t *pbSrc = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pSrc); uint32_t ulIdx; for(ulIdx = 0U; ulIdx < ulLen; ulIdx++) { pbDest[ulIdx] = pbSrc[ulIdx]; } }
/** @brief Move memory from one address to another. This function should only be called from RedMemMove(). @param pDest The destination buffer. @param pSrc The source buffer. @param ulLen The number of bytes to copy. */ static void RedMemMoveUnchecked( void *pDest, const void *pSrc, uint32_t ulLen) { uint8_t *pbDest = CAST_VOID_PTR_TO_UINT8_PTR(pDest); const uint8_t *pbSrc = CAST_VOID_PTR_TO_CONST_UINT8_PTR(pSrc); uint32_t ulIdx; if(MEMMOVE_MUST_COPY_FORWARD(pbDest, pbSrc)) { /* If the destination is lower than the source with overlapping memory regions, we must copy from start to end in order to copy the memory correctly. Don't use RedMemCpy() to do this. It is possible that RedMemCpy() has been replaced (even though this function has not been replaced) with an implementation that cannot handle any kind of buffer overlap. */ for(ulIdx = 0U; ulIdx < ulLen; ulIdx++) { pbDest[ulIdx] = pbSrc[ulIdx]; } } else { ulIdx = ulLen; while(ulIdx > 0U) { ulIdx--; pbDest[ulIdx] = pbSrc[ulIdx]; } } }