⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phydrv.c

📁 Vitesse 24port gigabit Switch Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
        phy_write(port_no, 23, VTSS_REG_23);

        assert_reset(port_no);
        init_seq_8224(port_no);
        phy_receiver_init(port_no);
        break;
#endif

#if VTSS_8204
    case PHY_FAMILY_VTSS_8204:
        phy_write(port_no, 23, VTSS_REG_23);
        break;
#endif

#if VTSS_8201
    case PHY_FAMILY_VTSS_8201:
        break;
#endif
    }

}

#if SFP_NUM
/* ************************************************************************ */
static void phy_sfp_init (uchar port_no)
/* ------------------------------------------------------------------------ --
 * Purpose     :
 * Remarks     :
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    ushort reg_val;
    uchar sfp_no;
    ushort mask;
    uchar present;

    for (sfp_no = 0; sfp_no < sizeof(sfp_ports); sfp_no++) {
        if (sfp_ports[sfp_no] == port_no) {
            break;
        }
    }
            
    /* read GPIO inputs with sfp module detect signals */
    phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0010);
    reg_val = phy_read(SFP_MODULE_DETECT_GPIO_PORT, 15);
    phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0000);
   
    /* enable fiber if sfp module detected */
    present = ((reg_val & bit_mask_16(sfp_module_detect_gpios[sfp_no])) == 0);
    if (present) {
        sfp_module_detect_status |= (1 << sfp_no);
        if ((h2_read(SYSTEM, 0, SYS_CHIPID) & 0xF0000000) > 0x10000000) {
            phy_write(port_no, 23, 0x0604);
        }
        else {
            phy_write(port_no, 23, 0x0204); /* fiber only */
        }
        assert_reset(port_no);
    }
    else {
        sfp_module_detect_status &= ~(1 << sfp_no);

        phy_write(port_no, 23, 0x0004);
        assert_reset(port_no);
    }


    /* set/reset TX disable signal */
    mask = bit_mask_16(sfp_tx_disable_gpios[sfp_no]);
    phy_write(SFP_TX_DISABLE_GPIO_PORT, 31, 0x0010);
    phy_write_masked(SFP_TX_DISABLE_GPIO_PORT, 0x11, mask, mask); /* Enable GPIO as output */
    if (present) {
        phy_write_masked(SFP_TX_DISABLE_GPIO_PORT, 0x10,    0, mask); /* reset GPIO */
    }
    else {
        phy_write_masked(SFP_TX_DISABLE_GPIO_PORT, 0x10, mask, mask); /* set GPIO */
    }
    phy_write(SFP_TX_DISABLE_GPIO_PORT, 31, 0x0000);
}

void phy_poll_sfp (void)
{
    ushort reg_val;
    uchar sfp_present_new;
    uchar port_no;
    uchar sfp_no;

    /* read GPIO inputs with sfp module detect signals */
    phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0010);
    reg_val = phy_read(SFP_MODULE_DETECT_GPIO_PORT, 15);
    phy_write(SFP_MODULE_DETECT_GPIO_PORT, 31, 0x0000);

    sfp_present_new = 0;
    for (sfp_no = 0; sfp_no < SFP_NUM; sfp_no++) {
        if ((reg_val & bit_mask_16(sfp_module_detect_gpios[sfp_no])) == 0) {
            sfp_present_new |= (1 << sfp_no);
        }
    }

    if (sfp_present_new != sfp_module_detect_status) {
        for (sfp_no = 0; sfp_no < SFP_NUM; sfp_no++) {
            if ((sfp_present_new & (1 << sfp_no)) != (sfp_module_detect_status & (1 << sfp_no))) {
                port_no = sfp_ports[sfp_no];
                assert_reset(port_no);
                phy_post_reset(port_no);
            }
        }
    }         
}

uchar phy_sfp_present (uchar port_no)
{
    uchar sfp_no;
    
    for (sfp_no = 0; sfp_no < sizeof(sfp_ports); sfp_no++) {
        if (sfp_ports[sfp_no] == port_no) {
            if (sfp_module_detect_status & (1 << sfp_no)) {
                return TRUE;
            }
            break;
        }
    }

    return FALSE;
}
#endif

/* ************************************************************************ */
ushort phy_read (uchar port_no, uchar reg_no) small
/* ------------------------------------------------------------------------ --
 * Purpose     : Read a PHY register.
 * Remarks     : port_no: The port number to which the PHY is attached.
 *               reg_no: the PHY register number (0-31).
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    ulong  dat;
    uchar  miim_no;
    uchar  phy_no;

    miim_no = phy_map_miim_no(port_no);
    phy_no  = phy_map_phy_no(port_no);

    h2_write(MIIM, miim_no, MIIMCMD, ushorts2ulong(0, ((ushort) phy_no << 5) | MIIM_CMD_READ | reg_no));

    phy_await_completed(miim_no);

    dat = h2_read(MIIM, miim_no, MIIMDATA);
    if (!(dat & MIIM_DATA_FAILURE_MASK)) {
        return (ushort) dat;
    }
    else {
        return 0;
    }
}

/* ************************************************************************ */
void phy_write (uchar port_no, uchar reg_no, ushort value) small
/* ------------------------------------------------------------------------ --
 * Purpose     : Write to a PHY register.
 * Remarks     : port_no: The port number to which the PHY is attached.
 *               reg_no: the PHY register number (0-31).
 *               value: value to be written.
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    uchar  miim_no;
    uchar  phy_no;

    miim_no = phy_map_miim_no(port_no);
    phy_no  = phy_map_phy_no(port_no);

    h2_write(MIIM, miim_no, MIIMCMD, build_phy_write_cmd(value, reg_no, phy_no));
    phy_await_completed(miim_no);
}

/* ************************************************************************ */
void phy_write_masked (uchar port_no, uchar reg_no, ushort value, ushort mask) small
/* ------------------------------------------------------------------------ --
 * Purpose     : Update specified bit(s) of a PHY register.
 * Remarks     : port_no: The port number to which the PHY is attached.
 *               reg_no: the PHY register number (0-31).
 *               value: Holds bits (in right positions) to be written.
 *               mask: Bit mask specifying the bits to be updated.
 * Restrictions:
 * See also    :
 * Example     : To set AN_EN and Restart_AN bits in register 0, write: 
 *                  phy_write_masked(miim_no, phy_no, 0, 0x1200, 0x1200);
 * ************************************************************************ */
{
    value |= (phy_read(port_no, reg_no) & ~mask);
    phy_write(port_no, reg_no, value);
}

/* ************************************************************************ */
void phy_read_id (uchar port_no, phy_id_t *phy_id_p)
/* ------------------------------------------------------------------------ --
 * Purpose     : Read PHY id from register 2 and 3 and generate software ids.
 * Remarks     : port_no: The port number to which the PHY is attached.
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    ul_union_t phy_id_raw;

    phy_id_raw.w[0] = phy_read(port_no, 2);
    phy_id_raw.w[1] = phy_read(port_no, 3); 

    /* Generate vendor identification */
    if (((phy_id_raw.l & 0xfffffc00) == PHY_OUI_VTSS_1) || 
        ((phy_id_raw.l & 0xfffffc00) == PHY_OUI_VTSS_2)) {
        phy_id_p->vendor = PHY_VENDOR_VTSS;
    }
    else {
        phy_id_p->vendor = PHY_VENDOR_UNKNOWN;
    }

    /* Retrieve revision number */
    phy_id_p->revision = phy_id_raw.w[1] & 0x000f;

    /* Generate family and model identifications */
    switch (phy_id_raw.l & 0xfffffff0) { /* mask out revision */
#if VTSS_8201
    case PHY_ID_VTSS_8201:
        phy_id_p->family = PHY_FAMILY_VTSS_8201;
        phy_id_p->model  = PHY_MODEL_VTSS_8201;
        break;
#endif
#if VTSS_8204
    case PHY_ID_VTSS_8204:
        phy_id_p->family = PHY_FAMILY_VTSS_8204;
        phy_id_p->model  = PHY_MODEL_VTSS_8204;
        break;
#endif
#if VTSS_8224
    case PHY_ID_VTSS_8224:
        phy_id_p->family = PHY_FAMILY_VTSS_8224;
        phy_id_p->model  = PHY_MODEL_VTSS_8224;
        break;
    case PHY_ID_VTSS_8234:
        phy_id_p->family = PHY_FAMILY_VTSS_8224;
        phy_id_p->model  = PHY_MODEL_VTSS_8234;
        break;
    case PHY_ID_VTSS_8244:
        phy_id_p->family = PHY_FAMILY_VTSS_8224;
        phy_id_p->model  = PHY_MODEL_VTSS_8244;
        break;
#endif
    case PHY_ID_VTSS_7390:
        phy_id_p->family = PHY_FAMILY_VTSS_7390;
        phy_id_p->model  = PHY_MODEL_VTSS_7390;
        break;
    case PHY_ID_VTSS_7389:
        phy_id_p->family = PHY_FAMILY_VTSS_7390;
        phy_id_p->model  = PHY_MODEL_VTSS_7389;
        break;
    case PHY_ID_VTSS_7391:
        phy_id_p->family = PHY_FAMILY_VTSS_7390;
        phy_id_p->model  = PHY_MODEL_VTSS_7391;
        break;
#if VTSS_8538
    case PHY_ID_VTSS_8538_A:
    case PHY_ID_VTSS_8538:
        phy_id_p->family = PHY_FAMILY_VTSS_8538;
        phy_id_p->model  = PHY_MODEL_VTSS_8538;
        break;
    case PHY_ID_VTSS_8558_A:
    case PHY_ID_VTSS_8558:
        phy_id_p->family = PHY_FAMILY_VTSS_8538;
        phy_id_p->model  = PHY_MODEL_VTSS_8558;
        break;
#endif
    default:
        phy_id_p->family = PHY_FAMILY_UNKNOWN;
        phy_id_p->model  = PHY_MODEL_UNKNOWN;
        break;
    }
}

/* ************************************************************************ */
void phy_restart_aneg (uchar port_no)
/* ------------------------------------------------------------------------ --
 * Purpose     : Restart auto-negotiation on the PHY connected to the
 *               specified port.
 * Remarks     :
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    /* start autonegotiation by writing to register 0 */
    phy_write_masked(port_no, 0, 0x1200, 0x1200);
}


#if LOOPBACK_TEST
/* ************************************************************************ */
void phy_set_forced_speed (uchar port_no, uchar link_mode)
/* ------------------------------------------------------------------------ --
 * Purpose     : Set forced speed.
 * Remarks     : link_mode specifies speed. See bit-map of link_mode in main.h. 
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    ushort val;

    if (link_mode & LINK_MODE_INT_LOOPBACK) {
	phy_suspend_10_100_fix(port_no);
    }

    /* temporary */
    phy_write(port_no, 0, 0);
    /* temporary ends */

    if ((link_mode & LINK_MODE_SPEED_MASK) == LINK_MODE_SPEED_10) {
        val = 0x0000;
    }
    else if ((link_mode & LINK_MODE_SPEED_MASK) == LINK_MODE_SPEED_100) {
        val = 0x2000;
    }
    else if ((link_mode & LINK_MODE_SPEED_MASK) == LINK_MODE_SPEED_1000) {
        val = 0x0040;
    }
    if (link_mode & LINK_MODE_FDX_MASK) {
        val |= 0x100;
    }
    if (link_mode & LINK_MODE_INT_LOOPBACK) {
        val |= 0x4000;
    }

    phy_write(port_no, 0, val);
}
#endif


/* ************************************************************************ */
bool phy_link_status (uchar port_no) small
/* ------------------------------------------------------------------------ --
 * Purpose     : Read link status bit from PHY.
 * Remarks     :
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    return ((phy_read(port_no, 1) & 0x0004) != 0);
}

#define __PHY_RESET__
#if LOOPBACK_TEST
#define __PHY_RESET__
#endif
#ifdef __PHY_RESET__
/* ************************************************************************ */
void phy_reset (uchar port_no)
/* ------------------------------------------------------------------------ --
 * Purpose     : Perform a reset of the PHY attached to the specified port.
 * Remarks     :
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    assert_reset(port_no);

    phy_post_reset(port_no);
}
#endif

/* ************************************************************************ */
void phy_do_link_up_settings (uchar port_no, uchar link_mode)
/* ------------------------------------------------------------------------ --
 * Purpose     : Do any PHY settings after link transition to up.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -