1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_netc_msg.h"
8 #include "netc_hw/fsl_netc_hw.h"
9 #include "netc_hw/fsl_netc_hw_enetc.h"
10 #include "fsl_adapter_crc.h"
11 
12 #ifndef NUM_MAC_FILTER_ENTRY
13 #define NUM_MAC_FILTER_ENTRY 4U
14 #endif
15 #ifndef NUM_VLAN_FILTER_ENTRY
16 #define NUM_VLAN_FILTER_ENTRY 4U
17 #endif
18 
19 /* MAC filter Operations */
20 
EP_RxL2MFFreeNum(ep_handle_t * handle)21 static uint8_t EP_RxL2MFFreeNum(ep_handle_t *handle)
22 {
23     uint8_t n = 0;
24     uint8_t i;
25 
26     for (i = 0; i < NUM_MAC_FILTER_ENTRY; i++)
27     {
28         if (handle->macFilterCount[i] == 0U)
29         {
30             n++;
31         }
32     }
33 
34     return n;
35 }
36 
EP_RxL2MFFreeIndex(ep_handle_t * handle,uint16_t * idx)37 static status_t EP_RxL2MFFreeIndex(ep_handle_t *handle, uint16_t *idx)
38 {
39     uint8_t i;
40 
41     for (i = 0; i < NUM_MAC_FILTER_ENTRY; i++)
42     {
43         if (handle->macFilterCount[i] == 0U)
44         {
45             *idx = i;
46             return kStatus_Success;
47         }
48     }
49 
50     return kStatus_Fail;
51 }
52 
EP_RxL2MFQueryEMTableEntry(ep_handle_t * handle,uint8_t * macAddr,emtable_query_result_t * result)53 static void EP_RxL2MFQueryEMTableEntry(ep_handle_t *handle, uint8_t *macAddr, emtable_query_result_t *result)
54 {
55     uint64_t address =
56         ((uint64_t)macAddr[4U] << 32U) + ((uint64_t)macAddr[5U] << 40U) + *(uint32_t *)(uintptr_t)&macAddr[0];
57     ENETC_SI_Type *base = handle->hw.si;
58     netc_cmd_bd_t cmdBd = {0};
59     status_t ret;
60     uint8_t i;
61 
62     (void)memset(result, 0, sizeof(*result));
63 
64     /* Only PSI can access MAC filter table */
65     if (getSiNum(handle->cfg.si) != 0U)
66     {
67         return;
68     }
69 
70     /* Query each entry */
71     for (i = 0U; i < NUM_MAC_FILTER_ENTRY; i++)
72     {
73         /* entry not in use */
74         if (handle->macFilterCount[i] == 0U)
75         {
76             continue;
77         }
78 
79         (void)memset(&cmdBd, 0, sizeof(cmdBd));
80         cmdBd.generic.index = i;
81         cmdBd.generic.cmd   = 1U;
82         cmdBd.generic.class = 1U;
83         cmdBd.generic.ci    = 0U;
84         cmdBd.generic.sf    = 1U;
85 
86         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
87                                     kNETC_NtmpV1_0);
88         if (ret != kStatus_Success)
89         {
90             result->valid = 0U;
91             return;
92         }
93 
94         if (cmdBd.generic.addr == address)
95         {
96             result->valid    = 1U;
97             result->match    = 1U;
98             result->siBitMap = (uint16_t)cmdBd.generic.siBitMap;
99             result->index    = i;
100             return;
101         }
102     }
103 
104     result->valid = 1U;
105     return;
106 }
107 
EP_RxL2MFQueryAddEMTableEntry(ep_handle_t * handle,uint8_t si,uint8_t count,uint8_t * macAddr)108 static uint16_t EP_RxL2MFQueryAddEMTableEntry(ep_handle_t *handle, uint8_t si, uint8_t count, uint8_t *macAddr)
109 {
110     emtable_query_result_t result[NUM_MAC_FILTER_ENTRY] = {0};
111     ENETC_SI_Type *base                                 = handle->hw.si;
112     netc_cmd_bd_t cmdBd                                 = {0};
113     uint8_t free_num                                    = EP_RxL2MFFreeNum(handle);
114     uint8_t match_num                                   = 0U;
115     uint8_t i, m;
116     status_t ret;
117     uint64_t address;
118     uint16_t index = 0U;
119 
120     /* Count 0 means only macAddr0 is considered. Treat as same case with array size 1. */
121     if (count == 0U)
122     {
123         count = 1U;
124     }
125 
126     if (count > NUM_MAC_FILTER_ENTRY)
127     {
128         return NETC_MSG_RETURN_CODE(kNETC_MsgClassMacFilter, kNETC_MsgMacFilterNoResource, 0U);
129     }
130 
131     /* Query for each MAC address */
132     for (i = 0U; i < count; i++)
133     {
134         EP_RxL2MFQueryEMTableEntry(handle, &macAddr[i * 6U], &result[i]);
135         if (result[i].valid == 0U)
136         {
137             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
138         }
139         if (result[i].match == 1U)
140         {
141             match_num++;
142         }
143     }
144 
145     /* Check resource */
146     if ((count - match_num) > free_num)
147     {
148         return NETC_MSG_RETURN_CODE(kNETC_MsgClassMacFilter, kNETC_MsgMacFilterNoResource, 0U);
149     }
150 
151     for (i = 0U; i < count; i++)
152     {
153         m       = 6U * i;
154         address = ((uint64_t)macAddr[m + 4U] << 32U) + ((uint64_t)macAddr[m + 5U] << 40U) +
155                   *(uint32_t *)(uintptr_t)&macAddr[m];
156 
157         (void)memset(&cmdBd, 0, sizeof(cmdBd));
158         cmdBd.generic.addr  = address;
159         cmdBd.generic.en    = 1;
160         cmdBd.generic.cmd   = 0;
161         cmdBd.generic.class = 1;
162         cmdBd.generic.ci    = 0;
163         cmdBd.generic.sf    = 1;
164 
165         /* For matched */
166         if (result[i].match == 1U)
167         {
168             cmdBd.generic.index    = result[i].index;
169             cmdBd.generic.siBitMap = (result[i].siBitMap | ((uint32_t)1U << si));
170         }
171         /* For new added */
172         else
173         {
174             if (EP_RxL2MFFreeIndex(handle, &index) != kStatus_Success)
175             {
176                 return NETC_MSG_RETURN_CODE(kNETC_MsgClassMacFilter, kNETC_MsgMacFilterNoResource, 0U);
177             }
178             cmdBd.generic.index    = index;
179             cmdBd.generic.siBitMap = ((uint32_t)1U << si);
180         }
181 
182         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
183                                     kNETC_NtmpV1_0);
184         if (ret != kStatus_Success)
185         {
186             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
187         }
188 
189         /* Update macFilterCount */
190         handle->macFilterCount[cmdBd.generic.index] = 1U;
191     }
192 
193     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
194 }
195 
EP_RxL2MFQueryDeleteEMTableEntry(ep_handle_t * handle,uint8_t si,uint8_t count,uint8_t * macAddr)196 static uint16_t EP_RxL2MFQueryDeleteEMTableEntry(ep_handle_t *handle, uint8_t si, uint8_t count, uint8_t *macAddr)
197 {
198     emtable_query_result_t result[NUM_MAC_FILTER_ENTRY] = {0};
199     ENETC_SI_Type *base                                 = handle->hw.si;
200     netc_cmd_bd_t cmdBd                                 = {0};
201     uint8_t i;
202     status_t ret;
203 
204     /* Count 0 means only macAddr0 is considered. Treat as same case with array size 1. */
205     if (count == 0U)
206     {
207         count = 1U;
208     }
209 
210     /* Query for each MAC address */
211     for (i = 0U; i < count; i++)
212     {
213         EP_RxL2MFQueryEMTableEntry(handle, &macAddr[i * 6U], &result[i]);
214         if (result[i].valid == 0U)
215         {
216             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
217         }
218         if (result[i].match == 0U)
219         {
220             return NETC_MSG_RETURN_CODE(kNETC_MsgClassMacFilter, kNETC_MsgMacFilterAddrNotFound, 0U);
221         }
222     }
223 
224     for (i = 0U; i < count; i++)
225     {
226         (void)memset(&cmdBd, 0, sizeof(cmdBd));
227 
228         cmdBd.generic.addr     = 0;
229         cmdBd.generic.en       = 1;
230         cmdBd.generic.siBitMap = 0;
231         cmdBd.generic.index    = result[i].index;
232         cmdBd.generic.cmd      = 0;
233         cmdBd.generic.class    = 1;
234         cmdBd.generic.ci       = 0;
235         cmdBd.generic.sf       = 1;
236 
237         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
238                                     kNETC_NtmpV1_0);
239         if (ret != kStatus_Success)
240         {
241             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
242         }
243 
244         /* Update macFilterCount */
245         handle->macFilterCount[result[i].index] = 0U;
246     }
247 
248     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
249 }
250 
EP_RxL2MFSetHashTable(ep_handle_t * handle,uint8_t si,uint8_t typeSize,uint8_t * HTWord)251 static uint16_t EP_RxL2MFSetHashTable(ep_handle_t *handle, uint8_t si, uint8_t typeSize, uint8_t *HTWord)
252 {
253     NETC_ENETC_Type *base = handle->hw.base;
254     uint32_t HT0Word0     = *(uint32_t *)((uint32_t)HTWord);
255     uint32_t HT0Word1     = *(uint32_t *)((uint32_t)HTWord + 0x4U);
256     uint32_t HT1Word0     = *(uint32_t *)((uint32_t)HTWord + 0x8U);
257     uint32_t HT1Word1     = *(uint32_t *)((uint32_t)HTWord + 0xcU);
258 
259     /* 64bits addr supported only */
260     if ((typeSize & 0x03U) != 0U)
261     {
262         return NETC_MSG_RETURN_CODE(kNETC_MsgClassMacFilter, kNETC_MsgMacFilterNotSupported, 0U);
263     }
264 
265     /* UC hash table (HT) only */
266     if ((typeSize & 0xc0U) == 0x40U)
267     {
268         base->NUM_SI[si].PSIUMHFR0 = HT0Word0;
269         base->NUM_SI[si].PSIUMHFR1 = HT0Word1;
270     }
271     /* MC hash table (HT) only */
272     else if ((typeSize & 0xc0U) == 0x80U)
273     {
274         base->NUM_SI[si].PSIMMHFR0 = HT0Word0;
275         base->NUM_SI[si].PSIMMHFR1 = HT0Word1;
276     }
277     /* UC and MC hash tables */
278     else
279     {
280         base->NUM_SI[si].PSIUMHFR0 = HT0Word0;
281         base->NUM_SI[si].PSIUMHFR1 = HT0Word1;
282         base->NUM_SI[si].PSIMMHFR0 = HT1Word0;
283         base->NUM_SI[si].PSIMMHFR1 = HT1Word1;
284     }
285 
286     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
287     ;
288 }
289 
EP_RxL2MFFlush(ep_handle_t * handle,uint8_t si,uint8_t type)290 static uint16_t EP_RxL2MFFlush(ep_handle_t *handle, uint8_t si, uint8_t type)
291 {
292     NETC_ENETC_Type *enetc = handle->hw.base;
293     ENETC_SI_Type *base    = handle->hw.si;
294     netc_cmd_bd_t cmdBd    = {0};
295     bool uc                = ((type == 0x40U) || (type == 0x00U) || (type == 0xc0U));
296     bool mc                = ((type == 0x80U) || (type == 0x00U) || (type == 0xc0U));
297     bool ucAddr;
298     bool delete;
299     uint8_t i;
300     status_t ret;
301 
302     /* Flush exact match table */
303     for (i = 0U; i < NUM_MAC_FILTER_ENTRY; i++)
304     {
305         /* entry not in use */
306         if (handle->macFilterCount[i] == 0U)
307         {
308             continue;
309         }
310 
311         (void)memset(&cmdBd, 0, sizeof(cmdBd));
312         cmdBd.generic.index = i;
313         cmdBd.generic.cmd   = 1U;
314         cmdBd.generic.class = 1U;
315         cmdBd.generic.ci    = 0U;
316         cmdBd.generic.sf    = 1U;
317 
318         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
319                                     kNETC_NtmpV1_0);
320         if (ret != kStatus_Success)
321         {
322             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
323         }
324 
325         ucAddr = ((cmdBd.generic.addr & 0x1U) == 0U);
326         delete = ((uc && ucAddr) || (mc && (!ucAddr)));
327 
328         if (!delete)
329         {
330             continue;
331         }
332 
333         if ((cmdBd.generic.siBitMap & ((uint32_t)1U << si)) == 0U)
334         {
335             continue;
336         }
337 
338         if (cmdBd.generic.siBitMap == ((uint32_t)1U << si))
339         {
340             cmdBd.generic.addr     = 0;
341             cmdBd.generic.siBitMap = 0;
342         }
343         else
344         {
345             cmdBd.generic.siBitMap &= ~((uint32_t)1U << si);
346         }
347         cmdBd.generic.en    = 1;
348         cmdBd.generic.index = i;
349         cmdBd.generic.cmd   = 0;
350         cmdBd.generic.class = 1;
351         cmdBd.generic.ci    = 0;
352         cmdBd.generic.sf    = 1;
353 
354         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&handle->hw.si->SICBDRMR, &handle->cmdBdRing, &cmdBd,
355                                     kNETC_NtmpV1_0);
356         if (ret != kStatus_Success)
357         {
358             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
359         }
360 
361         /* Update macFilterCount */
362         if (cmdBd.generic.siBitMap == ((uint32_t)1U << si))
363         {
364             handle->macFilterCount[i] = 0U;
365         }
366     }
367 
368     /* Flush hash table */
369     if (uc)
370     {
371         enetc->NUM_SI[si].PSIUMHFR0 = 0x0U;
372         enetc->NUM_SI[si].PSIUMHFR1 = 0x0U;
373     }
374 
375     if (mc)
376     {
377         enetc->NUM_SI[si].PSIMMHFR0 = 0x0U;
378         enetc->NUM_SI[si].PSIMMHFR1 = 0x0U;
379     }
380 
381     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
382 }
383 
EP_RxL2MFSetPromisc(ep_handle_t * handle,uint8_t si,uint8_t typeOp)384 static uint16_t EP_RxL2MFSetPromisc(ep_handle_t *handle, uint8_t si, uint8_t typeOp)
385 {
386     NETC_ENETC_Type *base = handle->hw.base;
387     bool enable           = ((typeOp & 0x2U) == 0x2U);
388     bool flush            = ((typeOp & 0x1U) == 0x1U);
389     uint8_t type          = (typeOp & 0xc0U);
390 
391     /* UC addresses */
392     if ((type == 0x40U) || (type == 0x00U) || (type == 0xc0U))
393     {
394         if (enable)
395         {
396             base->PSIPMMR |= ((uint32_t)NETC_ENETC_PSIPMMR_SI0_MAC_UP_MASK << si);
397         }
398         else
399         {
400             base->PSIPMMR &= ~((uint32_t)NETC_ENETC_PSIPMMR_SI0_MAC_UP_MASK << si);
401         }
402     }
403 
404     /* MC addresses */
405     if (type == 0x80U || (type == 0x00U) || (type == 0xc0U))
406     {
407         if (enable)
408         {
409             base->PSIPMMR |= ((uint32_t)NETC_ENETC_PSIPMMR_SI0_MAC_MP_MASK << si);
410         }
411         else
412         {
413             base->PSIPMMR &= ~((uint32_t)NETC_ENETC_PSIPMMR_SI0_MAC_MP_MASK << si);
414         }
415     }
416 
417     if (flush)
418     {
419         return EP_RxL2MFFlush(handle, si, type);
420     }
421 
422     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
423 }
424 
EP_PsiHandleMacFilter(ep_handle_t * handle,uint8_t vsi,netc_psi_rx_msg_t * msgInfo)425 static uint16_t EP_PsiHandleMacFilter(ep_handle_t *handle, uint8_t vsi, netc_psi_rx_msg_t *msgInfo)
426 {
427     NETC_ENETC_Type *base     = handle->hw.base;
428     netc_msg_header_t *header = (netc_msg_header_t *)(uint32_t)(msgInfo->msgBuff);
429     /* For exact table */
430     uint8_t count    = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x10U);
431     uint8_t *macAddr = (uint8_t *)((uint32_t)msgInfo->msgBuff + 0x14U);
432     /* For hash table */
433     uint8_t typeSize = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x10U);
434     uint8_t *HTWord  = (uint8_t *)((uint32_t)msgInfo->msgBuff + 0x14U);
435     /* For flush */
436     uint8_t type = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x10U);
437     /* For promisc */
438     uint8_t typeOp = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x10U);
439     uint16_t ret   = NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
440 
441     switch (header->cmdId)
442     {
443         case (uint8_t)kNETC_MsgMacFilterSetMacAddr:
444             NETC_EnetcSetSIMacAddr(base, vsi, macAddr);
445             ret = NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
446             break;
447         case (uint8_t)kNETC_MsgMacFilterAdd:
448             ret = EP_RxL2MFQueryAddEMTableEntry(handle, vsi, count, macAddr);
449             break;
450         case (uint8_t)kNETC_MsgMacFilterDelete:
451             ret = EP_RxL2MFQueryDeleteEMTableEntry(handle, vsi, count, macAddr);
452             break;
453         case (uint8_t)kNETC_MsgMacFilterSet:
454             ret = EP_RxL2MFSetHashTable(handle, vsi, typeSize, HTWord);
455             break;
456         case (uint8_t)kNETC_MsgMacFilterFlush:
457             ret = EP_RxL2MFFlush(handle, vsi, type);
458             break;
459         case (uint8_t)kNETC_MsgMacFilterSetMacPromisc:
460             ret = EP_RxL2MFSetPromisc(handle, vsi, typeOp);
461             break;
462         default:
463             /* To avoid MISRA-C 2012 rule 16.4 issue. */
464             break;
465     }
466 
467     return ret;
468 }
469 
470 /* VLAN filter Operations */
471 
EP_RxL2VFFreeNum(ep_handle_t * handle)472 static uint8_t EP_RxL2VFFreeNum(ep_handle_t *handle)
473 {
474     uint8_t n = 0;
475     uint8_t i;
476 
477     for (i = 0; i < NUM_VLAN_FILTER_ENTRY; i++)
478     {
479         if (handle->vlanFilterCount[i] == 0U)
480         {
481             n++;
482         }
483     }
484 
485     return n;
486 }
487 
EP_RxL2VFFreeIndex(ep_handle_t * handle,uint16_t * idx)488 static status_t EP_RxL2VFFreeIndex(ep_handle_t *handle, uint16_t *idx)
489 {
490     uint8_t i;
491 
492     for (i = 0; i < NUM_VLAN_FILTER_ENTRY; i++)
493     {
494         if (handle->vlanFilterCount[i] == 0U)
495         {
496             *idx = i;
497             return kStatus_Success;
498         }
499     }
500 
501     return kStatus_Fail;
502 }
503 
EP_RxL2VFQueryEMTableEntry(ep_handle_t * handle,uint8_t * vlanId,emtable_query_result_t * result)504 static void EP_RxL2VFQueryEMTableEntry(ep_handle_t *handle, uint8_t *vlanId, emtable_query_result_t *result)
505 {
506     uint64_t address    = *(uint32_t *)(uintptr_t)&vlanId[0];
507     ENETC_SI_Type *base = handle->hw.si;
508     netc_cmd_bd_t cmdBd = {0};
509     status_t ret;
510     uint8_t i;
511 
512     (void)memset(result, 0, sizeof(*result));
513 
514     /* Only PSI can access MAC filter table */
515     if (getSiNum(handle->cfg.si) != 0U)
516     {
517         return;
518     }
519 
520     /* Query each entry */
521     for (i = 0U; i < NUM_VLAN_FILTER_ENTRY; i++)
522     {
523         /* entry not in use */
524         if (handle->vlanFilterCount[i] == 0U)
525         {
526             continue;
527         }
528 
529         (void)memset(&cmdBd, 0, sizeof(cmdBd));
530         cmdBd.generic.index = i;
531         cmdBd.generic.cmd   = 1U;
532         cmdBd.generic.class = 2U;
533         cmdBd.generic.ci    = 0U;
534         cmdBd.generic.sf    = 1U;
535         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
536                                     kNETC_NtmpV1_0);
537         if (ret != kStatus_Success)
538         {
539             result->valid = 0U;
540             return;
541         }
542 
543         if (cmdBd.generic.addr == address)
544         {
545             result->valid    = 1U;
546             result->match    = 1U;
547             result->siBitMap = (uint16_t)cmdBd.generic.siBitMap;
548             result->index    = i;
549             return;
550         }
551     }
552 
553     result->valid = 1U;
554     return;
555 }
556 
EP_RxL2VFQueryAddEMTableEntry(ep_handle_t * handle,uint8_t si,uint8_t count,uint8_t * vlanId)557 static uint16_t EP_RxL2VFQueryAddEMTableEntry(ep_handle_t *handle, uint8_t si, uint8_t count, uint8_t *vlanId)
558 {
559     emtable_query_result_t result[NUM_VLAN_FILTER_ENTRY] = {0};
560     ENETC_SI_Type *base                                  = handle->hw.si;
561     netc_cmd_bd_t cmdBd                                  = {0};
562     uint8_t free_num                                     = EP_RxL2VFFreeNum(handle);
563     uint8_t match_num                                    = 0U;
564     uint8_t i, m;
565     status_t ret;
566     uint64_t address;
567     uint16_t index = 0U;
568 
569     /* Check count */
570     if (count == 0U)
571     {
572         return NETC_MSG_RETURN_CODE(kNETC_MsgClassVlanFilter, kNETC_MsgVlanFilterInvalidVlan, 0U);
573     }
574 
575     if (count > NUM_VLAN_FILTER_ENTRY)
576     {
577         return NETC_MSG_RETURN_CODE(kNETC_MsgClassVlanFilter, kNETC_MsgVlanFilterNoResource, 0U);
578     }
579 
580     /* Query for each VLAN ID */
581     for (i = 0U; i < count; i++)
582     {
583         EP_RxL2VFQueryEMTableEntry(handle, &vlanId[i * 4U], &result[i]);
584         if (result[i].valid == 0U)
585         {
586             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
587         }
588         if (result[i].match == 1U)
589         {
590             match_num++;
591         }
592     }
593 
594     /* Check resource */
595     if ((count - match_num) > free_num)
596     {
597         return NETC_MSG_RETURN_CODE(kNETC_MsgClassVlanFilter, kNETC_MsgVlanFilterNoResource, 0U);
598     }
599 
600     for (i = 0U; i < count; i++)
601     {
602         m       = 4U * i;
603         address = *(uint32_t *)(uintptr_t)&vlanId[m];
604 
605         (void)memset(&cmdBd, 0, sizeof(cmdBd));
606         cmdBd.generic.addr  = address;
607         cmdBd.generic.en    = 1;
608         cmdBd.generic.cmd   = 0;
609         cmdBd.generic.class = 1;
610         cmdBd.generic.ci    = 0;
611         cmdBd.generic.sf    = 1;
612 
613         /* For matched */
614         if (result[i].match == 1U)
615         {
616             cmdBd.generic.index    = result[i].index;
617             cmdBd.generic.siBitMap = (result[i].siBitMap | ((uint32_t)1U << si));
618         }
619         /* For new added */
620         else
621         {
622             if (EP_RxL2VFFreeIndex(handle, &index) != kStatus_Success)
623             {
624                 return NETC_MSG_RETURN_CODE(kNETC_MsgClassVlanFilter, kNETC_MsgVlanFilterNoResource, 0U);
625             }
626             cmdBd.generic.index    = index;
627             cmdBd.generic.siBitMap = ((uint32_t)1U << si);
628         }
629 
630         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
631                                     kNETC_NtmpV1_0);
632         if (ret != kStatus_Success)
633         {
634             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
635         }
636 
637         /* Update vlanFilterCount */
638         handle->vlanFilterCount[cmdBd.generic.index] = 1U;
639     }
640 
641     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
642 }
643 
EP_RxL2VFQueryDeleteEMTableEntry(ep_handle_t * handle,uint8_t si,uint8_t count,uint8_t * vlanId)644 static uint16_t EP_RxL2VFQueryDeleteEMTableEntry(ep_handle_t *handle, uint8_t si, uint8_t count, uint8_t *vlanId)
645 {
646     emtable_query_result_t result[NUM_VLAN_FILTER_ENTRY] = {0};
647     ENETC_SI_Type *base                                  = handle->hw.si;
648     netc_cmd_bd_t cmdBd                                  = {0};
649     uint8_t i;
650     status_t ret;
651 
652     if (count == 0U)
653     {
654         return NETC_MSG_RETURN_CODE(kNETC_MsgClassVlanFilter, kNETC_MsgVlanFilterInvalidVlan, 0U);
655     }
656 
657     /* Query for each VLAN ID */
658     for (i = 0U; i < count; i++)
659     {
660         EP_RxL2VFQueryEMTableEntry(handle, &vlanId[i * 4U], &result[i]);
661         if (result[i].valid == 0U)
662         {
663             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
664         }
665         if (result[i].match == 0U)
666         {
667             return NETC_MSG_RETURN_CODE(kNETC_MsgClassVlanFilter, kNETC_MsgVlanFilterAddrNotFound, 0U);
668         }
669     }
670 
671     for (i = 0U; i < count; i++)
672     {
673         (void)memset(&cmdBd, 0, sizeof(cmdBd));
674 
675         cmdBd.generic.addr     = 0;
676         cmdBd.generic.en       = 1;
677         cmdBd.generic.siBitMap = 0;
678         cmdBd.generic.index    = result[i].index;
679         cmdBd.generic.cmd      = 0;
680         cmdBd.generic.class    = 2;
681         cmdBd.generic.ci       = 0;
682         cmdBd.generic.sf       = 1;
683 
684         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
685                                     kNETC_NtmpV1_0);
686         if (ret != kStatus_Success)
687         {
688             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
689         }
690 
691         /* Update vlanFilterCount */
692         handle->vlanFilterCount[result[i].index] = 0U;
693     }
694 
695     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
696 }
697 
EP_RxL2VFSetHashTable(ep_handle_t * handle,uint8_t si,uint8_t size,uint8_t * HTWord)698 static uint16_t EP_RxL2VFSetHashTable(ep_handle_t *handle, uint8_t si, uint8_t size, uint8_t *HTWord)
699 {
700     NETC_ENETC_Type *base = handle->hw.base;
701     uint32_t HTWord0      = *(uint32_t *)((uint32_t)HTWord);
702     uint32_t HTWord1      = *(uint32_t *)((uint32_t)HTWord + 0x4U);
703 
704     /* 64bits addr supported only */
705     if (size != 0U)
706     {
707         return NETC_MSG_RETURN_CODE(kNETC_MsgClassVlanFilter, kNETC_MsgVlanFilterNotSupported, 0U);
708     }
709 
710     base->NUM_SI[si].PSIVHFR0 = HTWord0;
711     base->NUM_SI[si].PSIVHFR1 = HTWord1;
712 
713     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
714 }
715 
EP_RxL2VFFlush(ep_handle_t * handle,uint8_t si)716 static uint16_t EP_RxL2VFFlush(ep_handle_t *handle, uint8_t si)
717 {
718     NETC_ENETC_Type *enetc = handle->hw.base;
719     ENETC_SI_Type *base    = handle->hw.si;
720     netc_cmd_bd_t cmdBd    = {0};
721     uint8_t i;
722     status_t ret;
723 
724     /* Flush exact match table */
725     for (i = 0U; i < NUM_MAC_FILTER_ENTRY; i++)
726     {
727         /* entry not in use */
728         if (handle->macFilterCount[i] == 0U)
729         {
730             continue;
731         }
732 
733         (void)memset(&cmdBd, 0, sizeof(cmdBd));
734         cmdBd.generic.index = i;
735         cmdBd.generic.cmd   = 1U;
736         cmdBd.generic.class = 2U;
737         cmdBd.generic.ci    = 0U;
738         cmdBd.generic.sf    = 1U;
739 
740         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
741                                     kNETC_NtmpV1_0);
742         if (ret != kStatus_Success)
743         {
744             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
745         }
746 
747         if ((cmdBd.generic.siBitMap & ((uint32_t)1U << si)) == 0U)
748         {
749             continue;
750         }
751 
752         if (cmdBd.generic.siBitMap == ((uint32_t)1U << si))
753         {
754             cmdBd.generic.addr     = 0;
755             cmdBd.generic.siBitMap = 0;
756         }
757         else
758         {
759             cmdBd.generic.siBitMap &= ~((uint32_t)1U << si);
760         }
761         cmdBd.generic.en    = 1;
762         cmdBd.generic.index = i;
763         cmdBd.generic.cmd   = 0;
764         cmdBd.generic.class = 2;
765         cmdBd.generic.ci    = 0;
766         cmdBd.generic.sf    = 1;
767 
768         ret = NETC_CmdBDSendCommand((netc_cbdr_hw_t *)(uintptr_t)&base->SICBDRMR, &handle->cmdBdRing, &cmdBd,
769                                     kNETC_NtmpV1_0);
770         if (ret != kStatus_Success)
771         {
772             return NETC_MSG_RETURN_CODE(kNETC_MsgClassTimeout, 0U, 0U);
773         }
774 
775         /* Update vlanFilterCount */
776         if (cmdBd.generic.siBitMap == ((uint32_t)1U << si))
777         {
778             handle->vlanFilterCount[i] = 0U;
779         }
780     }
781 
782     /* Flush hash table */
783     enetc->NUM_SI[si].PSIVHFR0 = 0x0U;
784     enetc->NUM_SI[si].PSIVHFR1 = 0x0U;
785 
786     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
787 }
788 
EP_RxL2VFSetPromisc(ep_handle_t * handle,uint8_t si,uint8_t op)789 static uint16_t EP_RxL2VFSetPromisc(ep_handle_t *handle, uint8_t si, uint8_t op)
790 {
791     NETC_ENETC_Type *base = handle->hw.base;
792     bool enable           = ((op & 0x1U) == 0x1U);
793     bool flush            = ((op & 0x2U) == 0x2U);
794 
795     if (enable)
796     {
797         base->PSIPVMR |= ((uint32_t)NETC_ENETC_PSIPVMR_SI0_VLAN_P_MASK << si);
798     }
799     else
800     {
801         base->PSIPVMR &= ~((uint32_t)NETC_ENETC_PSIPVMR_SI0_VLAN_P_MASK << si);
802     }
803 
804     if (flush)
805     {
806         return EP_RxL2VFFlush(handle, si);
807     }
808 
809     return NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
810 }
811 
EP_PsiHandleVlanFilter(ep_handle_t * handle,uint8_t vsi,netc_psi_rx_msg_t * msgInfo)812 static uint16_t EP_PsiHandleVlanFilter(ep_handle_t *handle, uint8_t vsi, netc_psi_rx_msg_t *msgInfo)
813 {
814     netc_msg_header_t *header = (netc_msg_header_t *)(uint32_t)(msgInfo->msgBuff);
815     /* For exact table */
816     uint8_t count   = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x10U);
817     uint8_t *vlanId = (uint8_t *)((uint32_t)msgInfo->msgBuff + 0x14U);
818     /* For hash table */
819     uint8_t size    = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x10U);
820     uint8_t *HTWord = (uint8_t *)((uint32_t)msgInfo->msgBuff + 0x14U);
821     /* For promisc */
822     uint8_t op   = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x10U);
823     uint16_t ret = NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
824 
825     switch (header->cmdId)
826     {
827         case (uint8_t)kNETC_MsgVlanFilterAdd:
828             ret = EP_RxL2VFQueryAddEMTableEntry(handle, vsi, count, vlanId);
829             break;
830         case (uint8_t)kNETC_MsgVlanFilterDelete:
831             ret = EP_RxL2VFQueryDeleteEMTableEntry(handle, vsi, count, vlanId);
832             break;
833         case (uint8_t)kNETC_MsgVlanFilterSet:
834             ret = EP_RxL2VFSetHashTable(handle, vsi, size, HTWord);
835             break;
836         case (uint8_t)kNETC_MsgVlanFilterFlush:
837             ret = EP_RxL2VFFlush(handle, vsi);
838             break;
839         case (uint8_t)kNETC_MsgVlanFilterSetVlanPromisc:
840             ret = EP_RxL2VFSetPromisc(handle, vsi, op);
841             break;
842         default:
843             /* To avoid MISRA-C 2012 rule 16.4 issue. */
844             break;
845     }
846 
847     return ret;
848 }
849 
850 /* Link status operations */
851 
EP_GetLinkStatus(ep_handle_t * handle)852 static uint16_t EP_GetLinkStatus(ep_handle_t *handle)
853 {
854     uint8_t link = 0U;
855     status_t status;
856 
857     if (handle->getLinkStatus == NULL)
858     {
859         return NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
860     }
861 
862     status = handle->getLinkStatus(handle, &link);
863     if (status != kStatus_Success)
864     {
865         return NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
866     }
867 
868     return NETC_MSG_RETURN_CODE(kNETC_MsgClassLinkStatus, (link == 0U ? 0x1U : 0x0U), 0U);
869 }
870 
EP_PsiHandleLinkStatus(ep_handle_t * handle,uint8_t vsi,netc_psi_rx_msg_t * msgInfo)871 static uint16_t EP_PsiHandleLinkStatus(ep_handle_t *handle, uint8_t vsi, netc_psi_rx_msg_t *msgInfo)
872 {
873     netc_msg_header_t *header = (netc_msg_header_t *)(uint32_t)(msgInfo->msgBuff);
874     uint16_t ret              = NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
875 
876     switch (header->cmdId)
877     {
878         case (uint8_t)kNETC_MsgLinkStatusGet:
879             ret = EP_GetLinkStatus(handle);
880             break;
881         case (uint8_t)kNETC_MsgLinkStatusEnableNotify:
882             handle->vsiBitMapNotifyLinkStatus |= ((uint16_t)1U << vsi);
883             ret = NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
884             break;
885         case (uint8_t)kNETC_MsgLinkStatusCancelNotify:
886             handle->vsiBitMapNotifyLinkStatus &= ~((uint16_t)1U << vsi);
887             ret = NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
888             break;
889         default:
890             /* To avoid MISRA-C 2012 rule 16.4 issue. */
891             break;
892     }
893 
894     return ret;
895 }
896 
897 /* Link speed operations */
898 
EP_GetLinkSpeed(ep_handle_t * handle)899 static uint16_t EP_GetLinkSpeed(ep_handle_t *handle)
900 {
901     netc_hw_mii_speed_t speed;
902     netc_hw_mii_duplex_t duplex;
903     netc_msg_link_speed_code_t code;
904 
905     status_t status;
906 
907     if (handle->getLinkSpeed == NULL)
908     {
909         return NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
910     }
911 
912     status = handle->getLinkSpeed(handle, &speed, &duplex);
913     if (status != kStatus_Success)
914     {
915         return NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
916     }
917 
918     switch (speed)
919     {
920         case (kNETC_MiiSpeed10M):
921             code = ((duplex == kNETC_MiiHalfDuplex) ? kNETC_MsgLinkSpeed10HD : kNETC_MsgLinkSpeed10FD);
922             break;
923         case (kNETC_MiiSpeed100M):
924             code = ((duplex == kNETC_MiiHalfDuplex) ? kNETC_MsgLinkSpeed100HD : kNETC_MsgLinkSpeed100FD);
925             break;
926         case (kNETC_MiiSpeed1000M):
927             code = kNETC_MsgLinkSpeed1000;
928             break;
929         case (kNETC_MiiSpeed2500M):
930             code = kNETC_MsgLinkSpeed2500;
931             break;
932         case (kNETC_MiiSpeed5G):
933             code = kNETC_MsgLinkSpeed5000;
934             break;
935         case (kNETC_MiiSpeed10G):
936             code = kNETC_MsgLinkSpeed10G;
937             break;
938         default:
939             code = kNETC_MsgLinkSpeedNotSupport;
940             break;
941     }
942 
943     return NETC_MSG_RETURN_CODE(kNETC_MsgClassLinkSpeed, code, 0U);
944 }
945 
EP_PsiHandleLinkSpeed(ep_handle_t * handle,uint8_t vsi,netc_psi_rx_msg_t * msgInfo)946 static uint16_t EP_PsiHandleLinkSpeed(ep_handle_t *handle, uint8_t vsi, netc_psi_rx_msg_t *msgInfo)
947 {
948     netc_msg_header_t *header = (netc_msg_header_t *)(uint32_t)(msgInfo->msgBuff);
949     uint16_t ret              = NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
950 
951     switch (header->cmdId)
952     {
953         case (uint8_t)kNETC_MsgLinkSpeedGet:
954             ret = EP_GetLinkSpeed(handle);
955             break;
956         case (uint8_t)kNETC_MsgLinkSpeedEnableNotify:
957             handle->vsiBitMapNotifyLinkSpeed |= ((uint16_t)1U << vsi);
958             ret = NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
959             break;
960         case (uint8_t)kNETC_MsgLinkSpeedCancelNotify:
961             handle->vsiBitMapNotifyLinkSpeed &= ~((uint16_t)1U << vsi);
962             ret = NETC_MSG_RETURN_CODE(kNETC_MsgClassDone, 0U, 0U);
963             break;
964         default:
965             /* To avoid MISRA-C 2012 rule 16.4 issue. */
966             break;
967     }
968 
969     return ret;
970 }
971 
EP_PsiNotifyLink(ep_handle_t * handle)972 void EP_PsiNotifyLink(ep_handle_t *handle)
973 {
974     ENETC_SI_Type *base = handle->hw.si;
975     uint16_t code;
976 
977     if (handle->vsiBitMapNotifyLinkStatus != 0U)
978     {
979         code = EP_GetLinkStatus(handle);
980         if (code != NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U))
981         {
982             base->PSI_A.PSIMSGSR = (uint32_t)handle->vsiBitMapNotifyLinkStatus | ((uint32_t)code << 16U);
983         }
984     }
985 
986     if (handle->vsiBitMapNotifyLinkSpeed != 0U)
987     {
988         code = EP_GetLinkSpeed(handle);
989         if (code != NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U))
990         {
991             base->PSI_A.PSIMSGSR = (uint32_t)handle->vsiBitMapNotifyLinkSpeed | ((uint32_t)code << 16U);
992         }
993     }
994 }
995 
EP_PsiRxMsg(ep_handle_t * handle,netc_vsi_number_t vsi,netc_psi_rx_msg_t * msgInfo)996 status_t EP_PsiRxMsg(ep_handle_t *handle, netc_vsi_number_t vsi, netc_psi_rx_msg_t *msgInfo)
997 {
998     ENETC_SI_Type *base = handle->hw.si;
999     status_t result     = kStatus_Fail;
1000     uint16_t siBitMap   = (uint16_t)base->PSI_A.PSIMSGRR;
1001     uint8_t vsiIdx      = (uint8_t)NETC_SIGetVsiIndex(vsi);
1002     uint64_t address;
1003     uint8_t msgSize;
1004     uint32_t addrH;
1005     uint32_t addrL;
1006 
1007     if ((siBitMap & (uint16_t)vsi) != 0U)
1008     {
1009         addrH   = base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR1;
1010         addrL   = base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR0 & ENETC_SI_PSIVMSGRCVAR0_ADDRL_MASK;
1011         address = ((uint64_t)addrH << 32U) + addrL;
1012 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
1013         address = (uint64_t)MEMORY_ConvertMemoryMapAddress((uintptr_t)address, kMEMORY_DMA2Local);
1014 #endif
1015         msgInfo->msgBuff = (uint8_t *)(uintptr_t)address;
1016         msgSize          = (uint8_t)(base->PSI_A.VSI_NUM[vsiIdx].PSIVMSGRCVAR0 & ENETC_SI_PSIVMSGRCVAR0_MSIZE_MASK);
1017         msgInfo->msgLen  = (msgSize == 0U) ? 1024U : (32U * (uint32_t)msgSize);
1018 
1019         result = kStatus_Success;
1020     }
1021     return result;
1022 }
1023 
EP_PsiHandleRxMsg(ep_handle_t * handle,uint8_t vsi,netc_psi_rx_msg_t * msgInfo)1024 void EP_PsiHandleRxMsg(ep_handle_t *handle, uint8_t vsi, netc_psi_rx_msg_t *msgInfo)
1025 {
1026     netc_msg_header_t *header = (netc_msg_header_t *)(uint32_t)(msgInfo->msgBuff);
1027     uint8_t crc0              = *(uint8_t *)(msgInfo->msgBuff);
1028     uint8_t crc1              = *(uint8_t *)((uint32_t)msgInfo->msgBuff + 0x1U);
1029     uint16_t code             = NETC_MSG_RETURN_CODE(kNETC_MsgClassNotSupport, 0U, 0U);
1030     ENETC_SI_Type *base       = handle->hw.si;
1031     bool notify               = false;
1032     uint32_t crc;
1033     hal_crc_config_t config   = {
1034         .crcSize            = 2U,
1035         .crcStartByte       = 2U,
1036         .crcRefIn           = KHAL_CrcInputNoRef,
1037         .crcRefOut          = KHAL_CrcOutputNoRef,
1038         .crcByteOrder       = KHAL_CrcMSByteFirst,
1039         .complementChecksum = 0U,
1040         .crcSeed            = 0xFFFFU,
1041         .crcPoly            = (uint32_t)KHAL_CrcPolynomial_CRC_16,
1042         .crcXorOut          = 0x0000U,
1043     };
1044 
1045     if (msgInfo->msgLen != (((uint32_t)header->len + 1U) * 32U))
1046     {
1047         code = NETC_MSG_RETURN_CODE(kNETC_MsgClassLenError, 0U, 0U);
1048         goto out;
1049     }
1050 
1051     crc = HAL_CrcCompute(&config, (uint8_t *)msgInfo->msgBuff, msgInfo->msgLen);
1052     if (((crc & 0xffU) != (uint32_t)crc1) || (((crc >> 8U) & 0xffU) != (uint32_t)crc0))
1053     {
1054         code = NETC_MSG_RETURN_CODE(kNETC_MsgClassCsumError, 0U, 0U);
1055         goto out;
1056     }
1057 
1058     switch (header->classId)
1059     {
1060         case (uint8_t)kNETC_MsgClassMacFilter:
1061             code = EP_PsiHandleMacFilter(handle, vsi, msgInfo);
1062             break;
1063         case (uint8_t)kNETC_MsgClassVlanFilter:
1064             code = EP_PsiHandleVlanFilter(handle, vsi, msgInfo);
1065             break;
1066         case (uint8_t)kNETC_MsgClassLinkStatus:
1067             code = EP_PsiHandleLinkStatus(handle, vsi, msgInfo);
1068             if (header->cmdId == (uint8_t)kNETC_MsgLinkStatusEnableNotify)
1069             {
1070                 notify = true;
1071             }
1072             break;
1073         case (uint8_t)kNETC_MsgClassLinkSpeed:
1074             code = EP_PsiHandleLinkSpeed(handle, vsi, msgInfo);
1075             if (header->cmdId == (uint8_t)kNETC_MsgLinkSpeedEnableNotify)
1076             {
1077                 notify = true;
1078             }
1079             break;
1080         case (uint8_t)kNETC_MsgClassTimerSyncStatus:
1081             break;
1082         case (uint8_t)kNETC_MsgClassIpVersion:
1083             break;
1084         default:
1085             /* To avoid MISRA-C 2012 rule 16.4 issue. */
1086             break;
1087     }
1088 
1089 out:
1090     base->PSI_A.PSIMSGRR = ((uint32_t)vsi << 1U) | ((uint32_t)code << 16U);
1091 
1092     if (notify)
1093     {
1094         EP_PsiNotifyLink(handle);
1095     }
1096 }
1097