⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eth_drv.c

📁 移植到WLIT项目的redboot源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////      ecos/eth_drv.c////      Hardware independent ethernet driver////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####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#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 <eth_drv.h>#include <netdev.h>// ------------------------------------------------------------------------#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// ------------------------------------------------------------------------static int  eth_drv_ioctl(struct ifnet *, u_long, caddr_t);static void eth_drv_send(struct ifnet *);extern int net_debug;  // FIXME// 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;    // Set up hardware address    bcopy(enaddr, &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);    // Initialize ifnet structure    bcopy((void *)sc->dev_name, ifp->if_xname, IFNAMSIZ);    ifp->if_softc = sc;    ifp->if_start = eth_drv_send;    ifp->if_ioctl = eth_drv_ioctl;    ifp->if_flags =        IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;    sc->state = 0;    // Attach the interface    if_attach(ifp);    ether_ifattach(ifp);#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG// Set up interfaces so debug environment can share this device    {        void *dbg = CYGACC_CALL_IF_DBG_DATA();        if (!dbg) {            CYGACC_CALL_IF_DBG_DATA_SET((void *)sc);        }    }#endif}//// This [internal] function will be called to stop activity on an interface.//static voideth_drv_stop(struct eth_drv_sc *sc){    (sc->funs->stop)(sc);    sc->state &= ~ETH_DRV_STATE_ACTIVE;}//// This [internal] function will be called to start activity on an interface.//static voideth_drv_start(struct eth_drv_sc *sc){    struct ifnet *ifp = &sc->sc_arpcom.ac_if;    // Perform any hardware initialization    (sc->funs->start)(sc, (unsigned char *)&sc->sc_arpcom.ac_enaddr, 0);    // Set 'running' flag, and clear output active flag.    ifp->if_flags |= IFF_RUNNING;    ifp->if_flags &= ~IFF_OACTIVE;    sc->state |= ETH_DRV_STATE_ACTIVE;    eth_drv_send(ifp);  // Try and start up transmit}//// This function supports "I/O control" operations on an interface.//static int  eth_drv_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data){    struct eth_drv_sc *sc = ifp->if_softc;    struct ifaddr *ifa = (struct ifaddr *) data;    struct ifreq *ifr = (struct ifreq *)data;    int     s, error = 0;    s = splnet();    if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {        splx(s);        return error;    }    switch (cmd) {    case SIOCSIFADDR:        ifp->if_flags |= IFF_UP;        switch (ifa->ifa_addr->sa_family) {#ifdef INET        case AF_INET:            eth_drv_start(sc);            arp_ifinit(&sc->sc_arpcom, ifa);            break;#endif        default:            eth_drv_start(sc);            break;        }        break;    case SIOCGIFHWADDR:        // Get hardware (MAC) address        ifr->ifr_hwaddr.sa_family = AF_INET;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -