diskio.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,552 行 · 第 1/3 页
C
1,552 行
}
DEBUGMSG(ATAPI_IO, (TEXT("Current number of cylinders: %d\r\n"),
pId->NumberOfCurrentCylinders));
DEBUGMSG(ATAPI_IO, (TEXT("Current number of heads: %d\r\n"),
pId->NumberOfCurrentHeads));
DEBUGMSG(ATAPI_IO, (TEXT("Current number of sectors/track: %d\r\n"),
pId->CurrentSectorsPerTrack));
DEBUGMSG(ATAPI_IO, (TEXT("Current sector capacity: %d\r\n"),
pId->CurrentSectorCapacity));
DEBUGMSG(ATAPI_IO, (TEXT("Sectors per interrupt with r/w multiple: %d\r\n"),
pId->MultiSectorCount));
if (pId->MultiSectorSettingValid & 1) {
DEBUGMSG(ATAPI_IO, (TEXT("Multi sector setting valid\r\n")));
} else {
DEBUGMSG(ATAPI_IO, (TEXT("Multi sector setting is INVALID\r\n")));
}
DEBUGMSG(ATAPI_IO, (TEXT("Total user addressable sectors: %d\r\n"),
pId->TotalUserAddressableSectors));
DEBUGMSG(ATAPI_IO, (TEXT("Single word dma modes supported: %x\r\n"),
pId->SingleDmaModesSupported));
DEBUGMSG(ATAPI_IO, (TEXT("Single word transfer mode active: %x\r\n"),
pId->SingleDmaTransferActive));
DEBUGMSG(ATAPI_IO, (TEXT("Multi word dma modes supported: %x\r\n"),
pId->MultiDmaModesSupported));
DEBUGMSG(ATAPI_IO, (TEXT("Multi word transfer mode active: %x\r\n"),
pId->MultiDmaTransferActive));
DEBUGMSG(ATAPI_IO, (TEXT("ATDISK:ATAIssueIdentify done\r\n")));
#endif // DEBUG
return TRUE;
} // ATAIssueIdentify
//
// GetDiskInfo - return disk info in response to DISK_IOCTL_GETINFO
//
DWORD
GetDiskInfo(
PDISK pDisk,
PDISK_INFO pInfo
)
{
DWORD dwMAX_LBA;
DWORD dwMAX_BLB;
USHORT dwWork;
DWORD dwTimer;
DWORD dwWaitTime = INFINITE;
WORD *rdata;
WORD dwCount;
ATAPI_errcode = 0;
dwCount = 0;
RetryInfoSeek:
// Device selection protocol
while( ( *ATAPI_STAT & 0x88 ) != 0); // Status Reg BSY , DRQ = 0
*ATAPI_DSEL = 0xa0; // Device Select ( DRIVE 0 master )
while( ( *ATAPI_STAT & 0x88 ) != 0); // Status Reg BSY , DRQ = 0
// PACKET command protocol
*ATAPI_FETR = 0; // ATAPI Features ( Not use OverLap and DMA )
*ATAPI_IRRN = 0; // Sector Count
*ATAPI_RSVE = 0; // Sector Number
*ATAPI_BCTL = 8; // Byte Count Low ( 8 byte )
*ATAPI_BCTH = 0; // Byte Count High
*ATAPI_DCTR = 0x02; // Device Control ( INTRQ-OFF )
*ATAPI_COMD = ATPCOM_ATAPIPAKET; // ATA Command ( Packet Command A0)
// Status Reg BSY=0 , DRQ=1 ?
while( ( *ATAPI_STAT & 0x88 ) != 0x08 ); // Status BSY=0,DRQ=1 then next
CD_ROM_STA.flag = ATAPI_CAPPROC;
// Write Data Register (Command Packet)
*ATAPI_DATW = ATPCOM_READCAPACITY; // 0 Command code 25h
*ATAPI_DATW = 0; // 2 Reserved
*ATAPI_DATW = 0; // 4 Reserved
*ATAPI_DATW = 0; // 6 Reserved
*ATAPI_DATW = 0; // 8 Reserved
*ATAPI_DATW = 0; //10 Reserved
dwTimer = 0;
while( ( *ATAPI_STAT & ATPMASK_BUSY ) != 0){ // Status Reg BSY=0 then next
Sleep(ATAPI_SLEEP); // 100ms SLEEP
dwTimer++;
if(dwTimer>ATAPI_SLEEP)
break;
}
if(dwTimer>ATAPI_SLEEP){
SetLastError(ERROR_NOT_READY);
return FALSE;
}
if( (*ATAPI_STAT & ATPMASK_CHEK) != 0 ){ // Error ?
GetATAPError();
if(SenseKey==0x02){
if(SenseCode==0x04){ //LOGICAL DRIVE NOT READY
if(dwCount<100){
dwCount++;
ATAPI_errcode = NO_ERROR; //RETRY SEEK 100TIMES
goto RetryInfoSeek;
}
}
}
if(SenseKey==0x06){
if(SenseCode==0x28){ //NOT READY TO READY TRANSITION
if(dwCount<100){
dwCount++;
ATAPI_errcode = NO_ERROR; //RETRY SEEK 100TIMES
goto RetryInfoSeek;
}
}
}
SetLastError(ATAPI_errcode); // return ATAPI_errcode;
return FALSE;
}
if(ATAPI_errcode != NO_ERROR) { // Error ?
SetLastError(ATAPI_errcode);
return FALSE;
}
rdata = (WORD*)Kdata; // Saved data pointer
dwTimer = 0;
while(dwTimer < 4){
*rdata++ = *ATAPI_DATW; // Saved sense data
dwTimer++;
}
dwMAX_LBA=0;
dwWork = Kdata[0]; // Loical Block Address MSB
dwWork = (dwWork<<8) | (dwWork>>8); // Byte Swap
dwMAX_LBA |= (DWORD)dwWork;
dwMAX_LBA<<=16;
dwWork = Kdata[1]; // Loical Block Address LSB
dwWork = (dwWork<<8) | (dwWork>>8); // Byte Swap
dwMAX_LBA |= (DWORD)dwWork;
dwMAX_BLB=0;
dwWork = Kdata[2]; // Block Length in Bytes MSB
dwWork = (dwWork<<8) | (dwWork>>8); // Byte Swap
dwMAX_BLB |= (DWORD)dwWork;
dwMAX_BLB<<=16;
dwWork = Kdata[3]; // Block Length in Bytes LSB
dwWork = (dwWork<<8) | (dwWork>>8); // Byte Swap
dwMAX_BLB |= (DWORD)dwWork;
*pInfo = pDisk->d_DiskInfo;
pInfo->di_total_sectors = dwMAX_LBA;
pInfo->di_bytes_per_sect = dwMAX_BLB;
pInfo->di_cylinders = 1;
pInfo->di_heads = 1;
pInfo->di_sectors = dwMAX_LBA;
pInfo->di_flags |= DISK_INFO_FLAG_CDROM;
SetLastError(ERROR_SUCCESS);
return TRUE;
} // GetDiskInfo
//
// SetDiskInfo - store disk info in response to DISK_IOCTL_SETINFO
//
DWORD
SetDiskInfo(
PDISK pDisk,
PDISK_INFO pInfo
)
{
DWORD sectsize;
sectsize = pDisk->d_DiskInfo.di_bytes_per_sect;
pDisk->d_DiskInfo = *pInfo;
//
// Allocate the aligned buffer when we find out the sector size
//
if (pDisk->d_f16Bit) {
if (pInfo->di_bytes_per_sect != sectsize) {
if (pDisk->d_AlignBuf != NULL) {
LocalFree(pDisk->d_AlignBuf);
pDisk->d_AlignBuf = NULL;
}
}
if (pDisk->d_AlignBuf == NULL) {
pDisk->d_AlignBuf = (PUSHORT)LocalAlloc(LPTR,
pInfo->di_bytes_per_sect);
}
}
return ERROR_SUCCESS;
} // SetDiskInfo
//
// ATAInitController
//
BOOL
ATAInitController(
PDISK pDisk
)
{
BOOL ret = TRUE;
UCHAR status;
DEBUGMSG(ATAPI_INIT, (TEXT("ATAPI:ATAInitController entered\r\n")));
try {
status = ATA_READ_UCHAR(pDisk->d_pATAReg + ATA_REG_STATUS);
if ((status & 0x0f) == 0x0f) {
ret = FALSE;
DEBUGMSG(ATAPI_IO|ATAPI_ERROR,
(TEXT("ATAPI:ATAInitController - ATA_STATUS = 0x%x!\r\n"),
status));
}
DEBUGMSG(ATAPI_INIT,
(TEXT("ATAPI:ATAInitController writing to ATA_REG_DRV_CTRL\r\n")));
ATA_WRITE_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(ATAPI_IO|ATAPI_ERROR, (TEXT("ATAPI:ATAInitController - exception!\r\n")));
ret = FALSE;
}
DEBUGMSG(ATAPI_INIT, (TEXT("ATAPI: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(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI: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(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI: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(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI: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;
DriverKey = OpenDriverKey(pDisk->d_ActivePath);
if (DriverKey) {
*pcBytes = cBytes;
status = RegQueryValueEx(
DriverKey,
TEXT("Folder"),
NULL,
&ValType,
(PUCHAR)FolderName,
pcBytes);
if (status != ERROR_SUCCESS) {
DEBUGMSG(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI:GetFolderName - RegQueryValueEx(Folder) returned %d\r\n"),
status));
*pcBytes = 0;
} else {
DEBUGMSG(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI:GetFolderName - FolderName = %s, length = %d\r\n"),
FolderName, *pcBytes));
*pcBytes += sizeof(WCHAR); // account for terminating 0.
}
RegCloseKey(DriverKey);
if (status || (*pcBytes == 0)) {
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(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI: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(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI: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(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI:GetGeometry - RegQueryValueEx(Sectors) returned %d\r\n"),
status));
return FALSE;
}
*Sectors = (WORD)dwtmp;
return TRUE;
} // GetGeometry
//
// 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(ATAPI_INIT|ATAPI_ERROR,
(TEXT("ATAPI: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;
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(ATAPI_INIT,
(TEXT("ATAPI:InitDisk - Getting C:H:S from registry\r\n")));
GetGeometry(
DriverKey,
&(Id.NumberOfCylinders),
&(Id.NumberOfHeads),
&(Id.SectorsPerTrack));
DEBUGMSG(ATAPI_INIT,
(TEXT("ATAPI:InitDisk - C:H:S = %d:%d:%d\r\n"),
Id.NumberOfCylinders, Id.NumberOfHeads, Id.SectorsPerTrack));
}
pDisk->d_fLBAMode = (Id.Capabilities & 0x0200) ? TRUE:FALSE;
pDisk->d_DiskInfo.di_total_sectors =
Id.NumberOfCylinders * Id.NumberOfHeads * Id.SectorsPerTrack;
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 + =
减小字号Ctrl + -
显示快捷键?