]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo/src/Full_Demo/lwIP_port/netif/xemacpsif.c
Move the Zynq's lwIP example from the Full demo into its own configuration as having...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo / src / Full_Demo / lwIP_port / netif / xemacpsif.c
1 /*
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  *
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32
33 /*
34  * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.
35  *
36  * Xilinx, Inc.
37  * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
38  * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
39  * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
40  * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
41  * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
42  * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
43  * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
44  * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
45  * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
46  * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
47  * AND FITNESS FOR A PARTICULAR PURPOSE.
48  *
49  */
50
51 #include <stdio.h>
52 #include <string.h>
53
54 #include <xparameters.h>
55 #include "lwipopts.h"
56 #include "xlwipconfig.h"
57 #include "lwip/opt.h"
58 #include "lwip/def.h"
59 #include "lwip/mem.h"
60 #include "lwip/pbuf.h"
61 #include "lwip/sys.h"
62 #include "lwip/stats.h"
63 #include "lwip/igmp.h"
64
65 #include "netif/etharp.h"
66 #include "netif/xemacpsif.h"
67 #include "netif/xadapter.h"
68 #include "netif/xpqueue.h"
69 #include "xparameters.h"
70 #include "xuartps.h"
71 #include "xscugic.h"
72 #include "xemacps.h"
73
74
75 /* Define those to better describe your network interface. */
76 #define IFNAME0 't'
77 #define IFNAME1 'e'
78
79 #if LWIP_IGMP
80 static err_t xemacpsif_mac_filter_update (struct netif *netif,
81                                                         struct ip_addr *group, u8_t action);
82
83 static u8_t xemacps_mcast_entry_mask = 0;
84 #endif
85
86 XEmacPs_Config *mac_config;
87 struct netif *NetIf;
88 void FreeTxPBufs(void);
89 /*
90  * this function is always called with interrupts off
91  * this function also assumes that there are available BD's
92  */
93 static err_t _unbuffered_low_level_output(xemacpsif_s *xemacpsif,
94                                                                                                         struct pbuf *p)
95 {
96         XStatus status = 0;
97
98 #if ETH_PAD_SIZE
99         pbuf_header(p, -ETH_PAD_SIZE);  /* drop the padding word */
100 #endif
101         status = emacps_sgsend(xemacpsif, p);
102         if (status != XST_SUCCESS) {
103 #if LINK_STATS
104         lwip_stats.link.drop++;
105 #endif
106         }
107
108 #if ETH_PAD_SIZE
109         pbuf_header(p, ETH_PAD_SIZE);   /* reclaim the padding word */
110 #endif
111
112 #if LINK_STATS
113         lwip_stats.link.xmit++;
114 #endif /* LINK_STATS */
115
116         return ERR_OK;
117
118 }
119
120 /*
121  * low_level_output():
122  *
123  * Should do the actual transmission of the packet. The packet is
124  * contained in the pbuf that is passed to the function. This pbuf
125  * might be chained.
126  *
127  */
128
129 static err_t low_level_output(struct netif *netif, struct pbuf *p)
130 {
131         SYS_ARCH_DECL_PROTECT(lev);
132         err_t err;
133
134         struct xemac_s *xemac = (struct xemac_s *)(netif->state);
135         xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
136
137         SYS_ARCH_PROTECT(lev);
138
139
140         /* check if space is available to send */
141         if (is_tx_space_available(xemacpsif)) {
142                 _unbuffered_low_level_output(xemacpsif, p);
143                 err = ERR_OK;
144         } else {
145 #if LINK_STATS
146                 lwip_stats.link.drop++;
147 #endif
148                 print("pack dropped, no space\r\n");
149                 err = ERR_MEM;
150         }
151
152
153         SYS_ARCH_UNPROTECT(lev);
154         return err;
155 }
156
157 /*
158  * low_level_input():
159  *
160  * Should allocate a pbuf and transfer the bytes of the incoming
161  * packet from the interface into the pbuf.
162  *
163  */
164 static struct pbuf * low_level_input(struct netif *netif)
165 {
166         struct xemac_s *xemac = (struct xemac_s *)(netif->state);
167         xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
168         struct pbuf *p;
169
170         /* see if there is data to process */
171         if (pq_qlength(xemacpsif->recv_q) == 0)
172                 return NULL;
173
174         /* return one packet from receive q */
175         p = (struct pbuf *)pq_dequeue(xemacpsif->recv_q);
176         return p;
177 }
178
179 /*
180  * xemacpsif_output():
181  *
182  * This function is called by the TCP/IP stack when an IP packet
183  * should be sent. It calls the function called low_level_output() to
184  * do the actual transmission of the packet.
185  *
186  */
187
188 static err_t xemacpsif_output(struct netif *netif, struct pbuf *p,
189                 struct ip_addr *ipaddr)
190 {
191         /* resolve hardware address, then send (or queue) packet */
192         return etharp_output(netif, p, ipaddr);
193 }
194
195 /*
196  * xemacpsif_input():
197  *
198  * This function should be called when a packet is ready to be read
199  * from the interface. It uses the function low_level_input() that
200  * should handle the actual reception of bytes from the network
201  * interface.
202  *
203  * Returns the number of packets read (max 1 packet on success,
204  * 0 if there are no packets)
205  *
206  */
207
208 int xemacpsif_input(struct netif *netif)
209 {
210         struct eth_hdr *ethhdr;
211         struct pbuf *p;
212         SYS_ARCH_DECL_PROTECT(lev);
213
214 #ifdef OS_IS_FREERTOS
215         while (1)
216 #endif
217         {
218         /* move received packet into a new pbuf */
219         SYS_ARCH_PROTECT(lev);
220         p = low_level_input(netif);
221         SYS_ARCH_UNPROTECT(lev);
222
223         /* no packet could be read, silently ignore this */
224         if (p == NULL) {
225                 return 0;
226         }
227
228         /* points to packet payload, which starts with an Ethernet header */
229         ethhdr = p->payload;
230
231 #if LINK_STATS
232         lwip_stats.link.recv++;
233 #endif /* LINK_STATS */
234
235         switch (htons(ethhdr->type)) {
236                 /* IP or ARP packet? */
237                 case ETHTYPE_IP:
238                 case ETHTYPE_ARP:
239 #if PPPOE_SUPPORT
240                         /* PPPoE packet? */
241                 case ETHTYPE_PPPOEDISC:
242                 case ETHTYPE_PPPOE:
243 #endif /* PPPOE_SUPPORT */
244                         /* full packet send to tcpip_thread to process */
245                         if (netif->input(p, netif) != ERR_OK) {
246                                 LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_input: IP input error\r\n"));
247                                 pbuf_free(p);
248                                 p = NULL;
249                         }
250                         break;
251
252                 default:
253                         pbuf_free(p);
254                         p = NULL;
255                         break;
256         }
257         }
258
259         return 1;
260 }
261
262
263 static err_t low_level_init(struct netif *netif)
264 {
265         unsigned mac_address = (unsigned)(netif->state);
266         struct xemac_s *xemac;
267         xemacpsif_s *xemacpsif;
268         u32 dmacrreg;
269
270         int Status = XST_SUCCESS;
271
272         NetIf = netif;
273
274         xemacpsif = mem_malloc(sizeof *xemacpsif);
275         if (xemacpsif == NULL) {
276                 LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
277                 return ERR_MEM;
278         }
279
280         xemac = mem_malloc(sizeof *xemac);
281         if (xemac == NULL) {
282                 LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));
283                 return ERR_MEM;
284         }
285
286         xemac->state = (void *)xemacpsif;
287         xemac->topology_index = xtopology_find_index(mac_address);
288         xemac->type = xemac_type_emacps;
289
290         xemacpsif->send_q = NULL;
291         xemacpsif->recv_q = pq_create_queue();
292         if (!xemacpsif->recv_q)
293                 return ERR_MEM;
294
295         /* maximum transfer unit */
296         netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE;
297
298 #if LWIP_IGMP
299         netif->igmp_mac_filter = xemacpsif_mac_filter_update;
300 #endif
301
302         netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
303                                                                                         NETIF_FLAG_LINK_UP;
304
305 #if LWIP_IGMP
306         netif->flags |= NETIF_FLAG_IGMP;
307 #endif
308
309 #if !NO_SYS
310         sys_sem_new(&xemac->sem_rx_data_available, 0);
311 #endif
312         /* obtain config of this emac */
313         mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)netif->state);
314
315         Status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
316                                                 mac_config->BaseAddress);
317         if (Status != XST_SUCCESS) {
318                 xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
319         }
320
321         /* initialize the mac */
322         init_emacps(xemacpsif, netif);
323
324         dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
325                                                                                                                 XEMACPS_DMACR_OFFSET);
326         dmacrreg = dmacrreg | (0x00000010);
327         XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
328                                                                                         XEMACPS_DMACR_OFFSET, dmacrreg);
329
330         setup_isr(xemac);
331         init_dma(xemac);
332         start_emacps(xemacpsif);
333
334         /* replace the state in netif (currently the emac baseaddress)
335          * with the mac instance pointer.
336          */
337         netif->state = (void *)xemac;
338
339         return ERR_OK;
340 }
341
342 void HandleEmacPsError(struct xemac_s *xemac)
343 {
344         xemacpsif_s   *xemacpsif;
345         int Status = XST_SUCCESS;
346         u32 dmacrreg;
347
348         SYS_ARCH_DECL_PROTECT(lev);
349         SYS_ARCH_PROTECT(lev);
350
351         FreeTxRxPBufs();
352         xemacpsif = (xemacpsif_s *)(xemac->state);
353         Status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config,
354                                                 mac_config->BaseAddress);
355         if (Status != XST_SUCCESS) {
356                 xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);
357         }
358         /* initialize the mac */
359         init_emacps_on_error(xemacpsif, NetIf);
360         dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
361                                                                                                                 XEMACPS_DMACR_OFFSET);
362         dmacrreg = dmacrreg | (0x01000000);
363         XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
364                                                                                         XEMACPS_DMACR_OFFSET, dmacrreg);
365         setup_isr(xemac);
366         init_dma(xemac);
367         start_emacps(xemacpsif);
368
369         SYS_ARCH_UNPROTECT(lev);
370 }
371
372 void HandleTxErrors(struct xemac_s *xemac)
373 {
374         xemacpsif_s   *xemacpsif;
375         u32 netctrlreg;
376
377         SYS_ARCH_DECL_PROTECT(lev);
378         SYS_ARCH_PROTECT(lev);
379         xemacpsif = (xemacpsif_s *)(xemac->state);
380         netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
381                                                                                                 XEMACPS_NWCTRL_OFFSET);
382     netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
383         XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
384                                                                         XEMACPS_NWCTRL_OFFSET, netctrlreg);
385         FreeOnlyTxPBufs();
386
387         clean_dma_txdescs(xemac);
388         netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
389                                                                                                         XEMACPS_NWCTRL_OFFSET);
390         netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
391         XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
392                                                                                 XEMACPS_NWCTRL_OFFSET, netctrlreg);
393         SYS_ARCH_UNPROTECT(lev);
394 }
395
396
397 #if LWIP_IGMP
398 static err_t xemacpsif_mac_filter_update (struct netif *netif, struct ip_addr *group,
399                                                                 u8_t action)
400 {
401         return 0;
402 }
403 #endif
404
405 /*
406  * xemacpsif_init():
407  *
408  * Should be called at the beginning of the program to set up the
409  * network interface. It calls the function low_level_init() to do the
410  * actual setup of the hardware.
411  *
412  */
413
414 err_t xemacpsif_init(struct netif *netif)
415 {
416 #if LWIP_SNMP
417         /* ifType ethernetCsmacd(6) @see RFC1213 */
418         netif->link_type = 6;
419         /* your link speed here */
420         netif->link_speed = ;
421         netif->ts = 0;
422         netif->ifinoctets = 0;
423         netif->ifinucastpkts = 0;
424         netif->ifinnucastpkts = 0;
425         netif->ifindiscards = 0;
426         netif->ifoutoctets = 0;
427         netif->ifoutucastpkts = 0;
428         netif->ifoutnucastpkts = 0;
429         netif->ifoutdiscards = 0;
430 #endif
431
432         netif->name[0] = IFNAME0;
433         netif->name[1] = IFNAME1;
434         netif->output = xemacpsif_output;
435         netif->linkoutput = low_level_output;
436
437         low_level_init(netif);
438         return ERR_OK;
439 }
440
441 /*
442  * xemacpsif_resetrx_on_no_rxdata():
443  *
444  * Should be called by the user at regular intervals, typically
445  * from a timer (100 msecond). This is to provide a SW workaround
446  * for the HW bug (SI #692601). Please refer to the function header
447  * for the function resetrx_on_no_rxdata in xemacpsif_dma.c to
448  * know more about the SI.
449  *
450  */
451
452 void xemacpsif_resetrx_on_no_rxdata(struct netif *netif)
453 {
454         struct xemac_s *xemac = (struct xemac_s *)(netif->state);
455         xemacpsif_s *xemacpsif = (xemacpsif_s *)(xemac->state);
456
457         resetrx_on_no_rxdata(xemacpsif);
458 }