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

📄 disk.c

📁 Windows操作系统中文件系统过滤驱动和设备驱动之间的相似
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -