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

📄 hdd_file.c

📁 Sunplus 8202S source code.
💻 C
字号:
/*=================================================================

hdd_fs.c: Some FileSystem Info Function for HDD

2002-04-28 10:00AM Created  by Verdure
2002-06-12 08:42AM Modified by cyue

Copyright(c)2000-2002 by Worldplus Technology (ShenZhen) Co., Ltd.
                   ALL RIGHTS RESERVED 
=================================================================*/

#include "config.h"
#include "set.h"
#include "global.h"
#include "hdd_if.h"

#include "user_init.h"

#ifdef SUPPORT_HDD_ACCESS

#define	D	printf("INFO: __%d__(%s:%s)\n",__LINE__,__FILE__,__FUNCTION__);

#define	SUPPORT_FAT2			//MIKEY 2003.09.18 write FAT2
//#define	SUPPORT_BACKUP_FAT	//MIKEY 2003.09.18 copy FAT1 to FAT2

#define DBG_HDD_FS			//MIKEY_DEBUG


#ifndef DBG_HDD_FS
#undef printf
#define printf(f, a...)  {}
#endif


UINT32  keep_lba=-1;
//==============================================================
//
//==============================================================
// Global for FAT FS
extern UINT8  pwb[];

//UINT8 *Info_buff=pwb+0;
#define	NAVBUFSTART	(0xa03c0000)		// 0xa03c0000 40k
UINT8 *Info_buff=(UINT8 *)(NAVBUFSTART+0);
UINT8  HD_EXIST;
HDD_INFO HDD_Info;
BPB_INFO BPB;

UINT32 Data_Start_Clus;
UINT32 File_FDB_Lba;
UINT32 Start_LBA;
UINT32 Data_Curr_Clus;
UINT32 Data_Next_Clus;

int FS_Get_BPBPara(UINT8*);

PARTITION_INFO* HDD_AddPE(HDD_INFO* HDD_Info,UINT32 MBR,PARTITION_ENTRY* pe)
{
	PARTITION_INFO *pi=0;
#ifdef PI_USE_MATRIX
	int j;
	for(j=0;j<MAX_PART_INFO;j++)
	     if(!HDD_Info->part[j].type) break;
	pi=&HDD_Info->part[j]; 
#else
	PARTITION_INFO *hddpi;
	pi=(PARTITION_INFO*)malloc(sizeof(PARTITION_INFO));
#endif
	pi->type=pe->type;
	pi->next=NULL;
	pi->startlba=MBR+(pe->secfrommbr_hi<<16|pe->secfrommbr_lo);	
	Start_LBA=pi->startlba;
        // printf("\n startlba:%x\n",Start_LBA);//jichuan
	pi->seccnt=pe->seccnt_hi<<16|pe->seccnt_lo;
	pi->act=pe->act; 
#ifndef PI_USE_MATRIX
	if(HDD_Info->partition_list==NULL)
		HDD_Info->partition_list=pi;
	else {
		for(hddpi=HDD_Info->partition_list;hddpi->next!=NULL;hddpi=hddpi->next);
			hddpi->next=pi;
	}
#endif 
	return pi; 
}

int HDD_MakeInfo(HDD_INFO *HDD_Info,UINT8* buff)
{	
	PARTITION_ENTRY *pe;
	UINT32 i;     
	UINT32 MBR=0,secfrommbr,seccnt;

#ifdef PI_USE_MATRIX
	for(i=0;i<MAX_PART_INFO;i++)
		HDD_Info->part[i].type=0;
#else
	HDD_Info->partition_list=NULL;
#endif

	HDD_ReadSec(buff,MBR,1);
	//print_sector(buff);
	for(i=0;i<4;i++) { //Parse Primary partitions
		pe=(PARTITION_ENTRY*)(buff+ 0x1be +i*16);
		secfrommbr=pe->secfrommbr_hi<<16|pe->secfrommbr_lo;
		seccnt=pe->seccnt_hi<<16|pe->seccnt_lo;  
		printf("\n--secfrommbr=%lx--\n",secfrommbr);
		if (!pe->type)
			continue;
		if ((pe->type==0x0f)||(pe->type==0x05)) {
			// Extended Partition!!
			UINT32 MBREXT=MBR+secfrommbr;
			do {
				HDD_ReadSec(buff,MBREXT,1);
				printf("\n Parse EXT %lu... ",MBREXT);
				if (*(UINT16*)(buff+510)!=0xaa55) {
					printf("\n Fail EXT Partition!!");
					break;
				}
				pe=(PARTITION_ENTRY*)(buff + 0x1be);
				secfrommbr=pe->secfrommbr_hi<<16|pe->secfrommbr_lo;
				seccnt=pe->seccnt_hi<<16|pe->seccnt_lo;
				if (pe->type) {
#ifdef MIKEY
					HDD_AddPE(HDD_Info,MBREXT,pe);
#else
					printf("MIKEY: skip add EXT partition type[%x]\n",pe->type);
					break;
#endif
				}
				else
					break;
				pe=(PARTITION_ENTRY*)(buff+ 0x1be +16);
				if(!pe->type) {
					printf("\nLast MBR!!");
					MBREXT=HDD_Info->seccnt - seccnt;
				}
				else {
					MBREXT=MBREXT+secfrommbr+seccnt;
				}
			}while((pe->type==0x0f)||(pe->type==0x05));
		} 
		else {
			HDD_AddPE(HDD_Info,MBR,pe);
			printf("\n primary=%d \n",i);
		}
	}
	return 0;
}

void HDD_Dump_Info(HDD_INFO* HDD_Info)
{
	PARTITION_INFO *pi;
	int i;
	printf("\n\nHDD: C=%lu H=%lu S=%lu",HDD_Info->cyl,HDD_Info->head,HDD_Info->sec);
	printf("\nHDD total Sectors = %lu, %lu MB ",HDD_Info->seccnt,HDD_Info->seccnt/2000);
	printf("\nPAR  A TYPE START LBA       COUNT"); 
#ifdef PI_USE_MATRIX
	for(i=0;i<MAX_PART_INFO;i++) {
		pi= &HDD_Info->part[i];
		if(pi->type)
			printf("\n%2d  %02x  %02x %10lu  %10lu\n",i,pi->act,pi->type,pi->startlba,pi->seccnt);
	}
#else	
	for(i=0,pi=HDD_Info->partition_list;pi!=NULL;i++,pi=pi->next) {
		printf("\n%2d  %02x  %02x  %10lu  %10lu",i,pi->act,pi->type,pi->startlba,pi->seccnt);
	}
#endif
}


static int FS_check_SecPerClus(unsigned SecPerClus)
{
	unsigned char log;

	for(log = 0; log < 8; log++) {
		if(SecPerClus & 1) {
			SecPerClus >>= 1;
			return (SecPerClus != 0) ? -1 : log;
		}
		SecPerClus >>= 1;
	}
	return -1;
}

int FS_check_BootSec(UINT8* buf)
{
	UINT16 temp;

	//check Jump Code + NOP
	if(buf[0] == 0xE9)
		/* OK */;
	else if(buf[0] == 0xEB && buf[2] == 0x90)
		/* OK */;
	else {
		printf("Missing JMP/NOP\n");
		return 1;
	}

	//check Sectors Per Cluster
	temp = buf[13];
	if(FS_check_SecPerClus(temp) < 0) {
		printf("Sectors per cluster (%u) is not a power of 2\n",temp);
		return 1;
	}
	
	//check the Number of FATs
	temp = buf[16];
	if(temp != 1 && temp != 2) {
		printf("Invalid number of FATs (%u)\n",temp);
		return 1;
	}
	    
	//check Sectors Per Track
	temp = read_le16(buf + 24);
	if(temp == 0 || temp > 63) {
		printf("Invalid number of sectors (%u)\n",temp);
		return 1;
	}
	
	//check Number of Heads
	temp = read_le16(buf + 26);
	if(temp == 0 || temp > 255) {
		printf("Invalid number of heads (%u)\n",temp);
		return 1;
	}
	return FS_Get_BPBPara(buf);
}


int FS_Get_BPBPara(UINT8* buf)
{
	BPB.BytesPerSec=(buf[12]<<8)|buf[11];
	switch(BPB.BytesPerSec) {
		case 512: BPB.BytesPerSecPwr=9; break;
		case 2048: BPB.BytesPerSecPwr=11; break;
		case 256: BPB.BytesPerSecPwr=8; break;
	}
	printf("\n## BytesPerSec:%d ",BPB.BytesPerSec);
     
	BPB.SecPerClus=buf[13];
	switch(BPB.SecPerClus) {
		case 128: BPB.SecPerClusPwr=7; break; //64K allocation unit
		case  64: BPB.SecPerClusPwr=6; break; //32K allocation unit
		case  32: BPB.SecPerClusPwr=5; break; //16K allocation unit
		case  16: BPB.SecPerClusPwr=4; break; // 8K allocation unit
		case   8: BPB.SecPerClusPwr=3; break; // 4K allocation unit
		case   4: BPB.SecPerClusPwr=2; break; // 2K allocation unit
	}

	printf("\n## SecPerClus:%d ",BPB.SecPerClus);
	printf("\n## SecPerClusPwr:%d ",BPB.SecPerClusPwr);
     
	BPB.ReserSecCnt=read_le16(buf + 14);
	BPB.NumFATs=buf[16];
//	BPB.MediaDescriptor=buf[21];
//	BPB.SecPerTrack=read_le16(buf + 24);
//	BPB.NumHeads=read_le16(buf + 26);
//	BPB.HiddenSecCnt=read_le32(buf + 28);
//	BPB.TolSec32=read_le32(buf + 32);

	BPB.FATSize32=read_le32(buf + 36);
	printf("\n## FATSize32:%d ",BPB.FATSize32);
	BPB.CurrDirClus=BPB.RootClus=read_le32(buf + 44);
	BPB.FAT1_Start=Start_LBA+BPB.ReserSecCnt;
	printf("\n## BPB.FAT1_Start:%d ",BPB.FAT1_Start);
	if (BPB.NumFATs==1) 
		BPB.FAT2_Start=0;
	if (BPB.NumFATs==2)
		BPB.FAT2_Start=BPB.FAT1_Start+BPB.FATSize32;

	BPB.Data_Area_Start=((BPB.RootClus-2)*BPB.SecPerClus) + BPB.FAT1_Start+BPB.FATSize32*BPB.NumFATs;
	printf("\n## BPB.Data_Area_Start:%d \n",BPB.Data_Area_Start);
	return 0;
}

UINT32 Last_FAT_Lba=0x0FFFFFFF; // cyue: Try to make a cache 2002-06-11 11:14PM
UINT8 *FS_ReadInfoSec(UINT32 lba,int seccnt)
{
	if(Last_FAT_Lba!=lba) {
		HDD_ReadSec(Info_buff,lba,seccnt);
	}
	return Info_buff;
}


void FS_flush_cache()
{
	keep_lba=-1;
}


UINT32  FS_Get_NextClus(UINT32 clus)	//MIKEY 2003.09.02 for speed up
{
	UINT32 lba;
	UINT32 nOffset;
//	static UINT32  keep_lba=-1;
	static UINT32  keep_count=0;
//	extern UINT8  pwb[];
//	UINT8 *buff512=pwb+512;
	UINT8 *buff512=(UINT8 *)(NAVBUFSTART+512);

    keep_lba=-1; //MIKEY disable cache

	nOffset=clus&0x7F;//%128;
	lba=(clus>>7)+BPB.FAT1_Start;

	if(keep_lba!=lba) { //MIKEY_CACHE
		keep_lba=lba;
		HDD_ReadSec(buff512, lba, 1);
	}
	else {
		keep_count++;
		if((keep_count % 100)==99)
			printf("INFO: FS_Get_NextClus keep_count(%ld)\n",keep_count);
	}		
	Data_Next_Clus=read_le32(buff512+(nOffset<<2))&0x0fffffff;
	return Data_Next_Clus;
}

//==============================================================
//
//==============================================================
//extern BYTE CardReadSector();
extern BYTE FSReadSector();
extern BYTE CardWriteSector();
extern void *memcpy();
extern unsigned strlen();

/* Check whether HD present */
UINT8 HDD_DEV_Existence(void)
{
	return 0;
}

int HDD_ReadSec(UINT8 *buff, UINT32 lba, int seccnt)
{
	int i;
	int ret=0;
	for(i=0;i<5;i++) { // retry?
//		if((ret=CardReadSector(lba, seccnt, buff))==0)
		if((ret=FSReadSector(lba, seccnt, buff))==0)
			break; //OK
		printf("ERROR: HDD_ReadSec retry(%d)\n",i+1);
	}
	return ret;
} 

int HDD_WriteSec(UINT8 *buff, UINT32 lba, int seccnt)
{
	int i;
	int ret=0;
	for(i=0;i<5;i++) { // retry?
		if((ret=CardWriteSector(lba, seccnt, buff))==0)
			break; //OK
		printf("ERROR: HDD_WriteSec retry(%d)\n",i+1);
	}
	return ret;
} 


UINT32 FS_LBA2Clus(UINT32 lba)
{
	UINT32 clus;

	clus = (lba - BPB.Data_Area_Start)/BPB.SecPerClus + 2;
	return clus;
}

UINT32 FS_LBAinClus(UINT32 lba)
{
	UINT32 curClus, nextClus;
	int i;
    
	curClus = FS_LBA2Clus(lba);
	for (i=0; i<BPB.SecPerClus; i++) {
		nextClus = FS_LBA2Clus(lba+i+1);
		if (curClus != nextClus)
			break;
	}
	return i;
}


//==============================================================
//
//==============================================================
#ifdef SUPPORT_BACKUP_FAT
void  HDD_Backup_FAT(void)
{
	UINT32 i;
	if(BPB.NumFATs<2)
		return;
	
	for(i=0; i<BPB.FATSize32; i++) {
		HDD_ReadSec (Info_buff, BPB.FAT1_Start+i, 1);
		HDD_WriteSec(Info_buff, BPB.FAT2_Start+i, 1);
	}	
}
#endif //SUPPORT_BACKUP_FAT

int HDD_list_clus(FILE_INFO *fp)
{
	UINT32 st,next;
//	UINT32 lba_count=LBA_COUNT(fp->fsize),sec_count=BPB.SecPerClus; 
	int i=0;
	st=fp->start_clus;
	next=0;
//printf("MIKEY: lba_count(%d)/(%d)=(%d)\n",lba_count,sec_count,(lba_count+sec_count-1)/sec_count);
	while(1) {
		printf("$$ clus(%4d):[%x]\n",i,st);
		if(st>=0x0FFFFFF8) {//End?
			break;
		}
		next=FS_Get_NextClus(st);
		st=next;
		i++;
	}
	return 0;
}

//==============================================================
//
//==============================================================
UINT8  FS_Emu_stricmp(UINT8* s1, UINT8* s2)
{
	UINT16 i;

//MIKEY_BUG
//	for(i=0;(i<11)&&(*s1)&&(*s2);i++,s1++,s2++) {
	for(i=0;i<11;i++) {
		if(((s1[i])&~0x20)!=((s2[i])&~0x20))
    			return 1;
	}
	return 0;
}


UINT8  HDD_Mount(void)
{
	UINT8 i;
    
	if ((HD_EXIST = HDD_DEV_Existence()))
		return 0;
	HDD_MakeInfo(&HDD_Info,Info_buff);
	for(i=0;HDD_Info.part[i].type;i++) { /*浪代–

⌨️ 快捷键说明

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