if_ex_isa.c revision 119418
159816Smdodd/*- 259816Smdodd * Copyright (c) 2000 Matthew N. Dodd 359816Smdodd * All rights reserved. 459816Smdodd * 559816Smdodd * Redistribution and use in source and binary forms, with or without 659816Smdodd * modification, are permitted provided that the following conditions 759816Smdodd * are met: 859816Smdodd * 1. Redistributions of source code must retain the above copyright 959816Smdodd * notice, this list of conditions and the following disclaimer. 1059816Smdodd * 2. Redistributions in binary form must reproduce the above copyright 1159816Smdodd * notice, this list of conditions and the following disclaimer in the 1259816Smdodd * documentation and/or other materials provided with the distribution. 1359816Smdodd * 1459816Smdodd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1559816Smdodd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1659816Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1759816Smdodd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1859816Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1959816Smdodd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2059816Smdodd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2159816Smdodd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2259816Smdodd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2359816Smdodd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2459816Smdodd * SUCH DAMAGE. 2559816Smdodd * 2659816Smdodd */ 2759816Smdodd 28119418Sobrien#include <sys/cdefs.h> 29119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/ex/if_ex_isa.c 119418 2003-08-24 17:55:58Z obrien $"); 30119418Sobrien 3159816Smdodd#include <sys/param.h> 3259816Smdodd#include <sys/systm.h> 3359816Smdodd#include <sys/kernel.h> 3459816Smdodd#include <sys/socket.h> 3559816Smdodd 3659816Smdodd#include <sys/module.h> 3759816Smdodd#include <sys/bus.h> 3859816Smdodd 3959816Smdodd#include <machine/bus.h> 4059816Smdodd#include <machine/resource.h> 4159816Smdodd#include <sys/rman.h> 4259816Smdodd 4359816Smdodd#include <net/if.h> 4459816Smdodd#include <net/if_arp.h> 4559816Smdodd#include <net/if_media.h> 4659816Smdodd 4759816Smdodd 4859816Smdodd#include <isa/isavar.h> 4959816Smdodd#include <isa/pnpvar.h> 5059816Smdodd 5159816Smdodd#include <dev/ex/if_exreg.h> 5259816Smdodd#include <dev/ex/if_exvar.h> 5359816Smdodd 5459816Smdodd/* Bus Front End Functions */ 5592739Salfredstatic void ex_isa_identify (driver_t *, device_t); 5692739Salfredstatic int ex_isa_probe (device_t); 5792739Salfredstatic int ex_isa_attach (device_t); 5859816Smdodd 5959816Smdodd#if 0 6059816Smdoddstatic void ex_pnp_wakeup (void *); 6159816Smdodd 6259816SmdoddSYSINIT(ex_pnpwakeup, SI_SUB_CPU, SI_ORDER_ANY, ex_pnp_wakeup, NULL); 6359816Smdodd#endif 6459816Smdodd 65112801Smdoddstatic device_method_t ex_isa_methods[] = { 6659816Smdodd /* Device interface */ 6759816Smdodd DEVMETHOD(device_identify, ex_isa_identify), 6859816Smdodd DEVMETHOD(device_probe, ex_isa_probe), 6959816Smdodd DEVMETHOD(device_attach, ex_isa_attach), 70112800Smdodd DEVMETHOD(device_detach, ex_detach), 7159816Smdodd 7259816Smdodd { 0, 0 } 7359816Smdodd}; 7459816Smdodd 75112801Smdoddstatic driver_t ex_isa_driver = { 7659816Smdodd "ex", 77112801Smdodd ex_isa_methods, 7859816Smdodd sizeof(struct ex_softc), 7959816Smdodd}; 8059816Smdodd 81112801SmdoddDRIVER_MODULE(ex, isa, ex_isa_driver, ex_devclass, 0, 0); 8259816Smdodd 8359816Smdoddstatic struct isa_pnp_id ex_ids[] = { 8459816Smdodd { 0x3110d425, NULL }, /* INT1031 */ 8559816Smdodd { 0x3010d425, NULL }, /* INT1030 */ 8659816Smdodd { 0, NULL }, 8759816Smdodd}; 8859816Smdodd 8959816Smdodd#if 0 9059816Smdodd#define EX_PNP_WAKE 0x279 9159816Smdodd 9259816Smdoddstatic u_int8_t ex_pnp_wake_seq[] = 9359816Smdodd { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, 9459816Smdodd 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, 9559816Smdodd 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, 9659816Smdodd 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43 }; 9759816Smdodd 9859816Smdoddstatic void 9959816Smdoddex_pnp_wakeup (void * dummy) 10059816Smdodd{ 10159816Smdodd int tmp; 10259816Smdodd 10359816Smdodd if (bootverbose) 10459816Smdodd printf("ex_pnp_wakeup()\n"); 10559816Smdodd 10659816Smdodd outb(EX_PNP_WAKE, 0); 10759816Smdodd outb(EX_PNP_WAKE, 0); 10859816Smdodd for (tmp = 0; tmp < 32; tmp++) { 10959816Smdodd outb(EX_PNP_WAKE, ex_pnp_wake_seq[tmp]); 11059816Smdodd } 11159816Smdodd} 11259816Smdodd#endif 11359816Smdodd 11459816Smdodd/* 11559816Smdodd * Non-destructive identify. 11659816Smdodd */ 11759816Smdoddstatic void 11859816Smdoddex_isa_identify (driver_t *driver, device_t parent) 11959816Smdodd{ 12059816Smdodd device_t child; 12159816Smdodd u_int32_t ioport; 12259816Smdodd u_char enaddr[6]; 12359816Smdodd u_int irq; 12459816Smdodd int tmp; 12559816Smdodd const char * desc; 12659816Smdodd 12759816Smdodd if (bootverbose) 12859816Smdodd printf("ex_isa_identify()\n"); 12959816Smdodd 13059816Smdodd for (ioport = 0x200; ioport < 0x3a0; ioport += 0x10) { 13159816Smdodd 13259816Smdodd /* No board found at address */ 13359816Smdodd if (!look_for_card(ioport)) { 13459816Smdodd continue; 13559816Smdodd } 13659816Smdodd 13759816Smdodd if (bootverbose) 13859816Smdodd printf("ex: Found card at 0x%03x!\n", ioport); 13959816Smdodd 14059816Smdodd /* Board in PnP mode */ 14159816Smdodd if (eeprom_read(ioport, EE_W0) & EE_W0_PNP) { 14259816Smdodd /* Reset the card. */ 14359816Smdodd outb(ioport + CMD_REG, Reset_CMD); 14459816Smdodd DELAY(500); 14559816Smdodd if (bootverbose) 14659816Smdodd printf("ex: card at 0x%03x in PnP mode!\n", ioport); 14759816Smdodd continue; 14859816Smdodd } 14959816Smdodd 15059816Smdodd bzero(enaddr, sizeof(enaddr)); 15159816Smdodd 15259816Smdodd /* Reset the card. */ 15359816Smdodd outb(ioport + CMD_REG, Reset_CMD); 15459816Smdodd DELAY(400); 15559816Smdodd 15659816Smdodd ex_get_address(ioport, enaddr); 15759816Smdodd tmp = eeprom_read(ioport, EE_W1) & EE_W1_INT_SEL; 15859816Smdodd 15959816Smdodd /* work out which set of irq <-> internal tables to use */ 16059816Smdodd if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) { 16159816Smdodd irq = plus_ee2irqmap[tmp]; 16259816Smdodd desc = "Intel Pro/10+"; 16359816Smdodd } else { 16459816Smdodd irq = ee2irqmap[tmp]; 16559816Smdodd desc = "Intel Pro/10"; 16659816Smdodd } 16759816Smdodd 16859816Smdodd child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ex", -1); 16959816Smdodd device_set_desc_copy(child, desc); 17059816Smdodd device_set_driver(child, driver); 17159816Smdodd bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 17259816Smdodd bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, EX_IOSIZE); 17359816Smdodd 17459816Smdodd if (bootverbose) 17559816Smdodd printf("ex: Adding board at 0x%03x, irq %d\n", ioport, irq); 17659816Smdodd } 17759816Smdodd 17859816Smdodd return; 17959816Smdodd} 18059816Smdodd 18159816Smdoddstatic int 18259816Smdoddex_isa_probe(device_t dev) 18359816Smdodd{ 18459816Smdodd u_int iobase; 18559816Smdodd u_int irq; 18659816Smdodd char * irq2ee; 18759816Smdodd u_char * ee2irq; 18859816Smdodd u_char enaddr[6]; 18959816Smdodd int tmp; 19059816Smdodd int error; 19159816Smdodd 19259816Smdodd /* Check isapnp ids */ 19359816Smdodd error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids); 19459816Smdodd 19559816Smdodd /* If the card had a PnP ID that didn't match any we know about */ 19659816Smdodd if (error == ENXIO) { 19759816Smdodd return(error); 19859816Smdodd } 19959816Smdodd 20059816Smdodd /* If we had some other problem. */ 20159816Smdodd if (!(error == 0 || error == ENOENT)) { 20259816Smdodd return(error); 20359816Smdodd } 20459816Smdodd 20559816Smdodd iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0); 20659816Smdodd if (!iobase) { 20759816Smdodd printf("ex: no iobase?\n"); 20859816Smdodd return(ENXIO); 20959816Smdodd } 21059816Smdodd 21159816Smdodd if (!look_for_card(iobase)) { 21259816Smdodd printf("ex: no card found at 0x%03x\n", iobase); 21359816Smdodd return(ENXIO); 21459816Smdodd } 21559816Smdodd 21659816Smdodd if (bootverbose) 21759816Smdodd printf("ex: ex_isa_probe() found card at 0x%03x\n", iobase); 21859816Smdodd 21959816Smdodd /* 22059816Smdodd * Reset the card. 22159816Smdodd */ 22259816Smdodd outb(iobase + CMD_REG, Reset_CMD); 22359816Smdodd DELAY(800); 22459816Smdodd 22559816Smdodd ex_get_address(iobase, enaddr); 22659816Smdodd 22759816Smdodd /* work out which set of irq <-> internal tables to use */ 22859816Smdodd if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) { 22959816Smdodd irq2ee = plus_irq2eemap; 23059816Smdodd ee2irq = plus_ee2irqmap; 23159816Smdodd } else { 23259816Smdodd irq2ee = irq2eemap; 23359816Smdodd ee2irq = ee2irqmap; 23459816Smdodd } 23559816Smdodd 23659816Smdodd tmp = eeprom_read(iobase, EE_W1) & EE_W1_INT_SEL; 23759816Smdodd irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); 23859816Smdodd 23959816Smdodd if (irq > 0) { 24059816Smdodd /* This will happen if board is in PnP mode. */ 24159816Smdodd if (ee2irq[tmp] != irq) { 24259816Smdodd printf("ex: WARNING: board's EEPROM is configured" 24359816Smdodd " for IRQ %d, using %d\n", 24459816Smdodd ee2irq[tmp], irq); 24559816Smdodd } 24659816Smdodd } else { 24759816Smdodd irq = ee2irq[tmp]; 24859816Smdodd bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); 24959816Smdodd } 25059816Smdodd 25159816Smdodd if (irq == 0) { 25259816Smdodd printf("ex: invalid IRQ.\n"); 25359816Smdodd return(ENXIO); 25459816Smdodd } 25559816Smdodd 25659816Smdodd return(0); 25759816Smdodd} 25859816Smdodd 25959816Smdoddstatic int 26059816Smdoddex_isa_attach(device_t dev) 26159816Smdodd{ 26259816Smdodd struct ex_softc * sc = device_get_softc(dev); 26359816Smdodd int error = 0; 26459816Smdodd u_int16_t temp; 26559816Smdodd 26659816Smdodd sc->dev = dev; 26759816Smdodd sc->ioport_rid = 0; 26859816Smdodd sc->irq_rid = 0; 26959816Smdodd 27059816Smdodd if ((error = ex_alloc_resources(dev)) != 0) { 27159816Smdodd device_printf(dev, "ex_alloc_resources() failed!\n"); 27259816Smdodd goto bad; 27359816Smdodd } 27459816Smdodd 27559816Smdodd /* 27659816Smdodd * Fill in several fields of the softc structure: 27759816Smdodd * - I/O base address. 27859816Smdodd * - Hardware Ethernet address. 27959816Smdodd * - IRQ number (if not supplied in config file, read it from EEPROM). 28059816Smdodd * - Connector type. 28159816Smdodd */ 28259816Smdodd sc->iobase = rman_get_start(sc->ioport); 28359816Smdodd sc->irq_no = rman_get_start(sc->irq); 28459816Smdodd 28559816Smdodd ex_get_address(sc->iobase, sc->arpcom.ac_enaddr); 28659816Smdodd 28759816Smdodd temp = eeprom_read(sc->iobase, EE_W0); 28859816Smdodd device_printf(sc->dev, "%s config, %s bus, ", 28959816Smdodd (temp & EE_W0_PNP) ? "PnP" : "Manual", 29059816Smdodd (temp & EE_W0_BUS16) ? "16-bit" : "8-bit"); 29159816Smdodd 29259816Smdodd temp = eeprom_read(sc->iobase, EE_W6); 29359816Smdodd printf("board id 0x%03x, stepping 0x%01x\n", 29459816Smdodd (temp & EE_W6_BOARD_MASK) >> EE_W6_BOARD_SHIFT, 29559816Smdodd temp & EE_W6_STEP_MASK); 29659816Smdodd 29759816Smdodd if ((error = ex_attach(dev)) != 0) { 29859816Smdodd device_printf(dev, "ex_attach() failed!\n"); 29959816Smdodd goto bad; 30059816Smdodd } 30159816Smdodd 30259816Smdodd error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, 30359816Smdodd ex_intr, (void *)sc, &sc->ih); 30459816Smdodd if (error) { 30559816Smdodd device_printf(dev, "bus_setup_intr() failed!\n"); 30659816Smdodd goto bad; 30759816Smdodd } 30859816Smdodd 30959816Smdodd return(0); 31059816Smdoddbad: 31159816Smdodd ex_release_resources(dev); 31259816Smdodd return (error); 31359816Smdodd} 314