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