/*!
 * \brief Configure the internal PHY.
 *
 * Reset the PHY and initiate auto-negotiation.
 */
int NicPhyConfig(void)
{
    u_short phy_sor;
    u_short phy_sr;
    u_short phy_to;
    u_short mode;

    /* 
     * Reset the PHY and wait until this self clearing bit
     * becomes zero. We sleep 63 ms before each poll and
     * give up after 3 retries. 
     */
    NicPhyWrite(NIC_PHYCR, PHYCR_RST);
    for (phy_to = 0;; phy_to++) {
        Delay(1);
        if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)
            break;
        if (phy_to > 3) {
            return -1;
        }
    }
    Delay(1);

    /* Store PHY status output. */
    phy_sor = NicPhyRead(NIC_PHYSOR);

    /* Enable PHY interrupts. */
    NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
                PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);

    /* Set RPC register. */
    mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
    nic_bs(0);
    nic_outw(NIC_RPCR, mode);

    /*
     * Advertise our capabilities, initiate auto negotiation
     * and wait until this has been completed.
     */
    NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
    for (phy_to = 0, phy_sr = 0;; phy_to++) {
        /* Give up after long time wait. */
        if (phy_to >= 1024) {
            return -1;
        }
        /* Restart auto negotiation every 4 seconds or on failures. */
        if ((phy_to & 127) == 0 /* || (phy_sr & PHYSR_REM_FLT) != 0 */ ) {
            NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
            Delay(2);
        }
        /* Check if link status detected. */
        phy_sr = NicPhyRead(NIC_PHYSR);
        if (phy_sr & PHYSR_ANEG_ACK)
            break;
        Delay(3);
    }
    return 0;
}
Пример #2
0
/*!
 * \brief Configure the internal PHY.
 *
 * Reset the PHY and initiate auto-negotiation.
 */
static int NicPhyConfig(phantom_device_t * dev)
{
    u_int16_t phy_sor;
    u_int16_t phy_sr;
    u_int16_t phy_to;
    u_int16_t mode;

    /* 
     * Reset the PHY and wait until this self clearing bit
     * becomes zero. We sleep 63 ms before each poll and
     * give up after 3 retries. 
     */
    //printf("Reset PHY..");
    NicPhyWrite(dev, NIC_PHYCR, PHYCR_RST);
    for (phy_to = 0;; phy_to++) {
        NutSleep(63);
        if ((NicPhyRead(dev, NIC_PHYCR) & PHYCR_RST) == 0)
            break;
        if (phy_to > 3)
            return -1;
    }
    //printf("OK\n");

    /* Store PHY status output. */
    phy_sor = NicPhyRead(dev, NIC_PHYSOR);

    /* Enable PHY interrupts. */
    NicPhyWrite(dev, NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |
                PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);

    /* Set RPC register. */
    mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;
    nic_bs(0);
    nic_outw(NIC_RPCR, mode);

#ifdef NIC_FIXED
    /* Disable link. */
    phy_sr = NicPhyRead(NIC_PHYCFR1);
    NicPhyWrite(NIC_PHYCFR1, phy_sr | 0x8000);
    NutSleep(63);

    /* Set fixed capabilities. */
    NicPhyWrite(NIC_PHYCR, NIC_FIXED);
    nic_bs(0);
    nic_outw(NIC_RPCR, mode);

    /* Enable link. */
    phy_sr = NicPhyRead(NIC_PHYCFR1);
    NicPhyWrite(NIC_PHYCFR1, phy_sr & ~0x8000);
    phy_sr = NicPhyRead(NIC_PHYCFR1);

#else
    /*
     * Advertise our capabilities, initiate auto negotiation
     * and wait until this has been completed.
     */
    //printf("Negotiate..");
    NicPhyWrite(dev, NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);
    NutSleep(63);
    for (phy_to = 0, phy_sr = 0;; phy_to++) {
        /* Give up after 10 seconds. */
        if (phy_to >= 1024)
            return -1;
        /* Restart auto negotiation every 4 seconds or on failures. */
        if ((phy_to & 127) == 0 /* || (phy_sr & PHYSR_REM_FLT) != 0 */ ) {
            NicPhyWrite(dev, NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);
            //printf("Restart..");
            NutSleep(63);
        }
        /* Check if we are done. */
        phy_sr = NicPhyRead(dev, NIC_PHYSR);
        //printf("[SR %04X]", phy_sr);
        if (phy_sr & PHYSR_ANEG_ACK)
            break;
        NutSleep(63);
    }
    //printf("OK\n");
#endif

    return 0;
}