📄 mpc107dma.c
字号:
/* 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 + -