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

📄 mpc107dma.c

📁 VxWorks系统中DMA控制器驱动部分的源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
/* mpc107Dma.c - MPC107 DMA Interface support *//* Copyright 1996-2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,11sep00,rcs correct headerfile paths01a,18jun00,bri written*//*DESCRIPTIONThis module contains routines for the DMA interface of MPC107 .The DMA controller transfers blocks of data independent of the local processoror PCI hosts. Data movement occurs on the PCI and/or memory bus. The MPC107has two DMA channels, each with a 64-byte queue to facilitate the gatheringand sending of data.Both the local processor and PCI masters can initiate aDMA transfer.Some of the features of the MPC107 DMA unit are:Two DMA channels and both channels accessible by processor coreand remote PCI masters.Misaligned transfer capability.Chaining mode (including scatter gathering) and Direct mode.Interrupt on completed segment, chain, and error conditions.Four DMA transfer types:Local memory to local memory,PCI memory to PCI memory,PCI memory to local memory, and  Local memory to PCI memory.This module provides support for "chained" (periodic and non periodic )DMAand "direct" DMA  transfers on both DMA channels .All the four DMA transfer types are supported by this module (local memory tolocal memory,local memory to PCI mmeory, PCI memory to local memory andPCI to PCI memory) .The descriptors for the chained DMA are built in the local memory ..SH INITIALIZATIONThis driver is initialized from the BSP, usually as part of sysHwInit().The routine mpc107DmaInit() should be called to initialize the  driver .*//* includes */#include "vxWorks.h"#include "semLib.h"#include "sysLib.h"#include "drv/multi/mpc107.h"#include "drv/dma/mpc107Dma.h"#include "drv/intrCtl/mpc107Epic.h"#include "errno.h"#include "errnoLib.h"#include "cacheLib.h"#include "intLib.h"#include "memLib.h"#include "stdlib.h"/* static file scope locals */MPC107_DMA_DESCRIPTOR 	*pFirstDescriptorCh0 = NULL; /* Pointer to DMA */                                                     /* descriptor */MPC107_DMA_DESCRIPTOR	*pFirstDescriptorCh1 = NULL; /* Pointer to DMA */                                                     /* descriptor */BOOL 		chainedDma0FirstTime = FALSE;/* Flag for chained DMA CH0 */BOOL 		chainedDma1FirstTime = FALSE;/* Flag for chained DMA CH1 */ULONG 		dmaBuildDescrInProgCh0 = 0;  /* Flag for building descriptors */ULONG 		dmaBuildDescrInProgCh1 = 0;  /* Flag for building descriptors */SEM_ID 		semIdDirectDmaCh0;           /* Semaphore for direct DMA CH0 */SEM_ID 		semIdDirectDmaCh1;           /* Semaphore for direct DMA CH1 */SEM_ID 		semIdChainDmaCh0;            /* Semaphore for chained DMA CH0 */SEM_ID 		semIdChainDmaCh1;            /* Semaphore for chained DMA CH1 *//* forward Declarations */void 		mpc107DmaCh0Int (void); /* ISR for channel 0 */void 		mpc107DmaCh1Int (void); /* ISR for channel 1 */LOCAL STATUS	mpc107DmaChainStart (UINT32 channelNumber);LOCAL STATUS	mpc107DmaPeriodicStart (UINT32 channelNumber,UINT32 timePeriod);/***************************************************************************** mpc107DmaInit - initialize DMA  controller** The DMA interface is initialized to be in "Direct DMA transfer" mode and* DMA  interrupts(End of Transfer Interrupt and Error Interrupt) are* disabled .* This routine also attaches the interrupt handlers of the DMA interface.** This routine should be called only once, during hardware initialization,* before using the DMA interface.** RETURNS: N/A*/void mpc107DmaInit (void)    {    /*     * Initialize the  DMA Channel Zero for the following :     * Error Interrupt Disabled,     * End of Transfer Interrupt Disabled     * Direct Mode DMA transfer     */    MPC107EUMBBARWRITE(MPC107_DMA_DMR0, MPC107_DMA_DMR0_DEFAULT);    /*     * Initialize the  DMA Channel One for the following :     * Error Interrupt Disabled,     * End of Transfer Interrupt Disabled     * Direct Mode DMA transfer     */    MPC107EUMBBARWRITE(MPC107_DMA_DMR1, MPC107_DMA_DMR1_DEFAULT);    /*     * Semaphore used for mutual exclusion in Direct DMA transfer     * of Channel Zero     */    semIdDirectDmaCh0 = semBCreate ((INT32)SEM_FULL, SEM_Q_PRIORITY);    /*     * Semaphore used for mutual exclusion in Direct DMA transfer     * of Channel One     */    semIdDirectDmaCh1 = semBCreate ((INT32)SEM_FULL, SEM_Q_PRIORITY);    /*     * Semaphore used for mutual exclusion in Chained DMA transfer     * of Channel Zero     */    semIdChainDmaCh0  = semBCreate ((INT32)SEM_FULL, SEM_Q_PRIORITY);    /*     * Semaphore used for mutual exclusion in Chained DMA transfer     * of Channel One     */    semIdChainDmaCh1  = semBCreate ((INT32)SEM_FULL, SEM_Q_PRIORITY);    /* The ISR handlers should be hooked here */    intConnect ((VOIDFUNCPTR*)MPC107_EPIC_DMA0_INT_VECT,                                 (VOIDFUNCPTR)mpc107DmaCh0Int, 0);    intConnect ((VOIDFUNCPTR*)MPC107_EPIC_DMA1_INT_VECT,                                 (VOIDFUNCPTR)mpc107DmaCh1Int, 0);    }/***************************************************************************** mpc107DmaStartDirect - start  "Direct" DMA transfer** This routine is used for starting "Direct" mode of DMA transfer."Direct"* mode of DMA transfer can be done on both the DMA channels .All the registers* of the corresponding channel are initialized to perform "Direct" DMA transfer.** RETURNS:  OK, or ERROR if channel is configured for Periodic DMA or* <numberOfBytes> is zero or channel specified by <channelNumber> is* not valid .*/STATUS mpc107DmaStartDirect    (    UINT32 	channelNumber,      /* Channel Number */    UINT32 	transferType,       /* Transfer Type */    UINT32 	sourceAddress,      /* Source Address */    UINT32 	destinationAddress, /* Destinantion Address */    UINT32 	numberOfBytes       /* Number of Bytes */    )    {    UINT32 statusOfDmaReg = 0;    UINT32 dataReadDmaReg = 0;    if (channelNumber == MPC107_DMA_CHANNEL0) /* channel 0 */        {        /* Reading of DMA Mode Register */        statusOfDmaReg = MPC107EUMBBARREAD(MPC107_DMA_DMR0);        if ( (!(statusOfDmaReg & MPC107_DMA_DMR_CTM) &&               (statusOfDmaReg & MPC107_DMA_DMR_PDE)) != 0)            {            /* This channel is configured for Periodic DMA */            errnoSet (EBUSY);            return (ERROR);            }        if (numberOfBytes != 0) /* number of bytes is non-zero */            {            semTake (semIdDirectDmaCh0, WAIT_FOREVER); /* Take the semaphore */            /* waiting for the channel to be free */            while (MPC107EUMBBARREAD(MPC107_DMA_DSR0) & MPC107_DMA_DSR_CB);            /* Program the Source Address Register */            MPC107EUMBBARWRITE(MPC107_DMA_SAR0, sourceAddress);            /* Program the Destination Address Register */            MPC107EUMBBARWRITE(MPC107_DMA_DAR0, destinationAddress);            /* Program the number of bytes in the Byte Count Register */            MPC107EUMBBARWRITE(MPC107_DMA_BCR0, numberOfBytes);            /* Program the Current Descriptor Address Register 0 */            dataReadDmaReg =  (MPC107EUMBBARREAD(MPC107_DMA_CDAR0) &                               MPC107_DMA_CDAR_ADDR_MASK) |                              (transferType << MPC107_DMA_CDAR_CTT_SHIFT) ;            MPC107EUMBBARWRITE(MPC107_DMA_CDAR0, dataReadDmaReg);            /* Program the DMA Mode Register 0 to start DMA */            dataReadDmaReg = MPC107EUMBBARREAD(MPC107_DMA_DMR0) &                           !((MPC107_DMA_DMR_CS) | MPC107_DMA_DMR_CTM) ;            /*             * Clear the Channel Start Bit  and  the Channel Transfer Mode             * to be Direct DMA             */            MPC107EUMBBARWRITE(MPC107_DMA_DMR0, dataReadDmaReg);            /* Set the Channel Start Bit to start DMA transfer */            MPC107EUMBBARWRITE(MPC107_DMA_DMR0, dataReadDmaReg |                               MPC107_DMA_DMR_CS);            semGive (semIdDirectDmaCh0); /* release the semaphore */            }        else            {            errnoSet (EINVAL);            return (ERROR);            }        }    else if (channelNumber == MPC107_DMA_CHANNEL1) /* channel 1 */        {        statusOfDmaReg = MPC107EUMBBARREAD(MPC107_DMA_DMR1);        if ( (!(statusOfDmaReg & MPC107_DMA_DMR_CTM) &&               (statusOfDmaReg & MPC107_DMA_DMR_PDE)) != 0)            {            /* This channel is configured for Periodic DMA */            errnoSet (EBUSY);            return (ERROR);            }        if (numberOfBytes != 0) /* If number of bytes is not zero */            {            semTake (semIdDirectDmaCh1, WAIT_FOREVER); /* Take the semaphore */            /* Polling to see when the channel is free */            while (MPC107EUMBBARREAD(MPC107_DMA_DSR1) & MPC107_DMA_DSR_CB);            /* Program the Source Address Register */            MPC107EUMBBARWRITE(MPC107_DMA_SAR1, sourceAddress);            /* Program the Destination Address Register */            MPC107EUMBBARWRITE(MPC107_DMA_DAR1, destinationAddress);            /* Program the number of bytes in the Byte Count Register */            MPC107EUMBBARWRITE(MPC107_DMA_BCR1, numberOfBytes);            /* Program the Current Descriptor Address Register 1 */            dataReadDmaReg =  MPC107EUMBBARREAD(MPC107_DMA_CDAR1) &                                (MPC107_DMA_CDAR_ADDR_MASK |                                (transferType << MPC107_DMA_CDAR_CTT_SHIFT));            MPC107EUMBBARWRITE(MPC107_DMA_CDAR1, dataReadDmaReg);            /* Program the DMA Mode Register 1 to start DMA */            dataReadDmaReg = MPC107EUMBBARREAD(MPC107_DMA_DMR1) &                           !((MPC107_DMA_DMR_CS) | MPC107_DMA_DMR_CTM) ;            /*             * Clear the Channel Start Bit  and  the Channel Transfer Mode             * to be Direct DMA             */            MPC107EUMBBARWRITE(MPC107_DMA_DMR1, dataReadDmaReg);            /* Set the Channel Start Bit to start DMA transfer */            MPC107EUMBBARWRITE(MPC107_DMA_DMR1, dataReadDmaReg                              | MPC107_DMA_DMR_CS);            semGive (semIdDirectDmaCh1); /* Release the semaphore */            }        else            {            errnoSet (EINVAL);            return (ERROR); /* Number of bytes is Zero */            }        }    else        {        errnoSet (EINVAL);        return (ERROR) ; /* Undefined Channel Number */        }    return (OK) ;    }/***************************************************************************** mpc107DmaChainStart  -  start Chained (non-periodic) DMA Transfer** NOTES** This routine  initializes the specified DMA channel for a "chained"* (non-periodic) DMA transfer.This routine is called in the routine* mpc107DmaChainedStart() after the "DMA descriptors" are built using the* routine  mpc107DmaBuildDescriptor().** RETURNS: OK, or ERROR if channel specified by <channelNumber> is not* a valid channel or the channel is configured for "periodic" DMA .*/LOCAL STATUS mpc107DmaChainStart    (    UINT32 	channelNumber  /* channel number */    )    {    UINT32 	statusOfDmaReg;    UINT32 	dataReadDmaReg;    if (channelNumber == MPC107_DMA_CHANNEL0) /* channel 0 */        {        statusOfDmaReg = MPC107EUMBBARREAD(MPC107_DMA_DMR0);        if ( (!(statusOfDmaReg & MPC107_DMA_DMR_CTM) &&               (statusOfDmaReg & MPC107_DMA_DMR_PDE)) != 0 )            {            /* This channel is configured for Periodic DMA */            errnoSet (EBUSY);            return (ERROR);            }        else if ((statusOfDmaReg & MPC107_DMA_DMR_CTM) != 0)            {            /* This channel is configured for Direct DMA */            /* Waiting for the channel to be free */            while (MPC107EUMBBARREAD(MPC107_DMA_DSR0) & MPC107_DMA_DSR_CB);            /* Program the Current Descriptor Address Register 0 */            MPC107EUMBBARWRITE(MPC107_DMA_CDAR0, (UINT32)pFirstDescriptorCh0);            /* Program the DMA Mode Register 0 to start DMA */            dataReadDmaReg = MPC107EUMBBARREAD(MPC107_DMA_DMR0) &                           !(MPC107_DMA_DMR_CS) & !(MPC107_DMA_DMR_CTM);            /*             * Clear the Channel Start Bit  and  the Channel Transfer Mode             * to be Chained  DMA             */            MPC107EUMBBARWRITE(MPC107_DMA_DMR0, dataReadDmaReg);            /* Set the Channel Start Bit to start DMA transfer */            MPC107EUMBBARWRITE(MPC107_DMA_DMR0, dataReadDmaReg |

⌨️ 快捷键说明

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