source: SVN/cambria/redboot/packages/redboot/current/src/net/enet.c @ 1

Last change on this file since 1 was 1, checked in by Tim Harvey, 2 years ago

restored latest version of files from server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 6.6 KB
Line 
1//==========================================================================
2//
3//      net/enet.c
4//
5//      Stand-alone ethernet [link-layer] support for RedBoot
6//
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.
12//
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.
16//
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
20// for more details.
21//
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.
25//
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.
32//
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.
35//
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####
42//
43// Author(s):    gthomas
44// Contributors: gthomas
45// Date:         2000-07-14
46// Purpose:     
47// Description: 
48//             
49// This code is part of RedBoot (tm).
50//
51//####DESCRIPTIONEND####
52//
53//==========================================================================
54
55#include <redboot.h>
56#include <net/net.h>
57#include <cyg/io/eth/eth_drv.h>       // Logical driver interfaces
58
59//#define ENET_STATS 1
60
61#ifdef ENET_STATS
62static int num_ip = 0;
63static int num_arp = 0;
64#ifdef NET_SUPPORT_RARP
65static int num_rarp = 0;
66#endif
67static int num_received = 0;
68static int num_transmitted = 0;
69#endif
70
71//
72// Support for user handlers of additional ethernet packets (nonIP)
73//
74
75#define NUM_EXTRA_HANDLERS 4
76static struct {
77    int type;
78    pkt_handler_t handler;
79} eth_handlers[NUM_EXTRA_HANDLERS];
80
81pkt_handler_t
82__eth_install_listener(int eth_type, pkt_handler_t handler)
83{
84    int i, empty;
85    pkt_handler_t old;
86
87    if (eth_type > 0x800 || handler != (pkt_handler_t)0) {
88        empty = -1;
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;
94                return old;
95            }
96            if (eth_handlers[i].type == 0) {
97                empty = i;
98            }
99        }
100        if (empty >= 0) {
101            // Found a free slot
102            eth_handlers[empty].type = eth_type;
103            eth_handlers[empty].handler = handler;
104            return (pkt_handler_t)0;
105        }
106    }
107    diag_printf("** Warning: can't install listener for ethernet type 0x%02x\n", eth_type);
108    return (pkt_handler_t)0;
109}
110
111void 
112__eth_remove_listener(int eth_type)
113{
114    int i;
115   
116    for (i = 0;  i < NUM_EXTRA_HANDLERS;  i++) {
117        if (eth_handlers[i].type == eth_type) {
118            eth_handlers[i].type = 0;
119        }
120    }   
121}
122
123/*
124 * Non-blocking poll of ethernet link. Process packets until no more
125 * are available.
126 */
127void
128__enet_poll(void)
129{
130    pktbuf_t *pkt;
131    eth_header_t eth_hdr;
132    int i, type;
133#ifdef DEBUG_PKT_EXHAUSTION
134    static bool was_exhausted = false;
135#endif
136
137    while (true) {
138        /*
139         * Try to get a free pktbuf and return if none
140         * are available.
141         */
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");
147                __pktbuf_dump();
148                was_exhausted = true;
149                end_console(old);
150            } 
151#endif
152            return;
153        }
154#ifdef DEBUG_PKT_EXHAUSTION
155        was_exhausted = false;  // Report the next time we're out of buffers
156#endif
157
158        if ((pkt->pkt_bytes = eth_drv_read((char *)&eth_hdr, (char *)pkt->buf,
159                                           ETH_MAX_PKTLEN)) > 0) {
160#ifdef ENET_STATS
161            ++num_received;
162#endif
163            switch (type = ntohs(eth_hdr.type)) {
164
165            case ETH_TYPE_IP:
166#ifdef ENET_STATS
167                ++num_ip;
168#endif
169                pkt->ip_hdr = (ip_header_t *)pkt->buf;
170                __ip_handler(pkt, &eth_hdr.source);
171                break;
172
173            case ETH_TYPE_ARP:
174#ifdef ENET_STATS
175                ++num_arp;
176#endif
177                pkt->arp_hdr = (arp_header_t *)pkt->buf;
178                __arp_handler(pkt);
179                break;
180
181#ifdef NET_SUPPORT_RARP
182            case ETH_TYPE_RARP:
183#ifdef ENET_STATS
184                ++num_rarp;
185#endif
186                pkt->arp_hdr = (arp_header_t *)pkt->buf;
187                __rarp_handler(pkt);
188                break;
189#endif
190
191            default:
192                if (type > 0x800) {
193                    for (i = 0;  i < NUM_EXTRA_HANDLERS;  i++) {
194                        if (eth_handlers[i].type == type) {
195                            (eth_handlers[i].handler)(pkt, &eth_hdr);
196                        }
197                    }
198                }
199                __pktbuf_free(pkt);
200                break;
201            }
202        } else {
203            __pktbuf_free(pkt);
204            break;
205        } 
206    }
207}
208
209
210
211/*
212 * Send an ethernet packet.
213 */
214void
215__enet_send(pktbuf_t *pkt, enet_addr_t *dest, int eth_type)
216{
217    eth_header_t eth_hdr;
218
219    // Set up ethernet header
220    memcpy(&eth_hdr.destination, dest, sizeof(enet_addr_t));
221    memcpy(&eth_hdr.source, __local_enet_addr, sizeof(enet_addr_t));
222    eth_hdr.type = htons(eth_type);
223
224    eth_drv_write((char *)&eth_hdr, (char *)pkt->buf, pkt->pkt_bytes);
225#ifdef ENET_STATS
226    ++num_transmitted;
227#endif
228}
229
230#ifdef __LITTLE_ENDIAN__
231
232unsigned long 
233ntohl(unsigned long x)
234{
235    return (((x & 0x000000FF) << 24) |
236            ((x & 0x0000FF00) <<  8) |
237            ((x & 0x00FF0000) >>  8) |
238            ((x & 0xFF000000) >> 24));
239}
240
241unsigned long
242ntohs(unsigned short x)
243{
244    return (((x & 0x00FF) << 8) |
245            ((x & 0xFF00) >> 8));
246}
247
248#endif
Note: See TracBrowser for help on using the repository browser.