⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixatmdtxtransport.c

📁 有关ARM开发板上的IXP400网络驱动程序的源码以。
💻 C
📖 第 1 页 / 共 4 页
字号:
                /* 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 + -