1139749Simp/*-
265832Snyan * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
365832Snyan *
465832Snyan * This software may be used, modified, copied, distributed, and sold, in
565832Snyan * both source and binary form provided that the above copyright, these
665832Snyan * terms and the following disclaimer are retained.  The name of the author
765832Snyan * and/or the contributor may not be used to endorse or promote products
865832Snyan * derived from this software without specific prior written permission.
965832Snyan *
1065832Snyan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
1165832Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1265832Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1365832Snyan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
1465832Snyan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1565832Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1665832Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
1765832Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1865832Snyan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1965832Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2065832Snyan * SUCH DAMAGE.
2165832Snyan *
2265832Snyan */
2365832Snyan
24119418Sobrien#include <sys/cdefs.h>
25119418Sobrien__FBSDID("$FreeBSD$");
26119418Sobrien
2765832Snyan#include <sys/param.h>
2865832Snyan#include <sys/systm.h>
2965832Snyan#include <sys/kernel.h>
3065832Snyan#include <sys/socket.h>
3165832Snyan#include <sys/module.h>
3265832Snyan
3365832Snyan#include <sys/bus.h>
3465832Snyan#include <machine/bus.h>
3565832Snyan#include <sys/rman.h>
3665832Snyan
3765832Snyan#include <net/ethernet.h>
3865832Snyan#include <net/if.h>
3965832Snyan#include <net/if_mib.h>
4065832Snyan#include <net/if_media.h>
4165832Snyan
4265832Snyan#include <netinet/in.h>
4365832Snyan#include <netinet/if_ether.h>
4465832Snyan
45142135Simp#include <dev/fe/mb86960.h>
4665832Snyan#include <dev/fe/if_fereg.h>
4765832Snyan#include <dev/fe/if_fevar.h>
4865832Snyan
4967442Snyan#include <isa/isavar.h>
5067442Snyan
5165832Snyan/*
5265832Snyan *	Cbus specific code.
5365832Snyan */
5465832Snyanstatic int fe_isa_probe(device_t);
5565832Snyanstatic int fe_isa_attach(device_t);
5665832Snyan
5790183Snyanstatic struct isa_pnp_id fe_ids[] = {
5890183Snyan	{ 0x101ee0d,	NULL },		/* CON0101 - Contec C-NET(98)P2-T */
5990183Snyan	{ 0,		NULL }
6090183Snyan};
6190183Snyan
6265832Snyanstatic device_method_t fe_isa_methods[] = {
6365832Snyan	/* Device interface */
6465832Snyan	DEVMETHOD(device_probe,		fe_isa_probe),
6565832Snyan	DEVMETHOD(device_attach,	fe_isa_attach),
6665832Snyan
6765832Snyan	{ 0, 0 }
6865832Snyan};
6965832Snyan
7065832Snyanstatic driver_t fe_isa_driver = {
7165832Snyan	"fe",
7265832Snyan	fe_isa_methods,
7365832Snyan	sizeof (struct fe_softc)
7465832Snyan};
7565832Snyan
7665832SnyanDRIVER_MODULE(fe, isa, fe_isa_driver, fe_devclass, 0, 0);
7765832Snyan
7865832Snyan
7965832Snyanstatic int fe98_alloc_port(device_t, int);
8065832Snyan
8165832Snyanstatic int fe_probe_re1000(device_t);
8265832Snyanstatic int fe_probe_cnet9ne(device_t);
8365832Snyanstatic int fe_probe_rex(device_t);
8465832Snyanstatic int fe_probe_ssi(device_t);
8565832Snyanstatic int fe_probe_jli(device_t);
8665832Snyanstatic int fe_probe_lnx(device_t);
8765832Snyanstatic int fe_probe_gwy(device_t);
8865832Snyanstatic int fe_probe_ubn(device_t);
8965832Snyan
9065832Snyan/*
9165832Snyan * Determine if the device is present at a specified I/O address.  The
9265832Snyan * main entry to the driver.
9365832Snyan */
9465832Snyanstatic int
9565832Snyanfe_isa_probe(device_t dev)
9665832Snyan{
9790183Snyan	struct fe_softc *sc;
9865832Snyan	int error;
9965832Snyan
10065832Snyan	/* Prepare for the softc struct.  */
10165832Snyan	sc = device_get_softc(dev);
10265832Snyan	sc->sc_unit = device_get_unit(dev);
10365832Snyan
10490183Snyan	/* Check isapnp ids */
10590183Snyan	error = ISA_PNP_PROBE(device_get_parent(dev), dev, fe_ids);
10690183Snyan
10790183Snyan	/* If the card had a PnP ID that didn't match any we know about */
10890183Snyan	if (error == ENXIO)
10990183Snyan		goto end;
11090183Snyan
11190183Snyan	/* If we had some other problem. */
11290183Snyan	if (!(error == 0 || error == ENOENT))
11390183Snyan		goto end;
11490183Snyan
11565832Snyan	/* Probe for supported boards.  */
11665832Snyan	if ((error = fe_probe_re1000(dev)) == 0)
11765832Snyan		goto end;
11865832Snyan	fe_release_resource(dev);
11965832Snyan
12065832Snyan	if ((error = fe_probe_cnet9ne(dev)) == 0)
12165832Snyan		goto end;
12265832Snyan	fe_release_resource(dev);
12365832Snyan
12465832Snyan	if ((error = fe_probe_rex(dev)) == 0)
12565832Snyan		goto end;
12665832Snyan	fe_release_resource(dev);
12765832Snyan
12865832Snyan	if ((error = fe_probe_ssi(dev)) == 0)
12965832Snyan		goto end;
13065832Snyan	fe_release_resource(dev);
13165832Snyan
13265832Snyan	if ((error = fe_probe_jli(dev)) == 0)
13365832Snyan		goto end;
13465832Snyan	fe_release_resource(dev);
13565832Snyan
13665832Snyan	if ((error = fe_probe_lnx(dev)) == 0)
13765832Snyan		goto end;
13865832Snyan	fe_release_resource(dev);
13965832Snyan
14065832Snyan	if ((error = fe_probe_ubn(dev)) == 0)
14165832Snyan		goto end;
14265832Snyan	fe_release_resource(dev);
14365832Snyan
14465832Snyan	if ((error = fe_probe_gwy(dev)) == 0)
14565832Snyan		goto end;
14665832Snyan	fe_release_resource(dev);
14765832Snyan
14865832Snyanend:
14965832Snyan	if (error == 0)
15065832Snyan		error = fe_alloc_irq(dev, 0);
15165832Snyan
15265832Snyan	fe_release_resource(dev);
15365832Snyan	return (error);
15465832Snyan}
15565832Snyan
15665832Snyanstatic int
15765832Snyanfe_isa_attach(device_t dev)
15865832Snyan{
15965832Snyan	struct fe_softc *sc = device_get_softc(dev);
16065832Snyan
16165832Snyan	if (sc->port_used)
16265832Snyan		fe98_alloc_port(dev, sc->type);
16365832Snyan	fe_alloc_irq(dev, 0);
16465832Snyan
16565832Snyan	return fe_attach(dev);
16665832Snyan}
16765832Snyan
16865832Snyan
16965832Snyan/* Generic I/O address table */
17065832Snyanstatic bus_addr_t ioaddr_generic[MAXREGISTERS] = {
17165832Snyan	0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
17265832Snyan	0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
17365832Snyan	0x010, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x017,
17465832Snyan	0x018, 0x019, 0x01a, 0x01b, 0x01c, 0x01d, 0x01e, 0x01f,
17565832Snyan};
17665832Snyan
17765832Snyan/* I/O address table for RE1000/1000Plus */
17865832Snyanstatic bus_addr_t ioaddr_re1000[MAXREGISTERS] = {
17965832Snyan	0x0000, 0x0001, 0x0200, 0x0201, 0x0400, 0x0401, 0x0600, 0x0601,
18065832Snyan	0x0800, 0x0801, 0x0a00, 0x0a01, 0x0c00, 0x0c01, 0x0e00, 0x0e01,
18165832Snyan	0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00,
18265832Snyan	0x1001, 0x1201, 0x1401, 0x1601, 0x1801, 0x1a01, 0x1c01, 0x1e01,
18365832Snyan};
18465832Snyan
18565832Snyan/* I/O address table for CNET9NE */
18665832Snyanstatic bus_addr_t ioaddr_cnet9ne[MAXREGISTERS] = {
18765832Snyan	0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
18865832Snyan	0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
18965832Snyan	0x400, 0x402, 0x404, 0x406, 0x408, 0x40a, 0x40c, 0x40e,
19065832Snyan	0x401, 0x403, 0x405, 0x407, 0x409, 0x40b, 0x40d, 0x40f,
19165832Snyan};
19265832Snyan
19365832Snyan/* I/O address table for LAC-98 */
19465832Snyanstatic bus_addr_t ioaddr_lnx[MAXREGISTERS] = {
19565832Snyan	0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e,
19665832Snyan	0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e,
19765832Snyan	0x200, 0x202, 0x204, 0x206, 0x208, 0x20a, 0x20c, 0x20e,
19865832Snyan	0x300, 0x302, 0x304, 0x306, 0x308, 0x30a, 0x30c, 0x30e,
19965832Snyan};
20065832Snyan
20165832Snyan/* I/O address table for Access/PC N98C+ */
20265832Snyanstatic bus_addr_t ioaddr_ubn[MAXREGISTERS] = {
20365832Snyan	0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
20465832Snyan	0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
20565832Snyan	0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207,
20665832Snyan	0x208, 0x209, 0x20a, 0x20b, 0x20c, 0x20d, 0x20e, 0x20f,
20765832Snyan};
20865832Snyan
20965832Snyan/* I/O address table for REX-9880 */
21065832Snyanstatic bus_addr_t ioaddr_rex[MAXREGISTERS] = {
21165832Snyan	0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007,
21265832Snyan	0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
21365832Snyan	0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107,
21465832Snyan	0x108, 0x109, 0x10a, 0x10b, 0x10c, 0x10d, 0x10e, 0x10f,
21565832Snyan};
21665832Snyan
21765832Snyanstatic int
21865832Snyanfe98_alloc_port(device_t dev, int type)
21965832Snyan{
22065832Snyan	struct fe_softc *sc = device_get_softc(dev);
22165832Snyan	struct resource *res;
22265832Snyan	bus_addr_t *iat;
22365832Snyan	int size, rid;
22465832Snyan
22565832Snyan	switch (type) {
22665832Snyan	case FE_TYPE_RE1000:
22765832Snyan		iat = ioaddr_re1000;
22865832Snyan		size = MAXREGISTERS;
22965832Snyan		break;
23065832Snyan	case FE_TYPE_CNET9NE:
23179084Snyan		iat = ioaddr_cnet9ne;
23279084Snyan		size = MAXREGISTERS;
23365832Snyan		break;
23465832Snyan	case FE_TYPE_SSI:
23565832Snyan		iat = ioaddr_generic;
23665832Snyan		size = MAXREGISTERS;
23765832Snyan		break;
23865832Snyan	case FE_TYPE_LNX:
23965832Snyan		iat = ioaddr_lnx;
24065832Snyan		size = MAXREGISTERS;
24165832Snyan		break;
24265832Snyan	case FE_TYPE_GWY:
24365832Snyan		iat = ioaddr_generic;
24465832Snyan		size = MAXREGISTERS;
24565832Snyan		break;
24665832Snyan	case FE_TYPE_UBN:
24765832Snyan		iat = ioaddr_ubn;
24865832Snyan		size = MAXREGISTERS;
24965832Snyan		break;
25065832Snyan	case FE_TYPE_REX:
25165832Snyan		iat = ioaddr_rex;
25265832Snyan		size = MAXREGISTERS;
25365832Snyan		break;
25465832Snyan	default:
25565832Snyan		iat = ioaddr_generic;
25665832Snyan		size = MAXREGISTERS;
25765832Snyan		break;
25865832Snyan	}
25965832Snyan
26065832Snyan	rid = 0;
26165832Snyan	res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
26265832Snyan				  iat, size, RF_ACTIVE);
26365832Snyan	if (res == NULL)
26465832Snyan		return ENOENT;
26565832Snyan
26665832Snyan	isa_load_resourcev(res, iat, size);
26765832Snyan
26865832Snyan	sc->type = type;
26965832Snyan	sc->port_used = size;
27065832Snyan	sc->port_res = res;
27165832Snyan	return (0);
27265832Snyan}
27365832Snyan
27465832Snyan
27565832Snyan/*
27665832Snyan * Probe and initialization for Allied-Telesis RE1000 series.
27765832Snyan */
27865832Snyanstatic void
27965832Snyanfe_init_re1000(struct fe_softc *sc)
28065832Snyan{
28165832Snyan	/* Setup IRQ control register on the ASIC.  */
28265832Snyan	fe_outb(sc, FE_RE1000_IRQCONF, sc->priv_info);
28365832Snyan}
28465832Snyan
28565832Snyanstatic int
28665832Snyanfe_probe_re1000(device_t dev)
28765832Snyan{
28865832Snyan	struct fe_softc *sc = device_get_softc(dev);
28965832Snyan	int i, n;
29065832Snyan	u_long iobase, irq;
29165832Snyan	u_char sum;
29265832Snyan
29365832Snyan	static struct fe_simple_probe_struct probe_table [] = {
29465832Snyan		{ FE_DLCR2, 0x58, 0x00 },
29565832Snyan		{ FE_DLCR4, 0x08, 0x00 },
29665832Snyan		{ 0 }
29765832Snyan	};
29865832Snyan
29965832Snyan	/* See if the specified I/O address is possible for RE1000.  */
30065832Snyan	/* [01]D[02468ACE] are allowed.  */
30165832Snyan	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
30265832Snyan		return ENXIO;
30365832Snyan	if ((iobase & ~0x10E) != 0xD0)
30465832Snyan		return ENXIO;
30565832Snyan
30665832Snyan	if (fe98_alloc_port(dev, FE_TYPE_RE1000))
30765832Snyan		return ENXIO;
30865832Snyan
30965832Snyan	/* Fill the softc struct with default values.  */
31065832Snyan	fe_softc_defaults(sc);
31165832Snyan
31265832Snyan	/* See if the card is on its address.  */
31365832Snyan	if (!fe_simple_probe(sc, probe_table))
31465832Snyan		return ENXIO;
31565832Snyan
31665832Snyan	/* Get our station address from EEPROM.  */
317147304Sbrooks	fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
31865832Snyan
31965832Snyan	/* Make sure it is Allied-Telesis's.  */
320147304Sbrooks	if (!fe_valid_Ether_p(sc->enaddr, 0x0000F4))
32165832Snyan		return ENXIO;
32265832Snyan#if 1
32365832Snyan	/* Calculate checksum.  */
32465832Snyan	sum = fe_inb(sc, 0x1e);
32565832Snyan	for (i = 0; i < ETHER_ADDR_LEN; i++)
326147304Sbrooks		sum ^= sc->enaddr[i];
32765832Snyan	if (sum != 0)
32865832Snyan		return ENXIO;
32965832Snyan#endif
33065832Snyan	/* Setup the board type.  */
33165832Snyan	sc->typestr = "RE1000";
33265832Snyan
33365832Snyan	/* This looks like an RE1000 board.  It requires an
33465832Snyan	   explicit IRQ setting in config.  Make sure we have one,
33565832Snyan	   determining an appropriate value for the IRQ control
33665832Snyan	   register.  */
33765832Snyan	irq = 0;
33865832Snyan	bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
33965832Snyan	switch (irq) {
34065832Snyan	case 3:  n = 0x10; break;
34165832Snyan	case 5:  n = 0x20; break;
34265832Snyan	case 6:  n = 0x40; break;
34365832Snyan	case 12: n = 0x80; break;
34465832Snyan	default:
34565832Snyan		fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
34665832Snyan		return ENXIO;
34765832Snyan	}
34865832Snyan	sc->priv_info = (fe_inb(sc, FE_RE1000_IRQCONF) & 0x0f) | n;
34965832Snyan
35065832Snyan	/* Setup hooks.  We need a special initialization procedure.  */
35165832Snyan	sc->init = fe_init_re1000;
35265832Snyan
35365832Snyan	return 0;
35465832Snyan}
35565832Snyan
35665832Snyan/* JLI sub-probe for Allied-Telesis RE1000Plus/ME1500 series.  */
35765832Snyanstatic u_short const *
35865832Snyanfe_probe_jli_re1000p(struct fe_softc * sc, u_char const * eeprom)
35965832Snyan{
36065832Snyan	int i;
36165832Snyan	static u_short const irqmaps_re1000p [4] = { 3, 5, 6, 12 };
36265832Snyan
36365832Snyan	/* Make sure the EEPROM contains Allied-Telesis bit pattern.  */
36465832Snyan	if (eeprom[1] != 0xFF) return NULL;
36565832Snyan	for (i =  2; i <  8; i++) if (eeprom[i] != 0xFF) return NULL;
36665832Snyan	for (i = 14; i < 24; i++) if (eeprom[i] != 0xFF) return NULL;
36765832Snyan
36865832Snyan	/* Get our station address from EEPROM, and make sure the
36965832Snyan           EEPROM contains Allied-Telesis's address.  */
370147304Sbrooks	bcopy(eeprom + 8, sc->enaddr, ETHER_ADDR_LEN);
371147304Sbrooks	if (!fe_valid_Ether_p(sc->enaddr, 0x0000F4))
37265832Snyan		return NULL;
37365832Snyan
37465832Snyan	/* I don't know any sub-model identification.  */
37565832Snyan	sc->typestr = "RE1000Plus/ME1500";
37665832Snyan
37765832Snyan	/* Returns the IRQ table for the RE1000Plus.  */
37865832Snyan	return irqmaps_re1000p;
37965832Snyan}
38065832Snyan
38165832Snyan
38265832Snyan/*
38365832Snyan * Probe for Allied-Telesis RE1000Plus/ME1500 series.
38465832Snyan */
38565832Snyanstatic int
38665832Snyanfe_probe_jli(device_t dev)
38765832Snyan{
38865832Snyan	struct fe_softc *sc = device_get_softc(dev);
38965832Snyan	int i, n, xirq, error;
39065832Snyan	u_long iobase, irq;
39165832Snyan	u_char eeprom [JLI_EEPROM_SIZE];
39265832Snyan	u_short const * irqmap;
39365832Snyan
39465832Snyan	static u_short const baseaddr [8] =
39565832Snyan		{ 0x1D6, 0x1D8, 0x1DA, 0x1D4, 0x0D4, 0x0D2, 0x0D8, 0x0D0 };
39665832Snyan	static struct fe_simple_probe_struct const probe_table [] = {
39765832Snyan	/*	{ FE_DLCR1,  0x20, 0x00 },	Doesn't work. */
39865832Snyan		{ FE_DLCR2,  0x50, 0x00 },
39965832Snyan		{ FE_DLCR4,  0x08, 0x00 },
40065832Snyan	/*	{ FE_DLCR5,  0x80, 0x00 },	Doesn't work. */
40165832Snyan#if 0
40265832Snyan		{ FE_BMPR16, 0x1B, 0x00 },
40365832Snyan		{ FE_BMPR17, 0x7F, 0x00 },
40465832Snyan#endif
40565832Snyan		{ 0 }
40665832Snyan	};
40765832Snyan
40865832Snyan	/*
40965832Snyan	 * See if the specified address is possible for MB86965A JLI mode.
41065832Snyan	 */
41165832Snyan	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
41265832Snyan		return ENXIO;
41365832Snyan	for (i = 0; i < 8; i++) {
41465832Snyan		if (baseaddr[i] == iobase)
41565832Snyan			break;
41665832Snyan	}
41765832Snyan	if (i == 8)
41865832Snyan		return ENXIO;
41965832Snyan
42065832Snyan	if (fe98_alloc_port(dev, FE_TYPE_RE1000))
42165832Snyan		return ENXIO;
42265832Snyan
42365832Snyan	/* Fill the softc struct with default values.  */
42465832Snyan	fe_softc_defaults(sc);
42565832Snyan
42665832Snyan	/*
42765832Snyan	 * We should test if MB86965A is on the base address now.
42865832Snyan	 * Unfortunately, it is very hard to probe it reliably, since
42965832Snyan	 * we have no way to reset the chip under software control.
43065832Snyan	 * On cold boot, we could check the "signature" bit patterns
43165832Snyan	 * described in the Fujitsu document.  On warm boot, however,
43265832Snyan	 * we can predict almost nothing about register values.
43365832Snyan	 */
43465832Snyan	if (!fe_simple_probe(sc, probe_table))
43565832Snyan		return ENXIO;
43665832Snyan
43765832Snyan	/* Check if our I/O address matches config info on 86965.  */
43865832Snyan	n = (fe_inb(sc, FE_BMPR19) & FE_B19_ADDR) >> FE_B19_ADDR_SHIFT;
43965832Snyan	if (baseaddr[n] != iobase)
44065832Snyan		return ENXIO;
44165832Snyan
44265832Snyan	/*
44365832Snyan	 * We are now almost sure we have an MB86965 at the given
44465832Snyan	 * address.  So, read EEPROM through it.  We have to write
44565832Snyan	 * into LSI registers to read from EEPROM.  I want to avoid it
44665832Snyan	 * at this stage, but I cannot test the presence of the chip
44765832Snyan	 * any further without reading EEPROM.  FIXME.
44865832Snyan	 */
44965832Snyan	fe_read_eeprom_jli(sc, eeprom);
45065832Snyan
45165832Snyan	/* Make sure that config info in EEPROM and 86965 agree.  */
45265832Snyan	if (eeprom[FE_EEPROM_CONF] != fe_inb(sc, FE_BMPR19))
45365832Snyan		return ENXIO;
45465832Snyan
45565832Snyan	/* Use 86965 media selection scheme, unless othewise
45665832Snyan           specified.  It is "AUTO always" and "select with BMPR13".
45765832Snyan           This behaviour covers most of the 86965 based board (as
45865832Snyan           minimum requirements.)  It is backward compatible with
45965832Snyan           previous versions, also.  */
46065832Snyan	sc->mbitmap = MB_HA;
46165832Snyan	sc->defmedia = MB_HA;
46265832Snyan	sc->msel = fe_msel_965;
46365832Snyan
46465832Snyan	/* Perform board-specific probe.  */
46565832Snyan	if ((irqmap = fe_probe_jli_re1000p(sc, eeprom)) == NULL)
46665832Snyan		return ENXIO;
46765832Snyan
46865832Snyan	/* Find the IRQ read from EEPROM.  */
46965832Snyan	n = (fe_inb(sc, FE_BMPR19) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT;
47065832Snyan	xirq = irqmap[n];
47165832Snyan
47265832Snyan	/* Try to determine IRQ setting.  */
47365832Snyan	error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
47465832Snyan	if (error && xirq == NO_IRQ) {
47565832Snyan		/* The device must be configured with an explicit IRQ.  */
47665832Snyan		device_printf(dev, "IRQ auto-detection does not work\n");
47765832Snyan		return ENXIO;
47865832Snyan	} else if (error && xirq != NO_IRQ) {
47965832Snyan		/* Just use the probed IRQ value.  */
48065832Snyan		bus_set_resource(dev, SYS_RES_IRQ, 0, xirq, 1);
48165832Snyan	} else if (!error && xirq == NO_IRQ) {
48265832Snyan		/* No problem.  Go ahead.  */
48365832Snyan	} else if (irq == xirq) {
48465832Snyan		/* Good.  Go ahead.  */
48565832Snyan	} else {
48665832Snyan		/* User must be warned in this case.  */
48765832Snyan		sc->stability |= UNSTABLE_IRQ;
48865832Snyan	}
48965832Snyan
49065832Snyan	/* Setup a hook, which resets te 86965 when the driver is being
49165832Snyan           initialized.  This may solve a nasty bug.  FIXME.  */
49265832Snyan	sc->init = fe_init_jli;
49365832Snyan
49465832Snyan	return 0;
49565832Snyan}
49665832Snyan
49765832Snyan
49865832Snyan/*
49965832Snyan * Probe and initialization for Contec C-NET(9N)E series.
50065832Snyan */
50165832Snyan
50265832Snyan/* TODO: Should be in "if_fereg.h" */
50365832Snyan#define FE_CNET9NE_INTR		0x10		/* Interrupt Mask? */
50465832Snyan
50565832Snyanstatic void
50665832Snyanfe_init_cnet9ne(struct fe_softc *sc)
50765832Snyan{
50865832Snyan	/* Enable interrupt?  FIXME.  */
50965832Snyan	fe_outb(sc, FE_CNET9NE_INTR, 0x10);
51065832Snyan}
51165832Snyan
51265832Snyanstatic int
51365832Snyanfe_probe_cnet9ne (device_t dev)
51465832Snyan{
51565832Snyan	struct fe_softc *sc = device_get_softc(dev);
51665832Snyan	u_long iobase, irq;
51765832Snyan
51865832Snyan	static struct fe_simple_probe_struct probe_table [] = {
51965832Snyan		{ FE_DLCR2, 0x58, 0x00 },
52065832Snyan		{ FE_DLCR4, 0x08, 0x00 },
52165832Snyan		{ 0 }
52265832Snyan	};
52365832Snyan
52465832Snyan	/* See if the specified I/O address is possible for C-NET(9N)E.  */
52565832Snyan	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
52665832Snyan		return ENXIO;
52765832Snyan	if (iobase != 0x73D0)
52865832Snyan		return ENXIO;
52965832Snyan
53065832Snyan	if (fe98_alloc_port(dev, FE_TYPE_CNET9NE))
53165832Snyan		return ENXIO;
53265832Snyan
53365832Snyan	/* Fill the softc struct with default values.  */
53465832Snyan	fe_softc_defaults(sc);
53565832Snyan
53665832Snyan	/* See if the card is on its address.  */
53765832Snyan	if (!fe_simple_probe(sc, probe_table))
53865832Snyan		return ENXIO;
53965832Snyan
54065832Snyan	/* Get our station address from EEPROM.  */
541147304Sbrooks	fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
54265832Snyan
54365832Snyan	/* Make sure it is Contec's.  */
544147304Sbrooks	if (!fe_valid_Ether_p(sc->enaddr, 0x00804C))
54565832Snyan		return ENXIO;
54665832Snyan
54765832Snyan	/* Determine the card type.  */
548147304Sbrooks	if (sc->enaddr[3] == 0x06) {
54965832Snyan		sc->typestr = "C-NET(9N)C";
55065832Snyan
55165832Snyan		/* We seems to need our own IDENT bits...  FIXME.  */
55265832Snyan		sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;
55365832Snyan
55465832Snyan		/* C-NET(9N)C requires an explicit IRQ to work.  */
55565832Snyan		if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0) {
55665832Snyan			fe_irq_failure(sc->typestr, sc->sc_unit, NO_IRQ, NULL);
55765832Snyan			return ENXIO;
55865832Snyan		}
55965832Snyan	} else {
56065832Snyan		sc->typestr = "C-NET(9N)E";
56165832Snyan
56265832Snyan		/* C-NET(9N)E works only IRQ5.  */
56365832Snyan		if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0)
56465832Snyan			return ENXIO;
56565832Snyan		if (irq != 5) {
56665832Snyan			fe_irq_failure(sc->typestr, sc->sc_unit, irq, "5");
56765832Snyan			return ENXIO;
56865832Snyan		}
56965832Snyan
57065832Snyan		/* We need an init hook to initialize ASIC before we start.  */
57165832Snyan		sc->init = fe_init_cnet9ne;
57265832Snyan	}
57365832Snyan
57465832Snyan	/* C-NET(9N)E has 64KB SRAM.  */
57565832Snyan	sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB
57665832Snyan			| FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM;
57765832Snyan
57865832Snyan	return 0;
57965832Snyan}
58065832Snyan
58165832Snyan
58265832Snyan/*
58365832Snyan * Probe for Contec C-NET(98)P2 series.
58465832Snyan * (Logitec LAN-98TP/LAN-98T25P - parhaps)
58565832Snyan */
58665832Snyanstatic int
58765832Snyanfe_probe_ssi(device_t dev)
58865832Snyan{
58965832Snyan	struct fe_softc *sc = device_get_softc(dev);
59065832Snyan	u_long iobase, irq;
59165832Snyan
59265832Snyan	u_char eeprom [SSI_EEPROM_SIZE];
59365832Snyan	static struct fe_simple_probe_struct probe_table [] = {
59465832Snyan		{ FE_DLCR2, 0x08, 0x00 },
59565832Snyan		{ FE_DLCR4, 0x08, 0x00 },
59665832Snyan		{ 0 }
59765832Snyan	};
59865832Snyan	static u_short const irqmap[] = {
59965832Snyan		/*                        INT0          INT1    INT2       */
60065832Snyan		NO_IRQ, NO_IRQ, NO_IRQ,      3, NO_IRQ,    5,      6, NO_IRQ,
60165832Snyan		NO_IRQ,      9,     10, NO_IRQ,     12,   13, NO_IRQ, NO_IRQ,
60265832Snyan		/*        INT3   INT41            INT5  INT6               */
60365832Snyan	};
60465832Snyan
60565832Snyan	/* See if the specified I/O address is possible for 78Q8377A.  */
60665832Snyan	/* [0-D]3D0 are allowed.  */
60765832Snyan	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
60865832Snyan		return ENXIO;
60965832Snyan	if ((iobase & 0xFFF) != 0x3D0)
61065832Snyan		return ENXIO;
61165832Snyan
61265832Snyan	if (fe98_alloc_port(dev, FE_TYPE_SSI))
61365832Snyan		return ENXIO;
61465832Snyan
61565832Snyan	/* Fill the softc struct with default values.  */
61665832Snyan	fe_softc_defaults(sc);
61765832Snyan
61865832Snyan	/* See if the card is on its address.  */
61965832Snyan	if (!fe_simple_probe(sc, probe_table))
62065832Snyan		return ENXIO;
62165832Snyan
62265832Snyan	/* We now have to read the config EEPROM.  We should be very
62365832Snyan           careful, since doing so destroys a register.  (Remember, we
62465832Snyan           are not yet sure we have a C-NET(98)P2 board here.)  Don't
62565832Snyan           remember to select BMPRs bofore reading EEPROM, since other
62665832Snyan           register bank may be selected before the probe() is called.  */
62765832Snyan	fe_read_eeprom_ssi(sc, eeprom);
62865832Snyan
62965832Snyan	/* Make sure the Ethernet (MAC) station address is of Contec's.  */
630139972Simp	if (!fe_valid_Ether_p(eeprom + FE_SSI_EEP_ADDR, 0x00804C))
63165832Snyan		return ENXIO;
632147304Sbrooks	bcopy(eeprom + FE_SSI_EEP_ADDR, sc->enaddr, ETHER_ADDR_LEN);
63365832Snyan
63465832Snyan	/* Setup the board type.  */
63565832Snyan        sc->typestr = "C-NET(98)P2";
63665832Snyan
63790183Snyan	/* Non-PnP mode, set static resource from eeprom. */
63890183Snyan	if (!isa_get_vendorid(dev)) {
63990183Snyan		/* Get IRQ configuration from EEPROM.  */
64090183Snyan		irq = irqmap[eeprom[FE_SSI_EEP_IRQ]];
64190183Snyan		if (irq == NO_IRQ) {
64290183Snyan			fe_irq_failure(sc->typestr, sc->sc_unit, irq,
64390183Snyan				       "3/5/6/9/10/12/13");
64490183Snyan			return ENXIO;
64590183Snyan		}
64690183Snyan		bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
64765832Snyan	}
64865832Snyan
64965832Snyan	/* Get Duplex-mode configuration from EEPROM.  */
65065832Snyan	sc->proto_dlcr4 |= (eeprom[FE_SSI_EEP_DUPLEX] & FE_D4_DSC);
65165832Snyan
65265832Snyan	/* Fill softc struct accordingly.  */
65365832Snyan	sc->mbitmap = MB_HT;
65465832Snyan	sc->defmedia = MB_HT;
65565832Snyan
65665832Snyan	return 0;
65765832Snyan}
65865832Snyan
65965832Snyan
66065832Snyan/*
66165832Snyan * Probe for TDK LAC-98012/013/025/9N011 - parhaps.
66265832Snyan */
66365832Snyanstatic int
66465832Snyanfe_probe_lnx(device_t dev)
66565832Snyan{
66665832Snyan	struct fe_softc *sc = device_get_softc(dev);
66765832Snyan
66865832Snyan	u_long iobase, irq;
66965832Snyan	u_char eeprom [LNX_EEPROM_SIZE];
67065832Snyan
67165832Snyan	static struct fe_simple_probe_struct probe_table [] = {
67265832Snyan		{ FE_DLCR2, 0x58, 0x00 },
67365832Snyan		{ FE_DLCR4, 0x08, 0x00 },
67465832Snyan		{ 0 }
67565832Snyan	};
67665832Snyan
67765832Snyan	/* See if the specified I/O address is possible for TDK/LANX boards. */
67865832Snyan	/* 0D0, 4D0, 8D0, and CD0 are allowed.  */
67965832Snyan	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
68065832Snyan		return ENXIO;
68165832Snyan	if ((iobase & ~0xC00) != 0xD0)
68265832Snyan		return ENXIO;
68365832Snyan
68465832Snyan	if (fe98_alloc_port(dev, FE_TYPE_LNX))
68565832Snyan		return ENXIO;
68665832Snyan
68765832Snyan	/* Fill the softc struct with default values.  */
68865832Snyan	fe_softc_defaults(sc);
68965832Snyan
69065832Snyan	/* See if the card is on its address.  */
69165832Snyan	if (!fe_simple_probe(sc, probe_table))
69265832Snyan		return ENXIO;
69365832Snyan
69465832Snyan	/* We now have to read the config EEPROM.  We should be very
69565832Snyan           careful, since doing so destroys a register.  (Remember, we
69665832Snyan           are not yet sure we have a LAC-98012/98013 board here.)  */
69765832Snyan	fe_read_eeprom_lnx(sc, eeprom);
69865832Snyan
69965832Snyan	/* Make sure the Ethernet (MAC) station address is of TDK/LANX's.  */
700139972Simp	if (!fe_valid_Ether_p(eeprom, 0x008098))
70165832Snyan		return ENXIO;
702147304Sbrooks	bcopy(eeprom, sc->enaddr, ETHER_ADDR_LEN);
70365832Snyan
70465832Snyan	/* Setup the board type.  */
70565832Snyan	sc->typestr = "LAC-98012/98013";
70665832Snyan
70765832Snyan	/* This looks like a TDK/LANX board.  It requires an
70865832Snyan	   explicit IRQ setting in config.  Make sure we have one,
70965832Snyan	   determining an appropriate value for the IRQ control
71065832Snyan	   register.  */
71165832Snyan	irq = 0;
71265832Snyan	if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL) != 0)
71365832Snyan		return ENXIO;
71465832Snyan	switch (irq) {
71565832Snyan	case 3 : sc->priv_info = 0x10 | LNX_CLK_LO | LNX_SDA_HI; break;
71665832Snyan	case 5 : sc->priv_info = 0x20 | LNX_CLK_LO | LNX_SDA_HI; break;
71765832Snyan	case 6 : sc->priv_info = 0x40 | LNX_CLK_LO | LNX_SDA_HI; break;
71865832Snyan	case 12: sc->priv_info = 0x80 | LNX_CLK_LO | LNX_SDA_HI; break;
71965832Snyan	default:
72065832Snyan		fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
72165832Snyan		return ENXIO;
72265832Snyan	}
72365832Snyan
72465832Snyan	/* LAC-98's system bus width is 8-bit.  */
72565832Snyan	sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x2KB
72665832Snyan			| FE_D6_BBW_BYTE | FE_D6_SBW_BYTE | FE_D6_SRAM_150ns;
72765832Snyan
72865832Snyan	/* Setup hooks.  We need a special initialization procedure.  */
72965832Snyan	sc->init = fe_init_lnx;
73065832Snyan
73165832Snyan	return 0;
73265832Snyan}
73365832Snyan
73465832Snyan
73565832Snyan/*
73665832Snyan * Probe for Gateway Communications' old cards.
73765832Snyan * (both as Generic MB86960 probe routine)
73865832Snyan */
73965832Snyanstatic int
74065832Snyanfe_probe_gwy(device_t dev)
74165832Snyan{
74265832Snyan	struct fe_softc *sc = device_get_softc(dev);
74365832Snyan
74465832Snyan	static struct fe_simple_probe_struct probe_table [] = {
74565832Snyan	    /*	{ FE_DLCR2, 0x70, 0x00 }, */
74665832Snyan		{ FE_DLCR2, 0x58, 0x00 },
74765832Snyan		{ FE_DLCR4, 0x08, 0x00 },
74865832Snyan		{ 0 }
74965832Snyan	};
75065832Snyan
75165832Snyan	/*
75265832Snyan	 * XXX
75365832Snyan	 * I'm not sure which address is possible, so accepts any.
75465832Snyan	 */
75565832Snyan
75665832Snyan	if (fe98_alloc_port(dev, FE_TYPE_GWY))
75765832Snyan		return ENXIO;
75865832Snyan
75965832Snyan	/* Fill the softc struct with default values.  */
76065832Snyan	fe_softc_defaults(sc);
76165832Snyan
76265832Snyan	/* See if the card is on its address.  */
76365832Snyan	if (!fe_simple_probe(sc, probe_table))
76465832Snyan		return ENXIO;
76565832Snyan
76665832Snyan	/* Get our station address from EEPROM. */
767147304Sbrooks	fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
768147304Sbrooks	if (!fe_valid_Ether_p(sc->enaddr, 0x000000))
76965832Snyan		return ENXIO;
77065832Snyan
77165832Snyan	/* Determine the card type.  */
77265832Snyan	sc->typestr = "Generic MB86960 Ethernet";
773147304Sbrooks	if (fe_valid_Ether_p(sc->enaddr, 0x000061))
77465832Snyan		sc->typestr = "Gateway Ethernet (Fujitsu chipset)";
77565832Snyan
77665832Snyan	/* Gateway's board requires an explicit IRQ to work, since it
77765832Snyan	   is not possible to probe the setting of jumpers.  */
77865832Snyan	if (bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0) {
77965832Snyan		fe_irq_failure(sc->typestr, sc->sc_unit, NO_IRQ, NULL);
78065832Snyan		return ENXIO;
78165832Snyan	}
78265832Snyan
78365832Snyan	return 0;
78465832Snyan}
78565832Snyan
78665832Snyan
78765832Snyan/*
78865832Snyan * Probe for Ungermann-Bass Access/PC N98C+(Model 85152).
78965832Snyan */
79065832Snyanstatic int
79165832Snyanfe_probe_ubn(device_t dev)
79265832Snyan{
79365832Snyan	struct fe_softc *sc = device_get_softc(dev);
79465832Snyan
79565832Snyan	u_char sum, save7;
79665832Snyan	u_long iobase, irq;
79765832Snyan	int i;
79865832Snyan	static struct fe_simple_probe_struct const probe_table [] = {
79965832Snyan		{ FE_DLCR2, 0x58, 0x00 },
80065832Snyan		{ FE_DLCR4, 0x08, 0x00 },
80165832Snyan		{ 0 }
80265832Snyan	};
80365832Snyan
80465832Snyan	/* See if the specified I/O address is possible for Access/PC.  */
80565832Snyan	/* [01][048C]D0 are allowed.  */
80665832Snyan	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
80765832Snyan		return ENXIO;
80865832Snyan	if ((iobase & ~0x1C00) != 0xD0)
80965832Snyan		return ENXIO;
81065832Snyan
81165832Snyan	if (fe98_alloc_port(dev, FE_TYPE_UBN))
81265832Snyan		return ENXIO;
81365832Snyan
81465832Snyan	/* Fill the softc struct with default values.  */
81565832Snyan	fe_softc_defaults(sc);
81665832Snyan
81765832Snyan	/* Simple probe.  */
81865832Snyan	if (!fe_simple_probe(sc, probe_table))
81965832Snyan		return ENXIO;
82065832Snyan
82165832Snyan	/* NOTE: Access/NOTE N98 sometimes freeze when reading station
82265832Snyan	   address.  In case of using it togather with C-NET(9N)C,
82365832Snyan	   this problem usually happens.
82465832Snyan	   Writing DLCR7 prevents freezing, but I don't know why.  FIXME.  */
82565832Snyan
82665832Snyan	/* Save the current value for the DLCR7 register we are about
82765832Snyan	   to destroy.  */
82865832Snyan	save7 = fe_inb(sc, FE_DLCR7);
82965832Snyan	fe_outb(sc, FE_DLCR7,
83065832Snyan		sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP);
83165832Snyan
83265832Snyan	/* Get our station address form ID ROM and make sure it is UBN's.  */
833147304Sbrooks	fe_inblk(sc, 0x18, sc->enaddr, ETHER_ADDR_LEN);
834147304Sbrooks	if (!fe_valid_Ether_p(sc->enaddr, 0x00DD01))
83565832Snyan		goto fail_ubn;
83665832Snyan#if 1
83765832Snyan	/* Calculate checksum.  */
83865832Snyan	sum = fe_inb(sc, 0x1e);
83965832Snyan	for (i = 0; i < ETHER_ADDR_LEN; i++)
840147304Sbrooks		sum ^= sc->enaddr[i];
84165832Snyan	if (sum != 0)
84265832Snyan		goto fail_ubn;
84365832Snyan#endif
84465832Snyan
84565832Snyan	/* Setup the board type.  */
84665832Snyan	sc->typestr = "Access/PC";
84765832Snyan
84865832Snyan	/* This looks like an AccessPC/N98C+ board.  It requires an
84965832Snyan	   explicit IRQ setting in config.  Make sure we have one,
85065832Snyan	   determining an appropriate value for the IRQ control
85165832Snyan	   register.  */
85265832Snyan	irq = 0;
85365832Snyan	bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
85465832Snyan	switch (irq) {
85565832Snyan	case 3:  sc->priv_info = 0x01; break;
85665832Snyan	case 5:  sc->priv_info = 0x02; break;
85765832Snyan	case 6:  sc->priv_info = 0x04; break;
85865832Snyan	case 12: sc->priv_info = 0x08; break;
85965832Snyan	default:
86065832Snyan		fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
86165832Snyan		goto fail_ubn;
86265832Snyan	}
86365832Snyan
86465832Snyan	/* Setup hooks.  We need a special initialization procedure.  */
86565832Snyan	sc->init = fe_init_ubn;
86665832Snyan
86765832Snyan	return 0;
86865832Snyan
86965832Snyanfail_ubn:
87065832Snyan	fe_outb(sc, FE_DLCR7, save7);
87165832Snyan	return ENXIO;
87265832Snyan}
87365832Snyan
87465832Snyan
87565832Snyan/*
87665832Snyan * REX boards(non-JLI type) support routine.
87765832Snyan */
87865832Snyan
87965832Snyan#define REX_EEPROM_SIZE	32
88065832Snyan#define REX_DAT	0x01
88165832Snyan
88265832Snyanstatic void
88365832Snyanfe_read_eeprom_rex(struct fe_softc *sc, u_char *data)
88465832Snyan{
88565832Snyan	int i;
88665832Snyan	u_char bit, val;
88765832Snyan	u_char save16;
88865832Snyan
88965832Snyan	save16 = fe_inb(sc, 0x10);
89065832Snyan
89165832Snyan	/* Issue a start condition.  */
89265832Snyan	val = fe_inb(sc, 0x10) & 0xf0;
89365832Snyan	fe_outb(sc, 0x10, val);
89465832Snyan
89565832Snyan	(void) fe_inb(sc, 0x10);
89665832Snyan	(void) fe_inb(sc, 0x10);
89765832Snyan	(void) fe_inb(sc, 0x10);
89865832Snyan	(void) fe_inb(sc, 0x10);
89965832Snyan
90065832Snyan	/* Read bytes from EEPROM.  */
90165832Snyan	for (i = 0; i < REX_EEPROM_SIZE; i++) {
90265832Snyan		/* Read a byte and store it into the buffer.  */
90365832Snyan		val = 0x00;
90465832Snyan		for (bit = 0x01; bit != 0x00; bit <<= 1)
90565832Snyan			if (fe_inb(sc, 0x10) & REX_DAT)
90665832Snyan				val |= bit;
90765832Snyan		*data++ = val;
90865832Snyan	}
90965832Snyan
91065832Snyan	fe_outb(sc, 0x10, save16);
91165832Snyan
91265832Snyan#if 1
91365832Snyan	/* Report what we got.  */
91465832Snyan	if (bootverbose) {
91565832Snyan		data -= REX_EEPROM_SIZE;
91665832Snyan		for (i = 0; i < REX_EEPROM_SIZE; i += 16) {
91765832Snyan			printf("fe%d: EEPROM(REX):%3x: %16D\n",
91865832Snyan			       sc->sc_unit, i, data + i, " ");
91965832Snyan		}
92065832Snyan	}
92165832Snyan#endif
92265832Snyan}
92365832Snyan
92465832Snyan
92565832Snyanstatic void
92665832Snyanfe_init_rex(struct fe_softc *sc)
92765832Snyan{
92865832Snyan	/* Setup IRQ control register on the ASIC.  */
92965832Snyan	fe_outb(sc, 0x10, sc->priv_info);
93065832Snyan}
93165832Snyan
93265832Snyan/*
93365832Snyan * Probe for RATOC REX-9880/81/82/83 series.
93465832Snyan */
93565832Snyanstatic int
93665832Snyanfe_probe_rex(device_t dev)
93765832Snyan{
93865832Snyan	struct fe_softc *sc = device_get_softc(dev);
93965832Snyan
94065832Snyan	int i;
94165832Snyan	u_long iobase, irq;
94265832Snyan	u_char eeprom [REX_EEPROM_SIZE];
94365832Snyan
94465832Snyan	static struct fe_simple_probe_struct probe_table [] = {
94565832Snyan		{ FE_DLCR2, 0x58, 0x00 },
94665832Snyan		{ FE_DLCR4, 0x08, 0x00 },
94765832Snyan		{ 0 }
94865832Snyan	};
94965832Snyan
95065832Snyan	/* See if the specified I/O address is possible for REX-9880.  */
95165832Snyan	/* 6[46CE]D0 are allowed.  */
95265832Snyan	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
95365832Snyan		return ENXIO;
95465832Snyan	if ((iobase & ~0xA00) != 0x64D0)
95565832Snyan		return ENXIO;
95665832Snyan
95765832Snyan	if (fe98_alloc_port(dev, FE_TYPE_REX))
95865832Snyan		return ENXIO;
95965832Snyan
96065832Snyan	/* Fill the softc struct with default values.  */
96165832Snyan	fe_softc_defaults(sc);
96265832Snyan
96365832Snyan	/* See if the card is on its address.  */
96465832Snyan	if (!fe_simple_probe(sc, probe_table))
96565832Snyan		return ENXIO;
96665832Snyan
96765832Snyan	/* We now have to read the config EEPROM.  We should be very
96865832Snyan           careful, since doing so destroys a register.  (Remember, we
96965832Snyan           are not yet sure we have a REX-9880 board here.)  */
97065832Snyan	fe_read_eeprom_rex(sc, eeprom);
97165832Snyan	for (i = 0; i < ETHER_ADDR_LEN; i++)
972147304Sbrooks		sc->enaddr[i] = eeprom[7 - i];
97365832Snyan
97465832Snyan	/* Make sure it is RATOC's.  */
975147304Sbrooks	if (!fe_valid_Ether_p(sc->enaddr, 0x00C0D0) &&
976147304Sbrooks	    !fe_valid_Ether_p(sc->enaddr, 0x00803D))
97765832Snyan		return 0;
97865832Snyan
97965832Snyan	/* Setup the board type.  */
98065832Snyan	sc->typestr = "REX-9880/9883";
98165832Snyan
98265832Snyan	/* This looks like a REX-9880 board.  It requires an
98365832Snyan	   explicit IRQ setting in config.  Make sure we have one,
98465832Snyan	   determining an appropriate value for the IRQ control
98565832Snyan	   register.  */
98665832Snyan	irq = 0;
98765832Snyan	bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
98865832Snyan	switch (irq) {
98965832Snyan	case 3:  sc->priv_info = 0x10; break;
99065832Snyan	case 5:  sc->priv_info = 0x20; break;
99165832Snyan	case 6:  sc->priv_info = 0x40; break;
99265832Snyan	case 12: sc->priv_info = 0x80; break;
99365832Snyan	default:
99465832Snyan		fe_irq_failure(sc->typestr, sc->sc_unit, irq, "3/5/6/12");
99565832Snyan		return ENXIO;
99665832Snyan	}
99765832Snyan
99865832Snyan	/* Setup hooks.  We need a special initialization procedure.  */
99965832Snyan	sc->init = fe_init_rex;
100065832Snyan
100165832Snyan	/* REX-9880 has 64KB SRAM.  */
100265832Snyan	sc->proto_dlcr6 = FE_D6_BUFSIZ_64KB | FE_D6_TXBSIZ_2x4KB
100365832Snyan			| FE_D6_BBW_WORD | FE_D6_SBW_WORD | FE_D6_SRAM;
100465832Snyan#if 1
100565832Snyan	sc->proto_dlcr7 |= FE_D7_EOPPOL;	/* XXX */
100665832Snyan#endif
100765832Snyan
100865832Snyan	return 0;
100965832Snyan}
1010