⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atapiio.cpp

📁 这是运行在windows ce 4.2 版本下的关于硬盘加载的驱动程序
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include "atamain.h"
#undef ZONE_IO
#define ZONE_IO 1

BOOL CDisk::SendIOCommand(DWORD dwStartSector, DWORD dwNumberOfSectors, BYTE bCmd)
{
    
    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:SendIOCommand - Sector %d SectorsLeft %x Command %x\r\n"), dwStartSector,dwNumberOfSectors,bCmd));

    SelectDevice(); 

    if (WaitOnBusy(FALSE)) 
    {
        DEBUGMSG( ZONE_IO, (TEXT("ATAPI:SendIOCommand - Can't send a command!!! Status:%x Error:%x \r\n"), GetAltStatus(),GetError()));
        return (FALSE);
    }
    //
    //  To transfer 256 Sectors set Sector Count Register to 0.
    //
    if(dwNumberOfSectors == MAX_SECT_PER_COMMAND)
            dwNumberOfSectors = 0;

    WriteSectorCount((BYTE)dwNumberOfSectors);

    if (m_fLBAMode == TRUE) 
    {
        WriteSectorNumber( (BYTE)dwStartSector);
        WriteLowCount((BYTE)(dwStartSector >> 8));
        WriteHighCount((BYTE)(dwStartSector >> 16));
        WriteDriveHeadReg((BYTE)((dwStartSector >> 24) | ATA_HEAD_LBA_MODE) | ((m_dwDevice == 0 ) ? ATA_HEAD_DRIVE_1 : ATA_HEAD_DRIVE_2));
                            
    } else {    // translate LBA to CHS format

         DWORD dwSectors  = m_DiskInfo.di_sectors;
        DWORD dwHeads   = m_DiskInfo.di_heads;

        WriteSectorNumber((BYTE)((dwStartSector % dwSectors) + 1));
        WriteLowCount((BYTE) (dwStartSector /(dwSectors*dwHeads)));
        WriteHighCount((BYTE)((dwStartSector /(dwSectors*dwHeads)) >> 8));
        WriteDriveHeadReg((BYTE)(((dwStartSector/dwSectors)% dwHeads) | ((m_dwDevice == 0 ) ? ATA_HEAD_DRIVE_1 : ATA_HEAD_DRIVE_2)));
    }
    WriteCommand(bCmd);
    return (TRUE);
}   

/*------------------------------------------------------------------------------------------*/

BYTE CDisk::WaitOnBusy(BOOL fBase)
{ 
 	DWORD i,j;
	BYTE bStatus;
    for (i=0; i< DEFAULT_WAIT_CHECK_ITER; i++)   {
        for (j=0; j<DEFAULT_WAIT_SAMPLE_TIMES; j++)  {
            bStatus = fBase ? GetBaseStatus() : GetAltStatus();
            if (!(bStatus & ATA_STATUS_BUSY)) {
                return bStatus & (ATA_STATUS_ERROR |ATA_STATUS_BUSY);
            }    
        }
       StallExecution(DEFAULT_WAIT_STALL_TIME);            
	}
	return bStatus & (ATA_STATUS_ERROR |ATA_STATUS_BUSY);
}
/*------------------------------------------------------------------------------------------*/
BOOL CDisk::WaitForDisc(BYTE bStatusType, DWORD dwTimeOut, DWORD dwPeriod)
{
    BYTE bStatusRead;

    bStatusRead = 0;

    if (dwPeriod == 0)
        dwPeriod = dwTimeOut;

    while( TRUE)  {
        bStatusRead = GetAltStatus();
        switch (bStatusType)  {
            case WAIT_TYPE_BUSY:
                if (bStatusRead & ATA_STATUS_BUSY)  {
                    DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_BUSY\r\n")));
                    goto ExitDone;
                }
                break;

            case WAIT_TYPE_NOT_BUSY:
                if (!(bStatusRead & ATA_STATUS_BUSY))  {
                    DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_NOT_BUSY\r\n")));
                    goto ExitDone;
                }
                break;

            case WAIT_TYPE_READY:
                if (bStatusRead & ATA_STATUS_READY) {
                    DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_READY\r\n")));
                    StallExecution(100);
                    goto ExitDone;
                }
                break;

            case WAIT_TYPE_DRQ: 
                if (bStatusRead & ATA_STATUS_DATA_REQ) {
                    DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_DRQ\r\n")));
                    goto ExitDone;
                }
                break;

            case WAIT_TYPE_NOT_DRQ:
                if (!(bStatusRead & ATA_STATUS_DATA_REQ)) {
                    DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_NOT_DRQ\r\n")));
                    goto ExitDone;
                }
                break;
                
            case WAIT_TYPE_ERROR: 
                if (bStatusRead & ATA_STATUS_ERROR) {
                    DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_ERROR\r\n")));
                    goto ExitDone;
                }
                break;                
        }       
        if ((int)dwTimeOut > 0) {
            StallExecution(dwPeriod);
            dwTimeOut -= dwPeriod;
        } else {
            DEBUGMSG(ZONE_ERROR, (TEXT("ATAPI:WaitForDisc - TimeOut !!! WaitType = %ld Status=%02X\r\n"), bStatusType, bStatusRead));
            return ERROR_GEN_FAILURE;
        }    
    }

ExitDone:
    return ERROR_SUCCESS;
}

/*------------------------------------------------------------------------------------------*/
//
//  Wait for DRQ is set and device is read
//  to transfer data or timeout is occured
//  Return (Status == ATA_STATUS_DATA_REQ)
//

BOOL  CDisk::WaitForDRQ() 
{ 
    DWORD i,j;
    BYTE bStatus;
    
    for (i=0; i< DEFAULT_WAIT_CHECK_ITER; i++) {
        for (j=0; j<DEFAULT_WAIT_SAMPLE_TIMES; j++)  { 
            bStatus = GetAltStatus() & (ATA_STATUS_BUSY|ATA_STATUS_DATA_REQ); 

            if (bStatus & ATA_STATUS_BUSY) { 
                continue;
            }
            if (bStatus & ATA_STATUS_DATA_REQ){ 
                DEBUGMSG(ZONE_IO, (TEXT("ATAPI: ATA_STATUS_DATA_REQ J=: %x \r\n"),j));
                return TRUE;
            }
            StallExecution(DEFAULT_WAIT_STALL_TIME);            
        }
        DEBUGMSG( ZONE_WARNING, (TEXT("ATAPI:WaitForDRQ Status=%02X Error=%02X Reason=%02X\r\n"), GetAltStatus(), GetError(), GetReason()));
    } 
    //RetailPrint1("ATAPIPCI: ATA_STATUS_DATA_REQ (Sleep)i= %x \r\n",i);
    return(bStatus == ATA_STATUS_DATA_REQ); 
    
}


/*------------------------------------------------------------------------------------------*/
//                        
//                                          
//  Returns:    An interrupt reason for success; ATA_INTR_ERROR otherwise
//
//          - ATA_INTR_CMD  if Device ready to accept command packed
//          - ATA_INTR_READ if Device ready to transfer Data to Host
//          - ATA_INTR_WRITE if Device ready to read Data from Host 
//          - ATA_INTR_MSG   if Device ready to send message to Host
//          - ATA_INTR_READY if Device completed command processing
//      
//
//  ATAPI Interrupt Reason & Status Reg. Results
//
//                                 DRQ-IO-CoD
//#define ATA_INTR_CMD      5   //   1- 0 - 1 (5) ATA Device acknowledge command
//#define ATA_INTR_MSG      7   //   1- 1 - 1 (7) ATA Device ready to send MSG (Future) to host
//#define ATA_INTR_READ     6   //   1- 1 - 0 (6) ATA Device ready to transfer data to host
//#define ATA_INTR_WRITE    4   //   1- 0 - 0 (4) ATA Device ready to receive data from host
//#define ATA_INTR_READY    3   //   0- 1 - 1 (3) ATA Device Processing Completed
//#define ATA_INTR_ERROR    0   //   Return value in case of Device error
//#define ATA_INTR_DMA  8       //   DMA Interrupt

WORD CDisk::CheckIntrState()
{
    BYTE    bReason, bDRQ;

    WaitOnBusy(FALSE);   

    bReason = GetReason() & (ATA_IR_CoD | ATA_IR_IO);

    bDRQ = GetAltStatus() & ATA_STATUS_DATA_REQ;


    if (bDRQ)
        bReason |=4;

    if (bReason < 3)
        return((WORD) ATA_INTR_READY);

    return ((WORD) bReason);
}

/*------------------------------------------------------------------------------------------*/
 //
//  The smalest transfer unit between Ata device and host is one WORD. 
//  We have to save the last read but unused byte for the following 
//  transaction.

void  CDisk::ReadBuffer(PBYTE pBuffer,DWORD dwCount)
{
    //
    //  This is very unefficient way to solve word allignment violation.

    union {
        WORD us;
        BYTE  uc[2];
    }unisc;


    if (dwCount == 0)
        return;
        
    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:ReadBuffer Entry Status: %x\r\n"),GetAltStatus()));

    // Check whether required byte was already read in previous transaction!
    // Value -1 in m_wNextByte means - no byte was read.

    if (m_wNextByte != 0xFFFF) {
        DEBUGMSG( ZONE_WARNING, (TEXT("ATAPI:ReadBuffer - Unaligned buffer on prevous read!!!\r\n")));
        // Update the first byte.
        *pBuffer++ = (BYTE) m_wNextByte;
        dwCount--; 
    }
    //
    // Check allignemt of pBuffer
    //
    if ((DWORD) pBuffer & 1) {
        DEBUGMSG( ZONE_WARNING, (TEXT("ATAPI:ReadBuffer - Unaligned buffer !!!\r\n")));
        while (dwCount> 1) 
        {
            unisc.us = ReadWord();
            *pBuffer++= unisc.uc[0];
            *pBuffer++= unisc.uc[1];
            dwCount-=2;
        }
    } else {
        ReadWordBuffer((PWORD)pBuffer,(DWORD)(dwCount)/sizeof(SHORT));
        pBuffer += dwCount;
        dwCount &= 1;       // If 1, we need to read the next byte yet
        pBuffer -= dwCount; // Adjust pBuffer if its value is odd
    }
    //
    //  Also we have to read one Word event if need only one byte.
    //  Save unused byte and use it as the first byte in the following SG buffer.
        
    if (dwCount == 1) {
        DEBUGMSG( ZONE_WARNING, (TEXT("ATAPI:ReadBuffer - reading one word!!!\r\n")));
        unisc.us = ReadWord();
        *pBuffer=   unisc.uc[0];
        m_wNextByte = (WORD)unisc.uc[1];    // Save byte for the next SG if 
    }

    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:ReadBuffer Exit Status: %x\r\n"),GetAltStatus()));
}

/*------------------------------------------------------------------------------------------*/
//
//  The smalest transfer unit between Ata device and the host is one WORD. 
//  We have to save the last read but unused byte for the following 
//  transaction.

void  CDisk::WriteBuffer(PBYTE pBuffer, DWORD dwCount)
{
    //
    //  This is very inefficient way to solve word allignment violation.
    union {
        WORD us;
        BYTE  uc[2];
    }unisc;
    
    if (dwCount == 0)
        return;
        
    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:WriteBuffer Entry Status: %x\r\n"),GetAltStatus()));

    // Check whether one byte left from the  previous transaction!
    // Value -1 in m_wNextByte means - no byteleft.

    if (m_wNextByte != 0xFFFF) {
        // Update the first byte
        DEBUGMSG( ZONE_WARNING, (TEXT("ATAPI:ReadBuffer - Unaligned buffer on prevous read!!!\r\n")));
        unisc.uc[0] = (BYTE) m_wNextByte;
        unisc.uc[1] = *pBuffer++;
        dwCount--; 
        WriteWord(unisc.us);
    }
    //
    // Check allignemt of pBuffer
    //
    if ((DWORD) pBuffer & 1) {
        DEBUGMSG( ZONE_WARNING, (TEXT("ATAPI:ReadBuffer - Unaligned buffer !!!\r\n")));
        while (dwCount> 1)  {
            unisc.uc[0] = *pBuffer++;
            unisc.uc[1] = *pBuffer++;
            WriteWord(unisc.us);
            dwCount-=2;
        }
    } else {
        WriteWordBuffer((PWORD)pBuffer,(DWORD)(dwCount)/sizeof(SHORT));
        pBuffer += dwCount;
        dwCount &= 1;       // If 1, we need to write the next byte yet
        pBuffer -= dwCount; // Adjust pBuffer if its value is odd

    }
    //
    //  Also we have to transfer one Word event if need only one byte.
    //  Save unused byte and use it as the first byte in the following SG buffer.
        
    if (dwCount == 1) {
        DEBUGMSG( ZONE_WARNING, (TEXT("ATAPI:ReadBuffer - reading one word!!!\r\n")));
        m_wNextByte = (WORD) *pBuffer;  // Save byte for the next SG if 
    }
    
    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:WriteBuffer Exit Status: %x\r\n"),GetAltStatus()));
}


/*------------------------------------------------------------------------------------------*/
#define IDE_COMMAND_SET_FEATURE                 0xEF

BOOL CDisk::SetTransferMode(BYTE bMode)
 {
    BYTE bError, bStatus;
 
    SelectDevice();

    WaitForDisc(WAIT_TYPE_NOT_BUSY, 100);
    WaitForDisc(WAIT_TYPE_READY, 1000);
    WaitOnBusy(TRUE);
    
    SelectDevice();

    WriteFeature(ATA_SET_TRANSFER_MODE);
    WriteSectorCount( bMode);
    WriteSectorNumber(0);
    WriteLowCount(0);
    WriteHighCount(0);
    WriteCommand( IDE_COMMAND_SET_FEATURE);

    SelectDevice();
    WaitOnBusy(TRUE);
    //
    //  Set Default PIO mode 
    //
    SelectDevice();
    WaitForDisc(WAIT_TYPE_NOT_BUSY, 200);

    bStatus = GetBaseStatus();
    bError = GetError();
    DEBUGMSG( 1, (TEXT("ATAPI:SetTransferMode Mode=%02X Status=%02X Error=%02X\r\n"), bMode, bStatus, bError));
    if ((bStatus & 0x1) && (bError & 0x4)) {
        ResetController(FALSE);
        return FALSE;
    }
    return TRUE;
}

void CDisk::SetBestTransferMode()
{
    if ((m_dwBestPioMode != -1) && (m_dwBestPioMode >= 2)) {
        SetTransferMode( (BYTE)m_dwBestPioMode | ATA_PIO_FCT_MODE);
    }    
#if 0    
    if (m_dwBestMwDmaMode != -1) {
        SetTransferMode( (BYTE)m_dwBestMwDmaMode | ATA_DMA_MULTI_WORD_MODE);
    }
    if (m_dwBestUDmaMode != -1) {
        SetTransferMode( (BYTE)m_dwBestUDmaMode | ATA_DMA_ULTRA_MODE);
    }
#endif
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -