📄 ixatmdtxtransport.c
字号:
/* process all the remaining of the schedule table */ ixAtmdAccTxScheduleProcess (&qMgrEntryPtr, scheduleNewTableEntryPtr, scheduleNewTableSizeInEntries); } } else { /* the threshold is set to 0. There is no need to ensure * that there are enough entries in the txVc queues to * guarantee a constant interrupt rate. the schedule * table is directly processed */ ixAtmdAccTxScheduleProcess (&qMgrEntryPtr, scheduleTablePtr->table, scheduleTableSizeInEntries); } /* check unreachable condition : the number of entries should * not be greater than the size of the buffer. By construction * and after the tests of input parameters, this should never occur * at this point. */ IX_ATMDACC_ENSURE(qMgrEntryPtr - portDescriptor->qMgrEntries < IX_ATMDACC_TX_SCHEDULE_TABLE_SIZE, "Number of entries exceeded limit"); /* write all entries */ returnStatus = ixQMgrQBurstWrite (portDescriptor->txQueueId, (UINT32)(qMgrEntryPtr - portDescriptor->qMgrEntries), portDescriptor->qMgrEntries); if (returnStatus != IX_SUCCESS) { /* an unexpected error from qMgr occured.(tx queue full ?) * The scheduler is now out of sync with npe : Tr traffic get dropped, * but the npe and scheduler and atmd will get in sync * again when processing further traffic. * * But at this point, if there is an attempt to disconnect, * disconnect will permanently fail (except if the port is set down) */ returnStatus = IX_ATMDACC_WARNING; } } /* end of if(portDescriptor) */ else { /* we will not process a schedule table when * the port is DOWN. just update stats */ IX_ATMDACC_FULL_STATS( portStats->txProcessFailedCount++; ); returnStatus = IX_FAIL; } /* end of if-else(portDescriptor) */ portDescriptor->schedulingInProgress = FALSE; return returnStatus;}/* -------------------------------------------------------------* Get the maximum number of individual cells that can be* scheduled. This is deduced from the queu size and the* current queue level.*/PUBLIC IX_STATUSixAtmdAccPortTxFreeEntriesQuery (IxAtmLogicalPort port, unsigned int *numberOfCellsPtr){ /* check inputs */ IX_ATMDACC_PARAMS_CHECK( if ((port >= ixAtmdAccTxNumPortConfigured) || (port < IX_UTOPIA_PORT_0) || (numberOfCellsPtr == NULL)) { return IX_FAIL; }); return ixAtmdAccTxQFreeEntriesQuery (port, numberOfCellsPtr);}/* -----------------------------------------------------------* Get the number of free entries in the Tx queue and* pass this back to the user via the user supplied callback*/voidixAtmdAccTxLowCallBack (IxQMgrQId qId, IxQMgrCallbackId cbId){ IX_STATUS status; unsigned int cellNumber; /* When registering a cbId with the Q manager we actually gave * the port number, so we can get the port number back this way */ IxAtmLogicalPort port = (IxAtmLogicalPort)cbId; /* check callback parameter */ IX_ATMDACC_ENSURE (qId >= IX_NPE_A_QMQ_ATM_TXID_MIN, "Qmgr invalid callback qId"); IX_ATMDACC_ENSURE (qId <= IX_NPE_A_QMQ_ATM_TXID_MAX, "Qmgr invalid callback qId"); IX_ATMDACC_ENSURE (port < IX_UTOPIA_MAX_PORTS, "Qmgr invalid callback Id"); IX_ATMDACC_ENSURE (port >= IX_UTOPIA_PORT_0, "Qmgr invalid callback Id"); /* get the number of cells which can be scheduled for this port */ status = ixAtmdAccTxQFreeEntriesQuery (port, &cellNumber); IX_ATMDACC_ENSURE (status == IX_SUCCESS, "can not get tx queue level"); IX_ATMDACC_ENSURE (ixAtmdAccPortDescriptor[port].txLowCallback != NULL, "invalid callback pointer"); /* invoke the user notification callback */ (*ixAtmdAccPortDescriptor[port].txLowCallback) (port, cellNumber);}/* ----------------------------------------------------------* Recycle NPE decsriptors referenced by physical address* pass mbufs back to the user via user supplied callback*/PRIVATE voidixAtmdAccTxDoneProcess (unsigned int physicalAddress){ IxAtmdAccNpeDescriptor *npeDescriptor; IX_OSAL_MBUF *mbufPtr; IxAtmConnId connId; IxAtmdAccTxVcDescriptor *vcDescriptor; IX_ATMDACC_TX_QUEUE *txSwQueue; unsigned int descriptorIndex; /* convert the physical address to a logical address */ npeDescriptor = (IxAtmdAccNpeDescriptor *) physicalAddress; IX_ATMDACC_CONVERT_TO_VIRTUAL_ADDRESS (npeDescriptor); /* invalidate the xscale MMU */ IX_ATMDACC_DATA_CACHE_INVALIDATE(npeDescriptor, sizeof(npeDescriptor->npe.tx)); IX_ATMD_DEBUG_DO( /* check if the signature of the descriptor is still there */ IX_ATMDACC_ABORT(npeDescriptor->atmd.signature == IX_ATMDACC_DESCRIPTOR_SIGNATURE, "Imvalid pointer returned by NPE"); ); /* get values from the desriptor */ connId = npeDescriptor->atmd.connId; /* extract the VC descriptor pool index from the connId * and get the descriptor */ descriptorIndex = IX_ATMDACC_TX_VC_INDEX_GET (connId); vcDescriptor = &ixAtmdAccTxVcDescriptor[descriptorIndex]; txSwQueue = &vcDescriptor->queue; /* check unreachable sw queue conditions */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), " corrupted s/w tx queue"); /* check that NPE descriptor is the one we expected */ if (IX_ATMDACC_TXQ_HEAD_ENTRY_GET (txSwQueue)->atmd.physicalAddress != physicalAddress) { unsigned int count = 0; IX_ATMDACC_FULL_STATS( ixAtmdAccTxDoneDispatchStats.descriptorOrderErrorCount++; ); /* check if we missed a mbuf or a pdu (this occurs as part * of tx shutdown */ do { /* get the first mbuf of the pdu */ mbufPtr = ixAtmdAccUtilMbufFromNpeFormatConvert ( IX_ATMDACC_TXQ_HEAD_ENTRY_GET (txSwQueue)->atmd.pRootMbuf, FALSE); /* pass the pdu to the user */ (*vcDescriptor->txDoneCallback) (vcDescriptor->callbackId, mbufPtr); /* move forward in the queue */ IX_ATMDACC_TXQ_HEAD_INCR(txSwQueue); /* check unreachable sw queue conditions */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), " corrupted s/w tx queue"); count++; } while (count < IX_ATMDACC_TXQ_SIZE(txSwQueue) && IX_ATMDACC_TXQ_HEAD_ENTRY_GET (txSwQueue)->atmd.physicalAddress != physicalAddress); /* check that NPE descriptor is the one we expected */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_HEAD_ENTRY_GET (txSwQueue)->atmd.physicalAddress == physicalAddress, "NPE passed unexpected descriptor"); } /* restore the mbuf address/endianness from the NPE to the user domain */ mbufPtr = ixAtmdAccUtilMbufFromNpeFormatConvert (npeDescriptor->atmd.pRootMbuf, FALSE); /* recycle the descriptor using the descriptorIndex */ IX_ATMDACC_TXQ_HEAD_INCR (txSwQueue); /* check unreachable sw queue conditions */ IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), " corrupted s/w tx queue"); /* call the TX done event for this channel */ vcDescriptor->txDoneCallback (vcDescriptor->callbackId, mbufPtr);}/* ------------------------------------------------* Process a TX shutdown ack*/PRIVATE voidixAtmdAccTxShutdownAck (IxAtmLogicalPort port){ IxAtmdAccPortDescriptor *portDescriptor; if (port < IX_UTOPIA_MAX_PORTS) { portDescriptor = &ixAtmdAccPortDescriptor[port]; if (portDescriptor->status == IX_ATMDACC_PORT_DOWN_PENDING) { /* set the status to down */ portDescriptor->status = IX_ATMDACC_PORT_DOWN; } } /* end of if(port) */ else { /* we ignore the ack */ } /* end of if-else(port) */ return;}/* ------------------------------------------------* Try and process the specified number of entries* from the tx done queue, return the number* actually done*/PUBLIC IX_STATUSixAtmdAccTxDoneDispatch (unsigned int numberOfPdusToProcess, unsigned int *numberOfPdusProcessedPtr){ IX_STATUS returnStatus = IX_SUCCESS; IX_STATUS qmgrStatus; UINT32 qEntry; UINT32 *qEntryPtr; UINT32 numberOfEntriesToRead; IX_ATMDACC_FULL_STATS( unsigned int txDoneCount = 0; ); /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccTxDoneDispatchStats.invokeCount++; ); /* check inputs */ /* number of pdus to process must be > 0 */ /* pointer for return param must not be null */ IX_ATMDACC_PARAMS_CHECK( if (numberOfPdusToProcess == 0 || numberOfPdusProcessedPtr == NULL) { /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccTxDoneDispatchStats.failedCount++; ); return IX_FAIL; }); /* initialise the number of pdu processed */ *numberOfPdusProcessedPtr = 0; do { /* set the pointer to the beginning of the buffer */ qEntryPtr = ixAtmdAccTxDoneDispatchBuffer; /* get the number of entries to read */ if (numberOfPdusToProcess >= IX_ATMDACC_TXDONE_QUEUE_SIZE) { numberOfEntriesToRead = IX_ATMDACC_TXDONE_QUEUE_SIZE; } else { numberOfEntriesToRead = numberOfPdusToProcess; qEntryPtr[numberOfEntriesToRead] = 0; } /* read the TX Done queue. This algorithm suppose that * QMgr will store a null entry at the end of the buffer. The buffer size * is adjusted to contain an extra entry which is used to * mark the end of the buffer. */ qmgrStatus = ixQMgrQBurstRead (IX_NPE_A_QMQ_ATM_TX_DONE, numberOfEntriesToRead, qEntryPtr); /* get the first queue entry */ qEntry = *qEntryPtr; /* iterate until there is a null entry */ while (qEntry != 0) { /* update stats */ IX_ATMDACC_FULL_STATS( txDoneCount++; ); /* check the qentry type * Note for performance reasons the negative logical enables us to * deal with the normal case in the "then", whereas the untypical * is relegated to the "else". (hopefully avoiding a branch) */ if ((qEntry & NPE_TX_SHUTDOWN_ACK_MASK) != NPE_TX_SHUTDOWN_ACK) { /* process NPE descriptor referenced by physical address */ ixAtmdAccTxDoneProcess (qEntry & NPE_DESCRIPTOR_MASK); /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccTxDoneDispatchStats.pduCount++; ); /* increment the number of pdu processed */ (*numberOfPdusProcessedPtr)++; numberOfPdusToProcess--; } /* end of if(qEntry) */ else { /* process shutdown ack */ ixAtmdAccTxShutdownAck ((unsigned int) ((qEntry & NPE_TX_SHUTDOWN_ACK_PORT_MASK) >> NPE_SHUTDOWN_ACK_SHIFT)); /* update stats */ IX_ATMDACC_FULL_STATS( ixAtmdAccTxDoneDispatchStats.ackCount++; ); } /* end of if-else(qEntry) */ /* get the next entry */ qEntry = *(++qEntryPtr); } /* end of while(qEntry) */ } while ((qmgrStatus == IX_SUCCESS) && (numberOfPdusToProcess > 0)); IX_ATMDACC_FULL_STATS(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -