OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [redboot/] [v2_0/] [src/] [net/] [enet.c] - Diff between revs 1254 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.