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