static int admsw_attach(device_t dev) { uint8_t enaddr[ETHER_ADDR_LEN]; struct admsw_softc *sc = (struct admsw_softc *) device_get_softc(dev); struct ifnet *ifp; int error, i, rid; sc->sc_dev = dev; device_printf(dev, "ADM5120 Switch Engine, %d ports\n", SW_DEVS); sc->ndevs = 0; /* XXXMIPS: fix it */ enaddr[0] = 0x00; enaddr[1] = 0x0C; enaddr[2] = 0x42; enaddr[3] = 0x07; enaddr[4] = 0xB2; enaddr[5] = 0x4E; memcpy(sc->sc_enaddr, enaddr, sizeof(sc->sc_enaddr)); device_printf(sc->sc_dev, "base Ethernet address %s\n", ether_sprintf(enaddr)); callout_init(&sc->sc_watchdog, 1); rid = 0; if ((sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) { device_printf(dev, "unable to allocate memory resource\n"); return (ENXIO); } /* Hook up the interrupt handler. */ rid = 0; if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { device_printf(dev, "unable to allocate IRQ resource\n"); return (ENXIO); } if ((error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, admsw_intr, NULL, sc, &sc->sc_ih)) != 0) { device_printf(dev, "WARNING: unable to register interrupt handler\n"); return (error); } /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, sizeof(struct admsw_control_data), 1, sizeof(struct admsw_control_data), 0, NULL, NULL, &sc->sc_control_dmat)) != 0) { device_printf(sc->sc_dev, "unable to create control data DMA map, error = %d\n", error); return (error); } if ((error = bus_dmamem_alloc(sc->sc_control_dmat, (void **)&sc->sc_control_data, BUS_DMA_NOWAIT, &sc->sc_cddmamap)) != 0) { device_printf(sc->sc_dev, "unable to allocate control data, error = %d\n", error); return (error); } if ((error = bus_dmamap_load(sc->sc_control_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct admsw_control_data), admsw_dma_map_addr, &sc->sc_cddma, 0)) != 0) { device_printf(sc->sc_dev, "unable to load control data DMA map, error = %d\n", error); return (error); } /* * Create the transmit buffer DMA maps. */ if ((error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, 0, NULL, NULL, &sc->sc_bufs_dmat)) != 0) { device_printf(sc->sc_dev, "unable to create control data DMA map, error = %d\n", error); return (error); } for (i = 0; i < ADMSW_NTXHDESC; i++) { if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, &sc->sc_txhsoft[i].ds_dmamap)) != 0) { device_printf(sc->sc_dev, "unable to create txh DMA map %d, error = %d\n", i, error); return (error); } sc->sc_txhsoft[i].ds_mbuf = NULL; } for (i = 0; i < ADMSW_NTXLDESC; i++) { if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, &sc->sc_txlsoft[i].ds_dmamap)) != 0) { device_printf(sc->sc_dev, "unable to create txl DMA map %d, error = %d\n", i, error); return (error); } sc->sc_txlsoft[i].ds_mbuf = NULL; } /* * Create the receive buffer DMA maps. */ for (i = 0; i < ADMSW_NRXHDESC; i++) { if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, &sc->sc_rxhsoft[i].ds_dmamap)) != 0) { device_printf(sc->sc_dev, "unable to create rxh DMA map %d, error = %d\n", i, error); return (error); } sc->sc_rxhsoft[i].ds_mbuf = NULL; } for (i = 0; i < ADMSW_NRXLDESC; i++) { if ((error = bus_dmamap_create(sc->sc_bufs_dmat, 0, &sc->sc_rxlsoft[i].ds_dmamap)) != 0) { device_printf(sc->sc_dev, "unable to create rxl DMA map %d, error = %d\n", i, error); return (error); } sc->sc_rxlsoft[i].ds_mbuf = NULL; } admsw_init_bufs(sc); admsw_reset(sc); for (i = 0; i < SW_DEVS; i++) { ifmedia_init(&sc->sc_ifmedia[i], 0, admsw_mediachange, admsw_mediastatus); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_10_T, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_100_TX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO); ifp = sc->sc_ifnet[i] = if_alloc(IFT_ETHER); /* Setup interface parameters */ ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), i); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = admsw_ioctl; ifp->if_output = ether_output; ifp->if_start = admsw_start; ifp->if_init = admsw_init; ifp->if_mtu = ETHERMTU; ifp->if_baudrate = IF_Mbps(100); IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, ifqmaxlen)); ifp->if_snd.ifq_drv_maxlen = max(ADMSW_NTXLDESC, ifqmaxlen); IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities |= IFCAP_VLAN_MTU; /* Attach the interface. */ ether_ifattach(ifp, enaddr); enaddr[5]++; } /* XXX: admwdog_attach(sc); */ /* leave interrupts and cpu port disabled */ return (0); }
static void admsw_attach(device_t parent, device_t self, void *aux) { uint8_t enaddr[ETHER_ADDR_LEN]; struct admsw_softc *sc = device_private(self); struct obio_attach_args *aa = aux; struct ifnet *ifp; bus_dma_segment_t seg; int error, i, rseg; prop_data_t pd; printf(": ADM5120 Switch Engine, %d ports\n", SW_DEVS); sc->sc_dev = self; sc->sc_dmat = aa->oba_dt; sc->sc_st = aa->oba_st; pd = prop_dictionary_get(device_properties(self), "mac-address"); if (pd == NULL) { enaddr[0] = 0x02; enaddr[1] = 0xaa; enaddr[2] = 0xbb; enaddr[3] = 0xcc; enaddr[4] = 0xdd; enaddr[5] = 0xee; } else memcpy(enaddr, prop_data_data_nocopy(pd), sizeof(enaddr)); memcpy(sc->sc_enaddr, enaddr, sizeof(sc->sc_enaddr)); printf("%s: base Ethernet address %s\n", device_xname(sc->sc_dev), ether_sprintf(enaddr)); /* Map the device. */ if (bus_space_map(sc->sc_st, aa->oba_addr, 512, 0, &sc->sc_ioh) != 0) { printf("%s: unable to map device\n", device_xname(sc->sc_dev)); return; } /* Hook up the interrupt handler. */ sc->sc_ih = adm5120_intr_establish(aa->oba_irq, INTR_IRQ, admsw_intr, sc); if (sc->sc_ih == NULL) { printf("%s: unable to register interrupt handler\n", device_xname(sc->sc_dev)); return; } /* * Allocate the control data structures, and create and load the * DMA map for it. */ if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct admsw_control_data), PAGE_SIZE, 0, &seg, 1, &rseg, 0)) != 0) { printf("%s: unable to allocate control data, error = %d\n", device_xname(sc->sc_dev), error); return; } if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, sizeof(struct admsw_control_data), (void *)&sc->sc_control_data, 0)) != 0) { printf("%s: unable to map control data, error = %d\n", device_xname(sc->sc_dev), error); return; } if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct admsw_control_data), 1, sizeof(struct admsw_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); return; } if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, sc->sc_control_data, sizeof(struct admsw_control_data), NULL, 0)) != 0) { printf("%s: unable to load control data DMA map, error = %d\n", device_xname(sc->sc_dev), error); return; } /* * Create the transmit buffer DMA maps. */ for (i = 0; i < ADMSW_NTXHDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 2, MCLBYTES, 0, 0, &sc->sc_txhsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create txh DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_txhsoft[i].ds_mbuf = NULL; } for (i = 0; i < ADMSW_NTXLDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 2, MCLBYTES, 0, 0, &sc->sc_txlsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create txl DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_txlsoft[i].ds_mbuf = NULL; } /* * Create the receive buffer DMA maps. */ for (i = 0; i < ADMSW_NRXHDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxhsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create rxh DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_rxhsoft[i].ds_mbuf = NULL; } for (i = 0; i < ADMSW_NRXLDESC; i++) { if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0, &sc->sc_rxlsoft[i].ds_dmamap)) != 0) { printf("%s: unable to create rxl DMA map %d, " "error = %d\n", device_xname(sc->sc_dev), i, error); return; } sc->sc_rxlsoft[i].ds_mbuf = NULL; } admsw_init_bufs(sc); admsw_reset(sc); for (i = 0; i < SW_DEVS; i++) { ifmedia_init(&sc->sc_ifmedia[i], 0, admsw_mediachange, admsw_mediastatus); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_10_T, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_100_TX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_ifmedia[i], IFM_ETHER|IFM_AUTO); ifp = &sc->sc_ethercom[i].ec_if; strcpy(ifp->if_xname, device_xname(sc->sc_dev)); ifp->if_xname[5] += i; ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = admsw_ioctl; ifp->if_start = admsw_start; ifp->if_watchdog = admsw_watchdog; ifp->if_init = admsw_init; ifp->if_stop = admsw_stop; ifp->if_capabilities |= IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx; IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, IFQ_MAXLEN)); IFQ_SET_READY(&ifp->if_snd); /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, enaddr); enaddr[5]++; } #ifdef ADMSW_EVENT_COUNTERS evcnt_attach_dynamic(&sc->sc_ev_txstall, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "txstall"); evcnt_attach_dynamic(&sc->sc_ev_rxstall, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "rxstall"); evcnt_attach_dynamic(&sc->sc_ev_txintr, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "txintr"); evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "rxintr"); #if 1 evcnt_attach_dynamic(&sc->sc_ev_rxsync, EVCNT_TYPE_MISC, NULL, device_xname(sc->sc_dev), "rxsync"); #endif #endif admwdog_attach(sc); /* Make sure the interface is shutdown during reboot. */ sc->sc_sdhook = shutdownhook_establish(admsw_shutdown, sc); if (sc->sc_sdhook == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", device_xname(sc->sc_dev)); /* leave interrupts and cpu port disabled */ return; }