📄 phytsk.c
字号:
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 + -