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

📄 diskmain.cpp

📁 Samsung公司S3C6400芯片的BSP源码包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        else // CDisk::Identify has determined that the devce supports multi-sector transfers
            {
            m_bReadCommand = ATA_CMD_READ_MULTIPLE_EXT;
            m_bWriteCommand = ATA_CMD_WRITE_MULTIPLE_EXT;
            }

        m_bDMAReadCommand = ATA_CMD_READ_DMA_EXT;
        m_bDMAWriteCommand = ATA_CMD_WRITE_DMA_EXT;

        }
    else
        {
        m_fUseLBA48 = FALSE;
        }
}

// ----------------------------------------------------------------------------
// Function: ValidateSg
//     Map embedded pointers
//
// Parameters:
//     pSgReq -
//     InBufLen - The size of the actual buffer as specified by the user.
//                This needs to be cross checked with pSgReq->sr_num_sg to
//                prevent buffer overflows
//     saveoldptrs - Your old pointers are saved here. Must be at least
//                   pSgReq->sr_num_sg in size
// ----------------------------------------------------------------------------

BOOL
CDisk::ValidateSg(
    PSG_REQ pSgReq,
    DWORD InBufLen,
    DWORD dwArgType,
    OUT PUCHAR * saveoldptrs
    )
{
    DWORD dwIndex ;
    PUCHAR ptemp;

    if (NULL == pSgReq) {
        ASSERT(pSgReq);
        return FALSE;
    }

    if (InBufLen < sizeof(SG_REQ)) {
        ASSERT(InBufLen >= sizeof(SG_REQ));
        return FALSE;
    }

    // pSgReq is a sterile copy of the caller's SG_REQ; we're supposed to map
    // the embedded sb_bufs back into the SG_REQ

    if(
        !(pSgReq->sr_num_sg >= 1) ||
        !(pSgReq->sr_num_sg <= MAX_SG_BUF) ||
        !((sizeof(SG_REQ) + sizeof(SG_BUF)*(pSgReq->sr_num_sg-1)) == InBufLen) ||
        !(pSgReq->sr_num_sec > 0))
    {
        ASSERT(pSgReq->sr_num_sg >= 1);
        ASSERT(pSgReq->sr_num_sg <= MAX_SG_BUF);
        ASSERT((sizeof(SG_REQ) + sizeof(SG_BUF)*(pSgReq->sr_num_sg-1)) == InBufLen);
        ASSERT(pSgReq->sr_num_sec > 0);
        return FALSE;
    }

    for (dwIndex = 0; dwIndex < pSgReq->sr_num_sg; dwIndex++) {
        if (
            (NULL == pSgReq->sr_sglist[dwIndex].sb_buf) ||
            (0 == pSgReq->sr_sglist[dwIndex].sb_len)
        ) {
            goto CleanUpLeak;
        }

        // Verify embedded pointer access and map user mode pointers

        if (FAILED(CeOpenCallerBuffer(
                    (PVOID *)&ptemp,
                    (LPVOID)pSgReq->sr_sglist[dwIndex].sb_buf,
                    pSgReq->sr_sglist[dwIndex].sb_len,
                    dwArgType,
                    FALSE)))
        {
            goto CleanUpLeak;
        }

        saveoldptrs[dwIndex] = pSgReq->sr_sglist[dwIndex].sb_buf;
        pSgReq->sr_sglist[dwIndex].sb_buf = ptemp;

        if (NULL == pSgReq->sr_sglist[dwIndex].sb_buf) {
            goto CleanUpLeak;
        }
    }

    return TRUE;

CleanUpLeak:

    if (FAILED(UnmapSg(
                pSgReq->sr_sglist,
                saveoldptrs,
                dwIndex,
                dwArgType)))
    {
        ASSERT(!"Cleanup call to CeCloseCallerBuffer failed unexpectedly");
        return FALSE;
    }

    return FALSE;

}


// ----------------------------------------------------------------------------
// Function: UnmapSg
//     UnMap embedded pointers, previously mapped by ValidateSg.
//     Basically, an SG Array version of CeCloseCallerBuffer
//
// Parameters:
//     sr_sglist - List of mapped SG buffers to unmap
//     saveoldptrs - List of old unmapped pointers
//     sr_sglistlen - The size of sr_sglist
//     dwArgType - ARG_O_PTR/ ARG_I_PTR
//     Return value -  HRESULT from a failed call to CeCloseCallerBuffer
//                     otherwise ERROR_SUCCESS
// ----------------------------------------------------------------------------

HRESULT
CDisk::UnmapSg(
    IN const SG_BUF * sr_sglist,
    IN const PUCHAR * saveoldptrs,
    IN DWORD sr_sglistlen,
    IN DWORD dwArgType
    )
{
    HRESULT dwError = ERROR_SUCCESS;    
    ASSERT(sr_sglistlen <= MAX_SG_BUF);
    
    for (DWORD dwIndex = 0; dwIndex < sr_sglistlen; dwIndex++) {

        HRESULT dwtemp;
        ASSERT(NULL != sr_sglist[dwIndex].sb_buf);
        ASSERT(0 != sr_sglist[dwIndex].sb_len);

        // Close pointers previously mapped in ValidateSg

        dwtemp = CeCloseCallerBuffer(
                    (LPVOID)sr_sglist[dwIndex].sb_buf,
                    (LPVOID)saveoldptrs[dwIndex],
                    sr_sglist[dwIndex].sb_len,
                    dwArgType);
        
        if (FAILED(dwtemp)) {
            ASSERT(!"Cleanup call to CeCloseCallerBuffer failed unexpectedly");
            dwError = dwtemp;
        }
    }

    return dwError;
    
}

// ----------------------------------------------------------------------------
// Function: SendDiskPowerCommand
//     Put the device into a specified power state.  The optional parameter is
//     programmed into the Sector Count register, which is used for the
//     ATA NEW CMD IDLE and ATA CMD STANDBY commands.
//
// Parameters:
//     bCmd -
//     bParam -
// ----------------------------------------------------------------------------

BOOL
CDisk::SendDiskPowerCommand(
    BYTE bCmd,
    BYTE bParam
    )
{
    BYTE bError, bStatus;
    BOOL fOk = TRUE;

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

    // HI:Check_Status (Host Idle); wait until BSY=0 and DRQ=0
    // read Status register
    while (1) {
        bStatus = GetAltStatus();
        if (!(bStatus & (0x80|0x08))) break; // BSY := Bit 7, DRQ := Bit 3
        Sleep(5);
    }

    // HI:Device_Select; select device
    SelectDevice();

    // HI:Check_Status (Host Idle); wait until BSY=0 and DRQ=0
    // read Status register
    while (1) {
        bStatus = GetAltStatus();
        if (!(bStatus & (0x80|0x08))) break; // BSY := Bit 7, DRQ := Bit 3
        Sleep(5);
    }

    // HI:Write_Parameters
    WriteSectorCount(bParam);
    // WriteAltDriveController(0x00); // disable interrupt (nIEN := Bit 1 of Device Control register)

    // HI:Write_Command
    WriteCommand(bCmd);

    // transition to non-data command protocol

    // HND:INTRQ_Wait
    // transition to HND:Check_Status
    // read Status register
    while (1) { // BSY := Bit 7
        bStatus = GetAltStatus();
        bError = GetError();
        if (bError & 0x04) { // ABRT := Bit 2
            // command was aborted
            DEBUGMSG(ZONE_ERROR, (_T(
                "Atapi!CDisk::SendDiskPowerCommand> Failed to send command 0x%x, parameter 0x%x\r\n"
                ), bCmd, bParam));
            fOk = FALSE;
            break;
        }
        if (!(bStatus & 0x80)) break; // BSY := Bit 7
        Sleep(5);
    }

    // transition to host idle protocol

    return fOk;
}

// ----------------------------------------------------------------------------
// Function: GetDiskPowerInterface
//     Return the power management object associated with this device
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

CDiskPower *
CDisk::GetDiskPowerInterface(
    void
    )
{
    CDiskPower *pDiskPower = new CDiskPower;
    return pDiskPower;
}

// ----------------------------------------------------------------------------
// Function: SetDiskPowerState
//     Map a power state to an ATA power management command and issue the
//     command
//
// Parameters:
//     newDx -
// ----------------------------------------------------------------------------

