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, ðernetif_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