1 //==========================================================================
5 // Hardware independent ethernet driver
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 // Copyright (C) 2002, 2003 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors: gthomas
47 // Purpose: Hardware independent ethernet driver
51 //####DESCRIPTIONEND####
53 //==========================================================================
55 // High-level ethernet driver
57 #include <sys/param.h>
58 #include <sys/errno.h>
59 #include <sys/ioctl.h>
61 #include <sys/socket.h>
64 #include <net/if_dl.h>
65 #include <net/if_types.h>
66 #include <net/netisr.h>
69 #include <netinet/in.h>
70 #include <netinet/in_systm.h>
71 #include <netinet/in_var.h>
72 #include <netinet/ip.h>
73 #include <netinet/if_ether.h>
82 #include <net/bpfdesc.h>
85 #include <cyg/infra/cyg_ass.h>
86 #include <cyg/hal/drv_api.h>
87 #include <pkgconf/hal.h>
88 #include <cyg/hal/hal_if.h>
89 #include <pkgconf/io_eth_drivers.h> // module configury; SIMULATED_FAILURES
90 #include <pkgconf/net.h> // CYGPKG_NET_FAST_THREAD_TICKLE_DEVS?
92 #include <cyg/io/eth/eth_drv.h>
93 #include <cyg/io/eth/netdev.h>
96 #define min( _x_, _y_ ) ((_x_) < (_y_) ? (_x_) : (_y_))
99 // ------------------------------------------------------------------------
100 #ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES
102 #define noLOG_RANDOM 32 // so you can tell this is really being random
108 } random_log[LOG_RANDOM];
110 static int random_index = 0;
114 randomize( unsigned int *p )
117 HAL_CLOCK_READ( &r100 );
119 *p = (r100 * 1103515245) + 12345;
121 if ( r100 >= 100 ) // spread the overflow around evenly
122 r100 = 4 * (r100 - 100);
123 if ( r100 >= 100 ) // and again - (125,126,127=>100,104,108)
124 r100 = 12 * (r100 - 100); // =>(0,48,96)
126 random_log[random_index].which = p;
127 random_log[random_index].random = *p;
128 random_log[random_index].r100 = r100;
130 random_index &= (LOG_RANDOM-1);
135 #define SIMULATE_FAIL_SEND 1
136 #define SIMULATE_FAIL_RECV 2
137 #define SIMULATE_FAIL_CORRUPT 3
139 static struct simulated_failure_state {
140 struct eth_drv_sc *sc;
141 unsigned int r_tx_fail;
142 unsigned int r_rx_fail;
143 unsigned int r_rx_corrupt;
144 cyg_tick_count_t droptime;
145 cyg_tick_count_t passtime;
146 } simulated_failure_states[2] = {{0},{0}};
149 simulate_fail( struct eth_drv_sc *sc, int which )
151 struct simulated_failure_state *s;
153 for ( s = &simulated_failure_states[0]; s < &simulated_failure_states[2];
157 s->r_tx_fail = (unsigned int)sc;
158 s->r_rx_fail = (unsigned int)sc ^ 0x01234567;
159 s->r_rx_corrupt = (unsigned int)sc ^ 0xdeadbeef;
166 if ( &simulated_failure_states[2] == s ) {
167 CYG_FAIL( "No free slot in simulated_failure_states[]" );
168 return 1; // always fail
171 #ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_LINE_CUT
172 // Regardless of the question, we say "yes" during the period of
175 cyg_tick_count_t now = cyg_current_time();
176 if ( now > s->droptime && 0 == s->passtime ) { // [initial condition]
177 s->droptime = 0; // go into a passing phase
178 (void)randomize( &s->r_tx_fail );
179 (void)randomize( &s->r_rx_fail );
180 (void)randomize( &s->r_rx_corrupt );
181 s->passtime = s->r_tx_fail + s->r_rx_fail + s->r_rx_corrupt;
182 s->passtime &= 0x3fff; // 16k cS is up to 160S, about 2.5 minutes
185 else if ( now > s->passtime && 0 == s->droptime ) {
186 s->passtime = 0; // go into a dropping phase
187 (void)randomize( &s->r_tx_fail );
188 (void)randomize( &s->r_rx_fail );
189 (void)randomize( &s->r_rx_corrupt );
190 s->droptime = s->r_tx_fail + s->r_rx_fail + s->r_rx_corrupt;
191 s->droptime &= 0x0fff; // 4k cS is up to 40S, about 1/2 a minute
195 if ( now < s->droptime )
196 return 1; // Say "no"
201 #ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_TX
202 case SIMULATE_FAIL_SEND: {
203 unsigned int z = randomize( &s->r_tx_fail );
204 return z < CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_TX;
207 #ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_RX
208 case SIMULATE_FAIL_RECV: {
209 unsigned int z = randomize( &s->r_rx_fail );
210 return z < CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_RX;
213 #ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_CORRUPT_RX
214 case SIMULATE_FAIL_CORRUPT: {
215 unsigned int z = randomize( &s->r_rx_corrupt );
216 return z < CYGPKG_IO_ETH_DRIVERS_SIMULATE_CORRUPT_RX;
220 // do nothing - for when options above are not enabled.
225 #define noLOG_CORRUPTION 32 // so you can tell this is really being random
226 #ifdef LOG_CORRUPTION
233 } corruption_log[LOG_CORRUPTION];
235 static int corruption_index = 0;
239 simulate_fail_corrupt_sglist( struct eth_drv_sg *sg_list, int sg_len )
241 unsigned int z, len, i, off;
242 HAL_CLOCK_READ( &z );
243 z += simulated_failure_states[0].r_rx_corrupt;
244 z += simulated_failure_states[1].r_rx_corrupt;
246 CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow in corrupt" );
248 for ( i = 0, len = 0; i < sg_len && sg_list[i].buf && sg_list[i].len; i++ )
249 len =+ sg_list[i].len;
251 CYG_ASSERT( 1500 >= len, "sg...len > ether MTU" );
252 if ( 14 >= len ) // normal ether header
255 off = z & 2047; // next (2^N-1) > MTU
259 for ( i = 0; i < sg_len && sg_list[i].buf && sg_list[i].len; i++ ) {
260 if ( off < sg_list[i].len ) { // corrupt this one
261 unsigned char *p = (unsigned char *)sg_list[i].buf;
262 p[off] ^= (0xff & (z >> 11));
263 #ifdef LOG_CORRUPTION
264 corruption_log[corruption_index].len = len;
265 corruption_log[corruption_index].thislen = sg_list[i].len;
266 corruption_log[corruption_index].off = off;
267 corruption_log[corruption_index].xor = (0xff & (z >> 11));
268 corruption_log[corruption_index].idx = i;
270 corruption_index &= (LOG_CORRUPTION-1);
274 off -= sg_list[i].len;
276 CYG_FAIL( "Didn't corrupt anything" );
279 #endif // CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES
280 // ------------------------------------------------------------------------
282 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
284 #include <cyg/hal/hal_if.h>
286 // Use with care! Local variable defined!
287 #define START_CONSOLE() \
290 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); \
293 if ( CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET, \
294 "info_console_force", &i, \
295 CYGNUM_FLASH_CFG_TYPE_CONFIG_BOOL ) ) { \
297 if ( CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET, \
298 "info_console_number", &i, \
299 CYGNUM_FLASH_CFG_TYPE_CONFIG_INT ) ){ \
300 /* Then i is the console to force it to: */ \
301 CYGACC_CALL_IF_SET_CONSOLE_COMM( i ); \
307 #define END_CONSOLE() \
308 CYGACC_CALL_IF_SET_CONSOLE_COMM(_cur_console); \
312 #define START_CONSOLE()
313 #define END_CONSOLE()
315 // ------------------------------------------------------------------------
317 #ifdef CYGPKG_NET_FREEBSD_STACK
318 extern char *_ioctl_name(u_long cmd);
319 typedef void void_fun(void *);
322 static int eth_drv_ioctl(struct ifnet *, u_long, caddr_t);
323 static void eth_drv_send(struct ifnet *);
324 static void eth_drv_start(struct eth_drv_sc *sc);
326 #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
327 int cyg_io_eth_net_debug = CYGDBG_IO_ETH_DRIVERS_DEBUG_VERBOSITY;
330 // Interfaces exported to drivers
332 static void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr);
333 static void eth_drv_recv(struct eth_drv_sc *sc, int total_len);
334 static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRESS key, int status);
336 struct eth_drv_funs eth_drv_funs = {eth_drv_init, eth_drv_recv, eth_drv_tx_done};
339 // This function is called during system initialization to register a
340 // network interface with the system.
343 eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr)
345 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
346 #ifdef CYGPKG_NET_FREEBSD_STACK
351 // Set up hardware address
353 bcopy(enaddr, &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
355 // Initialize ifnet structure
357 ifp->if_start = eth_drv_send;
358 ifp->if_ioctl = eth_drv_ioctl;
359 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
360 #ifdef IFF_NOTRAILERS
361 ifp->if_flags |= IFF_NOTRAILERS;
363 #ifdef CYGPKG_NET_FREEBSD_STACK
364 ifp->if_name = xp = ifp->if_xname;
365 np = (char *)sc->dev_name;
367 while (*np && !((*np >= '0') && (*np <= '9'))) *xp++ = *np++;
371 unit = (unit * 10) + (*np++ - '0');
375 ifp->if_init = (void_fun *)eth_drv_start;
376 ifp->if_output = ether_output;
378 bcopy((void *)sc->dev_name, ifp->if_xname, IFNAMSIZ);
382 // Attach the interface
383 #ifdef CYGPKG_NET_FREEBSD_STACK
384 ether_ifattach(ifp, 0);
390 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
391 // Set up interfaces so debug environment can share this device
393 void *dbg = CYGACC_CALL_IF_DBG_DATA();
395 CYGACC_CALL_IF_DBG_DATA_SET((void *)sc);
402 // This [internal] function will be called to stop activity on an interface.
405 eth_drv_stop(struct eth_drv_sc *sc)
407 (sc->funs->stop)(sc);
408 sc->state &= ~ETH_DRV_STATE_ACTIVE;
412 // This [internal] function will be called to start activity on an interface.
415 eth_drv_start(struct eth_drv_sc *sc)
417 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
419 // Perform any hardware initialization
420 (sc->funs->start)(sc, (unsigned char *)&sc->sc_arpcom.ac_enaddr, 0);
421 #ifdef CYGPKG_NET_FREEBSD_STACK
422 // resend multicast addresses if present
423 if(ifp->if_multiaddrs.lh_first && ifp->if_ioctl) {
425 ifp->if_ioctl(ifp, SIOCADDMULTI, 0);
429 // Set 'running' flag, and clear output active flag.
430 ifp->if_flags |= IFF_RUNNING;
431 ifp->if_flags &= ~IFF_OACTIVE;
432 sc->state |= ETH_DRV_STATE_ACTIVE;
433 eth_drv_send(ifp); // Try and start up transmit
437 // This function supports "I/O control" operations on an interface.
440 eth_drv_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
442 struct eth_drv_sc *sc = ifp->if_softc;
443 #ifndef CYGPKG_NET_FREEBSD_STACK
444 struct ifaddr *ifa = (struct ifaddr *) data;
446 struct ifreq *ifr = (struct ifreq *)data;
450 #ifdef CYGPKG_NET_FREEBSD_STACK
451 log(LOG_IOCTL, "%s: cmd: %s, data:\n", __FUNCTION__, _ioctl_name(cmd));
452 log_dump(LOG_IOCTL, data, 32);
458 #ifdef CYGPKG_NET_FREEBSD_STACK
459 if ((error = ether_ioctl(ifp, cmd, data)) > 0) {
461 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
470 #ifndef CYGPKG_NET_FREEBSD_STACK // Now in if_ethersubr.c
471 ifp->if_flags |= IFF_UP;
473 switch (ifa->ifa_addr->sa_family) {
477 arp_ifinit(&sc->sc_arpcom, ifa);
484 #endif // CYGPKG_NET_FREEBSD_STACK
488 // Get hardware (MAC) address
489 ifr->ifr_hwaddr.sa_family = AF_INET;
490 bcopy(&sc->sc_arpcom.ac_enaddr, &ifr->ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
494 // Set hardware (MAC) address
495 bcopy(&ifr->ifr_hwaddr.sa_data, &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
496 if ((sc->funs->control)(sc, ETH_DRV_SET_MAC_ADDRESS,
497 &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN)) {
504 #ifdef SIOCGIFSTATSUD
507 // Get interface statistics:
508 if ((sc->funs->control)(sc, (cmd == SIOCGIFSTATS)
509 ? ETH_DRV_GET_IF_STATS
510 : ETH_DRV_GET_IF_STATS_UD,
515 #endif // SIOCGIFSTATS
518 if ((ifp->if_flags & IFF_UP) == 0 &&
519 (ifp->if_flags & IFF_RUNNING) != 0) {
521 * If interface is marked down and it is running, then
525 ifp->if_flags &= ~IFF_RUNNING;
527 if ((ifp->if_flags & IFF_UP) != 0 &&
528 (ifp->if_flags & IFF_RUNNING) == 0) {
530 * If interface is marked up and it is stopped, then
536 * Reset the interface to pick up changes in any other
537 * flags that affect hardware registers.
544 #ifdef CYGPKG_NET_FREEBSD_STACK
548 struct ifmultiaddr *ifma;
549 struct eth_drv_mc_list mc_list;
550 int mode = (ifp->if_flags & IFF_ALLMULTI) ? ETH_DRV_SET_MC_ALL :
554 log(LOG_ADDR, "%s Multi\n",(cmd == SIOCADDMULTI) ? "Add" : "Del");
557 LIST_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) {
558 if (ifma->ifma_addr->sa_family != AF_LINK) {
562 log_dump(LOG_ADDR, LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 6);
564 if ((LLADDR((struct sockaddr_dl *)ifma->ifma_addr)[0] & 0x01) == 0) {
566 log(LOG_ADDR, "** Not a multicast address - ignored\n");
570 if (mc_list.len < ETH_DRV_MAX_MC) {
571 bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
572 mc_list.addrs[mc_list.len], ETHER_ADDR_LEN);
575 mode = ETH_DRV_SET_MC_ALL;
578 // Note: drivers may behave like IFF_ALLMULTI if the list is
579 // more than their hardware can handle, e.g. some can only handle 1.
580 if ((sc->funs->control)(sc, mode, &mc_list, sizeof(mc_list))) {
581 diag_printf( "[%s] Warning: Driver can't set multi-cast mode\n",
599 // Control whether any special locking needs to take place if we intend to
600 // cooperate with a ROM monitor (e.g. RedBoot) using this hardware.
602 #if defined(CYGSEM_HAL_USE_ROM_MONITOR) && \
603 defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) && \
604 !defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)
606 // Indicate that special locking precautions are warranted.
607 #define _LOCK_WITH_ROM_MONITOR
609 // This defines the [well known] channel that RedBoot will use when it is
610 // using the network hardware for the debug channel.
611 #define RedBoot_TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
613 // Define this if you ever need to call 'diag_printf()' from interrupt level
614 // code (ISR) and the debug channel might be using the network hardware. If
615 // this is not the case, then disabling interrupts here is over-kill.
616 //#define _LOCK_USING_INTERRUPTS
620 // This routine is called to start transmitting if there is data
624 eth_drv_send(struct ifnet *ifp)
626 struct eth_drv_sc *sc = ifp->if_softc;
627 #if MAX_ETH_DRV_SG > 64
628 static // Avoid large stack requirements
630 struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
635 #ifdef _LOCK_WITH_ROM_MONITOR
636 #ifdef _LOCK_USING_INTERRUPTS
639 bool need_lock = false;
641 #endif // _LOCK_WITH_ROM_MONITOR
643 // This is now only called from network threads, so no guarding is
644 // required; locking is in place via the splfoo() mechanism already.
646 if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) {
650 // If nothing on the queue, no need to bother hardware
651 if (IF_IS_EMPTY(&ifp->if_snd)) {
655 while ((sc->funs->can_send)(sc) > 0) {
656 IF_DEQUEUE(&ifp->if_snd, m0);
661 #ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES
662 if ( simulate_fail( sc, SIMULATE_FAIL_SEND ) ) {
663 // must free the mbufs
665 continue; // next packet to send
669 #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
670 if (cyg_io_eth_net_debug) {
672 diag_printf("Sending %d bytes\n", m0->m_pkthdr.len);
677 /* We need to use m->m_pkthdr.len, so require the header */
678 if ((m0->m_flags & M_PKTHDR) == 0)
679 panic("eth_drv_send: no header mbuf");
682 /* Tap off here if there is a BPF listener. */
684 bpf_mtap(ifp->if_bpf, m0);
687 // Extract data pointers (don't actually move data here)
688 sg_len = 0; total_len = 0;
689 for (m = m0; m ; m = m->m_next) {
690 data = mtod(m, u_char *);
693 sg_list[sg_len].buf = (CYG_ADDRESS)data;
694 sg_list[sg_len].len = len;
697 #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
698 if (cyg_io_eth_net_debug) {
700 diag_printf("xmit %d bytes at %p sg[%d]\n", len, data, sg_len);
701 if ( cyg_io_eth_net_debug > 1)
702 diag_dump_buf(data, len);
706 if ( MAX_ETH_DRV_SG < sg_len ) {
707 #ifdef CYGPKG_IO_ETH_DRIVERS_WARN_NO_MBUFS
710 for (m1 = m0; m1 ; m1 = m1->m_next) needed++;
712 diag_printf("too many mbufs to tx, %d > %d, need %d\n",
713 sg_len, MAX_ETH_DRV_SG, needed );
717 break; // drop it on the floor
721 #ifdef _LOCK_WITH_ROM_MONITOR
722 // Firm lock on this portion of the driver. Since we are about to
723 // start messing with the actual hardware, it is imperative that the
724 // current thread not loose control of the CPU at this time. Otherwise,
725 // the hardware could be left in an unusable state. This caution is
726 // only warranted if there is a possibility of some other thread trying
727 // to use the hardware simultaneously. The network stack would prevent
728 // this implicitly since all accesses are controlled by the "splX()"
729 // locks, but if there is a ROM monitor, such as RedBoot, also using
730 // the hardware, all bets are off.
732 // Note: these operations can be avoided if it were well known that
733 // RedBoot was not using the network hardware for diagnostic I/O. This
734 // can be inferred by checking which I/O channel RedBoot is currently
736 debug_chan = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
737 if (debug_chan == RedBoot_TCP_CHANNEL) {
739 #ifdef _LOCK_USING_INTERRUPTS
740 HAL_DISABLE_INTERRUPTS(ints);
744 #endif // _LOCK_WITH_ROM_MONITOR
746 // Tell hardware to send this packet
748 (sc->funs->send)(sc, sg_list, sg_len, total_len, (unsigned long)m0);
750 #ifdef _LOCK_WITH_ROM_MONITOR
751 // Unlock the driver & hardware. It can once again be safely shared.
753 cyg_drv_dsr_unlock();
754 #ifdef _LOCK_USING_INTERRUPTS
755 HAL_RESTORE_INTERRUPTS(ints);
758 #endif // _LOCK_WITH_ROM_MONITOR
759 #undef _LOCK_WITH_ROM_MONITOR
764 // This function is called from the hardware driver when an output operation
765 // has completed - i.e. the packet has been sent.
767 static struct mbuf *mbuf_key;
770 eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRESS key, int status)
772 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
773 struct mbuf *m0 = (struct mbuf *)key;
774 CYGARC_HAL_SAVE_GP();
776 // Check for errors here (via 'status')
780 // Guard against a NULL return - can be caused by race conditions in
781 // the driver, this is the neatest fixup:
786 // Start another if possible
788 CYGARC_HAL_RESTORE_GP();
792 // This function is called from a hardware driver to indicate that an input
793 // packet has arrived. The routine will set up appropriate network resources
794 // (mbuf's) to hold the data and call back into the driver to retrieve the data.
797 eth_drv_recv(struct eth_drv_sc *sc, int total_len)
799 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
800 struct ether_header _eh, *eh=&_eh;
801 struct mbuf *top, **mp, *m;
804 #if MAX_ETH_DRV_SG > 64
805 static // Avoid large stack requirements
807 struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];
810 if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) {
811 return; // Interface not up, ignore this request
814 CYG_ASSERT( 0 != total_len, "total_len is zero!" );
815 CYG_ASSERT( 0 <= total_len, "total_len is negative!" );
816 CYG_ASSERT( sizeof( struct ether_header ) <= total_len,
817 "No ether header here!" );
819 if ( total_len < sizeof( struct ether_header ) )
820 // Our arithmetic below would go wrong
823 CYGARC_HAL_SAVE_GP(); // This is down here to make matching restore neat
825 /* Pull packet off interface. */
826 MGETHDR(m, M_DONTWAIT, MT_DATA);
828 #ifdef CYGPKG_IO_ETH_DRIVERS_WARN_NO_MBUFS
830 diag_printf("warning: eth_recv out of MBUFs\n");
831 #ifdef CYGDBG_NET_SHOW_MBUFS
832 cyg_net_show_mbufs();
839 // Unload ethernet header separately so IP/UDP/TCP headers are aligned
840 sg_list[0].buf = (CYG_ADDRESS)eh;
841 sg_list[0].len = sizeof(*eh);
844 // Compute total length (minus ethernet header)
845 total_len -= sizeof(*eh);
852 m->m_pkthdr.rcvif = ifp;
853 m->m_pkthdr.len = total_len;
855 sg_list[sg_len].buf = (CYG_ADDRESS)0;
856 sg_list[sg_len].len = total_len;
861 while (total_len > 0) {
863 MGET(m, M_DONTWAIT, MT_DATA);
866 #ifdef CYGPKG_IO_ETH_DRIVERS_WARN_NO_MBUFS
868 diag_printf("out of MBUFs [2]");
869 #ifdef CYGDBG_NET_SHOW_MBUFS
870 cyg_net_show_mbufs();
874 sg_list[sg_len].buf = (CYG_ADDRESS)0;
875 sg_list[sg_len].len = total_len;
882 if (total_len >= MINCLSIZE) {
883 MCLGET(m, M_DONTWAIT);
884 if ((m->m_flags & M_EXT) == 0) {
887 #ifdef CYGPKG_IO_ETH_DRIVERS_WARN_NO_MBUFS
889 diag_printf("warning: eth_recv out of MBUFs\n");
890 #ifdef CYGDBG_NET_SHOW_MBUFS
891 cyg_net_show_mbufs();
895 sg_list[sg_len].buf = (CYG_ADDRESS)0;
896 sg_list[sg_len].len = total_len;
903 m->m_len = mlen = min(total_len, mlen);
905 data = mtod(m, caddr_t);
906 sg_list[sg_len].buf = (CYG_ADDRESS)data;
907 sg_list[sg_len].len = mlen;
913 // Ask hardware to unload buffers
914 (sc->funs->recv)(sc, sg_list, sg_len);
916 #ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES
917 if ( simulate_fail( sc, SIMULATE_FAIL_RECV ) ) {
918 // toss the packet - note that some hardware gets
919 // fussy if the packet isn't "unloaded", thus we
920 // have to wait until now to throw it away
928 if ( simulate_fail( sc, SIMULATE_FAIL_CORRUPT ) ) {
930 simulate_fail_corrupt_sglist( sg_list, sg_len );
934 #ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
935 if (cyg_io_eth_net_debug) {
938 for (i = 0; i < sg_len; i++) {
939 if (sg_list[i].buf) {
940 diag_printf("rx %d bytes at %x sg[%d]\n", sg_list[i].len, sg_list[i].buf, i);
941 if ( cyg_io_eth_net_debug > 1 )
942 diag_dump_buf((void *)sg_list[i].buf, sg_list[i].len);
956 #error FIXME - Need mbuf with ethernet header attached
958 * Check if there's a BPF listener on this interface.
959 * If so, hand off the raw packet to bpf.
962 bpf_mtap(ifp->if_bpf, m);
965 // Push data into protocol stacks
966 ether_input(ifp, eh, m);
968 CYGARC_HAL_RESTORE_GP();
972 // ------------------------------------------------------------------------
973 // DSR to schedule network delivery thread
975 extern void ecos_synch_eth_drv_dsr(void); // from ecos/timeout.c in net stack
978 eth_drv_dsr(cyg_vector_t vector,
982 struct eth_drv_sc *sc = (struct eth_drv_sc *)data;
984 #ifdef CYGDBG_USE_ASSERTS
985 // then check that this really is a "sc"
987 cyg_netdevtab_entry_t *t;
988 for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++)
989 if ( ((struct eth_drv_sc *)t->device_instance) == sc )
991 CYG_ASSERT( t != &__NETDEVTAB_END__, "eth_drv_dsr: Failed to find sc in NETDEVTAB" );
993 #endif // Checking code
995 sc->state |= ETH_DRV_NEEDS_DELIVERY;
997 ecos_synch_eth_drv_dsr(); // [request] run delivery function for this dev
1000 // This is called from the delivery thread, to do just that:
1001 void eth_drv_run_deliveries( void )
1003 cyg_netdevtab_entry_t *t;
1004 for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
1005 struct eth_drv_sc *sc = (struct eth_drv_sc *)t->device_instance;
1006 if ( ETH_DRV_NEEDS_DELIVERY & sc->state ) {
1007 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
1008 cyg_bool was_ctrlc_int;
1010 sc->state &=~ETH_DRV_NEEDS_DELIVERY;
1011 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
1012 was_ctrlc_int = HAL_CTRLC_CHECK((*sc->funs->int_vector)(sc), (int)sc);
1013 if (!was_ctrlc_int) // Fall through and run normal code
1015 (*sc->funs->deliver)(sc);
1020 // This is called from the delivery thread, to unstick devices if there is
1021 // no network activity.
1022 #ifdef CYGPKG_NET_FAST_THREAD_TICKLE_DEVS
1023 void eth_drv_tickle_devices( void )
1025 cyg_netdevtab_entry_t *t;
1026 for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
1027 struct eth_drv_sc *sc = (struct eth_drv_sc *)t->device_instance;
1028 if ( ETH_DRV_STATE_ACTIVE & sc->state ) {
1029 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1030 // Try to dequeue a packet for this interface, if we can. This
1031 // will call can_send() for active interfaces. It is calls to
1032 // this function from tx_done() which normally provide
1033 // continuous transmissions; otherwise we do not get control.
1034 // This call fixes that.
1035 if (!IF_IS_EMPTY(&ifp->if_snd)) {
1041 #endif // CYGPKG_NET_FAST_THREAD_TICKLE_DEVS
1043 // ------------------------------------------------------------------------
1045 #ifdef CYGPKG_IO_PCMCIA
1046 // Lookup a 'netdev' entry, assuming that it is an ethernet device.
1047 cyg_netdevtab_entry_t *
1048 eth_drv_netdev(char *name)
1050 cyg_netdevtab_entry_t *t;
1051 struct eth_drv_sc *sc;
1052 for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {
1053 sc = (struct eth_drv_sc *)t->device_instance;
1054 if (strcmp(sc->dev_name, name) == 0) {
1058 return (cyg_netdevtab_entry_t *)NULL;
1060 #endif // CYGPKG_IO_PCMCIA
1062 // EOF src/net/eth_drv.c