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