📄 zl5011xdma.c
字号:
status = ZL5011X_CHECK_POINTERS(zl5011xParams, par);
if (status == ZL5011X_OK)
{
status = ZL5011X_CHECK_RUNNING(zl5011xParams);
}
if (status == ZL5011X_OK)
{
ZL5011X_TRACE(ZL5011X_DMA_FN_ID,
"zl5011xHostTxSendPacketStructInit:", 0, 0, 0, 0, 0, 0);
par->buffer = NULL;
par->pathType = ZL5011X_FLOW_CPU_PKT;
par->packetLength = 0;
/* Either the context or both the lanPort and lanPortQueue must be set.
LanPort and lanPortQueue are used when pathType is ZL5011X_FLOW_CPU_PKT.
Otherwise context is used. */
par->context = (Uint32T)ZL5011X_INVALID;
par->lanPort = (Uint32T)ZL5011X_INVALID;
par->lanPortQueue = 0;
par->sequenceNumber = 0;
par->tstampChksum = 0;
}
return status;
}
/*******************************************************************************
Function:
zl5011xHostTxSendPacket
Description:
Send a packet to the required destination
Inputs:
zl5011xParams Pointer to the structure for this device instance.
(Unused in this function)
par Pointer to the structure for configuration items. See below:
Structure inputs:
buffer Location of data to transmit
pathType Desired destination for packet
Any of: ZL5011X_FLOW_CPU_WAN,
ZL5011X_FLOW_CPU_PKT,
ZL5011X_FLOW_CPU_PE_PKT
packetLength Length of packet in bytes (Excluding CRC field and PTH)
context Context number for use when the pathType is one of:
ZL5011X_FLOW_CPU_WAN context range 0 to 127
ZL5011X_FLOW_CPU_PE_PKT context range 0 to 127
lanPort Output lan port to use (only valid when pathType
is ZL5011X_FLOW_CPU_PKT)
lanPortQueue Output queue to use on output lan port (only valid
when pathType is ZL5011X_FLOW_CPU_PKT)
sequenceNumber Sequence number for ZL5011X_FLOW_CPU_WAN mode only when
resequencing through the TFQ block is switched on. Otherwise
this parameter is ignored.
tstampChksum Test mode input, should be set to 0 under normal operation
Structure outputs:
None
Outputs:
None
Returns:
zlStatusE
Remarks:
This function will perform Endian conversions (if necessary) to the device
which is little Endian
This function does not set up the RTP block for the ZL5011X_FLOW_CPU_PE_PKT
flow. This must be done elsewhere.
*******************************************************************************/
zlStatusE zl5011xHostTxSendPacket(zl5011xParamsS *zl5011xParams, zl5011xHostTxSendPacketS *par)
{
zlStatusE status = ZL5011X_OK;
Uint32T *buffer,newLsbByteCount;
Uint32T sequenceNumber=0;
Uint16T context; /* The context to be used */
Uint16T tstampChksum=0;
status = ZL5011X_CHECK_POINTERS(zl5011xParams, par);
if (status == ZL5011X_OK)
{
status = ZL5011X_CHECK_RUNNING(zl5011xParams);
}
/* Store the context in a local variable */
context = par->context;
if (status == ZL5011X_OK)
{
ZL5011X_TRACE(ZL5011X_DMA_FN_ID,"zl5011xHostTxSendPacket:", 0, 0, 0, 0, 0, 0);
}
ZL5011X_CHECK_FOR_INVALID_VALUE(par->buffer,NULL,ZL5011X_INVALID_POINTER)
ZL5011X_CHECK_FOR_INVALID_VALUE(txQParams,NULL,ZL5011X_DMA_QUEUE_NOT_INIT)
/* Check packet length does not exceed buffer capability */
if (status == ZL5011X_OK)
{
if (par->packetLength >= (txQParams->dmaChannel.bufferSize*sizeof(Uint32T)))
{
status = ZL5011X_PARAMETER_INVALID;
}
}
if (par->packetLength == 0)
{
/* Nothing to send, so do nothing */
}
else
{ /* Valid packet length */
if (status == ZL5011X_OK)
{
switch (par->pathType)
{
case ZL5011X_FLOW_CPU_WAN:
/* check that the Wan Tx context is valid */
status = zl5011xContextCheckTx(zl5011xParams, context,
ZL5011X_CHECK_CONTEXT_ACTIVE);
if (status == ZL5011X_OK)
{
sequenceNumber = par->sequenceNumber;
tstampChksum = (Uint16T)par->tstampChksum;
}
break;
case ZL5011X_FLOW_CPU_PKT:
if (status == ZL5011X_OK)
{
/* Determine if the LAN port is configured */
status = zl5011xLanPortCheck(zl5011xParams,par->lanPort);
}
/* Check the supplied Lan queue number is valid */
ZL5011X_CHECK_PARAMETER_RANGE(par->lanPortQueue,0,ZL5011X_PKQ_NUM_QUEUES,ZL5011X_PARAMETER_INVALID);
/* Check the context is NOT specified when this pathType is specified */
if (status == ZL5011X_OK)
{
if (context != (Uint16T)ZL5011X_INVALID)
{
status = ZL5011X_PARAMETER_INVALID;
}
}
if (status == ZL5011X_OK)
{
/* Convert port and queue to a special host context number */
/* First map the requested port number to the internal hardware port based on the device variant */
Uint8T internalPort;
status = zl5011xPkiExternalPortToInternal(zl5011xParams, &internalPort, (Uint8T)par->lanPort);
if (status == ZL5011X_OK)
{
/* Now deduce which context we should use */
context = zl5011xConvertPortAndQueueToHostContext(internalPort, par->lanPortQueue);
}
}
break;
case ZL5011X_FLOW_CPU_PE_PKT:
/* check that the Wan Tx context is valid */
status = zl5011xContextCheckTx(zl5011xParams, context, ZL5011X_CHECK_CONTEXT_NUMBER);
if (status == ZL5011X_OK)
{
/* calculate partial checksum for payload */
status = zl5011xPacketCalculateChecksum(par->buffer,
(Uint16T)par->packetLength, &tstampChksum);
}
break;
default:
/* Invalid path */
status = ZL5011X_INVALID_FLOW_TYPE;
break;
}
}
ZL5011X_DYNAMIC_MUTEX_TAKE(txQParams)
if (status == ZL5011X_OK)
{
/* Determine if the descriptor chain is full */
if ((status == ZL5011X_OK) &&
(zl5011xDmaReadBufferStatus(&txQParams->dmaChannel,
txQParams->dmaChannel.bufferIndex) == ZL5011X_DMA_BUFFER_FULL))
{
status = ZL5011X_DMA_BUFFERS_FULL;
}
if (status == ZL5011X_DMA_BUFFERS_FULL)
{
txQParams->packetsSentFail++;
}
else
{
/* Begin processing packet - starting with the PTH word 0 */
buffer = (Uint32T *)zl5011xDmaReadSourceAddress(
&txQParams->dmaChannel,
txQParams->dmaChannel.bufferIndex);
zl5011xCpuDmaPTHWrite((Uint32T)par->pathType, (Uint16T)par->packetLength,
context, ZL5011X_CPU_SOURCE_BLOCK_ID, ZL5011X_INT_DONE,
ZL5011X_LAST_PKT, (Uint16T)sequenceNumber, tstampChksum,
zl5011xDmaProps.transaction64Bit, buffer);
/* Now add the data from the packet to the DMA buffer */
(void)zl5011xCopyPacketToDmaBuffer(buffer+ZL5011X_PTH_WORDSIZE, par->buffer, par->packetLength);
zl5011xDmaWriteLength(&txQParams->dmaChannel,
txQParams->dmaChannel.bufferIndex,
ZL5011X_ROUND_TO_INTEGER_WORDS(par->packetLength)
+ZL5011X_PTH_BYTESIZE);
/* Set the valid bit on the descriptor */
zl5011xDmaFreeDescriptorBuffer(&txQParams->dmaChannel);
/* Increment descriptor index */
txQParams->dmaChannel.bufferIndex++;
txQParams->dmaChannel.bufferIndex = txQParams->dmaChannel.bufferIndex
% txQParams->dmaChannel.numberOfBuffers;
newLsbByteCount = txQParams->bytesSentl +par->packetLength;
if (newLsbByteCount < txQParams->bytesSentl)
{
/* LSB counter has wrapped */
txQParams->bytesSenth++;
}
txQParams->bytesSentl = newLsbByteCount;
txQParams->packetsSent++;
}
}
ZL5011X_MUTEX_GIVE(txQParams)
/* Now look at the DMA status to determine if it needs restarting */
if ((status == ZL5011X_OK) || (status == ZL5011X_DMA_BUFFERS_FULL))
{
status = zl5011xStartDmaTx();
}
}
return(status);
}
/*******************************************************************************
Function:
zl5011xHostTxGetStatsStructInit
Description:
This function will set default values for function zl5011xHostTxGetStats
Inputs:
zl5011xParams Pointer to the structure for this device instance.
(Unused in this function)
par Pointer to the structure for configuration items.
Outputs:
None
Returns:
zlStatusE
Remarks:
None
*******************************************************************************/
zlStatusE zl5011xHostTxGetStatsStructInit(zl5011xParamsS *zl5011xParams, zl5011xHostTxGetStatsS *par)
{
zlStatusE status = ZL5011X_OK;
status = ZL5011X_CHECK_POINTERS(zl5011xParams, par);
if (status == ZL5011X_OK)
{
status = ZL5011X_CHECK_RUNNING(zl5011xParams);
}
if (status == ZL5011X_OK)
{
ZL5011X_TRACE(ZL5011X_DMA_FN_ID,"zl5011xHostTxGetStatsStructInit:",0,0,0,0,0,0);
par->packetsSent = 0;
par->packetsSentFail = 0;
par->packetsInQueue = 0;
par->bytesSenth = 0;
par->bytesSentl = 0;
}
return(status);
}
/*******************************************************************************
Function:
zl5011xHostTxGetStats
Description:
This function will return the stats for the transmit queue
Inputs:
zl5011xParams Pointer to the structure for this device instance.
(Unused in this function)
par Pointer to the structure for configuration items.
Structure inputs:
None
Structure outputs:
packetsSent Number of packets sent
bytesSenth The MSBs for the total number of bytes sent (excluding the
PTH)
bytesSentl The LSBs for the total number of bytes sent
packetsSentFail Number of packets that were failed to be sent because the
descriptor chain was full
packetsInQueue Number of packets waiting for transmission in the
descriptor chain
Outputs:
None
Returns:
zlStatusE
Remarks:
None
*******************************************************************************/
zlStatusE zl5011xHostTxGetStats(zl5011xParamsS *zl5011xParams, zl5011xHostTxGetStatsS *par)
{
zlStatusE status = ZL5011X_OK;
Uint32T n;
status = ZL5011X_CHECK_POINTERS(zl5011xParams, par);
if (status == ZL5011X_OK)
{
status = ZL5011X_CHECK_RUNNING(zl5011xParams);
}
if (status == ZL5011X_OK)
{
ZL5011X_TRACE(ZL5011X_DMA_FN_ID,"zl5011xHostTxGetStats:", 0, 0, 0, 0, 0, 0);
ZL5011X_CHECK_FOR_INVALID_VALUE(txQParams,NULL,ZL5011X_DMA_QUEUE_NOT_INIT)
ZL5011X_DYNAMIC_MUTEX_TAKE(txQParams);
if (status == ZL5011X_OK)
{
par->packetsSent = txQParams->packetsSent;
par->bytesSenth = txQParams->bytesSenth;
par->bytesSentl = txQParams->bytesSentl;
par->packetsSentFail = txQParams->packetsSentFail;
par->packetsInQueue = 0;
for (n=0;n<txQParams->dmaChannel.numberOfBuffers;n++)
{
if (zl5011xDmaReadBufferStatus(&txQParams->dmaChannel,n) ==
ZL5011X_DMA_BUFFER_FULL)
{
par->packetsInQueue++;
}
}
ZL5011X_MUTEX_GIVE(txQParams)
}
}
return status;
}
/*******************************************************************************
Function:
zl5011xHostRxInitialiseStructInit
Description:
Set up default parameters for the HostRxInitialise function
Inputs:
zl5011xParams Pointer to the structure for this device instance.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -