Home | History | Annotate | Line # | Download | only in isa
if_ef.c revision 1.1
      1 /*	$NetBSD: if_ef.c,v 1.1 1998/02/27 23:51:52 pk Exp $ */
      2 /*	$Id: if_ef.c,v 1.1 1998/02/27 23:51:52 pk Exp $ */
      3 
      4 /*-
      5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      6  * All rights reserved.
      7  *
      8  * This code is derived from software contributed to The NetBSD Foundation
      9  * by Rafal K. Boni.
     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 NetBSD
     22  *	Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/mbuf.h>
     43 #include <sys/errno.h>
     44 #include <sys/device.h>
     45 #include <sys/protosw.h>
     46 #include <sys/socket.h>
     47 
     48 #include <net/if.h>
     49 #include <net/if_dl.h>
     50 #include <net/if_types.h>
     51 #include <net/if_media.h>
     52 #include <net/if_ether.h>
     53 
     54 #include <vm/vm.h>
     55 
     56 #include <machine/cpu.h>
     57 #include <machine/bus.h>
     58 #include <machine/intr.h>
     59 
     60 #include <dev/isa/isareg.h>
     61 #include <dev/isa/isavar.h>
     62 
     63 #define _NEW_I82586
     64 #include <dev/ic/i82586reg.h>
     65 #include <dev/ic/i82586var.h>
     66 #include <dev/isa/if_efreg.h>
     67 #include <dev/isa/elink.h>
     68 
     69 #ifdef EF_DEBUG
     70 #define DPRINTF(x)	printf x
     71 #else
     72 #define DPRINTF(x)
     73 #endif
     74 
     75 struct ef_softc {
     76 	struct ie_softc sc_ie;
     77 
     78 	bus_space_tag_t sc_regt;	/* space tag for registers */
     79 	bus_space_handle_t sc_regh;	/* space handle for registers */
     80 
     81 	void* sc_ih;			/* interrupt handle */
     82 
     83 	u_int8_t card_rev;		/* hardware revision */
     84 	u_int8_t card_type;		/* card model -- AUI/BNC or TP */
     85 };
     86 
     87 int ef_media[] = {
     88 	IFM_ETHER | IFM_10_5,
     89 	IFM_ETHER | IFM_10_2,
     90 };
     91 #define NEF_MEDIA       (sizeof(ef_media) / sizeof(ef_media[0]))
     92 
     93 int eftp_media[] = {
     94 	IFM_ETHER | IFM_10_T,
     95 };
     96 #define NEFTP_MEDIA       (sizeof(eftp_media) / sizeof(eftp_media[0]))
     97 
     98 /* Routines required by the MI i82586 driver API */
     99 static void 	ef_reset __P((struct ie_softc *, int));
    100 static void 	ef_hwinit __P((struct ie_softc *));
    101 static void 	ef_atten __P((struct ie_softc *));
    102 static int 	ef_intrhook __P((struct ie_softc *, int));
    103 
    104 static void	ef_copyin __P((struct ie_softc *, void *, int, size_t));
    105 static void	ef_copyout __P((struct ie_softc *, const void *, int, size_t));
    106 
    107 static u_int16_t ef_read_16 __P((struct ie_softc *, int));
    108 static void	ef_write_16 __P((struct ie_softc *, int, u_int16_t));
    109 static void	ef_write_24 __P((struct ie_softc *, int, int));
    110 
    111 static void	ef_mediastatus __P((struct ie_softc *, struct ifmediareq *));
    112 
    113 /* Local routines */
    114 static int 	ef_port_check __P((bus_space_tag_t, bus_space_handle_t));
    115 
    116 #ifdef __BROKEN_INDIRECT_CONFIG
    117 int ef_match __P((struct device *, void*, void *));
    118 #else
    119 int ef_match __P((struct device *, struct cfdata *, void *));
    120 #endif
    121 void ef_attach __P((struct device *, struct device *, void *));
    122 
    123 /*
    124  * This keeps track of which ISAs have been through an ie probe sequence.
    125  * A simple static variable isn't enough, since it's conceivable that
    126  * a system might have more than one ISA bus.
    127  *
    128  * The "isa_bus" member is a pointer to the parent ISA bus device struct
    129  * which will unique per ISA bus.
    130  */
    131 
    132 #define MAXCARDS_PER_ISABUS     8       /* if you have more than 8, you lose */
    133 
    134 struct ef_isabus {
    135     LIST_ENTRY(ef_isabus) isa_link;
    136     struct device *isa_bus;
    137 
    138     int bus_state;
    139 
    140     struct card {
    141         bus_addr_t iobase;
    142         bus_addr_t maddr;
    143         bus_size_t msize;
    144         int irq;
    145         int available;
    146     } isa_cards[MAXCARDS_PER_ISABUS];
    147 };
    148 
    149 static LIST_HEAD(, ef_isabus) ef_isa_buses;
    150 static int ef_isa_buses_inited;
    151 
    152 static void
    153 ef_card_add(
    154     struct ef_isabus *bus,
    155     bus_addr_t iobase,
    156     bus_addr_t maddr,
    157     bus_size_t msize,
    158     int irq)
    159 {
    160     int idx;
    161 
    162     DPRINTF(("Adding 3c507 at 0x%x, IRQ %d, Mem 0x%lx/%ld\n", (u_int) iobase,
    163 						irq, (u_long) maddr, msize));
    164 
    165     for (idx = 0; idx < MAXCARDS_PER_ISABUS; idx++) {
    166         if (bus->isa_cards[idx].available == 0) {
    167             bus->isa_cards[idx].iobase = iobase;
    168             bus->isa_cards[idx].maddr = maddr;
    169             bus->isa_cards[idx].msize = msize;
    170             bus->isa_cards[idx].irq = irq;
    171             bus->isa_cards[idx].available = 1;
    172             break;
    173         }
    174     }
    175 }
    176 
    177 /*
    178  * 3C507 support routines
    179  */
    180 static void
    181 ef_reset(sc, why)
    182 	struct ie_softc *sc;
    183 	int why;
    184 {
    185     struct ef_softc* esc = (struct ef_softc *) sc;
    186 
    187     switch (why) {
    188 
    189       case CHIP_PROBE:		/* reset to chip to see if it responds */
    190         bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_CTRL, EF_CTRL_RESET);
    191         DELAY(100);
    192         bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_CTRL, EF_CTRL_NORMAL);
    193         DELAY(100);
    194 	break;
    195 
    196       case CARD_RESET:		/* this takes around 10sec, and we can get
    197 	break;			 * by quite well w/out it... */
    198     }
    199 }
    200 
    201 static void
    202 ef_atten(sc)
    203 	struct ie_softc *sc;
    204 {
    205     struct ef_softc* esc = (struct ef_softc *) sc;
    206     bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_ATTN, 1);
    207 }
    208 
    209 static void
    210 ef_hwinit(sc)
    211 	struct ie_softc *sc;
    212 {
    213     struct ef_softc* esc = (struct ef_softc *) sc;
    214     bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_ICTRL, 1);
    215 }
    216 
    217 static int
    218 ef_intrhook(sc, where)
    219 	struct ie_softc *sc;
    220 	int where;
    221 {
    222     unsigned char cr;
    223     struct ef_softc* esc = (struct ef_softc *) sc;
    224 
    225     switch (where) {
    226 
    227       case INTR_ENTER:		/* entering ISR: disable, ack card interrupts */
    228 	cr = bus_space_read_1(esc->sc_regt, esc->sc_regh, EF_CTRL);
    229 	bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_CTRL,
    230 							cr & ~EF_CTRL_IEN);
    231     	bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_ICTRL, 1);
    232 	break;
    233 
    234       case INTR_EXIT:		/* exiting ISR: re-enable card interrupts */
    235 	cr = bus_space_read_1(esc->sc_regt, esc->sc_regh, EF_CTRL);
    236 	bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_CTRL,
    237 							cr | EF_CTRL_IEN);
    238 	break;
    239 
    240       case INTR_LOOP:		/* looping in ISR: ack new interrupts */
    241     	bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_ICTRL, 1);
    242 	break;
    243     }
    244 
    245     return 1;
    246 }
    247 
    248 static u_int16_t
    249 ef_read_16 (sc, offset)
    250 	struct ie_softc *sc;
    251 	int offset;
    252 {
    253 	bus_space_barrier(sc->bt, sc->bh, offset, 2, BUS_SPACE_BARRIER_READ);
    254 	return bus_space_read_2(sc->bt, sc->bh, offset);
    255 }
    256 
    257 static void
    258 ef_copyin (sc, dst, offset, size)
    259 	struct ie_softc *sc;
    260 	void *dst;
    261 	int offset;
    262 	size_t size;
    263 {
    264     int dribble;
    265     u_int8_t* bptr = dst;
    266 
    267     bus_space_barrier(sc->bt, sc->bh, offset, size, BUS_SPACE_BARRIER_READ);
    268 
    269     if (offset % 2) {
    270 	*bptr = bus_space_read_1(sc->bt, sc->bh, offset);
    271 	offset++; bptr++; size--;
    272     }
    273 
    274     dribble = size % 2;
    275     bus_space_read_region_2(sc->bt, sc->bh, offset, (u_int16_t *) bptr,
    276 								  size >> 1);
    277 
    278     if (dribble) {
    279 	bptr += size - 1;
    280 	offset += size - 1;
    281 	*bptr = bus_space_read_1(sc->bt, sc->bh, offset);
    282     }
    283 }
    284 
    285 static void
    286 ef_copyout (sc, src, offset, size)
    287 	struct ie_softc *sc;
    288 	const void *src;
    289 	int offset;
    290 	size_t size;
    291 {
    292     int dribble;
    293     int osize = size;
    294     int ooffset = offset;
    295     const u_int8_t* bptr = src;
    296 
    297     if (offset % 2) {
    298 	bus_space_write_1(sc->bt, sc->bh, offset, *bptr);
    299 	offset++; bptr++; size--;
    300     }
    301 
    302     dribble = size % 2;
    303     bus_space_write_region_2(sc->bt, sc->bh, offset, (u_int16_t *)bptr,
    304 								  size >> 1);
    305     if (dribble) {
    306 	bptr += size - 1;
    307 	offset += size - 1;
    308 	bus_space_write_1(sc->bt, sc->bh, offset, *bptr);
    309     }
    310 
    311     bus_space_barrier(sc->bt, sc->bh, ooffset, osize, BUS_SPACE_BARRIER_WRITE);
    312 }
    313 
    314 static void
    315 ef_write_16 (sc, offset, value)
    316 	struct ie_softc *sc;
    317 	int offset;
    318 	u_int16_t value;
    319 {
    320 	bus_space_write_2(sc->bt, sc->bh, offset, value);
    321 	bus_space_barrier(sc->bt, sc->bh, offset, 2, BUS_SPACE_BARRIER_WRITE);
    322 }
    323 
    324 static void
    325 ef_write_24 (sc, offset, addr)
    326 	struct ie_softc *sc;
    327 	int offset, addr;
    328 {
    329 	bus_space_write_4(sc->bt, sc->bh, offset, addr +
    330 				(u_long) sc->sc_maddr - (u_long) sc->sc_iobase);
    331 	bus_space_barrier(sc->bt, sc->bh, offset, 4, BUS_SPACE_BARRIER_WRITE);
    332 }
    333 
    334 static void
    335 ef_mediastatus(sc, ifmr)
    336         struct ie_softc *sc;
    337         struct ifmediareq *ifmr;
    338 {
    339         struct ifmedia *ifm = &sc->sc_media;
    340 
    341         /*
    342          * The currently selected media is always the active media.
    343          */
    344         ifmr->ifm_active = ifm->ifm_cur->ifm_media;
    345 }
    346 
    347 int
    348 ef_match(parent, cf, aux)
    349 	struct device *parent;
    350 #ifdef __BROKEN_INDIRECT_CONFIG
    351         void *cf;
    352 #else
    353 	struct cfdata *cf;
    354 #endif
    355 	void *aux;
    356 {
    357     struct ef_softc *sc = (struct ef_softc *) cf;
    358     struct isa_attach_args * const ia = aux;
    359 
    360     int idx;
    361     struct ef_isabus *bus;
    362 
    363     bus_space_handle_t ioh;
    364     bus_space_tag_t iot = ia->ia_iot;
    365 
    366     if (ef_isa_buses_inited == 0) {
    367         LIST_INIT(&ef_isa_buses);
    368         ef_isa_buses_inited = 1;
    369     }
    370 
    371     /*
    372      * Probe this bus if we haven't done so already.
    373      */
    374     for (bus = ef_isa_buses.lh_first; bus != NULL;
    375                                          bus = bus->isa_link.le_next) {
    376         if (bus->isa_bus == parent)
    377             break;
    378     }
    379 
    380     if (bus == NULL) {
    381         bus_addr_t iobase;
    382 
    383         /*
    384          * Mark this bus so we don't probe it again.
    385          */
    386         bus = (struct ef_isabus *)
    387             malloc(sizeof(struct ef_isabus), M_DEVBUF, M_NOWAIT);
    388         if (bus == NULL)
    389             panic("ef_isa_probe: can't allocate state storage for %s",
    390                   parent->dv_xname);
    391 
    392 	bus->bus_state = 0;		/* nothing done yet */
    393         bus->isa_bus = parent;
    394 
    395         LIST_INSERT_HEAD(&ef_isa_buses, bus, isa_link);
    396 
    397 	if (bus_space_map(iot, ELINK_ID_PORT, 1, 0, &ioh)) {
    398 		DPRINTF(("3c507 probe: can't map Etherlink ID port\n"));
    399 		return 0;
    400 	}
    401 
    402 	/*
    403 	 * Reset and put card in CONFIG state without changing address.
    404 	 */
    405 	elink_reset(iot, ioh, sc->sc_ie.sc_dev.dv_parent->dv_unit);
    406 	elink_idseq(iot, ioh, ELINK_507_POLY);
    407 	elink_idseq(iot, ioh, ELINK_507_POLY);
    408         bus_space_write_1(iot, ioh, 0, 0xff);
    409 
    410 	/* Unmap the ID port */
    411 	bus_space_unmap(iot, ioh, 1);
    412 
    413 	bus->bus_state++;		/* cards now in CONFIG state */
    414 
    415         for (iobase = EF_IOBASE_LOW; iobase <= EF_IOBASE_HIGH;
    416 						iobase += EF_IOSIZE) {
    417             /*
    418              * Map the 507's port-space for the probe sequence.
    419              */
    420             if (bus_space_map(iot, iobase, EF_IOSIZE, 0, &ioh) != 0)
    421                 continue;
    422 
    423             /* Now look for the 3Com magic bytes */
    424 
    425             if (ef_port_check(iot, ioh)) {
    426                 int irq;
    427 		u_int8_t v;
    428                 bus_addr_t maddr;
    429                 bus_addr_t msize;
    430                 bus_space_handle_t memh;
    431 
    432 		irq = bus_space_read_1(iot, ioh, EF_IRQ) & EF_IRQ_MASK;
    433 
    434 		v = bus_space_read_1(iot, ioh, EF_MADDR);
    435 		maddr = ((v & EF_MADDR_MASK) << EF_MADDR_SHIFT) + EF_MADDR_BASE;
    436 		msize = ((v & EF_MSIZE_MASK) + 1) * EF_MSIZE_STEP;
    437 
    438                 if (bus_space_map(ia->ia_memt, maddr, msize, 0, &memh) == 0) {
    439                     ef_card_add(bus, iobase, maddr, msize, irq);
    440                     bus_space_unmap(ia->ia_memt, memh, msize);
    441                 }
    442             }
    443             bus_space_unmap(iot, ioh, EF_IOSIZE);
    444         }
    445     }
    446 
    447     for (idx = 0; idx < MAXCARDS_PER_ISABUS; idx++) {
    448         if (bus->isa_cards[idx].available != 1)
    449             continue;
    450         if (ia->ia_iobase != IOBASEUNK
    451                 && ia->ia_iobase != bus->isa_cards[idx].iobase)
    452             continue;
    453         if (ia->ia_maddr != MADDRUNK
    454                 && ia->ia_maddr != bus->isa_cards[idx].maddr)
    455             continue;
    456         if (ia->ia_irq != IRQUNK && ia->ia_irq != bus->isa_cards[idx].irq)
    457             continue;
    458         break;
    459     }
    460     if (idx == MAXCARDS_PER_ISABUS)
    461         return 0;
    462 
    463     bus->isa_cards[idx].available++;
    464     ia->ia_iobase = bus->isa_cards[idx].iobase;
    465     ia->ia_irq    = bus->isa_cards[idx].irq;
    466     ia->ia_iosize = EF_IOSIZE;
    467     ia->ia_maddr  = bus->isa_cards[idx].maddr;
    468     ia->ia_msize  = bus->isa_cards[idx].msize;
    469     return 1;
    470 }
    471 
    472 void
    473 ef_attach(parent, self, aux)
    474 	struct device *parent;
    475 	struct device *self;
    476 	void   *aux;
    477 {
    478     struct ef_softc *esc = (void *)self;
    479     struct ie_softc *sc = &esc->sc_ie;
    480     struct isa_attach_args *ia = aux;
    481     bus_space_tag_t iot = ia->ia_iot;
    482 
    483     int i;
    484     char version[20];
    485     struct ef_isabus *bus;
    486     u_int8_t partno[EF_TYPE_LEN];
    487     bus_space_handle_t ioh, memh;
    488     u_int8_t ethaddr[ETHER_ADDR_LEN];
    489 
    490     sc->hwinit = ef_hwinit;
    491     sc->hwreset = ef_reset;
    492     sc->chan_attn = ef_atten;
    493     sc->intrhook = ef_intrhook;
    494 
    495     sc->memcopyin = ef_copyin;
    496     sc->memcopyout = ef_copyout;
    497     sc->ie_bus_read16 = ef_read_16;
    498     sc->ie_bus_write16 = ef_write_16;
    499     sc->ie_bus_write24 = ef_write_24;
    500 
    501     sc->sc_msize = 0;
    502 
    503     /*
    504      * NOP chains don't give any advantage on this card, in fact they seem
    505      * to slow it down some.  As the doctor says, "if it hurts, don't do it".
    506      */
    507     sc->do_xmitnopchain = 0;
    508 
    509     sc->sc_mediachange = NULL;
    510     sc->sc_mediastatus = ef_mediastatus;
    511 
    512     /* Find the cards parent bus */
    513     for (bus = ef_isa_buses.lh_first; bus != NULL;
    514                                          bus = bus->isa_link.le_next) {
    515         if (bus->isa_bus == parent)
    516             break;
    517     }
    518 
    519     if (bus == NULL)
    520         panic("%s: Can't find parent bus!", sc->sc_dev.dv_xname);
    521 
    522 
    523     /* If the bus hasn't been transitioned to the RUN state, do so now */
    524     if (bus->bus_state == 1) {
    525         if (bus_space_map(iot, ELINK_ID_PORT, 1, 0, &ioh) != 0) {
    526 	    DPRINTF(("\n%s: Can't map Elink ID port!\n", sc->sc_dev.dv_xname));
    527 	    return;
    528 	}
    529 
    530         bus_space_write_1(ia->ia_iot, ioh, 0, 0x00);
    531         elink_idseq(ia->ia_iot, ioh, ELINK_507_POLY);
    532         bus_space_write_1(ia->ia_iot, ioh, 0, 0x00);
    533         bus_space_unmap(ia->ia_iot, ioh, 1);
    534 
    535         bus->bus_state++;
    536     }
    537 
    538     /* Map i/o space. */
    539     if (bus_space_map(ia->ia_iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh) != 0) {
    540         DPRINTF(("\n%s: can't map i/o space 0x%x-0x%x\n",
    541                   sc->sc_dev.dv_xname, ia->ia_iobase,
    542                   ia->ia_iobase + ia->ia_iosize - 1));
    543         return;
    544     }
    545 
    546     esc->sc_regt = ia->ia_iot;
    547     esc->sc_regh = ioh;
    548 
    549     if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh) != 0) {
    550         DPRINTF(("\n%s: can't map iomem space 0x%x-0x%x\n",
    551                 sc->sc_dev.dv_xname, ia->ia_maddr,
    552                 ia->ia_maddr + ia->ia_msize - 1));
    553         bus_space_unmap(ia->ia_iot, ioh, ia->ia_iosize);
    554         return;
    555     }
    556 
    557     sc->bt = ia->ia_memt;
    558     sc->bh = memh;
    559 
    560     sc->sc_msize = ia->ia_msize;
    561     sc->sc_maddr = (void *) memh;
    562     sc->sc_iobase = sc->sc_maddr + sc->sc_msize - (1 << 24);
    563 
    564     /* set up pointers to important on-card control structures */
    565     sc->iscp = 0;
    566     sc->scb = IE_ISCP_SZ;
    567     sc->scp = sc->sc_msize + IE_SCP_ADDR - (1 << 24);
    568 
    569     sc->buf_area = sc->scb + IE_SCB_SZ;
    570     sc->buf_area_sz = sc->sc_msize - IE_ISCP_SZ - IE_SCB_SZ - IE_SCP_SZ;
    571 
    572     /* zero card memory */
    573     bus_space_set_region_1(sc->bt, sc->bh, 0, 0, sc->sc_msize);
    574 
    575     /* set card to 16-bit bus mode */
    576     bus_space_write_1(sc->bt, sc->bh, IE_SCP_BUS_USE((u_long) sc->scp), 0);
    577 
    578     /* set up pointers to key structures */
    579     ef_write_24(sc, IE_SCP_ISCP((u_long)sc->scp), (u_long) sc->iscp);
    580     ef_write_16(sc, IE_ISCP_SCB((u_long)sc->iscp), (u_long) sc->scb);
    581     ef_write_24(sc, IE_ISCP_BASE((u_long)sc->iscp), (u_long) sc->iscp);
    582 
    583     /* flush setup of pointers, check if chip answers */
    584     bus_space_barrier(sc->bt, sc->bh, 0, sc->sc_msize, BUS_SPACE_BARRIER_WRITE);
    585     if (!i82586_proberam(sc)) {
    586         DPRINTF(("\n%s: can't talk to i82586!\n", sc->sc_dev.dv_xname));
    587         bus_space_unmap(ia->ia_iot, ioh, ia->ia_iosize);
    588         bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
    589 	return;
    590     }
    591 
    592     /* set bank 2 for card part number and revision */
    593     bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_CTRL, EF_CTRL_NRST |
    594 							   EF_CTRL_BNK2);
    595 
    596     /* card revision is encoded in BCD */
    597     i = bus_space_read_1(esc->sc_regt, esc->sc_regh, EF_REV);
    598     esc->card_rev = 10*(i / 16) + (i % 16);
    599 
    600     for (i = 0; i < EF_TYPE_LEN; i++)
    601 	partno[i] = bus_space_read_1(esc->sc_regt, esc->sc_regh, EF_TYPE + i);
    602 
    603     /* use part number to guess if card is TP or AUI/BNC model */
    604     esc->card_type = EF_IS_TP(partno) ? EF_CARD_TP : EF_CARD_BNC;
    605 
    606     /* set bank 0 for ethernet address */
    607     bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_CTRL, EF_CTRL_NORMAL);
    608     for (i = 0; i < EF_ADDR_LEN; i++)
    609 	ethaddr[i] = bus_space_read_1(esc->sc_regt, esc->sc_regh, EF_ADDR + i);
    610 
    611     sprintf(version, "%s, rev. %d",
    612 	(esc->card_type == EF_CARD_TP) ? "3C507-TP" : "3C507", esc->card_rev);
    613 
    614     if (esc->card_type == EF_CARD_TP)
    615 	i82586_attach(sc, version, ethaddr, eftp_media, NEFTP_MEDIA,
    616 							eftp_media[0]);
    617     else {
    618 	u_int8_t media = bus_space_read_1(esc->sc_regt, esc->sc_regh, EF_MEDIA);
    619         media = (media & EF_MEDIA_MASK) >> EF_MEDIA_SHIFT;
    620 
    621 	i82586_attach(sc, version, ethaddr, ef_media, NEF_MEDIA,
    622 						      ef_media[media]);
    623     }
    624 
    625     /* Clear the interrupt latch just in case. */
    626     bus_space_write_1(esc->sc_regt, esc->sc_regh, EF_ICTRL, 1);
    627 
    628     esc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
    629 				   IPL_NET, i82586_intr, sc);
    630     if (esc->sc_ih == NULL) {
    631         DPRINTF(("\n%s: can't establish interrupt\n", sc->sc_dev.dv_xname));
    632     }
    633 }
    634 
    635 static int
    636 ef_port_check(iot, ioh)
    637 	bus_space_tag_t iot;
    638 	bus_space_handle_t ioh;
    639 {
    640 	int i;
    641         u_char ch;
    642 	u_char* signature = EF_SIGNATURE;
    643 
    644 	for (i = 0; i < strlen(signature); i++) {
    645 		ch = bus_space_read_1(iot, ioh, i);
    646 		if (ch != signature[i])
    647 			return 0;
    648 	}
    649 
    650 	/* If card is mapped in high memory (above 15Meg), we can't use it */
    651 	ch = bus_space_read_1(iot, ioh, EF_MADDR);
    652 	if (ch & EF_MADDR_HIGH)
    653 	    return 0;			/* XXX: maybe we should panic?? */
    654 
    655 	return 1;
    656 }
    657 
    658 struct cfattach ef_ca = {
    659 	sizeof(struct ef_softc), ef_match, ef_attach
    660 };
    661 
    662