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

📄 disk.c

📁 从大量的wince源代码中剥离出的fat文件系统源代码.移植性非常高. 里面带有source i.rar
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// 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)!\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\n"), status));
        return status;
    }

    DEBUGMSG(ZONE_DISKIO,
             (DBGTEXT("FATFS!GetDiskInfo: DISK_IOCTL_GETINFO returned %d bytes\n"), cb));

    DEBUGMSG(ZONE_DISKIO,
             (DBGTEXT("FATFS!GetDiskInfo: Sectors=%d (0x%08x), BPS=%d, CHS=%d:%d:%d\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\n"), status));
        }
        else {
            DEBUGMSG(ZONE_DISKIO,
                    (DBGTEXT("FATFS!SetDiskInfo: DISK_IOCTL_SETINFO returned %d bytes\n"), cb));

            DEBUGMSG(ZONE_DISKIO,
                    (DBGTEXT("FATFS!SetDiskInfo: Sectors=%d (0x%08x), BPS=%d, CHS=%d:%d:%d\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;
}

#ifdef DISK_CACHING

DWORD NearestPwr2(unsigned int n)
{
    DWORD l=1;
    while((l << 1) <=  n) {
        l = l << 1;
    }
    return l;
}

DWORD GetBestCacheSize(PVOLUME pvol)
{
    DEBUGMSG( ZONE_INIT, (TEXT("FATFS: Sec/FAT = %ld!!!\r\n"), pvol->v_csecFAT));
    return min( 512, pvol->v_csecFAT);
}

void SetupDiskCache(PVOLUME pvol)
{
    DWORD dwError;
    DWORD dwStart, dwSector, dwLen;
    HKEY hKeyFATFS;
    DWORD dwWarmCache;

    dwError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, awcFATFS, 0, KEY_ALL_ACCESS, &hKeyFATFS);
    if (ERROR_SUCCESS == dwError) {
        dwLen = sizeof(DWORD);
//        dwError = RegQueryValueEx(hKeyFATFS, TEXT("CacheSize"), NULL, &dwType, (PUCHAR)&(pvol->v_CacheSize), &dwLen);
        if (!FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"CacheSize", &pvol->v_CacheSize)) {
            pvol->v_CacheSize = -1;
        }    
        if (!FSDMGR_GetRegistryValue((HDSK)pvol->v_pdsk->d_hdsk, L"EnableCacheWarm", &dwWarmCache)) {
            dwWarmCache = 1;
        }    
        if (pvol->v_CacheSize != -1) {
            if (!(pvol->v_CacheSize)) {
                pvol->v_CacheSize = GetBestCacheSize( pvol);
            }
            pvol->v_CacheSize = max( NearestPwr2(pvol->v_CacheSize), 16);
            DEBUGMSG( ZONE_INIT, (TEXT("FATFS: CacheSize = %ld!!!\r\n"), pvol->v_CacheSize));
            dwStart = pvol->v_secBlkBias;
            pvol->v_pFATCacheBuffer = VirtualAlloc(NULL, pvol->v_pdsk->d_diActive.di_bytes_per_sect * pvol->v_CacheSize, MEM_COMMIT, PAGE_READWRITE);
            if (!pvol->v_pFATCacheBuffer)
                goto ExitFailure;
            pvol->v_pFATCacheLookup = HeapAlloc( GetProcessHeap(), 0, pvol->v_CacheSize * sizeof(DWORD));
            if (!pvol->v_pFATCacheLookup) 
                goto ExitFailure;
            if (dwWarmCache) {
                DEBUGMSG( ZONE_INIT, (TEXT("FATFS: Warming Cache ...\r\n")));
                for (dwSector=0; dwSector < pvol->v_CacheSize; dwSector++) { // Prewarm the cache
                    dwError = ReadWriteDisk2( pvol, pvol->v_pdsk->d_hdsk, DISK_IOCTL_READ, &pvol->v_pdsk->d_diActive, dwStart+dwSector, 1, pvol->v_pFATCacheBuffer+(dwSector*512));
                    if (dwError == ERROR_SUCCESS) {
                        pvol->v_pFATCacheLookup[dwSector] = dwSector;
                    } else {
                        pvol->v_pFATCacheLookup[dwSector] = 0XFFFFFFFF;
                    }
                }    
            } else {
                // Invalidate all entries
                memset( pvol->v_pFATCacheLookup, 0xFF, pvol->v_CacheSize * sizeof(DWORD));
            }
        } else {
            goto ExitFailure;
        }
    }    
    return;
ExitFailure:
    DEBUGMSG( ZONE_INIT, (TEXT("No cache has been setup !!!\r\n")));
    pvol->v_CacheSize = 0;
    if (pvol->v_pFATCacheBuffer) {
        VirtualFree( pvol->v_pFATCacheBuffer, 0, MEM_RELEASE);
        pvol->v_pFATCacheBuffer = NULL;
    }
    if (pvol->v_pFATCacheLookup) {
        HeapFree( GetProcessHeap(), 0, pvol->v_pFATCacheLookup);
        pvol->v_pFATCacheLookup = NULL;
    }    
}

DWORD ReadWriteDisk(PVOLUME pvol, HANDLE hdsk, DWORD cmd, PDISK_INFO pdi, DWORD sector, int cSectors, PVOID pvBuffer)
{
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwOffset;
    DWORD dwSector;

    dwOffset = 0;

    if (!pvol || (sector < pvol->v_secBlkBias) || (pvol->v_CacheSize == 0))
        return ReadWriteDisk2( pvol, hdsk, cmd, pdi, sector, cSectors, pvBuffer);

    DEBUGMSG( ZONE_DISKIO, (TEXT("FATFS!ReadWriteDisk:Cached (%s, sector %d (0x%08x), total %d)\n"), cmd==DISK_IOCTL_READ? TEXTW("READ") : TEXTW("WRITE"), sector, sector, cSectors));
    // TODO: perf improvments to be had if we made a call to ReadWriteDisk2 with multiple sectors !!!
    for (dwSector = sector; dwSector < sector+cSectors; dwSector++) {
        dwOffset = dwSector - pvol->v_secBlkBias;
        DEBUGMSG( ZONE_DISKIO, (TEXT("FATFS!ReadWriteDisk:Cached dwSector=%ld dwOffset=%ld Index=%ld\r\n"), dwSector, dwOffset, dwOffset % pvol->v_CacheSize));
        if (cmd == DISK_IOCTL_READ) {
            if (pvol->v_pFATCacheLookup[dwOffset % pvol->v_CacheSize] != dwOffset) {
                DEBUGMSG( ZONE_DISKIO, (TEXT("FATFS!ReadWriteDisk:Cached CacheMiss !!!\r\n")));
                dwError = ReadWriteDisk2( pvol, hdsk, DISK_IOCTL_READ, pdi, dwSector, 1, pvol->v_pFATCacheBuffer+((dwOffset % pvol->v_CacheSize)*512));
                if (dwError != ERROR_SUCCESS) {
                    pvol->v_pFATCacheLookup[dwOffset % pvol->v_CacheSize] = 0XFFFFFFFF;
                    break;
                }
            }    
            memcpy( (LPBYTE)pvBuffer+((dwSector-sector)*512),  pvol->v_pFATCacheBuffer+((dwOffset % pvol->v_CacheSize)*512), 512);
        } else {
            memcpy( pvol->v_pFATCacheBuffer+((dwOffset % pvol->v_CacheSize)*512), (LPBYTE)pvBuffer+((dwSector-sector)*512),  512);
            dwError = ReadWriteDisk2( pvol, hdsk, DISK_IOCTL_WRITE, pdi, dwSector, 1, pvol->v_pFATCacheBuffer+((dwOffset % pvol->v_CacheSize)*512));
            if (dwError != ERROR_SUCCESS) {
                pvol->v_pFATCacheLookup[dwOffset % pvol->v_CacheSize] = 0XFFFFFFFF;
                break;
            }
        }
        pvol->v_pFATCacheLookup[dwOffset % pvol->v_CacheSize] = dwOffset;
    }    
    return dwError;
}    
#endif


/*  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         DISK_IOCTL_READ or DISK_IOCTL_WRITE
 *      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
 */         

#ifdef DISK_CACHING
DWORD ReadWriteDisk2(PVOLUME pvol, HANDLE hdsk, DWORD cmd, PDISK_INFO pdi, DWORD sector, int cSectors, PVOID pvBuffer)
#else
DWORD ReadWriteDisk(PVOLUME pvol, HANDLE hdsk, DWORD cmd, PDISK_INFO pdi, DWORD sector, int cSectors, PVOID pvBuffer)
#endif
{
    int k;
    int cRetry;
    SG_REQ Sg;
    DWORD dwError = ERROR_SUCCESS;

    ASSERT(hdsk != INVALID_HANDLE_VALUE);

#ifdef MAXDEBUG
    // See if we can catch excessive use of stack -JTP

    if (((DWORD)&k & 0xf000) <= 0x8000) {
        RETAILMSG(TRUE,(TEXT("FATFS!ReadWriteDisk: suspicious stack usage (%x)\n"), &k));
        DEBUGBREAK(TRUE);
    }
#endif

    DEBUGMSGW(ZONE_DISKIO,(DBGTEXTW("FATFS!ReadWriteDisk(%s, sector %d (0x%08x), total %d)\n"), cmd==DISK_IOCTL_READ? TEXTW("READ") : TEXTW("WRITE"), sector, sector, cSectors));

    
    if (sector == 0 && cmd == DISK_IOCTL_WRITE && (!pvol || !(pvol->v_flags & VOLF_LOCKED)) || sector + cSectors > pdi->di_total_sectors) {
        RETAILMSG(TRUE,(TEXT("FATFS!ReadWriteDisk: suspicious I/O! (sector %d)\n"), sector));
        return ERROR_GEN_FAILURE;
    }

    cRetry = 1;             do {
        Sg.sr_start = sector;
        Sg.sr_num_sec = cSectors;
        Sg.sr_num_sg = 1;
#ifdef UNDER_WIN95
        Sg.sr_callback = (PFN_REQDONE)pdi;
#else
        Sg.sr_callback = NULL;
#endif
        Sg.sr_sglist[0].sb_len = cSectors * pdi->di_bytes_per_sect;
        Sg.sr_sglist[0].sb_buf = pvBuffer;

#ifdef DEBUG
        if (ZONE_DISKIO && ZONE_PROMPTS && cmd == DISK_IOCTL_WRITE) {

            FATUIDATA fui;
            DWORD dwVolFlags;

            if (pvol) {

                // Setting some bit (like VOLF_LOCKED) that will prevent most
                // any other call from entering FATFS while the following dialog is
                // active is very important, because this thread is temporarily
                // leaving our control, so it could re-enter FATFS and mess up the
                // state of any streams we've currently got locked (since critical
                // sections only protect our state from *other* threads, not from
                // ourselves).

                
                dwVolFlags = pvol->v_flags;
                pvol->v_flags |= VOLF_LOCKED;
            }

            fui.dwSize = sizeof(fui);
            fui.dwFlags = FATUI_CANCEL | FATUI_DEBUGMESSAGE;
            fui.idsEvent = (UINT)TEXTW("Preparing to write %1!d! sector(s) at sector %2!d! on %3!s!.\n\nSelect OK to allow, or Cancel to fail.");
            fui.idsEventCaption = IDS_FATUI_WARNING;
            fui.cuiParams = 3;
            fui.auiParams[0].dwType = UIPARAM_VALUE;
            fui.auiParams[0].dwValue = cSectors;
            fui.auiParams[1].dwType = UIPARAM_VALUE;
            fui.auiParams[1].dwValue = sector;
            fui.auiParams[2].dwType = UIPARAM_VALUE;
            fui.auiParams[2].dwValue = (DWORD)((pvol && pvol->v_pwsHostRoot)? (pvol->v_pwsHostRoot+1) : TEXTW("Storage Card"));

#ifdef FATUI
            if (FATUIEvent(hFATFS, (PWSTR)fui.auiParams[3].dwValue, &fui) == FATUI_CANCEL)
                dwError = ERROR_BAD_UNIT;
#endif                

            if (pvol)
                pvol->v_flags = (pvol->v_flags & ~VOLF_LOCKED) | (dwVolFlags & VOLF_LOCKED);
        
            if (dwError)
                goto error;
        }
#endif

        // Here, at last, is where we actually do the I/O...

        if (pdi->di_flags & DISK_INFO_FLAGS_FATFS_SIMULATED) {

            DWORD cb;

            if (SetFilePointer(hdsk, sector * pdi->di_bytes_per_sect, NULL, FILE_BEGIN) == 0xFFFFFFFF) {
                dwError = GetLastError();
                goto error;
            }

            if (cmd != DISK_IOCTL_WRITE) {
                if (ReadFile(hdsk, pvBuffer, Sg.sr_sglist[0].sb_len, &cb, NULL) == FALSE) {
                    dwError = GetLastError();
                    goto error;
                }
            }
            else {
                if (WriteFile(hdsk, pvBuffer, Sg.sr_sglist[0].sb_len, &cb, NULL) == FALSE) {
                    dwError = GetLastError();
                    goto error;
                }
            }

            if (cb != Sg.sr_sglist[0].sb_len) {
                dwError = ERROR_GEN_FAILURE;
                goto error;
            }

            Sg.sr_status = ERROR_SUCCESS;
        }
        else {
            DWORD dwIOCTL = cmd;
            if (pdi->di_flags & DISK_INFO_FLAGS_FATFS_NEW_IOCTLS) {
                if (cmd == DISK_IOCTL_READ)
                    dwIOCTL = IOCTL_DISK_READ;
                else
                if (cmd == DISK_IOCTL_WRITE)
                    dwIOCTL = IOCTL_DISK_WRITE;
            }
            if (FSDMGR_DiskIoControl((HDSK)hdsk, dwIOCTL, &Sg, sizeof(Sg), NULL, 0, &k, NULL) == FALSE) {
                dwError = GetLastError();
                goto error;
            }
            else {
                if (pdi->di_flags & DISK_INFO_FLAGS_FATFS_NEW_IOCTLS)
                    Sg.sr_status = ERROR_SUCCESS;                   }
        }

⌨️ 快捷键说明

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