MII_EN_SCRM = 0x0004, /* enable scrambler (tp) */
};
+enum {
+ NATSEMI_FLAG_IGNORE_PHY = 0x1,
+};
/* array of board data directly indexed by pci_tbl[x].driver_data */
static const struct {
unsigned long flags;
unsigned int eeprom_size;
} natsemi_pci_info[] __devinitdata = {
+ { "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 },
{ "NatSemi DP8381[56]", 0, 24 },
};
static const struct pci_device_id natsemi_pci_tbl[] __devinitdata = {
+ { PCI_VENDOR_ID_NS, 0x0020, 0x12d9, 0x000c, 0, 0, 0 },
{ PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ } /* terminate list */
};
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;
static void reinit_ring(struct net_device *dev);
static void init_registers(struct net_device *dev);
static int start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
static void netdev_error(struct net_device *dev, int intr_status);
static int natsemi_poll(struct net_device *dev, int *budget);
static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do);
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);
np->hands_off = 0;
np->intr_status = 0;
np->eeprom_size = natsemi_pci_info[chip_idx].eeprom_size;
+ if (natsemi_pci_info[chip_idx].flags & NATSEMI_FLAG_IGNORE_PHY)
+ np->ignore_phy = 1;
+ else
+ 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.
* 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;
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;
}
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);
}
{
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.
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);
}
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))
/* The interrupt handler doesn't actually handle interrupts itself, it
* schedules a NAPI poll if there is anything to do. */
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t intr_handler(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct netdev_private *np = netdev_priv(dev);
static void natsemi_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
- intr_handler(dev->irq, dev, NULL);
+ intr_handler(dev->irq, dev);
enable_irq(dev->irq);
}
#endif
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.
*