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