static int le_isa_detach(device_t dev) { struct le_isa_softc *lesc; struct lance_softc *sc; lesc = device_get_softc(dev); sc = &lesc->sc_am7990.lsc; if (device_is_attached(dev)) { lwkt_serialize_enter(sc->ifp->if_serializer); lance_stop(sc); bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); lwkt_serialize_exit(sc->ifp->if_serializer); am7990_detach(&lesc->sc_am7990); } if (lesc->sc_ires) bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); if (lesc->sc_dres) bus_release_resource(dev, SYS_RES_DRQ, lesc->sc_drid, lesc->sc_dres); if (lesc->sc_rres) bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); if (lesc->sc_dmam) { bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); } if (lesc->sc_dmat) bus_dma_tag_destroy(lesc->sc_dmat); if (lesc->sc_pdmat) bus_dma_tag_destroy(lesc->sc_pdmat); return (0); }
static int le_isa_detach(device_t dev) { struct le_isa_softc *lesc; struct lance_softc *sc; lesc = device_get_softc(dev); sc = &lesc->sc_am7990.lsc; bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); am7990_detach(&lesc->sc_am7990); bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); bus_dma_tag_destroy(lesc->sc_dmat); bus_dma_tag_destroy(lesc->sc_pdmat); bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), lesc->sc_ires); bus_release_resource(dev, SYS_RES_DRQ, rman_get_rid(lesc->sc_dres), lesc->sc_dres); bus_release_resource(dev, SYS_RES_IOPORT, rman_get_rid(lesc->sc_rres), lesc->sc_rres); LE_LOCK_DESTROY(sc); return (0); }
static int le_dma_detach(device_t dev) { struct le_dma_softc *lesc; struct lance_softc *sc; int error; lesc = device_get_softc(dev); sc = &lesc->sc_am7990.lsc; bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); am7990_detach(&lesc->sc_am7990); bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); bus_dma_tag_destroy(lesc->sc_dmat); error = lsi64854_detach(lesc->sc_dma); if (error != 0) return (error); bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), lesc->sc_ires); bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres), lesc->sc_rres); LE_LOCK_DESTROY(sc); return (0); }
static int le_lebuffer_detach(device_t dev) { struct le_lebuffer_softc *lesc; struct lance_softc *sc; lesc = device_get_softc(dev); sc = &lesc->sc_am7990.lsc; bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); am7990_detach(&lesc->sc_am7990); bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres); bus_release_resource(device_get_parent(dev), SYS_RES_MEMORY, lesc->sc_brid, lesc->sc_bres); LE_LOCK_DESTROY(sc); return (0); }
static int le_lebuffer_attach(device_t dev) { struct le_lebuffer_softc *lesc; struct lance_softc *sc; int error, i; lesc = device_get_softc(dev); sc = &lesc->sc_am7990.lsc; LE_LOCK_INIT(sc, device_get_nameunit(dev)); /* * The "register space" of the parent is just a buffer where the * the LANCE descriptor rings and the RX/TX buffers can be stored. */ i = 0; lesc->sc_bres = bus_alloc_resource_any(device_get_parent(dev), SYS_RES_MEMORY, &i, RF_ACTIVE); if (lesc->sc_bres == NULL) { device_printf(dev, "cannot allocate LANCE buffer\n"); error = ENXIO; goto fail_mtx; } /* Allocate LANCE registers. */ i = 0; lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, RF_ACTIVE); if (lesc->sc_rres == NULL) { device_printf(dev, "cannot allocate LANCE registers\n"); error = ENXIO; goto fail_bres; } /* Allocate LANCE interrupt. */ i = 0; if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { device_printf(dev, "cannot allocate interrupt\n"); error = ENXIO; goto fail_rres; } /* * LANCE view is offset by buffer location. * Note that we don't use sc->sc_mem. */ sc->sc_addr = 0; sc->sc_memsize = rman_get_size(lesc->sc_bres); sc->sc_flags = 0; /* That old black magic... */ if (OF_getprop(ofw_bus_get_node(dev), "busmaster-regval", &sc->sc_conf3, sizeof(sc->sc_conf3)) == -1) sc->sc_conf3 = LE_C3_ACON | LE_C3_BCON; /* * Make sure LE_C3_BSWP is cleared so that for cards where * that flag actually works le_lebuffer_copy{from,to}buf() * don't fail... */ sc->sc_conf3 &= ~LE_C3_BSWP; OF_getetheraddr(dev, sc->sc_enaddr); sc->sc_copytodesc = le_lebuffer_copytodesc; sc->sc_copyfromdesc = le_lebuffer_copyfromdesc; sc->sc_copytobuf = le_lebuffer_copytobuf; sc->sc_copyfrombuf = le_lebuffer_copyfrombuf; sc->sc_zerobuf = le_lebuffer_zerobuf; sc->sc_rdcsr = le_lebuffer_rdcsr; sc->sc_wrcsr = le_lebuffer_wrcsr; sc->sc_hwreset = NULL; sc->sc_hwinit = NULL; sc->sc_hwintr = NULL; sc->sc_nocarrier = NULL; sc->sc_mediachange = NULL; sc->sc_mediastatus = NULL; sc->sc_supmedia = le_lebuffer_media; sc->sc_nsupmedia = NLEMEDIA; sc->sc_defaultmedia = le_lebuffer_media[0]; error = am7990_config(&lesc->sc_am7990, device_get_name(dev), device_get_unit(dev)); if (error != 0) { device_printf(dev, "cannot attach Am7990\n"); goto fail_ires; } error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, NULL, am7990_intr, sc, &lesc->sc_ih); if (error != 0) { device_printf(dev, "cannot set up interrupt\n"); goto fail_am7990; } return (0); fail_am7990: am7990_detach(&lesc->sc_am7990); fail_ires: bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), lesc->sc_ires); fail_rres: bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres), lesc->sc_rres); fail_bres: bus_release_resource(device_get_parent(dev), SYS_RES_MEMORY, rman_get_rid(lesc->sc_bres), lesc->sc_bres); fail_mtx: LE_LOCK_DESTROY(sc); return (error); }
static int le_isa_attach(device_t dev) { struct le_isa_softc *lesc; struct lance_softc *sc; bus_size_t macstart, rap, rdp; int error, i, macstride; lesc = device_get_softc(dev); sc = &lesc->sc_am7990.lsc; lesc->sc_rrid = 0; switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) { case 0: lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &lesc->sc_rrid, RF_ACTIVE); rap = PCNET_RAP; rdp = PCNET_RDP; macstart = 0; macstride = 1; break; case ENOENT: for (i = 0; i < NELEM(le_isa_params); i++) { if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) { lesc->sc_rres = bus_alloc_resource(dev, SYS_RES_IOPORT, &lesc->sc_rrid, 0, ~0, le_isa_params[i].iosize, RF_ACTIVE); rap = le_isa_params[i].rap; rdp = le_isa_params[i].rdp; macstart = le_isa_params[i].macstart; macstride = le_isa_params[i].macstride; goto found; } } /* FALLTHROUGH */ case ENXIO: default: device_printf(dev, "cannot determine chip\n"); error = ENXIO; goto fail_mtx; } found: if (lesc->sc_rres == NULL) { device_printf(dev, "cannot allocate registers\n"); error = ENXIO; goto fail_mtx; } lesc->sc_regt = rman_get_bustag(lesc->sc_rres); lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); lesc->sc_rap = rap; lesc->sc_rdp = rdp; lesc->sc_drid = 0; if ((lesc->sc_dres = bus_alloc_resource_any(dev, SYS_RES_DRQ, &lesc->sc_drid, RF_ACTIVE)) == NULL) { device_printf(dev, "cannot allocate DMA channel\n"); error = ENXIO; goto fail_rres; } lesc->sc_irid = 0; if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { device_printf(dev, "cannot allocate interrupt\n"); error = ENXIO; goto fail_dres; } error = bus_dma_tag_create( NULL, /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 0, /* nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ BUS_DMA_WAITOK, /* flags */ &lesc->sc_pdmat); if (error != 0) { device_printf(dev, "cannot allocate parent DMA tag\n"); goto fail_ires; } sc->sc_memsize = LE_ISA_MEMSIZE; /* * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte * aligned and the ring descriptors must be 8-byte aligned. */ error = bus_dma_tag_create( lesc->sc_pdmat, /* parent */ 8, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->sc_memsize, /* maxsize */ 1, /* nsegments */ sc->sc_memsize, /* maxsegsize */ BUS_DMA_WAITOK, /* flags */ &lesc->sc_dmat); if (error != 0) { device_printf(dev, "cannot allocate buffer DMA tag\n"); goto fail_pdtag; } error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); if (error != 0) { device_printf(dev, "cannot allocate DMA buffer memory\n"); goto fail_dtag; } sc->sc_addr = 0; error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, sc->sc_memsize, le_isa_dma_callback, sc, 0); if (error != 0 || sc->sc_addr == 0) { device_printf(dev, "cannot load DMA buffer map\n"); goto fail_dmem; } isa_dmacascade(rman_get_start(lesc->sc_dres)); sc->sc_flags = 0; sc->sc_conf3 = 0; /* * Extract the physical MAC address from the ROM. */ for (i = 0; i < sizeof(sc->sc_enaddr); i++) sc->sc_enaddr[i] = bus_space_read_1(lesc->sc_regt, lesc->sc_regh, macstart + i * macstride); sc->sc_copytodesc = lance_copytobuf_contig; sc->sc_copyfromdesc = lance_copyfrombuf_contig; sc->sc_copytobuf = lance_copytobuf_contig; sc->sc_copyfrombuf = lance_copyfrombuf_contig; sc->sc_zerobuf = lance_zerobuf_contig; sc->sc_rdcsr = le_isa_rdcsr; sc->sc_wrcsr = le_isa_wrcsr; sc->sc_hwreset = NULL; sc->sc_hwinit = NULL; sc->sc_hwintr = NULL; sc->sc_nocarrier = NULL; sc->sc_mediachange = NULL; sc->sc_mediastatus = NULL; sc->sc_supmedia = NULL; error = am7990_config(&lesc->sc_am7990, device_get_name(dev), device_get_unit(dev)); if (error != 0) { device_printf(dev, "cannot attach Am7990\n"); goto fail_dmap; } ifq_set_cpuid(&sc->ifp->if_snd, rman_get_cpuid(lesc->sc_ires)); error = bus_setup_intr(dev, lesc->sc_ires, INTR_MPSAFE, am7990_intr, sc, &lesc->sc_ih, sc->ifp->if_serializer); if (error != 0) { device_printf(dev, "cannot set up interrupt\n"); goto fail_am7990; } return (0); fail_am7990: am7990_detach(&lesc->sc_am7990); fail_dmap: bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); fail_dmem: bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); fail_dtag: bus_dma_tag_destroy(lesc->sc_dmat); fail_pdtag: bus_dma_tag_destroy(lesc->sc_pdmat); fail_ires: bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); fail_dres: bus_release_resource(dev, SYS_RES_DRQ, lesc->sc_drid, lesc->sc_dres); fail_rres: bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); fail_mtx: return (error); }
static int le_dma_attach(device_t dev) { struct le_dma_softc *lesc; struct lsi64854_softc *dma; struct lance_softc *sc; int error, i; lesc = device_get_softc(dev); sc = &lesc->sc_am7990.lsc; LE_LOCK_INIT(sc, device_get_nameunit(dev)); /* * Establish link to `ledma' device. * XXX hackery. */ dma = (struct lsi64854_softc *)device_get_softc(device_get_parent(dev)); lesc->sc_dma = dma; lesc->sc_dma->sc_client = lesc; i = 0; lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, RF_ACTIVE); if (lesc->sc_rres == NULL) { device_printf(dev, "cannot allocate registers\n"); error = ENXIO; goto fail_mtx; } i = 0; if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { device_printf(dev, "cannot allocate interrupt\n"); error = ENXIO; goto fail_rres; } /* Attach the DMA engine. */ error = lsi64854_attach(dma); if (error != 0) { device_printf(dev, "lsi64854_attach failed\n"); goto fail_ires; } sc->sc_memsize = LEDMA_MEMSIZE; error = bus_dma_tag_create( dma->sc_parent_dmat, /* parent */ LEDMA_ALIGNMENT, /* alignment */ LEDMA_BOUNDARY, /* boundary */ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->sc_memsize, /* maxsize */ 1, /* nsegments */ sc->sc_memsize, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &lesc->sc_dmat); if (error != 0) { device_printf(dev, "cannot allocate buffer DMA tag\n"); goto fail_lsi; } error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); if (error != 0) { device_printf(dev, "cannot allocate DMA buffer memory\n"); goto fail_dtag; } lesc->sc_laddr = 0; error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, sc->sc_memsize, le_dma_dma_callback, lesc, 0); if (error != 0 || lesc->sc_laddr == 0) { device_printf(dev, "cannot load DMA buffer map\n"); goto fail_dmem; } sc->sc_addr = lesc->sc_laddr & 0xffffff; sc->sc_flags = 0; sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; sc->sc_mediachange = le_dma_supmediachange; sc->sc_mediastatus = le_dma_supmediastatus; sc->sc_supmedia = le_dma_supmedia; sc->sc_nsupmedia = nitems(le_dma_supmedia); sc->sc_defaultmedia = le_dma_supmedia[0]; OF_getetheraddr(dev, sc->sc_enaddr); sc->sc_copytodesc = lance_copytobuf_contig; sc->sc_copyfromdesc = lance_copyfrombuf_contig; sc->sc_copytobuf = lance_copytobuf_contig; sc->sc_copyfrombuf = lance_copyfrombuf_contig; sc->sc_zerobuf = lance_zerobuf_contig; sc->sc_rdcsr = le_dma_rdcsr; sc->sc_wrcsr = le_dma_wrcsr; sc->sc_hwreset = le_dma_hwreset; sc->sc_hwintr = le_dma_hwintr; sc->sc_nocarrier = le_dma_nocarrier; error = am7990_config(&lesc->sc_am7990, device_get_name(dev), device_get_unit(dev)); if (error != 0) { device_printf(dev, "cannot attach Am7990\n"); goto fail_dmap; } error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, NULL, am7990_intr, sc, &lesc->sc_ih); if (error != 0) { device_printf(dev, "cannot set up interrupt\n"); goto fail_am7990; } return (0); fail_am7990: am7990_detach(&lesc->sc_am7990); fail_dmap: bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); fail_dmem: bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); fail_dtag: bus_dma_tag_destroy(lesc->sc_dmat); fail_lsi: lsi64854_detach(dma); fail_ires: bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), lesc->sc_ires); fail_rres: bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres), lesc->sc_rres); fail_mtx: LE_LOCK_DESTROY(sc); return (error); }