Home | History | Annotate | Line # | Download | only in isa
if_le_isa.c revision 1.9
      1 /*	$NetBSD: if_le_isa.c,v 1.9 1997/03/15 18:11:48 is Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
      5  * Copyright (c) 1992, 1993
      6  *	The Regents of the University of California.  All rights reserved.
      7  *
      8  * This code is derived from software contributed to Berkeley by
      9  * Ralph Campbell and Rick Macklem.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the University of
     22  *	California, Berkeley and its contributors.
     23  * 4. Neither the name of the University nor the names of its contributors
     24  *    may be used to endorse or promote products derived from this software
     25  *    without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37  * SUCH DAMAGE.
     38  *
     39  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
     40  */
     41 
     42 #include "bpfilter.h"
     43 
     44 #include <sys/param.h>
     45 #include <sys/systm.h>
     46 #include <sys/mbuf.h>
     47 #include <sys/syslog.h>
     48 #include <sys/socket.h>
     49 #include <sys/device.h>
     50 
     51 #include <net/if.h>
     52 #include <net/if_ether.h>
     53 
     54 #ifdef INET
     55 #include <netinet/in.h>
     56 #include <netinet/if_inarp.h>
     57 #endif
     58 
     59 #include <vm/vm.h>
     60 
     61 #include <machine/cpu.h>
     62 #include <machine/intr.h>
     63 #include <machine/bus.h>
     64 
     65 #include <dev/isa/isareg.h>
     66 #include <dev/isa/isavar.h>
     67 #include <dev/isa/isadmavar.h>
     68 
     69 #include <dev/ic/am7990reg.h>
     70 #include <dev/ic/am7990var.h>
     71 
     72 #include <dev/isa/if_levar.h>
     73 
     74 static char *card_type[] =
     75     { "unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA" };
     76 
     77 int le_isa_probe __P((struct device *, void *, void *));
     78 void le_isa_attach __P((struct device *, struct device *, void *));
     79 
     80 struct cfattach le_isa_ca = {
     81 	sizeof(struct le_softc), le_isa_probe, le_isa_attach
     82 };
     83 
     84 int depca_isa_probe __P((struct le_softc *, struct isa_attach_args *));
     85 int ne2100_isa_probe __P((struct le_softc *, struct isa_attach_args *));
     86 int bicc_isa_probe __P((struct le_softc *, struct isa_attach_args *));
     87 int lance_isa_probe __P((struct am7990_softc *));
     88 
     89 int le_isa_intredge __P((void *));
     90 
     91 hide void le_isa_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
     92 hide u_int16_t le_isa_rdcsr __P((struct am7990_softc *, u_int16_t));
     93 
     94 void	depca_copytobuf __P((struct am7990_softc *, void *, int, int));
     95 void	depca_copyfrombuf __P((struct am7990_softc *, void *, int, int));
     96 void	depca_zerobuf __P((struct am7990_softc *, int, int));
     97 
     98 hide void
     99 le_isa_wrcsr(sc, port, val)
    100 	struct am7990_softc *sc;
    101 	u_int16_t port, val;
    102 {
    103 	struct le_softc *lesc = (struct le_softc *)sc;
    104 	bus_space_tag_t iot = lesc->sc_iot;
    105 	bus_space_handle_t ioh = lesc->sc_ioh;
    106 
    107 	bus_space_write_2(iot, ioh, lesc->sc_rap, port);
    108 	bus_space_write_2(iot, ioh, lesc->sc_rdp, val);
    109 }
    110 
    111 hide u_int16_t
    112 le_isa_rdcsr(sc, port)
    113 	struct am7990_softc *sc;
    114 	u_int16_t port;
    115 {
    116 	struct le_softc *lesc = (struct le_softc *)sc;
    117 	bus_space_tag_t iot = lesc->sc_iot;
    118 	bus_space_handle_t ioh = lesc->sc_ioh;
    119 	u_int16_t val;
    120 
    121 	bus_space_write_2(iot, ioh, lesc->sc_rap, port);
    122 	val = bus_space_read_2(iot, ioh, lesc->sc_rdp);
    123 	return (val);
    124 }
    125 
    126 int
    127 le_isa_probe(parent, match, aux)
    128 	struct device *parent;
    129 	void *match, *aux;
    130 {
    131 	struct le_softc *lesc = match;
    132 	struct isa_attach_args *ia = aux;
    133 
    134 	if (bicc_isa_probe(lesc, ia))
    135 		return (1);
    136 	if (ne2100_isa_probe(lesc, ia))
    137 		return (1);
    138 	if (depca_isa_probe(lesc, ia))
    139 		return (1);
    140 
    141 	return (0);
    142 }
    143 
    144 int
    145 depca_isa_probe(lesc, ia)
    146 	struct le_softc *lesc;
    147 	struct isa_attach_args *ia;
    148 {
    149 	struct am7990_softc *sc = &lesc->sc_am7990;
    150 	int iobase = ia->ia_iobase, port;
    151 	bus_space_tag_t iot = ia->ia_iot;
    152 	bus_space_handle_t ioh;
    153 	bus_space_handle_t memh;
    154 #if 0
    155 	u_int32_t sum, rom_sum;
    156 	u_int8_t x;
    157 #endif
    158 	int i;
    159 
    160 	/* Map i/o space. */
    161 	if (bus_space_map(iot, iobase, 16, 0, &ioh))
    162 		return 0;
    163 
    164 	if (ia->ia_maddr == MADDRUNK || ia->ia_msize == -1)
    165 		goto bad;
    166 
    167 	/* Map card RAM. */
    168 	if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize,
    169 	    0, &memh))
    170 		goto bad;
    171 
    172 	/* Just needed to check mapability; don't need it anymore. */
    173 	bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
    174 
    175 	lesc->sc_iot = iot;
    176 	lesc->sc_ioh = ioh;
    177 	lesc->sc_rap = DEPCA_RAP;
    178 	lesc->sc_rdp = DEPCA_RDP;
    179 	lesc->sc_card = DEPCA;
    180 
    181 	if (lance_isa_probe(sc) == 0)
    182 		goto bad;
    183 
    184 	bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_DUM);
    185 
    186 	/*
    187 	 * Extract the physical MAC address from the ROM.
    188 	 *
    189 	 * The address PROM is 32 bytes wide, and we access it through
    190 	 * a single I/O port.  On each read, it rotates to the next
    191 	 * position.  We find the ethernet address by looking for a
    192 	 * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff,
    193 	 * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the
    194 	 * ethernet address and a checksum).
    195 	 *
    196 	 * It appears that the PROM can be at one of two locations, so
    197 	 * we just try both.
    198 	 */
    199 	port = DEPCA_ADP;
    200 	for (i = 0; i < 32; i++)
    201 		if (bus_space_read_1(iot, ioh, port) == 0xff &&
    202 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
    203 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
    204 		    bus_space_read_1(iot, ioh, port) == 0xaa &&
    205 		    bus_space_read_1(iot, ioh, port) == 0xff &&
    206 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
    207 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
    208 		    bus_space_read_1(iot, ioh, port) == 0xaa)
    209 			goto found;
    210 	port = DEPCA_ADP + 1;
    211 	for (i = 0; i < 32; i++)
    212 		if (bus_space_read_1(iot, ioh, port) == 0xff &&
    213 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
    214 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
    215 		    bus_space_read_1(iot, ioh, port) == 0xaa &&
    216 		    bus_space_read_1(iot, ioh, port) == 0xff &&
    217 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
    218 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
    219 		    bus_space_read_1(iot, ioh, port) == 0xaa)
    220 			goto found;
    221 	printf("%s: address not found\n", sc->sc_dev.dv_xname);
    222 	goto bad;
    223 
    224 found:
    225 	for (i = 0; i < sizeof(sc->sc_enaddr); i++)
    226 		sc->sc_enaddr[i] = bus_space_read_1(iot, ioh, port);
    227 
    228 #if 0
    229 	sum =
    230 	    (sc->sc_enaddr[0] <<  2) +
    231 	    (sc->sc_enaddr[1] << 10) +
    232 	    (sc->sc_enaddr[2] <<  1) +
    233 	    (sc->sc_enaddr[3] <<  9) +
    234 	    (sc->sc_enaddr[4] <<  0) +
    235 	    (sc->sc_enaddr[5] <<  8);
    236 	sum = (sum & 0xffff) + (sum >> 16);
    237 	sum = (sum & 0xffff) + (sum >> 16);
    238 
    239 	rom_sum = bus_space_read_1(iot, ioh, port);
    240 	rom_sum |= bus_space_read_1(iot, ioh, port) << 8;
    241 
    242 	if (sum != rom_sum) {
    243 		printf("%s: checksum mismatch; calculated %04x != read %04x",
    244 		    sc->sc_dev.dv_xname, sum, rom_sum);
    245 		goto bad;
    246 	}
    247 #endif
    248 
    249 	bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_NORMAL);
    250 
    251 	/*
    252 	 * XXX INDIRECT BROKENNESS!
    253 	 * XXX Should always unmap, and re-map in if_le_isa_attach().
    254 	 */
    255 
    256 	ia->ia_iosize = 16;
    257 	ia->ia_drq = DRQUNK;
    258 	return 1;
    259 
    260  bad:
    261 	bus_space_unmap(iot, ioh, 16);
    262 	return 0;
    263 }
    264 
    265 int
    266 ne2100_isa_probe(lesc, ia)
    267 	struct le_softc *lesc;
    268 	struct isa_attach_args *ia;
    269 {
    270 	struct am7990_softc *sc = &lesc->sc_am7990;
    271 	int iobase = ia->ia_iobase;
    272 	bus_space_tag_t iot = ia->ia_iot;
    273 	bus_space_handle_t ioh;
    274 	int i;
    275 
    276 	/* Map i/o space. */
    277 	if (bus_space_map(iot, iobase, 24, 0, &ioh))
    278 		return 0;
    279 
    280 	lesc->sc_iot = iot;
    281 	lesc->sc_ioh = ioh;
    282 	lesc->sc_rap = NE2100_RAP;
    283 	lesc->sc_rdp = NE2100_RDP;
    284 	lesc->sc_card = NE2100;
    285 
    286 	if (lance_isa_probe(sc) == 0) {
    287 		bus_space_unmap(iot, ioh, 24);
    288 		return 0;
    289 	}
    290 
    291 	/*
    292 	 * Extract the physical MAC address from the ROM.
    293 	 */
    294 	for (i = 0; i < sizeof(sc->sc_enaddr); i++)
    295 		sc->sc_enaddr[i] = bus_space_read_1(iot, ioh, i);
    296 
    297 	/*
    298 	 * XXX INDIRECT BROKENNESS!
    299 	 * XXX Should always unmap, and re-map in if_le_isa_attach().
    300 	 */
    301 
    302 	ia->ia_iosize = 24;
    303 	return 1;
    304 }
    305 
    306 int
    307 bicc_isa_probe(lesc, ia)
    308 	struct le_softc *lesc;
    309 	struct isa_attach_args *ia;
    310 {
    311 	struct am7990_softc *sc = &lesc->sc_am7990;
    312 	int iobase = ia->ia_iobase;
    313 	bus_space_tag_t iot = ia->ia_iot;
    314 	bus_space_handle_t ioh;
    315 	int i;
    316 
    317 	/* Map i/o space. */
    318 	if (bus_space_map(iot, iobase, 16, 0, &ioh))
    319 		return 0;
    320 
    321 	lesc->sc_iot = iot;
    322 	lesc->sc_ioh = ioh;
    323 	lesc->sc_rap = BICC_RAP;
    324 	lesc->sc_rdp = BICC_RDP;
    325 	lesc->sc_card = BICC;
    326 
    327 	if (lance_isa_probe(sc) == 0) {
    328 		bus_space_unmap(iot, ioh, 16);
    329 		return 0;
    330 	}
    331 
    332 	/*
    333 	 * Extract the physical MAC address from the ROM.
    334 	 */
    335 	for (i = 0; i < sizeof(sc->sc_enaddr); i++)
    336 		sc->sc_enaddr[i] = bus_space_read_1(iot, ioh, i * 2);
    337 
    338 	/*
    339 	 * XXX INDIRECT BROKENNESS!
    340 	 * XXX Should always unmap, and re-map in if_le_isa_attach().
    341 	 */
    342 
    343 	ia->ia_iosize = 16;
    344 	return 1;
    345 }
    346 
    347 /*
    348  * Determine which chip is present on the card.
    349  */
    350 int
    351 lance_isa_probe(sc)
    352 	struct am7990_softc *sc;
    353 {
    354 
    355 	/* Stop the LANCE chip and put it in a known state. */
    356 	le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP);
    357 	delay(100);
    358 
    359 	if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP)
    360 		return 0;
    361 
    362 	le_isa_wrcsr(sc, LE_CSR3, sc->sc_conf3);
    363 	return 1;
    364 }
    365 
    366 void
    367 le_isa_attach(parent, self, aux)
    368 	struct device *parent, *self;
    369 	void *aux;
    370 {
    371 	struct le_softc *lesc = (void *)self;
    372 	struct am7990_softc *sc = &lesc->sc_am7990;
    373 	struct isa_attach_args *ia = aux;
    374 	bus_space_tag_t iot = ia->ia_iot;
    375 	bus_space_tag_t memt = ia->ia_memt;
    376 	bus_space_handle_t memh;
    377 
    378 	printf(": %s Ethernet\n", card_type[lesc->sc_card]);
    379 
    380 	lesc->sc_iot = iot;
    381 	lesc->sc_memt = memt;
    382 
    383 	/* XXX SHOULD RE-MAP I/O SPACE HERE. */
    384 
    385 	if (lesc->sc_card == DEPCA) {
    386 		u_char val;
    387 		int i;
    388 
    389 		/* Map shared memory. */
    390 		if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize,
    391 		    0, &memh))
    392 			panic("le_isa_attach: can't map shared memory");
    393 
    394 		lesc->sc_memh = memh;
    395 
    396 		val = 0xff;
    397 		for (;;) {
    398 #if 0	/* XXX !! */
    399 			bus_space_set_region_1(memt, memh, 0, val);
    400 #else
    401 			for (i = 0; i < ia->ia_msize; i++)
    402 				bus_space_write_1(memt, memh, i, val);
    403 #endif
    404 			for (i = 0; i < ia->ia_msize; i++)
    405 				if (bus_space_read_1(memt, memh, 1) != val) {
    406 					printf("%s: failed to clear memory\n",
    407 					    sc->sc_dev.dv_xname);
    408 					return;
    409 				}
    410 			if (val == 0x00)
    411 				break;
    412 			val -= 0x55;
    413 		}
    414 
    415 		sc->sc_conf3 = LE_C3_ACON;
    416 		sc->sc_mem = 0;			/* Not used. */
    417 		sc->sc_addr = 0;
    418 		sc->sc_memsize = ia->ia_msize;
    419 	} else {
    420 		sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT);
    421 		if (sc->sc_mem == 0) {
    422 			printf("%s: couldn't allocate memory for card\n",
    423 			    sc->sc_dev.dv_xname);
    424 			return;
    425 		}
    426 
    427 		sc->sc_conf3 = 0;
    428 		sc->sc_addr = kvtop(sc->sc_mem);	/* XXX !! */
    429 		sc->sc_memsize = 16384;
    430 	}
    431 
    432 	if (lesc->sc_card == DEPCA) {
    433 		sc->sc_copytodesc = depca_copytobuf;
    434 		sc->sc_copyfromdesc = depca_copyfrombuf;
    435 		sc->sc_copytobuf = depca_copytobuf;
    436 		sc->sc_copyfrombuf = depca_copyfrombuf;
    437 		sc->sc_zerobuf = depca_zerobuf;
    438 	} else {
    439 		sc->sc_copytodesc = am7990_copytobuf_contig;
    440 		sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
    441 		sc->sc_copytobuf = am7990_copytobuf_contig;
    442 		sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
    443 		sc->sc_zerobuf = am7990_zerobuf_contig;
    444 	}
    445 
    446 	sc->sc_rdcsr = le_isa_rdcsr;
    447 	sc->sc_wrcsr = le_isa_wrcsr;
    448 	sc->sc_hwinit = NULL;
    449 
    450 	printf("%s", sc->sc_dev.dv_xname);
    451 	am7990_config(sc);
    452 
    453 	if (ia->ia_drq != DRQUNK)
    454 		isa_dmacascade(ia->ia_drq);
    455 
    456 	lesc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
    457 	    IPL_NET, le_isa_intredge, sc);
    458 }
    459 
    460 /*
    461  * Controller interrupt.
    462  */
    463 int
    464 le_isa_intredge(arg)
    465 	void *arg;
    466 {
    467 
    468 	if (am7990_intr(arg) == 0)
    469 		return (0);
    470 	for (;;)
    471 		if (am7990_intr(arg) == 0)
    472 			return (1);
    473 }
    474 
    475 /*
    476  * DEPCA shared memory access functions.
    477  */
    478 
    479 void
    480 depca_copytobuf(sc, from, boff, len)
    481 	struct am7990_softc *sc;
    482 	void *from;
    483 	int boff, len;
    484 {
    485 	struct le_softc *lesc = (struct le_softc *)sc;
    486 
    487 	bus_space_write_region_1(lesc->sc_memt, lesc->sc_memh, boff,
    488 	    from, len);
    489 }
    490 
    491 void
    492 depca_copyfrombuf(sc, to, boff, len)
    493 	struct am7990_softc *sc;
    494 	void *to;
    495 	int boff, len;
    496 {
    497 	struct le_softc *lesc = (struct le_softc *)sc;
    498 
    499 	bus_space_read_region_1(lesc->sc_memt, lesc->sc_memh, boff,
    500 	    to, len);
    501 }
    502 
    503 void
    504 depca_zerobuf(sc, boff, len)
    505 	struct am7990_softc *sc;
    506 	int boff, len;
    507 {
    508 	struct le_softc *lesc = (struct le_softc *)sc;
    509 
    510 #if 0	/* XXX !! */
    511 	bus_space_set_region_1(lesc->sc_memt, lesc->sc_memh, boff,
    512 	    0x00, len);
    513 #else
    514 	for (; len != 0; boff++, len--)
    515 		bus_space_write_1(lesc->sc_memt, lesc->sc_memh, boff, 0x00);
    516 #endif
    517 }
    518