source: SVN/cambria/redboot/packages/io/eth/current/src/lwip/eth_drv.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: 9.1 KB
Line 
1//==========================================================================
2//
3//      src/lwip/eth_drv.c
4//
5//      Hardware independent ethernet driver for lwIP
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):    Jani Monoses <jani@iv.ro>
44// Contributors:
45// Date:         2002-04-05
46// Purpose:      Hardware independent ethernet driver
47// Description:  Based on the standalone driver for RedBoot.
48//               
49//####DESCRIPTIONEND####
50//
51//==========================================================================
52
53#include <pkgconf/system.h>
54#include <pkgconf/io_eth_drivers.h>
55
56#include <cyg/infra/cyg_type.h>
57#include <cyg/hal/hal_arch.h>
58#include <cyg/infra/diag.h>
59#include <cyg/hal/drv_api.h>
60#include <cyg/hal/hal_if.h>
61#include <cyg/io/eth/eth_drv.h>
62#include <cyg/io/eth/netdev.h>
63#include <string.h>
64
65#include <cyg/hal/hal_tables.h>
66#include <cyg/kernel/kapi.h>
67
68#include "lwip/opt.h"
69#include "lwip/ip.h"
70#include "lwip/mem.h"
71#include "lwip/pbuf.h"
72#include "lwip/sys.h"
73
74#include "netif/etharp.h"
75
76
77// Interfaces exported to drivers
78
79static void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr);
80static void eth_drv_recv(struct eth_drv_sc *sc, int total_len);
81static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status);
82
83struct eth_drv_funs eth_drv_funs = { eth_drv_init, eth_drv_recv, eth_drv_tx_done };
84
85#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
86int cyg_io_eth_net_debug = CYGDBG_IO_ETH_DRIVERS_DEBUG_VERBOSITY;
87#endif
88
89extern void lwip_dsr_stuff(void);
90extern void lwip_set_addr(struct netif *);
91
92//DSR called from the low level driver.Signals the input_thread
93void
94eth_drv_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
95{
96  struct eth_drv_sc *sc = (struct eth_drv_sc *) data;
97  sc->state |= ETH_DRV_NEEDS_DELIVERY;
98  lwip_dsr_stuff();     
99}
100
101err_t ecosif_init(struct netif *netif);
102
103// This function is called during system initialization to register a
104// network interface with the system.
105static void
106eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr)
107{
108  struct netif *netif = &sc->sc_arpcom.ac_if;
109 
110  netif->state = sc;
111  ecosif_init(netif);
112 
113  // enaddr == 0 -> hardware init was incomplete (no ESA)
114  if (enaddr != 0) {
115    // Set up hardware address
116    memcpy(netif->hwaddr, enaddr, ETHER_ADDR_LEN);
117    // Perform any hardware initialization
118    (sc->funs->start) (sc, (unsigned char *) &netif->hwaddr, 0);
119  }
120#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
121// Set up interfaces so debug environment can share this device
122    {
123        void *dbg = CYGACC_CALL_IF_DBG_DATA();
124        if (!dbg) {
125            CYGACC_CALL_IF_DBG_DATA_SET((void *)sc);
126        }
127    }
128#endif
129
130}
131
132//
133// Control whether any special locking needs to take place if we intend to
134// cooperate with a ROM monitor (e.g. RedBoot) using this hardware. 
135//
136#if defined(CYGSEM_HAL_USE_ROM_MONITOR) && \
137    defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) && \
138   !defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)
139
140// Indicate that special locking precautions are warranted.
141#define _LOCK_WITH_ROM_MONITOR
142
143// This defines the [well known] channel that RedBoot will use when it is
144// using the network hardware for the debug channel.
145#define RedBoot_TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
146
147#endif
148
149//
150// Send a packet of data to the hardware
151//
152
153static void
154eth_drv_send(struct netif *netif, struct pbuf *p)
155{
156  struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
157  struct eth_drv_sc *sc = netif->state;
158  int sg_len = 0;
159  struct pbuf *q;
160
161#ifdef _LOCK_WITH_ROM_MONITOR
162    bool need_lock = false;
163    int debug_chan;
164#endif
165
166  while (!(sc->funs->can_send) (sc)); 
167
168  for (q = p; q != NULL; q = q->next) {
169    sg_list[sg_len].buf = (CYG_ADDRESS) q->payload;
170    sg_list[sg_len++].len = q->len;
171  }
172#ifdef _LOCK_WITH_ROM_MONITOR
173  debug_chan = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
174  if (debug_chan == RedBoot_TCP_CHANNEL) {
175    need_lock = true;
176    cyg_drv_dsr_lock();
177  }
178#endif // _LOCK_WITH_ROM_MONITOR
179
180  (sc->funs->send) (sc, sg_list, sg_len, p->tot_len,
181                    (CYG_ADDRWORD) p);
182
183#ifdef _LOCK_WITH_ROM_MONITOR
184  // Unlock the driver & hardware.  It can once again be safely shared.
185  if (need_lock) {
186    cyg_drv_dsr_unlock();
187  }
188#endif // _LOCK_WITH_ROM_MONITOR
189
190}
191
192//
193// This function is called from the hardware driver when an output operation
194// has completed - i.e. the packet has been sent.
195//
196static void
197eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRWORD key, int status)
198{
199#if 0   
200  struct pbuf *p = (struct pbuf *)key;
201  struct netif *netif = &sc->sc_arpcom.ac_if;
202
203  CYGARC_HAL_SAVE_GP();
204  CYGARC_HAL_RESTORE_GP();
205#endif 
206}
207
208static void ecosif_input(struct netif *netif, struct pbuf* pbuf);
209
210#define MAX_ETH_MSG 1540
211//
212// This function is called from a hardware driver to indicate that an input
213// packet has arrived.  The routine will set up appropriate network resources
214// to hold the data and call back into the driver to retrieve the data.
215//
216static void
217eth_drv_recv(struct eth_drv_sc *sc, int total_len)
218{
219  struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
220  struct netif *netif = &sc->sc_arpcom.ac_if;
221
222  struct pbuf *p, *q;
223
224  int sg_len = 0;
225  CYGARC_HAL_SAVE_GP();
226
227  if ((total_len > MAX_ETH_MSG) || (total_len < 0)) {
228    total_len = MAX_ETH_MSG;
229  }
230
231  p = pbuf_alloc(PBUF_RAW, total_len, PBUF_POOL);
232
233  if (p == NULL) {
234    LWIP_DEBUGF(0, ("ecosif_input: low_level_input returned NULL\n"));
235    return;
236  }
237
238  for (q = p; q != NULL; q = q->next) {
239    sg_list[sg_len].buf = (CYG_ADDRESS) q->payload;
240    sg_list[sg_len++].len = q->len;
241  }
242  (sc->funs->recv) (sc, sg_list, sg_len);
243  ecosif_input(netif, p);
244  CYGARC_HAL_RESTORE_GP();
245}
246
247
248#define IFNAME0 'e'
249#define IFNAME1 't'
250
251
252
253//
254// low_level_output():
255//
256// Should do the actual transmission of the packet. The packet is
257// contained in the pbuf that is passed to the function. This pbuf
258// might be chained.We pass the data down to the eCos hw independent
259// ethernet driver
260//
261
262static err_t
263low_level_output(struct netif *netif, struct pbuf *p)
264{
265  eth_drv_send(netif, p);
266  return ERR_OK;
267}
268
269//
270// ecosif_output():
271//
272// This function is called by the TCP/IP stack when an IP packet
273// should be sent. It calls the function called low_level_output() to
274// do the actual transmission of the packet.
275//
276//
277static err_t
278ecosif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
279{
280
281  p = etharp_output(netif, ipaddr, p);
282  if (p) {
283    low_level_output(netif, p);
284    p = NULL;
285  }
286  return ERR_OK;
287}
288
289
290
291//
292// ecosif_input():
293// This function is called when the eCos hw independent driver
294// has some data to pass up to lwIP.It does it through ecosif_input.
295//
296static void
297ecosif_input(struct netif *netif, struct pbuf *p)
298{
299  struct eth_hdr *ethhdr;
300 
301  ethhdr = p->payload;
302
303  switch (htons(ethhdr->type)) {
304  case ETHTYPE_IP:
305    LWIP_DEBUGF(0, ("ecosif_input: IP packet\n"));
306    etharp_ip_input(netif, p);
307    pbuf_header(p, -14);
308    netif->input(p, netif);
309    break;
310  case ETHTYPE_ARP:
311    LWIP_DEBUGF(0, ("ecosif_input: ARP packet\n"));
312    etharp_arp_input(netif, (struct eth_addr *) &netif->hwaddr, p);
313    break;
314  default:
315    pbuf_free(p);
316    break;
317  }
318
319}
320
321err_t
322ecosif_init(struct netif *netif)
323{
324  netif->name[0] = IFNAME0;
325  netif->name[1] = IFNAME1;
326  netif->hwaddr_len = 6;
327  netif->output = ecosif_output;
328  netif->linkoutput = low_level_output;
329  netif->mtu = 1500;
330  lwip_set_addr(netif);
331  return ERR_OK;
332}
Note: See TracBrowser for help on using the repository browser.