1158712Smarius/* $NetBSD: if_le_isa.c,v 1.41 2005/12/24 20:27:41 perry Exp $ */ 2158712Smarius 3158712Smarius/*- 4158712Smarius * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5158712Smarius * All rights reserved. 6158712Smarius * 7158712Smarius * This code is derived from software contributed to The NetBSD Foundation 8158712Smarius * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 9158712Smarius * Simulation Facility, NASA Ames Research Center. 10158712Smarius * 11158712Smarius * Redistribution and use in source and binary forms, with or without 12158712Smarius * modification, are permitted provided that the following conditions 13158712Smarius * are met: 14158712Smarius * 1. Redistributions of source code must retain the above copyright 15158712Smarius * notice, this list of conditions and the following disclaimer. 16158712Smarius * 2. Redistributions in binary form must reproduce the above copyright 17158712Smarius * notice, this list of conditions and the following disclaimer in the 18158712Smarius * documentation and/or other materials provided with the distribution. 19158712Smarius * 20158712Smarius * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21158712Smarius * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22158712Smarius * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23158712Smarius * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24158712Smarius * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25158712Smarius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26158712Smarius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27158712Smarius * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28158712Smarius * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29158712Smarius * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30158712Smarius * POSSIBILITY OF SUCH DAMAGE. 31158712Smarius */ 32158712Smarius 33158712Smarius/*- 34158712Smarius * Copyright (c) 1992, 1993 35158712Smarius * The Regents of the University of California. All rights reserved. 36158712Smarius * 37158712Smarius * This code is derived from software contributed to Berkeley by 38158712Smarius * Ralph Campbell and Rick Macklem. 39158712Smarius * 40158712Smarius * Redistribution and use in source and binary forms, with or without 41158712Smarius * modification, are permitted provided that the following conditions 42158712Smarius * are met: 43158712Smarius * 1. Redistributions of source code must retain the above copyright 44158712Smarius * notice, this list of conditions and the following disclaimer. 45158712Smarius * 2. Redistributions in binary form must reproduce the above copyright 46158712Smarius * notice, this list of conditions and the following disclaimer in the 47158712Smarius * documentation and/or other materials provided with the distribution. 48158712Smarius * 3. Neither the name of the University nor the names of its contributors 49158712Smarius * may be used to endorse or promote products derived from this software 50158712Smarius * without specific prior written permission. 51158712Smarius * 52158712Smarius * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53158712Smarius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54158712Smarius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55158712Smarius * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56158712Smarius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57158712Smarius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58158712Smarius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59158712Smarius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60158712Smarius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61158712Smarius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62158712Smarius * SUCH DAMAGE. 63158712Smarius * 64158712Smarius * @(#)if_le.c 8.2 (Berkeley) 11/16/93 65158712Smarius */ 66158712Smarius 67158712Smarius#include <sys/cdefs.h> 68158712Smarius__FBSDID("$FreeBSD: releng/10.3/sys/dev/le/if_le_isa.c 263687 2014-03-24 13:48:04Z emaste $"); 69158712Smarius 70158712Smarius#include <sys/param.h> 71158712Smarius#include <sys/systm.h> 72158712Smarius#include <sys/bus.h> 73158712Smarius#include <sys/endian.h> 74158712Smarius#include <sys/kernel.h> 75158712Smarius#include <sys/lock.h> 76158712Smarius#include <sys/module.h> 77158712Smarius#include <sys/mutex.h> 78158712Smarius#include <sys/resource.h> 79158712Smarius#include <sys/rman.h> 80158712Smarius#include <sys/socket.h> 81158712Smarius 82158712Smarius#include <net/ethernet.h> 83158712Smarius#include <net/if.h> 84158712Smarius#include <net/if_media.h> 85158712Smarius 86158712Smarius#include <machine/bus.h> 87158712Smarius#include <machine/resource.h> 88158712Smarius 89158712Smarius#include <isa/isavar.h> 90158712Smarius 91158712Smarius#include <dev/le/lancereg.h> 92158712Smarius#include <dev/le/lancevar.h> 93158712Smarius#include <dev/le/am7990var.h> 94158712Smarius 95158712Smarius#define LE_ISA_MEMSIZE (16*1024) 96158712Smarius#define PCNET_RDP 0x10 97158712Smarius#define PCNET_RAP 0x12 98158712Smarius 99158712Smariusstruct le_isa_softc { 100158712Smarius struct am7990_softc sc_am7990; /* glue to MI code */ 101158712Smarius 102158712Smarius bus_size_t sc_rap; /* offsets to LANCE... */ 103158712Smarius bus_size_t sc_rdp; /* ...registers */ 104158712Smarius 105158712Smarius struct resource *sc_rres; 106158712Smarius 107158712Smarius struct resource *sc_dres; 108158712Smarius 109158712Smarius struct resource *sc_ires; 110158712Smarius void *sc_ih; 111158712Smarius 112158712Smarius bus_dma_tag_t sc_pdmat; 113158712Smarius bus_dma_tag_t sc_dmat; 114158712Smarius bus_dmamap_t sc_dmam; 115158712Smarius}; 116158712Smarius 117158712Smariusstatic device_probe_t le_isa_probe; 118158712Smariusstatic device_attach_t le_isa_attach; 119158712Smariusstatic device_detach_t le_isa_detach; 120158712Smariusstatic device_resume_t le_isa_resume; 121158712Smariusstatic device_suspend_t le_isa_suspend; 122158712Smarius 123158712Smariusstatic device_method_t le_isa_methods[] = { 124158712Smarius /* Device interface */ 125158712Smarius DEVMETHOD(device_probe, le_isa_probe), 126158712Smarius DEVMETHOD(device_attach, le_isa_attach), 127158712Smarius DEVMETHOD(device_detach, le_isa_detach), 128158712Smarius /* We can just use the suspend method here. */ 129158712Smarius DEVMETHOD(device_shutdown, le_isa_suspend), 130158712Smarius DEVMETHOD(device_suspend, le_isa_suspend), 131158712Smarius DEVMETHOD(device_resume, le_isa_resume), 132158712Smarius 133158712Smarius { 0, 0 } 134158712Smarius}; 135158712Smarius 136158712SmariusDEFINE_CLASS_0(le, le_isa_driver, le_isa_methods, sizeof(struct le_isa_softc)); 137158712SmariusDRIVER_MODULE(le, isa, le_isa_driver, le_devclass, 0, 0); 138158712SmariusMODULE_DEPEND(le, ether, 1, 1, 1); 139158712Smarius 140158712Smariusstruct le_isa_param { 141158712Smarius const char *name; 142158712Smarius u_long iosize; 143158712Smarius bus_size_t rap; 144158712Smarius bus_size_t rdp; 145158712Smarius bus_size_t macstart; 146158712Smarius int macstride; 147158712Smarius} static const le_isa_params[] = { 148158712Smarius { "BICC Isolan", 24, 0xe, 0xc, 0, 2 }, 149158712Smarius { "Novell NE2100", 16, 0x12, 0x10, 0, 1 } 150158712Smarius}; 151158712Smarius 152158712Smariusstatic struct isa_pnp_id le_isa_ids[] = { 153158712Smarius { 0x0322690e, "Cabletron E2200 Single Chip" }, /* CSI2203 */ 154158712Smarius { 0x0110490a, "Boca LANCard Combo" }, /* BRI1001 */ 155158712Smarius { 0x0100a60a, "Melco Inc. LGY-IV" }, /* BUF0001 */ 156158712Smarius { 0xd880d041, "Novell NE2100" }, /* PNP80D8 */ 157158712Smarius { 0x0082d041, "Cabletron E2100 Series DNI" }, /* PNP8200 */ 158158712Smarius { 0x3182d041, "AMD AM1500T/AM2100" }, /* PNP8231 */ 159158712Smarius { 0x8c82d041, "AMD PCnet-ISA" }, /* PNP828C */ 160158712Smarius { 0x8d82d041, "AMD PCnet-32" }, /* PNP828D */ 161158712Smarius { 0xcefaedfe, "Racal InterLan EtherBlaster" }, /* _WMFACE */ 162158712Smarius { 0, NULL } 163158712Smarius}; 164158712Smarius 165158712Smariusstatic void le_isa_wrcsr(struct lance_softc *, uint16_t, uint16_t); 166158712Smariusstatic uint16_t le_isa_rdcsr(struct lance_softc *, uint16_t); 167158712Smariusstatic bus_dmamap_callback_t le_isa_dma_callback; 168158712Smariusstatic int le_isa_probe_legacy(device_t, const struct le_isa_param *); 169158712Smarius 170158712Smariusstatic void 171158712Smariusle_isa_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) 172158712Smarius{ 173158712Smarius struct le_isa_softc *lesc = (struct le_isa_softc *)sc; 174158712Smarius 175183337Smarius bus_write_2(lesc->sc_rres, lesc->sc_rap, port); 176183337Smarius bus_barrier(lesc->sc_rres, lesc->sc_rap, 2, BUS_SPACE_BARRIER_WRITE); 177183337Smarius bus_write_2(lesc->sc_rres, lesc->sc_rdp, val); 178158712Smarius} 179158712Smarius 180158712Smariusstatic uint16_t 181158712Smariusle_isa_rdcsr(struct lance_softc *sc, uint16_t port) 182158712Smarius{ 183158712Smarius struct le_isa_softc *lesc = (struct le_isa_softc *)sc; 184158712Smarius 185183337Smarius bus_write_2(lesc->sc_rres, lesc->sc_rap, port); 186183337Smarius bus_barrier(lesc->sc_rres, lesc->sc_rap, 2, BUS_SPACE_BARRIER_WRITE); 187183337Smarius return (bus_read_2(lesc->sc_rres, lesc->sc_rdp)); 188158712Smarius} 189158712Smarius 190158712Smariusstatic void 191158712Smariusle_isa_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 192158712Smarius{ 193158712Smarius struct lance_softc *sc = (struct lance_softc *)xsc; 194158712Smarius 195158712Smarius if (error != 0) 196158712Smarius return; 197158712Smarius KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); 198158712Smarius sc->sc_addr = segs[0].ds_addr; 199158712Smarius} 200158712Smarius 201158712Smariusstatic int 202158712Smariusle_isa_probe_legacy(device_t dev, const struct le_isa_param *leip) 203158712Smarius{ 204158712Smarius struct le_isa_softc *lesc; 205158712Smarius struct lance_softc *sc; 206183337Smarius int error, i; 207158712Smarius 208158712Smarius lesc = device_get_softc(dev); 209158712Smarius sc = &lesc->sc_am7990.lsc; 210158712Smarius 211183337Smarius i = 0; 212183337Smarius lesc->sc_rres = bus_alloc_resource(dev, SYS_RES_IOPORT, &i, 0, ~0, 213183337Smarius leip->iosize, RF_ACTIVE); 214158712Smarius if (lesc->sc_rres == NULL) 215158712Smarius return (ENXIO); 216158712Smarius lesc->sc_rap = leip->rap; 217158712Smarius lesc->sc_rdp = leip->rdp; 218158712Smarius 219158712Smarius /* Stop the chip and put it in a known state. */ 220158712Smarius le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP); 221158712Smarius DELAY(100); 222158712Smarius if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP) { 223158712Smarius error = ENXIO; 224158712Smarius goto fail; 225158712Smarius } 226158712Smarius le_isa_wrcsr(sc, LE_CSR3, 0); 227158712Smarius error = 0; 228158712Smarius 229158712Smarius fail: 230183337Smarius bus_release_resource(dev, SYS_RES_IOPORT, 231183337Smarius rman_get_rid(lesc->sc_rres), lesc->sc_rres); 232158712Smarius return (error); 233158712Smarius} 234158712Smarius 235158712Smariusstatic int 236158712Smariusle_isa_probe(device_t dev) 237158712Smarius{ 238158712Smarius int i; 239158712Smarius 240158712Smarius switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) { 241158712Smarius case 0: 242158712Smarius return (BUS_PROBE_DEFAULT); 243158712Smarius case ENOENT: 244158712Smarius for (i = 0; i < sizeof(le_isa_params) / 245158712Smarius sizeof(le_isa_params[0]); i++) { 246158712Smarius if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) { 247158712Smarius device_set_desc(dev, le_isa_params[i].name); 248158712Smarius return (BUS_PROBE_DEFAULT); 249158712Smarius } 250158712Smarius } 251158712Smarius /* FALLTHROUGH */ 252158712Smarius case ENXIO: 253158712Smarius default: 254158712Smarius return (ENXIO); 255158712Smarius } 256158712Smarius} 257158712Smarius 258158712Smariusstatic int 259158712Smariusle_isa_attach(device_t dev) 260158712Smarius{ 261158712Smarius struct le_isa_softc *lesc; 262158712Smarius struct lance_softc *sc; 263158712Smarius bus_size_t macstart, rap, rdp; 264183337Smarius int error, i, j, macstride; 265158712Smarius 266158712Smarius lesc = device_get_softc(dev); 267158712Smarius sc = &lesc->sc_am7990.lsc; 268158712Smarius 269158712Smarius LE_LOCK_INIT(sc, device_get_nameunit(dev)); 270158712Smarius 271183337Smarius j = 0; 272158712Smarius switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) { 273158712Smarius case 0: 274158712Smarius lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 275183337Smarius &j, RF_ACTIVE); 276158712Smarius rap = PCNET_RAP; 277158712Smarius rdp = PCNET_RDP; 278158712Smarius macstart = 0; 279158712Smarius macstride = 1; 280158712Smarius break; 281158712Smarius case ENOENT: 282158712Smarius for (i = 0; i < sizeof(le_isa_params) / 283158712Smarius sizeof(le_isa_params[0]); i++) { 284158712Smarius if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) { 285158712Smarius lesc->sc_rres = bus_alloc_resource(dev, 286183337Smarius SYS_RES_IOPORT, &j, 0, ~0, 287158712Smarius le_isa_params[i].iosize, RF_ACTIVE); 288158712Smarius rap = le_isa_params[i].rap; 289158712Smarius rdp = le_isa_params[i].rdp; 290158712Smarius macstart = le_isa_params[i].macstart; 291158712Smarius macstride = le_isa_params[i].macstride; 292158712Smarius goto found; 293158712Smarius } 294158712Smarius } 295158712Smarius /* FALLTHROUGH */ 296158712Smarius case ENXIO: 297158712Smarius default: 298158712Smarius device_printf(dev, "cannot determine chip\n"); 299158712Smarius error = ENXIO; 300158712Smarius goto fail_mtx; 301158712Smarius } 302158712Smarius 303158712Smarius found: 304158712Smarius if (lesc->sc_rres == NULL) { 305158712Smarius device_printf(dev, "cannot allocate registers\n"); 306158712Smarius error = ENXIO; 307158712Smarius goto fail_mtx; 308158712Smarius } 309158712Smarius lesc->sc_rap = rap; 310158712Smarius lesc->sc_rdp = rdp; 311158712Smarius 312183337Smarius i = 0; 313158712Smarius if ((lesc->sc_dres = bus_alloc_resource_any(dev, SYS_RES_DRQ, 314183337Smarius &i, RF_ACTIVE)) == NULL) { 315158712Smarius device_printf(dev, "cannot allocate DMA channel\n"); 316158712Smarius error = ENXIO; 317158712Smarius goto fail_rres; 318158712Smarius } 319158712Smarius 320183337Smarius i = 0; 321158712Smarius if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, 322183337Smarius &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 323158712Smarius device_printf(dev, "cannot allocate interrupt\n"); 324158712Smarius error = ENXIO; 325158712Smarius goto fail_dres; 326158712Smarius } 327158712Smarius 328158712Smarius error = bus_dma_tag_create( 329166138Smarius bus_get_dma_tag(dev), /* parent */ 330158712Smarius 1, 0, /* alignment, boundary */ 331158712Smarius BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ 332158712Smarius BUS_SPACE_MAXADDR, /* highaddr */ 333158712Smarius NULL, NULL, /* filter, filterarg */ 334158712Smarius BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 335158712Smarius 0, /* nsegments */ 336158712Smarius BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 337166148Smarius 0, /* flags */ 338158712Smarius NULL, NULL, /* lockfunc, lockarg */ 339158712Smarius &lesc->sc_pdmat); 340158712Smarius if (error != 0) { 341158712Smarius device_printf(dev, "cannot allocate parent DMA tag\n"); 342158712Smarius goto fail_ires; 343158712Smarius } 344158712Smarius 345158712Smarius sc->sc_memsize = LE_ISA_MEMSIZE; 346158712Smarius /* 347158712Smarius * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte 348158712Smarius * aligned and the ring descriptors must be 8-byte aligned. 349158712Smarius */ 350158712Smarius error = bus_dma_tag_create( 351158712Smarius lesc->sc_pdmat, /* parent */ 352158712Smarius 8, 0, /* alignment, boundary */ 353158712Smarius BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ 354158712Smarius BUS_SPACE_MAXADDR, /* highaddr */ 355158712Smarius NULL, NULL, /* filter, filterarg */ 356158712Smarius sc->sc_memsize, /* maxsize */ 357158712Smarius 1, /* nsegments */ 358158712Smarius sc->sc_memsize, /* maxsegsize */ 359166148Smarius 0, /* flags */ 360158712Smarius NULL, NULL, /* lockfunc, lockarg */ 361158712Smarius &lesc->sc_dmat); 362158712Smarius if (error != 0) { 363158712Smarius device_printf(dev, "cannot allocate buffer DMA tag\n"); 364158712Smarius goto fail_pdtag; 365158712Smarius } 366158712Smarius 367158712Smarius error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, 368158712Smarius BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); 369158712Smarius if (error != 0) { 370158712Smarius device_printf(dev, "cannot allocate DMA buffer memory\n"); 371158712Smarius goto fail_dtag; 372158712Smarius } 373158712Smarius 374158712Smarius sc->sc_addr = 0; 375158712Smarius error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, 376158712Smarius sc->sc_memsize, le_isa_dma_callback, sc, 0); 377158712Smarius if (error != 0 || sc->sc_addr == 0) { 378183337Smarius device_printf(dev, "cannot load DMA buffer map\n"); 379158712Smarius goto fail_dmem; 380158712Smarius } 381158712Smarius 382158712Smarius isa_dmacascade(rman_get_start(lesc->sc_dres)); 383158712Smarius 384158712Smarius sc->sc_flags = 0; 385158712Smarius sc->sc_conf3 = 0; 386158712Smarius 387158712Smarius /* 388158712Smarius * Extract the physical MAC address from the ROM. 389158712Smarius */ 390158712Smarius for (i = 0; i < sizeof(sc->sc_enaddr); i++) 391183337Smarius sc->sc_enaddr[i] = bus_read_1(lesc->sc_rres, 392183337Smarius macstart + i * macstride); 393158712Smarius 394158712Smarius sc->sc_copytodesc = lance_copytobuf_contig; 395158712Smarius sc->sc_copyfromdesc = lance_copyfrombuf_contig; 396158712Smarius sc->sc_copytobuf = lance_copytobuf_contig; 397158712Smarius sc->sc_copyfrombuf = lance_copyfrombuf_contig; 398158712Smarius sc->sc_zerobuf = lance_zerobuf_contig; 399158712Smarius 400158712Smarius sc->sc_rdcsr = le_isa_rdcsr; 401158712Smarius sc->sc_wrcsr = le_isa_wrcsr; 402158712Smarius sc->sc_hwreset = NULL; 403158712Smarius sc->sc_hwinit = NULL; 404158712Smarius sc->sc_hwintr = NULL; 405158712Smarius sc->sc_nocarrier = NULL; 406158712Smarius sc->sc_mediachange = NULL; 407158712Smarius sc->sc_mediastatus = NULL; 408158712Smarius sc->sc_supmedia = NULL; 409158712Smarius 410158712Smarius error = am7990_config(&lesc->sc_am7990, device_get_name(dev), 411158712Smarius device_get_unit(dev)); 412158712Smarius if (error != 0) { 413158712Smarius device_printf(dev, "cannot attach Am7990\n"); 414158712Smarius goto fail_dmap; 415158712Smarius } 416158712Smarius 417158712Smarius error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, 418166901Spiso NULL, am7990_intr, sc, &lesc->sc_ih); 419158712Smarius if (error != 0) { 420158712Smarius device_printf(dev, "cannot set up interrupt\n"); 421158712Smarius goto fail_am7990; 422158712Smarius } 423158712Smarius 424158712Smarius return (0); 425158712Smarius 426158712Smarius fail_am7990: 427158712Smarius am7990_detach(&lesc->sc_am7990); 428158712Smarius fail_dmap: 429158712Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 430158712Smarius fail_dmem: 431158712Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 432158712Smarius fail_dtag: 433158712Smarius bus_dma_tag_destroy(lesc->sc_dmat); 434158712Smarius fail_pdtag: 435158712Smarius bus_dma_tag_destroy(lesc->sc_pdmat); 436158712Smarius fail_ires: 437183337Smarius bus_release_resource(dev, SYS_RES_IRQ, 438183337Smarius rman_get_rid(lesc->sc_ires), lesc->sc_ires); 439158712Smarius fail_dres: 440183337Smarius bus_release_resource(dev, SYS_RES_DRQ, 441183337Smarius rman_get_rid(lesc->sc_dres), lesc->sc_dres); 442158712Smarius fail_rres: 443183337Smarius bus_release_resource(dev, SYS_RES_IOPORT, 444183337Smarius rman_get_rid(lesc->sc_rres), lesc->sc_rres); 445158712Smarius fail_mtx: 446158712Smarius LE_LOCK_DESTROY(sc); 447158712Smarius return (error); 448158712Smarius} 449158712Smarius 450158712Smariusstatic int 451158712Smariusle_isa_detach(device_t dev) 452158712Smarius{ 453158712Smarius struct le_isa_softc *lesc; 454158712Smarius struct lance_softc *sc; 455158712Smarius 456158712Smarius lesc = device_get_softc(dev); 457158712Smarius sc = &lesc->sc_am7990.lsc; 458158712Smarius 459158712Smarius bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); 460158712Smarius am7990_detach(&lesc->sc_am7990); 461158712Smarius bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); 462158712Smarius bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); 463158712Smarius bus_dma_tag_destroy(lesc->sc_dmat); 464158712Smarius bus_dma_tag_destroy(lesc->sc_pdmat); 465183337Smarius bus_release_resource(dev, SYS_RES_IRQ, 466183337Smarius rman_get_rid(lesc->sc_ires), lesc->sc_ires); 467183337Smarius bus_release_resource(dev, SYS_RES_DRQ, 468183337Smarius rman_get_rid(lesc->sc_dres), lesc->sc_dres); 469183337Smarius bus_release_resource(dev, SYS_RES_IOPORT, 470183337Smarius rman_get_rid(lesc->sc_rres), lesc->sc_rres); 471158712Smarius LE_LOCK_DESTROY(sc); 472158712Smarius 473158712Smarius return (0); 474158712Smarius} 475158712Smarius 476158712Smariusstatic int 477158712Smariusle_isa_suspend(device_t dev) 478158712Smarius{ 479158712Smarius struct le_isa_softc *lesc; 480158712Smarius 481158712Smarius lesc = device_get_softc(dev); 482158712Smarius 483158712Smarius lance_suspend(&lesc->sc_am7990.lsc); 484158712Smarius 485158712Smarius return (0); 486158712Smarius} 487158712Smarius 488158712Smariusstatic int 489158712Smariusle_isa_resume(device_t dev) 490158712Smarius{ 491158712Smarius struct le_isa_softc *lesc; 492158712Smarius 493158712Smarius lesc = device_get_softc(dev); 494158712Smarius 495158712Smarius lance_resume(&lesc->sc_am7990.lsc); 496158712Smarius 497158712Smarius return (0); 498158712Smarius} 499