📄 rtfiles.c
字号:
B->Next = FirstBuffer;
B->Prev = FirstBuffer->Prev;
B->Next->Prev = B;
B->Prev->Next = B;
}
}
/*-----------------------------------*/
static void INTERN FreeBuffer(RTFDevice * Dev)
// this is called only by UnlockDevice and GetBuffer
{
if (Dev->DevData.B)
{
Dev->DevData.B->Flags &= ~B_INUSE;
Dev->DevData.B = NULL;
}
}
/*-----------------------------------*/
static void INTERN DiscardOtherBuffer(RTFBuffer * B)
{
#ifdef __FS_DEBUG__
if (B->Flags & B_DIRTY)
BufferStat.DirtyBuffers--;
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
if (B->Flags & B_SINGLE)
B->Flags = B_SINGLE;
else
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */
B->Flags = 0;
B->recoverable_flag = RTF_NORMAL_WRITE;
ToTail(B);
}
/*-----------------------------------*/
static void INTERN DiscardBuffer(RTFDevice * Dev)
// this frees a buffer
{
#ifdef DEBUG
if (Dev->DevData.B == NULL)
RTFSYSErrorExit("Can't discard non-current buffer", 1);
#endif
DiscardOtherBuffer(Dev->DevData.B);
Dev->DevData.B = NULL;
}
/*-----------------------------------*/
static void INTERN AllocBuffers(void)
{
RTFBuffer * B;
UINT i;
if (FirstBuffer)
return;
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
#ifdef __FS_EMERGENT_NOR_BUFFER_SUPPORT__
g_Emergent_NOR_Buffer.Flags |= B_SINGLE;
g_Emergent_NOR_Buffer.recoverable_flag = RTF_NORMAL_WRITE;
g_Emergent_NOR_Buffer.Data = g_Emergent_NOR_BufferData;
#endif
#ifdef __FS_EMERGENT_NAND_BUFFER_SUPPORT__
g_Emergent_NAND_Buffer.Flags |= B_SINGLE;
g_Emergent_NAND_Buffer.recoverable_flag = RTF_NORMAL_WRITE;
g_Emergent_NAND_Buffer.Data = g_Emergent_NAND_BufferData;
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */
//if (gFS_Data.Version != RTFILE_VER)
//RTFSYSErrorExit("gFS_Data version mismatch", 1);
#ifdef __FS_DEBUG__
BufferStat.TotalBuffers = FS_MAX_BUFFERS;
#endif
if ((RTF_MIN_BUFFER_SIZE > RTF_MAX_BUFFER_SIZE) ||
!PowerTwo(RTF_MIN_BUFFER_SIZE))
RTFSYSErrorExit("Invalid RTF_BUFFER_SIZE", 1);
if (FS_MAX_FILES > FMAX)
RTFSYSErrorExit("Too many file handles", 1);
if (((DWORD) gFS_Data.BufferTable) % 4)
RTFSYSErrorExit("Cache buffer not properly aligned", 1);
for (i=0; i<FS_MAX_BUFFERS; i++)
{
B = gFS_Data.BufferTable + i;
B->Num = i;
B->recoverable_flag = RTF_NORMAL_WRITE;
B->Data = gFS_Data.BufferData + (i*RTF_MIN_BUFFER_SIZE);
B->Next = B + 1;
B->Prev = B - 1;
}
FirstBuffer = gFS_Data.BufferTable;
FirstBuffer->Prev = FirstBuffer + FS_MAX_BUFFERS - 1;
FirstBuffer->Prev->Next = FirstBuffer;
}
#ifdef __FS_DEBUG__
/*-----------------------------------*/
void RTFAPI RTFBufferInfo(RTFBufferStatistic * BufferInfo)
{
RTFBuffer * B;
#ifdef DEBUG
UINT Test = 0;
#endif
if (FirstBuffer == 0)
AllocBuffers();
*BufferInfo = BufferStat;
BufferInfo->CacheHits = BufferInfo->PhysicalBufferReads ? 100 * (BufferInfo->CachedBufferReads) / (BufferInfo->PhysicalBufferReads + BufferInfo->CachedBufferReads) : 0;
BufferInfo->ValidBuffers = 0;
B = FirstBuffer;
do
{
if (B->Flags & B_VALID)
BufferInfo->ValidBuffers++;
#ifdef DEBUG
if (B->Flags & B_DIRTY)
Test++;
#endif
B = B->Next;
} while (B != FirstBuffer);
#ifdef DEBUG
if (Test != BufferStat.DirtyBuffers)
RTFSYSErrorExit("DirtyBuffers incorrect", 0);
#endif
}
#endif
/*-----------------------------------*/
static void INTERN ReadBuffer(RTFBuffer * B)
{
int fs_block_type = FS_BLOCK_ENUM; /* Fix multi-access bug, Karen Hsu, 2004/07/08, ADD */
XTRY
case XCODE:
B->Flags |= B_BUSY;
ReadSectors(B->Dev, B->Data, B->Sector, 1, 0);
// set the recoverable_flag according to the TLS setting
fs_block_type = (int)RTFSYSGetTLS(TLSBlockIndex);
if (fs_block_type == FS_BLOCK_PROTECTION_ENUM)
B->recoverable_flag = RTF_RECOVERABLE_WRITE;
else
B->recoverable_flag = RTF_NORMAL_WRITE;
#ifdef __FS_DEBUG__
BufferStat.PhysicalBufferReads++;
#endif
B->Flags |= B_VALID;
break;
default:
ToTail(B);
B->Flags &= ~B_INUSE;
break;
case XFINALLY:
B->Flags &= ~B_BUSY;
break;
XENDX
}
/*-----------------------------------*/
static void INTERN WriteBuffer(RTFBuffer * B)
{
#ifdef DEBUG
if (B->Flags != (B_INUSE | B_VALID | B_DIRTY))
RTFSYSErrorExit("Attempt to write none inuse/valid/dirty buffer", 0);
#endif
XTRY
case XCODE:
B->Flags |= B_BUSY;
// recoverable_flag indicates if it has to use recoverablewritesector or not
if (B->recoverable_flag == RTF_RECOVERABLE_WRITE)
WriteSectors(B->Dev, B->Data, B->Sector, 1, 0, RTF_RECOVERABLE_WRITE);
else
WriteSectors(B->Dev, B->Data, B->Sector, 1, 0, RTF_NORMAL_WRITE);
// clear the recoverable_flag
B->recoverable_flag = RTF_NORMAL_WRITE;
B->Flags &= ~B_DIRTY;
#ifdef __FS_DEBUG__
BufferStat.PhysicalBufferWrites++;
BufferStat.AsynchBufferFlushs += (B->FirstDirtyTime != B->Dev->DevData.AccessCount);
BufferStat.DirtyBuffers--;
#endif
// check if this is a FAT sector and we have to
// take care of other FATs
// We will ignore any errors here, but we do want
// critical errors.
{
int i, FATs;
if ((B->FATSectorInfo) && ((B->Dev->DeviceFlags & RTF_DEVICE_SINGLE_FAT) == 0))
FATs = B->FATSectorInfo->FATCount;
else
FATs = 1;
if (FATs > 1)
{
B->Flags = B_VALID | B_INUSE | B_BUSY;
for (i=1; i<FATs; i++)
{
WriteSectors(B->Dev, B->Data, B->Sector + i * B->FATSectorInfo->SectorsPerFAT, 1, NO_RAISE, RTF_NORMAL_WRITE);
#ifdef __FS_DEBUG__
BufferStat.PhysicalBufferWrites++;
BufferStat.AsynchBufferFlushs += B->FirstDirtyTime != B->Dev->DevData.AccessCount;
#endif
}
B->Flags = B_VALID | B_INUSE;
}
}
break;
default: // only the first FAT can raise exceptions
B->Flags &= ~B_INUSE;
break;
case XFINALLY:
B->Flags &= ~B_BUSY;
break;
XENDX
}
/*-----------------------------------*/
static void * INTERN SearchBuffer(RTFDevice * Dev, RTFSector Sector)
{
RTFBuffer * B; // selected buffer
#ifdef DEBUG
if (!RTFSYSOwnMutex(RTFLock))
RTFSYSErrorExit("Attempt access buffers without locking", 1);
#endif
if (Dev->DevData.B && (Dev->DevData.B->Sector == Sector))
return Dev->DevData.B->Data;
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
#ifdef __FS_EMERGENT_NOR_BUFFER_SUPPORT__
B = &g_Emergent_NOR_Buffer;
if (B->Flags & B_VALID)
{
if ((B->Sector == Sector) && (B->Dev == Dev))
{
B->Flags |= B_INUSE;
FreeBuffer(Dev);
Dev->DevData.B = B;
return B->Data;
}
}
#endif
#ifdef __FS_EMERGENT_NAND_BUFFER_SUPPORT__
B = &g_Emergent_NAND_Buffer;
if (B->Flags & B_VALID)
{
if ((B->Sector == Sector) && (B->Dev == Dev))
{
B->Flags |= B_INUSE;
FreeBuffer(Dev);
Dev->DevData.B = B;
return B->Data;
}
}
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */
// search forward for the sector in question
B = FirstBuffer;
do
{
if (B->Flags & B_VALID)
{
if ((B->Sector == Sector) && (B->Dev == Dev))
{
#ifdef DEBUG
if (B->Flags & (B_INUSE | B_BUSY)) // double allocation
RTFSYSErrorExit("Buffer allocated twice", 0);
#endif
UpFront(B);
B->Flags |= B_INUSE;
FreeBuffer(Dev);
Dev->DevData.B = B;
return B->Data;
}
}
else
return NULL;
B = B->Next;
} while (B != FirstBuffer);
return NULL;
}
/*-----------------------------------*/
static void * INTERN GetBuffer(RTFDevice * Dev, RTFSector Sector, UINT Flags)
{
RTFBuffer * B; // selected buffer
#ifdef DEBUG
if (!RTFSYSOwnMutex(RTFLock))
RTFSYSErrorExit("Attempt access buffers without locking", 1);
if (Dev->DevData.AltBuffer)
RTFSYSErrorExit("AltBuffer not freed", 1);
#endif
if ((Flags & ALT_BUFFER) == 0)
if (Dev->DevData.B)
{
if (Dev->DevData.B->Sector == Sector)
return Dev->DevData.B->Data;
else
FreeBuffer(Dev);
}
// search forward for the sector in question or an invalid (free) buffer
B = FirstBuffer;
do
{
if (B->Flags != 0)
{
if ((B->Sector == Sector) && (B->Dev == Dev))
{
#ifdef DEBUG
if (B->Flags & (B_INUSE | B_BUSY)) // double allocation
RTFSYSErrorExit("Buffer allocated twice", 0);
if ((B->Flags & B_VALID) == 0)
RTFSYSErrorExit("allocating invalid buffer", 0);
#endif
#ifdef __FS_DEBUG__
BufferStat.CachedBufferReads++;
#endif
B->Flags |= B_INUSE;
goto SaveAndExit;
}
}
else // not allocated buffers follow the first unallocated buffer
{
#ifdef DEBUG
{
RTFBuffer * B1 = B;
do
{
if (B1->Flags != 0)
RTFSYSErrorExit("Buffer with flags after last valid buffer", 0);
B1 = B1->Next;
}
while (B1 != FirstBuffer);
}
#endif
goto ReadAndExit;
}
B = B->Next;
} while (B != FirstBuffer);
#ifdef __FS_DEBUG__
BufferStat.BuffersDiscarded++; // we have to discard one
#endif
// now search backwards (oldest first) for a buffer to discard:
// for any buffer on the same device
// or for a clean buffer
B = FirstBuffer->Prev;
do
{
if (((B->Flags & B_INUSE) == 0) && // it's not in use and
((B->Dev == Dev) || // it's on this device or
((B->Flags & B_DIRTY) == 0))) // it's not dirty
{
#ifdef DEBUG
if (B->Flags & B_BUSY)
RTFSYSErrorExit("can't discard a busy buffer", 0);
#endif
if (B->Flags & B_DIRTY)
{
#ifdef DEBUG
if (B->Dev != Dev)
RTFSYSErrorExit("can'd discard foreighn dirty buffer", 0);
#endif
B->Flags |= B_INUSE;
WriteBuffer(B);
}
goto ReadAndExit;
}
B = B->Prev;
} while (B != FirstBuffer->Prev);
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
#ifdef __FS_EMERGENT_NOR_BUFFER_SUPPORT__
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
{
B = &g_Emergent_NOR_Buffer;
B->Flags |= B_INUSE;
if ((B->Sector == Sector) && (B->Dev == Dev))
goto SaveAndExit;
else
goto ReadAndExit;
}
#endif
#ifdef __FS_EMERGENT_NAND_BUFFER_SUPPORT__
if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
{
B = &g_Emergent_NAND_Buffer;
B->Flags |= B_INUSE;
if ((B->Sector == Sector) && (B->Dev == Dev))
goto SaveAndExit;
else
goto ReadAndExit;
}
#endif
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */
#ifdef __FS_TRACE_SUPPORT__
if(g_TraceFlag & MT_TRACE_ERROR)
{
if(Dev->DeviceFlags & MT_DEVICE_NOR_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NOR, Sector: %d", Sector);
else if(Dev->DeviceFlags & MT_DEVICE_NAND_FLASH)
kal_sprintf(TraceTmpBuf, "Dev:NAND, Sector: %d", Sector);
else
kal_sprintf(TraceTmpBuf, "Dev:Card, Sector: %d", Sector);
memset(TraceTmpBuf+strlen((char *)TraceTmpBuf)+1, 0, 2);
MTTraceFS((DWORD)kal_get_current_thread_ID(), 1, __LINE__, RTF_OUT_OF_BUFFERS, NULL, (BYTE *)TraceTmpBuf);
}
#endif
XRAISE(RTF_OUT_OF_BUFFERS);
ReadAndExit:
B->Dev = Dev;
B->Sector = Sector;
B->FATSectorInfo = NULL;
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD START */
if (B->Flags & B_SINGLE)
{
B->Flags = (B_SINGLE | B_INUSE);
}
else
/* Guarantee fixed disk access, Karen Hsu, 2005/05/19, ADD END */
B->Flags = B_INUSE;
B->recoverable_flag = RTF_NORMAL_WRITE;
if (Flags & NO_LOAD)
B->Flags |= B_VALID;
else
ReadBuffer(B);
SaveAndExit:
UpFront(B);
if (Flags & ALT_BUFFER)
Dev->DevData.AltBuffer = B;
else
Dev->DevData.B = B;
return B->Data;
}
/*---------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -