📄 fat.c
字号:
/*C**************************************************************************
* $RCSfile: fat.c,v $
*----------------------------------------------------------------------------
* Copyright (c) 2002 Atmel.
*----------------------------------------------------------------------------
* RELEASE: $Name: DEMO_FAT_1_2_5 $
* REVISION: $Revision: 1.12 $
* FILE_CVSID: $Id: fat.c,v 1.12 2002/06/10 14:14:53 dturpin Exp $
*----------------------------------------------------------------------------
* PURPOSE:
* FAT16/FAT12 file-system basics functions
*
* NOTES:
* Supports only the first partition
* Supports only 512 bytes sector size
* Supports only file fragmentation < MAX_FILE_FRAGMENT_NUMBER
* Supports only one file openned at a time
*
* Global Variables:
* - gl_buffer: array of bytes in pdata space
* - gl_wav_header: wave structure in code
*
* CHANGES:
* - TD 2002/02/28
* Add new variables for mass storage purpose:
* fat_nb_sector
* fat_sector_per_track
* fat_end_head
* fat_end_cylinder
* - FF 2002/03/06
* Add fat_format function
*****************************************************************************/
/*_____ I N C L U D E S ____________________________________________________*/
#include "config.h" /* system configuration */
#include "..\mem\hard.h" /* low level function definition */
#include "file.h" /* file function definition */
#include "fat.h" /* fat file-system definition */
#include "wav.h" /* wav file definition */
/*_____ M A C R O S ________________________________________________________*/
/*_____ D E F I N I T I O N ________________________________________________*/
extern pdata Byte gl_buffer[];
extern code wav_struct gl_wav_header;
/* For exploration matters */
xdata Uint16 fat_directory_chain[MAX_DIRECTORY_FILE]; /* array of relative entries position */
xdata Uint16 fat_directory_pos; /* global entries offset */
xdata Uint16 fat_last_file; /* number of file stored (MP3, VOC, DIR) */
xdata Uint32 fat_directory_base; /* starting sector for directory */
idata Uint16 fat_file_ptr; /* entry number pointer */
xdata Uint32 fat_current_sector; /* current sector where the current */
/* file/dir info (cache.info) is situated */
xdata Uint16 fat_current_byte_counter; /* the byte counter offset in the current */
/* sector where is the current file/dir entry */
/* For file management matters */
/* the global byte counter, mainly use for the eof check */
static data Uint32 fat_file_byte_counter;
xdata fat_Cache fat_cache; /* The cache structure, see the .h for more info */
char pdata *lfn_name = &(gl_buffer[32]); /* long filename limited to MAX_FILENAME_LEN chars */
xdata char ext[3]; /* file extension (limited to 3 characters) */
/* file chain management */
static data Byte fat_chain_index; /* the number of the fragment of the file, in fact */
/* the index of the table in the cluster chain */
static data Byte fat_chain_cluster; /* the offset of the cluster from the first cluster */
/* of the fragment */
static xdata fat_cluster_chain clusters; /* cluster chain for the current file */
static xdata fat_cluster_chain dir_clusters; /* cluster chain for the current directory */
static bdata bit dir_is_root; /* TRUE: point the root directory */
static data Uint32 fat_ptr_fats; /* address of the first byte of FAT */
static data Uint32 fat_ptr_rdir; /* address of the first byte of root dir */
static data Uint32 fat_ptr_data; /* address of the first byte of data */
static data Byte fat_cluster_size; /* cluster size (sector count) */
static data Byte fat_cluster_mask; /* mask for end of cluster test */
static idata Byte fat_current_dir_fragment;
static idata Uint16 fat_current_dir_cluster;
static idata Byte fat_current_sector_cluster;
static bdata bit fat_is_fat16; /* TRUE: FAT16 - FALSE: FAT12 */
static bdata bit fat_open_mode; /* READ or WRITE */
/*_____ D E C L A R A T I O N ______________________________________________*/
static bit fat_get_clusters (fat_cluster_chain *);
static bit fat_dopen (void);
static bit fat_dseek (Int16);
static Byte fat_dgetc (void);
/*F**************************************************************************
* NAME: fat_install
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
* - OK: intallation succeeded
* - KO: - partition 1 not active
* - FAT type is not FAT16
* - sector size is not 512 bytes
* - MBR or PBR signatures are not correct
* - low level read open failure
*----------------------------------------------------------------------------
* PURPOSE:
* Install the fat system, read mbr, bootrecords...
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
* sector size is fixed to 512 bytes to simplify low level drivers
* fat_ptr_fats = partition offset + nb_reserved_sector
* fat_ptr_rdir = fat_ptr_fat + fat_size * nb_fat
* fat_ptr_data = fat_ptr_rdir + nb_root_entries * 32 / 512
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit fat_install (void)
{
Byte i;
Uint16 fat_fat_size;
Uint32 count_of_clusters;
Uint32 Tot_sect;
Uint32 fat_nb_sector;
/* read and check usefull MBR info */
/* go to the first partition field */
if (Hard_read_open(MBR_ADDRESS) == OK)
{
for (i= 446/2; i != 0; i--)
{
Hard_read_byte(); /* go to first partition entry */
Hard_read_byte();
}
/* check first partition state */
if (Hard_read_byte() != PARTITION_ACTIVE)
{
Hard_read_close(); /* close physical read */
return KO;
}
Hard_read_byte(); /* dummy reads */
Hard_read_byte();
Hard_read_byte();
Hard_read_byte();
Hard_read_byte(); /* dummy reads */
Hard_read_byte();
Hard_read_byte();
/* read partition offset (in sectors) at offset 8 */
((Byte*)&fat_ptr_fats)[3] = Hard_read_byte();
((Byte*)&fat_ptr_fats)[2] = Hard_read_byte();
((Byte*)&fat_ptr_fats)[1] = Hard_read_byte();
((Byte*)&fat_ptr_fats)[0] = Hard_read_byte();
/* go to the MBR signature field */
for (i= 52; i != 0; i--)
{
Hard_read_byte(); /* dummy reads */
}
/* check MBR signature */
if ((Hard_read_byte() != LOW(BR_SIGNATURE)) &&
(Hard_read_byte() != HIGH(BR_SIGNATURE)))
{
Hard_read_close(); /* close physical read */
return KO;
}
Hard_read_close(); /* close physical read */
}
else
{ /* low level error */
return KO;
}
/* read and check usefull PBR info */
if (Hard_read_open(fat_ptr_fats) == OK)
{
/* go to sector size field */
for (i= 11; i != 0; i--)
{
Hard_read_byte(); /* dummy reads */
}
/* read sector size (in bytes) */
if (Hard_read_byte() != LOW(SECTOR_SIZE) ||
Hard_read_byte() != HIGH(SECTOR_SIZE))
{
Hard_read_close(); /* close physical read */
return KO;
}
/* read cluster size (in sector) */
fat_cluster_size = Hard_read_byte();
fat_cluster_mask = HIGH((Uint16)fat_cluster_size * SECTOR_SIZE) - 1;
/* compute FATs sector address: add reserved sector number */
fat_ptr_fats += Hard_read_byte();
fat_ptr_fats += (Uint16)Hard_read_byte() << 8;
/* read number of FATs */
i = Hard_read_byte();
/* read number of dir entries and compute rdir offset */
((Byte*)&fat_ptr_data)[3] = Hard_read_byte();
((Byte*)&fat_ptr_data)[2] = Hard_read_byte();
((Byte*)&fat_ptr_data)[1] = 0;
((Byte*)&fat_ptr_data)[0] = 0;
fat_ptr_data = (fat_ptr_data * DIR_SIZE) / SECTOR_SIZE;
/* read number of sector in partition (<32Mb) */
((Byte*)&fat_nb_sector)[3] = Hard_read_byte();
((Byte*)&fat_nb_sector)[2] = Hard_read_byte();
((Byte*)&fat_nb_sector)[1] = 0x00;
((Byte*)&fat_nb_sector)[0] = 0x00;
Hard_read_byte();
/* compute root directory sector address */
((Byte*)&fat_fat_size)[1] = Hard_read_byte();
((Byte*)&fat_fat_size)[0] = Hard_read_byte();
fat_ptr_rdir = i * fat_fat_size;
fat_ptr_rdir += fat_ptr_fats;
Hard_read_byte();
Hard_read_byte();
Hard_read_byte();
Hard_read_byte();
Hard_read_byte();
Hard_read_byte();
Hard_read_byte();
Hard_read_byte();
/* read number of sector in partition (>32Mb) */
((Byte*)&fat_nb_sector)[3] += Hard_read_byte();
((Byte*)&fat_nb_sector)[2] += Hard_read_byte();
((Byte*)&fat_nb_sector)[1] += Hard_read_byte();
((Byte*)&fat_nb_sector)[0] += Hard_read_byte();
Tot_sect = fat_nb_sector - ( 1 + (i * fat_fat_size) + fat_ptr_data);
count_of_clusters = Tot_sect / fat_cluster_size;
if (count_of_clusters <= MAX_CLUSTERS12)
fat_is_fat16 = FALSE;
else
if (count_of_clusters <= MAX_CLUSTERS16)
fat_is_fat16 = TRUE;
/* else is FAT32 not supported */
/* compute data sector address */
fat_ptr_data += fat_ptr_rdir;
/* go to the signature field */
for (i= 237; i != 0; i--)
{
Hard_read_byte(); /* dummy reads */
Hard_read_byte();
}
/* check partition signature */
if ((Hard_read_byte() != LOW(BR_SIGNATURE)) &&
(Hard_read_byte() != HIGH(BR_SIGNATURE)))
{
Hard_read_close(); /* close physical read */
return KO;
}
Hard_read_close(); /* close physical read */
return OK;
}
else
{ /* low level error */
return KO;
}
}
/*F**************************************************************************
* NAME: fat_fetch_directory_info
*----------------------------------------------------------------------------
* PARAMS:
* entry: directory entry structure
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* Fetch from disk all information about a directory/file
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
* This function reads directly datas from sectors
* It automaticaly computes difference between LFN and normal entries
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void fat_fetch_directory_info (fat_dir_entry *entry)
{
bit exit_flag = FALSE;
bit lfn_entry_found = FALSE;
Byte i;
/* clear the name buffer */
for (i = MAX_FILENAME_LEN; i != 0; lfn_name[--i] = '\0');
while (!exit_flag)
/* loop while the entry is not a normal one. */
{
/* read the directory entry */
if (dir_is_root == TRUE)
{
for (i = 0; i < DIR_SIZE; i++)
{
gl_buffer[i] = Hard_read_byte();
}
}
else
{
for (i = 0; i < DIR_SIZE; i++)
{
gl_buffer[i] = fat_dgetc();
}
}
/*computes gathered data
/* check if we have a LFN entry */
if (gl_buffer[11] != ATTR_LFN_ENTRY)
{
if (!lfn_entry_found)
{
/* true DOS 8.3 entry format */
for (i = 0; i < 8; i++)
{
lfn_name[i] = gl_buffer[i];
if (lfn_name[i] == ' ')
{ /* space is end of name */
break;
}
}
/* append extension */
lfn_name[i++] = '.';
lfn_name[i++] = gl_buffer[8];
lfn_name[i++] = gl_buffer[9];
lfn_name[i++] = gl_buffer[10];
for (; i != 14; i++)
{
lfn_name[i] = ' '; /* append spaces for display reason */
}
lfn_name[i] = '\0'; /* end of string */
}
else
{ /* LFN name treatment */
i = 0;
/* search for the end of the string */
while (lfn_name[i] != '\0')
{
i++;
}
if (i <= 14)
{ /* append spaces for display reason (no scrolling) */
while (i != 14)
{
lfn_name[i++] = ' ';
}
}
else
{ /* append beginning of name to ease scrolling display */
lfn_name[i++] = ' ';
lfn_name[i++] = ' ';
lfn_name[i++] = lfn_name[0];
lfn_name[i++] = lfn_name[1];
lfn_name[i++] = lfn_name[2];
lfn_name[i++] = lfn_name[3];
lfn_name[i++] = lfn_name[4];
lfn_name[i++] = lfn_name[5];
lfn_name[i++] = lfn_name[6];
lfn_name[i++] = lfn_name[7];
lfn_name[i++] = lfn_name[8];
lfn_name[i++] = lfn_name[9];
lfn_name[i++] = lfn_name[10];
lfn_name[i++] = lfn_name[11];
lfn_name[i++] = lfn_name[12];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -