1 /*
2  * Copyright 2021-2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_netc_endpoint.h"
8 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_051130) && FSL_FEATURE_NETC_HAS_ERRATA_051130)
9 #include "fsl_netc_timer.h"
10 #endif
11 #if defined(FSL_FEATURE_NETC_HAS_ERRATA_051587) && FSL_FEATURE_NETC_HAS_ERRATA_051587
12 #include <math.h>
13 #endif
14 
15 /*! @name Defines some Ethernet parameters. */
16 /*@{*/
17 #define NETC_ENETC_TXFRAME_LEN_MAX (9600U) /*!< The Maximum length of frame length. */
18 #define NETC_ENETC_TXFRAME_LEN_MIN (16U)   /*!< The Minimum length of frame length. */
19 /*@}*/
20 
21 /*! @brief Mask the cache management code if cache control is disabled. */
22 #if !defined(FSL_ETH_ENABLE_CACHE_CONTROL)
23 #define NETC_DcacheInvalidateByRange(address, sizeByte)
24 #define NETC_DcacheCleanByRange(address, sizeByte)
25 #else
26 #define NETC_DcacheInvalidateByRange(address, sizeByte) DCACHE_InvalidateByRange(address, sizeByte)
27 #define NETC_DcacheCleanByRange(address, sizeByte)      DCACHE_CleanByRange(address, sizeByte)
28 #endif
29 
30 /*! @brief Command BD common buffer. */
31 AT_NONCACHEABLE_SECTION_ALIGN(static netc_tb_data_buffer_t s_cmdData, 16);
32 
33 /*!
34  * @brief Get register map resource for handle
35  *
36  * @param handle  The EP handle.
37  * @param si      The SI object.
38  */
EP_GetBaseResource(ep_handle_t * handle,netc_hw_si_idx_t si)39 static void EP_GetBaseResource(ep_handle_t *handle, netc_hw_si_idx_t si)
40 {
41     NETC_SocGetBaseResource(&handle->hw, si);
42 }
43 
44 /*!
45  * @brief Store necessary configuration constant in the handle
46  *
47  * @param handle  The EP handle.
48  * @param config  The user configuration.
49  */
EP_StoreConfig(ep_handle_t * handle,const ep_config_t * config)50 static void EP_StoreConfig(ep_handle_t *handle, const ep_config_t *config)
51 {
52     handle->cfg.si              = config->si;
53     handle->cfg.rxRingUse       = config->siConfig.rxRingUse;
54     handle->cfg.txRingUse       = config->siConfig.txRingUse;
55     handle->cfg.rxBdrGroupNum   = config->siConfig.rxBdrGroupNum;
56     handle->cfg.ringPerBdrGroup = config->siConfig.ringPerBdrGroup;
57     handle->cfg.entryNum        = config->entryNum;
58     handle->cfg.reclaimCallback = config->reclaimCallback;
59     handle->cfg.userData        = config->userData;
60     handle->cfg.rxCacheMaintain = config->rxCacheMaintain;
61     handle->cfg.txCacheMaintain = config->txCacheMaintain;
62     handle->cfg.rxZeroCopy      = config->rxZeroCopy;
63     handle->cfg.rxBuffAlloc     = config->rxBuffAlloc;
64     handle->cfg.rxBuffFree      = config->rxBuffFree;
65 }
66 
67 /*!
68  * @brief Free all Rx buffers
69  *
70  * @param handle  The EP handle.
71  */
EP_RxBufferFreeAll(ep_handle_t * handle)72 static void EP_RxBufferFreeAll(ep_handle_t *handle)
73 {
74     netc_rx_bdr_t *rxBdRing;
75     uint32_t maxHwBdNum;
76     uint32_t index;
77     uint8_t ring;
78 
79     if (handle->cfg.rxZeroCopy)
80     {
81         for (ring = 0U; ring < handle->cfg.rxRingUse; ring++)
82         {
83             rxBdRing = &handle->rxBdRing[ring];
84             /* Hardware BD number means actual BD number in hardware view, two standard BDs act as one extended BD. */
85             maxHwBdNum = rxBdRing->extendDesc ? (rxBdRing->len / 2U) : rxBdRing->len;
86 
87             for (index = 0U; index < maxHwBdNum; index++)
88             {
89                 if (rxBdRing->buffArray[index] != 0U)
90                 {
91                     handle->cfg.rxBuffFree(handle, ring, (void *)(uint8_t *)(uintptr_t)rxBdRing->buffArray[index],
92                                            handle->cfg.userData);
93                 }
94             }
95         }
96     }
97 }
98 
99 /*!
100  * @brief Allocate Rx buffers for Rx BD rings
101  *
102  * @param handle     The EP handle.
103  * @param config     The EP configuration.
104  * @param bdrConfig  The BD ring configuration.
105  */
EP_RxBufferAllocAll(ep_handle_t * handle,const ep_config_t * config,const netc_bdr_config_t * bdrConfig)106 static status_t EP_RxBufferAllocAll(ep_handle_t *handle, const ep_config_t *config, const netc_bdr_config_t *bdrConfig)
107 {
108     status_t result = kStatus_Success;
109     const netc_rx_bdr_config_t *rxRingConfig;
110     netc_rx_bd_t *rxDesc;
111     uint64_t buffAddr;
112     uint16_t buffIdx;
113     uint16_t index;
114     uint8_t ring;
115 
116     for (ring = 0U; ring < config->siConfig.rxRingUse; ring++)
117     {
118         rxRingConfig = &bdrConfig->rxBdrConfig[ring];
119         rxDesc       = &rxRingConfig->bdArray[0];
120 
121         /* Store address information in the array in case the buffer address is lost due to Rx BD write-back. */
122         handle->rxBdRing[ring].buffArray = rxRingConfig->buffAddrArray;
123 
124         /* Initialize the buffers in Rx BD ring. */
125         for (index = 0U; index < rxRingConfig->len; index++)
126         {
127             /* Clear Rx BD before config the receive buffer start address */
128             (void)memset(rxDesc, 0, sizeof(netc_rx_bd_t));
129 
130             /* When extended BD is enabled, two standard BDs represet one extended BD. Even number BD sets 0. */
131             if (rxRingConfig->extendDescEn && (index % 2U != 0U))
132             {
133                 rxDesc++;
134                 continue;
135             }
136 
137             buffIdx = rxRingConfig->extendDescEn ? (index / 2U) : index;
138             if (!config->rxZeroCopy)
139             {
140                 /* Get Rx buffer address from the address array provided by application. */
141                 buffAddr = handle->rxBdRing[ring].buffArray[buffIdx];
142             }
143             else
144             {
145                 /* Get Rx buffer address from the allocation function provided by application. */
146                 buffAddr = (uint64_t)(uintptr_t)(uint8_t *)handle->cfg.rxBuffAlloc(
147                     handle, ring, handle->rxBdRing[ring].buffSize, handle->cfg.userData);
148                 if (buffAddr == 0U)
149                 {
150                     EP_RxBufferFreeAll(handle);
151                     result = kStatus_NETC_LackOfResource;
152                     break;
153                 }
154 
155                 /* Keep Rx buffer address from pool in driver until it's freed. */
156                 handle->rxBdRing[ring].buffArray[buffIdx] = buffAddr;
157             }
158 
159 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
160             buffAddr = MEMORY_ConvertMemoryMapAddress((uintptr_t)buffAddr, kMEMORY_Local2DMA);
161 #endif
162             rxDesc->standard.addr = buffAddr;
163             rxDesc++;
164         }
165 
166         if (result != kStatus_Success)
167         {
168             break;
169         }
170     }
171 
172     return result;
173 }
174 
175 /*!
176  * @brief Initialize the Tx/Rx BD ring
177  *
178  * @param handle     The EP handle.
179  * @param config     The EP configuration.
180  * @param bdrConfig  The BD ring configuration.
181  */
EP_DescriptorInit(ep_handle_t * handle,const ep_config_t * config,const netc_bdr_config_t * bdrConfig)182 static status_t EP_DescriptorInit(ep_handle_t *handle, const ep_config_t *config, const netc_bdr_config_t *bdrConfig)
183 {
184     assert(bdrConfig != NULL);
185 
186     status_t result  = kStatus_Success;
187     uint8_t idxStart = 0U;
188     uint8_t ring;
189 
190     /* Setup Tx/Rx buffer descriptor rings. */
191     if (NETC_EnetcHasManagement(handle->hw.base) && (getSiNum(handle->cfg.si) == 0U))
192     {
193         /* For management ENETC, the SI 0 hardware Tx ring index 0 has been keep for direct switch enqueue feature */
194         idxStart = 1;
195     }
196     for (ring = 0; ring < config->siConfig.txRingUse; ring++)
197     {
198         if (NETC_SIConfigTxBDR(handle->hw.si, ring + idxStart, &bdrConfig->txBdrConfig[ring]) != kStatus_Success)
199         {
200             return kStatus_Fail;
201         }
202         handle->txBdRing[ring].bdBase    = bdrConfig->txBdrConfig[ring].bdArray;
203         handle->txBdRing[ring].dirtyBase = bdrConfig->txBdrConfig[ring].dirtyArray;
204         handle->txBdRing[ring].len       = bdrConfig->txBdrConfig[ring].len;
205     }
206     for (ring = 0; ring < config->siConfig.rxRingUse; ring++)
207     {
208         if (NETC_SIConfigRxBDR(handle->hw.si, ring, &bdrConfig->rxBdrConfig[ring]) != kStatus_Success)
209         {
210             return kStatus_Fail;
211         }
212         handle->rxBdRing[ring].extendDesc = bdrConfig->rxBdrConfig[ring].extendDescEn;
213         handle->rxBdRing[ring].bdBase     = bdrConfig->rxBdrConfig[ring].bdArray;
214         handle->rxBdRing[ring].len        = bdrConfig->rxBdrConfig[ring].len;
215         handle->rxBdRing[ring].buffSize   = bdrConfig->rxBdrConfig[ring].buffSize;
216     }
217 
218     /* Allocate Rx buffers to the BDs. */
219     result = EP_RxBufferAllocAll(handle, config, bdrConfig);
220     if (result != kStatus_Success)
221     {
222         return result;
223     }
224 
225     /* Enable the used BD ring. */
226     for (ring = 0; ring < config->siConfig.rxRingUse; ring++)
227     {
228         NETC_SIRxRingEnable(handle->hw.si, ring, true);
229     }
230 
231     return kStatus_Success;
232 }
233 
234 /*!
235  * @brief Setup Station Interface
236  *
237  * @param handle     The EP handle.
238  * @param si         The SI number.
239  * @param epConfig   The EP configuration.
240  * @param bdrConfig  The BD ring configuration.
241  */
EP_SISetup(ep_handle_t * handle,uint8_t si,const ep_config_t * epConfig,const netc_bdr_config_t * bdrConfig)242 static status_t EP_SISetup(ep_handle_t *handle,
243                            uint8_t si,
244                            const ep_config_t *epConfig,
245                            const netc_bdr_config_t *bdrConfig)
246 {
247     status_t result;
248 
249     if (((epConfig->siConfig.ringPerBdrGroup * epConfig->siConfig.rxBdrGroupNum) > epConfig->siConfig.rxRingUse) ||
250         (((uint8_t)epConfig->siConfig.defaultRxBdrGroup >= epConfig->siConfig.rxBdrGroupNum) &&
251          (epConfig->siConfig.defaultRxBdrGroup != kNETC_SiBDRGroupOne)) ||
252         (epConfig->siConfig.ringPerBdrGroup == 0U))
253     {
254         /* Not recommended to make groups use more rings than the total number available, and Can't selected non
255          * existing group */
256         return kStatus_InvalidArgument;
257     }
258 
259     NETC_SISetRxBDRGroup(handle->hw.si, (uint8_t)epConfig->siConfig.rxBdrGroupNum,
260                          (uint8_t)epConfig->siConfig.ringPerBdrGroup);
261     NETC_SISetDefaultRxBDRGroup(handle->hw.si, epConfig->siConfig.defaultRxBdrGroup);
262 
263     /* Configure station interface. */
264     result = NETC_EnetcConfigureSI(handle->hw.base, si, &epConfig->siConfig);
265     if (result != kStatus_Success)
266     {
267         return result;
268     }
269 
270     /* Initialize the Tx/Rx buffer descriptor. */
271     result = EP_DescriptorInit(handle, epConfig, bdrConfig);
272     if (result != kStatus_Success)
273     {
274         return result;
275     }
276     NETC_SIEnableVlanToIpv(handle->hw.si, (bool)epConfig->siConfig.valnToIpvEnable);
277     for (uint8_t i = 0U; i < 16U; i++)
278     {
279         if (epConfig->siConfig.vlanToIpvMap[i] > 7U)
280         {
281             /* The mapped IPV value range in 0 ~ 7 */
282             return kStatus_InvalidArgument;
283         }
284         else
285         {
286             NETC_SIMapVlanToIpv(handle->hw.si, i, epConfig->siConfig.vlanToIpvMap[i]);
287         }
288     }
289     for (uint8_t i = 0U; i < 8U; i++)
290     {
291         if ((epConfig->siConfig.ipvToRingMap[i] != 0U) &&
292             (epConfig->siConfig.ipvToRingMap[i] >= epConfig->siConfig.ringPerBdrGroup))
293         {
294             /* The mapped BD ring should be located in one BD ring group */
295             return kStatus_InvalidArgument;
296         }
297         else
298         {
299             NETC_SIMapIpvToRing(handle->hw.si, i, epConfig->siConfig.ipvToRingMap[i]);
300         }
301     }
302 
303     /* Enable station interface from both ENETC and SI sides. */
304     NETC_EnetcEnableSI(handle->hw.base, si, true);
305     NETC_SIEnable(handle->hw.si, true);
306 
307     return result;
308 }
309 
310 /*!
311  * @brief Set the MSIX entry table
312  *
313  * This function is to set entry table in specified MSIX Table memory. After entry table setup, set interrupts
314  * vector/entry index.
315  *
316  * @param handle  The EP handle.
317  * @param config  The EP configuration.
318  * @return status_t
319  */
EP_MSIXSetEntryTable(ep_handle_t * handle,const ep_config_t * config)320 static status_t EP_MSIXSetEntryTable(ep_handle_t *handle, const ep_config_t *config)
321 {
322     uint32_t *msixTable  = (uint32_t *)(uintptr_t)handle->hw.msixTable;
323     uint32_t *entryTable = (uint32_t *)(uintptr_t)config->msixEntry;
324     uint8_t siNum        = getSiNum(handle->cfg.si);
325     uint8_t msixNum;
326     status_t result;
327 
328     result = NETC_EnetcSetMsixEntryNum(handle->hw.base, siNum, config->entryNum);
329     if (result != kStatus_Success)
330     {
331         return result;
332     }
333 
334     msixNum = (uint8_t)(
335         ((handle->hw.si->SIPCAPR1 & ENETC_SI_SIPCAPR1_NUM_MSIX_MASK) >> ENETC_SI_SIPCAPR1_NUM_MSIX_SHIFT) + 1U);
336 
337     /* Entry > 0, enable MSIX. */
338     if (config->entryNum != 0U)
339     {
340         if (config->entryNum > msixNum)
341         {
342             return kStatus_InvalidArgument;
343         }
344 
345         if (MAX(MAX(config->siComEntryIdx, config->timerSyncEntryIdx), config->cmdBdEntryIdx) >= config->entryNum)
346         {
347             return kStatus_InvalidArgument;
348         }
349 
350         /* Use 32-bit access to set MSIX table. */
351         for (uint32_t i = 0; i < config->entryNum; i++)
352         {
353             msixTable[i * 4U]      = entryTable[i * 4U];
354             msixTable[i * 4U + 1U] = entryTable[i * 4U + 1U];
355             msixTable[i * 4U + 2U] = entryTable[i * 4U + 2U];
356             msixTable[i * 4U + 3U] = entryTable[i * 4U + 3U];
357         }
358 
359         /* Enable MSIX. */
360         if (siNum == 0U)
361         {
362             handle->hw.func.pf->PCI_CFC_MSIX_MSG_CTL = ENETC_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_MSIX_EN_MASK;
363         }
364         else
365         {
366             handle->hw.func.vf->PCI_CFC_MSIX_MSG_CTL = ENETC_VF_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_MSIX_EN_MASK;
367         }
368 
369         /* Set the MSIX table entry index for various events */
370         if (handle->capability.vsiNum > 0U)
371         {
372             handle->hw.si->SIMSIVR = (uint32_t)config->siComEntryIdx & ENETC_SI_SIMSIVR_VECTOR_MASK;
373         }
374         handle->hw.si->SITMRMSIVR = (uint32_t)config->timerSyncEntryIdx & ENETC_SI_SITMRMSIVR_VECTOR_MASK;
375         handle->hw.si->SICMSIVR   = (uint32_t)config->cmdBdEntryIdx & ENETC_SI_SICMSIVR_VECTOR_MASK;
376     }
377     else
378     {
379         /* Disable MSIX. */
380         if (siNum == 0U)
381         {
382             handle->hw.func.pf->PCI_CFC_MSIX_MSG_CTL = ENETC_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_FUNC_MASK_MASK;
383         }
384         else
385         {
386             handle->hw.func.vf->PCI_CFC_MSIX_MSG_CTL = ENETC_VF_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_FUNC_MASK_MASK;
387         }
388     }
389 
390     return kStatus_Success;
391 }
392 
393 /*!
394  * @brief Get the idle Tx BD number in the ring
395  * @note The last BD before producer index should be treated as an used BD according to hardware design.
396  *
397  * @param txBdRing  The EP handle.
398  * @return The idle BD number.
399  */
EP_GetIdleTxBDNum(netc_tx_bdr_t * txBdRing)400 static uint16_t EP_GetIdleTxBDNum(netc_tx_bdr_t *txBdRing)
401 {
402     if (txBdRing->producerIndex >= txBdRing->cleanIndex)
403     {
404         return (uint16_t)((txBdRing->len - txBdRing->producerIndex) + txBdRing->cleanIndex - 1U);
405     }
406     else
407     {
408         return (txBdRing->cleanIndex - txBdRing->producerIndex - 1U);
409     }
410 }
411 
EP_GetDefaultConfig(ep_config_t * config)412 status_t EP_GetDefaultConfig(ep_config_t *config)
413 {
414     assert(config != NULL);
415 
416     (void)memset(config, 0, sizeof(ep_config_t));
417 
418     config->port.common.acceptTpid.innerMask = (uint8_t)kNETC_OuterStanCvlan | (uint8_t)kNETC_OuterStanSvlan;
419     config->port.common.acceptTpid.outerMask = (uint8_t)kNETC_InnerStanCvlan | (uint8_t)kNETC_InnerStanSvlan;
420     config->port.common.pSpeed               = 0x63U;
421     config->port.common.rxTsSelect           = kNETC_SyncTime;
422 #if (defined(FSL_FEATURE_NETC_HAS_PORT_FCSEA) && FSL_FEATURE_NETC_HAS_PORT_FCSEA)
423     config->port.common.stompFcs = true;
424 #endif
425     config->port.common.rxPpduBco              = 20U;
426     config->port.common.txPpduBco              = 20U;
427     config->port.common.timeGate.holdSkew      = 64;
428     config->port.common.parser.l2PloadCount    = 24;
429     config->port.common.parser.l3PayloadCount  = 24;
430     config->port.common.parser.enableL3Parser  = true;
431     config->port.common.parser.l4PayloadCount  = 24;
432     config->port.common.parser.enableL4Parser  = true;
433     config->port.ethMac.enableRevMii           = false;
434     config->port.ethMac.preemptMode            = kNETC_PreemptDisable;
435     config->port.ethMac.enMergeVerify          = false;
436     config->port.ethMac.mergeVerifyTime        = 10U;
437     config->port.ethMac.txTsSelect             = kNETC_SyncTime;
438     config->port.ethMac.enTxPad                = true;
439     config->port.ethMac.rxMinFrameSize         = 64U;
440     config->port.ethMac.rxMaxFrameSize         = 0x600U;
441     config->port.ethMac.maxBackPressOn         = 3036U;
442     config->port.ethMac.minBackPressOff        = 20U;
443     config->port.enPseudoMacTxPad              = true;
444     config->psfpCfg.isiPortConfig.defaultISEID = 0xFFFFU;
445     config->siConfig.ringPerBdrGroup           = 0x1U;
446     for (uint8_t i = 0U; i < 8U; i++)
447     {
448         config->txTcCfg[i].enTcGate           = true;
449         config->txTcCfg[i].sduCfg.maxSduSized = 0x600U;
450         config->txTcCfg[i].sduCfg.sduType     = kNETC_MPDU;
451         config->txPrioToTC[i]                 = i;
452         config->siConfig.vsiTcToTC[i]         = i;
453     }
454 
455     return kStatus_Success;
456 }
457 
EP_Init(ep_handle_t * handle,uint8_t * macAddr,const ep_config_t * config,const netc_bdr_config_t * bdrConfig)458 status_t EP_Init(ep_handle_t *handle, uint8_t *macAddr, const ep_config_t *config, const netc_bdr_config_t *bdrConfig)
459 {
460     assert(handle != NULL);
461     assert(config != NULL);
462 
463     uint8_t siNum = getSiNum(config->si);
464     status_t result;
465 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_051246) && FSL_FEATURE_NETC_HAS_ERRATA_051246)
466     NETC_PORT_Type *swPseudoPort = (NETC_PORT_Type *)FSL_FEATURE_NETC_SWITCH_PSEUDO_PORT_BASE;
467     uint32_t porTemp             = 0U;
468 #endif
469 
470     (void)memset(handle, 0, sizeof(ep_handle_t));
471 
472     /* Get the register map resource for ENETC */
473     EP_GetBaseResource(handle, config->si);
474 
475     /* Store necessary configuration constant in the handle */
476     EP_StoreConfig(handle, config);
477 
478     if (siNum != 0U)
479     {
480         /* Reset VF function */
481         handle->hw.func.vf->PCI_CFC_PCIE_DEV_CTL |= ENETC_VF_PCI_TYPE0_PCI_CFC_PCIE_DEV_CTL_INIT_FLR_MASK;
482         while ((handle->hw.func.pf->PCI_CFC_PCIE_DEV_CTL & ENETC_VF_PCI_TYPE0_PCI_CFC_PCIE_DEV_CTL_INIT_FLR_MASK) != 0U)
483         {
484         }
485         /* Enable master bus and memory access for PCIe and MSI-X */
486         handle->hw.func.vf->PCI_CFH_CMD |= ENETC_VF_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK;
487 
488         NETC_EnetcGetCapability(handle->hw.base, &handle->capability);
489         /* Transmit priority to traffic class mapping */
490         handle->hw.base->NUM_SI[siNum].PSICFGR1 = NETC_ENETC_PSICFGR1_TC7_MAP(config->siConfig.vsiTcToTC[7]) |
491                                                   NETC_ENETC_PSICFGR1_TC6_MAP(config->siConfig.vsiTcToTC[6]) |
492                                                   NETC_ENETC_PSICFGR1_TC5_MAP(config->siConfig.vsiTcToTC[5]) |
493                                                   NETC_ENETC_PSICFGR1_TC4_MAP(config->siConfig.vsiTcToTC[4]) |
494                                                   NETC_ENETC_PSICFGR1_TC3_MAP(config->siConfig.vsiTcToTC[3]) |
495                                                   NETC_ENETC_PSICFGR1_TC2_MAP(config->siConfig.vsiTcToTC[2]) |
496                                                   NETC_ENETC_PSICFGR1_TC1_MAP(config->siConfig.vsiTcToTC[1]) |
497                                                   NETC_ENETC_PSICFGR1_TC0_MAP(config->siConfig.vsiTcToTC[0]);
498     }
499     else
500     {
501 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_051260) && FSL_FEATURE_NETC_HAS_ERRATA_051260)
502         /* Errata 051260: All NETC functions need to be enabled for ENETC NTMP operation */
503         SWITCH_PCI_HDR_TYPE0->PCI_CFH_CMD |=
504             ENETC_PCI_TYPE0_PCI_CFH_CMD_MEM_ACCESS_MASK | ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK;
505         ENETC0_PCI_HDR_TYPE0->PCI_CFH_CMD |=
506             ENETC_PCI_TYPE0_PCI_CFH_CMD_MEM_ACCESS_MASK | ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK;
507         ENETC1_PCI_HDR_TYPE0->PCI_CFH_CMD |=
508             ENETC_PCI_TYPE0_PCI_CFH_CMD_MEM_ACCESS_MASK | ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK;
509 #endif
510         /* Enable master bus and memory access for PCIe and MSI-X */
511         handle->hw.func.pf->PCI_CFH_CMD |=
512             (ENETC_PCI_TYPE0_PCI_CFH_CMD_MEM_ACCESS_MASK | ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK);
513 
514         if (!NETC_PortIsPseudo(handle->hw.portGroup.port))
515         {
516             handle->hw.portGroup.port->POR |= (NETC_PORT_POR_TXDIS_MASK | NETC_PORT_POR_RXDIS_MASK);
517             /* Do software reset first */
518             NETC_PortSoftwareResetEthMac(handle->hw.portGroup.eth);
519         }
520 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_051246) && FSL_FEATURE_NETC_HAS_ERRATA_051246)
521         else
522         {
523             if (0U != (SWITCH_PCI_HDR_TYPE0->PCI_CFH_CMD & ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK))
524             {
525                 porTemp = swPseudoPort->POR;
526                 /* Disable the internal switch port's Tx/Rx to prevent frames from flowing into the internal ENETC
527                  * during its FLR and bring up */
528                 swPseudoPort->POR |= (NETC_PORT_POR_TXDIS_MASK | NETC_PORT_POR_RXDIS_MASK);
529             }
530         }
531 #endif
532         /* Reset PF function */
533         handle->hw.func.pf->PCI_CFC_PCIE_DEV_CTL |= ENETC_PCI_TYPE0_PCI_CFC_PCIE_DEV_CTL_INIT_FLR_MASK;
534         while ((handle->hw.func.pf->PCI_CFC_PCIE_DEV_CTL & ENETC_PCI_TYPE0_PCI_CFC_PCIE_DEV_CTL_INIT_FLR_MASK) != 0U)
535         {
536         }
537 
538         /* Enable master bus and memory access for PCIe and MSI-X */
539         handle->hw.func.pf->PCI_CFH_CMD |=
540             (ENETC_PCI_TYPE0_PCI_CFH_CMD_MEM_ACCESS_MASK | ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK);
541 
542         /* TODO: Here enable virtaul fucntion as default, may need flexible way. */
543         /* Enable virtual function */
544         handle->hw.func.pf->PCIE_CFC_SRIOV_CTL |=
545             (ENETC_PCI_TYPE0_PCIE_CFC_SRIOV_CTL_VF_MSE_MASK | ENETC_PCI_TYPE0_PCIE_CFC_SRIOV_CTL_VF_ENABLE_MASK);
546 
547         NETC_EnetcGetCapability(handle->hw.base, &handle->capability);
548 
549         /* Only PSI needs to configure port */
550         result = NETC_PortConfig(handle->hw.portGroup.port, &config->port.common);
551         if (result != kStatus_Success)
552         {
553             return result;
554         }
555 
556         if (!NETC_PortIsPseudo(handle->hw.portGroup.port))
557         {
558             result = NETC_PortConfigEthMac(handle->hw.portGroup.eth, &config->port.ethMac);
559             if (result != kStatus_Success)
560             {
561                 return result;
562             }
563         }
564 #if !(defined(FSL_FEATURE_NETC_HAS_NO_SWITCH) && FSL_FEATURE_NETC_HAS_NO_SWITCH)
565         else
566         {
567             handle->hw.portGroup.pseudo->PPMCR = NETC_PSEUDO_LINK_PPMCR_TXPAD(config->port.enPseudoMacTxPad);
568         }
569 #endif
570         /* Configure Port VLAN classification control, only do PSI */
571         handle->hw.base->PVCLCTR = NETC_ENETC_PVCLCTR_OAI(config->enOuterAsInner);
572         /* Configure ENETC pasue on/off threshold, only do PSI */
573         handle->hw.base->PPAUONTR  = NETC_ENETC_PPAUONTR_THRESH(config->pauseOnThr);
574         handle->hw.base->PPAUOFFTR = NETC_ENETC_PPAUOFFTR_THRESH(config->pauseOffThr);
575         /* Transmit priority to traffic class mapping, only do PSI */
576         handle->hw.base->PRIO2TCMR0 = NETC_ENETC_PRIO2TCMR0_PRIO7TC(config->txPrioToTC[7]) |
577                                       NETC_ENETC_PRIO2TCMR0_PRIO6TC(config->txPrioToTC[6]) |
578                                       NETC_ENETC_PRIO2TCMR0_PRIO5TC(config->txPrioToTC[5]) |
579                                       NETC_ENETC_PRIO2TCMR0_PRIO4TC(config->txPrioToTC[4]) |
580                                       NETC_ENETC_PRIO2TCMR0_PRIO3TC(config->txPrioToTC[3]) |
581                                       NETC_ENETC_PRIO2TCMR0_PRIO2TC(config->txPrioToTC[2]) |
582                                       NETC_ENETC_PRIO2TCMR0_PRIO1TC(config->txPrioToTC[1]) |
583                                       NETC_ENETC_PRIO2TCMR0_PRIO0TC(config->txPrioToTC[0]);
584         /* Configure ENETC L3/L4 parser, only do on PSI */
585         NETC_EnetcSetParser(handle->hw.base, &config->parserCfg);
586         /* Configure ENETC PORT native VLAN, only do on PSI */
587         NETC_EnetcPortSetNativeVLAN(handle->hw.base, &config->rxOuterVLANCfg, true);
588         NETC_EnetcPortSetNativeVLAN(handle->hw.base, &config->rxInnerVLANCfg, false);
589 
590 #if defined(FSL_FEATURE_NETC_HAS_ERRATA_051524) && FSL_FEATURE_NETC_HAS_ERRATA_051524
591         /* ERRATA051524: The Ingress Stream Identification key construction check of payload may evaluate incorrectly
592            (indicating an invalid key construction) when the frame is received from a pseudo port (internal port) bound
593            to ENETC or the switch, and maximum frame size is 1024 bytes or larger. */
594         if ((config->port.ethMac.rxMaxFrameSize >= 1024U) && NETC_PortIsPseudo(handle->hw.portGroup.port))
595         {
596             /* Check the first payload is enough. */
597             if (config->psfpCfg.kcRule[0].payload[0].pfp == 1U)
598             {
599                 return kStatus_InvalidArgument;
600             }
601         }
602 #endif
603         /* Configure ENETC PSFP, only do PSI */
604         (void)EP_RxPSFPInit(handle, &config->psfpCfg);
605         /* Configure ENETC traffic class, only do PSI */
606         for (uint32_t i = 8U; i > 0U; i--)
607         {
608             result = EP_TxTrafficClassConfig(handle, (netc_hw_tc_idx_t)(uint32_t)(i - 1U), &config->txTcCfg[(i - 1U)]);
609             if (result != kStatus_Success)
610             {
611                 return result;
612             }
613         }
614 #if !(defined(FSL_FEATURE_NETC_HAS_ERRATA_051246) && FSL_FEATURE_NETC_HAS_ERRATA_051246)
615         /* Clear Tx/Rx disable to allow traffic to flow */
616         handle->hw.portGroup.port->POR &= ~(NETC_PORT_POR_TXDIS_MASK | NETC_PORT_POR_RXDIS_MASK);
617 #else
618         if (NETC_PortIsPseudo(handle->hw.portGroup.port))
619         {
620             if (0U != (SWITCH_PCI_HDR_TYPE0->PCI_CFH_CMD & ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK))
621             {
622                 swPseudoPort->POR = porTemp;
623             }
624         }
625 #endif
626     }
627 
628     /* Set primary MAC address */
629     result = EP_SetPrimaryMacAddr(handle, macAddr);
630     if (result != kStatus_Success)
631     {
632         return result;
633     }
634 
635     /* Set the MSIX table to handle interrupts */
636     result = EP_MSIXSetEntryTable(handle, config);
637     if (result != kStatus_Success)
638     {
639         return result;
640     }
641 
642     /* Initialize station interface */
643     result = EP_SISetup(handle, siNum, config, bdrConfig);
644     if (result != kStatus_Success)
645     {
646         return result;
647     }
648 
649     /* Initialize command BD ring for NTMP access */
650     result = EP_CmdBDRInit(handle, &config->cmdBdrConfig);
651     if (result != kStatus_Success)
652     {
653         return result;
654     }
655 
656     if (siNum == 0U)
657     {
658         /* Config TGS on PSI side */
659 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_051130) && FSL_FEATURE_NETC_HAS_ERRATA_051130)
660         result = EP_TxPortTGSEnable(handle, config->port.enableTg, 0xFFU);
661 #else
662         result = EP_TxPortTGSEnable(handle, config->port.enableTg);
663 #endif
664     }
665     if (result != kStatus_Success)
666     {
667         return result;
668     }
669 
670     if (siNum == 0U)
671     {
672         result = NETC_SocPreInitVsi(&handle->hw, config->si);
673     }
674     return result;
675 }
676 
EP_Deinit(ep_handle_t * handle)677 status_t EP_Deinit(ep_handle_t *handle)
678 {
679     uint8_t siNum = getSiNum(handle->cfg.si);
680 
681     (void)EP_CmdBDRDeinit(handle);
682     NETC_EnetcEnableSI(handle->hw.base, siNum, false);
683     NETC_SIEnable(handle->hw.si, false);
684     if (!NETC_PortIsPseudo(handle->hw.portGroup.port))
685     {
686         NETC_PortEthMacGracefulStop(handle->hw.portGroup.port);
687     }
688 
689     EP_RxBufferFreeAll(handle);
690 
691     return kStatus_Success;
692 }
693 
EP_Up(ep_handle_t * handle,netc_hw_mii_speed_t speed,netc_hw_mii_duplex_t duplex)694 status_t EP_Up(ep_handle_t *handle, netc_hw_mii_speed_t speed, netc_hw_mii_duplex_t duplex)
695 {
696     status_t result = kStatus_Success;
697     uint8_t siNum   = getSiNum(handle->cfg.si);
698     netc_hw_mii_mode_t miiMode;
699 
700     if ((siNum == 0U) && (!NETC_PortIsPseudo(handle->hw.portGroup.port)))
701     {
702         miiMode = NETC_PortGetMIIMode(handle->hw.portGroup.eth);
703         result  = NETC_PortSetMII(handle->hw.portGroup.eth, miiMode, speed, duplex);
704         if (result != kStatus_Success)
705         {
706             return result;
707         }
708     }
709 
710     NETC_EnetcEnableSI(handle->hw.base, siNum, true);
711     NETC_SIEnable(handle->hw.si, true);
712 
713     return result;
714 }
715 
EP_Down(ep_handle_t * handle)716 status_t EP_Down(ep_handle_t *handle)
717 {
718     NETC_EnetcEnableSI(handle->hw.base, getSiNum(handle->cfg.si), false);
719     NETC_SIEnable(handle->hw.si, false);
720 
721     return kStatus_Success;
722 }
723 
EP_SetPrimaryMacAddr(ep_handle_t * handle,uint8_t * macAddr)724 status_t EP_SetPrimaryMacAddr(ep_handle_t *handle, uint8_t *macAddr)
725 {
726     assert(macAddr != NULL);
727 
728     uint8_t siNum = getSiNum(handle->cfg.si);
729 
730     if (siNum == 0U)
731     {
732         NETC_PortSetMacAddr(handle->hw.portGroup.port, macAddr);
733     }
734     else
735     {
736         NETC_EnetcSetSIMacAddr(handle->hw.base, siNum, macAddr);
737     }
738 
739     return kStatus_Success;
740 }
741 
EP_SendFrameCommon(ep_handle_t * handle,netc_tx_bdr_t * txBdRing,uint8_t hwRing,netc_frame_struct_t * frame,void * context,netc_tx_bd_t * txDesc,bool txCacheMaintain)742 status_t EP_SendFrameCommon(ep_handle_t *handle,
743                             netc_tx_bdr_t *txBdRing,
744                             uint8_t hwRing,
745                             netc_frame_struct_t *frame,
746                             void *context,
747                             netc_tx_bd_t *txDesc,
748                             bool txCacheMaintain)
749 {
750     assert((frame != NULL) && (frame->buffArray != NULL));
751 
752     status_t result              = kStatus_Success;
753     netc_buffer_struct_t *txBuff = frame->buffArray;
754     uint32_t totBdNum            = frame->length;
755     uint16_t frameLen            = 0;
756     bool isExtEnable             = (bool)txDesc[0].standard.isExtended;
757     uint32_t address;
758     netc_tx_bd_t *txDesTemp = NULL;
759 
760     /* Check the frame length. */
761     if ((frame->buffArray[0].length < NETC_ENETC_TXFRAME_LEN_MIN) || (frame->length == 0U))
762     {
763         result = kStatus_NETC_TxFrameOverLen;
764     }
765 
766     /* Calculate frame length and Tx data buffer number. */
767     do
768     {
769         frameLen += txBuff->length;
770         txBuff++;
771     } while (--totBdNum != 0U);
772 
773     if (isExtEnable)
774     {
775         totBdNum = (uint32_t)frame->length + 1U;
776     }
777     else
778     {
779         totBdNum = frame->length;
780     }
781 
782     /* Check the frame total length. */
783     if ((frameLen > NETC_ENETC_TXFRAME_LEN_MAX) || (frameLen < NETC_ENETC_TXFRAME_LEN_MIN))
784     {
785         result = kStatus_NETC_TxFrameOverLen;
786     }
787     /* Check whether the available BD number is enough for Tx data buffer. */
788     else if (totBdNum > EP_GetIdleTxBDNum(txBdRing))
789     {
790         result = kStatus_Busy;
791     }
792     else
793     {
794         txBuff = frame->buffArray;
795         for (uint32_t bdIndex = 0; bdIndex < totBdNum; bdIndex++)
796         {
797             /* Check the buffer address */
798             if (txBuff->buffer == NULL)
799             {
800                 return kStatus_InvalidArgument;
801             }
802 
803             if (txCacheMaintain)
804             {
805                 /* Swith API share same cache */
806                 NETC_DcacheCleanByRange((uintptr_t)(uint8_t *)txBuff->buffer, txBuff->length);
807             }
808             /* Get latest Tx BD address and clean it content. */
809             txDesTemp = &txBdRing->bdBase[txBdRing->producerIndex];
810             (void)memset(txDesTemp, 0, sizeof(netc_tx_bd_t));
811 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
812             address =
813                 (uintptr_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)(uint8_t *)txBuff->buffer, kMEMORY_Local2DMA);
814 #else
815             address = (uintptr_t)(uint32_t *)txBuff->buffer;
816 #endif
817             if (bdIndex == 0U)
818             {
819                 /* Update latest Tx dirty frame info. */
820                 txBdRing->dirtyBase[txBdRing->producerIndex].context = context;
821                 if (0U != (txDesc[0].standard.flags & NETC_SI_TXDESCRIP_RD_TSR_MASK))
822                 {
823                     txBdRing->dirtyBase[txBdRing->producerIndex].isTxTsIdAvail = true;
824                 }
825                 else
826                 {
827                     txBdRing->dirtyBase[txBdRing->producerIndex].isTxTsIdAvail = false;
828                 }
829 
830                 if (isExtEnable && (0U != (txDesc[1].ext.eFlags & (uint32_t)kNETC_TxExtTwoStepTs)))
831                 {
832                     txBdRing->dirtyBase[txBdRing->producerIndex].isTsAvail = true;
833                 }
834                 else
835                 {
836                     txBdRing->dirtyBase[txBdRing->producerIndex].isTsAvail = false;
837                 }
838                 /* Copy user Tx descriptors to hardware Tx BD. */
839                 txDesTemp->standard.flags      = txDesc[0].standard.flags;
840                 txDesTemp->standard.addr       = address;
841                 txDesTemp->standard.bufLen     = txBuff->length;
842                 txDesTemp->standard.frameLen   = frameLen;
843                 txDesTemp->standard.isExtended = (uint32_t)isExtEnable;
844                 txDesTemp->standard.enableInterrupt =
845                     (uint32_t)((handle->hw.si->BDR[hwRing].TBIER & ENETC_SI_TBIER_TXFIE_MASK) != 0U);
846                 if (isExtEnable)
847                 {
848                     /* Increase producer index when first BD is extension BD. */
849                     txBdRing->producerIndex = EP_IncreaseIndex(txBdRing->producerIndex, txBdRing->len);
850                     txDesTemp               = &txBdRing->bdBase[txBdRing->producerIndex];
851                     txDesTemp->ext          = txDesc[1].ext;
852                     bdIndex++;
853                 }
854             }
855             else
856             {
857                 txDesTemp->standard.addr   = address;
858                 txDesTemp->standard.bufLen = txBuff->length;
859             }
860 
861             /* Increase tx buffer address index and producer index. */
862             txBuff++;
863             txBdRing->producerIndex = EP_IncreaseIndex(txBdRing->producerIndex, txBdRing->len);
864         }
865 
866         /* Set final flag in last BD, same bit for stand or extension BD */
867         if (txDesTemp != NULL)
868         {
869             txDesTemp->standard.isFinal = 1;
870         }
871 
872         /* Make sure all data in the Tx BD is ready. */
873         __DSB();
874 
875         /* Active Tx. */
876         NETC_SISetTxProducer(handle->hw.si, hwRing, txBdRing->producerIndex);
877     }
878 
879     return result;
880 }
881 
EP_SendFrame(ep_handle_t * handle,uint8_t ring,netc_frame_struct_t * frame,void * context,ep_tx_opt * opt)882 status_t EP_SendFrame(ep_handle_t *handle, uint8_t ring, netc_frame_struct_t *frame, void *context, ep_tx_opt *opt)
883 {
884     assert(handle != NULL);
885     netc_tx_bd_t txDesc[2] = {0};
886     uint8_t hwRing         = ring;
887 
888     if (ring >= handle->cfg.txRingUse)
889     {
890         /* Tx BD ring index is out of range */
891         return kStatus_InvalidArgument;
892     }
893     if (NETC_EnetcHasManagement(handle->hw.base) && (getSiNum(handle->cfg.si) == 0U))
894     {
895         /* Switch management ENETC Tx BD hardware ring 0 can't be used to send regular frame, so the index need increase
896          * 1 */
897         hwRing = ring + 1U;
898     }
899 
900     if (opt != NULL)
901     {
902         if ((opt->flags & (uint32_t)kEP_TX_OPT_START_TIME) != 0U)
903         {
904             txDesc[0].standard.flags = NETC_SI_TXDESCRIP_RD_FLQ(0x2U) | NETC_SI_TXDESCRIP_RD_TSE_MASK |
905                                        NETC_SI_TXDESCRIP_RD_TXSTART(opt->timestamp);
906         }
907         if ((opt->flags & (uint32_t)kEP_TX_OPT_VLAN_INSERT) != 0U)
908         {
909             txDesc[0].standard.isExtended = 1U;
910             txDesc[1].ext.pcp             = opt->vlan.pcp;
911             txDesc[1].ext.dei             = opt->vlan.dei;
912             txDesc[1].ext.vid             = opt->vlan.vid;
913             txDesc[1].ext.tpid            = (uint16_t)opt->vlan.tpid;
914             txDesc[1].ext.eFlags          = (uint8_t)kNETC_TxExtVlanInsert;
915         }
916         if ((opt->flags & (uint32_t)kEP_TX_OPT_REQ_TS) != 0U)
917         {
918             txDesc[0].standard.isExtended = 1U;
919             txDesc[1].ext.eFlags |= (uint8_t)kNETC_TxExtTwoStepTs;
920         }
921 #if !(defined(FSL_FEATURE_NETC_HAS_ERRATA_051255) && FSL_FEATURE_NETC_HAS_ERRATA_051255)
922         if ((opt->flags & (uint32_t)kEP_TX_OPT_REQ_ONE_STEP_TS) != 0U)
923         {
924             txDesc[0].standard.isExtended = 1U;
925             txDesc[1].ext.eFlags |= (uint8_t)kNETC_TxExtOneStepTs;
926         }
927 #endif
928     }
929     return EP_SendFrameCommon(handle, &handle->txBdRing[ring], hwRing, frame, context, &txDesc[0],
930                               handle->cfg.txCacheMaintain);
931 }
932 
EP_ReclaimTxDescCommon(ep_handle_t * handle,netc_tx_bdr_t * txBdRing,uint8_t hwRing,bool enCallback)933 netc_tx_frame_info_t *EP_ReclaimTxDescCommon(ep_handle_t *handle,
934                                              netc_tx_bdr_t *txBdRing,
935                                              uint8_t hwRing,
936                                              bool enCallback)
937 {
938     netc_tx_frame_info_t *frameInfo = NULL;
939     netc_tx_bd_t *txDesc;
940     uint16_t cleanNum;
941     uint16_t consumer = NETC_SIGetTxConsumer(handle->hw.si, hwRing);
942 
943     /* Get the dirty Tx BD number ready for reclaiming in the ring */
944     if (consumer >= txBdRing->cleanIndex)
945     {
946         cleanNum = (consumer - txBdRing->cleanIndex);
947     }
948     else
949     {
950         cleanNum = (uint16_t)(txBdRing->len - txBdRing->cleanIndex + consumer);
951     }
952 
953     while (cleanNum-- != 0U)
954     {
955         /* When callback enable, get the reclaim information. */
956         if (enCallback)
957         {
958             txDesc = &txBdRing->bdBase[txBdRing->cleanIndex];
959 
960             /* Valid Tx frame information is in the first BD of one BD chain. */
961             if (txDesc->writeback.written != 0U)
962             {
963                 /* When reclaim callback is enabled, never process more than one full frame */
964                 if (NULL != frameInfo)
965                 {
966                     break;
967                 }
968 
969                 frameInfo = &txBdRing->dirtyBase[txBdRing->cleanIndex];
970                 if (frameInfo->isTsAvail)
971                 {
972                     frameInfo->timestamp = txDesc->writeback.timestamp;
973                 }
974                 if (frameInfo->isTxTsIdAvail)
975                 {
976                     frameInfo->txtsid = (uint16_t)txDesc->writeback.txtsid;
977                 }
978                 frameInfo->status = (netc_ep_tx_status_t)txDesc->writeback.status;
979             }
980             else if (txDesc->standard.frameLen != 0U)
981             {
982                 /* When reclaim callback is enabled, never process more than one full frame */
983                 if (NULL != frameInfo)
984                 {
985                     break;
986                 }
987 
988                 frameInfo         = &txBdRing->dirtyBase[txBdRing->cleanIndex];
989                 frameInfo->status = kNETC_EPTxSuccess;
990             }
991             else
992             {
993                 /* Intentional empty */
994             }
995         }
996 
997         /* Update the clean index to free BD resource. */
998         txBdRing->cleanIndex = EP_IncreaseIndex(txBdRing->cleanIndex, txBdRing->len);
999 
1000         if (cleanNum == 0U)
1001         {
1002             consumer = NETC_SIGetTxConsumer(handle->hw.si, hwRing);
1003             /* Get the dirty Tx BD number again */
1004             if (consumer >= txBdRing->cleanIndex)
1005             {
1006                 cleanNum = (consumer - txBdRing->cleanIndex);
1007             }
1008             else
1009             {
1010                 cleanNum = (uint16_t)(txBdRing->len - txBdRing->cleanIndex + consumer);
1011             }
1012         }
1013     }
1014     return frameInfo;
1015 }
1016 
EP_ReclaimTxDescriptor(ep_handle_t * handle,uint8_t ring)1017 void EP_ReclaimTxDescriptor(ep_handle_t *handle, uint8_t ring)
1018 {
1019     assert(ring < handle->cfg.txRingUse);
1020     netc_tx_frame_info_t *frameInfo;
1021     uint8_t hwRing = ring;
1022 
1023     if (NETC_EnetcHasManagement(handle->hw.base) && (getSiNum(handle->cfg.si) == 0U))
1024     {
1025         /* Switch management ENETC Tx BD hardware ring 0 can't be used to send regular frame, so the index need increase
1026          * 1 */
1027         hwRing = ring + 1U;
1028     }
1029 
1030     do
1031     {
1032         frameInfo =
1033             EP_ReclaimTxDescCommon(handle, &handle->txBdRing[ring], hwRing, (handle->cfg.reclaimCallback != NULL));
1034         /* If reclaim callback is enabled, it must be called for each full frame. */
1035         if (frameInfo != NULL)
1036         {
1037             (void)handle->cfg.reclaimCallback(handle, ring, frameInfo, handle->cfg.userData);
1038             (void)memset(frameInfo, 0, sizeof(netc_tx_frame_info_t));
1039         }
1040     } while (frameInfo != NULL);
1041 }
1042 
EP_GetRxFrameSizeCommon(ep_handle_t * handle,netc_rx_bdr_t * rxBdRing,uint32_t * length)1043 status_t EP_GetRxFrameSizeCommon(ep_handle_t *handle, netc_rx_bdr_t *rxBdRing, uint32_t *length)
1044 {
1045     status_t result      = kStatus_NETC_RxHRZeroFrame;
1046     netc_rx_bd_t *rxDesc = &rxBdRing->bdBase[rxBdRing->index];
1047     uint16_t index       = rxBdRing->index;
1048     uint32_t totlen      = 0;
1049 
1050     /* Reset the length to zero. */
1051     *length = 0;
1052 
1053     /* Check the current buffer descriptor's ready flag. The flag in first BD indicates entire frame ready status. */
1054     if (rxDesc->writeback.isReady == 0U)
1055     {
1056         result = kStatus_NETC_RxFrameEmpty;
1057     }
1058     else
1059     {
1060         /* Check the status of the received frame. */
1061         if (rxDesc->writeback.error != 0U)
1062         {
1063             result = kStatus_NETC_RxFrameError;
1064         }
1065         else if ((netc_host_reason_t)rxDesc->writeback.hr != kNETC_TimestampResp)
1066         {
1067             if ((netc_host_reason_t)rxDesc->writeback.hr != kNETC_RegularFrame)
1068             {
1069                 result = kStatus_NETC_RxHRNotZeroFrame;
1070             }
1071             else
1072             {
1073                 result = kStatus_NETC_RxHRZeroFrame;
1074             }
1075             do
1076             {
1077                 /* Check abnormal case. */
1078                 if (rxDesc->writeback.bufLen == 0U)
1079                 {
1080                     result = kStatus_NETC_RxFrameError;
1081                     break;
1082                 }
1083                 totlen += rxDesc->writeback.bufLen;
1084 
1085                 /* Find the last buffer descriptor. */
1086                 if (rxDesc->writeback.isFinal != 0U)
1087                 {
1088                     *length = totlen;
1089                     break;
1090                 }
1091 
1092                 /* Extended BD needs additional offset. */
1093                 if (rxBdRing->extendDesc)
1094                 {
1095                     index = EP_IncreaseIndex(index, rxBdRing->len);
1096                 }
1097 
1098                 /* Increase to next buffer descriptor. */
1099                 index  = EP_IncreaseIndex(index, rxBdRing->len);
1100                 rxDesc = &rxBdRing->bdBase[index];
1101             } while (index != rxBdRing->index);
1102         }
1103         else
1104         {
1105             /* Get Transmit Timestamp Reference Response messages */
1106             result = kStatus_NETC_RxTsrResp;
1107         }
1108     }
1109     return result;
1110 }
1111 
EP_GetRxFrameSize(ep_handle_t * handle,uint8_t ring,uint32_t * length)1112 status_t EP_GetRxFrameSize(ep_handle_t *handle, uint8_t ring, uint32_t *length)
1113 {
1114     assert((handle != NULL) && (length != NULL));
1115     status_t result;
1116     if (ring >= handle->cfg.rxRingUse)
1117     {
1118         /* Rx BD ring index is out of range */
1119         return kStatus_InvalidArgument;
1120     }
1121     else
1122     {
1123         result = EP_GetRxFrameSizeCommon(handle, &handle->rxBdRing[ring], length);
1124         if (kStatus_NETC_RxHRZeroFrame == result)
1125         {
1126             /* Only return success when currently frame is regular frame */
1127             result = kStatus_Success;
1128         }
1129         return result;
1130     }
1131 }
1132 
EP_GetRxFrameAttribute(ep_handle_t * handle,netc_rx_bd_t * rxDesc,netc_frame_attr_t * attr)1133 static void EP_GetRxFrameAttribute(ep_handle_t *handle, netc_rx_bd_t *rxDesc, netc_frame_attr_t *attr)
1134 {
1135     bool isPseudoPort = NETC_PortIsPseudo(handle->hw.portGroup.port);
1136 
1137     (void)memset(attr, 0, sizeof(netc_frame_attr_t));
1138 
1139     attr->parserSummary = rxDesc->writeback.parserSummary;
1140     attr->hostReason    = (netc_host_reason_t)rxDesc->writeback.hr;
1141 
1142     if (isPseudoPort)
1143     {
1144         attr->srcPort = (uint8_t)rxDesc->writeback.srcPort;
1145     }
1146     if ((rxDesc->writeback.flags & (uint8_t)kEP_RX_RSS_VALID) != 0U)
1147     {
1148         attr->isRssHashValid = true;
1149         attr->rssHash        = isPseudoPort ? rxDesc->writeback.rssHash : rxDesc->writeback.rssHashSwt;
1150     }
1151     if ((rxDesc->writeback.flags & (uint8_t)kEP_RX_VLAN_VALID) != 0U)
1152     {
1153         attr->isVlanExtracted = true;
1154         attr->vlan.vid        = rxDesc->writeback.vid;
1155         attr->vlan.dei        = rxDesc->writeback.dei;
1156         attr->vlan.pcp        = rxDesc->writeback.pcp;
1157         attr->vlan.tpid       = rxDesc->writeback.tpid;
1158     }
1159     if ((rxDesc->writeback.flags & (uint8_t)kEP_RX_TIMESTAMP_VALID) != 0U)
1160     {
1161         attr->isTsAvail = true;
1162     }
1163 }
1164 
EP_DropFrame(ep_handle_t * handle,netc_rx_bdr_t * rxBdRing,uint8_t ring)1165 void EP_DropFrame(ep_handle_t *handle, netc_rx_bdr_t *rxBdRing, uint8_t ring)
1166 {
1167     netc_rx_bd_t *rxDesc;
1168     uint64_t rxDmaBuff;
1169     uint16_t index;
1170     bool isLastBd;
1171 
1172     /* Drop frame through updating BD status. */
1173     do
1174     {
1175         rxDesc    = &rxBdRing->bdBase[rxBdRing->index];
1176         index     = rxBdRing->extendDesc ? (rxBdRing->index / 2U) : rxBdRing->index;
1177         rxDmaBuff = rxBdRing->buffArray[index];
1178 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1179         rxDmaBuff = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)rxDmaBuff, kMEMORY_Local2DMA);
1180 #endif
1181         rxDesc->standard.addr = rxDmaBuff;
1182 
1183         /* Store last BD flag before it's cleared. */
1184         isLastBd = (rxDesc->writeback.isFinal != 0U) ? true : false;
1185 
1186         /* Update the receive buffer descriptors. */
1187         rxDesc->writeback.isFinal = 0;
1188         rxDesc->writeback.isReady = 0;
1189 
1190         if (rxBdRing->extendDesc)
1191         {
1192             /* Skip 16-bytes extended BD space. */
1193             rxBdRing->index = EP_IncreaseIndex(rxBdRing->index, rxBdRing->len);
1194         }
1195         rxBdRing->index = EP_IncreaseIndex(rxBdRing->index, rxBdRing->len);
1196     } while (!isLastBd);
1197 
1198     /* Update the Rx consumer index to free idle BD. */
1199     index = rxBdRing->extendDesc ? (rxBdRing->index / 2U) : rxBdRing->index;
1200     NETC_SISetRxConsumer(handle->hw.si, ring, index);
1201 }
1202 
EP_ReceiveFrameCopyCommon(ep_handle_t * handle,netc_rx_bdr_t * rxBdRing,uint8_t ring,void * buffer,uint32_t length,netc_frame_attr_t * attr,bool rxCacheMaintain)1203 status_t EP_ReceiveFrameCopyCommon(ep_handle_t *handle,
1204                                    netc_rx_bdr_t *rxBdRing,
1205                                    uint8_t ring,
1206                                    void *buffer,
1207                                    uint32_t length,
1208                                    netc_frame_attr_t *attr,
1209                                    bool rxCacheMaintain)
1210 {
1211     uint32_t leftLen = length;
1212     bool isTsBd      = true;
1213     uintptr_t offset = 0;
1214     netc_rx_bd_t *rxDesc;
1215     uint64_t rxDmaBuff;
1216     uint16_t copyLen;
1217     uintptr_t data;
1218     uint16_t index;
1219     bool isLastBd;
1220 
1221     /* For data-NULL input, drop the frame. */
1222     if (buffer == NULL)
1223     {
1224         EP_DropFrame(handle, rxBdRing, ring);
1225     }
1226     else
1227     {
1228         rxDesc = &rxBdRing->bdBase[rxBdRing->index];
1229 
1230         /* Get the Rx frame information from first BD. */
1231         if (attr != NULL)
1232         {
1233             EP_GetRxFrameAttribute(handle, rxDesc, attr);
1234         }
1235 
1236         do
1237         {
1238             /* Copy scattered buffers to contiguous application memory. */
1239             if (leftLen != 0U)
1240             {
1241                 /* Get the destination buffer address which NETC DMA copy frames to. */
1242                 rxDmaBuff = rxBdRing->extendDesc ? rxBdRing->buffArray[rxBdRing->index / 2U] :
1243                                                    rxBdRing->buffArray[rxBdRing->index];
1244                 if (rxCacheMaintain)
1245                 {
1246                     /* Invalidate cache before copy. */
1247                     NETC_DcacheInvalidateByRange((uintptr_t)rxDmaBuff, rxBdRing->buffSize);
1248                 }
1249 
1250                 data    = (uintptr_t)(uint8_t *)buffer + offset;
1251                 copyLen = (leftLen > rxDesc->writeback.bufLen) ? rxDesc->writeback.bufLen : (uint16_t)leftLen;
1252                 (void)memcpy((void *)(uint8_t *)data, (void *)(uint8_t *)(uintptr_t)rxDmaBuff, copyLen);
1253                 offset += copyLen;
1254                 leftLen -= copyLen;
1255             }
1256 
1257             /* Set the Rx buffer address in BD which is overwritten by BD writeback. */
1258             index     = rxBdRing->extendDesc ? (rxBdRing->index / 2U) : rxBdRing->index;
1259             rxDmaBuff = rxBdRing->buffArray[index];
1260 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1261             rxDmaBuff = (uintptr_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)rxDmaBuff, kMEMORY_Local2DMA);
1262 #endif
1263             rxDesc->standard.addr = rxDmaBuff;
1264 
1265             /* The last buffer descriptor flag of one frame. */
1266             isLastBd = (rxDesc->writeback.isFinal != 0U) ? true : false;
1267 
1268             /* Updates the receive buffer descriptors. */
1269             rxDesc->writeback.isFinal = 0;
1270             rxDesc->writeback.isReady = 0;
1271 
1272             if (rxBdRing->extendDesc)
1273             {
1274                 /* Extended BD occupies one more 16 bytes space. */
1275                 rxBdRing->index = EP_IncreaseIndex(rxBdRing->index, rxBdRing->len);
1276 
1277                 /* Get the timestamp from extended BD if it's valid. */
1278                 if ((attr != NULL) && isTsBd && attr->isTsAvail)
1279                 {
1280                     /* Only first extended BD takes timestamp. */
1281                     rxDesc          = &rxBdRing->bdBase[rxBdRing->index];
1282                     attr->timestamp = rxDesc->ext.timestamp;
1283                     isTsBd          = false;
1284                 }
1285             }
1286 
1287             /* Get the latest buffer descriptor. */
1288             rxBdRing->index = EP_IncreaseIndex(rxBdRing->index, rxBdRing->len);
1289             rxDesc          = &rxBdRing->bdBase[rxBdRing->index];
1290         } while (!isLastBd);
1291 
1292         /* Update the Rx consumer index to free BD whose data is taken away. */
1293         index = rxBdRing->extendDesc ? (rxBdRing->index / 2U) : rxBdRing->index;
1294         NETC_SISetRxConsumer(handle->hw.si, ring, index);
1295     }
1296 
1297     return kStatus_Success;
1298 }
1299 
EP_ReceiveFrameCopy(ep_handle_t * handle,uint8_t ring,void * buffer,uint32_t length,netc_frame_attr_t * attr)1300 status_t EP_ReceiveFrameCopy(ep_handle_t *handle, uint8_t ring, void *buffer, uint32_t length, netc_frame_attr_t *attr)
1301 {
1302     assert((handle != NULL) && (((buffer != NULL) && (length != 0U)) || (buffer == NULL)));
1303     if (ring >= handle->cfg.rxRingUse)
1304     {
1305         /* Rx BD ring index is out of range */
1306         return kStatus_InvalidArgument;
1307     }
1308     else
1309     {
1310         return EP_ReceiveFrameCopyCommon(handle, &handle->rxBdRing[ring], ring, buffer, length, attr,
1311                                          handle->cfg.rxCacheMaintain);
1312     }
1313 }
1314 
EP_ReceiveFrameCommon(ep_handle_t * handle,netc_rx_bdr_t * rxBdRing,uint8_t ring,netc_frame_struct_t * frame,netc_frame_attr_t * attr,bool rxCacheMaintain)1315 status_t EP_ReceiveFrameCommon(ep_handle_t *handle,
1316                                netc_rx_bdr_t *rxBdRing,
1317                                uint8_t ring,
1318                                netc_frame_struct_t *frame,
1319                                netc_frame_attr_t *attr,
1320                                bool rxCacheMaintain)
1321 {
1322     status_t result      = kStatus_Success;
1323     netc_rx_bd_t *rxDesc = &rxBdRing->bdBase[rxBdRing->index];
1324     bool isTsBd          = true;
1325     uint64_t rxDmaBuff;
1326     uint16_t buffIdx;
1327     uint16_t index;
1328     void *newBuff;
1329     bool isLastBd;
1330 
1331     /* Get the Rx frame information from first BD */
1332     rxDesc = &rxBdRing->bdBase[rxBdRing->index];
1333     if (attr != NULL)
1334     {
1335         EP_GetRxFrameAttribute(handle, rxDesc, attr);
1336     }
1337 
1338     index = 0;
1339     do
1340     {
1341         buffIdx = rxBdRing->extendDesc ? (rxBdRing->index / 2U) : rxBdRing->index;
1342 
1343         /* Get the destination buffer address which NETC DMA copy frames to. */
1344         rxDmaBuff = rxBdRing->buffArray[buffIdx];
1345 
1346         if (rxCacheMaintain)
1347         {
1348             NETC_DcacheInvalidateByRange((uintptr_t)rxDmaBuff, rxBdRing->buffSize);
1349         }
1350 
1351         newBuff                        = frame->buffArray[index].buffer;
1352         frame->buffArray[index].buffer = (void *)(uint8_t *)(uintptr_t)rxDmaBuff;
1353         frame->buffArray[index].length = rxDesc->writeback.bufLen;
1354         index++;
1355 
1356         /* Update the buffer address array. */
1357         rxBdRing->buffArray[buffIdx] = (uint64_t)(uintptr_t)(uint8_t *)newBuff;
1358 
1359         rxDmaBuff = (uint64_t)(uintptr_t)(uint8_t *)newBuff;
1360 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1361         rxDmaBuff = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)rxDmaBuff, kMEMORY_Local2DMA);
1362 #endif
1363         rxDesc->standard.addr = rxDmaBuff;
1364 
1365         /* The last buffer descriptor of one frame. */
1366         isLastBd = (rxDesc->writeback.isFinal != 0U) ? true : false;
1367 
1368         /* Updates the receive buffer descriptors. */
1369         rxDesc->writeback.isFinal = 0;
1370         rxDesc->writeback.isReady = 0;
1371 
1372         if (rxBdRing->extendDesc)
1373         {
1374             /* Extended BD occupies one more 16 bytes space. */
1375             rxBdRing->index = EP_IncreaseIndex(rxBdRing->index, rxBdRing->len);
1376 
1377             /* Get the timestamp from extended BD if it's valid. */
1378             if ((attr != NULL) && isTsBd && attr->isTsAvail)
1379             {
1380                 /* Only first extended BD takes timestamp. */
1381                 rxDesc          = &rxBdRing->bdBase[rxBdRing->index];
1382                 attr->timestamp = rxDesc->ext.timestamp;
1383                 isTsBd          = false;
1384             }
1385         }
1386 
1387         /* Get the latest buffer descriptor. */
1388         rxBdRing->index = EP_IncreaseIndex(rxBdRing->index, rxBdRing->len);
1389         rxDesc          = &rxBdRing->bdBase[rxBdRing->index];
1390     } while (!isLastBd);
1391 
1392     /* Get the Rx buffer array length. */
1393     frame->length = index;
1394 
1395     /* Update the Rx consumer index to free idle BD */
1396     index = rxBdRing->extendDesc ? (rxBdRing->index / 2U) : rxBdRing->index;
1397     NETC_SISetRxConsumer(handle->hw.si, ring, index);
1398 
1399     return result;
1400 }
1401 
EP_ReceiveFrame(ep_handle_t * handle,uint8_t ring,netc_frame_struct_t * frame,netc_frame_attr_t * attr)1402 status_t EP_ReceiveFrame(ep_handle_t *handle, uint8_t ring, netc_frame_struct_t *frame, netc_frame_attr_t *attr)
1403 {
1404     assert((handle != NULL) && (frame != NULL) && (handle->cfg.rxZeroCopy));
1405 
1406     status_t result         = kStatus_Success;
1407     netc_rx_bdr_t *rxBdRing = NULL;
1408     netc_rx_bd_t *rxDesc    = NULL;
1409     uint32_t buffNum        = 0;
1410     uint16_t index;
1411     void *newBuff;
1412 
1413     if (ring >= handle->cfg.rxRingUse)
1414     {
1415         /* Rx BD ring index is out of range. */
1416         return kStatus_InvalidArgument;
1417     }
1418     rxBdRing = &handle->rxBdRing[ring];
1419     rxDesc   = &rxBdRing->bdBase[rxBdRing->index];
1420 
1421     /* Check the current buffer descriptor's ready flag. The flag in first BD indicates entire frame ready status. */
1422     if (rxDesc->writeback.isReady == 0U)
1423     {
1424         /* Reset the buffer array length. */
1425         frame->length = 0;
1426         return kStatus_NETC_RxFrameEmpty;
1427     }
1428     else
1429     {
1430         /* Check the status of the received frame. */
1431         if (rxDesc->writeback.error != 0U)
1432         {
1433             result = kStatus_NETC_RxFrameError;
1434         }
1435         else if ((netc_host_reason_t)rxDesc->writeback.hr == kNETC_TimestampResp)
1436         {
1437             /* Get Transmit Timestamp Reference Response messages, use special API to receive this information. */
1438             return kStatus_NETC_RxTsrResp;
1439         }
1440         else
1441         {
1442             if ((netc_host_reason_t)rxDesc->writeback.hr != kNETC_RegularFrame)
1443             {
1444                 /* Return without receive when currently frame is not regular frame */
1445                 return kStatus_NETC_RxHRNotZeroFrame;
1446             }
1447             /* Check how many buffers will be taken away to receive one frame. */
1448             index = rxBdRing->index;
1449             do
1450             {
1451                 buffNum++;
1452 
1453                 /* Find the last BD of this frame. */
1454                 if (rxDesc->writeback.isFinal != 0U)
1455                 {
1456                     break;
1457                 }
1458 
1459                 if (rxBdRing->extendDesc)
1460                 {
1461                     /* Extended BD needs additional offset. */
1462                     index = EP_IncreaseIndex(index, rxBdRing->len);
1463                 }
1464                 index  = EP_IncreaseIndex(index, rxBdRing->len);
1465                 rxDesc = &rxBdRing->bdBase[index];
1466             } while (index != rxBdRing->index);
1467 
1468             /* The buffer array length provided by application is not enough to receive frame. */
1469             if (buffNum > frame->length)
1470             {
1471                 return kStatus_NETC_LackOfResource;
1472             }
1473 
1474             /* Prepare the buffer from appliction to exchange with the buffer in the BD. */
1475             index = 0;
1476             do
1477             {
1478                 newBuff = handle->cfg.rxBuffAlloc(handle, ring, rxBdRing->buffSize, handle->cfg.userData);
1479                 if (newBuff == NULL)
1480                 {
1481                     while (index-- > 0U)
1482                     {
1483                         handle->cfg.rxBuffFree(handle, ring, frame->buffArray[index].buffer, handle->cfg.userData);
1484                     }
1485                     /* When appliction buffer pool is not enough, drop frame in the BD to keep frame latest. */
1486                     result = kStatus_NETC_LackOfResource;
1487                     break;
1488                 }
1489 
1490                 /* Store in this strcuture, and exchange the buffer in the BD in below code. */
1491                 frame->buffArray[index].buffer = newBuff;
1492                 index++;
1493             } while (--buffNum != 0U);
1494         }
1495     }
1496 
1497     if (result != kStatus_Success)
1498     {
1499         frame->length = 0;
1500         EP_DropFrame(handle, rxBdRing, ring);
1501         return result;
1502     }
1503 
1504     return EP_ReceiveFrameCommon(handle, rxBdRing, ring, frame, attr, handle->cfg.rxCacheMaintain);
1505 }
1506 
EP_CmdBDRInit(ep_handle_t * handle,const netc_cmd_bdr_config_t * config)1507 status_t EP_CmdBDRInit(ep_handle_t *handle, const netc_cmd_bdr_config_t *config)
1508 {
1509     assert(handle != NULL);
1510 
1511     status_t result;
1512 
1513     result = NETC_CmdBDRInit((netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR, config);
1514     if (result != kStatus_Success)
1515     {
1516         return result;
1517     }
1518 
1519     handle->cmdBdRing.bdBase        = config->bdBase;
1520     handle->cmdBdRing.bdLength      = config->bdLength;
1521     handle->cmdBdRing.producerIndex = 0U;
1522     handle->cmdBdRing.cleanIndex    = 0U;
1523     handle->cmdBdRing.bdrEnable     = true;
1524 
1525     return result;
1526 }
1527 
EP_CmdBDRDeinit(ep_handle_t * handle)1528 status_t EP_CmdBDRDeinit(ep_handle_t *handle)
1529 {
1530     assert(handle != NULL);
1531     return NETC_CmdBDRDeinit((netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR);
1532 }
1533 
EP_RxIPFInit(ep_handle_t * handle,netc_ep_ipf_config_t * config)1534 status_t EP_RxIPFInit(ep_handle_t *handle, netc_ep_ipf_config_t *config)
1535 {
1536     NETC_IPFInit(handle->hw.common, &config->dosCfg);
1537     NETC_PortSetIPF(handle->hw.portGroup.port, &config->portConfig);
1538 
1539     return kStatus_Success;
1540 }
1541 
EP_RxIPFAddTableEntry(ep_handle_t * handle,netc_tb_ipf_config_t * config,uint32_t * entryID)1542 status_t EP_RxIPFAddTableEntry(ep_handle_t *handle, netc_tb_ipf_config_t *config, uint32_t *entryID)
1543 {
1544     assert((handle != NULL) && (config != NULL));
1545     netc_cbdr_handle_t cdbrHandle;
1546 
1547     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1548     cdbrHandle.cmdr   = &handle->cmdBdRing;
1549     cdbrHandle.buffer = &s_cmdData;
1550     return NETC_AddIPFTableEntry(&cdbrHandle, config, entryID);
1551 }
1552 
EP_RxIPFUpdateTableEntry(ep_handle_t * handle,uint32_t entryID,netc_tb_ipf_cfge_t * cfg)1553 status_t EP_RxIPFUpdateTableEntry(ep_handle_t *handle, uint32_t entryID, netc_tb_ipf_cfge_t *cfg)
1554 {
1555     assert((handle != NULL) && (cfg != NULL));
1556     netc_cbdr_handle_t cdbrHandle;
1557 
1558     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1559     cdbrHandle.cmdr   = &handle->cmdBdRing;
1560     cdbrHandle.buffer = &s_cmdData;
1561     return NETC_UpdateIPFTableEntry(&cdbrHandle, entryID, cfg);
1562 }
1563 
EP_RxIPFDelTableEntry(ep_handle_t * handle,uint32_t entryID)1564 status_t EP_RxIPFDelTableEntry(ep_handle_t *handle, uint32_t entryID)
1565 {
1566     assert(handle != NULL);
1567     netc_cbdr_handle_t cdbrHandle;
1568 
1569     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1570     cdbrHandle.cmdr   = &handle->cmdBdRing;
1571     cdbrHandle.buffer = &s_cmdData;
1572     return NETC_DelIPFTableEntry(&cdbrHandle, entryID);
1573 }
1574 
EP_RxIPFResetMatchCounter(ep_handle_t * handle,uint32_t entryID)1575 status_t EP_RxIPFResetMatchCounter(ep_handle_t *handle, uint32_t entryID)
1576 {
1577     assert(handle != NULL);
1578     netc_cbdr_handle_t cdbrHandle;
1579 
1580     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1581     cdbrHandle.cmdr   = &handle->cmdBdRing;
1582     cdbrHandle.buffer = &s_cmdData;
1583     return NETC_ResetIPFMatchCounter(&cdbrHandle, entryID);
1584 }
1585 
EP_RxIPFGetMatchedCount(ep_handle_t * handle,uint32_t entryID,uint64_t * count)1586 status_t EP_RxIPFGetMatchedCount(ep_handle_t *handle, uint32_t entryID, uint64_t *count)
1587 {
1588     assert(handle != NULL);
1589     netc_cbdr_handle_t cdbrHandle;
1590 
1591     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1592     cdbrHandle.cmdr   = &handle->cmdBdRing;
1593     cdbrHandle.buffer = &s_cmdData;
1594     return NETC_GetIPFMatchedCount(&cdbrHandle, entryID, count);
1595 }
1596 
EP_RxPSFPAddSGITableEntry(ep_handle_t * handle,netc_tb_sgi_config_t * config)1597 status_t EP_RxPSFPAddSGITableEntry(ep_handle_t *handle, netc_tb_sgi_config_t *config)
1598 {
1599     assert((handle != NULL) && (config != NULL));
1600     netc_cbdr_handle_t cdbrHandle;
1601 
1602     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1603     cdbrHandle.cmdr   = &handle->cmdBdRing;
1604     cdbrHandle.buffer = &s_cmdData;
1605     return NETC_AddOrUpdateSGITableEntry(&cdbrHandle, config, true);
1606 }
1607 
EP_RxPSFPUpdateSGITableEntry(ep_handle_t * handle,netc_tb_sgi_config_t * config)1608 status_t EP_RxPSFPUpdateSGITableEntry(ep_handle_t *handle, netc_tb_sgi_config_t *config)
1609 {
1610     assert((handle != NULL) && (config != NULL));
1611     netc_cbdr_handle_t cdbrHandle;
1612 
1613     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1614     cdbrHandle.cmdr   = &handle->cmdBdRing;
1615     cdbrHandle.buffer = &s_cmdData;
1616     return NETC_AddOrUpdateSGITableEntry(&cdbrHandle, config, false);
1617 }
1618 
EP_RxPSFPDelSGITableEntry(ep_handle_t * handle,uint32_t entryID)1619 status_t EP_RxPSFPDelSGITableEntry(ep_handle_t *handle, uint32_t entryID)
1620 {
1621     assert(handle != NULL);
1622     netc_cbdr_handle_t cdbrHandle;
1623 
1624     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1625     cdbrHandle.cmdr   = &handle->cmdBdRing;
1626     cdbrHandle.buffer = &s_cmdData;
1627     return NETC_DelSGITableEntry(&cdbrHandle, entryID);
1628 }
1629 
EP_RxPSFPGetSGIState(ep_handle_t * handle,uint32_t entryID,netc_tb_sgi_sgise_t * state)1630 status_t EP_RxPSFPGetSGIState(ep_handle_t *handle, uint32_t entryID, netc_tb_sgi_sgise_t *state)
1631 {
1632     assert((handle != NULL) && (state != NULL));
1633     netc_cbdr_handle_t cdbrHandle;
1634 
1635     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1636     cdbrHandle.cmdr   = &handle->cmdBdRing;
1637     cdbrHandle.buffer = &s_cmdData;
1638     return NETC_GetSGIState(&cdbrHandle, entryID, state);
1639 }
1640 
EP_RxPSFPAddSGCLTableEntry(ep_handle_t * handle,netc_tb_sgcl_gcl_t * config)1641 status_t EP_RxPSFPAddSGCLTableEntry(ep_handle_t *handle, netc_tb_sgcl_gcl_t *config)
1642 {
1643     assert((handle != NULL) && (config != NULL));
1644     netc_cbdr_handle_t cdbrHandle;
1645 
1646     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1647     cdbrHandle.cmdr   = &handle->cmdBdRing;
1648     cdbrHandle.buffer = &s_cmdData;
1649     return NETC_AddSGCLTableEntry(&cdbrHandle, config);
1650 }
1651 
EP_RxPSFPDelSGCLTableEntry(ep_handle_t * handle,uint32_t entryID)1652 status_t EP_RxPSFPDelSGCLTableEntry(ep_handle_t *handle, uint32_t entryID)
1653 {
1654     assert(handle != NULL);
1655     netc_cbdr_handle_t cdbrHandle;
1656 
1657     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1658     cdbrHandle.cmdr   = &handle->cmdBdRing;
1659     cdbrHandle.buffer = &s_cmdData;
1660     return NETC_DelSGCLTableEntry(&cdbrHandle, entryID);
1661 }
1662 
EP_RxPSFPGetSGCLGateList(ep_handle_t * handle,netc_tb_sgcl_gcl_t * gcl,uint32_t length)1663 status_t EP_RxPSFPGetSGCLGateList(ep_handle_t *handle, netc_tb_sgcl_gcl_t *gcl, uint32_t length)
1664 {
1665     assert((handle != NULL) && (gcl != NULL));
1666     netc_cbdr_handle_t cdbrHandle;
1667 
1668     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1669     cdbrHandle.cmdr   = &handle->cmdBdRing;
1670     cdbrHandle.buffer = &s_cmdData;
1671     return NETC_GetSGCLGateList(&cdbrHandle, gcl, length);
1672 }
1673 
EP_RxPSFPGetSGCLState(ep_handle_t * handle,uint32_t entryID,netc_tb_sgcl_sgclse_t * state)1674 status_t EP_RxPSFPGetSGCLState(ep_handle_t *handle, uint32_t entryID, netc_tb_sgcl_sgclse_t *state)
1675 {
1676     assert((handle != NULL) && (state != NULL));
1677     netc_cbdr_handle_t cdbrHandle;
1678 
1679     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1680     cdbrHandle.cmdr   = &handle->cmdBdRing;
1681     cdbrHandle.buffer = &s_cmdData;
1682     return NETC_GetSGCLState(&cdbrHandle, entryID, state);
1683 }
1684 
EP_RxPSFPAddRPTableEntry(ep_handle_t * handle,netc_tb_rp_config_t * config)1685 status_t EP_RxPSFPAddRPTableEntry(ep_handle_t *handle, netc_tb_rp_config_t *config)
1686 {
1687     assert((handle != NULL) && (config != NULL));
1688     netc_cbdr_handle_t cdbrHandle;
1689 
1690     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1691     cdbrHandle.cmdr   = &handle->cmdBdRing;
1692     cdbrHandle.buffer = &s_cmdData;
1693     return NETC_AddOrUpdateRPTableEntry(&cdbrHandle, config, kNETC_AddEntry);
1694 }
1695 
EP_RxPSFPUpdateRPTableEntry(ep_handle_t * handle,netc_tb_rp_config_t * config)1696 status_t EP_RxPSFPUpdateRPTableEntry(ep_handle_t *handle, netc_tb_rp_config_t *config)
1697 {
1698     assert((handle != NULL) && (config != NULL));
1699     netc_cbdr_handle_t cdbrHandle;
1700 
1701     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1702     cdbrHandle.cmdr   = &handle->cmdBdRing;
1703     cdbrHandle.buffer = &s_cmdData;
1704     return NETC_AddOrUpdateRPTableEntry(&cdbrHandle, config, kNETC_UpdateEntry);
1705 }
1706 
EP_RxPSFPAddOrUpdateRPTableEntry(ep_handle_t * handle,netc_tb_rp_config_t * config)1707 status_t EP_RxPSFPAddOrUpdateRPTableEntry(ep_handle_t *handle, netc_tb_rp_config_t *config)
1708 {
1709     assert((handle != NULL) && (config != NULL));
1710     netc_cbdr_handle_t cdbrHandle;
1711 
1712     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1713     cdbrHandle.cmdr   = &handle->cmdBdRing;
1714     cdbrHandle.buffer = &s_cmdData;
1715     return NETC_AddOrUpdateRPTableEntry(&cdbrHandle, config, kNETC_AddOrUpdateEntry);
1716 }
1717 
EP_RxPSFPDelRPTableEntry(ep_handle_t * handle,uint32_t entryID)1718 status_t EP_RxPSFPDelRPTableEntry(ep_handle_t *handle, uint32_t entryID)
1719 {
1720     assert(handle != NULL);
1721     netc_cbdr_handle_t cdbrHandle;
1722 
1723     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1724     cdbrHandle.cmdr   = &handle->cmdBdRing;
1725     cdbrHandle.buffer = &s_cmdData;
1726     return NETC_DelRPTableEntry(&cdbrHandle, entryID);
1727 }
1728 
EP_RxPSFPGetRPStatistic(ep_handle_t * handle,uint32_t entryID,netc_tb_rp_stse_t * statis)1729 status_t EP_RxPSFPGetRPStatistic(ep_handle_t *handle, uint32_t entryID, netc_tb_rp_stse_t *statis)
1730 {
1731     assert(handle != NULL);
1732     netc_cbdr_handle_t cdbrHandle;
1733 
1734     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
1735     cdbrHandle.cmdr   = &handle->cmdBdRing;
1736     cdbrHandle.buffer = &s_cmdData;
1737     return NETC_GetRPStatistic(&cdbrHandle, entryID, statis);
1738 }
1739 
EP_MsixSetGlobalMask(ep_handle_t * handle,bool mask)1740 status_t EP_MsixSetGlobalMask(ep_handle_t *handle, bool mask)
1741 {
1742     if (getSiNum(handle->cfg.si) == 0U)
1743     {
1744         if (mask)
1745         {
1746             handle->hw.func.pf->PCI_CFC_MSIX_MSG_CTL |= (uint16_t)ENETC_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_FUNC_MASK_MASK;
1747         }
1748         else
1749         {
1750             handle->hw.func.pf->PCI_CFC_MSIX_MSG_CTL &=
1751                 (uint16_t)(~ENETC_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_FUNC_MASK_MASK);
1752         }
1753     }
1754     else
1755     {
1756         if (mask)
1757         {
1758             handle->hw.func.vf->PCI_CFC_MSIX_MSG_CTL |=
1759                 (uint16_t)ENETC_VF_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_FUNC_MASK_MASK;
1760         }
1761         else
1762         {
1763             handle->hw.func.vf->PCI_CFC_MSIX_MSG_CTL &=
1764                 (uint16_t)(~ENETC_VF_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_FUNC_MASK_MASK);
1765         }
1766     }
1767 
1768     return kStatus_Success;
1769 }
1770 
EP_MsixSetEntryMask(ep_handle_t * handle,uint8_t entryIdx,bool mask)1771 status_t EP_MsixSetEntryMask(ep_handle_t *handle, uint8_t entryIdx, bool mask)
1772 {
1773     status_t result;
1774 
1775     if (entryIdx < handle->cfg.entryNum)
1776     {
1777         handle->hw.msixTable[entryIdx].control = (uint32_t)mask;
1778         result                                 = kStatus_Success;
1779     }
1780     else
1781     {
1782         result = kStatus_Fail;
1783     }
1784 
1785     return result;
1786 }
1787 
EP_MsixGetPendingStatus(ep_handle_t * handle,uint8_t pbaIdx,uint64_t * status)1788 status_t EP_MsixGetPendingStatus(ep_handle_t *handle, uint8_t pbaIdx, uint64_t *status)
1789 {
1790     status_t result = kStatus_Success;
1791     bool funcEnable;
1792 
1793     if (handle->cfg.entryNum == 0U)
1794     {
1795         return kStatus_Fail;
1796     }
1797 
1798     /* Check MSIX enable status. */
1799     if (getSiNum(handle->cfg.si) == 0U)
1800     {
1801         funcEnable =
1802             ((handle->hw.func.pf->PCI_CFC_MSIX_MSG_CTL & ENETC_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_MSIX_EN_MASK) != 0U);
1803     }
1804     else
1805     {
1806         funcEnable =
1807             ((handle->hw.func.vf->PCI_CFC_MSIX_MSG_CTL & ENETC_VF_PCI_TYPE0_PCI_CFC_MSIX_MSG_CTL_MSIX_EN_MASK) != 0U);
1808     }
1809 
1810     if (funcEnable)
1811     {
1812         if (pbaIdx <= ((handle->cfg.entryNum - 1U) / 64U))
1813         {
1814             *status = *(uint64_t *)((uintptr_t)handle->hw.msixTable + NETC_MSIX_TABLE_PBA_OFFSET + 8U * pbaIdx);
1815             result  = kStatus_Success;
1816         }
1817         else
1818         {
1819             result = kStatus_InvalidArgument;
1820         }
1821     }
1822     else
1823     {
1824         *status = 0;
1825         result  = kStatus_Fail;
1826     }
1827 
1828     return result;
1829 }
1830 
EP_RxL2MFInit(ep_handle_t * handle,netc_si_l2mf_config_t * config)1831 status_t EP_RxL2MFInit(ep_handle_t *handle, netc_si_l2mf_config_t *config)
1832 {
1833     uint8_t siNum = getSiNum(handle->cfg.si);
1834 
1835     NETC_EnetcEnablePromiscuous(handle->hw.base, siNum, config->macUCPromis, config->macMCPromis);
1836     NETC_SIEnablePromisc(handle->hw.si, kNETC_PacketUnicast, config->rejectUC);
1837     NETC_SIEnablePromisc(handle->hw.si, kNETC_PacketMulticast, config->rejectMC);
1838     NETC_SIEnablePromisc(handle->hw.si, kNETC_PacketBroadcast, config->rejectBC);
1839 
1840     return kStatus_Success;
1841 }
1842 
EP_RxL2MFAddHashEntry(ep_handle_t * handle,netc_packet_type_t type,uint8_t * macAddr)1843 status_t EP_RxL2MFAddHashEntry(ep_handle_t *handle, netc_packet_type_t type, uint8_t *macAddr)
1844 {
1845     assert(type != kNETC_PacketBroadcast);
1846 
1847     uint8_t siNum     = getSiNum(handle->cfg.si);
1848     uint8_t hashIndex = 0;
1849     uint64_t mac      = 0;
1850     int i             = 0;
1851 
1852     /* Calculate the hash index. */
1853     for (i = 5; i >= 0; i--)
1854     {
1855         mac = (mac << 8U) | macAddr[i];
1856     }
1857     for (i = 0; i < 8; i++)
1858     {
1859         hashIndex ^= (uint8_t)(mac & 0x3FU);
1860         mac = mac >> 6U;
1861     }
1862 
1863     NETC_EnetcAddMacAddrHash(handle->hw.base, siNum, type, hashIndex);
1864 
1865     /* Added the used count of hash index. */
1866     if (type == kNETC_PacketUnicast)
1867     {
1868         handle->unicastHashCount[hashIndex]++;
1869     }
1870     else
1871     {
1872         handle->multicastHashCount[hashIndex]++;
1873     }
1874 
1875     return kStatus_Success;
1876 }
1877 
EP_RxL2MFDelHashEntry(ep_handle_t * handle,netc_packet_type_t type,uint8_t * macAddr)1878 status_t EP_RxL2MFDelHashEntry(ep_handle_t *handle, netc_packet_type_t type, uint8_t *macAddr)
1879 {
1880     assert(type != kNETC_PacketBroadcast);
1881 
1882     uint8_t siNum     = getSiNum(handle->cfg.si);
1883     uint8_t hashIndex = 0;
1884     uint64_t mac      = 0;
1885     int i             = 0;
1886 
1887     /* Calculate the hash index. */
1888     for (i = 5; i >= 0; i--)
1889     {
1890         mac = (mac << 8U) | macAddr[i];
1891     }
1892     for (i = 0; i < 8; i++)
1893     {
1894         hashIndex ^= (uint8_t)(mac & 0x3FU);
1895         mac = mac >> 6U;
1896     }
1897 
1898     if (type == kNETC_PacketUnicast)
1899     {
1900         if (handle->unicastHashCount[hashIndex] == 0U)
1901         {
1902             return kStatus_Fail;
1903         }
1904         else
1905         {
1906             /* Delete the hash index when there's no address using this index. */
1907             if (--handle->unicastHashCount[hashIndex] == 0U)
1908             {
1909                 NETC_EnetcDelMacAddrHash(handle->hw.base, siNum, type, hashIndex);
1910             }
1911         }
1912     }
1913     else
1914     {
1915         if (handle->multicastHashCount[hashIndex] == 0U)
1916         {
1917             return kStatus_Fail;
1918         }
1919         else
1920         {
1921             /* Delete the hash index when there's no other MAC address using this hash index. */
1922             if (--handle->multicastHashCount[hashIndex] == 0U)
1923             {
1924                 NETC_EnetcDelMacAddrHash(handle->hw.base, siNum, type, hashIndex);
1925             }
1926         }
1927     }
1928 
1929     return kStatus_Success;
1930 }
1931 
EP_RxL2MFAddEMTableEntry(ep_handle_t * handle,uint32_t idx,uint8_t * macAddr)1932 status_t EP_RxL2MFAddEMTableEntry(ep_handle_t *handle, uint32_t idx, uint8_t *macAddr)
1933 {
1934     assert((handle != NULL) && ((macAddr != NULL)));
1935     uint64_t address =
1936         ((uint64_t)macAddr[4] << 32U) + ((uint64_t)macAddr[5] << 40U) + *(uint32_t *)(uintptr_t)&macAddr[0];
1937     netc_cmd_bd_t cmdBd = {0};
1938 
1939     /* Only PSI can access MAC filter table */
1940     if (getSiNum(handle->cfg.si) != 0U)
1941     {
1942         return kStatus_InvalidArgument;
1943     }
1944     cmdBd.generic.addr     = address;
1945     cmdBd.generic.en       = 1;
1946     cmdBd.generic.siBitMap = (uint32_t)1U << getSiNum(handle->cfg.si);
1947     cmdBd.generic.index    = idx;
1948     cmdBd.generic.cmd      = 0;
1949     cmdBd.generic.class    = 1;
1950     cmdBd.generic.ci       = 0;
1951     cmdBd.generic.sf       = 1;
1952     return NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR, &handle->cmdBdRing, &cmdBd,
1953                                  kNETC_NtmpV1_0);
1954 }
1955 
EP_RxL2MFDelEMTableEntry(ep_handle_t * handle,uint32_t idx)1956 status_t EP_RxL2MFDelEMTableEntry(ep_handle_t *handle, uint32_t idx)
1957 {
1958     assert(handle != NULL);
1959     netc_cmd_bd_t cmdBd = {0};
1960 
1961     /* Only PSI can access MAC filter table */
1962     if (getSiNum(handle->cfg.si) != 0U)
1963     {
1964         return kStatus_InvalidArgument;
1965     }
1966     cmdBd.generic.addr     = 0;
1967     cmdBd.generic.en       = 1;
1968     cmdBd.generic.siBitMap = 0;
1969     cmdBd.generic.index    = idx;
1970     cmdBd.generic.cmd      = 0;
1971     cmdBd.generic.class    = 1;
1972     cmdBd.generic.ci       = 0;
1973     cmdBd.generic.sf       = 1;
1974     return NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR, &handle->cmdBdRing, &cmdBd,
1975                                  kNETC_NtmpV1_0);
1976 }
1977 
EP_RxL2VFInit(ep_handle_t * handle,netc_si_l2vf_config_t * config)1978 status_t EP_RxL2VFInit(ep_handle_t *handle, netc_si_l2vf_config_t *config)
1979 {
1980     NETC_EnetcConfigureVlanFilter(handle->hw.base, getSiNum(handle->cfg.si), config);
1981     return kStatus_Success;
1982 }
1983 
EP_RxL2VFAddHashEntry(ep_handle_t * handle,uint16_t vlanId)1984 status_t EP_RxL2VFAddHashEntry(ep_handle_t *handle, uint16_t vlanId)
1985 {
1986     assert(handle != NULL);
1987     assert(vlanId <= 0xFFFU);
1988 
1989     uint8_t siNum     = getSiNum(handle->cfg.si);
1990     uint8_t hash0     = (uint8_t)((vlanId >> 6U) & 0x3FU);
1991     uint8_t hash1     = (uint8_t)(vlanId & 0x3FU);
1992     uint8_t hashIndex = hash0 ^ hash1;
1993 
1994     NETC_EnetcAddVlanHash(handle->hw.base, siNum, hashIndex);
1995 
1996     /* Added the used count of hash index. */
1997     handle->vlanHashCount[hashIndex]++;
1998 
1999     return kStatus_Success;
2000 }
2001 
EP_RxL2VFDelHashEntry(ep_handle_t * handle,uint16_t vlanId)2002 status_t EP_RxL2VFDelHashEntry(ep_handle_t *handle, uint16_t vlanId)
2003 {
2004     assert(handle != NULL);
2005     assert(vlanId <= 0xFFFU);
2006 
2007     uint8_t siNum     = getSiNum(handle->cfg.si);
2008     uint8_t hash0     = (uint8_t)((vlanId >> 6U) & 0x3FU);
2009     uint8_t hash1     = (uint8_t)(vlanId & 0x3FU);
2010     uint8_t hashIndex = hash0 ^ hash1;
2011 
2012     if (handle->vlanHashCount[hashIndex] == 0U)
2013     {
2014         return kStatus_Fail;
2015     }
2016     else
2017     {
2018         /* Delete the hash index when there's no other VLAN ID using this hash index. */
2019         if (--handle->vlanHashCount[hashIndex] == 0U)
2020         {
2021             NETC_EnetcDelVlanHash(handle->hw.base, siNum, hashIndex);
2022         }
2023     }
2024 
2025     return kStatus_Success;
2026 }
2027 
EP_RxL2VFAddEMTableEntry(ep_handle_t * handle,uint32_t idx,uint16_t vlanId,netc_vlan_tpid_select_t tpid)2028 status_t EP_RxL2VFAddEMTableEntry(ep_handle_t *handle, uint32_t idx, uint16_t vlanId, netc_vlan_tpid_select_t tpid)
2029 {
2030     assert(handle != NULL);
2031     netc_cmd_bd_t cmdBd = {0};
2032 
2033     /* Only PSI can access MAC filter table */
2034     if (getSiNum(handle->cfg.si) != 0U)
2035     {
2036         return kStatus_InvalidArgument;
2037     }
2038     cmdBd.generic.addr     = (uint64_t)vlanId | ((uint64_t)tpid << 16U);
2039     cmdBd.generic.en       = 1;
2040     cmdBd.generic.siBitMap = (uint32_t)1U << getSiNum(handle->cfg.si);
2041     cmdBd.generic.index    = idx;
2042     cmdBd.generic.cmd      = 0;
2043     cmdBd.generic.class    = 2;
2044     cmdBd.generic.ci       = 0;
2045     cmdBd.generic.sf       = 1;
2046     return NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR, &handle->cmdBdRing, &cmdBd,
2047                                  kNETC_NtmpV1_0);
2048 }
2049 
EP_RxL2VFDelEMTableEntry(ep_handle_t * handle,uint32_t idx)2050 status_t EP_RxL2VFDelEMTableEntry(ep_handle_t *handle, uint32_t idx)
2051 {
2052     assert(handle != NULL);
2053     netc_cmd_bd_t cmdBd = {0};
2054 
2055     /* Only PSI can access MAC filter table */
2056     if (getSiNum(handle->cfg.si) != 0U)
2057     {
2058         return kStatus_InvalidArgument;
2059     }
2060     cmdBd.generic.addr     = 0;
2061     cmdBd.generic.en       = 1;
2062     cmdBd.generic.siBitMap = 0;
2063     cmdBd.generic.index    = idx;
2064     cmdBd.generic.cmd      = 0;
2065     cmdBd.generic.class    = 2;
2066     cmdBd.generic.ci       = 0;
2067     cmdBd.generic.sf       = 1;
2068     return NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR, &handle->cmdBdRing, &cmdBd,
2069                                  kNETC_NtmpV1_0);
2070 }
2071 
2072 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_051130) && FSL_FEATURE_NETC_HAS_ERRATA_051130)
EP_TxPortTGSEnable(ep_handle_t * handle,bool enable,uint8_t gateState)2073 status_t EP_TxPortTGSEnable(ep_handle_t *handle, bool enable, uint8_t gateState)
2074 #else
2075 status_t EP_TxPortTGSEnable(ep_handle_t *handle, bool enable)
2076 #endif
2077 {
2078     assert(handle != NULL);
2079     status_t result = kStatus_Success;
2080 
2081     if (enable)
2082     {
2083         handle->hw.portGroup.port->PTGSCR |= NETC_PORT_PTGSCR_TGE_MASK;
2084 #if (defined(FSL_FEATURE_NETC_HAS_ERRATA_051130) && FSL_FEATURE_NETC_HAS_ERRATA_051130)
2085         netc_tgs_gate_entry_t gate[2] = {{.interval = 50000U, .tcGateState = gateState},
2086                                          {.interval = 50000U, .tcGateState = gateState}};
2087         netc_tb_tgs_gcl_t wTgsList    = {.cycleTime = 1000000U, .numEntries = 2U, .gcList = &gate[0]};
2088         uint64_t time;
2089         /* Enable master bus and memory access for default ns timer*/
2090         TMR_PCI_HDR_TYPE0->PCI_CFH_CMD |=
2091             (ENETC_PCI_TYPE0_PCI_CFH_CMD_MEM_ACCESS_MASK | ENETC_PCI_TYPE0_PCI_CFH_CMD_BUS_MASTER_EN_MASK);
2092 
2093         NETC_TimerGetTime(TMR0_BASE, &time);
2094 
2095         wTgsList.baseTime = time;
2096         result            = EP_TxTGSConfigAdminGcl(handle, &wTgsList);
2097 #endif
2098     }
2099     else
2100     {
2101         handle->hw.portGroup.port->PTGSCR &= ~NETC_PORT_PTGSCR_TGE_MASK;
2102     }
2103 
2104     return result;
2105 }
2106 
EP_TxTGSConfigAdminGcl(ep_handle_t * handle,netc_tb_tgs_gcl_t * config)2107 status_t EP_TxTGSConfigAdminGcl(ep_handle_t *handle, netc_tb_tgs_gcl_t *config)
2108 {
2109     assert((handle != NULL) && (config != NULL));
2110     netc_cbdr_handle_t cdbrHandle;
2111     status_t status = kStatus_Success;
2112 
2113     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2114     cdbrHandle.cmdr   = &handle->cmdBdRing;
2115     cdbrHandle.buffer = &s_cmdData;
2116 
2117     if (0U != (handle->hw.portGroup.port->PTGAGLSR & NETC_PORT_PTGAGLSR_CFG_PEND_MASK))
2118     {
2119         /* Removed the previous pending administrative gate control list */
2120         netc_tb_tgs_gcl_t emptyList = {.entryID = config->entryID, .numEntries = 0U};
2121         status                      = NETC_ConfigTGSAdminList(&cdbrHandle, &emptyList);
2122 
2123         if (kStatus_Success != status)
2124         {
2125             return status;
2126         }
2127     }
2128 #if defined(FSL_FEATURE_NETC_HAS_ERRATA_051587) && FSL_FEATURE_NETC_HAS_ERRATA_051587
2129     if (0U != (handle->hw.portGroup.port->PTGAGLSR & NETC_PORT_PTGAGLSR_TG_MASK))
2130     {
2131         netc_cmd_bd_t cmdBd = {0};
2132         uint32_t cycleTime;
2133         uint64_t time, minBaseTime;
2134 
2135         /* Read the previous active Operationa gate control list cycle time*/
2136         (void)memset(cdbrHandle.buffer, 0, sizeof(netc_tb_tgs_data_t));
2137         cdbrHandle.buffer->tgs.request.entryID                    = config->entryID;
2138         cdbrHandle.buffer->tgs.request.commonHeader.updateActions = 0U;
2139         cdbrHandle.buffer->tgs.request.commonHeader.queryActions  = 0U;
2140         cmdBd.req.addr                                            = (uintptr_t)cdbrHandle.buffer;
2141         cmdBd.req.reqLength                                       = 8U;
2142         /* Set Response Data Buffer length to MAX */
2143         cmdBd.req.resLength  = sizeof(netc_tb_tgs_data_t);
2144         cmdBd.req.tableId    = kNETC_TGSTable;
2145         cmdBd.req.cmd        = kNETC_QueryEntry;
2146         cmdBd.req.accessType = kNETC_EntryIDMatch;
2147         status               = NETC_CmdBDSendCommand(cdbrHandle.base, cdbrHandle.cmdr, &cmdBd, kNETC_NtmpV2_0);
2148         if (kStatus_Success == status)
2149         {
2150             cycleTime = ((netc_tb_tgs_olse_t *)(uintptr_t)(&((uint8_t *)cdbrHandle.buffer)[36U]))->operCycleTime;
2151         }
2152         else
2153         {
2154             return status;
2155         }
2156         /* Get Current Time */
2157         NETC_TimerGetTime(TMR0_BASE, &time);
2158 
2159         /* The minimum base time = current time + advance time (0.1us) + command processing time (~90us) + (2 *
2160          * operational cycle times) */
2161         minBaseTime = time + 100100U + (2U * cycleTime);
2162         /* Check, if there is operating GCL and if admin base time is in range described in ERR051587*/
2163         if ((config->numEntries > 0U) && (config->baseTime < minBaseTime))
2164         {
2165             config->baseTime +=
2166                 (((uint64_t)ceil(((double)minBaseTime - (double)config->baseTime) / (double)config->cycleTime))) *
2167                 config->cycleTime;
2168         }
2169     }
2170 #endif
2171     return NETC_ConfigTGSAdminList(&cdbrHandle, config);
2172 }
2173 
EP_TxtTGSGetOperGcl(ep_handle_t * handle,netc_tb_tgs_gcl_t * gcl,uint32_t length)2174 status_t EP_TxtTGSGetOperGcl(ep_handle_t *handle, netc_tb_tgs_gcl_t *gcl, uint32_t length)
2175 {
2176     assert((handle != NULL) && (gcl != NULL));
2177     netc_cbdr_handle_t cdbrHandle;
2178 
2179     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2180     cdbrHandle.cmdr   = &handle->cmdBdRing;
2181     cdbrHandle.buffer = &s_cmdData;
2182     return NETC_GetTGSOperationList(&cdbrHandle, gcl, length);
2183 }
2184 
EP_TxTrafficClassConfig(ep_handle_t * handle,netc_hw_tc_idx_t tcIdx,const netc_port_tx_tc_config_t * config)2185 status_t EP_TxTrafficClassConfig(ep_handle_t *handle, netc_hw_tc_idx_t tcIdx, const netc_port_tx_tc_config_t *config)
2186 {
2187     assert((handle != NULL) && (config != NULL));
2188     status_t reseult;
2189     uint32_t temp;
2190 
2191     if (!NETC_PortIsPseudo(handle->hw.portGroup.port))
2192     {
2193         temp                             = handle->hw.portGroup.port->PFPCR & (~((uint32_t)1U << (uint32_t)tcIdx));
2194         handle->hw.portGroup.port->PFPCR = temp | ((uint32_t)config->enPreemption << (uint32_t)tcIdx);
2195     }
2196     temp                             = handle->hw.portGroup.port->PDGSR & (~((uint32_t)1U << (uint32_t)tcIdx));
2197     handle->hw.portGroup.port->PDGSR = temp | ((uint32_t)config->enTcGate << (uint32_t)tcIdx);
2198 
2199     (void)NETC_EnetcPortEnableTSD(handle->hw.base, tcIdx, config->enableTsd);
2200 
2201     reseult = NETC_PortConfigTcMaxSDU(handle->hw.portGroup.port, tcIdx, &config->sduCfg);
2202     if ((kStatus_Success == reseult) && (config->enableCbs))
2203     {
2204         reseult = NETC_PortConfigTcCBS(handle->hw.portGroup.port, tcIdx, &config->cbsCfg);
2205     }
2206     return reseult;
2207 }
2208 
EP_RxPSFPAddISITableEntry(ep_handle_t * handle,netc_tb_isi_config_t * config,uint32_t * entryID)2209 status_t EP_RxPSFPAddISITableEntry(ep_handle_t *handle, netc_tb_isi_config_t *config, uint32_t *entryID)
2210 {
2211     assert((handle != NULL) && (config != NULL) && (entryID != NULL));
2212     netc_cbdr_handle_t cdbrHandle;
2213 
2214     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2215     cdbrHandle.cmdr   = &handle->cmdBdRing;
2216     cdbrHandle.buffer = &s_cmdData;
2217     return NETC_AddISITableEntry(&cdbrHandle, config, entryID);
2218 }
2219 
EP_RxPSFPDelISITableEntry(ep_handle_t * handle,uint32_t entryID)2220 status_t EP_RxPSFPDelISITableEntry(ep_handle_t *handle, uint32_t entryID)
2221 {
2222     assert(handle != NULL);
2223     netc_cbdr_handle_t cdbrHandle;
2224 
2225     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2226     cdbrHandle.cmdr   = &handle->cmdBdRing;
2227     cdbrHandle.buffer = &s_cmdData;
2228     return NETC_DelISITableEntry(&cdbrHandle, entryID);
2229 }
2230 
EP_RxPSFPAddISTableEntry(ep_handle_t * handle,netc_tb_is_config_t * config)2231 status_t EP_RxPSFPAddISTableEntry(ep_handle_t *handle, netc_tb_is_config_t *config)
2232 {
2233     assert((handle != NULL) && (config != NULL));
2234     netc_cbdr_handle_t cdbrHandle;
2235 
2236     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2237     cdbrHandle.cmdr   = &handle->cmdBdRing;
2238     cdbrHandle.buffer = &s_cmdData;
2239     return NETC_AddOrUpdateISTableEntry(&cdbrHandle, config, true);
2240 }
2241 
EP_RxPSFPUpdateISTableEntry(ep_handle_t * handle,netc_tb_is_config_t * config)2242 status_t EP_RxPSFPUpdateISTableEntry(ep_handle_t *handle, netc_tb_is_config_t *config)
2243 {
2244     assert((handle != NULL) && (config != NULL));
2245     netc_cbdr_handle_t cdbrHandle;
2246 
2247     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2248     cdbrHandle.cmdr   = &handle->cmdBdRing;
2249     cdbrHandle.buffer = &s_cmdData;
2250     return NETC_AddOrUpdateISTableEntry(&cdbrHandle, config, false);
2251 }
2252 
EP_RxPSFPDelISTableEntry(ep_handle_t * handle,uint32_t entryID)2253 status_t EP_RxPSFPDelISTableEntry(ep_handle_t *handle, uint32_t entryID)
2254 {
2255     assert(handle != NULL);
2256     netc_cbdr_handle_t cdbrHandle;
2257 
2258     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2259     cdbrHandle.cmdr   = &handle->cmdBdRing;
2260     cdbrHandle.buffer = &s_cmdData;
2261     return NETC_DelISTableEntry(&cdbrHandle, entryID);
2262 }
2263 
EP_RxPSFPAddISFTableEntry(ep_handle_t * handle,netc_tb_isf_config_t * config,uint32_t * entryID)2264 status_t EP_RxPSFPAddISFTableEntry(ep_handle_t *handle, netc_tb_isf_config_t *config, uint32_t *entryID)
2265 {
2266     assert((handle != NULL) && (config != NULL) && (entryID != NULL));
2267     netc_cbdr_handle_t cdbrHandle;
2268 
2269     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2270     cdbrHandle.cmdr   = &handle->cmdBdRing;
2271     cdbrHandle.buffer = &s_cmdData;
2272     return NETC_AddISFTableEntry(&cdbrHandle, config, entryID);
2273 }
2274 
EP_RxPSFPUpdateISFTableEntry(ep_handle_t * handle,uint32_t entryID,netc_tb_isf_cfge_t * cfg)2275 status_t EP_RxPSFPUpdateISFTableEntry(ep_handle_t *handle, uint32_t entryID, netc_tb_isf_cfge_t *cfg)
2276 {
2277     assert((handle != NULL) && (cfg != NULL));
2278     netc_cbdr_handle_t cdbrHandle;
2279 
2280     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2281     cdbrHandle.cmdr   = &handle->cmdBdRing;
2282     cdbrHandle.buffer = &s_cmdData;
2283     return NETC_UpdateISFTableEntry(&cdbrHandle, entryID, cfg);
2284 }
2285 
EP_RxPSFPDelISFTableEntry(ep_handle_t * handle,uint32_t entryID)2286 status_t EP_RxPSFPDelISFTableEntry(ep_handle_t *handle, uint32_t entryID)
2287 {
2288     assert(handle != NULL);
2289     netc_cbdr_handle_t cdbrHandle;
2290 
2291     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2292     cdbrHandle.cmdr   = &handle->cmdBdRing;
2293     cdbrHandle.buffer = &s_cmdData;
2294     return NETC_DelISFTableEntry(&cdbrHandle, entryID);
2295 }
2296 
EP_RxPSFPAddISCTableEntry(ep_handle_t * handle,uint32_t entryID)2297 status_t EP_RxPSFPAddISCTableEntry(ep_handle_t *handle, uint32_t entryID)
2298 {
2299     assert(handle != NULL);
2300     netc_cbdr_handle_t cdbrHandle;
2301 
2302     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2303     cdbrHandle.cmdr   = &handle->cmdBdRing;
2304     cdbrHandle.buffer = &s_cmdData;
2305     return NETC_AddISCTableEntry(&cdbrHandle, entryID);
2306 }
2307 
EP_RxPSFPGetISCStatistic(ep_handle_t * handle,uint32_t entryID,netc_tb_isc_stse_t * statistic)2308 status_t EP_RxPSFPGetISCStatistic(ep_handle_t *handle, uint32_t entryID, netc_tb_isc_stse_t *statistic)
2309 {
2310     assert(handle != NULL);
2311     netc_cbdr_handle_t cdbrHandle;
2312 
2313     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2314     cdbrHandle.cmdr   = &handle->cmdBdRing;
2315     cdbrHandle.buffer = &s_cmdData;
2316     return NETC_GetISCStatistic(&cdbrHandle, entryID, statistic);
2317 }
2318 
EP_RxPSFPResetISCStatistic(ep_handle_t * handle,uint32_t entryID)2319 status_t EP_RxPSFPResetISCStatistic(ep_handle_t *handle, uint32_t entryID)
2320 {
2321     assert(handle != NULL);
2322     netc_cbdr_handle_t cdbrHandle;
2323 
2324     cdbrHandle.base   = (netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR;
2325     cdbrHandle.cmdr   = &handle->cmdBdRing;
2326     cdbrHandle.buffer = &s_cmdData;
2327     return NETC_ResetISCStatistic(&cdbrHandle, entryID);
2328 }
2329 
EP_PsiEnableInterrupt(ep_handle_t * handle,uint32_t mask,bool enable)2330 void EP_PsiEnableInterrupt(ep_handle_t *handle, uint32_t mask, bool enable)
2331 {
2332     /* Check whether VSI number is over the capability. */
2333     assert(((uint16_t)mask >> handle->capability.vsiNum) <= 1U);
2334     assert(((uint16_t)(mask >> 16U) >> handle->capability.vsiNum) <= 1U);
2335     assert(getSiNum(handle->cfg.si) == 0U);
2336     NETC_SIPsiEnableInterrupt(handle->hw.si, mask, enable);
2337 }
2338 
EP_PsiGetStatus(ep_handle_t * handle)2339 uint32_t EP_PsiGetStatus(ep_handle_t *handle)
2340 {
2341     assert(handle->capability.vsiNum > 0U);
2342     assert(getSiNum(handle->cfg.si) == 0U);
2343     return NETC_SIPsiGetStatus(handle->hw.si);
2344 }
2345 
EP_PsiClearStatus(ep_handle_t * handle,uint32_t mask)2346 void EP_PsiClearStatus(ep_handle_t *handle, uint32_t mask)
2347 {
2348     /* Check whether VSI number is over the capability. */
2349     assert(((uint16_t)mask >> handle->capability.vsiNum) <= 1U);
2350     assert(((uint16_t)(mask >> 16U) >> handle->capability.vsiNum) <= 1U);
2351     assert(handle->capability.vsiNum > 0U);
2352     assert(getSiNum(handle->cfg.si) == 0U);
2353     NETC_SIPsiClearStatus(handle->hw.si, mask);
2354 }
2355 
EP_PsiSendMsg(ep_handle_t * handle,uint16_t msg,netc_vsi_number_t vsi)2356 status_t EP_PsiSendMsg(ep_handle_t *handle, uint16_t msg, netc_vsi_number_t vsi)
2357 {
2358     assert(handle->capability.vsiNum > NETC_SIGetVsiIndex(vsi));
2359     assert(getSiNum(handle->cfg.si) == 0U);
2360     return NETC_SIPsiSendMsg(handle->hw.si, msg, vsi);
2361 }
2362 
EP_PsiCheckTxBusy(ep_handle_t * handle,netc_vsi_number_t vsi)2363 bool EP_PsiCheckTxBusy(ep_handle_t *handle, netc_vsi_number_t vsi)
2364 {
2365     assert(handle->capability.vsiNum > NETC_SIGetVsiIndex(vsi));
2366     assert(getSiNum(handle->cfg.si) == 0U);
2367     return NETC_SIPsiCheckTxBusy(handle->hw.si, vsi);
2368 }
2369 
EP_PsiSetRxBuffer(ep_handle_t * handle,netc_vsi_number_t vsi,uint64_t buffAddr)2370 status_t EP_PsiSetRxBuffer(ep_handle_t *handle, netc_vsi_number_t vsi, uint64_t buffAddr)
2371 {
2372     assert(handle->capability.vsiNum > NETC_SIGetVsiIndex(vsi));
2373     assert(getSiNum(handle->cfg.si) == 0U);
2374     return NETC_SIPsiSetRxBuffer(handle->hw.si, vsi, buffAddr);
2375 }
2376 
EP_PsiGetRxMsg(ep_handle_t * handle,netc_vsi_number_t vsi,netc_psi_rx_msg_t * msgInfo)2377 status_t EP_PsiGetRxMsg(ep_handle_t *handle, netc_vsi_number_t vsi, netc_psi_rx_msg_t *msgInfo)
2378 {
2379     assert(handle->capability.vsiNum > NETC_SIGetVsiIndex(vsi));
2380     assert(getSiNum(handle->cfg.si) == 0U);
2381     return NETC_SIPsiGetRxMsg(handle->hw.si, vsi, msgInfo);
2382 }
2383 
EP_VsiEnableInterrupt(ep_handle_t * handle,uint32_t mask,bool enable)2384 void EP_VsiEnableInterrupt(ep_handle_t *handle, uint32_t mask, bool enable)
2385 {
2386     assert(getSiNum(handle->cfg.si) <= (uint8_t)handle->capability.vsiNum);
2387     assert(getSiNum(handle->cfg.si) != 0U);
2388     NETC_SIVsiEnableInterrupt(handle->hw.si, mask, enable);
2389 }
2390 
EP_VsiGetStatus(ep_handle_t * handle)2391 uint32_t EP_VsiGetStatus(ep_handle_t *handle)
2392 {
2393     assert(getSiNum(handle->cfg.si) <= (uint8_t)handle->capability.vsiNum);
2394     assert(getSiNum(handle->cfg.si) != 0U);
2395     return NETC_SIVsiGetStatus(handle->hw.si);
2396 }
2397 
EP_VsiClearStatus(ep_handle_t * handle,uint32_t mask)2398 void EP_VsiClearStatus(ep_handle_t *handle, uint32_t mask)
2399 {
2400     assert(getSiNum(handle->cfg.si) <= (uint8_t)handle->capability.vsiNum);
2401     assert(getSiNum(handle->cfg.si) != 0U);
2402     NETC_SIVsiClearStatus(handle->hw.si, mask);
2403 }
2404 
EP_VsiSendMsg(ep_handle_t * handle,uint64_t msgAddr,uint32_t msgLen)2405 status_t EP_VsiSendMsg(ep_handle_t *handle, uint64_t msgAddr, uint32_t msgLen)
2406 {
2407     assert(getSiNum(handle->cfg.si) <= (uint8_t)handle->capability.vsiNum);
2408     assert(getSiNum(handle->cfg.si) != 0U);
2409     return NETC_SIVsiSendMsg(handle->hw.si, msgAddr, msgLen);
2410 }
2411 
EP_VsiCheckTxStatus(ep_handle_t * handle,netc_vsi_msg_tx_status_t * status)2412 void EP_VsiCheckTxStatus(ep_handle_t *handle, netc_vsi_msg_tx_status_t *status)
2413 {
2414     assert(getSiNum(handle->cfg.si) <= (uint8_t)handle->capability.vsiNum);
2415     assert(getSiNum(handle->cfg.si) != 0U);
2416     NETC_SIVsiCheckTxStatus(handle->hw.si, status);
2417 }
2418 
EP_VsiReceiveMsg(ep_handle_t * handle,uint16_t * msg)2419 status_t EP_VsiReceiveMsg(ep_handle_t *handle, uint16_t *msg)
2420 {
2421     assert(getSiNum(handle->cfg.si) <= (uint8_t)handle->capability.vsiNum);
2422     assert(getSiNum(handle->cfg.si) != 0U);
2423     return NETC_SIVsiReceiveMsg(handle->hw.si, msg);
2424 }
2425