if_ex_isa.c revision 119418
1/*- 2 * Copyright (c) 2000 Matthew N. Dodd 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: head/sys/dev/ex/if_ex_isa.c 119418 2003-08-24 17:55:58Z obrien $"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/kernel.h> 34#include <sys/socket.h> 35 36#include <sys/module.h> 37#include <sys/bus.h> 38 39#include <machine/bus.h> 40#include <machine/resource.h> 41#include <sys/rman.h> 42 43#include <net/if.h> 44#include <net/if_arp.h> 45#include <net/if_media.h> 46 47 48#include <isa/isavar.h> 49#include <isa/pnpvar.h> 50 51#include <dev/ex/if_exreg.h> 52#include <dev/ex/if_exvar.h> 53 54/* Bus Front End Functions */ 55static void ex_isa_identify (driver_t *, device_t); 56static int ex_isa_probe (device_t); 57static int ex_isa_attach (device_t); 58 59#if 0 60static void ex_pnp_wakeup (void *); 61 62SYSINIT(ex_pnpwakeup, SI_SUB_CPU, SI_ORDER_ANY, ex_pnp_wakeup, NULL); 63#endif 64 65static device_method_t ex_isa_methods[] = { 66 /* Device interface */ 67 DEVMETHOD(device_identify, ex_isa_identify), 68 DEVMETHOD(device_probe, ex_isa_probe), 69 DEVMETHOD(device_attach, ex_isa_attach), 70 DEVMETHOD(device_detach, ex_detach), 71 72 { 0, 0 } 73}; 74 75static driver_t ex_isa_driver = { 76 "ex", 77 ex_isa_methods, 78 sizeof(struct ex_softc), 79}; 80 81DRIVER_MODULE(ex, isa, ex_isa_driver, ex_devclass, 0, 0); 82 83static struct isa_pnp_id ex_ids[] = { 84 { 0x3110d425, NULL }, /* INT1031 */ 85 { 0x3010d425, NULL }, /* INT1030 */ 86 { 0, NULL }, 87}; 88 89#if 0 90#define EX_PNP_WAKE 0x279 91 92static u_int8_t ex_pnp_wake_seq[] = 93 { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, 94 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, 95 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, 96 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43 }; 97 98static void 99ex_pnp_wakeup (void * dummy) 100{ 101 int tmp; 102 103 if (bootverbose) 104 printf("ex_pnp_wakeup()\n"); 105 106 outb(EX_PNP_WAKE, 0); 107 outb(EX_PNP_WAKE, 0); 108 for (tmp = 0; tmp < 32; tmp++) { 109 outb(EX_PNP_WAKE, ex_pnp_wake_seq[tmp]); 110 } 111} 112#endif 113 114/* 115 * Non-destructive identify. 116 */ 117static void 118ex_isa_identify (driver_t *driver, device_t parent) 119{ 120 device_t child; 121 u_int32_t ioport; 122 u_char enaddr[6]; 123 u_int irq; 124 int tmp; 125 const char * desc; 126 127 if (bootverbose) 128 printf("ex_isa_identify()\n"); 129 130 for (ioport = 0x200; ioport < 0x3a0; ioport += 0x10) { 131 132 /* No board found at address */ 133 if (!look_for_card(ioport)) { 134 continue; 135 } 136 137 if (bootverbose) 138 printf("ex: Found card at 0x%03x!\n", ioport); 139 140 /* Board in PnP mode */ 141 if (eeprom_read(ioport, EE_W0) & EE_W0_PNP) { 142 /* Reset the card. */ 143 outb(ioport + CMD_REG, Reset_CMD); 144 DELAY(500); 145 if (bootverbose) 146 printf("ex: card at 0x%03x in PnP mode!\n", ioport); 147 continue; 148 } 149 150 bzero(enaddr, sizeof(enaddr)); 151 152 /* Reset the card. */ 153 outb(ioport + CMD_REG, Reset_CMD); 154 DELAY(400); 155 156 ex_get_address(ioport, enaddr); 157 tmp = eeprom_read(ioport, EE_W1) & EE_W1_INT_SEL; 158 159 /* work out which set of irq <-> internal tables to use */ 160 if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) { 161 irq = plus_ee2irqmap[tmp]; 162 desc = "Intel Pro/10+"; 163 } else { 164 irq = ee2irqmap[tmp]; 165 desc = "Intel Pro/10"; 166 } 167 168 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ex", -1); 169 device_set_desc_copy(child, desc); 170 device_set_driver(child, driver); 171 bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 172 bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, EX_IOSIZE); 173 174 if (bootverbose) 175 printf("ex: Adding board at 0x%03x, irq %d\n", ioport, irq); 176 } 177 178 return; 179} 180 181static int 182ex_isa_probe(device_t dev) 183{ 184 u_int iobase; 185 u_int irq; 186 char * irq2ee; 187 u_char * ee2irq; 188 u_char enaddr[6]; 189 int tmp; 190 int error; 191 192 /* Check isapnp ids */ 193 error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids); 194 195 /* If the card had a PnP ID that didn't match any we know about */ 196 if (error == ENXIO) { 197 return(error); 198 } 199 200 /* If we had some other problem. */ 201 if (!(error == 0 || error == ENOENT)) { 202 return(error); 203 } 204 205 iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0); 206 if (!iobase) { 207 printf("ex: no iobase?\n"); 208 return(ENXIO); 209 } 210 211 if (!look_for_card(iobase)) { 212 printf("ex: no card found at 0x%03x\n", iobase); 213 return(ENXIO); 214 } 215 216 if (bootverbose) 217 printf("ex: ex_isa_probe() found card at 0x%03x\n", iobase); 218 219 /* 220 * Reset the card. 221 */ 222 outb(iobase + CMD_REG, Reset_CMD); 223 DELAY(800); 224 225 ex_get_address(iobase, enaddr); 226 227 /* work out which set of irq <-> internal tables to use */ 228 if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) { 229 irq2ee = plus_irq2eemap; 230 ee2irq = plus_ee2irqmap; 231 } else { 232 irq2ee = irq2eemap; 233 ee2irq = ee2irqmap; 234 } 235 236 tmp = eeprom_read(iobase, EE_W1) & EE_W1_INT_SEL; 237 irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); 238 239 if (irq > 0) { 240 /* This will happen if board is in PnP mode. */ 241 if (ee2irq[tmp] != irq) { 242 printf("ex: WARNING: board's EEPROM is configured" 243 " for IRQ %d, using %d\n", 244 ee2irq[tmp], irq); 245 } 246 } else { 247 irq = ee2irq[tmp]; 248 bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); 249 } 250 251 if (irq == 0) { 252 printf("ex: invalid IRQ.\n"); 253 return(ENXIO); 254 } 255 256 return(0); 257} 258 259static int 260ex_isa_attach(device_t dev) 261{ 262 struct ex_softc * sc = device_get_softc(dev); 263 int error = 0; 264 u_int16_t temp; 265 266 sc->dev = dev; 267 sc->ioport_rid = 0; 268 sc->irq_rid = 0; 269 270 if ((error = ex_alloc_resources(dev)) != 0) { 271 device_printf(dev, "ex_alloc_resources() failed!\n"); 272 goto bad; 273 } 274 275 /* 276 * Fill in several fields of the softc structure: 277 * - I/O base address. 278 * - Hardware Ethernet address. 279 * - IRQ number (if not supplied in config file, read it from EEPROM). 280 * - Connector type. 281 */ 282 sc->iobase = rman_get_start(sc->ioport); 283 sc->irq_no = rman_get_start(sc->irq); 284 285 ex_get_address(sc->iobase, sc->arpcom.ac_enaddr); 286 287 temp = eeprom_read(sc->iobase, EE_W0); 288 device_printf(sc->dev, "%s config, %s bus, ", 289 (temp & EE_W0_PNP) ? "PnP" : "Manual", 290 (temp & EE_W0_BUS16) ? "16-bit" : "8-bit"); 291 292 temp = eeprom_read(sc->iobase, EE_W6); 293 printf("board id 0x%03x, stepping 0x%01x\n", 294 (temp & EE_W6_BOARD_MASK) >> EE_W6_BOARD_SHIFT, 295 temp & EE_W6_STEP_MASK); 296 297 if ((error = ex_attach(dev)) != 0) { 298 device_printf(dev, "ex_attach() failed!\n"); 299 goto bad; 300 } 301 302 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, 303 ex_intr, (void *)sc, &sc->ih); 304 if (error) { 305 device_printf(dev, "bus_setup_intr() failed!\n"); 306 goto bad; 307 } 308 309 return(0); 310bad: 311 ex_release_resources(dev); 312 return (error); 313} 314