static void octm_init(void *arg) { struct ifnet *ifp; struct octm_softc *sc; cvmx_mgmt_port_netdevice_flags_t flags; uint64_t mac; sc = arg; ifp = sc->sc_ifp; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { cvmx_mgmt_port_disable(sc->sc_port); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; } /* * NB: * MAC must be set before allmulti and promisc below, as * cvmx_mgmt_port_set_mac will always enable the CAM, and turning on * promiscuous mode only works with the CAM disabled. */ mac = 0; memcpy((u_int8_t *)&mac + 2, IF_LLADDR(ifp), 6); cvmx_mgmt_port_set_mac(sc->sc_port, mac); /* * This is done unconditionally, rather than only if sc_flags have * changed because of set_mac's effect on the CAM noted above. */ flags = 0; if ((ifp->if_flags & IFF_ALLMULTI) != 0) flags |= CVMX_IFF_ALLMULTI; if ((ifp->if_flags & IFF_PROMISC) != 0) flags |= CVMX_IFF_PROMISC; cvmx_mgmt_port_set_multicast_list(sc->sc_port, flags); /* XXX link state? */ if ((ifp->if_flags & IFF_UP) != 0) cvmx_mgmt_port_enable(sc->sc_port); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; }
static void octm_init(void *arg) { struct ifnet *ifp; struct octm_softc *sc; cvmx_mgmt_port_netdevice_flags_t flags; uint64_t mac; sc = arg; ifp = sc->sc_ifp; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { cvmx_mgmt_port_disable(sc->sc_port); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; } if (((ifp->if_flags ^ sc->sc_flags) & (IFF_ALLMULTI | IFF_MULTICAST | IFF_PROMISC)) != 0) { flags = 0; if ((ifp->if_flags & IFF_ALLMULTI) != 0) flags |= CVMX_IFF_ALLMULTI; if ((ifp->if_flags & IFF_PROMISC) != 0) flags |= CVMX_IFF_PROMISC; cvmx_mgmt_port_set_multicast_list(sc->sc_port, flags); } mac = 0; memcpy((u_int8_t *)&mac + 2, IF_LLADDR(ifp), 6); cvmx_mgmt_port_set_mac(sc->sc_port, mac); /* XXX link state? */ if ((ifp->if_flags & IFF_UP) != 0) cvmx_mgmt_port_enable(sc->sc_port); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; }
static int octm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct octm_softc *sc; struct ifreq *ifr; #ifdef INET struct ifaddr *ifa; #endif int error; sc = ifp->if_softc; ifr = (struct ifreq *)data; #ifdef INET ifa = (struct ifaddr *)data; #endif switch (cmd) { case SIOCSIFADDR: #ifdef INET /* * Avoid reinitialization unless it's necessary. */ if (ifa->ifa_addr->sa_family == AF_INET) { ifp->if_flags |= IFF_UP; if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) octm_init(sc); arp_ifinit(ifp, ifa); return (0); } #endif error = ether_ioctl(ifp, cmd, data); if (error != 0) return (error); return (0); case SIOCSIFFLAGS: if (ifp->if_flags == sc->sc_flags) return (0); if ((ifp->if_flags & IFF_UP) != 0) { octm_init(sc); } else { if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { cvmx_mgmt_port_disable(sc->sc_port); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; } } sc->sc_flags = ifp->if_flags; return (0); case SIOCSIFCAP: /* * Just change the capabilities in software, currently none * require reprogramming hardware, they just toggle whether we * make use of already-present facilities in software. */ ifp->if_capenable = ifr->ifr_reqcap; return (0); case SIOCSIFMTU: cvmx_mgmt_port_set_max_packet_size(sc->sc_port, ifr->ifr_mtu + ifp->if_data.ifi_hdrlen); return (0); case SIOCSIFMEDIA: case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd); if (error != 0) return (error); return (0); default: error = ether_ioctl(ifp, cmd, data); if (error != 0) return (error); return (0); } }