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

📄 atapiio.cpp

📁 3sc2443的CF卡IDE源代码,肯定好用.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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>

// ----------------------------------------------------------------------------
// Function: SendIOCommand
//     Issue I/O command
//
// Parameters:
//     pId -
//     dwNumberOfSectors -
//     bCmd -
// ----------------------------------------------------------------------------

BOOL
CDisk::SendIOCommand(
    DWORD dwStartSector,
    DWORD dwNumberOfSectors,
    BYTE bCmd
    )
{
    DEBUGMSG(ZONE_IO, (TEXT(
        "Atapi!CDisk::SendIOCommand> sector(%d), sectors left(%x), command(%x)\r\n"
        ), dwStartSector,dwNumberOfSectors,bCmd));

    if (ZONE_CELOG) CeLogData(TRUE, CELID_ATAPI_IOCOMMAND, &bCmd, sizeof(bCmd), 0, CELZONE_ALWAYSON, 0, FALSE);

    SelectDevice();

    if (WaitOnBusy(FALSE)) {
        DEBUGMSG(ZONE_IO, (TEXT(
            "Atapi!CDisk::SendIOCommand> Failed to send command; status(%x), error(%x)\r\n"
            ), GetAltStatus(),GetError()));
        RETAILMSG(1, (TEXT(
            "Atapi!CDisk::SendIOCommand> Failed to send command; status(%x), error(%x)\r\n"
            ), GetAltStatus(),GetError()));            
        return FALSE;
    }

    if (m_fUseLBA48) {
        // to transfer 65536 sectors, set number of sectors to 0
        ASSERT(dwNumberOfSectors <= MAX_SECT_PER_EXT_COMMAND);
        if (dwNumberOfSectors == MAX_SECT_PER_EXT_COMMAND) {
            dwNumberOfSectors = 0;
        }

        WriteSectorCount((BYTE)(dwNumberOfSectors >> 8));   // Sector Count 15:8
        WriteSectorCount((BYTE)(dwNumberOfSectors));        // Sector Count 7:0

        // CE supports only 32-bit LBA.  Therefore, clear the upper 16 bits of LBA.
        WriteHighCount(0);    // LBA 47:40
        WriteLowCount(0);     // LBA 39:32
        WriteSectorNumber((BYTE)(dwStartSector >> 24));   // LBA 31:24
        WriteHighCount((BYTE)(dwStartSector >> 16));  // LBA 23:16
        WriteLowCount((BYTE)(dwStartSector >> 8));    // LBA 15:8
        WriteSectorNumber((BYTE)dwStartSector);           // LBA 7:0
        WriteDriveHeadReg( ATA_HEAD_LBA_MODE | ((m_dwDevice == 0 ) ? ATA_HEAD_DRIVE_1 : ATA_HEAD_DRIVE_2));
    }
    else {
        ASSERT(dwNumberOfSectors <= MAX_SECT_PER_COMMAND);
        // to transfer 256 sectors, set number of sectors to 0
        if (dwNumberOfSectors == MAX_SECT_PER_COMMAND) {
            dwNumberOfSectors = 0;
        }

        WriteSectorCount((BYTE)dwNumberOfSectors);
        if (m_fLBAMode == TRUE) {
            ASSERT((dwStartSector >> 28) == 0);
            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 {
            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);
}

// ----------------------------------------------------------------------------
// Function: WaitOnBusy
//     Wait for BSY=0
//
// Parameters:
//     fBase -
// ----------------------------------------------------------------------------

BYTE
CDisk::WaitOnBusy(
    BOOL fBase
    )
{
    DWORD i, j;
    BYTE bStatus = 0;
    for (i = 0; i < m_dwWaitCheckIter; i++) {
        for (j = 0; j < m_dwWaitSampleTimes; j++)  {
            bStatus = fBase ? GetBaseStatus() : GetAltStatus();
            if (!(bStatus & ATA_STATUS_BUSY)) {
                return bStatus & (ATA_STATUS_ERROR |ATA_STATUS_BUSY);
            }
        }
       StallExecution(m_dwWaitStallTime);
    }
    return bStatus & (ATA_STATUS_ERROR |ATA_STATUS_BUSY);
}

// ----------------------------------------------------------------------------
// Function: WaitForDisc
//     Generic wait routine; wait for @bStatusType
//
// Parameters:
//     bStatusType -
//     dwTimeOut -
//     dwPeriod -
// ----------------------------------------------------------------------------

BOOL
CDisk::WaitForDisc(
    BYTE bStatusType,
    DWORD dwTimeOut,
    DWORD dwPeriod
    )
{
    BYTE 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!CDisk::WaitForDisc> WAIT_TYPE_BUSY\r\n")));
                    goto ExitDone;
                }
                break;
            case WAIT_TYPE_NOT_BUSY:
                if (!(bStatusRead & ATA_STATUS_BUSY)) {
                    DEBUGMSG(ZONE_IO, (TEXT("Atapi!CDisk::WaitForDisc> WAIT_TYPE_NOT_BUSY\r\n")));
                    goto ExitDone;
                }
                break;
            case WAIT_TYPE_READY:
                if (bStatusRead & ATA_STATUS_READY) {
                    DEBUGMSG(ZONE_IO, (TEXT("Atapi!CDisk::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!CDisk::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!CDisk::WaitForDisc> WAIT_TYPE_NOT_DRQ\r\n")));
                    goto ExitDone;
                }
                break;
            case WAIT_TYPE_ERROR:
                if (bStatusRead & ATA_STATUS_ERROR) {
                    DEBUGMSG(ZONE_IO, (TEXT("Atapi!CDisk::WaitForDisc> WAIT_TYPE_ERROR\r\n")));
                    goto ExitDone;
                }
                break;
        }
        if ((int)dwTimeOut > 0) {
            StallExecution(dwPeriod);
            dwTimeOut -= dwPeriod;
        }
        else {
            DEBUGMSG(ZONE_ERROR, (TEXT(
                "Atapi!CDisk::WaitForDisc> timeout; bStatusType(%d); status(%02X)\r\n"
                ), bStatusType, bStatusRead));
            return ERROR_GEN_FAILURE;
        }
    }
ExitDone:
    return ERROR_SUCCESS;
}

// ----------------------------------------------------------------------------
// Function: WaitForDRQ
//     Wait for DRQ=1 (and device ready to transfer) or timeout
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

BOOL
CDisk::WaitForDRQ(
    )
{
    DWORD i,j;
    BYTE bStatus = 0;

    if (ZONE_CELOG) CeLogData(TRUE, CELID_ATAPI_WAITDRQ, NULL, 0, 0, CELZONE_ALWAYSON, 0, FALSE);

    for (i = 0; i < m_dwWaitCheckIter; i++) {
        for (j = 0; j < m_dwWaitSampleTimes; j++) {
            bStatus = GetAltStatus() & (ATA_STATUS_BUSY|ATA_STATUS_DATA_REQ);
            if ((bStatus & ATA_STATUS_BUSY) == 0) {
                if (bStatus & ATA_STATUS_DATA_REQ){
                    if (ZONE_CELOG) CeLogData(TRUE, CELID_ATAPI_STATUSWAITDRQ, &bStatus, sizeof(bStatus), 0, CELZONE_ALWAYSON, 0, FALSE);
                    return TRUE;
                }
            }
            StallExecution(m_dwWaitStallTime);
        }
        DEBUGMSG(ZONE_WARNING, (TEXT(
            "Atapi!CDisk::WaitForDRQ> status(%02X), error(%02X), reason(%02X)\r\n"
            ), GetAltStatus(), GetError(), GetReason()));
    }

    if (ZONE_CELOG) CeLogData(TRUE, CELID_ATAPI_STATUSWAITDRQ, &bStatus, sizeof(bStatus), 0, CELZONE_ALWAYSON, 0, FALSE);

    return (bStatus == ATA_STATUS_DATA_REQ);
}

// ----------------------------------------------------------------------------
// Function: CheckIntrState

⌨️ 快捷键说明

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