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

📄 cell.c

📁 AMD公司官方版FLASH文件系统。有详细说明文档和Windows仿真测试环境。
💻 C
字号:
/**
 * Cell.c
 * 
 */

#include "Cell.h"
#include "CellTable.h"
#include "CellInfo.h"
#include "Block.h"
#include "BlockTable.h"
#include "Sector.h"
#include "SectorInfo.h"
#include "SectorHeader.h"
#include <malloc.h>
                       
extern SECTOR_DESCRIPTIOR gpDeviceArchitecture[];
                       
/**
 * dms_CellRead
 *
 * This function reads cell data from the Flash.  The location 
 *   that the data is stored is designated in apData.  apData 
 *   must be allocated before calling this function.  
 *
 * Arguments
 *   aiCellNumber    The cell number to read
 *   apData          The location to put the cell data
 *                     that is stored in the flash.
 * Prerequisites:
 *   dms_CellInitialize();
 * Uses:
 *   dms_CellTableResetBlockPointer()
 *   dms_CellTableGetNextBlock()
 *   dms_BlockRead()
 * Used By:
 *   dms_Read()
 */
DMS_STATUS dms_CellRead (WORD awCellIndex, BYTE *apData){
  DMS_STATUS eStatus;
  WORD wSectorIndex;
  WORD wSectorBlockIndex;
  WORD wBlockIndex;

  /*
   * Read each block.
   */
  wBlockIndex = 0;
  dms_CellTableResetBlockPointer(awCellIndex);
  while (dms_CellTableGetNextBlock(&wSectorIndex,&wSectorBlockIndex)){
    eStatus = dms_BlockRead(wSectorIndex,wSectorBlockIndex,apData+(((DWORD)sizeof(DATABLOCK))*((DWORD)wBlockIndex)));
    if (eStatus != No_Error){
      return eStatus;
    }
    wBlockIndex++;
  }

  return No_Error;
}

/**
 * dms_CellWrite
 *
 * Writes the apData to the flash in the defined cell.
 * The old cell data is destroyed when writing of the new
 *   cell has completed.
 * This function will not return to the calling program until the
 *   write completes. 
 * The Cell Write Process:
 *   Foreach block in existing cell
 *     write CellValid2 in cell status.
 *   Foreach block in cell
 *     Get new block.
 *     Write BlockBeingWritten in block status.
 *     Write cell number.
 *     Write block number.
 *     Write CellValid1 in cell status.
 *     Write block data.
 *     Write BlockValid in block status.
 *   Foreach old block in cell
 *     Write BlockErase in block status.
 *     Add block to garbage count.
 *
 * Arguments
 *   aiCellNumber    The cell number to write
 *   apData          The location containing the cell data
 *                     that is to be written to the flash.
 * Prerequisites:
 *   dms_CellInitialize();
 * Uses:
 *   dms_CellInfoGetBlockCount()
 *   dms_CellTableResetBlockPointer()
 *   dms_CellTableGetNextBlock()
 *   dms_CellTableSetCellInProcess()
 *   dms_CellTableGetAvailableBlock()
 *   dms_CellTableDeleteCellInProcess()
 *   dms_BlockWrite()
 *   dms_BlockTableWriteCellStatus()
 *   dms_BlockTableWriteBlockStatus()
 *   dms_SectorCleanup()
 * Used By:
 *   dms_Write()
 */
DMS_STATUS dms_CellWrite(WORD awCellIndex, BYTE *apData){
  DMS_STATUS eStatus;
  WORD wBlockIndex;
  WORD wSectorIndex;
  WORD wSectorBlockIndex;

  /*
   * Change cell status of each existing block in cell.
   */
  dms_CellTableResetBlockPointer(awCellIndex);
  while (dms_CellTableGetNextBlock(&wSectorIndex,&wSectorBlockIndex)){
    eStatus = dms_BlockTableWriteCellStatus(wSectorIndex,wSectorBlockIndex,CellValid2);
    if (eStatus != No_Error){
      return eStatus;
    }
  }

  /* dmsdbg_Printf("  Cell Start Write Of New\n"); */
  /* Move cell from cell table to cell in process */
  eStatus = dms_CellTableSetCellInProcess(awCellIndex);
  if (eStatus != No_Error){
    return eStatus;
  }

  /*
   * Get a new block and write the new data for each block in the cell.
   * It is better here to write the blocks in reverse order to allow
   *   efficient insertion of the block entries into the cell table.
   *   (Adding the block at the beginning of the list instead of having to
   *   traverse through all the blocks to insert at the end.)
   * The condition on the look cannot be wBlockIndex >= 0 because wBlockIndex
   *   is a WORD which is always positive therefore wBlockIndex + 1 != 0 is
   *   used.
   */
  wBlockIndex = dms_CellInfoGetBlockCount(awCellIndex);
  do {
    wBlockIndex--;  /* Pre-decrement */
    eStatus = dms_CellTableGetAvailableBlock(awCellIndex,wBlockIndex,&wSectorIndex,&wSectorBlockIndex);
    /* dmsdbg_Printf("  New Block: Status=%d\n",eStatus); */
    /* dmsdbg_Printf("  New Block: Cell=%d,  Block=%d,  Sector=%d,  SectorBlock=%d\n",awCellIndex,wBlockIndex,wSectorIndex,wSectorBlockIndex); */
    if (eStatus == No_Available_Blocks){
      /* perform a clean to free blocks */
      eStatus = dms_SectorCleanup();
      if (eStatus != No_Error) {
        return eStatus;
      }
      eStatus = dms_CellTableGetAvailableBlock(awCellIndex,wBlockIndex,&wSectorIndex,&wSectorBlockIndex);
      if (eStatus != No_Error) {
        /* something is wrong because a clean should at least clean one block. */
        return eStatus;
      }
    } else if (eStatus != No_Error) {
      return eStatus;
    }
    eStatus = dms_BlockWrite(awCellIndex,wBlockIndex,(BYTE)CellValid1,wSectorIndex,wSectorBlockIndex,
                             apData+(((DWORD)sizeof(DATABLOCK))*((DWORD)wBlockIndex)));
    if (eStatus != No_Error) {
      return eStatus;
    }
  } while (wBlockIndex != 0);

  /* Cleanup any cell that was in process one block at a time. */
  while (dms_CellTableDeleteCellInProcess(&wSectorIndex,&wSectorBlockIndex)){
    eStatus = dms_BlockTableWriteBlockStatus(wSectorIndex,wSectorBlockIndex,BlockErase);
    if (eStatus != No_Error) {
      return eStatus;
    }
  }
  return No_Error;
}

/**
 * dms_CellInitialize
 * Prepairs the DMS software to do Reads and Writes.
 *
 * Prerequisites:
 *   gpDeviceArchitecture must be defined.
 * Uses:
 *   dms_SectorInfoDefineArchitecture()
 *   dms_SectorInfoGetCount()
 *   dms_SectorInfoFinalize()
 *   dms_SectorHeaderGetCellCount()
 *   dms_CellTableInitialize()
 *   dms_CellTableCheckValidity()
 *   dms_CellTableDeleteBlockInProcess()
 *   dms_CellTableDeleteCellInProcess()
 *   dms_CellTableIsBlockAvailable()
 *   dms_CellTableFinalize()
 *   dms_BlockTableWriteBlockStatus()
 *   dms_SectorInitialize()
 *   dms_SectorCleanup()
 * Used By:
 *   dms_Initialize()
 */
DMS_STATUS dms_CellInitialize(void)
{
  DMS_STATUS eStatus;
  WORD wSectorIndex;
  WORD wSectorBlockIndex;
  WORD wCellCount;

  /* dmsdbg_Printf("CellInitialize\n"); */

  eStatus = dms_SectorInfoDefineArchitecture(gpDeviceArchitecture);
  if (eStatus != No_Error) {
    dms_SectorInfoFinalize();
    return eStatus;
  }

  eStatus = dms_SectorHeaderGetCellCount(&wCellCount);
  if (eStatus != No_Error) {
    dms_SectorInfoFinalize();
    return eStatus;
  }

  eStatus = dms_CellTableInitialize(wCellCount);
  if (eStatus != No_Error) {
    dms_SectorInfoFinalize();
    return eStatus;
  }

  for (wSectorIndex = 0; wSectorIndex < dms_SectorInfoGetCount(); wSectorIndex++){
    /* 
     * Reads block table of sector and adds blocks to cell table and
     *   block allocate list
     */
    eStatus = dms_SectorInitialize(wSectorIndex);
    if (eStatus != No_Error) {
      dms_CellTableFinalize();
      dms_SectorInfoFinalize();
      return eStatus;
    }
  }

  /*
   * Check that all the blocks are in each cell.  (Note: Cannot detect if
   *   the last block is missing because it uses the blocks that are found
   *   to determine the size of each cell.
   * Check for a partial cell that was in-process durring a power loss.
   */
  eStatus = dms_CellTableCheckValidity();
  if (eStatus != No_Error) {
    dms_CellTableFinalize();
    dms_SectorInfoFinalize();
    return eStatus;
  }

  /* Cleanup any block that was in process */
  if(dms_CellTableDeleteBlockInProcess(&wSectorIndex,&wSectorBlockIndex)){
    eStatus = dms_BlockTableWriteBlockStatus(wSectorIndex,wSectorBlockIndex,BlockErase);
    if (eStatus != No_Error) {
      dms_CellTableFinalize();
      dms_SectorInfoFinalize();
      return eStatus;
    }
  }

  /* Cleanup any cell that was in process one block at a time. */
  while (dms_CellTableDeleteCellInProcess(&wSectorIndex,&wSectorBlockIndex)){
    eStatus = dms_BlockTableWriteBlockStatus(wSectorIndex,wSectorBlockIndex,BlockErase);
    if (eStatus != No_Error) {
      dms_CellTableFinalize();
      dms_SectorInfoFinalize();
      return eStatus;
    }
  }
  /*
   * Everything is initialized and ok.
   * It is time to do some cleanups.
   * If power was lost durring a cleanup where there could be 
   *   many less available blocks than the allowable minimum.
   *   In which case it may take several ceanups to get above
   *   the allowable minimum.  A dmsWrite allows for only one 
   *   cleanup per block so it would fail if it took more than
   *   one cleanup to get above the minumum allowable available
   *   blocks.
   * By doing "SectorCount" number of cleanups it guarantees that
   *   all sectors will be clean and there will be the maximum
   *   amount of available blocks.
   * Stops doing cleanups when the number of free blocks is
   *   greater than the minimum allowable free block count or
   *   when no sectors are dirty.
   */
  for (wSectorIndex = 0; wSectorIndex < dms_SectorInfoGetCount(); wSectorIndex++){
    /* 
     *  do a sector cleanup
     */
    if (dms_CellTableIsBlockAvailable()){
      /*
       * Done enough cleanup for now.
       */
      break;
    }
    eStatus = dms_SectorCleanup();
    if (eStatus == No_Garbage_Blocks){
      /*
       * All Sectors are clean.
       * break out of for loop.
       */
      break;
    } else if (eStatus != No_Error) {
      dms_CellTableFinalize();
      dms_SectorInfoFinalize();
      return eStatus;
    } 
  }
  
  /*
   * Ready to read and write.
   */
  return No_Error;
}


