📄 ixatmdrxtransport.c
字号:
IX_ATMDACC_CONVERT_TO_VIRTUAL_ADDRESS (npeDescriptor); /* invalidate the xscale MMU */ IX_ATMDACC_DATA_CACHE_INVALIDATE(npeDescriptor, sizeof(npeDescriptor->npe.rx)); IX_ATMD_DEBUG_DO( /* check if the signature of the descriptor is still there * If it is not, it means that this is not a valid pointer */ IX_ATMDACC_ABORT(npeDescriptor->atmd.signature == IX_ATMDACC_DESCRIPTOR_SIGNATURE, "Imvalid pointer returned by NPE"); ); /* get the connection ID in the desriptor fields */ connId = npeDescriptor->atmd.connId; /* get the channel */ rxId = IX_ATMDACC_RX_VC_INDEX_GET (connId); /* get the descriptor */ vcDescriptor = &ixAtmdAccRxVcDescriptor[rxId]; rxSwQueue = &vcDescriptor->queue; /* check the descriptor recycling */ IX_ATMDACC_ENSURE (IX_ATMDACC_RXQ_CONSISTENT (rxSwQueue), "Rx descriptors queue failure"); /* check the descriptor recycling is exact : no descriptor is missing */ IX_ATMDACC_ABORT (IX_ATMDACC_RXQ_HEAD_ENTRY_GET (rxSwQueue)->atmd.physicalAddress == physicalAddress, "Descriptor Recycling order is wrong"); /* get the PDU length information */ IX_ATMDACC_CONVERT_FROM_BIG_ENDIAN (UINT32, npeDescriptor->npe.rx.totalLen); /* get the mbuf pointer and process the endianness * and update the pkt header field, and the length of the last mbuf */ mbufPtr = ixAtmdAccUtilRxMbufFromNpeFormatConvert ( npeDescriptor->atmd.pRootMbuf, npeDescriptor->npe.rx.totalLen, &mbufCount); IX_ATMDACC_ENSURE((vcDescriptor->npeAalType == NPE_AAL5_TYPE) || ((vcDescriptor->npeAalType != NPE_AAL5_TYPE) && (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr) == NULL)), "Rx PDU has illegal chain on AAL0/OAM"); IX_ATMDACC_ENSURE(((vcDescriptor->npeAalType == NPE_OAM_TYPE) && (npeDescriptor->npe.rx.totalLen == vcDescriptor->cellSize)) || ((vcDescriptor->npeAalType != NPE_OAM_TYPE) && ((npeDescriptor->npe.rx.totalLen % vcDescriptor->cellSize) == 0)), "Rx PDU has incomplete cells (AALx) or multiple cells (OAM)"); rxBitField = npeDescriptor->npe.rx.rxBitField; IX_ATMDACC_CONVERT_FROM_BIG_ENDIAN(UINT32, rxBitField); atmCellHeader = npeDescriptor->npe.rx.atmCellHeader; IX_ATMDACC_CONVERT_FROM_BIG_ENDIAN(UINT32, atmCellHeader); /* check the channel + connId validity */ if (vcDescriptor->connId == connId) { /* the connId is valid */ /* get the PDU informations : status */ if (IX_NPE_A_RXBITFIELD_STATUS_GET(rxBitField) == NPE_RX_PDU_VALID) { pduStatus = vcDescriptor->pduValidStatusCode; } else { pduStatus = vcDescriptor->pduInvalidStatusCode; } /* end of if-else(npeDescriptor) */ clpStatus = IX_NPE_A_ATMCELLHEADER_CLP_GET(atmCellHeader); /* recycle the descriptors */ IX_ATMDACC_RXQ_HEAD_ADVANCE (rxSwQueue, mbufCount); /* check the descriptor queue */ IX_ATMDACC_ENSURE (IX_ATMDACC_RXQ_CONSISTENT (rxSwQueue), "Rx descriptors queue failure"); /* call the receive event for this channel id */ vcDescriptor->rxDoneCallback ( IX_NPE_A_RXBITFIELD_PORT_GET(rxBitField), vcDescriptor->callbackId, pduStatus, clpStatus, mbufPtr); } else { /* this descriptor is related to something old and already disconnected */ IX_ATMDACC_RXQ_HEAD_ADVANCE (rxSwQueue, mbufCount); /* check the descriptor queue */ IX_ATMDACC_ENSURE (IX_ATMDACC_RXQ_CONSISTENT (rxSwQueue), "Rx descriptors queue failure"); /* release the buffer */ (*vcDescriptor->rxDoneCallback) (vcDescriptor->port, vcDescriptor->callbackId, IX_ATMDACC_MBUF_RETURN, IX_ATMDACC_CLP_NOT_SET, mbufPtr); } /* end of if-else(vcDescriptor) */}/* ---------------------------------------------------------* process the entries from the RX queue*/PUBLIC IX_STATUSixAtmdAccRxDispatch (IxAtmRxQueueId atmdQueueId, unsigned int numberOfPdusToProcess, unsigned int *numberOfPdusProcessedPtr){ IX_STATUS returnStatus = IX_SUCCESS; IX_STATUS qmgrStatus = IX_SUCCESS; IxQMgrQId qId; UINT32 *qEntryPtr; UINT32 qEntry; UINT32 numberOfEntriesToRead; IX_ATMDACC_FULL_STATS( unsigned totalRx = 0; ); /* check the parameters */ IX_ATMDACC_PARAMS_CHECK( if ((numberOfPdusProcessedPtr == NULL) || (numberOfPdusToProcess == 0) || (ixAtmdAccUtilQmgrQIdGet (atmdQueueId, &qId) != IX_SUCCESS) || (qId != ixAtmdAccRxQMgrQId[atmdQueueId])) { /* param check failed */ IX_ATMDACC_FULL_STATS( if(atmdQueueId < IX_ATM_MAX_RX_STREAMS) { ixAtmdAccRxDispatchStats[atmdQueueId].failedCount++; }); return IX_FAIL; }); /* get the qId from a stream table * this overwrites the qId that was returned if param checks are enabled * but done this way for performance when they are not enabled */ qId = ixAtmdAccRxQMgrQId[atmdQueueId]; /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccRxDispatchStats[atmdQueueId].invokeCount++; ); /* initialise the result parameter */ *numberOfPdusProcessedPtr = 0; /* iterate until all entries requested are processed */ do { /* set the pointer to the beginning of the buffer */ qEntryPtr = ixAtmdAccRxQMgrBuffer[atmdQueueId]; /* get the number of entries to read */ if (numberOfPdusToProcess >= IX_ATMDACC_RX_QUEUE_SIZE) { numberOfEntriesToRead = IX_ATMDACC_RX_QUEUE_SIZE; } else { numberOfEntriesToRead = numberOfPdusToProcess; qEntryPtr[numberOfEntriesToRead] = 0; } /* read all the queue entries (note that the buffer size is adjusted * and initialised to ensure that there is always a null entry * at the end of the buffer. This code assume that a null entry * is stored by qMgr at the end of the input data. */ qmgrStatus = ixQMgrQBurstRead (qId, numberOfEntriesToRead, qEntryPtr); /* get the first entry from the buffer */ qEntry = *qEntryPtr; /* iterate through all entries until a null entry is found */ while (qEntry != 0) { /* check the queue entry type */ switch(qEntry & NPE_RX_TYPE_MASK) { case NPE_RX_DESCRIPTOR: IX_ATMD_DEBUG_DO( /* check the descriptor is from the right queue * and check the descriptor order is valid, and mbuf * chaining is correct, and try to recover if it * is possible to recover, and update statistics. */ ixAtmdAccRxPduPtrCheck(qEntry & NPE_DESCRIPTOR_MASK, qId) ); /* process data descriptor */ ixAtmdAccRxProcess (qEntry & NPE_DESCRIPTOR_MASK); /* update stats */ IX_ATMDACC_FULL_STATS( totalRx++; ixAtmdAccRxDispatchStats[atmdQueueId].spPduCount++; ); /* update the number of pdu processed */ numberOfPdusToProcess--; (*numberOfPdusProcessedPtr)++; break; case NPE_RX_SHUTDOWN_ACK: IX_ATMD_DEBUG_DO( /* check the descriptor ack is from the right queue */ ixAtmdAccRxAckCheck((qEntry & NPE_RX_SHUTDOWN_ACK_VCID_MASK) >> NPE_SHUTDOWN_ACK_SHIFT, qId); ); /* process rx shutdown ack */ ixAtmdAccRxShutdownAck ((unsigned int) ((qEntry & NPE_RX_SHUTDOWN_ACK_VCID_MASK) >> NPE_SHUTDOWN_ACK_SHIFT)); /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccRxDispatchStats[atmdQueueId].ackCount++; ); break; default: /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccRxDispatchStats[atmdQueueId].invalidDescCount++; ); returnStatus = IX_FAIL; break; } /* get the next entry from the buffer */ qEntry = *(++qEntryPtr); } /* end of while(qEntry) */ } while ((qmgrStatus == IX_SUCCESS) && (numberOfPdusToProcess > 0)); IX_ATMDACC_FULL_STATS( if (totalRx > ixAtmdAccRxDispatchStats[atmdQueueId].maxRxPerDispatch) { ixAtmdAccRxDispatchStats[atmdQueueId].maxRxPerDispatch = totalRx; if (returnStatus != IX_SUCCESS) { ixAtmdAccRxDispatchStats[atmdQueueId].failedCount++; } }); return returnStatus;}/* ---------------------------------------------------------* queue manager callback to be used to receive data from NPE*/voidixAtmdAccRxCallback (IxQMgrQId qMgrQueueId, IxQMgrCallbackId cbId){ unsigned int dummynumberOfPdusProcessed; unsigned int numberOfPdusToProcess = IX_ATMDACC_ALLPDUS;#ifndef __wince IX_STATUS returnStatus;#endif /* check queueId and callbackId values */ IX_ATMDACC_ENSURE (IX_ATMDACC_RX_VCQ_ID_VALID (qMgrQueueId), "Qmgr invalid qId"); IX_ATMDACC_ENSURE (IX_ATMDACC_RX_CALLBACK_ID_VALID (cbId), "Qmgr invalid callback Id"); /* WINCE_PORT NOTE: function pointer comparison across DLLs does not work. */#ifndef __wince /* check the registered callback : if it is the atmdAcc callback, there * is no need to read the qmgr level, because the action will be * to process all pdus. */ if (ixAtmdAccRxUserCallback[cbId] != ixAtmdAccRxDispatch) { returnStatus = ixAtmdAccRxQueueEntriesGet(qMgrQueueId, &numberOfPdusToProcess, IX_QMGR_Q_SIZE64); /* check the qmgr status : should not fail */ IX_ATMDACC_ABORT (returnStatus == IX_SUCCESS, "Qngr status failed"); if (numberOfPdusToProcess == 0) { /* nothing to process in this queue */ return; } } /* end of if(ixAtmdAccRxUserCallback) */#endif /* invoke the user callback */ (*ixAtmdAccRxUserCallback[cbId]) ((IxAtmRxQueueId) cbId, numberOfPdusToProcess, &dummynumberOfPdusProcessed);}/* ---------------------------------------------------------*/PRIVATE IX_STATUSixAtmdAccRxVcFreeReplenishPossible (IxAtmConnId connId, IX_OSAL_MBUF *mbufPtr, unsigned int * spaceInQmgrQueuePtr){ IX_STATUS returnStatus = IX_SUCCESS; unsigned int numEntriesInQmgrQueue; /* get the channel */ unsigned int rxId = IX_ATMDACC_RX_VC_INDEX_GET (connId); IxAtmdAccRxVcDescriptor *vcDescriptor = &ixAtmdAccRxVcDescriptor[rxId]; IX_ATMDACC_RX_QUEUE *rxSwQueue = &vcDescriptor->queue; /* check parameters */ if ((vcDescriptor->connId != connId) || (mbufPtr == NULL) || (IX_OSAL_MBUF_MLEN(mbufPtr) < vcDescriptor->cellSize) ) { returnStatus = IX_FAIL; } else { /* check if a descriptor is available */ if (IX_ATMDACC_RXQ_OVERLOADED (rxSwQueue)) { returnStatus = IX_ATMDACC_BUSY; } else { returnStatus = ixAtmdAccRxQueueEntriesGet(vcDescriptor->rxFreeQueueId, &numEntriesInQmgrQueue, 0); IX_ATMDACC_ENSURE (returnStatus == IX_SUCCESS, "Qngr status failed"); /* map the qmgr error code */ if (returnStatus == IX_SUCCESS) { *spaceInQmgrQueuePtr = vcDescriptor->rxFreeQueueSize - numEntriesInQmgrQueue; /* check the queue is full */ if (*spaceInQmgrQueuePtr == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -