1155093Smarius/* $NetBSD: if_le_ledma.c,v 1.26 2005/12/11 12:23:44 christos Exp $ */ 2155093Smarius 3155093Smarius/*- 4155093Smarius * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5155093Smarius * All rights reserved. 6155093Smarius * 7155093Smarius * This code is derived from software contributed to The NetBSD Foundation 8155093Smarius * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace 9155093Smarius * Simulation Facility, NASA Ames Research Center; Paul Kranenburg. 10155093Smarius * 11155093Smarius * Redistribution and use in source and binary forms, with or without 12155093Smarius * modification, are permitted provided that the following conditions 13155093Smarius * are met: 14155093Smarius * 1. Redistributions of source code must retain the above copyright 15155093Smarius * notice, this list of conditions and the following disclaimer. 16155093Smarius * 2. Redistributions in binary form must reproduce the above copyright 17155093Smarius * notice, this list of conditions and the following disclaimer in the 18155093Smarius * documentation and/or other materials provided with the distribution. 19155093Smarius * 20155093Smarius * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21155093Smarius * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22155093Smarius * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23155093Smarius * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24155093Smarius * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25155093Smarius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26155093Smarius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27155093Smarius * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28155093Smarius * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29155093Smarius * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30155093Smarius * POSSIBILITY OF SUCH DAMAGE. 31155093Smarius */ 32155093Smarius 33155093Smarius#include <sys/cdefs.h> 34155093Smarius__FBSDID("$FreeBSD$"); 35155093Smarius 36155093Smarius#include <sys/param.h> 37155093Smarius#include <sys/systm.h> 38155093Smarius#include <sys/bus.h> 39155093Smarius#include <sys/endian.h> 40155093Smarius#include <sys/kernel.h> 41155093Smarius#include <sys/lock.h> 42155093Smarius#include <sys/module.h> 43155093Smarius#include <sys/mutex.h> 44155093Smarius#include <sys/resource.h> 45155093Smarius#include <sys/rman.h> 46155093Smarius#include <sys/socket.h> 47155093Smarius 48155093Smarius#include <dev/ofw/ofw_bus.h> 49155093Smarius 50155093Smarius#include <machine/bus.h> 51155093Smarius#include <machine/ofw_machdep.h> 52155093Smarius#include <machine/resource.h> 53155093Smarius 54155093Smarius#include <net/ethernet.h> 55155093Smarius#include <net/if.h> 56257290Sglebius#include <net/if_var.h> 57155093Smarius#include <net/if_media.h> 58155093Smarius 59155093Smarius#include <sparc64/sbus/lsi64854reg.h> 60155093Smarius#include <sparc64/sbus/lsi64854var.h> 61155093Smarius 62155093Smarius#include <dev/le/lancereg.h> 63155093Smarius#include <dev/le/lancevar.h> 64155093Smarius#include <dev/le/am7990var.h> 65155093Smarius 66158663Smarius#define LEDMA_ALIGNMENT 8 /* ring desc. alignmet for NCR92C990 */ 67155093Smarius#define LEDMA_BOUNDARY (16*1024*1024) /* must not cross 16MB boundary */ 68155093Smarius#define LEDMA_MEMSIZE (16*1024) /* LANCE memory size */ 69155093Smarius#define LEREG1_RDP 0 /* Register Data Port */ 70155093Smarius#define LEREG1_RAP 2 /* Register Address Port */ 71155093Smarius 72155093Smariusstruct le_dma_softc { 73155093Smarius struct am7990_softc sc_am7990; /* glue to MI code */ 74155093Smarius 75155093Smarius struct resource *sc_rres; 76155093Smarius 77155093Smarius struct resource *sc_ires; 78155093Smarius void *sc_ih; 79155093Smarius 80155093Smarius bus_dma_tag_t sc_dmat; 81155093Smarius bus_dmamap_t sc_dmam; 82155093Smarius bus_addr_t sc_laddr; /* LANCE DMA address */ 83155093Smarius 84155093Smarius struct lsi64854_softc *sc_dma; /* pointer to DMA engine */ 85155093Smarius}; 86155093Smarius 87155093Smariusstatic device_probe_t le_dma_probe; 88155093Smariusstatic device_attach_t le_dma_attach; 89155093Smariusstatic device_detach_t le_dma_detach; 90155093Smariusstatic device_resume_t le_dma_resume; 91155093Smariusstatic device_suspend_t le_dma_suspend; 92155093Smarius 93155093Smariusstatic device_method_t le_dma_methods[] = { 94155093Smarius /* Device interface */ 95155093Smarius DEVMETHOD(device_probe, le_dma_probe), 96155093Smarius DEVMETHOD(device_attach, le_dma_attach), 97155093Smarius DEVMETHOD(device_detach, le_dma_detach), 98155093Smarius /* We can just use the suspend method here. */ 99155093Smarius DEVMETHOD(device_shutdown, le_dma_suspend), 100155093Smarius DEVMETHOD(device_suspend, le_dma_suspend), 101155093Smarius DEVMETHOD(device_resume, le_dma_resume), 102155093Smarius 103155093Smarius { 0, 0 } 104155093Smarius}; 105155093Smarius 106155093SmariusDEFINE_CLASS_0(le, le_dma_driver, le_dma_methods, sizeof(struct le_dma_softc)); 107155093SmariusDRIVER_MODULE(le, dma, le_dma_driver, le_devclass, 0, 0); 108182876SmariusMODULE_DEPEND(le, dma, 1, 1, 1); 109155093SmariusMODULE_DEPEND(le, ether, 1, 1, 1); 110155093Smarius 111155093Smarius/* 112155093Smarius * Media types supported 113155093Smarius */ 114155093Smariusstatic const int le_dma_supmedia[] = { 115155093Smarius IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0), 116155093Smarius IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), 117155093Smarius IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0) 118155093Smarius}; 119155093Smarius 120155093Smariusstatic void le_dma_wrcsr(struct lance_softc *, uint16_t, uint16_t); 121155093Smariusstatic uint16_t le_dma_rdcsr(struct lance_softc *, uint16_t); 122155093Smariusstatic void le_dma_setutp(struct lance_softc *); 123155093Smariusstatic void le_dma_setaui(struct lance_softc *); 124155093Smariusstatic int le_dma_supmediachange(struct lance_softc *); 125155093Smariusstatic void le_dma_supmediastatus(struct lance_softc *, struct ifmediareq *); 126155093Smariusstatic void le_dma_hwreset(struct lance_softc *); 127155093Smariusstatic int le_dma_hwintr(struct lance_softc *); 128155093Smariusstatic void le_dma_nocarrier(struct lance_softc *); 129155093Smariusstatic bus_dmamap_callback_t le_dma_dma_callback; 130155093Smarius 131155093Smariusstatic void 132155093Smariusle_dma_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 133155093Smarius{ 134155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 135155093Smarius 136182876Smarius bus_write_2(lesc->sc_rres, LEREG1_RAP, port); 137182876Smarius bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE); 138182876Smarius bus_write_2(lesc->sc_rres, LEREG1_RDP, val); 139155093Smarius} 140155093Smarius 141155093Smariusstatic uint16_t 142155093Smariusle_dma_rdcsr(struct lance_softc *sc, uint16_t port) 143155093Smarius{ 144155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 145155093Smarius 146182876Smarius bus_write_2(lesc->sc_rres, LEREG1_RAP, port); 147182876Smarius bus_barrier(lesc->sc_rres, LEREG1_RAP, 2, BUS_SPACE_BARRIER_WRITE); 148182876Smarius return (bus_read_2(lesc->sc_rres, LEREG1_RDP)); 149155093Smarius} 150155093Smarius 151155093Smariusstatic void 152155093Smariusle_dma_setutp(struct lance_softc *sc) 153155093Smarius{ 154155093Smarius struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 155155093Smarius 156155093Smarius L64854_SCSR(dma, L64854_GCSR(dma) | E_TP_AUI); 157155093Smarius DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 158155093Smarius} 159155093Smarius 160155093Smariusstatic void 161155093Smariusle_dma_setaui(struct lance_softc *sc) 162155093Smarius{ 163155093Smarius struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 164155093Smarius 165155093Smarius L64854_SCSR(dma, L64854_GCSR(dma) & ~E_TP_AUI); 166155093Smarius DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 167155093Smarius} 168155093Smarius 169155093Smariusstatic int 170155093Smariusle_dma_supmediachange(struct lance_softc *sc) 171155093Smarius{ 172155093Smarius struct ifmedia *ifm = &sc->sc_media; 173155093Smarius 174155093Smarius if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 175155093Smarius return (EINVAL); 176155093Smarius 177155093Smarius /* 178155093Smarius * Switch to the selected media. If autoselect is set, we don't 179155093Smarius * really have to do anything. We'll switch to the other media 180155093Smarius * when we detect loss of carrier. 181155093Smarius */ 182155093Smarius switch (IFM_SUBTYPE(ifm->ifm_media)) { 183155093Smarius case IFM_10_T: 184155093Smarius le_dma_setutp(sc); 185155093Smarius break; 186155093Smarius 187155093Smarius case IFM_10_5: 188155093Smarius le_dma_setaui(sc); 189155093Smarius break; 190155093Smarius 191155093Smarius case IFM_AUTO: 192155093Smarius break; 193155093Smarius 194155093Smarius default: 195155093Smarius return (EINVAL); 196155093Smarius } 197155093Smarius 198155093Smarius return (0); 199155093Smarius} 200155093Smarius 201155093Smariusstatic void 202155093Smariusle_dma_supmediastatus(struct lance_softc *sc, struct ifmediareq *ifmr) 203155093Smarius{ 204155093Smarius struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 205155093Smarius 206155093Smarius /* 207155093Smarius * Notify the world which media we're currently using. 208155093Smarius */ 209155093Smarius if (L64854_GCSR(dma) & E_TP_AUI) 210155093Smarius ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0); 211155093Smarius else 212155093Smarius ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0); 213155093Smarius} 214155093Smarius 215155093Smariusstatic void 216155093Smariusle_dma_hwreset(struct lance_softc *sc) 217155093Smarius{ 218155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 219155093Smarius struct lsi64854_softc *dma = lesc->sc_dma; 220155093Smarius uint32_t aui_bit, csr; 221155093Smarius 222155093Smarius /* 223155093Smarius * Reset DMA channel. 224155093Smarius */ 225155093Smarius csr = L64854_GCSR(dma); 226155093Smarius aui_bit = csr & E_TP_AUI; 227155093Smarius DMA_RESET(dma); 228155093Smarius 229155093Smarius /* Write bits 24-31 of Lance address. */ 230182876Smarius bus_write_4(dma->sc_res, L64854_REG_ENBAR, 231155093Smarius lesc->sc_laddr & 0xff000000); 232155093Smarius 233155093Smarius DMA_ENINTR(dma); 234155093Smarius 235155093Smarius /* 236155093Smarius * Disable E-cache invalidates on chip writes. 237155093Smarius * Retain previous cable selection bit. 238155093Smarius */ 239155093Smarius csr = L64854_GCSR(dma); 240155093Smarius csr |= (E_DSBL_WR_INVAL | aui_bit); 241155093Smarius L64854_SCSR(dma, csr); 242155093Smarius DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 243155093Smarius} 244155093Smarius 245155093Smariusstatic int 246155093Smariusle_dma_hwintr(struct lance_softc *sc) 247155093Smarius{ 248155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 249155093Smarius struct lsi64854_softc *dma = lesc->sc_dma; 250155093Smarius 251155093Smarius return (DMA_INTR(dma)); 252155093Smarius} 253155093Smarius 254155093Smariusstatic void 255155093Smariusle_dma_nocarrier(struct lance_softc *sc) 256155093Smarius{ 257155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 258155093Smarius 259155093Smarius /* 260155093Smarius * Check if the user has requested a certain cable type, and 261155093Smarius * if so, honor that request. 262155093Smarius */ 263155093Smarius 264155093Smarius if (L64854_GCSR(lesc->sc_dma) & E_TP_AUI) { 265155093Smarius switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { 266155093Smarius case IFM_10_5: 267155093Smarius case IFM_AUTO: 268155093Smarius if_printf(sc->sc_ifp, "lost carrier on UTP port, " 269155093Smarius "switching to AUI port\n"); 270155093Smarius le_dma_setaui(sc); 271155093Smarius } 272155093Smarius } else { 273155093Smarius switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { 274155093Smarius case IFM_10_T: 275155093Smarius case IFM_AUTO: 276155093Smarius if_printf(sc->sc_ifp, "lost carrier on AUI port, " 277155093Smarius "switching to UTP port\n"); 278155093Smarius le_dma_setutp(sc); 279155093Smarius } 280155093Smarius } 281155093Smarius} 282155093Smarius 283155093Smariusstatic void 284155093Smariusle_dma_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 285155093Smarius{ 286155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)xsc; 287155093Smarius 288155093Smarius if (error != 0) 289155093Smarius return; 290155093Smarius KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); 291155093Smarius lesc->sc_laddr = segs[0].ds_addr; 292155093Smarius} 293155093Smarius 294155093Smariusstatic int 295155093Smariusle_dma_probe(device_t dev) 296155093Smarius{ 297155093Smarius 298155093Smarius if (strcmp(ofw_bus_get_name(dev), "le") == 0) { 299155093Smarius device_set_desc(dev, "LANCE Ethernet"); 300155093Smarius return (BUS_PROBE_DEFAULT); 301155093Smarius } 302155093Smarius return (ENXIO); 303155093Smarius} 304155093Smarius 305155093Smariusstatic int 306155093Smariusle_dma_attach(device_t dev) 307155093Smarius{ 308155093Smarius struct le_dma_softc *lesc; 309155093Smarius struct lsi64854_softc *dma; 310155093Smarius struct lance_softc *sc; 311182876Smarius int error, i; 312155093Smarius 313155093Smarius lesc = device_get_softc(dev); 314155093Smarius sc = &lesc->sc_am7990.lsc; 315155093Smarius 316155093Smarius LE_LOCK_INIT(sc, device_get_nameunit(dev)); 317155093Smarius 318155093Smarius /* 319155093Smarius * Establish link to `ledma' device. 320155093Smarius * XXX hackery. 321155093Smarius */ 322155093Smarius dma = (struct lsi64854_softc *)device_get_softc(device_get_parent(dev)); 323155093Smarius lesc->sc_dma = dma; 324155093Smarius lesc->sc_dma->sc_client = lesc; 325155093Smarius 326182876Smarius i = 0; 327155093Smarius lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 328182876Smarius &i, RF_ACTIVE); 329155093Smarius if (lesc->sc_rres == NULL) { 330155093Smarius device_printf(dev, "cannot allocate registers\n"); 331155093Smarius error = ENXIO; 332155093Smarius goto fail_mtx; 333155093Smarius } 334155093Smarius 335182876Smarius i = 0; 336155093Smarius if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 337182876Smarius &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 338155093Smarius device_printf(dev, "cannot allocate interrupt\n"); 339155093Smarius error = ENXIO; 340155093Smarius goto fail_rres; 341155093Smarius } 342155093Smarius 343182876Smarius /* Attach the DMA engine. */ 344182876Smarius error = lsi64854_attach(dma); 345182876Smarius if (error != 0) { 346182876Smarius device_printf(dev, "lsi64854_attach failed\n"); 347182876Smarius goto fail_ires; 348182876Smarius } 349182876Smarius 350155093Smarius sc->sc_memsize = LEDMA_MEMSIZE; 351155093Smarius error = bus_dma_tag_create( 352155093Smarius dma->sc_parent_dmat, /* parent */ 353158663Smarius LEDMA_ALIGNMENT, /* alignment */ 354158663Smarius LEDMA_BOUNDARY, /* boundary */ 355155093Smarius BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 356155093Smarius BUS_SPACE_MAXADDR, /* highaddr */ 357155093Smarius NULL, NULL, /* filter, filterarg */ 358155093Smarius sc->sc_memsize, /* maxsize */ 359155093Smarius 1, /* nsegments */ 360155093Smarius sc->sc_memsize, /* maxsegsize */ 361166148Smarius 0, /* flags */ 362155093Smarius NULL, NULL, /* lockfunc, lockarg */ 363155093Smarius &lesc->sc_dmat); 364155093Smarius if (error != 0) { 365155093Smarius device_printf(dev, "cannot allocate buffer DMA tag\n"); 366182876Smarius goto fail_lsi; 367155093Smarius } 368155093Smarius 369155093Smarius error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, 370155093Smarius BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); 371155093Smarius if (error != 0) { 372155093Smarius device_printf(dev, "cannot allocate DMA buffer memory\n"); 373155093Smarius goto fail_dtag; 374155093Smarius } 375155093Smarius 376155093Smarius lesc->sc_laddr = 0; 377155093Smarius error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, 378155093Smarius sc->sc_memsize, le_dma_dma_callback, lesc, 0); 379155093Smarius if (error != 0 || lesc->sc_laddr == 0) { 380182876Smarius device_printf(dev, "cannot load DMA buffer map\n"); 381155093Smarius goto fail_dmem; 382155093Smarius } 383155093Smarius 384155093Smarius sc->sc_addr = lesc->sc_laddr & 0xffffff; 385155093Smarius sc->sc_flags = 0; 386155093Smarius sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; 387155093Smarius 388155093Smarius sc->sc_mediachange = le_dma_supmediachange; 389155093Smarius sc->sc_mediastatus = le_dma_supmediastatus; 390155093Smarius sc->sc_supmedia = le_dma_supmedia; 391298431Spfg sc->sc_nsupmedia = nitems(le_dma_supmedia); 392155093Smarius sc->sc_defaultmedia = le_dma_supmedia[0]; 393155093Smarius 394155093Smarius OF_getetheraddr(dev, sc->sc_enaddr); 395155093Smarius 396155093Smarius sc->sc_copytodesc = lance_copytobuf_contig; 397155093Smarius sc->sc_copyfromdesc = lance_copyfrombuf_contig; 398155093Smarius sc->sc_copytobuf = lance_copytobuf_contig; 399155093Smarius sc->sc_copyfrombuf = lance_copyfrombuf_contig; 400155093Smarius sc->sc_zerobuf = lance_zerobuf_contig; 401155093Smarius 402155093Smarius sc->sc_rdcsr = le_dma_rdcsr; 403155093Smarius sc->sc_wrcsr = le_dma_wrcsr; 404155093Smarius sc->sc_hwreset = le_dma_hwreset; 405155093Smarius sc->sc_hwintr = le_dma_hwintr; 406158663Smarius sc->sc_nocarrier = le_dma_nocarrier; 407155093Smarius 408155093Smarius error = am7990_config(&lesc->sc_am7990, device_get_name(dev), 409155093Smarius device_get_unit(dev)); 410155093Smarius if (error != 0) { 411158663Smarius device_printf(dev, "cannot attach Am7990\n"); 412155093Smarius goto fail_dmap; 413155093Smarius } 414155093Smarius 415155093Smarius error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, 416166901Spiso NULL, am7990_intr, sc, &lesc->sc_ih); 417155093Smarius if (error != 0) { 418155093Smarius device_printf(dev, "cannot set up interrupt\n"); 419155093Smarius goto fail_am7990; 420155093Smarius } 421155093Smarius 422155093Smarius return (0); 423155093Smarius 424155093Smarius fail_am7990: 425155093Smarius am7990_detach(&lesc->sc_am7990); 426155093Smarius fail_dmap: 427155093Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 428155093Smarius fail_dmem: 429155093Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 430155093Smarius fail_dtag: 431155093Smarius bus_dma_tag_destroy(lesc->sc_dmat); 432182876Smarius fail_lsi: 433182876Smarius lsi64854_detach(dma); 434155093Smarius fail_ires: 435182876Smarius bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), 436182876Smarius lesc->sc_ires); 437155093Smarius fail_rres: 438182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres), 439182876Smarius lesc->sc_rres); 440155093Smarius fail_mtx: 441155093Smarius LE_LOCK_DESTROY(sc); 442155093Smarius return (error); 443155093Smarius} 444155093Smarius 445155093Smariusstatic int 446155093Smariusle_dma_detach(device_t dev) 447155093Smarius{ 448155093Smarius struct le_dma_softc *lesc; 449155093Smarius struct lance_softc *sc; 450182876Smarius int error; 451155093Smarius 452155093Smarius lesc = device_get_softc(dev); 453155093Smarius sc = &lesc->sc_am7990.lsc; 454155093Smarius 455155093Smarius bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); 456155093Smarius am7990_detach(&lesc->sc_am7990); 457155093Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 458155093Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 459155093Smarius bus_dma_tag_destroy(lesc->sc_dmat); 460182876Smarius error = lsi64854_detach(lesc->sc_dma); 461182876Smarius if (error != 0) 462182876Smarius return (error); 463182876Smarius bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(lesc->sc_ires), 464182876Smarius lesc->sc_ires); 465182876Smarius bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lesc->sc_rres), 466182876Smarius lesc->sc_rres); 467155093Smarius LE_LOCK_DESTROY(sc); 468155093Smarius 469155093Smarius return (0); 470155093Smarius} 471155093Smarius 472155093Smariusstatic int 473155093Smariusle_dma_suspend(device_t dev) 474155093Smarius{ 475155093Smarius struct le_dma_softc *lesc; 476155093Smarius 477155093Smarius lesc = device_get_softc(dev); 478155093Smarius 479155093Smarius lance_suspend(&lesc->sc_am7990.lsc); 480155093Smarius 481155093Smarius return (0); 482155093Smarius} 483155093Smarius 484155093Smariusstatic int 485155093Smariusle_dma_resume(device_t dev) 486155093Smarius{ 487155093Smarius struct le_dma_softc *lesc; 488155093Smarius 489155093Smarius lesc = device_get_softc(dev); 490155093Smarius 491155093Smarius lance_resume(&lesc->sc_am7990.lsc); 492155093Smarius 493155093Smarius return (0); 494155093Smarius} 495