URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [redboot/] [current/] [src/] [net/] [enet.c] - Rev 819
Go to most recent revision | Compare with Previous | Blame | View Log
//========================================================================== // // 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 Free Software Foundation, 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., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 v2. // // This exception does not invalidate any other reasons why a work based // on this file might be covered by the GNU General Public 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_STATS static int num_ip = 0; static int num_arp = 0; #ifdef NET_SUPPORT_RARP static int num_rarp = 0; #endif static int num_received = 0; static int num_transmitted = 0; #endif // // Support for user handlers of additional ethernet packets (nonIP) // #define NUM_EXTRA_HANDLERS 4 static 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 short ntohs(unsigned short x) { return (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8)); } #endif
Go to most recent revision | Compare with Previous | Blame | View Log