/**
 * dms_CellFormat
 *
 * Upon completion of dms_CellFormat() the DMS software is
 *   completely shutdown.
 *
 * If dms_CellFormat returns anything other than No_Error then
 *   the flash must be reformated.
 *
 * Arguments
 *   aCellSize           Array of DWORDS that contains the size, 
 *                       in bytes, of each cell.  The array index
 *                       is the Cell number and the value in the
 *                       index is the size of the cell. 
 *   awCellCount         The number of elements in the array.
 * Prerequisites:
 *   gpDeviceArchitecture must be defined.
 * Uses:
 *   dms_SectorInfoDefineArchitecture()
 *   dms_SectorInfoGetBlockCount()
 *   dms_SectorInfoGetCount()
 *   dms_SectorInfoFinalize()
 *   dms_SectorFormatAll()
 *   dms_CellInfoDefineCellList()
 *   dms_CellInfoGetCount()
 *   dms_CellInfoGetBlockCount()
 *   dms_CellInfoFinalize()
 *   dms_BlockWrite()
 *   malloc()
 *   free()
 * Used By:
 *   dms_Format()
 */
DMS_STATUS dms_CellFormat (DWORD *apdwCellSize, WORD awCellCount)
{
    DMS_STATUS eStatus;
    WORD wSectorIndex;
    WORD wSectorBlockCount;
    WORD wCellIndex;
    WORD wBlockIndex;
    WORD wIndex;
    BYTE *bEmptyData;
                            
    /* dmsdbg_Printf("CellFormat\n"); */

    eStatus = dms_SectorInfoDefineArchitecture(gpDeviceArchitecture);
    if (eStatus != No_Error) {
      return eStatus;
    }

    eStatus = dms_CellInfoDefineCellList(apdwCellSize, awCellCount);
    if (eStatus != No_Error) {
      dms_SectorInfoFinalize();
      return eStatus;
    }

    /* erase sectors and write header information */
    eStatus = dms_SectorFormatAll(dms_CellInfoGetCount());
    if (eStatus != No_Error) {
      dms_CellInfoFinalize();
      dms_SectorInfoFinalize();
      return eStatus;
    }
   
    /* Create empty data to fill each new block with */
    bEmptyData = (BYTE*) malloc(sizeof(DATABLOCK));
    if (bEmptyData == NULL){
      dms_CellInfoFinalize();
      dms_SectorInfoFinalize();
      return Out_Of_Memory_Error;
    }
    /* Initialize data to 0 */
    for (wIndex = 0; wIndex < sizeof(DATABLOCK); wIndex++) bEmptyData[wIndex] = 0;
   
    /* Write each block of each cell into sector block table */
    wSectorIndex = 0;
    wSectorBlockCount = 0;
    for (wCellIndex = 0; wCellIndex < dms_CellInfoGetCount(); wCellIndex++){
      for (wBlockIndex = 0; wBlockIndex < dms_CellInfoGetBlockCount(wCellIndex); wBlockIndex++){
        if (wSectorBlockCount >= dms_SectorInfoGetBlockCount(wSectorIndex)){
          /* Increment through sectors as needed */
          wSectorIndex++;
          wSectorBlockCount = 0;
          if (wSectorIndex >= dms_SectorInfoGetCount()){
            free(bEmptyData);
            dms_CellInfoFinalize();
            dms_SectorInfoFinalize();
            return Total_Cell_Size_Too_Large;
          }
        }
        eStatus = dms_BlockWrite(wCellIndex,wBlockIndex,(BYTE)CellValid1,wSectorIndex,wSectorBlockCount,bEmptyData);
        if (eStatus != No_Error) {
          free(bEmptyData);
          dms_CellInfoFinalize();
          dms_SectorInfoFinalize();
          return eStatus;
        }
        wSectorBlockCount++;  
	  }
    }
    /* leave format with everything shut down */
    free(bEmptyData);
    dms_CellInfoFinalize();
    dms_SectorInfoFinalize();
    return No_Error;
}


/**
 * dms_CellFinalize
 * Frees all dynamic memory used by the dms software.
 * After this function is called then dms_CellInitialize()
 *   must be called to use dms again.
 * Prerequisites:
 *   None.
 * Uses:
 *   dms_CellTableFinalize()
 *   dms_SectorInfoFinalize()
 * Used By:
 *   dms_Shutdown()
 */
void dms_CellFinalize(void)
{
  dms_CellTableFinalize();
  dms_SectorInfoFinalize();
}

⌨️ 快捷键说明

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