fatlite.c
来自「cpc-1631的BSP包for VxWorks操作系统」· C语言 代码 · 共 1,760 行 · 第 1/5 页
C
1,760 行
buffer.sectorNo = UNASSIGNED_SECTOR; /* Current sector no. (none) */
buffer.dirty = buffer.checkPoint = FALSE;
#endif /* FILES > 0 */
}
vol.flags = 0; /* mark volume unmounted */
return flOK;
}
/*----------------------------------------------------------------------*/
/* m o u n t V o l u m e */
/* */
/* Mounts the Flash volume. */
/* */
/* In case the inserted volume has changed, or on the first access to */
/* the file system, it should be mounted before file operations can be */
/* done on it. */
/* Mounting a volume has the effect of discarding all open files (the */
/* files cannot be properly closed since the original volume is gone), */
/* and turning off the media-change indication to allow file processing */
/* calls. */
/* */
/* The volume automatically becomes unmounted if it is removed or */
/* changed. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/* Returns: */
/* FLStatus : 0 on success, otherwise failed */
/*----------------------------------------------------------------------*/
static FLStatus mountVolume(Volume vol)
{
SectorNo noOfSectors;
PartitionTable FAR0 *partitionTable;
DOSBootSector FAR0 *bootSector;
checkStatus(dismountVolume(&vol));
checkStatus(flMount(&vol - vols,&vol.tl,&vol.flash)); /* Try to mount translation layer */
/* Read in paritition table */
partitionTable = (PartitionTable FAR0 *) findSector(&vol,0);
if(partitionTable == NULL)
return flSectorNotFound;
/* *BUG* *BUG* Doesn't work if SECTOR_SIZE < 512 */
if (LE2(partitionTable->signature) == PARTITION_SIGNATURE &&
partitionTable->type != 0)
vol.bootSectorNo =
(unsigned) UNAL4(partitionTable->startingSectorOfPartition);
else
vol.bootSectorNo = 0; /* If partition table is undetected,
assume sector 0 is DOS boot block */
vol.firstFATSectorNo = vol.secondFATSectorNo = 0; /* Disable FAT monitoring */
vol.flags |= VOLUME_ABS_MOUNTED; /* Enough to do abs operations */
bootSector = (DOSBootSector FAR0 *) findSector(&vol,vol.bootSectorNo);
if(bootSector == NULL)
return flSectorNotFound;
/* Do the customary sanity checks */
if (!(bootSector->bpb.jumpInstruction[0] == 0xe9 ||
(bootSector->bpb.jumpInstruction[0] == 0xeb &&
bootSector->bpb.jumpInstruction[2] == 0x90))) {
#ifdef DEBUG_PRINT
DEBUG_PRINT("Debug: did not recognize format.\n");
#endif
return flNonFATformat;
}
/* See if we handle this sector size */
if (UNAL2(bootSector->bpb.bytesPerSector) != SECTOR_SIZE)
return flFormatNotSupported;
vol.sectorsPerCluster = bootSector->bpb.sectorsPerCluster;
vol.numberOfFATS = bootSector->bpb.noOfFATS;
vol.sectorsPerFAT = LE2(bootSector->bpb.sectorsPerFAT);
vol.firstFATSectorNo = vol.bootSectorNo +
LE2(bootSector->bpb.reservedSectors);
vol.secondFATSectorNo = vol.firstFATSectorNo +
LE2(bootSector->bpb.sectorsPerFAT);
vol.rootDirectorySectorNo = vol.firstFATSectorNo +
bootSector->bpb.noOfFATS * LE2(bootSector->bpb.sectorsPerFAT);
vol.sectorsInRootDirectory =
(UNAL2(bootSector->bpb.rootDirectoryEntries) * DIRECTORY_ENTRY_SIZE - 1) /
SECTOR_SIZE + 1;
vol.firstDataSectorNo = vol.rootDirectorySectorNo +
vol.sectorsInRootDirectory;
noOfSectors = UNAL2(bootSector->bpb.totalSectorsInVolumeDOS3);
if (noOfSectors == 0)
noOfSectors = (SectorNo) LE4(bootSector->bpb.totalSectorsInVolume);
vol.maxCluster = (unsigned) ((noOfSectors - vol.firstDataSectorNo) /
vol.sectorsPerCluster) + 1;
if (vol.maxCluster < 4085) {
#ifdef FAT_12BIT
vol.flags |= VOLUME_12BIT_FAT; /* 12-bit FAT */
#else
#ifdef DEBUG_PRINT
DEBUG_PRINT("Debug: FAT_12BIT must be defined.\n");
#endif
return flFormatNotSupported;
#endif
}
vol.bytesPerCluster = vol.sectorsPerCluster * SECTOR_SIZE;
vol.allocationRover = 2; /* Set rover at first cluster */
vol.flags |= VOLUME_MOUNTED; /* That's it */
return flOK;
}
#if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
/*----------------------------------------------------------------------*/
/* d e f r a g m e n t V o l u m e */
/* */
/* Performs a general defragmentation and recycling of non-writable */
/* Flash areas, to achieve optimal write speed. */
/* */
/* NOTE: The required number of sectors (in irLength) may be changed */
/* (from another execution thread) while defragmentation is active. In */
/* particular, the defragmentation may be cut short after it began by */
/* modifying the irLength field to 0. */
/* */
/* Parameters: */
/* ioreq->irLength : Minimum number of sectors to make available */
/* for writes. */
/* */
/* Returns: */
/* ioreq->irLength : Actual number of sectors available for writes */
/* FLStatus : 0 on success, otherwise failed */
/*----------------------------------------------------------------------*/
static FLStatus defragmentVolume(Volume vol, IOreq FAR2 *ioreq)
{
return vol.tl.defragment(vol.tl.rec,&ioreq->irLength);
}
#endif /* DEFRAGMENT_VOLUME */
#ifdef FORMAT_VOLUME
/*----------------------------------------------------------------------*/
/* f l F o r m a t V o l u m e */
/* */
/* Formats a volume, writing a new and empty file-system. All existing */
/* data is destroyed. Optionally, a low-level FTL formatting is also */
/* done. */
/* Formatting leaves the volume in the dismounted state, so that a */
/* flMountVolume call is necessary after it. */
/* */
/* Parameters: */
/* irHandle : Drive number (0, 1, ...) */
/* irFlags : NO_FTL_FORMAT: Do FAT formatting only */
/* FTL_FORMAT: Do FTL & FAT formatting */
/* FTL_FORMAT_IF_NEEDED: Do FTL formatting only */
/* if current format is invalid */
/* irData : Address of FormatParams structure to use */
/* */
/* Returns: */
/* FLStatus : 0 on success, otherwise failed */
/*----------------------------------------------------------------------*/
static FLStatus formatVolume(Volume vol, IOreq FAR2 *ioreq)
{
FormatParams FAR1 *formatParams = (FormatParams FAR1 *) ioreq->irData;
checkStatus(dismountVolume(&vol));
if (ioreq->irFlags == FTL_FORMAT) {
checkStatus(flFormat(&vol - vols,formatParams));
}
else {
FLStatus status = flMount(&vol - vols,&vol.tl,&vol.flash);
if ((status == flUnknownMedia || status == flBadFormat) &&
ioreq->irFlags == FTL_FORMAT_IF_NEEDED)
status = flFormat(&vol - vols,formatParams);
if (status != flOK)
return status;
}
checkStatus(flMount(&vol - vols,&vol.tl,&vol.flash));
checkStatus(flDosFormat(&vol.tl,formatParams));
return flOK;
}
#endif /* FORMAT_VOLUME */
#ifdef ABS_READ_WRITE
/*----------------------------------------------------------------------*/
/* a b s R e a d */
/* */
/* Reads absolute sectors by sector no. */
/* */
/* Parameters: */
/* irHandle : Drive number (0, 1, ...) */
/* irData : Address of user buffer to read into */
/* irSectorNo : First sector no. to read (sector 0 is the */
/* DOS boot sector). */
/* irSectorCount : Number of consectutive sectors to read */
/* */
/* Returns: */
/* FLStatus : 0 on success, otherwise failed */
/* irSectorCount : Number of sectors actually read */
/*----------------------------------------------------------------------*/
static FLStatus absRead(Volume vol, IOreq FAR2 *ioreq)
{
char FAR1 *userBuffer = (char FAR1 *) ioreq->irData;
SectorNo currSector = vol.bootSectorNo + ioreq->irSectorNo;
unsigned sectorCount = ioreq->irSectorCount;
for (ioreq->irSectorCount = 0;
ioreq->irSectorCount < sectorCount;
ioreq->irSectorCount++, currSector++, userBuffer += SECTOR_SIZE) {
const void FAR0 *mappedSector = findSector(&vol,currSector);
if (mappedSector)
tffscpy(userBuffer,mappedSector,SECTOR_SIZE);
else
tffsset(userBuffer,0,SECTOR_SIZE);
}
return flOK;
}
/*----------------------------------------------------------------------*/
/* r e p l a c e F A T s e c t o r */
/* */
/* Monitors sector deletions in the FAT. */
/* */
/* When a FAT block is about to be written by an absolute write, this */
/* routine will first scan whether any sectors are being logically */
/* deleted by this FAT update, and if so, it will delete-sector them */
/* before the actual FAT update takes place. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorNo : FAT Sector no. about to be written */
/* newFATsector : Address of FAT sector about to be written */
/* */
/* Returns: */
/* FLStatus : 0 on success, otherwise failed */
/*----------------------------------------------------------------------*/
FLStatus replaceFATsector(Volume vol,
SectorNo sectorNo,
const char FAR1 *newFATsector)
{
const char FAR0 *oldFATsector = (const char FAR0 *) findSector(&vol,sectorNo);
#ifdef FAT_12BIT
unsigned FAThalfBytes = vol.flags & VOLUME_12BIT_FAT ? 3 : 4;
unsigned firstCluster =
(FAThalfBytes == 3) ?
(((unsigned) (sectorNo - vol.firstFATSectorNo) * (2 * SECTOR_SIZE) + 2) / 3) :
((unsigned) (sectorNo - vol.firstFATSectorNo) * (SECTOR_SIZE / 2));
SectorNo firstSector =
((SectorNo) firstCluster - 2) * vol.sectorsPerCluster + vol.firstDataSectorNo;
unsigned int halfByteOffset =
(firstCluster * FAThalfBytes) & (2 * SECTOR_SIZE - 1);
if (oldFATsector == NULL)
return flOK;
/* Find if any clusters were logically deleted, and if so, delete them */
/* NOTE: We are skipping over 12-bit FAT entries which span more than */
/* one sector. Nobody's perfect anyway. */
for (; halfByteOffset < (2 * SECTOR_SIZE - 2);
firstSector += vol.sectorsPerCluster, halfByteOffset += FAThalfBytes) {
unsigned short oldFATentry, newFATentry;
#ifdef TFFS_BIG_ENDIAN
oldFATentry = LE2(*(LEushort FAR0 *)(oldFATsector + (halfByteOffset / 2)));
newFATentry = LE2(*(LEushort FAR1 *)(newFATsector + (halfByteOffset / 2)));
#else
oldFATentry = UNAL2(*(Unaligned FAR0 *)(oldFATsector + (halfByteOffset / 2)));
newFATentry = UNAL2(*(Unaligned FAR1 *)(newFATsector + (halfByteOffset / 2)));
#endif /* TFFS_BIG_ENDIAN */
if (halfByteOffset & 1) {
oldFATentry >>= 4;
newFATentry >>= 4;
}
else if (FAThalfBytes == 3) {
oldFATentry &= 0xfff;
newFATentry &= 0xfff;
}
#else
unsigned firstCluster =
((unsigned) (sectorNo - vol.firstFATSectorNo) * (SECTOR_SIZE / 2));
SectorNo firstSector =
((SectorNo) firstCluster - 2) * vol.sectorsPerCluster + vol.firstDataSectorNo;
unsigned int byteOffset;
if (oldFATsector == NULL)
return flOK;
/* Find if any clusters were logically deleted, and if so, delete them */
for (byteOffset = 0; byteOffset < SECTOR_SIZE;
firstSector += vol.sectorsPerCluster, byteOffset += 2) {
unsigned short oldFATentry = LE2(*(LEushort FAR0 *)(oldFATsector + byteOffset));
unsigned short newFATentry = LE2(*(LEushort FAR1 *)(newFATsector + byteOffset));
#endif
if (oldFATentry != FAT_FREE && newFATentry == FAT_FREE)
checkStatus(vol.tl.deleteSector(vol.tl.rec,firstSector,vol.sectorsPerCluster));
/* make sure sector is still there */
oldFATsector = (const char FAR0 *) findSector(&vol,sectorNo);
}
return flOK;
}
/*----------------------------------------------------------------------*/
/* d i s a b l e F A T m o n i t o r */
/* */
/* Turns off FAT monitor. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/* Returns: */
/* always flOK */
/*----------------------------------------------------------------------*/
static FLStatus disableFATmonitor(Volume vol)
{
vol.firstFATSectorNo = vol.secondFATSectorNo = 0; /* Disable FAT monitoring */
return flOK;
}
/*----------------------------------------------------------------------*/
/* a b s W r i t e */
/* */
/* Writes absolute sectors by sector no. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?