| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 | /* * File      : ethernetif.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date           Author       Notes * 2010-07-07     Bernard      fix ethernetif_linkoutput send mail issue. *//* * Copyright (c) 2001-2004 Swedish Institute of Computer Science. * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without modification,  * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, *    this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, *    this list of conditions and the following disclaimer in the documentation *    and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. *  * Author: Adam Dunkels <adam@sics.se> * */#include <rtthread.h>#include "uip.h"#include "uip_arp.h"#include "uip_netif.h"#include "uip_ethernetif.h"#include "uip_ipaddr.h"#ifndef NULL#define NULL (void *)0#endif /* NULL */#define BUF ((struct uip_eth_hdr *)&uip_buf[0])extern u16_t uip_len, uip_slen;/* eth rx/tx thread */static struct rt_mailbox eth_rx_thread_mb;static struct rt_thread eth_rx_thread;#ifndef RT_LWIP_ETHTHREAD_PRIORITY#define RT_ETHERNETIF_THREAD_PREORITY	0x90static char eth_rx_thread_mb_pool[48 * 4];static char eth_rx_thread_stack[1024];#else#define RT_ETHERNETIF_THREAD_PREORITY	RT_LWIP_ETHTHREAD_PRIORITYstatic char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4];static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE];#endifstruct eth_tx_msg{	struct netif 	*netif;	struct pbuf 	*buf;};static struct rt_mailbox eth_tx_thread_mb;static struct rt_thread eth_tx_thread;#ifndef RT_LWIP_ETHTHREAD_PRIORITYstatic char eth_tx_thread_mb_pool[32 * 4];static char eth_tx_thread_stack[512];#elsestatic char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4];static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE];#endif/* the interface provided to uIP */err_t eth_init(struct netif *netif){	return 0;}extern err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p);err_t eth_input(struct pbuf *p,struct netif *inp){	struct eth_hdr *ethhdr;	if(p != RT_NULL)	{#ifdef LINK_STATS		//LINK_STATS_INC(link.recv);#endif  LINK_STATS 		ethhdr = p->payload;		switch(uip_htons(ethhdr->type))		{		case ETHTYPE_IP: //ETHTYPE_IP			etharp_ip_input(inp, p);			pbuf_header(p, -((rt_int16_t)sizeof(struct eth_hdr)));			if (tcpip_input(p, inp) != ERR_OK)			{				// discard packet 				pbuf_free(p);			}			break;		case ETHTYPE_ARP:			etharp_arp_input(inp, (struct eth_addr *)inp->hwaddr, p);			break;		default:			pbuf_free(p);			p = RT_NULL;			break;		}	}    return ERR_OK;}err_t ethernetif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr){	return etharp_output(netif, p, ipaddr);}err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p){	struct eth_tx_msg msg;	struct eth_device* enetif;	enetif = (struct eth_device*)netif->state;	/* send a message to eth tx thread */	msg.netif = netif;	msg.buf   = p;	if (rt_mb_send(ð_tx_thread_mb, (rt_uint32_t) &msg) == RT_EOK)	{		/* waiting for ack */		rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER);	}	return ERR_OK;}/* ethernetif APIs */rt_err_t eth_device_init(struct eth_device* dev, const char* name){	struct netif* netif;        uip_ipaddr_t ipaddr;	netif = (struct netif*) rt_malloc (sizeof(struct netif));	if (netif == RT_NULL)	{		rt_kprintf("malloc netif failed\n");		return -RT_ERROR;	}	rt_memset(netif, 0, sizeof(struct netif));	/* set netif */	dev->netif = netif;	/* register to rt-thread device manager */	rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR);	dev->parent.type = RT_Device_Class_NetIf;	rt_sem_init(&(dev->tx_ack), name, 0, RT_IPC_FLAG_FIFO);	/* set name */	netif->name[0] = name[0];	netif->name[1] = name[1];	/* set hw address to 6 */	netif->hwaddr_len	= 6;	/* maximum transfer unit */	netif->mtu			= ETHERNET_MTU;	/* broadcast capability */	netif->flags		= NETIF_FLAG_BROADCAST;	#if LWIP_IGMP	/* igmp support */	netif->flags |= NETIF_FLAG_IGMP;#endif	/* get hardware address */	rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr);	/* set output */	netif->output		= ethernetif_output;	netif->linkoutput	= ethernetif_linkoutput;	/* add netif to lwip */        	if (netif_add(netif, IP_ADDR_ANY, IP_ADDR_BROADCAST, IP_ADDR_ANY, dev,		eth_init, eth_input) == RT_NULL)	{		/* failed, unregister device and free netif */		rt_device_unregister(&(dev->parent));		rt_free(netif);		return -RT_ERROR;	}        	netif_set_default(netif);	return RT_EOK;}/* ethernet buffer */void eth_tx_thread_entry(void* parameter){	struct eth_tx_msg* msg;	while (1)	{		if (rt_mb_recv(ð_tx_thread_mb, (rt_uint32_t*)&msg, RT_WAITING_FOREVER) == RT_EOK) 		{			struct eth_device* enetif;			RT_ASSERT(msg->netif != RT_NULL);			RT_ASSERT(msg->buf   != RT_NULL);			enetif = (struct eth_device*)msg->netif->state;			if (enetif != RT_NULL)			{				/* call driver's interface */				if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK)				{					rt_kprintf("transmit eth packet failed\n");				}			}			/* send ack */			rt_sem_release(&(enetif->tx_ack));		}	}}/* ethernet buffer */void eth_rx_thread_entry(void* parameter){	struct eth_device* device;	while (1)	{		if (rt_mb_recv(ð_rx_thread_mb, (rt_uint32_t*)&device, RT_WAITING_FOREVER) == RT_EOK) 		{			struct pbuf *p;			/* receive all of buffer */			while (1)			{				p = device->eth_rx(&(device->parent));				if (p != RT_NULL)				{					/* notify to upper layer */					eth_input(p, device->netif);				}				else break;			}		}	}}rt_err_t eth_device_ready(struct eth_device* dev){	/* post message to ethernet thread */	return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev);}rt_err_t eth_system_device_init(){	rt_err_t result = RT_EOK;	/* init rx thread */	/* init mailbox and create ethernet thread */	result = rt_mb_init(ð_rx_thread_mb, "erxmb",		ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/4,		RT_IPC_FLAG_FIFO);	RT_ASSERT(result == RT_EOK);	result = rt_thread_init(ð_rx_thread, "erx", eth_rx_thread_entry, RT_NULL,		ð_rx_thread_stack[0], sizeof(eth_rx_thread_stack),		RT_ETHERNETIF_THREAD_PREORITY, 16);	RT_ASSERT(result == RT_EOK);	result = rt_thread_startup(ð_rx_thread);	RT_ASSERT(result == RT_EOK);	/* init tx thread */	/* init mailbox and create ethernet thread */        	result = rt_mb_init(ð_tx_thread_mb, "etxmb",		ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/4,		RT_IPC_FLAG_FIFO);	RT_ASSERT(result == RT_EOK);	result = rt_thread_init(ð_tx_thread, "etx", eth_tx_thread_entry, RT_NULL,		ð_tx_thread_stack[0], sizeof(eth_tx_thread_stack),		RT_ETHERNETIF_THREAD_PREORITY, 16);	RT_ASSERT(result == RT_EOK);	result = rt_thread_startup(ð_tx_thread);	RT_ASSERT(result == RT_EOK);	return result;}
 |