int octeon_eth_mediainit(struct octeon_eth_softc *sc) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct mii_softc *child; sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = octeon_eth_mii_readreg; sc->sc_mii.mii_writereg = octeon_eth_mii_writereg; sc->sc_mii.mii_statchg = octeon_eth_mii_statchg; ifmedia_init(&sc->sc_mii.mii_media, 0, octeon_eth_mediachange, octeon_eth_mediastatus); mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, sc->sc_phy_addr, MII_OFFSET_ANY, MIIF_DOPAUSE); child = LIST_FIRST(&sc->sc_mii.mii_phys); if (child == NULL) { /* No PHY attached. */ ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); } else { ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); } return 0; }
void nep_attach(struct device *parent, struct device *self, void *aux) { struct nep_softc *sc = (struct nep_softc *)self; struct pci_attach_args *pa = aux; struct ifnet *ifp = &sc->sc_ac.ac_if; struct mii_data *mii = &sc->sc_mii; pcireg_t memtype; uint64_t cfg; sc->sc_dmat = pa->pa_dmat; memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT; if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems, 0)) { printf(": can't map registers\n"); return; } sc->sc_port = pa->pa_function; #ifdef __sparc64__ if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address", sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN) <= 0) myetheraddr(sc->sc_ac.ac_enaddr); #endif printf(", address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr)); cfg = nep_read(sc, MIF_CONFIG); cfg &= ~MIF_CONFIG_INDIRECT_MODE; nep_write(sc, MIF_CONFIG, cfg); strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof(ifp->if_xname)); ifp->if_softc = sc; ifp->if_ioctl = nep_ioctl; mii->mii_ifp = ifp; mii->mii_readreg = nep_mii_readreg; mii->mii_writereg = nep_mii_writereg; mii->mii_statchg = nep_mii_statchg; ifmedia_init(&mii->mii_media, 0, nep_mediachange, nep_mediastatus); mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, sc->sc_port, 0); ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); timeout_set(&sc->sc_tick_ch, nep_tick, sc); }
void che_attach(struct device *parent, struct device *self, void *aux) { struct cheg_softc *gsc = (struct cheg_softc *)parent; struct che_softc *sc = (struct che_softc *)self; struct che_attach_args *caa = aux; struct ifnet *ifp; sc->sc_cheg = gsc; sc->sc_port = caa->caa_port; bcopy(caa->caa_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); printf(": address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr)); ifp = &sc->sc_ac.ac_if; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = che_ioctl; ifp->if_start = che_start; ifp->if_watchdog = che_watchdog; ifp->if_hardmtu = MCLBYTES - ETHER_HDR_LEN - ETHER_CRC_LEN; /* XXX */ strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); IFQ_SET_MAXLEN(&ifp->if_snd, 400); IFQ_SET_READY(&ifp->if_snd); ifmedia_init(&sc->sc_mii.mii_media, 0, che_ifmedia_upd, che_ifmedia_sts); sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = che_miibus_ind_readreg; sc->sc_mii.mii_writereg = che_miibus_ind_writereg; sc->sc_mii.mii_statchg = che_miibus_statchg; mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, MIIF_DOPAUSE | MIIF_HAVEFIBER); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { printf("%s: no PHY found!\n", sc->sc_dev.dv_xname); ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); return; }
void ax88190_media_init(struct dp8390_softc *sc) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = ax88190_mii_readreg; sc->sc_mii.mii_writereg = ax88190_mii_writereg; sc->sc_mii.mii_statchg = ax88190_mii_statchg; ifmedia_init(&sc->sc_mii.mii_media, 0, dp8390_mediachange, dp8390_mediastatus); mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); }
static void bce_attach(device_t parent, device_t self, void *aux) { struct bce_softc *sc = device_private(self); struct pci_attach_args *pa = aux; const struct bce_product *bp; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; uint32_t command; pcireg_t memtype, pmode; bus_addr_t memaddr; bus_size_t memsize; void *kva; bus_dma_segment_t seg; int error, i, pmreg, rseg; struct ifnet *ifp; char intrbuf[PCI_INTRSTR_LEN]; sc->bce_dev = self; bp = bce_lookup(pa); KASSERT(bp != NULL); sc->bce_pa = *pa; /* BCM440x can only address 30 bits (1GB) */ if (bus_dmatag_subregion(pa->pa_dmat, 0, (1 << 30), &(sc->bce_dmatag), BUS_DMA_NOWAIT) != 0) { aprint_error_dev(self, "WARNING: failed to restrict dma range," " falling back to parent bus dma range\n"); sc->bce_dmatag = pa->pa_dmat; } aprint_naive(": Ethernet controller\n"); aprint_normal(": %s\n", bp->bp_name); /* * Map control/status registers. */ command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); command |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); if (!(command & PCI_COMMAND_MEM_ENABLE)) { aprint_error_dev(self, "failed to enable memory mapping!\n"); return; } memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCE_PCI_BAR0); switch (memtype) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: if (pci_mapreg_map(pa, BCE_PCI_BAR0, memtype, 0, &sc->bce_btag, &sc->bce_bhandle, &memaddr, &memsize) == 0) break; default: aprint_error_dev(self, "unable to find mem space\n"); return; } /* Get it out of power save mode if needed. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, NULL)) { pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3; if (pmode == 3) { /* * The card has lost all configuration data in * this state, so punt. */ aprint_error_dev(self, "unable to wake up from power state D3\n"); return; } if (pmode != 0) { aprint_normal_dev(self, "waking up from power state D%d\n", pmode); pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0); } } if (pci_intr_map(pa, &ih)) { aprint_error_dev(self, "couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); sc->bce_intrhand = pci_intr_establish(pc, ih, IPL_NET, bce_intr, sc); if (sc->bce_intrhand == NULL) { aprint_error_dev(self, "couldn't establish interrupt\n"); if (intrstr != NULL) aprint_error(" at %s", intrstr); aprint_error("\n"); return; } aprint_normal_dev(self, "interrupting at %s\n", intrstr); /* reset the chip */ bce_reset(sc); /* * Allocate DMA-safe memory for ring descriptors. * The receive, and transmit rings can not share the same * 4k space, however both are allocated at once here. */ /* * XXX PAGE_SIZE is wasteful; we only need 1KB + 1KB, but * due to the limition above. ?? */ if ((error = bus_dmamem_alloc(sc->bce_dmatag, 2 * PAGE_SIZE, PAGE_SIZE, 2 * PAGE_SIZE, &seg, 1, &rseg, BUS_DMA_NOWAIT))) { aprint_error_dev(self, "unable to alloc space for ring descriptors, error = %d\n", error); return; } /* map ring space to kernel */ if ((error = bus_dmamem_map(sc->bce_dmatag, &seg, rseg, 2 * PAGE_SIZE, &kva, BUS_DMA_NOWAIT))) { aprint_error_dev(self, "unable to map DMA buffers, error = %d\n", error); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* create a dma map for the ring */ if ((error = bus_dmamap_create(sc->bce_dmatag, 2 * PAGE_SIZE, 1, 2 * PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->bce_ring_map))) { aprint_error_dev(self, "unable to create ring DMA map, error = %d\n", error); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* connect the ring space to the dma map */ if (bus_dmamap_load(sc->bce_dmatag, sc->bce_ring_map, kva, 2 * PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) { bus_dmamap_destroy(sc->bce_dmatag, sc->bce_ring_map); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* save the ring space in softc */ sc->bce_rx_ring = (struct bce_dma_slot *) kva; sc->bce_tx_ring = (struct bce_dma_slot *) ((char *)kva + PAGE_SIZE); /* Create the transmit buffer DMA maps. */ for (i = 0; i < BCE_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, BCE_NTXFRAGS, MCLBYTES, 0, 0, &sc->bce_cdata.bce_tx_map[i])) != 0) { aprint_error_dev(self, "unable to create tx DMA map, error = %d\n", error); } sc->bce_cdata.bce_tx_chain[i] = NULL; } /* Create the receive buffer DMA maps. */ for (i = 0; i < BCE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->bce_cdata.bce_rx_map[i])) != 0) { aprint_error_dev(self, "unable to create rx DMA map, error = %d\n", error); } sc->bce_cdata.bce_rx_chain[i] = NULL; } /* Set up ifnet structure */ ifp = &sc->ethercom.ec_if; strcpy(ifp->if_xname, device_xname(self)); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = bce_ioctl; ifp->if_start = bce_start; ifp->if_watchdog = bce_watchdog; ifp->if_init = bce_init; ifp->if_stop = bce_stop; IFQ_SET_READY(&ifp->if_snd); /* Initialize our media structures and probe the MII. */ sc->bce_mii.mii_ifp = ifp; sc->bce_mii.mii_readreg = bce_mii_read; sc->bce_mii.mii_writereg = bce_mii_write; sc->bce_mii.mii_statchg = bce_statchg; sc->ethercom.ec_mii = &sc->bce_mii; ifmedia_init(&sc->bce_mii.mii_media, 0, ether_mediachange, ether_mediastatus); mii_attach(sc->bce_dev, &sc->bce_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, MIIF_FORCEANEG|MIIF_DOPAUSE); if (LIST_FIRST(&sc->bce_mii.mii_phys) == NULL) { ifmedia_add(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE); } else ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_AUTO); /* get the phy */ sc->bce_phy = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_PHY) & 0x1f; /* * Enable activity led. * XXX This should be in a phy driver, but not currently. */ bce_mii_write(sc->bce_dev, 1, 26, /* MAGIC */ bce_mii_read(sc->bce_dev, 1, 26) & 0x7fff); /* MAGIC */ /* enable traffic meter led mode */ bce_mii_write(sc->bce_dev, 1, 27, /* MAGIC */ bce_mii_read(sc->bce_dev, 1, 27) | (1 << 6)); /* MAGIC */ /* Attach the interface */ if_attach(ifp); sc->enaddr[0] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET0); sc->enaddr[1] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET1); sc->enaddr[2] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET2); sc->enaddr[3] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET3); sc->enaddr[4] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET4); sc->enaddr[5] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_MAGIC_ENET5); aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(sc->enaddr)); ether_ifattach(ifp, sc->enaddr); rnd_attach_source(&sc->rnd_source, device_xname(self), RND_TYPE_NET, 0); callout_init(&sc->bce_timeout, 0); if (pmf_device_register(self, NULL, bce_resume)) pmf_class_network_register(self, ifp); else aprint_error_dev(self, "couldn't establish power handler\n"); }
void beattach(device_t parent, device_t self, void *aux) { struct sbus_attach_args *sa = aux; struct qec_softc *qec = device_private(parent); struct be_softc *sc = device_private(self); struct ifnet *ifp = &sc->sc_ethercom.ec_if; struct mii_data *mii = &sc->sc_mii; struct mii_softc *child; int node = sa->sa_node; bus_dma_tag_t dmatag = sa->sa_dmatag; bus_dma_segment_t seg; bus_size_t size; int instance; int rseg, error; uint32_t v; sc->sc_dev = self; if (sa->sa_nreg < 3) { printf(": only %d register sets\n", sa->sa_nreg); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base), (bus_size_t)sa->sa_reg[0].oa_size, 0, &sc->sc_cr) != 0) { printf(": cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base), (bus_size_t)sa->sa_reg[1].oa_size, 0, &sc->sc_br) != 0) { printf(": cannot map registers\n"); return; } if (bus_space_map(sa->sa_bustag, (bus_addr_t)BUS_ADDR(sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base), (bus_size_t)sa->sa_reg[2].oa_size, 0, &sc->sc_tr) != 0) { printf(": cannot map registers\n"); return; } sc->sc_bustag = sa->sa_bustag; sc->sc_qec = qec; sc->sc_qr = qec->sc_regs; sc->sc_rev = prom_getpropint(node, "board-version", -1); printf(": rev %x,", sc->sc_rev); callout_init(&sc->sc_tick_ch, 0); sc->sc_channel = prom_getpropint(node, "channel#", -1); if (sc->sc_channel == -1) sc->sc_channel = 0; sc->sc_burst = prom_getpropint(node, "burst-sizes", -1); if (sc->sc_burst == -1) sc->sc_burst = qec->sc_burst; /* Clamp at parent's burst sizes */ sc->sc_burst &= qec->sc_burst; /* Establish interrupt handler */ if (sa->sa_nintr) (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, beintr, sc); prom_getether(node, sc->sc_enaddr); printf(" address %s\n", ether_sprintf(sc->sc_enaddr)); /* * Allocate descriptor ring and buffers. */ /* for now, allocate as many bufs as there are ring descriptors */ sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE; sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE; size = QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) + sc->sc_rb.rb_ntbuf * BE_PKT_BUF_SZ + sc->sc_rb.rb_nrbuf * BE_PKT_BUF_SZ; /* Get a DMA handle */ if ((error = bus_dmamap_create(dmatag, size, 1, size, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) { aprint_error_dev(self, "DMA map create error %d\n", error); return; } /* Allocate DMA buffer */ if ((error = bus_dmamem_alloc(sa->sa_dmatag, size, 0, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer alloc error %d\n", error); return; } /* Map DMA memory in CPU addressable space */ if ((error = bus_dmamem_map(sa->sa_dmatag, &seg, rseg, size, &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error_dev(self, "DMA buffer map error %d\n", error); bus_dmamem_free(sa->sa_dmatag, &seg, rseg); return; } /* Load the buffer */ if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap, sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "DMA buffer map load error %d\n", error); bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size); bus_dmamem_free(dmatag, &seg, rseg); return; } sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr; /* * Initialize our media structures and MII info. */ mii->mii_ifp = ifp; mii->mii_readreg = be_mii_readreg; mii->mii_writereg = be_mii_writereg; mii->mii_statchg = be_mii_statchg; ifmedia_init(&mii->mii_media, 0, be_ifmedia_upd, be_ifmedia_sts); /* * Initialize transceiver and determine which PHY connection to use. */ be_mii_sync(sc); v = bus_space_read_4(sc->sc_bustag, sc->sc_tr, BE_TRI_MGMTPAL); instance = 0; if ((v & MGMT_PAL_EXT_MDIO) != 0) { mii_attach(self, mii, 0xffffffff, BE_PHY_EXTERNAL, MII_OFFSET_ANY, 0); child = LIST_FIRST(&mii->mii_phys); if (child == NULL) { /* No PHY attached */ ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, instance), 0, NULL); ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, instance)); } else { /* * Note: we support just one PHY on the external * MII connector. */ #ifdef DIAGNOSTIC if (LIST_NEXT(child, mii_list) != NULL) { aprint_error_dev(self, "spurious MII device %s attached\n", device_xname(child->mii_dev)); } #endif if (child->mii_phy != BE_PHY_EXTERNAL || child->mii_inst > 0) { aprint_error_dev(self, "cannot accommodate MII device %s" " at phy %d, instance %d\n", device_xname(child->mii_dev), child->mii_phy, child->mii_inst); } else { sc->sc_phys[instance] = child->mii_phy; } /* * XXX - we can really do the following ONLY if the * phy indeed has the auto negotiation capability!! */ ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance)); /* Mark our current media setting */ be_pal_gate(sc, BE_PHY_EXTERNAL); instance++; } } if ((v & MGMT_PAL_INT_MDIO) != 0) { /* * The be internal phy looks vaguely like MII hardware, * but not enough to be able to use the MII device * layer. Hence, we have to take care of media selection * ourselves. */ sc->sc_mii_inst = instance; sc->sc_phys[instance] = BE_PHY_INTERNAL; /* Use `ifm_data' to store BMCR bits */ ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, instance), 0, NULL); ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, instance), BMCR_S100, NULL); ifmedia_add(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance), 0, NULL); printf("on-board transceiver at %s: 10baseT, 100baseTX, auto\n", device_xname(self)); be_mii_reset(sc, BE_PHY_INTERNAL); /* Only set default medium here if there's no external PHY */ if (instance == 0) { be_pal_gate(sc, BE_PHY_INTERNAL); ifmedia_set(&sc->sc_media, IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance)); } else be_mii_writereg(self, BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO); } memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = bestart; ifp->if_ioctl = beioctl; ifp->if_watchdog = bewatchdog; ifp->if_init = beinit; ifp->if_stop = bestop; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); /* claim 802.1q capability */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); }
/* * ae_attach: * * Attach an ae interface to the system. */ void ae_attach(device_t parent, device_t self, void *aux) { const uint8_t *enaddr; prop_data_t ea; struct ae_softc *sc = device_private(self); struct arbus_attach_args *aa = aux; struct ifnet *ifp = &sc->sc_ethercom.ec_if; int i, error; sc->sc_dev = self; callout_init(&sc->sc_tick_callout, 0); printf(": Atheros AR531X 10/100 Ethernet\n"); /* * Try to get MAC address. */ ea = prop_dictionary_get(device_properties(sc->sc_dev), "mac-address"); if (ea == NULL) { printf("%s: unable to get mac-addr property\n", device_xname(sc->sc_dev)); return; } KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); enaddr = prop_data_data_nocopy(ea); /* Announce ourselves. */ printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev), ether_sprintf(enaddr)); sc->sc_cirq = aa->aa_cirq; sc->sc_mirq = aa->aa_mirq; sc->sc_st = aa->aa_bst; sc->sc_dmat = aa->aa_dmat; SIMPLEQ_INIT(&sc->sc_txfreeq); SIMPLEQ_INIT(&sc->sc_txdirtyq); /* * Map registers. */ sc->sc_size = aa->aa_size; if ((error = bus_space_map(sc->sc_st, aa->aa_addr, sc->sc_size, 0, &sc->sc_sh)) != 0) { printf("%s: unable to map registers, error = %d\n", device_xname(sc->sc_dev), error); goto fail_0; } /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct ae_control_data), PAGE_SIZE, 0, &sc->sc_cdseg, 1, &sc->sc_cdnseg, 0)) != 0) { printf("%s: unable to allocate control data, error = %d\n", device_xname(sc->sc_dev), error); goto fail_1; } if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg, sizeof(struct ae_control_data), (void **)&sc->sc_control_data, BUS_DMA_COHERENT)) != 0) { printf("%s: unable to map control data, error = %d\n", device_xname(sc->sc_dev), error); goto fail_2; } if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct ae_control_data), 1, sizeof(struct ae_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { printf("%s: unable to create control data DMA map, " "error = %d\n", device_xname(sc->sc_dev), error); goto fail_3; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct ae_control_data), NULL, 0)) != 0) { printf("%s: unable to load control data DMA map, error = %d\n", device_xname(sc->sc_dev), error); goto fail_4; } /* * Create the transmit buffer DMA maps. */ for (i = 0; i < AE_TXQUEUELEN; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, AE_NTXSEGS, MCLBYTES, 0, 0, &sc->sc_txsoft[i].txs_dmamap)) != 0) { printf("%s: unable to create tx DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); goto fail_5; } } /* * Create the receive buffer DMA maps. */ for (i = 0; i < AE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { printf("%s: unable to create rx DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); goto fail_6; } sc->sc_rxsoft[i].rxs_mbuf = NULL; } /* * Reset the chip to a known state. */ ae_reset(sc); /* * From this point forward, the attachment cannot fail. A failure * before this point releases all resources that may have been * allocated. */ sc->sc_flags |= AE_ATTACHED; /* * Initialize our media structures. This may probe the MII, if * present. */ sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = ae_mii_readreg; sc->sc_mii.mii_writereg = ae_mii_writereg; sc->sc_mii.mii_statchg = ae_mii_statchg; sc->sc_ethercom.ec_mii = &sc->sc_mii; ifmedia_init(&sc->sc_mii.mii_media, 0, ether_mediachange, ether_mediastatus); mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); sc->sc_tick = ae_mii_tick; strcpy(ifp->if_xname, device_xname(sc->sc_dev)); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; sc->sc_if_flags = ifp->if_flags; ifp->if_ioctl = ae_ioctl; ifp->if_start = ae_start; ifp->if_watchdog = ae_watchdog; ifp->if_init = ae_init; ifp->if_stop = ae_stop; IFQ_SET_READY(&ifp->if_snd); /* * We can support 802.1Q VLAN-sized frames. */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; /* * Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, enaddr); ether_set_ifflags_cb(&sc->sc_ethercom, ae_ifflags_cb); rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev), RND_TYPE_NET, RND_FLAG_DEFAULT); /* * Make sure the interface is shutdown during reboot. */ sc->sc_sdhook = shutdownhook_establish(ae_shutdown, sc); if (sc->sc_sdhook == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", device_xname(sc->sc_dev)); /* * Add a suspend hook to make sure we come back up after a * resume. */ sc->sc_powerhook = powerhook_establish(device_xname(sc->sc_dev), ae_power, sc); if (sc->sc_powerhook == NULL) printf("%s: WARNING: unable to establish power hook\n", device_xname(sc->sc_dev)); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: for (i = 0; i < AE_NRXDESC; i++) { if (sc->sc_rxsoft[i].rxs_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxsoft[i].rxs_dmamap); } fail_5: for (i = 0; i < AE_TXQUEUELEN; i++) { if (sc->sc_txsoft[i].txs_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_txsoft[i].txs_dmamap); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); fail_4: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); fail_3: bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, sizeof(struct ae_control_data)); fail_2: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg); fail_1: bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_size); fail_0: return; }
int smc_attach(device_t dev) { int type, error; uint16_t val; u_char eaddr[ETHER_ADDR_LEN]; struct smc_softc *sc; struct ifnet *ifp; sc = device_get_softc(dev); error = 0; sc->smc_dev = dev; ifp = sc->smc_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { error = ENOSPC; goto done; } mtx_init(&sc->smc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); /* Set up watchdog callout. */ callout_init_mtx(&sc->smc_watchdog, &sc->smc_mtx, 0); type = SYS_RES_IOPORT; if (sc->smc_usemem) type = SYS_RES_MEMORY; sc->smc_reg_rid = 0; sc->smc_reg = bus_alloc_resource(dev, type, &sc->smc_reg_rid, 0, ~0, 16, RF_ACTIVE); if (sc->smc_reg == NULL) { error = ENXIO; goto done; } sc->smc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->smc_irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); if (sc->smc_irq == NULL) { error = ENXIO; goto done; } SMC_LOCK(sc); smc_reset(sc); SMC_UNLOCK(sc); smc_select_bank(sc, 3); val = smc_read_2(sc, REV); sc->smc_chip = (val & REV_CHIP_MASK) >> REV_CHIP_SHIFT; sc->smc_rev = (val * REV_REV_MASK) >> REV_REV_SHIFT; if (bootverbose) device_printf(dev, "revision %x\n", sc->smc_rev); callout_init_mtx(&sc->smc_mii_tick_ch, &sc->smc_mtx, CALLOUT_RETURNUNLOCKED); if (sc->smc_chip >= REV_CHIP_91110FD) { (void)mii_attach(dev, &sc->smc_miibus, ifp, smc_mii_ifmedia_upd, smc_mii_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (sc->smc_miibus != NULL) { sc->smc_mii_tick = smc_mii_tick; sc->smc_mii_mediachg = smc_mii_mediachg; sc->smc_mii_mediaioctl = smc_mii_mediaioctl; } } smc_select_bank(sc, 1); eaddr[0] = smc_read_1(sc, IAR0); eaddr[1] = smc_read_1(sc, IAR1); eaddr[2] = smc_read_1(sc, IAR2); eaddr[3] = smc_read_1(sc, IAR3); eaddr[4] = smc_read_1(sc, IAR4); eaddr[5] = smc_read_1(sc, IAR5); if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = smc_init; ifp->if_ioctl = smc_ioctl; ifp->if_start = smc_start; IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities = ifp->if_capenable = 0; #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif ether_ifattach(ifp, eaddr); /* Set up taskqueue */ TASK_INIT(&sc->smc_intr, SMC_INTR_PRIORITY, smc_task_intr, ifp); TASK_INIT(&sc->smc_rx, SMC_RX_PRIORITY, smc_task_rx, ifp); TASK_INIT(&sc->smc_tx, SMC_TX_PRIORITY, smc_task_tx, ifp); sc->smc_tq = taskqueue_create_fast("smc_taskq", M_NOWAIT, taskqueue_thread_enqueue, &sc->smc_tq); taskqueue_start_threads(&sc->smc_tq, 1, PI_NET, "%s taskq", device_get_nameunit(sc->smc_dev)); /* Mask all interrupts. */ sc->smc_mask = 0; smc_write_1(sc, MSK, 0); /* Wire up interrupt */ error = bus_setup_intr(dev, sc->smc_irq, INTR_TYPE_NET|INTR_MPSAFE, smc_intr, NULL, sc, &sc->smc_ih); if (error != 0) goto done; done: if (error != 0) smc_detach(dev); return (error); }
/* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ void rtk_attach(struct rtk_softc *sc) { device_t self = sc->sc_dev; struct ifnet *ifp; struct rtk_tx_desc *txd; uint16_t val; uint8_t eaddr[ETHER_ADDR_LEN]; int error; int i, addr_len; callout_init(&sc->rtk_tick_ch, 0); /* * Check EEPROM type 9346 or 9356. */ if (rtk_read_eeprom(sc, RTK_EE_ID, RTK_EEADDR_LEN1) == 0x8129) addr_len = RTK_EEADDR_LEN1; else addr_len = RTK_EEADDR_LEN0; /* * Get station address. */ val = rtk_read_eeprom(sc, RTK_EE_EADDR0, addr_len); eaddr[0] = val & 0xff; eaddr[1] = val >> 8; val = rtk_read_eeprom(sc, RTK_EE_EADDR1, addr_len); eaddr[2] = val & 0xff; eaddr[3] = val >> 8; val = rtk_read_eeprom(sc, RTK_EE_EADDR2, addr_len); eaddr[4] = val & 0xff; eaddr[5] = val >> 8; if ((error = bus_dmamem_alloc(sc->sc_dmat, RTK_RXBUFLEN + 16, PAGE_SIZE, 0, &sc->sc_dmaseg, 1, &sc->sc_dmanseg, BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "can't allocate recv buffer, error = %d\n", error); goto fail_0; } if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dmaseg, sc->sc_dmanseg, RTK_RXBUFLEN + 16, (void **)&sc->rtk_rx_buf, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { aprint_error_dev(self, "can't map recv buffer, error = %d\n", error); goto fail_1; } if ((error = bus_dmamap_create(sc->sc_dmat, RTK_RXBUFLEN + 16, 1, RTK_RXBUFLEN + 16, 0, BUS_DMA_NOWAIT, &sc->recv_dmamap)) != 0) { aprint_error_dev(self, "can't create recv buffer DMA map, error = %d\n", error); goto fail_2; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->recv_dmamap, sc->rtk_rx_buf, RTK_RXBUFLEN + 16, NULL, BUS_DMA_READ|BUS_DMA_NOWAIT)) != 0) { aprint_error_dev(self, "can't load recv buffer DMA map, error = %d\n", error); goto fail_3; } for (i = 0; i < RTK_TX_LIST_CNT; i++) { txd = &sc->rtk_tx_descs[i]; if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &txd->txd_dmamap)) != 0) { aprint_error_dev(self, "can't create snd buffer DMA map, error = %d\n", error); goto fail_4; } txd->txd_txaddr = RTK_TXADDR0 + (i * 4); txd->txd_txstat = RTK_TXSTAT0 + (i * 4); } SIMPLEQ_INIT(&sc->rtk_tx_free); SIMPLEQ_INIT(&sc->rtk_tx_dirty); /* * From this point forward, the attachment cannot fail. A failure * before this releases all resources thar may have been * allocated. */ sc->sc_flags |= RTK_ATTACHED; /* Reset the adapter. */ rtk_reset(sc); aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr)); ifp = &sc->ethercom.ec_if; ifp->if_softc = sc; strcpy(ifp->if_xname, device_xname(self)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = rtk_ioctl; ifp->if_start = rtk_start; ifp->if_watchdog = rtk_watchdog; ifp->if_init = rtk_init; ifp->if_stop = rtk_stop; IFQ_SET_READY(&ifp->if_snd); /* * Do ifmedia setup. */ sc->mii.mii_ifp = ifp; sc->mii.mii_readreg = rtk_phy_readreg; sc->mii.mii_writereg = rtk_phy_writereg; sc->mii.mii_statchg = rtk_phy_statchg; sc->ethercom.ec_mii = &sc->mii; ifmedia_init(&sc->mii.mii_media, IFM_IMASK, ether_mediachange, ether_mediastatus); mii_attach(self, &sc->mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); /* Choose a default media. */ if (LIST_FIRST(&sc->mii.mii_phys) == NULL) { ifmedia_add(&sc->mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&sc->mii.mii_media, IFM_ETHER|IFM_NONE); } else { ifmedia_set(&sc->mii.mii_media, IFM_ETHER|IFM_AUTO); } /* * Call MI attach routines. */ if_attach(ifp); ether_ifattach(ifp, eaddr); rnd_attach_source(&sc->rnd_source, device_xname(self), RND_TYPE_NET, RND_FLAG_DEFAULT); return; fail_4: for (i = 0; i < RTK_TX_LIST_CNT; i++) { txd = &sc->rtk_tx_descs[i]; if (txd->txd_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, txd->txd_dmamap); } fail_3: bus_dmamap_destroy(sc->sc_dmat, sc->recv_dmamap); fail_2: bus_dmamem_unmap(sc->sc_dmat, sc->rtk_rx_buf, RTK_RXBUFLEN + 16); fail_1: bus_dmamem_free(sc->sc_dmat, &sc->sc_dmaseg, sc->sc_dmanseg); fail_0: return; }
void bce_attach(struct device *parent, struct device *self, void *aux) { struct bce_softc *sc = (struct bce_softc *) self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; caddr_t kva; bus_dma_segment_t seg; int rseg; struct ifnet *ifp; pcireg_t memtype; bus_addr_t memaddr; bus_size_t memsize; int pmreg; pcireg_t pmode; int error; int i; sc->bce_pa = *pa; sc->bce_dmatag = pa->pa_dmat; /* * Map control/status registers. */ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCE_PCI_BAR0); if (pci_mapreg_map(pa, BCE_PCI_BAR0, memtype, 0, &sc->bce_btag, &sc->bce_bhandle, &memaddr, &memsize, 0)) { printf(": unable to find mem space\n"); return; } /* Get it out of power save mode if needed. */ if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) { pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3; if (pmode == 3) { /* * The card has lost all configuration data in * this state, so punt. */ printf(": unable to wake up from power state D3\n"); return; } if (pmode != 0) { printf(": waking up from power state D%d\n", pmode); pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0); } } if (pci_intr_map(pa, &ih)) { printf(": couldn't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->bce_intrhand = pci_intr_establish(pc, ih, IPL_NET, bce_intr, sc, self->dv_xname); if (sc->bce_intrhand == NULL) { printf(": couldn't establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } /* reset the chip */ bce_reset(sc); /* * Allocate DMA-safe memory for ring descriptors. * The receive, and transmit rings can not share the same * 4k space, however both are allocated at once here. */ /* * XXX PAGE_SIZE is wasteful; we only need 1KB + 1KB, but * due to the limition above. ?? */ if ((error = bus_dmamem_alloc(sc->bce_dmatag, 2 * PAGE_SIZE, PAGE_SIZE, 2 * PAGE_SIZE, &seg, 1, &rseg, BUS_DMA_NOWAIT))) { printf(": unable to alloc space for ring descriptors, " "error = %d\n", error); return; } /* map ring space to kernel */ if ((error = bus_dmamem_map(sc->bce_dmatag, &seg, rseg, 2 * PAGE_SIZE, &kva, BUS_DMA_NOWAIT))) { printf(": unable to map DMA buffers, error = %d\n", error); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* create a dma map for the ring */ if ((error = bus_dmamap_create(sc->bce_dmatag, 2 * PAGE_SIZE, 1, 2 * PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->bce_ring_map))) { printf(": unable to create ring DMA map, error = %d\n", error); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* connect the ring space to the dma map */ if (bus_dmamap_load(sc->bce_dmatag, sc->bce_ring_map, kva, 2 * PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) { printf(": unable to load ring DMA map\n"); bus_dmamap_destroy(sc->bce_dmatag, sc->bce_ring_map); bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE); bus_dmamem_free(sc->bce_dmatag, &seg, rseg); return; } /* save the ring space in softc */ sc->bce_rx_ring = (struct bce_dma_slot *) kva; sc->bce_tx_ring = (struct bce_dma_slot *) (kva + PAGE_SIZE); /* Create the transmit buffer DMA maps. */ for (i = 0; i < BCE_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, BCE_NTXFRAGS, MCLBYTES, 0, 0, &sc->bce_cdata.bce_tx_map[i])) != 0) { printf(": unable to create tx DMA map, error = %d\n", error); } sc->bce_cdata.bce_tx_chain[i] = NULL; } /* Create the receive buffer DMA maps. */ for (i = 0; i < BCE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->bce_cdata.bce_rx_map[i])) != 0) { printf(": unable to create rx DMA map, error = %d\n", error); } sc->bce_cdata.bce_rx_chain[i] = NULL; } /* Set up ifnet structure */ ifp = &sc->bce_ac.ac_if; strlcpy(ifp->if_xname, sc->bce_dev.dv_xname, IF_NAMESIZE); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = bce_ioctl; ifp->if_start = bce_start; ifp->if_watchdog = bce_watchdog; ifp->if_init = bce_init; IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities = IFCAP_VLAN_MTU; /* MAC address */ sc->bce_ac.ac_enaddr[0] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET0); sc->bce_ac.ac_enaddr[1] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET1); sc->bce_ac.ac_enaddr[2] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET2); sc->bce_ac.ac_enaddr[3] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET3); sc->bce_ac.ac_enaddr[4] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET4); sc->bce_ac.ac_enaddr[5] = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET5); printf(": %s, address %s\n", intrstr, ether_sprintf(sc->bce_ac.ac_enaddr)); /* Initialize our media structures and probe the MII. */ sc->bce_mii.mii_ifp = ifp; sc->bce_mii.mii_readreg = bce_mii_read; sc->bce_mii.mii_writereg = bce_mii_write; sc->bce_mii.mii_statchg = bce_statchg; ifmedia_init(&sc->bce_mii.mii_media, 0, bce_mediachange, bce_mediastatus); mii_attach(&sc->bce_dev, &sc->bce_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->bce_mii.mii_phys) == NULL) { ifmedia_add(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE); } else ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_AUTO); /* get the phy */ sc->bce_phy = bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_PHY) & 0x1f; /* * Enable activity led. * XXX This should be in a phy driver, but not currently. */ bce_mii_write((struct device *) sc, 1, 26, /* MAGIC */ bce_mii_read((struct device *) sc, 1, 26) & 0x7fff); /* MAGIC */ /* enable traffic meter led mode */ bce_mii_write((struct device *) sc, 1, 27, /* MAGIC */ bce_mii_read((struct device *) sc, 1, 27) | (1 << 6)); /* MAGIC */ /* Attach the interface */ if_attach(ifp); ether_ifattach(ifp); timeout_set(&sc->bce_timeout, bce_tick, sc); }
static int octe_attach(device_t dev) { struct ifnet *ifp; cvm_oct_private_t *priv; device_t child; unsigned qos; int error; priv = device_get_softc(dev); ifp = priv->ifp; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); if (priv->phy_id != -1) { if (priv->phy_device == NULL) { error = mii_attach(dev, &priv->miibus, ifp, octe_mii_medchange, octe_mii_medstat, BMSR_DEFCAPMASK, priv->phy_id, MII_OFFSET_ANY, 0); if (error != 0) device_printf(dev, "attaching PHYs failed\n"); } else { child = device_add_child(dev, priv->phy_device, -1); if (child == NULL) device_printf(dev, "missing phy %u device %s\n", priv->phy_id, priv->phy_device); } } if (priv->miibus == NULL) { ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat); ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO); } /* * XXX * We don't support programming the multicast filter right now, although it * ought to be easy enough. (Presumably it's just a matter of putting * multicast addresses in the CAM?) */ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI; ifp->if_init = octe_init; ifp->if_ioctl = octe_ioctl; priv->if_flags = ifp->if_flags; mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF); for (qos = 0; qos < 16; qos++) { mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF); IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH); } ether_ifattach(ifp, priv->mac); ifp->if_transmit = octe_transmit; ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; ifp->if_capenable = ifp->if_capabilities; ifp->if_hwassist = CSUM_TCP | CSUM_UDP; OCTE_TX_LOCK(priv); IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH); ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH; IFQ_SET_READY(&ifp->if_snd); OCTE_TX_UNLOCK(priv); return (bus_generic_attach(dev)); }
void cpsw_attach(struct device *parent, struct device *self, void *aux) { struct cpsw_softc *sc = (struct cpsw_softc *)self; struct armv7_attach_args *aa = aux; struct arpcom * const ac = &sc->sc_ac; struct ifnet * const ifp = &ac->ac_if; u_int32_t idver; int error; u_int i; timeout_set(&sc->sc_tick, cpsw_tick, sc); cpsw_get_mac_addr(sc); sc->sc_rxthih = arm_intr_establish(aa->aa_dev->irq[0] + CPSW_INTROFF_RXTH, IPL_NET, cpsw_rxthintr, sc, DEVNAME(sc)); sc->sc_rxih = arm_intr_establish(aa->aa_dev->irq[0] + CPSW_INTROFF_RX, IPL_NET, cpsw_rxintr, sc, DEVNAME(sc)); sc->sc_txih = arm_intr_establish(aa->aa_dev->irq[0] + CPSW_INTROFF_TX, IPL_NET, cpsw_txintr, sc, DEVNAME(sc)); sc->sc_miscih = arm_intr_establish(aa->aa_dev->irq[0] + CPSW_INTROFF_MISC, IPL_NET, cpsw_miscintr, sc, DEVNAME(sc)); sc->sc_bst = aa->aa_iot; sc->sc_bdt = aa->aa_dmat; error = bus_space_map(sc->sc_bst, aa->aa_dev->mem[0].addr, aa->aa_dev->mem[0].size, 0, &sc->sc_bsh); if (error) { printf("can't map registers: %d\n", error); return; } sc->sc_txdescs_pa = aa->aa_dev->mem[0].addr + CPSW_CPPI_RAM_TXDESCS_BASE; error = bus_space_subregion(sc->sc_bst, sc->sc_bsh, CPSW_CPPI_RAM_TXDESCS_BASE, CPSW_CPPI_RAM_TXDESCS_SIZE, &sc->sc_bsh_txdescs); if (error) { printf("can't subregion tx ring SRAM: %d\n", error); return; } sc->sc_rxdescs_pa = aa->aa_dev->mem[0].addr + CPSW_CPPI_RAM_RXDESCS_BASE; error = bus_space_subregion(sc->sc_bst, sc->sc_bsh, CPSW_CPPI_RAM_RXDESCS_BASE, CPSW_CPPI_RAM_RXDESCS_SIZE, &sc->sc_bsh_rxdescs); if (error) { printf("can't subregion rx ring SRAM: %d\n", error); return; } sc->sc_rdp = malloc(sizeof(*sc->sc_rdp), M_TEMP, M_WAITOK); KASSERT(sc->sc_rdp != NULL); for (i = 0; i < CPSW_NTXDESCS; i++) { if ((error = bus_dmamap_create(sc->sc_bdt, MCLBYTES, CPSW_TXFRAGS, MCLBYTES, 0, 0, &sc->sc_rdp->tx_dm[i])) != 0) { printf("unable to create tx DMA map: %d\n", error); } sc->sc_rdp->tx_mb[i] = NULL; } for (i = 0; i < CPSW_NRXDESCS; i++) { if ((error = bus_dmamap_create(sc->sc_bdt, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rdp->rx_dm[i])) != 0) { printf("unable to create rx DMA map: %d\n", error); } sc->sc_rdp->rx_mb[i] = NULL; } sc->sc_txpad = dma_alloc(ETHER_MIN_LEN, PR_WAITOK | PR_ZERO); KASSERT(sc->sc_txpad != NULL); bus_dmamap_create(sc->sc_bdt, ETHER_MIN_LEN, 1, ETHER_MIN_LEN, 0, BUS_DMA_WAITOK, &sc->sc_txpad_dm); bus_dmamap_load(sc->sc_bdt, sc->sc_txpad_dm, sc->sc_txpad, ETHER_MIN_LEN, NULL, BUS_DMA_WAITOK|BUS_DMA_WRITE); bus_dmamap_sync(sc->sc_bdt, sc->sc_txpad_dm, 0, ETHER_MIN_LEN, BUS_DMASYNC_PREWRITE); idver = bus_space_read_4(sc->sc_bst, sc->sc_bsh, CPSW_SS_IDVER); printf(": version %d.%d (%d), address %s\n", CPSW_SS_IDVER_MAJ(idver), CPSW_SS_IDVER_MIN(idver), CPSW_SS_IDVER_RTL(idver), ether_sprintf(ac->ac_enaddr)); ifp->if_softc = sc; ifp->if_capabilities = 0; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = cpsw_start; ifp->if_ioctl = cpsw_ioctl; ifp->if_watchdog = cpsw_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, CPSW_NTXDESCS - 1); IFQ_SET_READY(&ifp->if_snd); memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); cpsw_stop(ifp); sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = cpsw_mii_readreg; sc->sc_mii.mii_writereg = cpsw_mii_writereg; sc->sc_mii.mii_statchg = cpsw_mii_statchg; ifmedia_init(&sc->sc_mii.mii_media, 0, cpsw_mediachange, cpsw_mediastatus); mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { printf("no PHY found!\n"); ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL); } else { ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); } if_attach(ifp); ether_ifattach(ifp); return; }
/* Attach */ void url_attach(device_t parent, device_t self, void *aux) { struct url_softc *sc = device_private(self); struct usb_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usbd_status err; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; char *devinfop; struct ifnet *ifp; struct mii_data *mii; u_char eaddr[ETHER_ADDR_LEN]; int i, s; sc->sc_dev = self; aprint_naive("\n"); aprint_normal("\n"); devinfop = usbd_devinfo_alloc(dev, 0); aprint_normal_dev(self, "%s\n", devinfop); usbd_devinfo_free(devinfop); /* Move the device into the configured state. */ err = usbd_set_config_no(dev, URL_CONFIG_NO, 1); if (err) { aprint_error_dev(self, "failed to set configuration" ", err=%s\n", usbd_errstr(err)); goto bad; } usb_init_task(&sc->sc_tick_task, url_tick_task, sc, 0); rw_init(&sc->sc_mii_rwlock); usb_init_task(&sc->sc_stop_task, (void (*)(void *))url_stop_task, sc, 0); /* get control interface */ err = usbd_device2interface_handle(dev, URL_IFACE_INDEX, &iface); if (err) { aprint_error_dev(self, "failed to get interface, err=%s\n", usbd_errstr(err)); goto bad; } sc->sc_udev = dev; sc->sc_ctl_iface = iface; sc->sc_flags = url_lookup(uaa->vendor, uaa->product)->url_flags; /* get interface descriptor */ id = usbd_get_interface_descriptor(sc->sc_ctl_iface); /* find endpoints */ sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); if (ed == NULL) { aprint_error_dev(self, "couldn't get endpoint %d\n", i); goto bad; } if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */ else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */ else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) sc->sc_intrin_no = ed->bEndpointAddress; /* Status */ } if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 || sc->sc_intrin_no == -1) { aprint_error_dev(self, "missing endpoint\n"); goto bad; } s = splnet(); /* reset the adapter */ url_reset(sc); /* Get Ethernet Address */ err = url_mem(sc, URL_CMD_READMEM, URL_IDR0, (void *)eaddr, ETHER_ADDR_LEN); if (err) { aprint_error_dev(self, "read MAC address failed\n"); splx(s); goto bad; } /* Print Ethernet Address */ aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr)); /* initialize interface information */ ifp = GET_IFP(sc); ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; strncpy(ifp->if_xname, device_xname(self), IFNAMSIZ); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = url_start; ifp->if_ioctl = url_ioctl; ifp->if_watchdog = url_watchdog; ifp->if_init = url_init; ifp->if_stop = url_stop; IFQ_SET_READY(&ifp->if_snd); /* * Do ifmedia setup. */ mii = &sc->sc_mii; mii->mii_ifp = ifp; mii->mii_readreg = url_int_miibus_readreg; mii->mii_writereg = url_int_miibus_writereg; #if 0 if (sc->sc_flags & URL_EXT_PHY) { mii->mii_readreg = url_ext_miibus_readreg; mii->mii_writereg = url_ext_miibus_writereg; } #endif mii->mii_statchg = url_miibus_statchg; mii->mii_flags = MIIF_AUTOTSLEEP; sc->sc_ec.ec_mii = mii; ifmedia_init(&mii->mii_media, 0, url_ifmedia_change, url_ifmedia_status); mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&mii->mii_phys) == NULL) { ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); } else ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); /* attach the interface */ if_attach(ifp); ether_ifattach(ifp, eaddr); rnd_attach_source(&sc->rnd_source, device_xname(self), RND_TYPE_NET, 0); callout_init(&sc->sc_stat_ch, 0); sc->sc_attached = 1; splx(s); usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev); return; bad: sc->sc_dying = 1; return; }
int dtsec_attach(device_t dev) { struct dtsec_softc *sc; int error; struct ifnet *ifp; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_mac_mdio_irq = NO_IRQ; sc->sc_eth_id = device_get_unit(dev); /* Check if MallocSmart allocator is ready */ if (XX_MallocSmartInit() != E_OK) return (ENXIO); XX_TrackInit(); /* Init locks */ mtx_init(&sc->sc_lock, device_get_nameunit(dev), "DTSEC Global Lock", MTX_DEF); mtx_init(&sc->sc_mii_lock, device_get_nameunit(dev), "DTSEC MII Lock", MTX_DEF); /* Init callouts */ callout_init(&sc->sc_tick_callout, CALLOUT_MPSAFE); /* Read configuraton */ if ((error = fman_get_handle(&sc->sc_fmh)) != 0) return (error); if ((error = fman_get_muram_handle(&sc->sc_muramh)) != 0) return (error); if ((error = fman_get_bushandle(&sc->sc_fm_base)) != 0) return (error); /* Configure working mode */ dtsec_configure_mode(sc); /* If we are working in regular mode configure BMAN and QMAN */ if (sc->sc_mode == DTSEC_MODE_REGULAR) { /* Create RX buffer pool */ error = dtsec_rm_pool_rx_init(sc); if (error != 0) return (EIO); /* Create RX frame queue range */ error = dtsec_rm_fqr_rx_init(sc); if (error != 0) return (EIO); /* Create frame info pool */ error = dtsec_rm_fi_pool_init(sc); if (error != 0) return (EIO); /* Create TX frame queue range */ error = dtsec_rm_fqr_tx_init(sc); if (error != 0) return (EIO); } /* Init FMan MAC module. */ error = dtsec_fm_mac_init(sc, sc->sc_mac_addr); if (error != 0) { dtsec_detach(dev); return (ENXIO); } /* * XXX: All phys are connected to MDIO interface of the first dTSEC * device (dTSEC0). We have to save handle to the FM_MAC instance of * dTSEC0, which is used later during phy's registers accesses. Another * option would be adding new property to DTS pointing to correct dTSEC * instance, of which FM_MAC handle has to be used for phy's registers * accesses. We did not want to add new properties to DTS, thus this * quite ugly hack. */ if (sc->sc_eth_id == 0) dtsec_mdio_mac_handle = sc->sc_mach; if (sc->sc_hidden) return (0); /* Init FMan TX port */ error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev)); if (error != 0) { dtsec_detach(dev); return (ENXIO); } /* Init FMan RX port */ error = sc->sc_port_rx_init(sc, device_get_unit(sc->sc_dev)); if (error != 0) { dtsec_detach(dev); return (ENXIO); } /* Create network interface for upper layers */ ifp = sc->sc_ifnet = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(sc->sc_dev, "if_alloc() failed.\n"); dtsec_detach(dev); return (ENOMEM); } ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; /* TODO: Configure */ ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; ifp->if_init = dtsec_if_init; ifp->if_start = dtsec_if_start; ifp->if_ioctl = dtsec_if_ioctl; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; if (sc->sc_phy_addr >= 0) if_initname(ifp, device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev)); else if_initname(ifp, "dtsec_phy", device_get_unit(sc->sc_dev)); /* TODO */ #if 0 IFQ_SET_MAXLEN(&ifp->if_snd, TSEC_TX_NUM_DESC - 1); ifp->if_snd.ifq_drv_maxlen = TSEC_TX_NUM_DESC - 1; IFQ_SET_READY(&ifp->if_snd); #endif ifp->if_capabilities = 0; /* TODO: Check */ ifp->if_capenable = ifp->if_capabilities; /* Attach PHY(s) */ error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd, dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr, MII_OFFSET_ANY, 0); if (error) { device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error); dtsec_detach(sc->sc_dev); return (error); } sc->sc_mii = device_get_softc(sc->sc_mii_dev); /* Attach to stack */ ether_ifattach(ifp, sc->sc_mac_addr); return (0); }
static void ste_attach(device_t parent, device_t self, void *aux) { struct ste_softc *sc = device_private(self); struct pci_attach_args *pa = aux; struct ifnet *ifp = &sc->sc_ethercom.ec_if; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr = NULL; bus_space_tag_t iot, memt; bus_space_handle_t ioh, memh; bus_dma_segment_t seg; int ioh_valid, memh_valid; int i, rseg, error; const struct ste_product *sp; uint8_t enaddr[ETHER_ADDR_LEN]; uint16_t myea[ETHER_ADDR_LEN / 2]; callout_init(&sc->sc_tick_ch, 0); sp = ste_lookup(pa); if (sp == NULL) { printf("\n"); panic("ste_attach: impossible"); } printf(": %s\n", sp->ste_name); /* * Map the device. */ ioh_valid = (pci_mapreg_map(pa, STE_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, NULL) == 0); memh_valid = (pci_mapreg_map(pa, STE_PCI_MMBA, PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, NULL, NULL) == 0); if (memh_valid) { sc->sc_st = memt; sc->sc_sh = memh; } else if (ioh_valid) { sc->sc_st = iot; sc->sc_sh = ioh; } else { aprint_error_dev(&sc->sc_dev, "unable to map device registers\n"); return; } sc->sc_dmat = pa->pa_dmat; /* Enable bus mastering. */ pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | PCI_COMMAND_MASTER_ENABLE); /* power up chip */ if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, NULL)) && error != EOPNOTSUPP) { aprint_error_dev(&sc->sc_dev, "cannot activate %d\n", error); return; } /* * Map and establish our interrupt. */ if (pci_intr_map(pa, &ih)) { aprint_error_dev(&sc->sc_dev, "unable to map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ste_intr, sc); if (sc->sc_ih == NULL) { aprint_error_dev(&sc->sc_dev, "unable to establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf("%s: interrupting at %s\n", device_xname(&sc->sc_dev), intrstr); /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct ste_control_data), PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) { aprint_error_dev(&sc->sc_dev, "unable to allocate control data, error = %d\n", error); goto fail_0; } if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(struct ste_control_data), (void **)&sc->sc_control_data, BUS_DMA_COHERENT)) != 0) { aprint_error_dev(&sc->sc_dev, "unable to map control data, error = %d\n", error); goto fail_1; } if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct ste_control_data), 1, sizeof(struct ste_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { aprint_error_dev(&sc->sc_dev, "unable to create control data DMA map, " "error = %d\n", error); goto fail_2; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct ste_control_data), NULL, 0)) != 0) { aprint_error_dev(&sc->sc_dev, "unable to load control data DMA map, error = %d\n", error); goto fail_3; } /* * Create the transmit buffer DMA maps. */ for (i = 0; i < STE_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, STE_NTXFRAGS, MCLBYTES, 0, 0, &sc->sc_txsoft[i].ds_dmamap)) != 0) { aprint_error_dev(&sc->sc_dev, "unable to create tx DMA map %d, " "error = %d\n", i, error); goto fail_4; } } /* * Create the receive buffer DMA maps. */ for (i = 0; i < STE_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxsoft[i].ds_dmamap)) != 0) { aprint_error_dev(&sc->sc_dev, "unable to create rx DMA map %d, " "error = %d\n", i, error); goto fail_5; } sc->sc_rxsoft[i].ds_mbuf = NULL; } /* * Reset the chip to a known state. */ ste_reset(sc, AC_GlobalReset | AC_RxReset | AC_TxReset | AC_DMA | AC_FIFO | AC_Network | AC_Host | AC_AutoInit | AC_RstOut); /* * Read the Ethernet address from the EEPROM. */ for (i = 0; i < 3; i++) { ste_read_eeprom(sc, STE_EEPROM_StationAddress0 + i, &myea[i]); myea[i] = le16toh(myea[i]); } memcpy(enaddr, myea, sizeof(enaddr)); printf("%s: Ethernet address %s\n", device_xname(&sc->sc_dev), ether_sprintf(enaddr)); /* * Initialize our media structures and probe the MII. */ sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = ste_mii_readreg; sc->sc_mii.mii_writereg = ste_mii_writereg; sc->sc_mii.mii_statchg = ste_mii_statchg; sc->sc_ethercom.ec_mii = &sc->sc_mii; ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, ether_mediachange, ether_mediastatus); mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); ifp = &sc->sc_ethercom.ec_if; strlcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ste_ioctl; ifp->if_start = ste_start; ifp->if_watchdog = ste_watchdog; ifp->if_init = ste_init; ifp->if_stop = ste_stop; IFQ_SET_READY(&ifp->if_snd); /* * Default the transmit threshold to 128 bytes. */ sc->sc_txthresh = 128; /* * Disable MWI if the PCI layer tells us to. */ sc->sc_DMACtrl = 0; if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0) sc->sc_DMACtrl |= DC_MWIDisable; /* * We can support 802.1Q VLAN-sized frames. */ sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; /* * Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, enaddr); /* * Make sure the interface is shutdown during reboot. */ sc->sc_sdhook = shutdownhook_establish(ste_shutdown, sc); if (sc->sc_sdhook == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", device_xname(&sc->sc_dev)); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_5: for (i = 0; i < STE_NRXDESC; i++) { if (sc->sc_rxsoft[i].ds_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxsoft[i].ds_dmamap); } fail_4: for (i = 0; i < STE_NTXDESC; i++) { if (sc->sc_txsoft[i].ds_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_txsoft[i].ds_dmamap); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); fail_3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); fail_2: bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, sizeof(struct ste_control_data)); fail_1: bus_dmamem_free(sc->sc_dmat, &seg, rseg); fail_0: return; }
void bmac_attach(struct device *parent, struct device *self, void *aux) { struct confargs *ca = aux; struct bmac_softc *sc = (void *)self; struct ifnet *ifp = &sc->arpcom.ac_if; struct mii_data *mii = &sc->sc_mii; u_char laddr[6]; int nseg, error; timeout_set(&sc->sc_tick_ch, bmac_mii_tick, sc); sc->sc_flags =0; if (strcmp(ca->ca_name, "ethernet") == 0) { sc->sc_flags |= BMAC_BMACPLUS; } ca->ca_reg[0] += ca->ca_baseaddr; ca->ca_reg[2] += ca->ca_baseaddr; ca->ca_reg[4] += ca->ca_baseaddr; sc->sc_regs = (vaddr_t)mapiodev(ca->ca_reg[0], NBPG); bmac_write_reg(sc, INTDISABLE, NoEventsMask); if (OF_getprop(ca->ca_node, "local-mac-address", laddr, 6) == -1 && OF_getprop(ca->ca_node, "mac-address", laddr, 6) == -1) { printf(": cannot get mac-address\n"); return; } bcopy(laddr, sc->arpcom.ac_enaddr, 6); sc->sc_dmat = ca->ca_dmat; sc->sc_txdma = mapiodev(ca->ca_reg[2], 0x100); sc->sc_rxdma = mapiodev(ca->ca_reg[4], 0x100); sc->sc_txdbdma = dbdma_alloc(sc->sc_dmat, BMAC_TXBUFS); sc->sc_txcmd = sc->sc_txdbdma->d_addr; sc->sc_rxdbdma = dbdma_alloc(sc->sc_dmat, BMAC_RXBUFS + 1); sc->sc_rxcmd = sc->sc_rxdbdma->d_addr; error = bus_dmamem_alloc(sc->sc_dmat, BMAC_BUFSZ, PAGE_SIZE, 0, sc->sc_bufseg, 1, &nseg, BUS_DMA_NOWAIT); if (error) { printf(": cannot allocate buffers (%d)\n", error); return; } error = bus_dmamem_map(sc->sc_dmat, sc->sc_bufseg, nseg, BMAC_BUFSZ, &sc->sc_txbuf, BUS_DMA_NOWAIT); if (error) { printf(": cannot map buffers (%d)\n", error); bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, 1); return; } error = bus_dmamap_create(sc->sc_dmat, BMAC_BUFSZ, 1, BMAC_BUFSZ, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_bufmap); if (error) { printf(": cannot create buffer dmamap (%d)\n", error); bus_dmamem_unmap(sc->sc_dmat, sc->sc_txbuf, BMAC_BUFSZ); bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, 1); return; } error = bus_dmamap_load(sc->sc_dmat, sc->sc_bufmap, sc->sc_txbuf, BMAC_BUFSZ, NULL, BUS_DMA_NOWAIT); if (error) { printf(": cannot load buffers dmamap (%d)\n", error); bus_dmamap_destroy(sc->sc_dmat, sc->sc_bufmap); bus_dmamem_unmap(sc->sc_dmat, sc->sc_txbuf, BMAC_BUFSZ); bus_dmamem_free(sc->sc_dmat, sc->sc_bufseg, nseg); return; } sc->sc_txbuf_pa = sc->sc_bufmap->dm_segs->ds_addr; sc->sc_rxbuf = sc->sc_txbuf + BMAC_BUFLEN * BMAC_TXBUFS; sc->sc_rxbuf_pa = sc->sc_txbuf_pa + BMAC_BUFLEN * BMAC_TXBUFS; printf(" irq %d,%d: address %s\n", ca->ca_intr[0], ca->ca_intr[2], ether_sprintf(laddr)); mac_intr_establish(parent, ca->ca_intr[0], IST_LEVEL, IPL_NET, bmac_intr, sc, sc->sc_dev.dv_xname); mac_intr_establish(parent, ca->ca_intr[2], IST_LEVEL, IPL_NET, bmac_rint, sc, sc->sc_dev.dv_xname); bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_ioctl = bmac_ioctl; ifp->if_start = bmac_start; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; ifp->if_watchdog = bmac_watchdog; IFQ_SET_READY(&ifp->if_snd); mii->mii_ifp = ifp; mii->mii_readreg = bmac_mii_readreg; mii->mii_writereg = bmac_mii_writereg; mii->mii_statchg = bmac_mii_statchg; ifmedia_init(&mii->mii_media, 0, bmac_mediachange, bmac_mediastatus); mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); /* Choose a default media. */ if (LIST_FIRST(&mii->mii_phys) == NULL) { ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_10_T, 0, NULL); ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_10_T); } else ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); bmac_reset_chip(sc); if_attach(ifp); ether_ifattach(ifp); }
static void emac_init(struct emac_softc *sc) { bus_dma_segment_t segs; void *addr; int rsegs, err, i; struct ifnet * ifp = &sc->sc_ec.ec_if; uint32_t u; #if 0 int mdcdiv = DEFAULT_MDCDIV; #endif callout_init(&sc->emac_tick_ch, 0); // ok... EMAC_WRITE(ETH_CTL, ETH_CTL_MPE); // disable everything EMAC_WRITE(ETH_IDR, -1); // disable interrupts EMAC_WRITE(ETH_RBQP, 0); // clear receive EMAC_WRITE(ETH_CFG, ETH_CFG_CLK_32 | ETH_CFG_SPD | ETH_CFG_FD | ETH_CFG_BIG); EMAC_WRITE(ETH_TCR, 0); // send nothing // (void)EMAC_READ(ETH_ISR); u = EMAC_READ(ETH_TSR); EMAC_WRITE(ETH_TSR, (u & (ETH_TSR_UND | ETH_TSR_COMP | ETH_TSR_BNQ | ETH_TSR_IDLE | ETH_TSR_RLE | ETH_TSR_COL|ETH_TSR_OVR))); u = EMAC_READ(ETH_RSR); EMAC_WRITE(ETH_RSR, (u & (ETH_RSR_OVR|ETH_RSR_REC|ETH_RSR_BNA))); /* configure EMAC */ EMAC_WRITE(ETH_CFG, ETH_CFG_CLK_32 | ETH_CFG_SPD | ETH_CFG_FD | ETH_CFG_BIG); EMAC_WRITE(ETH_CTL, ETH_CTL_MPE); #if 0 if (device_cfdata(&sc->sc_dev)->cf_flags) mdcdiv = device_cfdata(&sc->sc_dev)->cf_flags; #endif /* set ethernet address */ EMAC_WRITE(ETH_SA1L, (sc->sc_enaddr[3] << 24) | (sc->sc_enaddr[2] << 16) | (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[0])); EMAC_WRITE(ETH_SA1H, (sc->sc_enaddr[5] << 8) | (sc->sc_enaddr[4])); EMAC_WRITE(ETH_SA2L, 0); EMAC_WRITE(ETH_SA2H, 0); EMAC_WRITE(ETH_SA3L, 0); EMAC_WRITE(ETH_SA3H, 0); EMAC_WRITE(ETH_SA4L, 0); EMAC_WRITE(ETH_SA4H, 0); /* Allocate a page of memory for receive queue descriptors */ sc->rbqlen = (ETH_RDSC_SIZE * (RX_QLEN + 1) * 2 + PAGE_SIZE - 1) / PAGE_SIZE; sc->rbqlen *= PAGE_SIZE; DPRINTFN(1,("%s: rbqlen=%i\n", __FUNCTION__, sc->rbqlen)); err = bus_dmamem_alloc(sc->sc_dmat, sc->rbqlen, 0, MAX(16384, PAGE_SIZE), // see EMAC errata why forced to 16384 byte boundary &segs, 1, &rsegs, BUS_DMA_WAITOK); if (err == 0) { DPRINTFN(1,("%s: -> bus_dmamem_map\n", __FUNCTION__)); err = bus_dmamem_map(sc->sc_dmat, &segs, 1, sc->rbqlen, &sc->rbqpage, (BUS_DMA_WAITOK|BUS_DMA_COHERENT)); } if (err == 0) { DPRINTFN(1,("%s: -> bus_dmamap_create\n", __FUNCTION__)); err = bus_dmamap_create(sc->sc_dmat, sc->rbqlen, 1, sc->rbqlen, MAX(16384, PAGE_SIZE), BUS_DMA_WAITOK, &sc->rbqpage_dmamap); } if (err == 0) { DPRINTFN(1,("%s: -> bus_dmamap_load\n", __FUNCTION__)); err = bus_dmamap_load(sc->sc_dmat, sc->rbqpage_dmamap, sc->rbqpage, sc->rbqlen, NULL, BUS_DMA_WAITOK); } if (err != 0) { panic("%s: Cannot get DMA memory", device_xname(sc->sc_dev)); } sc->rbqpage_dsaddr = sc->rbqpage_dmamap->dm_segs[0].ds_addr; bzero(sc->rbqpage, sc->rbqlen); /* Set up pointers to start of each queue in kernel addr space. * Each descriptor queue or status queue entry uses 2 words */ sc->RDSC = (void*)sc->rbqpage; /* Populate the RXQ with mbufs */ sc->rxqi = 0; for(i = 0; i < RX_QLEN; i++) { struct mbuf *m; err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, PAGE_SIZE, BUS_DMA_WAITOK, &sc->rxq[i].m_dmamap); if (err) { panic("%s: dmamap_create failed: %i\n", __FUNCTION__, err); } MGETHDR(m, M_WAIT, MT_DATA); MCLGET(m, M_WAIT); sc->rxq[i].m = m; if (mtod(m, intptr_t) & 3) { m_adj(m, mtod(m, intptr_t) & 3); } err = bus_dmamap_load(sc->sc_dmat, sc->rxq[i].m_dmamap, m->m_ext.ext_buf, MCLBYTES, NULL, BUS_DMA_WAITOK); if (err) { panic("%s: dmamap_load failed: %i\n", __FUNCTION__, err); } sc->RDSC[i].Addr = sc->rxq[i].m_dmamap->dm_segs[0].ds_addr | (i == (RX_QLEN-1) ? ETH_RDSC_F_WRAP : 0); sc->RDSC[i].Info = 0; bus_dmamap_sync(sc->sc_dmat, sc->rxq[i].m_dmamap, 0, MCLBYTES, BUS_DMASYNC_PREREAD); } /* prepare transmit queue */ for (i = 0; i < TX_QLEN; i++) { err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, (BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW), &sc->txq[i].m_dmamap); if (err) panic("ARGH #1"); sc->txq[i].m = NULL; } /* Program each queue's start addr, cur addr, and len registers * with the physical addresses. */ bus_dmamap_sync(sc->sc_dmat, sc->rbqpage_dmamap, 0, sc->rbqlen, BUS_DMASYNC_PREREAD); addr = (void *)sc->rbqpage_dmamap->dm_segs[0].ds_addr; EMAC_WRITE(ETH_RBQP, (u_int32_t)addr); /* Divide HCLK by 32 for MDC clock */ sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = emac_mii_readreg; sc->sc_mii.mii_writereg = emac_mii_writereg; sc->sc_mii.mii_statchg = emac_statchg; ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, emac_mediachange, emac_mediastatus); mii_attach((device_t )sc, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); // enable / disable interrupts #if 0 // enable / disable interrupts EMAC_WRITE(ETH_IDR, -1); EMAC_WRITE(ETH_IER, ETH_ISR_RCOM | ETH_ISR_TBRE | ETH_ISR_TIDLE | ETH_ISR_RBNA | ETH_ISR_ROVR); // (void)EMAC_READ(ETH_ISR); // why // enable transmitter / receiver EMAC_WRITE(ETH_CTL, ETH_CTL_TE | ETH_CTL_RE | ETH_CTL_ISR | ETH_CTL_CSR | ETH_CTL_MPE); #endif /* * We can support 802.1Q VLAN-sized frames. */ sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU; strcpy(ifp->if_xname, device_xname(sc->sc_dev)); ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; ifp->if_ioctl = emac_ifioctl; ifp->if_start = emac_ifstart; ifp->if_watchdog = emac_ifwatchdog; ifp->if_init = emac_ifinit; ifp->if_stop = emac_ifstop; ifp->if_timer = 0; ifp->if_softc = sc; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp, (sc)->sc_enaddr); }
void bmac_attach(struct device *parent, struct device *self, void *aux) { struct confargs *ca = aux; struct bmac_softc *sc = (void *)self; struct ifnet *ifp = &sc->sc_if; struct mii_data *mii = &sc->sc_mii; u_char laddr[6]; callout_init(&sc->sc_tick_ch, 0); sc->sc_flags =0; if (strcmp(ca->ca_name, "ethernet") == 0) { char name[64]; memset(name, 0, 64); OF_package_to_path(ca->ca_node, name, sizeof(name)); OF_open(name); sc->sc_flags |= BMAC_BMACPLUS; } ca->ca_reg[0] += ca->ca_baseaddr; ca->ca_reg[2] += ca->ca_baseaddr; ca->ca_reg[4] += ca->ca_baseaddr; sc->sc_iot = ca->ca_tag; if (bus_space_map(sc->sc_iot, ca->ca_reg[0], ca->ca_reg[1], 0, &sc->sc_ioh) != 0) { aprint_error(": couldn't map %#x", ca->ca_reg[0]); return; } bmac_write_reg(sc, INTDISABLE, NoEventsMask); if (OF_getprop(ca->ca_node, "local-mac-address", laddr, 6) == -1 && OF_getprop(ca->ca_node, "mac-address", laddr, 6) == -1) { printf(": cannot get mac-address\n"); return; } memcpy(sc->sc_enaddr, laddr, 6); sc->sc_txdma = mapiodev(ca->ca_reg[2], PAGE_SIZE); sc->sc_rxdma = mapiodev(ca->ca_reg[4], PAGE_SIZE); sc->sc_txcmd = dbdma_alloc(BMAC_TXBUFS * sizeof(dbdma_command_t)); sc->sc_rxcmd = dbdma_alloc((BMAC_RXBUFS + 1) * sizeof(dbdma_command_t)); sc->sc_txbuf = malloc(BMAC_BUFLEN * BMAC_TXBUFS, M_DEVBUF, M_NOWAIT); sc->sc_rxbuf = malloc(BMAC_BUFLEN * BMAC_RXBUFS, M_DEVBUF, M_NOWAIT); if (sc->sc_txbuf == NULL || sc->sc_rxbuf == NULL || sc->sc_txcmd == NULL || sc->sc_rxcmd == NULL) { printf("cannot allocate memory\n"); return; } printf(" irq %d,%d: address %s\n", ca->ca_intr[0], ca->ca_intr[2], ether_sprintf(laddr)); intr_establish(ca->ca_intr[0], IST_EDGE, IPL_NET, bmac_intr, sc); intr_establish(ca->ca_intr[2], IST_EDGE, IPL_NET, bmac_rint, sc); memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_ioctl = bmac_ioctl; ifp->if_start = bmac_start; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; ifp->if_watchdog = bmac_watchdog; IFQ_SET_READY(&ifp->if_snd); mii->mii_ifp = ifp; mii->mii_readreg = bmac_mii_readreg; mii->mii_writereg = bmac_mii_writereg; mii->mii_statchg = bmac_mii_statchg; sc->sc_ethercom.ec_mii = mii; ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); /* Choose a default media. */ if (LIST_FIRST(&mii->mii_phys) == NULL) { ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_10_T, 0, NULL); ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_10_T); } else ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); bmac_reset_chip(sc); if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); }
static int kr_attach(device_t dev) { uint8_t eaddr[ETHER_ADDR_LEN]; struct ifnet *ifp; struct kr_softc *sc; int error = 0, rid; int unit; sc = device_get_softc(dev); unit = device_get_unit(dev); sc->kr_dev = dev; mtx_init(&sc->kr_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); callout_init_mtx(&sc->kr_stat_callout, &sc->kr_mtx, 0); TASK_INIT(&sc->kr_link_task, 0, kr_link_task, sc); pci_enable_busmaster(dev); /* Map control/status registers. */ sc->kr_rid = 0; sc->kr_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->kr_rid, RF_ACTIVE); if (sc->kr_res == NULL) { device_printf(dev, "couldn't map memory\n"); error = ENXIO; goto fail; } sc->kr_btag = rman_get_bustag(sc->kr_res); sc->kr_bhandle = rman_get_bushandle(sc->kr_res); /* Allocate interrupts */ rid = 0; sc->kr_rx_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_RX_IRQ, KR_RX_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->kr_rx_irq == NULL) { device_printf(dev, "couldn't map rx interrupt\n"); error = ENXIO; goto fail; } rid = 0; sc->kr_tx_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_TX_IRQ, KR_TX_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->kr_tx_irq == NULL) { device_printf(dev, "couldn't map tx interrupt\n"); error = ENXIO; goto fail; } rid = 0; sc->kr_rx_und_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_RX_UND_IRQ, KR_RX_UND_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->kr_rx_und_irq == NULL) { device_printf(dev, "couldn't map rx underrun interrupt\n"); error = ENXIO; goto fail; } rid = 0; sc->kr_tx_ovr_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_TX_OVR_IRQ, KR_TX_OVR_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->kr_tx_ovr_irq == NULL) { device_printf(dev, "couldn't map tx overrun interrupt\n"); error = ENXIO; goto fail; } /* Allocate ifnet structure. */ ifp = sc->kr_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "couldn't allocate ifnet structure\n"); error = ENOSPC; goto fail; } ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = kr_ioctl; ifp->if_start = kr_start; ifp->if_init = kr_init; /* XXX: add real size */ IFQ_SET_MAXLEN(&ifp->if_snd, 9); ifp->if_snd.ifq_maxlen = 9; IFQ_SET_READY(&ifp->if_snd); ifp->if_capenable = ifp->if_capabilities; eaddr[0] = 0x00; eaddr[1] = 0x0C; eaddr[2] = 0x42; eaddr[3] = 0x09; eaddr[4] = 0x5E; eaddr[5] = 0x6B; if (kr_dma_alloc(sc) != 0) { error = ENXIO; goto fail; } /* TODO: calculate prescale */ CSR_WRITE_4(sc, KR_ETHMCP, (165000000 / (1250000 + 1)) & ~1); CSR_WRITE_4(sc, KR_MIIMCFG, KR_MIIMCFG_R); DELAY(1000); CSR_WRITE_4(sc, KR_MIIMCFG, 0); /* Do MII setup. */ error = mii_attach(dev, &sc->kr_miibus, ifp, kr_ifmedia_upd, kr_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (error != 0) { device_printf(dev, "attaching PHYs failed\n"); goto fail; } /* Call MI attach routine. */ ether_ifattach(ifp, eaddr); /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->kr_rx_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_rx_intr, sc, &sc->kr_rx_intrhand); if (error) { device_printf(dev, "couldn't set up rx irq\n"); ether_ifdetach(ifp); goto fail; } error = bus_setup_intr(dev, sc->kr_tx_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_tx_intr, sc, &sc->kr_tx_intrhand); if (error) { device_printf(dev, "couldn't set up tx irq\n"); ether_ifdetach(ifp); goto fail; } error = bus_setup_intr(dev, sc->kr_rx_und_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_rx_und_intr, sc, &sc->kr_rx_und_intrhand); if (error) { device_printf(dev, "couldn't set up rx underrun irq\n"); ether_ifdetach(ifp); goto fail; } error = bus_setup_intr(dev, sc->kr_tx_ovr_irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_tx_ovr_intr, sc, &sc->kr_tx_ovr_intrhand); if (error) { device_printf(dev, "couldn't set up tx overrun irq\n"); ether_ifdetach(ifp); goto fail; } fail: if (error) kr_detach(dev); return (error); }
static void ue_attach_post_task(struct usb_proc_msg *_task) { struct usb_ether_cfg_task *task = (struct usb_ether_cfg_task *)_task; struct usb_ether *ue = task->ue; struct ifnet *ifp; int error; char num[14]; /* sufficient for 32 bits */ /* first call driver's post attach routine */ ue->ue_methods->ue_attach_post(ue); UE_UNLOCK(ue); ue->ue_unit = alloc_unr(ueunit); usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0); sysctl_ctx_init(&ue->ue_sysctl_ctx); error = 0; CURVNET_SET_QUIET(vnet0); ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(ue->ue_dev, "could not allocate ifnet\n"); goto fail; } ifp->if_softc = ue; if_initname(ifp, "ue", ue->ue_unit); if (ue->ue_methods->ue_attach_post_sub != NULL) { ue->ue_ifp = ifp; error = ue->ue_methods->ue_attach_post_sub(ue); } else { ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; if (ue->ue_methods->ue_ioctl != NULL) ifp->if_ioctl = ue->ue_methods->ue_ioctl; else ifp->if_ioctl = uether_ioctl; ifp->if_start = ue_start; ifp->if_init = ue_init; IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ue->ue_ifp = ifp; if (ue->ue_methods->ue_mii_upd != NULL && ue->ue_methods->ue_mii_sts != NULL) { /* device_xxx() depends on this */ mtx_lock(&Giant); error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp, ue_ifmedia_upd, ue->ue_methods->ue_mii_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); mtx_unlock(&Giant); } } if (error) { device_printf(ue->ue_dev, "attaching PHYs failed\n"); goto fail; } if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev)); ether_ifattach(ifp, ue->ue_eaddr); /* Tell upper layer we support VLAN oversized frames. */ if (ifp->if_capabilities & IFCAP_VLAN_MTU) ifp->if_hdrlen = sizeof(struct ether_vlan_header); CURVNET_RESTORE(); snprintf(num, sizeof(num), "%u", ue->ue_unit); ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx, &SYSCTL_NODE_CHILDREN(_net, ue), OID_AUTO, num, CTLFLAG_RD, NULL, ""); SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx, SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO, "%parent", CTLTYPE_STRING | CTLFLAG_RD, ue, 0, ue_sysctl_parent, "A", "parent device"); UE_LOCK(ue); return; fail: CURVNET_RESTORE(); free_unr(ueunit, ue->ue_unit); if (ue->ue_ifp != NULL) { if_free(ue->ue_ifp); ue->ue_ifp = NULL; } UE_LOCK(ue); return; }
void mec_attach(struct device *parent, struct device *self, void *aux) { struct mec_softc *sc = (void *)self; struct confargs *ca = aux; struct ifnet *ifp = &sc->sc_ac.ac_if; uint32_t command; struct mii_softc *child; bus_dma_segment_t seg; int i, err, rseg; sc->sc_st = ca->ca_iot; if (bus_space_map(sc->sc_st, ca->ca_baseaddr, MEC_NREGS, 0, &sc->sc_sh) != 0) { printf(": can't map i/o space\n"); return; } /* Set up DMA structures. */ sc->sc_dmat = ca->ca_dmat; /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((err = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct mec_control_data), MEC_CONTROL_DATA_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { printf(": unable to allocate control data, error = %d\n", err); goto fail_0; } /* * XXX needs re-think... * control data structures contain whole RX data buffer, so * BUS_DMA_COHERENT (which disables cache) may cause some performance * issue on copying data from the RX buffer to mbuf on normal memory, * though we have to make sure all bus_dmamap_sync(9) ops are called * properly in that case. */ if ((err = bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(struct mec_control_data), (caddr_t *)&sc->sc_control_data, /*BUS_DMA_COHERENT*/ 0)) != 0) { printf(": unable to map control data, error = %d\n", err); goto fail_1; } memset(sc->sc_control_data, 0, sizeof(struct mec_control_data)); if ((err = bus_dmamap_create(sc->sc_dmat, sizeof(struct mec_control_data), 1, sizeof(struct mec_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { printf(": unable to create control data DMA map, error = %d\n", err); goto fail_2; } if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct mec_control_data), NULL, BUS_DMA_NOWAIT)) != 0) { printf(": unable to load control data DMA map, error = %d\n", err); goto fail_3; } /* Create TX buffer DMA maps. */ for (i = 0; i < MEC_NTXDESC; i++) { if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_txsoft[i].txs_dmamap)) != 0) { printf(": unable to create tx DMA map %d, error = %d\n", i, err); goto fail_4; } } timeout_set(&sc->sc_tick_ch, mec_tick, sc); /* Use the Ethernet address from the ARCBIOS. */ enaddr_aton(bios_enaddr, sc->sc_ac.ac_enaddr); /* Reset device. */ mec_reset(sc); command = bus_space_read_8(sc->sc_st, sc->sc_sh, MEC_MAC_CONTROL); printf(": MAC-110 rev %d, address %s\n", (command & MEC_MAC_REVISION) >> MEC_MAC_REVISION_SHIFT, ether_sprintf(sc->sc_ac.ac_enaddr)); /* Done, now attach everything. */ sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = mec_mii_readreg; sc->sc_mii.mii_writereg = mec_mii_writereg; sc->sc_mii.mii_statchg = mec_statchg; /* Set up PHY properties. */ ifmedia_init(&sc->sc_mii.mii_media, 0, mec_mediachange, mec_mediastatus); mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); child = LIST_FIRST(&sc->sc_mii.mii_phys); if (child == NULL) { /* No PHY attached. */ ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); } else { ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); sc->sc_phyaddr = child->mii_phy; } bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = mec_ioctl; ifp->if_start = mec_start; ifp->if_watchdog = mec_watchdog; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); IFQ_SET_MAXLEN(&ifp->if_snd, MEC_NTXDESC - 1); ether_ifattach(ifp); /* Establish interrupt handler. */ macebus_intr_establish(NULL, ca->ca_intr, IST_EDGE, IPL_NET, mec_intr, sc, sc->sc_dev.dv_xname); /* Set hook to stop interface on shutdown. */ sc->sc_sdhook = shutdownhook_establish(mec_shutdown, sc); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall though. */ fail_4: for (i = 0; i < MEC_NTXDESC; i++) { if (sc->sc_txsoft[i].txs_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_txsoft[i].txs_dmamap); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); fail_3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); fail_2: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data, sizeof(struct mec_control_data)); fail_1: bus_dmamem_free(sc->sc_dmat, &seg, rseg); fail_0: return; }
/* * cas_config: * * Attach a Cassini interface to the system. */ void cas_config(struct cas_softc *sc) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct mii_data *mii = &sc->sc_mii; struct mii_softc *child; int i, error; /* Make sure the chip is stopped. */ ifp->if_softc = sc; cas_reset(sc); /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct cas_control_data), CAS_PAGE_SIZE, 0, &sc->sc_cdseg, 1, &sc->sc_cdnseg, 0)) != 0) { printf("\n%s: unable to allocate control data, error = %d\n", sc->sc_dev.dv_xname, error); goto fail_0; } /* XXX should map this in with correct endianness */ if ((error = bus_dmamem_map(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg, sizeof(struct cas_control_data), (caddr_t *)&sc->sc_control_data, BUS_DMA_COHERENT)) != 0) { printf("\n%s: unable to map control data, error = %d\n", sc->sc_dev.dv_xname, error); goto fail_1; } if ((error = bus_dmamap_create(sc->sc_dmatag, sizeof(struct cas_control_data), 1, sizeof(struct cas_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { printf("\n%s: unable to create control data DMA map, " "error = %d\n", sc->sc_dev.dv_xname, error); goto fail_2; } if ((error = bus_dmamap_load(sc->sc_dmatag, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct cas_control_data), NULL, 0)) != 0) { printf("\n%s: unable to load control data DMA map, error = %d\n", sc->sc_dev.dv_xname, error); goto fail_3; } bzero(sc->sc_control_data, sizeof(struct cas_control_data)); /* * Create the receive buffer DMA maps. */ for (i = 0; i < CAS_NRXDESC; i++) { bus_dma_segment_t seg; caddr_t kva; int rseg; if ((error = bus_dmamem_alloc(sc->sc_dmatag, CAS_PAGE_SIZE, CAS_PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { printf("\n%s: unable to alloc rx DMA mem %d, " "error = %d\n", sc->sc_dev.dv_xname, i, error); goto fail_5; } sc->sc_rxsoft[i].rxs_dmaseg = seg; if ((error = bus_dmamem_map(sc->sc_dmatag, &seg, rseg, CAS_PAGE_SIZE, &kva, BUS_DMA_NOWAIT)) != 0) { printf("\n%s: unable to alloc rx DMA mem %d, " "error = %d\n", sc->sc_dev.dv_xname, i, error); goto fail_5; } sc->sc_rxsoft[i].rxs_kva = kva; if ((error = bus_dmamap_create(sc->sc_dmatag, CAS_PAGE_SIZE, 1, CAS_PAGE_SIZE, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { printf("\n%s: unable to create rx DMA map %d, " "error = %d\n", sc->sc_dev.dv_xname, i, error); goto fail_5; } if ((error = bus_dmamap_load(sc->sc_dmatag, sc->sc_rxsoft[i].rxs_dmamap, kva, CAS_PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) != 0) { printf("\n%s: unable to load rx DMA map %d, " "error = %d\n", sc->sc_dev.dv_xname, i, error); goto fail_5; } } /* * Create the transmit buffer DMA maps. */ for (i = 0; i < CAS_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmatag, MCLBYTES, CAS_NTXSEGS, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_txd[i].sd_map)) != 0) { printf("\n%s: unable to create tx DMA map %d, " "error = %d\n", sc->sc_dev.dv_xname, i, error); goto fail_6; } sc->sc_txd[i].sd_mbuf = NULL; } /* * From this point forward, the attachment cannot fail. A failure * before this point releases all resources that may have been * allocated. */ /* Announce ourselves. */ printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); /* Get RX FIFO size */ sc->sc_rxfifosize = 16 * 1024; /* Initialize ifnet structure. */ strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; ifp->if_start = cas_start; ifp->if_ioctl = cas_ioctl; ifp->if_watchdog = cas_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, CAS_NTXDESC - 1); IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities = IFCAP_VLAN_MTU; /* Initialize ifmedia structures and MII info */ mii->mii_ifp = ifp; mii->mii_readreg = cas_mii_readreg; mii->mii_writereg = cas_mii_writereg; mii->mii_statchg = cas_mii_statchg; ifmedia_init(&mii->mii_media, 0, cas_mediachange, cas_mediastatus); bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_MII_DATAPATH_MODE, 0); cas_mifinit(sc); if (sc->sc_mif_config & CAS_MIF_CONFIG_MDI1) { sc->sc_mif_config |= CAS_MIF_CONFIG_PHY_SEL; bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_MIF_CONFIG, sc->sc_mif_config); } mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); child = LIST_FIRST(&mii->mii_phys); if (child == NULL && sc->sc_mif_config & (CAS_MIF_CONFIG_MDI0|CAS_MIF_CONFIG_MDI1)) { /* * Try the external PCS SERDES if we didn't find any * MII devices. */ bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_MII_DATAPATH_MODE, CAS_MII_DATAPATH_SERDES); bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_MII_CONFIG, CAS_MII_CONFIG_ENABLE); mii->mii_readreg = cas_pcs_readreg; mii->mii_writereg = cas_pcs_writereg; mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, MIIF_NOISOLATE); } child = LIST_FIRST(&mii->mii_phys); if (child == NULL) { /* No PHY attached */ ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); } else { /* * Walk along the list of attached MII devices and * establish an `MII instance' to `phy number' * mapping. We'll use this mapping in media change * requests to determine which phy to use to program * the MIF configuration register. */ for (; child != NULL; child = LIST_NEXT(child, mii_list)) { /* * Note: we support just two PHYs: the built-in * internal device and an external on the MII * connector. */ if (child->mii_phy > 1 || child->mii_inst > 1) { printf("%s: cannot accommodate MII device %s" " at phy %d, instance %d\n", sc->sc_dev.dv_xname, child->mii_dev.dv_xname, child->mii_phy, child->mii_inst); continue; } sc->sc_phys[child->mii_inst] = child->mii_phy; } /* * XXX - we can really do the following ONLY if the * phy indeed has the auto negotiation capability!! */ ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO); } /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp); sc->sc_sh = shutdownhook_establish(cas_shutdown, sc); if (sc->sc_sh == NULL) panic("cas_config: can't establish shutdownhook"); timeout_set(&sc->sc_tick_ch, cas_tick, sc); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: for (i = 0; i < CAS_NTXDESC; i++) { if (sc->sc_txd[i].sd_map != NULL) bus_dmamap_destroy(sc->sc_dmatag, sc->sc_txd[i].sd_map); } fail_5: for (i = 0; i < CAS_NRXDESC; i++) { if (sc->sc_rxsoft[i].rxs_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmatag, sc->sc_rxsoft[i].rxs_dmamap); } bus_dmamap_unload(sc->sc_dmatag, sc->sc_cddmamap); fail_3: bus_dmamap_destroy(sc->sc_dmatag, sc->sc_cddmamap); fail_2: bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc->sc_control_data, sizeof(struct cas_control_data)); fail_1: bus_dmamem_free(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg); fail_0: return; }
void nfe_attach(struct device *parent, struct device *self, void *aux) { struct nfe_softc *sc = (struct nfe_softc *)self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr; struct ifnet *ifp; bus_size_t memsize; pcireg_t memtype; memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, NFE_PCI_BA); switch (memtype) { case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: if (pci_mapreg_map(pa, NFE_PCI_BA, memtype, 0, &sc->sc_memt, &sc->sc_memh, NULL, &memsize, 0) == 0) break; /* FALLTHROUGH */ default: printf(": could not map mem space\n"); return; } if (pci_intr_map(pa, &ih) != 0) { printf(": could not map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, nfe_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": could not establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s", intrstr); sc->sc_dmat = pa->pa_dmat; nfe_get_macaddr(sc, sc->sc_arpcom.ac_enaddr); printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); sc->sc_flags = 0; switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2: case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3: case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4: case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5: sc->sc_flags |= NFE_JUMBO_SUP | NFE_HW_CSUM; break; case PCI_PRODUCT_NVIDIA_MCP51_LAN1: case PCI_PRODUCT_NVIDIA_MCP51_LAN2: case PCI_PRODUCT_NVIDIA_MCP61_LAN1: case PCI_PRODUCT_NVIDIA_MCP61_LAN2: case PCI_PRODUCT_NVIDIA_MCP61_LAN3: case PCI_PRODUCT_NVIDIA_MCP61_LAN4: case PCI_PRODUCT_NVIDIA_MCP67_LAN1: case PCI_PRODUCT_NVIDIA_MCP67_LAN2: case PCI_PRODUCT_NVIDIA_MCP67_LAN3: case PCI_PRODUCT_NVIDIA_MCP67_LAN4: sc->sc_flags |= NFE_40BIT_ADDR; break; case PCI_PRODUCT_NVIDIA_CK804_LAN1: case PCI_PRODUCT_NVIDIA_CK804_LAN2: case PCI_PRODUCT_NVIDIA_MCP04_LAN1: case PCI_PRODUCT_NVIDIA_MCP04_LAN2: sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM; break; case PCI_PRODUCT_NVIDIA_MCP65_LAN1: case PCI_PRODUCT_NVIDIA_MCP65_LAN2: case PCI_PRODUCT_NVIDIA_MCP65_LAN3: case PCI_PRODUCT_NVIDIA_MCP65_LAN4: sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR; break; case PCI_PRODUCT_NVIDIA_MCP55_LAN1: case PCI_PRODUCT_NVIDIA_MCP55_LAN2: sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM | NFE_HW_VLAN; break; } /* enable jumbo frames for adapters that support it */ if (sc->sc_flags & NFE_JUMBO_SUP) sc->sc_flags |= NFE_USE_JUMBO; /* * Allocate Tx and Rx rings. */ if (nfe_alloc_tx_ring(sc, &sc->txq) != 0) { printf("%s: could not allocate Tx ring\n", sc->sc_dev.dv_xname); return; } if (nfe_alloc_rx_ring(sc, &sc->rxq) != 0) { printf("%s: could not allocate Rx ring\n", sc->sc_dev.dv_xname); nfe_free_tx_ring(sc, &sc->txq); return; } ifp = &sc->sc_arpcom.ac_if; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = nfe_ioctl; ifp->if_start = nfe_start; ifp->if_watchdog = nfe_watchdog; ifp->if_init = nfe_init; ifp->if_baudrate = IF_Gbps(1); IFQ_SET_MAXLEN(&ifp->if_snd, NFE_IFQ_MAXLEN); IFQ_SET_READY(&ifp->if_snd); strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); ifp->if_capabilities = IFCAP_VLAN_MTU; if (sc->sc_flags & NFE_USE_JUMBO) ifp->if_hardmtu = NFE_JUMBO_MTU; #if NVLAN > 0 if (sc->sc_flags & NFE_HW_VLAN) ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; #endif if (sc->sc_flags & NFE_HW_CSUM) { ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4; } sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = nfe_miibus_readreg; sc->sc_mii.mii_writereg = nfe_miibus_writereg; sc->sc_mii.mii_statchg = nfe_miibus_statchg; ifmedia_init(&sc->sc_mii.mii_media, 0, nfe_ifmedia_upd, nfe_ifmedia_sts); mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { printf("%s: no PHY found!\n", sc->sc_dev.dv_xname); ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); timeout_set(&sc->sc_tick_ch, nfe_tick, sc); sc->sc_powerhook = powerhook_establish(nfe_power, sc); }
/* * Attach an EPIC interface to the system. */ void epic_attach(struct epic_softc *sc, const char *intrstr) { bus_space_tag_t st = sc->sc_st; bus_space_handle_t sh = sc->sc_sh; struct ifnet *ifp = &sc->sc_arpcom.ac_if; int rseg, error, miiflags; u_int i; bus_dma_segment_t seg; u_int8_t enaddr[ETHER_ADDR_LEN], devname[12 + 1]; u_int16_t myea[ETHER_ADDR_LEN / 2], mydevname[6]; char *nullbuf; timeout_set(&sc->sc_mii_timeout, epic_tick, sc); /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct epic_control_data) + ETHER_PAD_LEN, PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { printf(": unable to allocate control data, error = %d\n", error); goto fail_0; } if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(struct epic_control_data) + ETHER_PAD_LEN, (caddr_t *)&sc->sc_control_data, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { printf(": unable to map control data, error = %d\n", error); goto fail_1; } nullbuf = (char *)sc->sc_control_data + sizeof(struct epic_control_data); memset(nullbuf, 0, ETHER_PAD_LEN); if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct epic_control_data), 1, sizeof(struct epic_control_data), 0, BUS_DMA_NOWAIT, &sc->sc_cddmamap)) != 0) { printf(": unable to create control data DMA map, error = %d\n", error); goto fail_2; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct epic_control_data), NULL, BUS_DMA_NOWAIT)) != 0) { printf(": unable to load control data DMA map, error = %d\n", error); goto fail_3; } /* * Create the transmit buffer DMA maps. */ for (i = 0; i < EPIC_NTXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, EPIC_NFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT, &EPIC_DSTX(sc, i)->ds_dmamap)) != 0) { printf(": unable to create tx DMA map %d, error = %d\n", i, error); goto fail_4; } } /* * Create the receive buffer DMA maps. */ for (i = 0; i < EPIC_NRXDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &EPIC_DSRX(sc, i)->ds_dmamap)) != 0) { printf(": unable to create rx DMA map %d, error = %d\n", i, error); goto fail_5; } EPIC_DSRX(sc, i)->ds_mbuf = NULL; } /* * create and map the pad buffer */ if ((error = bus_dmamap_create(sc->sc_dmat, ETHER_PAD_LEN, 1, ETHER_PAD_LEN, 0, BUS_DMA_NOWAIT,&sc->sc_nulldmamap)) != 0) { printf(": unable to create pad buffer DMA map, error = %d\n", error); goto fail_5; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_nulldmamap, nullbuf, ETHER_PAD_LEN, NULL, BUS_DMA_NOWAIT)) != 0) { printf(": unable to load pad buffer DMA map, error = %d\n", error); goto fail_6; } bus_dmamap_sync(sc->sc_dmat, sc->sc_nulldmamap, 0, ETHER_PAD_LEN, BUS_DMASYNC_PREWRITE); /* * Bring the chip out of low-power mode and reset it to a known state. */ bus_space_write_4(st, sh, EPIC_GENCTL, 0); epic_reset(sc); /* * Read the Ethernet address from the EEPROM. */ epic_read_eeprom(sc, 0, (sizeof(myea) / sizeof(myea[0])), myea); for (i = 0; i < sizeof(myea)/ sizeof(myea[0]); i++) { enaddr[i * 2] = myea[i] & 0xff; enaddr[i * 2 + 1] = myea[i] >> 8; } /* * ...and the device name. */ epic_read_eeprom(sc, 0x2c, (sizeof(mydevname) / sizeof(mydevname[0])), mydevname); for (i = 0; i < sizeof(mydevname) / sizeof(mydevname[0]); i++) { devname[i * 2] = mydevname[i] & 0xff; devname[i * 2 + 1] = mydevname[i] >> 8; } devname[sizeof(devname) - 1] = ' '; for (i = sizeof(devname) - 1; devname[i] == ' '; i--) { devname[i] = '\0'; if (i == 0) break; } printf(", %s : %s, address %s\n", devname, intrstr, ether_sprintf(enaddr)); miiflags = 0; if (sc->sc_hwflags & EPIC_HAS_MII_FIBER) miiflags |= MIIF_HAVEFIBER; /* * Initialize our media structures and probe the MII. */ sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = epic_mii_read; sc->sc_mii.mii_writereg = epic_mii_write; sc->sc_mii.mii_statchg = epic_statchg; ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, epic_mediachange, epic_mediastatus); mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, miiflags); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); if (sc->sc_hwflags & EPIC_HAS_BNC) { /* use the next free media instance */ sc->sc_serinst = sc->sc_mii.mii_instance++; ifmedia_add(&sc->sc_mii.mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc->sc_serinst), 0, NULL); } else sc->sc_serinst = -1; bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = epic_ioctl; ifp->if_start = epic_start; ifp->if_watchdog = epic_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, EPIC_NTXDESC - 1); IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities = IFCAP_VLAN_MTU; /* * Attach the interface. */ if_attach(ifp); ether_ifattach(ifp); return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: bus_dmamap_destroy(sc->sc_dmat, sc->sc_nulldmamap); fail_5: for (i = 0; i < EPIC_NRXDESC; i++) { if (EPIC_DSRX(sc, i)->ds_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, EPIC_DSRX(sc, i)->ds_dmamap); } fail_4: for (i = 0; i < EPIC_NTXDESC; i++) { if (EPIC_DSTX(sc, i)->ds_dmamap != NULL) bus_dmamap_destroy(sc->sc_dmat, EPIC_DSTX(sc, i)->ds_dmamap); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); fail_3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); fail_2: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data, sizeof(struct epic_control_data)); fail_1: bus_dmamem_free(sc->sc_dmat, &seg, rseg); fail_0: return; }
static int ed_pccard_attach(device_t dev) { u_char sum; u_char enaddr[ETHER_ADDR_LEN]; const struct ed_product *pp; int error, i, flags, port_rid, modem_rid; struct ed_softc *sc = device_get_softc(dev); u_long size; static uint16_t *intr_vals[] = {NULL, NULL}; sc->dev = dev; if ((pp = (const struct ed_product *) pccard_product_lookup(dev, (const struct pccard_product *) ed_pccard_products, sizeof(ed_pccard_products[0]), NULL)) == NULL) { printf("Can't find\n"); return (ENXIO); } modem_rid = port_rid = -1; if (pp->flags & NE2000DVF_MODEM) { for (i = 0; i < 4; i++) { size = bus_get_resource_count(dev, SYS_RES_IOPORT, i); if (size == ED_NOVELL_IO_PORTS) port_rid = i; else if (size == 8) modem_rid = i; } if (port_rid == -1) { device_printf(dev, "Cannot locate my ports!\n"); return (ENXIO); } } else { port_rid = 0; } /* Allocate the port resource during setup. */ error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS); if (error) { printf("alloc_port failed\n"); return (error); } if (rman_get_size(sc->port_res) == ED_NOVELL_IO_PORTS / 2) { port_rid++; sc->port_res2 = bus_alloc_resource(dev, SYS_RES_IOPORT, &port_rid, 0ul, ~0ul, 1, RF_ACTIVE); if (sc->port_res2 == NULL || rman_get_size(sc->port_res2) != ED_NOVELL_IO_PORTS / 2) { error = ENXIO; goto bad; } } error = ed_alloc_irq(dev, 0, 0); if (error) goto bad; /* * Determine which chipset we are. Almost all the PC Card chipsets * have the Novel ASIC and NIC offsets. There's 2 known cards that * follow the WD80x3 conventions, which are handled as a special case. */ sc->asic_offset = ED_NOVELL_ASIC_OFFSET; sc->nic_offset = ED_NOVELL_NIC_OFFSET; error = ENXIO; flags = device_get_flags(dev); if (error != 0) error = ed_pccard_dl100xx(dev, pp); if (error != 0) error = ed_pccard_ax88x90(dev, pp); if (error != 0) error = ed_pccard_tc5299j(dev, pp); if (error != 0) { error = ed_probe_Novell_generic(dev, flags); printf("Novell generic probe failed: %d\n", error); } if (error != 0 && (pp->flags & NE2000DVF_TOSHIBA)) { flags |= ED_FLAGS_TOSH_ETHER; flags |= ED_FLAGS_PCCARD; sc->asic_offset = ED_WD_ASIC_OFFSET; sc->nic_offset = ED_WD_NIC_OFFSET; error = ed_probe_WD80x3_generic(dev, flags, intr_vals); } if (error) goto bad; /* * There are several ways to get the MAC address for the card. * Some of the above probe routines can fill in the enaddr. If * not, we run through a number of 'well known' locations: * (1) From the PC Card FUNCE * (2) From offset 0 in the shared memory * (3) From a hinted offset in attribute memory * (4) From 0xff0 in attribute memory * If we can't get a non-zero MAC address from this list, we fail. */ for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) sum |= sc->enaddr[i]; if (sum == 0) { pccard_get_ether(dev, enaddr); if (bootverbose) device_printf(dev, "CIS MAC %6D\n", enaddr, ":"); for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) sum |= enaddr[i]; if (sum == 0 && ed_pccard_rom_mac(dev, enaddr)) { if (bootverbose) device_printf(dev, "ROM mac %6D\n", enaddr, ":"); sum++; } if (sum == 0 && pp->flags & NE2000DVF_ENADDR) { for (i = 0; i < ETHER_ADDR_LEN; i++) { pccard_attr_read_1(dev, pp->enoff + i * 2, enaddr + i); sum |= enaddr[i]; } if (bootverbose) device_printf(dev, "Hint %x MAC %6D\n", pp->enoff, enaddr, ":"); } if (sum == 0) { for (i = 0; i < ETHER_ADDR_LEN; i++) { pccard_attr_read_1(dev, ED_DEFAULT_MAC_OFFSET + i * 2, enaddr + i); sum |= enaddr[i]; } if (bootverbose) device_printf(dev, "Fallback MAC %6D\n", enaddr, ":"); } if (sum == 0) { device_printf(dev, "Cannot extract MAC address.\n"); ed_release_resources(dev); return (ENXIO); } bcopy(enaddr, sc->enaddr, ETHER_ADDR_LEN); } error = ed_attach(dev); if (error) goto bad; if (sc->chip_type == ED_CHIP_TYPE_DL10019 || sc->chip_type == ED_CHIP_TYPE_DL10022) { /* Try to attach an MII bus, but ignore errors. */ ed_pccard_dl100xx_mii_reset(sc); (void)mii_attach(dev, &sc->miibus, sc->ifp, ed_ifmedia_upd, ed_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, MIIF_FORCEANEG); } else if (sc->chip_type == ED_CHIP_TYPE_AX88190 || sc->chip_type == ED_CHIP_TYPE_AX88790 || sc->chip_type == ED_CHIP_TYPE_TC5299J) { error = mii_attach(dev, &sc->miibus, sc->ifp, ed_ifmedia_upd, ed_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, MIIF_FORCEANEG); if (error != 0) { device_printf(dev, "attaching PHYs failed\n"); goto bad; } } if (sc->miibus != NULL) { sc->sc_tick = ed_pccard_tick; sc->sc_mediachg = ed_pccard_mediachg; sc->sc_media_ioctl = ed_pccard_media_ioctl; ed_pccard_kick_phy(sc); } else { ed_gen_ifmedia_init(sc); } if (modem_rid != -1) ed_pccard_add_modem(dev); error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, NULL, edintr, sc, &sc->irq_handle); if (error) { device_printf(dev, "setup intr failed %d \n", error); goto bad; } return (0); bad: ed_detach(dev); return (error); }
void imxenet_attach(struct device *parent, struct device *self, void *args) { struct armv7_attach_args *aa = args; struct imxenet_softc *sc = (struct imxenet_softc *) self; struct mii_data *mii; struct ifnet *ifp; int tsize, rsize, tbsize, rbsize, s; sc->sc_iot = aa->aa_iot; if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr, aa->aa_dev->mem[0].size, 0, &sc->sc_ioh)) panic("imxenet_attach: bus_space_map failed!"); sc->sc_dma_tag = aa->aa_dmat; /* power it up */ clk_enable(clk_get("enet_ref")); clk_enable(clk_get("enet")); switch (board_id) { case BOARD_ID_IMX6_HUMMINGBOARD: imxgpio_set_dir(ENET_HUMMINGBOARD_PHY_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(ENET_HUMMINGBOARD_PHY_RST); delay(10); break; case BOARD_ID_IMX6_SABRELITE: /* SABRE Lite PHY reset */ imxgpio_set_dir(ENET_SABRELITE_PHY_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(ENET_SABRELITE_PHY_RST); delay(10); break; case BOARD_ID_IMX6_UDOO: // UDOO PHY reset imxgpio_set_dir(ENET_UDOO_PHY_RST, IMXGPIO_DIR_OUT); delay(10); imxgpio_set_bit(ENET_UDOO_PHY_RST); delay(10); break; } /* reset the controller */ HWRITE4(sc, ENET_ECR, ENET_ECR_RESET); while(HREAD4(sc, ENET_ECR) & ENET_ECR_RESET); HWRITE4(sc, ENET_EIMR, 0); HWRITE4(sc, ENET_EIR, 0xffffffff); sc->sc_ih = arm_intr_establish(aa->aa_dev->irq[0], IPL_NET, imxenet_intr, sc, sc->sc_dev.dv_xname); tsize = ENET_MAX_TXD * sizeof(struct imxenet_buf_desc); tsize = ENET_ROUNDUP(tsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, tsize, &sc->txdma)) { printf("%s: Unable to allocate tx_desc memory\n", sc->sc_dev.dv_xname); goto bad; } sc->tx_desc_base = (struct imxenet_buf_desc *)sc->txdma.dma_vaddr; rsize = ENET_MAX_RXD * sizeof(struct imxenet_buf_desc); rsize = ENET_ROUNDUP(rsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, rsize, &sc->rxdma)) { printf("%s: Unable to allocate rx_desc memory\n", sc->sc_dev.dv_xname); goto txdma; } sc->rx_desc_base = (struct imxenet_buf_desc *)sc->rxdma.dma_vaddr; tbsize = ENET_MAX_TXD * ENET_MAX_PKT_SIZE; tbsize = ENET_ROUNDUP(tbsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, tbsize, &sc->tbdma)) { printf("%s: Unable to allocate tx_buffer memory\n", sc->sc_dev.dv_xname); goto rxdma; } sc->tx_buffer_base = (struct imxenet_buffer *)sc->tbdma.dma_vaddr; rbsize = ENET_MAX_RXD * ENET_MAX_PKT_SIZE; rbsize = ENET_ROUNDUP(rbsize, PAGE_SIZE); if (imxenet_dma_malloc(sc, rbsize, &sc->rbdma)) { printf("%s: Unable to allocate rx_buffer memory\n", sc->sc_dev.dv_xname); goto tbdma; } sc->rx_buffer_base = (struct imxenet_buffer *)sc->rbdma.dma_vaddr; sc->cur_tx = 0; sc->cur_rx = 0; printf("\n"); s = splnet(); ifp = &sc->sc_ac.ac_if; ifp->if_softc = sc; strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = imxenet_ioctl; ifp->if_start = imxenet_start; ifp->if_capabilities = IFCAP_VLAN_MTU; memset(sc->sc_ac.ac_enaddr, 0xff, ETHER_ADDR_LEN); imxocotp_get_ethernet_address(sc->sc_ac.ac_enaddr); printf("%s: address %s\n", sc->sc_dev.dv_xname, ether_sprintf(sc->sc_ac.ac_enaddr)); /* initialize the chip */ imxenet_chip_init(sc); IFQ_SET_READY(&ifp->if_snd); /* Initialize MII/media info. */ mii = &sc->sc_mii; mii->mii_ifp = ifp; mii->mii_readreg = imxenet_miibus_readreg; mii->mii_writereg = imxenet_miibus_writereg; mii->mii_statchg = imxenet_miibus_statchg; mii->mii_flags = MIIF_AUTOTSLEEP; ifmedia_init(&mii->mii_media, 0, imxenet_ifmedia_upd, imxenet_ifmedia_sts); mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&mii->mii_phys) == NULL) { ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); } else ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); splx(s); imxenet_sc = sc; return; tbdma: imxenet_dma_free(sc, &sc->tbdma); rxdma: imxenet_dma_free(sc, &sc->rxdma); txdma: imxenet_dma_free(sc, &sc->txdma); bad: bus_space_unmap(sc->sc_iot, sc->sc_ioh, aa->aa_dev->mem[0].size); }
void smap_attach(struct device *parent, struct device *self, void *aux) { struct spd_attach_args *spa = aux; struct smap_softc *sc = (void *)self; struct emac3_softc *emac3 = &sc->emac3; struct ifnet *ifp = &sc->ethercom.ec_if; struct mii_data *mii = &emac3->mii; void *txbuf, *rxbuf; u_int16_t r; #ifdef SMAP_DEBUG __sc = sc; #endif printf(": %s\n", spa->spa_product_name); /* SPD EEPROM */ if (smap_get_eaddr(sc, emac3->eaddr) != 0) return; printf("%s: Ethernet address %s\n", DEVNAME, ether_sprintf(emac3->eaddr)); /* disable interrupts */ r = _reg_read_2(SPD_INTR_ENABLE_REG16); r &= ~(SPD_INTR_RXEND | SPD_INTR_TXEND | SPD_INTR_RXDNV | SPD_INTR_EMAC3); _reg_write_2(SPD_INTR_ENABLE_REG16, r); emac3_intr_disable(); /* clear pending interrupts */ _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND | SPD_INTR_RXDNV); emac3_intr_clear(); /* buffer descriptor mode */ _reg_write_1(SMAP_DESC_MODE_REG8, 0); if (smap_fifo_init(sc) != 0) return; if (emac3_init(&sc->emac3) != 0) return; emac3_intr_disable(); emac3_disable(); smap_desc_init(sc); /* allocate temporary buffer */ txbuf = malloc(ETHER_MAX_LEN - ETHER_CRC_LEN + SMAP_FIFO_ALIGN + 16, M_DEVBUF, M_NOWAIT); if (txbuf == NULL) { printf("%s: no memory.\n", DEVNAME); return; } rxbuf = malloc(ETHER_MAX_LEN + SMAP_FIFO_ALIGN + 16, M_DEVBUF, M_NOWAIT); if (rxbuf == NULL) { printf("%s: no memory.\n", DEVNAME); free(txbuf, M_DEVBUF); return; } sc->tx_buf = (u_int32_t *)ROUND16((vaddr_t)txbuf); sc->rx_buf = (u_int32_t *)ROUND16((vaddr_t)rxbuf); /* * setup MI layer */ strcpy(ifp->if_xname, DEVNAME); ifp->if_softc = sc; ifp->if_start = smap_start; ifp->if_ioctl = smap_ioctl; ifp->if_init = smap_init; ifp->if_stop = smap_stop; ifp->if_watchdog= smap_watchdog; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); /* ifmedia setup. */ mii->mii_ifp = ifp; mii->mii_readreg = emac3_phy_readreg; mii->mii_writereg = emac3_phy_writereg; mii->mii_statchg = emac3_phy_statchg; sc->ethercom.ec_mii = mii; ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); mii_attach(&emac3->dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); /* Choose a default media. */ if (LIST_FIRST(&mii->mii_phys) == NULL) { ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE); } else { ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); } if_attach(ifp); ether_ifattach(ifp, emac3->eaddr); spd_intr_establish(SPD_NIC, smap_intr, sc); #if NRND > 0 rnd_attach_source(&sc->rnd_source, DEVNAME, RND_TYPE_NET, RND_FLAG_DEFAULT); #endif }
void vte_attach(struct device *parent, struct device *self, void *aux) { struct vte_softc *sc = (struct vte_softc *)self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr; struct ifnet *ifp; pcireg_t memtype; int error = 0; memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, VTE_PCI_LOMEM); if (pci_mapreg_map(pa, VTE_PCI_LOMEM, memtype, 0, &sc->sc_mem_bt, &sc->sc_mem_bh, NULL, &sc->sc_mem_size, 0)) { printf(": can't map mem space\n"); return; } if (pci_intr_map(pa, &ih) != 0) { printf(": can't map interrupt\n"); goto fail; } /* * Allocate IRQ */ intrstr = pci_intr_string(pc, ih); sc->sc_irq_handle = pci_intr_establish(pc, ih, IPL_NET, vte_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_irq_handle == NULL) { printf(": could not establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); goto fail; } printf(": %s", intrstr); sc->sc_dmat = pa->pa_dmat; sc->sc_pct = pa->pa_pc; sc->sc_pcitag = pa->pa_tag; /* Reset the ethernet controller. */ vte_reset(sc); error = vte_dma_alloc(sc); if (error) goto fail; /* Load station address. */ vte_get_macaddr(sc); ifp = &sc->sc_arpcom.ac_if; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = vte_ioctl; ifp->if_start = vte_start; ifp->if_watchdog = vte_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, VTE_TX_RING_CNT - 1); IFQ_SET_READY(&ifp->if_snd); bcopy(sc->vte_eaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN); bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_capabilities = IFCAP_VLAN_MTU; printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); /* * Set up MII bus. * BIOS would have initialized VTE_MPSCCR to catch PHY * status changes so driver may be able to extract * configured PHY address. Since it's common to see BIOS * fails to initialize the register(including the sample * board I have), let mii(4) probe it. This is more * reliable than relying on BIOS's initialization. * * Advertising flow control capability to mii(4) was * intentionally disabled due to severe problems in TX * pause frame generation. See vte_rxeof() for more * details. */ sc->sc_miibus.mii_ifp = ifp; sc->sc_miibus.mii_readreg = vte_miibus_readreg; sc->sc_miibus.mii_writereg = vte_miibus_writereg; sc->sc_miibus.mii_statchg = vte_miibus_statchg; ifmedia_init(&sc->sc_miibus.mii_media, 0, vte_mediachange, vte_mediastatus); mii_attach(self, &sc->sc_miibus, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_miibus.mii_phys) == NULL) { printf("%s: no PHY found!\n", sc->sc_dev.dv_xname); ifmedia_add(&sc->sc_miibus.mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_miibus.mii_media, IFM_ETHER | IFM_MANUAL); } else ifmedia_set(&sc->sc_miibus.mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); timeout_set(&sc->vte_tick_ch, vte_tick, sc); return; fail: vte_detach(&sc->sc_dev, 0); }
void nfe_attach(struct device *parent, struct device *self, void *aux) { struct nfe_softc *sc = (struct nfe_softc *)self; struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; const char *intrstr; struct ifnet *ifp; bus_size_t memsize; pcireg_t memtype; memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, NFE_PCI_BA); if (pci_mapreg_map(pa, NFE_PCI_BA, memtype, 0, &sc->sc_memt, &sc->sc_memh, NULL, &memsize, 0)) { printf(": can't map mem space\n"); return; } if (pci_intr_map(pa, &ih) != 0) { printf(": can't map interrupt\n"); return; } intrstr = pci_intr_string(pc, ih); sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, nfe_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { printf(": could not establish interrupt"); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } printf(": %s", intrstr); sc->sc_dmat = pa->pa_dmat; sc->sc_flags = 0; switch (PCI_PRODUCT(pa->pa_id)) { case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2: case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3: case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4: case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5: sc->sc_flags |= NFE_JUMBO_SUP | NFE_HW_CSUM; break; case PCI_PRODUCT_NVIDIA_MCP51_LAN1: case PCI_PRODUCT_NVIDIA_MCP51_LAN2: sc->sc_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT; break; case PCI_PRODUCT_NVIDIA_MCP61_LAN1: case PCI_PRODUCT_NVIDIA_MCP61_LAN2: case PCI_PRODUCT_NVIDIA_MCP61_LAN3: case PCI_PRODUCT_NVIDIA_MCP61_LAN4: case PCI_PRODUCT_NVIDIA_MCP67_LAN1: case PCI_PRODUCT_NVIDIA_MCP67_LAN2: case PCI_PRODUCT_NVIDIA_MCP67_LAN3: case PCI_PRODUCT_NVIDIA_MCP67_LAN4: case PCI_PRODUCT_NVIDIA_MCP73_LAN1: case PCI_PRODUCT_NVIDIA_MCP73_LAN2: case PCI_PRODUCT_NVIDIA_MCP73_LAN3: case PCI_PRODUCT_NVIDIA_MCP73_LAN4: sc->sc_flags |= NFE_40BIT_ADDR | NFE_CORRECT_MACADDR | NFE_PWR_MGMT; break; case PCI_PRODUCT_NVIDIA_MCP77_LAN1: case PCI_PRODUCT_NVIDIA_MCP77_LAN2: case PCI_PRODUCT_NVIDIA_MCP77_LAN3: case PCI_PRODUCT_NVIDIA_MCP77_LAN4: sc->sc_flags |= NFE_40BIT_ADDR | NFE_HW_CSUM | NFE_CORRECT_MACADDR | NFE_PWR_MGMT; break; case PCI_PRODUCT_NVIDIA_MCP79_LAN1: case PCI_PRODUCT_NVIDIA_MCP79_LAN2: case PCI_PRODUCT_NVIDIA_MCP79_LAN3: case PCI_PRODUCT_NVIDIA_MCP79_LAN4: case PCI_PRODUCT_NVIDIA_MCP89_LAN: sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM | NFE_CORRECT_MACADDR | NFE_PWR_MGMT; break; case PCI_PRODUCT_NVIDIA_CK804_LAN1: case PCI_PRODUCT_NVIDIA_CK804_LAN2: case PCI_PRODUCT_NVIDIA_MCP04_LAN1: case PCI_PRODUCT_NVIDIA_MCP04_LAN2: sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM; break; case PCI_PRODUCT_NVIDIA_MCP65_LAN1: case PCI_PRODUCT_NVIDIA_MCP65_LAN2: case PCI_PRODUCT_NVIDIA_MCP65_LAN3: case PCI_PRODUCT_NVIDIA_MCP65_LAN4: sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_CORRECT_MACADDR | NFE_PWR_MGMT; break; case PCI_PRODUCT_NVIDIA_MCP55_LAN1: case PCI_PRODUCT_NVIDIA_MCP55_LAN2: sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM | NFE_HW_VLAN | NFE_PWR_MGMT; break; } if (sc->sc_flags & NFE_PWR_MGMT) { NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | NFE_RXTX_BIT2); NFE_WRITE(sc, NFE_MAC_RESET, NFE_MAC_RESET_MAGIC); DELAY(100); NFE_WRITE(sc, NFE_MAC_RESET, 0); DELAY(100); NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT2); NFE_WRITE(sc, NFE_PWR2_CTL, NFE_READ(sc, NFE_PWR2_CTL) & ~NFE_PWR2_WAKEUP_MASK); } nfe_get_macaddr(sc, sc->sc_arpcom.ac_enaddr); printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); /* * Allocate Tx and Rx rings. */ if (nfe_alloc_tx_ring(sc, &sc->txq) != 0) { printf("%s: could not allocate Tx ring\n", sc->sc_dev.dv_xname); return; } if (nfe_alloc_rx_ring(sc, &sc->rxq) != 0) { printf("%s: could not allocate Rx ring\n", sc->sc_dev.dv_xname); nfe_free_tx_ring(sc, &sc->txq); return; } ifp = &sc->sc_arpcom.ac_if; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = nfe_ioctl; ifp->if_start = nfe_start; ifp->if_watchdog = nfe_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, NFE_IFQ_MAXLEN); IFQ_SET_READY(&ifp->if_snd); strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); ifp->if_capabilities = IFCAP_VLAN_MTU; #ifndef SMALL_KERNEL ifp->if_capabilities |= IFCAP_WOL; ifp->if_wol = nfe_wol; nfe_wol(ifp, 0); #endif #if NVLAN > 0 if (sc->sc_flags & NFE_HW_VLAN) ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; #endif if (sc->sc_flags & NFE_HW_CSUM) { ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4; } sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = nfe_miibus_readreg; sc->sc_mii.mii_writereg = nfe_miibus_writereg; sc->sc_mii.mii_statchg = nfe_miibus_statchg; ifmedia_init(&sc->sc_mii.mii_media, 0, nfe_ifmedia_upd, nfe_ifmedia_sts); mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, 0, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { printf("%s: no PHY found!\n", sc->sc_dev.dv_xname); ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL); } else ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); timeout_set(&sc->sc_tick_ch, nfe_tick, sc); }
void tsec_attach(struct device *parent, struct device *self, void *aux) { struct tsec_softc *sc = (void *)self; struct obio_attach_args *oa = aux; struct ifnet *ifp; int phy, n; if (OF_getprop(oa->oa_node, "phy-handle", &phy, sizeof(phy)) == sizeof(phy)) { int node, reg; node = tsec_find_phy(OF_peer(0), phy); if (node == -1 || OF_getprop(node, "reg", ®, sizeof(reg)) != sizeof(reg)) { printf(": can't find PHY\n"); return; } oa->oa_phy = reg; } /* Map registers for TSEC1 & TSEC2 if they're not mapped yet. */ if (oa->oa_iot != tsec_iot) { tsec_iot = oa->oa_iot; if (bus_space_map(tsec_iot, oa->oa_offset & 0xffffc000, 8192, 0, &tsec_ioh)) { printf(": can't map registers\n"); return; } } sc->sc_iot = tsec_iot; sc->sc_dmat = oa->oa_dmat; /* Ethernet Controller registers. */ bus_space_subregion(tsec_iot, tsec_ioh, oa->oa_offset & 0x3fff, 3072, &sc->sc_ioh); /* MII Management registers. */ bus_space_subregion(tsec_iot, tsec_ioh, 0, 3072, &sc->sc_mii_ioh); myetheraddr(sc->sc_lladdr); printf(": address %s\n", ether_sprintf(sc->sc_lladdr)); timeout_set(&sc->sc_tick, tsec_tick, sc); ifp = &sc->sc_ac.ac_if; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = tsec_ioctl; ifp->if_start = tsec_start; ifp->if_watchdog = tsec_watchdog; IFQ_SET_MAXLEN(&ifp->if_snd, TSEC_NTXDESC - 1); IFQ_SET_READY(&ifp->if_snd); bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); m_clsetwms(ifp, MCLBYTES, 0, TSEC_NRXDESC); ifp->if_capabilities = IFCAP_VLAN_MTU; sc->sc_mii.mii_ifp = ifp; sc->sc_mii.mii_readreg = tsec_mii_readreg; sc->sc_mii.mii_writereg = tsec_mii_writereg; sc->sc_mii.mii_statchg = tsec_mii_statchg; ifmedia_init(&sc->sc_media, 0, tsec_media_change, tsec_media_status); tsec_reset(sc); /* Reset management. */ tsec_write(sc, TSEC_MIIMCFG, TSEC_MIIMCFG_RESET); tsec_write(sc, TSEC_MIIMCFG, 0x00000003); for (n = 0; n < 100; n++) { if ((tsec_read(sc, TSEC_MIIMIND) & TSEC_MIIMIND_BUSY) == 0) break; } mii_attach(self, &sc->sc_mii, 0xffffffff, oa->oa_phy, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { printf("%s: no PHY found!\n", sc->sc_dev.dv_xname); ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); } else ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO); if_attach(ifp); ether_ifattach(ifp); intr_establish(oa->oa_ivec, IST_LEVEL, IPL_NET, tsec_txintr, sc, sc->sc_dev.dv_xname); intr_establish(oa->oa_ivec + 1, IST_LEVEL, IPL_NET, tsec_rxintr, sc, sc->sc_dev.dv_xname); intr_establish(oa->oa_ivec + 2, IST_LEVEL, IPL_NET, tsec_errintr, sc, sc->sc_dev.dv_xname); }