|
@@ -568,6 +568,8 @@ struct netdev_private {
|
|
|
u32 intr_status;
|
|
|
/* Do not touch the nic registers */
|
|
|
int hands_off;
|
|
|
+ /* Don't pay attention to the reported link state. */
|
|
|
+ int ignore_phy;
|
|
|
/* external phy that is used: only valid if dev->if_port != PORT_TP */
|
|
|
int mii;
|
|
|
int phy_addr_external;
|
|
@@ -696,7 +698,10 @@ static void __devinit natsemi_init_media (struct net_device *dev)
|
|
|
struct netdev_private *np = netdev_priv(dev);
|
|
|
u32 tmp;
|
|
|
|
|
|
- netif_carrier_off(dev);
|
|
|
+ if (np->ignore_phy)
|
|
|
+ netif_carrier_on(dev);
|
|
|
+ else
|
|
|
+ netif_carrier_off(dev);
|
|
|
|
|
|
/* get the initial settings from hardware */
|
|
|
tmp = mdio_read(dev, MII_BMCR);
|
|
@@ -806,8 +811,10 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
|
|
|
np->hands_off = 0;
|
|
|
np->intr_status = 0;
|
|
|
np->eeprom_size = natsemi_pci_info[chip_idx].eeprom_size;
|
|
|
+ np->ignore_phy = 0;
|
|
|
|
|
|
/* Initial port:
|
|
|
+ * - If configured to ignore the PHY set up for external.
|
|
|
* - If the nic was configured to use an external phy and if find_mii
|
|
|
* finds a phy: use external port, first phy that replies.
|
|
|
* - Otherwise: internal port.
|
|
@@ -815,7 +822,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
|
|
|
* The address would be used to access a phy over the mii bus, but
|
|
|
* the internal phy is accessed through mapped registers.
|
|
|
*/
|
|
|
- if (readl(ioaddr + ChipConfig) & CfgExtPhy)
|
|
|
+ if (np->ignore_phy || readl(ioaddr + ChipConfig) & CfgExtPhy)
|
|
|
dev->if_port = PORT_MII;
|
|
|
else
|
|
|
dev->if_port = PORT_TP;
|
|
@@ -825,7 +832,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
|
|
|
|
|
|
if (dev->if_port != PORT_TP) {
|
|
|
np->phy_addr_external = find_mii(dev);
|
|
|
- if (np->phy_addr_external == PHY_ADDR_NONE) {
|
|
|
+ /* If we're ignoring the PHY it doesn't matter if we can't
|
|
|
+ * find one. */
|
|
|
+ if (!np->ignore_phy && np->phy_addr_external == PHY_ADDR_NONE) {
|
|
|
dev->if_port = PORT_TP;
|
|
|
np->phy_addr_external = PHY_ADDR_INTERNAL;
|
|
|
}
|
|
@@ -891,6 +900,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
|
|
|
printk("%02x, IRQ %d", dev->dev_addr[i], irq);
|
|
|
if (dev->if_port == PORT_TP)
|
|
|
printk(", port TP.\n");
|
|
|
+ else if (np->ignore_phy)
|
|
|
+ printk(", port MII, ignoring PHY\n");
|
|
|
else
|
|
|
printk(", port MII, phy ad %d.\n", np->phy_addr_external);
|
|
|
}
|
|
@@ -1571,9 +1582,13 @@ static void check_link(struct net_device *dev)
|
|
|
{
|
|
|
struct netdev_private *np = netdev_priv(dev);
|
|
|
void __iomem * ioaddr = ns_ioaddr(dev);
|
|
|
- int duplex;
|
|
|
+ int duplex = np->duplex;
|
|
|
u16 bmsr;
|
|
|
|
|
|
+ /* If we are ignoring the PHY then don't try reading it. */
|
|
|
+ if (np->ignore_phy)
|
|
|
+ goto propagate_state;
|
|
|
+
|
|
|
/* The link status field is latched: it remains low after a temporary
|
|
|
* link failure until it's read. We need the current link status,
|
|
|
* thus read twice.
|
|
@@ -1585,7 +1600,7 @@ static void check_link(struct net_device *dev)
|
|
|
if (netif_carrier_ok(dev)) {
|
|
|
if (netif_msg_link(np))
|
|
|
printk(KERN_NOTICE "%s: link down.\n",
|
|
|
- dev->name);
|
|
|
+ dev->name);
|
|
|
netif_carrier_off(dev);
|
|
|
undo_cable_magic(dev);
|
|
|
}
|
|
@@ -1609,6 +1624,7 @@ static void check_link(struct net_device *dev)
|
|
|
duplex = 1;
|
|
|
}
|
|
|
|
|
|
+propagate_state:
|
|
|
/* if duplex is set then bit 28 must be set, too */
|
|
|
if (duplex ^ !!(np->rx_config & RxAcceptTx)) {
|
|
|
if (netif_msg_link(np))
|
|
@@ -2818,6 +2834,15 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * If we're ignoring the PHY then autoneg and the internal
|
|
|
+ * transciever are really not going to work so don't let the
|
|
|
+ * user select them.
|
|
|
+ */
|
|
|
+ if (np->ignore_phy && (ecmd->autoneg == AUTONEG_ENABLE ||
|
|
|
+ ecmd->port == PORT_TP))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
/*
|
|
|
* maxtxpkt, maxrxpkt: ignored for now.
|
|
|
*
|