?? fat.c
字號:
//*****************************************************************************
//
// Title : FAT16/32 file system driver for ATMEL AVR
// Authors : Angelo Bannack, Giordano Bruno Wolaniuk
// File Name : 'fat.c'
// Date : April 26, 2004
// Version : 1.00
// Target MCU : Atmel AVR Series
// Editor Tabs : 4
//
// NOTE: This code is based on original library "FAT16/32 file system driver"
// from Pascal Stang.
//
// The authors in no way will be responsible for damages that you coul'd be using this code.
// Use this code at your own risk.
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "ata.h"
#include "fat.h"
#include "fatconf.h"
#include "fattime.h"
// globals
unsigned char *SectorBuffer = (unsigned char *) SECTOR_BUFFER_ADDR; // Sector Buffer
unsigned char *FatCache = (unsigned char *) FAT_CACHE_ADDR; // Fat Buffer
char VolLabel[12]; // Volume Label
struct partrecord PartInfo; // Partition Information
TFILE File; // File Information
unsigned long FSInfo; // File System Information
unsigned char Fat32Enabled; // Indicates if is FAT32 or FAT16
unsigned long FirstDataSector; // First Data Sector Address
unsigned int SectorsPerCluster; // Number of Sectors per Cluster
unsigned long FirstFATSector; // First FAT Sector Address
unsigned long FirstFAT2Sector; // First FAT2 Sector Address
unsigned long FirstDirCluster; // First Directory (Data) Cluster Address
unsigned long FatInCache = 0xFFFFFFFF; // Address of the FAT Cluster in FatCache
unsigned long FatSectors; // Number of FAT Sectors
unsigned long currentDirCluster; // Actual Dir Cluster Number
unsigned long NumClusters; // ATA Dispositive Cluster Numbers
unsigned long SectorInCache = 0xFFFFFFFF; // Address of the Sector Cluster in SectorBuffer
//*****************************************************************************
// Function: fatClustToSect
// Parameters: cluster
// Returns: sector
//
// Description: Converts Sectors in Clusters
//*****************************************************************************
unsigned long fatClustToSect(unsigned long clust)
{
if (clust == 0)
clust=2;
return ((clust-2) * SectorsPerCluster) + FirstDataSector;
}
//*****************************************************************************
// Function: fatSectToClust
// Parameters: sector
// Returns: cluster
//
// Description: Converts Clusters in Sectors
//*****************************************************************************
unsigned long fatSectToClust(unsigned long sect)
{
return (((sect - FirstDataSector) / SectorsPerCluster) + 2);
}
//*****************************************************************************
// Function: fatInit
// Parameters: none
// Returns: TRUE if a FAT drive was found, FALSE otherwise
//
// Description: Get FAT info from ATA dispositive and initialize internal variables
//*****************************************************************************
unsigned char fatInit(void)
{
struct bpb710 *bpb;
// read partition table
ataReadSectors(DRIVE0, 0, SectorBuffer, &SectorInCache);
// map first partition record
// save partition information to global PartInfo
PartInfo = *((struct partrecord *) ((struct partsector *) SectorBuffer)->psPart);
// Read the Partition BootSector
// **first sector of partition in PartInfo.prStartLBA
ataReadSectors( DRIVE0, PartInfo.prStartLBA, SectorBuffer, &SectorInCache );
bpb = (struct bpb710 *) ((struct bootsector710 *) SectorBuffer)->bsBPB;
// setup global disk constants
FirstDataSector = PartInfo.prStartLBA;
if(bpb->bpbFATsecs)
{
// bpbFATsecs is non-zero and is therefore valid
FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs;
}
else
{
// bpbFATsecs is zero, real value is in bpbBigFATsecs
FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbBigFATsecs;
}
SectorsPerCluster = bpb->bpbSecPerClust;
FirstFATSector = bpb->bpbResSectors + PartInfo.prStartLBA;
FatSectors = bpb->bpbBigFATsecs;
NumClusters = ataGetSizeInSectors()/(bpb->bpbSecPerClust);
// initialize Volume Label
memcpy(&VolLabel, bpb->bpbVolLabel, 11);
VolLabel[11]='\0';
switch (PartInfo.prPartType)
{
case PART_TYPE_DOSFAT16:
case PART_TYPE_FAT16:
case PART_TYPE_FAT16LBA:
// first directory cluster is 2 by default (clusters range 2->big)
FirstDirCluster = CLUST_FIRST;
// push data sector pointer to end of root directory area
//FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
Fat32Enabled = FALSE;
break;
case PART_TYPE_FAT32LBA:
case PART_TYPE_FAT32:
// bpbRootClust field exists in FAT32 bpb710, but not in lesser bpb's
FirstDirCluster = bpb->bpbRootClust;
// push data sector pointer to end of root directory area
// need this? FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
Fat32Enabled = TRUE;
break;
default:
//Found: No Partition!
return FALSE;
break;
}
if (Fat32Enabled)
FirstFAT2Sector=FirstFATSector+bpb->bpbBigFATsecs;
else
FirstFAT2Sector=FirstFATSector+bpb->bpbFATsecs;
FSInfo=bpb->bpbFSInfo+PartInfo.prStartLBA;
currentDirCluster= FirstDirCluster;
return TRUE;
}
//*****************************************************************************
// Function: fatNextCluster
// Parameters: cluster
// Returns: the next cluster
//
// Description: Find next cluster in the FAT chain
//*****************************************************************************
unsigned long fatNextCluster(unsigned long cluster)
{
unsigned long nextCluster;
unsigned long fatMask;
unsigned long fatOffset;
unsigned long sector;
unsigned int offset;
// get fat offset in bytes
if(Fat32Enabled)
{
// four FAT bytes (32 bits) for every cluster
fatOffset = cluster << 2;
// set the FAT bit mask
fatMask = FAT32_MASK;
}
else
{
// two FAT bytes (16 bits) for every cluster
fatOffset = cluster << 1;
// set the FAT bit mask
fatMask = FAT16_MASK;
}
// calculate the FAT sector that we're interested in
sector = FirstFATSector + (fatOffset / BYTES_PER_SECTOR);
// calculate offset of the our entry within that FAT sector
offset = fatOffset % BYTES_PER_SECTOR;
// if we don't already have this FAT chunk loaded, go get it
ataReadSectors( DRIVE0, sector, (unsigned char*)FAT_CACHE_ADDR, &FatInCache);
// read the nextCluster value
nextCluster = (*((unsigned long*) &((char*)FAT_CACHE_ADDR)[offset])) & fatMask;
// check to see if we're at the end of the chain
if (nextCluster == (CLUST_EOFE & fatMask))
nextCluster = 0;
return nextCluster;
}
//*****************************************************************************
// Function: fatClusterSize
// Parameters: none
// Returns: the size of a cluster in sectors
//
// Description: return the number of sectors in a disk cluster
//*****************************************************************************
unsigned int fatClusterSize(void)
{
return SectorsPerCluster;
}
//*****************************************************************************
// Function: fatGetFirstDirCluster
// Parameters: none
// Returns: the cluster number of the first dir entry in FAT
//
// Description: return the first dir entry cluster in FAT
//*****************************************************************************
unsigned long fatGetFirstDirCluster(void)
{
return(FirstDirCluster);
}
//*****************************************************************************
// Function: fatGetPartInfo
// Parameters: none
// Returns: FAT partition information
//
// Description: return the partition information read in fatInit routine
//*****************************************************************************
struct partrecord *fatGetPartInfo(void)
{
return (&PartInfo);
}
//*****************************************************************************
// Function: fatGetSecPerClust
// Parameters: none
// Returns: the number of Sectors per Cluster
//
// Description: return the number of Sectors per Cluster read in fatInit
//*****************************************************************************
unsigned int fatGetSecPerClust(void)
{
return SectorsPerCluster;
}
//*****************************************************************************
// Function: fatGetFirstFATSector
// Parameters: none
// Returns: the address of the first FAT Sector
//
// Description: return the sector address of the first FAT
//*****************************************************************************
unsigned long fatGetFirstFATSector(void)
{
return(FirstFATSector);
}
//*****************************************************************************
// Function: fatGetFirstFAT2Sector
// Parameters: none
// Returns: the address of the first second FAT Sector
//
// Description: return the sector address of the second FAT
//*****************************************************************************
unsigned long fatGetFirstFAT2Sector(void)
{
return(FirstFAT2Sector);
}
//*****************************************************************************
// Function: fatGetFirstDataSector
// Parameters: none
// Returns: the address of the first data Sector
//
// Description: return the sector address of the data in FAT
//*****************************************************************************
unsigned long fatGetFirstDataSector(void)
{
return(FirstDataSector);
}
//*****************************************************************************
// Function: fatGetNumClusters
// Parameters: none
// Returns: the total number of clusters
//
// Description: return the total number of clusters in the ata dispositive
//*****************************************************************************
unsigned long fatGetNumClusters(void)
{
return(NumClusters);
}
//*****************************************************************************
// Function: fatDir
// Parameters: initial cluster, offset
// Returns: On SUSCEFULL returns the sector with direntries info, otherwise
// returns NULL
//
// Description: return the sector with direntries info starting in the cluster,
// and with offset sectors from the begining cluster sector
//*****************************************************************************
unsigned char *fatDir(unsigned long cluster, unsigned long offset)
{
unsigned long index;
for (index=0; index < offset/SectorsPerCluster; index++)
cluster=fatNextCluster(cluster);
if (cluster == 0)
return NULL;
ataReadSectors(DRIVE0, fatClustToSect(cluster)+ offset%SectorsPerCluster, SectorBuffer, &SectorInCache);
return SectorBuffer;
}
//*****************************************************************************
// Function: fatGetFileInfo
// Parameters: address of direntry struct, short name of the file
// Returns: On SUSCEFULL, return the direntry struct filled out with the file info,
// otherwise returns NULL;
//
// Description: return the direntry struct of a short name file given
// this function will search for a filename only in the current
// directory, given by currentDirCluster
//*****************************************************************************
struct direntry *fatGetFileInfo(struct direntry *rde, char *shortName)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -