📄 fal.cpp
字号:
//----- 5. Initialize and start the compactor -----
if(!m_pCompactor->Init (pRegion, this))
{
ReportError((TEXT("FLASHDRV.DLL:StartupFAL() - Unable to initialize the compactor!!!\r\n")));
return FALSE;
}
return Fal::StartupFAL(pRegion);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: ShutdownFAL()
Description: Shuts down the FLASH Abstraction Layer (FAL)
Notes: The logical --> physical mapper and sector manager
are appropriately deinitialized. Note that the caller
is responsible for deinitializing the FMD.
Returns: Boolean indicating success.
-------------------------------------------------------------------*/
BOOL FileSysFal::ShutdownFAL()
{
if(!m_pCompactor->Deinit())
{
ReportError((TEXT("FLASHDRV.DLL:ShutdownFAL() - Unable to deinitialize the Compactor\r\n")));
}
return Fal::ShutdownFAL();
}
BOOL FileSysFal::BuildupMappingInfo()
{
DWORD i = 0;
DWORD dwBlockID = 0;
DWORD dwPhysSector = m_dwStartPhysSector;
DWORD dwLogSector = m_dwStartLogSector;
DWORD dwExistingPhysSector = 0;
SectorMappingInfo sectorMappingInfo;
DWORD counts[10];
memset(counts,0,sizeof(counts));
DEBUGMSG(1, (TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Enter. \r\n"), dwBlockID));
RETAILMSG(1,(TEXT("Initialize the FAL BuildupMappingInfo start:%d\r\n"),GetTickCount() ));
//----- 1. Read the entire media to determine the status of all sectors -----
for (dwBlockID = m_pRegion->dwStartPhysBlock; dwBlockID < m_pRegion->dwStartPhysBlock + m_pRegion->dwNumPhysBlocks; dwBlockID++)
{
//----- 2. What is the status of this block? -----
DWORD dwStatus = FMD.pGetBlockStatus (dwBlockID);
if (dwStatus & (BLOCK_STATUS_BAD | BLOCK_STATUS_RESERVED))
{
counts[0]++;
if(!m_pSectorMgr->MarkBlockUnusable(dwBlockID))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - SectorMgr::MarkBlockUnusable(%d) failed. \r\n"), dwBlockID));
}
dwPhysSector += m_pRegion->dwSectorsPerBlock; // Move to first sector in next block
continue;
}
//----- 4. Read the sector information stored on the physical media for each sector -----
for(i=0; i<(m_pRegion->dwSectorsPerBlock); i++, dwPhysSector++)
{
counts[1]++;
//----- Notice that SectorMappingInfo is cast to SectorInfo. SectorInfo is the public -----
// definition of the private structure SectorMappingInfo. Consequently, any
// changes to the SectorMappingInfo structure will require the SectorInfo
// structure's size be updated accordingly.
if(!FMD.pReadSector(dwPhysSector, NULL, (PSectorInfo)§orMappingInfo, 1))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to read sector information for sector %d\r\n"), dwPhysSector));
goto INIT_ERROR;
}
/* ctg -- start */
if (IsSecureWipeInProgress(sectorMappingInfo))
{
SecureWipe();
MarkSectorFree(sectorMappingInfo);
}
/* ctg -- stop */
//----- 5. Free sector? If so, add it to the "free sector list" the Sector Manager uses -----
// NOTE: Notice that we ONLY mark this sector as FREE if it is in a valid block.
if(IsSectorFree(sectorMappingInfo))
{
counts[2]++;
// OPTIMIZATION: Because the compactor always adds whole blocks of FREE sectors to the
// Sector Manager, we know that if the first sector in a block is FREE then
// all other sectors in this block are also FREE. Consequently, when the first
// sector in a block is FREE we don't have to read the other sectors in the block.
if(i == 0)
{
if(!m_pSectorMgr->AddSectorsToList(SectorMgr::Free, dwPhysSector, m_pRegion->dwSectorsPerBlock))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to mark sector %x as free.\r\n"), dwPhysSector));
}
dwPhysSector += m_pRegion->dwSectorsPerBlock;
break;
}
// The whole block isn't FREE; add just this sector to the Sector Manager's FREE list...
if(!m_pSectorMgr->AddSectorsToList(SectorMgr::Free, dwPhysSector, 1))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to mark sector %x as free.\r\n"), dwPhysSector));
}
continue;
}
//----- 6. DIRTY sector? If so, inform the Sector Manager... -----
if(IsSectorDirty(sectorMappingInfo))
{
counts[3]++;
if(!m_pSectorMgr->MarkSectorsAsDirty(dwPhysSector, 1))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to mark sector %x as dirty.\r\n"), dwPhysSector));
}
continue;
}
//----- 7. Mapped sector? If so, use logical --> sector mapper to create a mapping -----
if(IsSectorMapped(sectorMappingInfo))
{
counts[4]++;
// First sector in a block must be marked RO to indicate all sectors in the block are RO.
if ((dwStatus & BLOCK_STATUS_READONLY) && (i == 0))
{
DWORD iSector;
counts[7]++;
if(!m_pSectorMgr->AddSectorsToList(SectorMgr::ReadOnly, sectorMappingInfo.logicalSectorAddr, m_pRegion->dwSectorsPerBlock))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to mark sector %x as read only.\r\n"), dwPhysSector));
}
for (iSector = 0; iSector < m_pRegion->dwSectorsPerBlock; iSector++)
{
if(!m_pMap->MapLogicalSector(sectorMappingInfo.logicalSectorAddr + iSector, dwPhysSector + iSector, &dwExistingPhysSector))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to map logical sector 0x%08x to physical sector 0x%08x\r\n"),
sectorMappingInfo.logicalSectorAddr + iSector, dwPhysSector + iSector));
}
}
dwPhysSector += m_pRegion->dwSectorsPerBlock;
break;
}
if(!m_pMap->MapLogicalSector(sectorMappingInfo.logicalSectorAddr, dwPhysSector, &dwExistingPhysSector))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to map logical sector 0x%08x to physical sector 0x%08x\r\n"),
sectorMappingInfo.logicalSectorAddr, dwPhysSector));
}
// SPECIAL CASE: It is possible that a power-failure occured just after the contents of a MAPPED
// logical sector were updated but BEFORE the old data was marked DIRTY. This situation
// can be detected if (dwExistingPhysSector != UNMAPPED_LOGICAL_SECTOR). To fix
// this case, we should keep the latest logical --> physical mapping information and
// mark the data in the dwExistingPhysSector as DIRTY.
if ((dwExistingPhysSector != UNMAPPED_LOGICAL_SECTOR) && !m_fReadOnly)
{
counts[5]++;
DEBUGMSG(ZONE_WRITE_OPS,(TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Power failure during the last WRITE operation is detected, \
insuring data integrity for logical sector %08x\r\n"), sectorMappingInfo.logicalSectorAddr));
// NOTE: Since we don't know the contents of the sector mapping info for this physical sector,
// we can safely write all '1's (except the bit used to indicate the sector is "dirty").
memset(§orMappingInfo, 0xFF, sizeof(SectorMappingInfo));
MarkSectorDirty(sectorMappingInfo);
if(!FMD.pWriteSector(dwExistingPhysSector, NULL, (PSectorInfo)§orMappingInfo, 1))
{
counts[6]++;
DEBUGMSG(ZONE_WRITE_OPS,(TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to mark old physical sector 0x%08x as DIRTY! Calling HandleWriteFailure()\r\n"),
dwExistingPhysSector));
// WRITE operation failed, try to recover...
if(!HandleWriteFailure(dwExistingPhysSector))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - Unable to handle the WRITE failure to sector 0x%08x\r\n"), dwPhysSector));
goto INIT_ERROR;
}
}
// Inform the Sector Manager that this sector is DIRTY...
if(!m_pSectorMgr->MarkSectorsAsDirty(dwExistingPhysSector, 1))
{
ReportError((TEXT("FLASHDRV.DLL:BuildupMappingInfo() - FATAL_ERROR: SM_MarkSectorsAsDirty(0x%08x) failed!\r\n"), dwExistingPhysSector));
goto INIT_ERROR;
}
}
}
}
}
RETAILMSG(1,(TEXT("Initialize the FAL BuildupMappingInfo stop:%d\r\n"),GetTickCount() ));
RETAILMSG(1,(TEXT("counts(9876543210): %d %d %d %d %d %d %d %d %d %d\r\n"),
counts[9], counts[8], counts[7], counts[6], counts[5],
counts[4], counts[3], counts[2], counts[1], counts[0] ));
return TRUE;
INIT_ERROR:
return FALSE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: InternalWriteToMedia()
Description: Performs the specified scatter/gather WRITE request to the media.
Notes: After parsing the parameters, the actual WRITE request is handled
by the FLASH Media Driver (FMD).
Returns: Boolean indicating success.
-------------------------------------------------------------------------------*/
DWORD FileSysFal::InternalWriteToMedia(DWORD dwStartSector, DWORD dwNumSectors, LPBYTE pBuffer)
{
DWORD dwSGBuffNum = 0;
DWORD dwSGBuffPos = 0;
DWORD dwSectorAddr = 0;
SECTOR_ADDR physicalSectorAddr = 0;
SECTOR_ADDR existingPhysicalSectorAddr = 0;
SectorMappingInfo sectorMappingInfo;
DWORD dwError = ERROR_GEN_FAILURE;
for(dwSectorAddr = dwStartSector; dwSectorAddr < (dwStartSector + dwNumSectors); dwSectorAddr++)
{
//----- 2. Write the sector data to disk. Notice that this operation is repetitively -----
// tried ONLY if FMD_WriteSector() fails. Unless the FLASH block we are writing to
// has just gone bad, this loop will only execute once.
for(;;)
{
//----- 3. Get a free physical sector to store the data into. If this call FAILS, the WRITE -----
// cannot succeed because the media is full.
if(!m_pSectorMgr->GetNextFreeSector(&physicalSectorAddr, FALSE))
{
ReportError((TEXT("FLASHDRV.DLL:WriteToMedia() - Unable to get next free physical sector address for writing! The media is full...\r\n")));
dwError = ERROR_DISK_FULL;
goto WRITE_ERROR;
}
//----- For debugging purposes, print out the logical --> physical mapping... -----
DEBUGMSG(ZONE_WRITE_OPS, (TEXT("FLASHDRV.DLL:WriteToMedia() - logicalSector 0x%08x --> physicalSector 0x%08x\r\n"), dwSectorAddr, physicalSectorAddr));
//----- 4. Start the write operation (used to safeguard against power failure conditions) -----
// The rationale is as follows: If we lose power during before the data is written
// to the media, this bit should be set and this will allow us to detect that a
// WRITE was in progress when the power failed.
memset(§orMappingInfo, 0xFF, sizeof(SectorMappingInfo));
sectorMappingInfo.logicalSectorAddr = dwSectorAddr;
MarkSectorWriteInProgress(sectorMappingInfo);
if(!FMD.pWriteSector(physicalSectorAddr, NULL, (PSectorInfo)§orMappingInfo, 1))
{
DEBUGMSG(ZONE_WRITE_OPS, (TEXT("FLASHDRV.DLL:WriteToMedia() - Unable to start WRITE operation. Calling HandleWriteFailure()\r\n")));
// WRITE operation failed, try to recover...
if(!HandleWriteFailure(physicalSectorAddr))
{
ReportError((TEXT("FLASHDRV.DLL:WriteToMedia() - Unable to handle the WRITE failure to sector 0x%08x\r\n"), physicalSectorAddr));
goto WRITE_ERROR;
}
continue; // Try the WRITE at another physical sector...
}
//----- 5. Invoke the FLASH Media Driver (FMD) to write the sector data to the media -----
// NOTE: The write will be marked as "completed" if FMD_WriteSector() succeeeds
//
// NOTE: Currently, only one sector is written at a time (last parameter)
MarkSectorWriteCompleted(sectorMappingInfo);
if(!FMD.pWriteSector(physicalSectorAddr, (pBuffer+dwSGBuffPos), (PSectorInfo)§orMappingInfo, 1))
{
DEBUGMSG(ZONE_WRITE_OPS,(TEXT("FLASHDRV.DLL:WriteToMedia() - Unable to write to physical sector 0x%08x! Calling HandleWriteFailure()\r\n"),
physicalSectorAddr));
// WRITE operation failed, try to recover...
if(!HandleWriteFailure(physicalSectorAddr))
{
ReportError((TEXT("FLASHDRV.DLL:WriteToMedia() - Unable to handle the WRITE failure to sector 0x%08x\r\n"), physicalSectorAddr));
goto WRITE_ERROR;
}
continue; // Try the WRITE at another physical sector...
}
//----- 6. Perform the LOGICAL -> PHYSICAL mapping... -----
if(!m_pMap->MapLogicalSector(dwSectorAddr, physicalSectorAddr, &existingPhysicalSectorAddr))
{
ReportError((TEXT("FLASHDRV.DLL:WriteToMedia() = FATAL_ERROR: Unable to map logical sector 0x%08x to physical sector 0x%08x\r\n"),
dwSectorAddr, physicalSectorAddr));
goto WRITE_ERROR;
}
//----- 7. If this logical sector was already mapped, mark the "stale data" in the existing -----
// physical sector as "dirty."
if(existingPhysicalSectorAddr != UNMAPPED_LOGICAL_SECTOR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -