?? disk.c
字號:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
disk.c
Abstract:
This file contains routines for mounting and accessing disks.
Revision History:
--*/
#include "fatfs.h"
#if defined(UNDER_WIN95) && !defined(INCLUDE_FATFS)
#include <pcmd.h> // for interacting with ReadWriteDisk()
#endif
#ifdef DEBUG
extern DWORD csecWrite, creqWrite;
#endif
DWORD GetDiskInfo(HANDLE hdsk, PDISK_INFO pdi)
{
DWORD cb;
if (FSDMGR_DiskIoControl((HDSK)hdsk,
IOCTL_DISK_GETINFO,
NULL, 0,
pdi, sizeof(*pdi),
&cb, NULL)) {
pdi->di_flags |= DISK_INFO_FLAGS_FATFS_NEW_IOCTLS;
}
else
if (FSDMGR_DiskIoControl((HDSK)hdsk,
DISK_IOCTL_GETINFO,
pdi, sizeof(*pdi),
NULL, 0,
&cb, NULL)) {
// Make sure our private flags are never set by the driver
DEBUGMSG((pdi->di_flags & DISK_INFO_FLAGS_FATFS_NEW_IOCTLS),(DBGTEXT("FATFS!GetDiskInfo: driver is setting reserved bit(s)!\r\n")));
pdi->di_flags &= ~DISK_INFO_FLAGS_FATFS_NEW_IOCTLS;
}
else {
DWORD status = GetLastError();
DEBUGMSG(ZONE_DISKIO || ZONE_ERRORS,
(DBGTEXT("FATFS!GetDiskInfo: DISK_IOCTL_GETINFO failed %d\r\n"), status));
return status;
}
DEBUGMSG(ZONE_DISKIO,
(DBGTEXT("FATFS!GetDiskInfo: DISK_IOCTL_GETINFO returned %d bytes\r\n"), cb));
DEBUGMSG(ZONE_DISKIO,
(DBGTEXT("FATFS!GetDiskInfo: Sectors=%d (0x%08x), BPS=%d, CHS=%d:%d:%d\r\n"),
pdi->di_total_sectors, pdi->di_total_sectors, pdi->di_bytes_per_sect, pdi->di_cylinders, pdi->di_heads, pdi->di_sectors));
return ERROR_SUCCESS;
}
DWORD SetDiskInfo(HANDLE hdsk, PDISK_INFO pdi)
{
DWORD cb;
DWORD status = ERROR_SUCCESS;
if (!(pdi->di_flags & DISK_INFO_FLAGS_FATFS_SIMULATED)) {
if (FSDMGR_DiskIoControl((HDSK)hdsk,
(pdi->di_flags & DISK_INFO_FLAGS_FATFS_NEW_IOCTLS)? IOCTL_DISK_SETINFO : DISK_IOCTL_SETINFO,
pdi, sizeof(*pdi),
NULL, 0,
&cb, NULL) == FALSE) {
status = GetLastError();
DEBUGMSG(ZONE_DISKIO || ZONE_ERRORS,
(DBGTEXT("FATFS!SetDiskInfo: DISK_IOCTL_SETINFO failed %d\r\n"), status));
}
else {
DEBUGMSG(ZONE_DISKIO,
(DBGTEXT("FATFS!SetDiskInfo: DISK_IOCTL_SETINFO returned %d bytes\r\n"), cb));
DEBUGMSG(ZONE_DISKIO,
(DBGTEXT("FATFS!SetDiskInfo: Sectors=%d (0x%08x), BPS=%d, CHS=%d:%d:%d\r\n"),
pdi->di_total_sectors, pdi->di_total_sectors, pdi->di_bytes_per_sect, pdi->di_cylinders, pdi->di_heads, pdi->di_sectors));
}
}
return status;
}
#if 0
DWORD NearestPwr2(unsigned int n)
{
DWORD l=1;
while((l << 1) <= n) {
l = l << 1;
}
return l;
}
#endif
void SetupDiskCache(PVOLUME pvol)
{
DWORD dwFlags = 0;
DWORD dwCacheSize = 0, dwDataCacheSize = 0, dwFatCacheSize = 0;
BOOL fEnableCache = FALSE, fFatWarm = FALSE, fDataWarm = FALSE;
BOOL fWriteBack = FALSE;
DWORD dwStartFatCache;
DWORD dwLen = sizeof(DWORD);
if (!FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"EnableCache", &fEnableCache)) {
fEnableCache = FALSE;
}
if (!FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"CacheSize", &dwCacheSize)) {
dwCacheSize = -1;
}
// Keep setting dwCacheSize = -1 as option for disabling cache for backwards compatibility.
if (!fEnableCache || dwCacheSize == -1) {
pvol->v_FATCacheId = INVALID_CACHE_ID;
pvol->v_DataCacheId = INVALID_CACHE_ID;
return;
}
FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"EnableFatCacheWarm", &fFatWarm);
FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"EnableDataCacheWarm", &fDataWarm);
if (!fFatWarm) {
// Allow EnableCacheWarm to also be used to warm FAT cache for backwards compatibility
FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"EnableCacheWarm", &fFatWarm);
}
FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"FatCacheSize", &dwFatCacheSize);
FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"DataCacheSize", &dwDataCacheSize);
FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"EnableWriteBack", &fWriteBack);
if (!dwFatCacheSize) {
// If the FAT cache size was set to 0, use the size of the FAT, up to 512 sectors.
dwFatCacheSize = min( 512, pvol->v_csecFAT);
}
if (!dwDataCacheSize) {
if (dwCacheSize) {
// For backwards compatibility, still honor CacheSize reg setting
dwDataCacheSize = dwCacheSize;
} else {
dwDataCacheSize = min (1024, 2 * pvol->v_csecFAT);
}
}
// Set up the FAT cache flags
if (fFatWarm) {
dwFlags |= CACHE_FLAG_WARM;
}
if (fWriteBack) {
dwFlags |= CACHE_FLAG_WRITEBACK;
}
// Set up the FAT cache.
dwStartFatCache = pvol->v_secBlkBias;
#ifdef TFAT
// For TFAT, only cache FAT1. FAT0 will be uncached to ensure transactions
// are committed properly.
if (pvol->v_fTfat)
dwStartFatCache += pvol->v_csecFAT;
#endif
pvol->v_FATCacheId = FSDMGR_CreateCache ((HDSK)pvol->v_pdsk->d_hdsk, dwStartFatCache, pvol->v_secBlkBias + pvol->v_secEndAllFATs - 1,
dwFatCacheSize, pvol->v_pdsk->d_diActive.di_bytes_per_sect, dwFlags);
// Set up the data cache flags
dwFlags = 0;
if (fDataWarm) {
dwFlags |= CACHE_FLAG_WARM;
}
if (fWriteBack) {
dwFlags |= CACHE_FLAG_WRITEBACK;
}
// Set up data cache
pvol->v_DataCacheId = FSDMGR_CreateCache ((HDSK)pvol->v_pdsk->d_hdsk, pvol->v_secBlkBias + pvol->v_secEndAllFATs,
pvol->v_pdsk->d_diActive.di_total_sectors - 1, dwDataCacheSize, pvol->v_pdsk->d_diActive.di_bytes_per_sect, dwFlags);
}
/* ReadWriteDisk
*
* Reads/writes a set of contiguous sectors from a disk to/from memory.
*
* Entry:
* pvol pointer to VOLUME, NULL if none
* hdsk handle to disk
* cmd READ_DISK_CMD, WRITE_DISK_CMD, or WRITETHROUGH_DISK_CMD
* pdi address of DISK_INFO structure
* sector 0-based sector number
* cSectors number of sectors to read/write
* pvBuffer address of buffer to read/write sectors to/from
*
* Exit:
* ERROR_SUCCESS if successful, else GetLastError() from the FSDMGR_DiskIoControl call issued
*/
DWORD ReadWriteDisk(PVOLUME pvol, HANDLE hdsk, DWORD cmd, PDISK_INFO pdi, DWORD sector, int cSectors,
PVOID pvBuffer, BOOL fRemapFats)
{
DWORD dwError = ERROR_SUCCESS;
// DWORD dwOffset;
// DWORD dwSector;
BOOL bRWFromDisk = TRUE;
DWORD dwCacheId;
#ifdef TFAT
// Here is where we are going to redirect any writes to the FAT1 from FAT0;
if ( pvol && pvol->v_fTfat && (pvol->v_flags & VOLF_BACKUP_FAT) &&
IS_FAT_SECTOR(pvol, sector) && fRemapFats )
{
if( sector < ( pvol->v_secBlkBias + pvol->v_csecFAT ))
{
// Keep track what FAT sectors are modified
if (WRITE_DISK_CMD == cmd || WRITETHROUGH_DISK_CMD == cmd)
{
DWORD sec;
for (sec = sector - pvol->v_secBlkBias; sec < sector + cSectors - pvol->v_secBlkBias; sec++)
{
ASSERT (sec < pvol->v_secEndAllFATs);
ASSERT ((sec >> 3) < pvol->v_DirtySectorsInFAT.dwSize);
pvol->v_DirtySectorsInFAT.lpBits[ sec >> 3] |= 1 << (sec & 7);
}
}
// This is a read/write to the FAT0, redirect to FAT1
DEBUGMSGW( ZONE_TFAT && ZONE_DISKIO, ( DBGTEXTW( "FATFS!ReadWriteDisk: %s to sector %d, rerouting to sector %d\r\n" ),
( cmd == READ_DISK_CMD ) ? DBGTEXTW( "READ" ) : DBGTEXTW( "WRITE" ),
sector, sector + pvol->v_csecFAT));
sector += pvol->v_csecFAT;
}
else
{
DEBUGMSGW( ZONE_TFAT || ZONE_ERRORS, ( DBGTEXTW( "FATFS!ReadWriteDisk: %s to sector %d -- out of range warning\r\n" ),
( cmd == READ_DISK_CMD ) ? DBGTEXTW( "READ" ) : DBGTEXTW( "WRITE" ), sector));
ASSERT(FALSE);
}
}
#endif
if (pvol && sector >= pvol->v_secBlkBias && pvol->v_FATCacheId != INVALID_CACHE_ID && pvol->v_DataCacheId != INVALID_CACHE_ID)
{
dwCacheId = pvol->v_DataCacheId;
if (IS_FAT_SECTOR(pvol, sector))
{
dwCacheId = pvol->v_FATCacheId;
#ifdef TFAT
// If this is a FAT0 sector, write directly to disk
if (pvol->v_fTfat && sector < ( pvol->v_secBlkBias + pvol->v_csecFAT ))
return UncachedReadWriteDisk ((HDSK)hdsk, cmd, pdi, sector, cSectors, pvBuffer);
#endif
}
if (cmd == READ_DISK_CMD)
{
dwError = FSDMGR_CachedRead (dwCacheId, sector, cSectors, pvBuffer, 0);
}
else
{
dwError = FSDMGR_CachedWrite (dwCacheId, sector, cSectors, pvBuffer,
(cmd == WRITETHROUGH_DISK_CMD) ? CACHE_FORCE_WRITETHROUGH : 0);
}
}
else
{
// This is typically used for reading the boot sector, which is not cached, or if caching disabled.
dwError = UncachedReadWriteDisk ((HDSK)hdsk, cmd, pdi, sector, cSectors, pvBuffer);
}
return dwError;
}
DWORD UncachedReadWriteDisk (HDSK hdsk, DWORD cmd, PDISK_INFO pdi, DWORD sector, int cSectors, PVOID pvBuffer)
{
DWORD dwError;
if (cmd == READ_DISK_CMD)
{
dwError = FSDMGR_ReadDisk (hdsk, sector, cSectors, pvBuffer, cSectors * pdi->di_bytes_per_sect);
}
else
{
dwError = FSDMGR_WriteDisk (hdsk, sector, cSectors, pvBuffer, cSectors * pdi->di_bytes_per_sect);
}
return dwError;
}
/* FreeClusterOnDisk - Calls IOCTL_DISK_DELETE_SECTORS on sectors that are freed
*
* ENTRY
* pvol - pointer to volume
* dwStartCluster - starting cluster to free
* dwNumClusters - number of clusters to free
*
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -