1 /*
2 * Copyright (c) Texas Instruments Incorporated 2021
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
33 /*!
34 * \file icssg_enet_test.c
35 *
36 * \brief This file contains the implementation of the Enet lld with icssg example.
37 */
39 /* ========================================================================== */
40 /* Include Files */
41 /* ========================================================================== */
43 #include "icssg_enet_test.h"
45 /* ========================================================================== */
46 /* Macros & Typedefs */
47 /* ========================================================================== */
50 /* ========================================================================== */
51 /* Structure Declarations */
52 /* ========================================================================== */
55 /* ========================================================================== */
56 /* Function Declarations */
57 /* ========================================================================== */
59 static int32_t EnetIg_init(void);
61 static void EnetIg_deinit(void);
63 static int32_t EnetIg_open(EnetIg_PerCtxt *perCtxts,
64 uint32_t numPerCtxts);
66 static void EnetIg_close(EnetIg_PerCtxt *perCtxts,
67 uint32_t numPerCtxts);
69 static int32_t EnetIg_openPort(EnetIg_PerCtxt *perCtxt);
71 static void EnetIg_closePort(EnetIg_PerCtxt *perCtxt);
73 static void EnetIg_printStats(EnetIg_PerCtxt *perCtxts,
74 uint32_t numPerCtxts);
76 static void EnetIg_resetStats(EnetIg_PerCtxt *perCtxts, uint32_t numPerCtxts);
78 static int32_t EnetIg_waitForLinkUp(EnetIg_PerCtxt *perCtxt);
80 static void EnetIg_macMode2MacMii(emac_mode macMode,
81 EnetMacPort_Interface *mii);
83 static int32_t EnetIg_openDma(EnetIg_PerCtxt *perCtxt);
85 static void EnetIg_closeDma(EnetIg_PerCtxt *perCtxt);
87 static void EnetIg_initTxFreePktQ(void);
89 static void EnetIg_initRxReadyPktQ(EnetDma_RxChHandle hRxCh);
91 static uint32_t EnetIg_retrieveFreeTxPkts(EnetIg_PerCtxt *perCtxt);
93 static uint32_t BoardDiag_EnetIg_LpbkTxRx(void);
95 static uint32_t BoardDiag_EnetIg_Receive(EnetIg_PerCtxt *perCtxt);
97 static void BoardDiag_EnetIg_txIsrFxn(void *appData);
99 static void BoardDiag_EnetIg_rxIsrFxn(void *appData);
101 static int32_t BoardDiag_EnetIg_LpbckTest(EnetIg_PerCtxt *perCtxt, uint32_t numPerCtxts);
103 static void BoardDiag_printFrame(EthFrame *frame, uint32_t len);
105 static void BoardDiag_printMacAddr(uint8_t macAddr[]);
107 static uint32_t BoardDiag_EnetIg_Transmit(EnetIg_PerCtxt *txPerCtxt, EnetIg_PerCtxt *rxPerCtxt);
109 static void EnetIg_PortSelect(void);
111 /* ========================================================================== */
112 /* Global Variables */
113 /* ========================================================================== */
115 /* Enet Icssg Test Object */
116 EnetIg_Obj gEnetIg;
118 /* Statistics */
119 IcssgStats_MacPort gEnetIg_icssgStats;
120 IcssgStats_Pa gEnetIg_icssgPaStats;
122 bool printFrameEnable = false;
123 bool printStatsEnable = false;
125 static uint32_t gEnetLpbk_IterationCount;
127 /* Use this array to select the ports that will be used in the test */
128 const EnetIg_TestParams testParams[ENETIG_ICSSG_MAX_PORTS] =
129 {
130 /* ICSSG0 mode: DUALMAC */
131 { ENET_ICSSG_DUALMAC, 0U, { ENET_MAC_PORT_1 }, 1U, "icssg0-p1", },
132 { ENET_ICSSG_DUALMAC, 1U, { ENET_MAC_PORT_1 }, 1U, "icssg0-p2", },
133 /* ICSSG1 mode: DUALMAC */
134 { ENET_ICSSG_DUALMAC, 2U, { ENET_MAC_PORT_1 }, 1U, "icssg1-p1", },
135 { ENET_ICSSG_DUALMAC, 3U, { ENET_MAC_PORT_1 }, 1U, "icssg1-p2", },
136 /* ICSSG2 mode: DUALMAC */
137 { ENET_ICSSG_DUALMAC, 4U, { ENET_MAC_PORT_1 }, 1U, "icssg2-p1", },
138 { ENET_ICSSG_DUALMAC, 5U, { ENET_MAC_PORT_1 }, 1U, "icssg2-p2", },
139 };
141 /* ========================================================================== */
142 /* Function Definitions */
143 /* ========================================================================== */
145 int main(void)
146 {
147 int32_t status;
149 /* Board level initialization, UART might not be setup before this hence no prints yet */
150 status = EnetBoard_init();
151 if(status != ENET_SOK)
152 {
153 EnetAppUtils_print("\nBoard init failed with status: %d\n", status);
154 return status;
155 }
157 EnetIg_PortSelect();
159 for (gEnetIg.loopCnt = 0U; gEnetIg.loopCnt < gEnetLpbk_IterationCount; gEnetIg.loopCnt++)
160 {
161 EnetAppUtils_print("\n\n*******Iteration %d********\n", gEnetIg.loopCnt + 1);
163 /* Init driver */
164 status = EnetIg_init();
165 if (status != ENET_SOK)
166 {
167 EnetAppUtils_print("\nInitialization failed: %d\n", status);
168 return status;
169 }
171 /* Open all peripherals */
172 if (status == ENET_SOK)
173 {
174 status = EnetIg_open(gEnetIg.perCtxt, gEnetIg.numPerCtxts);
175 if (status != ENET_SOK)
176 {
177 EnetAppUtils_print("\nFailed to open peripherals: %d\n", status);
178 }
179 }
181 if (status == ENET_SOK)
182 {
183 status = BoardDiag_EnetIg_LpbckTest(gEnetIg.perCtxt, gEnetIg.numPerCtxts);
184 }
186 if(status == ENET_SOK)
187 {
188 EnetAppUtils_print("\n\nTest Passed");
189 }
190 else
191 {
192 EnetAppUtils_print("\n\nTest Failed");
193 }
195 /* Close all peripherals */
196 EnetIg_close(gEnetIg.perCtxt, gEnetIg.numPerCtxts);
198 /* Deinit driver */
199 EnetIg_deinit();
200 }
202 /* Board level deinitialization */
203 EnetBoard_deinit();
205 return 0;
206 }
208 static void EnetIg_PortSelect(void)
209 {
210 uint8_t i;
211 uint8_t j;
212 uint8_t port[ENETIG_ICSSG_INSTANCE_MAX] = {0};
214 #if defined(am65xx_evm)
215 /* Select port 4 and port 5 */
216 port[0] = 4;
217 port[1] = 5;
218 #elif defined(am65xx_idk)
219 /* Can change this to 0 and 1, 4 and 5 for IDK */
220 /* Select port 2 and port 3 */
221 port[0] = 2;
222 port[1] = 3;
223 #else
224 EnetAppUtils_print("\nBoard not supported for this test");
225 #endif
227 /* Initialize test config */
228 memset(&gEnetIg, 0, sizeof(gEnetIg));
230 gEnetIg.numPerCtxts = ENETIG_ICSSG_INSTANCE_MAX;
232 for(i = 0; i < gEnetIg.numPerCtxts; i++)
233 {
234 gEnetIg.perCtxt[i].enetType = testParams[port[i]].enetType;
235 gEnetIg.perCtxt[i].instId = testParams[port[i]].instId;
236 gEnetIg.perCtxt[i].name = testParams[port[i]].name;
238 gEnetIg.perCtxt[i].macPortNum = testParams[port[i]].macPortNum;
239 for (j = 0; j < gEnetIg.perCtxt[port[i]].macPortNum; j++)
240 {
241 gEnetIg.perCtxt[i].macPort[j] = testParams[port[i]].macPort[j];
242 }
243 }
244 EnetAppUtils_print("\nEnter number of iterations to test:");
245 gEnetLpbk_IterationCount = (uint32_t)EnetAppUtils_getNum();
246 }
248 static int32_t EnetIg_init(void)
249 {
250 EnetOsal_Cfg osalCfg;
251 EnetUtils_Cfg utilsCfg;
252 int32_t status = ENET_SOK;
254 /* Initialize Enet driver (use default OSAL and utils) */
255 EnetAppUtils_print("\nInit Enet's OSAL and utils to use defaults");
256 Enet_initOsalCfg(&osalCfg);
257 Enet_initUtilsCfg(&utilsCfg);
258 Enet_init(&osalCfg, &utilsCfg);
260 gEnetIg.coreId = EnetSoc_getCoreId();
262 /* Initialize memory */
263 EnetAppUtils_print("\nInit memory utils");
264 status = EnetMem_init();
265 if (status != ENET_SOK)
266 {
267 EnetAppUtils_print("\nFailed to initialize memory utils: %d\n", status);
268 EnetAppUtils_assert(false);
269 }
271 /* Initialize all queues */
272 EnetQueue_initQ(&gEnetIg.txFreePktInfoQ);
274 /* Open UDMA driver which is the same handle to be used for all peripherals */
275 if (status == ENET_SOK)
276 {
277 EnetAppUtils_print("\nOpen Main UDMA driver");
278 gEnetIg.hMainUdmaDrv = EnetAppUtils_udmaOpen(ENET_ICSSG_DUALMAC, NULL);
279 if (gEnetIg.hMainUdmaDrv == NULL)
280 {
281 EnetAppUtils_print("\nFailed to open Main UDMA driver: %d\n", status);
282 status = ENET_EALLOC;
283 EnetAppUtils_assert(false);
284 }
285 }
287 return status;
288 }
290 static void EnetIg_asyncIoctlCb(Enet_Event evt,
291 uint32_t evtNum,
292 void *evtCbArgs,
293 void *arg1,
294 void *arg2)
295 {
296 EnetIg_PerCtxt *perCtxt = (EnetIg_PerCtxt *)evtCbArgs;
298 EnetAppUtils_print("\n%s: Async IOCTL completed\n", perCtxt->name);
299 perCtxt->hAsyncIoctlSem = true;
300 }
302 static void EnetIg_txTsCb(Enet_Event evt,
303 uint32_t evtNum,
304 void *evtCbArgs,
305 void *arg1,
306 void *arg2)
307 {
308 EnetIg_PerCtxt *perCtxt = (EnetIg_PerCtxt *)evtCbArgs;
309 Icssg_TxTsEvtCbInfo *txTsInfo = (Icssg_TxTsEvtCbInfo *)arg1;
310 Enet_MacPort macPort = *(Enet_MacPort *)arg2;
311 uint32_t tsId = txTsInfo->txTsId;
312 uint64_t txTs = txTsInfo->ts;
313 uint64_t rxTs = perCtxt->rxTs[tsId % ENET_MEM_NUM_RX_PKTS];
314 uint64_t prevTs;
315 int64_t dt;
316 bool status = true;
318 dt = txTs - rxTs;
320 EnetAppUtils_print("\n%s: Port %u: RX-to-TX timestamp delta = %10lld (RX=%llu, TX=%llu)\n",
321 perCtxt->name, ENET_MACPORT_ID(macPort), dt, rxTs, txTs);
323 /* Check correct timestamp delta */
324 if (dt < 0)
325 {
326 EnetAppUtils_print("\n%s: Port %u: ERROR: RX timestamp > TX timestamp: %llu > %llu\n",
327 perCtxt->name, ENET_MACPORT_ID(macPort), rxTs, txTs);
328 status = false;
329 }
331 /* Check monotonicity of the TX and RX timestamps */
332 if (txTsInfo->txTsId > 0U)
333 {
334 prevTs = perCtxt->rxTs[(tsId - 1) % ENET_MEM_NUM_RX_PKTS];
335 if (prevTs > rxTs)
336 {
337 EnetAppUtils_print("\n%s: Port %u: ERROR: Non monotonic RX timestamp: %llu -> %llu\n",
338 perCtxt->name, ENET_MACPORT_ID(macPort), prevTs, rxTs);
339 status = false;
340 }
342 prevTs = perCtxt->txTs[(tsId - 1) % ENET_MEM_NUM_RX_PKTS];
343 if (prevTs > txTs)
344 {
345 EnetAppUtils_print("\n%s: Port %u: ERROR: Non monotonic TX timestamp: %llu -> %llu\n",
346 perCtxt->name, ENET_MACPORT_ID(macPort), prevTs, txTs);
347 status = false;
348 }
349 }
351 if (!status)
352 {
353 EnetAppUtils_print("\n");
354 }
356 /* Save current timestamp for future monotonicity checks */
357 perCtxt->txTs[txTsInfo->txTsId % ENET_MEM_NUM_RX_PKTS] = txTs;
359 perCtxt->hTxTsSem = true;
360 }
362 static void EnetIg_deinit(void)
363 {
364 /* Close UDMA driver if not closed */
365 EnetAppUtils_print("\nClose UDMA driver");
366 if(gEnetIg.hMainUdmaDrv != NULL)
367 {
368 EnetAppUtils_udmaclose(gEnetIg.hMainUdmaDrv);
369 }
371 if(gEnetIg.hMcuUdmaDrv != NULL)
372 {
373 EnetAppUtils_udmaclose(gEnetIg.hMcuUdmaDrv);
374 }
376 /* Deinitialize Enet driver (use default OSAL and utils) */
377 EnetAppUtils_print("\nDeinit Enet driver");
378 Enet_deinit();
380 /* Deinitialize memory */
381 EnetAppUtils_print("\nDeinit memory utils");
382 EnetMem_deInit();
384 EnetAppUtils_print("\nDeinit complete");
385 }
387 static int32_t EnetIg_open(EnetIg_PerCtxt *perCtxts,
388 uint32_t numPerCtxts)
389 {
390 EnetUdma_Cfg *dmaCfg;
391 EnetRm_ResCfg *resCfg;
392 Enet_IoctlPrms prms;
393 EnetPer_AttachCoreOutArgs attachCoreOutArgs;
395 uint32_t i;
396 uint32_t j;
397 int32_t status = ENET_SOK;
399 /* Do peripheral dependent initalization */
400 EnetAppUtils_print("\nInit all peripheral clocks");
401 EnetAppUtils_print("\n----------------------------------------------\n");
402 for (i = 0U; i < numPerCtxts; i++)
403 {
404 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
405 EnetAppUtils_enableClocks(perCtxt->enetType, perCtxt->instId);
407 /*Initialize aync IOCTL and TX timestamp flags*/
408 perCtxt->hAsyncIoctlSem = false;
409 perCtxt->hTxTsSem = false;
410 }
412 /* Prepare init configuration for all peripherals */
413 EnetAppUtils_print("\nInit all configs");
414 EnetAppUtils_print("\n----------------------------------------------");
415 for (i = 0U; i < numPerCtxts; i++)
416 {
417 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
419 dmaCfg = &perCtxt->dmaCfg;
420 dmaCfg->rxChInitPrms.dmaPriority = UDMA_DEFAULT_RX_CH_DMA_PRIORITY;
422 EnetAppUtils_print("\n%s: init config", perCtxt->name);
424 Icssg_Cfg *icssgCfg = &perCtxt->icssgCfg;
426 Enet_initCfg(perCtxt->enetType, perCtxt->instId, icssgCfg, sizeof(*icssgCfg));
427 resCfg = &icssgCfg->resCfg;
429 /* Set DMA configuration */
430 dmaCfg->hUdmaDrv = gEnetIg.hMainUdmaDrv;
431 icssgCfg->dmaCfg = (void *)dmaCfg;
433 /* Initialize RM */
434 EnetAppUtils_initResourceConfig(perCtxt->enetType, EnetSoc_getCoreId(), resCfg);
436 /* We use software MAC address pool from apputils, but it will give same MAC address.
437 * Add port index to make them unique */
438 for (j = 0U; j < ENETIG_PORT_MAX; j++)
439 {
440 resCfg->macList.macAddress[j][ENET_MAC_ADDR_LEN - 1] += (i * ENETIG_PORT_MAX) + j;
441 }
442 resCfg->macList.numMacAddress = ENETIG_PORT_MAX;
443 }
445 /* Open Enet driver for all peripherals */
446 EnetAppUtils_print("\n\nOpen all peripherals");
447 EnetAppUtils_print("\n----------------------------------------------");
448 for (i = 0U; i < numPerCtxts; i++)
449 {
450 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
451 EnetAppUtils_print("\n%s: Open enet", perCtxt->name);
453 Icssg_Cfg *icssgCfg = &perCtxt->icssgCfg;
454 perCtxt->hEnet = Enet_open(perCtxt->enetType, perCtxt->instId, icssgCfg, sizeof(*icssgCfg));
456 if (perCtxt->hEnet == NULL)
457 {
458 EnetAppUtils_print("\n%s: failed to open enet\n", perCtxt->name);
459 status = ENET_EFAIL;
460 break;
461 }
463 if (Enet_isIcssFamily(perCtxt->enetType))
464 {
465 EnetAppUtils_print("\n%s: Register async IOCTL callback", perCtxt->name);
466 Enet_registerEventCb(perCtxt->hEnet,
467 ENET_EVT_ASYNC_CMD_RESP,
468 0U,
469 EnetIg_asyncIoctlCb,
470 (void *)perCtxt);
472 EnetAppUtils_print("\n%s: Register TX timestamp callback", perCtxt->name);
473 perCtxt->txTsSeqId = 0U;
474 Enet_registerEventCb(perCtxt->hEnet,
475 ENET_EVT_TIMESTAMP_TX,
476 0U,
477 EnetIg_txTsCb,
478 (void *)perCtxt);
479 }
480 }
482 /* Attach the core with RM */
483 if (status == ENET_SOK)
484 {
485 EnetAppUtils_print("\n\nAttach core id %u on all peripherals", gEnetIg.coreId);
486 EnetAppUtils_print("\n----------------------------------------------");
487 for (i = 0U; i < numPerCtxts; i++)
488 {
489 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
491 EnetAppUtils_print("\n%s: Attach core", perCtxt->name);
493 ENET_IOCTL_SET_INOUT_ARGS(&prms, &gEnetIg.coreId, &attachCoreOutArgs);
495 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_PER_IOCTL_ATTACH_CORE, &prms);
496 if (status != ENET_SOK)
497 {
498 EnetAppUtils_print("\n%s: failed to attach: %d", perCtxt->name, status);
499 }
500 else
501 {
502 gEnetIg.coreKey = attachCoreOutArgs.coreKey;
503 }
504 }
505 }
507 return status;
508 }
510 static void EnetIg_close(EnetIg_PerCtxt *perCtxts,
511 uint32_t numPerCtxts)
512 {
513 Enet_IoctlPrms prms;
514 uint32_t i;
515 int32_t status;
517 EnetAppUtils_print("\n\nClose DMA for all peripherals");
518 EnetAppUtils_print("\n----------------------------------------------");
519 for (i = 0U; i < numPerCtxts; i++)
520 {
521 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
523 EnetAppUtils_print("\n%s: Close DMA", perCtxt->name);
525 EnetIg_closePort(perCtxt);
526 EnetIg_closeDma(perCtxt);
527 }
529 /* Detach core */
530 EnetAppUtils_print("\nDetach core from all peripherals");
531 EnetAppUtils_print("\n----------------------------------------------");
532 for (i = 0U; i < numPerCtxts; i++)
533 {
534 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
536 EnetAppUtils_print("\n%s: Detach core", perCtxt->name);
538 ENET_IOCTL_SET_IN_ARGS(&prms, &gEnetIg.coreKey);
539 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_PER_IOCTL_DETACH_CORE, &prms);
540 if (status != ENET_SOK)
541 {
542 EnetAppUtils_print("\n%s: Failed to detach: %d\n", perCtxt->name);
543 }
544 }
546 /* Close opened Enet drivers if any peripheral failed */
547 EnetAppUtils_print("\n\nClose all peripherals");
548 EnetAppUtils_print("\n----------------------------------------------");
549 for (i = 0U; i < numPerCtxts; i++)
550 {
551 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
553 EnetAppUtils_print("\n%s: Close enet", perCtxt->name);
555 if (Enet_isIcssFamily(perCtxt->enetType))
556 {
557 EnetAppUtils_print("\n%s: Unregister async IOCTL callback", perCtxt->name);
558 Enet_unregisterEventCb(perCtxt->hEnet,
559 ENET_EVT_ASYNC_CMD_RESP,
560 0U);
562 EnetAppUtils_print("\n%s: Unregister TX timestamp callback", perCtxt->name);
563 Enet_unregisterEventCb(perCtxt->hEnet,
564 ENET_EVT_TIMESTAMP_TX,
565 0U);
566 }
568 Enet_close(perCtxt->hEnet);
569 perCtxt->hEnet = NULL;
570 }
572 /* Do peripheral dependent initalization */
573 EnetAppUtils_print("\n\nDeinit all peripheral clocks");
574 EnetAppUtils_print("\n----------------------------------------------\n");
575 for (i = 0U; i < numPerCtxts; i++)
576 {
577 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
578 EnetAppUtils_disableClocks(perCtxt->enetType, perCtxt->instId);
579 }
581 /* Delete the semaphores */
582 EnetAppUtils_print("\nDeleting all the semaphores");
583 for (i = 0U; i < numPerCtxts; i++)
584 {
585 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
586 if(perCtxt->hRxSem != NULL)
587 {
588 SemaphoreP_delete(perCtxt->hRxSem);
589 }
591 if(perCtxt->hTxSem != NULL)
592 {
593 SemaphoreP_delete(perCtxt->hTxSem);
594 }
595 }
596 }
598 static void EnetIg_printStats(EnetIg_PerCtxt *perCtxts,
599 uint32_t numPerCtxts)
600 {
601 Enet_IoctlPrms prms;
602 Enet_MacPort macPort;
603 uint32_t i;
604 uint32_t j;
605 int32_t status;
607 EnetAppUtils_print("\nPrint statistics\n");
608 EnetAppUtils_print("----------------------------------------------\n");
609 for (i = 0U; i < numPerCtxts; i++)
610 {
611 EnetIg_PerCtxt *perCtxt = &gEnetIg.perCtxt[i];
613 if (Enet_isIcssFamily(perCtxt->enetType))
614 {
615 EnetAppUtils_print("\n%s - PA statistics\n", perCtxt->name);
616 EnetAppUtils_print("--------------------------------\n");
617 ENET_IOCTL_SET_OUT_ARGS(&prms, &gEnetIg_icssgPaStats);
618 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_STATS_IOCTL_GET_HOSTPORT_STATS, &prms);
619 if (status != ENET_SOK)
620 {
621 EnetAppUtils_print("\n%s: Failed to get PA stats\n", perCtxt->name);
622 }
624 EnetAppUtils_printIcssgPaStats(&gEnetIg_icssgPaStats);
625 EnetAppUtils_print("\n");
626 }
628 for (j = 0U; j < perCtxt->macPortNum; j++)
629 {
630 macPort = perCtxt->macPort[j];
632 EnetAppUtils_print("\n%s - Port %u statistics\n", perCtxt->name, ENET_MACPORT_ID(macPort));
633 EnetAppUtils_print("--------------------------------\n");
635 ENET_IOCTL_SET_INOUT_ARGS(&prms, &macPort, &gEnetIg_icssgStats);
637 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_STATS_IOCTL_GET_MACPORT_STATS, &prms);
638 if (status != ENET_SOK)
639 {
640 EnetAppUtils_print("\n%s: Failed to get port %u stats\n", perCtxt->name, ENET_MACPORT_ID(macPort));
641 continue;
642 }
644 EnetAppUtils_printIcssgMacPortStats(&gEnetIg_icssgStats, false);
645 EnetAppUtils_print("\n");
646 }
647 }
648 }
650 static void EnetIg_resetStats(EnetIg_PerCtxt *perCtxts,
651 uint32_t numPerCtxts)
652 {
653 Enet_IoctlPrms prms;
654 Enet_MacPort macPort;
655 uint32_t i;
656 uint32_t j;
657 int32_t status;
659 EnetAppUtils_print("\nReset statistics\n");
660 EnetAppUtils_print("----------------------------------------------\n");
661 for (i = 0U; i < numPerCtxts; i++)
662 {
663 EnetIg_PerCtxt *perCtxt = &gEnetIg.perCtxt[i];
665 EnetAppUtils_print("\n%s: Reset statistics", perCtxt->name);
667 for (j = 0U; j < perCtxt->macPortNum; j++)
668 {
669 macPort = perCtxt->macPort[j];
671 ENET_IOCTL_SET_IN_ARGS(&prms, &macPort);
672 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_STATS_IOCTL_RESET_MACPORT_STATS, &prms);
673 if (status != ENET_SOK)
674 {
675 EnetAppUtils_print("\n%s: Failed to reset port %u stats", perCtxt->name, ENET_MACPORT_ID(macPort));
676 continue;
677 }
678 }
679 }
680 }
682 static int32_t EnetIg_openPort(EnetIg_PerCtxt *perCtxt)
683 {
684 Enet_IoctlPrms prms;
685 EnetBoard_EthPort ethPort;
686 const EnetBoard_PhyCfg *boardPhyCfg;
687 EnetPer_PortLinkCfg portLinkCfg;
689 IcssgMacPort_Cfg icssgMacCfg;
690 EnetMacPort_LinkCfg *linkCfg = &portLinkCfg.linkCfg;
691 EnetMacPort_Interface *mii = &portLinkCfg.mii;
692 EnetPhy_Cfg *phyCfg = &portLinkCfg.phyCfg;
693 Enet_MacPort macPort;
694 uint32_t i;
695 int32_t status = ENET_SOK;
697 EnetAppUtils_print("\n\nOpen ports");
698 EnetAppUtils_print("\n----------------------------------------------");
700 for (i = 0U; i < perCtxt->macPortNum; i++)
701 {
702 macPort = perCtxt->macPort[i];
704 EnetAppUtils_print("\n%s: Open port %u", perCtxt->name, ENET_MACPORT_ID(macPort));
706 /* Setup board for requested Ethernet port */
707 ethPort.enetType = perCtxt->enetType;
708 ethPort.instId = perCtxt->instId;
709 ethPort.macPort = macPort;
710 ethPort.boardId = ENETBOARD_CPB_ID;
711 EnetIg_macMode2MacMii(RGMII, ðPort.mii);
713 status = EnetBoard_setupPorts(ðPort, 1U);
714 if (status != ENET_SOK)
715 {
716 EnetAppUtils_print("\n%s: Failed to setup MAC port %u\n", perCtxt->name, ENET_MACPORT_ID(macPort));
717 EnetAppUtils_assert(false);
718 }
720 IcssgMacPort_initCfg(&icssgMacCfg);
721 portLinkCfg.macCfg = &icssgMacCfg;
723 /* Set port link params */
724 portLinkCfg.macPort = macPort;
726 mii->layerType = ethPort.mii.layerType;
727 mii->sublayerType = ethPort.mii.sublayerType;
728 mii->variantType = ENET_MAC_VARIANT_FORCED;
730 linkCfg->speed = ENET_SPEED_AUTO;
731 linkCfg->duplexity = ENET_DUPLEX_AUTO;
733 boardPhyCfg = EnetBoard_getPhyCfg(ðPort);
734 if (boardPhyCfg != NULL)
735 {
736 EnetPhy_initCfg(phyCfg);
737 phyCfg->phyAddr = boardPhyCfg->phyAddr;
738 phyCfg->isStrapped = boardPhyCfg->isStrapped;
739 phyCfg->loopbackEn = false;
740 phyCfg->skipExtendedCfg = boardPhyCfg->skipExtendedCfg;
741 phyCfg->extendedCfgSize = boardPhyCfg->extendedCfgSize;
742 memcpy(phyCfg->extendedCfg, boardPhyCfg->extendedCfg, phyCfg->extendedCfgSize);
743 }
744 else
745 {
746 EnetAppUtils_print("%s: No PHY configuration found\n", perCtxt->name);
747 EnetAppUtils_assert(false);
748 }
750 /* Open port link */
751 if (status == ENET_SOK)
752 {
753 ENET_IOCTL_SET_IN_ARGS(&prms, &portLinkCfg);
755 EnetAppUtils_print("\n%s: Open port %u link", perCtxt->name, ENET_MACPORT_ID(macPort));
756 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_PER_IOCTL_OPEN_PORT_LINK, &prms);
757 if (status != ENET_SOK)
758 {
759 EnetAppUtils_print("\n%s: Failed to open port link: %d\n", perCtxt->name, status);
760 }
761 }
762 }
764 return status;
765 }
767 static void EnetIg_closePort(EnetIg_PerCtxt *perCtxt)
768 {
769 Enet_IoctlPrms prms;
770 Enet_MacPort macPort;
771 uint32_t i;
772 int32_t status;
774 for (i = 0U; i < perCtxt->macPortNum; i++)
775 {
776 macPort = perCtxt->macPort[i];
778 EnetAppUtils_print("\n%s: Close port %u", perCtxt->name, ENET_MACPORT_ID(macPort));
780 /* Close port link */
781 ENET_IOCTL_SET_IN_ARGS(&prms, &macPort);
783 EnetAppUtils_print("\n%s: Close port %u link", perCtxt->name, ENET_MACPORT_ID(macPort));
784 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_PER_IOCTL_CLOSE_PORT_LINK, &prms);
785 if (status != ENET_SOK)
786 {
787 EnetAppUtils_print("\n%s: Failed to close port link: %d\n", perCtxt->name, status);
788 }
789 }
790 }
792 static int32_t EnetIg_waitForLinkUp(EnetIg_PerCtxt *perCtxt)
793 {
794 Enet_IoctlPrms prms;
795 Enet_MacPort macPort;
796 IcssgMacPort_SetPortStateInArgs setPortStateInArgs;
797 bool linked;
799 uint32_t i;
800 uint32_t linkCheckTime = 0;
801 int32_t status = ENET_SOK;
803 EnetAppUtils_print("\n%s: Waiting for link up...\n", perCtxt->name);
805 for (i = 0U; i < perCtxt->macPortNum; i++)
806 {
807 macPort = perCtxt->macPort[i];
808 linked = false;
809 ENET_IOCTL_SET_INOUT_ARGS(&prms, &macPort, &linked);
811 while (!linked)
812 {
813 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ENET_PER_IOCTL_IS_PORT_LINK_UP, &prms);
814 if (status != ENET_SOK)
815 {
816 EnetAppUtils_print("\n%s: Failed to get port %u link status: %d\n",
817 perCtxt->name, ENET_MACPORT_ID(macPort), status);
818 linked = false;
819 break;
820 }
822 if (!linked)
823 {
824 Enet_periodicTick(perCtxt->hEnet);
825 EnetUtils_delay(10U);
826 }
828 linkCheckTime++;
829 if(linkCheckTime > BOARD_DIAG_ICSSG_LINKUP_TIMEOUT)
830 {
831 status = ENET_ETIMEOUT;
832 EnetAppUtils_print("\n%s: Port %u link up timed out\n",
833 perCtxt->name, ENET_MACPORT_ID(macPort));
834 break;
835 }
836 }
838 EnetAppUtils_print("\n%s: Port %u link is %s",
839 perCtxt->name, ENET_MACPORT_ID(macPort), linked ? "up" : "down");
841 /* Set port to 'Forward' state */
842 if (status == ENET_SOK)
843 {
844 EnetAppUtils_print("\n%s: Set port state to 'Forward'", perCtxt->name);
846 setPortStateInArgs.macPort = macPort;
847 setPortStateInArgs.portState = ICSSG_PORT_STATE_FORWARD;
848 ENET_IOCTL_SET_IN_ARGS(&prms, &setPortStateInArgs);
850 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ICSSG_PER_IOCTL_SET_PORT_STATE, &prms);
851 if (status == ENET_SINPROGRESS)
852 {
853 /* Wait for asyc ioctl to complete */
854 while(perCtxt->hAsyncIoctlSem != true)
855 {
856 Enet_poll(perCtxt->hEnet, ENET_EVT_ASYNC_CMD_RESP, NULL, 0U);
857 }
858 perCtxt->hAsyncIoctlSem = false;
860 status = ENET_SOK;
861 }
862 else
863 {
864 EnetAppUtils_print("\n%s: Failed to set port state: %d\n", perCtxt->name, status);
865 }
866 }
867 }
869 return status;
870 }
872 static void EnetIg_macMode2MacMii(emac_mode macMode,
873 EnetMacPort_Interface *mii)
874 {
875 switch (macMode)
876 {
877 #if defined(SOC_AM65XX) || defined(SOC_J7200) || defined(SOC_J721E) || defined(SOC_TPR12) || defined(SOC_AWR294X)
878 case RMII:
879 mii->layerType = ENET_MAC_LAYER_MII;
880 mii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
881 mii->variantType = ENET_MAC_VARIANT_NONE;
882 break;
884 case RGMII:
885 mii->layerType = ENET_MAC_LAYER_GMII;
886 mii->sublayerType = ENET_MAC_SUBLAYER_REDUCED;
887 mii->variantType = ENET_MAC_VARIANT_FORCED;
888 break;
889 #endif
890 #if defined(SOC_J7200) || defined(SOC_J721E)
891 case GMII:
892 mii->layerType = ENET_MAC_LAYER_GMII;
893 mii->sublayerType = ENET_MAC_SUBLAYER_STANDARD;
894 mii->variantType = ENET_MAC_VARIANT_NONE;
895 break;
897 case SGMII:
898 mii->layerType = ENET_MAC_LAYER_GMII;
899 mii->sublayerType = ENET_MAC_SUBLAYER_SERIAL;
900 mii->variantType = ENET_MAC_VARIANT_NONE;
901 break;
903 case QSGMII:
904 mii->layerType = ENET_MAC_LAYER_GMII;
905 mii->sublayerType = ENET_MAC_SUBLAYER_QUAD_SERIAL_MAIN;
906 mii->variantType = ENET_MAC_VARIANT_NONE;
907 break;
909 case QSGMII_SUB:
910 mii->layerType = ENET_MAC_LAYER_GMII;
911 mii->sublayerType = ENET_MAC_SUBLAYER_QUAD_SERIAL_SUB;
912 mii->variantType = ENET_MAC_VARIANT_NONE;
913 break;
915 case XFI:
916 mii->layerType = ENET_MAC_LAYER_XGMII;
917 mii->sublayerType = ENET_MAC_SUBLAYER_STANDARD;
918 mii->variantType = ENET_MAC_VARIANT_NONE;
919 break;
920 #endif
921 default:
922 EnetAppUtils_print("\nInvalid MAC mode: %u\n", macMode);
923 EnetAppUtils_assert(false);
924 break;
925 }
926 }
928 static void BoardDiag_EnetIg_rxIsrFxn(void *appData)
929 {
930 EnetIg_PerCtxt *perCtxt = (EnetIg_PerCtxt *)appData;
932 SemaphoreP_post(perCtxt->hRxSem);
933 }
935 static void BoardDiag_EnetIg_txIsrFxn(void *appData)
936 {
937 EnetIg_PerCtxt *perCtxt = (EnetIg_PerCtxt *)appData;
939 SemaphoreP_post(perCtxt->hTxSem);
940 }
942 static int32_t EnetIg_openDma(EnetIg_PerCtxt *perCtxt)
943 {
944 EnetUdma_OpenRxFlowPrms rxChCfg;
945 EnetUdma_OpenTxChPrms txChCfg;
946 int32_t status = ENET_SOK;
948 /* Open the TX channel */
949 EnetDma_initTxChParams(&txChCfg);
951 txChCfg.hUdmaDrv = (perCtxt->enetType == ENET_CPSW_2G) ? gEnetIg.hMcuUdmaDrv : gEnetIg.hMainUdmaDrv;
952 txChCfg.cbArg = perCtxt;
953 txChCfg.notifyCb = BoardDiag_EnetIg_txIsrFxn;
954 txChCfg.useGlobalEvt = true;
956 EnetAppUtils_setCommonTxChPrms(&txChCfg);
958 EnetAppUtils_openTxCh(perCtxt->hEnet,
959 gEnetIg.coreKey,
960 gEnetIg.coreId,
961 &perCtxt->txChNum,
962 &perCtxt->hTxCh,
963 &txChCfg);
964 if (perCtxt->hTxCh == NULL)
965 {
966 #if FIX_RM
967 /* Free the channel number if open Tx channel failed */
968 EnetAppUtils_freeTxCh(gEnetIg.hEnet,
969 gEnetIg.coreKey,
970 gEnetIg.coreId,
971 gEnetIg.txChNum);
972 #endif
973 EnetAppUtils_print("\nEnetIg_openDma() failed to open TX channel");
974 status = ENET_EFAIL;
975 EnetAppUtils_assert(perCtxt->hTxCh != NULL);
976 }
978 /* Allocate TX packets and keep them locally enqueued */
979 if (status == ENET_SOK)
980 {
981 EnetIg_initTxFreePktQ();
982 }
984 /* Open the RX flow */
985 if (status == ENET_SOK)
986 {
987 EnetDma_initRxChParams(&rxChCfg);
989 rxChCfg.hUdmaDrv = (perCtxt->enetType == ENET_CPSW_2G) ? gEnetIg.hMcuUdmaDrv : gEnetIg.hMainUdmaDrv;
990 rxChCfg.notifyCb = BoardDiag_EnetIg_rxIsrFxn;
991 rxChCfg.cbArg = perCtxt;
992 rxChCfg.useGlobalEvt = true;
993 rxChCfg.flowPrms.sizeThreshEn = 0U;
995 EnetAppUtils_setCommonRxFlowPrms(&rxChCfg);
996 EnetAppUtils_openRxFlow(perCtxt->enetType,
997 perCtxt->hEnet,
998 gEnetIg.coreKey,
999 gEnetIg.coreId,
1000 true,
1001 &perCtxt->rxStartFlowIdx,
1002 &perCtxt->rxFlowIdx,
1003 &perCtxt->macAddr[0U],
1004 &perCtxt->hRxCh,
1005 &rxChCfg);
1007 if (perCtxt->hRxCh == NULL)
1008 {
1009 EnetAppUtils_print("\nEnetIg_openRxCh() failed to open RX flow");
1010 status = ENET_EFAIL;
1011 EnetAppUtils_assert(perCtxt->hRxCh != NULL);
1012 }
1013 }
1015 /* Submit all ready RX buffers to DMA */
1016 if (status == ENET_SOK)
1017 {
1018 EnetIg_initRxReadyPktQ(perCtxt->hRxCh);
1019 }
1021 return status;
1022 }
1024 static void EnetIg_closeDma(EnetIg_PerCtxt *perCtxt)
1025 {
1026 EnetDma_PktQ fqPktInfoQ;
1027 EnetDma_PktQ cqPktInfoQ;
1029 EnetQueue_initQ(&fqPktInfoQ);
1030 EnetQueue_initQ(&cqPktInfoQ);
1032 /* Close RX channel */
1033 EnetAppUtils_closeRxFlow(perCtxt->enetType,
1034 perCtxt->hEnet,
1035 gEnetIg.coreKey,
1036 gEnetIg.coreId,
1037 true,
1038 &fqPktInfoQ,
1039 &cqPktInfoQ,
1040 perCtxt->rxStartFlowIdx,
1041 perCtxt->rxFlowIdx,
1042 perCtxt->macAddr,
1043 perCtxt->hRxCh);
1045 EnetAppUtils_freePktInfoQ(&fqPktInfoQ);
1046 EnetAppUtils_freePktInfoQ(&cqPktInfoQ);
1048 /* Close TX channel */
1049 EnetQueue_initQ(&fqPktInfoQ);
1050 EnetQueue_initQ(&cqPktInfoQ);
1052 /* Retrieve any pending TX packets from driver */
1053 EnetIg_retrieveFreeTxPkts(perCtxt);
1055 EnetAppUtils_closeTxCh(perCtxt->hEnet,
1056 gEnetIg.coreKey,
1057 gEnetIg.coreId,
1058 &fqPktInfoQ,
1059 &cqPktInfoQ,
1060 perCtxt->hTxCh,
1061 perCtxt->txChNum);
1063 EnetAppUtils_freePktInfoQ(&fqPktInfoQ);
1064 EnetAppUtils_freePktInfoQ(&cqPktInfoQ);
1065 EnetAppUtils_freePktInfoQ(&gEnetIg.txFreePktInfoQ);
1066 }
1068 static void EnetIg_initTxFreePktQ(void)
1069 {
1070 EnetDma_Pkt *pPktInfo;
1071 uint32_t i;
1073 /* Initialize TX EthPkts and queue them to txFreePktInfoQ */
1074 for (i = 0U; i < ENET_MEM_NUM_TX_PKTS; i++)
1075 {
1076 pPktInfo = EnetMem_allocEthPkt(&gEnetIg,
1077 ENET_MEM_LARGE_POOL_PKT_SIZE,
1078 ENETDMA_CACHELINE_ALIGNMENT);
1079 EnetAppUtils_assert(pPktInfo != NULL);
1080 ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ);
1082 EnetQueue_enq(&gEnetIg.txFreePktInfoQ, &pPktInfo->node);
1083 }
1085 EnetAppUtils_print("\ninitQs() txFreePktInfoQ initialized with %d pkts",
1086 EnetQueue_getQCount(&gEnetIg.txFreePktInfoQ));
1087 }
1089 static void EnetIg_initRxReadyPktQ(EnetDma_RxChHandle hRxCh)
1090 {
1091 EnetDma_PktQ rxReadyQ;
1092 EnetDma_PktQ rxFreeQ;
1093 EnetDma_Pkt *pPktInfo;
1094 uint32_t i;
1095 int32_t status;
1097 EnetQueue_initQ(&rxFreeQ);
1099 for (i = 0U; i < ENET_MEM_NUM_RX_PKTS; i++)
1100 {
1101 pPktInfo = EnetMem_allocEthPkt(&gEnetIg,
1102 ENET_MEM_LARGE_POOL_PKT_SIZE,
1103 ENETDMA_CACHELINE_ALIGNMENT);
1104 EnetAppUtils_assert(pPktInfo != NULL);
1106 ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ);
1108 EnetQueue_enq(&rxFreeQ, &pPktInfo->node);
1109 }
1111 /* Retrieve any packets which are ready */
1112 EnetQueue_initQ(&rxReadyQ);
1113 status = EnetDma_retrieveRxPktQ(hRxCh, &rxReadyQ);
1114 EnetAppUtils_assert(status == ENET_SOK);
1116 /* There should not be any packet with DMA during init */
1117 EnetAppUtils_assert(EnetQueue_getQCount(&rxReadyQ) == 0U);
1119 EnetDma_submitRxPktQ(hRxCh, &rxFreeQ);
1121 /* Assert here, as during init, the number of DMA descriptors should be equal to
1122 * the number of free Ethernet buffers available with app */
1123 EnetAppUtils_assert(EnetQueue_getQCount(&rxFreeQ) == 0U);
1124 }
1126 static uint32_t EnetIg_retrieveFreeTxPkts(EnetIg_PerCtxt *perCtxt)
1127 {
1128 EnetDma_PktQ txFreeQ;
1129 EnetDma_Pkt *pktInfo;
1130 uint32_t txFreeQCnt = 0U;
1131 int32_t status;
1133 EnetQueue_initQ(&txFreeQ);
1135 /* Retrieve any packets that may be free now */
1136 status = EnetDma_retrieveTxPktQ(perCtxt->hTxCh, &txFreeQ);
1137 if (status == ENET_SOK)
1138 {
1139 txFreeQCnt = EnetQueue_getQCount(&txFreeQ);
1141 pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ);
1142 while (NULL != pktInfo)
1143 {
1144 EnetDma_checkPktState(&pktInfo->pktState,
1145 ENET_PKTSTATE_MODULE_APP,
1146 ENET_PKTSTATE_APP_WITH_DRIVER,
1147 ENET_PKTSTATE_APP_WITH_FREEQ);
1149 EnetQueue_enq(&gEnetIg.txFreePktInfoQ, &pktInfo->node);
1150 pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ);
1151 }
1152 }
1153 else
1154 {
1155 EnetAppUtils_print("\nretrieveFreeTxPkts() failed to retrieve pkts: %d", status);
1156 }
1158 return txFreeQCnt;
1159 }
1161 static int32_t BoardDiag_EnetIg_LpbckTest(EnetIg_PerCtxt *perCtxts, uint32_t numPerCtxts)
1162 {
1163 uint32_t i;
1164 int32_t status = ENET_SOK;
1165 Enet_IoctlPrms prms;
1166 SemaphoreP_Params semParams;
1168 for (i = 0U; i < numPerCtxts; i++)
1169 {
1170 EnetIg_PerCtxt *perCtxt = &perCtxts[i];
1172 SemaphoreP_Params_init(&semParams);
1173 semParams.mode = SemaphoreP_Mode_BINARY;
1175 perCtxt->hRxSem = SemaphoreP_create(0, &semParams);
1176 EnetAppUtils_assert(perCtxt->hRxSem != NULL);
1178 perCtxt->hTxSem = SemaphoreP_create(0, &semParams);
1179 EnetAppUtils_assert(perCtxt->hTxSem != NULL);
1181 status = EnetIg_openPort(perCtxt);
1182 if (status != ENET_SOK)
1183 {
1184 EnetAppUtils_print("\n%s: Failed to open port link: %d\n", perCtxt->name, status);
1185 }
1187 status = EnetIg_waitForLinkUp(perCtxt);
1188 if (status != ENET_SOK)
1189 {
1190 EnetAppUtils_print("\n%s: Failed to wait for link up: %d\n", perCtxt->name, status);
1191 }
1193 /* Open DMA for peripheral/port */
1194 if (status == ENET_SOK)
1195 {
1196 EnetAppUtils_print("\n%s: Open DMA", perCtxt->name);
1198 status = EnetIg_openDma(perCtxt);
1199 if (status != ENET_SOK)
1200 {
1201 EnetAppUtils_print("\n%s: failed to open DMA: %d\n", perCtxt->name, status);
1202 }
1203 }
1205 /* Add port MAC entry */
1206 if ((status == ENET_SOK) && (Enet_isIcssFamily(perCtxt->enetType)))
1207 {
1208 EnetAppUtils_print("\n%s: Set MAC addr: ", perCtxt->name);
1209 EnetAppUtils_printMacAddr(&perCtxt->macAddr[0U]);
1211 if (perCtxt->enetType == ENET_ICSSG_DUALMAC)
1212 {
1213 IcssgMacPort_SetMacAddressInArgs inArgs;
1215 memset(&inArgs, 0, sizeof(inArgs));
1216 inArgs.macPort = perCtxt->macPort[0U];
1217 EnetUtils_copyMacAddr(&inArgs.macAddr[0U], &perCtxt->macAddr[0U]);
1218 ENET_IOCTL_SET_IN_ARGS(&prms, &inArgs);
1220 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ICSSG_MACPORT_IOCTL_SET_MACADDR, &prms);
1221 }
1222 else
1223 {
1224 Icssg_MacAddr addr; // FIXME Icssg_MacAddr type
1226 /* Set host port's MAC address */
1227 EnetUtils_copyMacAddr(&addr.macAddr[0U], &perCtxt->macAddr[0U]);
1228 ENET_IOCTL_SET_IN_ARGS(&prms, &addr);
1230 status = Enet_ioctl(perCtxt->hEnet, gEnetIg.coreId, ICSSG_HOSTPORT_IOCTL_SET_MACADDR, &prms);
1231 }
1233 if (status != ENET_SOK)
1234 {
1235 EnetAppUtils_print("\n%s: Failed to set MAC address entry: %d\n", perCtxt->name, status);
1236 }
1237 }
1238 }
1240 if(status == ENET_SOK)
1241 {
1242 status = BoardDiag_EnetIg_LpbkTxRx();
1243 }
1244 return status;
1245 }
1247 static uint32_t BoardDiag_EnetIg_Receive(EnetIg_PerCtxt *perCtxt)
1248 {
1249 EnetDma_PktQ rxReadyQ;
1250 EnetDma_PktQ rxFreeQ;
1251 EnetDma_Pkt *rxPktInfo;
1253 uint32_t rxReadyCnt = 0U;
1254 int32_t status;
1256 EnetQueue_initQ(&rxReadyQ);
1257 EnetQueue_initQ(&rxFreeQ);
1259 /* Get the packets received so far */
1260 status = EnetDma_retrieveRxPktQ(perCtxt->hRxCh, &rxReadyQ);
1261 if (status != ENET_SOK)
1262 {
1263 EnetAppUtils_print("\nreceivePkts() failed to retrieve pkts: %d\n", status);
1264 }
1265 else
1266 {
1267 rxReadyCnt = EnetQueue_getQCount(&rxReadyQ);
1269 /* Consume the received packets */
1270 rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
1272 while(rxPktInfo != NULL)
1273 {
1274 EnetDma_checkPktState(&rxPktInfo->pktState,
1275 ENET_PKTSTATE_MODULE_APP,
1276 ENET_PKTSTATE_APP_WITH_DRIVER,
1277 ENET_PKTSTATE_APP_WITH_READYQ);
1279 gEnetIg.rxFrame = (EthFrame *)rxPktInfo->bufPtr;
1281 EnetDma_checkPktState(&rxPktInfo->pktState,
1282 ENET_PKTSTATE_MODULE_APP,
1283 ENET_PKTSTATE_APP_WITH_READYQ,
1284 ENET_PKTSTATE_APP_WITH_FREEQ);
1286 /* Release the received packet */
1287 EnetQueue_enq(&rxFreeQ, &rxPktInfo->node);
1288 rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
1289 }
1291 EnetAppUtils_validatePacketState(&rxFreeQ,
1292 ENET_PKTSTATE_APP_WITH_FREEQ,
1293 ENET_PKTSTATE_APP_WITH_DRIVER);
1295 /* Submit now processed buffers */
1296 EnetDma_submitRxPktQ(perCtxt->hRxCh, &rxFreeQ);
1297 }
1299 return rxReadyCnt;
1300 }
1302 static uint32_t BoardDiag_EnetIg_Transmit(EnetIg_PerCtxt *txPerCtxt, EnetIg_PerCtxt *rxPerCtxt)
1303 {
1304 EnetDma_PktQ txSubmitQ;
1305 EnetDma_Pkt *txPktInfo;
1307 int32_t status = ENET_SOK;
1308 uint8_t bcastAddr[ENET_MAC_ADDR_LEN] =
1309 {0xffU, 0xffU, 0xffU, 0xffU, 0xffU, 0xffU};
1311 uint32_t pktCnt = 0;
1312 uint32_t txRetrievePktCnt = 0;
1313 uint32_t loopTxPktCnt = 0;
1314 uint32_t loopRxPktCnt = 0;
1315 uint32_t rxReadyCnt = 0;
1316 uint32_t txCnt = 0;
1317 SemaphoreP_Status semStatus;
1319 while (pktCnt < BOARD_DIAG_ENETLPBK_TEST_PKT_NUM)
1320 {
1321 loopRxPktCnt = loopTxPktCnt = 0U;
1323 /* Retrieve TX packets from driver and recycle them */
1324 EnetIg_retrieveFreeTxPkts(txPerCtxt);
1326 /* Transmit a single packet */
1327 EnetQueue_initQ(&txSubmitQ);
1329 /* Dequeue one free TX Eth packet */
1330 txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&gEnetIg.txFreePktInfoQ);
1332 memset(gEnetIg.txFrame, 0, sizeof(gEnetIg.txFrame));
1333 memset(gEnetIg.rxFrame, 0, sizeof(gEnetIg.rxFrame));
1335 while (NULL != txPktInfo)
1336 {
1337 pktCnt++;
1338 /* Fill the TX Eth frame with test content */
1339 gEnetIg.txFrame = (EthFrame *)txPktInfo->bufPtr;
1340 memcpy(gEnetIg.txFrame->hdr.dstMac, &bcastAddr[0U], ENET_MAC_ADDR_LEN);
1341 memcpy(gEnetIg.txFrame->hdr.srcMac, &txPerCtxt->macAddr[0U], ENET_MAC_ADDR_LEN);
1343 gEnetIg.txFrame->hdr.etherType = Enet_htons(0x0800);
1345 memset(&gEnetIg.txFrame->payload[0U], (uint8_t)(0xA5 + pktCnt),
1346 BOARD_DIAG_ENETLPBK_TEST_PKT_LEN);
1348 txPktInfo->userBufLen = BOARD_DIAG_ENETLPBK_TEST_PKT_LEN +
1349 sizeof(EthFrameHeader);
1351 txPktInfo->appPriv = &gEnetIg;
1352 txPktInfo->tsInfo.enableHostTxTs = false;
1354 /* Enqueue the packet for later transmission */
1355 EnetQueue_enq(&txSubmitQ, &txPktInfo->node);
1357 if (pktCnt >= BOARD_DIAG_ENETLPBK_TEST_PKT_NUM)
1358 {
1359 break;
1360 }
1362 /* Dequeue one free TX Eth packet */
1363 txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&gEnetIg.txFreePktInfoQ);
1364 }
1366 loopTxPktCnt = EnetQueue_getQCount(&txSubmitQ);
1367 while (0U != EnetQueue_getQCount(&txSubmitQ))
1368 {
1369 txCnt = EnetQueue_getQCount(&txSubmitQ);
1370 status = EnetDma_submitTxPktQ(txPerCtxt->hTxCh, &txSubmitQ);
1372 semStatus = SemaphoreP_pend(txPerCtxt->hTxSem, BOARD_DIAG_ENETLPBK_TIMEOUT);
1374 if(semStatus == SemaphoreP_TIMEOUT)
1375 {
1376 status = ENET_ETIMEOUT;
1377 EnetAppUtils_print("\n\nTrasmit timeout at packet %d", loopTxPktCnt);
1378 break;
1379 }
1382 /* Retrieve TX free packets */
1383 if (status == ENET_SOK)
1384 {
1385 txCnt = txCnt - EnetQueue_getQCount(&txSubmitQ);
1386 txRetrievePktCnt = 0U;
1387 while (txRetrievePktCnt != txCnt)
1388 {
1389 /* TODO this is not failure as HW is busy sending
1390 * packets, we need to wait and again call retrieve
1391 * packets */
1392 Osal_delay(10);
1393 txRetrievePktCnt += EnetIg_retrieveFreeTxPkts(txPerCtxt);
1394 }
1395 }
1396 else
1397 {
1398 break;
1399 }
1400 }
1402 if(status == ENET_SOK)
1403 {
1404 /* wait to receive the packet */
1405 do
1406 {
1407 semStatus = SemaphoreP_pend(rxPerCtxt->hRxSem, BOARD_DIAG_ENETLPBK_TIMEOUT);
1409 if(semStatus == SemaphoreP_TIMEOUT)
1410 {
1411 status = ENET_ETIMEOUT;
1412 EnetAppUtils_print("\n\nReceive timeout at packet %d", loopRxPktCnt);
1413 break;
1414 }
1416 rxReadyCnt = 0;
1418 if(status == ENET_SOK)
1419 {
1420 rxReadyCnt = BoardDiag_EnetIg_Receive(rxPerCtxt);
1421 loopRxPktCnt += rxReadyCnt;
1423 status = memcmp(&gEnetIg.txFrame->payload[0], &gEnetIg.rxFrame->payload[0], rxReadyCnt);
1424 if(status != ENET_SOK)
1425 {
1426 EnetAppUtils_print("\n\nPacket mismatch error at packet %d", pktCnt);
1427 EnetAppUtils_print("\n\nRx Byte Count = %d", rxReadyCnt);
1428 if(printFrameEnable == true)
1429 {
1430 EnetAppUtils_print("\n\nTransmitted Packets: ", pktCnt);
1431 BoardDiag_printFrame(gEnetIg.rxFrame, rxReadyCnt);
1432 }
1433 }
1434 }
1435 else
1436 {
1437 break;
1438 }
1440 }while(loopRxPktCnt < loopTxPktCnt);
1442 gEnetIg.totalRxCnt += loopTxPktCnt;
1443 }
1444 }
1446 gEnetIg.totalTxCnt += pktCnt;
1448 EnetAppUtils_print("\n\nTransmitted - %d packets\nReceived - %d packets\n",
1449 loopTxPktCnt, loopRxPktCnt);
1451 return status;
1452 }
1454 uint32_t BoardDiag_EnetIg_LpbkTxRx(void)
1455 {
1456 int32_t status = ENET_SOK;
1458 gEnetIg.totalTxCnt = 0U;
1459 gEnetIg.totalRxCnt = 0U;
1461 EnetAppUtils_print("\n\nPort %d to Port %d", gEnetIg.perCtxt[0].instId, gEnetIg.perCtxt[1].instId);
1463 status |= BoardDiag_EnetIg_Transmit(&gEnetIg.perCtxt[0], &gEnetIg.perCtxt[1]);
1464 Osal_delay(100);
1466 EnetAppUtils_print("\n\nPort %d to Port %d", gEnetIg.perCtxt[1].instId, gEnetIg.perCtxt[0].instId);
1468 status |= BoardDiag_EnetIg_Transmit(&gEnetIg.perCtxt[1], &gEnetIg.perCtxt[0]);
1469 Osal_delay(100);
1471 if(status == ENET_SOK)
1472 {
1473 if(gEnetIg.totalTxCnt != gEnetIg.totalRxCnt)
1474 {
1475 EnetAppUtils_print("\n\nPacket Loss, Test Failed");
1476 EnetAppUtils_print("\n\nTest Iteration %d failed", gEnetIg.loopCnt+1);
1477 gEnetIg.failIterations++;
1478 printStatsEnable = true;
1479 }
1480 else
1481 {
1482 EnetAppUtils_print("\n\nTest Iteration %d passed", gEnetIg.loopCnt+1);
1483 gEnetIg.passIterations++;
1484 }
1485 }
1486 else
1487 {
1488 gEnetIg.failIterations++;
1489 printStatsEnable = true;
1490 EnetAppUtils_print("\n\nFailed to transmit/receive packets");
1491 }
1493 EnetAppUtils_print("\n\nNo. of tests passed: %d", gEnetIg.passIterations);
1494 EnetAppUtils_print("\n\nNo. of tests failed: %d", gEnetIg.failIterations);
1495 if(printStatsEnable == true)
1496 {
1497 /* Print statistics */
1498 EnetIg_printStats(gEnetIg.perCtxt, gEnetIg.numPerCtxts);
1500 EnetIg_resetStats(gEnetIg.perCtxt, gEnetIg.numPerCtxts);
1502 printStatsEnable = false;
1503 }
1505 return status;
1506 }
1508 /**
1509 * \brief This function is used to display Mac address
1510 *
1511 * \param EthFrame EthFrame[] frame to be displayed
1512 * uint32_t len length of the frame
1513 * \return NULL
1514 *
1515 */
1516 static void BoardDiag_printFrame(EthFrame *frame, uint32_t len)
1517 {
1518 uint8_t *payload;
1519 uint32_t i;
1521 EnetAppUtils_print("\nDst addr : ");
1522 BoardDiag_printMacAddr(&frame->hdr.dstMac[0]);
1524 EnetAppUtils_print("\nSrc addr : ");
1525 BoardDiag_printMacAddr(&frame->hdr.srcMac[0]);
1528 EnetAppUtils_print("\nEtherType: 0x%04x",
1529 Enet_ntohs(frame->hdr.etherType) & 0xFFFFU);
1530 payload = frame->payload;
1532 EnetAppUtils_print("\nPayload : ");
1533 for (i = 0; i < len; i++)
1534 {
1535 EnetAppUtils_print("0x%02x ", payload[i]);
1536 if (i && (((i + 1) % OCTETS_PER_ROW) == 0))
1537 {
1538 EnetAppUtils_print("\n ");
1539 }
1540 }
1542 if (len && ((len % OCTETS_PER_ROW) != 0))
1543 {
1544 EnetAppUtils_print("\n");
1545 }
1547 EnetAppUtils_print("\n");
1548 }
1550 /**
1551 * \brief This function is used to display Mac address
1552 *
1553 * \param uint8_t macAddr[] MAC Address
1554 *
1555 * \return NULL
1556 *
1557 */
1558 static void BoardDiag_printMacAddr(uint8_t macAddr[])
1559 {
1560 EnetAppUtils_print("%02x:%02x:%02x:%02x:%02x:%02x\n",
1561 macAddr[0] & 0xFF,
1562 macAddr[1] & 0xFF,
1563 macAddr[2] & 0xFF,
1564 macAddr[3] & 0xFF,
1565 macAddr[4] & 0xFF,
1566 macAddr[5] & 0xFF);
1567 }