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