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

📄 ftllite.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
  return bestUnitSoFar;
}


/*----------------------------------------------------------------------*/
/*		       f i n d F r e e S e c t o r			*/
/*									*/
/* The allocation strategy goes this way:                               */
/*                                                                      */
/* We try to make consecutive virtual sectors physically consecutive if */
/* possible. If not, we prefer to have consecutive sectors on the same  */
/* unit at least. If all else fails, a sector is allocated on the unit  */
/* with most space available.                                           */
/*                                                                      */
/* The object of this strategy is to cluster related data (e.g. a file  */
/* data) in one unit, and to distribute unrelated data evenly among all */
/* units.								*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorNo        : virtual sector no. that we want to allocate.	*/
/*									*/
/* Returns:                                                             */
/*	newAddress	: Allocated logical sector no.			*/
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus findFreeSector(Flare vol,
			     VirtualSectorNo sectorNo,
			     LogicalSectorNo *newAddress)
{
  unsigned iSector;
  LEulong FAR0 *blockAllocMap;
  UnitHeader FAR0 *unitHeader;

  Unit *allocationUnit = NULL;

  LogicalSectorNo previousSectorAddress =
	 sectorNo > 0 ? virtual2Logical(&vol,sectorNo - 1) : UNASSIGNED_SECTOR;
#ifdef DEBUG_PRINT
  DEBUG_PRINT("Debug: findFreeSector -> %d !!\n", sectorNo);
#endif
  if (previousSectorAddress != UNASSIGNED_SECTOR &&
      previousSectorAddress != DELETED_SECTOR) {
    allocationUnit =
	vol.logicalUnits[previousSectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS)];
    if (allocationUnit->noOfFreeSectors > 0) {
      unsigned int sectorIndex = ((unsigned) previousSectorAddress & (vol.sectorsPerUnit - 1)) + 1;
      LEulong FAR0 *nextSectorAddress =
	   (LEulong FAR0 *) vol.flash.map(&vol.flash,
				     physicalBase(&vol,allocationUnit) +
                                          allocEntryOffset(&vol, sectorIndex),
				     sizeof(VirtualAddress));
      if (sectorIndex < vol.sectorsPerUnit && LE4(*nextSectorAddress) == FREE_SECTOR) {
	/* can write sequentially */
	*newAddress = previousSectorAddress + 1;
	return flOK;
      }
    }
    else
      allocationUnit = NULL;	/* no space here, try elsewhere */
  }

  if (allocationUnit == NULL)
    allocationUnit = bestUnitToAllocate(&vol);
  if (allocationUnit == NULL)	/* No ? then all is lost */ {
#ifdef DEBUG_PRINT
      DEBUG_PRINT("Debug: findFreeSector -> Unable to find free sector!!\n");
#endif
    return flGeneralFailure;
  }
  unitHeader = mapUnitHeader(&vol,allocationUnit,&blockAllocMap);
  for (iSector = vol.unitHeaderSectors; iSector < vol.sectorsPerUnit; iSector++) {
    if (LE4(blockAllocMap[iSector]) == FREE_SECTOR) {
      *newAddress = ((LogicalSectorNo) (LE2(unitHeader->logicalUnitNo)) << (vol.unitSizeBits - SECTOR_SIZE_BITS)) +
		    iSector;
      return flOK;
    }
  }
#ifdef DEBUG_PRINT
    DEBUG_PRINT("Debug: findFreeSector -> Problem marking allocation map!!\n");
#endif

  return flGeneralFailure;	/* what are we doing here ? */
}


/*----------------------------------------------------------------------*/
/*		           m a r k A l l o c M a p			*/
/*									*/
/* Writes a new value to a BAM entry.					*/
/*                                                                      */
/* This routine also updates the free & garbage sector counts.		*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorAddress	: Logical sector no. whose BAM entry to mark	*/
/*	allocMapEntry	: New BAM entry value				*/
/*	overwrite	: Whether we are overwriting some old value	*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus markAllocMap(Flare vol,
			   LogicalSectorNo sectorAddress,
			   VirtualAddress allocMapEntry,
			   FLBoolean overwrite)
{
  UnitNo unitNo = (UnitNo) (sectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS));
  Unit *unit = vol.logicalUnits[unitNo];
  int sectorInUnit = (unsigned) sectorAddress & (vol.sectorsPerUnit - 1);
  LEulong bamEntry;

  if (unitNo >= vol.noOfUnits - vol.noOfTransferUnits)
    return flGeneralFailure;

  if (allocMapEntry == GARBAGE_SECTOR)
    unit->noOfGarbageSectors++;
  else if (!overwrite) {
    unit->noOfFreeSectors--;
    vol.totalFreeSectors--;
  }

  toLE4(bamEntry,allocMapEntry);

  return flashWrite(&vol,
		    physicalBase(&vol,unit) + allocEntryOffset(&vol,sectorInUnit),
		    &bamEntry,
		    sizeof bamEntry,
		    overwrite);
}


/*----------------------------------------------------------------------*/
/*      	      d e l e t e L o g i c a l S e c t o r		*/
/*									*/
/* Marks a logical sector as deleted.					*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorAddress	: Logical sector no. to delete			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus deleteLogicalSector(Flare vol,  LogicalSectorNo sectorAddress)
{
  if (sectorAddress == UNASSIGNED_SECTOR ||
      sectorAddress == DELETED_SECTOR)
    return flOK;

  return markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE);
}


/* forward definition */
static FLStatus setVirtualMap(Flare vol,
			    VirtualSectorNo sectorNo,
			    LogicalSectorNo newAddress);


/*----------------------------------------------------------------------*/
/*      	     a l l o c a t e A n d W r i t e S e c t o r	*/
/*									*/
/* Allocates a sector or replacement page and (optionally) writes it.	*/
/*                                                                      */
/* An allocated replacement page also becomes the active replacement 	*/
/* page.								*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorNo	: Virtual sector no. to write			*/
/*	fromAddress	: Address of sector data. If NULL, sector is	*/
/*			  not written.					*/
/*	replacementPage	: This is a replacement page sector.		*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus allocateAndWriteSector(Flare vol,
				     VirtualSectorNo sectorNo,
				     void FAR1 *fromAddress,
				     FLBoolean replacementPage)
{
  FLStatus status;
  LogicalSectorNo sectorAddress;
  VirtualAddress bamEntry =
	((VirtualAddress) sectorNo - vol.noOfPages) << SECTOR_SIZE_BITS;
  long sectorsNeeded = 1;
#ifdef DEBUG_PRINT
  DEBUG_PRINT("Debug: calling defrgment routine!!\n");
#endif
  checkStatus(defragment(&vol,&sectorsNeeded));  /* Organize a free sector */

#ifdef DEBUG_PRINT
  DEBUG_PRINT("Debug: calling routine findFreeSector !!\n");
#endif
  checkStatus(findFreeSector(&vol,sectorNo,&sectorAddress));

  if (replacementPage)
    bamEntry |= REPLACEMENT_PAGE;
  else
    bamEntry |= DATA_SECTOR;

  status = markAllocMap(&vol,
			sectorAddress,
			sectorNo < vol.directAddressingSectors ?
			  ALLOCATED_SECTOR : bamEntry,
			FALSE);

  if (status == flOK && fromAddress)
    status = flashWrite(&vol,
			logical2Physical(&vol,sectorAddress),
			fromAddress,
			SECTOR_SIZE,
			0);

  if (sectorNo < vol.directAddressingSectors && status == flOK)
    status = markAllocMap(&vol,
			  sectorAddress,
			  bamEntry,
			  TRUE);

  if (status == flOK)
    if (replacementPage) {
      vol.replacementPageAddress = sectorAddress;
      vol.replacementPageNo = sectorNo;
    }
    else
      status = setVirtualMap(&vol,sectorNo,sectorAddress);

  if (status != flOK)
    status = markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE);

#ifdef DEBUG_PRINT
  if (status != flOK)
  DEBUG_PRINT("Debug: Bad status code at Allocate and Write sector !\n");
  DEBUG_PRINT("Debug: MarkAllocMap returned %d !\n", status);
#endif
  return status;
}


