1 #if WITH_LWIP
2 /*
3  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
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  * Author: Adam Dunkels <adam@sics.se>
31  *
32  */
33 
34 /*
35  * This file is a skeleton for developing Ethernet network interface
36  * drivers for lwIP. Add code to the low_level functions and do a
37  * search-and-replace for the word "ethernetif" to replace it with
38  * something that better describes your network interface.
39  */
40 /*
41  * ARMEMU bits
42  * Copyright (c) 2006 Travis Geiselbrecht
43  *
44  * Use of this source code is governed by a MIT-style
45  * license that can be found in the LICENSE file or at
46  * https://opensource.org/licenses/MIT
47  */
48 
49 #include <malloc.h>
50 #include <dev/ethernet.h>
51 #include <lk/err.h>
52 #include <lk/reg.h>
53 #include <string.h>
54 #include <platform/interrupts.h>
55 #include <platform/armemu/memmap.h>
56 
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 
64 #include "netif/etharp.h"
65 
66 /* Define those to better describe your network interface. */
67 #define IFNAME0 'e'
68 #define IFNAME1 'n'
69 
70 struct ethernetif {
71     struct eth_addr *ethaddr;
72     /* Add whatever per-interface state that is needed here. */
73 };
74 
75 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
76 
77 /* Forward declarations. */
78 static void  ethernetif_input(struct netif *netif);
79 static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
80                                struct ip_addr *ipaddr);
81 
82 static void
low_level_init(struct netif * netif)83 low_level_init(struct netif *netif) {
84     struct ethernetif *ethernetif = netif->state;
85 
86     /* set MAC hardware address length */
87     netif->hwaddr_len = 6;
88 
89     /* set MAC hardware address */
90     netif->hwaddr[0] = 0;
91     netif->hwaddr[1] = 0x01;
92     netif->hwaddr[2] = 0x02;
93     netif->hwaddr[3] = 0x03;
94     netif->hwaddr[4] = 0x04;
95     netif->hwaddr[5] = 0x05;
96 
97     /* maximum transfer unit */
98     netif->mtu = 1500;
99 
100     /* broadcast capability */
101     netif->flags = NETIF_FLAG_BROADCAST;
102 
103     /* Do whatever else is needed to initialize interface. */
104 }
105 
106 /*
107  * low_level_output():
108  *
109  * Should do the actual transmission of the packet. The packet is
110  * contained in the pbuf that is passed to the function. This pbuf
111  * might be chained.
112  *
113  */
114 
115 static err_t
low_level_output(struct netif * netif,struct pbuf * p)116 low_level_output(struct netif *netif, struct pbuf *p) {
117     struct ethernetif *ethernetif = netif->state;
118     struct pbuf *q;
119     int i;
120     int j;
121 
122 #if ETH_PAD_SIZE
123     pbuf_header(p, -ETH_PAD_SIZE);            /* drop the padding word */
124 #endif
125 
126     /* XXX maybe just a mutex? */
127     enter_critical_section();
128 
129     i = 0;
130     for (q = p; q != NULL; q = q->next) {
131         /* Send the data from the pbuf to the interface, one pbuf at a
132            time. The size of the data in each pbuf is kept in the ->len
133            variable. */
134 //  debug_dump_memory_bytes(q->payload, q->len);
135         for (j = 0; j < q->len; j++)
136             *REG8(NET_OUT_BUF + i + j) = ((unsigned char *)q->payload)[j];
137         i += q->len;
138     }
139 
140     *REG(NET_SEND_LEN) = i;
141     *REG(NET_SEND) = 1;
142 
143     exit_critical_section();
144 
145 #if ETH_PAD_SIZE
146     pbuf_header(p, ETH_PAD_SIZE);         /* reclaim the padding word */
147 #endif
148 
149 #if LINK_STATS
150     lwip_stats.link.xmit++;
151 #endif /* LINK_STATS */
152 
153     return ERR_OK;
154 }
155 
156 /*
157  * low_level_input():
158  *
159  * Should allocate a pbuf and transfer the bytes of the incoming
160  * packet from the interface into the pbuf.
161  *
162  */
163 
164 static struct pbuf *
low_level_input(struct netif * netif)165 low_level_input(struct netif *netif) {
166     struct ethernetif *ethernetif = netif->state;
167     struct pbuf *p, *q;
168     u16_t len;
169     int i;
170     int head, tail;
171 
172     /* get the head and tail pointers from the ethernet interface */
173     head = *REG(NET_HEAD);
174     tail = *REG(NET_TAIL);
175 
176     if (tail == head)
177         return NULL; // false alarm
178 
179     /* Obtain the size of the packet and put it into the "len"
180        variable. */
181     len = *REG(NET_IN_BUF_LEN);
182 
183 #if ETH_PAD_SIZE
184     len += ETH_PAD_SIZE;                      /* allow room for Ethernet padding */
185 #endif
186 
187     /* We allocate a pbuf chain of pbufs from the pool. */
188     p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
189     if (p != NULL) {
190 
191 #if ETH_PAD_SIZE
192         pbuf_header(p, -ETH_PAD_SIZE);          /* drop the padding word */
193 #endif
194 
195         /* We iterate over the pbuf chain until we have read the entire
196          * packet into the pbuf. */
197         int pos = 0;
198         for (q = p; q != NULL; q = q->next) {
199             /* Read enough bytes to fill this pbuf in the chain. The
200              * available data in the pbuf is given by the q->len
201              * variable. */
202             for (i=0; i < q->len; i++) {
203                 ((unsigned char *)q->payload)[i] = *REG8(NET_IN_BUF + pos);
204                 pos++;
205             }
206         }
207 
208 #if ETH_PAD_SIZE
209         pbuf_header(p, ETH_PAD_SIZE);           /* reclaim the padding word */
210 #endif
211 
212 #if LINK_STATS
213         lwip_stats.link.recv++;
214 #endif /* LINK_STATS */
215     } else {
216 #if LINK_STATS
217         lwip_stats.link.memerr++;
218         lwip_stats.link.drop++;
219 #endif /* LINK_STATS */
220     }
221 
222     /* push the tail pointer up by one, giving the buffer back to the hardware */
223     *REG(NET_TAIL) = (tail + 1) % NET_IN_BUF_COUNT;
224 
225     return p;
226 }
227 
228 /*
229  * ethernetif_output():
230  *
231  * This function is called by the TCP/IP stack when an IP packet
232  * should be sent. It calls the function called low_level_output() to
233  * do the actual transmission of the packet.
234  *
235  */
236 
237 static err_t
ethernetif_output(struct netif * netif,struct pbuf * p,struct ip_addr * ipaddr)238 ethernetif_output(struct netif *netif, struct pbuf *p,
239                   struct ip_addr *ipaddr) {
240 //  dprintf("ethernetif_output: netif %p, pbuf %p, ipaddr %p\n", netif, p, ipaddr);
241 
242     /* resolve hardware address, then send (or queue) packet */
243     return etharp_output(netif, ipaddr, p);
244 
245 }
246 
247 /*
248  * ethernetif_input():
249  *
250  * This function should be called when a packet is ready to be read
251  * from the interface. It uses the function low_level_input() that
252  * should handle the actual reception of bytes from the network
253  * interface.
254  *
255  */
256 
257 static void
ethernetif_input(struct netif * netif)258 ethernetif_input(struct netif *netif) {
259     struct ethernetif *ethernetif;
260     struct eth_hdr *ethhdr;
261     struct pbuf *p;
262 
263     ethernetif = netif->state;
264 
265     /* move received packet into a new pbuf */
266     p = low_level_input(netif);
267     /* no packet could be read, silently ignore this */
268     if (p == NULL) return;
269     /* points to packet payload, which starts with an Ethernet header */
270     ethhdr = p->payload;
271 
272 #if LINK_STATS
273     lwip_stats.link.recv++;
274 #endif /* LINK_STATS */
275 
276     ethhdr = p->payload;
277 
278 //  dprintf("ethernetif_input: type 0x%x\n", htons(ethhdr->type));
279 
280     switch (htons(ethhdr->type)) {
281         /* IP packet? */
282         case ETHTYPE_IP:
283             /* update ARP table */
284             etharp_ip_input(netif, p);
285             /* skip Ethernet header */
286             pbuf_header(p, -sizeof(struct eth_hdr));
287             /* pass to network layer */
288             netif->input(p, netif);
289             break;
290 
291         case ETHTYPE_ARP:
292             /* pass p to ARP module  */
293             etharp_arp_input(netif, ethernetif->ethaddr, p);
294             break;
295         default:
296             pbuf_free(p);
297             p = NULL;
298             break;
299     }
300 }
301 
ethernet_int(void * arg)302 static enum handler_return ethernet_int(void *arg) {
303     struct netif *netif = (struct netif *)arg;
304 
305     ethernetif_input(netif);
306 
307     return INT_RESCHEDULE;
308 }
309 
310 
311 
312 /*
313  * ethernetif_init():
314  *
315  * Should be called at the beginning of the program to set up the
316  * network interface. It calls the function low_level_init() to do the
317  * actual setup of the hardware.
318  *
319  */
320 
321 static err_t
ethernetif_init(struct netif * netif)322 ethernetif_init(struct netif *netif) {
323     struct ethernetif *ethernetif;
324 
325     ethernetif = mem_malloc(sizeof(struct ethernetif));
326 
327     if (ethernetif == NULL) {
328         LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
329         return ERR_MEM;
330     }
331 
332     netif->state = ethernetif;
333     netif->name[0] = IFNAME0;
334     netif->name[1] = IFNAME1;
335     netif->output = ethernetif_output;
336     netif->linkoutput = low_level_output;
337 
338     ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
339 
340     low_level_init(netif);
341 
342     return ERR_OK;
343 }
344 
ethernet_init(void)345 status_t ethernet_init(void) {
346     /* check to see if the ethernet feature is turned on */
347     if ((*REG(SYSINFO_FEATURES) & SYSINFO_FEATURE_NETWORK) == 0)
348         return ERR_NOT_FOUND;
349 
350     struct netif *netif = calloc(sizeof(struct netif), 1);
351     struct ip_addr *ipaddr = calloc(sizeof(struct ip_addr), 1);
352     struct ip_addr *netmask = calloc(sizeof(struct ip_addr), 1);
353     struct ip_addr *gw = calloc(sizeof(struct ip_addr), 1);
354 
355     struct netif *netifret = netif_add(netif, ipaddr, netmask, gw, NULL, &ethernetif_init, &ip_input);
356     if (netifret == NULL) {
357         free(netif);
358         free(ipaddr);
359         free(netmask);
360         free(gw);
361         return ERR_NOT_FOUND;
362     }
363 
364     /* register for interrupt handlers */
365     register_int_handler(INT_NET, ethernet_int, netif);
366 
367     netif_set_default(netif);
368 
369     unmask_interrupt(INT_NET, NULL);
370 
371     return NO_ERROR;
372 }
373 
374 #endif // WITH_LWIP
375