📄 blkmdd.c
字号:
//file: blkmdd.c
//功能:块设备模型设备驱动层
#include "fsdefs.h"
#include "blkmdd.h"
#include <memory.h>
static DS_MDDCB sg_mddcb;
static BOOL sg_isStarted=FALSE;
static U8 sg_sctBuf[CON_SectorSize]; //用电大户!
BOOL PHDRegisterHandlers(pfnPHDRdSct_t pfnRdSct, pfnPHDWrSct_t pfnWrSct)
{
if (NULL==pfnRdSct || NULL==pfnWrSct)
{
return FALSE;
}
sg_mddcb.pfnPHDRdSct=pfnRdSct;
sg_mddcb.pfnPHDWrSct=pfnWrSct;
return TRUE;
}
#if CFG_CacheUnitCnt>=1
BOOL CacheInit()
{
I32 i;
DS_SctCache *p;
p= sg_mddcb.cacheAry;
for (i=0;i<CFG_CacheUnitCnt;i++,p++)
{
p->sctNum=CON_MaxU32;
}
return TRUE;
}
BOOL CacheSearch(U32 sctNum, DS_SctCache** OUT ppCch)
{
IFAV i;
DS_SctCache *p;
p= sg_mddcb.cacheAry;
for (i=0;i<CFG_CacheUnitCnt;i++,p++)
{
if (p->sctNum==sctNum)
{
break;
}
}
if (i==CFG_CacheUnitCnt)
{
*ppCch=NULL;
return FALSE;
}
else
{
*ppCch=p;
return TRUE;
}
}
BOOL CacheRelease(DS_SctCache *p)
{
if (CON_MaxU32==p->sctNum)
{
return FALSE;
}
if (p->isDirty)
{
//数据已脏,需写回
sg_mddcb.pfnPHDWrSct(p->sctNum, p->buf);
#if CFG_IOStat==1
sg_mddcb.stat.phdWrCnt++;
#endif
}
return TRUE;
}
void CacheFlush()
{
I32 i;
DS_SctCache *p;
p= sg_mddcb.cacheAry;
for (i=0;i<CFG_CacheUnitCnt;i++,p++)
{
CacheRelease(p);
}
}
//给除了pCch之外的所有cache单元增加闲置计数的值
void CacheIncIdleCnt(DS_SctCache *pCch)
{
I32 i;
DS_SctCache *p=sg_mddcb.cacheAry;
for (i=0;i<CFG_CacheUnitCnt;i++,p++)
{
p->idleCnt++;
}
pCch->idleCnt--;
}
DS_SctCache* CacheFindMaxIdle()
{
//找出最近最久没有使用的,或者是空闲的
IFAV i, maxIdleCnt, maxIdleIdx;
DS_SctCache *p;
p= sg_mddcb.cacheAry;
maxIdleCnt=0;
maxIdleIdx=0;
for (i=0;i<CFG_CacheUnitCnt;i++,p++)
{
if (CON_MaxU32==p->sctNum)
{
//使用此空闲的cache单元
return p;
}
if ( p->idleCnt > maxIdleCnt )
{
//找到了一个更久没有使用的cache单元
maxIdleCnt= p->idleCnt;
maxIdleIdx= i;
}
}
p= sg_mddcb.cacheAry+maxIdleIdx;
return p;
}
//从cache中找到一个单元。这个函数比较高层,它在内部可能会处理cache内容替换
//参数: idx: 指定的cache单元,若为CON_MaxUFAV则由本函数负责分配一个cache单元
//返回一个cache单元指针
DS_SctCache* CacheAlloc(UFAV idx, U32 sctNum)
{
DS_SctCache *p;
p= sg_mddcb.cacheAry;
if (idx<CFG_CacheUnitCnt)
{
//重新分配该cache单元
p= sg_mddcb.cacheAry+idx;
CacheRelease(p);
p->sctNum=CON_MaxU32;
return p;
}
//正常情况下的分配cache
//找出最近最久没有使用的,或者是空闲的
p=CacheFindMaxIdle();
CacheRelease(p);
p->isDirty=FALSE;
p->sctNum=sctNum;
p->idleCnt=0;
return p;
}
//这是一个cache与上层的接口函数,把sctNum扇区的内容加载到idx指示的cache单元中。如idx为CON_MaxU32,则自行寻找合适的cache单元
DS_SctCache* CacheLoad(U32 sctNum, UFAV idx, U32 rdByteCnt)
{
DS_SctCache *pCch=NULL;
CacheSearch(sctNum, &pCch);
//无论如何都让cache中保有sctNum号扇区的数据,分两种情况
if (pCch)
{
//cache命中
#if CFG_IOStat
sg_mddcb.stat.hitCnt++;
//sg_mddcb.stat.cacheRdByteCnt+=rdByteCnt;
#endif
}
else
{
//cache没有命中,强行分配一个cache空间
pCch=CacheAlloc(idx, sctNum);
sg_mddcb.pfnPHDRdSct(sctNum, pCch->buf);
#if CFG_IOStat
sg_mddcb.stat.phdRdCnt++;
#endif
}
CacheIncIdleCnt(pCch);
#if CFG_IOStat
sg_mddcb.stat.hitRatio= 1000*sg_mddcb.stat.hitCnt / sg_mddcb.stat.ioCnt;
#endif
return pCch;
}
//这是带有cache的读函数
uint8_t BlkMdd_read(uint32_t offset, uint8_t* OUT buffer, uint16_t length)
{
U32 sctNum;
U16 sctOfs,effSize;
DS_SctCache *pCch;
#if CFG_IOStat
sg_mddcb.stat.rdCnt++;
sg_mddcb.stat.ioCnt++;
sg_mddcb.stat.rdByteCnt+=length;
#endif
sctNum= offset >> CON_SectorSizeShift;
sctOfs= (U16)(offset & (CON_SectorSize-1));
while (length>0)
{
effSize= CON_SectorSize-sctOfs;
if (effSize>length)
{
effSize=length;
}
pCch=CacheLoad(sctNum, CON_MaxU32,effSize);
memcpy(buffer, pCch->buf+sctOfs, effSize);
sctNum++;
sctOfs=0;
buffer+=effSize;
length-=effSize;
}
return 1;
}
uint8_t BlkMdd_write(uint32_t offset, const uint8_t* IN buffer, uint16_t length)
{
U32 sctNum;
U16 sctOfs,effSize;
DS_SctCache *pCch;
#if CFG_IOStat
sg_mddcb.stat.wrCnt++;
sg_mddcb.stat.ioCnt++;
sg_mddcb.stat.wrByteCnt+=length;
#endif
sctNum= offset >> CON_SectorSizeShift;
sctOfs= (U16)(offset & (CON_SectorSize-1));
while (length>0)
{
effSize= CON_SectorSize-sctOfs;
if (effSize>length)
{
effSize=length;
}
pCch=CacheLoad(sctNum, CON_MaxU32,effSize);
//把内容写到cache中
memcpy(pCch->buf+sctOfs, buffer, effSize);
pCch->isDirty=TRUE;
sctNum++;
sctOfs=0;
buffer+=effSize;
length-=effSize;
}
return 1;
}
#else
uint8_t BlkMdd_read(uint32_t offset, uint8_t* OUT buffer, uint16_t length)
{
U32 sctNum;
U16 sctOfs,effSize, rdSize;
sctNum= offset >> CON_SectorSizeShift;
sctOfs= (U16)(offset & (CON_SectorSize-1));
rdSize=0;
# if CFG_IOStat==1
sg_mddcb.stat.rdCnt++;
sg_mddcb.stat.rdByteCnt+= length;
#endif
//无cache的情况
if (0==sctOfs && CON_SectorSize==length)
{
sg_mddcb.pfnPHDRdSct(sctNum, buffer);
#if CFG_IOStat==1
sg_mddcb.stat.phdRdCnt++;
#endif
return 1;
}
else
{
while(length>0)
{
if (sctOfs==0 && length>=CON_SectorSize)
{
//无需借用sg_sctBuf,直接读到buffer
effSize=CON_SectorSize;
sg_mddcb.pfnPHDRdSct(sctNum, buffer);
#if CFG_IOStat==1
sg_mddcb.stat.phdRdCnt++;
#endif
}
else
{
//先读入到sg_sctBuf
sg_mddcb.pfnPHDRdSct(sctNum, sg_sctBuf);
#if CFG_IOStat==1
sg_mddcb.stat.phdRdCnt++;
#endif
//内存拷贝
effSize= CON_SectorSize-sctOfs;
if (effSize>length)
{
effSize=length;
}
memcpy(buffer,sg_sctBuf+sctOfs,effSize);
}
//更新buffer,length的值
buffer+=effSize;
length-=effSize;
sctOfs=0;
sctNum++;
}
}
return 1;
}
uint8_t BlkMdd_write(uint32_t offset, const uint8_t* IN buffer, uint16_t length)
{
U32 sctNum;
U16 sctOfs,effSize, wrSize;
sctNum= offset >> CON_SectorSizeShift;
sctOfs= (U16)(offset & (CON_SectorSize-1));
wrSize=0;
#if CFG_IOStat==1
sg_mddcb.stat.wrCnt++;
sg_mddcb.stat.wrByteCnt+= length;
#endif
if ( 0==sctOfs && CON_SectorSize==length)
{
//刚好对齐到一个扇区
sg_mddcb.pfnPHDWrSct(sctNum,buffer);
#if CFG_IOStat==1
sg_mddcb.stat.phdWrCnt++;
#endif
return 1;
}
while(length>0)
{
if (sctOfs==0 && length>=CON_SectorSize)
{
//无需先读入部分内容,直接写
effSize=CON_SectorSize;
sg_mddcb.pfnPHDWrSct(sctNum, buffer);
#if CFG_IOStat==1
sg_mddcb.stat.phdWrCnt++;
#endif
}
else
{
//先读入扇区原来的内容
sg_mddcb.pfnPHDRdSct(sctNum, sg_sctBuf);
#if CFG_IOStat==1
sg_mddcb.stat.phdRdCnt++;
#endif
effSize= CON_SectorSize-sctOfs;
if (effSize>length)
{
effSize=length;
}
//更改需要写入的部分
memcpy(sg_sctBuf+sctOfs,buffer,effSize);
//把更改后的数据写回
sg_mddcb.pfnPHDWrSct(sctNum, sg_sctBuf);
#if CFG_IOStat==1
sg_mddcb.stat.phdWrCnt++;
#endif
}
//更新buffer,length的值
buffer+=effSize;
length-=effSize;
sctOfs=0;
sctNum++;
}
return 1;
}
#endif
uint8_t BlkMdd_read_interval(uint32_t offset, uint8_t* buffer, uint16_t interval, uint16_t length, BlkMdd_read_interval_handler_t callback, void* p)
{
if(!buffer || interval == 0 || length < interval || !callback)
return 0;
while(length >= interval)
{
/* as reading is now buffered, we directly
* hand over the request to sd_raw_read()
*/
if(!BlkMdd_read(offset, buffer, interval))
return 0;
if(!callback(buffer, offset, p))
break;
offset += interval;
length -= interval;
}
return 1;
}
uint8_t BlkMdd_write_interval(uint32_t offset, uint8_t* buffer, uint16_t length, BlkMdd_write_interval_handler_t callback, void* p)
{
uint8_t endless = (length == 0);
uint16_t bytes_to_write;
if(!buffer || !callback)
return 0;
while(endless || length > 0)
{
bytes_to_write = callback(buffer, offset, p);
if(!bytes_to_write)
break;
if(!endless && bytes_to_write > length)
return 0;
/* as writing is always buffered, we directly
* hand over the request to sd_raw_write()
*/
if(!BlkMdd_write(offset, buffer, bytes_to_write))
return 0;
offset += bytes_to_write;
length -= bytes_to_write;
}
return 1;
}
BOOL BlkMdd_Startup()
{
BOOL boolRet;
if (sg_isStarted)
{
return TRUE;
}
//先初始化物理设备
boolRet=PHDInits();
if (!boolRet || NULL==sg_mddcb.pfnPHDRdSct || NULL==sg_mddcb.pfnPHDWrSct)
{
return FALSE;
}
#if CFG_CacheUnitCnt>=1
CacheInit();
#endif
#if CFG_IOStat==1
memset( &sg_mddcb.stat ,0 ,sizeof(sg_mddcb.stat));
#endif
sg_isStarted=TRUE;
return TRUE;
}
BOOL BlkMdd_Cleanup()
{
if (!sg_isStarted)
{
return TRUE;
}
PHDCleanup();
#if CFG_CacheUnitCnt>=1
CacheFlush();
#endif
sg_isStarted=FALSE;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -