if_le_cbus.c revision 166901
1158712Smarius/*- 2158712Smarius * Copyright (c) 1994-2000 3158712Smarius * Paul Richards. All rights reserved. 4158712Smarius * 5158712Smarius * PC-98 port by Chiharu Shibata & FreeBSD(98) porting team. 6158712Smarius * 7158712Smarius * Redistribution and use in source and binary forms, with or without 8158712Smarius * modification, are permitted provided that the following conditions 9158712Smarius * are met: 10158712Smarius * 1. Redistributions of source code must retain the above copyright 11158712Smarius * notice, this list of conditions and the following disclaimer, 12158712Smarius * verbatim and that no modifications are made prior to this 13158712Smarius * point in the file. 14158712Smarius * 2. Redistributions in binary form must reproduce the above copyright 15158712Smarius * notice, this list of conditions and the following disclaimer in the 16158712Smarius * documentation and/or other materials provided with the distribution. 17158712Smarius * 3. The name Paul Richards may not be used to endorse or promote products 18158712Smarius * derived from this software without specific prior written permission. 19158712Smarius * 20158712Smarius * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND 21158712Smarius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22158712Smarius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23158712Smarius * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE 24158712Smarius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25158712Smarius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26158712Smarius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27158712Smarius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28158712Smarius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29158712Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30158712Smarius * SUCH DAMAGE. 31158712Smarius * 32158712Smarius * from: FreeBSD: src/sys/dev/lnc/if_lnc_cbus.c,v 1.12 2005/11/12 19:14:21 33158712Smarius */ 34158712Smarius 35158712Smarius#include <sys/cdefs.h> 36158712Smarius__FBSDID("$FreeBSD: head/sys/dev/le/if_le_cbus.c 166901 2007-02-23 12:19:07Z piso $"); 37158712Smarius 38158712Smarius#include <sys/param.h> 39158712Smarius#include <sys/systm.h> 40158712Smarius#include <sys/bus.h> 41158712Smarius#include <sys/endian.h> 42158712Smarius#include <sys/kernel.h> 43158712Smarius#include <sys/lock.h> 44158712Smarius#include <sys/module.h> 45158712Smarius#include <sys/mutex.h> 46158712Smarius#include <sys/resource.h> 47158712Smarius#include <sys/rman.h> 48158712Smarius#include <sys/socket.h> 49158712Smarius 50158712Smarius#include <net/ethernet.h> 51158712Smarius#include <net/if.h> 52158712Smarius#include <net/if_media.h> 53158712Smarius 54158712Smarius#include <machine/bus.h> 55158712Smarius#include <machine/resource.h> 56158712Smarius 57158712Smarius#include <isa/isavar.h> 58158712Smarius 59158712Smarius#include <dev/le/lancereg.h> 60158712Smarius#include <dev/le/lancevar.h> 61158712Smarius#include <dev/le/am7990var.h> 62158712Smarius 63158712Smarius#define LE_CBUS_MEMSIZE (16*1024) 64158712Smarius#define CNET98S_IOSIZE 32 65158712Smarius#define CNET98S_RDP 0x10 66158712Smarius#define CNET98S_RAP 0x12 67158712Smarius#define CNET98S_RESET 0x14 68158712Smarius#define CNET98S_BDP 0x16 69158712Smarius 70158712Smariusstruct le_cbus_softc { 71158712Smarius struct am7990_softc sc_am7990; /* glue to MI code */ 72158712Smarius 73158712Smarius int sc_rrid; 74158712Smarius struct resource *sc_rres; 75158712Smarius bus_space_tag_t sc_regt; 76158712Smarius bus_space_handle_t sc_regh; 77158712Smarius 78158712Smarius int sc_irid; 79158712Smarius struct resource *sc_ires; 80158712Smarius void *sc_ih; 81158712Smarius 82158712Smarius bus_dma_tag_t sc_pdmat; 83158712Smarius bus_dma_tag_t sc_dmat; 84158712Smarius bus_dmamap_t sc_dmam; 85158712Smarius}; 86158712Smarius 87158712Smariusstatic device_probe_t le_cbus_probe; 88158712Smariusstatic device_attach_t le_cbus_attach; 89158712Smariusstatic device_detach_t le_cbus_detach; 90158712Smariusstatic device_resume_t le_cbus_resume; 91158712Smariusstatic device_suspend_t le_cbus_suspend; 92158712Smarius 93158712Smariusstatic device_method_t le_cbus_methods[] = { 94158712Smarius /* Device interface */ 95158712Smarius DEVMETHOD(device_probe, le_cbus_probe), 96158712Smarius DEVMETHOD(device_attach, le_cbus_attach), 97158712Smarius DEVMETHOD(device_detach, le_cbus_detach), 98158712Smarius /* We can just use the suspend method here. */ 99158712Smarius DEVMETHOD(device_shutdown, le_cbus_suspend), 100158712Smarius DEVMETHOD(device_suspend, le_cbus_suspend), 101158712Smarius DEVMETHOD(device_resume, le_cbus_resume), 102158712Smarius 103158712Smarius { 0, 0 } 104158712Smarius}; 105158712Smarius 106158712SmariusDEFINE_CLASS_0(le, le_cbus_driver, le_cbus_methods, sizeof(struct le_cbus_softc)); 107158829SnyanDRIVER_MODULE(le, isa, le_cbus_driver, le_devclass, 0, 0); 108158712SmariusMODULE_DEPEND(le, ether, 1, 1, 1); 109158712Smarius 110158712Smariusstatic bus_addr_t le_ioaddr_cnet98s[CNET98S_IOSIZE] = { 111158712Smarius 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 112158712Smarius 0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, 113158712Smarius 0x400, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 114158712Smarius 0x408, 0x409, 0x40a, 0x40b, 0x40c, 0x40d, 0x40e, 0x40f, 115158712Smarius}; 116158712Smarius 117158712Smariusstatic void le_cbus_wrbcr(struct lance_softc *, uint16_t, uint16_t); 118158712Smarius#ifdef LEDEBUG 119158712Smariusstatic uint16_t le_cbus_rdbcr(struct lance_softc *, uint16_t); 120158712Smarius#endif 121158712Smariusstatic void le_cbus_wrcsr(struct lance_softc *, uint16_t, uint16_t); 122158712Smariusstatic uint16_t le_cbus_rdcsr(struct lance_softc *, uint16_t); 123158712Smariusstatic void le_cbus_hwreset(struct lance_softc *); 124158712Smariusstatic bus_dmamap_callback_t le_cbus_dma_callback; 125158712Smarius 126158712Smariusstatic void 127158712Smariusle_cbus_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val) 128158712Smarius{ 129158712Smarius struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; 130158712Smarius 131158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); 132158712Smarius bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, 133158712Smarius BUS_SPACE_BARRIER_WRITE); 134158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_BDP, val); 135158712Smarius} 136158712Smarius 137158712Smarius#ifdef LEDEBUG 138158712Smariusstatic uint16_t 139158712Smariusle_cbus_rdbcr(struct lance_softc *sc, uint16_t port) 140158712Smarius{ 141158712Smarius struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; 142158712Smarius 143158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); 144158712Smarius bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, 145158712Smarius BUS_SPACE_BARRIER_WRITE); 146158712Smarius return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_BDP)); 147158712Smarius} 148158712Smarius#endif 149158712Smarius 150158712Smariusstatic void 151158712Smariusle_cbus_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 152158712Smarius{ 153158712Smarius struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; 154158712Smarius 155158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); 156158712Smarius bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, 157158712Smarius BUS_SPACE_BARRIER_WRITE); 158158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RDP, val); 159158712Smarius} 160158712Smarius 161158712Smariusstatic uint16_t 162158712Smariusle_cbus_rdcsr(struct lance_softc *sc, uint16_t port) 163158712Smarius{ 164158712Smarius struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; 165158712Smarius 166158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, port); 167158712Smarius bus_space_barrier(lesc->sc_regt, lesc->sc_regh, CNET98S_RAP, 2, 168158712Smarius BUS_SPACE_BARRIER_WRITE); 169158712Smarius return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RDP)); 170158712Smarius} 171158712Smarius 172158712Smariusstatic void 173158712Smariusle_cbus_hwreset(struct lance_softc *sc) 174158712Smarius{ 175158712Smarius struct le_cbus_softc *lesc = (struct le_cbus_softc *)sc; 176158712Smarius 177158712Smarius /* 178158712Smarius * NB: These are Contec C-NET(98)S only. 179158712Smarius */ 180158712Smarius 181158712Smarius /* Reset the chip. */ 182158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET, 183158712Smarius bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET)); 184158712Smarius DELAY(500); 185158712Smarius 186158712Smarius /* ISA bus configuration */ 187158712Smarius /* ISACSR0 - set Master Mode Read Active time to 300ns. */ 188158712Smarius le_cbus_wrbcr(sc, LE_BCR0, 0x0006); 189158712Smarius /* ISACSR1 - set Master Mode Write Active time to 300ns. */ 190158712Smarius le_cbus_wrbcr(sc, LE_BCR1, 0x0006); 191158712Smarius#ifdef LEDEBUG 192158712Smarius device_printf(dev, "ISACSR2=0x%x\n", le_cbus_rdbcr(sc, LE_BCR2)); 193158712Smarius#endif 194158712Smarius /* ISACSR5 - LED1 */ 195158712Smarius le_cbus_wrbcr(sc, LE_BCR5, LE_B4_PSE | LE_B4_XMTE); 196158712Smarius /* ISACSR6 - LED2 */ 197158712Smarius le_cbus_wrbcr(sc, LE_BCR6, LE_B4_PSE | LE_B4_RCVE); 198158712Smarius /* ISACSR7 - LED3 */ 199158712Smarius le_cbus_wrbcr(sc, LE_BCR7, LE_B4_PSE | LE_B4_COLE); 200158712Smarius} 201158712Smarius 202158712Smariusstatic void 203158712Smariusle_cbus_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 204158712Smarius{ 205158712Smarius struct lance_softc *sc = (struct lance_softc *)xsc; 206158712Smarius 207158712Smarius if (error != 0) 208158712Smarius return; 209158712Smarius KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); 210158712Smarius sc->sc_addr = segs[0].ds_addr; 211158712Smarius} 212158712Smarius 213158712Smariusstatic int 214158712Smariusle_cbus_probe(device_t dev) 215158712Smarius{ 216158712Smarius struct le_cbus_softc *lesc; 217158712Smarius struct lance_softc *sc; 218158712Smarius int error; 219158712Smarius 220158829Snyan /* 221158829Snyan * Skip PnP devices as some wedge when trying to probe them as 222158829Snyan * C-NET(98)S. 223158829Snyan */ 224158829Snyan if (isa_get_vendorid(dev)) 225158829Snyan return (ENXIO); 226158829Snyan 227158712Smarius lesc = device_get_softc(dev); 228158712Smarius sc = &lesc->sc_am7990.lsc; 229158712Smarius 230158712Smarius lesc->sc_rrid = 0; 231158712Smarius lesc->sc_rres = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &lesc->sc_rrid, 232158712Smarius le_ioaddr_cnet98s, CNET98S_IOSIZE, RF_ACTIVE); 233158712Smarius if (lesc->sc_rres == NULL) 234158712Smarius return (ENXIO); 235158712Smarius isa_load_resourcev(lesc->sc_rres, le_ioaddr_cnet98s, CNET98S_IOSIZE); 236158712Smarius lesc->sc_regt = rman_get_bustag(lesc->sc_rres); 237158712Smarius lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); 238158712Smarius 239158712Smarius /* Reset the chip. */ 240158712Smarius bus_space_write_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET, 241158712Smarius bus_space_read_2(lesc->sc_regt, lesc->sc_regh, CNET98S_RESET)); 242158712Smarius DELAY(500); 243158712Smarius 244158712Smarius /* Stop the chip and put it in a known state. */ 245158712Smarius le_cbus_wrcsr(sc, LE_CSR0, LE_C0_STOP); 246158712Smarius DELAY(100); 247158712Smarius if (le_cbus_rdcsr(sc, LE_CSR0) != LE_C0_STOP) { 248158712Smarius error = ENXIO; 249158712Smarius goto fail; 250158712Smarius } 251158712Smarius le_cbus_wrcsr(sc, LE_CSR3, 0); 252158712Smarius device_set_desc(dev, "C-NET(98)S"); 253158712Smarius error = BUS_PROBE_DEFAULT; 254158712Smarius 255158712Smarius fail: 256158712Smarius bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); 257158712Smarius return (error); 258158712Smarius} 259158712Smarius 260158712Smariusstatic int 261158712Smariusle_cbus_attach(device_t dev) 262158712Smarius{ 263158712Smarius struct le_cbus_softc *lesc; 264158712Smarius struct lance_softc *sc; 265158712Smarius int error, i; 266158712Smarius 267158712Smarius lesc = device_get_softc(dev); 268158712Smarius sc = &lesc->sc_am7990.lsc; 269158712Smarius 270158712Smarius LE_LOCK_INIT(sc, device_get_nameunit(dev)); 271158712Smarius 272158712Smarius lesc->sc_rrid = 0; 273158712Smarius lesc->sc_rres = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &lesc->sc_rrid, 274158712Smarius le_ioaddr_cnet98s, CNET98S_IOSIZE, RF_ACTIVE); 275158712Smarius if (lesc->sc_rres == NULL) { 276158712Smarius device_printf(dev, "cannot allocate registers\n"); 277158712Smarius error = ENXIO; 278158712Smarius goto fail_mtx; 279158712Smarius } 280158712Smarius isa_load_resourcev(lesc->sc_rres, le_ioaddr_cnet98s, CNET98S_IOSIZE); 281158712Smarius lesc->sc_regt = rman_get_bustag(lesc->sc_rres); 282158712Smarius lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); 283158712Smarius 284158712Smarius lesc->sc_irid = 0; 285158712Smarius if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 286158712Smarius &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 287158712Smarius device_printf(dev, "cannot allocate interrupt\n"); 288158712Smarius error = ENXIO; 289158712Smarius goto fail_rres; 290158712Smarius } 291158712Smarius 292158712Smarius error = bus_dma_tag_create( 293166138Smarius bus_get_dma_tag(dev), /* parent */ 294158712Smarius 1, 0, /* alignment, boundary */ 295158712Smarius BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ 296158712Smarius BUS_SPACE_MAXADDR, /* highaddr */ 297158712Smarius NULL, NULL, /* filter, filterarg */ 298158712Smarius BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 299158712Smarius 0, /* nsegments */ 300158712Smarius BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 301166148Smarius 0, /* flags */ 302158712Smarius NULL, NULL, /* lockfunc, lockarg */ 303158712Smarius &lesc->sc_pdmat); 304158712Smarius if (error != 0) { 305158712Smarius device_printf(dev, "cannot allocate parent DMA tag\n"); 306158712Smarius goto fail_ires; 307158712Smarius } 308158712Smarius 309158712Smarius sc->sc_memsize = LE_CBUS_MEMSIZE; 310158712Smarius /* 311158712Smarius * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte 312158712Smarius * aligned and the ring descriptors must be 8-byte aligned. 313158712Smarius */ 314158712Smarius error = bus_dma_tag_create( 315158712Smarius lesc->sc_pdmat, /* parent */ 316158712Smarius 8, 0, /* alignment, boundary */ 317158712Smarius BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ 318158712Smarius BUS_SPACE_MAXADDR, /* highaddr */ 319158712Smarius NULL, NULL, /* filter, filterarg */ 320158712Smarius sc->sc_memsize, /* maxsize */ 321158712Smarius 1, /* nsegments */ 322158712Smarius sc->sc_memsize, /* maxsegsize */ 323166148Smarius 0, /* flags */ 324158712Smarius NULL, NULL, /* lockfunc, lockarg */ 325158712Smarius &lesc->sc_dmat); 326158712Smarius if (error != 0) { 327158712Smarius device_printf(dev, "cannot allocate buffer DMA tag\n"); 328158712Smarius goto fail_pdtag; 329158712Smarius } 330158712Smarius 331158712Smarius error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, 332158712Smarius BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); 333158712Smarius if (error != 0) { 334158712Smarius device_printf(dev, "cannot allocate DMA buffer memory\n"); 335158712Smarius goto fail_dtag; 336158712Smarius } 337158712Smarius 338158712Smarius sc->sc_addr = 0; 339158712Smarius error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, 340158712Smarius sc->sc_memsize, le_cbus_dma_callback, sc, 0); 341158712Smarius if (error != 0 || sc->sc_addr == 0) { 342158712Smarius device_printf(dev, "cannot load DMA buffer map\n"); 343158712Smarius goto fail_dmem; 344158712Smarius } 345158712Smarius 346158712Smarius sc->sc_flags = 0; 347158712Smarius sc->sc_conf3 = 0; 348158712Smarius 349158712Smarius /* 350158712Smarius * Extract the physical MAC address from the ROM. 351158712Smarius */ 352158712Smarius for (i = 0; i < sizeof(sc->sc_enaddr); i++) 353158712Smarius sc->sc_enaddr[i] = bus_space_read_1(lesc->sc_regt, 354158712Smarius lesc->sc_regh, i * 2); 355158712Smarius 356158712Smarius sc->sc_copytodesc = lance_copytobuf_contig; 357158712Smarius sc->sc_copyfromdesc = lance_copyfrombuf_contig; 358158712Smarius sc->sc_copytobuf = lance_copytobuf_contig; 359158712Smarius sc->sc_copyfrombuf = lance_copyfrombuf_contig; 360158712Smarius sc->sc_zerobuf = lance_zerobuf_contig; 361158712Smarius 362158712Smarius sc->sc_rdcsr = le_cbus_rdcsr; 363158712Smarius sc->sc_wrcsr = le_cbus_wrcsr; 364158712Smarius sc->sc_hwreset = le_cbus_hwreset; 365158712Smarius sc->sc_hwinit = NULL; 366158712Smarius sc->sc_hwintr = NULL; 367158712Smarius sc->sc_nocarrier = NULL; 368158712Smarius sc->sc_mediachange = NULL; 369158712Smarius sc->sc_mediastatus = NULL; 370158712Smarius sc->sc_supmedia = NULL; 371158712Smarius 372158712Smarius error = am7990_config(&lesc->sc_am7990, device_get_name(dev), 373158712Smarius device_get_unit(dev)); 374158712Smarius if (error != 0) { 375158712Smarius device_printf(dev, "cannot attach Am7990\n"); 376158712Smarius goto fail_dmap; 377158712Smarius } 378158712Smarius 379158712Smarius error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, 380166901Spiso NULL, am7990_intr, sc, &lesc->sc_ih); 381158712Smarius if (error != 0) { 382158712Smarius device_printf(dev, "cannot set up interrupt\n"); 383158712Smarius goto fail_am7990; 384158712Smarius } 385158712Smarius 386158712Smarius return (0); 387158712Smarius 388158712Smarius fail_am7990: 389158712Smarius am7990_detach(&lesc->sc_am7990); 390158712Smarius fail_dmap: 391158712Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 392158712Smarius fail_dmem: 393158712Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 394158712Smarius fail_dtag: 395158712Smarius bus_dma_tag_destroy(lesc->sc_dmat); 396158712Smarius fail_pdtag: 397158712Smarius bus_dma_tag_destroy(lesc->sc_pdmat); 398158712Smarius fail_ires: 399158712Smarius bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); 400158712Smarius fail_rres: 401158712Smarius bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); 402158712Smarius fail_mtx: 403158712Smarius LE_LOCK_DESTROY(sc); 404158712Smarius return (error); 405158712Smarius} 406158712Smarius 407158712Smariusstatic int 408158712Smariusle_cbus_detach(device_t dev) 409158712Smarius{ 410158712Smarius struct le_cbus_softc *lesc; 411158712Smarius struct lance_softc *sc; 412158712Smarius 413158712Smarius lesc = device_get_softc(dev); 414158712Smarius sc = &lesc->sc_am7990.lsc; 415158712Smarius 416158712Smarius bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); 417158712Smarius am7990_detach(&lesc->sc_am7990); 418158712Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 419158712Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 420158712Smarius bus_dma_tag_destroy(lesc->sc_dmat); 421158712Smarius bus_dma_tag_destroy(lesc->sc_pdmat); 422158712Smarius bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); 423158712Smarius bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); 424158712Smarius LE_LOCK_DESTROY(sc); 425158712Smarius 426158712Smarius return (0); 427158712Smarius} 428158712Smarius 429158712Smariusstatic int 430158712Smariusle_cbus_suspend(device_t dev) 431158712Smarius{ 432158712Smarius struct le_cbus_softc *lesc; 433158712Smarius 434158712Smarius lesc = device_get_softc(dev); 435158712Smarius 436158712Smarius lance_suspend(&lesc->sc_am7990.lsc); 437158712Smarius 438158712Smarius return (0); 439158712Smarius} 440158712Smarius 441158712Smariusstatic int 442158712Smariusle_cbus_resume(device_t dev) 443158712Smarius{ 444158712Smarius struct le_cbus_softc *lesc; 445158712Smarius 446158712Smarius lesc = device_get_softc(dev); 447158712Smarius 448158712Smarius lance_resume(&lesc->sc_am7990.lsc); 449158712Smarius 450158712Smarius return (0); 451158712Smarius} 452