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

📄 s3c6410_dma_controller.c

📁 6410BSP3
💻 C
📖 第 1 页 / 共 3 页
字号:
    }

    pLLIEntry = (DMA_LLI_ENTRY *)(pCtxt->LLIVirAddr+sizeof(DMA_LLI_ENTRY)*iEntryNumber);

    pLLIEntry->SrcAddr = uiSrcAddr;
    pLLIEntry->DestAddr = uiDstAddr;
    pLLIEntry->Control0 = TCINT_ENABLE |(pCtxt->DstUpdate<<27) | (pCtxt->SrcUpdate<<26)
                    | (pCtxt->DstAHBM<<25) | (pCtxt->SrcAHBM<<24)|(pCtxt->DstUnit<<21)
                    | (pCtxt->SrcUnit<<18) | (pCtxt->DstBurst<<15) | (pCtxt->SrcBurst<<12);

    switch(pCtxt->SrcUnit)
    {
    case BYTE_UNIT:
        pLLIEntry->Control1 = TRANSFERCOUNT(uiByteCount);
        break;
    case HWORD_UNIT:
        pLLIEntry->Control1 = TRANSFERCOUNT(uiByteCount/2);
        break;
    case WORD_UNIT:
        pLLIEntry->Control1 = TRANSFERCOUNT(uiByteCount/4);
        break;
    }

    switch(NextItem)
    {
    case LLI_NEXT_ENTRY:
        if (iEntryNumber+1 > pCtxt->LLICount-1)
        {
            DMA_ERR((_T("[DMA:ERR] DMA_set_LLI_entry() : This Entry is Last. Can't set LLI to Next Entry (%d)\n\r"), iEntryNumber));
            error = DMA_ERROR_ILLEGAL_PARAMETER;
            goto CleanUp;
        }
        else
        {
            pLLIEntry->LLI = NEXT_LLI_ITEM(pCtxt->LLIPhyAddr+sizeof(DMA_LLI_ENTRY)*(iEntryNumber+1)) |pCtxt->LLIAHBM;
        }
        break;
    case LLI_FIRST_ENTRY:
        pLLIEntry->LLI = NEXT_LLI_ITEM(pCtxt->LLIPhyAddr) |pCtxt->LLIAHBM;
        break;
    case LLI_THIS_IS_END:
        pLLIEntry->LLI = 0;
        break;
    }

CleanUp:

    DMA_MSG((_T("[DMA]--DMA_set_LLI_entry() : %d\n\r"), error));

    return error;
}

DMA_ERROR DMA_channel_start(DMA_CH_CONTEXT *pCtxt)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;
    DMA_ERROR error = DMA_SUCCESS;

    DMA_MSG((_T("[DMA]++DMA_channel_start() : Ch%d in DMAC%d\n\r"), pCtxt->Channel, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        DMA_ERR((_T("[DMA:ERR] DMA_channel_start() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    pDMACHReg = (S3C6410_DMA_CH_REG *)pCtxt->pCHReg;

    if (pDMACHReg->Configuration & CHANNEL_ENABLE)
    {
        DMA_ERR((_T("[DMA:ERR] DMA_channel_start() : Channel Alread in Use\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    // Clear Interrupt Pending
    DMA_clear_interrupt_pending(pCtxt);

    // Clear Interrupt Mask
    DMA_clear_interrupt_mask(pCtxt);

    // Clear Halt Bit
    pDMACHReg->Configuration &= ~HALT;

    // Enable Channel
    pDMACHReg->Configuration |= CHANNEL_ENABLE;

CleanUp:

    DMA_MSG((_T("[DMA]--DMA_channel_start() : %d\n\r"), error));

    return error;
}

DMA_ERROR DMA_channel_stop(DMA_CH_CONTEXT *pCtxt)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;
    DMA_ERROR error = DMA_SUCCESS;

    DMA_MSG((_T("[DMA]++DMA_channel_stop() : Ch%d in DMAC%d\n\r"), pCtxt->Channel, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        DMA_ERR((_T("[DMA:ERR] DMA_channel_stop() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    pDMACHReg = (S3C6410_DMA_CH_REG *)pCtxt->pCHReg;

    if (!(pDMACHReg->Configuration & CHANNEL_ENABLE))
    {
        DMA_INF((_T("[DMA:INF] DMA_channel_stop() : Channel Already Disabled\n\r")));
    }
    else
    {
        // Set Interrupt Mask
        DMA_set_interrupt_mask(pCtxt);

        // Set Halt Bit
        pDMACHReg->Configuration |= HALT;

#if    0    // TODO: Sometimes Channel is not inactivated when TC reached to "0"
        // Wait For Channel Inactive
        while(pDMACHReg->Configuration & ACTIVE);
#endif

        // Disable Channel
        pDMACHReg->Configuration &= ~CHANNEL_ENABLE;
    }

    // Clear Interrupt Pending
    DMA_clear_interrupt_pending(pCtxt);

CleanUp:

    DMA_MSG((_T("[DMA]--DMA_channel_stop() : %d\n\r"), error));

    return error;
}

DMA_INT_STATUS DMA_get_interrupt_status(DMA_CH_CONTEXT *pCtxt)
{
    DMA_INT_STATUS status = NO_INT_PEND;

    if (pCtxt->Controller == DMAC0)        // channel in DMAC0
    {
        if (g_pDMAC0Reg->DMACIntTCStatus & (1<<(pCtxt->Channel)))
        {
            status |= TC_INT_PEND;
        }

        if (g_pDMAC0Reg->DMACIntErrStatus & (1<<(pCtxt->Channel)))
        {
            status |= ERR_INT_PEND;
        }
    }
    else if (pCtxt->Controller == DMAC1)    // channel in DMAC1
    {
        if (g_pDMAC1Reg->DMACIntTCStatus & (1<<(pCtxt->Channel)))
        {
            status |= TC_INT_PEND;
        }

        if (g_pDMAC1Reg->DMACIntErrStatus & (1<<(pCtxt->Channel)))
        {
            status |= ERR_INT_PEND;
        }
    }

    return status;
}

void DMA_set_interrupt_mask(DMA_CH_CONTEXT *pCtxt)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;

    pDMACHReg = (S3C6410_DMA_CH_REG *)pCtxt->pCHReg;

    pDMACHReg->Configuration &= ~(TCINT_UNMASK|ERRINT_UNMASK);        // Mask is Bit Clear, Unmask is Bit Set
}

void DMA_clear_interrupt_mask(DMA_CH_CONTEXT *pCtxt)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;

    pDMACHReg = (S3C6410_DMA_CH_REG *)pCtxt->pCHReg;

    pDMACHReg->Configuration |= (TCINT_UNMASK|ERRINT_UNMASK);        // Mask is Bit Clear, Unmask is Bit Set
}

void DMA_clear_interrupt_pending(DMA_CH_CONTEXT *pCtxt)
{
    if (pCtxt->Controller == DMAC0)        // channel in DMAC0
    {
        g_pDMAC0Reg->DMACIntTCClear = (1<<(pCtxt->Channel));
        g_pDMAC0Reg->DMACIntErrClear = (1<<(pCtxt->Channel));
    }
    else if (pCtxt->Controller == DMAC1)    // channel in DMAC1
    {
        g_pDMAC1Reg->DMACIntTCClear = (1<<(pCtxt->Channel));
        g_pDMAC1Reg->DMACIntErrClear = (1<<(pCtxt->Channel));
    }
}

static BOOL DMA_dmac0_enable(void)
{
    if (!(g_pDMAC0Reg->DMACConfiguration & DMAC_ENABLE))        // DMAC0 is Disabled
    {
        // Enable DMAC0
        g_pDMAC0Reg->DMACConfiguration = M1_LITTLE_ENDIAN | M2_LITTLE_ENDIAN | DMAC_ENABLE;
        DMA_MSG((_T("[DMA] DMA_dmac0_enable() : DMAC0 Enabled\n\r")));
    }

    return TRUE;
}

static BOOL DMA_dmac0_disable(void)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;
    BOOL bInUse = FALSE;
    int i;

    if (g_pDMAC0Reg->DMACConfiguration & DMAC_ENABLE)    // DMAC0 is Enabled
    {
        for (i=0; i<8; i++)        // Check channel in Use
        {
            pDMACHReg = (S3C6410_DMA_CH_REG *)((ULONG)g_pDMAC0Reg + DMA_CH_REG_OFFSET + i*DMA_CH_REG_SIZE);

            if (pDMACHReg->Control0 & TCINT_ENABLE)    // Check channel in use with TC Int Enable Bit !!!
            {
                bInUse = TRUE;
                break;
            }
        }

        if (bInUse == FALSE)
        {
            if (g_pDMAC0Reg->DMACEnbldChns & 0xff)
            {
                DMA_ERR((_T("[DMA:ERR] DMA_dmac0_disable() : All TCINT_ENABLE Bit is Clear, But Channel Enabled [0x%02x]\n\r"), (g_pDMAC0Reg->DMACEnbldChns&0xff)));
            }
            else        // There is no channel enabled
            {
                // Disable DMAC0
                g_pDMAC0Reg->DMACConfiguration &= ~DMAC_ENABLE;
                g_pSysConReg->HCLK_GATE &= ~(1<<12);    // DMAC0 HCLK Mask
                DMA_MSG((_T("[DMA] DMA_dmac0_disable() : DMAC0 Disabled\n\r")));
            }
        }
    }

    return TRUE;
}

static BOOL DMA_dmac1_enable(void)
{
    if (!(g_pDMAC1Reg->DMACConfiguration & DMAC_ENABLE))        // DMAC1 is Disabled
    {
        // Enable DMAC1
        g_pDMAC1Reg->DMACConfiguration = M1_LITTLE_ENDIAN | M2_LITTLE_ENDIAN | DMAC_ENABLE;
        DMA_MSG((_T("[DMA] DMA_dmac1_enable() : DMAC1 Enabled\n\r")));
    }

    return TRUE;
}

static BOOL DMA_dmac1_disable(void)
{
    volatile S3C6410_DMA_CH_REG *pDMACHReg;
    BOOL bInUse = FALSE;
    int i;

    if (g_pDMAC1Reg->DMACConfiguration & DMAC_ENABLE)    // DMAC0 is Enabled
    {
        for (i=0; i<8; i++)        // Check channel in Use
        {
            pDMACHReg = (S3C6410_DMA_CH_REG *)((ULONG)g_pDMAC1Reg + DMA_CH_REG_OFFSET + i*DMA_CH_REG_SIZE);

            if (pDMACHReg->Control0 & TCINT_ENABLE)    // Check channel in use with TC Int Enable Bit !!!
            {
                bInUse = TRUE;
                break;
            }
        }

        if (bInUse == FALSE)
        {
            if (g_pDMAC1Reg->DMACEnbldChns & 0xff)
            {
                DMA_ERR((_T("[DMA:ERR] DMA_dmac1_disable() : All TCINT_ENABLE Bit is Clear, But Channel Enabled [0x%02x]\n\r"), (g_pDMAC1Reg->DMACEnbldChns&0xff)));
            }
            else        // There is no channel enabled
            {
                // Disable DMAC1
                g_pDMAC1Reg->DMACConfiguration &= ~DMAC_ENABLE;
                g_pSysConReg->HCLK_GATE &= ~(1<<13);    // DMAC1 HCLK Mask
                DMA_MSG((_T("[DMA] DMA_dmac1_disable() : DMAC1 Disabled\n\r")));
            }
        }
    }

    return TRUE;
}

static BOOL DMA_allocate_LLI_context(DMA_CH_CONTEXT *pCtxt)
{
    DMA_ADAPTER_OBJECT Adapter;
    PHYSICAL_ADDRESS PhysicalAddress;
    PVOID pVirtualAddress;
    BOOL bRet = TRUE;

    DMA_MSG((_T("[DMA] ++DMA_allocate_LLI_context()\n\r")));

    if ((pCtxt->LLICount > MAX_LLI_ENTRY) || pCtxt->LLICount == 0)
    {
        DMA_ERR((_T("[DMA] DMA_allocate_LLI_context() : LLICount [%d] Out of Range \n\r"), pCtxt->LLICount));
        bRet = FALSE;
        goto CleanUp;
    }

    if (pCtxt->LLIVirAddr)    // for Reinitialize LLI case
    {
        DMA_free_LLI_context(pCtxt);
    }

    memset(&Adapter, 0, sizeof(DMA_ADAPTER_OBJECT));
    Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
    Adapter.InterfaceType = Internal;

    pVirtualAddress = HalAllocateCommonBuffer(&Adapter, pCtxt->LLICount*sizeof(DMA_LLI_ENTRY), &PhysicalAddress, FALSE);
    if (pVirtualAddress == NULL)
    {
        DMA_ERR((_T("[DMA] DMA_allocate_LLI_context() : HalAllocateCommonBuffer() Failed \n\r")));
        bRet = FALSE;
        goto CleanUp;
    }

    pCtxt->LLIPhyAddr = (unsigned int)PhysicalAddress.LowPart;
    pCtxt->LLIVirAddr = (unsigned int)pVirtualAddress;

CleanUp:

    if (bRet == FALSE)
    {
        pCtxt->LLIPhyAddr = 0;
        pCtxt->LLIVirAddr = 0;
    }

    DMA_MSG((_T("[DMA] --DMA_allocate_LLI_context() : %d\n\r"), bRet));

    return bRet;
}

static BOOL DMA_free_LLI_context(DMA_CH_CONTEXT *pCtxt)
{
    PHYSICAL_ADDRESS PhysicalAddress;
    PVOID pVirtualAddress;
    BOOL bRet = TRUE;

    DMA_MSG((_T("[DMA] ++DMA_free_LLI_context()\n\r")));

    if (pCtxt->LLIVirAddr)
    {
        PhysicalAddress.LowPart = pCtxt->LLIPhyAddr;        // No Meaning just for compile
        pVirtualAddress = (PVOID)pCtxt->LLIVirAddr;

        HalFreeCommonBuffer(0, 0, PhysicalAddress, pVirtualAddress, FALSE);

        pCtxt->LLIPhyAddr = 0;
        pCtxt->LLIVirAddr = 0;
    }

    DMA_MSG((_T("[DMA] --DMA_free_LLI_context() : %d\n\r"), bRet));

    return bRet;
}

static BOOL DMA_lock(void)
{
    DWORD dwRet;

    dwRet = WaitForSingleObject(g_hMutex, INFINITE);
    if (dwRet != WAIT_OBJECT_0)
    {
        DMA_ERR((_T("[DMA] DMA_lock() : WaitForSingleObject() Failed\n\r")));
        return FALSE;
    }

    return TRUE;
}

static BOOL DMA_unlock(void)
{
    BOOL bRet;

    bRet = ReleaseMutex(g_hMutex);
    if (bRet == FALSE)
    {
        DMA_ERR((_T("[DMA] DMA_unlock() : ReleaseMutex() Failed\n\r")));
        return FALSE;
    }

    return TRUE;
}

⌨️ 快捷键说明

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