⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 方便飞利浦arm7tdmi 处理器lpc2100开发的C函数库 Procyon ARMlib-LPC2100 C-Language Function Library for Philips LPC21
💻 C
📖 第 1 页 / 共 2 页
字号:
/*! \file fat.c \brief FAT16/32 file system driver. */
//*****************************************************************************
//
// File Name	: 'fat.c'
// Title		: FAT16/32 file system driver
// Author		: Pascal Stang
// Date			: 11/07/2000
// Revised		: 12/12/2000
// Version		: 0.3
// Target MCU	: ATmega103 (should work for Atmel AVR Series)
// Editor Tabs	: 4
//
// This code is based in part on work done by Jesper Hansen for his
//		YAMPP MP3 player project.
//
// NOTE: This code is currently below version 1.0, and therefore is considered
// to be lacking in some functionality or documentation, or may not be fully
// tested.  Nonetheless, you can expect most functions to work.
//
// This code is distributed under the GNU Public License
//		which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************


#include <string.h>

#include "ata.h"
#include "rprintf.h"
#include "debug.h"

#include "fat.h"
#include "fatconf.h"

// globals
// buffers
unsigned char *SectorBuffer  =		(unsigned char *) FAT_SECTOR_BUFFER_ADDR;
unsigned char *FileNameBuffer =		(unsigned char *) FAT_FILENAME_BUFFER_ADDR;
unsigned char *PathNameBuffer =		(unsigned char *) FAT_PATHNAME_BUFFER_ADDR;

// filesystem constants/metrics
struct partrecord PartInfo;
unsigned char Fat32Enabled;
unsigned long FirstDataSector;
unsigned short BytesPerSector;
unsigned short SectorsPerCluster;
unsigned long FirstFATSector;
unsigned long RootDirStartCluster;

// operating variables
unsigned long CurrentDirStartCluster;	//< current directory starting cluster
struct FileInfoStruct FileInfo;			//< file information for last file accessed
unsigned long FatInCache = 0;


/*************************************************************************/
/*************************************************************************/


unsigned long fatClustToSect(unsigned long clust)
{
	return ((clust-2) * SectorsPerCluster) + FirstDataSector;
}

unsigned int fatClusterSize(void)
{
	// return the number of sectors in a disk cluster
	return SectorsPerCluster;
}

unsigned char fatInit( unsigned char device)
{
	//struct partrecord *pr;
	struct bpb710 *bpb;

	// read partition table
	// TODO.... error checking
	ataReadSectors(DRIVE0, 0, 1, SectorBuffer);
	// map first partition record	
	// save partition information to global PartInfo
	PartInfo = *((struct partrecord *) ((struct partsector *) SectorBuffer)->psPart);
//	PartInfo = *pr;
	
	// Read the Partition BootSector
	// **first sector of partition in PartInfo.prStartLBA
	ataReadSectors( DRIVE0, PartInfo.prStartLBA, 1, SectorBuffer );
	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;
	BytesPerSector		= bpb->bpbBytesPerSec;
	FirstFATSector		= bpb->bpbResSectors + PartInfo.prStartLBA;

	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)
			RootDirStartCluster = 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
			RootDirStartCluster = bpb->bpbRootClust;
			// push data sector pointer to end of root directory area
			// need this? FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
			Fat32Enabled = TRUE;
			break;
		default:
			rprintfStr("Found: No Partition!\r\n");
			//return 1;
			break;
	}

	// set current directory to root (\)
	CurrentDirStartCluster = RootDirStartCluster;
	PathNameBuffer[0] = '\\';
	PathNameBuffer[1] = 0;


	// do debug
#ifdef DEBUG_FAT
	switch (PartInfo.prPartType)
	{
		case PART_TYPE_DOSFAT16:
				rprintfStr("Found: DOSFAT 16\r\n");
				break;
		case PART_TYPE_FAT16:
				rprintfStr("Found: FAT16\r\n");
				break;
		case PART_TYPE_FAT16LBA:
				rprintfStr("Found: FAT16 LBA\r\n");
				break;
		case PART_TYPE_FAT32LBA:
				rprintfStr("Found: FAT32 LBA\r\n");
				break;
		case PART_TYPE_FAT32:
				rprintfStr("Found: FAT32\r\n");
				//return 1;	
				break;
		default:
				rprintfStr("Found: No Partition!\r\n");
				//return 1;
				break;
	}

	rprintfStr("First sector    : ");	rprintfu32(PartInfo.prStartLBA);	rprintfCRLF();
	rprintfStr("Size            : ");	rprintfu32(PartInfo.prSize);		rprintfCRLF();
	rprintfStr("bytes/sector    : ");	rprintfu16(bpb->bpbBytesPerSec);	rprintfCRLF();
	rprintfStr("sectors/cluster : ");	rprintfu08(bpb->bpbSecPerClust);	rprintfCRLF();
	rprintfStr("reserved sectors: ");	rprintfu16(bpb->bpbResSectors);		rprintfCRLF();
	rprintfStr("FatSectors      : ");	rprintfu16(bpb->bpbFATsecs);		rprintfCRLF();
	rprintfStr("BigFatSectors   : ");	rprintfu32(bpb->bpbBigFATsecs);		rprintfCRLF();
	rprintfStr("Number of Fats  : ");	rprintfu08(bpb->bpbFATs);			rprintfCRLF();
	rprintfStr("First Fat Sector: ");	rprintfu32(FirstFATSector);			rprintfCRLF();
	rprintfStr("First Data Sect : ");	rprintfu32(FirstDataSector);		rprintfCRLF();
	rprintfStr("RootDirStartClus: ");	rprintfu32(RootDirStartCluster);	rprintfCRLF();
#endif

	return 0;	
}

void fatPrintPartition(struct partrecord *partition)
{
	rprintfStr("----- Partition -----\r\n");
	rprintfStr("Active        : ");	rprintfu08(partition->prIsActive);		rprintfCRLF();
	rprintfStr("StartHead     : ");	rprintfu08(partition->prStartHead);		rprintfCRLF();
	rprintfStr("StartCylSect  : ");	rprintfu16(partition->prStartCylSect);	rprintfCRLF();
	rprintfStr("Partition Type: ");
	switch(partition->prPartType)
	{
		case PART_TYPE_DOSFAT16:
				rprintfStr("Found: DOSFAT 16\r\n");
				break;
		case PART_TYPE_FAT16:
				rprintfStr("Found: FAT16\r\n");
				break;
		case PART_TYPE_FAT16LBA:
				rprintfStr("Found: FAT16 LBA\r\n");
				break;
		case PART_TYPE_FAT32LBA:
				rprintfStr("Found: FAT32 LBA\r\n");
				break;
		case PART_TYPE_FAT32:
				rprintfStr("Found: FAT32\r\n");
				break;
		case PART_TYPE_UNKNOWN:
				rprintfStr("No Partition\r\n");
				break;
		default:
				rprintf("Type: 0x%x\r\n", partition->prPartType);
				break;
	}
	rprintfStr("EndHead       : ");	rprintfu08(partition->prEndHead);		rprintfCRLF();
	rprintfStr("EndCylSect    : ");	rprintfu16(partition->prEndCylSect);	rprintfCRLF();
	rprintfStr("StartLBA      : ");	rprintfu32(partition->prStartLBA);		rprintfCRLF();
	rprintfStr("Size          : ");	rprintfu32(partition->prSize);			rprintfCRLF();
}

void fatPrintPartitionTable(struct partsector *buffer)
{
	ataReadSectors(DRIVE0, 0, 1, SectorBuffer);
	buffer = SectorBuffer;

	fatPrintPartition( (struct partrecord*) &(buffer->psPart[0x00]) );
	fatPrintPartition( (struct partrecord*) &(buffer->psPart[0x10]) );
	fatPrintPartition( (struct partrecord*) &(buffer->psPart[0x20]) );
	fatPrintPartition( (struct partrecord*) &(buffer->psPart[0x30]) );
	
	if( (buffer->psBootSectSig0 == BOOTSIG0) &&
		(buffer->psBootSectSig1 == BOOTSIG1) )
	{
		rprintfStr("Partition Sector Valid.");
	}
}


//////////////////////////////////////////////////////////////

unsigned char fatGetDirEntry(unsigned short entry)
{
	unsigned long sector;
	struct direntry *de = 0;	// avoid compiler warning by initializing
	struct winentry *we;
	unsigned char haveLongNameEntry;
	unsigned char gotEntry;
	unsigned short b;
	int i,index;
	char *fnbPtr;
	unsigned short entrycount = 0;

	// read dir data
	sector = fatClustToSect(CurrentDirStartCluster);

	haveLongNameEntry = 0;
	gotEntry = 0;

	index = 16;	// crank it up
	
	//while(entrycount < entry) 
	while(1)
	{
		if(index == 16)	// time for next sector ?
		{
			ataReadSectors( DRIVE0, sector++, 1, SectorBuffer);
			de = (struct direntry *) SectorBuffer;
			index = 0;
		}
		
		// check the status of this directory entry slot
		if(de->deName[0] == 0x00)
		{
			// slot is empty and this is the end of directory
			gotEntry = 0;
			break;
		}
		else if(de->deName[0] == 0xE5)
		{
			// this is an empty slot
			// do nothing and move to the next one
		}
		else
		{
			// this is a valid and occupied entry
			// is it a part of a long file/dir name?
			if(de->deAttributes == ATTR_LONG_FILENAME)
			{
				// we have a long name entry
				// cast this directory entry as a "windows" (LFN: LongFileName) entry
				we = (struct winentry *) de;
				
				b = WIN_ENTRY_CHARS*( (we->weCnt-1) & 0x0f);		// index into string
				fnbPtr = &FileNameBuffer[b];
				for (i=0;i<5;i++)	*fnbPtr++ = we->wePart1[i*2];	// copy first part
				for (i=0;i<6;i++)	*fnbPtr++ = we->wePart2[i*2];	// second part
				for (i=0;i<2;i++)	*fnbPtr++ = we->wePart3[i*2];	// and third part
				if (we->weCnt & WIN_LAST) *fnbPtr = 0;				// in case dirnamelength is multiple of 13, add termination
				if ((we->weCnt & 0x0f) == 1) haveLongNameEntry = 1;	// flag that we have a complete long name entry set
			}
			else
			{
				// we have a short name entry
				
				// check if this is the short name entry corresponding
				// to the end of a multi-part long name entry
				if(haveLongNameEntry)
				{
					// a long entry name has been collected
					if(entrycount == entry)		
					{
						// desired entry has been found, break out
						gotEntry = 1;
						break;
					}
					// otherwise
					haveLongNameEntry = 0;	// clear long name flag
					entrycount++;			// increment entry counter		
				}
				else
				{
					// entry is a short name (8.3 format) without a
					// corresponding multi-part long name entry
					fnbPtr = FileNameBuffer;
					for (i=0;i<8;i++)	*fnbPtr++ = de->deName[i];		// copy name
					*fnbPtr++ = '.';									// insert '.'
					for (i=0;i<3;i++)	*fnbPtr++ = de->deExtension[i];	// copy extension
					*fnbPtr = 0;										// null-terminate

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -