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

📄 celltable.c

📁 AMD公司官方版FLASH文件系统。有详细说明文档和Windows仿真测试环境。
💻 C
📖 第 1 页 / 共 3 页
字号:
 *   dms_CellWrite()
 */
WORD dms_CellTableDeleteCellInProcess(WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
  CELL_TABLE_ENTRY *pTmpEntry;
  if (lpCellInProcess == NULL){
    return 0;
  }
  pTmpEntry = lpCellInProcess;
  lpCellInProcess = lpCellInProcess->pNext;
  pTmpEntry->pNext = NULL;
  *apwSectorIndex = pTmpEntry->wSectorIndex;
  *apwSectorBlockIndex = pTmpEntry->wSectorBlockIndex;
  dms_BlockFree(pTmpEntry);
  return 1;
}

/**
 * dms_CellTableDeleteBlockInProcess
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   dms_BlockFree()
 * Used By:
 *   dms_CellInitialize()
 */
WORD dms_CellTableDeleteBlockInProcess(WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
  if (lpBlockInProcess == NULL){
    return 0;
  }
  *apwSectorIndex = lpBlockInProcess->wSectorIndex;
  *apwSectorBlockIndex = lpBlockInProcess->wSectorBlockIndex;
  dms_BlockFree(lpBlockInProcess);
  lpBlockInProcess = NULL;
  return 1;
}

/**
 * dms_CellTableResetBlockPointer
 * Sets an internal pointer to the first block of the
 *   given cell in the cell table.
 * This function allows dms_CellTableGetNextBlock to be 
 *   called repeatly to get info about each block in the cell.
 * One use for this function is to be called by a read operation.
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   Nothing outside this file.
 * Used By:
 *   dms_CellWrite()
 *   dms_CellRead()
 */
void dms_CellTableResetBlockPointer(WORD awCellIndex){
  lpCurrentBlockPointer = lpCellTable[awCellIndex];
}

/**
 * dms_CellTableGetNextBlock
 * Assigns apwSectorIndex and apwSectorBlockIndex to the values of the current
 *   block in the list then returns 1.
 * Otherwise if the end of the list is reached then returns 0.
 *
 * Prerequisites:
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 * Uses:
 *   Nothing outside this file.
 * Used By:
 *   dms_CellWrite()
 *   dms_CellRead()
 */
WORD dms_CellTableGetNextBlock(WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
  if (lpCurrentBlockPointer == NULL) {
    return 0;
  }
  *apwSectorIndex = lpCurrentBlockPointer->wSectorIndex;
  *apwSectorBlockIndex = lpCurrentBlockPointer->wSectorBlockIndex;
  lpCurrentBlockPointer = lpCurrentBlockPointer->pNext;
  return 1;
}

/**
 * dms_lCellTableCheckCellInProcess
 * Called after all Blocks are added to table.
 * Checks the CellInProcess list and compares it with the cell in the cell table
 *   and determines which one needs deleted.
 * Checks the BlockInProcess and compares it with the block in the cell table and
 *   determines which one needs deleted.
 */
