📄 fs_fat.c
字号:
sect = get_fat_sect (2);
cache_fat (sect);
for (clus = 2; clus < (mmc.DataClusCnt + 2); clus++) {
if ((clus & 0xFF) == 0) {
/* Read a part of FAT table to buffer. */
cache_fat (sect++);
}
/* if 'next' == 0 (LE or BE) */
if (((U16 *)fat.buf)[clus & 0xFF] == 0) {
nfree++;
}
}
return (nfree);
}
if (mmc.FatType == FS_FAT32) {
sect = get_fat_sect (2);
cache_fat (sect);
for (clus = 2; clus < (mmc.DataClusCnt + 2); clus++) {
if ((clus & 0x7F) == 0) {
/* Read a part of FAT table to buffer. */
cache_fat (sect++);
}
/* if 'next' == 0 (LE or BE) */
if (((U32 *)fat.buf)[clus & 0x7F] == 0) {
nfree++;
}
}
return (nfree);
}
return (0);
}
/*--------------------------- clus_to_sect ----------------------------------*/
static U32 clus_to_sect (U32 clus) {
/* Calculate absolute sector address from the cluster index. */
U32 sect,base;
base = mmc.BootRecSec + mmc.RootDirAddr;
if (mmc.FatType != FS_FAT32) {
base += mmc.RootSecCnt;
}
sect = (clus - 2) * mmc.SecPerClus;
return (base + sect);
}
/*--------------------------- get_fat_sect ----------------------------------*/
static U32 get_fat_sect (U32 clus) {
/* Calculate absolute FAT Sector address from cluster address. */
U32 fats;
switch (mmc.FatType) {
case FS_FAT12:
/* FAT Cluster width 12 bits. */
fats = (clus * 3) / 1024;
break;
case FS_FAT16:
/* FAT Cluster width 16 bits. */
fats = clus / 256;
break;
case FS_FAT32:
/* FAT Cluster width 32 bits. */
fats = clus / 128;
break;
default:
/* Not supported. */
return (0);
}
if (fats >= mmc.FatSize) {
return (0);
}
fats += (mmc.BootRecSec + mmc.RsvdSecCnt);
return (fats);
}
/*--------------------------- read_sector -----------------------------------*/
static BOOL read_sector (U32 sect) {
/* Read a 512 byte sector from Flash Card. */
if (sect == ca.sect) {
/* Required sector already in buffer. */
return (__TRUE);
}
if (sect >= ca.csect && sect < (ca.csect + ca.nwr)) {
/* This sector is in write cache buffer. */
memcpy (ca.buf, ca.cbuf + (sect - ca.csect) * 512, 512);
ca.sect = sect;
return (__TRUE);
}
/* Sector not in cache, read it from the Memory Card. */
if (mmc_read_sect (sect, ca.buf, 1) == __TRUE) {
ca.sect = sect;
return (__TRUE);
}
ca.sect = INVAL_SECT;
return (__FALSE);
}
/*--------------------------- write_sector ----------------------------------*/
static BOOL write_sector (U32 sect) {
/* Write a 512 byte sector to Flash Card. */
if (mmc_write_sect (sect, ca.buf, 1) == __TRUE) {
ca.sect = sect;
return (__TRUE);
}
return (__FALSE);
}
/*--------------------------- read_cache ------------------------------------*/
static BOOL read_cache (U32 sect, U32 cnt) {
/* Read a 512 byte sector from Flash Card. */
if ((_MC_CSIZE == 0) || (ca.nwr > 0)) {
/* File Caching switched off or write caching active. */
return (read_sector (sect));
}
if (ca.nrd > 0) {
if ((ca.csect <= sect) && sect < (ca.csect + ca.nrd)) {
/* Requested sector is already cached. */
memcpy (ca.buf, ca.cbuf + (sect - ca.csect) * 512, 512);
ca.sect = sect;
return (__TRUE);
}
}
if (cnt > _MC_CSIZE) {
cnt = _MC_CSIZE;
}
/* Sector not in cache, read it from the Memory Card. */
if (mmc_read_sect (sect, ca.buf, cnt) == __TRUE) {
ca.sect = sect;
/* First sector is used, the rest is cached. */
ca.csect = sect + 1;
ca.nrd = cnt - 1;
return (__TRUE);
}
ca.sect = INVAL_SECT;
ca.nrd = 0;
return (__FALSE);
}
/*--------------------------- write_cache -----------------------------------*/
static void write_cache (U32 sect) {
/* Write a 512 byte sector to Data cache. */
if (_MC_CSIZE == 0) {
/* File Caching switched off. */
if (sect) {
write_sector (sect);
}
return;
}
if (sect == 0) {
/* Flush cache request. */
if (ca.nwr) {
mmc_write_sect (ca.csect, ca.cbuf, ca.nwr);
ca.nwr = 0;
}
return;
}
ca.sect = sect;
if (ca.nwr > 0) {
if (sect == (ca.csect + ca.nwr) && ca.nwr < _MC_CSIZE) {
/* Next sector is continuous, still space in cache. */
memcpy (ca.cbuf + (ca.nwr * 512), ca.buf, 512);
ca.nwr++;
return;
}
/* Not continuous sector or buffer full, flush the cache. */
mmc_write_sect (ca.csect, ca.cbuf, ca.nwr);
ca.nwr = 0;
}
/* Write Data cache is empty. */
memcpy (ca.cbuf, ca.buf, 512);
ca.csect = sect;
ca.nwr = 1;
ca.nrd = 0;
}
/*--------------------------- cache_fat -------------------------------------*/
static BOOL cache_fat (U32 sect) {
/* Handle MC FAT Cache. Read/write a 512 byte FAT sector. */
if (sect == fat.sect) {
/* Required sector already in buffer. */
return (__TRUE);
}
if (fat.dirty == __TRUE) {
/* Current FAT sector has been changed, write it first. */
fat.dirty = __FALSE;
mmc_write_sect (fat.sect, fat.buf, 1);
}
if (sect == 0) {
/* Only write if sector updated. */
return (__TRUE);
}
if (mmc_read_sect (sect, fat.buf, 1) == __TRUE) {
fat.sect = sect;
return (__TRUE);
}
fat.sect = INVAL_SECT;
return (__FALSE);
}
/*--------------------------- is_EOC ----------------------------------------*/
static BOOL is_EOC (U32 clus) {
/* Check if this cluster is an End Of Chain Marker. */
switch (mmc.FatType) {
case FS_FAT12:
if (clus >= 0x0FF8) {
return (__TRUE);
}
break;
case FS_FAT16:
if (clus >= 0xFFF8) {
return (__TRUE);
}
break;
case FS_FAT32:
if ((clus & 0x0FFFFFFF) >= 0x0FFFFFF8) {
return (__TRUE);
}
break;
}
return (__FALSE);
}
/*--------------------------- get_EOC ---------------------------------------*/
static U32 get_EOC (void) {
/* Return an End Of Chain Marker. */
switch (mmc.FatType) {
case FS_FAT12:
return (0x0FFF);
case FS_FAT16:
return (0xFFFF);
case FS_FAT32:
return (0x0FFFFFFF);
}
return (0);
}
/*--------------------------- get_mbrec -------------------------------------*/
static BOOL get_mbrec (void) {
/* Read Master Volume Boot Record info. */
/* Read MBR and set FAT offset address. */
if (read_sector (0) == __FALSE) {
return (__FALSE);
}
/* Check Executable Marker. */
if (get_u16 (&ca.buf[510]) != 0xAA55) {
/* Invalid Master Boot Record. */
return (__FALSE);
}
if ((ca.buf[0] == 0xE9) || (ca.buf[0] == 0xEB && ca.buf[2] == 0x90)) {
/* Partition Table does not exist, this is a BPB. */
mmc.BootRecSec = 0;
}
else {
/* Flash Cards have only one Partition. */
mmc.BootRecSec = get_u32 (&ca.buf[454]);
}
return (__TRUE);
}
/*--------------------------- get_bootrec -----------------------------------*/
static BOOL get_bootrec (void) {
/* Read Volume Boot Record info. */
if (read_sector (mmc.BootRecSec) == __FALSE) {
return (__FALSE);
}
/* Check Executable Marker. */
if (get_u16 (&ca.buf[510]) != 0xAA55) {
/* Invalid Master Boot Record. */
return (__FALSE);
}
/* Set Volume Parameter Info. */
mmc.SecPerClus = ca.buf[13];
mmc.BytesPerSec= get_u16 (&ca.buf[11]);
mmc.RsvdSecCnt = get_u16 (&ca.buf[14]);
mmc.NumOfFat = ca.buf[16];
mmc.RootEntCnt = get_u16 (&ca.buf[17]);
mmc.DskSize = get_u16 (&ca.buf[19]);
mmc.FatSize = get_u16 (&ca.buf[22]);
if ((mmc.DskSize == 0) && (mmc.FatSize == 0)) {
/* Read or correct specific data in mmc structure for FAT32. */
mmc.FAT32_ExtFlags = get_u16 (&ca.buf[40]);
mmc.FAT32_RootClus = get_u32 (&ca.buf[44]);
mmc.FAT32_FSInfo = get_u16 (&ca.buf[48]);
mmc.FAT32_BkBootSec = get_u16 (&ca.buf[50]);
}
if (mmc.DskSize == 0) {
/* If num of sectors > 0xFFFF, this field is nonzero. */
mmc.DskSize = get_u32 (&ca.buf[32]);
}
if (mmc.FatSize == 0) {
/* Fat size is in this field for FAT32. */
mmc.FatSize = get_u32 (&ca.buf[36]);
}
return (__TRUE);
}
/*--------------------------- is_fat_valid ----------------------------------*/
static BOOL is_fat_valid (void) {
/* Check if Volume Info is sane. */
/* We only support 512 byte sectors. */
if (mmc.BytesPerSec != 512) {
return (__FALSE);
}
/* Check for Valid Sectors per Cluster values. */
switch (mmc.SecPerClus) {
case 1:
case 2:
case 4:
case 8:
case 16:
case 32:
case 64: break;
default: return (__FALSE);
}
/* There should be at least 1 reserved sector. */
if (mmc.RsvdSecCnt == 0 || mmc.RsvdSecCnt > 64) {
return (__FALSE);
}
/* Only 1 or 2 FAT tables supported. */
switch (mmc.NumOfFat) {
case 1:
case 2: break;
default: return (__FALSE);
}
if (mmc.FatSize > mmc.DskSize) {
return (__FALSE);
}
return (__TRUE);
}
/*--------------------------- get_time --------------------------------------*/
static U16 get_time (void) {
/* Get current system time for a time stamp of a file. */
U32 retv, time, v;
time = fs_get_time ();
/* Seconds: 0-29 (2-second count) */
v = (time >> 1) & 0x1F;
if (v > 29) v = 0;
retv = v;
/* Minutes: 0-59 */
v = (time >> 8) & 0x3F;
if (v > 59) v = 0;
retv |= (v << 5);
/* Hours: 0-23 */
v = (time >> 16) & 0x1F;
if (v > 23) v = 23;
retv |= (v << 11);
return (retv);
}
/*--------------------------- get_date --------------------------------------*/
static U16 get_date (void) {
/* Get current system date for a time stamp of a file. */
U32 retv, date, v;
date = fs_get_date ();
/* Days: 1-31 */
v = date & 0x1F;
if (v == 0) v = 1;
retv = v;
/* Month: 1-12 */
v = (date >> 8) & 0x0F;
if (v > 12 || v == 0) v = 1;
retv |= (v << 5);
/* Year: 0-127 */
v = (date >> 16) - 1980;
v &= 0x7F;
retv |= (v << 9);
return (retv);
}
/*--------------------------- set_time_date ---------------------------------*/
static void set_time_date (FINFO *info, FILEREC *frec) {
/* Convert date/time info and write to 'info' structure. */
U32 v;
v = get_u16 ((U8 *)&frec->WriteTime);
info->time.hr = (v >> 11);
info->time.min = (v >> 5) & 0x3F;
info->time.sec = (v & 0x1F) << 1;
v = get_u16 ((U8 *)&frec->WriteDate);
info->time.day = (v & 0x1F);
info->time.mon = (v >> 5) & 0x0F;
info->time.year= ((v >> 9) & 0x7F) + 1980;
}
/*--------------------------- cvt_fatname -----------------------------------*/
static BOOL cvt_fatname (const char *fn, char *en) {
/* Convert name to short file entry name. */
/* fn = pointer to the file name
en = pointer to the entry file name */
BOOL dot = 0;
U8 ch0, ch1, ch2;
U32 i;
/* Prepare entry name with 'space's. */
for (i = 0; i < 11; i++) {
en[i] = ' ';
}
/* Terminate entry name. */
en[i] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -