예제 #1
0
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));

    RETAILMSG(0, (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) {
        ASSERT(dwNumberOfSectors <= MAX_SECT_PER_EXT_COMMAND);
        // to transfer 65536 sectors, set number of sectors to 0
        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 as of now.  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 {
예제 #2
0
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()));
        return FALSE;
    }

    // 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) {
        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));
    }
예제 #3
0
BOOL
CST202T_SATA::ResetController(
    BOOL bSoftReset // ignore
    )
{
    DWORD dwAttempts = 0;
    DWORD dwStatus = 0;
    BYTE bStatus = 0;
    BOOL fRet = FALSE;

    ToggleOOB(SATA_SCONTROL_SPD_1_5_SPEEDLIMIT);  // This part supports generation 1 speeds only.

    // SError will reflect several transient error conditions resulting from
    // the reset sequence.  Clear them now.
    m_pRegSATA->dwSError = m_pRegSATA->dwSError;

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

    WriteAltDriveController(0x00);
    Sleep(2);
    ::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
    Sleep(2);
    ::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
        if ( !((m_pPort->m_pController->m_pIdeReg->dwSoftResetTimeout - dwAttempts) % 100) )
            {
            DEBUGMSG(ZONE_INIT, (TEXT(
                "Atapi!CDisk::ResetController> Device is busy; %u seconds remaining\r\n"
                ), ((m_pPort->m_pController->m_pIdeReg->dwSoftResetTimeout - dwAttempts)/100)));
            }

        Sleep(10);
        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)

    // From SATA 1.0A, seciton 9.1, 9.3, and 9.4:
    // Bit 0 of Error register is set to 1 if the reset succeeded.
    BYTE bError;
    bError = GetError();        // read Error register
    bStatus = GetAltStatus();   // read Status register
    if (!(bError & 0x01)) {
        DEBUGMSG(ZONE_INIT, (TEXT(
            "Atapi!CDisk::ResetController> SRST failed.  Error = 0x%x, Status = 0x%x\r\n"
            ), bError, bStatus));
        // TODO: Recover from error
        goto exit;
    }

    fRet = TRUE;

exit:;
    // SError will reflect several transient error conditions resulting from
    // the reset sequence.  Clear them now.
    m_pRegSATA->dwSError = m_pRegSATA->dwSError;

    // Clear any pending interrupt
    bStatus = GetBaseStatus();

    // Enable the SATA error interrupt (this is cleared by the COMRESET sequence).
    EnableSErrorInt(TRUE);

    return fRet;
}