void dms_lCellTableCheckCellInProcess(void){
  DMS_STATUS eStatus1;
  DMS_STATUS eStatus2;
  CELL_TABLE_ENTRY *pTmpList1;
  CELL_TABLE_ENTRY *pTmpList2;
  CELL_TABLE_ENTRY *pTmpEntry;
  WORD wBlockCount1 = 0;
  WORD wBlockCount2 = 0;

  if (lpBlockInProcess != NULL){
    /*
     * There is a block that was in process when a power failure occured.
     * As of now the only time a block is in process is during a move
     *   of that block.  In this case the blocks are identical so either
     *   one can be deleted.
     * Leave the block in the BlockInProcess and it will be deleted later when
     *   dms_CellTableDeleteBlockInProcess() is called.
     *   the extra one.
     */    
  }

  if (lpCellInProcess == NULL){
    /*
     * There was no cell in process. 
     * Then nothing else to check here.
     */
    return;
  }
  
  /*
   * Sort the lpBlockInProcess list and the lpCellTable[lwCellIndexOfCellInProcess]
   *   list so that one list has all CellValid1 and the other has CellValid2 because
   *   dms_CellTableAddBlock may mix them up.
   */
  /* Move tables to a temp table. */
  pTmpList1 = lpCellTable[lwCellIndexOfCellInProcess];
  pTmpList2 = lpCellInProcess;
  lpCellTable[lwCellIndexOfCellInProcess] = NULL;
  lpCellInProcess = NULL;

  /*
   * Remove blocks from the temp lists and insert them into the apporiate list.
   * Put CellValid2 blocks in the CellTable and CellValid1 blocks in the CellInProcess.
   * At this point it does not matter which ones go where but the odds are that the
   *   CellValid1 blocks are incomplete.  Later a complete check will be done to
   *   determine which cell is a keeper.
   */
  while (pTmpList1 != NULL){
    /* remove first entry from the temp list */
    pTmpEntry = pTmpList1;
    pTmpList1 = pTmpList1->pNext;
    pTmpEntry->pNext = NULL;
    if (pTmpEntry->bCellStatus == CellValid1) {
      dms_lCellTableInsertBlock(&lpCellInProcess,pTmpEntry);
    } else {  
      /* must be CellValid2 */
      dms_lCellTableInsertBlock(&lpCellTable[lwCellIndexOfCellInProcess],pTmpEntry);
    }   
  }
  while (pTmpList2 != NULL){
    /* remove first entry from the temp list */
    pTmpEntry = pTmpList2;
    pTmpList2 = pTmpList2->pNext;
    pTmpEntry->pNext = NULL;
    if (pTmpEntry->bCellStatus == CellValid1) {
      dms_lCellTableInsertBlock(&lpCellInProcess,pTmpEntry);
    } else {  
      /* must be CellValid2 */
      dms_lCellTableInsertBlock(&lpCellTable[lwCellIndexOfCellInProcess],pTmpEntry);
    }   
  }
  

  /* Count the blocks and check for missing blocks */
  eStatus1 = dms_lCellTableCountAndCheckBlocks(lpCellInProcess, &wBlockCount1);
  eStatus2 = dms_lCellTableCountAndCheckBlocks(lpCellTable[lwCellIndexOfCellInProcess], &wBlockCount2);
  /* Determine which version of the cell to keep */
  if (   eStatus1 == No_Error && eStatus2 != No_Error
      || eStatus1 == No_Error && wBlockCount1 > wBlockCount2
      || eStatus1 == No_Error && eStatus2 == No_Error && wBlockCount1 == wBlockCount2 
         && lpCellInProcess->bCellStatus == CellValid2){  /* Note lpCellInProcess was already checked to be NULL */
    /* 
     * Keep the cell in process
     * Swap lpCellInProcess and lpCellTable[lwCellIndexOfCellInProcess]
     * Leave the unwanted cell in the CellInProcess and it will be deleted later when
     *   dms_CellTableDeleteCellInProcess() is called.
     */
    pTmpList1 = lpCellTable[lwCellIndexOfCellInProcess];
    lpCellTable[lwCellIndexOfCellInProcess] = lpCellInProcess;
    lpCellInProcess = pTmpList1;
  } else {
    /*
     * Delete cell in process.
     * Keep the lists the way they are.
     * Leave the unwanted cell in the CellInProcess and it will be deleted later when
     *   dms_CellTableDeleteCellInProcess() is called.
     * Note: If CellTable cell is also not valid go ahead and set 
     *   CellInProcess to be erased and let the bad cell 
     *   be caught later by dms_CellTableCheckValidity.
     */
  }
  return;
}

/**
 * dms_lCellTableCreateNewEntry
 */
CELL_TABLE_ENTRY *dms_lCellTableCreateNewEntry(WORD awBlockIndex,
                                               BYTE abCellStatus,
                                               WORD awSectorIndex,
                                               WORD awSectorBlockIndex){
  CELL_TABLE_ENTRY *pTmpEntry;
  pTmpEntry = (CELL_TABLE_ENTRY*) malloc(sizeof(CELL_TABLE_ENTRY));
  if (pTmpEntry != NULL){
    pTmpEntry->bCellStatus = abCellStatus;
    pTmpEntry->wBlockIndex = awBlockIndex;
    pTmpEntry->wSectorIndex = awSectorIndex;
    pTmpEntry->wSectorBlockIndex = awSectorBlockIndex;
    pTmpEntry->pNext = NULL;
  }
  return pTmpEntry;
}

