1 //==========================================================================
5 // Stand-alone ethernet [link-layer] support for RedBoot
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
49 // This code is part of RedBoot (tm).
51 //####DESCRIPTIONEND####
53 //==========================================================================
57 #include <cyg/io/eth/eth_drv.h> // Logical driver interfaces
59 //#define ENET_STATS 1
62 static int num_ip = 0;
63 static int num_arp = 0;
64 #ifdef NET_SUPPORT_RARP
65 static int num_rarp = 0;
67 static int num_received = 0;
68 static int num_transmitted = 0;
72 // Support for user handlers of additional ethernet packets (nonIP)
75 #define NUM_EXTRA_HANDLERS 4
78 pkt_handler_t handler;
79 } eth_handlers[NUM_EXTRA_HANDLERS];
82 __eth_install_listener(int eth_type, pkt_handler_t handler)
87 if (eth_type > 0x800 || handler != (pkt_handler_t)0) {
89 for (i = 0; i < NUM_EXTRA_HANDLERS; i++) {
90 if (eth_handlers[i].type == eth_type) {
91 // Replace existing handler
92 old = eth_handlers[i].handler;
93 eth_handlers[i].handler = handler;
96 if (eth_handlers[i].type == 0) {
102 eth_handlers[empty].type = eth_type;
103 eth_handlers[empty].handler = handler;
104 return (pkt_handler_t)0;
107 diag_printf("** Warning: can't install listener for ethernet type 0x%02x\n", eth_type);
108 return (pkt_handler_t)0;
112 __eth_remove_listener(int eth_type)
116 for (i = 0; i < NUM_EXTRA_HANDLERS; i++) {
117 if (eth_handlers[i].type == eth_type) {
118 eth_handlers[i].type = 0;
124 * Non-blocking poll of ethernet link. Process packets until no more
131 eth_header_t eth_hdr;
133 #ifdef DEBUG_PKT_EXHAUSTION
134 static bool was_exhausted = false;
139 * Try to get a free pktbuf and return if none
142 if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) {
143 #ifdef DEBUG_PKT_EXHAUSTION
144 if (!was_exhausted) {
145 int old = start_console(); // Force output to standard port
146 diag_printf("__enet_poll: no more buffers\n");
148 was_exhausted = true;
154 #ifdef DEBUG_PKT_EXHAUSTION
155 was_exhausted = false; // Report the next time we're out of buffers
158 if ((pkt->pkt_bytes = eth_drv_read((char *)ð_hdr, (char *)pkt->buf,
159 ETH_MAX_PKTLEN)) > 0) {
163 switch (type = ntohs(eth_hdr.type)) {
169 pkt->ip_hdr = (ip_header_t *)pkt->buf;
170 __ip_handler(pkt, ð_hdr.source);
177 pkt->arp_hdr = (arp_header_t *)pkt->buf;
181 #ifdef NET_SUPPORT_RARP
186 pkt->arp_hdr = (arp_header_t *)pkt->buf;
193 for (i = 0; i < NUM_EXTRA_HANDLERS; i++) {
194 if (eth_handlers[i].type == type) {
195 (eth_handlers[i].handler)(pkt, ð_hdr);
212 * Send an ethernet packet.
215 __enet_send(pktbuf_t *pkt, enet_addr_t *dest, int eth_type)
217 eth_header_t eth_hdr;
219 // Set up ethernet header
220 memcpy(ð_hdr.destination, dest, sizeof(enet_addr_t));
221 memcpy(ð_hdr.source, __local_enet_addr, sizeof(enet_addr_t));
222 eth_hdr.type = htons(eth_type);
224 eth_drv_write((char *)ð_hdr, (char *)pkt->buf, pkt->pkt_bytes);
230 #ifdef __LITTLE_ENDIAN__
233 ntohl(unsigned long x)
235 return (((x & 0x000000FF) << 24) |
236 ((x & 0x0000FF00) << 8) |
237 ((x & 0x00FF0000) >> 8) |
238 ((x & 0xFF000000) >> 24));
242 ntohs(unsigned short x)
244 return (((x & 0x00FF) << 8) |
245 ((x & 0xFF00) >> 8));