if_fe_cbus.c revision 139749
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 139749 2005-01-06 01:43:34Z imp $"); 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 4665832Snyan#include <i386/isa/ic/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. */ 32065832Snyan fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); 32165832Snyan 32265832Snyan /* Make sure it is Allied-Telesis's. */ 32365832Snyan if (!valid_Ether_p(sc->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++) 32965832Snyan sum ^= sc->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. */ 37365832Snyan bcopy(eeprom + 8, sc->sc_enaddr, ETHER_ADDR_LEN); 37465832Snyan if (!valid_Ether_p(sc->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. */ 54465832Snyan fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); 54565832Snyan 54665832Snyan /* Make sure it is Contec's. */ 54765832Snyan if (!valid_Ether_p(sc->sc_enaddr, 0x00804C)) 54865832Snyan return ENXIO; 54965832Snyan 55065832Snyan /* Determine the card type. */ 55165832Snyan if (sc->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. */ 63365832Snyan if (!valid_Ether_p(eeprom + FE_SSI_EEP_ADDR, 0x00804C)) 63465832Snyan return ENXIO; 63565832Snyan bcopy(eeprom + FE_SSI_EEP_ADDR, sc->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. */ 70365832Snyan if (!valid_Ether_p(eeprom, 0x008098)) 70465832Snyan return ENXIO; 70565832Snyan bcopy(eeprom, sc->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. */ 77065832Snyan fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); 77165832Snyan if (!valid_Ether_p(sc->sc_enaddr, 0x000000)) 77265832Snyan return ENXIO; 77365832Snyan 77465832Snyan /* Determine the card type. */ 77565832Snyan sc->typestr = "Generic MB86960 Ethernet"; 77665832Snyan if (valid_Ether_p(sc->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. */ 83665832Snyan fe_inblk(sc, 0x18, sc->sc_enaddr, ETHER_ADDR_LEN); 83765832Snyan if (!valid_Ether_p(sc->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++) 84365832Snyan sum ^= sc->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++) 97565832Snyan sc->sc_enaddr[i] = eeprom[7 - i]; 97665832Snyan 97765832Snyan /* Make sure it is RATOC's. */ 97865832Snyan if (!valid_Ether_p(sc->sc_enaddr, 0x00C0D0) && 97965832Snyan !valid_Ether_p(sc->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