/** * Per network device initialization * * @param dev Device to initialize * @return Zero on success */ int cvm_oct_common_init(struct ifnet *ifp) { uint8_t mac[6]; cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; if (cvm_assign_mac_address(NULL, mac) != 0) return ENXIO; ifp->if_mtu = ETHERMTU; cvm_oct_mdio_setup_device(ifp); cvm_oct_common_set_mac_address(ifp, mac); cvm_oct_common_change_mtu(ifp, ifp->if_mtu); /* * Do any last-minute board-specific initialization. */ switch (cvmx_sysinfo_get()->board_type) { #if defined(OCTEON_VENDOR_LANNER) case CVMX_BOARD_TYPE_CUST_LANNER_MR320: case CVMX_BOARD_TYPE_CUST_LANNER_MR321X: if (priv->phy_id == 16) cvm_oct_mv88e61xx_setup_device(ifp); break; #endif default: break; } device_attach(priv->dev); return 0; }
static int octm_attach(device_t dev) { struct ifnet *ifp; struct octm_softc *sc; cvmx_mixx_irhwm_t mixx_irhwm; cvmx_mixx_intena_t mixx_intena; uint64_t mac; int error; int irq; int rid; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_port = device_get_unit(dev); switch (sc->sc_port) { case 0: irq = CVMX_IRQ_MII; break; case 1: irq = CVMX_IRQ_MII1; break; default: device_printf(dev, "unsupported management port %u.\n", sc->sc_port); return (ENXIO); } /* * Set MAC address for this management port. */ if (cvm_assign_mac_address(&mac, NULL) != 0) { device_printf(dev, "unable to allocate MAC address.\n"); return (ENXIO); } cvmx_mgmt_port_set_mac(sc->sc_port, mac); /* No watermark for input ring. */ mixx_irhwm.u64 = 0; cvmx_write_csr(CVMX_MIXX_IRHWM(sc->sc_port), mixx_irhwm.u64); /* Enable input ring interrupts. */ mixx_intena.u64 = 0; mixx_intena.s.ithena = 1; cvmx_write_csr(CVMX_MIXX_INTENA(sc->sc_port), mixx_intena.u64); /* Allocate and establish interrupt. */ rid = 0; sc->sc_intr = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ, &rid, irq, irq, 1, RF_ACTIVE); if (sc->sc_intr == NULL) { device_printf(dev, "unable to allocate IRQ.\n"); return (ENXIO); } error = bus_setup_intr(sc->sc_dev, sc->sc_intr, INTR_TYPE_NET, NULL, octm_rx_intr, sc, &sc->sc_intr_cookie); if (error != 0) { device_printf(dev, "unable to setup interrupt.\n"); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_intr); return (ENXIO); } bus_describe_intr(sc->sc_dev, sc->sc_intr, sc->sc_intr_cookie, "rx"); /* XXX Possibly should enable TX interrupts. */ ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "cannot allocate ifnet.\n"); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_intr); return (ENOMEM); } if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_mtu = ETHERMTU; ifp->if_init = octm_init; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI; ifp->if_ioctl = octm_ioctl; sc->sc_ifp = ifp; sc->sc_flags = ifp->if_flags; ifmedia_init(&sc->sc_ifmedia, 0, octm_medchange, octm_medstat); ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO); ether_ifattach(ifp, (const u_int8_t *)&mac + 2); ifp->if_transmit = octm_transmit; ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities = IFCAP_VLAN_MTU; ifp->if_capenable = ifp->if_capabilities; IFQ_SET_MAXLEN(&ifp->if_snd, CVMX_MGMT_PORT_NUM_TX_BUFFERS); ifp->if_snd.ifq_drv_maxlen = CVMX_MGMT_PORT_NUM_TX_BUFFERS; IFQ_SET_READY(&ifp->if_snd); return (bus_generic_attach(dev)); }