📄 fatfs_supp.c
字号:
diag_printf("FAT: FBR fat name: '%.8s'\n", fbr->fat_name);
diag_printf("FAT: FBR exe mark: 0x%02X 0x%02X\n",
fbr->exe_marker[0], fbr->exe_marker[1]);
}
#endif // TFT
// -------------------------------------------------------------------------
// read_boot_record()
// Reads FAT boot record from disk.
static int
read_boot_record(fatfs_disk_t *disk, fat_boot_record_t *fbr)
{
int len, err;
unsigned char data[0x3E];
len = 0x3E;
err = cyg_blib_read(&disk->blib, (void*)data, &len, 0, 0);
if (err != ENOERR)
return err;
GET_WORD(data, fbr->jump, 0x00);
GET_BYTES(data, fbr->oem_name, 8, 0x03);
GET_WORD(data, fbr->bytes_per_sec, 0x0B);
GET_BYTE(data, fbr->sec_per_clust, 0x0D);
GET_WORD(data, fbr->res_sec_num, 0x0E);
GET_BYTE(data, fbr->fat_tbls_num, 0x10);
GET_WORD(data, fbr->max_root_dents, 0x11);
GET_WORD(data, fbr->sec_num_32, 0x13);
GET_BYTE(data, fbr->media_desc, 0x15);
GET_WORD(data, fbr->sec_per_fat, 0x16);
GET_WORD(data, fbr->sec_per_track, 0x18);
GET_WORD(data, fbr->heads_num, 0x1A);
GET_DWORD(data, fbr->hsec_num, 0x1C);
GET_DWORD(data, fbr->sec_num, 0x20);
GET_WORD(data, fbr->ldrv_num, 0x24);
GET_BYTE(data, fbr->ext_sig, 0x26);
GET_DWORD(data, fbr->ser_num, 0x27);
GET_BYTES(data, fbr->vol_name, 11, 0x2B);
GET_BYTES(data, fbr->fat_name, 8, 0x36);
// Skip the exe code and read the end marker
len = 0x02;
err = cyg_blib_read(&disk->blib, (void*)data, &len, 0, 0x1FE);
if (err != ENOERR)
return err;
GET_BYTES(data, fbr->exe_marker, 2, 0);
// Zero terminate strings
fbr->oem_name[8] = '\0';
fbr->vol_name[11] = '\0';
fbr->fat_name[8] = '\0';
#if TFT
print_boot_record(fbr);
#endif
return ENOERR;
}
//==========================================================================
// FAT table entry functions
// -------------------------------------------------------------------------
// read_tentry()
// Reads FAT table entry from disk.
static int
read_tentry_fat12(fatfs_disk_t *disk, cyg_uint32 num, cyg_uint32 *entry)
{
unsigned char data[2];
cyg_uint32 pos, num3;
cyg_uint16 e;
int len, err;
num3 = num * 3;
pos = disk->fat_tbl_pos + (num3 >> 1);
len = 2;
err = cyg_blib_read(&disk->blib, (void*)data, &len, 0, pos);
if (err != ENOERR)
return err;
GET_WORD(data, e, 0x00);
if (0 == (num3 & 1))
*entry = e & 0x0FFF;
else
*entry = (e >> 4) & 0x0FFF;
CYG_TRACE3(TFT, "tentry=%x num=%d at %d", *entry, num, pos);
return ENOERR;
}
static int
read_tentry_fat16(fatfs_disk_t *disk, cyg_uint32 num, cyg_uint32 *entry)
{
unsigned char data[2];
cyg_uint32 pos;
cyg_uint16 e;
int len, err;
pos = disk->fat_tbl_pos + (num << 1);
len = 2;
err = cyg_blib_read(&disk->blib, (void*)data, &len, 0, pos);
if (err != ENOERR)
return err;
GET_WORD(data, e, 0x00);
*entry = e;
CYG_TRACE3(TFT, "tentry=%x num=%d at %d", *entry, num, pos);
return ENOERR;
}
static int
read_tentry(fatfs_disk_t *disk, cyg_uint32 num, cyg_uint32 *entry)
{
switch (disk->fat_type)
{
case FATFS_FAT12: return read_tentry_fat12(disk, num, entry);
case FATFS_FAT16: return read_tentry_fat16(disk, num, entry);
default: return EINVAL;
}
}
// -------------------------------------------------------------------------
// write_tentry()
// Writes FAT table entry to disk (to all copies of FAT).
static int
write_tentry_fat12(fatfs_disk_t *disk, cyg_uint32 num, cyg_uint32 *entry)
{
unsigned char data[2];
cyg_uint32 pos, num3;
cyg_uint16 e;
int i, len, err;
num3 = num * 3;
pos = disk->fat_tbl_pos + (num3 >> 1);
len = 2;
err = cyg_blib_read(&disk->blib, (void*)data, &len, 0, pos);
if (err != ENOERR)
return err;
GET_WORD(data, e, 0x00);
if (0 == (num3 & 1))
e = (e & 0xF000) | (*entry & 0x0FFF);
else
e = (e & 0x000F) | ((*entry & 0x0FFF) << 4);
SET_WORD(data, e, 0x00);
for (i = 0; i < disk->fat_tbls_num; i++)
{
err = cyg_blib_write(&disk->blib, (void*)data, &len, 0, pos);
if (err != ENOERR)
return err;
CYG_TRACE4(TFT, "tentry=%x num=%d at %d tbl=%d", *entry, num, pos, i);
pos += disk->fat_tbl_size;
}
return ENOERR;
}
static int
write_tentry_fat16(fatfs_disk_t *disk, cyg_uint32 num, cyg_uint32 *entry)
{
unsigned char data[2];
cyg_uint32 pos;
cyg_uint16 e;
int i, len, err;
pos = disk->fat_tbl_pos + (num << 1);
len = 2;
e = *entry;
SET_WORD(data, e, 0x00);
for (i = 0; i < disk->fat_tbls_num; i++)
{
err = cyg_blib_write(&disk->blib, (void*)data, &len, 0, pos);
if (err != ENOERR)
return err;
CYG_TRACE4(TFT, "tentry=%x num=%d at %d tbl=%d", *entry, num, pos, i);
pos += disk->fat_tbl_size;
}
return ENOERR;
}
static int
write_tentry(fatfs_disk_t *disk, cyg_uint32 num, cyg_uint32 *entry)
{
switch (disk->fat_type)
{
case FATFS_FAT12: return write_tentry_fat12(disk, num, entry);
case FATFS_FAT16: return write_tentry_fat16(disk, num, entry);
default: return EINVAL;
}
}
// -------------------------------------------------------------------------
// get_tentry_type()
// Gets the type of FAT table entry.
static int
get_tentry_type_fat12(fatfs_disk_t *disk, cyg_uint32 entry)
{
int type;
if (entry < 0x0FF0)
{
if (0x0000 == entry) type = TENTRY_FREE;
else type = TENTRY_REGULAR;
}
else if (entry >= 0x0FF8) type = TENTRY_LAST;
else if (0x0FF7 == entry) type = TENTRY_BAD;
else type = TENTRY_RESERVED;
#if TFT
CYG_TRACE2(TFT, "tentry=%04X type=%s", entry, tentry_type_name[type]);
#endif
return type;
}
static int
get_tentry_type_fat16(fatfs_disk_t *disk, cyg_uint32 entry)
{
int type;
if (entry < 0xFFF0)
{
if (0x0000 == entry) type = TENTRY_FREE;
else type = TENTRY_REGULAR;
}
else if (entry >= 0xFFF8) type = TENTRY_LAST;
else if (0xFFF7 == entry) type = TENTRY_BAD;
else type = TENTRY_RESERVED;
#if TFT
CYG_TRACE2(TFT, "tentry=%04X type=%s", entry, tentry_type_name[type]);
#endif
return type;
}
static int
get_tentry_type(fatfs_disk_t *disk, cyg_uint32 entry)
{
switch (disk->fat_type)
{
case FATFS_FAT12: return get_tentry_type_fat12(disk, entry);
case FATFS_FAT16: return get_tentry_type_fat16(disk, entry);
default: return TENTRY_BAD;
}
}
// -------------------------------------------------------------------------
// set_tentry_type()
// Sets the type of FAT table entry.
static void
set_tentry_type_fat12(fatfs_disk_t *disk, cyg_uint32 *entry, cyg_uint32 type)
{
switch (type)
{
case TENTRY_FREE: *entry = 0x0000; break;
case TENTRY_LAST: *entry = 0x0FF8; break;
case TENTRY_RESERVED: *entry = 0x0FF0; break;
case TENTRY_BAD: *entry = 0x0FF7; break;
default:
CYG_ASSERT(false, "Unknown tentry type");
}
}
static void
set_tentry_type_fat16(fatfs_disk_t *disk, cyg_uint32 *entry, cyg_uint32 type)
{
switch (type)
{
case TENTRY_FREE: *entry = 0x0000; break;
case TENTRY_LAST: *entry = 0xFFF8; break;
case TENTRY_RESERVED: *entry = 0xFFF0; break;
case TENTRY_BAD: *entry = 0xFFF7; break;
default:
CYG_ASSERT(false, "Unknown tentry type");
}
}
static void
set_tentry_type(fatfs_disk_t *disk, cyg_uint32 *entry, cyg_uint32 type)
{
switch (disk->fat_type)
{
case FATFS_FAT12: set_tentry_type_fat12(disk, entry, type);
case FATFS_FAT16: set_tentry_type_fat16(disk, entry, type);
}
}
// -------------------------------------------------------------------------
// get_tentry_next_cluster()
// Gets the the next file cluster number from FAT table entry.
static __inline__ cyg_uint32
get_tentry_next_cluster(fatfs_disk_t *disk, cyg_uint32 entry)
{
return entry;
}
// -------------------------------------------------------------------------
// set_tentry_next_cluster()
// Sets the the next cluster number to FAT table entry.
static __inline__ void
set_tentry_next_cluster(fatfs_disk_t *disk,
cyg_uint32 *entry,
cyg_uint32 next_cluster)
{
*entry = next_cluster;
}
//==========================================================================
// FAT cluster functions
// -------------------------------------------------------------------------
// is_pos_inside_cluster()
// Checks if the given position is inside cluster size.
static __inline__ bool
is_pos_inside_cluster(fatfs_disk_t *disk, cyg_uint32 pos)
{
return (pos < disk->cluster_size);
}
// -------------------------------------------------------------------------
// erase_cluster()
// Erases cluster (fills with 0x00).
static int
erase_cluster(fatfs_disk_t *disk, cyg_uint32 cluster)
{
unsigned char data[32];
cyg_uint32 apos;
int err, len, i;
len = 32;
memset((void*)data, 0x00, len);
apos = get_data_disk_apos(disk, cluster, 0);
CYG_TRACE1(TCL, "cluster=%d", cluster);
for (i = 0; i < (disk->cluster_size >> 5); i++)
{
err = cyg_blib_write(&disk->blib, (void*)data, &len, 0, apos);
if (err != ENOERR)
return err;
apos += len;
}
return ENOERR;
}
// -------------------------------------------------------------------------
// mark_cluster()
// Marks cluster (sets the cluster's FAT table entry to given type).
static int
mark_cluster(fatfs_disk_t *disk, cyg_uint32 cluster, cyg_uint32 type)
{
cyg_uint32 tentry;
int err;
set_tentry_type(disk, &tentry, type);
err = write_tentry(disk, cluster, &tentry);
CYG_TRACE3(TCL, "cluster=%d type=%d tentry=%d",
cluster, type, tentry);
return err;
}
// -------------------------------------------------------------------------
// link_cluster()
// Links two clusters.
static int
link_cluster(fatfs_disk_t *disk, cyg_uint32 cluster1, cyg_uint32 cluster2)
{
cyg_uint32 tentry;
int err;
set_tentry_next_cluster(disk, &tentry, cluster2);
err = write_tentry(disk, cluster1, &tentry);
CYG_TRACE3(TCL, "cluster1=%d cluster2=%d tentry=%d",
cluster1, cluster2, tentry);
return err;
}
// -------------------------------------------------------------------------
// find_next_free_cluster()
// Finds first free cluster starting from given cluster.
// If none is available free_cluster is set to 0.
// If mark_as_last is set the found cluster is marked as LAST.
static int
find_next_free_cluster(fatfs_disk_t *disk,
cyg_uint32 start_cluster,
cyg_uint32 *free_cluster,
cluster_opts_t opts)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -