/* -------------------------------------------------------------- Initialise system components used by the Atm Codelet. -------------------------------------------------------------- */ PUBLIC IX_STATUS ixAtmCodeletSystemInit (UINT32 numPorts, IxAtmCodeletMode mode) { IX_STATUS retval = IX_SUCCESS; #if IX_UTOPIAMODE == 1 IxAtmmPhyMode phyMode = IX_ATMM_SPHY_MODE; #else IxAtmmPhyMode phyMode = IX_ATMM_MPHY_MODE; #endif IxOsalThread dispatchtid; IxOsalThreadAttr threadAttr; char *pThreadName = "QMgr Dispatcher"; #ifdef __vxworks if (endFindByName ("ixe", 0) != NULL) { IX_ATMCODELET_LOG ("FAIL : Driver ixe0 detected\n"); printf("FAIL : Driver ixe0 detected\n"); return IX_FAIL; } if (endFindByName ("ixe", 1) != NULL) { IX_ATMCODELET_LOG ("FAIL : Driver ixe1 detected\\n"); printf("FAIL : Driver ixe1 detected\n"); return IX_FAIL; } #endif /**************** System initialisation ****************/ /* * The IxQMgr component provides interfaces for configuring and accessing the IXP4XX * AQM hardware queues used to facilitate communication of data between the NPEs and * the xscale. IxAtmdAcc configures these queues. The IxQMgr component provides a * dispatcher that will call registered callback functions will specified queue events * occur. */ IX_ATMCODELET_COMP_INIT(ixQMgrInit()); ixQMgrDispatcherLoopGet(&dispatcherFunc); /* This next section sets up how the IxQMgrDispatcher is called. * For the purposes of demonstration under vxWorks the IxQMgrDispatcher * is polled, and under Linux intterrupts are used. * This offers the best performance respectively. */ if (IX_ATMCODELET_USE_QMGR_INT) { /* Running IxQMgrDispatcher from interrupt level */ /* * Bind the IxQMgr dispatcher to interrupt. The IX_QMGR_QUELOW_GROUP group * of queues concern ATM Transmit , Receive, Transmit Done queues */ retval = ixOsalIrqBind(IX_OSAL_IXP400_QM1_IRQ_LVL, (IxOsalVoidFnVoidPtr)(dispatcherFunc), (void *)IX_QMGR_QUELOW_GROUP); if (IX_SUCCESS != retval) { IX_ATMCODELET_LOG ("Failed to bind to QM1 interrupt\n"); return IX_FAIL; } /* * Bind the IxQMgr dispatcher to interrupt. The IX_QMGR_QUELOW_GROUP group * of queues concern ATM Receive Free queues. */ retval = ixOsalIrqBind(IX_OSAL_IXP400_QM2_IRQ_LVL, (IxOsalVoidFnVoidPtr)(dispatcherFunc), (void *)IX_QMGR_QUEUPP_GROUP); if (IX_SUCCESS != retval) { IX_ATMCODELET_LOG ("Failed to bind to QM2 interrupt\n"); return IX_FAIL; } } else /* Running IxQMgrDispatcher from task level */ { threadAttr.name = pThreadName; threadAttr.stackSize = IX_ATMCODELET_QMGR_DISPATCHER_THREAD_STACK_SIZE; threadAttr.priority = IX_ATMCODELET_QMGR_DISPATCHER_PRIORITY; if (ixOsalThreadCreate(&dispatchtid, &threadAttr, (IxOsalVoidFnVoidPtr)ixAtmCodeletDispatchTask, NULL) != IX_SUCCESS) { IX_ATMCODELET_LOG ("Error spawning dispatch task\n"); return IX_FAIL; } if(IX_SUCCESS != ixOsalThreadStart(&dispatchtid)) { IX_ATMCODELET_LOG ("Error starting dispatch task\n"); return IX_FAIL; } } /* Initialise IxNpeMh */ IX_ATMCODELET_COMP_INIT(ixNpeMhInitialize (IX_NPEMH_NPEINTERRUPTS_YES)); /* Download NPE image */ retval = ixAtmUtilsAtmImageDownload (numPorts, &phyMode); if (retval != IX_SUCCESS) { IX_ATMCODELET_LOG ("NPE download failed\n"); return IX_FAIL; } ixAtmCodeletMode = mode; return IX_SUCCESS; }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletEthInit () * * @brief This function allocates resources and initializes every relevant * component that is needed for PTP message transmission from * each NPE. * * @return void */ PRIVATE IX_STATUS ixTimeSyncAccCodeletEthInit () { UINT32 channel, count; IxEthAccPortId portId; IxFeatureCtrlComponentType npe; IX_OSAL_MBUF *mBufPtr; /* check if the device is IXP46X */ if (IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X != ixFeatureCtrlDeviceRead ()) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: this device is not IXP46X\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* check if all NPEs are enabled */ for (channel = 0, npe = IX_FEATURECTRL_NPEA; npe <= IX_FEATURECTRL_NPEC; npe++, channel++) { if (IX_FEATURE_CTRL_COMPONENT_ENABLED != ixFeatureCtrlComponentCheck (npe)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: %s is not enabled\n", (UINT32) ixTimeSyncAccCodeletTSChannelLabel[channel], 0, 0, 0, 0, 0); return IX_FAIL; } } /* allocate mBufs */ ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_MBUF_ALLOC].initialized = TRUE; for (count = 0; count < IX_TIMESYNCACC_CODELET_MAX_TS_CHANNELS; count++) { mBufPtr = ixTimeSyncAccCodeletMbufAllocate (); if (NULL != mBufPtr) { ixTimeSyncAccCodeletGlobalMBuf[count] = mBufPtr; } else { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to allocate mBufs\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } } /* initialize Q Mgr */ if (IX_SUCCESS != ixQMgrInit ()) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to initialize queue manager\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_Q_MGR].initialized = TRUE; /* start Q Mgr dispatcher */ if (IX_SUCCESS != ixTimeSyncAccCodeletDispatcherStart ()) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to start queue manager dispatch loop\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_DISPATCHER].initialized = TRUE; /* initialize NPE message handler */ if (IX_SUCCESS != ixNpeMhInitialize (IX_NPEMH_NPEINTERRUPTS_YES)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to initialize NPE Message Handler\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_NPE_MH].initialized = TRUE; /* download NPE A's image with basic Ethernet Rx/Tx and activate NPE A */ if (IX_SUCCESS != ixNpeDlNpeInitAndStart (IX_NPEDL_NPEIMAGE_NPEA_ETH)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to initialize and start NPE A\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_NPE_A].initialized = TRUE; ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_NPE_DL].initialized = TRUE; /* download NPE B's image with basic Ethernet Rx/Tx and activate NPE B */ if (IX_SUCCESS != ixNpeDlNpeInitAndStart (IX_NPEDL_NPEIMAGE_NPEB_ETH)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to initialize and start NPE B\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_NPE_B].initialized = TRUE; /* download NPE C's image with basic Ethernet Rx/Tx and activate NPE C */ if (IX_SUCCESS != ixNpeDlNpeInitAndStart (IX_NPEDL_NPEIMAGE_NPEC_ETH)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to initialize and start NPE C\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_NPE_C].initialized = TRUE; /* initialize Ethernet Access component */ if (IX_ETH_ACC_SUCCESS != ixEthAccInit()) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to initialize Ethernet access driver\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_ETH_ACC].initialized = TRUE; /* initialize all ethernet ports */ for (portId = IX_ETH_PORT_1; portId <= IX_ETH_PORT_3; portId++) { if (IX_ETH_ACC_SUCCESS != ixEthAccPortInit (portId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to initialize Ethernet port %d\n", portId, 0, 0, 0, 0, 0); return IX_FAIL; } } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_ETH_PORTS].initialized = TRUE; /* spawn new thread to transmit PTP message from each NPEs */ if (IX_SUCCESS != ixTimeSyncAccCodeletNewThreadCreate ((IxOsalVoidFnPtr)ixTimeSyncAccCodeletPTPMsgTransmit, "Tx Thread")) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletEthInit: failed to spawn Tx Thread\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixTimeSyncAccCodeletUninitFuncMap[IX_TIMESYNCACC_CODELET_TX_PTP].initialized = TRUE; return IX_SUCCESS; } /* end of ixTimeSyncAccCodeletEthInit function */
/* * Function definition: ixEthAccCodeletInit() * * See header file for documentation. */ IX_STATUS ixEthAccCodeletInit(IxEthAccCodeletOperation operationType, IxEthAccPortId inPort, IxEthAccPortId outPort) { IxEthAccPortId portId; IxOsalThread statsPollThread; IxOsalThreadAttr threadAttr; threadAttr.name = "Codelet Stats"; threadAttr.stackSize = 32 * 1024; /* 32kbytes */ threadAttr.priority = 128; #ifdef __ixp46X /* Set the expansion bus fuse register to enable MUX for NPEA MII */ { UINT32 expbusCtrlReg; expbusCtrlReg = ixFeatureCtrlRead (); expbusCtrlReg |= ((unsigned long)1<<8); ixFeatureCtrlWrite (expbusCtrlReg); } #endif /* check the component is already initialized */ if(ixEthAccCodeletInitialised) { printf("CodeletMain: Ethernet codelet already initialised\n"); return(IX_SUCCESS); } #ifdef __vxworks /* When the ixe drivers are running, the codelets * cannot run. */ for (portId = 0; portId < IX_ETHACC_CODELET_MAX_PORT; portId++) { if (endFindByName ("ixe", portId) != NULL) { printf("CodeletMain: FAIL: Driver ixe%d detected\n",portId); return IX_FAIL; } } #endif /* Initialize NPE IMAGE ID here again to prevent confusion in multiple * ixEthAccCodeletMain() calls with different operationType. */ ETH_NPEA_IMAGEID = IX_NPEDL_NPEIMAGE_NPEA_ETH_MACFILTERLEARN_HSSCHAN_COEXIST; ETH_NPEB_IMAGEID = IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB; ETH_NPEC_IMAGEID = IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_MASK_FIREWALL_VLAN_QOS_EXTMIB; /* Create mutexes for thread control */ ixEthAccCodeletStatsPollTaskStop = TRUE; ixOsalMutexInit (&ixEthAccCodeletStatsPollTaskRunning); /* Initialise MBUF pool */ if(ixEthAccCodeletMemPoolInit() != IX_SUCCESS) { printf("CodeletMain: Error initialising mBuf pool\n"); return (IX_FAIL); } /* Check Silicon stepping */ printf("Checking Silicon stepping...\n"); if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X) { if ((ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) == IX_FEATURE_CTRL_SILICON_TYPE_B0) { /* * If it is B0 Silicon, we only enable port when its corresponding * Eth Coprocessor is available. */ if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == IX_FEATURE_CTRL_COMPONENT_ENABLED) { ixEthAccCodeletHardwareExists[IX_ETH_PORT_1] = TRUE; } if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == IX_FEATURE_CTRL_COMPONENT_ENABLED) { ixEthAccCodeletHardwareExists[IX_ETH_PORT_2] = TRUE; } } else if ((ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) == IX_FEATURE_CTRL_SILICON_TYPE_A0) { /* * If it is A0 Silicon, we enable both as both Eth Coprocessors * are available. */ ixEthAccCodeletHardwareExists[IX_ETH_PORT_1] = TRUE; ixEthAccCodeletHardwareExists[IX_ETH_PORT_2] = TRUE; } else { printf("CodeletMain: Error. Operation for other silicon stepping is undefined!.\n"); return (IX_FAIL); } } else if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X) { ixEthAccCodeletHardwareExists[IX_ETH_PORT_1] = TRUE; ixEthAccCodeletHardwareExists[IX_ETH_PORT_2] = TRUE; #ifdef __ixp46X ixEthAccCodeletHardwareExists[IX_ETH_PORT_3] = TRUE; #endif } /*********************************************************************** * * System initialisation done. Now initialise Access components. * ***********************************************************************/ /* Initialise Queue Manager */ printf("Initialising Queue Manager...\n"); if (ixQMgrInit() != IX_SUCCESS) { printf("CodeletMain: Error initialising queue manager!\n"); return (IX_FAIL); } /* Start the Queue Manager dispatcher */ if(ixEthAccCodeletDispatcherStart(IX_ETH_CODELET_QMGR_DISPATCH_MODE) != IX_SUCCESS) { printf("CodeletMain: Error starting queue manager dispatch loop!\n"); return (IX_FAIL); } /* Initialise NPE Message handler */ printf("\nStarting NPE message handler...\n"); if(ixNpeMhInitialize(IX_NPEMH_NPEINTERRUPTS_YES) != IX_SUCCESS) { printf("CodeletMain: Error initialising NPE Message handler!\n"); return (IX_FAIL); } /* Initialise NPEs firmware */ printf ("Initialising NPEs...\n"); if (ixEthAccCodeletHardwareExists[IX_ETH_PORT_1]) { if ((operationType == IX_ETHACC_CODELET_BRIDGE_WIFI) && (inPort == IX_ETH_PORT_1)) { printf("CodeletMain: the 802.3 <=> 802.11 header conversion image is loaded on NPE B\n"); ETH_NPEB_IMAGEID = IX_NPEDL_NPEIMAGE_NPEB_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB; } if (IX_SUCCESS != ixNpeDlNpeInitAndStart(ETH_NPEB_IMAGEID)) { printf ("CodeletMain: Error initialising and starting NPE B!\n"); return (IX_FAIL); } } if (ixEthAccCodeletHardwareExists[IX_ETH_PORT_2]) { if ((operationType == IX_ETHACC_CODELET_BRIDGE_WIFI) && (inPort == IX_ETH_PORT_2)) { printf("CodeletMain: the 802.3 <=> 802.11 header conversion image is loaded on NPE C\n"); ETH_NPEC_IMAGEID = IX_NPEDL_NPEIMAGE_NPEC_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB; } if (IX_SUCCESS != ixNpeDlNpeInitAndStart(ETH_NPEC_IMAGEID)) { printf ("CodeletMain: Error initialising and starting NPE C!\n"); return (IX_FAIL); } } #ifdef __ixp46X if (ixEthAccCodeletHardwareExists[IX_ETH_PORT_3]) { if ((operationType == IX_ETHACC_CODELET_BRIDGE_WIFI) && (inPort == IX_ETH_PORT_3)) { printf("CodeletMain: the 802.3 <=> 802.11 header conversion image is loaded on NPE A\n"); ETH_NPEA_IMAGEID = IX_NPEDL_NPEIMAGE_NPEA_ETH_SPAN_VLAN_QOS_HDR_CONV_EXTMIB; } if (IX_SUCCESS != ixNpeDlNpeInitAndStart(ETH_NPEA_IMAGEID)) { printf ("CodeletMain: Error initialising and starting NPE A!\n"); return (IX_FAIL); } } #endif printf ("Initialising Access Layers\n"); /* Enable QoS on ethDB. This has to be done before ethAcc initialisation */ if (operationType == IX_ETHACC_CODELET_BRIDGE_QOS) { printf("Enabling QoS\n"); if (IX_ETH_DB_SUCCESS != ixEthDBInit()) { printf ("CodeletMain: Error initialising EthDB\n"); return (IX_FAIL); } (void)ixEthDBPortInit(inPort); if (IX_ETH_DB_SUCCESS != ixEthDBFeatureEnable(inPort, IX_ETH_DB_VLAN_QOS, TRUE)) { printf("CodeletMain: Error enabling QoS on port %d\n",inPort); return (IX_FAIL); } } /* initialise ethAcc : QoS, if needed is already configured */ if (ixEthAccInit() != IX_ETH_ACC_SUCCESS) { printf("CodeletMain: Error initialising Ethernet access driver!\n"); return (IX_FAIL); } /*********************************************************************** * * Access components initialisation done. Now initialize the ports * ***********************************************************************/ /* Configure all available ports */ for (portId = 0; portId < IX_ETHACC_CODELET_MAX_PORT; portId++) { if (ixEthAccCodeletHardwareExists[portId]) { if(ixEthAccCodeletPortInit(portId) != IX_ETH_ACC_SUCCESS) { printf("CodeletMain: Error setup port %u\n", portId); return (IX_FAIL); } } } /* Find and initialise all available PHYs */ printf ("Discover and reset the PHYs...\n"); if(ixEthAccCodeletPhyInit() != IX_SUCCESS) { printf("CodeletMain: Error initialising Ethernet phy(s)!\n"); return (IX_FAIL); } /*********************************************************************** * * PortInitialization done. Now start the codelet features * ***********************************************************************/ /* starts ethDB maintenance running from a different task */ if (ixEthAccCodeletDBMaintenanceStart() != IX_SUCCESS) { printf("CodeletMain: Error spawning DB maintenance task\n"); return (IX_FAIL); } /* Starts the traffic display (in a different task) this is initially * set to FALSE in order to allow the traffic stats to start only * once traffic is started to be received */ ixEthAccCodeletTrafficPollEnabled = FALSE; if (ixOsalThreadCreate(&statsPollThread, &threadAttr, (IxOsalVoidFnVoidPtr) ixEthAccCodeletStatsPollTask, NULL) != IX_SUCCESS) { printf("CodeletMain: Error spawning stats task\n"); return (IX_FAIL); } /* Start the thread */ if (ixOsalThreadStart(&statsPollThread) != IX_SUCCESS) { printf("CodeletMain: Error failed to start the stats thread\n"); return IX_FAIL; } ixEthAccCodeletInitialised = TRUE; return (IX_SUCCESS); }