/*----------------------------------------------------------------------*/
/*      	     c l o s e R e p l a c e m e n t P a g e		*/
/*									*/
/* Closes the replacement page by merging it with the primary page.	*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus closeReplacementPage(Flare vol)
{
  FLStatus status;

#ifdef SINGLE_BUFFER
  int i;
  LogicalSectorNo nextReplacementPageAddress = vol.replacementPageAddress;
  VirtualSectorNo firstSectorNo =
	((VirtualSectorNo) vol.replacementPageNo << (PAGE_SIZE_BITS - SECTOR_SIZE_BITS)) +
	vol.noOfPages;
pageRetry:
  for (i = 0; i < ADDRESSES_PER_SECTOR; i++) {
    LogicalSectorNo logicalSectorNo = virtual2Logical(&vol,firstSectorNo + i);
    LEulong entryToWrite;
    toLE4(entryToWrite,logicalSectorNo == UNASSIGNED_SECTOR ?
		       UNASSIGNED_ADDRESS :
		       (LogicalAddress) logicalSectorNo << SECTOR_SIZE_BITS);
    if (flashWrite(&vol,
		   logical2Physical(&vol,nextReplacementPageAddress) +
			i * sizeof(LogicalAddress),
		   &entryToWrite,
		   sizeof entryToWrite,
		   OVERWRITE) != flOK)
      break;
  }

  if (i < ADDRESSES_PER_SECTOR &&
      nextReplacementPageAddress == vol.replacementPageAddress) {
    /* Uh oh. Trouble. Let's replace this replacement page. */
    LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress;

    checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,NULL,TRUE));
    nextReplacementPageAddress = vol.replacementPageAddress;
    vol.replacementPageAddress = prevReplacementPageAddress;
    goto pageRetry;
  }

  if (nextReplacementPageAddress != vol.replacementPageAddress) {
    LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress;
    vol.replacementPageAddress = nextReplacementPageAddress;
    checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress));
  }
#else
  setupMapCache(&vol,vol.replacementPageNo);	/* read replacement page into map cache */
  status = flashWrite(&vol,
		      logical2Physical(&vol,vol.replacementPageAddress),
		      mapCache,SECTOR_SIZE,OVERWRITE);
  if (status != flOK) {
    /* Uh oh. Trouble. Let's replace this replacement page. */
    LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress;

    checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,mapCache,TRUE));
    checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress));
  }
#endif
  checkStatus(setVirtualMap(&vol,vol.replacementPageNo,vol.replacementPageAddress));
  checkStatus(markAllocMap(&vol,
			   vol.replacementPageAddress,
			   (((VirtualAddress) vol.replacementPageNo - vol.noOfPages)
				<< SECTOR_SIZE_BITS) | DATA_SECTOR,
			   TRUE));

  vol.replacementPageNo = UNASSIGNED_SECTOR;

  return flOK;
}


/*----------------------------------------------------------------------*/
/*      	          s e t V i r t u a l M a p			*/
/*									*/
/* Changes an entry in the virtual map					*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorNo	: Virtual sector no. whose entry is changed.	*/
/*	newAddress	: Logical sector no. to assign in Virtual Map.	*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus setVirtualMap(Flare vol,
			    VirtualSectorNo sectorNo,
			    LogicalSectorNo newAddress)
{
  unsigned pageNo;
  int sectorInPage;
  CardAddress virtualMapEntryAddress;
  LEulong addressToWrite;
  LogicalAddress oldAddress;
  LogicalSectorNo updatedPage;

  vol.mappedSectorNo = UNASSIGNED_SECTOR;

  if (sectorNo < vol.directAddressingSectors) {
    checkStatus(deleteLogicalSector(&vol,vol.pageTable[sectorNo]));
    vol.pageTable[sectorNo] = newAddress;
    return flOK;
  }
  sectorNo -= vol.noOfPages;

  pageNo = sectorNo >> (PAGE_SIZE_BITS - SECTOR_SIZE_BITS);
  sectorInPage = (int) (sectorNo) % ADDRESSES_PER_SECTOR;
  updatedPage = vol.pageTable[pageNo];
  virtualMapEntryAddress = logical2Physical(&vol,updatedPage) +
				 sectorInPage * sizeof(LogicalAddress);
  oldAddress = LE4(*(LEulong FAR0 *)
	vol.flash.map(&vol.flash,virtualMapEntryAddress,sizeof(LogicalAddress)));

  if (oldAddress == DELETED_ADDRESS && vol.replacementPageNo == pageNo) {
    updatedPage = vol.replacementPageAddress;
    virtualMapEntryAddress = logical2Physical(&vol,updatedPage) +

⌨️ 快捷键说明

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