source: azure_iot_hub_f767zi/trunk/asp_baseplatform/lwip/contrib-2.1.0/ports/toppers/ethernetif.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 15.6 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2003-2015 by Ryosuke Takeuchi
7 * GJ Business Division RICOH COMPANY,LTD. JAPAN
8 * Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
9 *
10 * 上記著作権者は,Free Software Foundation によって公表されている
11 * GNU General Public License の Version 2 に記述されている条件か,以
12 * 下の(1)~(4)の条件を満たす場合に限り,本ソフトウェア(本ソフトウェ
13 * アを改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
14 * 利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを再利用可能なバイナリコード(リロケータブルオブ
19 * ジェクトファイルやライブラリなど)の形で利用する場合には,利用
20 * に伴うドキュメント(利用者マニュアルなど)に,上記の著作権表示,
21 * この利用条件および下記の無保証規定を掲載すること.
22 * (3) 本ソフトウェアを再利用不可能なバイナリコードの形または機器に組
23 * み込んだ形で利用する場合には,次のいずれかの条件を満たすこと.
24 * (a) 利用に伴うドキュメント(利用者マニュアルなど)に,上記の著作
25 * 権表示,この利用条件および下記の無保証規定を掲載すること.
26 * (b) 利用の形態を,別に定める方法によって,上記著作権者に報告する
27 * こと.
28 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29 * 害からも,上記著作権者を免責すること.
30 *
31 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者は,
32 * 本ソフトウェアに関して,その適用可能性も含めて,いかなる保証も行わ
33 * ない.また,本ソフトウェアの利用により直接的または間接的に生じたい
34 * かなる損害に関しても,その責任を負わない.
35 *
36 * @(#) $Id$
37 */
38
39/*
40 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without modification,
44 * are permitted provided that the following conditions are met:
45 *
46 * 1. Redistributions of source code must retain the above copyright notice,
47 * this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright notice,
49 * this list of conditions and the following disclaimer in the documentation
50 * and/or other materials provided with the distribution.
51 * 3. The name of the author may not be used to endorse or promote products
52 * derived from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
55 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
56 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
57 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
59 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
62 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
63 * OF SUCH DAMAGE.
64 *
65 * This file is part of the lwIP TCP/IP stack.
66 *
67 * Author: Adam Dunkels <adam@sics.se>
68 *
69 */
70
71/*
72 * This file is a skeleton for developing Ethernet network interface
73 * drivers for lwIP. Add code to the low_level functions and do a
74 * search-and-replace for the word "ethernetif" to replace it with
75 * something that better describes your network interface.
76 */
77
78#include "kernel_impl.h"
79#include <t_syslog.h>
80#include <t_stdlib.h>
81#include <sil.h>
82#include <string.h>
83#include <target_syssvc.h>
84#include "kernel_cfg.h"
85
86#include "lwip/opt.h"
87
88#include "lwip/def.h"
89#include "lwip/ip.h"
90#include "lwip/mem.h"
91#include "lwip/stats.h"
92#include "lwip/snmp.h"
93#include "lwip/pbuf.h"
94#include "lwip/sys.h"
95#include "lwip/timeouts.h"
96#include "netif/etharp.h"
97#include "lwip/ethip6.h"
98
99#include "emac.h"
100
101/*
102 * DESCRIPTOR定義
103 */
104#ifndef EMAC_PKTBUFSIZE
105#define EMAC_PKTBUFSIZE 1536
106#endif
107#ifndef NUM_RX_DESC
108#define NUM_RX_DESC 32 /* 受信キューの個数 */
109#endif
110#ifndef NUM_TX_DESC
111#define NUM_TX_DESC 24 /* 送信キューの個数 */
112#endif
113#define NUM_ALL_DESC (NUM_RX_DESC + NUM_TX_DESC)
114
115static uint32_t event_count, event_value;
116#ifndef EMAC_DATA_ATTRIBUTE
117static uint8_t netqueue[(NUM_ALL_DESC * EMAC_QUE_SIZE)] __attribute__ ((aligned (32)));
118static uint8_t netbuffer[(NUM_ALL_DESC * EMAC_PKTBUFSIZE)] __attribute__ ((aligned (32));
119#else
120static uint8_t netqueue[(NUM_ALL_DESC * EMAC_QUE_SIZE)] __attribute__ (EMAC_DATA_ATTRIBUTE) __attribute__ ((aligned (32)));
121static uint8_t netbuffer[(NUM_ALL_DESC * EMAC_PKTBUFSIZE)] __attribute__ (EMAC_DATA_ATTRIBUTE) __attribute__ ((aligned (32)));
122#endif
123
124/* Define those to better describe your network interface. */
125#define IFNAME0 'e'
126#define IFNAME1 'n'
127
128
129/**
130 * Helper struct to hold private data used to operate your ethernet interface.
131 * Keeping the ethernet address of the MAC in this struct is not necessary
132 * as it is already kept in the struct netif.
133 * But this is only an example, anyway...
134 */
135struct ethernetif {
136 struct netif *netif;
137 EMAC_Handle_t *emacdev;
138 struct eth_addr *ethaddr;
139 uint8_t enable;
140 /* Add whatever per-interface state that is needed here. */
141};
142
143/* Forward declarations. */
144static void ethernetif_input(struct netif *netif);
145static void ethernet_thread(void *arg);
146
147/**
148 * callback from emac
149 */
150static void
151emac_event(EMAC_Handle_t *hemac, int mode, uint32_t event)
152{
153 event_value |= event;
154 if((++event_count % 200) == 0){
155 syslog_3(LOG_NOTICE, "emac_event(%08x, %08x) count(%d)", hemac, event_value, event_count);
156 event_value = 0;
157 }
158 if(mode == 0)
159 iset_flg(FLG_GMAC, event);
160 else
161 set_flg(FLG_GMAC, event);
162}
163
164/**
165 * In this function, the hardware should be initialized.
166 * Called from ethernetif_init().
167 *
168 * @param netif the already initialized lwip network interface structure
169 * for this ethernetif
170 */
171static void
172low_level_init(struct netif *netif)
173{
174 EMAC_Init_t Init;
175 struct ethernetif *ethernetif = netif->state;
176 EMAC_Handle_t *emacdev;
177
178 /* set MAC hardware address length */
179 netif->hwaddr_len = ETHARP_HWADDR_LEN;
180
181 /* set MAC hardware address */
182 netif->hwaddr[0] = 0x02;
183 netif->hwaddr[1] = 0x12;
184 netif->hwaddr[2] = 0x34;
185 netif->hwaddr[3] = 0x56;
186 netif->hwaddr[4] = 0x78;
187 netif->hwaddr[5] = 0xab;
188
189 /* maximum transfer unit */
190 netif->mtu = 1500;
191
192 /* device capabilities */
193 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
194 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
195
196#if LWIP_IPV6 && LWIP_IPV6_MLD
197 /*
198 * For hardware/netifs that implement MAC filtering.
199 * All-nodes link-local is handled by default, so we must let the hardware know
200 * to allow multicast packets in.
201 * Should set mld_mac_filter previously. */
202 if (netif->mld_mac_filter != NULL) {
203 ip6_addr_t ip6_allnodes_ll;
204 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
205 netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
206 }
207#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
208
209 /* Do whatever else is needed to initialize interface. */
210
211// netif_set_link_up(netif);
212
213 ethernetif->netif = netif;
214 Init.paketbufsize = EMAC_PKTBUFSIZE;
215 Init.rxquecount = NUM_RX_DESC;
216 Init.txquecount = NUM_TX_DESC;
217 Init.quebuffer = netqueue;
218 Init.databuffer = netbuffer;
219 Init.semid = SEM_GMAC_MDIO;
220 emacdev = emac_init(MACDEF_PORTID, &Init);
221 ethernetif->emacdev = emacdev;
222 emacdev->emacevent = emac_event;
223
224 /* EMAC のリセット */
225 emac_reset(emacdev, (uint8_t *)ethernetif->ethaddr);
226
227 /* 送受信を開始する */
228#ifdef LWIP_AUTONEGO
229 emac_start(emacdev, EMAC_LINK_AUTONEGO);
230#else /* LWIP_AUTONEGO */
231 emac_start(emacdev, EMAC_LINK_100BASE_FULL);
232#endif /* LWIP_AUTONEGO */
233 ethernetif->enable = 1;
234 sys_thread_new("ethernet_thread", ethernet_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
235}
236
237/**
238 * This function should do the actual transmission of the packet. The packet is
239 * contained in the pbuf that is passed to the function. This pbuf
240 * might be chained.
241 *
242 * @param netif the lwip network interface structure for this ethernetif
243 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
244 * @return ERR_OK if the packet could be sent
245 * an err_t value if the packet couldn't be sent
246 *
247 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
248 * strange results. You might consider waiting for space in the DMA queue
249 * to become available since the stack doesn't retry to send a packet
250 * dropped because of memory failure (except for the TCP timers).
251 */
252static err_t
253low_level_output(struct netif *netif, struct pbuf *p)
254{
255 struct ethernetif *ethernetif = netif->state;
256 err_t err = ERR_OK;
257
258#if ETH_PAD_SIZE
259 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
260#endif
261
262 if(emac_send(ethernetif->emacdev, (struct emac_pkt *)p) != 0)
263 err = ERR_MEM;
264
265 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
266 if (((u8_t*)p->payload)[0] & 1) {
267 /* broadcast or multicast packet*/
268 MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
269 } else {
270 /* unicast packet */
271 MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
272 }
273 /* increase ifoutdiscards or ifouterrors on error */
274
275#if ETH_PAD_SIZE
276 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
277#endif
278
279 LINK_STATS_INC(link.xmit);
280
281 return err;
282}
283
284/**
285 * Should allocate a pbuf and transfer the bytes of the incoming
286 * packet from the interface into the pbuf.
287 *
288 * @param netif the lwip network interface structure for this ethernetif
289 * @return a pbuf filled with the received packet (including MAC header)
290 * NULL on memory error
291 */
292static struct pbuf *
293low_level_input(struct netif *netif)
294{
295 struct ethernetif *ethernetif = (struct ethernetif *)netif->state;
296 struct pbuf *p;
297 int len;
298 ER ercd;
299
300 /* Obtain the size of the packet and put it into the "len"
301 variable. */
302 len = emac_recv_length(ethernetif->emacdev);
303 if(len <= 0)
304 return NULL;
305
306#if ETH_PAD_SIZE
307 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
308#endif
309
310 /* We allocate a pbuf chain of pbufs from the pool. */
311 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
312
313 if (p != NULL) {
314
315#if ETH_PAD_SIZE
316 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
317#endif
318
319 ercd = emac_recv(ethernetif->emacdev, (struct emac_pkt *)p);
320 if(ercd != E_OK)
321 syslog_1(LOG_ERROR, "low_level_input emac_recv error(%d) !", ercd);
322
323 MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
324 if (((u8_t*)p->payload)[0] & 1) {
325 /* broadcast or multicast packet*/
326 MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
327 } else {
328 /* unicast packet*/
329 MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
330 }
331#if ETH_PAD_SIZE
332 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
333#endif
334
335 LINK_STATS_INC(link.recv);
336 } else {
337 emac_recv(ethernetif->emacdev, NULL);
338 LINK_STATS_INC(link.memerr);
339 LINK_STATS_INC(link.drop);
340 MIB2_STATS_NETIF_INC(netif, ifindiscards);
341 }
342
343 return p;
344}
345
346/**
347 * This function should be called when a packet is ready to be read
348 * from the interface. It uses the function low_level_input() that
349 * should handle the actual reception of bytes from the network
350 * interface. Then the type of the received packet is determined and
351 * the appropriate input function is called.
352 *
353 * @param netif the lwip network interface structure for this ethernetif
354 */
355static void
356ethernetif_input(struct netif *netif)
357{
358 struct pbuf *p;
359
360 /* move received packet into a new pbuf */
361 p = low_level_input(netif);
362 /* if no packet could be read, silently ignore this */
363 if (p != NULL) {
364 /* pass all packets to ethernet_input, which decides what packets it supports */
365 if (netif->input(p, netif) != ERR_OK) {
366 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
367 pbuf_free(p);
368 p = NULL;
369 }
370 }
371}
372
373/**
374 * Should be called at the beginning of the program to set up the
375 * network interface. It calls the function low_level_init() to do the
376 * actual setup of the hardware.
377 *
378 * This function should be passed as a parameter to netif_add().
379 *
380 * @param netif the lwip network interface structure for this ethernetif
381 * @return ERR_OK if the loopif is initialized
382 * ERR_MEM if private data couldn't be allocated
383 * any other err_t on error
384 */
385err_t
386ethernetif_init(struct netif *netif)
387{
388 struct ethernetif *ethernetif;
389
390 LWIP_ASSERT("netif != NULL", (netif != NULL));
391
392 ethernetif = mem_malloc(sizeof(struct ethernetif));
393 if (ethernetif == NULL) {
394 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
395 return ERR_MEM;
396 }
397
398#if LWIP_NETIF_HOSTNAME
399 /* Initialize interface hostname */
400 netif->hostname = "lwip";
401#endif /* LWIP_NETIF_HOSTNAME */
402
403 /*
404 * Initialize the snmp variables and counters inside the struct netif.
405 * The last argument should be replaced with your link speed, in units
406 * of bits per second.
407 */
408 MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
409
410 netif->state = ethernetif;
411
412 netif->name[0] = IFNAME0;
413 netif->name[1] = IFNAME1;
414 /* We directly use etharp_output() here to save a function call.
415 * You can instead declare your own function an call etharp_output()
416 * from it if you have to do some checks before sending (e.g. if link
417 * is available...) */
418 netif->output = etharp_output;
419#if LWIP_IPV6
420 netif->output_ip6 = ethip6_output;
421#endif /* LWIP_IPV6 */
422 netif->linkoutput = low_level_output;
423 netif->mtu = 1500;
424
425 ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
426
427 low_level_init(netif);
428
429 return ERR_OK;
430}
431
432/**
433 * ethernet polling thread
434 */
435static void
436ethernet_thread(void *arg)
437{
438 struct netif *netif;
439 struct ethernetif *ethernetif;
440 FLGPTN flgptn;
441 ER ercd;
442 uint32_t rlink;
443 int len;
444
445 netif = (struct netif *)arg;
446 ethernetif = (struct ethernetif *)netif->state;
447 dly_tsk(1000);
448
449 while(1) {
450 ercd = twai_flg(FLG_GMAC, 0x00ff, TWF_ORW, &flgptn, 100);
451 if(ercd == E_OK){
452 clr_flg(FLG_GMAC, ~flgptn);
453 if((flgptn & RESET_EVNT_DETECT) != 0){
454 emac_reset(ethernetif->emacdev, (uint8_t *)ethernetif->ethaddr);
455 continue;
456 }
457 }
458
459 rlink = emac_link_detect(ethernetif->emacdev);
460 if(rlink == 0 && (netif->flags & NETIF_FLAG_LINK_UP)){
461 syslog_2(LOG_NOTICE, "ethernetif:unlink[%08x][%08x] !", rlink, netif->flags);
462 netif_set_link_down(netif);
463 }
464 else if(rlink != 0 && !(netif->flags & NETIF_FLAG_LINK_UP)){
465 /* Interface mode の設定 */
466 emac_link_mode_set(ethernetif->emacdev, rlink);
467 syslog_2(LOG_NOTICE, "ethernetif:link[%08x][%08x] !", rlink, netif->flags);
468 netif_set_link_up(netif);
469 }
470
471 len = emac_recv_length(ethernetif->emacdev);
472
473 /* Wait for a packet to arrive. */
474 if(len > 0) {
475 /* Handle incoming packet. */
476 ethernetif_input(netif);
477 }
478 }
479}
480
Note: See TracBrowser for help on using the repository browser.