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

📄 atapiromi.cpp

📁 三星ARM9系列CPU S3C2440A的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    *pdwAddr = TransLogicalAddress.LowPart;

    return TRUE;
}

// ----------------------------------------------------------------------------
// Function: SetupDMA
//     Prepare DMA transfer
//
// Parameters:
//     pSgBuf -
//     dwSgCount -
//     fRead -
// ----------------------------------------------------------------------------

BOOL
CRomiDisk::SetupDMA(
    PSG_BUF pSgBuf,
    DWORD dwSgCount,
    BOOL fRead
    )
{
    DWORD dwAlignMask = m_dwDMAAlign - 1;
    DWORD dwPageMask = UserKInfo[KINX_PAGESIZE] - 1;

    DWORD iPage = 0, iPFN, iBuffer;
    BOOL fUnalign = FALSE;

    DMA_ADAPTER_OBJECT Adapter;

    Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
    Adapter.InterfaceType = (INTERFACE_TYPE)m_pPort->m_pController->m_dwi.dwInterfaceType;
    Adapter.BusNumber = m_pPort->m_pController->m_dwi.dwBusNumber;

    DEBUGMSG(ZONE_DMA, (_T(
        "Atapi!CRomiDisk::SetupDMA> Request(%s), SgCount(%d)\r\n"
        ), fRead ? (_T("Read")) : (_T("Write")), dwSgCount));

    // disable bus master
    WriteBMCommand(0);

    if (!m_pPRD) {
        m_pPRD = (PDMATable)HalAllocateCommonBuffer(&Adapter,
            UserKInfo[KINX_PAGESIZE], (PPHYSICAL_ADDRESS)&m_pPRDPhys, FALSE);
        if (!m_pPRD) {
            goto ExitFailure;
        }
    }

    // m_pPhysList tracks pages used for DMA buffers when the scatter/gather
    // buffer is unaligned
    if (!m_pPhysList) {
        m_pPhysList = (PPhysTable)VirtualAlloc(m_pStartMemory, UserKInfo[KINX_PAGESIZE], MEM_COMMIT, PAGE_READWRITE);
        if (!m_pPhysList) {
            goto ExitFailure;
        }
        // allocate the minimum number of fixed pages
        for (DWORD i = 0; i < MIN_PHYS_PAGES; i++) {
            PHYSICAL_ADDRESS PhysicalAddress = {0};
            m_pPhysList[i].pVirtualAddress = (LPBYTE)HalAllocateCommonBuffer(&Adapter,
                UserKInfo[KINX_PAGESIZE], &PhysicalAddress, FALSE);
            m_pPhysList[i].pPhysicalAddress = (LPBYTE)PhysicalAddress.QuadPart;
            if (!m_pPhysList[i].pVirtualAddress) {
                goto ExitFailure;
            }
        }
    }
    m_dwPhysCount = 0;

    // m_pSGCopy tracks the mapping between scatter/gather buffers and DMA
    // buffers when the scatter/gather buffer is unaligned and we are reading,
    // so we can copy the read data back to the scatter/gather buffer; when the
    // scatter/gather buffer is aligned, m_pSGCopy tracks the scatter/gather
    // buffers of a particular DMA transfer, so we can unlock the buffers at
    // completion

    if (!m_pSGCopy) {
        m_pSGCopy = (PSGCopyTable)VirtualAlloc(
            m_pStartMemory + UserKInfo[KINX_PAGESIZE],
            UserKInfo[KINX_PAGESIZE],
            MEM_COMMIT,
            PAGE_READWRITE);
        if (!m_pSGCopy) {
            goto ExitFailure;
        }
    }
    m_dwSGCount = 0;

    if (!m_pPFNs) {
        m_pPFNs = (PDWORD)VirtualAlloc(
            m_pStartMemory + 2*UserKInfo[KINX_PAGESIZE],
            UserKInfo[KINX_PAGESIZE],
            MEM_COMMIT,
            PAGE_READWRITE);
        if (!m_pPFNs) {
            goto ExitFailure;
        }
    }

    // determine whether the a buffer or the buffer length is unaligned
    for (iBuffer = 0; iBuffer < dwSgCount; iBuffer++) {
        if (
            ((DWORD)pSgBuf[iBuffer].sb_buf & dwAlignMask) ||
            ((DWORD)pSgBuf[iBuffer].sb_len & dwAlignMask)
        ) {
            fUnalign = TRUE;
            break;
        }
    }

    if (fUnalign) {

        DWORD dwCurPageOffset = 0;

        for (iBuffer = 0; iBuffer < dwSgCount; iBuffer++) {

            // Map address and check for security violation
            LPBYTE pBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[iBuffer].sb_buf, pSgBuf[iBuffer].sb_len);
            if (pSgBuf[iBuffer].sb_buf != NULL && pBuffer == NULL) {
                // security violation
                DEBUGMSG(ZONE_ERROR, (TEXT(
                    "Atapi!CRomiDisk::SetupDMA> Failed to map pointer to caller\r\n"
                    )));
                goto ExitFailure;
            }

            DWORD dwBufferLeft = pSgBuf[iBuffer].sb_len;
            while (dwBufferLeft) {

                DWORD dwBytesInCurPage = UserKInfo[KINX_PAGESIZE] - dwCurPageOffset;
                DWORD dwBytesToTransfer = (dwBufferLeft > dwBytesInCurPage) ? dwBytesInCurPage : dwBufferLeft;

                // allocate a new page, if necessary
                if ((dwCurPageOffset == 0) && (m_dwPhysCount >= MIN_PHYS_PAGES)) {
                    PHYSICAL_ADDRESS PhysicalAddress = {0};
                    m_pPhysList[m_dwPhysCount].pVirtualAddress = (LPBYTE)HalAllocateCommonBuffer(
                        &Adapter, UserKInfo[KINX_PAGESIZE], &PhysicalAddress, FALSE);
                    m_pPhysList[m_dwPhysCount].pPhysicalAddress = (LPBYTE)PhysicalAddress.QuadPart;
                    if (!m_pPhysList[m_dwPhysCount].pVirtualAddress) {
                        goto ExitFailure;
                    }
                }

                if (fRead) {

                    // prepare a scatter/gather copy entry on read, so we can
                    // copy data from the DMA buffer to the scatter/gather
                    // buffer after this DMA transfer is complete

                    m_pSGCopy[m_dwSGCount].pSrcAddress = m_pPhysList[m_dwPhysCount].pVirtualAddress + dwCurPageOffset;
                    m_pSGCopy[m_dwSGCount].pDstAddress = pBuffer;
                    m_pSGCopy[m_dwSGCount].dwSize = dwBytesToTransfer;
                    m_dwSGCount++;

                }
                else {
                    memcpy(m_pPhysList[m_dwPhysCount].pVirtualAddress + dwCurPageOffset, pBuffer, dwBytesToTransfer);
                }

                // if this buffer is larger than the space remaining on the page,
                // then finish processing this page by setting @dwCurPageOffset<-0

                if (dwBufferLeft >= dwBytesInCurPage) {
                    dwCurPageOffset = 0;
                }
                else {
                    dwCurPageOffset += dwBytesToTransfer;
                }

                // have we finished a page? (i.e., offset was reset or this is the last buffer)
                if ((dwCurPageOffset == 0) || (iBuffer == (dwSgCount - 1))) {
                    // add this to the PRD table
                    m_pPRD[m_dwPhysCount].physAddr = (DWORD)m_pPhysList[m_dwPhysCount].pPhysicalAddress;
                    m_pPRD[m_dwPhysCount].size = dwCurPageOffset ? (USHORT)dwCurPageOffset : (USHORT)UserKInfo[KINX_PAGESIZE];
                    m_pPRD[m_dwPhysCount].EOTpad = 0;
                    m_dwPhysCount++;
                }

                // update transfer
                dwBufferLeft -= dwBytesToTransfer;
                pBuffer += dwBytesToTransfer;
           }
        }

        m_pPRD[m_dwPhysCount - 1].EOTpad = 0x8000;

    }
    else {

        DWORD dwTotalBytes = 0;

        for (iBuffer = 0; iBuffer < dwSgCount; iBuffer++) {

            // Map address and check for security violation
            LPBYTE pBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[iBuffer].sb_buf, pSgBuf[iBuffer].sb_len);
            if (pSgBuf[iBuffer].sb_buf != NULL && pBuffer == NULL) {
                // security violation
                DEBUGMSG(ZONE_ERROR, (TEXT(
                    "Atapi!CRomiDisk::SetupDMA> Failed to map pointer to caller\r\n"
                    )));
                goto ExitFailure;
            }

            // determine the number of bytes remaining to be placed in PRD
            dwTotalBytes = pSgBuf[iBuffer].sb_len;
            if (!LockPages (
                pBuffer,
                dwTotalBytes,
                m_pPFNs,
                fRead ? LOCKFLAG_WRITE : LOCKFLAG_READ)
            ) {
                goto ExitFailure;
            }

            // add a scatter/gather copy entry for the area we lock, so that
            // we can unlock it when we are finished
            m_pSGCopy[m_dwSGCount].pSrcAddress = pBuffer;
            m_pSGCopy[m_dwSGCount].pDstAddress = 0;
            m_pSGCopy[m_dwSGCount].dwSize = dwTotalBytes;
            m_dwSGCount++;

            iPFN = 0;
            while (dwTotalBytes) {

                DWORD dwBytesToTransfer = UserKInfo[KINX_PAGESIZE];

                if ((DWORD)pBuffer & dwPageMask) {
                    // the buffer is not page aligned; use up the next page
                    // boundary
                    dwBytesToTransfer = UserKInfo[KINX_PAGESIZE] - ((DWORD)pBuffer & dwPageMask);
                }

                if (dwTotalBytes < dwBytesToTransfer) {
                    // use what remains
                    dwBytesToTransfer = dwTotalBytes;
                }

                m_pPRD[iPage].physAddr = (m_pPFNs[iPFN] << UserKInfo[KINX_PFN_SHIFT]) + ((DWORD)pBuffer & dwPageMask);

                if (!TranslateAddress(&m_pPRD[iPage].physAddr)) {
                    goto ExitFailure;
                }

                m_pPRD[iPage].size = (USHORT)dwBytesToTransfer;
                m_pPRD[iPage].EOTpad = 0;

                iPage++;
                iPFN++;

                // update transfer
                pBuffer += dwBytesToTransfer;
                dwTotalBytes -= dwBytesToTransfer;
            }
        }

        m_dwPhysCount = 0;
        m_pPRD[iPage-1].EOTpad = 0x8000;
    }

    return TRUE;

ExitFailure:

    DEBUGCHK(0);

    // clean up
    // FreeDMABuffers();

    return FALSE;
}

// ----------------------------------------------------------------------------
// Function: BeginDMA
//     Begin DMA transfer
//
// Parameters:
//     fRead -
// ----------------------------------------------------------------------------

BOOL
CRomiDisk::BeginDMA(
    BOOL fRead
    )
{
    BYTE bStatus, bCommand;

    CacheSync(CACHE_SYNC_DISCARD);

    WriteBMCommand(0);
    WriteBMTable(m_pPRDPhys);

    bStatus = ReadBMStatus();
    bStatus |= 0x06;
    // bStatus |= 0x66;

    WriteBMStatus(bStatus);

    if (fRead) {
        bCommand = 0x08 | 0x01;
    }
    else {
        bCommand = 0x00 | 0x01;
    }

    WriteBMCommand(bCommand);

    bStatus = ReadBMStatus();

    return TRUE;
}

// ----------------------------------------------------------------------------
// Function: EndDMA
//     End DMA transfer
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

BOOL
CRomiDisk::EndDMA(
    )
{
    BYTE bStatus = ReadBMStatus();

    if ((bStatus & BM_STATUS_INTR) && (bStatus & BM_STATUS_ACTIVE)) {
        DEBUGMSG(ZONE_DMA, (_T(
            "Atapi!CRomiDisk::EndDMA> Status: active; status(0x%x)\r\n"
            ), bStatus));
    }
    else if ((bStatus & BM_STATUS_INTR) && !(bStatus & BM_STATUS_ACTIVE)) {
        DEBUGMSG(ZONE_DMA, (_T(
            "Atapi!CRomiDisk::EndDMA> Status: inactive; status(0x%x)\r\n"
            ), bStatus));
    }
    else if (!(bStatus & BM_STATUS_INTR)&& (bStatus & BM_STATUS_ACTIVE)) {

        DEBUGMSG(ZONE_ERROR|ZONE_DMA, (_T(
            "Atapi!CRomiDisk::EndDMA> Interrupt delayed; status(0x%x)\r\n"
            ), bStatus));

        BOOL bCount = 0;

        while (TRUE) {

            StallExecution(100);

            bCount++;
            bStatus = ReadBMStatus();

            if ((bStatus & BM_STATUS_INTR) && !(bStatus & BM_STATUS_ACTIVE)) {
                DEBUGMSG(ZONE_DMA, (_T(
                    "Atapi!CRomiDisk::EndDMA> DMA complete after delay; status(0x%x)\r\n"
                    ), bStatus));
                break;
            }
            else {
                DEBUGMSG(ZONE_ERROR|ZONE_DMA, (_T(
                    "Atapi!CRomiDisk::EndDMA> Interrupt still delayed; status(0x%x)\r\n"
                    ), bStatus));
                if (bCount > 10) {
                    WriteBMCommand(0);
                    return FALSE;
                }
            }
        }
    }
    else {
        if (bStatus & BM_STATUS_ERROR) {
            DEBUGMSG(ZONE_ERROR|ZONE_DMA, (_T(
                "Atapi!CRomiDisk::EndDMA> Error; (0x%x)\r\n"
                ), bStatus));
            DEBUGCHK(0);
            return FALSE;
        }
    }

    WriteBMCommand(0);

    return TRUE;
}

// ----------------------------------------------------------------------------
// Function: AbortDMA
//     Abort DMA transfer
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

BOOL
CRomiDisk::AbortDMA(
    )
{
    DWORD i;

    WriteBMCommand(0);

    for (i = 0; i < m_dwSGCount; i++) {
        if (!m_pSGCopy[i].pDstAddress) {
            UnlockPages(m_pSGCopy[i].pSrcAddress, m_pSGCopy[i].dwSize);
        }
    }

    // free all but the first @MIN_PHYS_PAGES pages; these are fixed
    for (i = MIN_PHYS_PAGES; i < m_dwPhysCount; i++) {
        FreePhysMem(m_pPhysList[i].pVirtualAddress);
    }

    return FALSE;
}

// ----------------------------------------------------------------------------
// Function: CompleteDMA
//     Complete DMA transfer
//
// Parameters:
//     pSgBuf -
//     dwSgCount -
//     fRead -
// ----------------------------------------------------------------------------

BOOL
CRomiDisk::CompleteDMA(
    PSG_BUF pSgBuf,
    DWORD dwSgCount,
    BOOL fRead
    )
{
    DWORD i;

    for (i = 0; i < m_dwSGCount; i++) {
        if (m_pSGCopy[i].pDstAddress) {
            // this corresponds to an unaligned region; copy it back to the
            // scatter/gather buffer
            memcpy(m_pSGCopy[i].pDstAddress, m_pSGCopy[i].pSrcAddress, m_pSGCopy[i].dwSize);
        }
        else {
            // this memory region needs to be unlocked
            UnlockPages(m_pSGCopy[i].pSrcAddress, m_pSGCopy[i].dwSize);
        }
    }

    // free all but the first @MIN_PHYS_PAGES pages; the first @MIN_PHYS_PAGES
    // pages are fixed

    for (i = MIN_PHYS_PAGES; i < m_dwPhysCount; i++) {
        FreePhysMem(m_pPhysList[i].pVirtualAddress);
    }

    return TRUE;
}

BOOL
CRomiDisk::WakeUp(
    )
{
    BOOL retVal;
    //jungpil
    //RETAILMSG(1, (TEXT("Atapi!CDisk::WakeUp! \n")));
    //memory controller settings are not recovered from Wakeup
    m_vpMEMRegs->BWSCON = (m_vpMEMRegs->BWSCON & ~(0xf<<20)) |(0<<23)|(1<<22)|(1<<20);
    m_vpMEMRegs->BANKCON5 = (Tacs<<13) | (Tcos<<11) | (Tacc<<8) | (Tcoh<<6) | (Tcah<<4) | (Tacp<<2) | PMC;

    //power on
    retVal = ResetController(FALSE);
    DEBUGMSG(ZONE_INIT, (TEXT( "CRomiDisk::WakeUp ResetController returns: %d\n"),retVal));
    if(!retVal) return FALSE;
/*    if (!ResetController(FALSE)) {
        return FALSE;
    }*/
    return SendIdentifyDevice(IsAtapiDevice());
}

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




⌨️ 快捷键说明

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