diff options
| -rw-r--r-- | drivers/net/pcnet32.c | 236 |
1 files changed, 212 insertions, 24 deletions
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 7e900572eaf8..1bc3f5bffb95 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c | |||
| @@ -22,8 +22,8 @@ | |||
| 22 | *************************************************************************/ | 22 | *************************************************************************/ |
| 23 | 23 | ||
| 24 | #define DRV_NAME "pcnet32" | 24 | #define DRV_NAME "pcnet32" |
| 25 | #define DRV_VERSION "1.31c" | 25 | #define DRV_VERSION "1.32" |
| 26 | #define DRV_RELDATE "01.Nov.2005" | 26 | #define DRV_RELDATE "18.Mar.2006" |
| 27 | #define PFX DRV_NAME ": " | 27 | #define PFX DRV_NAME ": " |
| 28 | 28 | ||
| 29 | static const char * const version = | 29 | static const char * const version = |
| @@ -133,7 +133,7 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { | |||
| 133 | }; | 133 | }; |
| 134 | #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) | 134 | #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) |
| 135 | 135 | ||
| 136 | #define PCNET32_NUM_REGS 168 | 136 | #define PCNET32_NUM_REGS 136 |
| 137 | 137 | ||
| 138 | #define MAX_UNITS 8 /* More are supported, limit only on options */ | 138 | #define MAX_UNITS 8 /* More are supported, limit only on options */ |
| 139 | static int options[MAX_UNITS]; | 139 | static int options[MAX_UNITS]; |
| @@ -265,6 +265,9 @@ static int homepna[MAX_UNITS]; | |||
| 265 | * v1.31c 01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only. | 265 | * v1.31c 01 Nov 2005 Don Fry Allied Telesyn 2700/2701 FX are 100Mbit only. |
| 266 | * Force 100Mbit FD if Auto (ASEL) is selected. | 266 | * Force 100Mbit FD if Auto (ASEL) is selected. |
| 267 | * See Bugzilla 2669 and 4551. | 267 | * See Bugzilla 2669 and 4551. |
| 268 | * v1.32 18 Mar2006 Thomas Bogendoerfer and Don Fry added Multi-Phy | ||
| 269 | * handling for supporting AT-270x FTX cards with FX and Tx PHYs. | ||
| 270 | * Philippe Seewer assisted with auto negotiation and testing. | ||
| 268 | */ | 271 | */ |
| 269 | 272 | ||
| 270 | 273 | ||
| @@ -375,6 +378,7 @@ struct pcnet32_private { | |||
| 375 | unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ | 378 | unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ |
| 376 | struct net_device_stats stats; | 379 | struct net_device_stats stats; |
| 377 | char tx_full; | 380 | char tx_full; |
| 381 | char phycount; /* number of phys found */ | ||
| 378 | int options; | 382 | int options; |
| 379 | unsigned int shared_irq:1, /* shared irq possible */ | 383 | unsigned int shared_irq:1, /* shared irq possible */ |
| 380 | dxsuflo:1, /* disable transmit stop on uflo */ | 384 | dxsuflo:1, /* disable transmit stop on uflo */ |
| @@ -384,6 +388,9 @@ struct pcnet32_private { | |||
| 384 | struct timer_list watchdog_timer; | 388 | struct timer_list watchdog_timer; |
| 385 | struct timer_list blink_timer; | 389 | struct timer_list blink_timer; |
| 386 | u32 msg_enable; /* debug message level */ | 390 | u32 msg_enable; /* debug message level */ |
| 391 | |||
| 392 | /* each bit indicates an available PHY */ | ||
| 393 | u32 phymask; | ||
| 387 | }; | 394 | }; |
| 388 | 395 | ||
| 389 | static void pcnet32_probe_vlbus(void); | 396 | static void pcnet32_probe_vlbus(void); |
| @@ -415,6 +422,7 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
| 415 | static void pcnet32_purge_tx_ring(struct net_device *dev); | 422 | static void pcnet32_purge_tx_ring(struct net_device *dev); |
| 416 | static int pcnet32_alloc_ring(struct net_device *dev, char *name); | 423 | static int pcnet32_alloc_ring(struct net_device *dev, char *name); |
| 417 | static void pcnet32_free_ring(struct net_device *dev); | 424 | static void pcnet32_free_ring(struct net_device *dev); |
| 425 | static void pcnet32_check_media(struct net_device *dev, int verbose); | ||
| 418 | 426 | ||
| 419 | 427 | ||
| 420 | enum pci_flags_bit { | 428 | enum pci_flags_bit { |
| @@ -936,9 +944,14 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) | |||
| 936 | return 0; | 944 | return 0; |
| 937 | } | 945 | } |
| 938 | 946 | ||
| 947 | #define PCNET32_REGS_PER_PHY 32 | ||
| 948 | #define PCNET32_MAX_PHYS 32 | ||
| 939 | static int pcnet32_get_regs_len(struct net_device *dev) | 949 | static int pcnet32_get_regs_len(struct net_device *dev) |
| 940 | { | 950 | { |
| 941 | return(PCNET32_NUM_REGS * sizeof(u16)); | 951 | struct pcnet32_private *lp = dev->priv; |
| 952 | int j = lp->phycount * PCNET32_REGS_PER_PHY; | ||
| 953 | |||
| 954 | return((PCNET32_NUM_REGS + j) * sizeof(u16)); | ||
| 942 | } | 955 | } |
| 943 | 956 | ||
| 944 | static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, | 957 | static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, |
| @@ -998,9 +1011,14 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
| 998 | 1011 | ||
| 999 | /* read mii phy registers */ | 1012 | /* read mii phy registers */ |
| 1000 | if (lp->mii) { | 1013 | if (lp->mii) { |
| 1001 | for (i=0; i<32; i++) { | 1014 | int j; |
| 1002 | lp->a.write_bcr(ioaddr, 33, ((lp->mii_if.phy_id) << 5) | i); | 1015 | for (j=0; j<PCNET32_MAX_PHYS; j++) { |
| 1003 | *buff++ = lp->a.read_bcr(ioaddr, 34); | 1016 | if (lp->phymask & (1 << j)) { |
| 1017 | for (i=0; i<PCNET32_REGS_PER_PHY; i++) { | ||
| 1018 | lp->a.write_bcr(ioaddr, 33, (j << 5) | i); | ||
| 1019 | *buff++ = lp->a.read_bcr(ioaddr, 34); | ||
| 1020 | } | ||
| 1021 | } | ||
| 1004 | } | 1022 | } |
| 1005 | } | 1023 | } |
| 1006 | 1024 | ||
| @@ -1009,10 +1027,6 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
| 1009 | a->write_csr(ioaddr, 5, 0x0000); | 1027 | a->write_csr(ioaddr, 5, 0x0000); |
| 1010 | } | 1028 | } |
| 1011 | 1029 | ||
| 1012 | i = buff - (u16 *)ptr; | ||
| 1013 | for (; i < PCNET32_NUM_REGS; i++) | ||
| 1014 | *buff++ = 0; | ||
| 1015 | |||
| 1016 | spin_unlock_irqrestore(&lp->lock, flags); | 1030 | spin_unlock_irqrestore(&lp->lock, flags); |
| 1017 | } | 1031 | } |
| 1018 | 1032 | ||
| @@ -1185,7 +1199,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1185 | if (cards_found < MAX_UNITS && homepna[cards_found]) | 1199 | if (cards_found < MAX_UNITS && homepna[cards_found]) |
| 1186 | media |= 1; /* switch to home wiring mode */ | 1200 | media |= 1; /* switch to home wiring mode */ |
| 1187 | if (pcnet32_debug & NETIF_MSG_PROBE) | 1201 | if (pcnet32_debug & NETIF_MSG_PROBE) |
| 1188 | printk(KERN_DEBUG PFX "media set to %sMbit mode.\n", | 1202 | printk(KERN_DEBUG PFX "media set to %sMbit mode.\n", |
| 1189 | (media & 1) ? "1" : "10"); | 1203 | (media & 1) ? "1" : "10"); |
| 1190 | a->write_bcr(ioaddr, 49, media); | 1204 | a->write_bcr(ioaddr, 49, media); |
| 1191 | break; | 1205 | break; |
| @@ -1401,8 +1415,34 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
| 1401 | } | 1415 | } |
| 1402 | 1416 | ||
| 1403 | /* Set the mii phy_id so that we can query the link state */ | 1417 | /* Set the mii phy_id so that we can query the link state */ |
| 1404 | if (lp->mii) | 1418 | if (lp->mii) { |
| 1419 | /* lp->phycount and lp->phymask are set to 0 by memset above */ | ||
| 1420 | |||
| 1405 | lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f; | 1421 | lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f; |
| 1422 | /* scan for PHYs */ | ||
| 1423 | for (i=0; i<PCNET32_MAX_PHYS; i++) { | ||
| 1424 | unsigned short id1, id2; | ||
| 1425 | |||
| 1426 | id1 = mdio_read(dev, i, MII_PHYSID1); | ||
| 1427 | if (id1 == 0xffff) | ||
| 1428 | continue; | ||
| 1429 | id2 = mdio_read(dev, i, MII_PHYSID2); | ||
| 1430 | if (id2 == 0xffff) | ||
| 1431 | continue; | ||
| 1432 | if (i == 31 && ((chip_version + 1) & 0xfffe) == 0x2624) | ||
| 1433 | continue; /* 79C971 & 79C972 have phantom phy at id 31 */ | ||
| 1434 | lp->phycount++; | ||
| 1435 | lp->phymask |= (1 << i); | ||
| 1436 | lp->mii_if.phy_id = i; | ||
| 1437 | if (pcnet32_debug & NETIF_MSG_PROBE) | ||
| 1438 | printk(KERN_INFO PFX "Found PHY %04x:%04x at address %d.\n", | ||
| 1439 | id1, id2, i); | ||
| 1440 | } | ||
| 1441 | lp->a.write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5); | ||
| 1442 | if (lp->phycount > 1) { | ||
| 1443 | lp->options |= PCNET32_PORT_MII; | ||
| 1444 | } | ||
| 1445 | } | ||
| 1406 | 1446 | ||
| 1407 | init_timer (&lp->watchdog_timer); | 1447 | init_timer (&lp->watchdog_timer); |
| 1408 | lp->watchdog_timer.data = (unsigned long) dev; | 1448 | lp->watchdog_timer.data = (unsigned long) dev; |
| @@ -1625,7 +1665,7 @@ pcnet32_open(struct net_device *dev) | |||
| 1625 | dev->name); | 1665 | dev->name); |
| 1626 | } | 1666 | } |
| 1627 | } | 1667 | } |
| 1628 | { | 1668 | if (lp->phycount < 2) { |
| 1629 | /* | 1669 | /* |
| 1630 | * 24 Jun 2004 according AMD, in order to change the PHY, | 1670 | * 24 Jun 2004 according AMD, in order to change the PHY, |
| 1631 | * DANAS (or DISPM for 79C976) must be set; then select the speed, | 1671 | * DANAS (or DISPM for 79C976) must be set; then select the speed, |
| @@ -1651,6 +1691,62 @@ pcnet32_open(struct net_device *dev) | |||
| 1651 | lp->a.write_bcr(ioaddr, 32, val); | 1691 | lp->a.write_bcr(ioaddr, 32, val); |
| 1652 | } | 1692 | } |
| 1653 | } | 1693 | } |
| 1694 | } else { | ||
| 1695 | int first_phy = -1; | ||
| 1696 | u16 bmcr; | ||
| 1697 | u32 bcr9; | ||
| 1698 | struct ethtool_cmd ecmd; | ||
| 1699 | |||
| 1700 | /* | ||
| 1701 | * There is really no good other way to handle multiple PHYs | ||
| 1702 | * other than turning off all automatics | ||
| 1703 | */ | ||
| 1704 | val = lp->a.read_bcr(ioaddr, 2); | ||
| 1705 | lp->a.write_bcr(ioaddr, 2, val & ~2); | ||
| 1706 | val = lp->a.read_bcr(ioaddr, 32); | ||
| 1707 | lp->a.write_bcr(ioaddr, 32, val & ~(1 << 7)); /* stop MII manager */ | ||
| 1708 | |||
| 1709 | if (!(lp->options & PCNET32_PORT_ASEL)) { | ||
| 1710 | /* setup ecmd */ | ||
| 1711 | ecmd.port = PORT_MII; | ||
| 1712 | ecmd.transceiver = XCVR_INTERNAL; | ||
| 1713 | ecmd.autoneg = AUTONEG_DISABLE; | ||
| 1714 | ecmd.speed = lp->options & PCNET32_PORT_100 ? SPEED_100 : SPEED_10; | ||
| 1715 | bcr9 = lp->a.read_bcr(ioaddr, 9); | ||
| 1716 | |||
| 1717 | if (lp->options & PCNET32_PORT_FD) { | ||
| 1718 | ecmd.duplex = DUPLEX_FULL; | ||
| 1719 | bcr9 |= (1 << 0); | ||
| 1720 | } else { | ||
| 1721 | ecmd.duplex = DUPLEX_HALF; | ||
| 1722 | bcr9 |= ~(1 << 0); | ||
| 1723 | } | ||
| 1724 | lp->a.write_bcr(ioaddr, 9, bcr9); | ||
| 1725 | } | ||
| 1726 | |||
| 1727 | for (i=0; i<PCNET32_MAX_PHYS; i++) { | ||
| 1728 | if (lp->phymask & (1 << i)) { | ||
| 1729 | /* isolate all but the first PHY */ | ||
| 1730 | bmcr = mdio_read(dev, i, MII_BMCR); | ||
| 1731 | if (first_phy == -1) { | ||
| 1732 | first_phy = i; | ||
| 1733 | mdio_write(dev, i, MII_BMCR, bmcr & ~BMCR_ISOLATE); | ||
| 1734 | } else { | ||
| 1735 | mdio_write(dev, i, MII_BMCR, bmcr | BMCR_ISOLATE); | ||
| 1736 | } | ||
| 1737 | /* use mii_ethtool_sset to setup PHY */ | ||
| 1738 | lp->mii_if.phy_id = i; | ||
| 1739 | ecmd.phy_address = i; | ||
| 1740 | if (lp->options & PCNET32_PORT_ASEL) { | ||
| 1741 | mii_ethtool_gset(&lp->mii_if, &ecmd); | ||
| 1742 | ecmd.autoneg = AUTONEG_ENABLE; | ||
| 1743 | } | ||
| 1744 | mii_ethtool_sset(&lp->mii_if, &ecmd); | ||
| 1745 | } | ||
| 1746 | } | ||
| 1747 | lp->mii_if.phy_id = first_phy; | ||
| 1748 | if (netif_msg_link(lp)) | ||
| 1749 | printk(KERN_INFO "%s: Using PHY number %d.\n", dev->name, first_phy); | ||
| 1654 | } | 1750 | } |
| 1655 | 1751 | ||
| 1656 | #ifdef DO_DXSUFLO | 1752 | #ifdef DO_DXSUFLO |
| @@ -1680,11 +1776,9 @@ pcnet32_open(struct net_device *dev) | |||
| 1680 | 1776 | ||
| 1681 | netif_start_queue(dev); | 1777 | netif_start_queue(dev); |
| 1682 | 1778 | ||
| 1683 | /* If we have mii, print the link status and start the watchdog */ | 1779 | /* Print the link status and start the watchdog */ |
| 1684 | if (lp->mii) { | 1780 | pcnet32_check_media (dev, 1); |
| 1685 | mii_check_media (&lp->mii_if, netif_msg_link(lp), 1); | 1781 | mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); |
| 1686 | mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); | ||
| 1687 | } | ||
| 1688 | 1782 | ||
| 1689 | i = 0; | 1783 | i = 0; |
| 1690 | while (i++ < 100) | 1784 | while (i++ < 100) |
| @@ -2430,17 +2524,111 @@ static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
| 2430 | return rc; | 2524 | return rc; |
| 2431 | } | 2525 | } |
| 2432 | 2526 | ||
| 2527 | static int pcnet32_check_otherphy(struct net_device *dev) | ||
| 2528 | { | ||
| 2529 | struct pcnet32_private *lp = dev->priv; | ||
| 2530 | struct mii_if_info mii = lp->mii_if; | ||
| 2531 | u16 bmcr; | ||
| 2532 | int i; | ||
| 2533 | |||
| 2534 | for (i = 0; i < PCNET32_MAX_PHYS; i++) { | ||
| 2535 | if (i == lp->mii_if.phy_id) | ||
| 2536 | continue; /* skip active phy */ | ||
| 2537 | if (lp->phymask & (1 << i)) { | ||
| 2538 | mii.phy_id = i; | ||
| 2539 | if (mii_link_ok(&mii)) { | ||
| 2540 | /* found PHY with active link */ | ||
| 2541 | if (netif_msg_link(lp)) | ||
| 2542 | printk(KERN_INFO "%s: Using PHY number %d.\n", dev->name, i); | ||
| 2543 | |||
| 2544 | /* isolate inactive phy */ | ||
| 2545 | bmcr = mdio_read(dev, lp->mii_if.phy_id, MII_BMCR); | ||
| 2546 | mdio_write(dev, lp->mii_if.phy_id, MII_BMCR, bmcr | BMCR_ISOLATE); | ||
| 2547 | |||
| 2548 | /* de-isolate new phy */ | ||
| 2549 | bmcr = mdio_read(dev, i, MII_BMCR); | ||
| 2550 | mdio_write(dev, i, MII_BMCR, bmcr & ~BMCR_ISOLATE); | ||
| 2551 | |||
| 2552 | /* set new phy address */ | ||
| 2553 | lp->mii_if.phy_id = i; | ||
| 2554 | return 1; | ||
| 2555 | } | ||
| 2556 | } | ||
| 2557 | } | ||
| 2558 | return 0; | ||
| 2559 | } | ||
| 2560 | |||
| 2561 | /* | ||
| 2562 | * Show the status of the media. Similar to mii_check_media however it | ||
| 2563 | * correctly shows the link speed for all (tested) pcnet32 variants. | ||
| 2564 | * Devices with no mii just report link state without speed. | ||
| 2565 | * | ||
| 2566 | * Caller is assumed to hold and release the lp->lock. | ||
| 2567 | */ | ||
| 2568 | |||
| 2569 | static void pcnet32_check_media(struct net_device *dev, int verbose) | ||
| 2570 | { | ||
| 2571 | struct pcnet32_private *lp = dev->priv; | ||
| 2572 | int curr_link; | ||
| 2573 | int prev_link = netif_carrier_ok(dev) ? 1 : 0; | ||
| 2574 | u32 bcr9; | ||
| 2575 | |||
| 2576 | if (lp->mii) { | ||
| 2577 | curr_link = mii_link_ok(&lp->mii_if); | ||
| 2578 | } else { | ||
| 2579 | ulong ioaddr = dev->base_addr; /* card base I/O address */ | ||
| 2580 | curr_link = (lp->a.read_bcr(ioaddr, 4) != 0xc0); | ||
| 2581 | } | ||
| 2582 | if (!curr_link) { | ||
| 2583 | if (prev_link || verbose) { | ||
| 2584 | netif_carrier_off(dev); | ||
| 2585 | if (netif_msg_link(lp)) | ||
| 2586 | printk(KERN_INFO "%s: link down\n", dev->name); | ||
| 2587 | } | ||
| 2588 | if (lp->phycount > 1) { | ||
| 2589 | curr_link = pcnet32_check_otherphy(dev); | ||
| 2590 | prev_link = 0; | ||
| 2591 | } | ||
| 2592 | } else if (verbose || !prev_link) { | ||
| 2593 | netif_carrier_on(dev); | ||
| 2594 | if (lp->mii) { | ||
| 2595 | if (netif_msg_link(lp)) { | ||
| 2596 | struct ethtool_cmd ecmd; | ||
| 2597 | mii_ethtool_gset(&lp->mii_if, &ecmd); | ||
| 2598 | printk(KERN_INFO "%s: link up, %sMbps, %s-duplex\n", | ||
| 2599 | dev->name, | ||
| 2600 | (ecmd.speed == SPEED_100) ? "100" : "10", | ||
| 2601 | (ecmd.duplex == DUPLEX_FULL) ? "full" : "half"); | ||
| 2602 | } | ||
| 2603 | bcr9 = lp->a.read_bcr(dev->base_addr, 9); | ||
| 2604 | if ((bcr9 & (1 << 0)) != lp->mii_if.full_duplex) { | ||
| 2605 | if (lp->mii_if.full_duplex) | ||
| 2606 | bcr9 |= (1 << 0); | ||
| 2607 | else | ||
| 2608 | bcr9 &= ~(1 << 0); | ||
| 2609 | lp->a.write_bcr(dev->base_addr, 9, bcr9); | ||
| 2610 | } | ||
| 2611 | } else { | ||
| 2612 | if (netif_msg_link(lp)) | ||
| 2613 | printk(KERN_INFO "%s: link up\n", dev->name); | ||
| 2614 | } | ||
| 2615 | } | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | /* | ||
| 2619 | * Check for loss of link and link establishment. | ||
| 2620 | * Can not use mii_check_media because it does nothing if mode is forced. | ||
| 2621 | */ | ||
| 2622 | |||
| 2433 | static void pcnet32_watchdog(struct net_device *dev) | 2623 | static void pcnet32_watchdog(struct net_device *dev) |
| 2434 | { | 2624 | { |
| 2435 | struct pcnet32_private *lp = dev->priv; | 2625 | struct pcnet32_private *lp = dev->priv; |
| 2436 | unsigned long flags; | 2626 | unsigned long flags; |
| 2437 | 2627 | ||
| 2438 | /* Print the link status if it has changed */ | 2628 | /* Print the link status if it has changed */ |
| 2439 | if (lp->mii) { | 2629 | spin_lock_irqsave(&lp->lock, flags); |
| 2440 | spin_lock_irqsave(&lp->lock, flags); | 2630 | pcnet32_check_media(dev, 0); |
| 2441 | mii_check_media (&lp->mii_if, netif_msg_link(lp), 0); | 2631 | spin_unlock_irqrestore(&lp->lock, flags); |
| 2442 | spin_unlock_irqrestore(&lp->lock, flags); | ||
| 2443 | } | ||
| 2444 | 2632 | ||
| 2445 | mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); | 2633 | mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); |
| 2446 | } | 2634 | } |
