📄 diskio.c
字号:
(TEXT("ATADISK:ATAInitController writing to ATA_REG_DRV_CTRL\r\n")));
ATA_WRITE_UCHAR(pDisk->d_Flags, (UCHAR*)pDisk->d_pATARegAlt + ATA_REG_DRV_CTRL,
ATA_CTRL_ENABLE_INTR);
if (ATAWaitForDisk(
pDisk,
WAIT_TIME_LONG,
WAIT_TYPE_READY) != CERR_SUCCESS) {
ret = FALSE;
}
} except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG(ZONE_IO|ZONE_ERROR, (TEXT("ATADISK:ATAInitController - exception!\r\n")));
ret = FALSE;
}
DEBUGMSG(ZONE_INIT, (TEXT("ATADISK:ATAInitController done\r\n")));
return ret;
} // ATAInitController
//
// Function to open the driver key specified by the active key
//
// The caller is responsible for closing the returned HKEY
//
HKEY
OpenDriverKey(
LPTSTR ActiveKey
)
{
TCHAR DevKey[256];
HKEY hDevKey;
HKEY hActive;
DWORD ValType;
DWORD ValLen;
DWORD status;
//
// Get the device key from active device registry key
//
status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
ActiveKey,
0,
0,
&hActive);
if (status) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:OpenDriverKey RegOpenKeyEx(HLM\\%s) returned %d!!!\r\n"),
ActiveKey, status));
return NULL;
}
hDevKey = NULL;
ValLen = sizeof(DevKey);
status = RegQueryValueEx(
hActive,
DEVLOAD_DEVKEY_VALNAME,
NULL,
&ValType,
(PUCHAR)DevKey,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:OpenDriverKey - RegQueryValueEx(%s) returned %d\r\n"),
DEVLOAD_DEVKEY_VALNAME, status));
goto odk_fail;
}
//
// Get the geometry values from the device key
//
status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
DevKey,
0,
0,
&hDevKey);
if (status) {
hDevKey = NULL;
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:OpenDriverKey RegOpenKeyEx(HLM\\%s) returned %d!!!\r\n"),
DevKey, status));
}
odk_fail:
RegCloseKey(hActive);
return hDevKey;
} // OpenDriverKey
//
// Function to retrieve the folder name value from the driver key. The folder name is
// used by FATFS to name this disk volume.
//
BOOL
GetFolderName(
PDISK pDisk,
LPWSTR FolderName,
DWORD cBytes,
DWORD * pcBytes
)
{
HKEY DriverKey;
DWORD ValType;
DWORD status;
TCHAR szName[MAX_PATH];
DWORD dwSize;
DriverKey = OpenDriverKey(pDisk->d_ActivePath);
if (DriverKey) {
dwSize = sizeof(szName);
status = RegQueryValueEx(
DriverKey,
TEXT("Folder"),
NULL,
&ValType,
(LPBYTE)szName,
&dwSize);
if ((status != ERROR_SUCCESS) || (dwSize > cBytes)){
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:GetFolderName - RegQueryValueEx(Folder) returned %d\r\n"),
status));
*pcBytes = 0;
} else {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:GetFolderName - FolderName = %s, length = %d\r\n"),
FolderName, *pcBytes));
*pcBytes = (wcslen(szName)+1)*sizeof(WCHAR);
wcscpy( (LPWSTR)FolderName, szName);
}
RegCloseKey(DriverKey);
if (status || (*pcBytes == 0)) {
SetLastError( ERROR_NOT_FOUND);
return FALSE;
}
return TRUE;
}
return FALSE;
} // GetFolderName
//
// Function to get the C:H:S values for the disk specified by the ActiveKey.
//
// NOTE: Only one such set of values will be allowed per system since the active
// key is dynamic. The CHS values must be stored in the device key.
//
// NOTE2: C:H:S => Cylinders:Heads:Sectors per track
//
BOOL
GetGeometry(
HKEY hDevKey,
WORD * Cylinders,
WORD * Heads,
WORD * Sectors
)
{
DWORD ValType;
DWORD ValLen;
DWORD status;
DWORD dwtmp;
ValLen = sizeof(dwtmp);
status = RegQueryValueEx(
hDevKey,
TEXT("Cylinders"),
NULL,
&ValType,
(PUCHAR)&dwtmp,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:GetGeometry - RegQueryValueEx(Cylinders) returned %d\r\n"),
status));
return FALSE;
}
*Cylinders = (WORD)dwtmp;
ValLen = sizeof(dwtmp);
status = RegQueryValueEx(
hDevKey,
TEXT("Heads"),
NULL,
&ValType,
(PUCHAR)&dwtmp,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:GetGeometry - RegQueryValueEx(Heads) returned %d\r\n"),
status));
return FALSE;
}
*Heads = (WORD)dwtmp;
ValLen = sizeof(dwtmp);
status = RegQueryValueEx(
hDevKey,
TEXT("Sectors"),
NULL,
&ValType,
(PUCHAR)&dwtmp,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:GetGeometry - RegQueryValueEx(Sectors) returned %d\r\n"),
status));
return FALSE;
}
*Sectors = (WORD)dwtmp;
return TRUE;
} // GetGeometry
static BOOL
ParseATAIdString(
CHAR *str, int len, DWORD *pdwOffset, CHAR **ppDest, DWORD *pcBytesLeft
)
{
UCHAR *p;
DWORD cCopied;
CHAR *pDest;
// check validity (spec says ASCII, I assumed printable)
for (p = str; p < &str[len]; ++p)
if (*p < 0x20 || *p > 0x7F) {
*pdwOffset = 0;
return FALSE;
}
// find the last non-pad character
for (p = &str[len]; p > str && p[-1] == ' '; --p)
;
cCopied = p - str;
// special case - empty string implies not present
if (cCopied == 0) {
*pdwOffset = 0;
return TRUE;
}
++cCopied; // this is a byte count so add a terminating null
// always increment *ppDest because it counts the bytes that we want,
// not just the bytes that we've actually written.
pDest = *ppDest;
*ppDest += cCopied;
// if there has already been an error, then we needn't continue further
if (GetLastError() != ERROR_SUCCESS)
return TRUE;
// make sure there's enough space to copy into
if (cCopied > *pcBytesLeft) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
cCopied = *pcBytesLeft;
}
__try {
if (cCopied) {
memcpy(pDest, str, cCopied-1);
pDest[cCopied-1] = '\0';
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_INVALID_PARAMETER);
};
*pcBytesLeft -= cCopied;
return TRUE;
}
BOOL
GetStorageID(
PDISK pDisk,
PSTORAGE_IDENTIFICATION psid,
DWORD cBytes,
DWORD * pcBytes
)
{
IDENTIFY_DATA sAtaId;
PCHAR pDstOffset;
DWORD cRemaining;
memset( &sAtaId, 0, sizeof(IDENTIFY_DATA));
if (cBytes < sizeof(*psid)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
} else
// initialize the error status in case there are no errors
SetLastError(ERROR_SUCCESS);
__try {
psid->dwSize = sizeof(*psid);
psid->dwFlags = 0; // can be or of {MANUFACTUREID,SERIALNUM}_INVALID
psid->dwManufactureIDOffset = psid->dwSerialNumOffset = 0;
} __except (EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (ATAIssueIdentify(pDisk, &sAtaId) == FALSE) {
// leave the error code alone
return FALSE;
}
cRemaining = cBytes - sizeof(*psid);
pDstOffset = (PCHAR)(psid + 1);
// This macro is only used here; I think it's clearer than the expansion.
#define PARSESTRING(nSrcField,nOffField,nFlagPfx) \
if (1) { \
psid->nOffField = pDstOffset - (PCHAR)psid; \
if (ParseATAIdString((PCHAR)sAtaId.nSrcField, sizeof(sAtaId.nSrcField), \
&psid->nOffField, &pDstOffset, &cRemaining) == FALSE) \
psid->dwFlags |= nFlagPfx ## _INVALID; \
} else
PARSESTRING(ModelNumber, dwManufactureIDOffset, MANUFACTUREID);
PARSESTRING(SerialNumber, dwSerialNumOffset, SERIALNUM);
psid->dwSize = pDstOffset - (PCHAR)psid; // required size
*pcBytes = min(psid->dwSize, cBytes); // bytes written
return (GetLastError() == ERROR_SUCCESS);
}
//
// Function to check if the advertised LBA mode capability needs to be ignored.
//
// NOTE: Only one such set of value can be allowed per system since the active
// key is dynamic. The CHSMode value must be stored in the device key.
//
// NOTE2: C:H:S => Cylinders:Heads:Sectors per track
// LBA => Logical Block Address
//
BOOL
UseCHSMode(
HKEY hDevKey
)
{
DWORD ValType;
DWORD ValLen;
DWORD status;
DWORD dwtmp;
ValLen = sizeof(dwtmp);
status = RegQueryValueEx(
hDevKey,
TEXT("CHSMode"),
NULL,
&ValType,
(PUCHAR)&dwtmp,
&ValLen);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR,
(TEXT("ATADISK:UseCHSMode - RegQueryValueEx(CHSMode) returned %d\r\n"),
status));
return FALSE;
}
return dwtmp == 1 ? TRUE : FALSE;
} // UseCHSMode
//
// InitDisk
//
DWORD InitDisk(
PDISK pDisk,
LPTSTR ActiveKey
)
{
IDENTIFY_DATA Id;
HKEY DriverKey;
memset( &Id, 0, sizeof(IDENTIFY_DATA));
if (ATAInitController(pDisk) == FALSE) {
return 1;
}
if (ATAIssueIdentify(pDisk, &Id) == FALSE) {
return 2;
}
DriverKey = OpenDriverKey(ActiveKey);
//
// If the identify data block is not reliable, then get the values
// from the registry.
//
if (DriverKey && ((Id.TranslationFieldsValid & 1) == 0)) {
DEBUGMSG(ZONE_INIT,
(TEXT("ATADISK:InitDisk - Getting C:H:S from registry\r\n")));
GetGeometry(
DriverKey,
&(Id.NumberOfCylinders),
&(Id.NumberOfHeads),
&(Id.SectorsPerTrack));
DEBUGMSG(ZONE_INIT,
(TEXT("ATADISK:InitDisk - C:H:S = %d:%d:%d\r\n"),
Id.NumberOfCylinders, Id.NumberOfHeads, Id.SectorsPerTrack));
}
pDisk->d_fLBAMode = TRUE;
pDisk->d_DiskInfo.di_total_sectors = Id.TotalUserAddressableSectors;
pDisk->d_DiskInfo.di_bytes_per_sect = BYTES_PER_SECTOR; // Start with 512, then go with SetInfo changes
pDisk->d_DiskInfo.di_cylinders = Id.NumberOfCylinders;
pDisk->d_DiskInfo.di_heads = Id.NumberOfHeads;
pDisk->d_DiskInfo.di_sectors = Id.SectorsPerTrack;
pDisk->d_DiskInfo.di_flags = DISK_INFO_FLAG_MBR;
if (DriverKey) {
if (UseCHSMode(DriverKey)) {
pDisk->d_fLBAMode = FALSE;
}
RegCloseKey(DriverKey);
}
return 0;
} // Initdisk
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -