📄 fatlite.c
字号:
/*----------------------------------------------------------------------*//* 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. *//* *//* Parameters: *//* irHandle : Drive number (0, 1, ...) *//* irData : Address of user buffer to write from *//* irSectorNo : First sector no. to write (sector 0 is the *//* DOS boot sector). *//* irSectorCount : Number of consectutive sectors to write *//* *//* Returns: *//* FLStatus : 0 on success, otherwise failed *//* irSectorCount : Number of sectors actually written *//*----------------------------------------------------------------------*/static FLStatus absWrite(Volume vol, IOreq FAR2 *ioreq){ char FAR1 *userBuffer = (char FAR1 *) ioreq->irData; SectorNo currSector = vol.bootSectorNo + ioreq->irSectorNo; unsigned sectorCount = ioreq->irSectorCount; if (currSector < vol.secondFATSectorNo && currSector + sectorCount > vol.firstFATSectorNo) { unsigned iSector;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -