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

📄 phytsk.c

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

    delay_1(20);
}

static uchar phy_epg_running(uchar port_no)
{
    uchar running;

    phy_page_ext(port_no);
    running = ((phy_read(port_no, 0x1d) & 0xc000) == 0xc000);
    phy_page_std(port_no);

    return running;
}


static uchar phy_poll_for_lp(uchar port_no, uchar cur_state)
{
    ul_union_t tmp;
    uchar an_recv_state;
    uchar an_arb_state;
    ushort reg_5;
    ushort reg_9;
    ushort reg_10;
    uchar next_link_state;
    uchar an_ok;

    fix_data[port_no].phy_speed = 0xff;
    an_ok = FALSE;
    next_link_state = WAITING_FOR_LINK_SPECIAL_0;

    switch (cur_state) {

    case WAITING_FOR_LINK_SPECIAL_0:
        phy_page_tr(port_no);

        phy_write(port_no, 16, 0xa784);
        tmp.w[0] = phy_read(port_no, 18);
        tmp.w[1] = phy_read(port_no, 17);
        phy_page_std(port_no);

        an_recv_state = (tmp.w[0] << 2) & 4;
        an_recv_state |= ((tmp.w[1] >> 14) & 0x03);

        an_arb_state = (tmp.w[0] >> 3) & 0x0f;

        if ((an_recv_state > 1) && (an_arb_state == 3)) {
            delay_1(delay_a);

            phy_page_tr(port_no);
            phy_write(port_no, 16, 0xa780);
            reg_5 = phy_read(port_no, 17);
            phy_page_std(port_no);

            if ((reg_5 & 0x8000) != 0) {

                phy_page_tr(port_no);
                phy_write(port_no, 16, 0xa688);
                phy_write_masked(port_no, 17, 0x08, 0x08);
                phy_write(port_no, 16, 0x8688);
                phy_page_std(port_no);

                fix_data[port_no].timer = delay_b;

                return WAITING_FOR_LINK_SPECIAL_1;
            }
            else {
                an_ok = TRUE;
            }
        }
        break;
    case WAITING_FOR_LINK_SPECIAL_1:
        if (fix_data[port_no].timer == 0) {
            phy_write(port_no, 7, 0xb001);
            fix_data[port_no].timer = delay_c;
            return WAITING_FOR_LINK_SPECIAL_2;
        }
        return WAITING_FOR_LINK_SPECIAL_1;
        break;
    case WAITING_FOR_LINK_SPECIAL_2:
        if (fix_data[port_no].timer == 0) {
            phy_write(port_no, 7, 0xb001);
            fix_data[port_no].timer = delay_d;
            return WAITING_FOR_LINK_SPECIAL_3;
        }
        return WAITING_FOR_LINK_SPECIAL_2;
        break;
    case WAITING_FOR_LINK_SPECIAL_3:

        if (fix_data[port_no].timer != 0) {
            return WAITING_FOR_LINK_SPECIAL_3;
        }

        reg_9 = phy_read(port_no, 9);
        reg_10 = phy_read(port_no, 10);

        if ((reg_10 & 0x8000) != 0) {
            fix_data[port_no].phy_speed = LINK_MODE_SPEED_1000;
            next_link_state = SPECIAL_REINIT;
        }
        else if ((((reg_10 & 0x0c00) >> 2) & (reg_9 & 0x0300)) != 0) {
            fix_data[port_no].phy_speed = LINK_MODE_SPEED_1000;
            phy_write_masked(port_no, 4, 0x0000, 0x8000);
            next_link_state = WAITING_FOR_LINK_SPECIAL;
            fix_data[port_no].timer = 100; /* 1 second */
            fix_data[port_no].aux_timer = 0;
        }
        else {
            reg_5 = phy_read(port_no, 5);
            an_ok = TRUE;
        }
        break;
    default:
        break;
    }

    if (an_ok) {
        if (fix_data[port_no].phy_speed == 0xff) {
            tmp.w[0] = phy_read(port_no, 4) & reg_5;

            if ((tmp.w[0] & 0x0180) != 0) {
                fix_data[port_no].phy_speed = LINK_MODE_SPEED_100;
            }
            else if ((tmp.w[0] & 0x0060) != 0) {
                fix_data[port_no].phy_speed = LINK_MODE_SPEED_10;
            }
            else {
                fix_data[port_no].phy_speed = 0xff;
                next_link_state = SPECIAL_REINIT;
            }
        }
    }
    else {
        phy_page_tr(port_no);
        phy_write(port_no, 16, 0xa782);
        tmp.w[1] = phy_read(port_no, 17);
        phy_page_std(port_no);

        if ((tmp.b[3] & 0xc0) != 0) {
            fix_data[port_no].phy_speed = LINK_MODE_SPEED_10;
        }
        else if ((tmp.b[2] & 0x03) != 0) {
            fix_data[port_no].phy_speed = LINK_MODE_SPEED_100;
        }
    }

    if ((fix_data[port_no].phy_speed == LINK_MODE_SPEED_10) || 
        (fix_data[port_no].phy_speed == LINK_MODE_SPEED_100)) {

        if (fix_data[port_no].phy_speed == fix_data[port_no].mac_speed) {
            phy_write_masked(port_no, 4, 0, 0x8000);

            phy_page_tr(port_no);
            phy_write(port_no, 16, 0xa688);
            phy_write_masked(port_no, 17, 0x08, 0x08);
            phy_write(port_no, 16, 0x8688);
            phy_page_std(port_no);

            fix_data[port_no].timer = 100; /* 1 second */
            fix_data[port_no].aux_timer = 0;
            return WAITING_FOR_LINK_SPECIAL;
        }

        /*
        ** Start 10/100 fix
        */
	if (start_10_100_fix(port_no, FALSE)) {
	    next_link_state = PHASE_WALKING;
	}
	else {
	    next_link_state = SPECIAL_REINIT;
	}
    }
    return next_link_state;

}

static uchar start_10_100_fix(uchar port_no, uchar forced)
{
    uchar state;
    ul_union_t tmp;

    fix_data[port_no].save_reg_0  = phy_read(port_no, 0);
    fix_data[port_no].save_reg_29 = phy_read(port_no, 29);
    phy_write(port_no, 29, 0xeeee);

    h2_set_ana_recv_mask(port_no, 0);

    if (fix_data[port_no].phy_speed == LINK_MODE_SPEED_100) {
	phy_write(port_no, 0, 0x6100);
	h2_setup_mac(port_no, LINK_MODE_FDX_100);
    }
    else if (fix_data[port_no].phy_speed == LINK_MODE_SPEED_10) {
	phy_write(port_no, 0, 0x4100);
	h2_setup_mac(port_no, LINK_MODE_FDX_10);
    }
    else {
    }

    if (!forced) {
	phy_page_tr(port_no);
	phy_write(port_no, 16, 0xa688);
	phy_write_masked(port_no, 17, 0x08, 0x08);
	phy_write(port_no, 16, 0x8688);
	phy_page_std(port_no);
    }

    while ((phy_read(port_no, 1) & 0x0004) == 0) {
    }

    phy_epg_on(port_no);

    h2_enable_rx_tx(port_no);

    if (fix_data[port_no].phy_speed == LINK_MODE_SPEED_10) {
        phy_page_tp(port_no);
        phy_write_masked(port_no, 8, 0x0200, 0x0200);
        phy_page_std(port_no);
    }


    fix_data[port_no].phase = 0;

    for (state = 0; state < 2; state++) {
	if (await_activity(port_no)) {
	    delay_1(5);
	    (void) any_errors_seen(port_no); /* clear bits */
	    fix_data[port_no].timer = WAIT_ERROR_TIMEOUT(port_no);
	    break;
	}
	else {
	    if (state == 0) {
		if (no_activity_action_1 < 2) {
		    tmp.l = h2_read(PORT, port_no, PORT_MACCONF);
		    h2_write(PORT, port_no, PORT_MACCONF, MAC_RESET_MASK);
		    delay_1(2);
		    h2_write(PORT, port_no, PORT_MACCONF, tmp.l);
		}
		else {
		    if (fix_data[port_no].phy_speed  == LINK_MODE_SPEED_100) {
			h2_setup_mac(port_no, LINK_MODE_FDX_100);
		    }
		    else {
			h2_setup_mac(port_no, LINK_MODE_FDX_10);
		    }
		}

		if (no_activity_action_1 > 0) {
		    phy_epg_restart(port_no);
		    delay_1(5);
		}

	    }
	    else {
		/* Should not occur */
		if (no_activity_action_2 == 0) {
		    fix_data[port_no].timer = WAIT_ERROR_TIMEOUT(PORT);
		    return FALSE;
		}
		else {
		    phy_epg_off(port_no);
		    if (fix_data[port_no].phy_speed == LINK_MODE_SPEED_10) {
			phy_page_tp(port_no);
			phy_write_masked(port_no, 8, 0x0000, 0x0200);
			phy_page_std(port_no);
		    }
		    h2_setup_mac(port_no, LINK_MODE_DOWN);

		    if (!forced) {
			phy_page_tr(port_no);
			phy_write(port_no, 16, 0xa688);
			phy_write_masked(port_no, 17, 0x0000, 0x0008);
			phy_write(port_no, 16, 0x8688);
			phy_page_std(port_no);
		    }

		    if (forced) {
			phy_write(port_no,  0, fix_data[port_no].save_reg_0);
		    }
		    else {
			phy_write(port_no,  0, fix_data[port_no].save_reg_0 | 0x0200);
		    }

		    phy_write(port_no, 29, fix_data[port_no].save_reg_29);
		    
		    if (no_activity_action_2 > 1) {
			phy_reset(port_no);
		    }
		    
		    return FALSE;
		}
	    }
	}
    }

    return TRUE;

}


ulong xdata flip_count = 0;

static void flip_sgmii_clock(uchar port_no, uchar count)
{
    uchar delay;

    while (count--) {
        sgmii_write_gate_free_run(port_no, 1);
        flip_count++;
        for (delay = 0; delay < 20; delay++) {
        }
        sgmii_write_gate_free_run(port_no, 0);
        flip_count++;
        for (delay = 0; delay < 20; delay++) {
        }
    }
}

static void sgmii_write_gate_free_run(uchar port_no, uchar val)
{
    uchar dev;
    if ((port_no < 8) || (port_no > 15)) {
        if (port_no < 8) {
            dev = port_no;
        }
        else {
            dev = port_no - 8;
        }
    }

    /* SGMII Debug register */
    /*   CLK      | do access| write   | reg       */
    /*  (29 << 26 | 1 << 25  | 1 << 23 | 4 << 16)  = 0x76840000 */
    if(val) {    
        h2_write(SYSTEM, 0, SYS_SGMII_TR_DBG, 0x76840009 | ((ulong) dev << 19));
    } else {
        h2_write(SYSTEM, 0, SYS_SGMII_TR_DBG, 0x76840008 | ((ulong) dev << 19));
    }
}

static uchar suspect_port(uchar port_no)
{
    if ((h2_read(SYSTEM, 0, SYS_CHIPID) & 0xF0000000) > 0x10000000) {
	return FALSE;
    }

    if (port_no ==  0 || port_no ==  4 || port_no ==  5 || port_no ==  6 || port_no == 7 ||
	port_no == 16 || port_no == 17 || port_no == 18 || port_no == 19 || port_no == 23) {
	return TRUE;
    }
    else {
	return FALSE;
    }
}


static uchar use_special_state_machine(uchar port_no)
{
    if (!suspect_port(port_no)) {
	return FALSE;
    }

#if SFP_NUM
    if (phy_sfp_present(port_no)) {
	return FALSE;
    }
#endif

    return TRUE;
}

void phy_suspend_10_100_fix(uchar port_no)
{
    if (suspect_port(port_no)) {

	if (phy_epg_running(port_no)) {
	    phy_epg_off(port_no);
	    (void) any_errors_seen(port_no); /* clear bits */

	    if (fix_data[port_no].phy_speed == LINK_MODE_SPEED_10) {
		phy_page_tp(port_no);
		phy_write_masked(port_no, 8, 0x0000, 0x0200);
		phy_page_std(port_no);
	    }

	    phy_write(port_no,  0, fix_data[port_no].save_reg_0);
	    phy_write(port_no, 29, fix_data[port_no].save_reg_29);
	}

	/* reset supv_force_control_tr */
	phy_page_tr(port_no);
	phy_write(port_no, 16, 0xa686);
	phy_write_masked(port_no, 17, 0x0000, 0x0020);
	phy_write(port_no, 16, 0x8686);
	phy_page_std(port_no);

	phy_write_masked(port_no, 4, 0x0000, 0x8000);

	phy_state[port_no] = SET_UP_SPEED_MODE_ON_PHY;

	h2_setup_mac(port_no, LINK_MODE_DOWN);
    }
}

static uchar any_errors_seen(uchar port_no)
{
    return ((h2_read(PORT, port_no, 0x3c) & 0x0008) != 0);
}

static uchar await_activity(uchar port_no)
{
    h2_read(PORT, port_no, 0x3c);
    start_timer(MSEC_100);
    do {
        if (h2_read(PORT, port_no, 0x3c) & 0x0200) {
            return TRUE;
        }
    } while (!timeout());
    
    return FALSE;

}


⌨️ 快捷键说明

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