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