1 /*
2 * Copyright (C) 2010 - 2019 Xilinx, Inc.
3 * Copyright (C) 2021 WangHuachen.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
26 * OF SUCH DAMAGE.
27 *
28 * This file is part of the lwIP TCP/IP stack.
29 *
30 */
31
32 #include <stdio.h>
33 #include <string.h>
34
35 #include <xparameters.h>
36 #include "lwipopts.h"
37 #include "xlwipconfig.h"
38 #include "lwip/opt.h"
39 #include "lwip/def.h"
40 #include "lwip/mem.h"
41 #include "lwip/pbuf.h"
42 #include "lwip/sys.h"
43 #include "lwip/stats.h"
44 #include "lwip/igmp.h"
45
46 #include "netif/etharp.h"
47 #include "netif/xemacpsif.h"
48 #include "netif/xadapter.h"
49 #include "netif/xpqueue.h"
50 #include "xparameters.h"
51 // #include "xscugic.h"
52 #include "xemacps.h"
53
54 #if LWIP_IPV6
55 #include "lwip/ethip6.h"
56 #endif
57
58 #ifdef SYS_ARCH_DECL_PROTECT
59 #undef SYS_ARCH_DECL_PROTECT
60 #endif
61 #define SYS_ARCH_DECL_PROTECT(lev) rt_base_t lev;
62
63 #ifdef SYS_ARCH_PROTECT
64 #undef SYS_ARCH_PROTECT
65 #endif
66 #define SYS_ARCH_PROTECT(lev) lev = rt_hw_interrupt_disable();
67
68 #ifdef SYS_ARCH_UNPROTECT
69 #undef SYS_ARCH_UNPROTECT
70 #endif
71 #define SYS_ARCH_UNPROTECT(lev) rt_hw_interrupt_enable(lev);
72
73 /* Define those to better describe your network interface. */
74 #define IFNAME0 't'
75 #define IFNAME1 'e'
76
77 #if LWIP_IGMP
78 static err_t xemacpsif_mac_filter_update (struct netif *netif,
79 ip_addr_t *group, u8_t action);
80
81 static u8_t xemacps_mcast_entry_mask = 0;
82 #endif
83
84 #if LWIP_IPV6 && LWIP_IPV6_MLD
85 static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif,
86 ip_addr_t *group, u8_t action);
87
88 static u8_t xemacps_mld6_mcast_entry_mask;
89 #endif
90
91 XEmacPs_Config *mac_config;
92 struct netif *NetIf;
93
94 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
95 int32_t lExpireCounter = 0;
96 #define RESETRXTIMEOUT 10
97 #endif
98
99 /*
100 * this function is always called with interrupts off
101 * this function also assumes that there are available BD's
102 */
_unbuffered_low_level_output(xemacpsif_s * xemacpsif,struct pbuf * p)103 err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif,
104 struct pbuf *p)
105 {
106 XStatus status = 0;
107
108 #if ETH_PAD_SIZE
109 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
110 #endif
111 status = emacps_sgsend(xemacpsif, p);
112 if (status != XST_SUCCESS) {
113 #if LINK_STATS
114 lwip_stats.link.drop++;
115 #endif
116 }
117
118 #if ETH_PAD_SIZE
119 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
120 #endif
121
122 #if LINK_STATS
123 lwip_stats.link.xmit++;
124 #endif /* LINK_STATS */
125
126 return ERR_OK;
127
128 }
129
130 /*
131 * low_level_output():
132 *
133 * Should do the actual transmission of the packet. The packet is
134 * contained in the pbuf that is passed to the function. This pbuf
135 * might be chained.
136 *
137 */
138
low_level_output(struct netif * netif,struct pbuf * p)139 static err_t low_level_output(struct netif *netif, struct pbuf *p)
140 {
141 SYS_ARCH_DECL_PROTECT(lev);
142 err_t err;
143 s32_t freecnt;
144 XEmacPs_BdRing *txring;
145
146 struct xemac_s *xemac = (struct xemac_s *)(netif->state);
147 xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
148
149 SYS_ARCH_PROTECT(lev);
150
151 /* check if space is available to send */
152 freecnt = is_tx_space_available(xemacpsif);
153 if (freecnt <= 5) {
154 txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
155 process_sent_bds(xemacpsif, txring);
156 }
157
158 if (is_tx_space_available(xemacpsif)) {
159 _unbuffered_low_level_output(xemacpsif, p);
160 err = ERR_OK;
161 } else {
162 #if LINK_STATS
163 lwip_stats.link.drop++;
164 #endif
165 rt_kprintf("pack dropped, no space\r\n");
166 err = ERR_MEM;
167 }
168
169 SYS_ARCH_UNPROTECT(lev);
170 return err;
171 }
172
173 /*
174 * low_level_input():
175 *
176 * Should allocate a pbuf and transfer the bytes of the incoming
177 * packet from the interface into the pbuf.
178 *
179 */
low_level_input(struct netif * netif)180 static struct pbuf * low_level_input(struct netif *netif)
181 {
182 struct xemac_s *xemac = (struct xemac_s *)(netif->state);
183 xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
184 struct pbuf *p;
185
186 /* see if there is data to process */
187 if (pq_qlength(xemacpsif->recv_q) == 0)
188 return NULL;
189
190 /* return one packet from receive q */
191 p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
192 return p;
193 }
194
195 /*
196 * xemacpsif_output():
197 *
198 * This function is called by the TCP/IP stack when an IP packet
199 * should be sent. It calls the function called low_level_output() to
200 * do the actual transmission of the packet.
201 *
202 */
203
xemacpsif_output(struct netif * netif,struct pbuf * p,const ip_addr_t * ipaddr)204 static err_t xemacpsif_output(struct netif *netif, struct pbuf *p,
205 const ip_addr_t *ipaddr)
206 {
207 /* resolve hardware address, then send (or queue) packet */
208 return etharp_output(netif, p, ipaddr);
209 }
210
211 /*
212 * xemacpsif_input():
213 *
214 * This function should be called when a packet is ready to be read
215 * from the interface. It uses the function low_level_input() that
216 * should handle the actual reception of bytes from the network
217 * interface.
218 *
219 * Returns the number of packets read (max 1 packet on success,
220 * 0 if there are no packets)
221 *
222 */
223
xemacpsif_input(struct netif * netif)224 s32_t xemacpsif_input(struct netif *netif)
225 {
226 struct eth_hdr *ethhdr;
227 struct pbuf *p;
228 SYS_ARCH_DECL_PROTECT(lev);
229
230 #ifdef OS_IS_FREERTOS
231 while (1)
232 #endif
233 {
234 /* move received packet into a new pbuf */
235 SYS_ARCH_PROTECT(lev);
236 p = low_level_input(netif);
237 SYS_ARCH_UNPROTECT(lev);
238
239 /* no packet could be read, silently ignore this */
240 if (p == NULL) {
241 return 0;
242 }
243
244 /* points to packet payload, which starts with an Ethernet header */
245 ethhdr = p->payload;
246
247 #if LINK_STATS
248 lwip_stats.link.recv++;
249 #endif /* LINK_STATS */
250
251 switch (htons(ethhdr->type)) {
252 /* IP or ARP packet? */
253 case ETHTYPE_IP:
254 case ETHTYPE_ARP:
255 #if LWIP_IPV6
256 /*IPv6 Packet?*/
257 case ETHTYPE_IPV6:
258 #endif
259 #if PPPOE_SUPPORT
260 /* PPPoE packet? */
261 case ETHTYPE_PPPOEDISC:
262 case ETHTYPE_PPPOE:
263 #endif /* PPPOE_SUPPORT */
264 /* full packet send to tcpip_thread to process */
265 if (netif->input(p, netif) != ERR_OK) {
266 LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n"));
267 pbuf_free(p);
268 p = NULL;
269 }
270 break;
271
272 default:
273 pbuf_free(p);
274 p = NULL;
275 break;
276 }
277 }
278
279 return 1;
280 }
281
282
283 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
vTimerCallback(TimerHandle_t pxTimer)284 void vTimerCallback( TimerHandle_t pxTimer )
285 {
286 /* Do something if the pxTimer parameter is NULL */
287 configASSERT(pxTimer);
288
289 lExpireCounter++;
290 /* If the timer has expired 100 times then reset RX */
291 if(lExpireCounter >= RESETRXTIMEOUT) {
292 lExpireCounter = 0;
293 xemacpsif_resetrx_on_no_rxdata(NetIf);
294 }
295 }
296 #endif
297
low_level_init(struct netif * netif)298 static err_t low_level_init(struct netif *netif)
299 {
300 UINTPTR mac_address = (UINTPTR)(netif->state);
301 struct xemac_s *xemac;
302 xemacpsif_s *xemacpsif;
303 u32 dmacrreg;
304
305 s32_t status = XST_SUCCESS;
306
307 NetIf = netif;
308
309 xemacpsif = mem_malloc(sizeof *xemacpsif);
310 if (xemacpsif == NULL) {
311 LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
312 return ERR_MEM;
313 }
314
315 xemac = mem_malloc(sizeof *xemac);
316 if (xemac == NULL) {
317 LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
318 return ERR_MEM;
319 }
320
321 xemac->state = (void *)xemacpsif;
322 xemac->topology_index = xtopology_find_index(mac_address);
323 xemac->type = xemac_type_emacps;
324
325 xemacpsif->send_q = NULL;
326 xemacpsif->recv_q = pq_create_queue();
327 if (!xemacpsif->recv_q)
328 return ERR_MEM;
329
330 /* maximum transfer unit */
331 #ifdef ZYNQMP_USE_JUMBO
332 netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE;
333 #else
334 netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE;
335 #endif
336
337 #if LWIP_IGMP
338 netif->igmp_mac_filter = xemacpsif_mac_filter_update;
339 #endif
340
341 #if LWIP_IPV6 && LWIP_IPV6_MLD
342 netif->mld_mac_filter = xemacpsif_mld6_mac_filter_update;
343 #endif
344
345 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
346 NETIF_FLAG_LINK_UP;
347
348 #if LWIP_IPV6 && LWIP_IPV6_MLD
349 netif->flags |= NETIF_FLAG_MLD6;
350 #endif
351
352 #if LWIP_IGMP
353 netif->flags |= NETIF_FLAG_IGMP;
354 #endif
355
356 /* obtain config of this emac */
357 mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);
358
359 #if EL1_NONSECURE
360 /* Request device to indicate that this library is using it */
361 if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
362 Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0);
363 }
364 if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {
365 Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0);
366 }
367 #endif
368
369 status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
370 mac_config->BaseAddress);
371 if (status != XST_SUCCESS) {
372 xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
373 }
374
375 /* initialize the mac */
376 init_emacps(xemacpsif, netif);
377
378 dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
379 XEMACPS_DMACR_OFFSET);
380 dmacrreg = dmacrreg | (0x00000010);
381 XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
382 XEMACPS_DMACR_OFFSET, dmacrreg);
383
384 #if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)
385 /* Freertos tick is 10ms by default; set period to the same */
386 xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback);
387 if (xemac->xTimer == NULL) {
388 xil_printf("In %s:Timer creation failed....\r\n", __func__);
389 } else {
390 if(xTimerStart(xemac->xTimer, 0) != pdPASS) {
391 xil_printf("In %s:Timer start failed....\r\n", __func__);
392 }
393 }
394 #endif
395 setup_isr(xemac);
396 init_dma(xemac);
397 start_emacps(xemacpsif);
398
399 /* replace the state in netif (currently the emac baseaddress)
400 * with the mac instance pointer.
401 */
402 netif->state = (void *)xemac;
403
404 return ERR_OK;
405 }
406
HandleEmacPsError(struct xemac_s * xemac)407 void HandleEmacPsError(struct xemac_s *xemac)
408 {
409 xemacpsif_s *xemacpsif;
410 s32_t status = XST_SUCCESS;
411 u32 dmacrreg;
412
413 SYS_ARCH_DECL_PROTECT(lev);
414 SYS_ARCH_PROTECT(lev);
415
416 xemacpsif = (xemacpsif_s *)(xemac->state);
417 free_txrx_pbufs(xemacpsif);
418 status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
419 mac_config->BaseAddress);
420 if (status != XST_SUCCESS) {
421 xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
422 }
423 /* initialize the mac */
424 init_emacps_on_error(xemacpsif, NetIf);
425 dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
426 XEMACPS_DMACR_OFFSET);
427 dmacrreg = dmacrreg | (0x01000000);
428 XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
429 XEMACPS_DMACR_OFFSET, dmacrreg);
430 setup_isr(xemac);
431 init_dma(xemac);
432 start_emacps(xemacpsif);
433
434 SYS_ARCH_UNPROTECT(lev);
435 }
436
HandleTxErrors(struct xemac_s * xemac)437 void HandleTxErrors(struct xemac_s *xemac)
438 {
439 xemacpsif_s *xemacpsif;
440 u32 netctrlreg;
441
442 SYS_ARCH_DECL_PROTECT(lev);
443 SYS_ARCH_PROTECT(lev);
444 xemacpsif = (xemacpsif_s *)(xemac->state);
445 netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
446 XEMACPS_NWCTRL_OFFSET);
447 netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
448 XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
449 XEMACPS_NWCTRL_OFFSET, netctrlreg);
450 free_onlytx_pbufs(xemacpsif);
451
452 clean_dma_txdescs(xemac);
453 netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
454 XEMACPS_NWCTRL_OFFSET);
455 netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
456 XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
457 XEMACPS_NWCTRL_OFFSET, netctrlreg);
458 SYS_ARCH_UNPROTECT(lev);
459 }
460
461 #if LWIP_IPV6 && LWIP_IPV6_MLD
xemacpsif_ip6_addr_ismulticast(ip6_addr_t * ip_addr)462 static u8_t xemacpsif_ip6_addr_ismulticast(ip6_addr_t* ip_addr)
463 {
464 if(ip6_addr_ismulticast_linklocal(ip_addr)||
465 ip6_addr_ismulticast_iflocal(ip_addr) ||
466 ip6_addr_ismulticast_adminlocal(ip_addr)||
467 ip6_addr_ismulticast_sitelocal(ip_addr) ||
468 ip6_addr_ismulticast_orglocal(ip_addr) ||
469 ip6_addr_ismulticast_global(ip_addr)) {
470 /*Return TRUE if IPv6 is Multicast type*/
471 return TRUE;
472 } else {
473 return FALSE;
474 }
475 }
476
xemacpsif_mld6_mac_hash_update(struct netif * netif,u8_t * ip_addr,u8_t action)477 static void xemacpsif_mld6_mac_hash_update (struct netif *netif, u8_t *ip_addr,
478 u8_t action)
479 {
480 u8_t multicast_mac_addr[6];
481 struct xemac_s *xemac = (struct xemac_s *) (netif->state);
482 xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
483 XEmacPs_BdRing *txring;
484 txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
485
486 multicast_mac_addr[0] = LL_IP6_MULTICAST_ADDR_0;
487 multicast_mac_addr[1] = LL_IP6_MULTICAST_ADDR_1;
488 multicast_mac_addr[2] = ip_addr[12];
489 multicast_mac_addr[3] = ip_addr[13];
490 multicast_mac_addr[4] = ip_addr[14];
491 multicast_mac_addr[5] = ip_addr[15];
492
493 /* Wait till all sent packets are acknowledged from HW */
494 while(txring->HwCnt);
495
496 SYS_ARCH_DECL_PROTECT(lev);
497
498 SYS_ARCH_PROTECT(lev);
499
500 /* Stop Ethernet */
501 XEmacPs_Stop(&xemacpsif->emacps);
502
503 if (action == NETIF_ADD_MAC_FILTER) {
504 /* Set Mulitcast mac address in hash table */
505 XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
506
507 } else if (action == NETIF_DEL_MAC_FILTER) {
508 /* Remove Mulitcast mac address in hash table */
509 XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
510 }
511
512 /* Reset DMA */
513 reset_dma(xemac);
514
515 /* Start Ethernet */
516 XEmacPs_Start(&xemacpsif->emacps);
517
518 SYS_ARCH_UNPROTECT(lev);
519 }
520
xemacpsif_mld6_mac_filter_update(struct netif * netif,ip_addr_t * group,u8_t action)521 static err_t xemacpsif_mld6_mac_filter_update (struct netif *netif, ip_addr_t *group,
522 u8_t action)
523 {
524 u8_t temp_mask;
525 unsigned int i;
526 u8_t * ip_addr = (u8_t *) group;
527
528 if(!(xemacpsif_ip6_addr_ismulticast((ip6_addr_t*) ip_addr))) {
529 LWIP_DEBUGF(NETIF_DEBUG,
530 ("%s: The requested MAC address is not a multicast address.\r\n", __func__)); LWIP_DEBUGF(NETIF_DEBUG,
531 ("Multicast address add operation failure !!\r\n"));
532 return ERR_ARG;
533 }
534 if (action == NETIF_ADD_MAC_FILTER) {
535 for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
536 temp_mask = (0x01) << i;
537 if ((xemacps_mld6_mcast_entry_mask & temp_mask) == temp_mask) {
538 continue;
539 }
540 xemacps_mld6_mcast_entry_mask |= temp_mask;
541
542 /* Update mac address in hash table */
543 xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
544
545 LWIP_DEBUGF(NETIF_DEBUG,
546 ("%s: Multicast MAC address successfully added.\r\n", __func__));
547
548 return ERR_OK;
549 }
550 LWIP_DEBUGF(NETIF_DEBUG,
551 ("%s: No multicast address registers left.\r\n", __func__));
552 LWIP_DEBUGF(NETIF_DEBUG,
553 ("Multicast MAC address add operation failure !!\r\n"));
554 return ERR_MEM;
555 } else if (action == NETIF_DEL_MAC_FILTER) {
556 for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
557 temp_mask = (0x01) << i;
558 if ((xemacps_mld6_mcast_entry_mask & temp_mask) != temp_mask) {
559 continue;
560 }
561 xemacps_mld6_mcast_entry_mask &= (~temp_mask);
562
563 /* Update mac address in hash table */
564 xemacpsif_mld6_mac_hash_update(netif, ip_addr, action);
565
566 LWIP_DEBUGF(NETIF_DEBUG,
567 ("%s: Multicast MAC address successfully removed.\r\n", __func__));
568
569 return ERR_OK;
570 }
571 LWIP_DEBUGF(NETIF_DEBUG,
572 ("%s: No multicast address registers present with\r\n", __func__));
573 LWIP_DEBUGF(NETIF_DEBUG,
574 ("the requested Multicast MAC address.\r\n"));
575 LWIP_DEBUGF(NETIF_DEBUG,
576 ("Multicast MAC address removal failure!!.\r\n"));
577 return ERR_MEM;
578 }
579 return ERR_ARG;
580 }
581 #endif
582
583 #if LWIP_IGMP
xemacpsif_mac_hash_update(struct netif * netif,u8_t * ip_addr,u8_t action)584 static void xemacpsif_mac_hash_update (struct netif *netif, u8_t *ip_addr,
585 u8_t action)
586 {
587 u8_t multicast_mac_addr[6];
588 struct xemac_s *xemac = (struct xemac_s *) (netif->state);
589 xemacpsif_s *xemacpsif = (xemacpsif_s *) (xemac->state);
590 XEmacPs_BdRing *txring;
591 txring = &(XEmacPs_GetTxRing(&xemacpsif->emacps));
592
593 multicast_mac_addr[0] = 0x01;
594 multicast_mac_addr[1] = 0x00;
595 multicast_mac_addr[2] = 0x5E;
596 multicast_mac_addr[3] = ip_addr[1] & 0x7F;
597 multicast_mac_addr[4] = ip_addr[2];
598 multicast_mac_addr[5] = ip_addr[3];
599
600 /* Wait till all sent packets are acknowledged from HW */
601 while(txring->HwCnt);
602
603 SYS_ARCH_DECL_PROTECT(lev);
604
605 SYS_ARCH_PROTECT(lev);
606
607 /* Stop Ethernet */
608 XEmacPs_Stop(&xemacpsif->emacps);
609
610 if (action == IGMP_ADD_MAC_FILTER) {
611 /* Set Mulitcast mac address in hash table */
612 XEmacPs_SetHash(&xemacpsif->emacps, multicast_mac_addr);
613
614 } else if (action == IGMP_DEL_MAC_FILTER) {
615 /* Remove Mulitcast mac address in hash table */
616 XEmacPs_DeleteHash(&xemacpsif->emacps, multicast_mac_addr);
617 }
618
619 /* Reset DMA */
620 reset_dma(xemac);
621
622 /* Start Ethernet */
623 XEmacPs_Start(&xemacpsif->emacps);
624
625 SYS_ARCH_UNPROTECT(lev);
626 }
627
xemacpsif_mac_filter_update(struct netif * netif,ip_addr_t * group,u8_t action)628 static err_t xemacpsif_mac_filter_update (struct netif *netif, ip_addr_t *group,
629 u8_t action)
630 {
631 u8_t temp_mask;
632 unsigned int i;
633 u8_t * ip_addr = (u8_t *) group;
634
635 if ((ip_addr[0] < 224) && (ip_addr[0] > 239)) {
636 LWIP_DEBUGF(NETIF_DEBUG,
637 ("%s: The requested MAC address is not a multicast address.\r\n", __func__));
638 LWIP_DEBUGF(NETIF_DEBUG,
639 ("Multicast address add operation failure !!\r\n"));
640
641 return ERR_ARG;
642 }
643
644 if (action == IGMP_ADD_MAC_FILTER) {
645
646 for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
647 temp_mask = (0x01) << i;
648 if ((xemacps_mcast_entry_mask & temp_mask) == temp_mask) {
649 continue;
650 }
651 xemacps_mcast_entry_mask |= temp_mask;
652
653 /* Update mac address in hash table */
654 xemacpsif_mac_hash_update(netif, ip_addr, action);
655
656 LWIP_DEBUGF(NETIF_DEBUG,
657 ("%s: Multicast MAC address successfully added.\r\n", __func__));
658
659 return ERR_OK;
660 }
661 if (i == XEMACPS_MAX_MAC_ADDR) {
662 LWIP_DEBUGF(NETIF_DEBUG,
663 ("%s: No multicast address registers left.\r\n", __func__));
664 LWIP_DEBUGF(NETIF_DEBUG,
665 ("Multicast MAC address add operation failure !!\r\n"));
666
667 return ERR_MEM;
668 }
669 } else if (action == IGMP_DEL_MAC_FILTER) {
670 for (i = 0; i < XEMACPS_MAX_MAC_ADDR; i++) {
671 temp_mask = (0x01) << i;
672 if ((xemacps_mcast_entry_mask & temp_mask) != temp_mask) {
673 continue;
674 }
675 xemacps_mcast_entry_mask &= (~temp_mask);
676
677 /* Update mac address in hash table */
678 xemacpsif_mac_hash_update(netif, ip_addr, action);
679
680 LWIP_DEBUGF(NETIF_DEBUG,
681 ("%s: Multicast MAC address successfully removed.\r\n", __func__));
682
683 return ERR_OK;
684 }
685 if (i == XEMACPS_MAX_MAC_ADDR) {
686 LWIP_DEBUGF(NETIF_DEBUG,
687 ("%s: No multicast address registers present with\r\n", __func__));
688 LWIP_DEBUGF(NETIF_DEBUG,
689 ("the requested Multicast MAC address.\r\n"));
690 LWIP_DEBUGF(NETIF_DEBUG,
691 ("Multicast MAC address removal failure!!.\r\n"));
692
693 return ERR_MEM;
694 }
695 }
696 return ERR_OK;
697 }
698 #endif
699
700 /*
701 * xemacpsif_init():
702 *
703 * Should be called at the beginning of the program to set up the
704 * network interface. It calls the function low_level_init() to do the
705 * actual setup of the hardware.
706 *
707 */
708
xemacpsif_init(struct netif * netif)709 err_t xemacpsif_init(struct netif *netif)
710 {
711 #if LWIP_SNMP
712 /* ifType ethernetCsmacd(6) @see RFC1213 */
713 netif->link_type = 6;
714 /* your link speed here */
715 netif->link_speed = ;
716 netif->ts = 0;
717 netif->ifinoctets = 0;
718 netif->ifinucastpkts = 0;
719 netif->ifinnucastpkts = 0;
720 netif->ifindiscards = 0;
721 netif->ifoutoctets = 0;
722 netif->ifoutucastpkts = 0;
723 netif->ifoutnucastpkts = 0;
724 netif->ifoutdiscards = 0;
725 #endif
726
727 netif->name[0] = IFNAME0;
728 netif->name[1] = IFNAME1;
729 netif->output = xemacpsif_output;
730 netif->linkoutput = low_level_output;
731 #if LWIP_IPV6
732 netif->output_ip6 = ethip6_output;
733 #endif
734
735 low_level_init(netif);
736 return ERR_OK;
737 }
738
739 /*
740 * xemacpsif_resetrx_on_no_rxdata():
741 *
742 * Should be called by the user at regular intervals, typically
743 * from a timer (100 msecond). This is to provide a SW workaround
744 * for the HW bug (SI #692601). Please refer to the function header
745 * for the function resetrx_on_no_rxdata in xemacpsif_dma.c to
746 * know more about the SI.
747 *
748 */
749
xemacpsif_resetrx_on_no_rxdata(struct netif * netif)750 void xemacpsif_resetrx_on_no_rxdata(struct netif *netif)
751 {
752 struct xemac_s *xemac = (struct xemac_s *)(netif->state);
753 xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
754
755 resetrx_on_no_rxdata(xemacpsif);
756 }
757