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 + -
显示快捷键?