📄 ixatmdtxtransport.c
字号:
if (returnStatus != IX_SUCCESS) { /* update stats */ ixAtmdAccTxDoneDispatchStats.failedCount++; } else { /* update stats */ if (txDoneCount > ixAtmdAccTxDoneDispatchStats.maxPduPerDispatch) { ixAtmdAccTxDoneDispatchStats.maxPduPerDispatch = txDoneCount; } }); return returnStatus;}/* ----------------------------------------------------------* Return the level of the Tx done queue*/PUBLIC IX_STATUSixAtmdAccTxDoneLevelQuery (unsigned int *numberOfPdusPtr){ IX_STATUS returnStatus = IX_SUCCESS; /* check for null pointer */ if (numberOfPdusPtr == NULL) { returnStatus = IX_FAIL; } else { /* get the number of entries from the Q manager */ returnStatus = ixAtmdAccTxQueueEntriesGet (IX_NPE_A_QMQ_ATM_TX_DONE, numberOfPdusPtr, IX_ATMDACC_TXDONE_QUEUE_SIZE); } /* end of if-else(numberOfPdusPtr) */ return returnStatus;}/* ----------------------------------------------------* notify the user that the tx done queue level is high*/voidixAtmdAccTxDoneCallBack (IxQMgrQId qId, IxQMgrCallbackId cbId) {#ifndef __wince IX_STATUS status;#endif unsigned int numberOfPdus = IX_ATMDACC_ALLPDUS; unsigned int numberOfPdusProcessed = 0; /* WINCE_PORT NOTE: function pointer comparison across DLLs does not work. */#ifndef __wince /* if the callback is not the internal dispatcher function * get the number of entries from the queue */ if(ixAtmdAccTxDoneDispatcher != ixAtmdAccTxDoneDispatch) { status = ixAtmdAccTxQueueEntriesGet (IX_NPE_A_QMQ_ATM_TX_DONE, &numberOfPdus, IX_ATMDACC_TXDONE_QUEUE_SIZE); /* no way to continue if the status is not success */ IX_ATMDACC_ABORT(status == IX_SUCCESS, "TxDoneCallBack ixAtmdAccTxQueueEntriesGet failed"); }#endif /* process all entries from the queue */ (*ixAtmdAccTxDoneDispatcher) (numberOfPdus, &numberOfPdusProcessed);}/* -------------------------------------------------------* Submit a PDU for transmission*/PUBLIC IX_STATUSixAtmdAccTxVcPduSubmit (IxAtmConnId connId, IX_OSAL_MBUF* mbufPtr, IxAtmdAccClpStatus clp, unsigned int numberOfCells){ IX_STATUS status; UINT32 atmCellHeader; IxAtmdAccNpeDescriptor *npeDescriptor; IxAtmdAccPortDescriptor *portDescriptor; IxAtmdAccTxVcDescriptor *vcDescriptor; IX_STATUS returnStatus = IX_SUCCESS; IX_ATMDACC_TX_QUEUE *txSwQueue; unsigned int descriptorIndex = IX_ATMDACC_TX_VC_INDEX_GET (connId); vcDescriptor = &ixAtmdAccTxVcDescriptor[descriptorIndex]; /* indicate that a PDU transmit is in progress * i.e. not safe to disconnect */ vcDescriptor->pduTransmitInProgress = TRUE; /* sanity check the parameters, includes a check to ensure * that a disconnecting or obsolete connId are rejected */ IX_ATMDACC_PARAMS_CHECK( if ((vcDescriptor->connId != connId) || (mbufPtr == NULL) || (numberOfCells == 0) || ((unsigned int)IX_OSAL_MBUF_MLEN(mbufPtr) == 0) || ((unsigned int)IX_OSAL_MBUF_PKT_LEN(mbufPtr) > IX_ATMDACC_MAX_PDU_LEN) || ((unsigned int)IX_OSAL_MBUF_PKT_LEN(mbufPtr) != numberOfCells * vcDescriptor->cellSize) || ((clp != IX_ATMDACC_CLP_SET) && (clp != IX_ATMDACC_CLP_NOT_SET))) { /* param check failed */ IX_ATMDACC_FULL_STATS( if(vcDescriptor->connId == connId) { /* increment the stats of the correct channel */ vcDescriptor->txVcPduSubmitFailureCount++; }); vcDescriptor->pduTransmitInProgress = FALSE; return IX_FAIL; }); /* extract the VC descriptor pool index from the connId * and get the descriptor */ txSwQueue = &vcDescriptor->queue; /* check the state of the tx queue */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), "corrupted sw tx queue"); /* get a recycled descriptor */ if (!IX_ATMDACC_TXQ_OVERLOADED (txSwQueue)) { /* indicate that a PDU transmit is in progress * i.e. not safe to disconnect */ /* get the current descriptor from the tx sw queue */ npeDescriptor = IX_ATMDACC_TXQ_MID_ENTRY_GET (txSwQueue); /* get a port descriptor for this port */ portDescriptor = &ixAtmdAccPortDescriptor[vcDescriptor->port]; /* convert the mbuf/chain to Npe (physical) address, and * big endian format */ npeDescriptor->atmd.pRootMbuf = mbufPtr; npeDescriptor->atmd.totalCell = numberOfCells; /* fill the NPE descriptor fields */ atmCellHeader = npeDescriptor->npe.tx.atmCellHeader; IX_ATMDACC_CONVERT_FROM_BIG_ENDIAN(UINT32, atmCellHeader); IX_NPE_A_ATMCELLHEADER_PTI_SET(atmCellHeader, 0); IX_NPE_A_ATMCELLHEADER_CLP_SET(atmCellHeader, clp); IX_ATMDACC_CONVERT_TO_BIG_ENDIAN(UINT32, atmCellHeader); npeDescriptor->npe.tx.atmCellHeader = atmCellHeader; npeDescriptor->npe.tx.totalLen = IX_OSAL_MBUF_PKT_LEN(mbufPtr); npeDescriptor->npe.tx.currMbufLen = IX_OSAL_MBUF_MLEN(mbufPtr); IX_ATMDACC_CONVERT_TO_BIG_ENDIAN (UINT32, npeDescriptor->npe.tx.totalLen); IX_ATMDACC_CONVERT_TO_BIG_ENDIAN16 (npeDescriptor->npe.tx.currMbufLen); npeDescriptor->npe.tx.pCurrMbuf = ixAtmdAccUtilMbufToNpeFormatConvert (mbufPtr); npeDescriptor->npe.tx.pCurrMbufData = (unsigned char *)IX_OSAL_MBUF_MDATA(mbufPtr); npeDescriptor->npe.tx.pNextMbuf = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr); npeDescriptor->npe.tx.aal5CrcResidue = 0xffffffff; /* flush the xscale MMU */ IX_ATMDACC_DATA_CACHE_FLUSH(npeDescriptor, sizeof(npeDescriptor->npe.tx)); /* store the pdu in a sw queue */ IX_ATMDACC_TXQ_MID_INCR (txSwQueue); /* check unreachable conditions */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), "corrupted sw tx queue"); /* submit this request to the scheduler */ status = (*(portDescriptor->schDemandUpdate)) (vcDescriptor->port, vcDescriptor->schedulerVcId, numberOfCells); switch (status) { case IX_SUCCESS: break; case IX_FAIL: case IX_ATMDACC_BUSY: /* If scheduler fails to accept this request we may need to roll back */ /* perform a full rollback : remove the PDU from the queue */ IX_ATMDACC_TXQ_MID_DECR (txSwQueue); /* if the sw queue is in a bad state, this is because there is over scheduling * during a channelUpdate failure (double failure from the scheduler). In this * situation, there is no possible recovery. */ IX_ATMDACC_ABORT (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), "corrupted sw tx queue (overscheduling detected)"); /* convert back to logical address for the user domain */ ixAtmdAccUtilMbufFromNpeFormatConvert (mbufPtr, FALSE); /* update stats */ IX_ATMDACC_FULL_STATS( vcDescriptor->txSubmitOverloadedCount++); /* no descriptor available */ returnStatus = IX_ATMDACC_BUSY; break; default: /* any other kind of failure we dont roll back * because the NPE may have started to operate on * the PDU */ IX_ATMDACC_ABORT(0, "ixAtmdAccTxPduSubmit non recoverable scheduling entity error"); break; } /* end of switch(status) */ } /* end of if(IX_ATMDACC_TXQ_OVERLOADED) */ else { /* update stats */ IX_ATMDACC_FULL_STATS( vcDescriptor->txSubmitOverloadedCount++; ); /* no descriptor available */ returnStatus = IX_ATMDACC_BUSY; } /* end of if-else(IX_ATMDACC_TXQ_OVERLOADED) */ /* indicate that a PDU transmission is complete * i.e. safe to disconnect now */ vcDescriptor->pduTransmitInProgress = FALSE; return returnStatus;}/* -----------------------------------------------------------* transmit the specified number of cells emediately,* behaves like a dummy scheduler*/IX_STATUSixAtmdAccTxDummyDemandUpdate (IxAtmLogicalPort port, int vcId, unsigned int numberOfCells){ IxAtmdAccTxVcDescriptor *vcDescriptor; IxAtmdAccNpeDescriptor *npeDescriptor; IxAtmdAccPortDescriptor *portDescriptor; IX_ATMDACC_TX_QUEUE *txSwQueue; unsigned int numFreeEntries; unsigned int numEntries; unsigned int numEntriesReqd; unsigned int descriptorIndex; IX_STATUS returnStatus; UINT32 *qMgrEntryPtr; portDescriptor = &ixAtmdAccPortDescriptor[port]; /* ixAtmdAccTxUnscheduledModeVcIdGet ensures that VcId is a descriptorIndex */ descriptorIndex = vcId; vcDescriptor = &ixAtmdAccTxVcDescriptor[descriptorIndex]; txSwQueue = &vcDescriptor->queue; /* check the number of entries in the queue */ returnStatus = ixAtmdAccTxQueueEntriesGet (portDescriptor->txQueueId, &numEntries, 0); if (returnStatus == IX_SUCCESS) { /* compute the number of free entries in the TX queue */ numFreeEntries = portDescriptor->txQueueSize - (unsigned int) numEntries; /* compute the number of free entries required by the current demand */ numEntriesReqd = (numberOfCells + (NPE_TX_MAXCELLS_PER_QENTRY - 1)) / NPE_TX_MAXCELLS_PER_QENTRY; /* compare the available queue level and the requested number of entries requested */ if (numFreeEntries < numEntriesReqd) { /* cannot put all the PDU in the TX queue */ returnStatus = IX_ATMDACC_BUSY; } } /* end of if(returnStatus) */ if (returnStatus == IX_SUCCESS) { /* check unreachable conditions */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), "corrupted sw tx queue"); /* check that there is something in the queue to schedule */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_SCHEDULE_PENDING (txSwQueue), "corrupted sw tx queue"); /* get the the descriptor from the tx queue */ npeDescriptor = IX_ATMDACC_TXQ_TAIL_ENTRY_GET (txSwQueue); IX_ATMDACC_TXQ_TAIL_INCR (txSwQueue); /* check unreachable conditions */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), "corrupted sw tx queue"); /* check that everything in the queue has been scheduled */ IX_ATMDACC_ENSURE (!IX_ATMDACC_TXQ_SCHEDULE_PENDING (txSwQueue), "corrupted sw tx queue"); qMgrEntryPtr = portDescriptor->qMgrEntries; /* transmit all Cells from the current PDU */ ixAtmdAccCellTx (&qMgrEntryPtr, npeDescriptor->atmd.physicalAddress, (unsigned int) numberOfCells, NPE_TX_DATACELL); /* get the number of entries by a pointer substraction and * burst write all entries if no error found before */ returnStatus = ixQMgrQBurstWrite (portDescriptor->txQueueId, qMgrEntryPtr - portDescriptor->qMgrEntries, portDescriptor->qMgrEntries); if (returnStatus != IX_SUCCESS) { returnStatus = IX_FAIL; } /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccTxTransportStats[port].dataCellScheduledCount += numberOfCells; ); } /* end of if(returnStatus) */ return returnStatus;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -