1
0
forked from me/IronOS
Files
IronOS/S100App/Src/2FAT12.c
2016-04-30 20:56:50 +05:00

238 lines
9.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/********************* (C) COPYRIGHT 2015 e-Design Co.,Ltd. ********************
File Name : 2FAT12.c
Version : S100 APP Ver 2.11
Description:
Author : bure & Celery
Data: 2015/08/03
History:
2015/08/03 统一命名;
*******************************************************************************/
#include <string.h>
#include "FAT12.h"
#include "BIOS.h"
#define FAT_LEN 0x1800
#define FAT1_BASE 0x00001000 // FAT1区开始地址
#define FAT2_BASE 0x00002800 // FAT2区开始地址
#define ROOT_BASE 0x00004000 // 根目录开始地址
#define FILE_BASE 0x00008000 // 文件区开始地址
#define SEC_LEN 0x200 // 扇区长度
#define FAT1_SEC 0x0C // FAT1扇区数
#define FAT2_SEC 0x0C // FAT2扇区数
#define OK 0 // 操作完成
#define SEC_ERR 1 // 扇区读写错误
#define FAT_ERR 2 // FAT表读写错误
#define OVER 3 // 操作溢出
#define NEW 4 // 新目录项
#define END 0xFFF // 链接结束
#define OW 0 // 或写(数据从0变1改写)
#define RW 1 // 重写
/*******************************************************************************
查找下一个链接簇号后返回
*******************************************************************************/
u8 NextCluster(u16* pCluster)
{
u16 FatNum;
u32 Addr = FAT1_BASE +(*pCluster + *pCluster/2);
*(pCluster+1)= *pCluster; // 保存前一个簇号
// *(pCluster+1)= 0;
if((*pCluster >= END)||(*pCluster < 2)) return OK;
if(ReadDiskData((u8*)&FatNum, Addr, 2)!= OK) return SEC_ERR;
*pCluster = (*pCluster & 1)?(FatNum >>4):(FatNum & 0x0FFF); // 指向下一个簇号
return OK;
}
/*******************************************************************************
读文件扇区(512 Bytes), 返回下一个簇号
*******************************************************************************/
u8 ReadFileSec(u8* pBuffer, u16* pCluster)
{
u32 ReadAddr = FILE_BASE + SEC_LEN*(*pCluster-2);
if(ReadDiskData(pBuffer, ReadAddr, 256)!=OK) return SEC_ERR; // 读前半扇区
pBuffer += 256;
ReadAddr += 256;
if(ReadDiskData(pBuffer, ReadAddr, 256)!=OK) return SEC_ERR; // 读后半扇区
if(NextCluster(pCluster)!=0) return FAT_ERR; // 取下一个簇号
return OK;
}
/*******************************************************************************
写文件扇区(512 Bytes)填写当前FAT表及返回查找到的下一个簇号
*******************************************************************************/
u8 ProgFileSec(u8* pBuffer, u16* pCluster)
{
u16 Tmp;
u32 ProgAddr = FILE_BASE + SEC_LEN*(*pCluster-2);
if(ProgDiskPage(pBuffer, ProgAddr)!= OK) return SEC_ERR; // 写前半扇区
pBuffer += 256;
ProgAddr += 256;
if(ProgDiskPage(pBuffer, ProgAddr)!= OK) return SEC_ERR; // 写后半扇区
Tmp = *pCluster;
switch(Tmp) {
case 0: // 空闲簇号
case 1: // 空闲簇号
if(SeekBlank (pBuffer, pCluster )!= OK) return OVER;
if(SetCluster(pBuffer, pCluster )!= OK) return SEC_ERR;
*(pCluster+1) = Tmp;
return OK;
case END: // 链接结束
default :
if(NextCluster(pCluster)!= OK) return FAT_ERR; // 取下一个簇号
return OK;
}
}
/*******************************************************************************
查找空闲簇号,包含数据校对及纠错,返回值包括当前空闲簇号及下一个空闲簇号
*******************************************************************************/
u8 SeekBlank(u8* pBuffer, u16* pCluster)
{
u16 Offset, Tmp, i, n = 0;
u32 SecAddr;
for(i=0; i<4096; i++) {
Offset = i + i/2;
if((Offset%256)== 0) {
SecAddr = FAT1_BASE +(Offset &(~0xFF));
if(ReadDiskData(pBuffer, SecAddr, 258)!= 0) return SEC_ERR;
}
Offset %= 256;
Tmp = pBuffer[Offset] + pBuffer[Offset+1] <<8;
Tmp = (i & 1)?(Tmp >>4):(Tmp & 0xFFF);
if(Tmp == 0) {
*pCluster++ = i;
n++;
if(n > 1) return OK;
}
}
*(pCluster+1)= 0xFFF;
return OK;
}
/*******************************************************************************
将下一个簇号写入FAT表当前簇号链接位置返回时当前簇号为原下一个簇号
*******************************************************************************/
u8 SetCluster(u8* pBuffer, u16* pCluster)
{
u16 Offset, Tmp, i, k;
u32 SecAddr;
i = *pCluster; // 提取原当前簇号
k = *(pCluster+1); // 提取下一簇号
*pCluster = k;
Offset = i + i/2;
SecAddr = FAT1_BASE +(Offset &(~0xFF));
Tmp = Offset & 0xFF;
if(ReadDiskData(pBuffer, SecAddr, 256)!= 0) return SEC_ERR;
if(i & 1) pBuffer[Tmp]=((k<<4)& 0xF0)+(pBuffer[Tmp]& 0x0F);
else pBuffer[Tmp]= k;
if(Tmp++ < 256) {
if(i & 1) pBuffer[Tmp]= k>>4;
else pBuffer[Tmp]=((k>>8)& 0x0F)+(pBuffer[Tmp]& 0xF0);
if(ProgDiskPage(pBuffer, SecAddr)!= 0) return SEC_ERR;
} else {
if(ProgDiskPage(pBuffer, SecAddr)!= 0) return SEC_ERR;
SecAddr += 256;
if(ReadDiskData(pBuffer, SecAddr, 256)!= 0) return SEC_ERR;
if(i & 1) pBuffer[0]= k>>4;
else pBuffer[0]=((k>>8)& 0x0F)+(pBuffer[0]& 0xF0);
if(ProgDiskPage(pBuffer, SecAddr)!= 0) return SEC_ERR;
}
return OK;
}
/*******************************************************************************
*******************************************************************************/
u8 SearchFile(u8* pBuffer, u8* pFileName, u16* pCluster, u32* pDirAddr,u32* flag)
{
u16 i, n;
*pCluster = 0;
for(*pDirAddr=ROOT_BASE; *pDirAddr<FILE_BASE; ) {
if(ReadDiskData(pBuffer, *pDirAddr, 256)!= OK) return SEC_ERR;
for(n=0; n<256; n+=32) {
for(i=0; i<4; i++) {
if(pBuffer[n + i]!= 0) {
if(pBuffer[n + i]!= pFileName[i]) break;
if(i == 3) { // 找到文件名
*pCluster = *(u16*)(pBuffer + n + 0x1A); // 文件第一个簇号
return OK;
}
} else return NEW; // 遇到第一个空白目录项后返回
}
*pDirAddr += 32;
}
}
return OVER;
}
/*******************************************************************************
读模式打开文件:返回文件第一个簇号及目录项地址或 0簇号及第一个空白目录项地址
*******************************************************************************/
u8 OpenFileRd(u8* pBuffer, u8* pFileName, u16* pCluster, u32* pDirAddr)
{
u16 i, n;
*pCluster = 0;
for(*pDirAddr=ROOT_BASE; *pDirAddr<FILE_BASE; ) {
if(ReadDiskData(pBuffer, *pDirAddr, 256)!= OK) return SEC_ERR;
for(n=0; n<256; n+=32) {
for(i=0; i<11; i++) {
if(pBuffer[n + i]!= 0) {
if(pBuffer[n + i]!= pFileName[i]) break;
if(i == 10) { // 找到文件名
*pCluster = *(u16*)(pBuffer + n + 0x1A); // 文件第一个簇号
return OK;
}
} else return NEW; // 遇到第一个空白目录项后返回
}
*pDirAddr += 32;
}
}
return OVER;
}
/*******************************************************************************
写模式打开文件:返回文件第一个簇号及目录项地址
*******************************************************************************/
u8 OpenFileWr(u8* pBuffer, u8* pFileName, u16* pCluster, u32* pDirAddr)
{
u16 i, n;
i = OpenFileRd(pBuffer, pFileName, pCluster, pDirAddr);
if(i != NEW) return i;
else { // 当前项为空白目录项
if(SeekBlank(pBuffer, pCluster)!= OK) return OVER; // 若FAT表满返回
n =*pDirAddr & 0xFF; // n为当前页目录号
if(ReadDiskData(pBuffer,(*pDirAddr)-n, 256)!= OK) return SEC_ERR;
for(i=0; i<11; i++) pBuffer[n + i]= pFileName[i]; // 创建新目录项
*(u16*)(pBuffer + n + 0x1A)= *pCluster;
if(ProgDiskPage(pBuffer,(*pDirAddr)-n)!= OK) return SEC_ERR;
return OK;
}
}
/*******************************************************************************
关闭文件将结束符写入FAT表将文件长度写入目录项复制FAT1到FAT2
*******************************************************************************/
u8 CloseFile(u8* pBuffer, u32 Lenght, u16* pCluster, u32* pDirAddr)
{
u16 n;
// *pCluster = *(pCluster+1); // 提取前一个簇号
*(pCluster+1) = 0xFFF;
SetCluster(pBuffer, pCluster);
if(ReadDiskData(pBuffer, (*pDirAddr &(~0xFF)), 256)!= OK) return SEC_ERR;
*(u8* )(pBuffer +(*pDirAddr & 0xFF)+ 0x0B)= 0x20;
*(u32*)(pBuffer +(*pDirAddr & 0xFF)+ 0x1C)= Lenght;
if(ProgDiskPage(pBuffer, (*pDirAddr &(~0xFF)))!= OK) return SEC_ERR;
for(n=0; n<FAT1_SEC; n++) {
if(ReadDiskData(pBuffer, FAT1_BASE+n*256, 256)!= OK) return SEC_ERR;
if(ProgDiskPage(pBuffer, FAT2_BASE+n*256 )!= OK) return SEC_ERR;
}
return OK;
}
/******************************** END OF FILE *********************************/