void __mii_init(void) { FEC_INFO_T *info; volatile FEC_T *fecp; struct eth_device *dev; int miispd = 0, i = 0; u16 status = 0; u16 linkgood = 0; /* retrieve from register structure */ dev = eth_get_dev(); info = dev->priv; fecp = (FEC_T *) info->miibase; fecpin_setclear(dev, 1); mii_reset(info); /* We use strictly polling mode only */ fecp->eimr = 0; /* Clear any pending interrupt */ fecp->eir = 0xffffffff; /* Set MII speed */ miispd = (gd->bus_clk / 1000000) / 5; fecp->mscr = miispd << 1; info->phy_addr = mii_discover_phy(dev); while (i < MCFFEC_TOUT_LOOP) { status = 0; i++; /* Read PHY control register */ miiphy_read(dev->name, info->phy_addr, MII_BMCR, &status); /* If phy set to autonegotiate, wait for autonegotiation done, * if phy is not autonegotiating, just wait for link up. */ if ((status & BMCR_ANENABLE) == BMCR_ANENABLE) { linkgood = (BMSR_ANEGCOMPLETE | BMSR_LSTATUS); } else { linkgood = BMSR_LSTATUS; } /* Read PHY status register */ miiphy_read(dev->name, info->phy_addr, MII_BMSR, &status); if ((status & linkgood) == linkgood) break; udelay(1); } if (i >= MCFFEC_TOUT_LOOP) { printf("Link UP timeout\n"); } /* adapt to the duplex and speed settings of the phy */ info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16; info->dup_spd |= miiphy_speed(dev->name, info->phy_addr); }
static void mii_write_bmcr(Mii *s, uint16_t v) { if (v & 0x8000) { mii_reset(s); } else { s->regs[MII_BMCR] = v; } }
/** * Probe PCI device * * @v pci PCI device * @ret rc Return status code */ static int skeleton_probe ( struct pci_device *pci ) { struct net_device *netdev; struct skeleton_nic *skel; int rc; /* Allocate and initialise net device */ netdev = alloc_etherdev ( sizeof ( *skel ) ); if ( ! netdev ) { rc = -ENOMEM; goto err_alloc; } netdev_init ( netdev, &skeleton_operations ); skel = netdev->priv; pci_set_drvdata ( pci, netdev ); netdev->dev = &pci->dev; memset ( skel, 0, sizeof ( *skel ) ); /* Fix up PCI device */ adjust_pci_device ( pci ); /* Map registers */ skel->regs = ioremap ( pci->membase, SKELETON_BAR_SIZE ); /* Reset the NIC */ if ( ( rc = skeleton_reset ( skel ) ) != 0 ) goto err_reset; /* Initialise and reset MII interface */ mii_init ( &skel->mii, &skeleton_mii_operations ); if ( ( rc = mii_reset ( &skel->mii ) ) != 0 ) { DBGC ( skel, "SKELETON %p could not reset MII: %s\n", skel, strerror ( rc ) ); goto err_mii_reset; } /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) goto err_register_netdev; /* Set initial link state */ skeleton_check_link ( netdev ); return 0; unregister_netdev ( netdev ); err_register_netdev: err_mii_reset: skeleton_reset ( skel ); err_reset: iounmap ( skel->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: return rc; }
void __mii_init(void) { volatile fec_t *fecp; struct fec_info_s *info; struct eth_device *dev; int miispd = 0, i = 0; u16 autoneg = 0; /* retrieve from register structure */ dev = eth_get_dev(); info = dev->priv; fecp = (fec_t *) info->miibase; fecpin_setclear(dev, 1); mii_reset(info); /* We use strictly polling mode only */ fecp->eimr = 0; /* Clear any pending interrupt */ fecp->eir = 0xffffffff; /* Set MII speed */ miispd = (gd->bus_clk / 1000000) / 5; fecp->mscr = miispd << 1; info->phy_addr = mii_discover_phy(dev); #define AUTONEGLINK (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS) while (i < MCFFEC_TOUT_LOOP) { autoneg = 0; miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &autoneg); i++; if ((autoneg & AUTONEGLINK) == AUTONEGLINK) break; udelay(500); } if (i >= MCFFEC_TOUT_LOOP) { printf("Auto Negotiation not complete\n"); } /* adapt to the half/full speed settings */ info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16; info->dup_spd |= miiphy_speed(dev->name, info->phy_addr); }
/* * ISR/periodic callbacks. */ uint_t efe_intr(caddr_t arg1, caddr_t arg2) { efe_t *efep = (void *)arg1; uint32_t status; mblk_t *mp = NULL; _NOTE(ARGUNUSED(arg2)); mutex_enter(&efep->efe_intrlock); if (efep->efe_flags & FLAG_SUSPENDED) { mutex_exit(&efep->efe_intrlock); return (DDI_INTR_UNCLAIMED); } status = GETCSR(efep, CSR_INTSTAT); if (!(status & INTSTAT_ACTV)) { mutex_exit(&efep->efe_intrlock); return (DDI_INTR_UNCLAIMED); } PUTCSR(efep, CSR_INTSTAT, status); if (status & INTSTAT_RCC) { mp = efe_recv(efep); } if (status & INTSTAT_RQE) { efep->efe_ierrors++; efep->efe_macrcv_errors++; /* Kick the receiver */ PUTCSR(efep, CSR_COMMAND, COMMAND_RXQUEUED); } if (status & INTSTAT_TXC) { mutex_enter(&efep->efe_txlock); efe_send_done(efep); mutex_exit(&efep->efe_txlock); } if (status & INTSTAT_FATAL) { mutex_enter(&efep->efe_txlock); efe_error(efep->efe_dip, "bus error; resetting!"); efe_restart(efep); mutex_exit(&efep->efe_txlock); } mutex_exit(&efep->efe_intrlock); if (mp != NULL) { mac_rx(efep->efe_mh, NULL, mp); } if (status & INTSTAT_TXC) { mac_tx_update(efep->efe_mh); } if (status & INTSTAT_FATAL) { mii_reset(efep->efe_miih); } return (DDI_INTR_CLAIMED); }
void __mii_init(void) { FEC_INFO_T *info; volatile FEC_T *fecp; struct eth_device *dev; int miispd = 0, i = 0; u16 status = 0; u16 linkgood = 0; /* retrieve from register structure */ dev = eth_get_dev(); info = dev->priv; fecp = (FEC_T *) info->miibase; fecpin_setclear(dev, 1); mii_reset(info); /* We use strictly polling mode only */ fecp->eimr = 0; /* Clear any pending interrupt */ fecp->eir = 0xffffffff; /* Set MII speed */ #ifdef CONFIG_M68K miispd = (gd->bus_clk / 1000000) / 5; #else /* * The MSCR[MII_SPEED] bit field is minus 1 encoded. * * We round the value in MSCR[MII_SPEED] up, so that the MDC frequency * never exceeds CONFIG_MCFFEC_MII_SPEED_LIMIT. */ miispd = (CONFIG_MCFFEC_MAC_CLK - 1) / (2 * CONFIG_MCFFEC_MII_SPEED_LIMIT); #endif /* CONFIG_M68K */ if (miispd > MCFFEC_MII_SPEED_MAX) miispd = MCFFEC_MII_SPEED_MAX; fecp->mscr = miispd << 1; info->phy_addr = mii_discover_phy(dev); while (i < MCFFEC_TOUT_LOOP) { status = 0; i++; /* Read PHY control register */ miiphy_read(dev->name, info->phy_addr, PHY_BMCR, &status); /* If phy set to autonegotiate, wait for autonegotiation done, * if phy is not autonegotiating, just wait for link up. */ if ((status & PHY_BMCR_AUTON) == PHY_BMCR_AUTON) { linkgood = (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS); } else { linkgood = PHY_BMSR_LS; } /* Read PHY status register */ miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &status); if ((status & linkgood) == linkgood) break; udelay(1); } if (i >= MCFFEC_TOUT_LOOP) { printf("Link UP timeout\n"); } /* adapt to the duplex and speed settings of the phy */ info->dup_spd = miiphy_duplex(dev->name, info->phy_addr) << 16; info->dup_spd |= miiphy_speed(dev->name, info->phy_addr); }
static unsigned pcn_intr(caddr_t arg1) { pcn_t *pcnp = (void *)arg1; mblk_t *mp = NULL; uint32_t status, status2; boolean_t do_reset = B_FALSE; mutex_enter(&pcnp->pcn_intrlock); if (IS_SUSPENDED(pcnp)) { mutex_exit(&pcnp->pcn_intrlock); return (DDI_INTR_UNCLAIMED); } while ((status = pcn_csr_read(pcnp, PCN_CSR_CSR)) & PCN_CSR_INTR) { pcn_csr_write(pcnp, PCN_CSR_CSR, status); status2 = pcn_csr_read(pcnp, PCN_CSR_EXTCTL2); if (status & PCN_CSR_TINT) { mutex_enter(&pcnp->pcn_xmtlock); pcn_reclaim(pcnp); mutex_exit(&pcnp->pcn_xmtlock); } if (status & PCN_CSR_RINT) mp = pcn_receive(pcnp); if (status & PCN_CSR_ERR) { do_reset = B_TRUE; break; } /* timer interrupt */ if (status2 & PCN_EXTCTL2_STINT) { /* ack it */ PCN_CSR_SETBIT(pcnp, PCN_CSR_EXTCTL2, PCN_EXTCTL2_STINT); if (pcn_watchdog(pcnp) != DDI_SUCCESS) { do_reset = B_TRUE; break; } } } if (do_reset) { mutex_enter(&pcnp->pcn_xmtlock); pcn_resetall(pcnp); mutex_exit(&pcnp->pcn_xmtlock); mutex_exit(&pcnp->pcn_intrlock); mii_reset(pcnp->pcn_mii); } else { mutex_exit(&pcnp->pcn_intrlock); } if (mp) mac_rx(pcnp->pcn_mh, NULL, mp); return (DDI_INTR_CLAIMED); }
/** * Probe PCI device * * @v pci PCI device * @ret rc Return status code */ static int rhine_probe ( struct pci_device *pci ) { struct net_device *netdev; struct rhine_nic *rhn; uint8_t revision; unsigned int i; int rc; /* Allocate and initialise net device */ netdev = alloc_etherdev ( sizeof ( *rhn ) ); if ( ! netdev ) { rc = -ENOMEM; goto err_alloc; } netdev_init ( netdev, &rhine_operations ); rhn = netdev->priv; pci_set_drvdata ( pci, netdev ); netdev->dev = &pci->dev; memset ( rhn, 0, sizeof ( *rhn ) ); rhine_init_ring ( &rhn->tx, RHINE_TXDESC_NUM, RHINE_TXQUEUE_BASE ); rhine_init_ring ( &rhn->rx, RHINE_RXDESC_NUM, RHINE_RXQUEUE_BASE ); /* Fix up PCI device */ adjust_pci_device ( pci ); /* Map registers */ rhn->regs = ioremap ( pci->membase, RHINE_BAR_SIZE ); rhn->ioaddr = pci->ioaddr; DBGC ( rhn, "RHINE %p regs at %08lx, I/O at %04lx\n", rhn, pci->membase, pci->ioaddr ); /* Reset the NIC */ if ( ( rc = rhine_reset ( rhn ) ) != 0 ) goto err_reset; /* Reload EEPROM */ if ( ( rc = rhine_reload_eeprom ( rhn ) ) != 0 ) goto err_reload_eeprom; /* Read card revision and enable MMIO */ pci_read_config_byte ( pci, PCI_REVISION, &revision ); DBGC ( rhn, "RHINE %p revision %#02x detected\n", rhn, revision ); rhine_enable_mmio ( rhn, revision ); /* Read MAC address */ for ( i = 0 ; i < ETH_ALEN ; i++ ) netdev->hw_addr[i] = readb ( rhn->regs + RHINE_MAC + i ); /* Initialise and reset MII interface */ mii_init ( &rhn->mii, &rhine_mii_operations ); if ( ( rc = mii_reset ( &rhn->mii ) ) != 0 ) { DBGC ( rhn, "RHINE %p could not reset MII: %s\n", rhn, strerror ( rc ) ); goto err_mii_reset; } DBGC ( rhn, "RHINE PHY vendor %04x device %04x\n", rhine_mii_read ( &rhn->mii, 0x02 ), rhine_mii_read ( &rhn->mii, 0x03 ) ); /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) goto err_register_netdev; /* Set initial link state */ rhine_check_link ( netdev ); return 0; err_register_netdev: err_mii_reset: err_reload_eeprom: rhine_reset ( rhn ); err_reset: netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: return rc; }