/* checks that attached switch is 5325/5352/5354/5356/5357/53115/5301x */ static int robo_vlan535x(robo_t *robo, u32 phyid) { #ifdef BCM5301X if ((robo_read32(robo, ROBO_MGMT_PAGE, ROBO_DEVICE_ID) & 0xfffffff0) == 0x53010) return 5; #else /* set vlan access id to 15 and read it back */ u16 val16 = 15; robo_write16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350, val16); /* 5365 will refuse this as it does not have this reg */ if (robo_read16(robo, ROBO_VLAN_PAGE, ROBO_VLAN_TABLE_ACCESS_5350) != val16) return 0; /* gigabit ? */ if (robo->et != 1 && (mdio_read(robo, 0, ROBO_MII_STAT) & 0x0100)) robo->gmii = ((mdio_read(robo, 0, 0x0f) & 0xf000) != 0); /* 53115 ? */ if (robo->gmii && robo_read32(robo, ROBO_STAT_PAGE, ROBO_LSA_IM_PORT) != 0) { robo_write16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395, val16); robo_write16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395, (1 << 7) /* start */ | 1 /* read */); if (robo_read16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_ACCESS_5395) == 1 && robo_read16(robo, ROBO_ARLIO_PAGE, ROBO_VTBL_INDX_5395) == val16) return 4; } /* dirty trick for 5356/5357 */ if ((phyid & 0xfff0ffff ) == 0x5da00362 || (phyid & 0xfff0ffff ) == 0x5e000362) return 3; /* 5325/5352/5354*/ return 1; #endif }
static int mdio_probe(struct meth_private *priv) { int i; unsigned long p2, p3, flags; /* check if phy is detected already */ if(priv->phy_addr>=0&&priv->phy_addr<32) return 0; spin_lock_irqsave(&priv->meth_lock, flags); for (i=0;i<32;++i){ priv->phy_addr=i; p2=mdio_read(priv,2); p3=mdio_read(priv,3); #if MFE_DEBUG>=2 switch ((p2<<12)|(p3>>4)){ case PHY_QS6612X: DPRINTK("PHY is QS6612X\n"); break; case PHY_ICS1889: DPRINTK("PHY is ICS1889\n"); break; case PHY_ICS1890: DPRINTK("PHY is ICS1890\n"); break; case PHY_DP83840: DPRINTK("PHY is DP83840\n"); break; } #endif if(p2!=0xffff&&p2!=0x0000){ DPRINTK("PHY code: %x\n",(p2<<12)|(p3>>4)); break; } }
static __u32 robo_read32(__u8 page, __u8 reg) { robo_reg(page, reg, REG_MII_ADDR_READ); return mdio_read(robo.phy_addr, REG_MII_DATA0) + (mdio_read(robo.phy_addr, REG_MII_DATA0 + 1) << 16); }
static __u32 robo_read32(__u8 page, __u8 reg) { robo_reg(page, reg, REG_MII_ADDR_READ); return mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0) + (mdio_read(ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16); }
int am79c874_init(struct net_device *dev, int phy_addr) { s16 data; /* 79c874 has quit resembled bit assignments to BCM5201 */ if (au1000_debug > 4) printk("am79c847_init\n"); /* Stop auto-negotiation */ data = mdio_read(dev, phy_addr, MII_CONTROL); mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO); /* Set advertisement to 10/100 and Half/Full duplex * (full capabilities) */ data = mdio_read(dev, phy_addr, MII_ANADV); data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T; mdio_write(dev, phy_addr, MII_ANADV, data); /* Restart auto-negotiation */ data = mdio_read(dev, phy_addr, MII_CONTROL); data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO; mdio_write(dev, phy_addr, MII_CONTROL, data); if (au1000_debug > 4) dump_mii(dev, phy_addr); return 0; }
int bcm_5201_init(struct net_device *dev, int phy_addr) { s16 data; /* Stop auto-negotiation */ //printk("bcm_5201_init\n"); data = mdio_read(dev, phy_addr, MII_CONTROL); mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO); /* Set advertisement to 10/100 and Half/Full duplex * (full capabilities) */ data = mdio_read(dev, phy_addr, MII_ANADV); data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T; mdio_write(dev, phy_addr, MII_ANADV, data); /* Restart auto-negotiation */ data = mdio_read(dev, phy_addr, MII_CONTROL); data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO; mdio_write(dev, phy_addr, MII_CONTROL, data); /* Enable TX LED instead of FDX */ data = mdio_read(dev, phy_addr, MII_INT); data &= ~MII_FDX_LED; mdio_write(dev, phy_addr, MII_INT, data); if (au1000_debug > 4) dump_mii(dev, phy_addr); return 0; }
int show_basic_mii(int sock, int phy_id) { char buf[100]; int i, mii_val[32]; unsigned bmcr, bmsr, advert, lkpar, bmcr2, lpa2; /* Some bits in the BMSR are latched, but we can't rely on being the only reader, so only the current values are meaningful */ mdio_read(sock, MII_BMSR); for (i = 0; i < ((verbose > 1) ? 32 : MII_BASIC_MAX); i++) mii_val[i] = mdio_read(sock, i); if (mii_val[MII_BMCR] == 0xffff || mii_val[MII_BMSR] == 0x0000) { fprintf(stderr, " No MII transceiver present!.\n"); return -1; } /* Descriptive rename. */ bmcr = mii_val[MII_BMCR]; bmsr = mii_val[MII_BMSR]; advert = mii_val[MII_ANAR]; lkpar = mii_val[MII_ANLPAR]; bmcr2 = mii_val[MII_CTRL1000]; lpa2 = mii_val[MII_STAT1000]; sprintf(buf, "%s: ", ifr.ifr_name); if (bmcr & MII_BMCR_AN_ENA) { if (bmsr & MII_BMSR_AN_COMPLETE) { if (advert & lkpar) { strcat(buf, (lkpar & MII_AN_ACK) ? "negotiated" : "no autonegotiation,"); strcat(buf, media_list(advert & lkpar, bmcr2 & lpa2>>2, 1)); strcat(buf, ", "); } else { strcat(buf, "autonegotiation failed, "); } } else if (bmcr & MII_BMCR_RESTART) {
static int aq100x_intr_clear(struct cphy *phy) { unsigned int v; mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &v); mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &v); return 0; }
// Enables loopback on the Ethernet PHY. // NOTE: Software reset will disable loopback. void eth_enable_loopback (void) { // Set to 100Mbps int x = mdio_read (ETH_PHY_ADR, 20) & ~(7 << 4); mdio_write (ETH_PHY_ADR, 20, x | (5 << 4)); eth_soft_reset (); // Loopback mdio_write (ETH_PHY_ADR, 0, mdio_read (ETH_PHY_ADR, 0) | (1 << 14)); }
static void netdev_error(struct net_device *dev, int intr_status) { long ioaddr = dev->base_addr; struct netdev_private *np = dev->priv; u16 mii_reg0, mii_reg4, mii_reg5; int speed; if (intr_status & IntrDrvRqst) { /* Stop the down counter and turn interrupts back on. */ if (debug > 1) printk("%s: Turning interrupts back on.\n", dev->name); writew(0, ioaddr + IntrEnable); writew(0, ioaddr + DownCounter); writew(IntrRxDone | IntrRxDMADone | IntrPCIErr | IntrDrvRqst | IntrTxDone | StatsMax | LinkChange, ioaddr + IntrEnable); /* Ack buggy InRequest */ writew (IntrDrvRqst, ioaddr + IntrStatus); } if (intr_status & LinkChange) { if (np->an_enable) { mii_reg4 = mdio_read (dev, np->phys[0], 4); mii_reg5= mdio_read (dev, np->phys[0], 5); mii_reg4 &= mii_reg5; printk (KERN_INFO "%s: Link changed: ", dev->name); if (mii_reg4 & 0x0100) printk ("100Mbps, full duplex\n"); else if (mii_reg4 & 0x0080) printk ("100Mbps, half duplex\n"); else if (mii_reg4 & 0x0040) printk ("10Mbps, full duplex\n"); else if (mii_reg4 & 0x0020) printk ("10Mbps, half duplex\n"); else printk ("\n"); } else { mii_reg0 = mdio_read (dev, np->phys[0], 0); speed = (mii_reg0 & 0x2000) ? 100 : 10; printk (KERN_INFO "%s: Link changed: %dMbps ,", dev->name, speed); printk ("%s duplex.\n", (mii_reg0 & 0x0100) ? "full" : "half"); } check_duplex (dev); } if (intr_status & StatsMax) { get_stats(dev); } if (intr_status & IntrPCIErr) { printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", dev->name, intr_status); /* We must do a global reset of DMA to continue. */ } }
static void dump_mii(struct net_device *dev, int phy_id) { int i, val; for (i = 0; i < 7; i++) { if ((val = mdio_read(dev, phy_id, i)) >= 0) printk("%s: MII Reg %d=%x\n", dev->name, i, val); } for (i = 16; i < 25; i++) { if ((val = mdio_read(dev, phy_id, i)) >= 0) printk("%s: MII Reg %d=%x\n", dev->name, i, val); } }
static int aq100x_intr_handler(struct cphy *phy) { int err; unsigned int cause, v; err = mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &cause); if (err) return err; /* Read (and reset) the latching version of the status */ mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &v); return cphy_cause_link_change; }
static u32 robo_read32(robo_t *robo, u8 page, u8 reg) { #ifdef BCM5301X u32 val32; robo_read(robo, page, reg, (u16 *) &val32, 2); return val32; #else robo_reg(robo, page, reg, REG_MII_ADDR_READ); return ((u32 )mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0)) | ((u32 )mdio_read(robo, ROBO_PHY_ADDR, REG_MII_DATA0 + 1) << 16); #endif }
static int mv88x201x_interrupt_clear(struct cphy *cphy) { u32 elmer; u32 val; #ifdef MV88x2010_LINK_STATUS_BUGS /* Required to read twice before clear takes affect. */ mdio_read(cphy, 0x1, 0x9003, &val); mdio_read(cphy, 0x1, 0x9004, &val); mdio_read(cphy, 0x1, 0x9005, &val); /* Read this register after the others above it else * the register doesn't clear correctly. */ mdio_read(cphy, 0x1, 0x1, &val); #endif /* Clear link status. */ mdio_read(cphy, 0x1, 0x1, &val); /* Clear PHY LASI interrupts. */ mdio_read(cphy, 0x1, 0x9005, &val); #ifdef MV88x2010_LINK_STATUS_BUGS /* Do it again. */ mdio_read(cphy, 0x1, 0x9003, &val); mdio_read(cphy, 0x1, 0x9004, &val); #endif /* Clear Marvell interrupts through Elmer0. */ t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); elmer |= ELMER0_GP_BIT6; t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); return 0; }
/* on each timer ticks we check two things, Link Status (ON/OFF) and Link Mode (10/100/Full/Half) */ static void sis900_timer(unsigned long data) { struct device *net_dev = (struct device *)data; struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; struct mii_phy *mii_phy = sis_priv->mii; static int next_tick = 5*HZ; u16 status; status = mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS); /* current mii phy is failed to link, try another one */ while (!(status & MII_STAT_LINK)) { if (mii_phy->next == NULL) { if (sis_priv->LinkOn) { /* link stat change from ON to OFF */ next_tick = HZ; sis_priv->LinkOn = FALSE; printk(KERN_INFO "%s: Media Link Off\n", net_dev->name); } sis_priv->timer.expires = jiffies + next_tick; add_timer(&sis_priv->timer); return; } mii_phy = mii_phy->next; status = mdio_read(net_dev, mii_phy->phy_addr, MII_STATUS); } if (!sis_priv->LinkOn) { /* link stat change forn OFF to ON, read and report link mode */ sis_priv->LinkOn = TRUE; next_tick = 5*HZ; /* change what cur_phy means */ if (mii_phy->phy_addr != sis_priv->cur_phy) { printk(KERN_INFO "%s: Changing transceiver to %s\n", net_dev->name, mii_phy->chip_info->name); status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL); mdio_write(net_dev, sis_priv->cur_phy, MII_CONTROL, status | MII_CNTL_ISOLATE); status = mdio_read(net_dev, mii_phy->phy_addr, MII_CONTROL); mdio_write(net_dev, mii_phy->phy_addr, MII_CONTROL, status & ~MII_CNTL_ISOLATE); sis_priv->cur_phy = mii_phy->phy_addr; } sis900_check_mode(net_dev, mii_phy); } sis_priv->timer.expires = jiffies + next_tick; add_timer(&sis_priv->timer); }
static void rtl8169_phy_timer(unsigned long __opaque) { struct net_device *dev = (struct net_device *)__opaque; struct rtl8169_private *tp = dev->priv; struct timer_list *timer = &tp->timer; void *ioaddr = tp->mmio_addr; assert(tp->mac_version > RTL_GIGA_MAC_VER_B); assert(tp->phy_version < RTL_GIGA_PHY_VER_G); if (RTL_R8(PHYstatus) & LinkStatus) tp->phy_link_down_cnt = 0; else { tp->phy_link_down_cnt++; if (tp->phy_link_down_cnt >= 12) { int reg; // If link on 1000, perform phy reset. reg = mdio_read(ioaddr, PHY_1000_CTRL_REG); if (reg & PHY_Cap_1000_Full) rtl8169_hw_phy_reset(dev); tp->phy_link_down_cnt = 0; } } mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT); }
static void rtl_hw_start(struct dev *dev) { struct nic *tp = (struct nic *) dev->privdata; long ioaddr = tp->iobase; int i; // Soft reset the chip outp(ioaddr + ChipCmd, CmdReset); // Check that the chip has finished the reset for (i = 1000; i > 0; i--) { if ((inp(ioaddr + ChipCmd) & CmdReset) == 0) break; } // Restore our idea of the MAC address outp(ioaddr + Cfg9346, 0xC0); outpd(ioaddr + MAC0 + 0, *(unsigned long *)(tp->hwaddr.addr + 0)); outpd(ioaddr + MAC0 + 4, *(unsigned long *)(tp->hwaddr.addr + 4)); // Hmmm, do these belong here? tp->cur_rx = 0; // Must enable Tx/Rx before setting transfer thresholds! outp(ioaddr + ChipCmd, CmdRxEnb | CmdTxEnb); outpd(ioaddr + RxConfig, tp->rx_config); // Check this value: the documentation contradicts ifself. Is the // IFG correct with bit 28:27 zero, or with |0x03000000 ? outpd(ioaddr + TxConfig, (TX_DMA_BURST << 8)); // This is check_duplex() if (tp->phys[0] >= 0 || (tp->flags & HAS_MII_XCVR)) { unsigned short mii_reg5 = mdio_read(dev, tp->phys[0], 5); if (mii_reg5 != 0xffff) { if ((mii_reg5 & 0x0100) == 0x0100 || (mii_reg5 & 0x00C0) == 0x0040) { tp->full_duplex = 1; } } kprintf(KERN_INFO "%s: Setting %s%s-duplex based on auto-negotiated partner ability %4.4x\n", dev->name, mii_reg5 == 0 ? "" : (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ", tp->full_duplex ? "full" : "half", mii_reg5); } if (tp->flags & HAS_MII_XCVR) { // RTL8129 chip outp(ioaddr + Config1, tp->full_duplex ? 0x60 : 0x20); } outp(ioaddr + Cfg9346, 0x00); outpd(ioaddr + RxBuf, virt2phys(tp->rx_ring)); // Start the chip's Tx and Rx process outpd(ioaddr + RxMissed, 0); rtl8139_set_rx_mode(dev); outp(ioaddr + ChipCmd, CmdRxEnb | CmdTxEnb); // Enable all known interrupts by setting the interrupt mask outpw(ioaddr + IntrMask, PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK); }
static int mv88e1xxx_intr_clear(struct cphy *cphy) { u32 val; /* Clear PHY interrupts by reading the register. */ return mdio_read(cphy, 0, MV88E1XXX_INTR_STATUS, &val); }
static void check_duplex(struct nic *nic) { int mii_lpa = mdio_read(nic, sdc->phys[0], MII_LPA); int negotiated = mii_lpa & sdc->mii_if.advertising; int duplex; /* Force media */ if (!sdc->an_enable || mii_lpa == 0xffff) { if (sdc->mii_if.full_duplex) outw(inw(BASE + MACCtrl0) | EnbFullDuplex, BASE + MACCtrl0); return; } /* Autonegotiation */ duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; if (sdc->mii_if.full_duplex != duplex) { sdc->mii_if.full_duplex = duplex; DBG ("%s: Setting %s-duplex based on MII #%d " "negotiated capability %4.4x.\n", sdc->nic_name, duplex ? "full" : "half", sdc->phys[0], negotiated ); outw(inw(BASE + MACCtrl0) | duplex ? 0x20 : 0, BASE + MACCtrl0); } }
static int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_ok, int *speed, int *duplex, int *fc) { u32 status; int sp = -1, dplx = -1, pause = 0; mdio_read(cphy, 0, MV88E1XXX_SPECIFIC_STATUS, &status); if ((status & V_PSSR_STATUS_RESOLVED) != 0) { if (status & V_PSSR_RX_PAUSE) pause |= PAUSE_RX; if (status & V_PSSR_TX_PAUSE) pause |= PAUSE_TX; dplx = (status & V_PSSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; sp = G_PSSR_SPEED(status); if (sp == 0) sp = SPEED_10; else if (sp == 1) sp = SPEED_100; else sp = SPEED_1000; } if (link_ok) *link_ok = (status & V_PSSR_LINK) != 0; if (speed) *speed = sp; if (duplex) *duplex = dplx; if (fc) *fc = pause; return 0; }
int t3_vsc8211_fifo_depth(adapter_t *adap, unsigned int mtu, int port) { /* TX FIFO Depth set bits 9:7 to 100 (IEEE mode) */ unsigned int val = 4; unsigned int currentregval; unsigned int regval; int err; /* Retrieve the port info structure from adater_t */ struct port_info *portinfo = adap2pinfo(adap, port); /* What phy is this */ struct cphy *phy = &portinfo->phy; /* Read the current value of the PHY control Register */ err = mdio_read(phy, 0, VSC8211_PHY_CTRL, ¤tregval); if (err) return err; /* IEEE mode supports up to 1518 bytes */ /* mtu does not contain the header + FCS (18 bytes) */ if (mtu > 1500) /* * If using a packet size > 1500 set TX FIFO Depth bits * 9:7 to 011 (Jumbo packet mode) */ val = 3; regval = V_VSC8211_TXFIFODEPTH(val) | V_VSC8211_RXFIFODEPTH(val) | (currentregval & ~V_VSC8211_TXFIFODEPTH(M_VSC8211_TXFIFODEPTH) & ~V_VSC8211_RXFIFODEPTH(M_VSC8211_RXFIFODEPTH)); return mdio_write(phy, 0, VSC8211_PHY_CTRL, regval); }
static int vsc8211_intr_clear(struct cphy *cphy) { u32 val; /* Clear PHY interrupts by reading the register. */ return mdio_read(cphy, 0, VSC8211_INTR_STATUS, &val); }
static void sis900_read_mode(struct device *net_dev, int phy_addr, int *speed, int *duplex) { int i = 0; u32 status; /* STSOUT register is Latched on Transition, read operation updates it */ while (i++ < 2) status = mdio_read(net_dev, phy_addr, MII_STSOUT); if (status & MII_STSOUT_SPD) *speed = HW_SPEED_100_MBPS; else *speed = HW_SPEED_10_MBPS; if (status & MII_STSOUT_DPLX) *duplex = FDX_CAPABLE_FULL_SELECTED; else *duplex = FDX_CAPABLE_HALF_SELECTED; if (status & MII_STSOUT_LINK_FAIL) printk(KERN_INFO "%s: Media Link Off\n", net_dev->name); else printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", net_dev->name, *speed == HW_SPEED_100_MBPS ? "100mbps" : "10mbps", *duplex == FDX_CAPABLE_FULL_SELECTED ? "full" : "half"); }
static void speedo_show_state(struct dev *dev) { struct nic *sp = (struct nic *) dev->privdata; long ioaddr = sp->iobase; int phy_num = sp->phy[0] & 0x1f; unsigned int i; // Print a few items for debugging kprintf("%s: Tx ring dump, Tx queue %d / %d:\n", dev->name, sp->cur_tx, sp->dirty_tx); for (i = 0; i < TX_RING_SIZE; i++) { kprintf("%s: %c%c%d %8.8x\n", dev->name, i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ', i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ', i, sp->tx_ring[i].status); } kprintf("%s: Rx ring dump (next to receive into %d)\n", dev->name, sp->cur_rx); for (i = 0; i < RX_RING_SIZE; i++) { kprintf(" Rx ring entry %d %8.8x\n", i, sp->rx_ringp[i]->status); } for (i = 0; i < 16; i++) { if (i == 6) i = 21; kprintf(" PHY index %d register %d is %4.4x.\n", phy_num, i, mdio_read(ioaddr, phy_num, i)); } }
static void check_duplex(struct net_device *dev) { struct netdev_private *np = dev->priv; long ioaddr = dev->base_addr; int mii_reg5 = mdio_read(dev, np->phys[0], 5); int negotiated = mii_reg5 & np->advertising; int duplex; /* Force media */ if (!np->an_enable || mii_reg5 == 0xffff) { if (np->full_duplex) writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex, ioaddr + MACCtrl0); return; } /* Autonegotiation */ duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; if (np->full_duplex != duplex) { np->full_duplex = duplex; if (debug) printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d " "negotiated capability %4.4x.\n", dev->name, duplex ? "full" : "half", np->phys[0], negotiated); writew(duplex ? 0x20 : 0, ioaddr + MACCtrl0); } }
static void netdev_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct am_net_private *np = netdev_priv(dev); unsigned long ioaddr = np->base_addr; static int error_num = 0; int val; if (debug > 2) printk(KERN_INFO "%s: Media selection timer tick, mac status %8.8x \n", dev->name, ioread32(ioaddr + ETH_DMA_5_Status)); if (!phy_linked(np)) { //unlink ..... error_num++; if (error_num > 30) { error_num = 0; spin_lock_irq(&np->lock); val = (1 << 14) | (7 << 5) | np->phys[0]; mdio_write(dev, np->phys[0], 18, val); // Auto negotiation restart val = mdio_read(dev, np->phys[0], MII_BMCR); #ifdef PHY_LOOPBACK_TEST val = 1<<14 | 1<<8 | 1<<13;//100M,full,seting it as #else val |= BMCR_ANENABLE | BMCR_ANRESTART; #endif mdio_write(dev, np->phys[0], MII_BMCR, val); spin_unlock_irq(&np->lock); } np->timer.expires = jiffies + 1 * HZ; netif_stop_queue(dev); netif_carrier_off(dev); np->phy_set[0] = 0; } else { //linked val = mdio_read(dev, np->phys[0], 1); if (np->phy_set[0] != val) { np->phy_set[0] =val; phy_auto_negotiation_set(np); } error_num = 0; netif_carrier_on(dev); netif_start_queue(dev); np->timer.expires = jiffies + 1 * HZ; } add_timer(&np->timer); }
static void rtl8129_timer(unsigned long data) { struct device *dev = (struct device *)data; struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv; long ioaddr = dev->base_addr; int next_tick = 60*HZ; int mii_reg5 = mdio_read(dev, tp->phys[0], 5); if (! tp->duplex_lock && mii_reg5 != 0xffff) { int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040; if (tp->full_duplex != duplex) { tp->full_duplex = duplex; printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link" " partner ability of %4.4x.\n", dev->name, tp->full_duplex ? "full" : "half", tp->phys[0], mii_reg5); outb(0xC0, ioaddr + Cfg9346); outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1); outb(0x00, ioaddr + Cfg9346); } } /* Check for bogusness. */ if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) { int status = inw(ioaddr + IntrStatus); if (status & (TxOK | RxOK)) { /* Double check */ printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n", dev->name, status); rtl8129_interrupt(dev->irq, dev, 0); } } if (dev->tbusy && jiffies - dev->trans_start >= 2*TX_TIMEOUT) rtl8129_tx_timeout(dev); #if 0 if (tp->twistie) { unsigned int CSCRval = inw(ioaddr + CSCR); /* Read link status. */ if (tp->twistie == 1) { if (CSCRval & CSCR_LinkOKBit) { outw(CSCR_LinkDownOffCmd, ioaddr + CSCR); tp->twistie = 2; next_tick = HZ/10; } else { outw(CSCR_LinkDownCmd, ioaddr + CSCR); outl(FIFOTMS_default,ioaddr + FIFOTMS); outl(PARA78_default ,ioaddr + PARA78); outl(PARA7c_default ,ioaddr + PARA7c); tp->twistie = 0; } } else if (tp->twistie == 2) { int linkcase = (CSCRval & CSCR_LinkStatusBits) >> 12; int row; if (linkcase >= 0x7000) row = 3; else if (linkcase >= 0x3000) row = 2; else if (linkcase >= 0x1000) row = 1; else row = 0; tp->twistie == row + 3; outw(0,ioaddr+FIFOTMS); outl(param[row][0], ioaddr+PARA7c); tp->twist_cnt = 1; } else {
static int my3126_interrupt_handler(struct cphy *cphy) { u32 val; u16 val16; u16 status; u32 act_count; adapter_t *adapter; adapter = cphy->adapter; if (cphy->count == 50) { mdio_read(cphy, 0x1, 0x1, &val); val16 = (u16) val; status = cphy->bmsr ^ val16; if (status & BMSR_LSTATUS) t1_link_changed(adapter, 0); cphy->bmsr = val16; /* We have only enabled link change interrupts so it must be that */ cphy->count = 0; } t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL), SUNI1x10GEXP_BITMSK_MSTAT_SNAP); t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count); t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val); act_count += val; /* Populate elmer_gpo with the register value */ t1_tpi_read(adapter, A_ELMER0_GPO, &val); cphy->elmer_gpo = val; if ( (val & (1 << 8)) || (val & (1 << 19)) || (cphy->act_count == act_count) || cphy->act_on ) { if (is_T2(adapter)) val |= (1 << 9); else if (t1_is_T1B(adapter)) val |= (1 << 20); cphy->act_on = 0; } else { if (is_T2(adapter)) val &= ~(1 << 9); else if (t1_is_T1B(adapter)) val &= ~(1 << 20); cphy->act_on = 1; } t1_tpi_write(adapter, A_ELMER0_GPO, val); cphy->elmer_gpo = val; cphy->act_count = act_count; cphy->count++; return cphy_cause_link_change; }
static void monitor_status(long ioaddr, int phy_id) { unsigned int baseline_1 = 0x55555555; /* Always show initial status. */ while (1) { unsigned int new_1 = mdio_read(ioaddr, phy_id, 1); if (new_1 != baseline_1) { printf("%-12s 0x%4.4x 0x%4.4x\n", new_1 & 0x04 ? (new_1==0xffff ? "unknown" : "up") : new_1 & 0x20 ? "negotiating" : "down", new_1, mdio_read(ioaddr, phy_id, 5)); fflush(stdout); baseline_1 = new_1; } sleep(1); } }
static int robo_probe(char *devname) { struct ethtool_drvinfo info; int i; __u32 phyid; printk("Probing device %s: ", devname); strcpy(ifr.ifr_name, devname); if ((dev = dev_get_by_name(devname)) == NULL) { printk("No such device\n"); return 1; } info.cmd = ETHTOOL_GDRVINFO; if (do_ioctl(SIOCETHTOOL, (void *) &info) < 0) { printk("SIOCETHTOOL: not supported\n"); return 1; } /* try access using MII ioctls - get phy address */ if (do_ioctl(SIOCGMIIPHY, NULL) < 0) { use_et = 1; } else { /* got phy address check for robo address */ struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &ifr.ifr_data; if (mii->phy_id != ROBO_PHY_ADDR) { printk("Invalid phy address (%d)\n", mii->phy_id); return 1; } } phyid = mdio_read(ROBO_PHY_ADDR, 0x2) | (mdio_read(ROBO_PHY_ADDR, 0x3) << 16); if (phyid == 0xffffffff || phyid == 0x55210022) { printk("No Robo switch in managed mode found\n"); return 1; } is_5350 = robo_vlan5350(); printk("found!\n"); return 0; }