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

📄 diskmain.cpp

📁 WinCE5.0BSP for Renesas SH7770
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    }

    AnalyzeDeviceCapabilities(&m_Id, bTransferMode);

    // @bTransferMode is a valid transfer mode
    if (!SetTransferMode(m_bTransferMode)) {
        DEBUGMSG(ZONE_INIT, (_T(
            "Atapi!CDisk::Init> Failed to set transfer mode(0x%x)\r\n"
            ), m_bTransferMode));
    }
	
	SetDeviceTiming(m_dwDeviceId, m_dwPioMode, m_dwDmaMode, m_dwUdmaMode);

    fRet = TRUE;

exit:;
    return fRet;
}

// ----------------------------------------------------------------------------
// Function: ResetController
//     Implement ATA/ATAPI-6 R3B 9.2 (Software reset protocol)
//
// Parameters:
//     bSoftReset -
// ----------------------------------------------------------------------------

BOOL
CDisk::ResetController(
    BOOL bSoftReset // ignore
    )
{
    DWORD dwAttempts = 0;
    BYTE bStatus = 0;
    BOOL fRet = FALSE;

    // we have to negate the RESET signal for 5 microseconds before we assert it

    WriteAltDriveController(0x00);
    ::StallExecution(25);

    // Set_SRST
    // --------
    // to enter Set_SRST state, set SRST in the Device Control register to one;
    // this will assert the RESET signal and reset both devices on the current
    // channel

    WriteAltDriveController(0x04); // 0x04 == SRST

    // remain in this state for at least 5 microseconds; i.e., assert RESET signal
    // for at least 5 microseconds
    // if this is a hardware reset, then assert RESET signal for at least 25
    // microseconds

    ::StallExecution(25); // this should be CEDDK implementation

    // Clear_wait
    // ----------
    // clear SRST in the Device Control register, i.e., negate RESET signal

    WriteAltDriveController(0x00);

    // remain in this state for at least 2 milliseconds

    Sleep(5);

HSR2_Check_status:;

    // Check_status
    // ------------
    // read the Status or Alternate Status register
    // if BSY is set to one, then re-enter this state
    // if BSY is cleared to zero, check the ending status in the Error register
    // and the signature (9.12) and transition to Host_Idle

    bStatus = GetAltStatus(); // read Status register
    if (bStatus & 0x80) {
        // BSY is set to one, re-enter this state
        DEBUGMSG(ZONE_INIT, (TEXT(
            "Atapi!CDisk::ResetController> Device is busy; %u seconds remaining\r\n"
            ), (m_pPort->m_pController->m_pIdeReg->dwSoftResetTimeout - dwAttempts)));
        Sleep(1000);
        dwAttempts += 1;
        // a device has at most 31 seconds to complete a software reset; we'll use 3 seconds
        if (dwAttempts == m_pPort->m_pController->m_pIdeReg->dwSoftResetTimeout) {
            DEBUGMSG(ZONE_INIT, (TEXT("Atapi!CDisk::ResetController> Timeout\r\n")));
            goto exit;
        }
        goto HSR2_Check_status;
    }
    DEBUGMSG(ZONE_INIT, (TEXT(
        "Atapi!CDisk::ResetController> Device is ready\r\n"
        )));

    // BSY is cleared to zero, check the ending status in the Error register
    // and the signature
    // TODO: Check the signature (9.12)

    // if ERR bit set to one, then the reset failed
    bStatus = GetAltStatus(); // read Status register
    if (bStatus & 0x01) {
        // ERR is set to one
        // the bits in the Error register are valid, but the Error register
        // doesn't provide any useful information in the case of SRST failing
        DEBUGMSG(ZONE_INIT, (TEXT(
            "Atapi!CDisk::ResetController> SRST failed\r\n"
            )));
        // TODO: Recover from error
        goto exit;
    }

    fRet = TRUE;

exit:;
    return fRet;
}

// ----------------------------------------------------------------------------
// Function: AtapiSoftReset
//     Issue ATAPI SOFT RESET command
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

void
CDisk::AtapiSoftReset(
    )
{
    WriteCommand(ATAPI_CMD_SOFT_RESET);
    WaitForDisc(WAIT_TYPE_NOT_BUSY, 400);
    WaitForDisc(WAIT_TYPE_READY, 500);
}

// ----------------------------------------------------------------------------
// Function: IsDevicePresent
//     Determine whether a device is present on the channel
//
// Parameters:
//     None
//
// Notes:
//     If a device is present on a channel, then the device's associated
//     Error register is populated with 0x1.  If a device is not present on
//     a channel, then the device's associated Error register is populated
//     with 0xa or 0xb, for master or slave, respectively.
// ----------------------------------------------------------------------------

BOOL
CDisk::IsDevicePresent(
    )
{
    BYTE bError;
    BYTE bStatus;

    // determine which device to select (i.e., which device this device is)
    if ((m_dwDevice == 0) || (m_dwDevice == 2)) {
        // select device 0
        ATA_WRITE_BYTE(m_pATAReg + m_dwDrvHeadOffset, ATA_HEAD_DRIVE_1);
    }
    else {
        // select device 1
        ATA_WRITE_BYTE(m_pATAReg + m_dwDrvHeadOffset, ATA_HEAD_DRIVE_2);
    }

    // read Status register
    bStatus = GetAltStatus();

    // read Error register
    bError = GetError();
    // test Error register
    if (bError == 0x1) {
        DEBUGMSG(ZONE_INIT, (_T(
            "Atapi!CDisk::IsDevicePresent> Device %d is present\r\n"
            ), m_dwDevice));
        return TRUE;
    }
    DEBUGMSG(ZONE_INIT, (_T(
        "Atapi!CDisk::IsDevicePresent> Device %d is not present; Error register(0x%x)\r\n"
        ), m_dwDevice, bError));
    return FALSE;
}

// ----------------------------------------------------------------------------
// Function: SendExecuteDeviceDiagnostic
//     Implement ATA/ATAPI-6 R3B 9.10 (Device diagnostic protocol)
//
// Parameters:
//     pbDiagnosticCode - diagnostic code returned by controller in Error
//                        register as a result of issuing EXECUTE DEVICE
//                        DIAGNOSTIC (8.11)
//
//     pfIsAtapi - whether device is an ATAPI device
// ----------------------------------------------------------------------------

BOOL
CDisk::SendExecuteDeviceDiagnostic(
    PBYTE pbDiagnosticCode,
    PBOOL pfIsAtapi
    )
{
    BYTE bStatus = 0;
    DWORD dwWaitAttempts = 1200;
    BOOL fReadSignature = FALSE;

    PREFAST_DEBUGCHK(NULL != pbDiagnosticCode);
    PREFAST_DEBUGCHK(NULL != pfIsAtapi);

    // HI4:HED0, write command

    WaitOnBusy(FALSE);
    WriteCommand(0x90); // EXECUTE DEVICE DIAGNOSTIC command code

    // HED0:Wait, wait for at least 2 milliseconds; see following Sleep(5)
    // HED2:Check_Status, wait on BSY=0

    while (1) {
        Sleep(5);                 // wait 5 milliseconds
        bStatus = GetAltStatus(); // get status
        // test error
        if (bStatus & ATA_STATUS_ERROR) {
            // error
            DEBUGMSG(ZONE_ERROR, (TEXT(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device failed to process command\r\n"
                ), m_dwDeviceId));
            break;
        }
        // test BSY=0
        if (!(bStatus & ATA_STATUS_BUSY)) break;
        // retry
        if (dwWaitAttempts-- == 0) {
            DEBUGMSG(ZONE_ERROR, (TEXT(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> No response; assuming channel is empty\r\n"
                ), m_dwDeviceId));
            break; // return FALSE;
        }
    }

    // inspect result of diagnosis (table 26, 8.11); select self

    SelectDevice();
    *pbDiagnosticCode = GetError();
    if ((m_dwDevice == 0) || (m_dwDevice == 0)) {
        // device 0 (master)
        if (*pbDiagnosticCode == 0x01) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 passed, Device 1 passed or not present\r\n"
                )));
            fReadSignature = TRUE; // read signature to determine if we're ATA or ATAPI
        }
        else if (*pbDiagnosticCode == 0x00 || (0x02 <= *pbDiagnosticCode && *pbDiagnosticCode <= 0x7F)) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 failed, Device 1 passed or not present\r\n"
                )));
        }
        else if (*pbDiagnosticCode == 0x81) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 passed, Device 1 failed\r\n"
                )));
            fReadSignature = TRUE; // read signature to determine if we're ATA or ATAPI
        }
        else if (*pbDiagnosticCode == 0x80 || (0x82 <= *pbDiagnosticCode && *pbDiagnosticCode <= 0xFF)) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 failed, Device 1 failed\r\n"
                )));
        }
        else {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Unknown diagnostic code(0x%x)\r\n"
                ), *pbDiagnosticCode));
        }
    }
    else {
        // device 1 (slave)
        if (*pbDiagnosticCode == 0x01) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 1 passed\r\n"
                )));
            fReadSignature = TRUE; // read signature to determine if we're ATA or ATAPI
        }
        else if (*pbDiagnosticCode == 0x00 || (0x02 <= *pbDiagnosticCode && *pbDiagnosticCode <= 0x7F)) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 1 failed\r\n"
                )));
        }
        else {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Unknown diagnostic code(0x%x)\r\n"
                ), *pbDiagnosticCode));
        }
    }

    if (fReadSignature) {

        // we passed; read signature to determine if it's ATA or ATAPI

        // test for ATA
        if (
            ATA_READ_BYTE(m_pATAReg + m_dwSectNumOffset) == 0x01 &&
            ATA_READ_BYTE(m_pATAReg + m_dwByteCountLowOffset) == 0x00 &&
            ATA_READ_BYTE(m_pATAReg + m_dwByteCountHighOffset) == 0x00 // &&
            // ATA_READ_BYTE(m_pATAReg + m_dwDrvHeadOffset) == 0x00 &&
            // ATA_READ_BYTE(m_pATAReg + m_dwSectCntReasonOffset) == 0x01 &&
        ) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> ATA device\r\n"
                )));
            *pfIsAtapi = FALSE;
        }
        // test for ATAPI
        else if (
            ATA_READ_BYTE(m_pATAReg + m_dwSectNumOffset) == 0x01 &&
            ATA_READ_BYTE(m_pATAReg + m_dwByteCountLowOffset) == 0x14 &&
            ATA_READ_BYTE(m_pATAReg + m_dwByteCountHighOffset) == 0xEB // &&
            // ATA_READ_BYTE(m_pATAReg + m_dwDrvHeadOffset) == 0x00 &&
            // ATA_READ_BYTE(m_pATAReg + m_dwSectCntReasonOffset) == 0x01 &&
        ) {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> ATAPI device\r\n"
                )));
            *pfIsAtapi = TRUE;
        }
        // unknown
        else {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 = Unknown device type (i.e., not ATA, not ATAPI)\r\n"
                )));
        }
    }

    return TRUE;
}

