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

📄 atmoc3rxcp.c

📁 摩托罗拉Motolola公司网络处理器C3的示范代码.实现了ATM的AAL2层交换功能.想了解网络处理器的可以
💻 C
字号:
/* *  Copyright (c) 2000,2001, 2002 C-Port Corporation,A Motorola Company *  All Rights Reserved * *  The information contained in this file is confidential and proprietary. *  Any reproduction, use or disclosure, in whole or in part, of this *  program, including any attempt to obtain a human-readable version of this *  program, without the express, prior written consent of C-Port *  Corporation or Motorola Incorporated is strictly prohibited. * *  File  :     atmRx.c * *  Receive side of the ATM cell switch */#include <dcpPduSvcs.h>#include <dcpQueueSvcs.h>#include <dcpTableSvcs.h>#include <dcpKernelSvcs.h>#include <dcpDiagSvcs.h>#include "atm.h"#include "atmStatus.h"#include "atmIf.h"#include "atmPrivate.h"#include "atmCellDesc.h"#include "atmVcTable.h"#include "rcSdpAtmApiIf.h"#include "errorHandling.h"static QsMessage ALIGNED64 atmRxCellDescMsg;static Boolean     payloadEnqueue = FALSE;static BsBufHandle lastBufferEnqueued = 0;int32u atmCpQmuIrqHandler(void *irqInfo);extern KsContext atmRxNextContext;extern int32u atmPortNum;/* *  atmRx() - Dispatch a cell to the egress CP */int32uatmRx(void* arg){    AtmExtract*      atmExtract;    BsBufHandle      bufHandle;    int32u*          ptr;     VcIngress*       vi;    CellDescriptor*  atmRxCellDesc;    PduHandle        pduHandle;    Boolean          circuitValid = FALSE;    int              destination = 0;    TsStatus         status;    /* QsQueueLevel     trafficClass = 0; */    /*     *  Setup the Cell Descriptor memory     *  Write it once with zeroes to work around the Simulator's      *  read before write feature     */    atmRxCellDesc = qsMessageGetData(&atmRxCellDescMsg);    memset(atmRxCellDesc, 0, sizeof(CellDescriptor));		/* Register the QMU IRQ handler */    ksEventRegisterInterrupt(ksEventIdQmuError, (KsFunc)&atmCpQmuIrqHandler, (void*)0 );    while (1)     {        MSG_EVENT("CPRC: ATMRX wait for scope");                /*         *  Wait for the DCP to signal the reception of a cell header         */        while ((pduHandle = pduRxAllocate()) == NULL)        {            ksContextSwitch(atmRxNextContext);        }        MSG_EVENT("CPRC: ATMRX got scope");        /*         *  Record the payload buffer handle in the cell descriptor         */        bufHandle = pduRxBufHandleGet(pduHandle);        atmRxCellDesc->Bh = bufHandle;        atmExtract = (AtmExtract*)pduRxHeaderGet(pduHandle);        /*         * Record the number of cells dropped by rxByte while         * awaiting scope from the RC - if this count is incrementing,         * the RC cannot keep up with the line.         */        atmStatsBuffer.rxCongestDrops += atmExtract->congestionDrops;#ifdef SIM        if (atmExtract->congestionDrops)         ksPrintf("Cells dropped due to congestion: %x\n", atmExtract->congestionDrops);#endif       /*        * If there is no header error        */        if (!atmExtract->pduHdrStatus)         {            /*             *  Record the Payload Type Indicator and Cell Loss Priority bits             *   in the cell descriptor             */            atmRxCellDesc->payloadType = atmExtract->encodedPti;                       MSG_EVENT("CPRC: ATMRX wait for VC lookup");            /*             *  The SDP microcode launched a lookup of the Vc entry.             *  Wait for the Vc entry lookup response to arrive here.             *   The response is a VC Control Block             */            while (!(status=tsLookupResponseValid(viTag)))             {                ksContextSwitch(atmRxNextContext);            }                          MSG_EVENT("CPRC: ATMRX got VC lookup");            /*             *  Set up the VC control block pointer             *  The VC Control block is always received in ringbus receive slot0             */            ptr  = (int32u*)tsLookupGetResponse(viTag);            /*             * If the cell is on an established connection...             */                        if(ptr!=NULL)            {                   ptr+=2;                 vi=(VcIngress*)ptr;                if((circuitValid = BitIsSet(vi->VcUnicastIngress.Flags,                                                VCFLAGS_VALID_CONNECTION)))                 {                    /* ... if pt-to-pt... */                    if (BitIsClear(vi->VcUnicastIngress.Flags,                                             VCFLAGS_MULTICAST))                     {                        /* if not OAM/RM */                        if (!atmRxCellDesc->payloadType)                         {		            /* 			     * Egress VPI and VCI are being stored in the 			     * ATM cell header. Ingress VcIndex will be 			     * stored in case of AAL2 payloads. Switching			     * is done in AAL2 layer for these cells			     */                            atmRxCellDesc->CellHeader.word =                                (int32u) vi->VcUnicastIngress.atmEgressKey;                            destination  = vi->VcUnicastIngress.QueueId;                                        atmRxCellDesc->VcIndex = vi->VcUnicastIngress.VcIndex;                            atmRxCellDesc->MulticastFlag   = 0;                            atmStatsBuffer.rxGoodCells++;                                                     /* else OAM/RM */                        }                         else                         {                            atmRxCellDesc->CellHeader.word =                                 (atmExtract->cellHeader.word & 0xfffffff0) | atmPortNum;                            destination                  = ATM_CONTROL_PLANE_QUEUE;                            atmRxCellDesc->MulticastFlag = 0;                            atmStatsBuffer.rxOamCells++;                        }                                /* else pt-mpt */                    }                     else                     {                        ksPrintf ("ATM Multi-cast support not provided in Aal2 Switch App") ;                        /*                        destination =(int) (vi->VcMulticastIngress.MulticastVector);                        atmRxCellDesc->VcIndex   = vi->VcMulticastIngress.VcIndex;                        */                        atmRxCellDesc->MulticastFlag = -1;                        /*                        trafficClass   = vi->VcMulticastIngress.TrafficClass;                        atmStatsBuffer.rxGoodCells++;                        */                    }                }                   ptr = NULL;            }            /*             *  We are now finished with the VC Control Block             *   so release the response holding register back to the DCP             */                       tsLookupRelease(viTag);            atmRxCellDesc->crc10Err = atmExtract->crc10Indicator;            if (circuitValid)             {                MSG_EVENT("CPRC: ATMRX wait for payload");                /*                 *  Wait for the cell payload to be fully transfered                 *    into the DRAM buffer                 */                while (!pduRxPayloadDone(pduHandle))                 {                    ksContextSwitch(atmRxNextContext);                }                MSG_EVENT("CPRC: ATMRX got payload");                            if (atmRxCellDesc->MulticastFlag == 0)                 {                    /*                     * The last buffer enqueued is used when an                     * enqueue failed. This buffer must be deallocated                     * if the enqueue fails; otherwise, the buffer                     * is lost. Because the SONET monitoring code                     * enqueues control information to the XPU                     * without any buffer associated with it, we need                     * to mark this enqueue as one with payload.                     * The payloadEnqueue flag does this.                     */                    lastBufferEnqueued = atmRxCellDesc->Bh;                    payloadEnqueue = TRUE;                    qsMessageSend(destination, &atmRxCellDescMsg);                    MSG_EVENT("CPRC: ATMRX wait for buffer allocate");                    /*                     * Allocate a new buffer handle                     * for for using with the PDU services.                     */                    while (bsError(bufHandle = bsBufferAllocate(poolId)))                     {                         ksContextSwitch(atmRxNextContext);                    }                    MSG_EVENT("CPRC: ATMRX buffer allocate done");                }                else                 {                    ksPrintf ("ATM Multi-cast support not provided in Aal2 Switch App") ;                    /*                    qsMessageSendMulti(destination, trafficClass,                                         &atmRxCellDescMsg);                    */                                       /*                     * Use the same buffer handle for the next set of                      * PDU services.                     */                    bufHandle = pduRxBufHandleGet(pduHandle);                }                circuitValid = FALSE;                pduRxBufHandleSet(pduHandle, bufHandle);                pduRxPayloadSet(pduHandle, 0);                pduRxFree(pduHandle);                MSG_EVENT("CPRC: ATMRX scope released");            }             else /* Invalid VC */            {                while (!pduRxPayloadDone(pduHandle)) {                    ksContextSwitch(atmRxNextContext);                }                bufHandle = pduRxBufHandleGet(pduHandle);                pduRxBufHandleSet(pduHandle, bufHandle);                pduRxPayloadSet(pduHandle, 0);                pduRxFree(pduHandle);                atmStatsBuffer.rxInvalidVc++;                dcpTrace1(("Invalid circuit: CP%d CellHeader=0x%08x",                                ksCpId, atmExtract->cellHeader));            }         }        /*         * Else there is a header error, free extract space and reuse buffer         */        else        {            dcpTrace1(("atmRx: Header Error: status=0x%x CellHeader=0x%08x",                      atmExtract->pduHdrStatus, atmExtract->cellHeader.word));            atmStatsBuffer.rxHecErrored++;            while (!pduRxPayloadDone(pduHandle)) {                ksContextSwitch(atmRxNextContext);            }            bufHandle = pduRxBufHandleGet(pduHandle);            pduRxBufHandleSet(pduHandle, bufHandle);            pduRxPayloadSet(pduHandle, 0);            pduRxFree(pduHandle);        }    } /* end while forever */} /* end atmRx() *//* *  Function:      atmCpQmuIrqHandler() * *  Description:   This function is interrupt handler for QMU errors. It is typically *                 called under normal congestion conditions when an enqueue fails *                 to succeed due to the target queue being full. When this occurs *                 this irq handler must free the buffer associated with the last *                 enqueue. * *  Arguments:     An eventInfo block passed in by kernel services. * *  Returns: */int32u atmCpQmuIrqHandler(void *irqInfo){    KsEventInfo *eventInfo = (KsEventInfo *)irqInfo;    if(eventInfo->eventId == ksEventIdQmuError) {        dcpTrace1(("Queue irq, queue %d", eventInfo->address));        /* Only free the buffer associated with the last enqueue if the failed enqueue         * was a unicast operation with payload information. */        // if(eventInfo->command == qsCmdUnicastEnqueue) {            if(payloadEnqueue == TRUE ) {                // ksPrintf("Event address: %d, command: %d", 		        // eventInfo->address, eventInfo->command);                /* Save any context before doing an operation. */                ksEventContextSave();                /* Free the buffer associated with the last enqueue. */                bsBufferFree(lastBufferEnqueued);                /* Wait until operation is done and then restore any context. */                while(!bsBufferWriteComplete());                ksEventContextRestore();                payloadEnqueue = FALSE;                atmStatsBuffer.enqueueFail++;            }            else {                atmStatsBuffer.otherEnqueueFail++;            }        // }    }    return(0);}

⌨️ 快捷键说明

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