📄 eth_drv.c
字号:
//==========================================================================//// src/net/eth_drv.c//// Hardware independent ethernet driver////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002, 2003 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-01-10// Purpose: Hardware independent ethernet driver// Description: // ////####DESCRIPTIONEND####////==========================================================================// High-level ethernet driver#include <sys/param.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#include <net/netisr.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#endif#ifndef NBPFILTER#define NBPFILTER 0#endif#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endif#include <cyg/infra/cyg_ass.h>#include <cyg/hal/drv_api.h>#include <pkgconf/hal.h>#include <cyg/hal/hal_if.h>#include <pkgconf/io_eth_drivers.h> // module configury; SIMULATED_FAILURES#include <pkgconf/net.h> // CYGPKG_NET_FAST_THREAD_TICKLE_DEVS?#include <cyg/io/eth/eth_drv.h>#include <cyg/io/eth/netdev.h>#ifndef min#define min( _x_, _y_ ) ((_x_) < (_y_) ? (_x_) : (_y_))#endif// ------------------------------------------------------------------------#ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES#define noLOG_RANDOM 32 // so you can tell this is really being random#ifdef LOG_RANDOMstatic struct { unsigned int *which; unsigned int random; unsigned int r100;} random_log[LOG_RANDOM];static int random_index = 0;#endifstatic unsigned intrandomize( unsigned int *p ){ unsigned int r100; HAL_CLOCK_READ( &r100 ); r100 ^= *p; *p = (r100 * 1103515245) + 12345; r100 &= 127; if ( r100 >= 100 ) // spread the overflow around evenly r100 = 4 * (r100 - 100); if ( r100 >= 100 ) // and again - (125,126,127=>100,104,108) r100 = 12 * (r100 - 100); // =>(0,48,96)#ifdef LOG_RANDOM random_log[random_index].which = p; random_log[random_index].random = *p; random_log[random_index].r100 = r100; random_index++; random_index &= (LOG_RANDOM-1);#endif return r100;}#define SIMULATE_FAIL_SEND 1#define SIMULATE_FAIL_RECV 2#define SIMULATE_FAIL_CORRUPT 3static struct simulated_failure_state { struct eth_drv_sc *sc; unsigned int r_tx_fail; unsigned int r_rx_fail; unsigned int r_rx_corrupt; cyg_tick_count_t droptime; cyg_tick_count_t passtime;} simulated_failure_states[2] = {{0},{0}};static intsimulate_fail( struct eth_drv_sc *sc, int which ){ struct simulated_failure_state *s; for ( s = &simulated_failure_states[0]; s < &simulated_failure_states[2]; s++ ) { if ( 0 == s->sc ) { s->sc = sc; s->r_tx_fail = (unsigned int)sc; s->r_rx_fail = (unsigned int)sc ^ 0x01234567; s->r_rx_corrupt = (unsigned int)sc ^ 0xdeadbeef; s->droptime = 0; s->passtime = 0; } if ( sc == s->sc ) break; } if ( &simulated_failure_states[2] == s ) { CYG_FAIL( "No free slot in simulated_failure_states[]" ); return 1; // always fail }#ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_LINE_CUT // Regardless of the question, we say "yes" during the period of // unpluggedness... { cyg_tick_count_t now = cyg_current_time(); if ( now > s->droptime && 0 == s->passtime ) { // [initial condition] s->droptime = 0; // go into a passing phase (void)randomize( &s->r_tx_fail ); (void)randomize( &s->r_rx_fail ); (void)randomize( &s->r_rx_corrupt ); s->passtime = s->r_tx_fail + s->r_rx_fail + s->r_rx_corrupt; s->passtime &= 0x3fff; // 16k cS is up to 160S, about 2.5 minutes s->passtime += now; } else if ( now > s->passtime && 0 == s->droptime ) { s->passtime = 0; // go into a dropping phase (void)randomize( &s->r_tx_fail ); (void)randomize( &s->r_rx_fail ); (void)randomize( &s->r_rx_corrupt ); s->droptime = s->r_tx_fail + s->r_rx_fail + s->r_rx_corrupt; s->droptime &= 0x0fff; // 4k cS is up to 40S, about 1/2 a minute s->droptime += now; } if ( now < s->droptime ) return 1; // Say "no" }#endif switch ( which ) {#ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_TX case SIMULATE_FAIL_SEND: { unsigned int z = randomize( &s->r_tx_fail ); return z < CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_TX; }#endif#ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_RX case SIMULATE_FAIL_RECV: { unsigned int z = randomize( &s->r_rx_fail ); return z < CYGPKG_IO_ETH_DRIVERS_SIMULATE_DROP_RX; }#endif#ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATE_CORRUPT_RX case SIMULATE_FAIL_CORRUPT: { unsigned int z = randomize( &s->r_rx_corrupt ); return z < CYGPKG_IO_ETH_DRIVERS_SIMULATE_CORRUPT_RX; }#endif default: // do nothing - for when options above are not enabled. } return 0;}#define noLOG_CORRUPTION 32 // so you can tell this is really being random#ifdef LOG_CORRUPTIONstatic struct { int len; int thislen; int off; unsigned char xor; unsigned char idx;} corruption_log[LOG_CORRUPTION];static int corruption_index = 0;#endifstatic voidsimulate_fail_corrupt_sglist( struct eth_drv_sg *sg_list, int sg_len ){ unsigned int z, len, i, off; HAL_CLOCK_READ( &z ); z += simulated_failure_states[0].r_rx_corrupt; z += simulated_failure_states[1].r_rx_corrupt; CYG_ASSERT( MAX_ETH_DRV_SG >= sg_len, "sg_len overflow in corrupt" ); for ( i = 0, len = 0; i < sg_len && sg_list[i].buf && sg_list[i].len; i++ ) len =+ sg_list[i].len; CYG_ASSERT( 1500 >= len, "sg...len > ether MTU" ); if ( 14 >= len ) // normal ether header return; off = z & 2047; // next (2^N-1) > MTU while ( off > len ) off -= len; for ( i = 0; i < sg_len && sg_list[i].buf && sg_list[i].len; i++ ) { if ( off < sg_list[i].len ) { // corrupt this one unsigned char *p = (unsigned char *)sg_list[i].buf; p[off] ^= (0xff & (z >> 11));#ifdef LOG_CORRUPTION corruption_log[corruption_index].len = len; corruption_log[corruption_index].thislen = sg_list[i].len; corruption_log[corruption_index].off = off; corruption_log[corruption_index].xor = (0xff & (z >> 11)); corruption_log[corruption_index].idx = i; corruption_index++; corruption_index &= (LOG_CORRUPTION-1);#endif return; } off -= sg_list[i].len; } CYG_FAIL( "Didn't corrupt anything" );}#endif // CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES// ------------------------------------------------------------------------#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT#include <cyg/hal/hal_if.h>// Use with care! Local variable defined!#define START_CONSOLE() \{ /* NEW BLOCK */ \ int _cur_console = \ CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); \ { \ int i; \ if ( CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET, \ "info_console_force", &i, \ CYGNUM_FLASH_CFG_TYPE_CONFIG_BOOL ) ) { \ if ( i ) { \ if ( CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET, \ "info_console_number", &i, \ CYGNUM_FLASH_CFG_TYPE_CONFIG_INT ) ){ \ /* Then i is the console to force it to: */ \ CYGACC_CALL_IF_SET_CONSOLE_COMM( i ); \ } \ } \ } \ }#define END_CONSOLE() \ CYGACC_CALL_IF_SET_CONSOLE_COMM(_cur_console); \} /* END BLOCK */#else#define START_CONSOLE()#define END_CONSOLE()#endif// ------------------------------------------------------------------------#ifdef CYGPKG_NET_FREEBSD_STACKextern char *_ioctl_name(u_long cmd);typedef void void_fun(void *);#endifstatic int eth_drv_ioctl(struct ifnet *, u_long, caddr_t);static void eth_drv_send(struct ifnet *);static void eth_drv_start(struct eth_drv_sc *sc);#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG int cyg_io_eth_net_debug = CYGDBG_IO_ETH_DRIVERS_DEBUG_VERBOSITY;#endif// Interfaces exported to driversstatic void eth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr);static void eth_drv_recv(struct eth_drv_sc *sc, int total_len);static void eth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRESS key, int status);struct eth_drv_funs eth_drv_funs = {eth_drv_init, eth_drv_recv, eth_drv_tx_done};//// This function is called during system initialization to register a// network interface with the system.//static voideth_drv_init(struct eth_drv_sc *sc, unsigned char *enaddr){ struct ifnet *ifp = &sc->sc_arpcom.ac_if;#ifdef CYGPKG_NET_FREEBSD_STACK int unit; char *np, *xp;#endif // Set up hardware address if (NULL != enaddr) bcopy(enaddr, &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); // Initialize ifnet structure
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -