📄 fat.c
字号:
useTopList = curr;
return 0;
}
/*-----------------------------------------------------------------------------*/
static int WriteSector(UCHAR driveNum, ULONG sector, UCHAR *buf)
{
char curr, prev;
int i, flag;
CACHE_RES *cache;
i = 0;
flag = 0;
if (useTopList != -1) {
curr = prev = useTopList;
for(i = 0; i < CFG_CACHE_NUM; i++) {
cache = &cacheRes[curr];
if (cache->drive == driveNum && cache->sector == sector) {
flag = 1;
break;
}
if (cache->next == -1) { // list end ?
break;
}
prev = curr;
curr = cache->next;
}
}
if (flag == 0) { /* not found */
if (i < CFG_CACHE_NUM-1) { // exist blank cache
curr = (char)GetBlankCache();
cache = &cacheRes[curr];
}
else { // cache full
if (cache->write_flag == 1) {
driverAPI[cache->drive].write(cache->sector, 1, cache->buffer);
}
cacheRes[prev].next = -1; // set end-mark
}
cache->drive = driveNum;
cache->sector = sector;
}
memcpy(cache->buffer, buf, SECTOR_SIZE);
cache->write_flag = 1;
cache->next = useTopList;
useTopList = curr;
return 0;
}
/*-----------------------------------------------------------------------------*/
static int GetBlankCache(void)
{
int i;
for(i = 0; i < CFG_CACHE_NUM; i++) {
if (cacheRes[i].use_flag == 0) {
cacheRes[i].use_flag = 1;
return i;
}
}
return -1;
}
/*-----------------------------------------------------------------------------*/
static int FlushCache(void)
{
char curr;
CACHE_RES *cache;
int i;
if (useTopList != -1) {
curr = useTopList;
for(i = 0; i < CFG_CACHE_NUM; i++) {
cache = &cacheRes[curr];
if (cache->write_flag == 1) {
driverAPI[cache->drive].write(cache->sector, 1, cache->buffer);
cache->write_flag = 0;
}
if (cache->next == -1) { // list end ?
break;
}
curr = cache->next;
}
}
return 0;
}
/*-----------------------------------------------------------------------------*/
static int GetTotalFreeClu(UCHAR driveNum, ULONG *freeCnt)
{
int ret;
FlushCache();
if (fatDriveRes[driveNum].fileType == TYPE_FAT12) {
ret = _GetTotalFreeClu12(driveNum, freeCnt);
}
else { // TYPE_FAT16
ret = _GetTotalFreeClu16(driveNum, freeCnt);
}
return ret;
}
/*-----------------------------------------------------------------------------*/
static int _GetTotalFreeClu12(UCHAR driveNum, ULONG *freeCnt)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
USHORT secOffset, byteOffset;
ULONG total;
int i, j;
UCHAR buf[3];
total = 0;
secOffset = 0;
byteOffset = TOP_CLUSTER*3/2;
driverAPI[driveNum].read(drive->fatSector, 1, workBuffer);
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
for(j = 0; j < 3; j++) {
buf[j] = workBuffer[byteOffset++];
if (byteOffset >= SECTOR_SIZE) {
byteOffset = 0;
secOffset ++;
driverAPI[driveNum].read(drive->fatSector+secOffset, 1, workBuffer);
}
}
if (buf[0] == 0 && (buf[1] & 0x0F) == 0) {
total ++;
}
i++;
if (i > drive->maxClu) {
break;
}
if ((buf[1] & 0xF0) == 0 && buf[2] == 0) {
total ++;
}
}
*freeCnt = total;
return 0;
}
/*-----------------------------------------------------------------------------*/
static int _GetTotalFreeClu16(UCHAR driveNum, ULONG *freeCnt)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
USHORT secOffset, byteOffset;
ULONG total;
int i;
total = 0;
secOffset = 0;
byteOffset = TOP_CLUSTER*2;
driverAPI[driveNum].read(drive->fatSector, 1, workBuffer);
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
if (ushort(workBuffer[byteOffset]) == 0) {
total++;
}
byteOffset +=2;
if (byteOffset >= SECTOR_SIZE) {
byteOffset = 0;
secOffset ++;
driverAPI[driveNum].read(drive->fatSector+secOffset, 1, workBuffer);
}
}
*freeCnt = total;
return 0;
}
/*-----------------------------------------------------------------------------*/
static int GetFreeClu(UCHAR driveNum, USHORT *freeClu)
{
int ret;
if (fatDriveRes[driveNum].fileType == TYPE_FAT12) {
ret = _GetFreeClu12(driveNum, freeClu);
}
else { // TYPE_FAT16
ret = _GetFreeClu16(driveNum, freeClu);
}
return ret;
}
/*-----------------------------------------------------------------------------*/
static int _GetFreeClu12(UCHAR driveNum, USHORT *freeClu)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
USHORT offset, secOffset, byteOffset, cluster;
int i, j;
UCHAR buf[3];
cluster = drive->freeClu +1;
if (cluster > drive->maxClu) {
cluster = TOP_CLUSTER;
}
if (cluster & 0x01) { /* odd number */
offset = (cluster-1)*3/2;
}
else {
offset = cluster*3/2;
}
secOffset = offset/SECTOR_SIZE;
byteOffset = offset%SECTOR_SIZE;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
for(j = 0; j < 3; j++) {
buf[j] = workBuffer[byteOffset++];
if (byteOffset >= SECTOR_SIZE) {
byteOffset = 0;
secOffset ++;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
}
}
if ((cluster & 0x01) == 0) { /* even number */
if (buf[0] == 0 && (buf[1] & 0x0F) == 0) {
*freeClu = cluster;
drive->freeClu = cluster;
/*
buf[0]=[SECTOR_SIZE-1], buf[1]=[0], buf[2]=[1], byteOffset = 2
*/
if (byteOffset == 2) { /* sector over */
workBuffer[0] = (workBuffer[0] & 0x0F0) + (UCHAR)((END_CLUSTER >> 8) & 0x0F);
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
secOffset --;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
workBuffer[SECTOR_SIZE-1] = (UCHAR)END_CLUSTER;
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
}
else {
if (byteOffset < 2) {
secOffset --;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
byteOffset += SECTOR_SIZE;
}
byteOffset -= 3; /* 1st byte */
workBuffer[byteOffset] = (UCHAR)END_CLUSTER;
workBuffer[byteOffset+1] = (workBuffer[byteOffset+1] & 0x0F0) + (UCHAR)((END_CLUSTER >> 8) & 0x0F);
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
}
return 0;
}
cluster ++;
if (cluster > drive->maxClu) {
cluster = TOP_CLUSTER;
byteOffset = TOP_CLUSTER*3/2;
secOffset = 0;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
continue;
}
}
if ((buf[1] & 0xF0) == 0 && buf[2] == 0) {
*freeClu = cluster;
drive->freeClu = cluster;
/*
buf[0]=[SECTOR_SIZE-2], buf[1]=[SECTOR_SIZE-1], buf[2]=[0], byteOffset = 1
*/
if (byteOffset == 1) { /* sector over */
workBuffer[0] = (UCHAR)(END_CLUSTER >> 4);
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
secOffset --;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
workBuffer[SECTOR_SIZE-1] = (workBuffer[SECTOR_SIZE-1] & 0x0F) + (UCHAR)(END_CLUSTER << 4);
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
}
else {
if (byteOffset < 1) {
secOffset --;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
byteOffset += SECTOR_SIZE;
}
byteOffset -= 2; /* 2nd byte */
workBuffer[byteOffset] = (workBuffer[byteOffset] & 0x0F) + (UCHAR)(END_CLUSTER << 4);
workBuffer[byteOffset+1] = (UCHAR)(END_CLUSTER >> 4);
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
}
return 0;
}
i ++;
cluster ++;
if (cluster > drive->maxClu) {
cluster = TOP_CLUSTER;
byteOffset = TOP_CLUSTER*3/2;
secOffset = 0;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
}
}
return -1;
}
/*-----------------------------------------------------------------------------*/
static int _GetFreeClu16(UCHAR driveNum, USHORT *freeClu)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
USHORT offset, secOffset, byteOffset, cluster;
int i;
cluster = drive->freeClu +1;
if (cluster > drive->maxClu) {
cluster = TOP_CLUSTER;
}
offset = cluster*2;
secOffset = offset/SECTOR_SIZE;
byteOffset = offset%SECTOR_SIZE;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
if (ushort(workBuffer[byteOffset]) == 0) {
*freeClu = cluster;
drive->freeClu = cluster;
workBuffer[byteOffset] = (UCHAR)END_CLUSTER;
workBuffer[byteOffset+1] = (UCHAR)(END_CLUSTER >> 8);
WriteSector(driveNum, drive->fatSector+secOffset, workBuffer);
CopyFATSector(driveNum, secOffset, workBuffer);
return 0;
}
byteOffset +=2;
if (byteOffset >= SECTOR_SIZE) {
byteOffset = 0;
secOffset ++;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
}
cluster ++;
if (cluster > drive->maxClu) {
cluster = TOP_CLUSTER;
byteOffset = TOP_CLUSTER*2;
secOffset = 0;
ReadSector(driveNum, drive->fatSector+secOffset, workBuffer);
}
}
return -1;
}
/*-----------------------------------------------------------------------------*/
static int GetDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry, ULONG *sector, USHORT *offset)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i, ret;
USHORT next;
if (cluster == 0) { /* root directory */
if (_GetDirEntry(driveNum, cluster, entry, sector, offset) == 0) {
return 0;
}
else {
return -1;
}
}
else {
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
if (_GetDirEntry(driveNum, cluster, entry, sector, offset) == 0) {
return 0; /* found */
}
ret = NextFATEntry(driveNum, cluster, &next);
if (ret != 1) { /* cluster error/cluster end */
break;
}
cluster = next;
}
return -1; /* not found */
}
}
/*-----------------------------------------------------------------------------*/
static int _GetDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry, ULONG *secNum, USHORT *offset)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i, j, numSector;
ULONG sector;
DIR_ENT *readEntry;
if (cluster == 0) { /* root */
sector = drive->rootSector;
numSector = drive->numRootSector;
}
else {
sector = CluToSector(driveNum, cluster);
numSector = drive->sectorPerClu;
}
for(i = 0; i < numSector; i++) {
ReadSector(driveNum, sector, workBuffer);
for(j = 0; j < SECTOR_SIZE; j+=32) {
readEntry = (DIR_ENT*)(workBuffer+j);
/* compair filename + extension */
if (strncmp((char*)entry->filename, (char*)readEntry->filename, 11) == 0) {
*entry = *readEntry;
if (secNum != NULL) {
*secNum = sector;
}
if (offset != NULL) {
*offset = j;
}
return 0;
}
}
sector ++;
}
return -1;
}
/*-----------------------------------------------------------------------------*/
static int AddDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i, ret;
USHORT newClu, next;
ULONG sector;
if (cluster == 0) { /* root directory */
if (_AddDirEntry(driveNum, cluster, entry) == 0) {
return 0;
}
else {
return -1;
}
}
else {
for(i = TOP_CLUSTER; i <= drive->maxClu; i++) {
if (_AddDirEntry(driveNum, cluster, entry) == 0) {
return 0;
}
ret = NextFATEntry(driveNum, cluster, &next);
if (ret < 0) { /* cluster error */
return -1;
}
if (ret == 0) { /* cluster end */
break;
}
cluster = next;
}
if (i > drive->maxClu) { /* cluster chain error */
return -1;
}
if (GetFreeClu(driveNum,&newClu) == 0) {
sector = CluToSector(driveNum, newClu);
memset(workBuffer, 0, SECTOR_SIZE);
for(i = 1; i < drive->sectorPerClu; i++) {
driverAPI[driveNum].write(sector+i, 1, workBuffer);
}
*(DIR_ENT *)(workBuffer) = *entry;
WriteSector(driveNum, sector, workBuffer);
WriteFATEntry(driveNum, cluster, newClu);
return 0;
}
return -1; /* disk full */
}
}
/*-----------------------------------------------------------------------------*/
static int _AddDirEntry(UCHAR driveNum, USHORT cluster, DIR_ENT *entry)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i, j, numSector;
ULONG sector;
DIR_ENT *readEntry;
if (cluster == 0) { /* root */
sector = drive->rootSector;
numSector = drive->numRootSector;
}
else {
sector = CluToSector(driveNum, cluster);
numSector = drive->sectorPerClu;
}
for(i = 0; i < numSector; i++) {
ReadSector(driveNum, sector, workBuffer);
for(j = 0; j < SECTOR_SIZE; j+=32) {
readEntry = (DIR_ENT*)(workBuffer+j);
if (readEntry->filename[0] == DELETE_MARK ||
readEntry->filename[0] == 0) /* deleted or blank */
{
*readEntry = *entry;
WriteSector(driveNum, sector, workBuffer);
return 0;
}
}
sector ++;
}
return -1;
}
/*-----------------------------------------------------------------------------*/
static int CheckDirEmpty(UCHAR driveNum, USHORT cluster)
{
FATDRIVE_RES *drive= &fatDriveRes[driveNum];
int i, ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -