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