if_xl.c (223385) | if_xl.c (226995) |
---|---|
1/*- 2 * Copyright (c) 1997, 1998, 1999 3 * Bill Paul <wpaul@ctr.columbia.edu>. 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 --- 17 unchanged lines hidden (view full) --- 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1997, 1998, 1999 3 * Bill Paul <wpaul@ctr.columbia.edu>. 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 --- 17 unchanged lines hidden (view full) --- 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/dev/xl/if_xl.c 223385 2011-06-21 22:17:28Z imp $"); | 34__FBSDID("$FreeBSD: head/sys/dev/xl/if_xl.c 226995 2011-11-01 16:13:59Z marius $"); |
35 36/* 37 * 3Com 3c90x Etherlink XL PCI NIC driver 38 * 39 * Supports the 3Com "boomerang", "cyclone" and "hurricane" PCI 40 * bus-master chips (3c90x cards and embedded controllers) including 41 * the following: 42 * --- 79 unchanged lines hidden (view full) --- 122#include <net/bpf.h> 123 124#include <machine/bus.h> 125#include <machine/resource.h> 126#include <sys/bus.h> 127#include <sys/rman.h> 128 129#include <dev/mii/mii.h> | 35 36/* 37 * 3Com 3c90x Etherlink XL PCI NIC driver 38 * 39 * Supports the 3Com "boomerang", "cyclone" and "hurricane" PCI 40 * bus-master chips (3c90x cards and embedded controllers) including 41 * the following: 42 * --- 79 unchanged lines hidden (view full) --- 122#include <net/bpf.h> 123 124#include <machine/bus.h> 125#include <machine/resource.h> 126#include <sys/bus.h> 127#include <sys/rman.h> 128 129#include <dev/mii/mii.h> |
130#include <dev/mii/mii_bitbang.h> |
|
130#include <dev/mii/miivar.h> 131 132#include <dev/pci/pcireg.h> 133#include <dev/pci/pcivar.h> 134 135MODULE_DEPEND(xl, pci, 1, 1, 1); 136MODULE_DEPEND(xl, ether, 1, 1, 1); 137MODULE_DEPEND(xl, miibus, 1, 1, 1); --- 17 unchanged lines hidden (view full) --- 155#define XL905B_CSUM_FEATURES 0 156#else 157#define XL905B_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 158#endif 159 160/* 161 * Various supported device vendors/types and their names. 162 */ | 131#include <dev/mii/miivar.h> 132 133#include <dev/pci/pcireg.h> 134#include <dev/pci/pcivar.h> 135 136MODULE_DEPEND(xl, pci, 1, 1, 1); 137MODULE_DEPEND(xl, ether, 1, 1, 1); 138MODULE_DEPEND(xl, miibus, 1, 1, 1); --- 17 unchanged lines hidden (view full) --- 156#define XL905B_CSUM_FEATURES 0 157#else 158#define XL905B_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 159#endif 160 161/* 162 * Various supported device vendors/types and their names. 163 */ |
163static const struct xl_type xl_devs[] = { | 164static const struct xl_type const xl_devs[] = { |
164 { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT, 165 "3Com 3c900-TPO Etherlink XL" }, 166 { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT_COMBO, 167 "3Com 3c900-COMBO Etherlink XL" }, 168 { TC_VENDORID, TC_DEVICEID_BOOMERANG_10_100BT, 169 "3Com 3c905-TX Fast Etherlink XL" }, 170 { TC_VENDORID, TC_DEVICEID_BOOMERANG_100BT4, 171 "3Com 3c905-T4 Fast Etherlink XL" }, --- 81 unchanged lines hidden (view full) --- 253static int xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count); 254#endif 255 256static int xl_ifmedia_upd(struct ifnet *); 257static void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *); 258 259static int xl_eeprom_wait(struct xl_softc *); 260static int xl_read_eeprom(struct xl_softc *, caddr_t, int, int, int); | 165 { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT, 166 "3Com 3c900-TPO Etherlink XL" }, 167 { TC_VENDORID, TC_DEVICEID_BOOMERANG_10BT_COMBO, 168 "3Com 3c900-COMBO Etherlink XL" }, 169 { TC_VENDORID, TC_DEVICEID_BOOMERANG_10_100BT, 170 "3Com 3c905-TX Fast Etherlink XL" }, 171 { TC_VENDORID, TC_DEVICEID_BOOMERANG_100BT4, 172 "3Com 3c905-T4 Fast Etherlink XL" }, --- 81 unchanged lines hidden (view full) --- 254static int xl_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count); 255#endif 256 257static int xl_ifmedia_upd(struct ifnet *); 258static void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *); 259 260static int xl_eeprom_wait(struct xl_softc *); 261static int xl_read_eeprom(struct xl_softc *, caddr_t, int, int, int); |
261static void xl_mii_sync(struct xl_softc *); 262static void xl_mii_send(struct xl_softc *, u_int32_t, int); 263static int xl_mii_readreg(struct xl_softc *, struct xl_mii_frame *); 264static int xl_mii_writereg(struct xl_softc *, struct xl_mii_frame *); | |
265 266static void xl_rxfilter(struct xl_softc *); 267static void xl_rxfilter_90x(struct xl_softc *); 268static void xl_rxfilter_90xB(struct xl_softc *); 269static void xl_setcfg(struct xl_softc *); 270static void xl_setmode(struct xl_softc *, int); 271static void xl_reset(struct xl_softc *); 272static int xl_list_rx_init(struct xl_softc *); --- 8 unchanged lines hidden (view full) --- 281static void xl_testpacket(struct xl_softc *); 282#endif 283 284static int xl_miibus_readreg(device_t, int, int); 285static int xl_miibus_writereg(device_t, int, int, int); 286static void xl_miibus_statchg(device_t); 287static void xl_miibus_mediainit(device_t); 288 | 262 263static void xl_rxfilter(struct xl_softc *); 264static void xl_rxfilter_90x(struct xl_softc *); 265static void xl_rxfilter_90xB(struct xl_softc *); 266static void xl_setcfg(struct xl_softc *); 267static void xl_setmode(struct xl_softc *, int); 268static void xl_reset(struct xl_softc *); 269static int xl_list_rx_init(struct xl_softc *); --- 8 unchanged lines hidden (view full) --- 278static void xl_testpacket(struct xl_softc *); 279#endif 280 281static int xl_miibus_readreg(device_t, int, int); 282static int xl_miibus_writereg(device_t, int, int, int); 283static void xl_miibus_statchg(device_t); 284static void xl_miibus_mediainit(device_t); 285 |
286/* 287 * MII bit-bang glue 288 */ 289static uint32_t xl_mii_bitbang_read(device_t); 290static void xl_mii_bitbang_write(device_t, uint32_t); 291 292static const struct mii_bitbang_ops xl_mii_bitbang_ops = { 293 xl_mii_bitbang_read, 294 xl_mii_bitbang_write, 295 { 296 XL_MII_DATA, /* MII_BIT_MDO */ 297 XL_MII_DATA, /* MII_BIT_MDI */ 298 XL_MII_CLK, /* MII_BIT_MDC */ 299 XL_MII_DIR, /* MII_BIT_DIR_HOST_PHY */ 300 0, /* MII_BIT_DIR_PHY_HOST */ 301 } 302}; 303 |
|
289static device_method_t xl_methods[] = { 290 /* Device interface */ 291 DEVMETHOD(device_probe, xl_probe), 292 DEVMETHOD(device_attach, xl_attach), 293 DEVMETHOD(device_detach, xl_detach), 294 DEVMETHOD(device_shutdown, xl_shutdown), 295 DEVMETHOD(device_suspend, xl_suspend), 296 DEVMETHOD(device_resume, xl_resume), --- 57 unchanged lines hidden (view full) --- 354 * MII access routines are provided for adapters with external 355 * PHYs (3c905-TX, 3c905-T4, 3c905B-T4) and those with built-in 356 * autoneg logic that's faked up to look like a PHY (3c905B-TX). 357 * Note: if you don't perform the MDIO operations just right, 358 * it's possible to end up with code that works correctly with 359 * some chips/CPUs/processor speeds/bus speeds/etc but not 360 * with others. 361 */ | 304static device_method_t xl_methods[] = { 305 /* Device interface */ 306 DEVMETHOD(device_probe, xl_probe), 307 DEVMETHOD(device_attach, xl_attach), 308 DEVMETHOD(device_detach, xl_detach), 309 DEVMETHOD(device_shutdown, xl_shutdown), 310 DEVMETHOD(device_suspend, xl_suspend), 311 DEVMETHOD(device_resume, xl_resume), --- 57 unchanged lines hidden (view full) --- 369 * MII access routines are provided for adapters with external 370 * PHYs (3c905-TX, 3c905-T4, 3c905B-T4) and those with built-in 371 * autoneg logic that's faked up to look like a PHY (3c905B-TX). 372 * Note: if you don't perform the MDIO operations just right, 373 * it's possible to end up with code that works correctly with 374 * some chips/CPUs/processor speeds/bus speeds/etc but not 375 * with others. 376 */ |
362#define MII_SET(x) \ 363 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \ 364 CSR_READ_2(sc, XL_W4_PHY_MGMT) | (x)) | |
365 | 377 |
366#define MII_CLR(x) \ 367 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \ 368 CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~(x)) 369 | |
370/* | 378/* |
371 * Sync the PHYs by setting data bit and strobing the clock 32 times. | 379 * Read the MII serial port for the MII bit-bang module. |
372 */ | 380 */ |
373static void 374xl_mii_sync(struct xl_softc *sc) | 381static uint32_t 382xl_mii_bitbang_read(device_t dev) |
375{ | 383{ |
376 register int i; | 384 struct xl_softc *sc; 385 uint32_t val; |
377 | 386 |
378 XL_SEL_WIN(4); 379 MII_SET(XL_MII_DIR|XL_MII_DATA); | 387 sc = device_get_softc(dev); |
380 | 388 |
381 for (i = 0; i < 32; i++) { 382 MII_SET(XL_MII_CLK); 383 MII_SET(XL_MII_DATA); 384 MII_SET(XL_MII_DATA); 385 MII_CLR(XL_MII_CLK); 386 MII_SET(XL_MII_DATA); 387 MII_SET(XL_MII_DATA); 388 } | 389 /* We're already in window 4. */ 390 val = CSR_READ_2(sc, XL_W4_PHY_MGMT); 391 CSR_BARRIER(sc, XL_W4_PHY_MGMT, 2, 392 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 393 394 return (val); |
389} 390 391/* | 395} 396 397/* |
392 * Clock a series of bits through the MII. | 398 * Write the MII serial port for the MII bit-bang module. |
393 */ 394static void | 399 */ 400static void |
395xl_mii_send(struct xl_softc *sc, u_int32_t bits, int cnt) | 401xl_mii_bitbang_write(device_t dev, uint32_t val) |
396{ | 402{ |
397 int i; | 403 struct xl_softc *sc; |
398 | 404 |
399 XL_SEL_WIN(4); 400 MII_CLR(XL_MII_CLK); | 405 sc = device_get_softc(dev); |
401 | 406 |
402 for (i = (0x1 << (cnt - 1)); i; i >>= 1) { 403 if (bits & i) { 404 MII_SET(XL_MII_DATA); 405 } else { 406 MII_CLR(XL_MII_DATA); 407 } 408 MII_CLR(XL_MII_CLK); 409 MII_SET(XL_MII_CLK); 410 } | 407 /* We're already in window 4. */ 408 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, val); 409 CSR_BARRIER(sc, XL_W4_PHY_MGMT, 2, 410 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); |
411} 412 | 411} 412 |
413/* 414 * Read an PHY register through the MII. 415 */ | |
416static int | 413static int |
417xl_mii_readreg(struct xl_softc *sc, struct xl_mii_frame *frame) 418{ 419 int i, ack; 420 421 /* Set up frame for RX. */ 422 frame->mii_stdelim = XL_MII_STARTDELIM; 423 frame->mii_opcode = XL_MII_READOP; 424 frame->mii_turnaround = 0; 425 frame->mii_data = 0; 426 427 /* Select register window 4. */ 428 XL_SEL_WIN(4); 429 430 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0); 431 /* Turn on data xmit. */ 432 MII_SET(XL_MII_DIR); 433 434 xl_mii_sync(sc); 435 436 /* Send command/address info. */ 437 xl_mii_send(sc, frame->mii_stdelim, 2); 438 xl_mii_send(sc, frame->mii_opcode, 2); 439 xl_mii_send(sc, frame->mii_phyaddr, 5); 440 xl_mii_send(sc, frame->mii_regaddr, 5); 441 442 /* Idle bit */ 443 MII_CLR((XL_MII_CLK|XL_MII_DATA)); 444 MII_SET(XL_MII_CLK); 445 446 /* Turn off xmit. */ 447 MII_CLR(XL_MII_DIR); 448 449 /* Check for ack */ 450 MII_CLR(XL_MII_CLK); 451 ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA; 452 MII_SET(XL_MII_CLK); 453 454 /* 455 * Now try reading data bits. If the ack failed, we still 456 * need to clock through 16 cycles to keep the PHY(s) in sync. 457 */ 458 if (ack) { 459 for (i = 0; i < 16; i++) { 460 MII_CLR(XL_MII_CLK); 461 MII_SET(XL_MII_CLK); 462 } 463 goto fail; 464 } 465 466 for (i = 0x8000; i; i >>= 1) { 467 MII_CLR(XL_MII_CLK); 468 if (!ack) { 469 if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA) 470 frame->mii_data |= i; 471 } 472 MII_SET(XL_MII_CLK); 473 } 474 475fail: 476 MII_CLR(XL_MII_CLK); 477 MII_SET(XL_MII_CLK); 478 479 return (ack ? 1 : 0); 480} 481 482/* 483 * Write to a PHY register through the MII. 484 */ 485static int 486xl_mii_writereg(struct xl_softc *sc, struct xl_mii_frame *frame) 487{ 488 489 /* Set up frame for TX. */ 490 frame->mii_stdelim = XL_MII_STARTDELIM; 491 frame->mii_opcode = XL_MII_WRITEOP; 492 frame->mii_turnaround = XL_MII_TURNAROUND; 493 494 /* Select the window 4. */ 495 XL_SEL_WIN(4); 496 497 /* Turn on data output. */ 498 MII_SET(XL_MII_DIR); 499 500 xl_mii_sync(sc); 501 502 xl_mii_send(sc, frame->mii_stdelim, 2); 503 xl_mii_send(sc, frame->mii_opcode, 2); 504 xl_mii_send(sc, frame->mii_phyaddr, 5); 505 xl_mii_send(sc, frame->mii_regaddr, 5); 506 xl_mii_send(sc, frame->mii_turnaround, 2); 507 xl_mii_send(sc, frame->mii_data, 16); 508 509 /* Idle bit. */ 510 MII_SET(XL_MII_CLK); 511 MII_CLR(XL_MII_CLK); 512 513 /* Turn off xmit. */ 514 MII_CLR(XL_MII_DIR); 515 516 return (0); 517} 518 519static int | |
520xl_miibus_readreg(device_t dev, int phy, int reg) 521{ 522 struct xl_softc *sc; | 414xl_miibus_readreg(device_t dev, int phy, int reg) 415{ 416 struct xl_softc *sc; |
523 struct xl_mii_frame frame; | |
524 525 sc = device_get_softc(dev); 526 | 417 418 sc = device_get_softc(dev); 419 |
527 bzero((char *)&frame, sizeof(frame)); 528 frame.mii_phyaddr = phy; 529 frame.mii_regaddr = reg; | 420 /* Select the window 4. */ 421 XL_SEL_WIN(4); |
530 | 422 |
531 xl_mii_readreg(sc, &frame); 532 533 return (frame.mii_data); | 423 return (mii_bitbang_readreg(dev, &xl_mii_bitbang_ops, phy, reg)); |
534} 535 536static int 537xl_miibus_writereg(device_t dev, int phy, int reg, int data) 538{ 539 struct xl_softc *sc; | 424} 425 426static int 427xl_miibus_writereg(device_t dev, int phy, int reg, int data) 428{ 429 struct xl_softc *sc; |
540 struct xl_mii_frame frame; | |
541 542 sc = device_get_softc(dev); 543 | 430 431 sc = device_get_softc(dev); 432 |
544 bzero((char *)&frame, sizeof(frame)); 545 frame.mii_phyaddr = phy; 546 frame.mii_regaddr = reg; 547 frame.mii_data = data; | 433 /* Select the window 4. */ 434 XL_SEL_WIN(4); |
548 | 435 |
549 xl_mii_writereg(sc, &frame); | 436 mii_bitbang_writereg(dev, &xl_mii_bitbang_ops, phy, reg, data); |
550 551 return (0); 552} 553 554static void 555xl_miibus_statchg(device_t dev) 556{ 557 struct xl_softc *sc; --- 2853 unchanged lines hidden --- | 437 438 return (0); 439} 440 441static void 442xl_miibus_statchg(device_t dev) 443{ 444 struct xl_softc *sc; --- 2853 unchanged lines hidden --- |