]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/redboot/v2_0/src/net/enet.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / redboot / v2_0 / src / net / enet.c
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
62 static int num_ip = 0;
63 static int num_arp = 0;
64 #ifdef NET_SUPPORT_RARP
65 static int num_rarp = 0;
66 #endif
67 static int num_received = 0;
68 static 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
76 static struct {
77     int type;
78     pkt_handler_t handler;
79 } eth_handlers[NUM_EXTRA_HANDLERS];
80
81 pkt_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
111 void 
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  */
127 void
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  */
214 void
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
232 unsigned long  
233 ntohl(unsigned long x)
234 {
235     return (((x & 0x000000FF) << 24) |
236             ((x & 0x0000FF00) <<  8) |
237             ((x & 0x00FF0000) >>  8) |
238             ((x & 0xFF000000) >> 24));
239 }
240
241 unsigned short
242 ntohs(unsigned short x)
243 {
244     return (((x & 0x00FF) << 8) |
245             ((x & 0xFF00) >> 8));
246 }
247
248 #endif