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