BOOL
CDisk::SetDiskPowerState(
    CEDEVICE_POWER_STATE newDx
    )
{
    BYTE bCmd;

    if (ZONE_CELOG) {
        DWORD dwDx = (DWORD) newDx;
        CeLogData(TRUE, CELID_ATAPI_SETDEVICEPOWER, &dwDx, sizeof(dwDx), 0, CELZONE_ALWAYSON, 0, FALSE);
    }

    // on D0 go to IDLE to minimize latency during disk accesses
    if(newDx == D0 || newDx == D1) {
        bCmd = ATA_CMD_IDLE_IMMEDIATE;
    }
    else if(newDx == D2) {
        bCmd = ATA_CMD_STANDBY_IMMEDIATE;
    }
    else if(newDx == D3 || newDx == D4) {
        bCmd = ATA_CMD_SLEEP;
    }
    else {
        DEBUGMSG(ZONE_WARNING, (_T(
            "CDisk::SetDiskPowerState> Invalid power state value(%u)\r\n"
            ), newDx));
        return FALSE;
    }

    // update the disk power state
    return SendDiskPowerCommand(bCmd);
}

// ----------------------------------------------------------------------------
// Function: WakeUp
//     Wake the device up from sleep
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

BOOL
CDisk::WakeUp(
    )
{
    if (!ResetController(FALSE)) {
        return FALSE;
    }
    return SendIdentifyDevice(IsAtapiDevice());
}

// ----------------------------------------------------------------------------
// Function: MainIoctl
//     Process IOCTL_DISK_ and DISK_IOCTL_ I/O controls
//
// Parameters:
//     pIOReq -
// ----------------------------------------------------------------------------
DWORD CDisk::MainIoctl(PIOREQ pIOReq)
{
    DWORD dwError = ERROR_SUCCESS;

    DEBUGMSG(ZONE_IOCTL, (TEXT("Atapi!CDisk::MainIoctl> IOCTL(%x), device(%x)\r\n"), pIOReq->dwCode, m_dwDeviceId));

    // If device is powering down, then fail.
    if (m_dwDeviceFlags & DFLAGS_DEVICE_PWRDN) {
        SetLastError(ERROR_DEVICE_NOT_AVAILABLE);
        return FALSE;
    }
    switch(pIOReq->dwCode) {
        case IOCTL_DISK_GETINFO:
        case DISK_IOCTL_GETINFO:
            if (IsCDRomDevice()) {
                dwError = ERROR_BAD_COMMAND;
            }
            else {
                dwError = GetDiskInfo(pIOReq);
            }
            break;
        case IOCTL_DISK_DEVICE_INFO:
            dwError = GetDeviceInfo(pIOReq);
            break;
        case DISK_IOCTL_GETNAME:
        case IOCTL_DISK_GETNAME:
            dwError = GetDiskName(pIOReq);
            break;
        case DISK_IOCTL_SETINFO:
        case IOCTL_DISK_SETINFO:
            dwError = SetDiskInfo(pIOReq);
            break;
        case DISK_IOCTL_READ:
        case IOCTL_DISK_READ:
        case DISK_IOCTL_WRITE:
        case IOCTL_DISK_WRITE:
        {
            PSG_REQ pUnsafeInBuf = (PSG_REQ)pIOReq->pInBuf;
            BOOL    fRead = (pIOReq->dwCode == DISK_IOCTL_READ || pIOReq->dwCode == IOCTL_DISK_READ);

			//RETAILMSG(1,(TEXT("######### fRead %d BufLength 0x%x ##########\n"),fRead,pUnsafeInBuf->sr_sglist[0].sb_len));

            if (!pIOReq->dwInBufSize || !pIOReq->pInBuf) {
                dwError = ERROR_INVALID_PARAMETER;
                break;
            }
            
            if (pIOReq->dwInBufSize >(sizeof(SG_REQ) + ((MAX_SG_BUF) - 1) * sizeof(SG_BUF))) {
                dwError = ERROR_INVALID_PARAMETER;
                // size of m_pSterileIoRequest is sizeof(SG_REQ) + ((MAX_SG_BUF) - 1) * sizeof(SG_BUF))
                break;
            }

            // Copy the caller's SG_REQ.
            if (0 == CeSafeCopyMemory((LPVOID)m_pSterileIoRequest, (LPVOID)pUnsafeInBuf, pIOReq->dwInBufSize)) {
                dwError = ERROR_INVALID_PARAMETER;
                break;
            }

            if (NULL == m_pSterileIoRequest) {
                ASSERT(m_pSterileIoRequest);

⌨️ 快捷键说明

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