if_ie_isa.c revision 153110
1/*- 2 * Copyright (c) 2003 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 * Portions: 27 * Copyright (c) 1992, 1993, University of Vermont and State 28 * Agricultural College. 29 * Copyright (c) 1992, 1993, Garrett A. Wollman. 30 * Copyright (c) 1990, 1991, William F. Jolitz 31 * Copyright (c) 1990, The Regents of the University of California 32 * Copyright (c) 1993, 1994, Charles M. Hannum 33 * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes 34 * Copyright (c) 1997, Aaron C. Smith 35 * 36 * See if_ie.c for applicable license. 37 */ 38 39#include <sys/cdefs.h> 40__FBSDID("$FreeBSD: head/sys/dev/ie/if_ie_isa.c 153110 2005-12-05 11:58:35Z ru $"); 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/socket.h> 46 47#include <sys/module.h> 48#include <sys/bus.h> 49 50#include <machine/bus.h> 51#include <machine/resource.h> 52#include <sys/rman.h> 53 54#include <machine/clock.h> 55#include <machine/md_var.h> 56 57#include <net/if.h> 58#include <net/if_arp.h> 59#include <net/if_media.h> 60 61#include <isa/isavar.h> 62#include <isa/pnpvar.h> 63 64#include <i386/isa/elink.h> 65 66#include <dev/ic/i82586.h> 67#include <dev/ie/if_ie507.h> 68#include <dev/ie/if_iee16.h> 69#include <dev/ie/if_iereg.h> 70#include <dev/ie/if_ievar.h> 71 72static int ie_modevent (module_t, int, void *); 73 74static void ie_isa_3C507_identify (driver_t *, device_t); 75static int ie_isa_3C507_probe (device_t); 76static int ie_isa_3C507_attach (device_t); 77static int ie_3C507_port_check (u_int32_t); 78 79static void ie_isa_ee16_identify (driver_t *, device_t); 80static int ie_isa_ee16_probe (device_t); 81static int ie_isa_ee16_attach (device_t); 82static int ie_ee16_port_check (u_int32_t port); 83static u_int16_t ie_ee16_hw_read_eeprom (u_int32_t port, int loc); 84 85static int ie_isa_sl_probe (device_t); 86static int ie_isa_sl_attach (device_t); 87static enum ie_hardware ie_isa_sl_get_hard_type (u_int32_t); 88 89/* 90 * 3Com 3C507 Etherlink 16 91 */ 92#define IE_3C507_IOBASE_LOW 0x200 93#define IE_3C507_IOBASE_HIGH 0x3e0 94#define IE_3C507_IOSIZE 16 95 96#define IE_3C507_IRQ_MASK 0x0f 97 98#define IE_3C507_MADDR_HIGH 0x20 99#define IE_3C507_MADDR_MASK 0x1c 100#define IE_3C507_MADDR_BASE 0xc0000 101#define IE_3C507_MADDR_SHIFT 12 102 103#define IE_3C507_MSIZE_MASK 3 104#define IE_3C507_MSIZE_SHIFT 14 105 106static void 107ie_isa_3C507_identify (driver_t *driver, device_t parent) 108{ 109 char * desc = "3Com 3C507 Etherlink 16"; 110 device_t child; 111 u_int32_t port, maddr, msize; 112 u_int8_t irq, data; 113 int error; 114 115 /* Reset and put card in CONFIG state without changing address. */ 116 elink_reset(); 117 elink_idseq(ELINK_507_POLY); 118 elink_idseq(ELINK_507_POLY); 119 outb(ELINK_ID_PORT, 0xff); 120 121 for (port = IE_3C507_IOBASE_LOW; 122 port <= IE_3C507_IOBASE_HIGH; 123 port += IE_3C507_IOSIZE) { 124 125 if (ie_3C507_port_check(port)) { 126#ifdef DEBUG 127 if (bootverbose) { 128 device_printf(parent, 129 "(if_ie) (3C507) not found at port %#x\n", 130 port); 131 } 132#endif 133 continue; 134 } 135 136 outb(port + IE507_CTRL, EL_CTRL_NRST); 137 138 data = inb(port + IE507_IRQ); 139 irq = data & IE_3C507_IRQ_MASK; 140 141 data = inb(port + IE507_MADDR); 142 143 if (data & IE_3C507_MADDR_HIGH) { 144 if (bootverbose) { 145 device_printf(parent, 146 "(if_ie) can't map 3C507 RAM in high memory\n"); 147 } 148 continue; 149 } 150 151 maddr = IE_3C507_MADDR_BASE + 152 ((data & IE_3C507_MADDR_MASK) 153 << IE_3C507_MADDR_SHIFT); 154 msize = ((data & IE_3C507_MSIZE_MASK) + 1) 155 << IE_3C507_MSIZE_SHIFT; 156 157 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1); 158 device_set_desc_copy(child, desc); 159 device_set_driver(child, driver); 160 161 error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 162 if (error) { 163 device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n", 164 irq); 165 error = device_delete_child(parent, child); 166 continue; 167 } 168 169 error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_3C507_IOSIZE); 170 if (error) { 171 device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n", 172 port, port+IE_3C507_IOSIZE); 173 error = device_delete_child(parent, child); 174 continue; 175 } 176 177 error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize); 178 if (error) { 179 device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n", 180 maddr, maddr+msize); 181 error = device_delete_child(parent, child); 182 continue; 183 } 184 185 if (bootverbose) { 186 device_printf(parent, 187 "(if_ie) <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n", 188 desc, 189 port, (port + IE_3C507_IOSIZE) - 1, 190 irq, 191 (u_long)maddr, (u_long)(maddr + msize) - 1, 192 (msize / 1024)); 193 } 194 } 195 196 /* go to RUN state */ 197 outb(ELINK_ID_PORT, 0x00); 198 elink_idseq(ELINK_507_POLY); 199 outb(ELINK_ID_PORT, 0x00); 200 201 return; 202} 203 204static int 205ie_isa_3C507_probe (device_t dev) 206{ 207 u_int32_t iobase; 208 209 /* No ISA-PnP support */ 210 if (isa_get_vendorid(dev)) { 211 return (ENXIO); 212 } 213 214 /* No ISA-HINT support */ 215 if (!device_get_desc(dev)) { 216 return (EBUSY); 217 } 218 219 /* Have we at least an ioport? */ 220 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) { 221 return (ENXIO); 222 } 223 224 /* Is this thing really a 3c507? */ 225 if (ie_3C507_port_check(iobase)) { 226 return (ENXIO); 227 } 228 229 return (0); 230} 231 232static int 233ie_isa_3C507_attach (device_t dev) 234{ 235 struct ie_softc * sc; 236 int error; 237 238 sc = device_get_softc(dev); 239 240 sc->io_rid = 0; 241 sc->irq_rid = 0; 242 sc->mem_rid = 0; 243 244 error = ie_alloc_resources(dev); 245 if (error) { 246 goto bad; 247 } 248 249 sc->bus_use = 0; 250 sc->ie_reset_586 = el_reset_586; 251 sc->ie_chan_attn = el_chan_attn; 252 sc->hard_type = IE_3C507; 253 sc->hard_vers = 0; 254 255 outb(PORT(sc) + IE507_CTRL, EL_CTRL_NORMAL); 256 257 if (!check_ie_present(sc)) { 258 error = ENXIO; 259 goto bad; 260 } 261 262 sl_read_ether(sc, sc->enaddr); 263 264 /* Clear the interrupt latch just in case. */ 265 outb(PORT(sc) + IE507_ICTRL, 1); 266 267 error = ie_attach(dev); 268 if (error) { 269 device_printf(dev, "ie_attach() failed.\n"); 270 goto bad; 271 } 272 273 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 274 ie_intr, sc, &sc->irq_ih); 275 if (error) { 276 device_printf(dev, "Unable to register interrupt handler\n"); 277 goto bad; 278 } 279 280 return (0); 281bad: 282 ie_release_resources(dev); 283 284 return (error); 285} 286 287/* 288 * If a 3c507 is present, return 0 289 * else, return 1. 290 */ 291static int 292ie_3C507_port_check (u_int32_t port) 293{ 294 u_char * signature = "*3COM*"; 295 int i; 296 297 for (i = 0; i < 6; i++) 298 if (inb(port + i) != signature[i]) 299 return (ENXIO); 300 301 return (0); 302} 303 304/* 305 * Intel EtherExpress 16 306 */ 307#define IE_EE16_ID_PORT 0x0f 308#define IE_EE16_ID 0xbaba 309#define IE_EE16_EEPROM_CONFIG1 0x00 310#define IE_EE16_EEPROM_IRQ_MASK 0xe000 311#define IE_EE16_EEPROM_IRQ_SHIFT 13 312#define IE_EE16_EEPROM_MEMCFG 0x06 313#define IE_EE16_IOSIZE 16 314 315/* 316 * TODO: 317 * Test for 8/16 bit mode. 318 * Test for invalid mem sizes. 319 */ 320static void 321ie_isa_ee16_identify (driver_t *driver, device_t parent) 322{ 323 char * desc = "Intel EtherExpress 16"; 324 device_t child; 325 u_int16_t ports[] = { 326 0x300, 0x310, 0x320, 0x330, 327 0x340, 0x350, 0x360, 0x370, 328 0x200, 0x210, 0x220, 0x230, 329 0x240, 0x250, 0x260, 0x270, 330 0 331 }; 332 u_int16_t irqs[] = { 0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0 }; 333 u_int32_t port, maddr, msize; 334 u_int8_t irq; 335 u_int16_t data; 336 int i, error; 337 338 for (i = 0; ports[i]; i++) { 339 port = ports[i]; 340 341 if (ie_ee16_port_check(port)) { 342#ifdef DEBUG 343 if (bootverbose) { 344 device_printf(parent, 345 "if_ie: (EE16) not found at port %#x\n", 346 port); 347 } 348#endif 349 continue; 350 } 351 352 /* reset any ee16 at the current iobase */ 353 outb(port + IEE16_ECTRL, IEE16_RESET_ASIC); 354 outb(port + IEE16_ECTRL, 0); 355 DELAY(240); 356 357 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_CONFIG1); 358 irq = irqs[((data & IE_EE16_EEPROM_IRQ_MASK) 359 >> IE_EE16_EEPROM_IRQ_SHIFT)]; 360 361 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_MEMCFG); 362 maddr = 0xc0000 + ((ffs(data & 0x00ff) - 1) * 0x4000); 363 msize = (fls((data & 0x00ff) >> (ffs(data & 0x00ff) - 1))) 364 * 0x4000; 365 366 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1); 367 device_set_desc_copy(child, desc); 368 device_set_driver(child, driver); 369 370 error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 371 if (error) { 372 device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n", 373 irq); 374 error = device_delete_child(parent, child); 375 continue; 376 } 377 378 error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_EE16_IOSIZE); 379 if (error) { 380 device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n", 381 port, port+IE_EE16_IOSIZE); 382 error = device_delete_child(parent, child); 383 continue; 384 } 385 386 error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize); 387 if (error) { 388 device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n", 389 maddr, maddr+msize); 390 error = device_delete_child(parent, child); 391 continue; 392 } 393 394 if (bootverbose) { 395 device_printf(parent, 396 "if_ie: <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n", 397 desc, 398 port, (port + IE_EE16_IOSIZE) - 1, 399 irq, 400 (u_long)maddr, (u_long)(maddr + msize) - 1, 401 (msize / 1024)); 402 } 403 } 404 405 return; 406} 407 408static int 409ie_isa_ee16_probe (device_t dev) 410{ 411 u_int32_t iobase; 412 413 /* No ISA-PnP support */ 414 if (isa_get_vendorid(dev)) 415 return (ENXIO); 416 417 /* No ISA-HINT support */ 418 if (!device_get_desc(dev)) 419 return (EBUSY); 420 421 /* Have we at least an ioport? */ 422 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) 423 return (ENXIO); 424 425 /* Is this really an EE16? */ 426 if (ie_ee16_port_check(iobase)) 427 return (ENXIO); 428 429 return (0); 430} 431 432static int 433ie_isa_ee16_attach (device_t dev) 434{ 435 struct ie_softc * sc; 436 int i, error; 437 u_int16_t checksum; 438 u_short eaddrtemp, pg, adjust, decode, edecode; 439 u_char bart_config; 440 441 sc = device_get_softc(dev); 442 443 sc->io_rid = 0; 444 sc->irq_rid = 0; 445 sc->mem_rid = 0; 446 447 error = ie_alloc_resources(dev); 448 if (error) { 449 goto bad; 450 } 451 452 sc->bus_use = 0; 453 sc->ie_reset_586 = ee16_reset_586; 454 sc->ie_chan_attn = ee16_chan_attn; 455 sc->hard_type = IE_EE16; 456 sc->hard_vers = 0; 457 sc->iomem = 0; 458 459 /* reset any ee16 at the current iobase */ 460 outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_ASIC); 461 outb(PORT(sc) + IEE16_ECTRL, 0); 462 DELAY(240); 463 464 /* Is this really an EE16? */ 465 if (ie_ee16_port_check(PORT(sc))) { 466 device_printf(dev, "ie_ee16_port_check() failed\n"); 467 error = ENXIO; 468 goto bad; 469 } 470 471 /* need to put the 586 in RESET while we access the eeprom. */ 472 outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_586); 473 474 /* read the eeprom and checksum it, should == IE_E16_ID */ 475 checksum = 0; 476 for (i = 0; i < 0x40; i++) 477 checksum += ie_ee16_hw_read_eeprom(PORT(sc), i); 478 479 if (checksum != IE_EE16_ID) { 480 device_printf(dev, "invalid eeprom checksum: %x\n", checksum); 481 error = ENXIO; 482 goto bad; 483 } 484 485 if ((kvtop(sc->iomembot) < 0xC0000) || 486 (kvtop(sc->iomembot) + sc->iosize > 0xF0000)) { 487 device_printf(sc->dev, "mapped memory location %p out of range\n", 488 (void *)sc->iomembot); 489 error = ENXIO; 490 goto bad; 491 } 492 493 pg = ((kvtop(sc->iomembot)) & 0x3C000) >> 14; 494 adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2; 495 decode = ((1 << (sc->iosize / 16384)) - 1) << pg; 496 edecode = ((~decode >> 4) & 0xF0) | (decode >> 8); 497 498 /* ZZZ This should be checked against eeprom location 6, low byte */ 499 outb(PORT(sc) + IEE16_MEMDEC, decode & 0xFF); 500 /* ZZZ This should be checked against eeprom location 1, low byte */ 501 outb(PORT(sc) + IEE16_MCTRL, adjust); 502 /* ZZZ Now if I could find this one I would have it made */ 503 outb(PORT(sc) + IEE16_MPCTRL, (~decode & 0xFF)); 504 /* ZZZ I think this is location 6, high byte */ 505 outb(PORT(sc) + IEE16_MECTRL, edecode); /* XXX disable Exxx */ 506 507#if 0 508 (void) kvtop(sc->iomembot); 509#endif 510 511 /* 512 * first prime the stupid bart DRAM controller so that it works, 513 * then zero out all of memory. 514 */ 515 bzero(sc->iomembot, 32); 516 bzero(sc->iomembot, sc->iosize); 517 518 /* Get the encoded interrupt number from the EEPROM */ 519 sc->irq_encoded = ie_ee16_hw_read_eeprom(PORT(sc), 520 IE_EE16_EEPROM_CONFIG1); 521 sc->irq_encoded = (sc->irq_encoded & IE_EE16_EEPROM_IRQ_MASK) >> 522 IE_EE16_EEPROM_IRQ_SHIFT; 523 524 /* 525 * Get the hardware ethernet address from the EEPROM and save it in 526 * the softc for use by the 586 setup code. 527 */ 528 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_HIGH); 529 sc->enaddr[1] = eaddrtemp & 0xFF; 530 sc->enaddr[0] = eaddrtemp >> 8; 531 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_MID); 532 sc->enaddr[3] = eaddrtemp & 0xFF; 533 sc->enaddr[2] = eaddrtemp >> 8; 534 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_LOW); 535 sc->enaddr[5] = eaddrtemp & 0xFF; 536 sc->enaddr[4] = eaddrtemp >> 8; 537 538 /* disable the board interrupts */ 539 outb(PORT(sc) + IEE16_IRQ, sc->irq_encoded); 540 541 /* enable loopback to keep bad packets off the wire */ 542 bart_config = inb(PORT(sc) + IEE16_CONFIG); 543 bart_config |= IEE16_BART_LOOPBACK; 544 bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */ 545 outb(PORT(sc) + IEE16_CONFIG, bart_config); 546 bart_config = inb(PORT(sc) + IEE16_CONFIG); 547 548 /* take the board out of reset state */ 549 outb(PORT(sc) + IEE16_ECTRL, 0); 550 DELAY(100); 551 552 if (!check_ie_present(sc)) { 553 device_printf(dev, "check_ie_present() returned false.\n"); 554 error = ENXIO; 555 goto bad; 556 } 557 558 error = ie_attach(dev); 559 if (error) { 560 device_printf(dev, "ie_attach() failed.\n"); 561 goto bad; 562 } 563 564 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 565 ie_intr, sc, &sc->irq_ih); 566 if (error) { 567 device_printf(dev, "Unable to register interrupt handler\n"); 568 goto bad; 569 } 570 571 return (0); 572bad: 573 ie_release_resources(dev); 574 575 return (error); 576} 577 578/* 579 * If an EE16 is present, return 0 580 * else, return 1. 581 */ 582static int 583ie_ee16_port_check (u_int32_t port) 584{ 585 int i; 586 u_int16_t board_id; 587 u_int8_t data; 588 589 board_id = 0; 590 for (i = 0; i < 4; i++) { 591 data = inb(port + IE_EE16_ID_PORT); 592 board_id |= ((data >> 4) << ((data & 0x03) << 2)); 593 } 594 595 if (board_id != IE_EE16_ID) 596 return (1); 597 598 return (0); 599} 600 601static void 602ie_ee16_hw_eeprom_clock (u_int32_t port, int state) 603{ 604 u_int8_t ectrl; 605 606 ectrl = inb(port + IEE16_ECTRL); 607 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK); 608 609 if (state) { 610 ectrl |= IEE16_ECTRL_EESK; 611 } 612 outb(port + IEE16_ECTRL, ectrl); 613 DELAY(9); /* EESK must be stable for 8.38 uSec */ 614} 615 616static void 617ie_ee16_hw_eeprom_out (u_int32_t port, u_int16_t edata, int count) 618{ 619 u_int8_t ectrl; 620 int i; 621 622 ectrl = inb(port + IEE16_ECTRL); 623 ectrl &= ~IEE16_RESET_ASIC; 624 625 for (i = count - 1; i >= 0; i--) { 626 ectrl &= ~IEE16_ECTRL_EEDI; 627 if (edata & (1 << i)) { 628 ectrl |= IEE16_ECTRL_EEDI; 629 } 630 outb(port + IEE16_ECTRL, ectrl); 631 DELAY(1); /* eeprom data must be setup for 0.4 uSec */ 632 ie_ee16_hw_eeprom_clock(port, 1); 633 ie_ee16_hw_eeprom_clock(port, 0); 634 } 635 ectrl &= ~IEE16_ECTRL_EEDI; 636 outb(port + IEE16_ECTRL, ectrl); 637 DELAY(1); /* eeprom data must be held for 0.4 uSec */ 638 639 return; 640} 641 642static u_int16_t 643ie_ee16_hw_eeprom_in (u_int32_t port) 644{ 645 u_int8_t ectrl; 646 u_int16_t edata; 647 int i; 648 649 ectrl = inb(port + IEE16_ECTRL); 650 ectrl &= ~IEE16_RESET_ASIC; 651 652 for (edata = 0, i = 0; i < 16; i++) { 653 edata = edata << 1; 654 ie_ee16_hw_eeprom_clock(port, 1); 655 ectrl = inb(port + IEE16_ECTRL); 656 if (ectrl & IEE16_ECTRL_EEDO) { 657 edata |= 1; 658 } 659 ie_ee16_hw_eeprom_clock(port, 0); 660 } 661 return (edata); 662} 663 664static u_int16_t 665ie_ee16_hw_read_eeprom (u_int32_t port, int loc) 666{ 667 u_int8_t ectrl; 668 u_int16_t edata; 669 670 ectrl = inb(port + IEE16_ECTRL); 671 ectrl &= IEE16_ECTRL_MASK; 672 ectrl |= IEE16_ECTRL_EECS; 673 outb(port + IEE16_ECTRL, ectrl); 674 675 ie_ee16_hw_eeprom_out(port, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1); 676 ie_ee16_hw_eeprom_out(port, loc, IEE16_EEPROM_ADDR_SIZE); 677 edata = ie_ee16_hw_eeprom_in(port); 678 679 ectrl = inb(port + IEE16_ECTRL); 680 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS); 681 outb(port + IEE16_ECTRL, ectrl); 682 683 ie_ee16_hw_eeprom_clock(port, 1); 684 ie_ee16_hw_eeprom_clock(port, 0); 685 686 return (edata); 687} 688 689/* 690 * AT&T StarLan/ 691 */ 692 693static int 694ie_isa_sl_probe (device_t dev) 695{ 696 u_int32_t iobase; 697 698 /* No ISA-PnP support */ 699 if (isa_get_vendorid(dev)) 700 return (ENXIO); 701 702 /* ISA-HINT support only! */ 703 if (device_get_desc(dev)) 704 return (EBUSY); 705 706 /* Have we at least an ioport? */ 707 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) 708 return (ENXIO); 709 710 /* Is this really an SL board? */ 711 if (ie_isa_sl_get_hard_type(iobase) == IE_NONE) 712 return (ENXIO); 713 714 return (ENXIO); 715} 716 717static int 718ie_isa_sl_attach (device_t dev) 719{ 720 struct ie_softc * sc; 721 int error; 722 723 sc = device_get_softc(dev); 724 725 sc->io_rid = 0; 726 sc->irq_rid = 0; 727 sc->mem_rid = 0; 728 729 error = ie_alloc_resources(dev); 730 if (error) { 731 goto bad; 732 } 733 734 /* Is this really an SL board? */ 735 if ((sc->hard_type = ie_isa_sl_get_hard_type(PORT(sc))) == IE_NONE) { 736 error = ENXIO; 737 goto bad; 738 } 739 740 sc->hard_vers = SL_REV(inb(PORT(sc) + IEATT_REVISION)); 741 if (sc->hard_type == IE_NI5210) { 742 sc->bus_use = 1; 743 } else { 744 sc->bus_use = 0; 745 } 746 747 sc->ie_reset_586 = sl_reset_586; 748 sc->ie_chan_attn = sl_chan_attn; 749 750 if (!check_ie_present(sc)) { 751 error = ENXIO; 752 goto bad; 753 } 754 755 switch (sc->hard_type) { 756 case IE_EN100: 757 case IE_STARLAN10: 758 case IE_SLFIBER: 759 case IE_NI5210: 760 sl_read_ether(sc, sc->enaddr); 761 break; 762 default: 763 if (bootverbose) 764 device_printf(sc->dev, "unknown AT&T board type code %d\n", sc->hard_type); 765 error = ENXIO; 766 goto bad; 767 break; 768 } 769 770 error = ie_attach(dev); 771 if (error) { 772 device_printf(dev, "ie_attach() failed.\n"); 773 goto bad; 774 } 775 776 error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, 777 ie_intr, sc, &sc->irq_ih); 778 if (error) { 779 device_printf(dev, "Unable to register interrupt handler\n"); 780 goto bad; 781 } 782 783 return (0); 784bad: 785 ie_release_resources(dev); 786 787 return (error); 788} 789 790static enum ie_hardware 791ie_isa_sl_get_hard_type (u_int32_t port) 792{ 793 u_char c; 794 enum ie_hardware retval; 795 796 c = inb(port + IEATT_REVISION); 797 switch (SL_BOARD(c)) { 798 case SL1_BOARD: 799 if (inb(port + IEATT_ATTRIB) != NI5210_BOARD) 800 retval = IE_NONE; 801 retval = IE_NI5210; 802 break; 803 case SL10_BOARD: 804 retval = IE_STARLAN10; 805 break; 806 case EN100_BOARD: 807 retval = IE_EN100; 808 break; 809 case SLFIBER_BOARD: 810 retval = IE_SLFIBER; 811 break; 812 default: 813 retval = IE_NONE; 814 } 815 return (retval); 816} 817 818static devclass_t ie_devclass; 819 820static device_method_t ie_isa_3C507_methods[] = { 821 DEVMETHOD(device_identify, ie_isa_3C507_identify), 822 DEVMETHOD(device_probe, ie_isa_3C507_probe), 823 DEVMETHOD(device_attach, ie_isa_3C507_attach), 824 DEVMETHOD(device_detach, ie_detach), 825 { 0, 0 } 826}; 827static driver_t ie_isa_3C507_driver = { 828 "ie", 829 ie_isa_3C507_methods, 830 sizeof(struct ie_softc), 831}; 832DRIVER_MODULE(ie_3C507, isa, ie_isa_3C507_driver, ie_devclass, ie_modevent, 0); 833MODULE_DEPEND(ie_3C507, elink, 1, 1, 1); 834 835static device_method_t ie_isa_ee16_methods[] = { 836 DEVMETHOD(device_identify, ie_isa_ee16_identify), 837 DEVMETHOD(device_probe, ie_isa_ee16_probe), 838 DEVMETHOD(device_attach, ie_isa_ee16_attach), 839 DEVMETHOD(device_detach, ie_detach), 840 { 0, 0 } 841}; 842static driver_t ie_isa_ee16_driver = { 843 "ie", 844 ie_isa_ee16_methods, 845 sizeof(struct ie_softc), 846}; 847DRIVER_MODULE(ie_EE16, isa, ie_isa_ee16_driver, ie_devclass, ie_modevent, 0); 848 849static device_method_t ie_isa_sl_methods[] = { 850 DEVMETHOD(device_probe, ie_isa_sl_probe), 851 DEVMETHOD(device_attach, ie_isa_sl_attach), 852 DEVMETHOD(device_detach, ie_detach), 853 { 0, 0 } 854}; 855static driver_t ie_isa_sl_driver = { 856 "ie", 857 ie_isa_sl_methods, 858 sizeof(struct ie_softc), 859}; 860DRIVER_MODULE(ie_SL, isa, ie_isa_sl_driver, ie_devclass, ie_modevent, 0); 861 862static int 863ie_modevent (mod, what, arg) 864 module_t mod; 865 int what; 866 void * arg; 867{ 868 device_t * devs; 869 int count; 870 int i; 871 872 switch (what) { 873 case MOD_LOAD: 874 break; 875 case MOD_UNLOAD: 876 devclass_get_devices(ie_devclass, &devs, &count); 877 for (i = 0; i < count; i++) 878 device_delete_child(device_get_parent(devs[i]), devs[i]); 879 break; 880 default: 881 break; 882 }; 883 884 return (0); 885} 886