/**
 * dms_lCellTableRemoveBlock
 * Local Function.
 * Traverses through the list and removes the entry whose wBlockIndex matches the 
 *   provided awBlockIndex and returns a pointer to the removed entry.
 * Returns NULL is entry is not found.
 */
CELL_TABLE_ENTRY *dms_lCellTableRemoveBlock(CELL_TABLE_ENTRY **appCell, WORD awBlockIndex){
  CELL_TABLE_ENTRY *pReturnEntry;
  while (*appCell != NULL){
    if ((*appCell)->wBlockIndex == awBlockIndex){
      pReturnEntry = (*appCell);
      (*appCell) = (*appCell)->pNext;
      pReturnEntry->pNext = NULL;
      return pReturnEntry;
    }
    appCell = &((*appCell)->pNext);
  }
  return NULL;
}

/**
 * dms_lCellTableRemoveExactBlock
 * Local Function.
 * Traverses through the list and removes the entry whose SectorIndex
 *   and SectorBlockIndex matches the provided and returns a pointer
 *   to the removed entry.
 * Returns NULL is entry is not found.
 */
CELL_TABLE_ENTRY *dms_lCellTableRemoveExactBlock(CELL_TABLE_ENTRY **appCell, 
                                                 WORD awSectorIndex, 
                                                 WORD awSectorBlockIndex){
  CELL_TABLE_ENTRY *pReturnEntry;
  while (*appCell != NULL){
    if ((*appCell)->wSectorIndex == awSectorIndex && (*appCell)->wSectorBlockIndex == awSectorBlockIndex){
      pReturnEntry = (*appCell);
      (*appCell) = (*appCell)->pNext;
      pReturnEntry->pNext = NULL;
      return pReturnEntry;
    }
    appCell = &((*appCell)->pNext);
  }
  return NULL;
}

/**
 * dms_lCellTableInsertBlock
 * Local Function.
 * Traverses through the list and inserts entry in order of assending block index.
 * Does not allow duplicate blocks. 
 * Returns Duplicate_Block if aNewEntry is a duplicate.
 * Note: If function fails then remember to free pNewEntry.
 * Note: Used by dms_CellTableAddBlock() and assumes returns Duplicate_Block,
 *   Exact_Duplicate_Block, or No_Error only.
 */ 
DMS_STATUS dms_lCellTableInsertBlock(CELL_TABLE_ENTRY **appCell,CELL_TABLE_ENTRY *pNewEntry){

  while (*appCell != NULL && (*appCell)->wBlockIndex < pNewEntry->wBlockIndex){
    appCell = &((*appCell)->pNext);
  }
  if (*appCell != NULL && (*appCell)->wBlockIndex == pNewEntry->wBlockIndex){
    if ((*appCell)->bCellStatus == pNewEntry->bCellStatus){
      return Exact_Duplicate_Block;
    } else {
      return Duplicate_Block;
    }
  }
  pNewEntry->pNext = (*appCell);
  (*appCell) = pNewEntry;
  return No_Error;
}

/**
 * dms_lCellTableCountAndCheckBlocks
 * Local Function.
 * Traverses through the list, counts the blocks, and makes sure that none are missing.
 * Note:  Because the cell size is determined by the blocks found if the last block is 
 *   missing there is no way to detect it.
 */
DMS_STATUS dms_lCellTableCountAndCheckBlocks(CELL_TABLE_ENTRY *apCellTable, WORD *apwBlockCount){
  *apwBlockCount = 0;
  while (apCellTable != NULL){
    if (apCellTable->wBlockIndex != *apwBlockCount) {
      return Missing_Block_In_Cell;
    }
   (*apwBlockCount)++;
   apCellTable = apCellTable->pNext;
  }
  return No_Error;
}

⌨️ 快捷键说明

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