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

📄 celltable.c

📁 AMD公司官方版FLASH文件系统。有详细说明文档和Windows仿真测试环境。
💻 C
📖 第 1 页 / 共 3 页
字号:
     *   allow a check to make sure there is only one of these
     *   blocks.
     * If there are more then something went wrong.
     */
    if (lpBlockInProcess == NULL){
      lwCellIndexOfBlockInProcess = awCellIndex;
      lpBlockInProcess = pTmpEntry;
      return No_Error;
    } else {
      free(pTmpEntry);
      return More_Than_Two_Dirty_Cells;
    }
  }
  return No_Error;
}


/**
 * dms_CellTableAddAvailableBlock
 * Adds block to BlockAlloc's AvailableBlockList.
 * Interface function so only CellTable interfaces with BlockAlloc.
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 * Uses:
 *   dms_BlockAddAvailable()
 * Used By:
 *   dms_SectorInitialize()
 */
DMS_STATUS dms_CellTableAddAvailableBlock(WORD awSectorIndex, WORD awSectorBlockIndex){
  return dms_BlockAddAvailable(awSectorIndex,awSectorBlockIndex);
}

/**
 * dms_CellTableAddGarbageBlock
 * Adds block to BlockAlloc's AvailableBlockList.
 * Interface function so only CellTable interfaces with BlockAlloc.
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 * Uses:
 *   dms_BlockAddAvailable()
 * Used By:
 *   dms_SectorInitialize()
 */
void dms_CellTableAddGarbageBlock(WORD awSectorIndex, WORD awSectorBlockIndex){
  dms_BlockIncrementGarbageCount(awSectorIndex);
}

/**
 * dms_CellTableGetBestSectorToErase
 * Computes the best sector to erase based on the dirty count in each
 *   sector.
 * Interface function so only CellTable interfaces with BlockAlloc.
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   dms_BlockGetBestSectorToErase()
 * Used By:
 *   dms_SectorCleanup()
 */
DMS_STATUS dms_CellTableGetBestSectorToErase(WORD *apwSectorIndex){
  return dms_BlockGetBestSectorToErase(apwSectorIndex);
}

/**
 * dms_CellTableIsBlockAvailable()
 * Returns non-zero if the number of available blocks is above the minimum
 *   allowable free blocks.
 * Interface function so only CellTable interfaces with BlockAlloc.
 * 
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   dms_BlockAllocIsAvailable()
 * Used By:
 *   dms_CellInitialize()
 */
BYTE dms_CellTableIsBlockAvailable(void){
  return dms_BlockAllocIsAvailable();
}

/**
 * dms_CellTableGetAvailableBlock
 * Puts new block in CellTable.
 * Returns Duplicate_Block if block already exists.
 * Returns No_Available_Blocks if minumum free block threshold is reached
 *   and a cleanup is needed.
 * 
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   dms_BlockAlloc()
 *   dms_lCellTableInsertBlock()
 * Used By:
 *   dms_CellWrite()
 */
DMS_STATUS dms_CellTableGetAvailableBlock(WORD awCellIndex, WORD awBlockIndex,
                                          WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
  CELL_TABLE_ENTRY *pEntry;
  DMS_STATUS eStatus;

  pEntry = dms_BlockAlloc();
  if (pEntry == NULL){
    return No_Available_Blocks;
  }
  pEntry->wBlockIndex = awBlockIndex;
  *apwSectorIndex = pEntry->wSectorIndex;
  *apwSectorBlockIndex = pEntry->wSectorBlockIndex;
  eStatus = dms_lCellTableInsertBlock(&lpCellTable[awCellIndex],pEntry);
  if (eStatus != No_Error){
    return eStatus;
  }
  return No_Error;
}


/**
 * dms_CellTableCheckValidity
 * Determines which version of cell should be deleted if one was in
 *   process during a power failure.
 * Defines cell size for each cell by counting the blocks that were added
 *   by dms_CellTableAddBlock()
 * Checks:
 *   1.  missing blocks in a cell.
 *   2.  each cell has at least one block.
 * 
 * Prerequisites:
 *   dms_CellTableInitialize()
 * Uses:
 *   dms_lCellTableCheckCellInProcess()
 *   dms_CellInfoGetCount()
 *   dms_lCellTableCountAndCheckBlocks()
 *   dms_CellInfoDefineCellBlockCount()
 *   dms_CellInfoCheckValidity()
 *   dms_BlockAllocComputeMinimumAllowableBlocksFree()
 *   dms_SectorInfoGetLargestSectorBlockCount()
 *   dms_CellInfoGetTotalBlockCount()
 *   dms_SectorInfoGetTotalBlockCount()
 * Used By:
 *   dms_CellInitialize()
 */
