ioman_v2.c
来自「efsl-0.2.8(sd card 文件系统 fat)」· C语言 代码 · 共 403 行
C
403 行
/*****************************************************************************\* libfat - General purpose FAT library ** ---------------------------------- ** ** Filename : ioman.c ** Description : The IO Manager receives all requests for sectors in a central ** allowing it to make smart decision regarding caching. ** The IOMAN_NUMBUFFER parameter determines how many sectors ** ioman can cache. ioman also supports overallocating and ** backtracking sectors ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License ** as published by the Free Software Foundation; version 2 ** of the License. * ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** As a special exception, if other files instantiate templates or ** use macros or inline functions from this file, or you compile this ** file and link it with other works to produce a work based on this file, ** this file does not by itself cause the resulting work to be covered ** by the GNU General Public License. However the source code for this ** file must still be made available in accordance with section (3) of ** the GNU General Public License. ** ** This exception does not invalidate any other reasons why a work based ** on this file might be covered by the GNU General Public License. ** ** (c)2006 Lennart Yseboodt ** (c)2006 Michael De Nil *\*****************************************************************************//*****************************************************************************/#include "ioman_v2.h"/*****************************************************************************/esint8 ioman_init(IOManager *ioman, hwInterface *iface, euint8* bufferarea){ ioman->iface=iface; ioman->bufptr = ioman_getBuffer(ioman,bufferarea); ioman->numbuf = IOMAN_NUMBUFFER; ioman->numit = IOMAN_NUMITERATIONS; ioman_reset(ioman); return(0);}void ioman_reset(IOManager *ioman){ euint16 nb,ni; memClr(ioman->sector,sizeof(euint32)*ioman->numbuf); memClr(ioman->status,sizeof(euint8) *ioman->numbuf); memClr(ioman->usage ,sizeof(euint8) *ioman->numbuf); memClr(ioman->itptr ,sizeof(euint8) *ioman->numbuf); for(nb=0;nb<ioman->numbuf;nb++){ for(ni=0;ni<ioman->numit;ni++){ ioman->stack[nb][ni].sector=0; ioman->stack[nb][ni].status=0; ioman->stack[nb][ni].usage =0; } }}euint8* ioman_getBuffer(IOManager *ioman,euint8* bufferarea){ static euint8 buf[512 * IOMAN_NUMBUFFER]; return(buf);}void ioman_setAttr(IOManager *ioman,euint16 bufplace,euint8 attribute,euint8 val){ if(bufplace>=ioman->numbuf)return; /* Out of bounds */ if(val){ ioman->status[bufplace]|=1<<attribute; }else{ ioman->status[bufplace]&=~(1<<attribute); }}euint8 ioman_getAttr(IOManager *ioman,euint16 bufplace,euint8 attribute){ if(bufplace>=ioman->numbuf) return(0xFF); /* Out of bounds */ return(ioman->status[bufplace]&(1<<attribute));}euint8 ioman_getUseCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return(0x00); return(ioman->usage[bufplace]);}void ioman_incUseCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return; if(ioman->usage[bufplace]==0xFF)return; else ioman->usage[bufplace]++;}void ioman_decUseCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return; if(ioman->usage[bufplace]==0x0)return; else ioman->usage[bufplace]--;}void ioman_resetUseCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return; ioman->usage[bufplace]=0x00;}euint8 ioman_getRefCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return(0x00); return(ioman->reference[bufplace]);}void ioman_incRefCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return; if(ioman->reference[bufplace]==0xFF)return; else ioman->reference[bufplace]++;}void ioman_decRefCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return; if(ioman->reference[bufplace]==0x00)return; else ioman->reference[bufplace]--;}void ioman_resetRefCnt(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return; ioman->reference[bufplace]=0x00;}esint8 ioman_pop(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return(-1); if(ioman->itptr[bufplace]==0 || ioman->itptr[bufplace]>IOMAN_NUMITERATIONS)return(-1); ioman->sector[bufplace] = ioman->stack[bufplace][ioman->itptr[bufplace]].sector; ioman->status[bufplace] = ioman->stack[bufplace][ioman->itptr[bufplace]].status; ioman->usage[bufplace] = ioman->stack[bufplace][ioman->itptr[bufplace]].usage; ioman->itptr[bufplace]--; return(0);}esint8 ioman_push(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return(-1); if(ioman->itptr[bufplace]>=IOMAN_NUMITERATIONS)return(-1); ioman->itptr[bufplace]++; ioman->stack[bufplace][ioman->itptr[bufplace]].sector = ioman->sector[bufplace]; ioman->stack[bufplace][ioman->itptr[bufplace]].status = ioman->status[bufplace]; ioman->stack[bufplace][ioman->itptr[bufplace]].usage = ioman->usage[bufplace]; return(0);}euint8* ioman_getPtr(IOManager *ioman,euint16 bufplace){ if(bufplace>=ioman->numbuf)return(0); return(ioman->bufptr+bufplace*512);}esint16 ioman_getBp(IOManager *ioman,euint8* buf){ if(buf<(ioman->bufptr) || buf>=( ioman->bufptr+(ioman->numbuf*512) )){ return(-1); } return((buf-(ioman->bufptr))/512);}esint8 ioman_readSector(IOManager *ioman,euint32 address,euint8* buf){ esint8 r; /*DBG((TXT("ioman_readSector::Requesting address %u to be put in %p.\n"),address,buf));*/ if(buf==0){ /*DBG((TXT("Refused to read sector, buf=0\n")));*/ return(-1); } r=if_readBuf(ioman->iface,address,buf); if(r!=0){ return(-1); } return(0);}esint8 ioman_writeSector(IOManager *ioman, euint32 address, euint8* buf){ esint8 r; if(buf==0)return(-1); r=if_writeBuf(ioman->iface,address,buf); if(r<=0){ return(-1); } return(0);}void ioman_resetCacheItem(IOManager *ioman,euint16 bufplace){ ioman->sector[bufplace] = 0; ioman->status[bufplace] = 0; ioman->usage[bufplace] = 0; ioman->reference[bufplace] = 0;}esint32 ioman_findSectorInCache(IOManager *ioman, euint32 address){ euint16 c; for(c=0;c<ioman->numbuf;c++){ if(ioman_isValid(c) && ioman->sector[c] == address)return(c); } return(-1);}esint32 ioman_findFreeSpot(IOManager *ioman){ euint16 c; for(c=0;c<ioman->numbuf;c++){ if(!ioman_isValid(c))return(c); } return(-1);}esint32 ioman_findUnusedSpot(IOManager *ioman){ esint32 r=-1; euint16 c; euint8 fr=0,lr=0xFF; for(c=0;c<ioman->numbuf;c++){ if(ioman_getUseCnt(ioman,c)==0){ if(!ioman_isWritable(c) && !fr){ fr=1; lr=0xFF; r=-1; } if(ioman_isWritable(c) && !fr){ if(ioman_getRefCnt(ioman,c)<=lr){ r=c; lr=ioman_getRefCnt(ioman,c); } } if(fr && !ioman_isWritable(c)){ if(ioman_getRefCnt(ioman,c)<=lr){ r=c; lr=ioman_getRefCnt(ioman,c); } } } } return(r);}esint32 ioman_findOverallocableSpot(IOManager *ioman){ euint8 points,lp=0xFF; euint16 c; esint32 r=-1; for(c=0;c<ioman->numbuf;c++){ if(ioman->itptr[c]<ioman->numit){ points = 0; if(ioman_isWritable(c))points+=0x7F; points += ((euint16)(ioman->itptr[c]*0x4D))/(ioman->numit); points += ((euint16)(ioman_getRefCnt(ioman,c)*0x33))/0xFF; if(points<lp){ lp=points; r=c; } } } return(r);}esint8 ioman_putSectorInCache(IOManager *ioman, euint32 address, euint16 bufplace){ euint8* buf; if((buf = ioman_getPtr(ioman,bufplace))==0)return(-1); if((ioman_readSector(ioman,address,buf)))return(-1); ioman_setValid(bufplace); ioman->sector[bufplace]=address; return(0);}esint8 ioman_flushSector(IOManager *ioman, euint16 bufplace){ euint8* buf; if((buf = ioman_getPtr(ioman,bufplace))==0)return(-1); if(!ioman_isWritable(bufplace))return(-1); if(!(ioman_writeSector(ioman,ioman->sector[bufplace],buf)))return(-1); return(0);}euint8* ioman_getSector(IOManager *ioman,euint32 address, euint8 mode){ esint32 bp; if((bp=ioman_findSectorInCache(ioman,address))!=-1){ if(mode==IOM_MODE_READWRITE){ ioman_setWritable(bp); } ioman_incUseCnt(ioman,bp); ioman_incRefCnt(ioman,bp); return(ioman_getPtr(ioman,bp)); } if((bp=ioman_findFreeSpot(ioman))==-1){ if(((bp=ioman_findUnusedSpot(ioman))!=-1)&&(ioman_isWritable(bp))){ ioman_flushSector(ioman,bp); } } if(bp!=-1){ ioman_resetCacheItem(ioman,bp); if((ioman_putSectorInCache(ioman,address,bp))){ return(0); } if(mode==IOM_MODE_READWRITE){ ioman_setWritable(bp); } ioman_incUseCnt(ioman,bp); ioman_incRefCnt(ioman,bp); return(ioman_getPtr(ioman,bp)); } if((bp=ioman_findOverallocableSpot(ioman))!=-1){ if(ioman_isWritable(bp)){ ioman_flushSector(ioman,bp); } if(ioman_push(ioman,bp)){ return(0); } ioman_resetCacheItem(ioman,bp); if((ioman_putSectorInCache(ioman,address,bp))){ return(0); } if(mode==IOM_MODE_READWRITE){ ioman_setWritable(bp); } ioman_incUseCnt(ioman,bp); ioman_incRefCnt(ioman,bp); return(ioman_getPtr(ioman,bp)); } return(0);}esint8 ioman_releaseSector(IOManager *ioman,euint8* buf){ euint16 bp; bp=ioman_getBp(ioman,buf); ioman_decUseCnt(ioman,bp); if(ioman_getUseCnt(ioman,bp)==0 && ioman->itptr!=0){ if(ioman_isWritable(bp)){ ioman_flushSector(ioman,bp); } ioman_pop(ioman,bp); ioman_putSectorInCache(ioman,ioman->sector[bp],bp); } return(0);}void ioman_printStatus(IOManager *ioman){ euint16 c; DBG(TXT("IO-Manager -- Report\n====================\n\n")); DBG(TXT("Buffer is %i sectors, from %p to %p\n"), ioman->numbuf,ioman->bufptr,ioman->bufptr+(ioman->numbuf*512)); for(c=0;c<ioman->numbuf;c++){ if(ioman_isValid(c)){ DBG(TXT("BP %3i\t SC %i\t\t US %i\t RF %i\t %s %s\n"), c,ioman->sector[c],ioman_getUseCnt(ioman,c),ioman_getRefCnt(ioman,c), ioman_isUserBuf(c) ? "USRBUF" : " ", ioman_isWritable(c) ? "WRITABLE" : "READONLY"); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?