/*----------------------------------------------------------------------------- * Based on Acontis EcDeviceCPSW.cpp * Description ICSS EMAC EtherCAT linklayer driver. *---------------------------------------------------------------------------*/ /*-INCLUDES------------------------------------------------------------------*/ #include #include #include #include #include // //PC-- added TTS test #include #include #include #include #include #include #include #include //PC-- added TTS test #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "icssEmacEcDevice.h" /*-DEFINES-------------------------------------------------------------------*/ #define CPSWID "ICSS_EMAC" #ifdef __cplusplus # define CCALLING extern "C" #else # define CCALLING #endif /* ifdef __cplusplus */ #undef TRACE #ifndef PRINT # if 0 // Used for tracing # define PRINT(msg, ...) fprintf(stdout, (msg), __VA_ARGS__); fflush(stdout) # elif defined __GNUC__ # define PRINT(msg, ...) LinkOsDbgMsg((msg), ##__VA_ARGS__) # else # define PRINT(msg, ...) LinkOsDbgMsg((msg), __VA_ARGS__) # endif #endif #ifdef DEBUG # if defined STARTERWARE_NOOS int G_bCPSWverbose; # define DBG if (G_bCPSWverbose) PRINT # elif defined __GNUC__ # define DBG(msg, ...) PRINT(CPSWID " DBG: " msg, ##__VA_ARGS__) # else # define DBG(msg, ...) PRINT(CPSWID " DBG: " msg, __VA_ARGS__) # endif #else # define DBG(msg, ...) #endif #ifdef TRACE # if defined __GNUC__ # define TRC(msg, ...) PRINT(CPSWID " TRC: " msg, ##__VA_ARGS__) # else # define TRC(msg, ...) PRINT(CPSWID " TRC: " msg, __VA_ARGS__) # endif #else # define TRC(msg, ...) #endif #define _TRC(msg, ...) // Noop. Disabled TRC() #if defined STARTERWARE_NOOS # define INF PRINT # define ERR PRINT #elif defined __GNUC__ # define INF(msg, ...) PRINT(CPSWID " INF: " msg, ##__VA_ARGS__) # define ERR(msg, ...) PRINT(CPSWID " ERR: " msg, ##__VA_ARGS__) #else #define INF(msg, ...) PRINT(CPSWID " INF: " msg, __VA_ARGS__) #define ERR(msg, ...) PRINT(CPSWID " ERR: " msg, __VA_ARGS__) #endif #if defined STARTERWARE_NOOS && defined ADAPTER_DESC_FROM_UC_MEM CCALLING EC_T_DWORD GetStartAddrDdrUc(void); #endif #define ICSS_PORT0_PHY_ADDR 1 #define ICSS_PORT1_PHY_ADDR 2 #define ICSS_PORT1_PHY_ADDR_ICE2 3 unsigned int uartInstance =0; #define RX_BUF_PTR(idx) ((T_CPSW_FRAMEBUFENTRY *) (pAdapter->pRxBuffer + (idx) * sizeof(T_CPSW_FRAMEBUFENTRY))) #define TX_BUF_PTR(idx) ((T_CPSW_FRAMEBUFENTRY *) (pAdapter->pTxBuffer + (idx) * ICSS_TXBUFLEN)) /**This value in the MDIO Reg means 10 mbps mode is enabled*/ #define Ten_Mbps 0xa /**This value in the MDIO Reg means 100 mbps mode is enabled*/ #define Hundread_Mbps 0x64 #define PKT_TX_COUNT 10 #define PRU2ETH0 2 #define PRU2ETH1 3 #ifdef TTS /* TTS Macros */ #define ICSS_EMAC_TTS_CONFIG_TIME 120000 #endif /*************************************************************************************************** * FORWARD DECLARATIONS */ static EC_T_DWORD EcLinkOpen(void* pvLinkParms, EC_T_RECEIVEFRAMECALLBACK pfReceiveFrameCallback, EC_T_LINK_NOTIFY pfLinkNotifyCallback, void* pvContext, void** ppvInstance); static EC_T_DWORD EcLinkClose(void *pvInstance); static EC_T_LINKSTATUS EcLinkGetStatus(void *pvInstance); static EC_T_BOOL ListAddOI(PT_ICSS_EC_INTERNAL poAdapter); static EC_T_BOOL ListRmOI(PT_ICSS_EC_INTERNAL poAdapter); static void ICSSRegisterSet(PT_ICSS_EC_INTERNAL pAdapter,uint8_t PRUSSinstance); static void ICSSSetupBuffers(PT_ICSS_EC_INTERNAL pAdapter); EC_T_DWORD emllPRUTestFrameRcv(void* pvContext, struct _EC_T_LINK_FRAMEDESC* pLinkFrameDesc, EC_T_BOOL* pbFrameProcessed); EC_T_DWORD emllPRUTestNotify(EC_T_DWORD dwCode, struct _EC_T_LINK_NOTIFYPARMS* pParms); static EC_T_BOOL sendAllFrames(EC_T_BYTE *frame, EC_T_DWORD frameLen, EC_T_BYTE dstAddr[6], EC_T_BYTE srcAddr[6], EC_T_DWORD *frameCounter, int txFrames); static EC_T_BOOL sendFrame(EC_T_BYTE *frame, EC_T_DWORD frameLen, EC_T_BYTE dstAddr[6], EC_T_BYTE srcAddr[6]); static EC_T_DWORD EcLinkGetEthernetAddress(void* pvInstance,EC_T_BYTE* pbyEthernetAddress ); static EC_T_LINKMODE EcLinkGetMode(void* pvInstance); static EC_T_DWORD EcLinkGetSpeed(void* pvInstance); static EC_T_DWORD EcLinkIoctl(void* pvInstance, EC_T_DWORD dwCode, EC_T_LINK_IOCTLPARMS* pParms); /*************************************************************************************************** * PRU-ICSS EMAC functions */ static EC_T_DWORD ICSSPhyUpdateLinkStatus(PT_ICSS_EC_INTERNAL pAdapter,ICSS_EmacHandle icssemacHandle); void ICSS_HardwareInit(EC_T_LINK_PARMS_ICSS *pLinkParmsAdapter); int32_t ICSS_EMAC_PruIcssInstance2Setup(void); void ICSS_EMAC_PruIcssFirmwareLoad(uint8_t instance); void ICSS_EMAC_SocCtrlGetPortMacAddr(uint32_t portNum, uint8_t *pMacAddr); void ICSS_EMAC_DrvInit(ICSS_EmacHandle handle, uint8_t instance); void ICSS_EMAC_InterruptInit(ICSS_EmacHandle icssEmacHandle); Bool ICSS_EMAC_IMemInit(PRUICSS_Handle ICSS_EMAC_PruIcssHandle ); Bool ICSS_EMAC_FwVerValidate(ICSS_EmacHandle icssEmacHandle); Bool ICSS_EMAC_DMemInit(PRUICSS_Handle ICSS_EMAC_PruIcssHandle ); /* Call back functions registered with ICSS-EMAC LLD */ void ICSS_EMAC_CallbackRxPacket2(uint8_t* queueNum, void* ICSS_EmacSubSysHandle); void ICSS_EMAC_CallbackRxPacket3(uint8_t* queueNum, void* ICSS_EmacSubSysHandle); void ICSS_EMAC_CallbackTxComplete(void* ICSS_EmacSubSysHandle, void* arg2); #ifdef TTS int8_t ttsSemCreate(); /* TTS Callback and Local functions */ void ICSS_EMAC_TtsCycPort1Callback(); void ICSS_EMAC_TtsCycPort2Callback(); uint32_t deInitTTS(ICSS_EmacHandle icssEmacHandle); EC_T_BYTE initTTS(ICSS_EmacHandle icssEmacHandle, uint32_t cyclePeriod); /* TTS Global Variables */ SemaphoreP_Handle ttsP1TxSem; SemaphoreP_Handle ttsP2TxSem; #endif /*************************************************************************************************** /*************************************************************************************************** * LOCALS */ static EC_T_INT S_nOpenedInstances; static PT_ICSS_EC_INTERNAL S_oOpenInstanceRoot; /*************************************************************************************************** * Variables */ extern ICSS_EmacBaseAddrCfgParams icss_EmacBaseAddrCfgParams[3]; //extern uint8_t board_type; //PC-- Need to check if works May 19 2016 extern uint8_t ICSS_EMAC_testEvmType; //PC-- 03/14/2017 Board_IDInfo info; PRUICSS_Handle pruIcssHandle2; ICSS_EmacHandle emachandle2; ICSS_EmacHandle emachandle3; uint8_t lclMac2[6] = {0x01, 0xbb, 0xce, 0xdd, 0xee, 0xff}; uint8_t lclMac3[6] = {0x01, 0xb4, 0xc4, 0xd4, 0xe4, 0xff}; uint32_t packetLength = 0; uint8_t packet_array[256] = {0}; void* pvLLInstance; //used in TestAppl PT_BUF_QUEUE RxBufQueue; PT_CPSW_FRAMEBUFENTRY pBufEntry_base; uint32_t packetRcvd_port2 = 0; uint32_t packetRcvd_port3 = 0; uint32_t packetTxComplete_port2 = 0; uint32_t packetTxComplete_port3 = 0; #ifdef TTS uint8_t tts_enabled = EC_FALSE; uint32_t max_jitter = 0; #endif uint32_t linkIsr_pru2eth0 = 0; uint32_t linkIsr_pru2eth1 = 0; //PC-- TX Priority Queue number. For TX callback function. Used to classify Cyc/Acycl uint32_t TxPrioQueueNum = 0; /*************************************************************************************************** * DRIVER API */ /********************************************************************************/ /** \brief Open Link Layer connection. * * \return EC_E_NOERROR or error code. */ static EC_T_DWORD EcLinkOpen ( void* pvLinkParms, /* [in] link parameters */ EC_T_RECEIVEFRAMECALLBACK pfReceiveFrameCallback, /* [in] pointer to rx callback function */ EC_T_LINK_NOTIFY pfLinkNotifyCallback, /* [in] pointer to notification callback function */ void* pvContext, /* [in] caller context, to be used in callback functions */ void** ppvInstance /* [out] instance handle */ ) { EC_T_DWORD dwRetVal = EC_E_ERROR; EC_T_LINK_PARMS_ICSS *pLinkParmsAdapter = (EC_T_LINK_PARMS_ICSS*)pvLinkParms; PT_ICSS_EC_INTERNAL pAdapter = EC_NULL; EC_UNREFPARM(pfLinkNotifyCallback); /* check parameters */ if (ppvInstance == EC_NULL) { System_printf("ICSS_EMAC-EcLinkOpen(): No memory for Driver Instance handle provided (ppvInstance may not be EC_NULL)!\n"); dwRetVal = EC_E_INVALIDPARM; goto Exit; } if (pLinkParmsAdapter == EC_NULL) { System_printf("ICSS_EMAC-EcLinkOpen(): Missing Configuration for ICSS Link Layer!\n"); dwRetVal = EC_E_INVALIDPARM; goto Exit; } if (pLinkParmsAdapter->linkParms.dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) { System_printf("ICSS_EMAC-EcLinkOpen(): Invalid Configuration for ICSS Link Layer!\n"); dwRetVal = EC_E_INVALIDPARM; goto Exit; } if ((EC_NULL == pfReceiveFrameCallback) && (EcLinkMode_INTERRUPT == pLinkParmsAdapter->linkParms.eLinkMode) ) { System_printf("ICSS_EMAC-EcLinkOpen(): Missing receive frame callback for interrupt mode!\n"); dwRetVal = EC_E_INVALIDPARM; goto Exit; } if ((pLinkParmsAdapter->linkParms.dwInstance < 1) || (pLinkParmsAdapter->linkParms.dwInstance > 2)) { System_printf("ICSS_EMAC-EcLinkOpen(): Instance must be 1 or 2!\n"); dwRetVal = EC_E_INVALIDPARM; goto Exit; } System_printf( "Instance %d, Port %d\n", pLinkParmsAdapter->linkParms.dwInstance, pLinkParmsAdapter->dwPort); /* create instance */ *ppvInstance = EC_NULL; pAdapter = (PT_ICSS_EC_INTERNAL) LinkOsMalloc(sizeof(T_ICSS_EC_INTERNAL)); LinkOsMemset(pAdapter, 0, sizeof(T_ICSS_EC_INTERNAL)); LinkOsMemcpy(&(pAdapter->oInitParms), pLinkParmsAdapter, sizeof(EC_T_LINK_PARMS_ICSS)); pAdapter->dwLosalHandle = LinkOsOpen(); //if (pAdapter->oInitParms.bMaster) { LinkOsPlatformInit(); } //PC-- ICSS EMAC hardware Init ICSS_HardwareInit(pLinkParmsAdapter); //PC-- ICSS and PRU init. PHY and MAC init. RX interrupt and RX tast init. PRU firmware load ICSSRegisterSet(pAdapter,(uint8_t)pLinkParmsAdapter->linkParms.dwInstance); /* configure new instance */ pAdapter->dwSignature = EC_LINK_PARMS_SIGNATURE_ICSS; pAdapter->pfReceiveFrameCallback = pfReceiveFrameCallback; //PC-- TODO: I think this callback function is not required since Receive works in polling mode only. Need to confirm pAdapter->pvCallbackContext = pvContext; RxBufQueue=QueueBufCreate(); //PC-- RX ring buffer pBufEntry_base= FrameBufEntryCreate(); //PC-- experimental trying to match Acontis buffers // Store address of RX buffers pAdapter->pRxBuffer = (EC_T_BYTE *)pBufEntry_base; ICSSSetupBuffers(pAdapter); //PC-- experimental trying to match Acontis buffers LinkOsSleep(2000); // wait until status is connected //PC-- Update/Check Link status EcLinkIoctl(pAdapter, EC_LINKIOCTL_UPDATE_LINKSTATUS, 0); // Update link status if (EcLinkGetStatus(pAdapter) != eLinkStatus_OK) { System_printf("EcLinkOpen: LINK IS DOWN\n"); }else{ System_printf("EcLinkOpen: LINK IS UP\n"); } // enqueue adapter ListAddOI(pAdapter); // increment instance counter S_nOpenedInstances++; // return "handle" *ppvInstance = pAdapter; // no errors dwRetVal = EC_E_NOERROR; Exit: if (EC_E_NOERROR != dwRetVal && EC_E_INVALIDSTATE != dwRetVal) { *ppvInstance = EC_NULL; if (EC_NULL != pAdapter) { EcLinkClose(pAdapter); pAdapter = EC_NULL; } } return dwRetVal; }; /********************************************************************************/ /** \brief Close Link Layer connection. * * \return EC_E_NOERROR or error code. */ static EC_T_DWORD EcLinkClose( void* pvInstance /* [in] instance handle */ ) { EC_T_DWORD dwRetVal = EC_E_ERROR; PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL) pvInstance; #if defined DEBUG // check for Type Signature */ if (EC_NULL == pAdapter || pAdapter->dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) { dwRetVal = EC_E_INVALIDPARM; goto Exit; } #endif if ( EcLinkMode_INTERRUPT == pAdapter->oInitParms.linkParms.eLinkMode ) { // Disable interrupt LinkOsInterruptDisable( &pAdapter->oIrqParms ); } //PC-- free RX ring FIFO buffer QueueBufDestroy(RxBufQueue); // Remove adapter instance from instance-list ListRmOI(pAdapter); S_nOpenedInstances--; LinkOsFree(pAdapter); dwRetVal = EC_E_NOERROR; goto Exit; Exit: return dwRetVal; }; /*****************************************************************************/ /** \brief Send data frame * * \return EC_E_NOERROR or error code. */ //PC-- TODO: Set/Get the right pLinkFrameDesc input static EC_T_DWORD EcLinkSendFrame(void* pvInstance, EC_T_LINK_FRAMEDESC* pLinkFrameDesc) { EC_T_DWORD dwRetVal = EC_E_ERROR; PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL) pvInstance; ICSS_EmacTxArgument txArg; EC_T_DWORD dwErr; memset(&txArg, 0, sizeof(ICSS_EmacTxArgument)); txArg.srcAddress = pLinkFrameDesc->pbyFrame; txArg.portNumber = (pAdapter->oInitParms.dwPort + 1); txArg.queuePriority = 3; txArg.lengthOfPacket = pLinkFrameDesc->dwSize; if(pAdapter->oInitParms.linkParms.dwInstance==2 && pAdapter->oInitParms.dwPort==0){ txArg.icssEmacHandle = emachandle2; }else if(pAdapter->oInitParms.linkParms.dwInstance==2 && pAdapter->oInitParms.dwPort==1){ txArg.icssEmacHandle = emachandle3; } #ifdef TTS uint8_t tts_cyc_byte_val; #endif if (pLinkFrameDesc->dwSize < 60) { ERR("Can't handle short TX frame (%u Bytes)\n", pLinkFrameDesc->dwSize); dwRetVal = EC_E_ERROR; goto Exit; } txArg.icssEmacHandle = emachandle2; txArg.lengthOfPacket = pLinkFrameDesc->dwSize; txArg.portNumber = (pAdapter->oInitParms.dwPort + 1); txArg.srcAddress = pLinkFrameDesc->pbyFrame; txArg.queuePriority = ICSS_EMAC_QUEUE4; TxPrioQueueNum=4; #ifdef TTS if(tts_enabled == EC_TRUE) { //Hack to queue cyclic frames in queue 1 and others in queue 2. //TODO: Change this to use Acontis structure to find if packet is cyclic or acyclic. tts_cyc_byte_val = HW_RD_REG8((uint32_t)((uint32_t)(pLinkFrameDesc->pbyFrame) + 44)); if(tts_cyc_byte_val==0xc) //Cyclic Frame --> Queue 1 { txArg.queuePriority = ICSS_EMAC_QUEUE1; TxPrioQueueNum=1; } else //Acyclic Frame --> Queue 2 { txArg.queuePriority = ICSS_EMAC_QUEUE2; TxPrioQueueNum=2; } } #endif dwRetVal = ICSS_EmacTxPacket(&txArg, NULL); if (dwRetVal != EC_E_NOERROR) { System_printf( "ICSS_EmacTxPacket returned error 0x%x\n", dwRetVal); return EC_E_ERROR; } // no errors dwRetVal = EC_E_NOERROR; Exit: return dwRetVal; }; /********************************************************************************/ /** \brief Send data frame and free the frame buffer. This function must be * supported if EcLinkAllocSendFrame() is supported * * \return EC_E_NOERROR or error code. */ //PC-- TODO: Set/Get the right pLinkFrameDesc input static EC_T_DWORD EcLinkSendAndFreeFrame( void* pvInstance, EC_T_LINK_FRAMEDESC* pLinkFrameDesc /* [in] link frame descriptor */ ) { EC_T_DWORD dwRetVal = EC_E_ERROR; /* free-ing of buffers and descriptors is done during EcLinkAllocSendFrame so * calling the send routine is enough */ dwRetVal = EcLinkSendFrame(pvInstance, pLinkFrameDesc); return dwRetVal; }; /********************************************************************************/ /** \brief Allocate a frame buffer used for send * * If the link layer doesn't support frame allocation, this function must return * EC_E_NOTSUPPORTED * * \return EC_E_NOERROR or error code. */ static EC_T_DWORD EcLinkAllocSendFrame( void* pvInstance, EC_T_LINK_FRAMEDESC* pLinkFrameDesc, /* [in/out] link frame descriptor */ EC_T_DWORD dwSize /* [in] size of the frame to allocate */ ) { #if defined DEBUG PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL) pvInstance; /* check for Type Signature */ if (EC_NULL == pAdapter || pAdapter->dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) { ERR("Can't alloc TX buffer (Invalid param)\n"); return EC_E_INVALIDPARM; } #endif return EC_E_NOTSUPPORTED;; }; /********************************************************************************/ /** \brief Release a frame buffer previously allocated with EcLinkAllocFrame() * */ static void EcLinkFreeSendFrame( void* pvInstance, EC_T_LINK_FRAMEDESC* pLinkFrameDesc /* [in] link frame descriptor */ ) { EC_UNREFPARM(pvInstance); if (!pLinkFrameDesc || !pLinkFrameDesc->pbyFrame) { return; // wrong parameter } //PC-- TODO: free TX buffer }; /********************************************************************************/ /** \brief Poll for received frame. This function is called by the ethercat Master * if the function EcLinkGetMode() returns EcLinkMode_POLLING * * \return EC_E_NOERROR or error code. */ static EC_T_DWORD EcLinkRecvFrame(void* pvInstance, EC_T_LINK_FRAMEDESC* pLinkFrameDesc) { EC_T_DWORD dwRetVal = EC_E_ERROR; // Needed by upper layer pLinkFrameDesc->pbyFrame = NULL; pLinkFrameDesc->dwSize = 0; //PC-- check if there are buffers ready to be processed if(RxBufQueue->NumWriteBuf>0) { pLinkFrameDesc->pbyFrame = (EC_T_BYTE*)(RxBufQueue->buffer + (RxBufQueue->head*BUF_SIZE)); pLinkFrameDesc->dwSize = (EC_T_DWORD)RxBufQueue->PktLength[RxBufQueue->head]; } if(RxBufQueue->NumWriteBuf>MAX_NUM_BUF) { dwRetVal = EC_E_ERROR; //PC-- need to define an error.. it shouldn't happen goto Exit; } dwRetVal = EC_E_NOERROR; Exit: return dwRetVal; }; /********************************************************************************/ /** \brief Release a frame buffer given to the ethercat master through the receive * callback function * * \return Number of buffers that can be free. */ EC_T_INT EcLinkFreeRecvFrame(void* pvInstance, EC_T_LINK_FRAMEDESC* pLinkFrameDesc) { EC_T_INT RemainingBuf=0; RemainingBuf= QueueFreeBuf(RxBufQueue); //PC-- Free a buffer in Rx DDR ring Queue return RemainingBuf; }; /********************************************************************************/ /** \brief Determine link layer MAC address * * \return EC_E_NOERROR or error code. */ static EC_T_DWORD EcLinkGetEthernetAddress( void* pvInstance, EC_T_BYTE* pbyEthernetAddress ) /* [out] Ethernet MAC address */ { PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL) pvInstance; EC_T_DWORD dwRetVal = EC_E_ERROR; /* check for Type Signature */ if ( (EC_NULL == pAdapter) || (pAdapter->dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) ) { dwRetVal = EC_E_INVALIDPARM; goto Exit; } // TODO do nothing OsMemcpy(pbyEthernetAddress, pAdapter->oInitParms.abyStationAddress, 6); dwRetVal = EC_E_NOERROR; Exit: return dwRetVal; }; /********************************************************************************/ /** \brief Determine current link status. * This routine is called in the EtherCAT main cycle. Be fast... * * \return Current link status. */ static EC_T_LINKSTATUS EcLinkGetStatus(void* pvInstance) { PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL) pvInstance; EC_T_DWORD linkStatus; #if defined DEBUG /* check for Type Signature */ if (EC_NULL == pAdapter || pAdapter->dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) { return eLinkStatus_UNDEFINED; } #endif linkStatus = pAdapter->dwLinkStatus; if (linkStatus & ICSS_LINKFLAG_LINKOK) { if (linkStatus & (ICSS_LINKFLAG_1000baseT_Half | ICSS_LINKFLAG_100baseT_Half | ICSS_LINKFLAG_10baseT_Half)) { return eLinkStatus_HALFDUPLEX; } return eLinkStatus_OK; } return eLinkStatus_DISCONNECTED; }; /********************************************************************************/ /** \brief Determine link speed. * * \return link speed in MBit/sec */ static EC_T_DWORD EcLinkGetSpeed(void* pvInstance) { PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL) pvInstance; EC_T_DWORD dwSpeed = 10; #if defined DEBUG /* check for Type Signature */ if (EC_NULL == pAdapter || pAdapter->dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) { dwSpeed = EC_E_INVALIDPARM; goto Exit; } #endif if (pAdapter->dwLinkStatus & (ICSS_LINKFLAG_1000baseT_Full | ICSS_LINKFLAG_1000baseT_Half)) { dwSpeed = 1000; } else if (pAdapter->dwLinkStatus & (ICSS_LINKFLAG_100baseT_Full | ICSS_LINKFLAG_100baseT_Half)) { dwSpeed = 100; } goto Exit; Exit: return dwSpeed; }; /********************************************************************************/ /** \brief Determine link mode * * \return link mode */ static EC_T_LINKMODE EcLinkGetMode(void* pvInstance) { PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL)pvInstance; EC_T_LINKMODE oLink = EcLinkMode_UNDEFINED; #if defined DEBUG /* check for Type Signature */ if (EC_NULL == pAdapter || pAdapter->dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) { goto Exit; } #endif oLink = pAdapter->oInitParms.linkParms.eLinkMode; goto Exit; Exit: return oLink; }; /********************************************************************************/ /** \brief Multi Purpose LinkLayer IOCTL * * \return EC_E_NOERROR or error code. */ static EC_T_DWORD EcLinkIoctl( void* pvInstance, EC_T_DWORD dwCode, EC_T_LINK_IOCTLPARMS* pParms ) { EC_T_DWORD dwRetVal = EC_E_ERROR; PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL)pvInstance; #if defined DEBUG /* check for Type Signature */ if (EC_NULL == pAdapter || pAdapter->dwSignature != EC_LINK_PARMS_SIGNATURE_ICSS) { goto Exit; } #endif /* fan out IOCTL functions */ switch( dwCode ) { case EC_LINKIOCTL_UPDATE_LINKSTATUS: { //EC_T_DWORD dwOldLinkStatus = pAdapter->dwLinkStatus; if(pAdapter->oInitParms.linkParms.dwInstance==2 && pAdapter->oInitParms.dwPort==0){ pAdapter->dwLinkStatus = ICSSPhyUpdateLinkStatus(pAdapter, emachandle2); }else if(pAdapter->oInitParms.linkParms.dwInstance==2 && pAdapter->oInitParms.dwPort==1){ pAdapter->dwLinkStatus = ICSSPhyUpdateLinkStatus(pAdapter, emachandle3); } // Reconfigure MAC if PHY speed has changed // if (dwOldLinkStatus != pAdapter->dwLinkStatus) // { // CPSWUpdateMacSpeed(pAdapter); // } } break; case EC_LINKIOCTL_GET_ETHERNET_ADDRESS: { if ((EC_NULL == pParms) || (EC_NULL == pParms->pbyOutBuf) || (pParms->dwOutBufSize < 6)) { dwRetVal = EC_E_INVALIDPARM; goto Exit; } dwRetVal = EcLinkGetEthernetAddress(pAdapter, pParms->pbyOutBuf); } break; default: { dwRetVal = EC_E_INVALIDCMD; goto Exit; } } /* no error */ dwRetVal = EC_E_NOERROR; Exit: if( EC_E_NOERROR != dwRetVal ) { #if (defined __RCX__) if( bAllocIrq ) { static RX_RESULT rxRes = RX_OK; rxRes = rX_MemFreeMemory(pAdapter->hInterrupt); OsDbgAssert(rxRes == RX_OK); } #else ;; #endif } return dwRetVal; }; EC_T_DWORD emllPRUTestFrameRcv ( void* pvContext, struct _EC_T_LINK_FRAMEDESC* pLinkFrameDesc, EC_T_BOOL* pbFrameProcessed ) { PT_ICSS_EC_INTERNAL pAdapter = (PT_ICSS_EC_INTERNAL) pvLLInstance; EC_UNREFPARM(pvContext); EC_UNREFPARM(pbFrameProcessed); #ifdef TRACE // Print frame emllDumpFrame(EC_FALSE, (EC_T_BYTE *) pLinkFrameDesc->pbyFrame, pLinkFrameDesc->dwSize); #endif // Frame release EcLinkFreeRecvFrame(pAdapter, pLinkFrameDesc); return EC_E_NOERROR; }; EC_T_DWORD emllPRUTestNotify(EC_T_DWORD dwCode, struct _EC_T_LINK_NOTIFYPARMS* pParms) { EC_UNREFPARM(dwCode); EC_UNREFPARM(pParms); return EC_E_NOERROR; }; static EC_T_LINKSTATUS emllPRUTestGetStatus(void *pvLLInstance) // Query PHY's link status and reconfigure MAC { EcLinkIoctl(pvLLInstance, EC_LINKIOCTL_UPDATE_LINKSTATUS, 0); // Update link status return EcLinkGetStatus(pvLLInstance); }; static EC_T_BOOL sendAllFrames( EC_T_BYTE *frame, EC_T_DWORD frameLen, EC_T_BYTE dstAddr[6], EC_T_BYTE srcAddr[6], EC_T_DWORD *frameCounter, int txFrames) { int j=0; for (j = 0; j < txFrames; ++j) { if (!sendFrame(frame, frameLen, dstAddr, srcAddr)) return EC_FALSE; //PC-- for a quick test dst and src are not updated System_printf("emllPRUTest: Sent frame %d\n",j); (*frameCounter)++; } return EC_TRUE; }; static EC_T_BOOL sendFrame( EC_T_BYTE *frame, EC_T_DWORD frameLen, EC_T_BYTE dstAddr[6], EC_T_BYTE srcAddr[6]) { EC_T_DWORD dwStatus; ICSS_EmacTxArgument txArg; memset(&txArg, 0, sizeof(ICSS_EmacTxArgument)); txArg.srcAddress = frame; txArg.portNumber = 1; txArg.queuePriority = 3; txArg.lengthOfPacket = frameLen; txArg.icssEmacHandle = emachandle2; dwStatus = ICSS_EmacTxPacket(&txArg, NULL); if (dwStatus != EC_E_NOERROR) { System_printf( "ICSS_EmacTxPacket returned error 0x%x\n", dwStatus); return EC_FALSE; } return EC_TRUE; }; /********************************************************************************/ /** \brief Register link layer driver. * * \return EC_E_NOERROR or error code. */ CCALLING EC_T_DWORD emllRegisterICSS( EC_T_LINK_DRV_DESC* pLinkDrvDesc /* [in,out] link layer driver descriptor */ ,EC_T_DWORD dwLinkDrvDescSize /* [in] size in bytes of link layer driver descriptor */ ) { EC_T_DWORD dwResult = EC_E_NOERROR; EC_T_BOOL bInterfaceSupported = EC_FALSE; if (pLinkDrvDesc->dwValidationPattern != LINK_LAYER_DRV_DESC_PATTERN) { ERR("emllRegister: invalid descriptor pattern 0x%x instead of 0x%x\n", pLinkDrvDesc->dwValidationPattern, LINK_LAYER_DRV_DESC_PATTERN); dwResult = EC_E_INVALIDPARM; goto Exit; } /* Check the size of the given link layer driver descriptor */ if (dwLinkDrvDescSize > sizeof(EC_T_LINK_DRV_DESC)) { ERR("emllRegister: link layer driver descriptor size too large\n"); dwResult = EC_E_INVALIDPARM; goto Exit; } bInterfaceSupported = EC_FALSE; /* Check if the version of the interface is supported */ if ( (sizeof(EC_T_LINK_DRV_DESC) == dwLinkDrvDescSize) && (pLinkDrvDesc->dwInterfaceVersion == LINK_LAYER_DRV_DESC_VERSION) ) { bInterfaceSupported = EC_TRUE; } /* Interface is not supported. */ if (! bInterfaceSupported) { ERR("emllRegister: invalid descriptor interface version 0x%x instead of 0x%x\n", pLinkDrvDesc->dwInterfaceVersion, LINK_LAYER_DRV_DESC_VERSION); dwResult = EC_E_INVALIDPARM; goto Exit; } pLinkDrvDesc->pfEcLinkOpen = EcLinkOpen; pLinkDrvDesc->pfEcLinkClose = EcLinkClose; pLinkDrvDesc->pfEcLinkSendFrame = EcLinkSendFrame; pLinkDrvDesc->pfEcLinkSendAndFreeFrame = EcLinkSendAndFreeFrame; pLinkDrvDesc->pfEcLinkRecvFrame = EcLinkRecvFrame; pLinkDrvDesc->pfEcLinkAllocSendFrame = EcLinkAllocSendFrame; pLinkDrvDesc->pfEcLinkFreeSendFrame = EcLinkFreeSendFrame; pLinkDrvDesc->pfEcLinkFreeRecvFrame = EcLinkFreeRecvFrame; pLinkDrvDesc->pfEcLinkGetEthernetAddress = EcLinkGetEthernetAddress; pLinkDrvDesc->pfEcLinkGetStatus = EcLinkGetStatus; pLinkDrvDesc->pfEcLinkGetSpeed = EcLinkGetSpeed; pLinkDrvDesc->pfEcLinkGetMode = EcLinkGetMode; pLinkDrvDesc->pfEcLinkIoctl = EcLinkIoctl; /* store DBG Message hook */ LinkOsAddDbgMsgHook(pLinkDrvDesc->pfOsDbgMsgHook); Exit: return dwResult; }; /*************************************************************************************************** * ICSS-PRU Initialization */ /* * ---function to setup Timer for Receive Packet pacing--- */ int32_t ICSS_EMAC_TimerSetup(ICSS_EmacHandle icssEmacHandle) { void * timerHandle = NULL; TimerP_Params timerParams; memset(&timerParams, 0, sizeof(TimerP_Params)); ICSS_EMAC_osalTimerParamsInit(&timerParams); timerParams.runMode = TimerP_RunMode_CONTINUOUS; timerParams.startMode = TimerP_StartMode_USER; timerParams.periodType = TimerP_PeriodType_MICROSECS; timerParams.period = ICSS_EMAC_TEST_TIMER_PERIOD; timerParams.arg = (void*)icssEmacHandle; /*Create Interrupt Pacing Timer*/ timerHandle = ICSS_EMAC_osalTimerCreate(ICSS_EMAC_TEST_TIMER_ID, (TimerP_Fxn)ICSS_EmacInterruptPacingISR, &timerParams); if ( timerHandle == NULL) { return -1; } else { ((ICSS_EmacObject*)icssEmacHandle->object)->rxPacingTimerHandle = timerHandle; return 0; } }; void ICSS_HardwareInit(EC_T_LINK_PARMS_ICSS *pLinkParmsAdapter) { ICSS_EMAC_PruIcssInstance2Setup(); ICSS_EMAC_PruIcssFirmwareLoad(2); }; int32_t ICSS_EMAC_PruIcssInstance2Setup(void) { PRUICSS_IntcInitData pruss_intc_initdata = PRUSS_INTC_INITDATA; PRUICSS_Config *cfg; ICSS_EmacInitConfig* icss_emacInitCfg0; ICSS_EmacInitConfig* icss_emacInitCfg1; ICSS_EmacFwStaticMmap *pIcssEmacStaticMMap; ICSS_EmacFwDynamicMmap *pIcssEmacDynamicMMap; Task_Params taskParams; int32_t ret = PRUICSS_socGetInitCfg(&cfg); if (ret != PRUICSS_RETURN_SUCCESS) { return (ret); } pruIcssHandle2 = PRUICSS_create((PRUICSS_Config*)cfg,PRUICCSS_INSTANCE_TWO); /* For PRU2 Eth0 */ CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_127, CSL_XBAR_PRUSS2_IRQ_HOST8); /* link ISR */ CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_137, CSL_XBAR_PRUSS2_IRQ_HOST2); /* RX PKT ISR */ CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_129, CSL_XBAR_PRUSS2_IRQ_HOST4); /* TX PKT ISR */ /* For PRU2 Eth1 */ CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_134, CSL_XBAR_PRUSS2_IRQ_HOST9); /* link ISR */ CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_135, CSL_XBAR_PRUSS2_IRQ_HOST3); /* RX PKT ISR */ CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_136, CSL_XBAR_PRUSS2_IRQ_HOST5); /* TX PKT ISR */ /*PRU2 ETH0 initializations*/ emachandle2 = (ICSS_EmacHandle)malloc(sizeof(ICSS_EmacConfig)); icss_emacInitCfg0 = (ICSS_EmacInitConfig*)malloc(sizeof(ICSS_EmacInitConfig)); if ((emachandle2 == NULL) || (icss_emacInitCfg0 == NULL)) { PRINT("main: malloc returned null\n"); } icss_emacInitCfg0->phyAddr[0]=BOARD_ICSS_EMAC_PORT0_PHY_ADDR; icss_emacInitCfg0->portMask = ICSS_EMAC_MODE_MAC1; icss_emacInitCfg0->ethPrioQueue = ICSS_EMAC_QUEUE1; icss_emacInitCfg0->halfDuplexEnable = 0; icss_emacInitCfg0->enableIntrPacing = ICSS_EMAC_ENABLE_PACING;//ICSS_EMAC_ENABLE_PACING; icss_emacInitCfg0->ICSS_EmacIntrPacingMode = ICSS_EMAC_INTR_PACING_MODE2; icss_emacInitCfg0->pacingThreshold = 0; icss_emacInitCfg0->learningEn = 0; icss_emacInitCfg0->macId = lclMac2; ICSS_EMAC_DrvInit(emachandle2,2); #ifdef TTS /*Enable interrupt mode for TTS Cyclic Packet */ icss_emacInitCfg0->ICSS_EmacTTSEnableCycPktInterrupt = ICSS_EMAC_TTS_CYC_INTERRUPT_ENABLE; #endif icss_emacInitCfg0->rxIntNum = CSL_armGicGetGicIdForIrqInputLine(137); icss_emacInitCfg0->linkIntNum=CSL_armGicGetGicIdForIrqInputLine(127); icss_emacInitCfg0->txIntNum = CSL_armGicGetGicIdForIrqInputLine(129); ((ICSS_EmacObject*)emachandle2->object)->pruIcssHandle = pruIcssHandle2; ((ICSS_EmacObject*)emachandle2->object)->emacInitcfg = icss_emacInitCfg0; if (icss_emacGetFwMMapInitConfig(1, &pIcssEmacStaticMMap, &pIcssEmacDynamicMMap) != 0) { PRINT("ICSS_EMAC_PruIcssInstance2Setup: invalid instance Id when calling icss_emacGetFwStaticConfig\n"); return -1; } icss_emacSetFwMMapInitConfig(emachandle2, 1, pIcssEmacStaticMMap, pIcssEmacDynamicMMap); ICSS_EmacInit(emachandle2,&pruss_intc_initdata,ICSS_EMAC_MODE_MAC1|ICSS_EMAC_MODE_DUALMAC); ICSS_EmacRegisterHwIntRx(emachandle2, (ICSS_EmacCallBack)ICSS_EMAC_CallbackRxPacket2); ICSS_EmacRegisterHwIntTx(emachandle2, (ICSS_EmacCallBack)ICSS_EMAC_CallbackTxComplete); #ifdef TTS ICSS_EmacRegisterHwIntTTSCyc(emachandle2, (ICSS_EmacCallBack)ICSS_EMAC_TtsCycPort1Callback); #endif /*PRU2 ETH1 initializations*/ emachandle3 = (ICSS_EmacHandle)malloc(sizeof(ICSS_EmacConfig)); icss_emacInitCfg1 = (ICSS_EmacInitConfig*)malloc(sizeof(ICSS_EmacInitConfig)); if ((emachandle3 == NULL) || (icss_emacInitCfg1 == NULL)) { PRINT("main: malloc returned null\n"); } icss_emacInitCfg1->phyAddr[0]= BOARD_ICSS_EMAC_PORT1_PHY_ADDR; icss_emacInitCfg1->portMask = ICSS_EMAC_MODE_MAC2; icss_emacInitCfg1->ethPrioQueue = ICSS_EMAC_QUEUE3; icss_emacInitCfg1->enableIntrPacing = ICSS_EMAC_DISABLE_PACING; icss_emacInitCfg1->pacingThreshold = 100; icss_emacInitCfg1->learningEn = 0; icss_emacInitCfg1->macId = lclMac3; ICSS_EMAC_DrvInit(emachandle3, 2); #ifdef TTS /* Enable interrupt mode for TTS Cyclic Packet */ icss_emacInitCfg1->ICSS_EmacTTSEnableCycPktInterrupt = ICSS_EMAC_TTS_CYC_INTERRUPT_ENABLE; #endif icss_emacInitCfg1->rxIntNum = CSL_armGicGetGicIdForIrqInputLine(135); icss_emacInitCfg1->linkIntNum=CSL_armGicGetGicIdForIrqInputLine(134); icss_emacInitCfg1->txIntNum = CSL_armGicGetGicIdForIrqInputLine(136); ((ICSS_EmacObject*)emachandle3->object)->pruIcssHandle = pruIcssHandle2; ((ICSS_EmacObject*)emachandle3->object)->emacInitcfg = icss_emacInitCfg1; if (icss_emacGetFwMMapInitConfig(1, &pIcssEmacStaticMMap, &pIcssEmacDynamicMMap) != 0) { PRINT("ICSS_EMAC_PruIcssInstance2Setup: invalid instance Id when calling icss_emacGetFwStaticConfig\n"); return -1; } icss_emacSetFwMMapInitConfig(emachandle3, 1, pIcssEmacStaticMMap, pIcssEmacDynamicMMap); ICSS_EmacInit(emachandle3,&pruss_intc_initdata,ICSS_EMAC_MODE_MAC2|ICSS_EMAC_MODE_DUALMAC); ICSS_EmacRegisterHwIntRx(emachandle3, (ICSS_EmacCallBack)ICSS_EMAC_CallbackRxPacket3); ICSS_EmacRegisterHwIntTx(emachandle3, (ICSS_EmacCallBack)ICSS_EMAC_CallbackTxComplete); #ifdef TTS ICSS_EmacRegisterHwIntTTSCyc(emachandle3, (ICSS_EmacCallBack)ICSS_EMAC_TtsCycPort2Callback); #endif Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port2_rxTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle2; ((ICSS_EmacObject*)emachandle2->object)->rxTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsRxTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle2->object)->rxTaskHandle==NULL) { return -2; } Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port2_txTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle2; ((ICSS_EmacObject*)emachandle2->object)->txTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsTxTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle2->object)->txTaskHandle==NULL) { return -2; } Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port2_linkTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle2; ((ICSS_EmacObject*)emachandle2->object)->linkTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsLinkTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle2->object)->linkTaskHandle==NULL) { return -2; } #ifdef TTS Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port2_ttsCycTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle2; ((ICSS_EmacObject*)emachandle2->object)->ttsCycTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsTTSCycTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle2->object)->ttsCycTaskHandle==NULL) { return -2; } #endif Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port3_rxTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle3; ((ICSS_EmacObject*)emachandle3->object)->rxTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsRxTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle3->object)->rxTaskHandle==NULL) { return -2; } Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port3_txTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle3; ((ICSS_EmacObject*)emachandle3->object)->txTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsTxTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle3->object)->txTaskHandle==NULL) { return -2; } Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port3_linkTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle3; ((ICSS_EmacObject*)emachandle3->object)->linkTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsLinkTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle3->object)->linkTaskHandle==NULL) { return -2; } #ifdef TTS Task_Params_init(&taskParams); taskParams.priority = 15; taskParams.instance->name = (char*)"port3_ttsCycTaskFnc"; taskParams.stackSize = 0x1000; taskParams.arg0 = (UArg)emachandle3; ((ICSS_EmacObject*)emachandle3->object)->ttsCycTaskHandle = Task_create((ti_sysbios_knl_Task_FuncPtr)ICSS_EMacOsTTSCycTaskFnc, &taskParams, NULL); if(((ICSS_EmacObject*)emachandle3->object)->ttsCycTaskHandle==NULL) { return -2; } #endif ICSS_EMAC_InterruptInit(emachandle2); ICSS_EMAC_TimerSetup(emachandle2); ICSS_EMAC_InterruptInit(emachandle3); return 0; }; Bool ICSS_EMAC_IMemInit(PRUICSS_Handle ICSS_EMAC_PruIcssHandle ) { Bool retVal = FALSE; uint32_t ICSS_EMAC_PgVersion = (HW_RD_REG32(CSL_MPU_CTRL_MODULE_WKUP_CORE_REGISTERS_REGS + CTRL_WKUP_ID_CODE) & 0xf0000000) >> 28; if (ICSS_EMAC_PgVersion >= 2) { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_IRAM(0) ,0, (uint32_t *) &pru_imem0_rev2_start, &pru_imem0_rev2_end - &pru_imem0_rev2_start)) { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_IRAM(1) ,0, (uint32_t *) &pru_imem1_rev2_start, &pru_imem1_rev2_end - &pru_imem1_rev2_start)) { retVal = TRUE; } } } else { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_IRAM(0) ,0, (uint32_t *) &pru_imem0_rev1_start, &pru_imem0_rev1_end - &pru_imem0_rev1_start)) { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_IRAM(1) ,0, (uint32_t *) &pru_imem1_rev1_start, &pru_imem1_rev1_end - &pru_imem1_rev1_start)) { retVal = TRUE; } } } return retVal; }; Bool ICSS_EMAC_FwVerValidate(ICSS_EmacHandle icssEmacHandle) { ICSS_EmacFwStaticMmap *pStaticMMap = (&((ICSS_EmacObject*)icssEmacHandle->object)->fwStaticMMap); if (HW_RD_REG32((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr +pStaticMMap->versionOffset) != ICSS_FIRMWARE_RELEASE_1) { PRINT("ICSS_EMAC_FwVerValidate: Firmware validate failure\n"); return FALSE; } else { if (HW_RD_REG32((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr +pStaticMMap->version2Offset) != ICSS_FIRMWARE_RELEASE_2) { PRINT("ICSS_EMAC_FwVerValidate: Firmware validate failure\n"); return FALSE; } } if (HW_RD_REG32((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr +pStaticMMap->versionOffset) != ICSS_FIRMWARE_RELEASE_1) { PRINT("ICSS_EMAC_FwVerValidate: Firmware validate failure\n"); return FALSE; } else { if (HW_RD_REG32((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr +pStaticMMap->version2Offset) != ICSS_FIRMWARE_RELEASE_2) { PRINT("ICSS_EMAC_FwVerValidate: Firmware validate failure\n"); return FALSE; } } PRINT("Validate PRU-ICSS EMAC Firmware: Release1: 0x%x, Release2: 0x%x\n", ICSS_FIRMWARE_RELEASE_1, ICSS_FIRMWARE_RELEASE_2); return TRUE; }; Bool ICSS_EMAC_DMemInit(PRUICSS_Handle ICSS_EMAC_PruIcssHandle ) { Bool retVal = FALSE; uint32_t size = 16U; uint32_t ICSS_EMAC_PgVersion = (HW_RD_REG32(CSL_MPU_CTRL_MODULE_WKUP_CORE_REGISTERS_REGS + CTRL_WKUP_ID_CODE) & 0xf0000000) >> 28; if (ICSS_EMAC_PgVersion >= 2) { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_DATARAM(0) ,0, (uint32_t *) &pru_dmem0_rev2_start, size)) { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_DATARAM(1) ,0, (uint32_t *) &pru_dmem1_rev2_start, size)) { retVal = TRUE; } } } else { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_DATARAM(0) ,0, (uint32_t *) &pru_dmem0_rev1_start, size)) { if(PRUICSS_pruWriteMemory(ICSS_EMAC_PruIcssHandle,PRU_ICSS_DATARAM(1) ,0, (uint32_t *) &pru_dmem1_rev1_start, size)) { retVal = TRUE; } } } return retVal; }; void ICSS_EMAC_PruIcssFirmwareLoad(uint8_t instance) { Bool retVal = FALSE; PRUICSS_pruDisable(pruIcssHandle2, ICSS_EMAC_PORT_1-1); PRUICSS_pruDisable(pruIcssHandle2, ICSS_EMAC_PORT_2-1); retVal = ICSS_EMAC_DMemInit(pruIcssHandle2); if (!retVal) { return; } retVal = ICSS_EMAC_FwVerValidate(emachandle2); if (!retVal) { return; } retVal = ICSS_EMAC_IMemInit(pruIcssHandle2); if( retVal) { PRUICSS_pruEnable(pruIcssHandle2, ICSS_EMAC_PORT_1-1); PRUICSS_pruEnable(pruIcssHandle2, ICSS_EMAC_PORT_2-1); } }; void ICSS_EMAC_DrvInit(ICSS_EmacHandle handle, uint8_t instance) { /* LLD attributes mallocs */ handle->object = (ICSS_EmacObject*)malloc(sizeof(ICSS_EmacObject)); handle->hwAttrs= (ICSS_EmacHwAttrs*)malloc(sizeof(ICSS_EmacHwAttrs)); /* Callback mallocs */ ICSS_EmacCallBackObject* callBackObj = (ICSS_EmacCallBackObject*)malloc(sizeof(ICSS_EmacCallBackObject)); callBackObj->learningExCallBack=(ICSS_EmacCallBackConfig*)malloc(sizeof(ICSS_EmacCallBackConfig)); callBackObj->rxRTCallBack=(ICSS_EmacCallBackConfig*)malloc(sizeof(ICSS_EmacCallBackConfig)); callBackObj->rxCallBack=(ICSS_EmacCallBackConfig*)malloc(sizeof(ICSS_EmacCallBackConfig)); callBackObj->txCallBack=(ICSS_EmacCallBackConfig*)malloc(sizeof(ICSS_EmacCallBackConfig)); ((ICSS_EmacObject*)handle->object)->callBackHandle = callBackObj; /*Allocate memory for learning*/ ((ICSS_EmacObject*)handle->object)->macTablePtr = (HashTable_t*)malloc(NUM_PORTS * sizeof(HashTable_t)); /*Allocate memory for PRU Statistics*/ ((ICSS_EmacObject*)handle->object)->pruStat = (ICSS_EmacPruStatistics_t*)malloc(NUM_PORTS * sizeof(ICSS_EmacPruStatistics_t)); /*Allocate memory for Host Statistics*/ ((ICSS_EmacObject*)handle->object)->hostStat = (ICSS_EmacHostStatistics_t*)malloc(NUM_PORTS * sizeof(ICSS_EmacHostStatistics_t)); /*Allocate memory for Storm Prevention*/ ((ICSS_EmacObject*)handle->object)->stormPrevPtr = (stormPrevention_t*)malloc(NUM_PORTS * sizeof(stormPrevention_t)); /* Base address initialization */ if(NULL == ((ICSS_EmacHwAttrs*)handle->hwAttrs)->emacBaseAddrCfg) { ((ICSS_EmacHwAttrs*)handle->hwAttrs)->emacBaseAddrCfg = (ICSS_EmacBaseAddressHandle_T)malloc(sizeof(ICSS_EmacBaseAddrCfgParams)); } ICSS_EmacBaseAddressHandle_T emacBaseAddr = ((ICSS_EmacHwAttrs*)handle->hwAttrs)->emacBaseAddrCfg; ICSS_EmacSocGetInitCfg((instance-1), emacBaseAddr ); /* Restricting l3OcmcBaseAddr to 0x40xxxx00. * This is done because L3 OCMC Base Address must be 256 byte aligned and to support OCMC memory usage for Linux Power Management. */ emacBaseAddr->l3OcmcBaseAddr = (((emacBaseAddr->l3OcmcBaseAddr)&0xFFFF00)|0x40000000); ICSS_EmacSocSetInitCfg((instance-1), emacBaseAddr ); ICSS_EmacSocGetInitCfg((instance-1), emacBaseAddr ); // PRINT("ICSS_EMAC_DrvInit: instance: %d, data0RamSize: 0x%x, data1RamSize: 0x%x, sharedDataRamSize: 0x%x, l3OcmcSize: 0x%x\n", // instance, emacBaseAddr->dataRam0Size, emacBaseAddr->dataRam1Size, emacBaseAddr->sharedDataRamSize, emacBaseAddr->l3OcmcSize); }; /** * @internal * @brief Registering Interrupts and Enabling global interrupts * * @param icssEmacHandle icssEmacHandle handle to ICSS_EMAC Instance. * * @retval none */ void ICSS_EMAC_InterruptInit(ICSS_EmacHandle icssEmacHandle) { HwiP_Handle rxHwiHandle; HwiP_Handle linkHwiHandle; HwiP_Handle txHwiHandle; static uint32_t cookie = 0; uint32_t linkIntrN = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->linkIntNum; uint32_t rxIntrN = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->rxIntNum; uint32_t txIntrN = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->txIntNum; cookie = ICSS_EMAC_osalHardwareIntDisable(); HwiP_Params hwiParams; ICSS_EMAC_osalHwiParamsInit(&hwiParams); hwiParams.arg = (uintptr_t)icssEmacHandle; hwiParams.evtId = 0; hwiParams.priority = 20; rxHwiHandle = ICSS_EMAC_osalRegisterInterrupt(rxIntrN, (HwiP_Fxn)ICSS_EmacRxInterruptHandler, &hwiParams); if (rxHwiHandle == NULL ){ return; } hwiParams.arg = (uintptr_t)icssEmacHandle; hwiParams.evtId = 0; hwiParams.priority = 20; linkHwiHandle = ICSS_EMAC_osalRegisterInterrupt(linkIntrN, (HwiP_Fxn)ICSS_EmacLinkISR, &hwiParams); if (linkHwiHandle == NULL) { return; } hwiParams.arg = (uintptr_t)icssEmacHandle; hwiParams.evtId = 0; hwiParams.priority = 20; txHwiHandle = ICSS_EMAC_osalRegisterInterrupt(txIntrN, (HwiP_Fxn)ICSS_EmacTxInterruptHandler, &hwiParams); if (txHwiHandle == NULL) { return; } ((ICSS_EmacObject*)icssEmacHandle->object)->txintHandle = txHwiHandle; ((ICSS_EmacObject*)icssEmacHandle->object)->rxintHandle = rxHwiHandle; ((ICSS_EmacObject*)icssEmacHandle->object)->linkintHandle = linkHwiHandle; ICSS_EMAC_osalHardwareIntRestore(cookie); }; static void ICSSRegisterSet(PT_ICSS_EC_INTERNAL pAdapter, uint8_t PRUSSinstance) { PICSS_EC_REGSET pRegs = &pAdapter->regs; EC_T_LINK_PLATFORMDATA_ICSS *pPCfg = &pAdapter->oInitParms.oPlatCfg; //PC-- TODO: need to check if Regs are required on both (pAdapter->regs and pAdapter->oInitParms.oPlatCfg) or if I can avoid double copy pPCfg->dwDataRam0BaseAddr = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].dataRam0BaseAddr; pPCfg->dwDataRam1BaseAddr = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].dataRam1BaseAddr; pPCfg->dwL3OcmcBaseAddr = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].l3OcmcBaseAddr; pPCfg->dwPrussCfgRegs = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].prussCfgRegs; pPCfg->dwPrussIepRegs = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].prussIepRegs; pPCfg->dwPrussIntcRegs = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].prussIntcRegs; pPCfg->dwPrussMiiMdioRegs = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].prussMiiMdioRegs; pPCfg->dwPrussMiiRtCfgRegsBaseAddr = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].prussMiiRtCfgRegsBaseAddr; pPCfg->dwPrussPru0CtrlRegs = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].prussPru0CtrlRegs; pPCfg->dwPrussPru1CtrlRegs = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].prussPru1CtrlRegs; pPCfg->dwSharedDataRamBaseAddrs = icss_EmacBaseAddrCfgParams[PRUSSinstance-1].sharedDataRamBaseAddr; pRegs->dwPrussMiiMdioRegs = pPCfg->dwPrussMiiMdioRegs; pRegs->dwDataRam0BaseAddr = pPCfg->dwDataRam0BaseAddr; pRegs->dwDataRam1BaseAddr = pPCfg->dwDataRam1BaseAddr; pRegs->dwL3OcmcBaseAddr = pPCfg->dwL3OcmcBaseAddr; pRegs->dwPrussCfgRegs = pPCfg->dwPrussCfgRegs; pRegs->dwPrussIepRegs = pPCfg->dwPrussIepRegs; pRegs->dwPrussIntcRegs = pPCfg->dwPrussIntcRegs; pRegs->dwPrussMiiRtCfgRegsBaseAddr = pPCfg->dwPrussMiiRtCfgRegsBaseAddr; pRegs->dwPrussPru0CtrlRegs = pPCfg->dwPrussPru0CtrlRegs; pRegs->dwPrussPru1CtrlRegs = pPCfg->dwPrussPru1CtrlRegs; pRegs->dwSharedDataRamBaseAddrs = pPCfg->dwSharedDataRamBaseAddrs; }; #ifdef TTS /* ---function to create TTS Semaphores---*/ int8_t ttsSemCreate() { SemaphoreP_Params semParams; /* Creating semaphores for TTS Task Port 1 */ ICSS_EMAC_osalSemParamsInit(&semParams); semParams.mode = SemaphoreP_Mode_BINARY; semParams.name = "ttsPort1TxSemaphore"; ttsP1TxSem = ICSS_EMAC_osalCreateBlockingLock(0, &semParams); if(ttsP1TxSem == NULL) { return -1; } /* Creating semaphores for TTS Task Port 2 */ ICSS_EMAC_osalSemParamsInit(&semParams); semParams.mode = SemaphoreP_Mode_BINARY; semParams.name = "ttsPort2TxSemaphore"; ttsP2TxSem = ICSS_EMAC_osalCreateBlockingLock(0, &semParams); if(ttsP2TxSem == NULL) { return -1; } return 0; }; /* Function to de-initialize time triggered send.*/ uint32_t deInitTTS(ICSS_EmacHandle icssEmacHandle) { ICSSEMAC_IoctlCmd ioctlParams; ICSS_EmacTTSConfig ttsConfig; uint8_t portNumber; int8_t ret; if(icssEmacHandle == emachandle2) { portNumber = ICSS_EMAC_PORT_1; } else { portNumber = ICSS_EMAC_PORT_2; } //Setting tts status (Port 1). ttsConfig.icssEmacHandle = icssEmacHandle; ttsConfig.statusTTS = ICSS_EMAC_TTS_DISABLE; ttsConfig.cyclePeriod = 0; ttsConfig.configTime = 0; ttsConfig.cycleStartTime = 0; ttsConfig.cycTxSOFStatus = ICSS_EMAC_TTS_CYC_TXSOF_DISABLE; ttsConfig.portNumber = portNumber; ioctlParams.command = 0; ioctlParams.ioctlVal = (void *)(&ttsConfig); //Disabling time triggered send on PORT 1 (PRU0). ret = ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_TTS_CTRL, portNumber, &ioctlParams); assert(ret == 0); tts_enabled = EC_FALSE; return max_jitter; //PC-- added to return max_jitter for a quick test }; /* Function to initialize time triggered send.*/ EC_T_BYTE initTTS(ICSS_EmacHandle icssEmacHandle, uint32_t cyclePeriod) { int8_t ret; uint8_t portNumber; uint32_t iepRegsBase; uint64_t iepCounterVal; ICSSEMAC_IoctlCmd ioctlParams; ICSS_EmacTTSConfig ttsConfig; /* Create TTS related semaphores */ ret = ttsSemCreate(); assert(ret == 0); if(icssEmacHandle == emachandle2) { portNumber = ICSS_EMAC_PORT_1; } else //if(icssEmacHandle == emachandle3) { portNumber = ICSS_EMAC_PORT_2; } cyclePeriod *= 1000; //Convert from us to ns. ioctlParams.command = 0; iepRegsBase = (((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussIepRegs; ioctlParams.ioctlVal = (void *)(&ttsConfig); ttsConfig.icssEmacHandle = icssEmacHandle; ttsConfig.cycTxSOFStatus = ICSS_EMAC_TTS_CYC_TXSOF_ENABLE; ttsConfig.portNumber = portNumber; ttsConfig.configTime = ICSS_EMAC_TTS_CONFIG_TIME; ttsConfig.cyclePeriod = cyclePeriod; ttsConfig.statusTTS = ICSS_EMAC_TTS_ENABLE; //Reading IEP Counter Value. iepCounterVal = (*((uint64_t*)(iepRegsBase + CSL_ICSSIEP_COUNT_REG0))); /* Calculating cycle start value by adding 100us to counter value. */ ttsConfig.cycleStartTime = (uint64_t)(iepCounterVal + 100000); //Enabling time triggered send. ret = ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_TTS_CTRL, portNumber, &ioctlParams); assert(ret == 0); tts_enabled = EC_TRUE; return ret; }; #endif //TTS /*************************************************************************************************** * Buffer */ PT_BUF_QUEUE QueueBufCreate(void) { PT_BUF_QUEUE BufRing; BufRing = (PT_BUF_QUEUE)malloc(sizeof(BufferQueue)); if (BufRing == NULL) { System_printf("QueueBufCreate: Insufficient Memory for new Queue.\n"); exit(ERROR_MEMORY); } BufRing->head = 0; BufRing->NumAllocBuf = 0; BufRing->NumWriteBuf = 0; BufRing->NumReadBuf = 0; return BufRing; }; PT_CPSW_FRAMEBUFENTRY FrameBufEntryCreate(void) //PC-- experimental trying to match Acontis buffers { PT_CPSW_FRAMEBUFENTRY pBufEntry; pBufEntry = (PT_CPSW_FRAMEBUFENTRY)malloc(sizeof(T_CPSW_FRAMEBUFENTRY)*MAX_NUM_BUF); if (pBufEntry == NULL) { System_printf("FrameBufEntryCreate: Insufficient Memory for new Frame BufEntry.\n"); exit(ERROR_MEMORY); } return pBufEntry; }; void QueueBufDestroy(PT_BUF_QUEUE BufRing) { free(BufRing); }; EC_T_INT QueueFreeBuf(PT_BUF_QUEUE BufQueue) { if (BufQueue->NumAllocBuf <= 0) { //System_printf("QueueFreeBuf: Deleting on Empty Queue.\n"); //exit(ERROR_QUEUE); } if (BufQueue->NumReadBuf <= 0) { //System_printf("QueueFreeBuf: Buffers haven't been processed cannot be free.\n"); //exit(ERROR_QUEUE); } BufQueue->PktLength[BufQueue->head]=0; BufQueue->head++; //PC-- Advance head index BufQueue->head %= MAX_NUM_BUF; //PC-- wraps around BufQueue->NumAllocBuf--; BufQueue->NumReadBuf--; BufQueue->NumWriteBuf--; return BufQueue->NumWriteBuf; }; EC_T_BYTE* QueueAllocBuf(PT_BUF_QUEUE BufQueue) { int newBufIndex; EC_T_BYTE *pBufInQueue; if (BufQueue->NumAllocBuf >= MAX_NUM_BUF) { System_printf("QueueAllocBuf: Allocating on Full Queue.\n"); exit(ERROR_QUEUE); } newBufIndex = (BufQueue->head + BufQueue->NumAllocBuf)% MAX_NUM_BUF; pBufInQueue = (EC_T_BYTE *)(BufQueue->buffer + (newBufIndex*BUF_SIZE)); BufQueue->NumAllocBuf++; return pBufInQueue; }; //PC-- experimental trying to match Acontis buffers TODO: this is unfinished static void ICSSSetupBuffers(PT_ICSS_EC_INTERNAL pAdapter) { T_CPSW_FRAMEBUFENTRY *pBufEntry; int i; for (i = 0; i < (ICSS_RXDESCNT); ++i) { pBufEntry = RX_BUF_PTR(i); pBufEntry->bufentry.dwMagicKey = BUFFER_MAGIC_RX; pBufEntry->bufentry.eBufState = BS_FREE; } }; /*************************************************************************************************** * Callback function */ void ICSS_EMAC_CallbackTxComplete(void* ICSS_EmacSubSysHandle, void* queueNum) { if((ICSS_EmacHandle)ICSS_EmacSubSysHandle == emachandle2) { //UART_printf("packet transmission complete for packet(PRU2ETH0) %d\n", packetTxComplete_port2); packetTxComplete_port2++; } else if((ICSS_EmacHandle)ICSS_EmacSubSysHandle == emachandle3) { //UART_printf("packet transmission complete for packet(PRU2ETH1): %d\n", packetTxComplete_port3); packetTxComplete_port3++; } }; #ifdef TTS /* * ---TTS Cyclic Packet Insertion Interrupt Callback Port 1--- */ void ICSS_EMAC_TtsCycPort1Callback() { ICSS_EMAC_osalPostLock(ttsP1TxSem); }; /* * ---TTS Cyclic Packet Insertion Interrupt Callback Port 2--- */ void ICSS_EMAC_TtsCycPort2Callback() { ICSS_EMAC_osalPostLock(ttsP2TxSem); }; #endif void ICSS_EMAC_CallbackRxPacket2(uint8_t* queueNum, void* ICSS_EmacSubSysHandle) { uint32_t tmp; int32_t morePkts; int32_t port; uint32_t queue; uint32_t idx; queue = (*queueNum); EC_T_BYTE* pRxDDRbuf; packetLength=0; ICSS_EmacRxArgument rxArgs; rxArgs.icssEmacHandle = emachandle2; rxArgs.queueNumber = queue; rxArgs.more = &morePkts; rxArgs.port = &port; if((ICSS_EmacHandle)ICSS_EmacSubSysHandle == emachandle2) /* PRU2 ETH 0 */ { for (tmp = 1; tmp; ) { pRxDDRbuf = QueueAllocBuf(RxBufQueue); rxArgs.destAddress = (uint32_t)pRxDDRbuf; packetLength = ICSS_EmacRxPktGet(&rxArgs, NULL); if(packetLength>0) { RxBufQueue->NumWriteBuf++; idx= (RxBufQueue->head + RxBufQueue->NumAllocBuf-1)% MAX_NUM_BUF; RxBufQueue->PktLength[idx]=packetLength; } if(rxArgs.more== 0) tmp = 0; // exit if there are no more packets } } }; /* PRU2 ETH 0 */ void ICSS_EMAC_CallbackRxPacket3(uint8_t* queueNum, void* ICSS_EmacSubSysHandle) { uint32_t tmp; int32_t morePkts; int32_t port; uint32_t queue; uint32_t idx; queue = (*queueNum); EC_T_BYTE* pRxDDRbuf; packetLength=0; ICSS_EmacRxArgument rxArgs; rxArgs.icssEmacHandle = emachandle3; rxArgs.queueNumber = queue; rxArgs.more = &morePkts; rxArgs.port = &port; if((ICSS_EmacHandle)ICSS_EmacSubSysHandle == emachandle3) /* PRU2 ETH 1 */ { for (tmp = 1; tmp; ) { pRxDDRbuf = QueueAllocBuf(RxBufQueue); rxArgs.destAddress = (uint32_t)pRxDDRbuf; packetLength = ICSS_EmacRxPktGet(&rxArgs, NULL); if(packetLength>0) { RxBufQueue->NumWriteBuf++; idx= (RxBufQueue->head + RxBufQueue->NumAllocBuf-1)% MAX_NUM_BUF; RxBufQueue->PktLength[idx]=packetLength; } if(rxArgs.more== 0) tmp = 0; // exit if there are no more packets } } };/* PRU2 ETH 1 */ /*************************************************************************************************** * PHY & Co */ static EC_T_DWORD ICSSPhyUpdateLinkStatus(PT_ICSS_EC_INTERNAL pAdapter, ICSS_EmacHandle icssemacHandle) { EC_T_DWORD dwLinkStatus = 0; EC_T_DWORD phySpeed=0; volatile uint8_t portStatus = 0; ICSS_EmacFwStaticMmap *pStaticMMap = (&((ICSS_EmacObject*)icssemacHandle->object)->fwStaticMMap); //PC-- added 03/14/17 dwLinkStatus = ICSS_EmacPhyLinkStatusGet((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs, (((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg)->phyAddr[0], 100); if (dwLinkStatus) { dwLinkStatus |= ICSS_LINKFLAG_LINKOK; } //phySpeed = *((uint32_t*)((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + PHY_SPEED_OFFSET)); phySpeed = *((uint32_t*)((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + pStaticMMap->phySpeedOffset)); //portStatus = *((uint8_t*)((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + PORT_STATUS_OFFSET)); portStatus = *((uint8_t*)((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + pStaticMMap->portStatusOffset)); if (phySpeed==Hundread_Mbps && portStatus==ICSS_EMAC_PORT_IS_HD_MASK ) { pAdapter->dwPhyFeatures |= ICSS_LINKFLAG_100baseT_Half; dwLinkStatus |= ICSS_LINKFLAG_100baseT_Half; } if (phySpeed==Hundread_Mbps && portStatus!=ICSS_EMAC_PORT_IS_HD_MASK ) { pAdapter->dwPhyFeatures |= ICSS_LINKFLAG_100baseT_Full; dwLinkStatus |= ICSS_LINKFLAG_100baseT_Full; } if (phySpeed==Ten_Mbps && portStatus==ICSS_EMAC_PORT_IS_HD_MASK ) { pAdapter->dwPhyFeatures |= ICSS_LINKFLAG_10baseT_Half; dwLinkStatus |= ICSS_LINKFLAG_10baseT_Half; } if (phySpeed==Ten_Mbps && portStatus!=ICSS_EMAC_PORT_IS_HD_MASK ) { pAdapter->dwPhyFeatures |= ICSS_LINKFLAG_10baseT_Full; dwLinkStatus |= ICSS_LINKFLAG_10baseT_Full; } return dwLinkStatus; }; /*************************************************************************************************** * List Management */ static EC_T_BOOL ListAddOI(PT_ICSS_EC_INTERNAL poAdapter) { EC_T_BOOL bResult = EC_TRUE; PT_ICSS_EC_INTERNAL oCur = EC_NULL; oCur = S_oOpenInstanceRoot; if( EC_NULL == oCur ) { S_oOpenInstanceRoot = poAdapter; S_oOpenInstanceRoot->pPrev = S_oOpenInstanceRoot->pNext = EC_NULL; } else { while( EC_NULL != oCur->pNext ) { oCur = oCur->pNext; } oCur->pNext = poAdapter; poAdapter->pPrev = oCur; poAdapter->pNext = EC_NULL; }; return bResult; }; static EC_T_BOOL ListRmOI(PT_ICSS_EC_INTERNAL poAdapter) { EC_T_BOOL bResult = EC_TRUE; if( S_oOpenInstanceRoot == poAdapter ) { S_oOpenInstanceRoot = poAdapter->pNext; } if( EC_NULL != poAdapter->pPrev ) { poAdapter->pPrev->pNext = poAdapter->pNext; } if( EC_NULL != poAdapter->pNext ) { poAdapter->pNext->pPrev = poAdapter->pPrev; } poAdapter->pPrev = EC_NULL; poAdapter->pNext = EC_NULL; return bResult; }; void ICSS_EMAC_SocCtrlGetPortMacAddr(uint32_t addrIdx, uint8_t *pMacAddr) { if(addrIdx == 0) { pMacAddr[2U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_1 >> 16U) & 0xFFU; pMacAddr[1U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_1 >> 8U) & 0xFFU; pMacAddr[0U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_1) & 0xFF; pMacAddr[5U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_0 >> 16U) & 0xFFU; pMacAddr[4U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_0 >> 8U) & 0xFFU; pMacAddr[3U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_0) & 0xFFU; } else { pMacAddr[2U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_3 >> 16U) & 0xFFU; pMacAddr[1U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_3 >> 8U) & 0xFFU; pMacAddr[0U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_3) & 0xFF; pMacAddr[5U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_2 >> 16U) & 0xFFU; pMacAddr[4U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_2 >> 8U) & 0xFFU; pMacAddr[3U] = (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->MAC_ID_SW_2) & 0xFFU; } }; /*************************************************************************************************** * TEST APPLICATION */ static EC_T_BYTE S_abyFrameData[60] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Dest Mac */ /*0-5*/ 0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xBE, /* Src Mac */ /*6-11*/ 0x88, 0xa4, /* Type ECAT */ /*12-13*/ 0x0e, 0x10, /* E88A4 Length 0x0e, Type ECAT (0x1) */ /*14-15*/ 0x01, /* APRD */ /*16*/ 0x80, /* Index */ /*17*/ 0x00, 0x00, /* Slave Address */ /*18-19*/ 0x30, 0x01, /* Offset Address */ /*20-21*/ 0x04, 0x00, /* Length - Last sub command */ /*22-23*/ 0x00, 0x00, /* Interrupt */ /*24-25*/ 0x00, 0x00, /* Data */ /*26-27*/ 0x00, 0x00, /* Data 2 */ /*28-29*/ 0x00, 0x00 /* Working Counter */ /*30-31*/ }; #define TXBURST_FRAMES 8 // Number of frames to send per cycle #define RXMSK 1 #define TXMSK 2 //PC-- Test Application function void emll_ICSS_Test() { EC_T_LINK_PARMS_ICSS LinkParamICSS; EC_T_DWORD dwStatus; EC_T_LINK_FRAMEDESC oRecvFrame = {0}; EC_T_DWORD i; EC_T_BYTE dstAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; EC_T_BYTE srcAddress[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xBE }; EC_T_DWORD dwInstance = 0; EC_T_DWORD intFlag = 0; EC_T_BOOL bMaster = EC_FALSE; EC_T_DWORD rxtxMask = 0; EC_T_DWORD numframes = 0; EC_T_DWORD txFrames = 0; EC_T_DWORD rxFrames = 0; EC_T_INT RemainingRxframes =0; System_printf("emll_ICSS_Test test program\n"); //PC-- hard code params dwInstance = 2; //ICSS Eth0 /* dwInstance is 1-based but port index is 0-based */ intFlag = 0; //Polling bMaster = 'm'; rxtxMask = 3; rxtxMask &= 0x3; numframes = 5; System_printf("\n\nInstance %d, Flags [%s] [%s] [%s %s], TX-Frames %d, " "Dst-Addr: %02x:%02x:%02x:%02x:%02x:%02x, Src-Addr: %02x:%02x:%02x:%02x:%02x:%02x\n\n", dwInstance, intFlag ? "Interrupt" : "Polling", bMaster ? "Master" : "Slave", (rxtxMask & RXMSK) ? "RX" : "--", (rxtxMask & TXMSK) ? "TX" : "--", numframes, dstAddress[0], dstAddress[1], dstAddress[2], dstAddress[3], dstAddress[4], dstAddress[5], srcAddress[0], srcAddress[1], srcAddress[2], srcAddress[3], srcAddress[4], srcAddress[5]); /* initialization */ memset(&LinkParamICSS, 0, sizeof(LinkParamICSS)); LinkParamICSS.linkParms.dwInstance = dwInstance; LinkParamICSS.linkParms.dwSignature = EC_LINK_PARMS_SIGNATURE_ICSS; LinkParamICSS.linkParms.eLinkMode = intFlag; dwStatus = EcLinkOpen( &LinkParamICSS, emllPRUTestFrameRcv, emllPRUTestNotify, EC_NULL, &pvLLInstance ); //LinkParamICSS.dwPort = (&pvLLInstance->oInitParms.dwPort+1)%2; // 0 -> Eth0, 1 -> Eth1 LinkParamICSS.dwPort = 1; if (dwStatus != EC_E_NOERROR) { System_printf("emllPRUTest: error 0x%x in EcLinkOpen!\n", dwStatus ); return; } // PC-- Check Link status in ICSS2 eth0 // Wait for link while (emllPRUTestGetStatus(pvLLInstance) != eLinkStatus_OK) { LinkOsSleep(2000); System_printf("emll_ICSS_Test: LINK IS DOWN\n"); } System_printf("emll_ICSS_Test: LINK IS UP\n"); for (i = 0; numframes == 0 || i < numframes; ++i) { if (rxtxMask & TXMSK) { if (!sendAllFrames(S_abyFrameData, sizeof(S_abyFrameData),dstAddress, srcAddress, &txFrames, TXBURST_FRAMES)) System_printf("emllICSSTest: Sent frame %d\n",i); } if (rxtxMask & RXMSK) { // receive frame(s) RemainingRxframes=0xff; for (;;) { if(RemainingRxframes==0) break; //PC-- Nothing to be processed dwStatus = EcLinkRecvFrame(pvLLInstance, &oRecvFrame); // Simulated frame processing Task_sleep(50); //PC-- if buffer gets processed by EC-Master then we can mark it as read and free it RxBufQueue->NumReadBuf++; if (dwStatus != EC_E_NOERROR) { System_printf( "EcLinkRecvFrame returned error 0x%x\n", dwStatus); goto Exit; } if (oRecvFrame.pbyFrame == EC_NULL) break; rxFrames++; // Release frame if(RemainingRxframes>=0) { RemainingRxframes = EcLinkFreeRecvFrame(pvLLInstance, &oRecvFrame); } } } } Exit: dwStatus = EcLinkClose( pvLLInstance ); if( dwStatus != EC_E_NOERROR ) { PRINT( "EcLinkClose returned error 0x%x\n", dwStatus ); return; } }; /*-END OF SOURCE FILE--------------------------------------------------------*/