1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Email: opensource_embedded@phytium.com.cn
7 *
8 * Change Logs:
9 * Date Author Notes
10 * 2022-07-07 liuzhihong first commit
11 * 2023-07-14 liuzhihong support RT-Smart
12 * 2023-12-01 liuzhihong support initialisation of multiple mac
13 */
14
15 #include"rtconfig.h"
16
17 #ifdef BSP_USING_ETH
18
19 #include "board.h"
20 #define LOG_TAG "xmac_drv"
21 #include "drv_log.h"
22 #include "mm_aspace.h"
23 #ifdef RT_USING_SMART
24 #include "ioremap.h"
25 #endif
26
27
28 #include "eth_board.h"
29 #include "drv_xmac.h"
30
31 #define FXMAC_BD_TO_INDEX(ringptr, bdptr) \
32 (((uintptr)bdptr - (uintptr)(ringptr)->base_bd_addr) / (ringptr)->separation)
33
34
35 static void FXmacInitOnError(FXmacOs *instance_p);
36 static void FXmacSetupIsr(FXmacOs *instance_p);
37
38 static FXmacOs fxmac_os_instace[FXMAC_NUM] =
39 {
40 [FXMAC0_ID] =
41 {
42 .config = (0),
43 .hwaddr = {0x98, 0x0e, 0x24, 0x00, 0x11, 0x0},
44
45 },
46 [FXMAC1_ID] =
47 {
48 .config = (0),
49 .hwaddr = {0x98, 0x0e, 0x24, 0x00, 0x11, 0x1},
50
51 },
52 [FXMAC2_ID] =
53 {
54 .config = (0),
55 .hwaddr = {0x98, 0x0e, 0x24, 0x00, 0x11, 0x2},
56 },
57 [FXMAC3_ID] =
58 {
59 .config = (0),
60 .hwaddr = {0x98, 0x0e, 0x24, 0x00, 0x11, 0x3},
61 },
62 };
63
64 int isr_calling_flg = 0;
65
66 /* queue */
67
FXmacQueueInit(PqQueue * q)68 void FXmacQueueInit(PqQueue *q)
69 {
70 FASSERT(q != NULL);
71 q->head = q->tail = q->len = 0;
72 }
73
FXmacPqEnqueue(PqQueue * q,void * p)74 int FXmacPqEnqueue(PqQueue *q, void *p)
75 {
76 if (q->len == PQ_QUEUE_SIZE)
77 {
78 return -1;
79 }
80
81 q->data[q->head] = (uintptr)p;
82 q->head = (q->head + 1) % PQ_QUEUE_SIZE;
83 q->len++;
84
85 return 0;
86 }
87
FXmacPqDequeue(PqQueue * q)88 void *FXmacPqDequeue(PqQueue *q)
89 {
90 int ptail;
91
92 if (q->len == 0)
93 {
94 return NULL;
95 }
96
97 ptail = q->tail;
98 q->tail = (q->tail + 1) % PQ_QUEUE_SIZE;
99 q->len--;
100
101 return (void *)q->data[ptail];
102 }
103
FXmacPqQlength(PqQueue * q)104 int FXmacPqQlength(PqQueue *q)
105 {
106 return q->len;
107 }
108
109 /* dma */
110
111 /**
112 * @name: IsTxSpaceAvailable
113 * @msg: Get the number of free BDs in the Bdrings
114 * @param {ethernetif} *ethernetif_p
115 * @return {*}
116 */
IsTxSpaceAvailable(FXmacOs * instance_p)117 static u32 IsTxSpaceAvailable(FXmacOs *instance_p)
118 {
119 FXmacBdRing *txring;
120 u32 freecnt;
121 FASSERT(instance_p != NULL);
122
123 txring = &(FXMAC_GET_TXRING(instance_p->instance));
124
125 /* tx space is available as long as there are valid BD's */
126 freecnt = FXMAC_BD_RING_GET_FREE_CNT(txring);
127 return freecnt;
128 }
129
130 /**
131 * @name: FXmacProcessSentBds
132 * @msg: Free up memory space of pbuf on the send queue
133 * @return {*}
134 * @param {ethernetif} *ethernetif_p
135 * @param {FXmacBdRing} *txring
136 */
FXmacProcessSentBds(FXmacOs * instance_p,FXmacBdRing * txring)137 void FXmacProcessSentBds(FXmacOs *instance_p, FXmacBdRing *txring)
138 {
139 FXmacBd *txbdset;
140 FXmacBd *curbdpntr;
141 u32 n_bds;
142 FError status;
143 u32 n_pbufs_freed;
144 u32 bdindex;
145 struct pbuf *p;
146 u32 *temp;
147
148 while (1)
149 {
150 /* obtain processed BD's */
151 n_bds = FXmacBdRingFromHwTx(txring, FXMAX_TX_PBUFS_LENGTH, &txbdset);
152 if (n_bds == 0)
153 {
154 return;
155 }
156 /* free the processed BD's */
157 n_pbufs_freed = n_bds;
158 curbdpntr = txbdset;
159 while (n_pbufs_freed > 0)
160 {
161 bdindex = FXMAC_BD_TO_INDEX(txring, curbdpntr);
162 temp = (u32 *)curbdpntr;
163 *temp = 0; /* Word 0 */
164 temp++;
165 if (bdindex == (FXMAX_TX_PBUFS_LENGTH - 1))
166 {
167 *temp = 0xC0000000; /* Word 1 ,used/Wrap – marks last descriptor in transmit buffer descriptor list.*/
168 }
169 else
170 {
171 *temp = 0x80000000; /* Word 1 , Used – must be zero for GEM to read data to the transmit buffer.*/
172 }
173
174
175 p = (struct pbuf *)instance_p->buffer.tx_pbufs_storage[bdindex];
176
177 if (p != NULL)
178 {
179 pbuf_free(p);
180 }
181 instance_p->buffer.tx_pbufs_storage[bdindex] = (uintptr)NULL;
182 curbdpntr = FXMAC_BD_RING_NEXT(txring, curbdpntr);
183 n_pbufs_freed--;
184
185 }
186
187 status = FXmacBdRingFree(txring, n_bds, txbdset);
188 if (status != FT_SUCCESS)
189 {
190 LOG_I("Failure while freeing in Tx Done ISR.");
191 }
192 }
193 return;
194 }
195
FXmacSgsend(FXmacOs * instance_p,struct pbuf * p)196 FError FXmacSgsend(FXmacOs *instance_p, struct pbuf *p)
197 {
198 struct pbuf *q;
199 u32 n_pbufs;
200 FXmacBd *txbdset, *txbd, *last_txbd = NULL;
201 FXmacBd *temp_txbd;
202 FError status;
203 FXmacBdRing *txring;
204 u32 bdindex;
205 uintptr tx_payload ;
206 u32 max_fr_size;
207
208
209 txring = &(FXMAC_GET_TXRING(instance_p->instance));
210
211 /* first count the number of pbufs */
212 for (q = p, n_pbufs = 0; q != NULL; q = q->next)
213 {
214 n_pbufs++;
215 }
216
217 /* obtain as many BD's */
218 status = FXmacBdRingAlloc(txring, n_pbufs, &txbdset);
219 if (status != FT_SUCCESS)
220 {
221 LOG_I("sgsend: Error allocating TxBD.");
222 return ERR_GENERAL;
223 }
224
225 for (q = p, txbd = txbdset; q != NULL; q = q->next)
226 {
227 bdindex = FXMAC_BD_TO_INDEX(txring, txbd);
228
229 if (instance_p->buffer.tx_pbufs_storage[bdindex])
230 {
231 LOG_I("txbd %p, txring->base_bd_addr %p", txbd, txring->base_bd_addr);
232 LOG_I("PBUFS not available bdindex is %d ", bdindex);
233 LOG_I("instance_p->buffer.tx_pbufs_storage[bdindex] %p ", instance_p->buffer.tx_pbufs_storage[bdindex]);
234 return ERR_GENERAL;
235 }
236
237 /* Send the data from the pbuf to the interface, one pbuf at a
238 time. The size of the data in each pbuf is kept in the ->len
239 variable. */
240 tx_payload = (uintptr)q->payload;
241 #ifdef RT_USING_SMART
242 tx_payload += PV_OFFSET;
243 #endif
244 FXMAC_BD_SET_ADDRESS_TX(txbd, (uintptr)tx_payload);
245 if (instance_p->config & FXMAC_OS_CONFIG_JUMBO)
246 {
247 max_fr_size = FXMAC_MAX_FRAME_SIZE_JUMBO;
248 }
249 else
250 {
251 max_fr_size = FXMAC_MAX_FRAME_SIZE;
252 }
253
254 if (q->len > max_fr_size)
255 {
256 FXMAC_BD_SET_LENGTH(txbd, max_fr_size & 0x3FFF);
257 }
258 else
259 {
260 FXMAC_BD_SET_LENGTH(txbd, q->len & 0x3FFF);
261 }
262
263 instance_p->buffer.tx_pbufs_storage[bdindex] = (uintptr)q;
264
265 pbuf_ref(q);
266 last_txbd = txbd;
267 FXMAC_BD_CLEAR_LAST(txbd);
268 txbd = FXMAC_BD_RING_NEXT(txring, txbd);
269 }
270 FXMAC_BD_SET_LAST(last_txbd);
271 /* For fragmented packets, remember the 1st BD allocated for the 1st
272 packet fragment. The used bit for this BD should be cleared at the end
273 after clearing out used bits for other fragments. For packets without
274 just remember the allocated BD. */
275 temp_txbd = txbdset;
276 txbd = txbdset;
277 txbd = FXMAC_BD_RING_NEXT(txring, txbd);
278 q = p->next;
279 for (; q != NULL; q = q->next)
280 {
281 FXMAC_BD_CLEAR_TX_USED(txbd);
282
283 txbd = FXMAC_BD_RING_NEXT(txring, txbd);
284 }
285 FXMAC_BD_CLEAR_TX_USED(temp_txbd);
286
287
288 status = FXmacBdRingToHw(txring, n_pbufs, txbdset);
289 if (status != FT_SUCCESS)
290 {
291 LOG_I("sgsend: Error submitting TxBD.");
292 return ERR_GENERAL;
293 }
294 /* Start transmit */
295 FXMAC_WRITEREG32((instance_p->instance).config.base_address,
296 FXMAC_NWCTRL_OFFSET,
297 (FXMAC_READREG32(instance_p->instance.config.base_address,
298 FXMAC_NWCTRL_OFFSET) |
299 FXMAC_NWCTRL_STARTTX_MASK));
300
301 return status;
302 }
303
SetupRxBds(FXmacOs * instance_p,FXmacBdRing * rxring)304 void SetupRxBds(FXmacOs *instance_p, FXmacBdRing *rxring)
305 {
306 FXmacBd *rxbd;
307 FError status;
308 struct pbuf *p;
309 u32 freebds;
310 u32 bdindex;
311 u32 *temp;
312 uintptr_t pl_paddr;
313 freebds = FXMAC_BD_RING_GET_FREE_CNT(rxring);
314 while (freebds > 0)
315 {
316 freebds--;
317
318 if (instance_p->config & FXMAC_OS_CONFIG_JUMBO)
319 {
320 p = pbuf_alloc(PBUF_RAW, FXMAC_MAX_FRAME_SIZE_JUMBO, PBUF_RAM);
321 }
322 else
323 {
324 p = pbuf_alloc(PBUF_RAW, FXMAC_MAX_FRAME_SIZE, PBUF_RAM);
325 }
326
327 if (!p)
328 {
329 #if LINK_STATS
330 lwip_stats.link.memerr++;
331 lwip_stats.link.drop++;
332 #endif
333 LOG_I("Unable to alloc pbuf in recv_handler.");
334 return;
335 }
336 status = FXmacBdRingAlloc(rxring, 1, &rxbd);
337 if (status != FT_SUCCESS)
338 {
339 LOG_I("SetupRxBds: Error allocating RxBD.");
340 pbuf_free(p);
341 return;
342 }
343 status = FXmacBdRingToHw(rxring, 1, rxbd);
344 if (status != FT_SUCCESS)
345 {
346 LOG_I("Error committing RxBD to hardware: ");
347 if (status == FXMAC_ERR_SG_LIST)
348 {
349 LOG_I("XST_DMA_SG_LIST_ERROR: this function was called out of sequence with FXmacBdRingAlloc().");
350 }
351 else
352 {
353 LOG_I("Set of BDs was rejected because the first BD did not have its start-of-packet bit set, or the last BD did not have its end-of-packet bit set, or any one of the BD set has 0 as length value.");
354 }
355
356 pbuf_free(p);
357 FXmacBdRingUnAlloc(rxring, 1, rxbd);
358 return;
359 }
360
361 bdindex = FXMAC_BD_TO_INDEX(rxring, rxbd);
362 temp = (u32 *)rxbd;
363 if (bdindex == (FXMAX_RX_PBUFS_LENGTH - 1))
364 {
365 *temp = 0x00000002;
366 }
367 else
368 {
369 *temp = 0;
370 }
371 temp++;
372 *temp = 0;
373 pl_paddr = (uintptr)p->payload;
374 #ifdef RT_USING_SMART
375 pl_paddr += PV_OFFSET;
376 #endif
377 FXMAC_BD_SET_ADDRESS_RX(rxbd, (uintptr)pl_paddr);
378 instance_p->buffer.rx_pbufs_storage[bdindex] = (uintptr)p;
379 }
380 }
FXmacRecvSemaphoreHandler(void * arg)381 void FXmacRecvSemaphoreHandler(void *arg)
382 {
383 FXmacOs *instance_p;
384 rt_err_t result;
385
386 if (RT_NULL == arg)
387 {
388 LOG_E("Args is NULL");
389 return;
390 }
391
392 instance_p = (FXmacOs *)arg;
393
394 result = eth_device_ready(&(instance_p->parent));
395 if (result != RT_EOK)
396 {
397 LOG_I("RxCpltCallback err = %d", result);
398 }
399
400 }
FXmacRecvHandler(void * arg)401 void FXmacRecvHandler(void *arg)
402 {
403 struct pbuf *p;
404 FXmacBd *rxbdset, *curbdptr;
405 FXmacBdRing *rxring;
406 volatile u32 bd_processed;
407 u32 rx_bytes, k;
408 u32 bdindex;
409 u32 regval;
410 FXmacOs *instance_p;
411 FASSERT(arg != NULL);
412
413 instance_p = (FXmacOs *)arg;
414 rxring = &FXMAC_GET_RXRING(instance_p->instance);
415
416 /* If Reception done interrupt is asserted, call RX call back function
417 to handle the processed BDs and then raise the according flag.*/
418 regval = FXMAC_READREG32(instance_p->instance.config.base_address, FXMAC_RXSR_OFFSET);
419 FXMAC_WRITEREG32(instance_p->instance.config.base_address, FXMAC_RXSR_OFFSET, regval);
420
421 while (1)
422 {
423 bd_processed = FXmacBdRingFromHwRx(rxring, FXMAX_RX_PBUFS_LENGTH, &rxbdset);
424 if (bd_processed <= 0)
425 {
426 break;
427 }
428
429 for (k = 0, curbdptr = rxbdset; k < bd_processed; k++)
430 {
431
432 bdindex = FXMAC_BD_TO_INDEX(rxring, curbdptr);
433 p = (struct pbuf *)instance_p->buffer.rx_pbufs_storage[bdindex];
434 /*
435 * Adjust the buffer size to the actual number of bytes received.
436 */
437 if (instance_p->config & FXMAC_OS_CONFIG_JUMBO)
438 {
439 rx_bytes = FXMAC_GET_RX_FRAME_SIZE(curbdptr);
440 }
441 else
442 {
443 rx_bytes = FXMAC_BD_GET_LENGTH(curbdptr);
444 }
445
446 pbuf_realloc(p, rx_bytes);
447
448 /* Invalidate RX frame before queuing to handle
449 * L1 cache prefetch conditions on any architecture.
450 */
451 // FCacheDCacheInvalidateRange((uintptr)p->payload, rx_bytes);
452
453 /* store it in the receive queue,
454 * where it'll be processed by a different handler
455 */
456 if (FXmacPqEnqueue(&instance_p->recv_q, (void *)p) < 0)
457 {
458 #if LINK_STATS
459 lwip_stats.link.memerr++;
460 lwip_stats.link.drop++;
461 #endif
462 pbuf_free(p);
463 }
464 instance_p->buffer.rx_pbufs_storage[bdindex] = (uintptr)NULL;
465 curbdptr = FXMAC_BD_RING_NEXT(rxring, curbdptr);
466 }
467
468 /* free up the BD's */
469 FXmacBdRingFree(rxring, bd_processed, rxbdset);
470 SetupRxBds(instance_p, rxring);
471
472 }
473
474 return;
475 }
476
477
CleanDmaTxdescs(FXmacOs * instance_p)478 void CleanDmaTxdescs(FXmacOs *instance_p)
479 {
480 FXmacBd bdtemplate;
481 FXmacBdRing *txringptr;
482
483 txringptr = &FXMAC_GET_TXRING((instance_p->instance));
484 FXMAC_BD_CLEAR(&bdtemplate);
485 FXMAC_BD_SET_STATUS(&bdtemplate, FXMAC_TXBUF_USED_MASK);
486
487 FXmacBdRingCreate(txringptr, (uintptr)instance_p->buffer.tx_bdspace,
488 (uintptr)instance_p->buffer.tx_bdspace, BD_ALIGNMENT,
489 sizeof(instance_p->buffer.tx_bdspace));
490
491 FXmacBdRingClone(txringptr, &bdtemplate, FXMAC_SEND);
492 }
493
FXmacInitDma(FXmacOs * instance_p)494 FError FXmacInitDma(FXmacOs *instance_p)
495 {
496 FXmacBd bdtemplate;
497 FXmacBdRing *rxringptr, *txringptr;
498 FXmacBd *rxbd;
499 struct pbuf *p;
500 FError status;
501 int i;
502 u32 bdindex;
503 u32 *temp;
504 uintptr rx_paddr;
505 uintptr tx_paddr;
506 uintptr pl_paddr;
507
508 /*
509 * The BDs need to be allocated in uncached memory. Hence the 1 MB
510 * address range allocated for Bd_Space is made uncached
511 * by setting appropriate attributes in the translation table.
512 * The Bd_Space is aligned to 1MB and has a size of 1 MB. This ensures
513 * a reserved uncached area used only for BDs.
514 */
515
516 rxringptr = &FXMAC_GET_RXRING(instance_p->instance);
517 txringptr = &FXMAC_GET_TXRING(instance_p->instance);
518 LOG_I("rxringptr: 0x%08x", rxringptr);
519 LOG_I("txringptr: 0x%08x", txringptr);
520
521 LOG_I("rx_bdspace: %p ", instance_p->buffer.rx_bdspace);
522 LOG_I("tx_bdspace: %p ", instance_p->buffer.tx_bdspace);
523
524 /* Setup RxBD space. */
525 FXMAC_BD_CLEAR(&bdtemplate);
526 rx_paddr = (uintptr)instance_p->buffer.rx_bdspace;
527 #ifdef RT_USING_SMART
528 rx_paddr += PV_OFFSET;
529 #endif
530
531 /* Create the RxBD ring */
532 status = FXmacBdRingCreate(rxringptr, (uintptr)rx_paddr,
533 (uintptr)instance_p->buffer.rx_bdspace, BD_ALIGNMENT,
534 FXMAX_RX_PBUFS_LENGTH);
535
536 if (status != FT_SUCCESS)
537 {
538 LOG_I("Error setting up RxBD space.");
539 return ERR_IF;
540 }
541
542 status = FXmacBdRingClone(rxringptr, &bdtemplate, FXMAC_RECV);
543 if (status != FT_SUCCESS)
544 {
545 LOG_I("Error initializing RxBD space.");
546 return ERR_IF;
547 }
548
549 FXMAC_BD_CLEAR(&bdtemplate);
550 FXMAC_BD_SET_STATUS(&bdtemplate, FXMAC_TXBUF_USED_MASK);
551
552 tx_paddr = (uintptr)instance_p->buffer.tx_bdspace;
553 #ifdef RT_USING_SMART
554 tx_paddr += PV_OFFSET;
555 #endif
556 /* Create the TxBD ring */
557 status = FXmacBdRingCreate(txringptr, (uintptr)tx_paddr,
558 (uintptr)instance_p->buffer.tx_bdspace, BD_ALIGNMENT,
559 FXMAX_TX_PBUFS_LENGTH);
560
561 if (status != FT_SUCCESS)
562 {
563 return ERR_IF;
564 }
565
566 /* We reuse the bd template, as the same one will work for both rx and tx. */
567 status = FXmacBdRingClone(txringptr, &bdtemplate, FXMAC_SEND);
568 if (status != FT_SUCCESS)
569 {
570 return ERR_IF;
571 }
572
573 /*
574 * Allocate RX descriptors, 1 RxBD at a time.
575 */
576 for (i = 0; i < FXMAX_RX_PBUFS_LENGTH; i++)
577 {
578 if (instance_p->config & FXMAC_OS_CONFIG_JUMBO)
579 {
580 p = pbuf_alloc(PBUF_RAW, FXMAC_MAX_FRAME_SIZE_JUMBO, PBUF_RAM);
581 }
582 else
583 {
584 p = pbuf_alloc(PBUF_RAW, FXMAC_MAX_FRAME_SIZE, PBUF_RAM);
585 }
586
587 if (!p)
588 {
589 #if LINK_STATS
590 lwip_stats.link.memerr++;
591 lwip_stats.link.drop++;
592 #endif
593 LOG_E("Unable to alloc pbuf in InitDma.");
594 return ERR_IF;
595 }
596 status = FXmacBdRingAlloc(rxringptr, 1, &rxbd);
597 if (status != FT_SUCCESS)
598 {
599 LOG_E("InitDma: Error allocating RxBD.");
600 pbuf_free(p);
601 return ERR_IF;
602 }
603 /* Enqueue to HW */
604 status = FXmacBdRingToHw(rxringptr, 1, rxbd);
605 if (status != FT_SUCCESS)
606 {
607 LOG_E("Error: committing RxBD to HW.");
608 pbuf_free(p);
609 FXmacBdRingUnAlloc(rxringptr, 1, rxbd);
610 return ERR_IF;
611 }
612
613 bdindex = FXMAC_BD_TO_INDEX(rxringptr, rxbd);
614 temp = (u32 *)rxbd;
615 *temp = 0;
616 if (bdindex == (FXMAX_RX_PBUFS_LENGTH - 1))
617 {
618 *temp = 0x00000002;
619 }
620 temp++;
621 *temp = 0;
622
623 pl_paddr = (uintptr)p->payload;
624 #ifdef RT_USING_SMART
625 pl_paddr += PV_OFFSET;
626 #endif
627 FXMAC_BD_SET_ADDRESS_RX(rxbd, (uintptr)pl_paddr);
628
629 instance_p->buffer.rx_pbufs_storage[bdindex] = (uintptr)p;
630 }
631
632 FXmacSetQueuePtr(&(instance_p->instance), instance_p->instance.tx_bd_queue.bdring.phys_base_addr, 0, (u16)FXMAC_SEND);
633 FXmacSetQueuePtr(&(instance_p->instance), instance_p->instance.rx_bd_queue.bdring.phys_base_addr, 0, (u16)FXMAC_RECV);
634
635 return 0;
636 }
637
FreeOnlyTxPbufs(FXmacOs * instance_p)638 static void FreeOnlyTxPbufs(FXmacOs *instance_p)
639 {
640 u32 index;
641 struct pbuf *p;
642
643 for (index = 0; index < (FXMAX_TX_PBUFS_LENGTH); index++)
644 {
645 if (instance_p->buffer.tx_pbufs_storage[index] != 0)
646 {
647 p = (struct pbuf *)instance_p->buffer.tx_pbufs_storage[index];
648 pbuf_free(p);
649 instance_p->buffer.tx_pbufs_storage[index] = (uintptr)NULL;
650 }
651 instance_p->buffer.tx_pbufs_storage[index] = (uintptr)0;
652 }
653 }
654
655
FreeOnlyRxPbufs(FXmacOs * instance_p)656 static void FreeOnlyRxPbufs(FXmacOs *instance_p)
657 {
658 u32 index;
659 struct pbuf *p;
660
661 for (index = 0; index < (FXMAX_RX_PBUFS_LENGTH); index++)
662 {
663 if (instance_p->buffer.rx_pbufs_storage[index] != 0)
664 {
665 p = (struct pbuf *)instance_p->buffer.rx_pbufs_storage[index];
666 pbuf_free(p);
667 instance_p->buffer.rx_pbufs_storage[index] = (uintptr)0;
668 }
669 }
670 }
671
672
FreeTxRxPbufs(FXmacOs * instance_p)673 static void FreeTxRxPbufs(FXmacOs *instance_p)
674 {
675 u32 rx_queue_len;
676 struct pbuf *p;
677 /* first :free PqQueue data */
678 rx_queue_len = FXmacPqQlength(&instance_p->recv_q);
679
680 while (rx_queue_len)
681 {
682 /* return one packet from receive q */
683 p = (struct pbuf *)FXmacPqDequeue(&instance_p->recv_q);
684 pbuf_free(p);
685 LOG_E("Delete queue %p", p);
686 rx_queue_len--;
687 }
688 FreeOnlyTxPbufs(instance_p);
689 FreeOnlyRxPbufs(instance_p);
690
691 }
692
693 /* interrupt */
FXmacHandleDmaTxError(FXmacOs * instance_p)694 static void FXmacHandleDmaTxError(FXmacOs *instance_p)
695 {
696 s32_t status = FT_SUCCESS;
697 u32 dmacrreg;
698
699 FreeTxRxPbufs(instance_p);
700 status = FXmacCfgInitialize(&instance_p->instance, &instance_p->instance.config);
701
702 if (status != FT_SUCCESS)
703 {
704 LOG_E("In %s:EmacPs Configuration Failed....", __func__);
705 }
706
707 /* initialize the mac */
708 FXmacInitOnError(instance_p); /* need to set mac filter address */
709 dmacrreg = FXMAC_READREG32(instance_p->instance.config.base_address, FXMAC_DMACR_OFFSET);
710 dmacrreg = dmacrreg | (FXMAC_DMACR_ORCE_DISCARD_ON_ERR_MASK); /* force_discard_on_err */
711 FXMAC_WRITEREG32(instance_p->instance.config.base_address, FXMAC_DMACR_OFFSET, dmacrreg);
712 FXmacSetupIsr(instance_p);
713 FXmacInitDma(instance_p);
714
715 FXmacStart(&instance_p->instance);
716
717 }
718
FXmacHandleTxErrors(FXmacOs * instance_p)719 void FXmacHandleTxErrors(FXmacOs *instance_p)
720 {
721 u32 netctrlreg;
722
723 netctrlreg = FXMAC_READREG32(instance_p->instance.config.base_address,
724 FXMAC_NWCTRL_OFFSET);
725 netctrlreg = netctrlreg & (~FXMAC_NWCTRL_TXEN_MASK);
726 FXMAC_WRITEREG32(instance_p->instance.config.base_address,
727 FXMAC_NWCTRL_OFFSET, netctrlreg);
728 FreeOnlyTxPbufs(instance_p);
729
730 CleanDmaTxdescs(instance_p);
731 netctrlreg = FXMAC_READREG32(instance_p->instance.config.base_address, FXMAC_NWCTRL_OFFSET);
732 netctrlreg = netctrlreg | (FXMAC_NWCTRL_TXEN_MASK);
733 FXMAC_WRITEREG32(instance_p->instance.config.base_address, FXMAC_NWCTRL_OFFSET, netctrlreg);
734 }
735
FXmacErrorHandler(void * arg,u8 direction,u32 error_word)736 void FXmacErrorHandler(void *arg, u8 direction, u32 error_word)
737 {
738 FXmacBdRing *rxring;
739 FXmacBdRing *txring;
740 FXmacOs *instance_p;
741
742 instance_p = (FXmacOs *)arg;
743 rxring = &FXMAC_GET_RXRING(instance_p->instance);
744 txring = &FXMAC_GET_TXRING(instance_p->instance);
745
746 if (error_word != 0)
747 {
748 switch (direction)
749 {
750 case FXMAC_RECV:
751 if (error_word & FXMAC_RXSR_HRESPNOK_MASK)
752 {
753 LOG_I("Receive DMA error.");
754 FXmacHandleDmaTxError(instance_p);
755 }
756 if (error_word & FXMAC_RXSR_RXOVR_MASK)
757 {
758 LOG_I("Receive over run.");
759 FXmacRecvHandler(arg);
760 }
761 if (error_word & FXMAC_RXSR_BUFFNA_MASK)
762 {
763 LOG_I("Receive buffer not available.");
764 FXmacRecvHandler(arg);
765 }
766 break;
767 case FXMAC_SEND:
768 if (error_word & FXMAC_TXSR_HRESPNOK_MASK)
769 {
770 LOG_I("Transmit DMA error.");
771 FXmacHandleDmaTxError(instance_p);
772 }
773 if (error_word & FXMAC_TXSR_URUN_MASK)
774 {
775 LOG_I("Transmit under run.");
776 FXmacHandleTxErrors(instance_p);
777 }
778 if (error_word & FXMAC_TXSR_BUFEXH_MASK)
779 {
780 LOG_I("Transmit buffer exhausted.");
781 FXmacHandleTxErrors(instance_p);
782 }
783 if (error_word & FXMAC_TXSR_RXOVR_MASK)
784 {
785 LOG_I("Transmit retry excessed limits.");
786 FXmacHandleTxErrors(instance_p);
787 }
788 if (error_word & FXMAC_TXSR_FRAMERX_MASK)
789 {
790 LOG_I("Transmit collision.");
791 FXmacProcessSentBds(instance_p, txring);
792 }
793 break;
794 }
795 }
796 }
797
FXmacLinkChange(void * arg)798 void FXmacLinkChange(void *arg)
799 {
800 u32 ctrl;
801 u32 link, link_status;
802 FXmac *xmac_p;
803 FXmacOs *instance_p;
804
805 instance_p = (FXmacOs *)arg;
806 xmac_p = &instance_p->instance;
807
808 if (xmac_p->config.interface == FXMAC_PHY_INTERFACE_MODE_SGMII)
809 {
810 LOG_I("xmac_p->config.base_address is %p", xmac_p->config.base_address);
811 ctrl = FXMAC_READREG32(xmac_p->config.base_address, FXMAC_PCS_AN_LP_OFFSET);
812 link = (ctrl & FXMAC_PCS_LINK_PARTNER_NEXT_PAGE_STATUS) >> 15;
813
814
815 switch (link)
816 {
817 case 0:
818 LOG_I("Link status is down");
819 link_status = FXMAC_LINKDOWN;
820 break;
821 case 1:
822 LOG_I("Link status is up");
823 link_status = FXMAC_LINKUP;
824 break;
825 default:
826 LOG_E("Link status is error 0x%x ", link);
827 return;
828 }
829
830 if (link_status == FXMAC_LINKUP)
831 {
832 if (link_status != xmac_p->link_status)
833 {
834 xmac_p->link_status = FXMAC_NEGOTIATING;
835 LOG_I("Need NEGOTIATING.");
836 }
837 }
838 else
839 {
840 xmac_p->link_status = FXMAC_LINKDOWN;
841 }
842 }
843 }
844
845 /* phy */
846
847 /**
848 * @name: FXmacPhyLinkDetect
849 * @msg: Get current link status
850 * @note:
851 * @param {FXmac} *fxmac_p
852 * @param {u32} phy_addr
853 * @return {*} 1 is link up , 0 is link down
854 */
FXmacPhyLinkDetect(FXmac * xmac_p,u32 phy_addr)855 static u32 FXmacPhyLinkDetect(FXmac *xmac_p, u32 phy_addr)
856 {
857 u16 status;
858
859 /* Read Phy Status register twice to get the confirmation of the current
860 * link status.
861 */
862
863 FXmacPhyRead(xmac_p, phy_addr, PHY_STATUS_REG_OFFSET, &status);
864
865 if (status & PHY_STAT_LINK_STATUS)
866 {
867 return 1;
868 }
869 return 0;
870 }
871
FXmacPhyAutonegStatus(FXmac * xmac_p,u32 phy_addr)872 static u32 FXmacPhyAutonegStatus(FXmac *xmac_p, u32 phy_addr)
873 {
874 u16 status;
875
876 /* Read Phy Status register twice to get the confirmation of the current
877 * link status.
878 */
879 FXmacPhyRead(xmac_p, phy_addr, PHY_STATUS_REG_OFFSET, &status);
880
881 if (status & PHY_STATUS_AUTONEGOTIATE_COMPLETE)
882 {
883 return 1;
884 }
885 return 0;
886 }
887
FXmacLwipPortLinkDetect(FXmacOs * instance_p)888 enum lwip_port_link_status FXmacLwipPortLinkDetect(FXmacOs *instance_p)
889 {
890 u32 phy_link_status;
891 FXmac *xmac_p = &instance_p->instance;
892
893 if (xmac_p->is_ready != (u32)FT_COMPONENT_IS_READY)
894 {
895 return ETH_LINK_UNDEFINED;
896 }
897
898 phy_link_status = FXmacPhyLinkDetect(xmac_p, xmac_p->phy_address);
899
900 if ((xmac_p->link_status == FXMAC_LINKUP) && (!phy_link_status))
901 {
902 xmac_p->link_status = FXMAC_LINKDOWN;
903 }
904
905 switch (xmac_p->link_status)
906 {
907 case FXMAC_LINKUP:
908 return ETH_LINK_UP;
909 case FXMAC_LINKDOWN:
910 xmac_p->link_status = FXMAC_NEGOTIATING;
911 LOG_D("Ethernet Link down.");
912 return ETH_LINK_DOWN;
913 case FXMAC_NEGOTIATING:
914 if ((phy_link_status == FXMAC_LINKUP) && FXmacPhyAutonegStatus(xmac_p, xmac_p->phy_address))
915 {
916 err_t phy_ret;
917 phy_ret = FXmacPhyInit(xmac_p, xmac_p->config.speed, xmac_p->config.duplex, xmac_p->config.auto_neg, XMAC_PHY_RESET_DISABLE);
918
919 if (phy_ret != FT_SUCCESS)
920 {
921 LOG_E("FXmacPhyInit is error.");
922 return ETH_LINK_DOWN;
923 }
924 FXmacSelectClk(xmac_p);
925 FXmacInitInterface(xmac_p);
926
927 /* Initiate Phy setup to get link speed */
928 xmac_p->link_status = FXMAC_LINKUP;
929 LOG_D("Ethernet Link up.");
930 return ETH_LINK_UP;
931 }
932 return ETH_LINK_DOWN;
933 default:
934 return ETH_LINK_DOWN;
935 }
936 }
937
FXmacPhyReconnect(FXmacOs * instance_p)938 enum lwip_port_link_status FXmacPhyReconnect(FXmacOs *instance_p)
939 {
940 FXmac *xmac_p;
941
942 xmac_p = &instance_p->instance;
943
944 if (xmac_p->config.interface == FXMAC_PHY_INTERFACE_MODE_SGMII)
945 {
946 rt_hw_interrupt_mask(xmac_p->config.queue_irq_num[0]);
947 if (xmac_p->link_status == FXMAC_NEGOTIATING)
948 {
949 /* auto negotiation again*/
950 err_t phy_ret;
951 phy_ret = FXmacPhyInit(xmac_p, xmac_p->config.speed, xmac_p->config.duplex, xmac_p->config.auto_neg, XMAC_PHY_RESET_DISABLE);
952 if (phy_ret != FT_SUCCESS)
953 {
954 LOG_I("FXmacPhyInit is error.");
955 rt_hw_interrupt_umask(xmac_p->config.queue_irq_num[0]);
956 return ETH_LINK_DOWN;
957 }
958 FXmacSelectClk(xmac_p);
959 FXmacInitInterface(xmac_p);
960 xmac_p->link_status = FXMAC_LINKUP;
961 }
962
963 rt_hw_interrupt_umask(xmac_p->config.queue_irq_num[0]);
964
965 switch (xmac_p->link_status)
966 {
967 case FXMAC_LINKDOWN:
968 return ETH_LINK_DOWN;
969 case FXMAC_LINKUP:
970 return ETH_LINK_UP;
971 default:
972 return ETH_LINK_DOWN;
973 }
974 }
975 else if ((xmac_p->config.interface == FXMAC_PHY_INTERFACE_MODE_RMII) || (xmac_p->config.interface == FXMAC_PHY_INTERFACE_MODE_RGMII))
976 {
977 return FXmacLwipPortLinkDetect(instance_p);
978 }
979 else
980 {
981 switch (xmac_p->link_status)
982 {
983 case FXMAC_LINKDOWN:
984 return ETH_LINK_DOWN;
985 case FXMAC_LINKUP:
986 return ETH_LINK_UP;
987 default:
988 return ETH_LINK_DOWN;
989 }
990 }
991 }
992
FxmacOsIntrHandler(s32 vector,void * args)993 static void FxmacOsIntrHandler(s32 vector, void *args)
994 {
995 isr_calling_flg++;
996 FXmacIntrHandler(vector, args);
997 isr_calling_flg--;
998 }
999
FXmacSetupIsr(FXmacOs * instance_p)1000 static void FXmacSetupIsr(FXmacOs *instance_p)
1001 {
1002
1003 /* Setup callbacks */
1004 FXmacSetHandler(&instance_p->instance, FXMAC_HANDLER_DMARECV, FXmacRecvSemaphoreHandler, instance_p);
1005 FXmacSetHandler(&instance_p->instance, FXMAC_HANDLER_ERROR, FXmacErrorHandler, instance_p);
1006 FXmacSetHandler(&instance_p->instance, FXMAC_HANDLER_LINKCHANGE, FXmacLinkChange, instance_p);
1007
1008 rt_hw_interrupt_install(instance_p->instance.config.queue_irq_num[0], FxmacOsIntrHandler, &instance_p->instance, "fxmac");
1009 rt_hw_interrupt_umask(instance_p->instance.config.queue_irq_num[0]);
1010 }
1011
1012 /* init fxmac instance */
1013
FXmacInitOnError(FXmacOs * instance_p)1014 static void FXmacInitOnError(FXmacOs *instance_p)
1015 {
1016 FXmac *xmac_p;
1017 u32 status = FT_SUCCESS;
1018 xmac_p = &instance_p->instance;
1019
1020 /* set mac address */
1021 status = FXmacSetMacAddress(xmac_p, (void *)(instance_p->hwaddr), 1);
1022 if (status != FT_SUCCESS)
1023 {
1024 LOG_E("In %s:Emac Mac Address set failed...", __func__);
1025 }
1026 }
1027
1028 /* step 1: initialize instance */
1029 /* step 2: depend on config set some options : JUMBO / IGMP */
1030 /* step 3: FXmacSelectClk */
1031 /* step 4: FXmacInitInterface */
1032 /* step 5: initialize phy */
1033 /* step 6: initialize dma */
1034 /* step 7: initialize interrupt */
1035 /* step 8: start mac */
1036
FXmacOsInit(FXmacOs * instance_p)1037 FError FXmacOsInit(FXmacOs *instance_p)
1038 {
1039 FXmacConfig mac_config;
1040 FXmacConfig *mac_config_p;
1041 FXmacPhyInterface interface = FXMAC_PHY_INTERFACE_MODE_SGMII;
1042 FXmac *xmac_p;
1043 u32 dmacrreg;
1044 FError status;
1045 FASSERT(instance_p != NULL);
1046 FASSERT(instance_p->mac_config.instance_id < FXMAC_NUM);
1047
1048 xmac_p = &instance_p->instance;
1049 LOG_I("instance_id IS %d", instance_p->mac_config.instance_id);
1050 mac_config_p = FXmacLookupConfig(instance_p->mac_config.instance_id);
1051 if (mac_config_p == NULL)
1052 {
1053 LOG_E("FXmacLookupConfig is error , instance_id is %d", instance_p->mac_config.instance_id);
1054 return FREERTOS_XMAC_INIT_ERROR;
1055 }
1056 #ifdef RT_USING_SMART
1057 mac_config_p->base_address = (uintptr)rt_ioremap((void *)mac_config_p->base_address, 0x2000);
1058 #endif
1059 mac_config = *mac_config_p;
1060 switch (instance_p->mac_config.interface)
1061 {
1062 case FXMAC_OS_INTERFACE_SGMII:
1063 interface = FXMAC_PHY_INTERFACE_MODE_SGMII;
1064 LOG_I("SGMII select.");
1065 break;
1066 case FXMAC_OS_INTERFACE_RMII:
1067 interface = FXMAC_PHY_INTERFACE_MODE_RMII;
1068 LOG_I("RMII select.");
1069 break;
1070 case FXMAC_OS_INTERFACE_RGMII:
1071 LOG_I("RGMII select.");
1072 interface = FXMAC_PHY_INTERFACE_MODE_RGMII;
1073 break;
1074 default:
1075 LOG_E("Update interface is error , interface is %d", instance_p->mac_config.instance_id);
1076 return FREERTOS_XMAC_INIT_ERROR;
1077 }
1078 mac_config.interface = interface;
1079
1080 if (instance_p->mac_config.autonegotiation)
1081 {
1082 mac_config.auto_neg = 1;
1083 }
1084 else
1085 {
1086 mac_config.auto_neg = 0;
1087 }
1088
1089 switch (instance_p->mac_config.phy_speed)
1090 {
1091 case FXMAC_PHY_SPEED_10M:
1092 mac_config.speed = FXMAC_SPEED_10;
1093 break;
1094 case FXMAC_PHY_SPEED_100M:
1095 mac_config.speed = FXMAC_SPEED_100;
1096 break;
1097 case FXMAC_PHY_SPEED_1000M:
1098 mac_config.speed = FXMAC_SPEED_1000;
1099 break;
1100 default:
1101 LOG_E("Setting speed is not valid , speed is %d", instance_p->mac_config.phy_speed);
1102 return FREERTOS_XMAC_INIT_ERROR;
1103 }
1104
1105 switch (instance_p->mac_config.phy_duplex)
1106 {
1107 case FXMAC_PHY_HALF_DUPLEX:
1108 mac_config.duplex = 0;
1109 break;
1110 case FXMAC_PHY_FULL_DUPLEX:
1111 mac_config.duplex = 1;
1112 break;
1113 }
1114
1115 status = FXmacCfgInitialize(xmac_p, &mac_config);
1116 if (status != FT_SUCCESS)
1117 {
1118 LOG_E("In %s:EmacPs Configuration Failed....", __func__);
1119 }
1120
1121 if (instance_p->config & FXMAC_OS_CONFIG_JUMBO)
1122 {
1123 FXmacSetOptions(xmac_p, FXMAC_JUMBO_ENABLE_OPTION, 0);
1124 }
1125
1126 if (instance_p->config & FXMAC_OS_CONFIG_MULTICAST_ADDRESS_FILITER)
1127 {
1128 FXmacSetOptions(xmac_p, FXMAC_MULTICAST_OPTION, 0);
1129 }
1130
1131 /* enable copy all frames */
1132 if (instance_p->config & FXMAC_OS_CONFIG_COPY_ALL_FRAMES)
1133 {
1134 FXmacSetOptions(xmac_p, FXMAC_PROMISC_OPTION, 0);
1135 }
1136
1137 status = FXmacSetMacAddress(xmac_p, (void *)(instance_p->hwaddr), 0);
1138 if (status != FT_SUCCESS)
1139 {
1140 LOG_E("In %s:Emac Mac Address set failed...", __func__);
1141 }
1142
1143 /* close fcs check */
1144 if (instance_p->config & FXMAC_OS_CONFIG_CLOSE_FCS_CHECK)
1145 {
1146 FXmacSetOptions(xmac_p, FXMAC_FCS_STRIP_OPTION, 0);
1147 }
1148
1149 /* initialize phy */
1150 status = FXmacPhyInit(xmac_p, xmac_p->config.speed, xmac_p->config.duplex, xmac_p->config.auto_neg, XMAC_PHY_RESET_ENABLE);
1151 if (status != FT_SUCCESS)
1152 {
1153 LOG_W("FXmacPhyInit is error.");
1154 }
1155
1156 FXmacSelectClk(xmac_p);
1157 FXmacInitInterface(xmac_p);
1158
1159 /* initialize dma */
1160 dmacrreg = FXMAC_READREG32(xmac_p->config.base_address, FXMAC_DMACR_OFFSET);
1161 dmacrreg &= (~(FXMAC_DMACR_BLENGTH_MASK));
1162 dmacrreg |= (FXMAC_DMACR_INCR16_AHB_AXI_BURST); /* Attempt to use bursts of up to 16. */
1163 FXMAC_WRITEREG32(xmac_p->config.base_address, FXMAC_DMACR_OFFSET, dmacrreg);
1164 FXmacInitDma(instance_p);
1165
1166
1167 /* initialize interrupt */
1168 FXmacSetupIsr(instance_p);
1169
1170 return FT_SUCCESS;
1171 }
1172
1173
1174
1175
1176 /**
1177 * @name: FXmacOsRx
1178 * @msg: struct pbuf *FXmacOsRx(FXmacOs *instance_p)
1179 * @return {*}
1180 * @note:
1181 * @param {FXmacOs} *instance_p
1182 */
FXmacOsRx(FXmacOs * instance_p)1183 struct pbuf *FXmacOsRx(FXmacOs *instance_p)
1184 {
1185 FASSERT(instance_p != NULL);
1186 struct pbuf *p;
1187
1188 /* see if there is data to process */
1189 if (FXmacPqQlength(&instance_p->recv_q) == 0)
1190 {
1191 return NULL;
1192 }
1193 /* return one packet from receive q */
1194 p = (struct pbuf *)FXmacPqDequeue(&instance_p->recv_q);
1195
1196 return p;
1197 }
1198
FXmacOsOutput(FXmacOs * instance_p,struct pbuf * p)1199 static FError FXmacOsOutput(FXmacOs *instance_p, struct pbuf *p)
1200 {
1201 FError status;
1202
1203 status = FXmacSgsend(instance_p, p);
1204 if (status != FT_SUCCESS)
1205 {
1206 #if LINK_STATS
1207 lwip_stats.link.drop++;
1208 #endif
1209 }
1210
1211 #if LINK_STATS
1212 lwip_stats.link.xmit++;
1213 #endif /* LINK_STATS */
1214
1215 return status;
1216 }
1217
FXmacOsTx(FXmacOs * instance_p,void * tx_buf)1218 FError FXmacOsTx(FXmacOs *instance_p, void *tx_buf)
1219 {
1220 FXmacBdRing *txring;
1221 FError ret;
1222 struct pbuf *p;
1223 FASSERT(instance_p != NULL);
1224 FASSERT(tx_buf != NULL);
1225
1226 p = tx_buf;
1227 txring = &(FXMAC_GET_TXRING(instance_p->instance));
1228 FXmacProcessSentBds(instance_p, txring);
1229
1230 /* check if space is available to send */
1231 if (IsTxSpaceAvailable(instance_p))
1232 {
1233 ret = FXmacOsOutput(instance_p, p);
1234 }
1235 else
1236 {
1237 #if LINK_STATS
1238 lwip_stats.link.drop++;
1239 #endif
1240 LOG_E("Pack dropped, no space.");
1241 ret = FREERTOS_XMAC_NO_VALID_SPACE;
1242 }
1243
1244 return ret;
1245 }
1246
FXmacOsGetInstancePointer(FXmacOsControl * config_p)1247 FXmacOs *FXmacOsGetInstancePointer(FXmacOsControl *config_p)
1248 {
1249 FXmacOs *instance_p;
1250 FASSERT(config_p != NULL);
1251 FASSERT(config_p->instance_id < FXMAC_NUM);
1252 FASSERT_MSG(config_p->interface < FXMAC_OS_INTERFACE_LENGTH, "config_p->interface %d is over %d", config_p->interface, FXMAC_OS_INTERFACE_LENGTH);
1253 FASSERT_MSG(config_p->autonegotiation <= 1, "config_p->autonegotiation %d is over 1", config_p->autonegotiation);
1254 FASSERT_MSG(config_p->phy_speed <= FXMAC_PHY_SPEED_1000M, "config_p->phy_speed %d is over 1000", config_p->phy_speed);
1255 FASSERT_MSG(config_p->phy_duplex <= FXMAC_PHY_FULL_DUPLEX, "config_p->phy_duplex %d is over FXMAC_PHY_FULL_DUPLEX", config_p->phy_duplex);
1256
1257 instance_p = &fxmac_os_instace[config_p->instance_id];
1258 memcpy(&instance_p->mac_config, config_p, sizeof(FXmacOsControl));
1259 return instance_p;
1260 }
1261
FXmacOsStart(FXmacOs * instance_p)1262 void FXmacOsStart(FXmacOs *instance_p)
1263 {
1264 FASSERT(instance_p != NULL);
1265
1266 /* start mac */
1267 instance_p->instance.mask &= (~FXMAC_IXR_TXCOMPL_MASK);
1268 FXmacStart(&instance_p->instance);
1269 }
1270
rt_xmac_init(rt_device_t dev)1271 static rt_err_t rt_xmac_init(rt_device_t dev)
1272 {
1273
1274 struct eth_device *pXmacParent;
1275 FXmacOs *pOsMac;
1276
1277 FError ret;
1278
1279 pXmacParent = rt_container_of(dev, struct eth_device, parent);
1280 if (NULL == pXmacParent)
1281 {
1282 return -RT_ENOMEM;
1283 }
1284
1285 pOsMac = rt_container_of(pXmacParent, FXmacOs, parent);
1286 if (NULL == pOsMac)
1287 {
1288 return -RT_ENOMEM;
1289 }
1290
1291
1292 ret = FXmacOsInit(pOsMac);
1293
1294 if (ret != FT_SUCCESS)
1295 {
1296 LOG_E("FXmacOsInit is error\r\n");
1297 return -RT_ERROR;
1298 }
1299 rt_kprintf("FXMAC OS Init Success!\n");
1300
1301
1302 return RT_EOK;
1303 }
1304
rt_xmac_open(rt_device_t dev,rt_uint16_t oflag)1305 static rt_err_t rt_xmac_open(rt_device_t dev, rt_uint16_t oflag)
1306 {
1307 LOG_D("xmac open");
1308 return RT_EOK;
1309 }
1310
rt_xmac_close(rt_device_t dev)1311 static rt_err_t rt_xmac_close(rt_device_t dev)
1312 {
1313 LOG_D("xmac close");
1314 return RT_EOK;
1315 }
1316
rt_xmac_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)1317 static rt_ssize_t rt_xmac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
1318 {
1319 LOG_D("xmac read");
1320 rt_set_errno(-RT_ENOSYS);
1321 return 0;
1322 }
1323
rt_xmac_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)1324 static rt_ssize_t rt_xmac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
1325 {
1326 LOG_D("xmac write");
1327 rt_set_errno(-RT_ENOSYS);
1328 return 0;
1329 }
1330
rt_xmac_control(rt_device_t dev,int cmd,void * args)1331 static rt_err_t rt_xmac_control(rt_device_t dev, int cmd, void *args)
1332 {
1333
1334 FXmacOs *pOsMac;
1335 struct eth_device *pXmacParent;
1336
1337
1338 pXmacParent = rt_container_of(dev, struct eth_device, parent);
1339
1340 if (NULL == pXmacParent)
1341 {
1342 return -RT_ENOMEM;
1343 }
1344
1345 pOsMac = rt_container_of(pXmacParent, FXmacOs, parent);
1346 if (NULL == pOsMac)
1347 {
1348 return -RT_ENOMEM;
1349 }
1350 switch (cmd)
1351 {
1352 case NIOCTL_GADDR:
1353 /* get mac address */
1354 if (args)
1355 {
1356 rt_memcpy(args, pOsMac->hwaddr, 6);
1357 }
1358
1359 else
1360 {
1361 return -RT_ERROR;
1362 }
1363 break;
1364
1365 default:
1366 break;
1367 }
1368
1369 return RT_EOK;
1370 }
1371
rt_xmac_tx(rt_device_t dev,struct pbuf * p)1372 rt_err_t rt_xmac_tx(rt_device_t dev, struct pbuf *p)
1373 {
1374 FXmacOs *pOsMac;
1375 struct eth_device *pXmacParent;
1376 FError ret;
1377
1378 pXmacParent = rt_container_of(dev, struct eth_device, parent);
1379 if (NULL == pXmacParent)
1380 {
1381 return -RT_ENOMEM;
1382 }
1383
1384 pOsMac = rt_container_of(pXmacParent, FXmacOs, parent);
1385 if (NULL == pOsMac)
1386 {
1387 return -RT_ENOMEM;
1388 }
1389
1390 #if RT_LWIP_ETH_PAD_SIZE
1391 pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
1392 #endif
1393 ret = FXmacOsTx(pOsMac, p);
1394 #if RT_LWIP_ETH_PAD_SIZE
1395 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
1396 #endif
1397
1398
1399 if (ret != FT_SUCCESS)
1400 {
1401 return ERR_MEM;
1402 }
1403
1404 return RT_EOK;
1405
1406 }
1407
rt_xmac_rx(rt_device_t dev)1408 struct pbuf *rt_xmac_rx(rt_device_t dev)
1409 {
1410 FXmacOs *pOsMac;
1411 struct eth_device *pXmacParent;
1412 struct pbuf *p;
1413
1414 pXmacParent = rt_container_of(dev, struct eth_device, parent);
1415 if (NULL == pXmacParent)
1416 {
1417 return RT_NULL;
1418 }
1419
1420 pOsMac = rt_container_of(pXmacParent, FXmacOs, parent);
1421 if (NULL == pOsMac)
1422 {
1423 return RT_NULL;
1424 }
1425
1426 FXmacRecvHandler(pOsMac);
1427 p = FXmacOsRx(pOsMac);
1428 return p;
1429 }
1430
1431
eth_link_detect(FXmacOs * instance_p)1432 enum lwip_port_link_status eth_link_detect(FXmacOs *instance_p)
1433 {
1434 if (instance_p->instance.is_ready != FT_COMPONENT_IS_READY)
1435 {
1436 return ETH_LINK_UNDEFINED;
1437 }
1438
1439 return FXmacPhyReconnect(instance_p);
1440 }
1441
1442
ethernet_link_thread(void * Args)1443 static void ethernet_link_thread(void *Args)
1444 {
1445
1446 if (RT_NULL == Args)
1447 {
1448 return;
1449 }
1450
1451 FXmacOs *pOsMac;
1452 pOsMac = (FXmacOs *)Args;
1453
1454 while (1)
1455 {
1456 /* Call eth_link_detect() every 500ms to detect Ethernet link
1457 * change.
1458 */
1459
1460 switch (eth_link_detect(pOsMac))
1461 {
1462 case ETH_LINK_UP:
1463 if (pOsMac->is_link_up == 0)
1464 {
1465 LOG_I("netif flag is link_up\n");
1466 pOsMac->is_link_up = 1;
1467 eth_device_linkchange(&pOsMac->parent, RT_TRUE);
1468 }
1469 break;
1470 case ETH_LINK_DOWN:
1471 default:
1472 if (pOsMac->is_link_up == 1)
1473 {
1474 LOG_I("netif flag is link_down\n");
1475 pOsMac->is_link_up = 0;
1476 eth_device_linkchange(&pOsMac->parent, RT_FALSE);
1477 }
1478 break;
1479 }
1480 rt_thread_mdelay(500);
1481 }
1482 }
1483
1484 #ifdef RT_USING_DEVICE_OPS
1485 const struct rt_device_ops net_ops=
1486 {
1487 rt_xmac_init,
1488 rt_xmac_open,
1489 rt_xmac_close,
1490 rt_xmac_read,
1491 rt_xmac_write,
1492 rt_xmac_control
1493 };
1494 #endif
1495
rt_hw_xmac_init(FXmacOs * pOsMac,const char * name,const char * link_thread_name)1496 static int rt_hw_xmac_init(FXmacOs *pOsMac, const char *name, const char *link_thread_name)
1497 {
1498 rt_err_t state = RT_EOK;
1499
1500 #ifdef RT_USING_DEVICE_OPS
1501 pOsMac->parent.parent.ops= &net_ops;
1502 #else
1503 pOsMac->parent.parent.init = rt_xmac_init;
1504 pOsMac->parent.parent.open = rt_xmac_open;
1505 pOsMac->parent.parent.close = rt_xmac_close;
1506 pOsMac->parent.parent.read = rt_xmac_read;
1507 pOsMac->parent.parent.write = rt_xmac_write;
1508 pOsMac->parent.parent.control = rt_xmac_control;
1509 #endif
1510 pOsMac->parent.parent.user_data = RT_NULL;
1511
1512 pOsMac->parent.eth_rx = rt_xmac_rx;
1513 pOsMac->parent.eth_tx = rt_xmac_tx;
1514
1515 /* register eth device */
1516 state = eth_device_init(&(pOsMac->parent), name);
1517
1518 if (RT_EOK != state)
1519 {
1520 LOG_E("xmac device init faild: %d", state);
1521 return -RT_ERROR;
1522 }
1523 rt_kprintf("Xmac %s Initiailized!\n", name);
1524
1525
1526
1527 state = rt_thread_init(&pOsMac->_link_thread,
1528 link_thread_name,
1529 ethernet_link_thread,
1530 pOsMac,
1531 &pOsMac->_link_thread_stack[0],
1532 sizeof(pOsMac->_link_thread_stack),
1533 12, 2);
1534 if (RT_EOK == state)
1535 {
1536 rt_thread_startup(&pOsMac->_link_thread);
1537 }
1538 else
1539 {
1540 LOG_E("rt_thread_init is error");
1541 return -RT_ERROR;
1542 }
1543
1544 return RT_EOK;
1545 }
rt_hw_xmac_eth_init(void)1546 static int rt_hw_xmac_eth_init(void)
1547 {
1548 rt_err_t state = RT_EOK;
1549 FXmacOsControl os_config;
1550 FXmacOs *pOsMac;
1551
1552 #if defined(MAC_NUM0)
1553 /* os_config initialize,need to be set manually here */
1554 os_config.instance_id = MAC_NUM0_CONTROLLER;
1555 os_config.interface = MAC_NUM0_MII_INTERFACE;
1556 os_config.autonegotiation = 1; /* 1 is autonegotiation ,0 is manually set */
1557 os_config.phy_speed = FXMAC_PHY_SPEED_1000M; /* FXMAC_PHY_SPEED_XXX */
1558 os_config.phy_duplex = FXMAC_PHY_FULL_DUPLEX; /* FXMAC_PHY_XXX_DUPLEX */
1559
1560 pOsMac = FXmacOsGetInstancePointer(&os_config);
1561 if (pOsMac == NULL)
1562 {
1563 LOG_E("FXmacOsGetInstancePointer is error\r\n");
1564 return -RT_ERROR;
1565 }
1566
1567 const char *os_drv_xmac0_name = "e0";
1568 const char *e0_thread_name = "e0_link_detect";
1569
1570 state = rt_hw_xmac_init(pOsMac, os_drv_xmac0_name, e0_thread_name);
1571 extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr);
1572
1573 rt_kprintf("Set netif %s ip addr!\n", os_drv_xmac0_name);
1574 set_if(os_drv_xmac0_name, "192.168.4.10", "192.168.4.1", "255.255.255.0");
1575 if (RT_EOK != state)
1576 {
1577 goto __exit;
1578 }
1579 #endif
1580 #if defined(MAC_NUM1)
1581 os_config.instance_id = MAC_NUM1_CONTROLLER;
1582 os_config.interface = MAC_NUM1_MII_INTERFACE;
1583 os_config.autonegotiation = 1; /* 1 is autonegotiation ,0 is manually set */
1584 os_config.phy_speed = FXMAC_PHY_SPEED_1000M; /* FXMAC_PHY_SPEED_XXX */
1585 os_config.phy_duplex = FXMAC_PHY_FULL_DUPLEX; /* FXMAC_PHY_XXX_DUPLEX */
1586
1587 pOsMac = FXmacOsGetInstancePointer(&os_config);
1588 if (pOsMac == NULL)
1589 {
1590 LOG_E("FXmacOsGetInstancePointer is error\r\n");
1591 return -RT_ERROR;
1592 }
1593
1594 const char *os_drv_xmac1_name = "e1";
1595 const char *e1_thread_name = "e1_link_detect";
1596
1597 state = rt_hw_xmac_init(pOsMac, os_drv_xmac1_name, e1_thread_name);
1598 rt_kprintf("Set Xmac %s ip addr!\n", os_drv_xmac1_name);
1599 set_if(os_drv_xmac1_name, "192.168.4.11", "192.168.4.1", "255.255.255.0");
1600 if (RT_EOK != state)
1601 {
1602 goto __exit;
1603 }
1604 #endif
1605
1606 #if defined(MAC_NUM0)
1607 rt_kprintf("Start Xmac NUM0 \n");
1608 FXmacOsStart(&fxmac_os_instace[MAC_NUM0_CONTROLLER]);
1609 #endif
1610 #if defined(MAC_NUM1)
1611 rt_kprintf("Start Xmac NUM1 \n");
1612 FXmacOsStart(&fxmac_os_instace[MAC_NUM1_CONTROLLER]);
1613 #endif
1614
1615 __exit:
1616 return state;
1617 }
1618 INIT_DEVICE_EXPORT(rt_hw_xmac_eth_init);
1619 #endif