📄 enet.c
字号:
//==========================================================================//// net/enet.c//// Stand-alone ethernet [link-layer] support for RedBoot////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-07-14// Purpose: // Description: // // This code is part of RedBoot (tm).////####DESCRIPTIONEND####////==========================================================================#include <redboot.h>#include <net/net.h>#include <cyg/io/eth/eth_drv.h> // Logical driver interfaces//#define ENET_STATS 1#ifdef ENET_STATSstatic int num_ip = 0;static int num_arp = 0;#ifdef NET_SUPPORT_RARPstatic int num_rarp = 0;#endifstatic int num_received = 0;static int num_transmitted = 0;#endif//// Support for user handlers of additional ethernet packets (nonIP)//#define NUM_EXTRA_HANDLERS 4static struct { int type; pkt_handler_t handler;} eth_handlers[NUM_EXTRA_HANDLERS];pkt_handler_t __eth_install_listener(int eth_type, pkt_handler_t handler){ int i, empty; pkt_handler_t old; if (eth_type > 0x800 || handler != (pkt_handler_t)0) { empty = -1; for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { if (eth_handlers[i].type == eth_type) { // Replace existing handler old = eth_handlers[i].handler; eth_handlers[i].handler = handler; return old; } if (eth_handlers[i].type == 0) { empty = i; } } if (empty >= 0) { // Found a free slot eth_handlers[empty].type = eth_type; eth_handlers[empty].handler = handler; return (pkt_handler_t)0; } } diag_printf("** Warning: can't install listener for ethernet type 0x%02x\n", eth_type); return (pkt_handler_t)0;}void __eth_remove_listener(int eth_type){ int i; for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { if (eth_handlers[i].type == eth_type) { eth_handlers[i].type = 0; } } }/* * Non-blocking poll of ethernet link. Process packets until no more * are available. */void__enet_poll(void){ pktbuf_t *pkt; eth_header_t eth_hdr; int i, type;#ifdef DEBUG_PKT_EXHAUSTION static bool was_exhausted = false;#endif while (true) { /* * Try to get a free pktbuf and return if none * are available. */ if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) {#ifdef DEBUG_PKT_EXHAUSTION if (!was_exhausted) { int old = start_console(); // Force output to standard port diag_printf("__enet_poll: no more buffers\n"); __pktbuf_dump(); was_exhausted = true; end_console(old); } #endif return; }#ifdef DEBUG_PKT_EXHAUSTION was_exhausted = false; // Report the next time we're out of buffers#endif if ((pkt->pkt_bytes = eth_drv_read((char *)ð_hdr, (char *)pkt->buf, ETH_MAX_PKTLEN)) > 0) {#ifdef ENET_STATS ++num_received;#endif switch (type = ntohs(eth_hdr.type)) { case ETH_TYPE_IP:#ifdef ENET_STATS ++num_ip;#endif pkt->ip_hdr = (ip_header_t *)pkt->buf; __ip_handler(pkt, ð_hdr.source); break; case ETH_TYPE_ARP:#ifdef ENET_STATS ++num_arp;#endif pkt->arp_hdr = (arp_header_t *)pkt->buf; __arp_handler(pkt); break;#ifdef NET_SUPPORT_RARP case ETH_TYPE_RARP:#ifdef ENET_STATS ++num_rarp;#endif pkt->arp_hdr = (arp_header_t *)pkt->buf; __rarp_handler(pkt); break;#endif default: if (type > 0x800) { for (i = 0; i < NUM_EXTRA_HANDLERS; i++) { if (eth_handlers[i].type == type) { (eth_handlers[i].handler)(pkt, ð_hdr); } } } __pktbuf_free(pkt); break; } } else { __pktbuf_free(pkt); break; } }}/* * Send an ethernet packet. */void__enet_send(pktbuf_t *pkt, enet_addr_t *dest, int eth_type){ eth_header_t eth_hdr; // Set up ethernet header memcpy(ð_hdr.destination, dest, sizeof(enet_addr_t)); memcpy(ð_hdr.source, __local_enet_addr, sizeof(enet_addr_t)); eth_hdr.type = htons(eth_type); eth_drv_write((char *)ð_hdr, (char *)pkt->buf, pkt->pkt_bytes);#ifdef ENET_STATS ++num_transmitted;#endif}#ifdef __LITTLE_ENDIAN__unsigned long ntohl(unsigned long x){ return (((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24));}unsigned longntohs(unsigned short x){ return (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -