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

📄 ixatmdtxtransport.c

📁 有关ARM开发板上的IXP400网络驱动程序的源码以。
💻 C
📖 第 1 页 / 共 4 页
字号:
    {        /* check if all cells are from the current PDU */        if (cellCount <= vcDescriptor->remainingPduCellCount)        {            /* update the current cell count for this pdu */            vcDescriptor->remainingPduCellCount -= cellCount;            /* reuse the same descriptor and transmit the data */            ixAtmdAccCellTx (qMgrEntryPtr,                vcDescriptor->currentNpeDesc->atmd.physicalAddress,                cellCount,                NPE_TX_DATACELL);            /* update stats */            IX_ATMDACC_FULL_STATS(                ixAtmdAccTxTransportStats[vcDescriptor->port].dataCellScheduledCount += cellCount; );            /* all data is transmitted, update the current cell count */            cellCount = 0;        } /* end of if(cellCount) */        else        {        /* we may have to cross a PDU boundary this occur when        * the scheduler schedule cells over PDU boundaries, or        * when the last pdu is completely sent on a previous call        */            if (vcDescriptor->remainingPduCellCount > 0)            {                /* now send the remaining of current PDU */                ixAtmdAccCellTx (qMgrEntryPtr,                    vcDescriptor->currentNpeDesc->atmd.physicalAddress,                    vcDescriptor->remainingPduCellCount,                    NPE_TX_DATACELL);                /* update stats */                IX_ATMDACC_FULL_STATS(                    ixAtmdAccTxTransportStats[vcDescriptor->port].dataCellScheduledCount +=                    vcDescriptor->remainingPduCellCount; );                /* update the current cell count */                cellCount -= vcDescriptor->remainingPduCellCount;            } /* end of if(vcDescriptor) */            /* are there any more PDUs to transmit ? */            if (!IX_ATMDACC_TXQ_SCHEDULE_PENDING (txSwQueue))            {                /* no data available for TX : this should never occur */                /* transmit idle cells as a possible workaround, */                ixAtmdAccCellTx (qMgrEntryPtr,                     NPE_TX_IDLECELL_ADDRESS,                     cellCount,                     NPE_TX_IDLECELL);                /* invalidate the current PDU cell count so that on subsequent                * invocation we behave correctly                */                /* update stats */                IX_ATMDACC_FULL_STATS(                    ixAtmdAccTxTransportStats[vcDescriptor->port].overScheduledCellCount +=                    cellCount; );                cellCount = 0;                vcDescriptor->remainingPduCellCount = 0;            } /* end of if(IX_ATMDACC_TXQ_SCHEDULE_PENDING) */                                                   else            {                /* there are more PDUs to transmit                * get the next descriptor with the PDU attached                 */                /* check unreachable conditions */                IX_ATMDACC_ENSURE (IX_ATMDACC_TXQ_CONSISTENT (txSwQueue), "corrupted sw tx queue");                /* get the current npeDescriptor from the sw queue */                vcDescriptor->currentNpeDesc = 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");                /* update the remaining PDU cell count from the PDU size in cells */                vcDescriptor->remainingPduCellCount = vcDescriptor->currentNpeDesc->atmd.totalCell;                /* update stats */                IX_ATMDACC_FULL_STATS( ixAtmdAccTxTransportStats[vcDescriptor->port].pduScheduledCount++; );            } /* end of if-else(IX_ATMDACC_TXQ_SCHEDULE_PENDING) */        } /* end of if-else(cellCount) */    } /* end of while(cellCount) */}/* -----------------------------------------------------* process the tx schedule array* - qMgrEntryPtr : pointer to a storage area containing requests to the NPE* - scheduleTableEntryPtr : array of entries* - lastScheduleTableEntry : number of entries*/PRIVATE voidixAtmdAccTxScheduleProcess (UINT32 **qMgrEntryPtr,                            IxAtmScheduleTableEntry *scheduleTableEntryPtr,                            unsigned int lastScheduleTableEntry){    /* iterate through each entry of scheduler table */    IxAtmConnId connId;    unsigned int descriptorIndex;    unsigned int cellCount;    IxAtmdAccTxVcDescriptor *vcDescriptor;    IxAtmScheduleTableEntry *lastScheduleTableEntryPtr;        IX_ATMDACC_FULL_STATS( IxAtmdAccTxTransportStats *portStats; );    /* pointer to the last table entry + 1 : this is used as an address comparison    * to check the end of table (more efficient than an index and a loop)    */    lastScheduleTableEntryPtr = &scheduleTableEntryPtr[lastScheduleTableEntry];    /* Iterate through the schedule table and transmit idle    * or data cells on each VC as requested    */    while (scheduleTableEntryPtr != lastScheduleTableEntryPtr)    {        /* get the connection Id from this table entry */        connId = scheduleTableEntryPtr->connId;                /* get the cell count from this table entry */        cellCount = scheduleTableEntryPtr->numberOfCells;        /* extract the VC descriptor pool index from the connId */        descriptorIndex = IX_ATMDACC_TX_VC_INDEX_GET (connId);        vcDescriptor = &ixAtmdAccTxVcDescriptor[descriptorIndex];        IX_ATMDACC_FULL_STATS(         portStats = &ixAtmdAccTxTransportStats[vcDescriptor->port]; );        /* adavnce to the next table entry */        scheduleTableEntryPtr++;        if(cellCount != 0)        {            if (connId == IX_ATM_IDLE_CELLS_CONNID)            {                /* transmit idle cells */                ixAtmdAccCellTx (qMgrEntryPtr,                    NPE_TX_IDLECELL_ADDRESS,                    cellCount,                    NPE_TX_IDLECELL);                                /* update stats */                IX_ATMDACC_FULL_STATS(                    portStats->idleCellScheduledCount +=                    cellCount; );            } /* end of if(connId) */            else            {                if (vcDescriptor->connId == connId)                {                    /* transmit data cells as requested */                    ixAtmdAccChannelTx (qMgrEntryPtr,                        vcDescriptor,                        cellCount);                }                else                {                    /* check for disconnected channels */                    if (IX_ATMDACC_TX_DISCONNECTCHECK(connId,vcDescriptor->connId))                    {                        /* the connId is obsolete, this may occur if the scheduling entity is                        * processing is schedule table exactly during a disconnect. The                        * action is to transmit data cells as requested. This way, recycling                        * can be complete through txDone mechanism                        */                        ixAtmdAccChannelTx (qMgrEntryPtr,                            vcDescriptor,                            cellCount);                        /* update stats */                        IX_ATMDACC_FULL_STATS( portStats->disconnectScheduledCount++; );                    } /* end of if(vcDescriptor) */                    else                    {                        /* The connId provided is obsolete. To fullfill the port                        * contract, idle cells are transmitted instead of data cells                        */                        ixAtmdAccCellTx (qMgrEntryPtr,                            NPE_TX_IDLECELL_ADDRESS,                            cellCount,                            NPE_TX_IDLECELL);                                                /* update stats */                        IX_ATMDACC_FULL_STATS(                             portStats->wrongConnIdScheduledCount++;                            portStats->idleCellScheduledCount += cellCount; );                    } /* end of if-else(vcDescriptor) */                } /* end of if-else(vcDescriptor) */            } /* end of if-else(connId) */        }        else        {            /* update stats */            IX_ATMDACC_FULL_STATS( portStats->zeroCellCount++; );        } /* end of if-else(cellCount) */    } /* end of for(scheduleEntry) */}/* -----------------------------------------------------* process the tx schedule table for this port* the schedule table contains the following fields :* - a table size* - an array pointer* Each elementy of the array contains a connId and a * cell count (the number of cells to be transmitted * for the connection referenced by the connId)*/PUBLIC IX_STATUSixAtmdAccPortTxProcess (IxAtmLogicalPort port,                        IxAtmScheduleTable * scheduleTablePtr){    IxAtmdAccPortDescriptor *portDescriptor;    unsigned int scheduleTableSizeInEntries;    UINT32 *qMgrEntryPtr;    unsigned int numberOfExtraEntriesRequired;    unsigned int scheduleNewTableSizeInEntries;    IxAtmConnId connId;    unsigned int numberOfCells;                  IxAtmScheduleTableEntry *scheduleNewTableEntryPtr;    IX_STATUS returnStatus;    IX_ATMDACC_FULL_STATS( IxAtmdAccTxTransportStats *portStats; );    returnStatus = IX_SUCCESS;        IX_ATMDACC_PARAMS_CHECK(    /* check the port range and schedule table validity */    if ((port >= IX_UTOPIA_MAX_PORTS)        ||        (port < IX_UTOPIA_PORT_0)            ||        (scheduleTablePtr == NULL)           ||        (scheduleTablePtr->table == NULL)    ||        (scheduleTablePtr->totalCellSlots >= IX_ATMDACC_TX_SCHEDULE_TABLE_SIZE)    ||        (scheduleTablePtr->tableSize >= IX_ATMDACC_TX_SCHEDULE_TABLE_SIZE)    ||        (scheduleTablePtr->tableSize == 0))    {        IX_ATMDACC_FULL_STATS(        /* update the stats per port if the port range is valid */        if ((port < IX_UTOPIA_MAX_PORTS) &&            (port >= IX_UTOPIA_PORT_0))        {            portStats = &ixAtmdAccTxTransportStats[port];            IX_ATMDACC_FULL_STATS( portStats->txProcessFailedCount++; );        });        return IX_FAIL;    });    scheduleTableSizeInEntries = scheduleTablePtr->tableSize;    portDescriptor = &ixAtmdAccPortDescriptor[port];    qMgrEntryPtr = portDescriptor->qMgrEntries;     IX_ATMDACC_FULL_STATS(         portStats = &ixAtmdAccTxTransportStats[port];        portStats->txProcessInvokeCount++; );    /* indicate that schedule processing is in progress    * i.e. it is not safe to disconnect    */    portDescriptor->schedulingInProgress = TRUE;    if (portDescriptor->status == IX_ATMDACC_PORT_UP)    {        /* check if there is a threshold set. If so, fill the        * tx queue with single cells to meet the threshold requirements        */        if (portDescriptor->txQueueThreshold > 0)        {            /* move scheduled entries from the schedule table to             * a temporary table,and fill this table with single entries.            * This will guarantee the accuracy of the threshold event.            */            numberOfExtraEntriesRequired = portDescriptor->txQueueThreshold + 1;            scheduleNewTableSizeInEntries = 0;            scheduleNewTableEntryPtr = &portDescriptor->scheduleTable[IX_ATMDACC_TX_SCHEDULE_TABLE_SIZE - 1];            /* reads backwards the schedule table and fill an other schedule            * table containing the exact number of entries required, with            * one cell per entry.            */            while (scheduleTableSizeInEntries > 0 && numberOfExtraEntriesRequired > 0)            {                /* remove the last schedule table entry */                scheduleTableSizeInEntries--;                connId = scheduleTablePtr->table[scheduleTableSizeInEntries].connId;                numberOfCells = scheduleTablePtr->table[scheduleTableSizeInEntries].numberOfCells;                                /* build many new entries with this last schedule table entry */                while (numberOfCells > 0 && numberOfExtraEntriesRequired > 0)                {                    /* add 1 table entry per 1 cell */                    scheduleNewTableEntryPtr--;                    scheduleNewTableSizeInEntries++;                    scheduleNewTableEntryPtr->connId = connId;                    scheduleNewTableEntryPtr->numberOfCells = 1;                    numberOfExtraEntriesRequired--;                    numberOfCells--;                }                if (numberOfCells > 0)                {                    /* update the current new entry with remaining cells                     */                    scheduleNewTableEntryPtr->numberOfCells += numberOfCells;                }            }                        IX_ATMDACC_FULL_STATS(            if ((scheduleTableSizeInEntries + scheduleNewTableSizeInEntries) <= portDescriptor->txQueueThreshold)            {                portStats->txProcessUnderscheduledCount++;            });            /* process the initial schedule table (if any remaining) */            if (scheduleTableSizeInEntries > 0)            {                /* process the schedule table */                ixAtmdAccTxScheduleProcess (&qMgrEntryPtr,                    scheduleTablePtr->table,                    scheduleTableSizeInEntries);            }            /* process the additional schedule table (if any generated) */            if (scheduleNewTableSizeInEntries > 0)            {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -