initial release
[apps/tidep0074.git] / ipu1 / icss_emacDrv.c
1 /**
2  * @file icss_emacDrv.c
3  * @brief Contains the Rx and Tx functions for packet processing on ARM including the ISR for two PRU
4  *
5  */
7 /* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/ 
8 *
9 *   Redistribution and use in source and binary forms, with or without 
10 *   modification, are permitted provided that the following conditions 
11 *   are met:
12 *
13 *     Redistributions of source code must retain the above copyright 
14 *     notice, this list of conditions and the following disclaimer.
15 *
16 *     Redistributions in binary form must reproduce the above copyright
17 *     notice, this list of conditions and the following disclaimer in the 
18 *     documentation and/or other materials provided with the   
19 *     distribution.
20 *
21 *     Neither the name of Texas Instruments Incorporated nor the names of
22 *     its contributors may be used to endorse or promote products derived
23 *     from this software without specific prior written permission.
24 *
25 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
26 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
27 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
29 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
30 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
31 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
34 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
35 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
41 /* ========================================================================== */
42 /*                             Include Files                                  */
43 /* ========================================================================== */
45 #include <stdint.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
51 #include <xdc/std.h>
52 #include <xdc/runtime/Error.h>
53 #include <xdc/runtime/System.h>
54 #include <xdc/runtime/knl/Cache.h>
56 #include <xdc/runtime/Diags.h>
57 #include <xdc/runtime/Log.h>
59 #include <ti/csl/src/ip/icss/V0/cslr_icss_intc.h>
60 #include <ti/csl/src/ip/mdio/V2/cslr_mdio.h>
61 #include <ti/csl/src/ip/mdio/V2/csl_mdio.h>
62 #include <ti/csl/src/ip/mdio/V2/csl_mdioAux.h>
64 #include <ti/drv/pruss/pruicss.h>
66 //#include <ti/drv/icss_emac/icss_emacDrv.h>
67 #include <icss_emacDrv.h>
68 #include <ti/drv/icss_emac/icss_emacCommon.h>
69 #include <ti/drv/icss_emac/icss_emacStatistics.h>
70 #include <ti/drv/icss_emac/icss_emacStormControl.h>
71 #include <ti/drv/icss_emac/icss_emacLearning.h>
72 #include <ti/drv/icss_emac/icss_emacFwInit.h>
73 #include <ti/drv/icss_emac/icss_emac_osal.h>
75 extern int32_t PruSwitch(char *pIcssRxPkt);
76 /* ========================================================================== */
77 /*                           Macros & Typedefs                                */
78 /* ========================================================================== */
80 /**This value in the MDIO Reg means 10 mbps mode is enabled*/
81 #define Ten_Mbps  0xa
82 /**This value in the MDIO Reg means 100 mbps mode is enabled*/
83 #define Hundread_Mbps 0x64
84 /**Minimum supported size of Ethernet frame*/
85 #define ETHERNET_FRAME_SIZE_60 60
87 #define LINK0_PRU_EVT_MASK  (0x200U)
88 #define LINK1_PRU_EVT_MASK  (0x200000U)
89 /**Pacing timer Value*/
90 #define DEFAULT_PACING_TIMER_VAL 100
92 #define ENABLE_TIMER_SUPPORT
94 /**Timer Handle for pacing*/
95 #ifdef ENABLE_TIMER_SUPPORT
96 void* pacingTimerHandle;
97 #endif
99 #define PHY_LINK_STATUS                   (0x0004u)
100 #define PHY_BSR                           (1u)
101 /* ========================================================================== */
102 /*                            Global Variables                                */
103 /* ========================================================================== */
106 /** Variable containing list of implemented protocols*/
107 uint16_t numImplementedProtocols = NUM_PROTOCOLS_IMPLEMENTED;
108 /**list of identified protocol types, rest initialized to zero*/
109 uint16_t protocol_impl[MAX_NUM_PROTOCOL_IMPLEMENTED] = {IP4_PROT_TYPE, ARP_PROT_TYPE,0,0,0,0, 0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
110                                                         0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0};
111 /** port params for three ports, two physical and one for host*/
112 //ICSS_EmacPortParams switchPort[3];
113 /**Number of collisions occured*/
114 int32_t num_of_collision_occured = 0;
115 /**Number of packets dropped as a result of collision not resolved*/
116 int32_t collision_pkt_dropped =0;
117 /** @brief User specific data HW Port 0 Link ISR*/
120 /* ========================================================================== */
121 /*                          Function Definitions                              */
122 /* ========================================================================== */
123 /**
124  *  \name ICSS_EmacClearRxIrq
125  *  @brief Clears Rx interrupt
126  *
127  *  @param none
128  *
129  *  @retval none
130  *
131  */
132 inline void ICSS_EmacClearRxIrq(ICSS_EmacHandle icssemacHandle);   /* for misra warning*/
133 inline void ICSS_EmacClearRxIrq(ICSS_EmacHandle icssemacHandle)
135     if((((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg)->portMask == ICSS_EMAC_MODE_MAC2) {
136         HW_WR_FIELD32(((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->prussIntcRegs + CSL_ICSSINTC_SECR0),
137                 CSL_ICSSINTC_SECR0_ENA_STATUS_31_0, (1U) << 21);
138     } else {
139         HW_WR_FIELD32(((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->prussIntcRegs + CSL_ICSSINTC_SECR0),
140                 CSL_ICSSINTC_SECR0_ENA_STATUS_31_0, (1U) << 20);
141     }
144 void ICSS_EmacEnableRxInterrupt(ICSS_EmacHandle icssemacHandle);   /* for misra warning*/
145 void ICSS_EmacEnableRxInterrupt(ICSS_EmacHandle icssemacHandle)
147     uint32_t intNum = ((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg->rxIntNum;
148     ICSS_EMAC_osalHardwareInterruptEnable((int32_t)intNum);
151 void ICSS_EmacDisableRxInterrupt(ICSS_EmacHandle icssemacHandle);  /* for misra warning*/
152 void ICSS_EmacDisableRxInterrupt(ICSS_EmacHandle icssemacHandle)
154     uint32_t intNum = ((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg->rxIntNum;
155     ICSS_EMAC_osalHardwareInterruptDisable((int32_t)intNum);
160 /**
161  *  \name ICSS_EmacClearTxIrq
162  *  @brief Clears Tx Packet Completion interrupt
163  *
164  *  @param none
165  *
166  *  @retval none
167  *
168  */
169 inline void ICSS_EmacClearTxIrq(ICSS_EmacHandle icssemacHandle); /* for misra warnings*/
170 inline void ICSS_EmacClearTxIrq(ICSS_EmacHandle icssemacHandle)
172     if((((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg)->portMask == ICSS_EMAC_MODE_MAC2) {
173         HW_WR_FIELD32(((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->prussIntcRegs + CSL_ICSSINTC_SECR0),
174                 CSL_ICSSINTC_SECR0_ENA_STATUS_31_0, (1U) << 23);
175     } else {
176         HW_WR_FIELD32(((((ICSS_EmacHwAttrs*)icssemacHandle->hwAttrs)->emacBaseAddrCfg)->prussIntcRegs + CSL_ICSSINTC_SECR0),
177                 CSL_ICSSINTC_SECR0_ENA_STATUS_31_0, (1U) << 22);
178     }
181 void ICSS_EmacEnableTxInterrupt(ICSS_EmacHandle icssemacHandle); /* for misra warnings*/
182 void ICSS_EmacEnableTxInterrupt(ICSS_EmacHandle icssemacHandle) {
183     uint32_t intNum = ((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg->txIntNum;
184     ICSS_EMAC_osalHardwareInterruptEnable((int32_t)intNum);
187 void ICSS_EmacDisableTxInterrupt(ICSS_EmacHandle icssemacHandle); /* for misra warnings*/
188 void ICSS_EmacDisableTxInterrupt(ICSS_EmacHandle icssemacHandle) {
189     uint32_t intNum = ((ICSS_EmacObject*)icssemacHandle->object)->emacInitcfg->txIntNum;
190     ICSS_EMAC_osalHardwareInterruptDisable((int32_t)intNum);
193 /**
194  *  \name ICSS_EmacTxInterruptHandler
195  *  @brief Main Tx completion interrupt service routine
196  *
197  *  @param args arguments if any
198  *
199  *  @retval
200  *       void
201  *
202  */
203 void ICSS_EmacTxInterruptHandler(void *args)
205     ICSS_EmacHandle handle = (ICSS_EmacHandle)args;
206     ICSS_EMAC_osalPostLock(((ICSS_EmacObject*)handle->object)->txSemaphoreHandle);
207     ICSS_EmacClearTxIrq((ICSS_EmacHandle)args);
209 /**
210  *  \name ICSS_EmacRxInterruptHandler
211  *  @brief Main Rx interrupt service routine
212  *
213  *  @param args arguments if any
214  *
215  *  @retval
216  *       void
217  *
218  */
219 void ICSS_EmacRxInterruptHandler(void *args)
221     uint8_t pacingEnabled;
222 #ifdef ENABLE_TIMER_SUPPORT
223     uint8_t pacingMode;
224 #endif
225     ICSS_EmacHandle handle = (ICSS_EmacHandle)args;
226     ICSS_EmacClearRxIrq((ICSS_EmacHandle)args);
228     pacingEnabled = (((ICSS_EmacObject*)handle->object)->emacInitcfg)->enableIntrPacing;
230 #ifdef ENABLE_TIMER_SUPPORT
231     pacingMode = (((ICSS_EmacObject*)handle->object)->emacInitcfg)->ICSS_EmacIntrPacingMode;
232 #endif
233     /*disable Rx interrupt on ARM, PRU line stays high*/
234     if(pacingEnabled == ICSS_EMAC_ENABLE_PACING) {
235         ICSS_EmacDisableRxInterrupt(handle);
237 #ifdef ENABLE_TIMER_SUPPORT
238         if(pacingMode == ICSS_EMAC_INTR_PACING_MODE2) {
239             ICSS_EMAC_osalTimerStart(pacingTimerHandle);
240         }
241 #endif
242      }
244     ICSS_EMAC_osalPostLock(((ICSS_EmacObject*)handle->object)->rxSemaphoreHandle);
247 /**
248  *  \name ICSS_EMacOsRxTaskFnc
249  *  @brief
250  *      Function which pends on Rx semaphore.Gets the Rx packet info for processing
251  *
252  *  @param a0 arg 1
253  *  @param a1 arg 2
254  *
255  *  @retval none
256  *
257  */
258 void ICSS_EMacOsRxTaskFnc(uint32_t a0, uint32_t a1)
260     int32_t port_number;
261     int32_t queue_number;
262     int32_t pkt_proc;
263     int16_t pLength;
264     int32_t allQueuesEempty = 0;
265     int8_t  dest_address[ICSS_EMAC_MAXMTU];
266     uint16_t numPacketsInLoop = 0;
267     uint8_t pacingEnabled;
268     uint8_t pacingMode;
269     ICSS_EmacHandle icssEmacHandle;
270     icssEmacHandle = (ICSS_EmacHandle)a0;
271     ICSS_EmacRxArgument rxArg;
273     pacingEnabled = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->enableIntrPacing;
274     pacingMode    = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->ICSS_EmacIntrPacingMode;
276     while(1)
277     {
278         ICSS_EMAC_osalPendLock(((ICSS_EmacObject*)icssEmacHandle->object)->rxSemaphoreHandle, SemaphoreP_WAIT_FOREVER);
280         while((allQueuesEempty != 1) && (numPacketsInLoop <= ((((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->pacingThreshold)))
281         {
282             pLength = ((int16_t)(ICSS_EmacRxPktInfo(icssEmacHandle, &port_number, &queue_number, &pkt_proc)));
283             if(pLength > 0)
284             {
285                 /*Ethernet packet will be put into ICSS_EMAC_QUEUEPRIO4 only
286                  * Give the packet to ndk stack*/
287                 if(queue_number >= ((ICSS_EmacObject*)(icssEmacHandle->object))->emacInitcfg->ethPrioQueue)
288                 {
289                       ((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntRx(&queue_number,icssEmacHandle);
290                 } 
291                 else 
292                 {
293                     if(((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->callBack != NULL) {
294                         ((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->callBack(&queue_number,
295                                 ((((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->rxRTCallBack)->userArg);
296                     } else {
297                             rxArg.icssEmacHandle = icssEmacHandle;
298                             rxArg.destAddress = (uint32_t)dest_address;
299                             rxArg.more = 0;
300                             rxArg.queueNumber = queue_number;
301                             rxArg.port=port_number;
303                             ((((ICSS_EmacObject *)icssEmacHandle->object)->callBackHandle)->rxCallBack)->callBack(&rxArg,NULL);   /* just dump the packet here so we do no stall the queues */
304                     }
306                 }
307                 if(pacingEnabled == ICSS_EMAC_ENABLE_PACING) {
308                     numPacketsInLoop++;
309                 }
310             } 
311             else 
312             {
313                 allQueuesEempty =1;
314             }
315         }
316         allQueuesEempty =0;
318         if(pacingEnabled == ICSS_EMAC_ENABLE_PACING) {
319             numPacketsInLoop = 0;
320             /*Enable interrupts*/
321             if(pacingMode == ICSS_EMAC_INTR_PACING_MODE1) {
322                 ICSS_EmacEnableRxInterrupt(icssEmacHandle);
323             }
324         }
326     }
328 /**
329  *  \name ICSS_EmacInterruptPacingISR
330  *  @brief ISR for Interrupt Pacing DM Timer
331  *
332  *  @param args arguments if any
333  *
334  *  @retval
335  *       void
336  *
337  */
338 void ICSS_EmacInterruptPacingISR(void *args); /* for misra warning*/
339 void ICSS_EmacInterruptPacingISR(void *args)
341     ICSS_EmacHandle icssEmacHandle;
342     icssEmacHandle = (ICSS_EmacHandle)args;
343     ICSS_EmacEnableRxInterrupt(icssEmacHandle);
346 /**
347  *  @b Description
348  *  @n
349  *      API to queue a frame which has to be transmitted on the
350  *      specified port queue
351  *
352  *  @param[in]  txArg defined at @ref ICSS_EmacTxArgument
353  *  @param[in]  userArg custom Tx packet callback packet options only required for custom TxPacket implementations,
354                 default to NULL when calling ICSS_EmacTxPacket which is default Tx Packet API
355  *  @retval     0 on scuess,  <0 on failure
356  */
357 int32_t ICSS_EmacTxPacket(ICSS_EmacTxArgument *txArg, void* userArg)
360     int32_t ret=-1;
361     const uint8_t*        macId;
362     uint8_t txPort, trigTx1, trigTx2;
364     ICSS_EmacHandle icssEmacHandle = txArg->icssEmacHandle;
365     uint8_t portNumber= txArg->portNumber;
366     uint8_t queuePriority = txArg->queuePriority;
367     uint16_t lengthOfPacket = txArg->lengthOfPacket;
369     
370     int32_t ret_val = 0;
372     macId = txArg->srcAddress;
374     if (portNumber == ICSS_EMAC_PORT_0)    /* special case to use MAC learning */
375     {
376         /* get the Port number from MAC tables.. */
377         txPort = findMAC(macId, ((ICSS_EmacObject*)(icssEmacHandle)->object)->macTablePtr);
379         switch (txPort)
380         {
381             case 0U: /* need to send on both ports */
382                 trigTx1 = 1U;
383                 trigTx2 = 1U;
384                 break;
385             case 1U: /* ICSS_EMAC_PORT_1 */
386                 trigTx1 = 1U;
387                 trigTx2 = 0U;
388                 break;
389             case 2U: /* ICSS_EMAC_PORT_2 */
390                 trigTx1 = 0U;
391                 trigTx2 = 1U;
392                 break;
393             default:    /* ICSS_EMAC_PORT_0 */
394                 trigTx1 = 1U;
395                 trigTx2 = 0U;
396                 break;
397         }
398         if(trigTx1 == 1U)
399         {
400             ret = ICSS_EmacTxPacketEnqueue(icssEmacHandle,
401                                            txArg->srcAddress,
402                                            ICSS_EMAC_PORT_1, 
403                                            queuePriority,
404                                            lengthOfPacket);
405         }
406         if(trigTx2 == 1U)
407         {
408             if (ret == 0) {
409                 ICSS_EmacTxPacketEnqueue( icssEmacHandle,
410                                           txArg->srcAddress,
411                                           ICSS_EMAC_PORT_2,
412                                           queuePriority,
413                                           lengthOfPacket);
414             } else {
415                 ret = ICSS_EmacTxPacketEnqueue( icssEmacHandle,
416                                                 txArg->srcAddress,
417                                                 ICSS_EMAC_PORT_2,
418                                                 queuePriority,
419                                                 lengthOfPacket);
420             }
421         }
423     }
424     else
425     {
426         ret = ICSS_EmacTxPacketEnqueue(icssEmacHandle,
427                                        txArg->srcAddress,
428                                        portNumber,
429                                        queuePriority,
430                                        lengthOfPacket);
431     }
433     if(ret == 0)
434     {
435         ret_val = 0;
436     }
437     else
438     {
439         ret_val = -1;
440     }
442     return(ret_val);
445 /* Local Functions */
446 /**
447  *  @brief  API to copy a packet from DDR to Tx Queue memory on L3 and synchronize with
448  *  firmware
449  *
450  *  @param[in]  icssEmacHandle handle to ICSS_EMAC Instance.
451  *  @param[in]  srcAddress    Base address of the buffer where the frame to be transmitted resides
452  *  @param[in]  portNumber   Port on which frame has to be transmitted.
453  *                            Valid values are:
454                               1 == PORT1, 2 == PORT2
455  *  @param[in]  queuePriority    Queue number in which frame will be
456  *                               queued for transmission
457  *  @param[in] lengthOfPacket   length of the frame in bytes
458  *  @retval     0 on scuess,  <0 on failure
459  */
460 int32_t ICSS_EmacTxPacketEnqueue (ICSS_EmacHandle icssEmacHandle,
461                                   const uint8_t* srcAddress,
462                                   uint8_t portNumber,
463                                   uint8_t queuePriority,
464                                   uint16_t lengthOfPacket)
466     uint16_t buffer_offset_computed =0;
467     uint32_t buffer_des = 0;
468     uint16_t queue_wr_ptr =0;
469     uint16_t wrk_queue_wr_ptr =0;
470     uint16_t size = 0;
471     uint16_t queue_rd_ptr =0;
472     uint16_t num_of_bytes =0;
473     uint16_t new_packet_length =0;
474     uint32_t temp =0;
475     uint16_t i =0;
476     uint32_t collision_queue_selected =0;
477     uint16_t collision_status =0;
478     uint16_t col_queue_already_occupied =0;
479     uint16_t original_length_of_packet =0;
480     uint16_t packet_min_size_padding = 0;
481     uint16_t remaining_valid_frame_data_length =0;
482     uint8_t *macAddr;
483     uint32_t pruSharedMem = 0;
484     ICSS_EmacQueueParams *txQueue;
485     ICSS_EmacHostStatistics_t* hostStatPtr;
486     uint8_t linkStatus=0;
488     uint8_t emacMode=0;
490     uint32_t temp_addr = 0U;
491     if((((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->portMask == ICSS_EMAC_MODE_SWITCH)
492     {
493         emacMode =0;
494     }
495     else
496     {
497         emacMode =1U;
498     }
500     if(emacMode) { /*MAC Mode*/
502         if(ICSS_EMAC_PORT_1 == portNumber) {
503             pruSharedMem = (((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr;
504         }
505         if(ICSS_EMAC_PORT_2 == portNumber) {
506             pruSharedMem = (((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr;
507         }
508         linkStatus = ((ICSS_EmacObject*)icssEmacHandle->object)->linkStatus[0];
509         hostStatPtr = (ICSS_EmacHostStatistics_t*)((((ICSS_EmacObject*)icssEmacHandle->object)->hostStat));
510     }
511     else
512     {
513         linkStatus = ((ICSS_EmacObject*)icssEmacHandle->object)->linkStatus[portNumber-1];
514         hostStatPtr = (ICSS_EmacHostStatistics_t*)((((ICSS_EmacObject*)icssEmacHandle->object)->hostStat));
515         hostStatPtr += (portNumber - 1);/*Switch mode. Points to correct structure depending on port*/
516     }
518     if((portNumber != ICSS_EMAC_PORT_1) && (portNumber != ICSS_EMAC_PORT_2))
519     {
520         hostStatPtr->txDroppedPackets++;
521         return ((int32_t)ICSS_EMAC_SWITCH_INVALID_PORT);
522     }
523     if((queuePriority < ICSS_EMAC_QUEUE1) || (queuePriority > ICSS_EMAC_QUEUE4))
524     {
525         hostStatPtr->txDroppedPackets++;
526         return ((int32_t)ICSS_EMAC_ERR_SWITCH_INVALID_PARAM);
527     }
528     if(lengthOfPacket > (int32_t)ICSS_EMAC_MAXMTU)
529     {    
530         hostStatPtr->txDroppedPackets++;
531         return ((int32_t)ICSS_EMAC_ERR_BADPACKET);
532     }
533     if(lengthOfPacket < ICSS_EMAC_MINMTU)
534     {    
535         hostStatPtr->txDroppedPackets++;
536         return ((int32_t)ICSS_EMAC_ERR_BADPACKET);
537     }
539     if(lengthOfPacket < ETHERNET_FRAME_SIZE_60)
540     {
541         original_length_of_packet = (uint16_t)lengthOfPacket;
542         packet_min_size_padding =1U;
543         lengthOfPacket = ETHERNET_FRAME_SIZE_60;
544     }
545     else
546     {
547         packet_min_size_padding = 0;
548     }
550     macAddr = (uint8_t*)srcAddress;
552     if(linkStatus == 0U)
553     {
554         hostStatPtr->txDroppedPackets++;
555         return ((int32_t)ICSS_EMAC_ERR_TX_NO_LINK);
556     }
558     ICSS_EmacPortParams *sPort;
559     sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[portNumber]);
560     if(emacMode == 0U) { /*Switch Mode*/
562          txQueue = &(sPort->queue[queuePriority]);
563         /* Check whether Queue is busy.If yes then put the packet in the collision Queue. Set the busy_s bit because Host is always a Slave. */
564         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset + 4U);
565         temp =  HWREG(temp_addr);
566         collision_queue_selected =  (temp & 0x00000100U);  /* Check the "busy_m" bit */
567         if(collision_queue_selected != 0U)
568         {
569            num_of_collision_occured = num_of_collision_occured +1;
570            /* Queue is busy  .. put the packet in the collision Queue */
571            txQueue = &(sPort->queue[ICSS_EMAC_COLQUEUE]);
572             if(portNumber == ICSS_EMAC_PORT_1)
573             {
574                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + COLLISION_STATUS_ADDR + 1U);
575                 col_queue_already_occupied = HWREGB(temp_addr);
576             }
577             else
578             {
579                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + COLLISION_STATUS_ADDR + 2U);
580                 col_queue_already_occupied = HWREGB(temp_addr);
581             }
582             if(col_queue_already_occupied != 0)
583             {
584               hostStatPtr->txDroppedPackets++;
585               collision_pkt_dropped ++;
586               return ((int32_t)ICSS_EMAC_ERR_COLLISION_FAIL);   /*No space in collision queue */
587             }
588         }
589         else
590         {
591             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset + 4U);
592             /* Queue is Not Busy .. Acquire the Queue by setting "busy_s" bit */
593             HWREGB(temp_addr) = 1; /* Set the "busy_s" bit */
594             /*Again check if host acquired the queue successfully by checking the busy_m bit */
595             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset + 4U);
596             temp =  HWREG(temp_addr);
597             collision_queue_selected =  (temp & 0x00000100U);  /* Check the "busy_m" bit */
598             if(collision_queue_selected != 0U)
599             {
600                 num_of_collision_occured = num_of_collision_occured +1;
601                 temp_addr = ( (((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr+ txQueue->queue_desc_offset + 4U);
602                 HWREGB(temp_addr) = 0; /* Clear the busy_s bit */
603                 /* Queue is busy  .. put the packet in the collision Queue */
604                 txQueue = &(sPort->queue[ICSS_EMAC_COLQUEUE]);
605             }
606         }
607     } else { /*MAC Mode*/
608         txQueue = &(sPort->queue[queuePriority]);
609         /* Queue is Not Busy .. Acquire the Queue by setting "busy_s" bit */
610         temp_addr = (pruSharedMem + txQueue->queue_desc_offset + 4U);
611         HWREGB(temp_addr) = 1U; /* Set the "busy_s" bit */
613     }
614     /*  Compute the buffer descriptor ..length is from bit 18 to 28 */
615     buffer_des = (((uint32_t)(lengthOfPacket)) << 18U);
617     if(emacMode == 0U) { /*Switch Mode*/
618         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset);
619         /*  Read the write pointer from Queue descriptor */
620         temp =  HWREG(temp_addr);
621     } else {
622         temp_addr = (pruSharedMem + txQueue->queue_desc_offset);
623         temp =  HWREG(temp_addr);
624     }
626     queue_wr_ptr = ((uint16_t)(temp >> 16));
627     queue_rd_ptr = ((uint16_t)(temp & 0x0000ffffU));
629     wrk_queue_wr_ptr = (((uint16_t)(lengthOfPacket)) >> 5U);  /* Divide by 32 */
630     wrk_queue_wr_ptr = (wrk_queue_wr_ptr << 2);  /* Multiply by 4 ..as one descriptor represents 32 bytes and BD takes 4 bytes */
631     if((((uint32_t)(lengthOfPacket)) & 0x0000001fU) != 0U)
632     {
633          wrk_queue_wr_ptr = wrk_queue_wr_ptr + 4U;
634     }
636     /* Add to get the value of new queue write pointer */
637     wrk_queue_wr_ptr = wrk_queue_wr_ptr + queue_wr_ptr;
638     size = txQueue->queue_size;
639     /*Check if queue is full and there is an wrap around */
640     if(((queue_wr_ptr + 4U) % size) == 0U)
641     {
642         if(queue_rd_ptr == txQueue->buffer_desc_offset) /* Since queue is not starting from 0. */
643         {
644             txQueue->qStat.errCount++;
645             if(emacMode == 0U) { /*Switch Mode*/
646                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset + 4U);
647                 HWREGB(temp_addr) = 0;
648             } else {
649                 temp_addr = (pruSharedMem + txQueue->queue_desc_offset + 4U);
650                 HWREGB(temp_addr) = 0U;
651             }
652             hostStatPtr->txDroppedPackets++;
653             return ((int32_t)ICSS_EMAC_ERR_TX_OUT_OF_BD);   /* No space in queue */
654         }
655     }
656     /* Check if the Queue is already full */
657     if((queue_wr_ptr + 4U) == queue_rd_ptr)
658     {
659         txQueue->qStat.errCount++;
660         if(emacMode == 0U) { /*Switch Mode*/
661             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr+ txQueue->queue_desc_offset + 4U);
662             HWREGB(temp_addr) = 0;
663         } else {
664             temp_addr = (pruSharedMem + txQueue->queue_desc_offset + 4U);
665             HWREGB(temp_addr) = 0U;
666         }
667         hostStatPtr->txDroppedPackets++;
668         return ((int32_t)ICSS_EMAC_ERR_TX_OUT_OF_BD);       /* No space in queue */
669     }
670     /* Three cases arise between wr_ptr and rd_ptr */
671     if(queue_wr_ptr == queue_rd_ptr)
672     {
673         /*Check for wrap around */
674         if(wrk_queue_wr_ptr >=  size)
675         {
676             wrk_queue_wr_ptr = (wrk_queue_wr_ptr % size);
677             /*Add offset as queue doesn't start from 0. */
678             wrk_queue_wr_ptr = wrk_queue_wr_ptr + txQueue->buffer_desc_offset;
679         }
680     }
681     else if(queue_wr_ptr > queue_rd_ptr)
682     {
683         /*Check for wrap around */
684         if(wrk_queue_wr_ptr >=  size)
685         {
686             wrk_queue_wr_ptr = (wrk_queue_wr_ptr % size);
687             wrk_queue_wr_ptr = wrk_queue_wr_ptr + txQueue->buffer_desc_offset;
688             if(wrk_queue_wr_ptr >= queue_rd_ptr)
689             {
690                 txQueue->qStat.errCount++;
691                 if(emacMode == 0U) { /*Switch Mode*/
692                     temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset + 4U);
693                     HWREGB(temp_addr) = 0;
694                 } else {
695                     temp_addr = (pruSharedMem + txQueue->queue_desc_offset + 4U);
696                     HWREGB(temp_addr) = 0U;
697                 }
698                 hostStatPtr->txDroppedPackets++;
699                 return ((int32_t)ICSS_EMAC_ERR_TX_OUT_OF_BD);      /* No space in queue */
700             }
701         }
702     }
703     else
704     {
705         if(wrk_queue_wr_ptr >= queue_rd_ptr)
706         {
707             txQueue->qStat.errCount++;
708             if(emacMode == 0U) { /*Switch Mode*/
709                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset + 4U);
710                 HWREGB(temp_addr) = 0;
711             } else {
712                 temp_addr = (pruSharedMem + txQueue->queue_desc_offset + 4U);
713                 HWREGB(temp_addr) = 0U;
714             }
715             hostStatPtr->txDroppedPackets++;
716             return ((int32_t)ICSS_EMAC_ERR_TX_OUT_OF_BD);                          /* No space in queue */
717         }
718     }
719     /* Compute the offset of buffer descriptor in ICSS shared RAM */
720     buffer_offset_computed = txQueue->buffer_offset + ((queue_wr_ptr - txQueue->buffer_desc_offset)*8U);    /* queue_wr_ptr points to currently available free buffer */
722     /* Check if queue wrap around has happened. If yes then data can't be stored sequentially. */
723     if( (wrk_queue_wr_ptr < queue_wr_ptr) &&  (wrk_queue_wr_ptr != txQueue->buffer_desc_offset))
724     {
725         num_of_bytes = (size - queue_wr_ptr);
726         num_of_bytes *= 8U;                    /* divide by 4 * 32! */
727         /* check if Padding has to be done. If yes then Pad with Zero's to reach the minimum size for the ethernet frame. */
728         if(packet_min_size_padding == 1U)
729         {
730             if( num_of_bytes <= original_length_of_packet)
731             {
732                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed));
733                 memcpy((int32_t*)(temp_addr), (int32_t*) srcAddress, num_of_bytes);
734             }
735             else
736             {
737                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed));
738                 /* Copy the valid packet data first and then Pad with zero's.  */
739                 memcpy((int32_t*)(temp_addr), (int32_t*) srcAddress, original_length_of_packet);
740                 /* Padd the remaining bytes with Zero's */
741                 for(i=0; i< (num_of_bytes - original_length_of_packet); i++)
742                 {
743                     temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr+ ((uint32_t)buffer_offset_computed) + original_length_of_packet + i);
744                     HWREGB(temp_addr) = 0;
745                 }
746             }
747         }
748         else
749         {
750             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed));
751             memcpy((int32_t*)(temp_addr), (int32_t*) srcAddress, num_of_bytes);
752         }
753         new_packet_length = ((uint16_t)lengthOfPacket) - num_of_bytes;
754         srcAddress = srcAddress + num_of_bytes;
756         if(emacMode == 0U) { /*Switch Mode*/
757             if(collision_queue_selected != 0) {
758                 buffer_offset_computed = buffer_offset_computed + num_of_bytes;
759             } else {
760                 buffer_offset_computed = txQueue->buffer_offset;
761             }
762         } else { /*MAC Mode*/
763             buffer_offset_computed = txQueue->buffer_offset;
764         }
766         if( packet_min_size_padding == 1u)
767         {
768             if(    original_length_of_packet <= num_of_bytes)
769             {
770                 /* Pad all the remaining bytes with Zero's */
771                 for(i=0; i< new_packet_length; i++)
772                 {
773                     temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed) + i);
774                     HWREGB(temp_addr) = 0;
775                 }
776             }
777             else
778             {
779                 /* Fill the frame data  */
780                 remaining_valid_frame_data_length = (original_length_of_packet- num_of_bytes);
781                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed));
782                 memcpy((int32_t*)(temp_addr),(int32_t*) srcAddress, remaining_valid_frame_data_length);
783                 /*Pad the remaining bytes with Zero's */
784                 for(i=0; i< (new_packet_length - remaining_valid_frame_data_length); i++)
785                 {
786                     temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed) + remaining_valid_frame_data_length+ i);
787                     HWREGB(temp_addr) = 0;
788                 }
789             }
790         }    
791         else
792         {
793             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed));
794             memcpy((int32_t*)(temp_addr),(int32_t*) srcAddress, new_packet_length);
795         }
796     }
797     else
798     {
799         if( packet_min_size_padding  == 1u)
800         {
801             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed));
802             memcpy((int32_t*)(temp_addr), (int32_t*)srcAddress, original_length_of_packet);
803             /* Padd the remaining bytes with Zero's */
804             for(i=0; i< (((uint16_t)lengthOfPacket) - original_length_of_packet); i++)
805             {
806                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed) + original_length_of_packet + i);
807                 HWREGB(temp_addr) = 0;
808             }
809         }
810         else
811         {
812             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + ((uint32_t)buffer_offset_computed));
813             memcpy((int32_t*)(temp_addr), (int32_t*)srcAddress, (uint32_t)lengthOfPacket);
814         }
815     }
816     if(emacMode == 0U) { /*Switch Mode*/
817         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + ((uint32_t)queue_wr_ptr) );
818         HWREG(temp_addr) = buffer_des;
819         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset +2U);
820         /* Write new wr_ptr in the queue descriptor */
821         HWREGH(temp_addr) = wrk_queue_wr_ptr;
822     } else {
823         temp_addr = (pruSharedMem + queue_wr_ptr );
824         HWREG(temp_addr) = buffer_des;
825         temp_addr = (pruSharedMem + txQueue->queue_desc_offset +2U);
826         HWREGH(temp_addr) = wrk_queue_wr_ptr;
827     }
829     txQueue->qStat.rawCount++;
831     if(emacMode == 0U) { /*Switch Mode*/
832         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + txQueue->queue_desc_offset + 4U);
833         /* Release the Queue. Clear the "busy_s" bit .. even if collision queue was selected then below line won't have any impact. */
834         HWREGB(temp_addr) = 0;
835     } else {
836         temp_addr = (pruSharedMem + txQueue->queue_desc_offset + 4U);
837         HWREGB(temp_addr) = 0U;
838     }
840     if(emacMode == 0U) { /*Switch Mode*/
841         /* If packet was put in collision queue then indiciate it to collision task */
842         if(collision_queue_selected != 0)
843         {
844             if(portNumber ==ICSS_EMAC_PORT_1)
845             {
846                 collision_status = ((uint16_t)queuePriority);
847                 collision_status = (collision_status << 1);
848                 collision_status = (collision_status | 0x0001U);
849                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + COLLISION_STATUS_ADDR +1U);
850                 HWREGB(temp_addr) = collision_status;
851             }
852             else
853             {
854                 collision_status = ((uint16_t)queuePriority);
855                 collision_status = (collision_status << 1);
856                 collision_status = (collision_status | 0x0001U);
857                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + COLLISION_STATUS_ADDR + 2U);
858                 HWREGB(temp_addr) = collision_status;
859             }
860         }
861     }
863     
864     if(emacMode == 0U) /*In Switch Mode both the statistics structures are in single handle.Depending on port update the corresponding structure*/
865     hostStatPtr += (portNumber - 1);
866     ICSS_EmacUpdateTxStats(macAddr,(uint32_t)lengthOfPacket, hostStatPtr);
867     return 0;
870 /**
871  *  @b Description
872  *  @n
873  *       API to retrieve the information about the received frame which
874  *       is then used to dequeue the frame from the host queues
875  *
876  *  @param[in]  icssEmacHandle handle to ICSS_EMAC Instance.
877  *  @param[out]  portNumber    Return pointer of port number where frame was received
878  *  @param[out]  queueNumber   Return pointer of host queue where the received frame is queued
879  *  @param[out]  pktProc       Return pointer of packet type
881  *  @retval     none
882  */
883 int32_t ICSS_EmacRxPktInfo(ICSS_EmacHandle icssEmacHandle,
884                            int32_t* portNumber,
885                            int32_t* queueNumber,
886                                    int32_t* pktProc)
889     uint16_t queue_rd_ptr;
890     uint16_t queue_wr_ptr;
891     uint32_t rd_buf_desc=0;
892     uint16_t rd_packet_length;
893     int32_t packet_found =0;
894     Queue *qDesc;
895     uint16_t shadow=0;
896     uint32_t rd_buffer_l3_addr;
897     uint16_t rd_buf_desc_num;
898     ICSS_EmacQueueParams *rxQueue;
900     uint8_t initPrioQueue = ICSS_EMAC_QUEUE1;
901     uint8_t finalPrioQueue = (uint8_t)ICSS_EMAC_QUEUE4;
902     uint8_t i= ICSS_EMAC_QUEUE1;
904     uint8_t emacMode=0;
905     uint32_t temp_addr = 0U;
906     uint32_t temp_var1 = 0U;
907     uint32_t temp_var2 = 0U;
909     ICSS_EmacPortParams *sPort;
911     switch((((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->portMask)
912     {
913         case ICSS_EMAC_MODE_SWITCH:
914             emacMode =0;
915             initPrioQueue = ICSS_EMAC_QUEUE1;
916             finalPrioQueue = (uint8_t)ICSS_EMAC_QUEUE4;
917             break;
918         case ICSS_EMAC_MODE_MAC1:
919             emacMode =1u;
920             initPrioQueue = ICSS_EMAC_QUEUE1;
921             finalPrioQueue= (uint8_t)ICSS_EMAC_QUEUE2;
922             break;
923         case ICSS_EMAC_MODE_MAC2:
924             emacMode =1u;
925             initPrioQueue = (uint8_t)ICSS_EMAC_QUEUE3;
926             finalPrioQueue= (uint8_t)ICSS_EMAC_QUEUE4;
927             break;
928         default:
929             break;
930     }
932     i=initPrioQueue;
934     while((packet_found == 0) && (i <= finalPrioQueue))
935     {
937         if(emacMode == 0U) { /*Switch Mode*/
938             temp_var1 = ((uint32_t)(i))*8U;
939             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + P0_QUEUE_DESC_OFFSET + temp_var1);
940             qDesc = (Queue *)(temp_addr);
941         } else {
942             temp_var1 = ((uint32_t)(i))*8U;
943             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + HOST_QUEUE_DESC_OFFSET + temp_var1);
944             qDesc = (Queue *)(temp_addr);
945         }
946         queue_wr_ptr = qDesc->wr_ptr;
947         queue_rd_ptr = qDesc->rd_ptr;
949         sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_0]);
951         if(qDesc->overflow_cnt > 0)
952         {
953             sPort->queue[i].qStat.errCount += qDesc->overflow_cnt;  /* increment missed packets to error counter */
954             qDesc->overflow_cnt = 0;    /* reset to zero as limited to 256 anyway */
955         }
956         if(queue_rd_ptr != queue_wr_ptr)
957         {
958             (*queueNumber) = i;
959             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + ((uint32_t)queue_rd_ptr));
960             rd_buf_desc = HWREG(temp_addr);
961             /* Take out the port number */
962             (*portNumber) = (0x00030000U & rd_buf_desc) >> 16U;
963             /* Get the length */
964             rd_packet_length = ((uint16_t)((0x1ffc0000U & rd_buf_desc) >> 18U));
965             packet_found = 1;
967             rxQueue = &(sPort->queue[i]);
969             if(emacMode == 0U) { /*Switch Mode*/
970                 /* Determine the address of the first buffer descriptor from the rd_ptr */
971                 /*Check if Packet was received in collision queue or not */
972                 shadow = ((uint16_t)((rd_buf_desc & 0x00004000U) >> 14U));
973                 if(shadow != 0)
974                 {
975                   /* Pick the data from collision buffer's */
976                     rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr+ P0_COL_BUFFER_OFFSET);
977                 } else  {
978                     rd_buf_desc_num = (queue_rd_ptr - rxQueue->buffer_desc_offset) >> 2;
979                     temp_var1 = (((uint32_t)(rd_buf_desc_num)) * 32U);
980                     temp_var2 = (rxQueue->buffer_offset);
981                     rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + temp_var1 + temp_var2);
982                 }
983             } else {
984                 rd_buf_desc_num = (queue_rd_ptr - rxQueue->buffer_desc_offset) >> 2;
985                 temp_var1 = ((uint32_t)(rd_buf_desc_num)) * 32U;
986                 temp_var2 = (rxQueue->buffer_offset);
987                 rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + temp_var1 + temp_var2);
988             }
989             *pktProc = PruSwitch((char *)rd_buffer_l3_addr);
990         }
991         i++;
992     }
993     /* Received IRQ but can't find the packet in any queue */
994     if(packet_found == 0)
995     {
996         rd_packet_length = 0;
997     }
998     return (int32_t)rd_packet_length;
1001 /**
1002  *  @b Description
1003  *  @n
1004  *      Retrieves a frame from a host queue and copies it
1005  *           in the allocated stack buffer
1006  *
1007  *  @param[in]  rxArg defined at @ref ICSS_EmacRxArgument
1008  *  @param[in]  userArg custom Rx packet callback packet options only required for custom RxPacket implementations,
1009                 default to NULL when calling ICSS_EmacRxPktGet which is default Tx Packet API
1010  *  @retval     Length of the frame received in number of bytes or -1 on Failure
1011  */
1012 int32_t ICSS_EmacRxPktGet(ICSS_EmacRxArgument *rxArg, void* userArg)
1015     uint16_t queue_rd_ptr;
1016     uint16_t queue_wr_ptr;
1017     uint16_t rd_buf_desc_num;
1018     uint32_t rd_buf_desc=0;
1019     uint16_t rd_packet_length;
1020     uint32_t rd_buffer_l3_addr;
1021     uint16_t size =0;
1022     uint16_t update_rd_ptr=0;
1023     uint16_t rx_num_of_bytes=0;
1024     uint16_t new_size =0;
1025     ICSS_EmacQueueParams *rxQueue;
1026     Queue *qDesc;
1027     uint16_t    shadow=0;
1029     uint8_t* srcMacId;
1030     uint8_t* destMacId;
1032     uint16_t *typeProt;
1033     uint16_t  typeProt1;
1034     uint16_t  typeProt2;
1036     uint8_t emacMode=0;
1038     uint32_t temp_addr = 0U;
1039     uint32_t temp_var1 = 0U;
1040     uint32_t temp_var2 = 0U;
1042     uint8_t ret_flag = 0U;
1043     int32_t ret_val = 0;
1045     ICSS_EmacHandle icssEmacHandle = rxArg->icssEmacHandle;
1046     uint32_t  destAddress = rxArg->destAddress;
1047     uint8_t queueNumber= rxArg->queueNumber;
1049     
1050     ICSS_EmacPortParams *sPort;
1051     if((((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->portMask == ICSS_EMAC_MODE_SWITCH)
1052     {
1053         emacMode =0;
1054     }
1055     else
1056     {
1057         emacMode =1U;
1058     }
1060     HashTable_t *macTablePtr;
1061     ICSS_EmacHostStatistics_t* hostStatPtr;
1063     ICSS_EmacCallBackConfig* learningExcCallback;
1065 #ifdef SWITCH_DEBUG
1066         genSeqOfEvents(RX_PACKET_GET);
1067 #endif
1069     if(emacMode == 0U) { /*Switch Mode*/
1070         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr+ P0_QUEUE_DESC_OFFSET + (((uint32_t)(queueNumber))*8U));
1071         qDesc = (Queue *)(temp_addr);
1072     } else {
1073         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + HOST_QUEUE_DESC_OFFSET + (((uint32_t)(queueNumber))*8U));
1074         qDesc = (Queue *)(temp_addr);
1075     }
1076     queue_wr_ptr = qDesc->wr_ptr;
1077     queue_rd_ptr = qDesc->rd_ptr;
1078     sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_0]);
1079     if(qDesc->overflow_cnt > 0)
1080     {
1081         sPort->queue[queueNumber].qStat.errCount += qDesc->overflow_cnt;        /* increment missed packets to error counter */
1082         qDesc->overflow_cnt = 0;
1083         /* reset to zero as limited to 256 anyway */
1084     }
1085     temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + ((uint32_t)queue_rd_ptr));
1086     rd_buf_desc = HWREG(temp_addr);
1087     rxQueue = &(sPort->queue[queueNumber]);
1089     if(emacMode == 0U) { /*Switch Mode*/
1090         /* Determine the address of the first buffer descriptor from the rd_ptr */
1091         /*Check if Packet was received in collision queue or not */
1092         shadow = ((uint16_t)((rd_buf_desc & 0x00004000U) >> 14U));
1093         if(shadow != 0)
1094         {
1095           /* Pick the data from collision buffer's */
1096             rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr+ P0_COL_BUFFER_OFFSET);
1097         } else  {
1098             rd_buf_desc_num = (queue_rd_ptr - rxQueue->buffer_desc_offset) >> 2;
1099             temp_var1 = (((uint32_t)(rd_buf_desc_num)) * 32U);
1100             temp_var2 = (rxQueue->buffer_offset);
1101             rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + temp_var1 + temp_var2);
1102         }
1103     } else {
1104         rd_buf_desc_num = (queue_rd_ptr - rxQueue->buffer_desc_offset) >> 2;
1105         temp_var1 = ((uint32_t)(rd_buf_desc_num)) * 32U;
1106         temp_var2 = (rxQueue->buffer_offset);
1107         rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + temp_var1 + temp_var2);
1108     }
1109     /* Take out the port number - it may have changed */
1110     rxArg->port = (0x00030000U & rd_buf_desc)>>16;
1112     temp_addr = (rd_buffer_l3_addr + 6U);
1113     srcMacId = (uint8_t*)(temp_addr);
1115     destMacId = (uint8_t*)rd_buffer_l3_addr;
1118     rd_packet_length = ((uint16_t)((0x1ffc0000U & rd_buf_desc) >> 18));
1120     size = (rd_packet_length >>2);
1121     if( (rd_packet_length & 0x00000003U) != 0U )
1122     {
1123         size = size + 1u;
1124     }
1126     /*Compute number of buffer desc required & update rd_ptr in queue */
1127     update_rd_ptr = ((rd_packet_length >> 5U)*4U) + queue_rd_ptr;
1128     if( (rd_packet_length & 0x0000001fU) != 0U) /* checks multiple of 32 else need to increment by 4 */
1129     {
1130         update_rd_ptr += 4U;
1131     }
1132     /*Check for wrap around */
1133     if(update_rd_ptr >= rxQueue->queue_size)
1134     {
1135         update_rd_ptr = update_rd_ptr - (rxQueue->queue_size - rxQueue->buffer_desc_offset);
1136     }
1137     if(rd_packet_length <= ICSS_EMAC_MAXMTU)        /* make sure we do not have too big packets */
1138     {
1140         if((((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->learningEn) { /*Switch Mode*/
1142             learningExcCallback = (((ICSS_EmacObject*)icssEmacHandle->object)->callBackHandle)->learningExCallBack;
1143             macTablePtr = (HashTable_t*)(((ICSS_EmacObject*)icssEmacHandle->object)->macTablePtr);
1144             updateHashTable(srcMacId, rxArg->port, macTablePtr,learningExcCallback);
1146         }
1148         /* Copy the data from switch buffers to DDR */
1149         if( (update_rd_ptr < queue_rd_ptr) && (update_rd_ptr != rxQueue->buffer_desc_offset))
1150         {
1151             typeProt = (uint16_t*)rd_buffer_l3_addr + 6;
1152             typeProt1 = ((uint16_t)((*typeProt) << 8U));
1153             typeProt2 = ((uint16_t)((*typeProt) >> 8U));
1154             typeProt1 = typeProt1 | typeProt2;
1155             rx_num_of_bytes = (rxQueue->queue_size - queue_rd_ptr);
1156             rx_num_of_bytes = (rx_num_of_bytes >> 2);
1157             rx_num_of_bytes = (rx_num_of_bytes << 5);
1159             memcpy((int32_t*)destAddress, (int32_t*)rd_buffer_l3_addr, rx_num_of_bytes);
1160               destAddress = destAddress + rx_num_of_bytes;
1161               new_size = rd_packet_length - rx_num_of_bytes;
1163               if(emacMode == 0U) { /*Switch Mode*/
1164                   if(shadow != 0) {
1165                       rd_buffer_l3_addr = rd_buffer_l3_addr + rx_num_of_bytes;
1166                   } else {
1167                       rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + rxQueue->buffer_offset);
1168                   }
1169               } else {
1170                   rd_buffer_l3_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->l3OcmcBaseAddr + rxQueue->buffer_offset);
1171               }
1173               memcpy((int32_t*)destAddress, (int32_t*)rd_buffer_l3_addr, new_size);
1174         }
1175         else
1176         {
1178             memcpy((int32_t*)destAddress, (int32_t*)rd_buffer_l3_addr, rd_packet_length);
1179             typeProt = (uint16_t*)destAddress + 6;
1180             typeProt1 = ((uint16_t)((*typeProt) << 8U));
1181             typeProt2 = ((uint16_t)((*typeProt) >> 8U));
1182             typeProt1 = typeProt1 | typeProt2;
1183         }
1184     }
1185     else  /* wrong packet size (exceeds ICSS_EMAC_MAXMTU)*/
1186     {
1187         rxQueue->qStat.errCount++;
1188         ret_flag = 1U;
1189         ret_val = -1;
1190     }
1192     if(ret_flag == 0U)
1193     {
1194         if(emacMode == 0U) { /*Switch Mode*/
1195             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + P0_QUEUE_DESC_OFFSET + (((uint32_t)(queueNumber))*8U));
1196             /* Write back to queue */
1197             HWREGH(temp_addr) = update_rd_ptr;
1198              /* Check if Host needs to change the wr_ptr for collision queue as well */
1199             if(shadow != 0)
1200             {
1201                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + P0_COL_QUEUE_DESC_OFFSET);
1202                 Queue *qDescCol = (Queue *)(temp_addr);
1203                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + P0_COL_QUEUE_DESC_OFFSET +2U);
1204                 /*Write back to collision queue desc */
1205                 HWREGH(temp_addr) = qDescCol->rd_ptr;
1206                 
1207                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + COLLISION_STATUS_ADDR +3U);
1208                 HWREGH(temp_addr) = 0;
1210             }
1211         } else {
1212             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + HOST_QUEUE_DESC_OFFSET + (((uint32_t)(queueNumber))*8U));
1213             HWREGH(temp_addr) = update_rd_ptr;
1214         }
1215         rxQueue->qStat.rawCount++;
1217         rxArg->more = 0;
1218         if(emacMode == 0U) { /*Switch Mode*/
1219             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + P0_QUEUE_DESC_OFFSET + (((uint32_t)(queueNumber))*8U));
1220             /* get new pointer data in case new packets received in meantime - experimental.. */
1221             qDesc = (Queue *)(temp_addr);
1222         } else {
1223             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + HOST_QUEUE_DESC_OFFSET + (((uint32_t)(queueNumber))*8U));
1224             qDesc = (Queue *)(temp_addr);
1225         }
1226         queue_wr_ptr = qDesc->wr_ptr;
1228         if(update_rd_ptr != queue_wr_ptr)
1229         {
1230             rxArg->more = 1;
1231         }
1233         hostStatPtr = (ICSS_EmacHostStatistics_t*)((((ICSS_EmacObject*)icssEmacHandle->object)->hostStat));
1234         if(emacMode == 0U) /*In Switch Mode both the statistics structures are in single handle.Depending on port update the corresponding structure*/
1235             hostStatPtr += (rxArg->port - 1);
1236         ICSS_EmacUpdateRxStats(destMacId,rd_packet_length, typeProt1, hostStatPtr);
1238         ret_val = (int32_t)rd_packet_length;
1239     }
1240     return (ret_val);
1243 /**
1244  *  @b Description
1245  *  @n
1246  *      Finds the maximum fill level of the queue in terms of 32 byte blocks.
1247         For example, if there was only one 64 byte packet received when this
1248         API is called then it would return value of 2.
1249         It also returns number of times queue has overflown.
1250  *
1251  *  @param[in]  icssEmacHandle handle to ICSS_EMAC Instance.
1252  *  @param[in]  portNumber    Port on which queue resides. Valid values are:
1253                               0 == PORT0, 1 == PORT1, 2 == PORT2
1254  *  @param[in]  queuePriority   Priority of the queue or queue number whose fill level has to be found
1255  *  @param[in]  queueType   Rx/Tx Queue
1256  *  @param[out]  queueOverflowCount    Number of times queue has overflown
1258  *  @retval     The maximum fill level of the queue in terms of 32 byte blocks or
1259  *              <0 if there was an error in the input parameters
1260  */
1261 int32_t ICSS_EmacGetMaxQueueFillLevel(ICSS_EmacHandle icssEmacHandle,
1262                                       int32_t portNumber, 
1263                                       int32_t queuePriority, 
1264                                       uint8_t queueType,
1265                                       int32_t* queueOverflowCount)
1267     int32_t queueMaxFillLevel =0;
1268     uint32_t temp_addr = 0U;
1269     ICSS_EmacPortParams *sPort;
1271     int32_t ret_val = 0;
1273     if((portNumber != ICSS_EMAC_PORT_0) && 
1274        (portNumber != ICSS_EMAC_PORT_1) &&
1275        (portNumber != ICSS_EMAC_PORT_2))
1276     {    
1277         ret_val = ((int32_t)ICSS_EMAC_SWITCH_INVALID_PORT);
1278     }
1279     else
1280     {
1281        sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[portNumber]);
1282         if((queuePriority < ICSS_EMAC_QUEUE1) || (queuePriority > ICSS_EMAC_QUEUE4))
1283         {
1284             ret_val = ((int32_t)ICSS_EMAC_ERR_SWITCH_INVALID_PARAM);
1285         }
1286         else
1287         {
1288             ICSS_EmacQueueParams *queue_local = &(sPort->queue[queuePriority]);
1290             /*Read the max fill level for the queue */
1291             if(ICSS_EMAC_MODE_SWITCH == (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->portMask) { /*Switch Mode*/
1292                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + queue_local->queue_desc_offset + Q_MAX_FILL_LEVEL_OFFSET);
1293                 queueMaxFillLevel =  HWREGB(temp_addr);
1294                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + queue_local->queue_desc_offset + Q_OVERFLOW_CNT_OFFSET);
1295                 *queueOverflowCount = HWREGB(temp_addr);
1296             } else {
1297                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr + queue_local->queue_desc_offset + Q_MAX_FILL_LEVEL_OFFSET);
1298                 queueMaxFillLevel =  HWREGB(temp_addr);
1299                 temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->sharedDataRamBaseAddr+ queue_local->queue_desc_offset + Q_OVERFLOW_CNT_OFFSET);
1300                 *queueOverflowCount = HWREGB(temp_addr);
1301             }
1302             ret_val = queueMaxFillLevel;
1303         }
1304     }
1305     return ret_val;
1307 /**
1308  *  \name ClearStatistics
1309  *  @brief  Function to clear queue statistics
1310  *
1311  *  @param none
1312  *  @retval none
1313  */
1314 void ClearStatistics(ICSS_EmacHandle icssEmacHandle); /* for misra warning*/
1315 void ClearStatistics(ICSS_EmacHandle icssEmacHandle)
1317     ICSS_EmacPortParams *sPort;
1319     int32_t i, j;
1320     for (j=0; j<3; j++)
1321     {
1322         sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[j]);
1323         sPort->errCount = 0;
1324         sPort->rawCount = 0;
1325         for (i=0; i<ICSS_EMAC_NUMQUEUES; i++)
1326         {
1327             sPort->queue[i].qStat.errCount = 0;
1328             sPort->queue[i].qStat.rawCount = 0;
1329         }
1330     }
1333 void ICSS_EmacHostInit(ICSS_EmacHandle icssEmacHandle)
1335     ICSS_EmacPortParams *sPort;
1337     /* Initialize port 0*/
1338     sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_0]);
1339     sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P0_Q1_BUFFER_OFFSET;
1340     sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P0_Q1_BD_OFFSET;
1341     sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = HOST_QUEUE_DESC_OFFSET;
1342     sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (HOST_QUEUE_1_SIZE << 2) + P0_Q1_BD_OFFSET;        /* really the end of Queue */
1344     sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P0_Q2_BUFFER_OFFSET;
1345     sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P0_Q2_BD_OFFSET;
1346     sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = HOST_QUEUE_DESC_OFFSET + 8U;
1347     sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (HOST_QUEUE_2_SIZE << 2) + P0_Q2_BD_OFFSET;
1349     sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P0_Q3_BUFFER_OFFSET;
1350     sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P0_Q3_BD_OFFSET;
1351     sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = HOST_QUEUE_DESC_OFFSET + 16U;
1352     sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (HOST_QUEUE_3_SIZE << 2) + P0_Q3_BD_OFFSET;
1354     sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P0_Q4_BUFFER_OFFSET;
1355     sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P0_Q4_BD_OFFSET;
1356     sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = HOST_QUEUE_DESC_OFFSET + 24U;
1357     sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (HOST_QUEUE_4_SIZE << 2) + P0_Q4_BD_OFFSET;
1361 void ICSS_EmacMACInit(ICSS_EmacHandle icssEmacHandle, uint8_t portNum)
1363     ICSS_EmacPortParams *sPort;
1365     if(((uint8_t)(ICSS_EMAC_PORT_1)) == portNum) {
1366         sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_1]);
1367        /* Initialize port 1*/
1368         sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P1_Q1_BUFFER_OFFSET;
1369         sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P1_Q1_BD_OFFSET;
1370         sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET;
1371         sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P1_Q1_BD_OFFSET;
1373         sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P1_Q2_BUFFER_OFFSET;
1374         sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P1_Q2_BD_OFFSET;
1375         sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 8U;
1376         sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P1_Q2_BD_OFFSET;
1378         sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P1_Q3_BUFFER_OFFSET;
1379         sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P1_Q3_BD_OFFSET;
1380         sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 16U;
1381         sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P1_Q3_BD_OFFSET;
1383         sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P1_Q4_BUFFER_OFFSET;
1384         sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P1_Q4_BD_OFFSET;
1385         sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 24U;
1386         sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P1_Q4_BD_OFFSET;
1387     }
1389     if(((uint8_t)(ICSS_EMAC_PORT_2)) == portNum) {
1390         /* Initialize port 2*/
1391         sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_2]);
1392        sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P2_Q1_BUFFER_OFFSET;
1393         sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P2_Q1_BD_OFFSET;
1394         sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET;
1395         sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P2_Q1_BD_OFFSET;
1397         sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P2_Q2_BUFFER_OFFSET;
1398         sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P2_Q2_BD_OFFSET;
1399         sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 8U;
1400         sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P2_Q2_BD_OFFSET;
1402         sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P2_Q3_BUFFER_OFFSET;
1403         sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P2_Q3_BD_OFFSET;
1404         sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 16U;
1405         sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P2_Q3_BD_OFFSET;
1407         sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P2_Q4_BUFFER_OFFSET;
1408         sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P2_Q4_BD_OFFSET;
1409         sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 24U;
1410         sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P2_Q4_BD_OFFSET;
1411     }
1415 int32_t ICSS_EmacPortInit(ICSS_EmacHandle icssEmacHandle); /* for misra warning*/
1416 int32_t ICSS_EmacPortInit(ICSS_EmacHandle icssEmacHandle)
1418     ICSS_EmacPortParams *sPort;
1419     /* Clear counters */
1420     ClearStatistics(icssEmacHandle);
1421     /* Initialize port 0*/
1422     sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_0]);
1423     sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P0_Q1_BUFFER_OFFSET;
1424     sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P0_Q1_BD_OFFSET;
1425     sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = P0_QUEUE_DESC_OFFSET;
1426     sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (HOST_QUEUE_1_SIZE << 2) + P0_Q1_BD_OFFSET;        /* really the end of Queue */
1428     sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P0_Q2_BUFFER_OFFSET;
1429     sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P0_Q2_BD_OFFSET;
1430     sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = P0_QUEUE_DESC_OFFSET + 8U;
1431     sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (HOST_QUEUE_2_SIZE << 2) + P0_Q2_BD_OFFSET;
1433     sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P0_Q3_BUFFER_OFFSET;
1434     sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P0_Q3_BD_OFFSET;
1435     sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = P0_QUEUE_DESC_OFFSET + 16U;
1436     sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (HOST_QUEUE_3_SIZE << 2) + P0_Q3_BD_OFFSET;
1438     sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P0_Q4_BUFFER_OFFSET;
1439     sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P0_Q4_BD_OFFSET;
1440     sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = P0_QUEUE_DESC_OFFSET + 24U;
1441     sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (HOST_QUEUE_4_SIZE << 2) + P0_Q4_BD_OFFSET;
1443     /* Initialize port 1*/
1444     sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_1]);
1445    sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P1_Q1_BUFFER_OFFSET;
1446     sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P1_Q1_BD_OFFSET;
1447     sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = P1_QUEUE_DESC_OFFSET;
1448     sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P1_Q1_BD_OFFSET;
1450     sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P1_Q2_BUFFER_OFFSET;
1451     sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P1_Q2_BD_OFFSET;
1452     sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = P1_QUEUE_DESC_OFFSET + 8U;
1453     sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P1_Q2_BD_OFFSET;
1455     sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P1_Q3_BUFFER_OFFSET;
1456     sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P1_Q3_BD_OFFSET;
1457     sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = P1_QUEUE_DESC_OFFSET +16U;
1458     sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P1_Q3_BD_OFFSET;
1460     sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P1_Q4_BUFFER_OFFSET;
1461     sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P1_Q4_BD_OFFSET;
1462     sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = P1_QUEUE_DESC_OFFSET +24U;
1463     sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P1_Q4_BD_OFFSET;
1464     
1465     /*Collision Queue */
1466     sPort->queue[ICSS_EMAC_COLQUEUE].buffer_offset           = P1_COL_BUFFER_OFFSET;
1467     sPort->queue[ICSS_EMAC_COLQUEUE].buffer_desc_offset = P1_COL_BD_OFFSET;
1468     sPort->queue[ICSS_EMAC_COLQUEUE].queue_desc_offset  = P1_COL_QUEUE_DESC_OFFSET;
1469     sPort->queue[ICSS_EMAC_COLQUEUE].queue_size         = (COLLISION_QUEUE_SIZE << 2) + P1_COL_BD_OFFSET;
1471     /* Initialize port 2*/
1472     sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_2]);
1473     sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P2_Q1_BUFFER_OFFSET;
1474     sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P2_Q1_BD_OFFSET;
1475     sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = P2_QUEUE_DESC_OFFSET;
1476     sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P2_Q1_BD_OFFSET;
1478     sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P2_Q2_BUFFER_OFFSET;
1479     sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P2_Q2_BD_OFFSET;
1480     sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = P2_QUEUE_DESC_OFFSET + 8U;
1481     sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P2_Q2_BD_OFFSET;
1483     sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P2_Q3_BUFFER_OFFSET;
1484     sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P2_Q3_BD_OFFSET;
1485     sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = P2_QUEUE_DESC_OFFSET +16U;
1486     sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P2_Q3_BD_OFFSET;
1488     sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P2_Q4_BUFFER_OFFSET;
1489     sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P2_Q4_BD_OFFSET;
1490     sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = P2_QUEUE_DESC_OFFSET +24U;
1491     sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P2_Q4_BD_OFFSET;
1492     
1493     /*Collision Queue */
1494     sPort->queue[ICSS_EMAC_COLQUEUE].buffer_offset           = P2_COL_BUFFER_OFFSET;
1495     sPort->queue[ICSS_EMAC_COLQUEUE].buffer_desc_offset = P2_COL_BD_OFFSET;
1496     sPort->queue[ICSS_EMAC_COLQUEUE].queue_desc_offset  = P2_COL_QUEUE_DESC_OFFSET;
1497     sPort->queue[ICSS_EMAC_COLQUEUE].queue_size         = (COLLISION_QUEUE_SIZE << 2) + P2_COL_BD_OFFSET;
1499     return 0;
1503 /**
1504 *  @internal
1505 *  @brief Function to re-initialize all Port Queue params
1507 *  @param portNumber number of the port to flush
1508 *  @retval None
1509 */
1510 void macFlush(ICSS_EmacHandle icssEmacHandle, Int32 portNumber); /* for misra warning*/
1511 void macFlush(ICSS_EmacHandle icssEmacHandle, Int32 portNumber)
1513     ICSS_EmacPortParams *sPort;
1515     switch(portNumber) {
1516         case ICSS_EMAC_PORT_1:
1517         sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_1]);
1518         /* Initialize port 1*/
1519         sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P1_Q1_BUFFER_OFFSET;
1520         sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P1_Q1_BD_OFFSET;
1521         sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET;
1522         sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P1_Q1_BD_OFFSET;
1524         sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P1_Q2_BUFFER_OFFSET;
1525         sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P1_Q2_BD_OFFSET;
1526         sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 8U;
1527         sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P1_Q2_BD_OFFSET;
1529         sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P1_Q3_BUFFER_OFFSET;
1530         sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P1_Q3_BD_OFFSET;
1531         sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET +16U;
1532         sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P1_Q3_BD_OFFSET;
1534         sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P1_Q4_BUFFER_OFFSET;
1535         sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P1_Q4_BD_OFFSET;
1536         sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET +24U;
1537         sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P1_Q4_BD_OFFSET;
1538         break;
1540     case ICSS_EMAC_PORT_2:
1541         /* Initialize port 2*/
1542         sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_2]);
1543         sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset       = P2_Q1_BUFFER_OFFSET;
1544         sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P2_Q1_BD_OFFSET;
1545         sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET;
1546         sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P2_Q1_BD_OFFSET;
1548         sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset       = P2_Q2_BUFFER_OFFSET;
1549         sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P2_Q2_BD_OFFSET;
1550         sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET + 8U;
1551         sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P2_Q2_BD_OFFSET;
1553         sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset       = P2_Q3_BUFFER_OFFSET;
1554         sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P2_Q3_BD_OFFSET;
1555         sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET +16U;
1556         sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P2_Q3_BD_OFFSET;
1558         sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset       = P2_Q4_BUFFER_OFFSET;
1559         sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P2_Q4_BD_OFFSET;
1560         sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = PORT_QUEUE_DESC_OFFSET +24U;
1561         sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P2_Q4_BD_OFFSET;
1562         break;
1564     default:
1565         break;
1566     }
1570 /**
1571  *  @b Description
1572  *  @n
1573  *      API Function to re-initialize all Port Queue params
1574  * 
1575  *  @param[in]  icssEmacHandle handle to ICSS_EMAC Instance
1576  *  @param[in]  portNumber number of the port to flush
1577  *  @retval None
1578  */
1579 void ICSS_EmacPortFlush(ICSS_EmacHandle icssEmacHandle, int32_t portNumber)
1581   ICSS_EmacPortParams *sPort;
1583   switch ( portNumber )
1584   {
1585     case ICSS_EMAC_PORT_1:
1586       sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_1]);
1588       sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset      = P1_Q1_BUFFER_OFFSET;
1589       sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P1_Q1_BD_OFFSET;
1590       sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = P1_QUEUE_DESC_OFFSET;
1591       sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P1_Q1_BD_OFFSET;
1593       sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset      = P1_Q2_BUFFER_OFFSET;
1594       sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P1_Q2_BD_OFFSET;
1595       sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = P1_QUEUE_DESC_OFFSET + 8U;
1596       sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P1_Q2_BD_OFFSET;
1598       sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset      = P1_Q3_BUFFER_OFFSET;
1599       sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P1_Q3_BD_OFFSET;
1600       sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = P1_QUEUE_DESC_OFFSET +16U;
1601       sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P1_Q3_BD_OFFSET;
1603       sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset      = P1_Q4_BUFFER_OFFSET;
1604       sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P1_Q4_BD_OFFSET;
1605       sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = P1_QUEUE_DESC_OFFSET +24U;
1606       sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P1_Q4_BD_OFFSET;
1608       sPort->queue[ICSS_EMAC_COLQUEUE].buffer_offset      = P1_COL_BUFFER_OFFSET;
1609       sPort->queue[ICSS_EMAC_COLQUEUE].buffer_desc_offset = P1_COL_BD_OFFSET;
1610       sPort->queue[ICSS_EMAC_COLQUEUE].queue_desc_offset  = P1_COL_QUEUE_DESC_OFFSET;
1611       sPort->queue[ICSS_EMAC_COLQUEUE].queue_size         = (COLLISION_QUEUE_SIZE << 2) + P1_COL_BD_OFFSET;
1613       break;
1615     case ICSS_EMAC_PORT_2:
1616       sPort = &(((ICSS_EmacObject*)icssEmacHandle->object)->switchPort[ICSS_EMAC_PORT_2]);
1618       sPort->queue[ICSS_EMAC_QUEUE1].buffer_offset      = P2_Q1_BUFFER_OFFSET;
1619       sPort->queue[ICSS_EMAC_QUEUE1].buffer_desc_offset = P2_Q1_BD_OFFSET;
1620       sPort->queue[ICSS_EMAC_QUEUE1].queue_desc_offset  = P2_QUEUE_DESC_OFFSET;
1621       sPort->queue[ICSS_EMAC_QUEUE1].queue_size         = (QUEUE_1_SIZE << 2) + P2_Q1_BD_OFFSET;
1623       sPort->queue[ICSS_EMAC_QUEUE2].buffer_offset      = P2_Q2_BUFFER_OFFSET;
1624       sPort->queue[ICSS_EMAC_QUEUE2].buffer_desc_offset = P2_Q2_BD_OFFSET;
1625       sPort->queue[ICSS_EMAC_QUEUE2].queue_desc_offset  = P2_QUEUE_DESC_OFFSET + 8U;
1626       sPort->queue[ICSS_EMAC_QUEUE2].queue_size         = (QUEUE_2_SIZE << 2) + P2_Q2_BD_OFFSET;
1628       sPort->queue[ICSS_EMAC_QUEUE3].buffer_offset      = P2_Q3_BUFFER_OFFSET;
1629       sPort->queue[ICSS_EMAC_QUEUE3].buffer_desc_offset = P2_Q3_BD_OFFSET;
1630       sPort->queue[ICSS_EMAC_QUEUE3].queue_desc_offset  = P2_QUEUE_DESC_OFFSET +16U;
1631       sPort->queue[ICSS_EMAC_QUEUE3].queue_size         = (QUEUE_3_SIZE << 2) + P2_Q3_BD_OFFSET;
1633       sPort->queue[ICSS_EMAC_QUEUE4].buffer_offset      = P2_Q4_BUFFER_OFFSET;
1634       sPort->queue[ICSS_EMAC_QUEUE4].buffer_desc_offset = P2_Q4_BD_OFFSET;
1635       sPort->queue[ICSS_EMAC_QUEUE4].queue_desc_offset  = P2_QUEUE_DESC_OFFSET +24U;
1636       sPort->queue[ICSS_EMAC_QUEUE4].queue_size         = (QUEUE_4_SIZE << 2) + P2_Q4_BD_OFFSET;
1638       sPort->queue[ICSS_EMAC_COLQUEUE].buffer_offset      = P2_COL_BUFFER_OFFSET;
1639       sPort->queue[ICSS_EMAC_COLQUEUE].buffer_desc_offset = P2_COL_BD_OFFSET;
1640       sPort->queue[ICSS_EMAC_COLQUEUE].queue_desc_offset  = P2_COL_QUEUE_DESC_OFFSET;
1641       sPort->queue[ICSS_EMAC_COLQUEUE].queue_size         = (COLLISION_QUEUE_SIZE << 2) + P2_COL_BD_OFFSET;
1643       break;
1645     default:
1646       break;
1647   }
1649 /**
1650  *  @b Description
1651  *  @n
1652  *      API to register the hardware interrupt receive packet callback function
1653  *
1654  *  @param[in]  hwIntRx    hardware interrupt receive packet callback function
1655  *  @retval     none
1656  */
1657 void ICSS_EmacRegisterHwIntRx (ICSS_EmacHandle icssEmacHandle, ICSS_EmacCallBack hwIntRx)
1659     ((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntRx = hwIntRx;
1662 /**
1663  *  @b Description
1664  *  @n
1665  *      API to register the hardware interrupt for Transmit packet complete by PRU-ICSS firmware
1666  *
1667  *  @param[in]  hwIntRx    hardware interrupt transmit packet complete callback function
1668  *  @retval     none
1669  */
1670 void ICSS_EmacRegisterHwIntTx(ICSS_EmacHandle icssEmacHandle, ICSS_EmacCallBack hwIntTx)
1672     ((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntTx = hwIntTx;
1674 int8_t ICSS_EmacOSInit(ICSS_EmacHandle icssEmacHandle)
1676     int8_t ret_val = 0;
1678 #ifdef ENABLE_TIMER_SUPPORT
1679     uint8_t pacingMode;
1680     TimerP_Params timerParams;
1681 #endif
1682     SemaphoreP_Params semParams;
1684     ICSS_EMAC_osalSemParamsInit(&semParams);
1685     semParams.mode = SemaphoreP_Mode_BINARY;
1686     semParams.name= "rxSemaphore";
1688     ((ICSS_EmacObject*)icssEmacHandle->object)->rxSemaphoreHandle =  ICSS_EMAC_osalCreateBlockingLock(0,&semParams);
1689     if(((ICSS_EmacObject*)icssEmacHandle->object)->rxSemaphoreHandle==NULL)
1690     {
1691         ret_val = -1;
1692     }
1693     else
1694     {
1695         ICSS_EMAC_osalSemParamsInit(&semParams);
1696         semParams.mode = SemaphoreP_Mode_BINARY;
1697         semParams.name= "txSemaphore";
1698         ((ICSS_EmacObject*)icssEmacHandle->object)->txSemaphoreHandle =  ICSS_EMAC_osalCreateBlockingLock(0,&semParams);
1699         if(((ICSS_EmacObject*)icssEmacHandle->object)->txSemaphoreHandle==NULL)
1700         {
1701             ret_val = -1;
1702         }
1703 #ifdef ENABLE_TIMER_SUPPORT
1704         else
1705         {
1706             pacingMode = (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->ICSS_EmacIntrPacingMode;
1707             if(pacingMode == ICSS_EMAC_INTR_PACING_MODE2)
1708             {
1709                 ICSS_EMAC_osalTimerParamsInit(&timerParams);
1711                 timerParams.period = DEFAULT_PACING_TIMER_VAL;
1712                 timerParams.arg = (void*)icssEmacHandle;
1713                 timerParams.freqHi = 0;
1714                 timerParams.freqLo = DMTIMER_SRC_CLK_FREQ;
1716                 /*Create Interrupt Pacing Timer*/
1717                 ICSS_EMAC_osalTimerCreate(DMTIMER4_ID, (TimerP_Fxn)ICSS_EmacInterruptPacingISR, &timerParams);
1719                 if (pacingTimerHandle == NULL) {
1720                     ret_val = -1;
1721                 }
1722             }
1723         }
1724 #endif
1725     }
1726     return ret_val;
1728 /**
1729 * @internal
1730 * @brief Function to delete Rx task (to receive packet)
1732 * @param none
1734 * @retval Success -   0
1735 *         Error   -   <0
1736 */
1737 int8_t ICSS_EmacOSDeInit(ICSS_EmacHandle icssEmacHandle)
1739     ICSS_EMAC_osalDeleteBlockingLock(((ICSS_EmacObject*)icssEmacHandle->object)->rxSemaphoreHandle);
1740     return 0;
1743 void ICSS_EmacAddProtocolToList(uint16_t protocolType);   /* for misra warning*/
1744 void ICSS_EmacAddProtocolToList(uint16_t protocolType)
1746     if(MAX_NUM_PROTOCOL_IMPLEMENTED > numImplementedProtocols) {
1747         protocol_impl[numImplementedProtocols] =  protocolType;
1748         numImplementedProtocols++;
1749     }
1752 void ICSS_EmacUpdatePhyStatus(uint8_t portNum,ICSS_EmacHandle icssEmacHandle);  /* for misra warning*/
1753 void ICSS_EmacUpdatePhyStatus(uint8_t portNum,ICSS_EmacHandle icssEmacHandle) 
1756     volatile uint8_t *portStatusPtr=NULL;
1757     volatile uint8_t portStatus = 0;
1758     uint8_t linkStatus=0;
1759     volatile uint32_t *phySpeedStatusPtr=NULL;
1760     uint8_t index=0;
1761     uint16_t phyStat=0;
1762     uint8_t duplexity=1U;
1763     uint16_t regStatus=0;
1765     uint32_t temp_addr = 0U;
1767     if(ICSS_EMAC_MODE_SWITCH == (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->portMask)
1768     {
1769         index= portNum-1U;
1770     }
1771     else
1772     {
1773         index= 0;
1774     }
1776     linkStatus = ((ICSS_EmacObject*)icssEmacHandle->object)->linkStatus[index];
1778     if(portNum == ((uint8_t)(ICSS_EMAC_PORT_1))) {
1779         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + PHY_SPEED_OFFSET);
1780         phySpeedStatusPtr = (uint32_t*)(temp_addr);
1781         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam0BaseAddr + PORT_STATUS_OFFSET);
1782         portStatusPtr = (uint8_t*)(temp_addr);
1783     }
1785     if(portNum == ((uint8_t)(ICSS_EMAC_PORT_2))) {
1786         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + PHY_SPEED_OFFSET);
1787         phySpeedStatusPtr = (uint32_t*)(temp_addr);
1788         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->dataRam1BaseAddr + PORT_STATUS_OFFSET);
1789         portStatusPtr = (uint8_t*)(temp_addr);
1790     }
1792     if(linkStatus)
1793     {
1794             CSL_MDIO_phyRegRead((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs,
1795                                                (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->phyAddr[index], TLKPHY_PHYSTS_REG, &regStatus);
1796             if (regStatus & TLK_SPEED_STATUS) /*Speed is 10*/
1797             {
1798                 if (regStatus & TLK_DUPLEX_STATUS)
1799                 {
1800                     phyStat = PHY_CONFIG_10FD;
1801                 }
1802                 else
1803                 {
1804                     phyStat =  PHY_CONFIG_10HD;
1805                 }
1806             }
1807             else/*Speed is 100*/
1808             {
1809                 if (regStatus & TLK_DUPLEX_STATUS)
1810                 {
1811                     phyStat =  PHY_CONFIG_100FD;
1812                 }
1813                 else
1814                 {
1815                     phyStat = PHY_CONFIG_100HD;
1816                 }
1817         }
1819         if(phySpeedStatusPtr != NULL)
1820         {
1821             switch(phyStat)
1822             {
1823                 case PHY_CONFIG_100FD:
1824                     *(phySpeedStatusPtr) = Hundread_Mbps;
1825                     duplexity=1u;
1826                     break;
1827                 case PHY_CONFIG_100HD:
1828                     *(phySpeedStatusPtr) = Hundread_Mbps;
1829                     duplexity=0;
1830                     break;
1831                 case PHY_CONFIG_10FD:
1832                     *(phySpeedStatusPtr) = Ten_Mbps;
1833                     duplexity=1u;
1834                     break;
1835                 case PHY_CONFIG_10HD:
1836                     *(phySpeedStatusPtr) = Ten_Mbps;
1837                     duplexity=0;
1838                     break;
1839                 default:
1840                     *(phySpeedStatusPtr) = Hundread_Mbps;
1841                     duplexity=1u;    
1842                     break;
1843             }
1844         }
1845         if((((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->halfDuplexEnable)
1846         {
1847             /*set flags for HD*/
1848             if(duplexity == 0U) {
1849                 portStatus |= PORT_IS_HD_MASK;
1850             } else
1851             {
1852                 portStatus &= ~(PORT_IS_HD_MASK);
1853             }
1854         }
1855         /*Set Link Up Flag*/
1856         portStatus |= PORT_LINK_MASK;
1858
1859     else
1860     {
1861         /*Clear Link Up Flag*/
1862         portStatus &= ~(PORT_LINK_MASK);
1863     }
1865     if(portStatusPtr != NULL)
1866     {
1867         /*write back*/
1868         *(portStatusPtr) = portStatus;
1869     }
1871 /**
1872 * @brief Link change status interrupt for Port 0 and Port 1
1873 *         calls a user callback if defined to provide link info to stack
1875 * @param arg
1877 * @retval none
1878 */
1879 void ICSS_EmacLinkISR(void* arg) {
1881     volatile uint32_t linkStatus;
1882     volatile uint32_t *intStatusPtr;
1883     ICSSEMAC_IoctlCmd ioctlParams;
1884     uint8_t ioctlvalue = 0;
1885     ICSS_EmacHandle icssEmacHandle = (ICSS_EmacHandle)arg;
1887     uint32_t temp_addr = 0U;
1889     temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussIntcRegs + CSL_ICSSINTC_SECR1);
1890     /*Find out which port it is*/
1891     intStatusPtr = (uint32_t*)(temp_addr);
1893     if(LINK0_PRU_EVT_MASK & *intStatusPtr) { /**Link 0 Port event*/
1894         linkStatus = ICSS_EmacPhyLinkStatusGet((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs, 
1895                                                                  (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->phyAddr[0],
1896                                                                  100U);
1897         ((ICSS_EmacObject*)icssEmacHandle->object)->linkStatus[0]=(uint8_t)linkStatus;
1899         /*Update flags in memory*/
1900         ICSS_EmacUpdatePhyStatus((uint8_t)ICSS_EMAC_PORT_1, icssEmacHandle);
1902         if(linkStatus) {
1903             ioctlvalue = ICSS_EMAC_IOCTL_PORT_CTRL_ENABLE;
1904             ioctlParams.ioctlVal = &ioctlvalue;
1905             ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_PORT_CTRL, (uint8_t)ICSS_EMAC_PORT_1, (void*)&ioctlParams);
1906         } else {
1907             ioctlvalue = ICSS_EMAC_IOCTL_PORT_CTRL_DISABLE;
1908             ioctlParams.ioctlVal = &ioctlvalue;
1909             ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_PORT_CTRL, (uint8_t)ICSS_EMAC_PORT_1, (void*)&ioctlParams);
1910         }
1912         /*Protocol specific processing*/
1913         if(((ICSS_EmacObject*)icssEmacHandle->object)->port0ISRCall != NULL) {
1914            ((ICSS_EmacObject*)icssEmacHandle->object)->port0ISRCall((void *)linkStatus,((ICSS_EmacObject*)icssEmacHandle->object)->port0ISRUser);
1915         }
1916         
1917         temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs + ICSS_MDIO_LINKINT_RAW_MASK_OFFSET);
1918         /*clear interrupt in MDIO*/
1919         HWREG(temp_addr) = 0x01;
1921         /*clear PRU-ICSS INTC interrupt*/
1922         *intStatusPtr = LINK0_PRU_EVT_MASK;
1923     } else {
1924         if(LINK1_PRU_EVT_MASK & *intStatusPtr) { /**Link 1 Port event*/
1925             if(ICSS_EMAC_MODE_SWITCH != ((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg->portMask) {
1926                 linkStatus = ICSS_EmacPhyLinkStatusGet((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs,
1927                                                                     (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->phyAddr[0],
1928                                                                      100U);
1929                 ((ICSS_EmacObject*)icssEmacHandle->object)->linkStatus[0]=(uint8_t)linkStatus;
1930             } else {
1931                 linkStatus = ICSS_EmacPhyLinkStatusGet((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs,
1932                                                                    (((ICSS_EmacObject*)icssEmacHandle->object)->emacInitcfg)->phyAddr[1],
1933                                                                                 100U);
1934                 ((ICSS_EmacObject*)icssEmacHandle->object)->linkStatus[ICSS_EMAC_PORT_2-1]=(uint8_t)linkStatus;
1935             }
1938             /*Update flags in memory*/
1939             ICSS_EmacUpdatePhyStatus((uint8_t)ICSS_EMAC_PORT_2, icssEmacHandle);
1941             if(linkStatus) {
1942                 ioctlvalue = ICSS_EMAC_IOCTL_PORT_CTRL_ENABLE;
1943                 ioctlParams.ioctlVal = &ioctlvalue;
1944                 ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_PORT_CTRL, (uint8_t)ICSS_EMAC_PORT_2, (void*)&ioctlParams);
1945             } else {
1946                 ioctlvalue = ICSS_EMAC_IOCTL_PORT_CTRL_DISABLE;
1947                 ioctlParams.ioctlVal = &ioctlvalue;
1948                 ICSS_EmacIoctl(icssEmacHandle, ICSS_EMAC_IOCTL_PORT_CTRL, (uint8_t)ICSS_EMAC_PORT_2, (void*)&ioctlParams);
1949             }
1951             if(((ICSS_EmacObject*)icssEmacHandle->object)->port1ISRCall != NULL) {
1952                ((ICSS_EmacObject*)icssEmacHandle->object)->port1ISRCall((void *)linkStatus,((ICSS_EmacObject*)icssEmacHandle->object)->port1ISRUser);
1953             }
1955             temp_addr = ((((ICSS_EmacHwAttrs*)icssEmacHandle->hwAttrs)->emacBaseAddrCfg)->prussMiiMdioRegs + ICSS_MDIO_LINKINT_RAW_MASK_OFFSET);
1956             /*clear interrupt in MDIO*/
1957             HWREG(temp_addr) = 0x02;
1959             /*clear PRU-ICSS INTC interrupt*/
1960             *intStatusPtr = LINK1_PRU_EVT_MASK;
1961         }
1962     }
1965 /**
1966 * @brief Callback function to process protocol specific handler for link status ISR for Port 0
1968 * @param callBack    Callback function pointer
1969 * @param userArg    user specific parameter
1971 * @retval none
1972 */
1973 void ICSS_EmacRegisterPort0ISRCallback(ICSS_EmacHandle icssEmacHandle, ICSS_EmacCallBack callBack, void *userArg)
1975    ((ICSS_EmacObject*)icssEmacHandle->object)->port0ISRCall = callBack;
1976    ((ICSS_EmacObject*)icssEmacHandle->object)->port0ISRUser = userArg;
1979 /**
1980 * @brief Callback function to process protocol specific handler for link status ISR for Port 1
1982 * @param callBack    Callback function pointer
1983 * @param userArg    user specific parameter
1985 * @retval none
1986 */
1987 void ICSS_EmacRegisterPort1ISRCallback(ICSS_EmacHandle icssEmacHandle, ICSS_EmacCallBack callBack, void *userArg)
1989    ((ICSS_EmacObject*)icssEmacHandle->object)->port1ISRCall = callBack;
1990    ((ICSS_EmacObject*)icssEmacHandle->object)->port1ISRUser = userArg;
1995 /**
1996 * @brief Function to status of Phy Link
1998 * @param mdioBaseAddr       mdio subsystem base address
1999 * @param phyAddr            physical address
2000 * @param retries            retry count
2002 * @retval 1 if phy link up, 0 phy link down
2003 */
2004 uint32_t ICSS_EmacPhyLinkStatusGet(uint32_t mdioBaseAddr,
2005                               uint32_t phyAddr,
2006                               volatile uint32_t retries)
2008     volatile uint16_t linkStatus;
2009     uint32_t ret_val = FALSE_VAL;
2010     retries++;
2011     while (retries)
2012     {
2013         /* First read the BSR of the PHY */
2014         CSL_MDIO_phyRegRead(mdioBaseAddr, phyAddr, PHY_BSR, (uint16_t*)&linkStatus);
2016         if(linkStatus & PHY_LINK_STATUS)
2017         {
2018             ret_val = TRUE_VAL;
2019             break;
2020         }
2022         retries--;
2023     }
2025     return ret_val;
2027 /**
2028  *  \name ICSS_EMacOsTxTaskFnc
2029  *  @brief
2030  *      Function which pends on Tx semaphore.Invokes registered Tx Callback function
2031  *
2032  *  @param a0 arg 1
2033  *  @param a1 arg 2
2034  *
2035  *  @retval none
2036  *
2037  */
2038 void ICSS_EMacOsTxTaskFnc(uint32_t a0, uint32_t a1)
2040     ICSS_EmacHandle icssEmacHandle;
2041     icssEmacHandle = (ICSS_EmacHandle)a0;
2043     while(1)
2044     {
2045         ICSS_EMAC_osalPendLock(((ICSS_EmacObject*)icssEmacHandle->object)->txSemaphoreHandle, SemaphoreP_WAIT_FOREVER);
2046         ((ICSS_EmacObject*)icssEmacHandle->object)->icssEmacHwIntTx(icssEmacHandle,NULL);
2047     }