// ----------------------------------------------------------------------------
// Function: SendIdentifyDevice
//     Issue IDENTIFY_DEVICE or IDENTIFY_PACKET_DEVICE depending on whether
//     fIsAtapi is TRUE.  Implement PIO data-in command protocol as per
//     ATA/ATAPI-6 R3B 9.2.
//     Implement ATA/ATAPI-6 R3B 9.10 (Device diagnostic protocol)
//
// Parameters:
//     fIsAtapi - if device is ATAPI, send IDENTIFY PACKET DEVICE
//
// Notes:
//     After issuing a PIO data-in command, if BSY=0 and DRQ=0, then the device
//     failed to process the command.  However, there exist devices that
//     require additional time to return status via the Status register.  As
//     such, a delayed retry has been introduced to faciliate such devices,
//     even though their actions do not comply with the specification.
// ----------------------------------------------------------------------------

#define HPIOI1_CHECK_STATUS_RETRIES 10
BOOL
CDisk::SendIdentifyDevice(
    BOOL fIsAtapi
    )
{
    BOOL fResult = TRUE;
    DWORD dwRetries = 0;
    BYTE bStatus;               // Status register
    DWORD cbIdentifyDeviceData; // IDENTIFY DEVICE data size

    // Host Idle protocol

    // select correct device
    SelectDevice();

    // HI1:Check_Status
    // ----------------
HI1_Check_Status:;
    bStatus = GetAltStatus();
    if ((bStatus & ATA_STATUS_BUSY) || (bStatus & ATA_STATUS_DATA_REQ)) { // BSY=1 or DRQ=1
        Sleep(5);
        goto HI1_Check_Status;
    }

    // HI3:Write_Parameters
    // --------------------
    // no paramters

    // HI4:Write_Command
    __try {
        WriteCommand(fIsAtapi ? ATAPI_CMD_IDENTIFY : ATA_CMD_IDENTIFY);
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        DEBUGMSG(ZONE_ERROR, (_T(
            "Atapi!CDisk::SendIdentifyDevice> Exception writing to Command register\r\n"
            )));
        fResult = FALSE;
        goto exit;
    }

    // PIO data-in command protocol

    // HPIOI1:Check_Status
    // -------------------
HPIOI1_Check_Status:;
    __try {
        bStatus = GetAltStatus();
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        DEBUGMSG(ZONE_ERROR, (_T(

⌨️ 快捷键说明

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