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