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