/* $NetBSD: if_lc_isa.c,v 1.19.4.1 2005/04/29 11:28:54 kent Exp $ */ /*- * Copyright (c) 1994, 1995, 1997 Matt Thomas * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * DEC EtherWORKS 3 Ethernet Controllers * * Written by Matt Thomas * * This driver supports the LEMAC (DE203, DE204, and DE205) cards. */ #include __KERNEL_RCSID(0, "$NetBSD: if_lc_isa.c,v 1.19.4.1 2005/04/29 11:28:54 kent Exp $"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern struct cfdriver lc_cd; static int lemac_isa_find(lemac_softc_t *, struct isa_attach_args *, int); static int lemac_isa_probe(struct device *, struct cfdata *, void *); static void lemac_isa_attach(struct device *, struct device *, void *); CFATTACH_DECL(lc_isa, sizeof(lemac_softc_t), lemac_isa_probe, lemac_isa_attach, NULL, NULL); static int lemac_isa_find(sc, ia, attach) lemac_softc_t *sc; struct isa_attach_args *ia; int attach; { bus_addr_t maddr; bus_addr_t msize; int rv = 0, irq; if (ia->ia_nio < 1) return (0); if (ia->ia_niomem < 1) return (0); if (ia->ia_nirq < 1) return (0); if (ISA_DIRECT_CONFIG(ia)) return (0); /* * Disallow wildcarded i/o addresses. */ if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) return 0; /* * Make sure this is a valid LEMAC address. */ if (ia->ia_io[0].ir_addr & (LEMAC_IOSIZE - 1)) return 0; sc->sc_iot = ia->ia_iot; if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, LEMAC_IOSIZE, 0, &sc->sc_ioh)) { if (attach) printf(": can't map i/o space\n"); return 0; } /* * Read the Ethernet address from the EEPROM. * It must start with one of the DEC OUIs and pass the * DEC ethernet checksum test. */ if (lemac_port_check(sc->sc_iot, sc->sc_ioh) == 0) goto outio; /* * Get information about memory space and attempt to map it. */ lemac_info_get(sc->sc_iot, sc->sc_ioh, &maddr, &msize, &irq); if (ia->ia_iomem[0].ir_addr != ISA_UNKNOWN_IOMEM && ia->ia_iomem[0].ir_addr != maddr) goto outio; if (attach) { if (msize == 0) { printf(": memory configuration is invalid\n"); goto outio; } sc->sc_memt = ia->ia_memt; if (bus_space_map(ia->ia_memt, maddr, msize, 0, &sc->sc_memh)) { printf(": can't map mem space\n"); goto outio; } } /* * Double-check IRQ configuration. */ if (ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ && ia->ia_irq[0].ir_irq != irq) printf("%s: overriding IRQ %d to %d\n", sc->sc_dv.dv_xname, ia->ia_irq[0].ir_irq, irq); if (attach) { sc->sc_ats = shutdownhook_establish(lemac_shutdown, sc); if (sc->sc_ats == NULL) printf("\n%s: warning: can't establish shutdown hook\n", sc->sc_dv.dv_xname); lemac_ifattach(sc); sc->sc_ih = isa_intr_establish(ia->ia_ic, irq, IST_EDGE, IPL_NET, lemac_intr, sc); } /* * I guess we've found one. */ rv = 1; ia->ia_nio = 1; ia->ia_io[0].ir_size = LEMAC_IOSIZE; ia->ia_niomem = 1; ia->ia_iomem[0].ir_addr = maddr; ia->ia_iomem[0].ir_size = msize; ia->ia_nirq = 1; ia->ia_irq[0].ir_irq = irq; ia->ia_ndrq = 0; if (rv == 0 && attach) bus_space_unmap(sc->sc_memt, sc->sc_memh, msize); outio: if (rv == 0 || !attach) bus_space_unmap(sc->sc_iot, sc->sc_ioh, LEMAC_IOSIZE); return rv; } static int lemac_isa_probe(parent, match, aux) struct device *parent; struct cfdata *match; void *aux; { struct isa_attach_args *ia = aux; struct cfdata *cf = match; lemac_softc_t sc; snprintf(sc.sc_dv.dv_xname, sizeof(sc.sc_dv.dv_xname), "%s%d", lc_cd.cd_name, cf->cf_unit); return lemac_isa_find(&sc, ia, 0); } static void lemac_isa_attach(parent, self, aux) struct device *parent; struct device *self; void *aux; { lemac_softc_t *sc = (void *)self; struct isa_attach_args *ia = aux; (void) lemac_isa_find(sc, ia, 1); }