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$"); 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/md_var.h> 55 56#include <net/if.h> 57#include <net/if_arp.h> 58#include <net/if_media.h> 59 60#include <isa/isavar.h> 61#include <isa/pnpvar.h> 62 63#include <i386/isa/elink.h> 64 65#include <dev/ic/i82586.h> 66#include <dev/ie/if_ie507.h> 67#include <dev/ie/if_iee16.h> 68#include <dev/ie/if_iereg.h> 69#include <dev/ie/if_ievar.h> 70 71static int ie_modevent (module_t, int, void *); 72 73static void ie_isa_3C507_identify (driver_t *, device_t); 74static int ie_isa_3C507_probe (device_t); 75static int ie_isa_3C507_attach (device_t); 76static int ie_3C507_port_check (u_int32_t); 77 78static void ie_isa_ee16_identify (driver_t *, device_t); 79static int ie_isa_ee16_probe (device_t); 80static int ie_isa_ee16_attach (device_t); 81static int ie_isa_ee16_shutdown (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 return (0); 274bad: 275 ie_release_resources(dev); 276 277 return (error); 278} 279 280/* 281 * If a 3c507 is present, return 0 282 * else, return 1. 283 */ 284static int 285ie_3C507_port_check (u_int32_t port) 286{ 287 u_char * signature = "*3COM*"; 288 int i; 289 290 for (i = 0; i < 6; i++) 291 if (inb(port + i) != signature[i]) 292 return (ENXIO); 293 294 return (0); 295} 296 297/* 298 * Intel EtherExpress 16 299 */ 300#define IE_EE16_ID_PORT 0x0f 301#define IE_EE16_ID 0xbaba 302#define IE_EE16_EEPROM_CONFIG1 0x00 303#define IE_EE16_EEPROM_IRQ_MASK 0xe000 304#define IE_EE16_EEPROM_IRQ_SHIFT 13 305#define IE_EE16_EEPROM_MEMCFG 0x06 306#define IE_EE16_IOSIZE 16 307 308/* 309 * TODO: 310 * Test for 8/16 bit mode. 311 * Test for invalid mem sizes. 312 */ 313static void 314ie_isa_ee16_identify (driver_t *driver, device_t parent) 315{ 316 char * desc = "Intel EtherExpress 16"; 317 device_t child; 318 u_int16_t ports[] = { 319 0x300, 0x310, 0x320, 0x330, 320 0x340, 0x350, 0x360, 0x370, 321 0x200, 0x210, 0x220, 0x230, 322 0x240, 0x250, 0x260, 0x270, 323 0 324 }; 325 u_int16_t irqs[] = { 0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0 }; 326 u_int32_t port, maddr, msize; 327 u_int8_t irq; 328 u_int16_t data; 329 int i, error; 330 331 for (i = 0; ports[i]; i++) { 332 port = ports[i]; 333 334 if (ie_ee16_port_check(port)) { 335#ifdef DEBUG 336 if (bootverbose) { 337 device_printf(parent, 338 "if_ie: (EE16) not found at port %#x\n", 339 port); 340 } 341#endif 342 continue; 343 } 344 345 /* reset any ee16 at the current iobase */ 346 outb(port + IEE16_ECTRL, IEE16_RESET_ASIC); 347 outb(port + IEE16_ECTRL, 0); 348 DELAY(240); 349 350 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_CONFIG1); 351 irq = irqs[((data & IE_EE16_EEPROM_IRQ_MASK) 352 >> IE_EE16_EEPROM_IRQ_SHIFT)]; 353 354 data = ie_ee16_hw_read_eeprom(port, IE_EE16_EEPROM_MEMCFG); 355 maddr = 0xc0000 + ((ffs(data & 0x00ff) - 1) * 0x4000); 356 msize = (fls((data & 0x00ff) >> (ffs(data & 0x00ff) - 1))) 357 * 0x4000; 358 359 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ie", -1); 360 device_set_desc_copy(child, desc); 361 device_set_driver(child, driver); 362 363 error = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 364 if (error) { 365 device_printf(parent, "(if_ie) Unable to set IRQ resource %d.\n", 366 irq); 367 error = device_delete_child(parent, child); 368 continue; 369 } 370 371 error = bus_set_resource(child, SYS_RES_IOPORT, 0, port, IE_EE16_IOSIZE); 372 if (error) { 373 device_printf(parent, "(if_ie) Unable to set IOPORT resource %#x-%#x.\n", 374 port, port+IE_EE16_IOSIZE); 375 error = device_delete_child(parent, child); 376 continue; 377 } 378 379 error = bus_set_resource(child, SYS_RES_MEMORY, 0, maddr, msize); 380 if (error) { 381 device_printf(parent, "(if_ie) Unable to set MEMORY resource %#x-%#x.\n", 382 maddr, maddr+msize); 383 error = device_delete_child(parent, child); 384 continue; 385 } 386 387 if (bootverbose) { 388 device_printf(parent, 389 "if_ie: <%s> at port %#x-%#x irq %d iomem %#lx-%#lx (%dKB)\n", 390 desc, 391 port, (port + IE_EE16_IOSIZE) - 1, 392 irq, 393 (u_long)maddr, (u_long)(maddr + msize) - 1, 394 (msize / 1024)); 395 } 396 } 397 398 return; 399} 400 401static int 402ie_isa_ee16_probe (device_t dev) 403{ 404 u_int32_t iobase; 405 406 /* No ISA-PnP support */ 407 if (isa_get_vendorid(dev)) 408 return (ENXIO); 409 410 /* No ISA-HINT support */ 411 if (!device_get_desc(dev)) 412 return (EBUSY); 413 414 /* Have we at least an ioport? */ 415 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) 416 return (ENXIO); 417 418 /* Is this really an EE16? */ 419 if (ie_ee16_port_check(iobase)) 420 return (ENXIO); 421 422 return (0); 423} 424 425static int 426ie_isa_ee16_attach (device_t dev) 427{ 428 struct ie_softc * sc; 429 int i, error; 430 u_int16_t checksum; 431 u_short eaddrtemp, pg, adjust, decode, edecode; 432 u_char bart_config; 433 434 sc = device_get_softc(dev); 435 436 sc->io_rid = 0; 437 sc->irq_rid = 0; 438 sc->mem_rid = 0; 439 440 error = ie_alloc_resources(dev); 441 if (error) { 442 goto bad; 443 } 444 445 sc->bus_use = 0; 446 sc->ie_reset_586 = ee16_reset_586; 447 sc->ie_chan_attn = ee16_chan_attn; 448 sc->hard_type = IE_EE16; 449 sc->hard_vers = 0; 450 sc->iomem = 0; 451 452 /* reset any ee16 at the current iobase */ 453 outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_ASIC); 454 outb(PORT(sc) + IEE16_ECTRL, 0); 455 DELAY(240); 456 457 /* Is this really an EE16? */ 458 if (ie_ee16_port_check(PORT(sc))) { 459 device_printf(dev, "ie_ee16_port_check() failed\n"); 460 error = ENXIO; 461 goto bad; 462 } 463 464 /* need to put the 586 in RESET while we access the eeprom. */ 465 outb(PORT(sc) + IEE16_ECTRL, IEE16_RESET_586); 466 467 /* read the eeprom and checksum it, should == IE_E16_ID */ 468 checksum = 0; 469 for (i = 0; i < 0x40; i++) 470 checksum += ie_ee16_hw_read_eeprom(PORT(sc), i); 471 472 if (checksum != IE_EE16_ID) { 473 device_printf(dev, "invalid eeprom checksum: %x\n", checksum); 474 error = ENXIO; 475 goto bad; 476 } 477 478 if ((kvtop(sc->iomembot) < 0xC0000) || 479 (kvtop(sc->iomembot) + sc->iosize > 0xF0000)) { 480 device_printf(sc->dev, "mapped memory location %p out of range\n", 481 (void *)sc->iomembot); 482 error = ENXIO; 483 goto bad; 484 } 485 486 pg = ((kvtop(sc->iomembot)) & 0x3C000) >> 14; 487 adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2; 488 decode = ((1 << (sc->iosize / 16384)) - 1) << pg; 489 edecode = ((~decode >> 4) & 0xF0) | (decode >> 8); 490 491 /* ZZZ This should be checked against eeprom location 6, low byte */ 492 outb(PORT(sc) + IEE16_MEMDEC, decode & 0xFF); 493 /* ZZZ This should be checked against eeprom location 1, low byte */ 494 outb(PORT(sc) + IEE16_MCTRL, adjust); 495 /* ZZZ Now if I could find this one I would have it made */ 496 outb(PORT(sc) + IEE16_MPCTRL, (~decode & 0xFF)); 497 /* ZZZ I think this is location 6, high byte */ 498 outb(PORT(sc) + IEE16_MECTRL, edecode); /* XXX disable Exxx */ 499 500#if 0 501 (void) kvtop(sc->iomembot); 502#endif 503 504 /* 505 * first prime the stupid bart DRAM controller so that it works, 506 * then zero out all of memory. 507 */ 508 bzero(sc->iomembot, 32); 509 bzero(sc->iomembot, sc->iosize); 510 511 /* Get the encoded interrupt number from the EEPROM */ 512 sc->irq_encoded = ie_ee16_hw_read_eeprom(PORT(sc), 513 IE_EE16_EEPROM_CONFIG1); 514 sc->irq_encoded = (sc->irq_encoded & IE_EE16_EEPROM_IRQ_MASK) >> 515 IE_EE16_EEPROM_IRQ_SHIFT; 516 517 /* 518 * Get the hardware ethernet address from the EEPROM and save it in 519 * the softc for use by the 586 setup code. 520 */ 521 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_HIGH); 522 sc->enaddr[1] = eaddrtemp & 0xFF; 523 sc->enaddr[0] = eaddrtemp >> 8; 524 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_MID); 525 sc->enaddr[3] = eaddrtemp & 0xFF; 526 sc->enaddr[2] = eaddrtemp >> 8; 527 eaddrtemp = ie_ee16_hw_read_eeprom(PORT(sc), IEE16_EEPROM_ENET_LOW); 528 sc->enaddr[5] = eaddrtemp & 0xFF; 529 sc->enaddr[4] = eaddrtemp >> 8; 530 531 /* disable the board interrupts */ 532 outb(PORT(sc) + IEE16_IRQ, sc->irq_encoded); 533 534 /* enable loopback to keep bad packets off the wire */ 535 bart_config = inb(PORT(sc) + IEE16_CONFIG); 536 bart_config |= IEE16_BART_LOOPBACK; 537 bart_config |= IEE16_BART_MCS16_TEST;/* inb doesn't get bit! */ 538 outb(PORT(sc) + IEE16_CONFIG, bart_config); 539 bart_config = inb(PORT(sc) + IEE16_CONFIG); 540 541 /* take the board out of reset state */ 542 outb(PORT(sc) + IEE16_ECTRL, 0); 543 DELAY(100); 544 545 if (!check_ie_present(sc)) { 546 device_printf(dev, "check_ie_present() returned false.\n"); 547 error = ENXIO; 548 goto bad; 549 } 550 551 error = ie_attach(dev); 552 if (error) { 553 device_printf(dev, "ie_attach() failed.\n"); 554 goto bad; 555 } 556 557 return (0); 558bad: 559 ie_release_resources(dev); 560 561 return (error); 562} 563 564static int 565ie_isa_ee16_shutdown(device_t dev) 566{ 567 struct ie_softc * sc; 568 569 sc = device_get_softc(dev); 570 IE_LOCK(sc); 571 ee16_shutdown(sc); 572 IE_UNLOCK(sc); 573 574 return (0); 575} 576 577/* 578 * If an EE16 is present, return 0 579 * else, return 1. 580 */ 581static int 582ie_ee16_port_check (u_int32_t port) 583{ 584 int i; 585 u_int16_t board_id; 586 u_int8_t data; 587 588 board_id = 0; 589 for (i = 0; i < 4; i++) { 590 data = inb(port + IE_EE16_ID_PORT); 591 board_id |= ((data >> 4) << ((data & 0x03) << 2)); 592 } 593 594 if (board_id != IE_EE16_ID) 595 return (1); 596 597 return (0); 598} 599 600static void 601ie_ee16_hw_eeprom_clock (u_int32_t port, int state) 602{ 603 u_int8_t ectrl; 604 605 ectrl = inb(port + IEE16_ECTRL); 606 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK); 607 608 if (state) { 609 ectrl |= IEE16_ECTRL_EESK; 610 } 611 outb(port + IEE16_ECTRL, ectrl); 612 DELAY(9); /* EESK must be stable for 8.38 uSec */ 613} 614 615static void 616ie_ee16_hw_eeprom_out (u_int32_t port, u_int16_t edata, int count) 617{ 618 u_int8_t ectrl; 619 int i; 620 621 ectrl = inb(port + IEE16_ECTRL); 622 ectrl &= ~IEE16_RESET_ASIC; 623 624 for (i = count - 1; i >= 0; i--) { 625 ectrl &= ~IEE16_ECTRL_EEDI; 626 if (edata & (1 << i)) { 627 ectrl |= IEE16_ECTRL_EEDI; 628 } 629 outb(port + IEE16_ECTRL, ectrl); 630 DELAY(1); /* eeprom data must be setup for 0.4 uSec */ 631 ie_ee16_hw_eeprom_clock(port, 1); 632 ie_ee16_hw_eeprom_clock(port, 0); 633 } 634 ectrl &= ~IEE16_ECTRL_EEDI; 635 outb(port + IEE16_ECTRL, ectrl); 636 DELAY(1); /* eeprom data must be held for 0.4 uSec */ 637 638 return; 639} 640 641static u_int16_t 642ie_ee16_hw_eeprom_in (u_int32_t port) 643{ 644 u_int8_t ectrl; 645 u_int16_t edata; 646 int i; 647 648 ectrl = inb(port + IEE16_ECTRL); 649 ectrl &= ~IEE16_RESET_ASIC; 650 651 for (edata = 0, i = 0; i < 16; i++) { 652 edata = edata << 1; 653 ie_ee16_hw_eeprom_clock(port, 1); 654 ectrl = inb(port + IEE16_ECTRL); 655 if (ectrl & IEE16_ECTRL_EEDO) { 656 edata |= 1; 657 } 658 ie_ee16_hw_eeprom_clock(port, 0); 659 } 660 return (edata); 661} 662 663static u_int16_t 664ie_ee16_hw_read_eeprom (u_int32_t port, int loc) 665{ 666 u_int8_t ectrl; 667 u_int16_t edata; 668 669 ectrl = inb(port + IEE16_ECTRL); 670 ectrl &= IEE16_ECTRL_MASK; 671 ectrl |= IEE16_ECTRL_EECS; 672 outb(port + IEE16_ECTRL, ectrl); 673 674 ie_ee16_hw_eeprom_out(port, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1); 675 ie_ee16_hw_eeprom_out(port, loc, IEE16_EEPROM_ADDR_SIZE); 676 edata = ie_ee16_hw_eeprom_in(port); 677 678 ectrl = inb(port + IEE16_ECTRL); 679 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS); 680 outb(port + IEE16_ECTRL, ectrl); 681 682 ie_ee16_hw_eeprom_clock(port, 1); 683 ie_ee16_hw_eeprom_clock(port, 0); 684 685 return (edata); 686} 687 688/* 689 * AT&T StarLan/ 690 */ 691 692static int 693ie_isa_sl_probe (device_t dev) 694{ 695 u_int32_t iobase; 696 697 /* No ISA-PnP support */ 698 if (isa_get_vendorid(dev)) 699 return (ENXIO); 700 701 /* ISA-HINT support only! */ 702 if (device_get_desc(dev)) 703 return (EBUSY); 704 705 /* Have we at least an ioport? */ 706 if ((iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) 707 return (ENXIO); 708 709 /* Is this really an SL board? */ 710 if (ie_isa_sl_get_hard_type(iobase) == IE_NONE) 711 return (ENXIO); 712 713 return (ENXIO); 714} 715 716static int 717ie_isa_sl_attach (device_t dev) 718{ 719 struct ie_softc * sc; 720 int error; 721 722 sc = device_get_softc(dev); 723 724 sc->io_rid = 0; 725 sc->irq_rid = 0; 726 sc->mem_rid = 0; 727 728 error = ie_alloc_resources(dev); 729 if (error) { 730 goto bad; 731 } 732 733 /* Is this really an SL board? */ 734 if ((sc->hard_type = ie_isa_sl_get_hard_type(PORT(sc))) == IE_NONE) { 735 error = ENXIO; 736 goto bad; 737 } 738 739 sc->hard_vers = SL_REV(inb(PORT(sc) + IEATT_REVISION)); 740 if (sc->hard_type == IE_NI5210) { 741 sc->bus_use = 1; 742 } else { 743 sc->bus_use = 0; 744 } 745 746 sc->ie_reset_586 = sl_reset_586; 747 sc->ie_chan_attn = sl_chan_attn; 748 749 if (!check_ie_present(sc)) { 750 error = ENXIO; 751 goto bad; 752 } 753 754 switch (sc->hard_type) { 755 case IE_EN100: 756 case IE_STARLAN10: 757 case IE_SLFIBER: 758 case IE_NI5210: 759 sl_read_ether(sc, sc->enaddr); 760 break; 761 default: 762 if (bootverbose) 763 device_printf(sc->dev, "unknown AT&T board type code %d\n", sc->hard_type); 764 error = ENXIO; 765 goto bad; 766 break; 767 } 768 769 error = ie_attach(dev); 770 if (error) { 771 device_printf(dev, "ie_attach() failed.\n"); 772 goto bad; 773 } 774 775 return (0); 776bad: 777 ie_release_resources(dev); 778 779 return (error); 780} 781 782static enum ie_hardware 783ie_isa_sl_get_hard_type (u_int32_t port) 784{ 785 u_char c; 786 enum ie_hardware retval; 787 788 c = inb(port + IEATT_REVISION); 789 switch (SL_BOARD(c)) { 790 case SL1_BOARD: 791 if (inb(port + IEATT_ATTRIB) != NI5210_BOARD) 792 retval = IE_NONE; 793 retval = IE_NI5210; 794 break; 795 case SL10_BOARD: 796 retval = IE_STARLAN10; 797 break; 798 case EN100_BOARD: 799 retval = IE_EN100; 800 break; 801 case SLFIBER_BOARD: 802 retval = IE_SLFIBER; 803 break; 804 default: 805 retval = IE_NONE; 806 } 807 return (retval); 808} 809 810static devclass_t ie_devclass; 811 812static device_method_t ie_isa_3C507_methods[] = { 813 DEVMETHOD(device_identify, ie_isa_3C507_identify), 814 DEVMETHOD(device_probe, ie_isa_3C507_probe), 815 DEVMETHOD(device_attach, ie_isa_3C507_attach), 816 DEVMETHOD(device_detach, ie_detach), 817 { 0, 0 } 818}; 819 820static driver_t ie_isa_3C507_driver = { 821 "ie", 822 ie_isa_3C507_methods, 823 sizeof(struct ie_softc), 824}; 825 826DRIVER_MODULE(ie_3C507, isa, ie_isa_3C507_driver, ie_devclass, ie_modevent, 0); 827MODULE_DEPEND(ie_3C507, elink, 1, 1, 1); 828 829static device_method_t ie_isa_ee16_methods[] = { 830 DEVMETHOD(device_identify, ie_isa_ee16_identify), 831 DEVMETHOD(device_probe, ie_isa_ee16_probe), 832 DEVMETHOD(device_attach, ie_isa_ee16_attach), 833 DEVMETHOD(device_shutdown, ie_isa_ee16_shutdown), 834 DEVMETHOD(device_detach, ie_detach), 835 { 0, 0 } 836}; 837 838static driver_t ie_isa_ee16_driver = { 839 "ie", 840 ie_isa_ee16_methods, 841 sizeof(struct ie_softc), 842}; 843 844DRIVER_MODULE(ie, isa, ie_isa_ee16_driver, ie_devclass, ie_modevent, 0); 845 846static device_method_t ie_isa_sl_methods[] = { 847 DEVMETHOD(device_probe, ie_isa_sl_probe), 848 DEVMETHOD(device_attach, ie_isa_sl_attach), 849 DEVMETHOD(device_detach, ie_detach), 850 { 0, 0 } 851}; 852 853static driver_t ie_isa_sl_driver = { 854 "ie", 855 ie_isa_sl_methods, 856 sizeof(struct ie_softc), 857}; 858 859DRIVER_MODULE(ie_SL, isa, ie_isa_sl_driver, ie_devclass, ie_modevent, 0); 860 861static int 862ie_modevent (mod, what, arg) 863 module_t mod; 864 int what; 865 void * arg; 866{ 867 device_t * devs; 868 int count; 869 int i; 870 871 switch (what) { 872 case MOD_LOAD: 873 break; 874 case MOD_UNLOAD: 875 devclass_get_devices(ie_devclass, &devs, &count); 876 for (i = 0; i < count; i++) 877 device_delete_child(device_get_parent(devs[i]), devs[i]); 878 free(devs, M_TEMP); 879 break; 880 default: 881 break; 882 }; 883 884 return (0); 885} 886