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