diskio.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,552 行 · 第 1/3 页
C
1,552 行
/*
Copyright(c) 1998,1999 SIC/Hitachi,Ltd.
Module Name:
diskio.c
Revision History:
4th August 1999 Released
4th December 1999 Read Process modified
*/
#include <windows.h>
#include <types.h>
#include <tchar.h>
#include <excpt.h>
#include <cardserv.h>
#include <cardapi.h>
#include <atapi.h>
#include <diskio.h>
#include <devload.h>
#include <ceddk.h>
#include <atapidev.h>
//
// This module contains the functions:
// CloseDisk
// ATAWaitForDisk
// ATASetSector
// CDRead
// ATAWrite
// DoDiskIO
// ATAIssueIdentify
// GetDiskInfo
// SetDiskInfo
// ATAInitController
// OpenDriverKey
// GetFolderName
// GetGeometry
// UseCHSMode
// InitDisk
//
/*****************************************************************************
* Modification for Aspen done by Maneesh Gupta
*
* Functions declaration for TurnATAPI & StartATAPIUnit has been added
* TurnATAPI check whether the drive is ready or not
* StartATAPIUnit stops & starts it again.
****************************************************************************/
extern WORD TurnATAPI(VOID);
extern WORD StartATAPIUnit(VOID);
/*****************************************************************************
* End of Modification for Aspen done by Maneesh Gupta
*
****************************************************************************/
union LongShort LBaddress;
union CharShort datasize;
USHORT dwHighLBA , dwLowLBA ;
//#define USE_INTERRUPT 1
#ifdef x86
#define ATA_READ_UCHAR(p) READ_PORT_UCHAR(p)
#define ATA_READ_USHORT(p) READ_PORT_USHORT(p)
#define ATA_WRITE_UCHAR(p,b) WRITE_PORT_UCHAR(p,b)
#define ATA_WRITE_USHORT(p,w) WRITE_PORT_USHORT(p,w)
#else
#define ATA_READ_UCHAR(p) (UCHAR)*(p)
#define ATA_READ_USHORT(p) (USHORT)*(p)
#define ATA_WRITE_UCHAR(p,b) *(p) = (UCHAR)(b)
#define ATA_WRITE_USHORT(p,w) *(p) = (USHORT)(w)
#endif
//
// CloseDisk - finish and free all outstanding requests and free other resources
// associated with the specified disk
//
VOID
CloseDisk(
PDISK pDisk
)
{
PDISK pd;
DEBUGMSG(ATAPI_IO, (TEXT("ATAPI:CloseDisk closing 0x%x\r\n"), pDisk));
//
// Remove it from the global list of disks
//
EnterCriticalSection(&v_ATAPICrit);
if (pDisk == v_DiskList) {
v_DiskList = pDisk->d_next;
} else {
pd = v_DiskList;
while (pd->d_next != NULL) {
if (pd->d_next == pDisk) {
pd->d_next = pDisk->d_next;
break;
}
pd = pd->d_next;
}
}
LeaveCriticalSection(&v_ATAPICrit);
DEBUGMSG(ATAPI_IO, (TEXT("ATAPI:CloseDisk - freeing resources\r\n")));
DeleteCriticalSection(&(pDisk->d_DiskCardCrit));
if (pDisk->d_AlignBuf) {
LocalFree(pDisk->d_AlignBuf);
}
if (pDisk->d_ActivePath) {
LocalFree(pDisk->d_ActivePath);
}
LocalFree(pDisk);
DEBUGMSG(ATAPI_IO, (TEXT("ATAPI:CloseDisk done with 0x%x\r\n"), pDisk));
} // CloseDisk
#ifdef DEBUG
LPTSTR WaitTypes[4] = {
TEXT("WAIT_TYPE_BUSY"),
TEXT("WAIT_TYPE_NOT_BUSY"),
TEXT("WAIT_TYPE_READY"),
TEXT("WAIT_TYPE_DRQ")
};
#endif
#define WAIT_TYPE_BUSY 1
#define WAIT_TYPE_NOT_BUSY 2
#define WAIT_TYPE_READY 3
#define WAIT_TYPE_DRQ 4 // wait for data request
#define WAIT_TIME_NORMAL 3000
#define WAIT_TIME_LONG 30000
//
// ATAWaitForDisk
//
DWORD
ATAWaitForDisk(
PDISK pDisk,
DWORD Times,
UCHAR Type
)
{
UCHAR ata_status = 0;
DWORD error = ERROR_SUCCESS;
DWORD start = GetTickCount();
while (Times) {
if ((pDisk->d_DiskCardState == STATE_DEAD) ||
(pDisk->d_DiskCardState == STATE_REMOVED)) {
DEBUGMSG(ATAPI_IO|ATAPI_ERROR,
(TEXT("ATAPI:ATAWaitForDisk - STATE_DEAD!\r\n")));
return GetDiskStateError(pDisk->d_DiskCardState);
}
try {
ata_status = ATA_READ_UCHAR(pDisk->d_pATAReg + ATA_REG_STATUS);
} except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG(ATAPI_IO|ATAPI_ERROR, (TEXT("ATAPI:ATAWaitForDisk - exception!\r\n")));
error = GetDiskStateError(pDisk->d_DiskCardState);
}
if (error != ERROR_SUCCESS) {
return error;
}
DEBUGMSG(ATAPI_IO,
(TEXT("ATAPI:ATAWaitForDisk - ata_status = 0x%x\r\n"), ata_status));
switch (Type) {
case WAIT_TYPE_BUSY:
if (ata_status & ATA_STATUS_BUSY) {
DEBUGMSG(ATAPI_IO,
(TEXT("ATAPI:ATAWaitForDisk - ATA_STATUS_BUSY\r\n")));
goto awfd_done;
}
break;
case WAIT_TYPE_NOT_BUSY:
if (!(ata_status & ATA_STATUS_BUSY)) {
goto awfd_done;
}
break;
case WAIT_TYPE_READY:
if (ata_status & ATA_STATUS_READY) {
DEBUGMSG(ATAPI_IO,
(TEXT("ATAPI:ATAWaitForDisk - ATA_STATUS_READY 0x%x\r\n"),
ata_status));
Sleep(1);
goto awfd_done;
}
break;
case WAIT_TYPE_DRQ:
if (ata_status & ATA_STATUS_DATA_REQ) {
goto awfd_done;
}
break;
}
//
// Since Sleep(1) can be as long as a time slice (~25ms),
// this loop is limited by looking at the milliseconds elapsed.
//
if ((GetTickCount() - start) >= Times) {
Times = 0;
}
}
awfd_done:
if (Times == 0) {
DEBUGMSG(ATAPI_IO|ATAPI_ERROR,
(TEXT("ATAPI:ATAWaitForDisk - %s wait timed out\r\n"),
WaitTypes[Type-1]));
return GetDiskStateError(pDisk->d_DiskCardState);
} else {
return ERROR_SUCCESS;
}
} // ATAWaitForDisk
//
// ATASetSector - write a sector number to the appropriate ATA registers taking
// into account for the mode being used (LBA or CHS). Also write the next
// command.
//
DWORD
ATASetSector(
PDISK pDisk,
DWORD sectno,
DWORD cmd
)
{
PUCHAR base;
DWORD sectors;
DWORD heads;
base = pDisk->d_pATAReg;
ATA_WRITE_UCHAR(base + ATA_REG_SECT_CNT, 1);
if (pDisk->d_fLBAMode == TRUE) {
ATA_WRITE_UCHAR(base + ATA_REG_SECT_NUM, (UCHAR)sectno);
ATA_WRITE_UCHAR(base + ATA_REG_CYL_LOW, (UCHAR)(sectno >> 8));
ATA_WRITE_UCHAR(base + ATA_REG_CYL_HIGH, (UCHAR)(sectno >> 16));
ATA_WRITE_UCHAR(base + ATA_REG_DRV_HEAD,
(UCHAR)(((UCHAR)(sectno>>24))|ATA_HEAD_LBA_MODE|ATA_HEAD_DRIVE_1));
} else { // translate LBA to CHS format
sectors = pDisk->d_DiskInfo.di_sectors;
heads = pDisk->d_DiskInfo.di_heads;
ATA_WRITE_UCHAR(base+ATA_REG_SECT_NUM, (UCHAR)((sectno%sectors)+1));
ATA_WRITE_UCHAR(base+ATA_REG_CYL_LOW, (UCHAR)(sectno/(sectors*heads)));
ATA_WRITE_UCHAR(base+ATA_REG_CYL_HIGH,
(UCHAR)((sectno/(sectors*heads)) >> 8));
ATA_WRITE_UCHAR(base + ATA_REG_DRV_HEAD,
(UCHAR)(((sectno/sectors)%heads)|ATA_HEAD_DRIVE_1));
}
ATA_WRITE_UCHAR(base + ATA_REG_COMMAND, (UCHAR)cmd);
return ERROR_SUCCESS;
} // ATASetSector
//
// CDSeek -
//
DWORD
CDSeek(
PDISK pDisk,
PSG_REQ pSgr
)
{
DWORD dwWaitTime = INFINITE;
WORD dwTimer;
WORD dwCount;
ATAPI_errcode = NO_ERROR;
dwCount = 0;
RetrySeek:
dwTimer = 0;
while( ( *ATAPI_STAT & 0x88 ) != 0){ // Status Reg BSY , DRQ = 0
Sleep(ATAPI_SLEEP); // 100ms SLEEP
dwTimer++;
if(dwTimer>ATAPI_SLEEP)
break;
}
if(dwTimer>ATAPI_SLEEP){
pSgr->sr_status = ERROR_NOT_READY;
return FALSE;
}
*ATAPI_DSEL = 0xa0; // Device Select ( DRIVE 0 master )
dwTimer = 0;
while( ( *ATAPI_STAT & 0x88 ) != 0){ // Status Reg BSY , DRQ = 0
Sleep(ATAPI_SLEEP); // 100ms SLEEP
dwTimer++;
if(dwTimer>ATAPI_SLEEP)
break;
}
if(dwTimer>ATAPI_SLEEP){
pSgr->sr_status = ERROR_NOT_READY;
return FALSE;
}
CD_ROM_STA.flag = ATAPI_ATAPROC; // Send ATA Command
// PACKET command protocol
*ATAPI_FETR = 0x00; // ATAPI Features ( Not use OverLap and DMA )
*ATAPI_IRRN = 0; // Sector Count
*ATAPI_RSVE = 0; // Sector Number
*ATAPI_BCTL = 0; // Byte Count Low ( byte )
*ATAPI_BCTH = 0x80; // Byte Count High
*ATAPI_DCTR = 0x02; // Device Control ( INTRQ-ON : 0x00 OFF : 0x02)
*ATAPI_COMD = ATPCOM_ATAPIPAKET; // ATA Command ( Packet Command A0)
dwTimer = 0;
// Status Reg BSY=0 , DRQ=1 ?
while( ( *ATAPI_STAT & ATPMASK_BUSYDREQ ) != 0x08 ){// Status BSY=0,DRQ=1 then next
Sleep(ATAPI_SLEEP); // 100ms SLEEP
dwTimer++;
if(dwTimer>ATAPI_SLEEP)
break;
}
if(dwTimer>ATAPI_SLEEP){
pSgr->sr_status = ERROR_NOT_READY;
return FALSE;
}
if( ( *ATAPI_STAT & ATPMASK_CHEK) != 0 ){ // Error ?
GetATAPError();
pSgr->sr_status = ATAPI_errcode;
return FALSE;
}
CD_ROM_STA.flag = ATAPI_READPROC; // Read flag On
// SEEK command
*ATAPI_DATW = ATAPI_SEEK; // SEEK Command code (2bh)
*ATAPI_DATW = dwHighLBA; // 2 Logical Block Address(MSB)
*ATAPI_DATW = dwLowLBA; // 4 Logical Block Address(LSB)
*ATAPI_DATW = 0; // 6 reserved
*ATAPI_DATW = 0; // 8 reserved
*ATAPI_DATW = 0; //10 reserved
// Complete CD SEEK operation 丠
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){
pSgr->sr_status = 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 RetrySeek;
}
}
}
if(SenseKey==0x06){
if(SenseCode==0x28){ //NOT READY TO READY TRANSITION
if(dwCount<100){
dwCount++;
ATAPI_errcode = NO_ERROR; //RETRY SEEK 100TIMES
goto RetrySeek;
}
}
}
pSgr->sr_status = ATAPI_errcode; // return ATAPI_errcode;
return FALSE;
}
return ATAPI_errcode;
}
//
// CDRead - fulfill one scatter/gather read request
//
DWORD
CDRead(
PDISK pDisk,
PSG_REQ pSgr
)
{
DWORD dwWaitTime = INFINITE;
WORD dwTimer;
WORD dwCount;
PSG_REQ pSG;
ATAPI_errcode = 0;
dwCount = 0;
pSG = (PSG_REQ)pSgr;
//CD READ PROCESS
RetryRead:
/*****************************************************************************
* Modification for Aspen doen by Maneesh Gupta
*
* Sometimes the CD-Drive is not ready for responding to Read commands.So for
* such conditions we first check whether drive is ready or not.If the drive
* is not ready then Drive is made ready by issuing the Start Atapi Unit comm-
* and.
****************************************************************************/
DEBUGMSG( ATAPI_ERROR, (TEXT("TurnATAPI function Called\r \n")));
if( TurnATAPI() == FALSE )
{
StartATAPIUnit();
}
if(dwCount>ATAPI_SLEEP)
{
if(ATAPI_errcode != ERROR_NO_MEDIA_IN_DRIVE)
{
SetLastError(ATAPI_errcode);
RETAILMSG(1, (TEXT("ATAPI_TESTUNITREADY Command : GetLastError() = %d\r\n"), GetLastError()));
return FALSE;
}
}
/*****************************************************************************
* End of Modification for Aspen doen by Maneesh Gupta
****************************************************************************/
dwTimer = 0;
while( ( *ATAPI_ASTA & 0x88 ) != 0){ // Status Reg BSY , DRQ = 0
Sleep(ATAPI_SLEEP); // 100ms SLEEP
dwTimer++;
if(dwTimer>ATAPI_SLEEP)
break;
}
if(dwTimer>ATAPI_SLEEP){
pSgr->sr_status = ERROR_NOT_READY;
return FALSE;
}
*ATAPI_DSEL = 0xa0; // Device Select ( DRIVE 0 master )
dwTimer = 0;
while( ( *ATAPI_ASTA & 0x88 ) != 0){ // Status Reg BSY , DRQ = 0
Sleep(ATAPI_SLEEP); // 100ms SLEEP
dwTimer++;
if(dwTimer>ATAPI_SLEEP)
break;
}
if(dwTimer>ATAPI_SLEEP){
pSgr->sr_status = ERROR_NOT_READY;
return FALSE;
}
CD_ROM_STA.flag = ATAPI_ATAPROC; // Send ATA Command
// PACKET command protocol
*ATAPI_FETR = 0x00; // ATAPI Features ( Not use OverLap and DMA )
*ATAPI_IRRN = 0; // Sector Count
*ATAPI_RSVE = 0; // Sector Number
*ATAPI_BCTL = 0; // Byte Count Low ( byte )
*ATAPI_BCTH = 0x80; // Byte Count High
*ATAPI_DCTR = 0x00; // Device Control ( INTRQ-ON : 0x00 OFF : 0x02)
*ATAPI_COMD = ATPCOM_ATAPIPAKET; // ATA Command ( Packet Command A0)
dwTimer = 0;
// Status Reg BSY=0 , DRQ=1 ?
while( ( *ATAPI_STAT & ATPMASK_BUSYDREQ ) != 0x08 ){// Status BSY=0,DRQ=1 then next
Sleep(ATAPI_SLEEP); // 100ms SLEEP
dwTimer++;
if(dwTimer>ATAPI_SLEEP)
break;
}
if(dwTimer>ATAPI_SLEEP){
pSgr->sr_status = ERROR_NOT_READY;
return FALSE;
}
if( ( *ATAPI_STAT & ATPMASK_CHEK) != 0 ){ // Error ?
GetATAPError();
pSgr->sr_status = ATAPI_errcode;
return FALSE;
}
CD_ROM_STA.flag = ATAPI_READPROC; // Read flag On
// Write Data Register (Command Packet) MAX255 Block
*ATAPI_DATW = ATAPI_READG12; // READ Command code (A8h)
*ATAPI_DATW = dwHighLBA; // 2 Logical Block Address(MSB)
*ATAPI_DATW = dwLowLBA; // 4 Logical Block Address(LSB)
*ATAPI_DATW = 0; // 6 Transfer Length (MSB)
*ATAPI_DATW = (ushort)datasize.word; // 8 Transfer Length (LSB)
*ATAPI_DATW = 0; //10reserved
if( WaitForSingleObject( pDisk->d_ReadEvent, dwWaitTime ) == WAIT_TIMEOUT ){
DEBUGMSG( ATAPI_ERROR, (TEXT("ATAPI: CD-ROM write interrupt is time out.\r\n")));
}
// Complete CD read operation 丠
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){
pSgr->sr_status = ERROR_NOT_READY;
return FALSE;
}
if( (*ATAPI_STAT & ATPMASK_CHEK) != 0 ){ // Error ?
GetATAPError();
if(NO_ERROR == CDSeek(pDisk, pSG)) { // Read Error If Retry Seek = No_ERROR , Retry CDRead
goto RetryRead;
}
pSgr->sr_status = ATAPI_errcode; // return ATAPI_errcode;
return FALSE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?