📄 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)!\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 + -