?? zl5011xdma.c
字號(hào):
/*******************************************************************************
*
* File name: zl5011xDma.c
*
* Version: 50
*
* Author: ARW
*
* Date created: 17/09/2002
*
* Copyright 2002, 2003, 2004, 2005, Zarlink Semiconductor Limited.
* All rights reserved.
*
* Module Description:
* This module contains functions for supporting DMA transfers
*
* Note:
* These API functions do not check that the DMA channel is free for use
* before programming the channel. It is up to the application to perform
* this check.
*
* Terminology:
* All references to transmit or Tx are with respect to the system
* application, i.e. from CPU (Host) to device.
* Conversely all references to receive or Rx refer to the device to CPU
* direction.
*
* Revision History:
*
* Rev: Date: Author: Comments:
* 1 17/09/2002 ARW New Data
* 2 17/10/2002 ARW Peer review actions (54)
* Major changes to the allocation of
* dynamic (hidden) memory for DMA
* operation.
* Changes to how the device is initialised
* Made DMA padding an option dependent on
* the micro's DMA capability
* Corrected bugs found whilst testing on a
* board without a device
* 3 17/10/2002 ARW Added missing StructInit functions
* 4 23/10/2002 ARW Removed some redundant byte swapping code
* Moved PTH write and PRH read to low level
* API file (zl5011xCpu.c/h)
* 5 31/10/2002 MRC Added variants + minor fixes
* 6 01/11/2002 ARW Changed _DEV_BOARD to _NO_DEVICE
* 7 07/11/2002 ARW Small change to SendPacket (whole number of
* words)
* 8 13/11/2002 ARW Used new error codes
* 9 04/12/2002 ARW Minor mods to code compiled with _NO_DEVICE
* 10 10/12/2002 ARW Reduced priority of zl5011xDmaPktRx and
* zl5011xDmaRxQService tasks when there is no device
* Added extra fields zl5011xHostRxGetStats
* 11 13/01/2003 JFE Modified zl5011xRxQService to take account of CPU bug
* preventing change to queue with no packets.
* 12 24/01/2003 ARW Removed special task priorities set specially for
* _NO_DEVICE option
* 13 29/01/2003 ARW Calculate partial checksum when required in
* zl5011xHostTxSendPacket
* 14 18/02/2003 ARW Fixed to compile warnings produced in RTL compile
* 15 21/03/2003 ARW Fixed functions to transmit and receive packets
* separately
* 16 07/04/2003 ARW Partial fix to receive packets from several
* queues. NOTE: THIS IS NOT YET COMPLETE
* 17 10/04/2003 ARW Removed _NO_DEVICE compilation code
* 18 15/04/2003 ARW Optimised functions zl5011xHostSendPacket,
* zl5011xPktRx and zl5011xRxQService for bit rate
* 19 15/04/2003 ARW Amalgamated zl5011xRxQService task into
* zl5011xPktRx
* Reduced CPQ thresholds in
* zl5011xRxInitialiseStructInit()
* 20 22/04/2003 ARW Modified Zl5011xTxSendPacket to correctly process
* packets of lengths not integers of 64bits
* 21 06/05/2003 ARW Fixed bug in zl5011xPktRx regarding packet class
* identification
* 22 10/06/2003 DJA Performed pre-audit actions
* 23 10/06/2003 DJA Performed some more pre-audit actions
* 24 02/07/2003 ARW Removed unused comments in zl5011xTxSendPacket
* 25 09/07/2003 APL Some comment formats now compatible with release
* function extractor
* 26 15/07/2003 ARW Changed checking parameters in function
* zl5011xHostTxSendPacket()
* 27 21/07/2003 APL Reset dmaRxEnabled in zl5011xHostRxDisable()
* 28 21/07/2003 APL Undo previous change
* 29 23/07/2003 ARW Fixed bug in zl5011xRxQService()
* 30 29/07/2003 APL Added support for devices with no TDM
* Fixed bug in number of buffer range check
* 31 08/07/2003 MRC Used queue enumeration rather than number
* 32 11/08/2003 MRC Added check to RxQService function
* 33 26/09/2003 APL When transmitting from DMA to Pkt via the PE don't set the
* context switch in the context ID or the wrong header will be used
* 34 21/10/2003 AMS Moved define for ZL5011X_BITS_PER_BYTE to main hdr
* 35 06/01/2004 MRC Update
* 36 29/07/2004 MRC Fixed some compiler warnings
* 37 03/09/2004 APL DMA Busy logic changed
* 38 03/09/2004 APL DMA Busy logic corrected when disabling host Tx
* 39 06/09/2004 APL Added port/queue parameter to zl5011xHostTxSendPacket
* Added support for more device variants
* 40 10/09/2004 APL Sorted out file history
* 41 13/09/2004 APL Port mapping function renamed
* 42 29/09/2004 APL Ran spelling check on comments
* 43 19/10/2004 APL Send a dummy packet to flush the Tx DMA
* interface when initialising
* 44 25/10/2004 APL Fixed code formatting error
* 45 16/11/2004 MRC Shortened task label
* 46 07/02/2005 MRC Added error check before call zl5011xCpuDmaGetRxSeqNum
* 47 11/02/2005 MRC Used macros for writing / reading DMA packets
* 48 31/03/2005 MRC Added support for DMA packet Rx interrupt
* 49 15/04/2005 APL Updated comment
* 50 04/05/2005 APL Added ethernetSrcAddressFromMac flag to
* zl5011xHostTxInitialise
*
*******************************************************************************/
/***************** INCLUDE FILES ******************************************/
#include "zl5011x.h"
#include "zl5011xDma.h"
#include "zl5011xDmaTaskInfo.h"
#include "zl5011xInterrupts.h"
/***************** # DEFINES **********************************************/
#define ZL5011X_MINIMUM_PACKET_SIZE 60 /* Minimum Ethernet packet size
(excluding CRC) */
#define ZL5011X_MAXIMUM_PACKET_SIZE 1518 /* Maximum Ethernet packet size
(excluding CRC) */
#define ZL5011X_MAX_GRANULE_ALLOC 0xFFFFD /* Maximum number of granules, packets
for the CPU are allowed to have */
#define ZL5011X_64_BIT_TRANSFER_NUM_BYTES 8 /* The number of bytes corresponding
to a 64-bit transfer */
#define ZL5011X_DMA_START_PACKET_LENGTH 8 /* The length of dummy packet to send to
start the DMA up */
#define ZL5011X_DMA_FLUSH_PACKET_LENGTH 4 /* The number of bytes used to flush the
first transmit packet through the DMA */
#define ZL5011X_ISR_PACKET_RX_MUTEX_TIMEOUT_MS 500
#define ZL5011X_BITS_PER_WORD (sizeof(Uint32T) * ZL5011X_BITS_PER_BYTE)
#define ZL5011X_WORDS_PER_TRANSFER \
(zl5011xDmaProps.transferBufferSize/sizeof(Uint32T))
/* (zl5011xDmaProps.transferBufferSize is a micro specific number, set in the
micro specific h file) */
/* Macro for checking a parameter has not been set to an invalid value */
#define ZL5011X_CHECK_FOR_INVALID_VALUE(par,value,errorCode) { \
if ((status == ZL5011X_OK) && (par == value)) \
{ \
status = errorCode; \
} }
/* Macro to check that a parameter is inside the correct range */
#define ZL5011X_CHECK_PARAMETER_RANGE(par,minValue,maxValue,errorCode) { \
if (status == ZL5011X_OK) \
{ \
if ((par < minValue) || (par >= maxValue)) \
{ \
status = errorCode; \
} \
} }
/* Macro to take a semaphore */
#define ZL5011X_MUTEX_TAKE(mutex) { \
if ((status == ZL5011X_OK) && (OS_MUTEX_TAKE(mutex) != OS_OK)) \
{ \
status = ZL5011X_RTOS_SEMA4_TAKE_FAIL; \
} }
/* Macro to take a semaphore that could be deleted by a separate task at any
time. Uses a sort of spinlock approach - check mutex exists, if it does then
try to take it, repeat if unsuccessful or until the mutex doesn't exist.
It is only possible to leave this block in the following states:
a) the mutex was taken. Exit status wil be ZL5011X_OK
b) the mutex has been deleted. Exit status will be ZL5011X_DMA_QUEUE_NOT_INIT
c) the block was skipped because status was not OK on entry */
#define ZL5011X_DYNAMIC_MUTEX_TAKE(ptr) { \
while(status == ZL5011X_OK) \
{ \
ZL5011X_CHECK_FOR_INVALID_VALUE(ptr,NULL,ZL5011X_DMA_QUEUE_NOT_INIT) \
ZL5011X_CHECK_FOR_INVALID_VALUE(ptr->mutex,OS_SEM_INVALID, \
ZL5011X_DMA_QUEUE_NOT_INIT) \
if ((status == ZL5011X_OK) && (OS_MUTEX_TAKE_T(ptr->mutex,1) == OS_OK)) \
{ \
break; \
} \
OS_TICK_DELAY(1); \
} \
if (status == ZL5011X_OK) \
{ \
ZL5011X_CHECK_FOR_INVALID_VALUE(ptr,NULL,ZL5011X_DMA_QUEUE_NOT_INIT) \
ZL5011X_CHECK_FOR_INVALID_VALUE(ptr->mutex,OS_SEM_INVALID, \
ZL5011X_DMA_QUEUE_NOT_INIT) \
} }
/* Macro to give a semaphore
The following flows through this block are possible:
a) the mutex was previously taken and is given OK. Exit status will be
the same as on block entry
c) the mutex give fails. No previous error had been indicated. Exit
status is now ZL5011X_RTOS_SEMA4_GIVE_FAIL.
b) the mutex give fails. A previous error already existed. Exit
status will be the same as on block entry */
#define ZL5011X_MUTEX_GIVE(ptr) { \
if (OS_MUTEX_GIVE(ptr->mutex) != OS_OK) \
{ \
if (status == ZL5011X_OK) \
{ \
status = ZL5011X_RTOS_SEMA4_GIVE_FAIL; \
} \
} }
#define ZL5011X_NORMAL_PRIORITY 0 /* Priority of messages sent between
zl5011xDmaPktRx & the application */
/* Macros for determining the receive packet class */
#define ZL5011X_MAC_ADDRESS_SIZE 6
#define ZL5011X_ROUND_TO_INTEGER_WORDS(bytes) \
((((bytes-1)/sizeof(Uint32T))+1)*sizeof(Uint32T))
/***************** ENUMERATIONS ******************************************/
/***************** DATA STRUCTURES ****************************************/
/* Definition of the elements for the message queue */
typedef struct zl5011xRxMessageQS
{
Uint32T *buffer; /* Pointer to the packet associated
with this message */
Uint16T packetLength; /* The packet length in bytes */
Uint16T sequenceNumber; /* Sequence number given to the packet
by the device. (This is not related
to any number provided on
transmission) */
Uint8T truncationFlag; /* Flag indicating the current packet
has been truncated because it is too
big for the message queue buffer */
zl5011xPacketClassE packetClass; /* Class of packet */
}zl5011xRxMessageQS;
/* Definition of structure used to process receive descriptors */
typedef struct zl5011xRxProcessDescriptorS
{
/* Current packet parameters (all in words) that need to be preserved
between buffer descriptors */
Uint16T packetOffset; /* Number of payload words read so for
for current packet */
Uint16T prhOffset; /* Number of header words read so far
for current packet */
Uint16T nextBufferOffset; /* Number of complete words to skip in
order to align to the beginning of
the next packet in the next buffer
(usually zero unless the packets are
being dropped) */
/* Parameters read from the PRH */
Uint16T nextPacketOffset; /* Number of complete words of padding
at the end of the current packet */
Uint16T packetLengthInWords;
zl5011xQueueE queueNumber; /* Receive queue this packet is destined
for */
/* Parameters to be passed in the message */
zl5011xRxMessageQS RxMsgQ;
}zl5011xRxProcessDescriptorS;
/***************** STATIC FUNCTION DECLARATIONS ***************************/
static void zl5011xPktRx(void);
static zlStatusE zl5011xRxQService(Uint32T currentTick);
static zlStatusE zl5011xRxProcessDescriptor(
zl5011xRxProcessDescriptorS *RxProcDesc,zl5011xBooleanE *stopFlag);
static zlStatusE zl5011xDmaAllocateStructure(zl5011xParamsS *zl5011xParams,
zl5011xDmaDirectionE dmaDirection);
static Uint32T zl5011xConvertPortAndQueueToHostContext(Uint32T port, Uint32T queue);
static zlStatusE zl5011xHostTxSendDMAStartPacket(zl5011xParamsS *zl5011xParams);
static zlStatusE zl5011xCopyPacketToDmaBuffer(Uint32T *dmaBuffer, Uint8T *pPacketData, Uint32T packetLength);
static zlStatusE zl5011xStartDmaTx(void);
/***************** STATIC GLOBAL VARIABLES ********************************/
zl5011xReceiveQueueParamsS *rxQParams = NULL;
zl5011xTransmitQueueParamsS *txQParams = NULL;
/***************** EXPORTED GLOBAL VARIABLES ******************************/
/***************** EXPORTED FUNCTION DEFINTIONS ***************************/
/*******************************************************************************
Function:
zl5011xDmaRxPacketInterrupt
Description:
Function called from the interrupt handler task to inform of DMA packet
transfer.
Inputs:
void
Outputs:
None
Returns:
zlStatusE
Remarks:
None
*******************************************************************************/
zlStatusE zl5011xDmaRxPacketInterrupt(void)
{
zlStatusE status = ZL5011X_OK;
if ((rxQParams->useInterrupt == ZL5011X_TRUE) && (rxQParams->rxPktSemId != OS_SEM_INVALID))
{
/* ignore the return code, since there is no point in upsetting the interrupt
routines for an error with the DMA semaphore */
(void)OS_MUTEX_GIVE(rxQParams->rxPktSemId);
}
return status;
}
/*******************************************************************************
Function:
zl5011xDmaRxInterruptInitialise
Description:
Initialises handling of the packet Rx interrupt.
Inputs:
zl5011xParams Pointer to the structure for this device instance.
Outputs:
None
Returns:
zlStatusE
Remarks:
None
*******************************************************************************/
zlStatusE zl5011xDmaRxInterruptInitialise(zl5011xParamsS *zl5011xParams)
{
zlStatusE status = ZL5011X_OK;
zl5011xIsrInterruptSourceS isrSource;
if (status == ZL5011X_OK)
{
/* create a mutex for signalling packet Rx */
if (rxQParams->rxPktSemId == OS_SEM_INVALID)
{
rxQParams->rxPktSemId = OS_MUTEX_CREATE(OS_SEM_FULL);
}
if (rxQParams->rxPktSemId == OS_SEM_INVALID)
{
status = ZL5011X_RTOS_SEMA4_CREATE_FAIL;
}
}
if (status == ZL5011X_OK)
{
/* register a function for handling the packet Rx interrupt */
status = zl5011xIsrSetDmaRxFunc(zl5011xDmaRxPacketInterrupt);
}
if (status == ZL5011X_OK)
{
/* setup the DMA to interrupt on every packet transfer */
status = zl5011xCpuDmaSetInterruptMode(zl5011xParams, ZL5011X_DMA_INTERRUPT_ON_PACKET);
}
if (status == ZL5011X_OK)
{
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -