if_le_ledma.c revision 155093
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 * 3. All advertising materials mentioning features or use of this software 20155093Smarius * must display the following acknowledgement: 21155093Smarius * This product includes software developed by the NetBSD 22155093Smarius * Foundation, Inc. and its contributors. 23155093Smarius * 4. Neither the name of The NetBSD Foundation nor the names of its 24155093Smarius * contributors may be used to endorse or promote products derived 25155093Smarius * from this software without specific prior written permission. 26155093Smarius * 27155093Smarius * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28155093Smarius * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29155093Smarius * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30155093Smarius * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31155093Smarius * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32155093Smarius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33155093Smarius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34155093Smarius * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35155093Smarius * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36155093Smarius * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37155093Smarius * POSSIBILITY OF SUCH DAMAGE. 38155093Smarius */ 39155093Smarius 40155093Smarius#include <sys/cdefs.h> 41155093Smarius__FBSDID("$FreeBSD: head/sys/dev/le/if_le_ledma.c 155093 2006-01-31 14:48:58Z marius $"); 42155093Smarius 43155093Smarius#include <sys/param.h> 44155093Smarius#include <sys/systm.h> 45155093Smarius#include <sys/bus.h> 46155093Smarius#include <sys/endian.h> 47155093Smarius#include <sys/kernel.h> 48155093Smarius#include <sys/lock.h> 49155093Smarius#include <sys/module.h> 50155093Smarius#include <sys/mutex.h> 51155093Smarius#include <sys/resource.h> 52155093Smarius#include <sys/rman.h> 53155093Smarius#include <sys/socket.h> 54155093Smarius 55155093Smarius#include <dev/ofw/ofw_bus.h> 56155093Smarius 57155093Smarius#include <machine/bus.h> 58155093Smarius#include <machine/ofw_machdep.h> 59155093Smarius#include <machine/resource.h> 60155093Smarius 61155093Smarius#include <net/ethernet.h> 62155093Smarius#include <net/if.h> 63155093Smarius#include <net/if_media.h> 64155093Smarius 65155093Smarius#include <sparc64/sbus/lsi64854reg.h> 66155093Smarius#include <sparc64/sbus/lsi64854var.h> 67155093Smarius 68155093Smarius#include <dev/le/lancereg.h> 69155093Smarius#include <dev/le/lancevar.h> 70155093Smarius#include <dev/le/am7990var.h> 71155093Smarius 72155093Smarius#define LEDMA_BOUNDARY (16*1024*1024) /* must not cross 16MB boundary */ 73155093Smarius#define LEDMA_MEMSIZE (16*1024) /* LANCE memory size */ 74155093Smarius#define LEREG1_RDP 0 /* Register Data Port */ 75155093Smarius#define LEREG1_RAP 2 /* Register Address Port */ 76155093Smarius 77155093Smariusstruct le_dma_softc { 78155093Smarius struct am7990_softc sc_am7990; /* glue to MI code */ 79155093Smarius 80155093Smarius int sc_rrid; 81155093Smarius struct resource *sc_rres; 82155093Smarius bus_space_tag_t sc_regt; 83155093Smarius bus_space_handle_t sc_regh; 84155093Smarius 85155093Smarius int sc_irid; 86155093Smarius struct resource *sc_ires; 87155093Smarius void *sc_ih; 88155093Smarius 89155093Smarius bus_dma_tag_t sc_dmat; 90155093Smarius bus_dmamap_t sc_dmam; 91155093Smarius bus_addr_t sc_laddr; /* LANCE DMA address */ 92155093Smarius 93155093Smarius struct lsi64854_softc *sc_dma; /* pointer to DMA engine */ 94155093Smarius}; 95155093Smarius 96155093Smariusstatic device_probe_t le_dma_probe; 97155093Smariusstatic device_attach_t le_dma_attach; 98155093Smariusstatic device_detach_t le_dma_detach; 99155093Smariusstatic device_resume_t le_dma_resume; 100155093Smariusstatic device_suspend_t le_dma_suspend; 101155093Smarius 102155093Smariusstatic device_method_t le_dma_methods[] = { 103155093Smarius /* Device interface */ 104155093Smarius DEVMETHOD(device_probe, le_dma_probe), 105155093Smarius DEVMETHOD(device_attach, le_dma_attach), 106155093Smarius DEVMETHOD(device_detach, le_dma_detach), 107155093Smarius /* We can just use the suspend method here. */ 108155093Smarius DEVMETHOD(device_shutdown, le_dma_suspend), 109155093Smarius DEVMETHOD(device_suspend, le_dma_suspend), 110155093Smarius DEVMETHOD(device_resume, le_dma_resume), 111155093Smarius 112155093Smarius { 0, 0 } 113155093Smarius}; 114155093Smarius 115155093SmariusDEFINE_CLASS_0(le, le_dma_driver, le_dma_methods, sizeof(struct le_dma_softc)); 116155093SmariusDRIVER_MODULE(le, dma, le_dma_driver, le_devclass, 0, 0); 117155093SmariusMODULE_DEPEND(le, ether, 1, 1, 1); 118155093Smarius 119155093Smarius/* 120155093Smarius * Media types supported 121155093Smarius */ 122155093Smariusstatic const int le_dma_supmedia[] = { 123155093Smarius IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0), 124155093Smarius IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), 125155093Smarius IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0) 126155093Smarius}; 127155093Smarius 128155093Smariusstatic void le_dma_wrcsr(struct lance_softc *, uint16_t, uint16_t); 129155093Smariusstatic uint16_t le_dma_rdcsr(struct lance_softc *, uint16_t); 130155093Smariusstatic void le_dma_setutp(struct lance_softc *); 131155093Smariusstatic void le_dma_setaui(struct lance_softc *); 132155093Smariusstatic int le_dma_supmediachange(struct lance_softc *); 133155093Smariusstatic void le_dma_supmediastatus(struct lance_softc *, struct ifmediareq *); 134155093Smariusstatic void le_dma_hwreset(struct lance_softc *); 135155093Smariusstatic int le_dma_hwintr(struct lance_softc *); 136155093Smariusstatic void le_dma_nocarrier(struct lance_softc *); 137155093Smariusstatic bus_dmamap_callback_t le_dma_dma_callback; 138155093Smarius 139155093Smariusstatic void 140155093Smariusle_dma_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 141155093Smarius{ 142155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 143155093Smarius 144155093Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port); 145155093Smarius bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2, 146155093Smarius BUS_SPACE_BARRIER_WRITE); 147155093Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP, val); 148155093Smarius} 149155093Smarius 150155093Smariusstatic uint16_t 151155093Smariusle_dma_rdcsr(struct lance_softc *sc, uint16_t port) 152155093Smarius{ 153155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 154155093Smarius 155155093Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port); 156155093Smarius bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2, 157155093Smarius BUS_SPACE_BARRIER_WRITE); 158155093Smarius return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP)); 159155093Smarius} 160155093Smarius 161155093Smariusstatic void 162155093Smariusle_dma_setutp(struct lance_softc *sc) 163155093Smarius{ 164155093Smarius struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 165155093Smarius 166155093Smarius L64854_SCSR(dma, L64854_GCSR(dma) | E_TP_AUI); 167155093Smarius DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 168155093Smarius} 169155093Smarius 170155093Smariusstatic void 171155093Smariusle_dma_setaui(struct lance_softc *sc) 172155093Smarius{ 173155093Smarius struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 174155093Smarius 175155093Smarius L64854_SCSR(dma, L64854_GCSR(dma) & ~E_TP_AUI); 176155093Smarius DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 177155093Smarius} 178155093Smarius 179155093Smariusstatic int 180155093Smariusle_dma_supmediachange(struct lance_softc *sc) 181155093Smarius{ 182155093Smarius struct ifmedia *ifm = &sc->sc_media; 183155093Smarius 184155093Smarius if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 185155093Smarius return (EINVAL); 186155093Smarius 187155093Smarius /* 188155093Smarius * Switch to the selected media. If autoselect is set, we don't 189155093Smarius * really have to do anything. We'll switch to the other media 190155093Smarius * when we detect loss of carrier. 191155093Smarius */ 192155093Smarius switch (IFM_SUBTYPE(ifm->ifm_media)) { 193155093Smarius case IFM_10_T: 194155093Smarius le_dma_setutp(sc); 195155093Smarius break; 196155093Smarius 197155093Smarius case IFM_10_5: 198155093Smarius le_dma_setaui(sc); 199155093Smarius break; 200155093Smarius 201155093Smarius case IFM_AUTO: 202155093Smarius break; 203155093Smarius 204155093Smarius default: 205155093Smarius return (EINVAL); 206155093Smarius } 207155093Smarius 208155093Smarius return (0); 209155093Smarius} 210155093Smarius 211155093Smariusstatic void 212155093Smariusle_dma_supmediastatus(struct lance_softc *sc, struct ifmediareq *ifmr) 213155093Smarius{ 214155093Smarius struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma; 215155093Smarius 216155093Smarius /* 217155093Smarius * Notify the world which media we're currently using. 218155093Smarius */ 219155093Smarius if (L64854_GCSR(dma) & E_TP_AUI) 220155093Smarius ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0); 221155093Smarius else 222155093Smarius ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0); 223155093Smarius} 224155093Smarius 225155093Smariusstatic void 226155093Smariusle_dma_hwreset(struct lance_softc *sc) 227155093Smarius{ 228155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 229155093Smarius struct lsi64854_softc *dma = lesc->sc_dma; 230155093Smarius uint32_t aui_bit, csr; 231155093Smarius 232155093Smarius /* 233155093Smarius * Reset DMA channel. 234155093Smarius */ 235155093Smarius csr = L64854_GCSR(dma); 236155093Smarius aui_bit = csr & E_TP_AUI; 237155093Smarius DMA_RESET(dma); 238155093Smarius 239155093Smarius /* Write bits 24-31 of Lance address. */ 240155093Smarius bus_space_write_4(dma->sc_regt, dma->sc_regh, L64854_REG_ENBAR, 241155093Smarius lesc->sc_laddr & 0xff000000); 242155093Smarius 243155093Smarius DMA_ENINTR(dma); 244155093Smarius 245155093Smarius /* 246155093Smarius * Disable E-cache invalidates on chip writes. 247155093Smarius * Retain previous cable selection bit. 248155093Smarius */ 249155093Smarius csr = L64854_GCSR(dma); 250155093Smarius csr |= (E_DSBL_WR_INVAL | aui_bit); 251155093Smarius L64854_SCSR(dma, csr); 252155093Smarius DELAY(20000); /* We must not touch the LANCE chip for 20ms. */ 253155093Smarius} 254155093Smarius 255155093Smariusstatic int 256155093Smariusle_dma_hwintr(struct lance_softc *sc) 257155093Smarius{ 258155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 259155093Smarius struct lsi64854_softc *dma = lesc->sc_dma; 260155093Smarius 261155093Smarius return (DMA_INTR(dma)); 262155093Smarius} 263155093Smarius 264155093Smariusstatic void 265155093Smariusle_dma_nocarrier(struct lance_softc *sc) 266155093Smarius{ 267155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)sc; 268155093Smarius 269155093Smarius /* 270155093Smarius * Check if the user has requested a certain cable type, and 271155093Smarius * if so, honor that request. 272155093Smarius */ 273155093Smarius 274155093Smarius if (L64854_GCSR(lesc->sc_dma) & E_TP_AUI) { 275155093Smarius switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { 276155093Smarius case IFM_10_5: 277155093Smarius case IFM_AUTO: 278155093Smarius if_printf(sc->sc_ifp, "lost carrier on UTP port, " 279155093Smarius "switching to AUI port\n"); 280155093Smarius le_dma_setaui(sc); 281155093Smarius } 282155093Smarius } else { 283155093Smarius switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) { 284155093Smarius case IFM_10_T: 285155093Smarius case IFM_AUTO: 286155093Smarius if_printf(sc->sc_ifp, "lost carrier on AUI port, " 287155093Smarius "switching to UTP port\n"); 288155093Smarius le_dma_setutp(sc); 289155093Smarius } 290155093Smarius } 291155093Smarius} 292155093Smarius 293155093Smariusstatic void 294155093Smariusle_dma_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 295155093Smarius{ 296155093Smarius struct le_dma_softc *lesc = (struct le_dma_softc *)xsc; 297155093Smarius 298155093Smarius if (error != 0) 299155093Smarius return; 300155093Smarius KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); 301155093Smarius lesc->sc_laddr = segs[0].ds_addr; 302155093Smarius} 303155093Smarius 304155093Smariusstatic int 305155093Smariusle_dma_probe(device_t dev) 306155093Smarius{ 307155093Smarius 308155093Smarius if (strcmp(ofw_bus_get_name(dev), "le") == 0) { 309155093Smarius device_set_desc(dev, "LANCE Ethernet"); 310155093Smarius return (BUS_PROBE_DEFAULT); 311155093Smarius } 312155093Smarius return (ENXIO); 313155093Smarius} 314155093Smarius 315155093Smariusstatic int 316155093Smariusle_dma_attach(device_t dev) 317155093Smarius{ 318155093Smarius struct le_dma_softc *lesc; 319155093Smarius struct lsi64854_softc *dma; 320155093Smarius struct lance_softc *sc; 321155093Smarius int error; 322155093Smarius 323155093Smarius lesc = device_get_softc(dev); 324155093Smarius sc = &lesc->sc_am7990.lsc; 325155093Smarius 326155093Smarius LE_LOCK_INIT(sc, device_get_nameunit(dev)); 327155093Smarius 328155093Smarius /* 329155093Smarius * Establish link to `ledma' device. 330155093Smarius * XXX hackery. 331155093Smarius */ 332155093Smarius dma = (struct lsi64854_softc *)device_get_softc(device_get_parent(dev)); 333155093Smarius lesc->sc_dma = dma; 334155093Smarius lesc->sc_dma->sc_client = lesc; 335155093Smarius 336155093Smarius lesc->sc_rrid = 0; 337155093Smarius lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 338155093Smarius &lesc->sc_rrid, RF_ACTIVE); 339155093Smarius if (lesc->sc_rres == NULL) { 340155093Smarius device_printf(dev, "cannot allocate registers\n"); 341155093Smarius error = ENXIO; 342155093Smarius goto fail_mtx; 343155093Smarius } 344155093Smarius lesc->sc_regt = rman_get_bustag(lesc->sc_rres); 345155093Smarius lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); 346155093Smarius 347155093Smarius lesc->sc_irid = 0; 348155093Smarius if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 349155093Smarius &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 350155093Smarius device_printf(dev, "cannot allocate interrupt\n"); 351155093Smarius error = ENXIO; 352155093Smarius goto fail_rres; 353155093Smarius } 354155093Smarius 355155093Smarius sc->sc_memsize = LEDMA_MEMSIZE; 356155093Smarius error = bus_dma_tag_create( 357155093Smarius dma->sc_parent_dmat, /* parent */ 358155093Smarius 1, LEDMA_BOUNDARY, /* alignment, boundary */ 359155093Smarius BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 360155093Smarius BUS_SPACE_MAXADDR, /* highaddr */ 361155093Smarius NULL, NULL, /* filter, filterarg */ 362155093Smarius sc->sc_memsize, /* maxsize */ 363155093Smarius 1, /* nsegments */ 364155093Smarius sc->sc_memsize, /* maxsegsize */ 365155093Smarius BUS_DMA_WAITOK, /* flags */ 366155093Smarius NULL, NULL, /* lockfunc, lockarg */ 367155093Smarius &lesc->sc_dmat); 368155093Smarius if (error != 0) { 369155093Smarius device_printf(dev, "cannot allocate buffer DMA tag\n"); 370155093Smarius goto fail_ires; 371155093Smarius } 372155093Smarius 373155093Smarius error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, 374155093Smarius BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); 375155093Smarius if (error != 0) { 376155093Smarius device_printf(dev, "cannot allocate DMA buffer memory\n"); 377155093Smarius goto fail_dtag; 378155093Smarius } 379155093Smarius 380155093Smarius lesc->sc_laddr = 0; 381155093Smarius error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, 382155093Smarius sc->sc_memsize, le_dma_dma_callback, lesc, 0); 383155093Smarius if (error != 0 || lesc->sc_laddr == 0) { 384155093Smarius device_printf(dev, "cannot load DMA buffer map\n"); 385155093Smarius goto fail_dmem; 386155093Smarius } 387155093Smarius 388155093Smarius sc->sc_addr = lesc->sc_laddr & 0xffffff; 389155093Smarius sc->sc_flags = 0; 390155093Smarius sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; 391155093Smarius 392155093Smarius sc->sc_mediachange = le_dma_supmediachange; 393155093Smarius sc->sc_mediastatus = le_dma_supmediastatus; 394155093Smarius sc->sc_supmedia = le_dma_supmedia; 395155093Smarius sc->sc_nsupmedia = sizeof(le_dma_supmedia) / sizeof(le_dma_supmedia[0]); 396155093Smarius sc->sc_defaultmedia = le_dma_supmedia[0]; 397155093Smarius 398155093Smarius OF_getetheraddr(dev, sc->sc_enaddr); 399155093Smarius 400155093Smarius sc->sc_copytodesc = lance_copytobuf_contig; 401155093Smarius sc->sc_copyfromdesc = lance_copyfrombuf_contig; 402155093Smarius sc->sc_copytobuf = lance_copytobuf_contig; 403155093Smarius sc->sc_copyfrombuf = lance_copyfrombuf_contig; 404155093Smarius sc->sc_zerobuf = lance_zerobuf_contig; 405155093Smarius 406155093Smarius sc->sc_rdcsr = le_dma_rdcsr; 407155093Smarius sc->sc_wrcsr = le_dma_wrcsr; 408155093Smarius sc->sc_nocarrier = le_dma_nocarrier; 409155093Smarius sc->sc_hwreset = le_dma_hwreset; 410155093Smarius sc->sc_hwintr = le_dma_hwintr; 411155093Smarius 412155093Smarius error = am7990_config(&lesc->sc_am7990, device_get_name(dev), 413155093Smarius device_get_unit(dev)); 414155093Smarius if (error != 0) { 415155093Smarius device_printf(dev, "cannot attach AM7990\n"); 416155093Smarius goto fail_dmap; 417155093Smarius } 418155093Smarius 419155093Smarius error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, 420155093Smarius am7990_intr, sc, &lesc->sc_ih); 421155093Smarius if (error != 0) { 422155093Smarius device_printf(dev, "cannot set up interrupt\n"); 423155093Smarius goto fail_am7990; 424155093Smarius } 425155093Smarius 426155093Smarius return (0); 427155093Smarius 428155093Smarius fail_am7990: 429155093Smarius am7990_detach(&lesc->sc_am7990); 430155093Smarius fail_dmap: 431155093Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 432155093Smarius fail_dmem: 433155093Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 434155093Smarius fail_dtag: 435155093Smarius bus_dma_tag_destroy(lesc->sc_dmat); 436155093Smarius fail_ires: 437155093Smarius bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); 438155093Smarius fail_rres: 439155093Smarius bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, 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; 450155093Smarius 451155093Smarius lesc = device_get_softc(dev); 452155093Smarius sc = &lesc->sc_am7990.lsc; 453155093Smarius 454155093Smarius bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); 455155093Smarius am7990_detach(&lesc->sc_am7990); 456155093Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 457155093Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 458155093Smarius bus_dma_tag_destroy(lesc->sc_dmat); 459155093Smarius bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); 460155093Smarius bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres); 461155093Smarius LE_LOCK_DESTROY(sc); 462155093Smarius 463155093Smarius return (0); 464155093Smarius} 465155093Smarius 466155093Smariusstatic int 467155093Smariusle_dma_suspend(device_t dev) 468155093Smarius{ 469155093Smarius struct le_dma_softc *lesc; 470155093Smarius 471155093Smarius lesc = device_get_softc(dev); 472155093Smarius 473155093Smarius lance_suspend(&lesc->sc_am7990.lsc); 474155093Smarius 475155093Smarius return (0); 476155093Smarius} 477155093Smarius 478155093Smariusstatic int 479155093Smariusle_dma_resume(device_t dev) 480155093Smarius{ 481155093Smarius struct le_dma_softc *lesc; 482155093Smarius 483155093Smarius lesc = device_get_softc(dev); 484155093Smarius 485155093Smarius lance_resume(&lesc->sc_am7990.lsc); 486155093Smarius 487155093Smarius return (0); 488155093Smarius} 489