]> git.sur5r.net Git - freertos/blob - Demo/Common/ethernet/lwIP/netif/ethernetif.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / Common / ethernet / lwIP / netif / ethernetif.c
1 /*\r
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
3  * All rights reserved. \r
4  * \r
5  * Redistribution and use in source and binary forms, with or without modification, \r
6  * are permitted provided that the following conditions are met:\r
7  *\r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  *    this list of conditions and the following disclaimer.\r
10  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
11  *    this list of conditions and the following disclaimer in the documentation\r
12  *    and/or other materials provided with the distribution.\r
13  * 3. The name of the author may not be used to endorse or promote products\r
14  *    derived from this software without specific prior written permission. \r
15  *\r
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED \r
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \r
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT \r
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, \r
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \r
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \r
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING \r
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY \r
25  * OF SUCH DAMAGE.\r
26  *\r
27  * This file is part of the lwIP TCP/IP stack.\r
28  * \r
29  * Author: Adam Dunkels <adam@sics.se>\r
30  *\r
31  */\r
32 \r
33 /*\r
34  * This file is a skeleton for developing Ethernet network interface\r
35  * drivers for lwIP. Add code to the low_level functions and do a\r
36  * search-and-replace for the word "ethernetif" to replace it with\r
37  * something that better describes your network interface.\r
38  */\r
39 \r
40 #include "lwip/opt.h"\r
41 #include "lwip/def.h"\r
42 #include "lwip/mem.h"\r
43 #include "lwip/pbuf.h"\r
44 #include "lwip/sys.h"\r
45 #include <lwip/stats.h>\r
46 \r
47 #include "netif/etharp.h"\r
48 \r
49 /* Define those to better describe your network interface. */\r
50 #define IFNAME0 'e'\r
51 #define IFNAME1 'n'\r
52 \r
53 struct ethernetif {\r
54   struct eth_addr *ethaddr;\r
55   /* Add whatever per-interface state that is needed here. */\r
56 };\r
57 \r
58 static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};\r
59 \r
60 /* Forward declarations. */\r
61 static void  ethernetif_input(struct netif *netif);\r
62 static err_t ethernetif_output(struct netif *netif, struct pbuf *p,\r
63              struct ip_addr *ipaddr);\r
64 \r
65 static void\r
66 low_level_init(struct netif *netif)\r
67 {\r
68   struct ethernetif *ethernetif = netif->state;\r
69   \r
70   /* set MAC hardware address length */\r
71   netif->hwaddr_len = 6;\r
72 \r
73   /* set MAC hardware address */\r
74   netif->hwaddr[0] = ;\r
75   ...\r
76   netif->hwaddr[5] = ;\r
77 \r
78   /* maximum transfer unit */\r
79   netif->mtu = 1500;\r
80   \r
81   /* broadcast capability */\r
82   netif->flags = NETIF_FLAG_BROADCAST;\r
83  \r
84   /* Do whatever else is needed to initialize interface. */  \r
85 }\r
86 \r
87 /*\r
88  * low_level_output():\r
89  *\r
90  * Should do the actual transmission of the packet. The packet is\r
91  * contained in the pbuf that is passed to the function. This pbuf\r
92  * might be chained.\r
93  *\r
94  */\r
95 \r
96 static err_t\r
97 low_level_output(struct netif *netif, struct pbuf *p)\r
98 {\r
99   struct ethernetif *ethernetif = netif->state;\r
100   struct pbuf *q;\r
101 \r
102   initiate transfer();\r
103   \r
104 #if ETH_PAD_SIZE\r
105   pbuf_header(p, -ETH_PAD_SIZE);                        /* drop the padding word */\r
106 #endif\r
107 \r
108   for(q = p; q != NULL; q = q->next) {\r
109     /* Send the data from the pbuf to the interface, one pbuf at a\r
110        time. The size of the data in each pbuf is kept in the ->len\r
111        variable. */\r
112     send data from(q->payload, q->len);\r
113   }\r
114 \r
115   signal that packet should be sent();\r
116 \r
117 #if ETH_PAD_SIZE\r
118   pbuf_header(p, ETH_PAD_SIZE);                 /* reclaim the padding word */\r
119 #endif\r
120   \r
121 #if LINK_STATS\r
122   lwip_stats.link.xmit++;\r
123 #endif /* LINK_STATS */      \r
124 \r
125   return ERR_OK;\r
126 }\r
127 \r
128 /*\r
129  * low_level_input():\r
130  *\r
131  * Should allocate a pbuf and transfer the bytes of the incoming\r
132  * packet from the interface into the pbuf.\r
133  *\r
134  */\r
135 \r
136 static struct pbuf *\r
137 low_level_input(struct netif *netif)\r
138 {\r
139   struct ethernetif *ethernetif = netif->state;\r
140   struct pbuf *p, *q;\r
141   u16_t len;\r
142 \r
143   /* Obtain the size of the packet and put it into the "len"\r
144      variable. */\r
145   len = ;\r
146 \r
147 #if ETH_PAD_SIZE\r
148   len += ETH_PAD_SIZE;                                          /* allow room for Ethernet padding */\r
149 #endif\r
150 \r
151   /* We allocate a pbuf chain of pbufs from the pool. */\r
152   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);\r
153   \r
154   if (p != NULL) {\r
155 \r
156 #if ETH_PAD_SIZE\r
157     pbuf_header(p, -ETH_PAD_SIZE);                      /* drop the padding word */\r
158 #endif\r
159 \r
160     /* We iterate over the pbuf chain until we have read the entire\r
161      * packet into the pbuf. */\r
162     for(q = p; q != NULL; q = q->next) {\r
163       /* Read enough bytes to fill this pbuf in the chain. The\r
164        * available data in the pbuf is given by the q->len\r
165        * variable. */\r
166       read data into(q->payload, q->len);\r
167     }\r
168     acknowledge that packet has been read();\r
169 \r
170 #if ETH_PAD_SIZE\r
171     pbuf_header(p, ETH_PAD_SIZE);                       /* reclaim the padding word */\r
172 #endif\r
173 \r
174 #if LINK_STATS\r
175     lwip_stats.link.recv++;\r
176 #endif /* LINK_STATS */      \r
177   } else {\r
178     drop packet();\r
179 #if LINK_STATS\r
180     lwip_stats.link.memerr++;\r
181     lwip_stats.link.drop++;\r
182 #endif /* LINK_STATS */      \r
183   }\r
184 \r
185   return p;  \r
186 }\r
187 \r
188 /*\r
189  * ethernetif_output():\r
190  *\r
191  * This function is called by the TCP/IP stack when an IP packet\r
192  * should be sent. It calls the function called low_level_output() to\r
193  * do the actual transmission of the packet.\r
194  *\r
195  */\r
196 \r
197 static err_t\r
198 ethernetif_output(struct netif *netif, struct pbuf *p,\r
199       struct ip_addr *ipaddr)\r
200 {\r
201   \r
202  /* resolve hardware address, then send (or queue) packet */\r
203   return etharp_output(netif, ipaddr, p);\r
204  \r
205 }\r
206 \r
207 /*\r
208  * ethernetif_input():\r
209  *\r
210  * This function should be called when a packet is ready to be read\r
211  * from the interface. It uses the function low_level_input() that\r
212  * should handle the actual reception of bytes from the network\r
213  * interface.\r
214  *\r
215  */\r
216 \r
217 static void\r
218 ethernetif_input(struct netif *netif)\r
219 {\r
220   struct ethernetif *ethernetif;\r
221   struct eth_hdr *ethhdr;\r
222   struct pbuf *p;\r
223 \r
224   ethernetif = netif->state;\r
225   \r
226   /* move received packet into a new pbuf */\r
227   p = low_level_input(netif);\r
228   /* no packet could be read, silently ignore this */\r
229   if (p == NULL) return;\r
230   /* points to packet payload, which starts with an Ethernet header */\r
231   ethhdr = p->payload;\r
232 \r
233 #if LINK_STATS\r
234   lwip_stats.link.recv++;\r
235 #endif /* LINK_STATS */\r
236 \r
237   ethhdr = p->payload;\r
238     \r
239   switch (htons(ethhdr->type)) {\r
240   /* IP packet? */\r
241   case ETHTYPE_IP:\r
242 #if 0\r
243 /* CSi disabled ARP table update on ingress IP packets.\r
244    This seems to work but needs thorough testing. */\r
245     /* update ARP table */\r
246     etharp_ip_input(netif, p);\r
247 #endif\r
248     /* skip Ethernet header */\r
249     pbuf_header(p, -sizeof(struct eth_hdr));\r
250     /* pass to network layer */\r
251     netif->input(p, netif);\r
252     break;\r
253       \r
254     case ETHTYPE_ARP:\r
255       /* pass p to ARP module  */\r
256       etharp_arp_input(netif, ethernetif->ethaddr, p);\r
257       break;\r
258     default:\r
259       pbuf_free(p);\r
260       p = NULL;\r
261       break;\r
262   }\r
263 }\r
264 \r
265 static void\r
266 arp_timer(void *arg)\r
267 {\r
268   etharp_tmr();\r
269   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);\r
270 }\r
271 \r
272 /*\r
273  * ethernetif_init():\r
274  *\r
275  * Should be called at the beginning of the program to set up the\r
276  * network interface. It calls the function low_level_init() to do the\r
277  * actual setup of the hardware.\r
278  *\r
279  */\r
280 \r
281 err_t\r
282 ethernetif_init(struct netif *netif)\r
283 {\r
284   struct ethernetif *ethernetif;\r
285     \r
286   ethernetif = mem_malloc(sizeof(struct ethernetif));\r
287   \r
288   if (ethernetif == NULL)\r
289   {\r
290         LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));\r
291         return ERR_MEM;\r
292   }\r
293 \r
294 #if LWIP_SNMP\r
295   /* ifType ethernetCsmacd(6) @see RFC1213 */\r
296   netif->link_type = 6;\r
297   /* your link speed here */\r
298   netif->link_speed = ;\r
299   netif->ts = 0;\r
300   netif->ifinoctets = 0;\r
301   netif->ifinucastpkts = 0;\r
302   netif->ifinnucastpkts = 0;\r
303   netif->ifindiscards = 0;\r
304   netif->ifoutoctets = 0;\r
305   netif->ifoutucastpkts = 0;\r
306   netif->ifoutnucastpkts = 0;\r
307   netif->ifoutdiscards = 0;\r
308 #endif\r
309   \r
310   netif->state = ethernetif;\r
311   netif->name[0] = IFNAME0;\r
312   netif->name[1] = IFNAME1;\r
313   netif->output = ethernetif_output;\r
314   netif->linkoutput = low_level_output;\r
315   \r
316   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);\r
317   \r
318   low_level_init(netif);\r
319 \r
320   etharp_init();\r
321 \r
322   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);\r
323 \r
324   return ERR_OK;\r
325 }\r
326 \r