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

📄 eth_drv.c

📁 ecos实时嵌入式操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
        bcopy(enaddr, &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);    // Initialize ifnet structure    ifp->if_softc = sc;    ifp->if_start = eth_drv_send;    ifp->if_ioctl = eth_drv_ioctl;    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;#ifdef IFF_NOTRAILERS    ifp->if_flags |= IFF_NOTRAILERS;#endif#ifdef CYGPKG_NET_FREEBSD_STACK    ifp->if_name = xp = ifp->if_xname;    np = (char *)sc->dev_name;    unit = 0;    while (*np && !((*np >= '0') && (*np <= '9'))) *xp++ = *np++;    if (*np) {        *xp = '\0';        while (*np) {            unit = (unit * 10) + (*np++ - '0');        }        ifp->if_unit = unit;    }    ifp->if_init = (void_fun *)eth_drv_start;    ifp->if_output = ether_output;#else    bcopy((void *)sc->dev_name, ifp->if_xname, IFNAMSIZ);#endif    sc->state = 0;    // Attach the interface#ifdef CYGPKG_NET_FREEBSD_STACK    ether_ifattach(ifp, 0);#else    if_attach(ifp);    ether_ifattach(ifp);#endif#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);#ifdef CYGPKG_NET_FREEBSD_STACK    // resend multicast addresses if present    if(ifp->if_multiaddrs.lh_first && ifp->if_ioctl) {        int s = splimp();	ifp->if_ioctl(ifp, SIOCADDMULTI, 0);	splx(s);    }#endif    // 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;#ifndef CYGPKG_NET_FREEBSD_STACK    struct ifaddr *ifa = (struct ifaddr *) data;#endif    struct ifreq *ifr = (struct ifreq *)data;    int     s, error = 0;// DEBUG#ifdef CYGPKG_NET_FREEBSD_STACK    log(LOG_IOCTL, "%s: cmd: %s, data:\n", __FUNCTION__, _ioctl_name(cmd));    log_dump(LOG_IOCTL, data, 32);#endif// DEBUG    s = splnet();#ifdef CYGPKG_NET_FREEBSD_STACK    if ((error = ether_ioctl(ifp, cmd, data)) > 0) {#else    if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {#endif        splx(s);        return error;    }    switch (cmd) {    case SIOCSIFADDR:#ifndef CYGPKG_NET_FREEBSD_STACK // Now in if_ethersubr.c        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;        }#endif // CYGPKG_NET_FREEBSD_STACK        break;    case SIOCGIFHWADDR:        // Get hardware (MAC) address        ifr->ifr_hwaddr.sa_family = AF_INET;        bcopy(&sc->sc_arpcom.ac_enaddr, &ifr->ifr_hwaddr.sa_data, ETHER_ADDR_LEN);        break;    case SIOCSIFHWADDR:        // Set hardware (MAC) address        bcopy(&ifr->ifr_hwaddr.sa_data, &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);        if ((sc->funs->control)(sc, ETH_DRV_SET_MAC_ADDRESS,                                &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN)) {            error = EINVAL;        }        break;#ifdef SIOCGIFSTATS    case SIOCGIFSTATS:#ifdef SIOCGIFSTATSUD    case SIOCGIFSTATSUD:#endif        // Get interface statistics:        if ((sc->funs->control)(sc, (cmd == SIOCGIFSTATS)                                ? ETH_DRV_GET_IF_STATS                                : ETH_DRV_GET_IF_STATS_UD,                                data, 0 ) ) {            error = EINVAL;        }        break;#endif // SIOCGIFSTATS    case SIOCSIFFLAGS:        if ((ifp->if_flags & IFF_UP) == 0 &&            (ifp->if_flags & IFF_RUNNING) != 0) {            /*             * If interface is marked down and it is running, then             * stop it.             */            eth_drv_stop(sc);            ifp->if_flags &= ~IFF_RUNNING;        } else            if ((ifp->if_flags & IFF_UP) != 0 &&                (ifp->if_flags & IFF_RUNNING) == 0) {                /*                 * If interface is marked up and it is stopped, then                 * start it.                 */                eth_drv_start(sc);            } else {                /*                 * Reset the interface to pick up changes in any other                 * flags that affect hardware registers.                 */                eth_drv_stop(sc);                eth_drv_start(sc);            }        break;#ifdef CYGPKG_NET_FREEBSD_STACK    case SIOCADDMULTI:    case SIOCDELMULTI:    {	struct ifmultiaddr *ifma;        struct eth_drv_mc_list mc_list;        int mode = (ifp->if_flags & IFF_ALLMULTI) ? ETH_DRV_SET_MC_ALL :                                                    ETH_DRV_SET_MC_LIST;#ifdef DEBUG        log(LOG_ADDR, "%s Multi\n",(cmd == SIOCADDMULTI) ? "Add" : "Del");#endif        mc_list.len = 0;        LIST_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) {  	    if (ifma->ifma_addr->sa_family != AF_LINK) {	      continue;	    }#ifdef DEBUG            log_dump(LOG_ADDR, LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 6);#endif            if ((LLADDR((struct sockaddr_dl *)ifma->ifma_addr)[0] & 0x01) == 0) {#ifdef DEBUG                log(LOG_ADDR, "** Not a multicast address - ignored\n");#endif                continue;            }            if (mc_list.len < ETH_DRV_MAX_MC) {                bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),                      mc_list.addrs[mc_list.len], ETHER_ADDR_LEN);                mc_list.len++;            } else {                mode = ETH_DRV_SET_MC_ALL;            }        }        // Note: drivers may behave like IFF_ALLMULTI if the list is         // more than their hardware can handle, e.g. some can only handle 1.        if ((sc->funs->control)(sc, mode, &mc_list, sizeof(mc_list))) {            diag_printf( "[%s] Warning: Driver can't set multi-cast mode\n",                         __FUNCTION__ );            error = EINVAL;        }        break;    }#endif    default:        error = EINVAL;        break;    }    splx(s);    return (error);}//// Control whether any special locking needs to take place if we intend to// cooperate with a ROM monitor (e.g. RedBoot) using this hardware.  //#if defined(CYGSEM_HAL_USE_ROM_MONITOR) && \    defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) && \   !defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)// Indicate that special locking precautions are warranted.#define _LOCK_WITH_ROM_MONITOR// This defines the [well known] channel that RedBoot will use when it is// using the network hardware for the debug channel.#define RedBoot_TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS// Define this if you ever need to call 'diag_printf()' from interrupt level// code (ISR) and the debug channel might be using the network hardware. If// this is not the case, then disabling interrupts here is over-kill.//#define _LOCK_USING_INTERRUPTS#endif//// This routine is called to start transmitting if there is data// available.//static void eth_drv_send(struct ifnet *ifp){    struct eth_drv_sc *sc = ifp->if_softc;#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;    struct mbuf *m0, *m;    int len, total_len;    unsigned char *data;#ifdef _LOCK_WITH_ROM_MONITOR#ifdef _LOCK_USING_INTERRUPTS    cyg_uint32 ints;#endif    bool need_lock = false;    int debug_chan;#endif // _LOCK_WITH_ROM_MONITOR    // This is now only called from network threads, so no guarding is    // required; locking is in place via the splfoo() mechanism already.    if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) {         return;    }    while ((sc->funs->can_send)(sc) > 0) {        IF_DEQUEUE(&ifp->if_snd, m0);        if (m0 == 0) {            break;        }#ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES        if ( simulate_fail( sc, SIMULATE_FAIL_SEND ) ) {            // must free the mbufs            m_freem(m0);            continue; // next packet to send        }#endif#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG        if (cyg_io_eth_net_debug) {            START_CONSOLE();            diag_printf("Sending %d bytes\n", m0->m_pkthdr.len);            END_CONSOLE();        }#endif        /* We need to use m->m_pkthdr.len, so require the header */        if ((m0->m_flags & M_PKTHDR) == 0)            panic("eth_drv_send: no header mbuf");#if NBPFILTER > 0        /* Tap off here if there is a BPF listener. */        if (ifp->if_bpf)            bpf_mtap(ifp->if_bpf, m0);#endif        // Extract data pointers (don't actually move data here)        sg_len = 0;  total_len = 0;        for (m = m0; m ; m = m->m_next) {            data = mtod(m, u_char *);            len = m->m_len;            total_len += len;            sg_list[sg_len].buf = (CYG_ADDRESS)data;            sg_list[sg_len].len = len;            if ( len )                sg_len++;#ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG            if (cyg_io_eth_net_debug) {                START_CONSOLE();                diag_printf("xmit %d bytes at %x sg[%d]\n", len, data, sg_len);                if ( cyg_io_eth_net_debug > 1)                    diag_dump_buf(data, len);                END_CONSOLE();            }#endif

⌨️ 快捷键说明

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