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

📄 eth_drv.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
                START_CONSOLE();                diag_printf("too many mbufs to tx, %d > %d, need %d\n",                             sg_len, MAX_ETH_DRV_SG, needed );                END_CONSOLE();#endif                sg_len = 0;                break; // drop it on the floor            }        }#ifdef _LOCK_WITH_ROM_MONITOR        // Firm lock on this portion of the driver.  Since we are about to        // start messing with the actual hardware, it is imperative that the        // current thread not loose control of the CPU at this time.  Otherwise,        // the hardware could be left in an unusable state.  This caution is        // only warranted if there is a possibility of some other thread trying        // to use the hardware simultaneously.  The network stack would prevent        // this implicitly since all accesses are controlled by the "splX()"        // locks, but if there is a ROM monitor, such as RedBoot, also using        // the hardware, all bets are off.        // Note: these operations can be avoided if it were well known that        // RedBoot was not using the network hardware for diagnostic I/O.  This        // can be inferred by checking which I/O channel RedBoot is currently        // hooked to.        debug_chan = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);        if (debug_chan == RedBoot_TCP_CHANNEL) {            need_lock = true;#ifdef _LOCK_USING_INTERRUPTS            HAL_DISABLE_INTERRUPTS(ints);#endif            cyg_drv_dsr_lock();        }#endif // _LOCK_WITH_ROM_MONITOR        // Tell hardware to send this packet        if ( sg_len )            (sc->funs->send)(sc, sg_list, sg_len, total_len, (unsigned long)m0);#ifdef _LOCK_WITH_ROM_MONITOR        // Unlock the driver & hardware.  It can once again be safely shared.        if (need_lock) {            cyg_drv_dsr_unlock();#ifdef _LOCK_USING_INTERRUPTS            HAL_RESTORE_INTERRUPTS(ints);#endif        }#endif // _LOCK_WITH_ROM_MONITOR#undef _LOCK_WITH_ROM_MONITOR    }}//// This function is called from the hardware driver when an output operation// has completed - i.e. the packet has been sent.//static struct mbuf *mbuf_key;static voideth_drv_tx_done(struct eth_drv_sc *sc, CYG_ADDRESS key, int status){    struct ifnet *ifp = &sc->sc_arpcom.ac_if;    struct mbuf *m0 = (struct mbuf *)key;    CYGARC_HAL_SAVE_GP();    // Check for errors here (via 'status')    ifp->if_opackets++;    // Done with packet    // Guard against a NULL return - can be caused by race conditions in    // the driver, this is the neatest fixup:    if (m0) {         mbuf_key = m0;        m_freem(m0);    }    // Start another if possible    eth_drv_send(ifp);    CYGARC_HAL_RESTORE_GP();}//// This function is called from a hardware driver to indicate that an input// packet has arrived.  The routine will set up appropriate network resources// (mbuf's) to hold the data and call back into the driver to retrieve the data.//static voideth_drv_recv(struct eth_drv_sc *sc, int total_len){    struct ifnet *ifp = &sc->sc_arpcom.ac_if;    struct ether_header _eh, *eh=&_eh;    struct mbuf *top, **mp, *m;    int mlen;    unsigned char *data;#if MAX_ETH_DRV_SG > 64    static  // Avoid large stack requirements#endif    struct eth_drv_sg sg_list[MAX_ETH_DRV_SG];    int sg_len;    if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) {        return;  // Interface not up, ignore this request    }    CYG_ASSERT( 0 != total_len, "total_len is zero!" );    CYG_ASSERT( 0 <= total_len, "total_len is negative!" );    CYG_ASSERT( sizeof( struct ether_header ) <= total_len,                "No ether header here!" );    if ( total_len < sizeof( struct ether_header ) )        // Our arithmetic below would go wrong        return;    CYGARC_HAL_SAVE_GP();  // This is down here to make matching restore neat    /* Pull packet off interface. */    MGETHDR(m, M_DONTWAIT, MT_DATA);    if (m == 0) {#ifdef CYGPKG_IO_ETH_DRIVERS_WARN_NO_MBUFS        START_CONSOLE();        diag_printf("warning: eth_recv out of MBUFs\n");#ifdef CYGDBG_NET_SHOW_MBUFS                cyg_net_show_mbufs();#endif        END_CONSOLE();#endif    }    // Set up buffers    // Unload ethernet header separately so IP/UDP/TCP headers are aligned    sg_list[0].buf = (CYG_ADDRESS)eh;    sg_list[0].len = sizeof(*eh);    sg_len = 1;    // Compute total length (minus ethernet header)    total_len -= sizeof(*eh);    top = 0;    mlen = MHLEN;    mp = &top;    if (m) {        m->m_pkthdr.rcvif = ifp;        m->m_pkthdr.len = total_len;    } else {        sg_list[sg_len].buf = (CYG_ADDRESS)0;        sg_list[sg_len].len = total_len;        sg_len++;        total_len = 0;    }    while (total_len > 0) {        if (top) {            MGET(m, M_DONTWAIT, MT_DATA);            if (m == 0) {                m_freem(top);#ifdef CYGPKG_IO_ETH_DRIVERS_WARN_NO_MBUFS                START_CONSOLE();                diag_printf("out of MBUFs [2]");#ifdef CYGDBG_NET_SHOW_MBUFS                                cyg_net_show_mbufs();#endif                END_CONSOLE();#endif                sg_list[sg_len].buf = (CYG_ADDRESS)0;                sg_list[sg_len].len = total_len;                sg_len++;                top = 0;                break;            }            mlen = MLEN;        }        if (total_len >= MINCLSIZE) {            MCLGET(m, M_DONTWAIT);            if ((m->m_flags & M_EXT) == 0) {                m_freem(top);                m_free(m);#ifdef CYGPKG_IO_ETH_DRIVERS_WARN_NO_MBUFS                START_CONSOLE();                diag_printf("warning: eth_recv out of MBUFs\n");#ifdef CYGDBG_NET_SHOW_MBUFS                                cyg_net_show_mbufs();#endif                END_CONSOLE();#endif                sg_list[sg_len].buf = (CYG_ADDRESS)0;                sg_list[sg_len].len = total_len;                sg_len++;                top = 0;                break;            }            mlen = MCLBYTES;        }        m->m_len = mlen = min(total_len, mlen);        total_len -= mlen;        data = mtod(m, caddr_t);        sg_list[sg_len].buf = (CYG_ADDRESS)data;        sg_list[sg_len].len = mlen;        sg_len++;        *mp = m;        mp = &m->m_next;    } // endwhile    // Ask hardware to unload buffers    (sc->funs->recv)(sc, sg_list, sg_len);#ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES    if ( simulate_fail( sc, SIMULATE_FAIL_RECV ) ) {        // toss the packet - note that some hardware gets        // fussy if the packet isn't "unloaded", thus we        // have to wait until now to throw it away        if (top) {	    m_free(top);        }        ifp->if_ierrors++;        return;    }    if ( simulate_fail( sc, SIMULATE_FAIL_CORRUPT ) ) {        // Corrupt the data        simulate_fail_corrupt_sglist( sg_list, sg_len );    }#endif#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG    if (cyg_io_eth_net_debug) {        int i;        START_CONSOLE();        for (i = 0;  i < sg_len;  i++) {            if (sg_list[i].buf) {                diag_printf("rx %d bytes at %x sg[%d]\n", sg_list[i].len, sg_list[i].buf, i);                if ( cyg_io_eth_net_debug > 1 )                    diag_dump_buf((void *)sg_list[i].buf, sg_list[i].len);            }        }        END_CONSOLE();    }#endif    m = top;    if (m == 0) {        ifp->if_ierrors++;    }    else {        ifp->if_ipackets++;#if NBPFILTER > 0#error FIXME - Need mbuf with ethernet header attached        /*         * Check if there's a BPF listener on this interface.         * If so, hand off the raw packet to bpf.         */        if (ifp->if_bpf)            bpf_mtap(ifp->if_bpf, m);#endif        // Push data into protocol stacks        ether_input(ifp, eh, m);    }    CYGARC_HAL_RESTORE_GP();}// ------------------------------------------------------------------------// DSR to schedule network delivery threadextern void ecos_synch_eth_drv_dsr(void); // from ecos/timeout.c in net stackvoideth_drv_dsr(cyg_vector_t vector,            cyg_ucount32 count,            cyg_addrword_t data){    struct eth_drv_sc *sc = (struct eth_drv_sc *)data;#ifdef CYGDBG_USE_ASSERTS    // then check that this really is a "sc"    {        cyg_netdevtab_entry_t *t;        for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++)            if ( ((struct eth_drv_sc *)t->device_instance) == sc )                break; // found it        CYG_ASSERT( t != &__NETDEVTAB_END__, "eth_drv_dsr: Failed to find sc in NETDEVTAB" );    }#endif // Checking code    sc->state |= ETH_DRV_NEEDS_DELIVERY;    ecos_synch_eth_drv_dsr(); // [request] run delivery function for this dev}// This is called from the delivery thread, to do just that:void eth_drv_run_deliveries( void ){    cyg_netdevtab_entry_t *t;    for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {        struct eth_drv_sc *sc = (struct eth_drv_sc *)t->device_instance;        if ( ETH_DRV_NEEDS_DELIVERY & sc->state ) {#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)            cyg_bool was_ctrlc_int;#endif            sc->state &=~ETH_DRV_NEEDS_DELIVERY;#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)            was_ctrlc_int = HAL_CTRLC_CHECK((*sc->funs->int_vector)(sc), (int)sc);            if (!was_ctrlc_int) // Fall through and run normal code#endif            (*sc->funs->deliver)(sc);        }    }}// This is called from the delivery thread, to unstick devices if there is// no network activity.#ifdef CYGPKG_NET_FAST_THREAD_TICKLE_DEVSvoid eth_drv_tickle_devices( void ){    cyg_netdevtab_entry_t *t;    for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {        struct eth_drv_sc *sc = (struct eth_drv_sc *)t->device_instance;        if ( ETH_DRV_STATE_ACTIVE & sc->state ) {            struct ifnet *ifp = &sc->sc_arpcom.ac_if;            // Try to dequeue a packet for this interface, if we can.  This            // will call can_send() for active interfaces.  It is calls to            // this function from tx_done() which normally provide            // continuous transmissions; otherwise we do not get control.            // This call fixes that.            if (!IF_IS_EMPTY(&ifp->if_snd)) {                eth_drv_send(ifp);            }        }    }}#endif // CYGPKG_NET_FAST_THREAD_TICKLE_DEVS// ------------------------------------------------------------------------#ifdef CYGPKG_IO_PCMCIA// Lookup a 'netdev' entry, assuming that it is an ethernet device.cyg_netdevtab_entry_t * eth_drv_netdev(char *name){    cyg_netdevtab_entry_t *t;    struct eth_drv_sc *sc;    for (t = &__NETDEVTAB__[0]; t != &__NETDEVTAB_END__; t++) {        sc = (struct eth_drv_sc *)t->device_instance;        if (strcmp(sc->dev_name, name) == 0) {            return t;        }    }    return (cyg_netdevtab_entry_t *)NULL;}#endif // CYGPKG_IO_PCMCIA// EOF src/net/eth_drv.c

⌨️ 快捷键说明

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