Home | History | Annotate | Line # | Download | only in isa
      1 /*	$NetBSD: if_lc_isa.c,v 1.35 2016/07/11 11:31:50 msaitoh Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1994, 1995, 1997 Matt Thomas <matt (at) 3am-software.com>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. The name of the author may not be used to endorse or promote products
     13  *    derived from this software without specific prior written permission
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 /*
     28  * DEC EtherWORKS 3 Ethernet Controllers
     29  *
     30  * Written by Matt Thomas
     31  *
     32  *   This driver supports the LEMAC (DE203, DE204, and DE205) cards.
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: if_lc_isa.c,v 1.35 2016/07/11 11:31:50 msaitoh Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/mbuf.h>
     41 #include <sys/socket.h>
     42 #include <sys/ioctl.h>
     43 #include <sys/errno.h>
     44 #include <sys/syslog.h>
     45 #include <sys/select.h>
     46 #include <sys/device.h>
     47 #include <sys/queue.h>
     48 
     49 #include <net/if.h>
     50 #include <net/if_dl.h>
     51 #include <net/if_ether.h>
     52 #include <net/if_media.h>
     53 
     54 #include <sys/cpu.h>
     55 #include <sys/bus.h>
     56 #include <sys/intr.h>
     57 
     58 #include <dev/ic/lemacreg.h>
     59 #include <dev/ic/lemacvar.h>
     60 
     61 #include <dev/isa/isavar.h>
     62 
     63 extern struct cfdriver lc_cd;
     64 
     65 static int lemac_isa_find(lemac_softc_t *, const char *,
     66     struct isa_attach_args *, int);
     67 static int lemac_isa_probe(device_t, cfdata_t, void *);
     68 static void lemac_isa_attach(device_t, device_t, void *);
     69 
     70 CFATTACH_DECL_NEW(lc_isa, sizeof(lemac_softc_t),
     71     lemac_isa_probe, lemac_isa_attach, NULL, NULL);
     72 
     73 static int
     74 lemac_isa_find(lemac_softc_t *sc, const char *xname,
     75     struct isa_attach_args *ia, int attach)
     76 {
     77 	bus_addr_t maddr;
     78 	bus_size_t msiz;
     79 	int rv = 0, irq;
     80 
     81 	if (ia->ia_nio < 1)
     82 		return (0);
     83 	if (ia->ia_niomem < 1)
     84 		return (0);
     85 	if (ia->ia_nirq < 1)
     86 		return (0);
     87 
     88 	if (ISA_DIRECT_CONFIG(ia))
     89 		return (0);
     90 
     91 	/*
     92 	 * Disallow wildcarded i/o addresses.
     93 	 */
     94 	if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
     95 		return 0;
     96 
     97 	/*
     98 	 * Make sure this is a valid LEMAC address.
     99 	 */
    100 	if (ia->ia_io[0].ir_addr & (LEMAC_IOSIZE - 1))
    101 		return 0;
    102 
    103 	sc->sc_iot = ia->ia_iot;
    104 
    105 	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, LEMAC_IOSIZE, 0,
    106 	    &sc->sc_ioh)) {
    107 		if (attach)
    108 			printf(": can't map i/o space\n");
    109 		return 0;
    110 	}
    111 
    112 	/*
    113 	 * Read the Ethernet address from the EEPROM.
    114 	 * It must start with one of the DEC OUIs and pass the
    115 	 * DEC ethernet checksum test.
    116 	 */
    117 	if (lemac_port_check(sc->sc_iot, sc->sc_ioh) == 0)
    118 		goto outio;
    119 
    120 	/*
    121 	 * Get information about memory space and attempt to map it.
    122 	 */
    123 	lemac_info_get(sc->sc_iot, sc->sc_ioh, &maddr, &msiz, &irq);
    124 
    125 	if (ia->ia_iomem[0].ir_addr != ISA_UNKNOWN_IOMEM &&
    126 	    ia->ia_iomem[0].ir_addr != maddr)
    127 		goto outio;
    128 
    129 	if (attach) {
    130 		if (msiz == 0) {
    131 			printf(": memory configuration is invalid\n");
    132 			goto outio;
    133 		}
    134 
    135 		sc->sc_memt = ia->ia_memt;
    136 		if (bus_space_map(ia->ia_memt, maddr, msiz, 0, &sc->sc_memh)) {
    137 			printf(": can't map mem space\n");
    138 			goto outio;
    139 		}
    140 	}
    141 
    142 	/*
    143 	 * Double-check IRQ configuration.
    144 	 */
    145 	if (ia->ia_irq[0].ir_irq != ISA_UNKNOWN_IRQ &&
    146 	    ia->ia_irq[0].ir_irq != irq)
    147 		printf("%s: overriding IRQ %d to %d\n", xname,
    148 		       ia->ia_irq[0].ir_irq, irq);
    149 
    150 	if (attach) {
    151 		sc->sc_ats = shutdownhook_establish(lemac_shutdown, sc);
    152 		if (sc->sc_ats == NULL) {
    153 			aprint_normal("\n");
    154 			aprint_error(
    155 				"%s: warning: can't establish shutdown hook\n",
    156 				xname);
    157 		}
    158 
    159 		lemac_ifattach(sc);
    160 
    161 		sc->sc_ih = isa_intr_establish(ia->ia_ic, irq, IST_EDGE,
    162 		    IPL_NET, lemac_intr, sc);
    163 	}
    164 
    165 	/*
    166 	 * I guess we've found one.
    167 	 */
    168 	rv = 1;
    169 
    170 	ia->ia_nio = 1;
    171 	ia->ia_io[0].ir_size = LEMAC_IOSIZE;
    172 
    173 	ia->ia_niomem = 1;
    174 	ia->ia_iomem[0].ir_addr = maddr;
    175 	ia->ia_iomem[0].ir_size = msiz;
    176 
    177 	ia->ia_nirq = 1;
    178 	ia->ia_irq[0].ir_irq = irq;
    179 
    180 	ia->ia_ndrq = 0;
    181 
    182 outio:
    183 	if (rv == 0 || !attach)
    184 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, LEMAC_IOSIZE);
    185 	return rv;
    186 }
    187 
    188 static int
    189 lemac_isa_probe(device_t parent, cfdata_t match, void *aux)
    190 {
    191 	struct isa_attach_args *ia = aux;
    192 	cfdata_t cf = match;
    193 	lemac_softc_t sc;
    194 	char xname[16];
    195 
    196 	snprintf(xname, sizeof(xname), "%s%d", lc_cd.cd_name, cf->cf_unit);
    197 
    198 	return lemac_isa_find(&sc, xname, ia, 0);
    199 }
    200 
    201 static void
    202 lemac_isa_attach(device_t parent, device_t self, void *aux)
    203 {
    204 	lemac_softc_t *sc = device_private(self);
    205 	struct isa_attach_args *ia = aux;
    206 
    207 	sc->sc_dev = self;
    208 	(void) lemac_isa_find(sc, device_xname(self), ia, 1);
    209 }
    210