DMS_STATUS dms_CellTableCheckValidity(void){
  DMS_STATUS eStatus;
  WORD wCellIndex;
  WORD wBlockCount;

  /* Move any in process blocks or cells to the in process location. */
  dms_lCellTableCheckCellInProcess();

  /* 
   * Check each block of each cell and make sure no blocks are missing
   * If cell is completly empty then that will be caught later by
   *   dms_CellInfoCheckValidity
   */
  for (wCellIndex = 0; wCellIndex < dms_CellInfoGetCount(); wCellIndex++){
    eStatus = dms_lCellTableCountAndCheckBlocks(lpCellTable[wCellIndex], &wBlockCount);
    if (eStatus != No_Error) {
      return eStatus;
    }
    dms_CellInfoDefineCellBlockCount(wCellIndex,wBlockCount);
  }

  /* Check cell size */
  eStatus = dms_CellInfoCheckValidity();
  if (eStatus != No_Error){
    return eStatus;
  }

  /* calculate the minimum number of free blocks allowed. */
  /* This can be done now because the largest cell size is known at this time. */
  dms_BlockAllocComputeMinimumAllowableBlocksFree( dms_SectorInfoGetLargestSectorBlockCount(),
                                                   dms_CellInfoGetLargestCellBlockCount());
  if (dms_CellInfoGetTotalBlockCount() >= (WORD) (dms_SectorInfoGetTotalBlockCount()
                                        - dms_SectorInfoGetLargestSectorBlockCount()
                                        - dms_CellInfoGetLargestCellBlockCount())){
    return Not_Enough_Free_Blocks;
  }

  /* Validity Check Passed */
  return No_Error;
}


/**
 * dms_CellTableSetCellInProcess
 * Moves list of the specified cell from the CellTable
 *   to CellInProcessList.
 * This is done during a cell write where the new cell blocks
 *   are added to the CellTable and the CellInProcess cell 
 *   is deleted after all new blocks are written.
 * The CellInProcess is deleted by dms_CellTableDeleteCellInProcess().
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   Nothing outside this file.
 * Used By:
 *   dms_CellWrite();
 */
DMS_STATUS dms_CellTableSetCellInProcess(WORD awCellIndex){
  if (lpCellInProcess != NULL) {
    return Cell_Already_In_Process;
  }
  /* Move cell to cell in process */
  lpCellInProcess = lpCellTable[awCellIndex];
  lpCellTable[awCellIndex] = NULL;
  lwCellIndexOfCellInProcess = awCellIndex;
  return No_Error;
}

/**
 * dms_CellTableMoveBlock
 * Called during Cleanups to move blocks.  It removes
 *   the specified block from the CellTable or CellInProcessList, gets a new
 *   block using dms_BlockAllocNoMinimum() inserts the new block in the
 *   CellTable or CellInProcessList, and provides the SectorIndex and 
 *   SectorBlockIndex of the new Block.
 * It does not add the old block to the GarbageCount because it assums
 *   that this is being called during a cleanup where the GarbageCount is
 *   already set to zero by dms_CellTableGetBestSectorToErase().
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   dms_lCellTableRemoveExactBlock()
 *   dms_BlockAllocNoMinimum()
 *   dms_lCellTableInsertBlock()
 *   free()
 * Used By:
 *   dms_SectorCleanup()
 */
DMS_STATUS dms_CellTableMoveBlock(WORD awSectorIndex, WORD awSectorBlockIndex,
                                  WORD awCellIndex,
                                  WORD *apwNewSectorIndex, WORD *apwNewSectorBlockIndex){
  CELL_TABLE_ENTRY *pEntry;
  DMS_STATUS eStatus;
  CELL_TABLE_ENTRY **ppTablePointer;

  /* Set Block as block in process */
  if (lpBlockInProcess != NULL) {
    return Block_Already_In_Process;
  }
  /* Move block to block in process */
  ppTablePointer = &lpCellTable[awCellIndex];
  lpBlockInProcess = dms_lCellTableRemoveExactBlock(ppTablePointer,awSectorIndex,awSectorBlockIndex);
  if (lpBlockInProcess == NULL) {
    /* the requested block must be in the cell in process */
    if (lwCellIndexOfCellInProcess != awCellIndex){
      return Block_Not_Found;
    }
    ppTablePointer = &lpCellInProcess;  /* ppTablePointer is used below to insert the new block into the correct table */
    lpBlockInProcess = dms_lCellTableRemoveExactBlock(ppTablePointer,awSectorIndex,awSectorBlockIndex);
    if (lpBlockInProcess == NULL) {
      return Block_Not_Found;
    }
  }
  lwCellIndexOfBlockInProcess = awCellIndex;

  /* Get New Block */
  pEntry = dms_BlockAllocNoMinimum();
  if (pEntry == NULL){
    return No_Available_Blocks;
  }
  pEntry->wBlockIndex = lpBlockInProcess->wBlockIndex;
  *apwNewSectorIndex = pEntry->wSectorIndex;
  *apwNewSectorBlockIndex = pEntry->wSectorBlockIndex;
  eStatus = dms_lCellTableInsertBlock(ppTablePointer,pEntry);
  if (eStatus != No_Error){
    free(pEntry);
    return eStatus;
  }
  /*
   * Do not call dms_BlockFree because the sector dirty block count was set to zero
   *   earlier when the best sector to erase was gotten.  calling dms_BlockFree
   *   will cause the sector dirty block count to increment.
   */
  free(lpBlockInProcess);
  lpBlockInProcess = NULL;

  return No_Error;

}

/**
 * dms_CellTableDeleteCellInProcess
 * Returns zero if CellInProcess is empty.
 * If there are blocks in CellInProcess then the first block in the cell
 *   is deleted from the list, added to the garbage count, apwSectorIndex and
 *   apwSectorBlockIndex are set so the caller can write the erase status in
 *   the flash.
 * This function should be called repeatly untill it returns 0 (all blocks
 *   are removed from the list)
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   dms_BlockFree()
 * Used By:
 *   dms_CellInitialize()

⌨️ 快捷键说明

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