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