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 + -
显示快捷键?