#include <sys/nxge/nxge_impl.h>
#include <sys/nxge/nxge_mac.h>
#include <sys/nxge/nxge_hio.h>
#define LINK_MONITOR_PERIOD (1000 * 1000)
#define LM_WAIT_MULTIPLIER 8
#define SERDES_RDY_WT_INTERVAL 50
#define MAX_SERDES_RDY_RETRIES 10
#define TN1010_SPEED_1G 1
#define TN1010_SPEED_10G 0
#define TN1010_AN_IN_PROG 0
#define TN1010_AN_COMPLETE 1
#define TN1010_AN_RSVD 2
#define TN1010_AN_FAILED 3
extern uint32_t nxge_no_link_notify;
extern boolean_t nxge_no_msg;
extern uint32_t nxge_lb_dbg;
extern uint32_t nxge_jumbo_mtu;
typedef enum {
CHECK_LINK_RESCHEDULE,
CHECK_LINK_STOP
} check_link_state_t;
static check_link_state_t nxge_check_link_stop(nxge_t *);
static ether_addr_st etherbroadcastaddr =
{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
static ether_addr_st etherzeroaddr =
{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
static uint32_t nxge_supported_cl45_ids[] = {
BCM8704_DEV_ID,
MARVELL_88X_201X_DEV_ID,
BCM8706_DEV_ID,
TN1010_DEV_ID
};
static uint32_t nxge_supported_cl22_ids[] = {
BCM5464R_PHY_ID,
BCM5482_PHY_ID
};
#define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \
sizeof (uint32_t))
#define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \
sizeof (uint32_t))
static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int);
static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int);
static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int);
static boolean_t nxge_is_supported_phy(uint32_t, uint8_t);
static boolean_t nxge_hswap_phy_present(p_nxge_t, uint8_t);
static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t);
static nxge_status_t nxge_n2_serdes_init(p_nxge_t);
static nxge_status_t nxge_n2_kt_serdes_init(p_nxge_t);
static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t);
static nxge_status_t nxge_1G_serdes_init(p_nxge_t);
static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t);
static nxge_status_t nxge_10G_link_intr_start(p_nxge_t);
static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t);
static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t);
static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t);
static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t);
static nxge_status_t nxge_check_mii_link(p_nxge_t);
static nxge_status_t nxge_check_10g_link(p_nxge_t);
static nxge_status_t nxge_10G_xcvr_init(p_nxge_t);
static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t);
static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t);
static nxge_status_t nxge_1G_xcvr_init(p_nxge_t);
static void nxge_bcm5464_link_led_off(p_nxge_t);
static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *);
static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t);
static nxge_status_t nxge_check_nlp2020_link(p_nxge_t, boolean_t *);
static nxge_status_t nxge_nlp2020_xcvr_init(p_nxge_t);
static int nxge_nlp2020_i2c_read(p_nxge_t, uint8_t, uint16_t, uint16_t,
uint8_t *);
static boolean_t nxge_is_nlp2020_phy(p_nxge_t);
static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t);
static nxge_status_t nxge_set_nlp2020_param(p_nxge_t);
static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui);
static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed);
static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep);
static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep,
nxge_link_state_t *link_up);
static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep);
static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep);
nxge_status_t nxge_mac_init(p_nxge_t);
static nxge_status_t nxge_mii_get_link_mode(p_nxge_t);
#ifdef NXGE_DEBUG
static void nxge_mii_dump(p_nxge_t);
static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep);
static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep);
#endif
static nxge_xcvr_table_t nxge_n2_10G_table = {
nxge_n2_serdes_init,
nxge_10G_xcvr_init,
nxge_10G_link_intr_stop,
nxge_10G_link_intr_start,
nxge_check_10g_link,
PCS_XCVR
};
static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = {
nxge_n2_serdes_init,
nxge_tn1010_xcvr_init,
nxge_10G_link_intr_stop,
nxge_10G_link_intr_start,
nxge_check_tn1010_link,
XPCS_XCVR
};
static nxge_xcvr_table_t nxge_n2_1G_table = {
nxge_n2_serdes_init,
nxge_1G_xcvr_init,
nxge_1G_fiber_link_intr_stop,
nxge_1G_fiber_link_intr_start,
nxge_check_mii_link,
PCS_XCVR
};
static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = {
nxge_n2_serdes_init,
nxge_tn1010_xcvr_init,
nxge_1G_fiber_link_intr_stop,
nxge_1G_fiber_link_intr_start,
nxge_check_tn1010_link,
PCS_XCVR
};
static nxge_xcvr_table_t nxge_10G_tn1010_table = {
nxge_neptune_10G_serdes_init,
nxge_tn1010_xcvr_init,
nxge_10G_link_intr_stop,
nxge_10G_link_intr_start,
nxge_check_tn1010_link,
XPCS_XCVR
};
static nxge_xcvr_table_t nxge_1G_tn1010_table = {
nxge_1G_serdes_init,
nxge_tn1010_xcvr_init,
nxge_1G_fiber_link_intr_stop,
nxge_1G_fiber_link_intr_start,
nxge_check_tn1010_link,
PCS_XCVR
};
static nxge_xcvr_table_t nxge_10G_fiber_table = {
nxge_neptune_10G_serdes_init,
nxge_10G_xcvr_init,
nxge_10G_link_intr_stop,
nxge_10G_link_intr_start,
nxge_check_10g_link,
PCS_XCVR
};
static nxge_xcvr_table_t nxge_1G_copper_table = {
NULL,
nxge_1G_xcvr_init,
nxge_1G_copper_link_intr_stop,
nxge_1G_copper_link_intr_start,
nxge_check_mii_link,
INT_MII_XCVR
};
static nxge_xcvr_table_t nxge_1G_fiber_table = {
nxge_1G_serdes_init,
nxge_1G_xcvr_init,
nxge_1G_fiber_link_intr_stop,
nxge_1G_fiber_link_intr_start,
nxge_check_mii_link,
PCS_XCVR
};
static nxge_xcvr_table_t nxge_10G_copper_table = {
nxge_neptune_10G_serdes_init,
NULL,
NULL,
NULL,
NULL,
PCS_XCVR
};
static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep)
{
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn))
& NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
return (B_TRUE);
} else {
return (B_FALSE);
}
}
nxge_status_t
nxge_get_xcvr_type(p_nxge_t nxgep)
{
nxge_status_t status = NXGE_OK;
char *phy_type;
char *prop_val;
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
uint32_t val;
npi_status_t rs;
if (nxgep->mac.portmode == PORT_10G_SERDES &&
nxgep->statsp->mac_stats.link_up) {
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
return (status);
}
nxgep->mac.portmode = 0;
nxgep->xcvr_addr = 0;
if (nxgep->hot_swappable_phy == B_TRUE) {
nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
nxgep->mac.portmode = PORT_HSP_MODE;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable"));
} else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip,
DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
"hot-swappable-phy") == 1) {
nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
nxgep->mac.portmode = PORT_HSP_MODE;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable"));
} else if (nxgep->niu_type == N2_NIU &&
ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0,
"hot-swappable-phy") == 1) {
nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR;
nxgep->mac.portmode = PORT_HSP_MODE;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable"));
}
if (nxgep->mac.portmode == PORT_HSP_MODE) {
nxgep->hot_swappable_phy = B_TRUE;
if (portn > 1) {
return (NXGE_ERROR);
}
if (nxge_hswap_phy_present(nxgep, portn))
goto found_phy;
nxgep->phy_absent = B_TRUE;
rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
XPCS_REG_STATUS, &val);
if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) {
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
nxgep->mac.portmode = PORT_10G_SERDES;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"HSP 10G Serdes FOUND!!"));
}
goto check_phy_done;
found_phy:
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
nxgep->mac.portmode = PORT_10G_FIBER;
nxgep->phy_absent = B_FALSE;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr "
"found for hot swappable phy"));
check_phy_done:
return (status);
}
if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip,
DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
"phy-type", &prop_val)) == DDI_PROP_SUCCESS) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"found conf file: phy-type %s", prop_val));
if (strcmp("xgsd", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
nxgep->mac.portmode = PORT_10G_SERDES;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"found: 10G Serdes"));
} else if (strcmp("gsd", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
nxgep->mac.portmode = PORT_1G_SERDES;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes"));
} else if (strcmp("mif", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
nxgep->mac.portmode = PORT_1G_COPPER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr"));
} else if (strcmp("pcs", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
nxgep->mac.portmode = PORT_1G_FIBER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr"));
} else if (strcmp("xgf", prop_val) == 0) {
if (nxge_is_tn1010_phy(nxgep)) {
if ((status = nxge_set_tn1010_param(nxgep))
!= NXGE_OK) {
return (status);
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
} else {
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
nxgep->mac.portmode = PORT_10G_FIBER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"10G Fiber Xcvr"));
}
} else if (strcmp("xgc", prop_val) == 0) {
if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK)
return (status);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
}
(void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip,
"phy-type", prop_val);
ddi_prop_free(prop_val);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
"Got phy type [0x%x] from conf file",
nxgep->mac.portmode));
return (NXGE_OK);
}
if (nxgep->niu_type == N2_NIU) {
if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0,
"phy-type", &prop_val) == DDI_PROP_SUCCESS) {
if (strcmp("xgf", prop_val) == 0) {
if (nxge_is_tn1010_phy(nxgep)) {
if ((status =
nxge_set_tn1010_param(nxgep))
!= NXGE_OK) {
return (status);
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"TN1010 Xcvr"));
} else if (nxge_is_nlp2020_phy(nxgep)) {
if ((status =
nxge_set_nlp2020_param(nxgep))
!= NXGE_OK) {
return (status);
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"NLP2020 Xcvr"));
} else {
nxgep->statsp->mac_stats.xcvr_inuse
= XPCS_XCVR;
nxgep->mac.portmode = PORT_10G_FIBER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"10G Fiber Xcvr"));
}
} else if (strcmp("mif", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse =
INT_MII_XCVR;
nxgep->mac.portmode = PORT_1G_COPPER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"1G Copper Xcvr"));
} else if (strcmp("pcs", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
nxgep->mac.portmode = PORT_1G_FIBER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"1G Fiber Xcvr"));
} else if (strcmp("xgc", prop_val) == 0) {
status = nxge_set_tn1010_param(nxgep);
if (status != NXGE_OK)
return (status);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr"));
} else if (strcmp("xgsd", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
nxgep->mac.portmode = PORT_10G_SERDES;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"OBP: 10G Serdes"));
} else if (strcmp("gsd", prop_val) == 0) {
nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
nxgep->mac.portmode = PORT_1G_SERDES;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"OBP: 1G Serdes"));
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unknown phy-type: %s", prop_val));
ddi_prop_free(prop_val);
return (NXGE_ERROR);
}
status = NXGE_OK;
(void) ddi_prop_update_string(DDI_DEV_T_NONE,
nxgep->dip, "phy-type", prop_val);
ddi_prop_free(prop_val);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
"Got phy type [0x%x] from OBP",
nxgep->mac.portmode));
return (status);
} else {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Exiting...phy-type property not found"));
return (NXGE_ERROR);
}
}
if (!nxgep->vpd_info.present) {
return (NXGE_OK);
}
if (!nxgep->vpd_info.ver_valid) {
goto read_seeprom;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Reading phy type from expansion ROM"));
phy_type = nxgep->vpd_info.phy_type;
if (strncmp(phy_type, "mif", 3) == 0) {
nxgep->mac.portmode = PORT_1G_COPPER;
nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR;
} else if (strncmp(phy_type, "xgf", 3) == 0) {
nxgep->mac.portmode = PORT_10G_FIBER;
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
} else if (strncmp(phy_type, "pcs", 3) == 0) {
nxgep->mac.portmode = PORT_1G_FIBER;
nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
} else if (strncmp(phy_type, "xgc", 3) == 0) {
status = nxge_set_tn1010_param(nxgep);
if (status != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_get_xcvr_type: Failed to set TN1010 param"));
goto read_seeprom;
}
} else if (strncmp(phy_type, "xgsd", 4) == 0) {
nxgep->mac.portmode = PORT_10G_SERDES;
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
} else if (strncmp(phy_type, "gsd", 3) == 0) {
nxgep->mac.portmode = PORT_1G_SERDES;
nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
} else {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
phy_type[0], phy_type[1], phy_type[2]));
goto read_seeprom;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: "
"Got phy type [0x%x] from VPD", nxgep->mac.portmode));
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type"));
return (status);
read_seeprom:
status = nxge_espc_phy_type_get(nxgep);
if (status != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Failed to get phy type"));
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version "
"[%s] invalid...please update", nxgep->vpd_info.ver));
}
return (status);
}
nxge_status_t
nxge_setup_xcvr_table(p_nxge_t nxgep)
{
nxge_status_t status = NXGE_OK;
uint32_t port_type;
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
uint32_t pcs_id = 0;
uint32_t pma_pmd_id = 0;
uint32_t phy_id = 0;
uint16_t chip_id = 0;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>",
portn));
switch (nxgep->niu_type) {
case N2_NIU:
switch (nxgep->mac.portmode) {
case PORT_1G_FIBER:
case PORT_1G_SERDES:
nxgep->xcvr = nxge_n2_1G_table;
nxgep->xcvr_addr = portn;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr",
(nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" :
"Serdes"));
break;
case PORT_10G_FIBER:
case PORT_10G_COPPER:
case PORT_10G_SERDES:
nxgep->xcvr = nxge_n2_10G_table;
if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
nxgep->xcvr_addr =
nxgep->nxge_hw_p->xcvr_addr[portn];
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr",
(nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" :
((nxgep->mac.portmode == PORT_10G_COPPER) ?
"Copper" : "Serdes")));
break;
case PORT_1G_TN1010:
nxgep->xcvr = nxge_n2_1G_tn1010_table;
nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"TN1010 Copper Xcvr in 1G"));
break;
case PORT_10G_TN1010:
nxgep->xcvr = nxge_n2_10G_tn1010_table;
nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"TN1010 Copper Xcvr in 10G"));
break;
case PORT_HSP_MODE:
nxgep->xcvr = nxge_n2_10G_table;
nxgep->xcvr.xcvr_inuse = HSP_XCVR;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot "
"Swappable Xcvr (not present)"));
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_setup_xcvr_table: "
"Unable to determine NIU portmode"));
return (NXGE_ERROR);
}
break;
default:
if (nxgep->mac.portmode == 0) {
if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_setup_xcvr_table:"
" Invalid Neptune type [0x%x]",
nxgep->niu_type));
return (NXGE_ERROR);
}
port_type = nxgep->niu_type >>
(NXGE_PORT_TYPE_SHIFT * portn);
port_type = port_type & (NXGE_PORT_TYPE_MASK);
switch (port_type) {
case NXGE_PORT_1G_COPPER:
nxgep->mac.portmode = PORT_1G_COPPER;
break;
case NXGE_PORT_10G_COPPER:
nxgep->mac.portmode = PORT_10G_COPPER;
break;
case NXGE_PORT_1G_FIBRE:
nxgep->mac.portmode = PORT_1G_FIBER;
break;
case NXGE_PORT_10G_FIBRE:
nxgep->mac.portmode = PORT_10G_FIBER;
break;
case NXGE_PORT_1G_SERDES:
nxgep->mac.portmode = PORT_1G_SERDES;
break;
case NXGE_PORT_10G_SERDES:
nxgep->mac.portmode = PORT_10G_SERDES;
break;
case NXGE_PORT_1G_RGMII_FIBER:
nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
break;
case NXGE_PORT_TN1010:
if ((status = nxge_set_tn1010_param(nxgep))
!= NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_set_tn1010_param failed"));
return (status);
}
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_setup_xcvr_table: "
"Unknown port-type: 0x%x", port_type));
return (NXGE_ERROR);
}
}
switch (nxgep->mac.portmode) {
case PORT_1G_COPPER:
case PORT_1G_RGMII_FIBER:
nxgep->xcvr = nxge_1G_copper_table;
nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
switch (nxgep->platform_type) {
case P_NEPTUNE_ATLAS_4PORT:
case P_NEPTUNE_MARAMBA_P0:
case P_NEPTUNE_MARAMBA_P1:
switch (portn) {
case 0:
nxgep->xcvr_addr += 3;
break;
case 1:
nxgep->xcvr_addr += 1;
break;
case 2:
nxgep->xcvr_addr -= 1;
break;
case 3:
nxgep->xcvr_addr -= 3;
break;
default:
return (NXGE_ERROR);
}
break;
default:
break;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
(nxgep->mac.portmode == PORT_1G_COPPER) ?
"Copper" : "RGMII Fiber"));
break;
case PORT_10G_COPPER:
nxgep->xcvr = nxge_10G_copper_table;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr"));
break;
case PORT_1G_TN1010:
nxgep->xcvr = nxge_1G_tn1010_table;
nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"1G TN1010 copper Xcvr"));
break;
case PORT_10G_TN1010:
nxgep->xcvr = nxge_10G_tn1010_table;
nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"10G TN1010 copper Xcvr"));
break;
case PORT_1G_FIBER:
case PORT_1G_SERDES:
nxgep->xcvr = nxge_1G_fiber_table;
nxgep->xcvr_addr = portn;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr",
(nxgep->mac.portmode == PORT_1G_FIBER) ?
"Fiber" : "Serdes"));
break;
case PORT_10G_FIBER:
case PORT_10G_SERDES:
nxgep->xcvr = nxge_10G_fiber_table;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr "
"nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
"nxgep->xcvr_addr = [%d]",
nxgep->nxge_hw_p->xcvr_addr[portn],
nxgep->xcvr_addr));
if (nxgep->nxge_hw_p->xcvr_addr[portn]) {
nxgep->xcvr_addr =
nxgep->nxge_hw_p->xcvr_addr[portn];
}
switch (nxgep->platform_type) {
case P_NEPTUNE_MARAMBA_P0:
case P_NEPTUNE_MARAMBA_P1:
nxge_bcm5464_link_led_off(nxgep);
break;
default:
break;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr",
(nxgep->mac.portmode == PORT_10G_FIBER) ?
"Fiber" : "Serdes"));
break;
case PORT_HSP_MODE:
nxgep->xcvr = nxge_10G_fiber_table;
nxgep->xcvr.xcvr_inuse = HSP_XCVR;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot "
"Swappable Xcvr (not present)"));
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unknown port-type: 0x%x", port_type));
return (NXGE_ERROR);
}
}
if (nxgep->mac.portmode == PORT_10G_FIBER ||
nxgep->mac.portmode == PORT_10G_COPPER) {
uint32_t pma_pmd_id;
pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep,
nxgep->xcvr_addr);
if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) {
chip_id = MRVL88X201X_CHIP_ID;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_setup_xcvr_table: "
"Chip ID MARVELL [0x%x] for 10G xcvr", chip_id));
} else if ((pma_pmd_id & NLP2020_DEV_ID_MASK) ==
NLP2020_DEV_ID) {
chip_id = NLP2020_CHIP_ID;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_setup_xcvr_table: "
"Chip ID AEL2020 [0x%x] for 10G xcvr", chip_id));
} else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr,
BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG,
&chip_id)) == NXGE_OK) {
switch (chip_id) {
case BCM8704_CHIP_ID:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_setup_xcvr_table: "
"Chip ID 8704 [0x%x] for 10G xcvr",
chip_id));
break;
case BCM8706_CHIP_ID:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_setup_xcvr_table: "
"Chip ID 8706 [0x%x] for 10G xcvr",
chip_id));
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_setup_xcvr_table: "
"Unknown Chip ID [0x%x] for 10G xcvr",
chip_id));
break;
}
}
}
nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse;
nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr;
nxgep->chip_id = chip_id;
nxgep->statsp->mac_stats.xcvr_id = 0;
pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr);
if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) {
nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id;
} else {
pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr);
if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) {
nxgep->statsp->mac_stats.xcvr_id = pcs_id;
} else {
phy_id = nxge_get_cl22_phy_id(nxgep,
nxgep->xcvr_addr);
if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
nxgep->statsp->mac_stats.xcvr_id = phy_id;
}
}
}
nxgep->mac.linkchkmode = LINKCHK_TIMER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type"
"[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type,
nxgep->platform_type, nxgep->xcvr_addr));
return (status);
}
nxge_status_t
nxge_mac_init(p_nxge_t nxgep)
{
uint8_t portn;
nxge_status_t status = NXGE_OK;
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn));
nxgep->mac.portnum = portn;
nxgep->mac.porttype = PORT_TYPE_XMAC;
if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1))
nxgep->mac.porttype = PORT_TYPE_BMAC;
if ((status = nxge_xif_init(nxgep)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK)
goto fail;
if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
goto fail;
if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK)
goto fail;
if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
goto fail;
if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK)
goto fail;
if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) {
if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
goto fail;
}
if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) {
goto fail;
}
nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize;
if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
((nxgep->mac.portmode == PORT_1G_SERDES) ||
(nxgep->mac.portmode == PORT_1G_TN1010) ||
(nxgep->mac.portmode == PORT_1G_FIBER)) &&
((portn == 0) || (portn == 1))) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_mac_init: reinit Neptune 1G Serdes "));
if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) {
goto fail;
}
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_mac_init: failed to initialize MAC port<%d>", portn));
return (status);
}
nxge_status_t
nxge_link_init(p_nxge_t nxgep)
{
nxge_status_t status = NXGE_OK;
nxge_port_mode_t portmode;
#ifdef NXGE_DEBUG
uint8_t portn;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn));
#endif
portmode = nxgep->mac.portmode;
if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) &&
(portmode != PORT_10G_TN1010) &&
(portmode != PORT_1G_TN1010) &&
(portmode != PORT_1G_SERDES)) {
if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) {
goto fail;
}
}
NXGE_DELAY(200000);
if ((status = nxge_serdes_init(nxgep)) != NXGE_OK)
goto fail;
NXGE_DELAY(200000);
if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ",
"failed to initialize Ethernet link on port<%d>", portn));
return (status);
}
nxge_status_t
nxge_xif_init(p_nxge_t nxgep)
{
uint32_t xif_cfg = 0;
npi_attr_t ap;
uint8_t portn;
nxge_port_t portt;
nxge_port_mode_t portmode;
p_nxge_stats_t statsp;
npi_status_t rs = NPI_SUCCESS;
npi_handle_t handle;
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn));
handle = nxgep->npi_handle;
portmode = nxgep->mac.portmode;
portt = nxgep->mac.porttype;
statsp = nxgep->statsp;
if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
((nxgep->mac.portmode == PORT_1G_SERDES) ||
(nxgep->mac.portmode == PORT_1G_TN1010) ||
(nxgep->mac.portmode == PORT_1G_FIBER)) &&
((portn == 0) || (portn == 1))) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_xcvr_init: set ATCA mode"));
npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE);
}
if (portt == PORT_TYPE_XMAC) {
if ((portmode == PORT_10G_FIBER) ||
(portmode == PORT_10G_COPPER) ||
(portmode == PORT_10G_TN1010) ||
(portmode == PORT_HSP_MODE) ||
(portmode == PORT_10G_SERDES))
xif_cfg |= CFG_XMAC_XIF_LFS;
if (portmode == PORT_1G_COPPER) {
xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS;
}
if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
xif_cfg |= CFG_XMAC_XIF_LOOPBACK;
if (statsp->mac_stats.link_speed == 100)
xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ;
xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT;
if ((portmode == PORT_10G_FIBER) ||
(portmode == PORT_10G_COPPER) ||
(portmode == PORT_10G_TN1010) ||
(portmode == PORT_1G_TN1010) ||
(portmode == PORT_HSP_MODE) ||
(portmode == PORT_10G_SERDES)) {
if (statsp->mac_stats.link_up) {
xif_cfg |= CFG_XMAC_XIF_LED_POLARITY;
} else {
xif_cfg |= CFG_XMAC_XIF_LED_FORCE;
}
}
rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg);
if (rs != NPI_SUCCESS)
goto fail;
nxgep->mac.xif_config = xif_cfg;
if ((portmode == PORT_10G_FIBER) ||
(portmode == PORT_10G_COPPER) ||
(portmode == PORT_10G_TN1010) ||
(portmode == PORT_HSP_MODE) ||
(portmode == PORT_10G_SERDES)) {
SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
MAC_XGMII_MODE, rs);
if (rs != NPI_SUCCESS)
goto fail;
if (statsp->mac_stats.link_up) {
if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
goto fail;
} else {
if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
goto fail;
}
} else if ((portmode == PORT_1G_FIBER) ||
(portmode == PORT_1G_COPPER) ||
(portmode == PORT_1G_SERDES) ||
(portmode == PORT_1G_TN1010) ||
(portmode == PORT_1G_RGMII_FIBER)) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_xif_init: Port[%d] Mode[%d] Speed[%d]",
portn, portmode, statsp->mac_stats.link_speed));
if (statsp->mac_stats.link_speed == 1000) {
SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
MAC_GMII_MODE, rs);
} else {
SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE,
MAC_MII_MODE, rs);
}
if (rs != NPI_SUCCESS)
goto fail;
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_xif_init: Unknown port mode (%d)"
" for port<%d>", portmode, portn));
goto fail;
}
} else if (portt == PORT_TYPE_BMAC) {
if ((portmode == PORT_1G_COPPER) ||
(portmode == PORT_1G_RGMII_FIBER)) {
if (statsp->mac_stats.link_speed == 100)
xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ;
}
if (statsp->port_stats.lb_mode == nxge_lb_mac1000)
xif_cfg |= CFG_BMAC_XIF_LOOPBACK;
if (statsp->mac_stats.link_speed == 1000)
xif_cfg |= CFG_BMAC_XIF_GMII_MODE;
xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT;
rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg);
if (rs != NPI_SUCCESS)
goto fail;
nxgep->mac.xif_config = xif_cfg;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_xif_init: Failed to initialize XIF port<%d>", portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_pcs_init(p_nxge_t nxgep)
{
pcs_cfg_t pcs_cfg;
uint32_t val;
uint8_t portn;
nxge_port_mode_t portmode;
npi_handle_t handle;
p_nxge_stats_t statsp;
pcs_ctrl_t pcs_ctrl;
npi_status_t rs = NPI_SUCCESS;
uint8_t i;
handle = nxgep->npi_handle;
portmode = nxgep->mac.portmode;
portn = nxgep->mac.portnum;
statsp = nxgep->statsp;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn));
if (portmode == PORT_1G_FIBER ||
portmode == PORT_1G_TN1010 ||
portmode == PORT_1G_SERDES) {
if (portmode == PORT_1G_TN1010) {
for (i = 0; i < 6; i ++) {
if ((rs = npi_mac_pcs_reset(handle, portn))
!= NPI_SUCCESS) {
goto fail;
}
}
} else {
if ((rs = npi_mac_pcs_reset(handle, portn))
!= NPI_SUCCESS)
goto fail;
}
pcs_cfg.value = 0;
pcs_cfg.bits.w0.enable = 1;
pcs_cfg.bits.w0.mask = 1;
PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value);
PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
portn, pcs_cfg.value));
if (portmode == PORT_1G_TN1010) {
pcs_ctrl.value = 0;
PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG,
pcs_ctrl.value);
}
} else if (portmode == PORT_10G_FIBER ||
portmode == PORT_10G_COPPER ||
portmode == PORT_10G_TN1010 ||
portmode == PORT_HSP_MODE ||
portmode == PORT_10G_SERDES) {
XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
val &= ~XMAC_XIF_XPCS_BYPASS;
XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS)
goto fail;
if ((rs = npi_xmac_xpcs_read(handle, portn,
XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS)
goto fail;
if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) ||
(statsp->port_stats.lb_mode == nxge_lb_mac1000))
val |= XPCS_CTRL1_LOOPBK;
else
val &= ~XPCS_CTRL1_LOOPBK;
if ((rs = npi_xmac_xpcs_write(handle, portn,
XPCS_REG_CONTROL1, val)) != NPI_SUCCESS)
goto fail;
if ((rs = npi_xmac_xpcs_write(handle, portn,
XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
goto fail;
if ((rs = npi_xmac_xpcs_read(handle, portn,
XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS)
goto fail;
if ((rs = npi_xmac_xpcs_read(handle, portn,
XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS)
goto fail;
} else if ((portmode == PORT_1G_COPPER) ||
(portmode == PORT_1G_RGMII_FIBER)) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_pcs_init: (1G) copper port<%d>", portn));
if (portn < 4) {
PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG,
PCS_DATAPATH_MODE_MII);
}
if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS)
goto fail;
} else {
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_mac_ctrl_init(p_nxge_t nxgep)
{
uint8_t portn;
nxge_port_t portt;
p_nxge_stats_t statsp;
npi_handle_t handle;
uint32_t val;
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>",
portn));
handle = nxgep->npi_handle;
portt = nxgep->mac.porttype;
statsp = nxgep->statsp;
if (portt == PORT_TYPE_XMAC) {
XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val);
if (statsp->mac_stats.adv_cap_asmpause) {
if (!statsp->mac_stats.adv_cap_pause) {
val |= XMAC_RX_CFG_RX_PAUSE_EN;
} else {
val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
}
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mac_ctrl_init: port<%d>: pause",
portn));
if (statsp->mac_stats.adv_cap_pause) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mac_ctrl_init: port<%d>: "
"enable pause", portn));
val |= XMAC_RX_CFG_RX_PAUSE_EN;
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mac_ctrl_init: port<%d>: "
"disable pause", portn));
val &= ~XMAC_RX_CFG_RX_PAUSE_EN;
}
}
XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val);
} else if (portt == PORT_TYPE_BMAC) {
BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val);
if (statsp->mac_stats.adv_cap_asmpause) {
if (statsp->mac_stats.adv_cap_pause) {
val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN;
} else {
val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN;
}
} else {
if (statsp->mac_stats.adv_cap_pause) {
val |= MAC_CTRL_CFG_RECV_PAUSE_EN;
} else {
val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
~MAC_CTRL_CFG_RECV_PAUSE_EN);
}
}
BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val);
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>",
portn));
return (NXGE_OK);
}
nxge_status_t
nxge_serdes_init(p_nxge_t nxgep)
{
p_nxge_stats_t statsp;
#ifdef NXGE_DEBUG
uint8_t portn;
#endif
nxge_status_t status = NXGE_OK;
#ifdef NXGE_DEBUG
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_serdes_init port<%d>", portn));
#endif
if (nxgep->xcvr.serdes_init) {
statsp = nxgep->statsp;
status = nxgep->xcvr.serdes_init(nxgep);
if (status != NXGE_OK)
goto fail;
statsp->mac_stats.serdes_inits++;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_serdes_init: Failed to initialize serdes for port<%d>",
portn));
return (status);
}
static nxge_status_t
nxge_n2_serdes_init(p_nxge_t nxgep)
{
uint8_t portn;
int chan;
esr_ti_cfgpll_l_t pll_cfg_l;
esr_ti_cfgpll_l_t pll_sts_l;
esr_ti_cfgrx_l_t rx_cfg_l;
esr_ti_cfgrx_h_t rx_cfg_h;
esr_ti_cfgtx_l_t tx_cfg_l;
esr_ti_cfgtx_h_t tx_cfg_h;
#ifdef NXGE_DEBUG
esr_ti_testcfg_t cfg;
#endif
esr_ti_testcfg_t test_cfg;
nxge_status_t status = NXGE_OK;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>",
portn));
if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: KT-NIU", portn));
return (nxge_n2_kt_serdes_init(nxgep));
}
tx_cfg_l.value = 0;
tx_cfg_h.value = 0;
rx_cfg_l.value = 0;
rx_cfg_h.value = 0;
pll_cfg_l.value = 0;
pll_sts_l.value = 0;
test_cfg.value = 0;
if (nxgep->mac.portmode == PORT_1G_TN1010 ||
nxgep->mac.portmode == PORT_10G_TN1010) {
if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
goto fail;
}
}
if (nxgep->mac.portmode == PORT_10G_FIBER ||
nxgep->mac.portmode == PORT_10G_COPPER ||
nxgep->mac.portmode == PORT_10G_TN1010 ||
nxgep->mac.portmode == PORT_HSP_MODE ||
nxgep->mac.portmode == PORT_10G_SERDES) {
tx_cfg_l.bits.entx = 1;
tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
rx_cfg_l.bits.enrx = 1;
rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
tx_cfg_l.bits.entest = 1;
rx_cfg_l.bits.entest = 1;
test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
if ((status = nxge_mdio_write(nxgep, portn,
ESR_N2_DEV_ADDR,
ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK)
goto fail;
}
pll_cfg_l.bits.mpy = CFGPLL_MPY_10X;
pll_cfg_l.bits.enpll = 1;
pll_sts_l.bits.enpll = 1;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
goto fail;
#ifdef NXGE_DEBUG
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, &cfg.value);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
portn, pll_cfg_l.value, cfg.value));
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_STS_L_REG, &cfg.value);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
portn, pll_sts_l.value, cfg.value));
#endif
} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
nxgep->mac.portmode == PORT_1G_TN1010 ||
nxgep->mac.portmode == PORT_1G_SERDES) {
tx_cfg_l.bits.entx = 1;
tx_cfg_l.bits.rate = CFGTX_RATE_HALF;
tx_cfg_l.bits.swing = CFGTX_SWING_1375MV;
rx_cfg_l.bits.enrx = 1;
rx_cfg_l.bits.rate = CFGRX_RATE_HALF;
rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT;
rx_cfg_l.bits.align = CFGRX_ALIGN_EN;
rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES;
if (portn == 0) {
rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF;
}
pll_cfg_l.bits.mpy = CFGPLL_MPY_8X;
pll_cfg_l.bits.enpll = 1;
pll_sts_l.bits.enpll = 1;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK)
goto fail;
#ifdef NXGE_DEBUG
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, &cfg.value);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
portn, pll_cfg_l.value, cfg.value));
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_STS_L_REG, &cfg.value);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
portn, pll_sts_l.value, cfg.value));
#endif
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
tx_cfg_l.bits.entest = 1;
rx_cfg_l.bits.entest = 1;
test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
portn, test_cfg.value));
if ((status = nxge_mdio_write(nxgep, portn,
ESR_N2_DEV_ADDR,
ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
goto fail;
}
}
} else {
goto fail;
}
NXGE_DELAY(20);
for (chan = 0; chan < 4; chan++) {
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
portn, chan, tx_cfg_l.value));
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
portn, chan, tx_cfg_h.value));
}
for (chan = 0; chan < 4; chan++) {
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
portn, chan, rx_cfg_l.value));
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
portn, chan, rx_cfg_h.value));
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
portn));
return (status);
}
static nxge_status_t
nxge_n2_kt_serdes_init(p_nxge_t nxgep)
{
uint8_t portn;
int chan, i;
k_esr_ti_cfgpll_l_t pll_cfg_l;
k_esr_ti_cfgrx_l_t rx_cfg_l;
k_esr_ti_cfgrx_h_t rx_cfg_h;
k_esr_ti_cfgtx_l_t tx_cfg_l;
k_esr_ti_cfgtx_h_t tx_cfg_h;
#ifdef NXGE_DEBUG
k_esr_ti_testcfg_t cfg;
#endif
k_esr_ti_testcfg_t test_cfg;
nxge_status_t status = NXGE_OK;
boolean_t mode_1g = B_FALSE;
uint64_t val;
npi_handle_t handle;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d>", portn));
handle = nxgep->npi_handle;
tx_cfg_l.value = 0;
tx_cfg_h.value = 0;
rx_cfg_l.value = 0;
rx_cfg_h.value = 0;
pll_cfg_l.value = 0;
test_cfg.value = 0;
if (nxgep->mac.portmode == PORT_1G_TN1010 ||
nxgep->mac.portmode == PORT_10G_TN1010) {
if (nxge_set_tn1010_param(nxgep) != NXGE_OK) {
goto fail;
}
}
if (nxgep->mac.portmode == PORT_10G_FIBER ||
nxgep->mac.portmode == PORT_10G_COPPER ||
nxgep->mac.portmode == PORT_10G_TN1010 ||
nxgep->mac.portmode == PORT_10G_SERDES) {
if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGL) {
tx_cfg_l.value = nxgep->srds_prop.tx_cfg_l;
} else {
tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX;
tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
portn, tx_cfg_l.value));
if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGH) {
tx_cfg_h.value = nxgep->srds_prop.tx_cfg_h;
} else {
tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
portn, tx_cfg_h.value));
if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGL) {
rx_cfg_l.value = nxgep->srds_prop.rx_cfg_l;
} else {
rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX;
rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
portn, rx_cfg_l.value));
if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGH) {
rx_cfg_h.value = nxgep->srds_prop.rx_cfg_h;
} else {
rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x",
portn, rx_cfg_h.value));
if (nxgep->srds_prop.prop_set & NXGE_SRDS_PLLCFGL) {
pll_cfg_l.value = nxgep->srds_prop.pll_cfg_l;
} else {
pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
portn, pll_cfg_l.value));
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
portn, pll_cfg_l.value));
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK;
rx_cfg_l.bits.los = 0;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: "
"loopback 0x%x", portn, tx_cfg_h.value));
}
#ifdef NXGE_DEBUG
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, &cfg.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: "
"PLL cfg.l 0x%x (0x%x)",
portn, pll_cfg_l.value, cfg.value));
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_STS_L_REG, &cfg.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
portn, cfg.value));
#endif
} else if (nxgep->mac.portmode == PORT_1G_FIBER ||
nxgep->mac.portmode == PORT_1G_TN1010 ||
nxgep->mac.portmode == PORT_1G_SERDES) {
mode_1g = B_TRUE;
tx_cfg_l.bits.entx = 1;
tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF;
tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
portn, tx_cfg_l.value));
tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
portn, tx_cfg_h.value));
rx_cfg_l.bits.enrx = 1;
rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF;
rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN;
rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
portn, rx_cfg_l.value));
rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
portn, rx_cfg_h.value));
pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X;
pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
portn, pll_cfg_l.value));
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value))
!= NXGE_OK)
goto fail;
#ifdef NXGE_DEBUG
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_CFG_L_REG, &cfg.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
portn, pll_cfg_l.value, cfg.value));
nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_PLL_STS_L_REG, &cfg.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
portn, cfg.value));
#endif
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: "
"loopback 0x%x", portn, test_cfg.value));
if ((status = nxge_mdio_write(nxgep, portn,
ESR_N2_DEV_ADDR,
ESR_N2_TX_CFG_L_REG_ADDR(0),
tx_cfg_h.value)) != NXGE_OK) {
goto fail;
}
}
} else {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_n2_kt_serdes_init:port<%d> - "
"unsupported port mode %d",
portn, nxgep->mac.portmode));
goto fail;
}
NXGE_DELAY(20);
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) {
goto fail;
}
NXGE_DELAY(20);
for (chan = 0; chan < 4; chan++) {
if (mode_1g)
tx_cfg_l.value = 0;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: "
"chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value));
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: "
"chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value));
}
for (chan = 0; chan < 4; chan++) {
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value))
!= NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR,
ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value))
!= NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: "
"chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value));
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_n2_kt_serdes_init port<%d>: "
"chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value));
}
if (portn == 0) {
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
if ((val & ESR_SIG_P0_BITS_MASK) !=
(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
ESR_SIG_XSERDES_RDY_P0 |
ESR_SIG_XDETECT_P0_CH3 |
ESR_SIG_XDETECT_P0_CH2 |
ESR_SIG_XDETECT_P0_CH1 |
ESR_SIG_XDETECT_P0_CH0))
NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_n2_kt_serdes_init: "
"Serdes/signal for port<%d> not ready", portn));
goto done;
}
} else if (portn == 1) {
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
if ((val & ESR_SIG_P1_BITS_MASK) !=
(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
ESR_SIG_XSERDES_RDY_P1 |
ESR_SIG_XDETECT_P1_CH3 |
ESR_SIG_XDETECT_P1_CH2 |
ESR_SIG_XDETECT_P1_CH1 |
ESR_SIG_XDETECT_P1_CH0))
NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_n2_kt_serdes_init: "
"Serdes/signal for port<%d> not ready", portn));
goto done;
}
}
done:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_n2_kt_serdes_init port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
portn));
return (status);
}
static nxge_status_t
nxge_neptune_10G_serdes_init(p_nxge_t nxgep)
{
npi_handle_t handle;
uint8_t portn;
int chan, i;
sr_rx_tx_ctrl_l_t rx_tx_ctrl_l;
sr_rx_tx_ctrl_h_t rx_tx_ctrl_h;
sr_glue_ctrl0_l_t glue_ctrl0_l;
sr_glue_ctrl0_h_t glue_ctrl0_h;
uint64_t val;
uint16_t val16l;
uint16_t val16h;
nxge_status_t status = NXGE_OK;
portn = nxgep->mac.portnum;
if ((portn != 0) && (portn != 1))
return (NXGE_OK);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_neptune_10G_serdes_init port<%d>", portn));
handle = nxgep->npi_handle;
switch (portn) {
case 0:
ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0);
NXGE_DELAY(20);
ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
NXGE_DELAY(2000);
ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
ESR_PLL_CFG_10G_SERDES);
ESR_REG_WR(handle, ESR_0_CONTROL_REG,
ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
(0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_3_SHIFT));
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
ESR_REG_WR(handle,
ESR_0_TEST_CONFIG_REG,
ESR_PAD_LOOPBACK_CH3 |
ESR_PAD_LOOPBACK_CH2 |
ESR_PAD_LOOPBACK_CH1 |
ESR_PAD_LOOPBACK_CH0);
} else {
ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
}
break;
case 1:
ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1);
NXGE_DELAY(20);
ESR_REG_WR(handle, ESR_RESET_REG, 0x0);
NXGE_DELAY(2000);
ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
ESR_PLL_CFG_10G_SERDES);
ESR_REG_WR(handle, ESR_1_CONTROL_REG,
ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 |
ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 |
(0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
(0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_0_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_1_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_2_SHIFT) |
(0x1 << ESR_CTL_LOSADJ_3_SHIFT));
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) {
ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 |
ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0);
} else {
ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
}
break;
default:
goto done;
}
for (chan = 0; chan < 4; chan++) {
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
&rx_tx_ctrl_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
&rx_tx_ctrl_h.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
&glue_ctrl0_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
&glue_ctrl0_h.value)) != NXGE_OK)
goto fail;
rx_tx_ctrl_l.bits.enstretch = 1;
rx_tx_ctrl_h.bits.vmuxlo = 2;
rx_tx_ctrl_h.bits.vpulselo = 2;
glue_ctrl0_l.bits.rxlosenable = 1;
glue_ctrl0_l.bits.samplerate = 0xF;
glue_ctrl0_l.bits.thresholdcount = 0xFF;
glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
rx_tx_ctrl_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
rx_tx_ctrl_h.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
glue_ctrl0_l.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
glue_ctrl0_h.value)) != NXGE_OK)
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
(uint16_t)0)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
NXGE_OK)
goto fail;
NXGE_DELAY(200);
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
NXGE_OK)
goto fail;
NXGE_DELAY(200);
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK)
goto fail;
NXGE_DELAY(200);
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(),
&val16l)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK)
goto fail;
if ((val16l != 0) || (val16h != 0)) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Failed to reset port<%d> XAUI Serdes "
"(val16l 0x%x val16h 0x%x)",
portn, val16l, val16h));
}
if (portn == 0) {
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
if ((val & ESR_SIG_P0_BITS_MASK) !=
(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 |
ESR_SIG_XSERDES_RDY_P0 |
ESR_SIG_XDETECT_P0_CH3 |
ESR_SIG_XDETECT_P0_CH2 |
ESR_SIG_XDETECT_P0_CH1 |
ESR_SIG_XDETECT_P0_CH0))
NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_neptune_10G_serdes_init: "
"Serdes/signal for port<%d> not ready", portn));
goto done;
}
} else if (portn == 1) {
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
if ((val & ESR_SIG_P1_BITS_MASK) !=
(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 |
ESR_SIG_XSERDES_RDY_P1 |
ESR_SIG_XDETECT_P1_CH3 |
ESR_SIG_XDETECT_P1_CH2 |
ESR_SIG_XDETECT_P1_CH1 |
ESR_SIG_XDETECT_P1_CH0))
NXGE_DELAY(SERDES_RDY_WT_INTERVAL);
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_neptune_10G_serdes_init: "
"Serdes/signal for port<%d> not ready", portn));
goto done;
}
}
done:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_neptune_10G_serdes_init port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_neptune_10G_serdes_init: "
"Failed to initialize Neptune serdes for port<%d>", portn));
return (status);
}
static nxge_status_t
nxge_1G_serdes_init(p_nxge_t nxgep)
{
npi_handle_t handle;
uint8_t portn;
int chan;
sr_rx_tx_ctrl_l_t rx_tx_ctrl_l;
sr_rx_tx_ctrl_h_t rx_tx_ctrl_h;
sr_glue_ctrl0_l_t glue_ctrl0_l;
sr_glue_ctrl0_h_t glue_ctrl0_h;
uint64_t val;
uint16_t val16l;
uint16_t val16h;
nxge_status_t status = NXGE_OK;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_1G_serdes_init port<%d>", portn));
handle = nxgep->npi_handle;
switch (portn) {
case 0:
ESR_REG_RD(handle, ESR_RESET_REG, &val);
val |= ESR_RESET_0;
ESR_REG_WR(handle, ESR_RESET_REG, val);
ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG,
ESR_PLL_CFG_1G_SERDES);
ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES);
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG,
ESR_TSTCFG_LBTEST_PAD);
} else {
ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0);
}
ESR_REG_RD(handle, ESR_RESET_REG, &val);
val &= ~ESR_RESET_0;
ESR_REG_WR(handle, ESR_RESET_REG, val);
break;
case 1:
ESR_REG_RD(handle, ESR_RESET_REG, &val);
val |= ESR_RESET_1;
ESR_REG_WR(handle, ESR_RESET_REG, val);
ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG,
ESR_PLL_CFG_1G_SERDES);
ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES);
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) {
ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG,
ESR_TSTCFG_LBTEST_PAD);
} else {
ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0);
}
ESR_REG_RD(handle, ESR_RESET_REG, &val);
val &= ~ESR_RESET_1;
ESR_REG_WR(handle, ESR_RESET_REG, val);
break;
default:
goto done;
}
for (chan = 0; chan < 4; chan++) {
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
&rx_tx_ctrl_l.value)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
&rx_tx_ctrl_h.value)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
&glue_ctrl0_l.value)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_read(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
&glue_ctrl0_h.value)) != NXGE_OK) {
goto fail;
}
rx_tx_ctrl_l.bits.enstretch = 1;
rx_tx_ctrl_h.bits.vmuxlo = 2;
rx_tx_ctrl_h.bits.vpulselo = 2;
glue_ctrl0_l.bits.rxlosenable = 1;
glue_ctrl0_l.bits.samplerate = 0xF;
glue_ctrl0_l.bits.thresholdcount = 0xFF;
glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES;
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan),
rx_tx_ctrl_l.value)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan),
rx_tx_ctrl_h.value)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan),
glue_ctrl0_l.value)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn,
ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan),
glue_ctrl0_h.value)) != NXGE_OK) {
goto fail;
}
}
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) !=
NXGE_OK) {
goto fail;
}
NXGE_DELAY(200);
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) !=
NXGE_OK) {
goto fail;
}
NXGE_DELAY(200);
if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) {
goto fail;
}
NXGE_DELAY(200);
if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR,
ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) {
goto fail;
}
if ((val16l != 0) || (val16h != 0)) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Failed to reset port<%d> XAUI Serdes "
"(val16l 0x%x val16h 0x%x)", portn, val16l, val16h));
status = NXGE_ERROR;
goto fail;
}
NXGE_DELAY(200);
ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_neptune_serdes_init: read internal signal reg port<%d> "
"val 0x%x", portn, val));
if (portn == 0) {
if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
(ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_neptune_1G_serdes_init: "
"Serdes/signal for port<%d> not ready", portn));
goto done;
}
} else if (portn == 1) {
if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
(ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_neptune_1G_serdes_init: "
"Serdes/signal for port<%d> not ready", portn));
goto done;
}
}
done:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_1G_serdes_init port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_1G_serdes_init: "
"Failed to initialize Neptune serdes for port<%d>",
portn));
return (status);
}
#define NXGE_SET_PHY_TUNABLES(nxgep, phy_port, stat) \
{ \
int i; \
\
if (nxgep->phy_prop.cnt > 0) { \
for (i = 0; i < nxgep->phy_prop.cnt; i++) { \
if ((stat = nxge_mdio_write(nxgep, phy_port, \
nxgep->phy_prop.arr[i].dev, \
nxgep->phy_prop.arr[i].reg, \
nxgep->phy_prop.arr[i].val)) != NXGE_OK) { \
break; \
} \
NXGE_DEBUG_MSG((nxgep, MAC_CTL, \
"From OBP, write<dev.reg.val> = " \
"<0x%x.0x%x.0x%x>", \
nxgep->phy_prop.arr[i].dev, \
nxgep->phy_prop.arr[i].reg, \
nxgep->phy_prop.arr[i].val)); \
} \
} \
}
static nxge_status_t
nxge_BCM8704_xcvr_init(p_nxge_t nxgep)
{
uint16_t val;
#ifdef NXGE_DEBUG
uint8_t portn;
uint16_t val1;
#endif
uint8_t phy_port_addr;
pmd_tx_control_t tx_ctl;
control_t ctl;
phyxs_control_t phyxs_ctl;
pcs_control_t pcs_ctl;
uint32_t delay = 0;
optics_dcntr_t op_ctr;
nxge_status_t status = NXGE_OK;
#ifdef NXGE_DEBUG
portn = nxgep->mac.portnum;
#endif
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
portn));
phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
goto fail;
phyxs_ctl.bits.reset = 1;
if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
goto fail;
do {
drv_usecwait(500);
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
&phyxs_ctl.value)) != NXGE_OK)
goto fail;
delay++;
} while ((phyxs_ctl.bits.reset) && (delay < 100));
if (delay == 100) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
"failed to reset Transceiver on port<%d>", portn));
status = NXGE_ERROR;
goto fail;
}
ctl.value = 0;
ctl.bits.res1 = 0x3F;
ctl.bits.optxon_lvl = 1;
ctl.bits.oprxflt_lvl = 1;
ctl.bits.optrxlos_lvl = 1;
ctl.bits.optxflt_lvl = 1;
ctl.bits.opprflt_lvl = 1;
ctl.bits.obtmpflt_lvl = 1;
ctl.bits.opbiasflt_lvl = 1;
ctl.bits.optxrst_lvl = 1;
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value))
!= NXGE_OK)
goto fail;
tx_ctl.value = 0;
tx_ctl.bits.tsck_lpwren = 1;
tx_ctl.bits.tx_dac_txck = 0x2;
tx_ctl.bits.tx_dac_txd = 0x1;
tx_ctl.bits.xfp_clken = 1;
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG,
tx_ctl.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
!= NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val))
!= NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
!= NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val))
!= NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
&op_ctr.value)) != NXGE_OK)
goto fail;
if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
op_ctr.bits.gpio_sel = 0x1;
} else {
op_ctr.bits.gpio_sel = 0x3;
}
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
op_ctr.value)) != NXGE_OK)
goto fail;
NXGE_DELAY(1000000);
NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
if (status != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_BCM8704_xcvr_init: Failed setting PHY tunables"));
goto fail;
}
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
!= NXGE_OK)
goto fail;
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
pcs_ctl.bits.loopback = 1;
else
pcs_ctl.bits.loopback = 0;
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
!= NXGE_OK)
goto fail;
status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val);
if (status != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val));
status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val);
if (status != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val));
status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val);
if (status != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val));
#ifdef NXGE_DEBUG
status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR,
BCM8704_USER_ANALOG_STATUS0_REG,
&val);
if (status != NXGE_OK)
goto fail;
status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val);
if (status != NXGE_OK)
goto fail;
status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
if (status != NXGE_OK)
goto fail;
status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1);
if (status != NXGE_OK)
goto fail;
if (val != 0x3FC) {
if ((val == 0x43BC) && (val1 != 0)) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Cable not connected to peer or bad"
" cable on port<%d>\n", portn));
} else if (val == 0x639C) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Optical module (XFP) is bad or absent"
" on port<%d>\n", portn));
}
}
#endif
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
"port<%d>", nxgep->mac.portnum));
return (NXGE_ERROR);
}
static nxge_status_t
nxge_BCM8706_xcvr_init(p_nxge_t nxgep)
{
uint8_t phy_port_addr;
phyxs_control_t phyxs_ctl;
pcs_control_t pcs_ctl;
uint32_t delay = 0;
optics_dcntr_t op_ctr;
nxge_status_t status = NXGE_OK;
#ifdef NXGE_DEBUG
uint8_t portn = nxgep->mac.portnum;
#endif
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
portn));
phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK)
goto fail;
phyxs_ctl.bits.reset = 1;
if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK)
goto fail;
do {
drv_usecwait(500);
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG,
&phyxs_ctl.value)) != NXGE_OK)
goto fail;
delay++;
} while ((phyxs_ctl.bits.reset) && (delay < 100));
if (delay == 100) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: "
"failed to reset Transceiver on port<%d>", portn));
status = NXGE_ERROR;
goto fail;
}
NXGE_DELAY(1000000);
NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
if (status != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_BCM8706_xcvr_init: Failed setting PHY tunables"));
goto fail;
}
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value))
!= NXGE_OK)
goto fail;
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
pcs_ctl.bits.loopback = 1;
else
pcs_ctl.bits.loopback = 0;
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value))
!= NXGE_OK)
goto fail;
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
&op_ctr.value)) != NXGE_OK)
goto fail;
op_ctr.bits.gpio_sel = 0x3;
op_ctr.bits.res2 = 0x1;
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG,
op_ctr.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
"port<%d>", nxgep->mac.portnum));
return (status);
}
static int
nxge_nlp2020_i2c_read(p_nxge_t nxgep, uint8_t ctrl_port, uint16_t address,
uint16_t reg, uint8_t *data)
{
int phy_dev, phy_reg;
uint16_t phy_data = 0;
uint16_t stat;
uint8_t count = 100;
phy_dev = NLP2020_I2C_SNOOP_DEV_ADDR;
phy_reg = NLP2020_I2C_SNOOP_ADDR_REG;
phy_data = ((address + 1) << NLP2020_XCVR_I2C_ADDR_SH) | reg;
if (nxge_mdio_write(nxgep, ctrl_port,
phy_dev, phy_reg, phy_data) != NXGE_OK)
goto fail;
phy_reg = NLP2020_I2C_SNOOP_STAT_REG;
(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, &stat);
while ((stat != 0x01) && (count-- > 0)) {
(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
&stat);
}
if (count) {
phy_reg = NLP2020_I2C_SNOOP_DATA_REG;
(void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg,
&phy_data);
*data = (phy_data >> 8);
return (0);
}
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_nlp2020_i2c_read: FAILED"));
return (1);
}
#define NLP_INI_WAIT 1
#define NLP_INI_STOP 0
static nxge_nlp_initseq_t nlp2020_revC_fiber_init[] = {
{0x1C003, 0x3101},
{0x1CC01, 0x488a},
{0x1CB1B, 0x0200},
{0x1CB1C, 0x00f0},
{0x1CC06, 0x00e0},
{NLP_INI_STOP, 0},
};
static nxge_nlp_initseq_t nlp2020_revC_copper_init[] = {
{0x1C003, 0x3101},
{0x1CD40, 0x0001},
{0x1CA12, 0x0100},
{0x1CA22, 0x0100},
{0x1CA42, 0x0100},
{0x1C20D, 0x0002},
{NLP_INI_WAIT, 100},
{0x1ff28, 0x4001},
{0x1ff2A, 0x004A},
{NLP_INI_WAIT, 500},
{0x1d000, 0x5200},
{NLP_INI_WAIT, 500},
{0x1d800, 0x4009},
{0x1d801, 0x2fff},
{0x1d802, 0x300f},
{0x1d803, 0x40aa},
{0x1d804, 0x401c},
{0x1d805, 0x401e},
{0x1d806, 0x20c5},
{0x1d807, 0x3c05},
{0x1d808, 0x6536},
{0x1d809, 0x2fe4},
{0x1d80a, 0x3dc4},
{0x1d80b, 0x6624},
{0x1d80c, 0x2ff4},
{0x1d80d, 0x3dc4},
{0x1d80e, 0x2035},
{0x1d80f, 0x30a5},
{0x1d810, 0x6524},
{0x1d811, 0x2ca2},
{0x1d812, 0x3012},
{0x1d813, 0x1002},
{0x1d814, 0x2882},
{0x1d815, 0x3022},
{0x1d816, 0x1002},
{0x1d817, 0x2972},
{0x1d818, 0x3022},
{0x1d819, 0x1002},
{0x1d81a, 0x2892},
{0x1d81b, 0x3012},
{0x1d81c, 0x1002},
{0x1d81d, 0x24e2},
{0x1d81e, 0x3022},
{0x1d81f, 0x1002},
{0x1d820, 0x27e2},
{0x1d821, 0x3012},
{0x1d822, 0x1002},
{0x1d823, 0x2422},
{0x1d824, 0x3022},
{0x1d825, 0x1002},
{0x1d826, 0x22cd},
{0x1d827, 0x301d},
{0x1d828, 0x2992},
{0x1d829, 0x3022},
{0x1d82a, 0x1002},
{0x1d82b, 0x5553},
{0x1d82c, 0x0307},
{0x1d82d, 0x2572},
{0x1d82e, 0x3022},
{0x1d82f, 0x1002},
{0x1d830, 0x21a2},
{0x1d831, 0x3012},
{0x1d832, 0x1002},
{0x1d833, 0x4016},
{0x1d834, 0x5e63},
{0x1d835, 0x0344},
{0x1d836, 0x21a2},
{0x1d837, 0x3012},
{0x1d838, 0x1002},
{0x1d839, 0x400e},
{0x1d83a, 0x2572},
{0x1d83b, 0x3022},
{0x1d83c, 0x1002},
{0x1d83d, 0x2b22},
{0x1d83e, 0x3012},
{0x1d83f, 0x1002},
{0x1d840, 0x28e2},
{0x1d841, 0x3022},
{0x1d842, 0x1002},
{0x1d843, 0x2782},
{0x1d844, 0x3022},
{0x1d845, 0x1002},
{0x1d846, 0x2fa4},
{0x1d847, 0x3dc4},
{0x1d848, 0x6624},
{0x1d849, 0x2e8b},
{0x1d84a, 0x303b},
{0x1d84b, 0x56b3},
{0x1d84c, 0x03c6},
{0x1d84d, 0x866b},
{0x1d84e, 0x400c},
{0x1d84f, 0x2782},
{0x1d850, 0x3012},
{0x1d851, 0x1002},
{0x1d852, 0x2c4b},
{0x1d853, 0x309b},
{0x1d854, 0x56b3},
{0x1d855, 0x03c3},
{0x1d856, 0x866b},
{0x1d857, 0x400c},
{0x1d858, 0x22a2},
{0x1d859, 0x3022},
{0x1d85a, 0x1002},
{0x1d85b, 0x28e2},
{0x1d85c, 0x3022},
{0x1d85d, 0x1002},
{0x1d85e, 0x2782},
{0x1d85f, 0x3022},
{0x1d860, 0x1002},
{0x1d861, 0x2fb4},
{0x1d862, 0x3dc4},
{0x1d863, 0x6624},
{0x1d864, 0x56b3},
{0x1d865, 0x03c3},
{0x1d866, 0x866b},
{0x1d867, 0x401c},
{0x1d868, 0x2c45},
{0x1d869, 0x3095},
{0x1d86a, 0x5b53},
{0x1d86b, 0x23d2},
{0x1d86c, 0x3012},
{0x1d86d, 0x13c2},
{0x1d86e, 0x5cc3},
{0x1d86f, 0x2782},
{0x1d870, 0x3012},
{0x1d871, 0x1312},
{0x1d872, 0x2b22},
{0x1d873, 0x3012},
{0x1d874, 0x1002},
{0x1d875, 0x28e2},
{0x1d876, 0x3022},
{0x1d877, 0x1002},
{0x1d878, 0x2672},
{0x1d879, 0x3022},
{0x1d87a, 0x1002},
{0x1d87b, 0x21a2},
{0x1d87c, 0x3012},
{0x1d87d, 0x1002},
{0x1d87e, 0x628f},
{0x1d87f, 0x2985},
{0x1d880, 0x33a5},
{0x1d881, 0x2782},
{0x1d882, 0x3022},
{0x1d883, 0x1002},
{0x1d884, 0x5653},
{0x1d885, 0x03d2},
{0x1d886, 0x401e},
{0x1d887, 0x6f72},
{0x1d888, 0x1002},
{0x1d889, 0x628f},
{0x1d88a, 0x2304},
{0x1d88b, 0x3c84},
{0x1d88c, 0x6436},
{0x1d88d, 0xdff4},
{0x1d88e, 0x6436},
{0x1d88f, 0x2ff5},
{0x1d890, 0x3005},
{0x1d891, 0x8656},
{0x1d892, 0xdfba},
{0x1d893, 0x56a3},
{0x1d894, 0xd05a},
{0x1d895, 0x29e2},
{0x1d896, 0x3012},
{0x1d897, 0x1392},
{0x1d898, 0xd05a},
{0x1d899, 0x56a3},
{0x1d89a, 0xdfba},
{0x1d89b, 0x0383},
{0x1d89c, 0x6f72},
{0x1d89d, 0x1002},
{0x1d89e, 0x2a64},
{0x1d89f, 0x3014},
{0x1d8a0, 0x2005},
{0x1d8a1, 0x3d75},
{0x1d8a2, 0xc451},
{0x1d8a3, 0x2a42},
{0x1d8a4, 0x3022},
{0x1d8a5, 0x1002},
{0x1d8a6, 0x178c},
{0x1d8a7, 0x1898},
{0x1d8a8, 0x19a4},
{0x1d8a9, 0x1ab0},
{0x1d8aa, 0x1bbc},
{0x1d8ab, 0x1cc8},
{0x1d8ac, 0x1dd3},
{0x1d8ad, 0x1ede},
{0x1d8ae, 0x1fe9},
{0x1d8af, 0x20f4},
{0x1d8b0, 0x21ff},
{0x1d8b1, 0x0000},
{0x1d8b2, 0x27e1},
{0x1d8b3, 0x3021},
{0x1d8b4, 0x1001},
{0x1d8b5, 0xc620},
{0x1d8b6, 0x0000},
{0x1d8b7, 0xc621},
{0x1d8b8, 0x0000},
{0x1d8b9, 0xc622},
{0x1d8ba, 0x00e2},
{0x1d8bb, 0xc623},
{0x1d8bc, 0x007f},
{0x1d8bd, 0xc624},
{0x1d8be, 0x00ce},
{0x1d8bf, 0xc625},
{0x1d8c0, 0x0000},
{0x1d8c1, 0xc627},
{0x1d8c2, 0x0000},
{0x1d8c3, 0xc628},
{0x1d8c4, 0x0000},
{0x1d8c5, 0xc90a},
{0x1d8c6, 0x3a7c},
{0x1d8c7, 0xc62c},
{0x1d8c8, 0x0000},
{0x1d8c9, 0x0000},
{0x1d8ca, 0x27e1},
{0x1d8cb, 0x3021},
{0x1d8cc, 0x1001},
{0x1d8cd, 0xc502},
{0x1d8ce, 0x53ac},
{0x1d8cf, 0xc503},
{0x1d8d0, 0x2cd3},
{0x1d8d1, 0xc600},
{0x1d8d2, 0x2a6e},
{0x1d8d3, 0xc601},
{0x1d8d4, 0x2a2c},
{0x1d8d5, 0xc605},
{0x1d8d6, 0x5557},
{0x1d8d7, 0xc60c},
{0x1d8d8, 0x5400},
{0x1d8d9, 0xc710},
{0x1d8da, 0x0700},
{0x1d8db, 0xc711},
{0x1d8dc, 0x0f06},
{0x1d8dd, 0xc718},
{0x1d8de, 0x0700},
{0x1d8df, 0xc719},
{0x1d8e0, 0x0f06},
{0x1d8e1, 0xc720},
{0x1d8e2, 0x4700},
{0x1d8e3, 0xc721},
{0x1d8e4, 0x0f06},
{0x1d8e5, 0xc728},
{0x1d8e6, 0x0700},
{0x1d8e7, 0xc729},
{0x1d8e8, 0x1207},
{0x1d8e9, 0xc801},
{0x1d8ea, 0x7f50},
{0x1d8eb, 0xc802},
{0x1d8ec, 0x7760},
{0x1d8ed, 0xc803},
{0x1d8ee, 0x7fce},
{0x1d8ef, 0xc804},
{0x1d8f0, 0x520e},
{0x1d8f1, 0xc805},
{0x1d8f2, 0x5c11},
{0x1d8f3, 0xc806},
{0x1d8f4, 0x3c51},
{0x1d8f5, 0xc807},
{0x1d8f6, 0x4061},
{0x1d8f7, 0xc808},
{0x1d8f8, 0x49c1},
{0x1d8f9, 0xc809},
{0x1d8fa, 0x3840},
{0x1d8fb, 0xc80a},
{0x1d8fc, 0x0000},
{0x1d8fd, 0xc821},
{0x1d8fe, 0x0002},
{0x1d8ff, 0xc822},
{0x1d900, 0x0046},
{0x1d901, 0xc844},
{0x1d902, 0x182f},
{0x1d903, 0xc849},
{0x1d904, 0x0400},
{0x1d905, 0xc84a},
{0x1d906, 0x0002},
{0x1d907, 0xc013},
{0x1d908, 0xf341},
{0x1d909, 0xc084},
{0x1d90a, 0x0030},
{0x1d90b, 0xc904},
{0x1d90c, 0x1401},
{0x1d90d, 0xcb0c},
{0x1d90e, 0x0004},
{0x1d90f, 0xcb0e},
{0x1d910, 0xa00a},
{0x1d911, 0xcb0f},
{0x1d912, 0xc0c0},
{0x1d913, 0xcb10},
{0x1d914, 0xc0c0},
{0x1d915, 0xcb11},
{0x1d916, 0x00a0},
{0x1d917, 0xcb12},
{0x1d918, 0x0007},
{0x1d919, 0xc241},
{0x1d91a, 0xa000},
{0x1d91b, 0xc243},
{0x1d91c, 0x7fe0},
{0x1d91d, 0xc604},
{0x1d91e, 0x000e},
{0x1d91f, 0xc609},
{0x1d920, 0x00f5},
{0x1d921, 0x0c61},
{0x1d922, 0x000e},
{0x1d923, 0xc660},
{0x1d924, 0x9600},
{0x1d925, 0xc687},
{0x1d926, 0x0004},
{0x1d927, 0xc60a},
{0x1d928, 0x04f5},
{0x1d929, 0x0000},
{0x1d92a, 0x27e1},
{0x1d92b, 0x3021},
{0x1d92c, 0x1001},
{0x1d92d, 0xc620},
{0x1d92e, 0x14e5},
{0x1d92f, 0xc621},
{0x1d930, 0xc53d},
{0x1d931, 0xc622},
{0x1d932, 0x3cbe},
{0x1d933, 0xc623},
{0x1d934, 0x4452},
{0x1d935, 0xc624},
{0x1d936, 0xc5c5},
{0x1d937, 0xc625},
{0x1d938, 0xe01e},
{0x1d939, 0xc627},
{0x1d93a, 0x0000},
{0x1d93b, 0xc628},
{0x1d93c, 0x0000},
{0x1d93d, 0xc62c},
{0x1d93e, 0x0000},
{0x1d93f, 0xc90a},
{0x1d940, 0x3a7c},
{0x1d941, 0x0000},
{0x1d942, 0x2b84},
{0x1d943, 0x3c74},
{0x1d944, 0x6435},
{0x1d945, 0xdff4},
{0x1d946, 0x6435},
{0x1d947, 0x2806},
{0x1d948, 0x3006},
{0x1d949, 0x8565},
{0x1d94a, 0x2b24},
{0x1d94b, 0x3c24},
{0x1d94c, 0x6436},
{0x1d94d, 0x1002},
{0x1d94e, 0x2b24},
{0x1d94f, 0x3c24},
{0x1d950, 0x6436},
{0x1d951, 0x4045},
{0x1d952, 0x8656},
{0x1d953, 0x5663},
{0x1d954, 0x0302},
{0x1d955, 0x401e},
{0x1d956, 0x1002},
{0x1d957, 0x2017},
{0x1d958, 0x3b17},
{0x1d959, 0x2084},
{0x1d95a, 0x3c14},
{0x1d95b, 0x6724},
{0x1d95c, 0x2807},
{0x1d95d, 0x31a7},
{0x1d95e, 0x20c4},
{0x1d95f, 0x3c24},
{0x1d960, 0x6724},
{0x1d961, 0x2ff7},
{0x1d962, 0x30f7},
{0x1d963, 0x20c4},
{0x1d964, 0x3c04},
{0x1d965, 0x6724},
{0x1d966, 0x1002},
{0x1d967, 0x2807},
{0x1d968, 0x3187},
{0x1d969, 0x20c4},
{0x1d96a, 0x3c24},
{0x1d96b, 0x6724},
{0x1d96c, 0x2fe4},
{0x1d96d, 0x3dc4},
{0x1d96e, 0x6437},
{0x1d96f, 0x20c4},
{0x1d970, 0x3c04},
{0x1d971, 0x6724},
{0x1d972, 0x2017},
{0x1d973, 0x3d17},
{0x1d974, 0x2084},
{0x1d975, 0x3c14},
{0x1d976, 0x6724},
{0x1d977, 0x1002},
{0x1d978, 0x24f4},
{0x1d979, 0x3c64},
{0x1d97a, 0x6436},
{0x1d97b, 0xdff4},
{0x1d97c, 0x6436},
{0x1d97d, 0x1002},
{0x1d97e, 0x2006},
{0x1d97f, 0x3d76},
{0x1d980, 0xc161},
{0x1d981, 0x6134},
{0x1d982, 0x6135},
{0x1d983, 0x5443},
{0x1d984, 0x0303},
{0x1d985, 0x6524},
{0x1d986, 0x00fb},
{0x1d987, 0x1002},
{0x1d988, 0x20d4},
{0x1d989, 0x3c24},
{0x1d98a, 0x2025},
{0x1d98b, 0x3005},
{0x1d98c, 0x6524},
{0x1d98d, 0x1002},
{0x1d98e, 0xd019},
{0x1d98f, 0x2104},
{0x1d990, 0x3c24},
{0x1d991, 0x2105},
{0x1d992, 0x3805},
{0x1d993, 0x6524},
{0x1d994, 0xdff4},
{0x1d995, 0x4005},
{0x1d996, 0x6524},
{0x1d997, 0x2e8d},
{0x1d998, 0x303d},
{0x1d999, 0x2408},
{0x1d99a, 0x35d8},
{0x1d99b, 0x5dd3},
{0x1d99c, 0x0307},
{0x1d99d, 0x8887},
{0x1d99e, 0x63a7},
{0x1d99f, 0x8887},
{0x1d9a0, 0x63a7},
{0x1d9a1, 0xdffd},
{0x1d9a2, 0x00f9},
{0x1d9a3, 0x1002},
{0x1d9a4, 0x866a},
{0x1d9a5, 0x6138},
{0x1d9a6, 0x5883},
{0x1d9a7, 0x2b42},
{0x1d9a8, 0x3022},
{0x1d9a9, 0x1302},
{0x1d9aa, 0x2ff7},
{0x1d9ab, 0x3007},
{0x1d9ac, 0x8785},
{0x1d9ad, 0xb887},
{0x1d9ae, 0x8786},
{0x1d9af, 0xb8c6},
{0x1d9b0, 0x5a53},
{0x1d9b1, 0x2a52},
{0x1d9b2, 0x3022},
{0x1d9b3, 0x13c2},
{0x1d9b4, 0x2474},
{0x1d9b5, 0x3c84},
{0x1d9b6, 0x64d7},
{0x1d9b7, 0x64d7},
{0x1d9b8, 0x2ff5},
{0x1d9b9, 0x3c05},
{0x1d9ba, 0x8757},
{0x1d9bb, 0xb886},
{0x1d9bc, 0x9767},
{0x1d9bd, 0x67c4},
{0x1d9be, 0x6f72},
{0x1d9bf, 0x1002},
{0x1d9c0, 0x0000},
{0x1d080, 0x0100},
{0x1d092, 0x0000},
{NLP_INI_STOP, 0},
};
static nxge_status_t
nxge_nlp2020_xcvr_init(p_nxge_t nxgep)
{
uint8_t phy_port_addr;
nxge_status_t status = NXGE_OK;
uint16_t ctrl_reg, rst_val, pmd_ctl, rx_los;
int i = 0, count = 1000;
uint8_t connector = 0, len, lpm;
p_nxge_nlp_initseq_t initseq;
uint16_t dev, reg, val;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_nlp2020_xcvr_init: "
"port<%d>, phyaddr[0x%x]", nxgep->mac.portnum,
nxgep->statsp->mac_stats.xcvr_portn));
phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
rst_val = ctrl_reg = NLP2020_PMA_PMD_PHY_RST;
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, rst_val))
!= NXGE_OK)
goto fail;
while ((count--) && (ctrl_reg & rst_val)) {
drv_usecwait(1000);
(void) nxge_mdio_read(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &ctrl_reg);
}
if (count == 0) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_nlp2020_xcvr_init: "
"PMA_PMD reset failed"));
goto fail;
}
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &pmd_ctl))
!= NXGE_OK)
goto fail;
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
pmd_ctl |= 0x0001;
else
pmd_ctl &= 0xfffe;
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, pmd_ctl))
!= NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_nlp2020_xcvr_init: "
"setting LB, wrote NLP2020_PMA_PMD_CTL_REG[0x%x]", pmd_ctl));
if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
QSFP_MSA_CONN_REG, &connector) == 1) {
goto fail;
}
switch (connector) {
case SFPP_FIBER:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_nlp2020_xcvr_init: SFPP_FIBER detected"));
initseq = nlp2020_revC_fiber_init;
nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
break;
case QSFP_FIBER:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_nlp2020_xcvr_init: QSFP_FIBER detected"));
initseq = nlp2020_revC_fiber_init;
nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
break;
case QSFP_COPPER_TWINAX:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_nlp2020_xcvr_init: QSFP_COPPER_TWINAX/"
"SFPP_COPPER_TWINAX detected"));
initseq = nlp2020_revC_copper_init;
nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_LT_7M;
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_nlp2020_xcvr_init: Unknown type [0x%x] detected",
"...setting to QSFP_FIBER",
connector));
initseq = nlp2020_revC_fiber_init;
nxgep->nlp_conn = NXGE_NLP_CONN_FIBER;
break;
}
for (i = 0; initseq[i].dev_reg != NLP_INI_STOP; i++) {
dev = initseq[i].dev_reg >> 16;
reg = initseq[i].dev_reg & 0xffff;
val = initseq[i].val;
if (reg == NLP_INI_WAIT) {
drv_usecwait(1000 * val);
} else {
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
dev, reg, val)) != NXGE_OK)
goto fail;
}
}
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, &rx_los)) != NXGE_OK)
goto fail;
rx_los &= ~(NLP2020_RXLOS_ACT_H);
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, rx_los)) != NXGE_OK)
goto fail;
if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
QSFP_MSA_LEN_REG, &len) == 1) {
goto fail;
}
if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR,
QSFP_MSA_LPM_REG, &lpm) == 1) {
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_nlp2020_xcvr_init: len[0x%x] lpm[0x%x]", len, lpm));
if (connector == QSFP_COPPER_TWINAX) {
if (len >= 7) {
nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_7M_ABOVE;
(void) nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL1_REG,
NLP2020_TX_DRV_CTL1_PREEMP_EN);
(void) nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL2_REG,
NLP2020_TX_DRV_CTL2_EMP_VAL);
(void) nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
NLP2020_UC_CTL_STOP);
(void) nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_UC_PC_START_REG,
NLP2020_UC_PC_START_VAL);
(void) nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG,
NLP2020_UC_CTL_START);
}
}
if (lpm & QSFP_MSA_LPM_HIGH) {
(void) nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
NLP2020_GPIO_ACT);
} else {
(void) nxge_mdio_write(nxgep, phy_port_addr,
NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG,
NLP2020_GPIO_INACT);
}
NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status);
if (status != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_nlp2020_xcvr_init: Failed setting PHY tunables"));
goto fail;
}
drv_usecwait(2000000);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_nlp2020_xcvr_init: "
"port<%d> phyaddr[0x%x]", nxgep->mac.portnum, phy_port_addr));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_nlp2020_xcvr_init: failed to initialize transceiver for "
"port<%d>", nxgep->mac.portnum));
return (status);
}
static boolean_t nxge_is_nlp2020_phy(p_nxge_t nxgep)
{
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
uint32_t pcs_id = 0;
uint32_t pma_pmd_id = 0;
uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, xcvr_addr);
pcs_id = nxge_get_cl45_pcs_id(nxgep, xcvr_addr);
if (((pma_pmd_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) ||
((pcs_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID)) {
return (B_TRUE);
} else {
return (B_FALSE);
}
}
static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t nxgep)
{
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
uint8_t connector = 0;
(void) nxge_nlp2020_i2c_read(nxgep, xcvr_addr, NLP2020_XCVR_I2C_ADDR,
QSFP_MSA_CONN_REG, &connector);
return (connector);
}
static nxge_status_t nxge_set_nlp2020_param(p_nxge_t nxgep)
{
uint8_t connector = 0;
connector = nxge_get_nlp2020_connector_type(nxgep);
switch (connector) {
case SFPP_FIBER:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_set_nlp2020_param: SFPP_FIBER detected"));
nxgep->mac.portmode = PORT_10G_FIBER;
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
break;
case QSFP_FIBER:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_set_nlp2020_param: QSFP_FIBER detected"));
nxgep->mac.portmode = PORT_10G_FIBER;
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
break;
case QSFP_COPPER_TWINAX:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_set_nlp2020_param: QSFP_COPPER_TWINAX/"
"SFPP_COPPER_TWINAX detected"));
nxgep->mac.portmode = PORT_10G_COPPER;
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_set_nlp2020_param: Unknown type [0x%x] detected"
"...setting to QSFP_FIBER",
connector));
nxgep->mac.portmode = PORT_10G_FIBER;
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
break;
}
return (NXGE_OK);
}
#define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail
#define MRVL88X2011_RD(nxgep, port, d, r, p) \
CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p))
#define MRVL88X2011_WR(nxgep, port, d, r, p) \
CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p))
static void
nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate)
{
uint16_t value;
uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) {
value &= ~MRVL_88X2011_LED_BLK_MASK;
value |= (rate << MRVL_88X2011_LED_BLK_SHIFT);
(void) nxge_mdio_write(nxgep, phy,
MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL,
value);
}
}
static nxge_status_t
nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep)
{
nxge_status_t status;
pcs_control_t pcs_ctl;
uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value);
if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g)
pcs_ctl.bits.loopback = 1;
else
pcs_ctl.bits.loopback = 0;
MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value);
fail:
return (status);
}
static void
nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val)
{
uint16_t val2;
uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn;
val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT,
MRVL_88X2011_LED_CTL_MASK);
val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val);
if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR,
MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
}
}
static nxge_status_t
nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep)
{
uint8_t phy;
nxge_status_t status;
uint16_t clk;
phy = nxgep->statsp->mac_stats.xcvr_portn;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
nxgep->mac.portnum, phy));
nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS);
nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT);
MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
MRVL_88X2011_GEN_CTL, &clk);
clk |= MRVL_88X2011_ENA_XFPREFCLK;
MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
MRVL_88X2011_GEN_CTL, clk);
CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep));
MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK"));
fail:
return (status);
}
static nxge_status_t
nxge_10G_xcvr_init(p_nxge_t nxgep)
{
p_nxge_stats_t statsp;
p_nxge_param_t param_arr = nxgep->param_arr;
nxge_status_t status = NXGE_OK;
#ifdef NXGE_DEBUG
uint8_t portn = nxgep->mac.portnum;
#endif
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
portn));
statsp = nxgep->statsp;
if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
goto done;
if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) {
goto done;
}
npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
switch (nxgep->chip_id) {
case BCM8704_CHIP_ID:
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
"Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id));
status = nxge_BCM8704_xcvr_init(nxgep);
break;
case BCM8706_CHIP_ID:
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
"Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id));
status = nxge_BCM8706_xcvr_init(nxgep);
break;
case MRVL88X201X_CHIP_ID:
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
"Chip ID MRVL [0x%x] for 10G xcvr", nxgep->chip_id));
status = nxge_mrvl88x2011_xcvr_init(nxgep);
break;
case NLP2020_CHIP_ID:
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: "
"Chip ID NL2020 [0x%x] for 10G xcvr", nxgep->chip_id));
status = nxge_nlp2020_xcvr_init(nxgep);
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: "
"Unknown chip ID 0x%x for 10G xcvr addr[%d]",
nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn));
goto fail;
}
if (status != NXGE_OK) {
goto fail;
}
done:
statsp->mac_stats.cap_10gfdx = 1;
statsp->mac_stats.lp_cap_10gfdx = 1;
statsp->mac_stats.adv_cap_asmpause =
param_arr[param_anar_asmpause].value;
statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_10G_xcvr_init: failed to initialize transceiver for "
"port<%d>", nxgep->mac.portnum));
return (NXGE_ERROR);
}
static nxge_status_t
nxge_1G_xcvr_init(p_nxge_t nxgep)
{
p_nxge_param_t param_arr = nxgep->param_arr;
p_nxge_stats_t statsp = nxgep->statsp;
nxge_status_t status = NXGE_OK;
if (nxgep->mac.portmode == PORT_1G_SERDES) {
statsp->mac_stats.cap_1000fdx =
param_arr[param_anar_1000fdx].value;
goto done;
}
npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE);
statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value;
if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
(nxgep->mac.portmode == PORT_1G_FIBER)) {
statsp->mac_stats.cap_100fdx =
param_arr[param_anar_100fdx].value;
statsp->mac_stats.cap_10fdx =
param_arr[param_anar_10fdx].value;
}
status = nxge_mii_xcvr_init(nxgep);
done:
return (status);
}
static nxge_status_t
nxge_tn1010_xcvr_init(p_nxge_t nxgep)
{
p_nxge_param_t param_arr;
p_nxge_stats_t statsp;
tn1010_pcs_ctrl_t tn1010_pcs_ctrl;
uint16_t speed;
uint8_t phy_port_addr;
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
int status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init"));
param_arr = nxgep->param_arr;
statsp = nxgep->statsp;
statsp->mac_stats.cap_autoneg = 1;
statsp->mac_stats.cap_100T4 = 0;
if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) {
goto fail;
}
if (speed == TN1010_SPEED_1G) {
statsp->mac_stats.cap_10gfdx = 0;
} else {
statsp->mac_stats.cap_10gfdx = 1;
}
statsp->mac_stats.cap_1000fdx = 1;
statsp->mac_stats.cap_1000hdx = 0;
statsp->mac_stats.cap_100fdx = 0;
statsp->mac_stats.cap_100hdx = 0;
statsp->mac_stats.cap_10fdx = 0;
statsp->mac_stats.cap_10hdx = 0;
statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
statsp->mac_stats.adv_cap_autoneg
= param_arr[param_autoneg].value = 1;
statsp->mac_stats.adv_cap_1000fdx
= param_arr[param_anar_1000fdx].value = 1;
statsp->mac_stats.adv_cap_100fdx
= param_arr[param_anar_100fdx].value = 0;
statsp->mac_stats.adv_cap_10fdx
= param_arr[param_anar_10fdx].value = 0;
statsp->mac_stats.adv_cap_100T4
= param_arr[param_anar_100T4].value = 0;
statsp->mac_stats.adv_cap_1000hdx
= param_arr[param_anar_1000hdx].value = 0;
statsp->mac_stats.adv_cap_100hdx
= param_arr[param_anar_100hdx].value = 0;
statsp->mac_stats.adv_cap_10hdx
= param_arr[param_anar_10hdx].value = 0;
statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
statsp->mac_stats.adv_cap_asmpause
= param_arr[param_anar_asmpause].value;
statsp->mac_stats.link_T4 = 0;
statsp->mac_stats.link_asmpause = 0;
statsp->mac_stats.link_pause = 0;
if (speed == TN1010_SPEED_1G) {
statsp->mac_stats.link_speed = 1000;
statsp->mac_stats.link_duplex = 2;
statsp->mac_stats.link_up = 1;
} else {
statsp->mac_stats.link_speed = 10000;
statsp->mac_stats.link_duplex = 2;
statsp->mac_stats.link_up = 1;
}
if (speed == TN1010_SPEED_1G) {
statsp->mac_stats.lp_cap_1000fdx = 1;
statsp->mac_stats.lp_cap_10gfdx = 0;
} else {
statsp->mac_stats.lp_cap_1000fdx = 0;
statsp->mac_stats.lp_cap_10gfdx = 1;
}
statsp->mac_stats.lp_cap_10ghdx = 0;
statsp->mac_stats.lp_cap_1000hdx = 0;
statsp->mac_stats.lp_cap_100fdx = 0;
statsp->mac_stats.lp_cap_100hdx = 0;
statsp->mac_stats.lp_cap_10fdx = 0;
statsp->mac_stats.lp_cap_10hdx = 0;
statsp->mac_stats.lp_cap_10gfdx = 0;
statsp->mac_stats.lp_cap_10ghdx = 0;
statsp->mac_stats.lp_cap_100T4 = 0;
statsp->mac_stats.lp_cap_autoneg = 1;
statsp->mac_stats.lp_cap_asmpause = 0;
statsp->mac_stats.lp_cap_pause = 0;
npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
&tn1010_pcs_ctrl.value)) != NXGE_OK) {
goto fail;
}
if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) ||
(statsp->port_stats.lb_mode == nxge_lb_phy10g)) {
tn1010_pcs_ctrl.bits.loopback = 1;
} else {
tn1010_pcs_ctrl.bits.loopback = 0;
}
if ((status = nxge_mdio_write(nxgep, phy_port_addr,
TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG,
tn1010_pcs_ctrl.value)) != NXGE_OK) {
goto fail;
}
statsp->mac_stats.xcvr_inits++;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
return (status);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
return (status);
}
nxge_status_t
nxge_xcvr_init(p_nxge_t nxgep)
{
p_nxge_stats_t statsp;
#ifdef NXGE_DEBUG
uint8_t portn;
#endif
nxge_status_t status = NXGE_OK;
#ifdef NXGE_DEBUG
portn = nxgep->mac.portnum;
#endif
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn));
statsp = nxgep->statsp;
statsp->mac_stats.cap_autoneg = 0;
statsp->mac_stats.cap_100T4 = 0;
statsp->mac_stats.cap_100fdx = 0;
statsp->mac_stats.cap_100hdx = 0;
statsp->mac_stats.cap_10fdx = 0;
statsp->mac_stats.cap_10hdx = 0;
statsp->mac_stats.cap_asmpause = 0;
statsp->mac_stats.cap_pause = 0;
statsp->mac_stats.cap_1000fdx = 0;
statsp->mac_stats.cap_1000hdx = 0;
statsp->mac_stats.cap_10gfdx = 0;
statsp->mac_stats.cap_10ghdx = 0;
statsp->mac_stats.link_T4 = 0;
statsp->mac_stats.link_asmpause = 0;
statsp->mac_stats.link_pause = 0;
if (nxgep->xcvr.xcvr_init) {
status = nxgep->xcvr.xcvr_init(nxgep);
if (status != NXGE_OK)
goto fail;
statsp->mac_stats.xcvr_inits++;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_xcvr_init: failed to initialize transceiver for port<%d>",
portn));
return (status);
}
nxge_status_t
nxge_xcvr_find(p_nxge_t nxgep)
{
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>",
nxgep->mac.portnum));
if (nxge_get_xcvr_type(nxgep) != NXGE_OK)
return (NXGE_ERROR);
if (nxge_setup_xcvr_table(nxgep) != NXGE_OK)
return (NXGE_ERROR);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d",
nxgep->statsp->mac_stats.xcvr_inuse));
return (NXGE_OK);
}
nxge_status_t
nxge_tx_mac_init(p_nxge_t nxgep)
{
npi_attr_t ap;
uint8_t portn;
nxge_port_mode_t portmode;
nxge_port_t portt;
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
portt = nxgep->mac.porttype;
handle = nxgep->npi_handle;
portmode = nxgep->mac.portmode;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>",
portn));
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_tx_mac_init: port<%d> "
"min framesize %d max framesize %d ",
nxgep->mac.minframesize,
nxgep->mac.maxframesize,
portn));
SET_MAC_ATTR2(handle, ap, portn,
MAC_PORT_FRAME_SIZE,
nxgep->mac.minframesize,
nxgep->mac.maxframesize,
rs);
if (rs != NPI_SUCCESS)
goto fail;
if (portt == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn,
0)) != NPI_SUCCESS)
goto fail;
nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS;
if ((portmode == PORT_10G_FIBER) ||
(portmode == PORT_10G_COPPER) ||
(portmode == PORT_10G_TN1010) ||
(portmode == PORT_HSP_MODE) ||
(portmode == PORT_10G_SERDES)) {
SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG,
XGMII_IPG_12_15, rs);
if (rs != NPI_SUCCESS)
goto fail;
nxgep->mac.ipg[0] = XGMII_IPG_12_15;
} else {
SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG,
MII_GMII_IPG_12, rs);
if (rs != NPI_SUCCESS)
goto fail;
nxgep->mac.ipg[0] = MII_GMII_IPG_12;
}
if ((rs = npi_xmac_tx_config(handle, INIT, portn,
CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS)
goto fail;
nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX;
nxgep->mac.maxburstsize = 0;
nxgep->mac.ctrltype = 0;
nxgep->mac.pa_size = 0;
if ((rs = npi_xmac_zap_tx_counters(handle, portn))
!= NPI_SUCCESS)
goto fail;
} else {
if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn,
0)) != NPI_SUCCESS)
goto fail;
nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS;
SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808,
rs);
if (rs != NPI_SUCCESS)
goto fail;
nxgep->mac.ctrltype = 0x8808;
SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs);
if (rs != NPI_SUCCESS)
goto fail;
nxgep->mac.pa_size = 0x7;
if ((rs = npi_bmac_tx_config(handle, INIT, portn,
CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS)
goto fail;
nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
return (NXGE_ERROR | rs);
}
static npi_status_t
nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep)
{
uint32_t i;
uint16_t hashtab_e;
p_hash_filter_t hash_filter;
uint8_t portn;
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
handle = nxgep->npi_handle;
hash_filter = nxgep->hash_filter;
for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
if (hash_filter != NULL) {
hashtab_e = (uint16_t)hash_filter->hash_filter_regs[
(NMCFILTER_REGS - 1) - i];
} else {
hashtab_e = 0;
}
if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i,
(uint16_t *)&hashtab_e)) != NPI_SUCCESS)
return (rs);
}
return (NPI_SUCCESS);
}
nxge_status_t
nxge_rx_mac_init(p_nxge_t nxgep)
{
npi_attr_t ap;
nxge_port_t portt;
uint8_t portn;
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
uint16_t *addr16p;
uint16_t addr0, addr1, addr2;
xmac_rx_config_t xconfig;
bmac_rx_config_t bconfig;
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n",
portn));
handle = nxgep->npi_handle;
portt = nxgep->mac.porttype;
addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet;
addr0 = ntohs(addr16p[2]);
addr1 = ntohs(addr16p[1]);
addr2 = ntohs(addr16p[0]);
SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR,
addr0, addr1, addr2, rs);
if (rs != NPI_SUCCESS)
goto fail;
SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs);
if (rs != NPI_SUCCESS)
goto fail;
SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs);
if (rs != NPI_SUCCESS)
goto fail;
rs = nxge_rx_mac_mcast_hash_table(nxgep);
if (rs != NPI_SUCCESS)
goto fail;
if (portt == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn,
0)) != NPI_SUCCESS)
goto fail;
nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS;
(void) nxge_fflp_init_hostinfo(nxgep);
xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK |
CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK &
~CFG_XMAC_RX_STRIP_CRC;
if (nxgep->filter.all_phys_cnt != 0)
xconfig |= CFG_XMAC_RX_PROMISCUOUS;
if (nxgep->filter.all_multicast_cnt != 0)
xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP;
xconfig |= CFG_XMAC_RX_HASH_FILTER;
if ((rs = npi_xmac_rx_config(handle, INIT,
portn, xconfig)) != NPI_SUCCESS)
goto fail;
nxgep->mac.rx_config = xconfig;
if ((rs = npi_xmac_zap_rx_counters(handle, portn))
!= NPI_SUCCESS)
goto fail;
} else {
if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn,
0) != NPI_SUCCESS)
goto fail;
nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS;
(void) nxge_fflp_init_hostinfo(nxgep);
bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX &
~CFG_BMAC_RX_STRIP_CRC;
if (nxgep->filter.all_phys_cnt != 0)
bconfig |= CFG_BMAC_RX_PROMISCUOUS;
if (nxgep->filter.all_multicast_cnt != 0)
bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP;
bconfig |= CFG_BMAC_RX_HASH_FILTER;
if ((rs = npi_bmac_rx_config(handle, INIT,
portn, bconfig)) != NPI_SUCCESS)
goto fail;
nxgep->mac.rx_config = bconfig;
if ((rs = npi_mac_altaddr_enable(handle,
portn, 0)) != NPI_SUCCESS)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_tx_mac_enable(p_nxge_t nxgep)
{
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
nxge_status_t status = NXGE_OK;
handle = nxgep->npi_handle;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>",
nxgep->mac.portnum));
if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK)
goto fail;
nxgep->msg_min = ETHERMIN;
if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
CFG_XMAC_TX)) != NPI_SUCCESS)
goto fail;
} else {
if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum,
CFG_BMAC_TX)) != NPI_SUCCESS)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>",
nxgep->mac.portnum));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
nxgep->mac.portnum));
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (status);
}
nxge_status_t
nxge_tx_mac_disable(p_nxge_t nxgep)
{
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
if (isLDOMguest(nxgep))
return (NXGE_OK);
handle = nxgep->npi_handle;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>",
nxgep->mac.portnum));
if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_tx_config(handle, DISABLE,
nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS)
goto fail;
} else {
if ((rs = npi_bmac_tx_config(handle, DISABLE,
nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>",
nxgep->mac.portnum));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
nxgep->mac.portnum));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_rx_mac_enable(p_nxge_t nxgep)
{
npi_handle_t handle;
uint8_t portn;
npi_status_t rs = NPI_SUCCESS;
nxge_status_t status = NXGE_OK;
if (isLDOMguest(nxgep))
return (status);
handle = nxgep->npi_handle;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>",
portn));
if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
goto fail;
if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_rx_config(handle, ENABLE, portn,
CFG_XMAC_RX)) != NPI_SUCCESS)
goto fail;
} else {
if ((rs = npi_bmac_rx_config(handle, ENABLE, portn,
CFG_BMAC_RX)) != NPI_SUCCESS)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_rx_mac_enable: port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (status);
}
nxge_status_t
nxge_rx_mac_disable(p_nxge_t nxgep)
{
npi_handle_t handle;
uint8_t portn;
npi_status_t rs = NPI_SUCCESS;
if (isLDOMguest(nxgep))
return (NXGE_OK);
handle = nxgep->npi_handle;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>",
portn));
if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_rx_config(handle, DISABLE, portn,
CFG_XMAC_RX)) != NPI_SUCCESS)
goto fail;
} else {
if ((rs = npi_bmac_rx_config(handle, DISABLE, portn,
CFG_BMAC_RX)) != NPI_SUCCESS)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_tx_mac_reset(p_nxge_t nxgep)
{
npi_handle_t handle;
uint8_t portn;
npi_status_t rs = NPI_SUCCESS;
handle = nxgep->npi_handle;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>",
portn));
if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL))
!= NPI_SUCCESS)
goto fail;
} else {
if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET))
!= NPI_SUCCESS)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_rx_mac_reset(p_nxge_t nxgep)
{
npi_handle_t handle;
uint8_t portn;
npi_status_t rs = NPI_SUCCESS;
handle = nxgep->npi_handle;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>",
portn));
if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL))
!= NPI_SUCCESS)
goto fail;
} else {
if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET))
!= NPI_SUCCESS)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>",
portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
return (NXGE_ERROR | rs);
}
static nxge_status_t
nxge_10G_link_intr_start(p_nxge_t nxgep)
{
npi_status_t rs = NPI_SUCCESS;
uint8_t portn = nxgep->mac.portnum;
rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
static nxge_status_t
nxge_10G_link_intr_stop(p_nxge_t nxgep)
{
npi_status_t rs = NPI_SUCCESS;
uint8_t portn = nxgep->mac.portnum;
rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
static nxge_status_t
nxge_1G_fiber_link_intr_start(p_nxge_t nxgep)
{
npi_status_t rs = NPI_SUCCESS;
uint8_t portn = nxgep->mac.portnum;
rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
static nxge_status_t
nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep)
{
npi_status_t rs = NPI_SUCCESS;
uint8_t portn = nxgep->mac.portnum;
rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
static nxge_status_t
nxge_1G_copper_link_intr_start(p_nxge_t nxgep)
{
npi_status_t rs = NPI_SUCCESS;
uint8_t portn = nxgep->mac.portnum;
rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn,
MII_STATUS, MII_STATUS_LINKUP);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
static nxge_status_t
nxge_1G_copper_link_intr_stop(p_nxge_t nxgep)
{
npi_status_t rs = NPI_SUCCESS;
uint8_t portn = nxgep->mac.portnum;
rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn);
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
nxge_status_t
nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable)
{
uint8_t portn;
nxge_status_t status = NXGE_OK;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn));
if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start)
return (NXGE_OK);
if (enable == LINK_INTR_START)
status = nxgep->xcvr.link_intr_start(nxgep);
else if (enable == LINK_INTR_STOP)
status = nxgep->xcvr.link_intr_stop(nxgep);
if (status != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
return (status);
}
nxge_status_t
nxge_mii_xcvr_init(p_nxge_t nxgep)
{
p_nxge_param_t param_arr;
p_nxge_stats_t statsp;
uint8_t xcvr_portn;
p_mii_regs_t mii_regs;
mii_bmcr_t bmcr;
mii_bmsr_t bmsr;
mii_anar_t anar;
mii_gcr_t gcr;
mii_esr_t esr;
mii_aux_ctl_t bcm5464r_aux;
int status = NXGE_OK;
uint_t delay;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init"));
param_arr = nxgep->param_arr;
statsp = nxgep->statsp;
xcvr_portn = statsp->mac_stats.xcvr_portn;
mii_regs = NULL;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
(void) nxge_mii_get_link_mode(nxgep);
if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
return (nxge_mii_xcvr_fiber_init(nxgep));
}
delay = 0;
bmcr.value = 0;
bmcr.bits.reset = 1;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)&mii_regs->bmcr,
bmcr.value)) != NXGE_OK)
goto fail;
do {
drv_usecwait(500);
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)&mii_regs->bmcr,
&bmcr.value)) != NXGE_OK)
goto fail;
delay++;
} while ((bmcr.bits.reset) && (delay < 1000));
if (delay == 1000) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
goto fail;
}
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmsr),
&bmsr.value)) != NXGE_OK)
goto fail;
param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4;
param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx;
param_arr[param_anar_100hdx].value = 0;
param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx;
param_arr[param_anar_10hdx].value = 0;
statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4;
statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx;
statsp->mac_stats.cap_100hdx = 0;
statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx;
statsp->mac_stats.cap_10hdx = 0;
statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
statsp->mac_stats.adv_cap_asmpause =
param_arr[param_anar_asmpause].value;
statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
if (bmsr.bits.extend_status) {
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->esr),
&esr.value)) != NXGE_OK)
goto fail;
param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx;
param_arr[param_anar_1000hdx].value = 0;
statsp->mac_stats.cap_1000fdx =
(esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
statsp->mac_stats.cap_1000hdx = 0;
} else {
param_arr[param_anar_1000fdx].value = 0;
param_arr[param_anar_1000hdx].value = 0;
}
statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
statsp->mac_stats.link_T4 = 0;
statsp->mac_stats.link_asmpause = 0;
statsp->mac_stats.link_pause = 0;
statsp->mac_stats.link_speed = 0;
statsp->mac_stats.link_duplex = 0;
statsp->mac_stats.link_up = 0;
bmcr.value = 0;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr),
bmcr.value)) != NXGE_OK)
goto fail;
if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
bmcr.bits.loopback = 1;
bmcr.bits.enable_autoneg = 0;
if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
bmcr.bits.speed_1000_sel = 1;
bmcr.bits.duplex_mode = 1;
param_arr[param_autoneg].value = 0;
} else {
bmcr.bits.loopback = 0;
}
if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
param_arr[param_autoneg].value = 0;
bcm5464r_aux.value = 0;
bcm5464r_aux.bits.ext_lb = 1;
bcm5464r_aux.bits.write_1 = 1;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
goto fail;
}
if (param_arr[param_autoneg].value) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Restarting Auto-negotiation."));
anar.value = 0;
anar.bits.selector = 1;
anar.bits.cap_100T4 = param_arr[param_anar_100T4].value;
anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value;
anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value;
anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value;
anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value;
anar.bits.cap_asmpause = 0;
anar.bits.cap_pause = 0;
if (param_arr[param_anar_1000fdx].value ||
param_arr[param_anar_100fdx].value ||
param_arr[param_anar_10fdx].value) {
anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause;
anar.bits.cap_pause = statsp->mac_stats.cap_pause;
}
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->anar),
anar.value)) != NXGE_OK)
goto fail;
if (bmsr.bits.extend_status) {
gcr.value = 0;
gcr.bits.ms_mode_en =
param_arr[param_master_cfg_enable].value;
gcr.bits.master =
param_arr[param_master_cfg_value].value;
gcr.bits.link_1000fdx =
param_arr[param_anar_1000fdx].value;
gcr.bits.link_1000hdx =
param_arr[param_anar_1000hdx].value;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->gcr),
gcr.value)) != NXGE_OK)
goto fail;
}
bmcr.bits.enable_autoneg = 1;
bmcr.bits.restart_autoneg = 1;
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
bmcr.bits.speed_1000_sel =
param_arr[param_anar_1000fdx].value |
param_arr[param_anar_1000hdx].value;
bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) &
(param_arr[param_anar_100fdx].value |
param_arr[param_anar_100hdx].value);
if (bmcr.bits.speed_1000_sel) {
statsp->mac_stats.link_speed = 1000;
gcr.value = 0;
gcr.bits.ms_mode_en =
param_arr[param_master_cfg_enable].value;
gcr.bits.master =
param_arr[param_master_cfg_value].value;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->gcr),
gcr.value)) != NXGE_OK)
goto fail;
if (param_arr[param_anar_1000fdx].value) {
bmcr.bits.duplex_mode = 1;
statsp->mac_stats.link_duplex = 2;
} else
statsp->mac_stats.link_duplex = 1;
} else if (bmcr.bits.speed_sel) {
statsp->mac_stats.link_speed = 100;
if (param_arr[param_anar_100fdx].value) {
bmcr.bits.duplex_mode = 1;
statsp->mac_stats.link_duplex = 2;
} else
statsp->mac_stats.link_duplex = 1;
} else {
statsp->mac_stats.link_speed = 10;
if (param_arr[param_anar_10fdx].value) {
bmcr.bits.duplex_mode = 1;
statsp->mac_stats.link_duplex = 2;
} else
statsp->mac_stats.link_duplex = 1;
}
if (statsp->mac_stats.link_duplex != 1) {
statsp->mac_stats.link_asmpause =
statsp->mac_stats.cap_asmpause;
statsp->mac_stats.link_pause =
statsp->mac_stats.cap_pause;
}
if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) ||
(statsp->port_stats.lb_mode == nxge_lb_ext100) ||
(statsp->port_stats.lb_mode == nxge_lb_ext10)) {
if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
gcr.value = 0;
gcr.bits.ms_mode_en = 1;
gcr.bits.master = 1;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->gcr),
gcr.value)) != NXGE_OK)
goto fail;
bmcr.value = 0;
bmcr.bits.speed_1000_sel = 1;
statsp->mac_stats.link_speed = 1000;
} else if (statsp->port_stats.lb_mode
== nxge_lb_ext100) {
bmcr.value = 0;
bmcr.bits.speed_sel = 1;
bmcr.bits.duplex_mode = 1;
statsp->mac_stats.link_speed = 100;
} else if (statsp->port_stats.lb_mode
== nxge_lb_ext10) {
bmcr.value = 0;
bmcr.bits.duplex_mode = 1;
statsp->mac_stats.link_speed = 10;
}
}
}
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr),
bmcr.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr),
&bmcr.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value));
nxgep->soft_bmsr.value = 0;
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmsr),
&nxgep->bmsr.value)) != NXGE_OK)
goto fail;
statsp->mac_stats.xcvr_inits++;
nxgep->bmsr.value = 0;
fail:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_mii_xcvr_init status 0x%x", status));
return (status);
}
nxge_status_t
nxge_mii_xcvr_fiber_init(p_nxge_t nxgep)
{
p_nxge_param_t param_arr;
p_nxge_stats_t statsp;
uint8_t xcvr_portn;
p_mii_regs_t mii_regs;
mii_bmcr_t bmcr;
mii_bmsr_t bmsr;
mii_gcr_t gcr;
mii_esr_t esr;
mii_aux_ctl_t bcm5464r_aux;
int status = NXGE_OK;
uint_t delay;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init"));
param_arr = nxgep->param_arr;
statsp = nxgep->statsp;
xcvr_portn = statsp->mac_stats.xcvr_portn;
mii_regs = NULL;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_mii_xcvr_fiber_init: "
"nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value));
delay = 0;
bmcr.value = 0;
bmcr.bits.reset = 1;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
goto fail;
do {
drv_usecwait(500);
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value))
!= NXGE_OK)
goto fail;
delay++;
} while ((bmcr.bits.reset) && (delay < 1000));
if (delay == 1000) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed."));
goto fail;
}
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK)
goto fail;
param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able;
param_arr[param_anar_100T4].value = 0;
param_arr[param_anar_100fdx].value = 0;
param_arr[param_anar_100hdx].value = 0;
param_arr[param_anar_10fdx].value = 0;
param_arr[param_anar_10hdx].value = 0;
statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able;
statsp->mac_stats.cap_100T4 = 0;
statsp->mac_stats.cap_100fdx = 0;
statsp->mac_stats.cap_100hdx = 0;
statsp->mac_stats.cap_10fdx = 0;
statsp->mac_stats.cap_10hdx = 0;
statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value;
statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value;
statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value;
statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value;
statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value;
statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value;
statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value;
statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value;
statsp->mac_stats.adv_cap_asmpause =
param_arr[param_anar_asmpause].value;
statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value;
if (bmsr.bits.extend_status) {
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) !=
NXGE_OK)
goto fail;
param_arr[param_anar_1000fdx].value &=
esr.bits.link_1000fdx;
param_arr[param_anar_1000hdx].value = 0;
statsp->mac_stats.cap_1000fdx =
(esr.bits.link_1000Xfdx || esr.bits.link_1000fdx);
statsp->mac_stats.cap_1000hdx = 0;
} else {
param_arr[param_anar_1000fdx].value = 0;
param_arr[param_anar_1000hdx].value = 0;
}
statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value;
statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value;
statsp->mac_stats.link_T4 = 0;
statsp->mac_stats.link_asmpause = 0;
statsp->mac_stats.link_pause = 0;
statsp->mac_stats.link_speed = 0;
statsp->mac_stats.link_duplex = 0;
statsp->mac_stats.link_up = 0;
bmcr.value = 0;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK)
goto fail;
if ((statsp->port_stats.lb_mode == nxge_lb_phy) ||
(statsp->port_stats.lb_mode == nxge_lb_phy1000)) {
bmcr.bits.loopback = 1;
bmcr.bits.enable_autoneg = 0;
if (statsp->port_stats.lb_mode == nxge_lb_phy1000)
bmcr.bits.speed_1000_sel = 1;
bmcr.bits.duplex_mode = 1;
param_arr[param_autoneg].value = 0;
} else {
bmcr.bits.loopback = 0;
}
if (statsp->port_stats.lb_mode == nxge_lb_ext1000) {
param_arr[param_autoneg].value = 0;
bcm5464r_aux.value = 0;
bcm5464r_aux.bits.ext_lb = 1;
bcm5464r_aux.bits.write_1 = 1;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK)
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode."));
bmcr.bits.speed_1000_sel = 1;
bmcr.bits.speed_sel = 0;
bmcr.bits.duplex_mode = 1;
statsp->mac_stats.link_speed = 1000;
statsp->mac_stats.link_duplex = 2;
if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) {
gcr.value = 0;
gcr.bits.ms_mode_en = 1;
gcr.bits.master = 1;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->gcr),
gcr.value)) != NXGE_OK)
goto fail;
bmcr.value = 0;
bmcr.bits.speed_1000_sel = 1;
statsp->mac_stats.link_speed = 1000;
}
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr),
bmcr.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
bmcr.value));
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value));
nxgep->soft_bmsr.value = 0;
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmsr),
&nxgep->bmsr.value)) != NXGE_OK)
goto fail;
statsp->mac_stats.xcvr_inits++;
nxgep->bmsr.value = 0;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_mii_xcvr_fiber_init status 0x%x", status));
return (status);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_mii_xcvr_fiber_init status 0x%x", status));
return (status);
}
nxge_status_t
nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
uint16_t *value)
{
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>"
"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
(nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle,
xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
goto fail;
} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
(nxgep->mac.portmode == PORT_1G_SERDES)) {
if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle,
xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
goto fail;
} else
goto fail;
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>"
"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value));
return (NXGE_OK);
fail:
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg,
uint16_t value)
{
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>"
"xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value));
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
if ((nxgep->mac.portmode == PORT_1G_COPPER) ||
(nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) {
if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle,
xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
goto fail;
} else if ((nxgep->mac.portmode == PORT_1G_FIBER) ||
(nxgep->mac.portmode == PORT_1G_SERDES)) {
if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle,
xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS)
goto fail;
} else
goto fail;
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>"
"xcvr_reg<%d>", xcvr_portn, xcvr_reg));
return (NXGE_OK);
fail:
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
uint16_t xcvr_reg, uint16_t *value)
{
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>",
xcvr_portn));
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle,
xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
goto fail;
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>",
xcvr_portn));
return (NXGE_OK);
fail:
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device,
uint16_t xcvr_reg, uint16_t value)
{
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>",
xcvr_portn));
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle,
xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS)
goto fail;
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>",
xcvr_portn));
return (NXGE_OK);
fail:
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
nxge_status_t
nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints,
nxge_link_state_t *link_up)
{
p_nxge_param_t param_arr;
p_nxge_stats_t statsp;
p_mii_regs_t mii_regs;
p_mii_bmsr_t soft_bmsr;
mii_anar_t anar;
mii_anlpar_t anlpar;
mii_anar_t an_common;
mii_aner_t aner;
mii_gsr_t gsr;
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check"));
mii_regs = NULL;
param_arr = nxgep->param_arr;
statsp = nxgep->statsp;
soft_bmsr = &nxgep->soft_bmsr;
*link_up = LINK_NO_CHANGE;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
bmsr.value, bmsr_ints.value));
if (bmsr_ints.bits.link_status) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
bmsr.value, bmsr_ints.value));
if (bmsr.bits.link_status) {
soft_bmsr->bits.link_status = 1;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
"0x%x", bmsr.value, bmsr_ints.value));
} else {
if (statsp->mac_stats.link_up == 1) {
*link_up = LINK_IS_DOWN;
nxgep->link_notify = B_FALSE;
}
statsp->mac_stats.link_up = 0;
soft_bmsr->bits.link_status = 0;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Link down cable problem"));
}
}
if (nxgep->mac.portmode == PORT_1G_COPPER &&
param_arr[param_autoneg].value) {
if (bmsr_ints.bits.auto_neg_complete) {
if (bmsr.bits.auto_neg_complete)
soft_bmsr->bits.auto_neg_complete = 1;
else
soft_bmsr->bits.auto_neg_complete = 0;
}
if (soft_bmsr->bits.link_status == 0) {
statsp->mac_stats.link_T4 = 0;
statsp->mac_stats.link_speed = 0;
statsp->mac_stats.link_duplex = 0;
statsp->mac_stats.link_asmpause = 0;
statsp->mac_stats.link_pause = 0;
statsp->mac_stats.lp_cap_autoneg = 0;
statsp->mac_stats.lp_cap_100T4 = 0;
statsp->mac_stats.lp_cap_1000fdx = 0;
statsp->mac_stats.lp_cap_1000hdx = 0;
statsp->mac_stats.lp_cap_100fdx = 0;
statsp->mac_stats.lp_cap_100hdx = 0;
statsp->mac_stats.lp_cap_10fdx = 0;
statsp->mac_stats.lp_cap_10hdx = 0;
statsp->mac_stats.lp_cap_10gfdx = 0;
statsp->mac_stats.lp_cap_10ghdx = 0;
statsp->mac_stats.lp_cap_asmpause = 0;
statsp->mac_stats.lp_cap_pause = 0;
}
} else
soft_bmsr->bits.auto_neg_complete = 1;
if ((bmsr_ints.bits.link_status ||
bmsr_ints.bits.auto_neg_complete) &&
soft_bmsr->bits.link_status &&
soft_bmsr->bits.auto_neg_complete) {
if (statsp->mac_stats.link_up == 0) {
*link_up = LINK_IS_UP;
nxgep->link_notify = B_FALSE;
}
statsp->mac_stats.link_up = 1;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mii_check "
"(auto negotiation complete or link up) "
"soft bmsr 0x%x bmsr_int 0x%x",
bmsr.value, bmsr_ints.value));
if (nxgep->mac.portmode == PORT_1G_COPPER &&
param_arr[param_autoneg].value) {
if ((status = nxge_mii_read(nxgep,
statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->anar),
&anar.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mii_read(nxgep,
statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->anlpar),
&anlpar.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mii_read(nxgep,
statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->aner),
&aner.value)) != NXGE_OK)
goto fail;
statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able;
statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4;
statsp->mac_stats.lp_cap_100fdx =
anlpar.bits.cap_100fdx;
statsp->mac_stats.lp_cap_100hdx =
anlpar.bits.cap_100hdx;
statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx;
statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx;
statsp->mac_stats.lp_cap_asmpause =
anlpar.bits.cap_asmpause;
statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause;
an_common.value = anar.value & anlpar.value;
if (param_arr[param_anar_1000fdx].value ||
param_arr[param_anar_1000hdx].value) {
if ((status = nxge_mii_read(nxgep,
statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->gsr),
&gsr.value)) != NXGE_OK)
goto fail;
statsp->mac_stats.lp_cap_1000fdx =
gsr.bits.link_1000fdx;
statsp->mac_stats.lp_cap_1000hdx =
gsr.bits.link_1000hdx;
if (param_arr[param_anar_1000fdx].value &&
gsr.bits.link_1000fdx) {
statsp->mac_stats.link_speed = 1000;
statsp->mac_stats.link_duplex = 2;
} else if (
param_arr[param_anar_1000hdx].value &&
gsr.bits.link_1000hdx) {
statsp->mac_stats.link_speed = 1000;
statsp->mac_stats.link_duplex = 1;
}
}
if ((an_common.value != 0) &&
!(statsp->mac_stats.link_speed)) {
if (an_common.bits.cap_100T4) {
statsp->mac_stats.link_T4 = 1;
statsp->mac_stats.link_speed = 100;
statsp->mac_stats.link_duplex = 1;
} else if (an_common.bits.cap_100fdx) {
statsp->mac_stats.link_speed = 100;
statsp->mac_stats.link_duplex = 2;
} else if (an_common.bits.cap_100hdx) {
statsp->mac_stats.link_speed = 100;
statsp->mac_stats.link_duplex = 1;
} else if (an_common.bits.cap_10fdx) {
statsp->mac_stats.link_speed = 10;
statsp->mac_stats.link_duplex = 2;
} else if (an_common.bits.cap_10hdx) {
statsp->mac_stats.link_speed = 10;
statsp->mac_stats.link_duplex = 1;
} else {
goto fail;
}
}
if (statsp->mac_stats.link_duplex != 1) {
int link_pause;
int cp, lcp;
statsp->mac_stats.link_asmpause =
an_common.bits.cap_asmpause;
cp = statsp->mac_stats.cap_pause;
lcp = statsp->mac_stats.lp_cap_pause;
if (statsp->mac_stats.link_asmpause) {
if ((cp == 0) && (lcp == 1)) {
link_pause = 0;
} else {
link_pause = 1;
}
} else {
link_pause = an_common.bits.cap_pause;
}
statsp->mac_stats.link_pause = link_pause;
}
} else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) {
statsp->mac_stats.link_speed = 1000;
statsp->mac_stats.link_duplex = 2;
}
}
if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED &&
(statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) {
*link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP :
LINK_IS_DOWN);
nxgep->link_notify = B_FALSE;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check"));
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_check: Unable to check MII"));
return (status);
}
void
nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up)
{
p_nxge_stats_t statsp;
boolean_t linkup;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check"));
statsp = nxgep->statsp;
*link_up = LINK_NO_CHANGE;
(void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup);
if (linkup) {
if ((nxgep->link_notify &&
nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
nxgep->statsp->mac_stats.link_up == 0) {
statsp->mac_stats.link_up = 1;
statsp->mac_stats.link_speed = 1000;
statsp->mac_stats.link_duplex = 2;
*link_up = LINK_IS_UP;
nxgep->link_notify = B_FALSE;
}
} else {
if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
nxgep->statsp->mac_stats.link_up == 1) {
statsp->mac_stats.link_up = 0;
statsp->mac_stats.link_speed = 0;
statsp->mac_stats.link_duplex = 0;
*link_up = LINK_IS_DOWN;
nxgep->link_notify = B_FALSE;
}
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check"));
}
nxge_status_t
nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
{
uint32_t mchash;
p_hash_filter_t hash_filter;
uint16_t hash_bit;
uint_t j;
nxge_status_t status = NXGE_OK;
npi_status_t rs;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr"));
RW_ENTER_WRITER(&nxgep->filter_lock);
mchash = crc32_mchash(addrp);
if (nxgep->hash_filter == NULL) {
NXGE_DEBUG_MSG((NULL, STR_CTL,
"Allocating hash filter storage."));
nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t),
KM_SLEEP);
}
hash_filter = nxgep->hash_filter;
j = mchash / HASH_REG_WIDTH;
hash_bit = (1 << (mchash % HASH_REG_WIDTH));
hash_filter->hash_filter_regs[j] |= hash_bit;
hash_filter->hash_bit_ref_cnt[mchash]++;
if (hash_filter->hash_bit_ref_cnt[mchash] == 1) {
hash_filter->hash_ref_cnt++;
}
rs = nxge_rx_mac_mcast_hash_table(nxgep);
if (rs != NPI_SUCCESS)
goto fail;
RW_EXIT(&nxgep->filter_lock);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr"));
return (NXGE_OK);
fail:
RW_EXIT(&nxgep->filter_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: "
"Unable to add multicast address"));
return (status);
}
nxge_status_t
nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp)
{
uint32_t mchash;
p_hash_filter_t hash_filter;
uint16_t hash_bit;
uint_t j;
nxge_status_t status = NXGE_OK;
npi_status_t rs;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr"));
RW_ENTER_WRITER(&nxgep->filter_lock);
mchash = crc32_mchash(addrp);
if (nxgep->hash_filter == NULL) {
NXGE_DEBUG_MSG((NULL, STR_CTL,
"Hash filter already de_allocated."));
RW_EXIT(&nxgep->filter_lock);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
return (NXGE_OK);
}
hash_filter = nxgep->hash_filter;
hash_filter->hash_bit_ref_cnt[mchash]--;
if (hash_filter->hash_bit_ref_cnt[mchash] == 0) {
j = mchash / HASH_REG_WIDTH;
hash_bit = (1 << (mchash % HASH_REG_WIDTH));
hash_filter->hash_filter_regs[j] &= ~hash_bit;
hash_filter->hash_ref_cnt--;
}
if (hash_filter->hash_ref_cnt == 0) {
NXGE_DEBUG_MSG((NULL, STR_CTL,
"De-allocating hash filter storage."));
KMEM_FREE(hash_filter, sizeof (hash_filter_t));
nxgep->hash_filter = NULL;
}
rs = nxge_rx_mac_mcast_hash_table(nxgep);
if (rs != NPI_SUCCESS)
goto fail;
RW_EXIT(&nxgep->filter_lock);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr"));
return (NXGE_OK);
fail:
RW_EXIT(&nxgep->filter_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: "
"Unable to remove multicast address"));
return (status);
}
nxge_status_t
nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp)
{
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr"));
MUTEX_ENTER(&nxgep->ouraddr_lock);
if (((addrp->ether_addr_octet[0] & 01) == 1) ||
(ether_cmp(addrp, ðerbroadcastaddr) == 0) ||
(ether_cmp(addrp, &nxgep->ouraddr) == 0)) {
goto nxge_set_mac_addr_exit;
}
nxgep->ouraddr = *addrp;
RW_ENTER_WRITER(&nxgep->filter_lock);
if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK)
goto fail;
if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK)
goto fail;
RW_EXIT(&nxgep->filter_lock);
MUTEX_EXIT(&nxgep->ouraddr_lock);
goto nxge_set_mac_addr_end;
nxge_set_mac_addr_exit:
MUTEX_EXIT(&nxgep->ouraddr_lock);
nxge_set_mac_addr_end:
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr"));
return (NXGE_OK);
fail:
MUTEX_EXIT(&nxgep->ouraddr_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: "
"Unable to set mac address"));
return (status);
}
static
check_link_state_t
nxge_check_link_stop(nxge_t *nxge)
{
MUTEX_ENTER(&nxge->poll_lock);
if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) {
nxge->poll_state = LINK_MONITOR_STOP;
nxge->nxge_link_poll_timerid = 0;
cv_broadcast(&nxge->poll_cv);
MUTEX_EXIT(&nxge->poll_lock);
NXGE_DEBUG_MSG((nxge, MAC_CTL,
"nxge_check_%s_link(port<%d>) stopped.",
nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii",
nxge->mac.portnum));
return (CHECK_LINK_STOP);
}
MUTEX_EXIT(&nxge->poll_lock);
return (CHECK_LINK_RESCHEDULE);
}
static nxge_status_t
nxge_check_mii_link(p_nxge_t nxgep)
{
mii_bmsr_t bmsr_ints, bmsr_data;
mii_anlpar_t anlpar;
mii_gsr_t gsr;
p_mii_regs_t mii_regs;
nxge_status_t status = NXGE_OK;
uint8_t portn;
nxge_link_state_t link_up;
if (nxgep->nxge_magic != NXGE_MAGIC)
return (NXGE_ERROR);
if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
return (NXGE_OK);
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>",
portn));
mii_regs = NULL;
RW_ENTER_WRITER(&nxgep->filter_lock);
if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
goto nxge_check_mii_link_exit;
switch (nxgep->mac.portmode) {
default:
bmsr_data.value = 0;
if ((status = nxge_mii_read(nxgep,
nxgep->statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmsr),
&bmsr_data.value)) != NXGE_OK) {
goto fail;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_check_mii_link port<0x%x> "
"RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
portn, bmsr_data.value, nxgep->bmsr.value));
if (nxgep->param_arr[param_autoneg].value) {
if ((status = nxge_mii_read(nxgep,
nxgep->statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->gsr),
&gsr.value)) != NXGE_OK)
goto fail;
if ((status = nxge_mii_read(nxgep,
nxgep->statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->anlpar),
&anlpar.value)) != NXGE_OK)
goto fail;
if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) {
if (nxgep->statsp->mac_stats.link_up &&
((nxgep->statsp->mac_stats.lp_cap_1000fdx ^
gsr.bits.link_1000fdx) ||
(nxgep->statsp->mac_stats.lp_cap_1000hdx ^
gsr.bits.link_1000hdx) ||
(nxgep->statsp->mac_stats.lp_cap_100T4 ^
anlpar.bits.cap_100T4) ||
(nxgep->statsp->mac_stats.lp_cap_100fdx ^
anlpar.bits.cap_100fdx) ||
(nxgep->statsp->mac_stats.lp_cap_100hdx ^
anlpar.bits.cap_100hdx) ||
(nxgep->statsp->mac_stats.lp_cap_10fdx ^
anlpar.bits.cap_10fdx) ||
(nxgep->statsp->mac_stats.lp_cap_10hdx ^
anlpar.bits.cap_10hdx))) {
bmsr_data.bits.link_status = 0;
}
}
}
if (bmsr_data.value == 0) {
cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n");
goto nxge_check_mii_link_exit;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_check_mii_link port<0x%x> :"
"BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
portn, nxgep->bmsr.value, bmsr_data.value));
bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value;
nxgep->bmsr.value = bmsr_data.value;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_check_mii_link port<0x%x> CALLING "
"bmsr_data 0x%x bmsr_ints.value 0x%x",
portn, bmsr_data.value, bmsr_ints.value));
if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints,
&link_up)) != NXGE_OK) {
goto fail;
}
break;
case PORT_1G_SERDES:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_check_mii_link port<%d> (SERDES)", portn));
nxge_pcs_check(nxgep, portn, &link_up);
break;
}
nxge_check_mii_link_exit:
RW_EXIT(&nxgep->filter_lock);
if (link_up == LINK_IS_UP) {
nxge_link_is_up(nxgep);
} else if (link_up == LINK_IS_DOWN) {
nxge_link_is_down(nxgep);
}
(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>",
portn));
return (NXGE_OK);
fail:
RW_EXIT(&nxgep->filter_lock);
(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_check_mii_link: Failed to check link port<%d>", portn));
return (status);
}
static nxge_status_t
nxge_check_10g_link(p_nxge_t nxgep)
{
uint8_t portn;
nxge_status_t status = NXGE_OK;
boolean_t link_up;
uint32_t val;
npi_status_t rs;
if (nxgep->nxge_magic != NXGE_MAGIC)
return (NXGE_ERROR);
if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
return (NXGE_OK);
portn = nxgep->mac.portnum;
val = 0;
rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>",
portn));
switch (nxgep->mac.portmode) {
default:
if (nxgep->hot_swappable_phy) {
boolean_t phy_present_now = B_FALSE;
if (nxge_hswap_phy_present(nxgep, portn))
phy_present_now = B_TRUE;
rs = npi_xmac_xpcs_read(nxgep->npi_handle,
nxgep->mac.portnum, XPCS_REG_STATUS, &val);
if (rs != 0)
goto fail;
link_up = B_FALSE;
if (val & XPCS_STATUS_LANE_ALIGN) {
link_up = B_TRUE;
}
if (nxgep->phy_absent) {
if (phy_present_now) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Hot swappable phy DETECTED!!"));
nxgep->phy_absent = B_FALSE;
(void) nxge_xcvr_find(nxgep);
(void) nxge_link_init(nxgep);
if (!(nxgep->drv_state &
STATE_HW_INITIALIZED)) {
status = nxge_init(nxgep);
if (status != NXGE_OK) {
NXGE_ERROR_MSG((nxgep,
NXGE_ERR_CTL,
"Hot swappable "
"phy present, but"
" driver init"
" failed..."));
goto fail;
}
}
} else if (link_up) {
nxgep->statsp->mac_stats.xcvr_inuse =
XPCS_XCVR;
nxgep->mac.portmode = PORT_10G_SERDES;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"HSP 10G Serdes DETECTED!!"));
break;
}
if (nxgep->link_notify &&
nxgep->link_check_count > 3 &&
nxgep->nxge_mac_state == NXGE_MAC_STARTED ||
nxgep->statsp->mac_stats.link_up == 1) {
nxgep->statsp->mac_stats.link_up = 0;
nxgep->statsp->mac_stats.link_speed = 0;
nxgep->statsp->mac_stats.link_duplex =
0;
nxge_link_is_down(nxgep);
nxgep->link_notify = B_FALSE;
}
goto start_link_check;
} else if (!phy_present_now) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Hot swappable phy REMOVED!!"));
nxgep->phy_absent = B_TRUE;
nxgep->statsp->mac_stats.link_up = 0;
nxgep->statsp->mac_stats.link_speed = 0;
nxgep->statsp->mac_stats.link_duplex = 0;
nxge_link_is_down(nxgep);
nxgep->link_notify = B_FALSE;
(void) nxge_xcvr_find(nxgep);
goto start_link_check;
}
}
switch (nxgep->chip_id) {
case MRVL88X201X_CHIP_ID:
status = nxge_check_mrvl88x2011_link(nxgep, &link_up);
break;
case NLP2020_CHIP_ID:
status = nxge_check_nlp2020_link(nxgep, &link_up);
break;
default:
status = nxge_check_bcm8704_link(nxgep, &link_up);
break;
}
if (status != NXGE_OK)
goto fail;
break;
case PORT_10G_SERDES:
rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
XPCS_REG_STATUS, &val);
if (rs != 0)
goto fail;
link_up = B_FALSE;
if (val & XPCS_STATUS_LANE_ALIGN) {
link_up = B_TRUE;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_check_10g_link port<%d> "
"XPCS_REG_STATUS2 0x%x link_up %d",
portn, val, link_up));
break;
}
if (link_up) {
if ((nxgep->link_notify &&
nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
nxgep->statsp->mac_stats.link_up == 0) {
if (nxge_10g_link_led_on(nxgep) != NXGE_OK)
goto fail;
nxgep->statsp->mac_stats.link_up = 1;
nxgep->statsp->mac_stats.link_speed = 10000;
nxgep->statsp->mac_stats.link_duplex = 2;
nxge_link_is_up(nxgep);
nxgep->link_notify = B_FALSE;
}
} else {
if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
nxgep->statsp->mac_stats.link_up == 1) {
if (nxge_10g_link_led_off(nxgep) != NXGE_OK)
goto fail;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Link down cable problem"));
nxgep->statsp->mac_stats.link_up = 0;
nxgep->statsp->mac_stats.link_speed = 0;
nxgep->statsp->mac_stats.link_duplex = 0;
nxge_link_is_down(nxgep);
nxgep->link_notify = B_FALSE;
if (nxgep->mac.portmode == PORT_10G_SERDES) {
(void) nxge_xcvr_find(nxgep);
}
}
}
start_link_check:
(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>",
portn));
return (NXGE_OK);
fail:
(void) nxge_check_link_stop(nxgep);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_check_10g_link: Failed to check link port<%d>",
portn));
return (status);
}
void
nxge_link_is_down(p_nxge_t nxgep)
{
p_nxge_stats_t statsp;
char link_stat_msg[64];
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down"));
statsp = nxgep->statsp;
(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down",
statsp->mac_stats.xcvr_portn);
if (nxge_no_msg == B_FALSE) {
NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
}
mac_link_update(nxgep->mach, LINK_STATE_DOWN);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down"));
}
void
nxge_link_is_up(p_nxge_t nxgep)
{
p_nxge_stats_t statsp;
char link_stat_msg[64];
uint32_t val;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up"));
statsp = nxgep->statsp;
(void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ",
statsp->mac_stats.xcvr_portn,
statsp->mac_stats.link_speed);
if (statsp->mac_stats.link_T4)
(void) strcat(link_stat_msg, "T4");
else if (statsp->mac_stats.link_duplex == 2)
(void) strcat(link_stat_msg, "full duplex");
else
(void) strcat(link_stat_msg, "half duplex");
if ((nxgep->mac.portmode == PORT_10G_FIBER) ||
(nxgep->mac.portmode == PORT_10G_COPPER) ||
(nxgep->mac.portmode == PORT_10G_SERDES)) {
(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
}
if (nxgep->mac.portmode == PORT_1G_TN1010 ||
nxgep->mac.portmode == PORT_10G_TN1010) {
(void) nxge_set_tn1010_param(nxgep);
if (nxge_xcvr_find(nxgep) != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_link_is_up: nxge_xcvr_find failed"));
}
if (nxge_link_init(nxgep) != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_link_is_up: nxge_link_init failed"));
}
if (nxge_mac_init(nxgep) != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_link_is_up: nxge_mac_init failed"));
}
} else {
(void) nxge_xif_init(nxgep);
}
if (nxge_no_msg == B_FALSE) {
NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg));
}
mac_link_update(nxgep->mach, LINK_STATE_UP);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up"));
}
#ifdef NXGE_DEBUG
static void
nxge_dump_tn1010_status_regs(p_nxge_t nxgep)
{
uint16_t val;
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PMA_PMD_DEV_ADDR, 1, &val);
cmn_err(CE_NOTE, "PMA status1 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PMA_PMD_DEV_ADDR, 8, &val);
cmn_err(CE_NOTE, "PMA status2 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PMA_PMD_DEV_ADDR, 129, &val);
cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PCS_DEV_ADDR, 1, &val);
cmn_err(CE_NOTE, "PCS status1 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PCS_DEV_ADDR, 8, &val);
cmn_err(CE_NOTE, "PCS status2 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PCS_DEV_ADDR, 32, &val);
cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PCS_DEV_ADDR, 33, &val);
cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PHYXS_DEV_ADDR, 1, &val);
cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PHYXS_DEV_ADDR, 8, &val);
cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_PHYXS_DEV_ADDR, 24, &val);
cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_AUTONEG_DEV_ADDR, 1, &val);
cmn_err(CE_NOTE, "Autoneg status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_AUTONEG_DEV_ADDR, 33, &val);
cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val);
cmn_err(CE_NOTE, "TN1010 status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val);
cmn_err(CE_NOTE, "Device status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val);
cmn_err(CE_NOTE, "DDR status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val);
cmn_err(CE_NOTE, "DDR fault status = 0x%x", val);
nxge_mdio_read(nxgep, nxgep->xcvr_addr,
TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val);
cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x",
val, (val & 0xFF00) >> 8, val & 0x00FF);
}
#endif
uint32_t
crc32_mchash(p_ether_addr_t addr)
{
uint8_t *cp;
uint32_t crc;
uint32_t c;
int byte;
int bit;
cp = (uint8_t *)addr;
crc = (uint32_t)0xffffffff;
for (byte = 0; byte < 6; byte++) {
c = (uint32_t)cp[byte];
for (bit = 0; bit < 8; bit++) {
if ((c & 0x1) ^ (crc & 0x1))
crc = (crc >> 1)^0xedb88320;
else
crc = (crc >> 1);
c >>= 1;
}
}
return ((~crc) >> (32 - HASH_BITS));
}
nxge_status_t
nxge_serdes_reset(p_nxge_t nxgep)
{
npi_handle_t handle;
handle = nxgep->npi_handle;
ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1);
drv_usecwait(500);
ESR_REG_WR(handle, ESR_CONFIG_REG, 0);
return (NXGE_OK);
}
nxge_status_t
nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable)
{
nxge_status_t status = NXGE_OK;
if (isLDOMguest(nxgep))
return (status);
if ((nxgep->mac.portmode == PORT_10G_FIBER ||
nxgep->mac.portmode == PORT_10G_COPPER ||
nxgep->mac.portmode == PORT_10G_SERDES) &&
(nxgep->mac.portnum > 1))
return (NXGE_OK);
if (nxgep->statsp == NULL) {
return (NXGE_OK);
}
if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g)
return (NXGE_OK);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_link_monitor port<%d> enable=%d",
nxgep->mac.portnum, enable));
if (enable == LINK_MONITOR_START) {
if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
if ((status = nxge_link_intr(nxgep, LINK_INTR_START))
!= NXGE_OK)
goto fail;
} else {
timeout_id_t timerid;
if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP)
return (NXGE_OK);
if (nxgep->xcvr.check_link) {
timerid = timeout((fptrv_t)(uintptr_t)
(nxgep->xcvr.check_link),
nxgep,
drv_usectohz(LINK_MONITOR_PERIOD));
MUTEX_ENTER(&nxgep->poll_lock);
nxgep->nxge_link_poll_timerid = timerid;
MUTEX_EXIT(&nxgep->poll_lock);
nxgep->link_check_count ++;
} else {
return (NXGE_ERROR);
}
}
} else {
if (nxgep->mac.linkchkmode == LINKCHK_INTR) {
if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP))
!= NXGE_OK)
goto fail;
} else {
clock_t rv;
MUTEX_ENTER(&nxgep->poll_lock);
if (nxgep->nxge_link_poll_timerid == 0) {
MUTEX_EXIT(&nxgep->poll_lock);
return (NXGE_OK);
}
nxgep->poll_state = LINK_MONITOR_STOPPING;
rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock,
drv_usectohz(LM_WAIT_MULTIPLIER *
LINK_MONITOR_PERIOD), TR_CLOCK_TICK);
if (rv == -1) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> stopping port %d: "
"cv_timedwait(%d) timed out",
nxgep->mac.portnum, nxgep->poll_state));
nxgep->poll_state = LINK_MONITOR_STOP;
nxgep->nxge_link_poll_timerid = 0;
}
MUTEX_EXIT(&nxgep->poll_lock);
}
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_link_monitor port<%d> enable=%d",
nxgep->mac.portnum, enable));
return (NXGE_OK);
fail:
return (status);
}
nxge_status_t
nxge_check_tn1010_link(p_nxge_t nxgep)
{
nxge_status_t status = NXGE_OK;
nxge_link_state_t link_up;
if (nxgep->nxge_magic != NXGE_MAGIC) {
return (NXGE_ERROR);
}
if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) {
return (NXGE_OK);
}
if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10)
goto nxge_check_tn1010_link_exit;
if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK)
goto fail;
nxge_check_tn1010_link_exit:
if (link_up == LINK_IS_UP)
nxge_link_is_up(nxgep);
else if (link_up == LINK_IS_DOWN)
nxge_link_is_down(nxgep);
(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
return (NXGE_OK);
fail:
(void) nxge_link_monitor(nxgep, LINK_MONITOR_START);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_check_tn1010_link: Failed to check link"));
return (status);
}
static nxge_status_t
nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up)
{
nxge_status_t status = NXGE_OK;
p_nxge_stats_t statsp;
uint8_t phy_port_addr, portn;
uint16_t val;
*link_up = LINK_NO_CHANGE;
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
statsp = nxgep->statsp;
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val))
!= NXGE_OK) {
goto fail;
}
if (val & TN1010_AN_LINK_STAT_BIT) {
if ((nxgep->link_notify &&
nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
nxgep->statsp->mac_stats.link_up == 0) {
statsp->mac_stats.link_up = 1;
statsp->mac_stats.link_duplex = 2;
*link_up = LINK_IS_UP;
nxgep->link_notify = B_FALSE;
}
} else {
if ((nxgep->link_notify && nxgep->link_check_count > 3 &&
nxgep->nxge_mac_state == NXGE_MAC_STARTED) ||
nxgep->statsp->mac_stats.link_up == 1) {
statsp->mac_stats.link_up = 0;
statsp->mac_stats.link_speed = 0;
statsp->mac_stats.link_duplex = 0;
*link_up = LINK_IS_DOWN;
nxgep->link_notify = B_FALSE;
}
}
return (NXGE_OK);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_tn1010_check: Unable to check TN1010"));
return (status);
}
nxge_status_t
nxge_set_promisc(p_nxge_t nxgep, boolean_t on)
{
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on));
nxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
RW_ENTER_WRITER(&nxgep->filter_lock);
if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) {
goto fail;
}
RW_EXIT(&nxgep->filter_lock);
if (on)
nxgep->statsp->mac_stats.promisc = B_TRUE;
else
nxgep->statsp->mac_stats.promisc = B_FALSE;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc"));
return (NXGE_OK);
fail:
RW_EXIT(&nxgep->filter_lock);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: "
"Unable to set promisc (%d)", on));
return (status);
}
uint_t
nxge_mif_intr(void *arg1, void *arg2)
{
#ifdef NXGE_DEBUG
p_nxge_t nxgep = (p_nxge_t)arg2;
#endif
#if NXGE_MIF
p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
uint32_t status;
npi_handle_t handle;
uint8_t portn;
p_nxge_stats_t statsp;
#endif
#ifdef NXGE_MIF
if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
nxgep = ldvp->nxgep;
}
nxgep = ldvp->nxgep;
#endif
NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr"));
return (DDI_INTR_CLAIMED);
}
uint_t
nxge_mac_intr(void *arg1, void *arg2)
{
p_nxge_t nxgep = (p_nxge_t)arg2;
p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1;
p_nxge_ldg_t ldgp;
uint32_t status;
npi_handle_t handle;
uint8_t portn;
p_nxge_stats_t statsp;
npi_status_t rs = NPI_SUCCESS;
if (arg2 == NULL || (void *)ldvp->nxgep != arg2) {
nxgep = ldvp->nxgep;
}
ldgp = ldvp->ldgp;
NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: "
"group %d", ldgp->ldg));
handle = NXGE_DEV_NPI_HANDLE(nxgep);
statsp = (p_nxge_stats_t)nxgep->statsp;
portn = nxgep->mac.portnum;
NXGE_DEBUG_MSG((nxgep, INT_CTL,
"==> nxge_mac_intr: reading mac stats: port<%d>", portn));
if (nxgep->mac.porttype == PORT_TYPE_XMAC) {
rs = npi_xmac_tx_get_istatus(handle, portn,
(xmac_tx_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_XMAC_TX_ALL) {
if (status & ICFG_XMAC_TX_UNDERRUN) {
statsp->xmac_stats.tx_underflow_err++;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
}
if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
statsp->xmac_stats.tx_maxpktsize_err++;
}
if (status & ICFG_XMAC_TX_OVERFLOW) {
statsp->xmac_stats.tx_overflow_err++;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_TXMAC_OVERFLOW);
}
if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
statsp->xmac_stats.tx_fifo_xfr_err++;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR);
}
if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
statsp->xmac_stats.tx_byte_cnt +=
XTXMAC_BYTE_CNT_MASK;
}
if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
statsp->xmac_stats.tx_frame_cnt +=
XTXMAC_FRM_CNT_MASK;
}
}
rs = npi_xmac_rx_get_istatus(handle, portn,
(xmac_rx_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_XMAC_RX_ALL) {
if (status & ICFG_XMAC_RX_OVERFLOW)
statsp->xmac_stats.rx_overflow_err++;
if (status & ICFG_XMAC_RX_UNDERFLOW) {
statsp->xmac_stats.rx_underflow_err++;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_RXMAC_UNDERFLOW);
}
if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
statsp->xmac_stats.rx_crc_err_cnt +=
XRXMAC_CRC_ER_CNT_MASK;
}
if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
statsp->xmac_stats.rx_len_err_cnt +=
MAC_LEN_ER_CNT_MASK;
}
if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
statsp->xmac_stats.rx_viol_err_cnt +=
XRXMAC_CD_VIO_CNT_MASK;
}
if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
statsp->xmac_stats.rx_byte_cnt +=
XRXMAC_BT_CNT_MASK;
}
if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
statsp->xmac_stats.rx_hist1_cnt +=
XRXMAC_HIST_CNT1_MASK;
}
if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
statsp->xmac_stats.rx_hist2_cnt +=
XRXMAC_HIST_CNT2_MASK;
}
if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
statsp->xmac_stats.rx_hist3_cnt +=
XRXMAC_HIST_CNT3_MASK;
}
if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
statsp->xmac_stats.rx_hist4_cnt +=
XRXMAC_HIST_CNT4_MASK;
}
if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
statsp->xmac_stats.rx_hist5_cnt +=
XRXMAC_HIST_CNT5_MASK;
}
if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
statsp->xmac_stats.rx_hist6_cnt +=
XRXMAC_HIST_CNT6_MASK;
}
if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
statsp->xmac_stats.rx_broadcast_cnt +=
XRXMAC_BC_FRM_CNT_MASK;
}
if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
statsp->xmac_stats.rx_mult_cnt +=
XRXMAC_MC_FRM_CNT_MASK;
}
if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
statsp->xmac_stats.rx_frag_cnt +=
XRXMAC_FRAG_CNT_MASK;
}
if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
statsp->xmac_stats.rx_frame_align_err_cnt +=
XRXMAC_AL_ER_CNT_MASK;
}
if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
statsp->xmac_stats.rx_linkfault_err_cnt +=
XMAC_LINK_FLT_CNT_MASK;
}
if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
statsp->xmac_stats.rx_remotefault_err++;
}
if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
statsp->xmac_stats.rx_localfault_err++;
}
}
rs = npi_xmac_ctl_get_istatus(handle, portn,
(xmac_ctl_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_XMAC_CTRL_ALL) {
if (status & ICFG_XMAC_CTRL_PAUSE_RCVD)
statsp->xmac_stats.rx_pause_cnt++;
if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
statsp->xmac_stats.tx_pause_state++;
if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE)
statsp->xmac_stats.tx_nopause_state++;
}
} else if (nxgep->mac.porttype == PORT_TYPE_BMAC) {
rs = npi_bmac_tx_get_istatus(handle, portn,
(bmac_tx_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_BMAC_TX_ALL) {
if (status & ICFG_BMAC_TX_UNDERFLOW) {
statsp->bmac_stats.tx_underrun_err++;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_TXMAC_UNDERFLOW);
}
if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
statsp->bmac_stats.tx_max_pkt_err++;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR);
}
if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
statsp->bmac_stats.tx_byte_cnt +=
BTXMAC_BYTE_CNT_MASK;
}
if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
statsp->bmac_stats.tx_frame_cnt +=
BTXMAC_FRM_CNT_MASK;
}
}
rs = npi_bmac_rx_get_istatus(handle, portn,
(bmac_rx_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_BMAC_RX_ALL) {
if (status & ICFG_BMAC_RX_OVERFLOW) {
statsp->bmac_stats.rx_overflow_err++;
}
if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
statsp->bmac_stats.rx_frame_cnt +=
RXMAC_FRM_CNT_MASK;
}
if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
statsp->bmac_stats.rx_crc_err_cnt +=
BMAC_CRC_ER_CNT_MASK;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP);
}
if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
statsp->bmac_stats.rx_len_err_cnt +=
MAC_LEN_ER_CNT_MASK;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP);
}
if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) {
statsp->bmac_stats.rx_viol_err_cnt +=
BMAC_CD_VIO_CNT_MASK;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP);
}
if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
statsp->bmac_stats.rx_byte_cnt +=
BRXMAC_BYTE_CNT_MASK;
}
if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
statsp->bmac_stats.rx_align_err_cnt +=
BMAC_AL_ER_CNT_MASK;
NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP);
}
rs = npi_bmac_ctl_get_istatus(handle, portn,
(bmac_ctl_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_BMAC_CTL_ALL) {
if (status & ICFG_BMAC_CTL_RCVPAUSE)
statsp->bmac_stats.rx_pause_cnt++;
if (status & ICFG_BMAC_CTL_INPAUSE_ST)
statsp->bmac_stats.tx_pause_state++;
if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST)
statsp->bmac_stats.tx_nopause_state++;
}
}
}
if (ldgp->nldvs == 1) {
(void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg,
B_TRUE, ldgp->ldg_timer);
}
NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
return (DDI_INTR_CLAIMED);
npi_fail:
NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr"));
return (DDI_INTR_UNCLAIMED);
}
nxge_status_t
nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up)
{
uint8_t phy_port_addr;
nxge_status_t status = NXGE_OK;
boolean_t rx_sig_ok;
boolean_t pcs_blk_lock;
boolean_t link_align;
uint16_t val1, val2, val3;
#ifdef NXGE_DEBUG_SYMBOL_ERR
uint16_t val_debug;
uint32_t val;
#endif
phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn;
#ifdef NXGE_DEBUG_SYMBOL_ERR
(void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug);
if ((val_debug & ~0x200) != 0) {
cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n",
nxgep->mac.portnum, val_debug);
(void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18,
&val_debug);
cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n",
nxgep->mac.portnum, val_debug);
}
(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
XPCS_REG_DESCWERR_COUNTER, &val);
if (val != 0)
cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val);
(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val);
if (val != 0)
cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val);
(void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum,
XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val);
if (val != 0)
cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val);
#endif
status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR,
BCM8704_PMD_RECEIVE_SIG_DETECT, &val1);
if (status != NXGE_OK)
goto fail;
rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE);
if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR,
BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS)
goto fail;
pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE);
status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR,
BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3);
if (status != NXGE_OK)
goto fail;
switch (nxgep->chip_id) {
case BCM8704_CHIP_ID:
link_align = (val3 == (XGXS_LANE_ALIGN_STATUS |
XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE;
break;
case BCM8706_CHIP_ID:
link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) &&
(val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) &&
(val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ?
B_TRUE : B_FALSE;
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:"
"Unknown chip ID [0x%x]", nxgep->chip_id));
goto fail;
}
#ifdef NXGE_DEBUG_ALIGN_ERR
if (pcs_blk_lock == B_FALSE) {
if (val2 != 0x4) {
pcs_blk_lock = B_TRUE;
cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 "
"Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2);
}
}
if (link_align == B_FALSE) {
if (val3 != 0x140f) {
link_align = B_TRUE;
cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 "
"Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3);
}
}
if (rx_sig_ok == B_FALSE) {
if ((val2 == 0) || (val3 == 0)) {
rx_sig_ok = B_TRUE;
cmn_err(CE_NOTE,
"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
nxgep->mac.portnum);
}
}
#endif
*link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) &&
(link_align == B_TRUE)) ? B_TRUE : B_FALSE;
return (NXGE_OK);
fail:
return (status);
}
static nxge_status_t
nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up)
{
uint8_t phy;
nxge_status_t status = NXGE_OK;
boolean_t pma_status;
boolean_t pcs_status;
boolean_t xgxs_status;
uint16_t val;
phy = nxgep->statsp->mac_stats.xcvr_portn;
MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
MRVL_88X2011_10G_PMD_STAT_2, &val);
*link_up = B_FALSE;
MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR,
MRVL_88X2011_PMA_PMD_STAT_1, &val);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_check_mrvl88x2011_link: pmd=0x%x", val));
pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
MRVL_88X2011_PMA_PMD_STAT_1, &val);
MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR,
MRVL_88X2011_PMA_PMD_STAT_1, &val);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_check_mrvl88x2011_link: pcs=0x%x", val));
pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE);
MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR,
MRVL_88X2011_10G_XGXS_LANE_STAT, &val);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC |
XGXS_LANE2_SYNC | XGXS_LANE1_SYNC |
XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY |
XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE;
*link_up = (pma_status && pcs_status && xgxs_status) ?
B_TRUE : B_FALSE;
fail:
if (*link_up == B_FALSE) {
nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF);
} else {
nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT);
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
" <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
return (status);
}
static nxge_status_t
nxge_check_nlp2020_link(p_nxge_t nxgep, boolean_t *link_up)
{
uint8_t phy;
nxge_status_t status = NXGE_OK;
uint16_t pmd_rx_sig, pcs_10gbr_stat1, phy_xs_ln_stat;
uint8_t connector = 0;
phy = nxgep->statsp->mac_stats.xcvr_portn;
*link_up = B_FALSE;
status = nxge_mdio_read(nxgep, phy, NLP2020_PMA_PMD_ADDR,
NLP2020_PMA_PMD_RX_SIG_DET_REG, &pmd_rx_sig);
if (status != NXGE_OK)
goto fail;
status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_PCS_ADDR,
NLP2020_PHY_PCS_10GBR_STAT1_REG, &pcs_10gbr_stat1);
if (status != NXGE_OK)
goto fail;
status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_XS_ADDR,
NLP2020_PHY_XS_LN_ST_REG, &phy_xs_ln_stat);
if (status != NXGE_OK)
goto fail;
if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) &&
(pcs_10gbr_stat1 & NLP2020_PHY_PCS_10GBR_RX_LINK_UP) &&
(phy_xs_ln_stat & NLP2020_PHY_XS_LN_ALIGN_SYNC))
*link_up = B_TRUE;
if (nxgep->statsp->mac_stats.link_up == 0) {
(void) nxge_nlp2020_i2c_read(nxgep, phy,
NLP2020_XCVR_I2C_ADDR, QSFP_MSA_CONN_REG, &connector);
switch (connector) {
case SFPP_FIBER:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_check_nlp2020_link: SFPP_FIBER"));
if (nxgep->mac.portmode != PORT_10G_FIBER) {
nxgep->mac.portmode = PORT_10G_FIBER;
(void) nxge_nlp2020_xcvr_init(nxgep);
}
break;
case QSFP_FIBER:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_check_nlp2020_link: QSFP_FIBER"));
if (nxgep->mac.portmode != PORT_10G_FIBER) {
nxgep->mac.portmode = PORT_10G_FIBER;
(void) nxge_nlp2020_xcvr_init(nxgep);
}
break;
case QSFP_COPPER_TWINAX:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_check_nlp2020_link: "
"QSFP_COPPER_TWINAX/"
"SFPP_COPPER_TWINAX"));
if (nxgep->mac.portmode != PORT_10G_COPPER) {
nxgep->mac.portmode = PORT_10G_COPPER;
(void) nxge_nlp2020_xcvr_init(nxgep);
} else {
uint8_t len = 0;
(void) nxge_nlp2020_i2c_read(nxgep, phy,
NLP2020_XCVR_I2C_ADDR, QSFP_MSA_LEN_REG,
&len);
if (((len < 7) &&
(nxgep->nlp_conn ==
NXGE_NLP_CONN_COPPER_7M_ABOVE)) ||
((len >= 7) &&
(nxgep->nlp_conn ==
NXGE_NLP_CONN_COPPER_LT_7M))) {
(void) nxge_nlp2020_xcvr_init(nxgep);
}
}
break;
default:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_check_nlp2020_link: Unknown type [0x%x] "
"detected...setting to QSFP_FIBER",
connector));
if (nxgep->mac.portmode != PORT_10G_FIBER) {
nxgep->mac.portmode = PORT_10G_FIBER;
(void) nxge_nlp2020_xcvr_init(nxgep);
}
break;
}
}
fail:
if (*link_up == B_FALSE && nxgep->statsp->mac_stats.link_up == 1) {
(void) nxge_mdio_write(nxgep, phy,
NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xb000);
(void) nxge_mdio_write(nxgep, phy,
NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0x0);
} else if (*link_up == B_TRUE &&
nxgep->statsp->mac_stats.link_up == 0) {
(void) nxge_mdio_write(nxgep, phy,
NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xd000);
(void) nxge_mdio_write(nxgep, phy,
NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0xfbff);
(void) nxge_mdio_write(nxgep, phy,
NLP2020_GPIO_ADDR, 0xff2a, 0x004a);
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
" <== nxge_check_nlp2020_link: up=%d", *link_up));
return (status);
}
nxge_status_t
nxge_10g_link_led_on(p_nxge_t nxgep)
{
if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE)
!= NPI_SUCCESS)
return (NXGE_ERROR);
else
return (NXGE_OK);
}
nxge_status_t
nxge_10g_link_led_off(p_nxge_t nxgep)
{
if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE)
!= NPI_SUCCESS)
return (NXGE_ERROR);
else
return (NXGE_OK);
}
static boolean_t
nxge_hswap_phy_present(p_nxge_t nxgep, uint8_t portn)
{
if (portn == 1) {
if (nxge_is_phy_present(nxgep, ALT_GOA_CLAUSE45_PORT1_ADDR,
BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
nxgep->xcvr_addr = ALT_GOA_CLAUSE45_PORT1_ADDR;
goto found_phy;
}
}
if (nxge_is_phy_present(nxgep, GOA_CLAUSE45_PORT_ADDR_BASE + portn,
BCM8706_DEV_ID, BCM_PHY_ID_MASK)) {
nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + portn;
goto found_phy;
}
switch (portn) {
case 0:
if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR0,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR0;
goto found_phy;
} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR1,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR1;
goto found_phy;
} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR2,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR2;
goto found_phy;
} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR3,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR3;
goto found_phy;
}
break;
case 1:
if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR0,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR0;
goto found_phy;
} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR1,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR1;
goto found_phy;
} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR2,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR2;
goto found_phy;
} else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR3,
NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) {
nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR3;
goto found_phy;
}
break;
default:
break;
}
return (B_FALSE);
found_phy:
return (B_TRUE);
}
static boolean_t
nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask)
{
uint32_t pma_pmd_id = 0;
uint32_t pcs_id = 0;
uint32_t phy_id = 0;
pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
if ((pma_pmd_id & mask) == (id & mask))
goto found_phy;
pcs_id = nxge_get_cl45_pcs_id(nxgep, addr);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
if ((pcs_id & mask) == (id & mask))
goto found_phy;
phy_id = nxge_get_cl22_phy_id(nxgep, addr);
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_is_phy_present: phy_id[0x%x]", phy_id));
if ((phy_id & mask) == (id & mask))
goto found_phy;
return (B_FALSE);
found_phy:
return (B_TRUE);
}
static boolean_t
nxge_is_supported_phy(uint32_t id, uint8_t type)
{
int i;
boolean_t found = B_FALSE;
switch (type) {
case CLAUSE_45_TYPE:
for (i = 0; i < NUM_CLAUSE_45_IDS; i++) {
if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) ==
(id & BCM_PHY_ID_MASK)) ||
(TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK)) ||
(NLP2020_DEV_ID == (id & NLP2020_DEV_ID_MASK))) {
found = B_TRUE;
break;
}
}
break;
case CLAUSE_22_TYPE:
for (i = 0; i < NUM_CLAUSE_22_IDS; i++) {
if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) ==
(id & BCM_PHY_ID_MASK)) {
found = B_TRUE;
break;
}
}
break;
default:
break;
}
return (found);
}
static uint32_t
nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port)
{
uint16_t val1 = 0;
uint16_t val2 = 0;
uint32_t pma_pmd_dev_id = 0;
npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
NXGE_DEV_ID_REG_1, &val1);
(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR,
NXGE_DEV_ID_REG_2, &val2);
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
pma_pmd_dev_id = val1;
pma_pmd_dev_id = (pma_pmd_dev_id << 16);
pma_pmd_dev_id |= val2;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD "
"devid[0x%llx]", phy_port, pma_pmd_dev_id));
return (pma_pmd_dev_id);
}
static uint32_t
nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port)
{
uint16_t val1 = 0;
uint16_t val2 = 0;
uint32_t pcs_dev_id = 0;
npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
NXGE_DEV_ID_REG_1, &val1);
(void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR,
NXGE_DEV_ID_REG_2, &val2);
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
pcs_dev_id = val1;
pcs_dev_id = (pcs_dev_id << 16);
pcs_dev_id |= val2;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
"devid[0x%llx]", phy_port, pcs_dev_id));
return (pcs_dev_id);
}
static uint32_t
nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port)
{
uint16_t val1 = 0;
uint16_t val2 = 0;
uint32_t phy_id = 0;
npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep);
npi_status_t npi_status = NPI_SUCCESS;
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1,
&val1);
if (npi_status != NPI_SUCCESS) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
"clause 22 read to reg 2 failed!!!"));
goto exit;
}
npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2,
&val2);
if (npi_status != 0) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
"clause 22 read to reg 3 failed!!!"));
goto exit;
}
phy_id = val1;
phy_id = (phy_id << 16);
phy_id |= val2;
exit:
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]",
phy_port, phy_id));
return (phy_id);
}
nxge_status_t
nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p)
{
int i, j, l;
uint32_t pma_pmd_dev_id = 0;
uint32_t pcs_dev_id = 0;
uint32_t phy_id = 0;
uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE];
uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE];
uint32_t port_phy_id[NXGE_PORTS_NEPTUNE];
uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS];
uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS];
uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS];
uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS];
uint8_t total_port_fd, total_phy_fd;
uint8_t num_xaui;
nxge_status_t status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: "));
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
nxgep->niu_type));
if (isLDOMguest(nxgep)) {
hw_p->niu_type = NIU_TYPE_NONE;
hw_p->platform_type = P_NEPTUNE_NONE;
return (NXGE_OK);
}
j = l = 0;
total_port_fd = total_phy_fd = 0;
for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i);
if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) {
pma_pmd_dev_fd[i] = 1;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] "
"PMA/PMD dev %x found", i, pma_pmd_dev_id));
if (j < NXGE_PORTS_NEPTUNE) {
if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
port_pma_pmd_dev_id[j] = TN1010_DEV_ID;
} else if ((pma_pmd_dev_id &
NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) {
port_pma_pmd_dev_id[j] =
NLP2020_DEV_ID;
} else {
port_pma_pmd_dev_id[j] =
pma_pmd_dev_id & BCM_PHY_ID_MASK;
}
port_fd_arr[j] = (uint8_t)i;
j++;
}
} else {
pma_pmd_dev_fd[i] = 0;
}
pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i);
if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) {
pcs_dev_fd[i] = 1;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS "
"dev %x found", i, pcs_dev_id));
if (pma_pmd_dev_fd[i] == 1) {
if ((pcs_dev_id & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
port_pcs_dev_id[j - 1] =
TN1010_DEV_ID;
} else if ((pcs_dev_id & NLP2020_DEV_ID_MASK)
== NLP2020_DEV_ID) {
port_pcs_dev_id[j - 1] =
NLP2020_DEV_ID;
} else {
port_pcs_dev_id[j - 1] =
pcs_dev_id &
BCM_PHY_ID_MASK;
}
} else {
if (j < NXGE_PORTS_NEPTUNE) {
if ((pcs_dev_id & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
port_pcs_dev_id[j] =
TN1010_DEV_ID;
} else if ((pcs_dev_id &
NLP2020_DEV_ID_MASK)
== NLP2020_DEV_ID) {
port_pcs_dev_id[j] =
NLP2020_DEV_ID;
} else {
port_pcs_dev_id[j] =
pcs_dev_id &
BCM_PHY_ID_MASK;
}
port_fd_arr[j] = (uint8_t)i;
j++;
}
}
} else {
pcs_dev_fd[i] = 0;
}
if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) {
total_port_fd ++;
}
phy_id = nxge_get_cl22_phy_id(nxgep, i);
if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) {
total_phy_fd ++;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID"
"%x found", i, phy_id));
if (l < NXGE_PORTS_NEPTUNE) {
if ((phy_id & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
port_phy_id[l] = TN1010_DEV_ID;
} else {
port_phy_id[l]
= phy_id & BCM_PHY_ID_MASK;
}
phy_fd_arr[l] = (uint8_t)i;
l++;
}
}
}
switch (total_port_fd) {
case 2:
switch (total_phy_fd) {
case 2:
if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
(port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
(port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) &&
((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
(port_phy_id[1] == PHY_BCM5482_FAMILY))) {
switch (hw_p->platform_type) {
case P_NEPTUNE_ROCK:
hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
hw_p->xcvr_addr[1] = port_fd_arr[0];
hw_p->xcvr_addr[0] = port_fd_arr[1];
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Rock with 2 10G, 2 1GC"));
break;
case P_NEPTUNE_NONE:
default:
hw_p->platform_type =
P_NEPTUNE_GENERIC;
hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF;
hw_p->xcvr_addr[0] = port_fd_arr[0];
hw_p->xcvr_addr[1] = port_fd_arr[1];
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"ARTM card with 2 10G, 2 1GF"));
break;
}
hw_p->xcvr_addr[2] = phy_fd_arr[0];
hw_p->xcvr_addr[3] = phy_fd_arr[1];
} else {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unsupported neptune type 1"));
goto error_exit;
}
break;
case 1:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 2 10G, 1 1G"));
goto error_exit;
case 0:
if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
(port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) ||
((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
(port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) ||
((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
(port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) ||
((port_pma_pmd_dev_id[0] ==
MARVELL_88X201X_PHY_ID) &&
(port_pma_pmd_dev_id[1] ==
MARVELL_88X201X_PHY_ID))) {
switch (port_fd_arr[0]) {
case NEPTUNE_CLAUSE45_PORT_ADDR_BASE:
hw_p->niu_type = NEPTUNE_2_10GF;
hw_p->platform_type =
P_NEPTUNE_ATLAS_2PORT;
break;
case GOA_CLAUSE45_PORT_ADDR_BASE:
if (hw_p->platform_type !=
P_NEPTUNE_NIU) {
hw_p->platform_type =
P_NEPTUNE_GENERIC;
hw_p->niu_type =
NEPTUNE_2_10GF;
}
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unsupported neptune type 2 - 1"));
goto error_exit;
}
for (i = 0; i < 2; i++) {
hw_p->xcvr_addr[i] = port_fd_arr[i];
}
} else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) &&
(port_pcs_dev_id[1] == NLP2020_DEV_ID)) ||
((port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) &&
(port_pma_pmd_dev_id[1] == NLP2020_DEV_ID))) {
if (hw_p->platform_type != P_NEPTUNE_NIU) {
hw_p->platform_type =
P_NEPTUNE_GENERIC;
hw_p->niu_type =
NEPTUNE_2_10GF;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Found 2 NL PHYs at addrs 0x%x and 0x%x",
port_fd_arr[0], port_fd_arr[1]));
hw_p->xcvr_addr[0] = port_fd_arr[0];
hw_p->xcvr_addr[1] = port_fd_arr[1];
} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID)) ||
(((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID))) {
hw_p->niu_type = NEPTUNE_2_TN1010;
hw_p->xcvr_addr[0] = port_fd_arr[0];
hw_p->xcvr_addr[1] = port_fd_arr[1];
} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
(port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) ||
(port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
(port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) ==
TN1010_DEV_ID)) {
hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010;
hw_p->xcvr_addr[0] = port_fd_arr[0];
hw_p->xcvr_addr[1] = port_fd_arr[1];
} else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY &&
(port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) ||
(port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
(port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID)) {
hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF;
hw_p->xcvr_addr[0] = port_fd_arr[0];
hw_p->xcvr_addr[1] = port_fd_arr[1];
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 2"));
goto error_exit;
}
break;
case 4:
if (nxge_get_num_of_xaui(
port_pma_pmd_dev_id, port_pcs_dev_id,
port_phy_id, &num_xaui) == NXGE_ERROR) {
goto error_exit;
}
if (num_xaui != 2)
goto error_exit;
switch (phy_fd_arr[0]) {
case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
hw_p->platform_type =
P_NEPTUNE_MARAMBA_P0;
break;
case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
hw_p->platform_type =
P_NEPTUNE_MARAMBA_P1;
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unknown port %d...Cannot "
"determine platform type", i));
goto error_exit;
}
hw_p->xcvr_addr[0] = port_fd_arr[0];
hw_p->xcvr_addr[1] = port_fd_arr[1];
hw_p->xcvr_addr[2] = phy_fd_arr[2];
hw_p->xcvr_addr[3] = phy_fd_arr[3];
if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
(port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC;
} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC;
} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) {
hw_p->niu_type = NEPTUNE_2_10GF_2_1GC;
} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
(port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC;
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 3"));
goto error_exit;
}
break;
default:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 5"));
goto error_exit;
}
break;
case 1:
switch (total_phy_fd) {
case 3:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 7"));
goto error_exit;
case 2:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 8"));
goto error_exit;
case 1:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 9"));
goto error_exit;
case 0:
if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
switch (port_fd_arr[0]) {
case N2_CLAUSE45_PORT_ADDR_BASE:
case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
case ALT_GOA_CLAUSE45_PORT1_ADDR:
if (hw_p->platform_type !=
P_NEPTUNE_NIU) {
hw_p->platform_type =
P_NEPTUNE_GENERIC;
hw_p->niu_type =
NEPTUNE_2_10GF;
}
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unsupported neptune type 10"));
goto error_exit;
}
if (port_fd_arr[0] ==
ALT_GOA_CLAUSE45_PORT1_ADDR) {
hw_p->xcvr_addr[1] = port_fd_arr[0];
} else {
hw_p->xcvr_addr[nxgep->function_num] =
port_fd_arr[0];
}
} else if (port_pcs_dev_id[0] == NLP2020_DEV_ID ||
port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) {
switch (port_fd_arr[0]) {
case NLP2020_CL45_PORT0_ADDR0:
case NLP2020_CL45_PORT0_ADDR1:
case NLP2020_CL45_PORT0_ADDR2:
case NLP2020_CL45_PORT0_ADDR3:
case NLP2020_CL45_PORT1_ADDR0:
case NLP2020_CL45_PORT1_ADDR1:
case NLP2020_CL45_PORT1_ADDR2:
case NLP2020_CL45_PORT1_ADDR3:
if (hw_p->platform_type !=
P_NEPTUNE_NIU) {
hw_p->platform_type =
P_NEPTUNE_GENERIC;
hw_p->niu_type =
NEPTUNE_2_10GF;
}
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unsupported neptune type 10-1"));
goto error_exit;
}
switch (port_fd_arr[0]) {
case NLP2020_CL45_PORT0_ADDR0:
case NLP2020_CL45_PORT0_ADDR1:
case NLP2020_CL45_PORT0_ADDR2:
case NLP2020_CL45_PORT0_ADDR3:
hw_p->xcvr_addr[0] = port_fd_arr[0];
break;
case NLP2020_CL45_PORT1_ADDR0:
case NLP2020_CL45_PORT1_ADDR1:
case NLP2020_CL45_PORT1_ADDR2:
case NLP2020_CL45_PORT1_ADDR3:
hw_p->xcvr_addr[1] = port_fd_arr[0];
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unsupported neptune type 10-11"));
goto error_exit;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Found 1 NL PHYs at addr 0x%x",
port_fd_arr[0]));
} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID ||
(port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
switch (port_fd_arr[0]) {
case N2_CLAUSE45_PORT_ADDR_BASE:
hw_p->niu_type = NEPTUNE_1_TN1010;
break;
case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
hw_p->niu_type
= NEPTUNE_1_NONE_1_TN1010;
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unsupported XAUI port address"));
goto error_exit;
}
hw_p->xcvr_addr[nxgep->function_num]
= port_fd_arr[0];
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported PHY type"));
goto error_exit;
}
break;
case 4:
if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) &&
(port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) &&
((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
!= TN1010_DEV_ID) &&
((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
!= TN1010_DEV_ID)) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 12"));
goto error_exit;
}
switch (phy_fd_arr[0]) {
case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE:
hw_p->platform_type =
P_NEPTUNE_MARAMBA_P0;
break;
case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
hw_p->platform_type =
P_NEPTUNE_MARAMBA_P1;
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unknown port %d...Cannot "
"determine platform type 10 - 2",
i));
goto error_exit;
}
switch (port_fd_arr[0]) {
case MARAMBA_CLAUSE45_PORT_ADDR_BASE:
if (port_pcs_dev_id[0]
== PHY_BCM8704_FAMILY ||
port_pma_pmd_dev_id[0]
== PHY_BCM8704_FAMILY) {
hw_p->niu_type
= NEPTUNE_1_10GF_3_1GC;
} else {
hw_p->niu_type
= NEPTUNE_1_TN1010_3_1GC;
}
hw_p->xcvr_addr[0] = port_fd_arr[0];
for (i = 1; i < NXGE_MAX_PORTS; i++) {
hw_p->xcvr_addr[i] =
phy_fd_arr[i];
}
break;
case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
if (port_pcs_dev_id[0]
== PHY_BCM8704_FAMILY ||
port_pma_pmd_dev_id[0]
== PHY_BCM8704_FAMILY) {
hw_p->niu_type =
NEPTUNE_1_1GC_1_10GF_2_1GC;
} else {
hw_p->niu_type =
NEPTUNE_1_1GC_1_TN1010_2_1GC;
}
hw_p->xcvr_addr[0] = phy_fd_arr[0];
hw_p->xcvr_addr[1] = port_fd_arr[0];
hw_p->xcvr_addr[2] = phy_fd_arr[2];
hw_p->xcvr_addr[3] = phy_fd_arr[3];
break;
default:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 11"));
goto error_exit;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Maramba with 1 XAUI (fiber or copper)"));
break;
default:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 13"));
goto error_exit;
}
break;
case 0:
switch (total_phy_fd) {
case 4:
if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
(port_phy_id[1] == PHY_BCM5464R_FAMILY) &&
(port_phy_id[2] == PHY_BCM5464R_FAMILY) &&
(port_phy_id[3] == PHY_BCM5464R_FAMILY)) {
switch (phy_fd_arr[0]) {
case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE:
hw_p->platform_type =
P_NEPTUNE_MARAMBA_P1;
break;
case NEPTUNE_CLAUSE22_PORT_ADDR_BASE:
hw_p->platform_type =
P_NEPTUNE_ATLAS_4PORT;
break;
default:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unknown port %d...Cannot "
"determine platform type", i));
goto error_exit;
}
hw_p->niu_type = NEPTUNE_4_1GC;
for (i = 0; i < NXGE_MAX_PORTS; i++) {
hw_p->xcvr_addr[i] = phy_fd_arr[i];
}
} else {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 14"));
goto error_exit;
}
break;
case 3:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 15"));
goto error_exit;
case 2:
if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
(port_phy_id[1] == PHY_BCM5482_FAMILY)) {
hw_p->platform_type = P_NEPTUNE_GENERIC;
hw_p->niu_type = NEPTUNE_2_1GRF;
hw_p->xcvr_addr[2] = phy_fd_arr[0];
hw_p->xcvr_addr[3] = phy_fd_arr[1];
} else {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"Unsupported neptune type 16"));
goto error_exit;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"2 RGMII Fiber ports - RTM"));
break;
case 1:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 17"));
goto error_exit;
default:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 18, total phy fd %d",
total_phy_fd));
goto error_exit;
}
break;
default:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"Unsupported neptune type 19"));
goto error_exit;
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, "
"niu type [0x%x]\n", hw_p->niu_type));
return (status);
error_exit:
return (NXGE_ERROR);
}
boolean_t
nxge_is_valid_local_mac(ether_addr_st mac_addr)
{
if ((mac_addr.ether_addr_octet[0] & 0x01) ||
(ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) ||
(ether_cmp(&mac_addr, ðerzeroaddr) == 0))
return (B_FALSE);
else
return (B_TRUE);
}
static void
nxge_bcm5464_link_led_off(p_nxge_t nxgep)
{
npi_status_t rs = NPI_SUCCESS;
uint8_t xcvr_portn;
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off"));
switch (nxgep->nxge_hw_p->platform_type) {
case P_NEPTUNE_MARAMBA_P1:
xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE;
break;
case P_NEPTUNE_MARAMBA_P0:
xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE;
break;
default:
xcvr_portn = 0;
break;
}
switch (portn) {
case 0:
xcvr_portn += 3;
break;
case 1:
xcvr_portn += 2;
break;
case 2:
xcvr_portn += 1;
break;
case 3:
default:
break;
}
MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock);
rs = npi_mac_mif_mii_write(nxgep->npi_handle,
xcvr_portn, BCM5464R_MISC, 0xb4ee);
if (rs != NPI_SUCCESS) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
"returned error 0x[%x]", rs));
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
return;
}
rs = npi_mac_mif_mii_write(nxgep->npi_handle,
xcvr_portn, BCM5464R_MISC, 0xb8ee);
if (rs != NPI_SUCCESS) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
"returned error 0x[%x]", rs));
}
MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock);
}
static nxge_status_t
nxge_mii_get_link_mode(p_nxge_t nxgep)
{
p_nxge_stats_t statsp;
uint8_t xcvr_portn;
p_mii_regs_t mii_regs;
mii_mode_control_stat_t mode;
int status = NXGE_OK;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode"));
statsp = nxgep->statsp;
xcvr_portn = statsp->mac_stats.xcvr_portn;
mii_regs = NULL;
mode.value = 0;
mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
if ((status = nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->shadow),
mode.value)) != NXGE_OK) {
goto fail;
}
if ((status = nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->shadow),
&mode.value)) != NXGE_OK) {
goto fail;
}
if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) {
nxgep->mac.portmode = PORT_1G_RGMII_FIBER;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_mii_get_link_mode: fiber mode"));
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_mii_get_link_mode: "
"(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
NXGE_MII_MODE_CONTROL_REG, xcvr_portn,
mode.value, nxgep->mac.portmode));
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_mii_get_link_mode"));
return (status);
fail:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"<== nxge_mii_get_link_mode (failed)"));
return (NXGE_ERROR);
}
nxge_status_t
nxge_mac_set_framesize(p_nxge_t nxgep)
{
npi_attr_t ap;
uint8_t portn;
npi_handle_t handle;
npi_status_t rs = NPI_SUCCESS;
NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize"));
portn = NXGE_GET_PORT_NUM(nxgep->function_num);
handle = nxgep->npi_handle;
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"==> nxge_mac_sec_framesize: port<%d> "
"min framesize %d max framesize %d ",
portn,
nxgep->mac.minframesize,
nxgep->mac.maxframesize));
SET_MAC_ATTR2(handle, ap, portn,
MAC_PORT_FRAME_SIZE,
nxgep->mac.minframesize,
nxgep->mac.maxframesize,
rs);
if (rs != NPI_SUCCESS) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_mac_set_framesize: failed to configure "
"max/min frame size port %d", portn));
return (NXGE_ERROR | rs);
}
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"<== nxge_mac_set_framesize: port<%d>", portn));
return (NXGE_OK);
}
static nxge_status_t
nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id,
uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui)
{
uint8_t i;
for (i = 0; i < 4; i++) {
if (port_phy_id[i] != PHY_BCM5464R_FAMILY)
return (NXGE_ERROR);
}
*num_xaui = 0;
if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) ||
(((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID))) {
(*num_xaui) ++;
}
if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY &&
port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) ||
(((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID))) {
(*num_xaui) ++;
}
return (NXGE_OK);
}
static nxge_status_t
nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed)
{
uint8_t phy_port_addr, autoneg_stat, link_up;
nxge_status_t status = NXGE_OK;
uint16_t val;
uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num);
*speed = TN1010_SPEED_10G;
npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE);
phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn];
status = nxge_mdio_read(nxgep, phy_port_addr,
TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val);
if (status != NXGE_OK)
goto fail;
link_up = ((val & TN1010_AN_LINK_STAT_BIT)
? B_TRUE : B_FALSE);
if (link_up == B_FALSE) {
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_get_tn1010_speed: link is down"));
goto nxge_get_tn1010_speed_exit;
}
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG,
&val)) != NXGE_OK) {
goto fail;
}
autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >>
TN1010_VENDOR_MMD1_AN_STAT_SHIFT;
switch (autoneg_stat) {
case TN1010_AN_IN_PROG:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_get_tn1010_speed: Auto-negotiation in progress"));
break;
case TN1010_AN_COMPLETE:
if ((status = nxge_mdio_read(nxgep, phy_port_addr,
TN1010_VENDOR_MMD1_DEV_ADDR,
TN1010_VENDOR_MMD1_STATUS_REG,
&val)) != NXGE_OK) {
goto fail;
}
*speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >>
TN1010_VENDOR_MMD1_AN_SPEED_SHIFT;
break;
case TN1010_AN_RSVD:
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_get_tn1010_speed: Autoneg status undefined"));
break;
case TN1010_AN_FAILED:
NXGE_DEBUG_MSG((nxgep, MAC_CTL,
"nxge_get_tn1010_speed: Auto-negotiation failed"));
break;
default:
break;
}
nxge_get_tn1010_speed_exit:
return (NXGE_OK);
fail:
return (status);
}
static nxge_status_t
nxge_set_tn1010_param(p_nxge_t nxgep)
{
uint16_t speed;
if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) {
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_set_tn1010_param: "
"Failed to get TN1010 speed"));
return (NXGE_ERROR);
}
if (speed == TN1010_SPEED_1G) {
nxgep->mac.portmode = PORT_1G_TN1010;
nxgep->statsp->mac_stats.link_speed = 1000;
nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR;
} else {
nxgep->mac.portmode = PORT_10G_TN1010;
nxgep->statsp->mac_stats.link_speed = 10000;
nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR;
}
return (NXGE_OK);
}
#ifdef NXGE_DEBUG
static void
nxge_mii_dump(p_nxge_t nxgep)
{
p_nxge_stats_t statsp;
uint8_t xcvr_portn;
p_mii_regs_t mii_regs;
mii_bmcr_t bmcr;
mii_bmsr_t bmsr;
mii_idr1_t idr1;
mii_idr2_t idr2;
mii_mode_control_stat_t mode;
p_nxge_param_t param_arr;
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump"));
statsp = nxgep->statsp;
xcvr_portn = statsp->mac_stats.xcvr_portn;
mii_regs = NULL;
(void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
xcvr_portn, bmcr.value));
(void) nxge_mii_read(nxgep,
nxgep->statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
xcvr_portn, bmsr.value));
(void) nxge_mii_read(nxgep,
nxgep->statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value);
(void) nxge_mii_read(nxgep,
nxgep->statsp->mac_stats.xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
xcvr_portn, idr1.value));
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
xcvr_portn, idr2.value));
mode.value = 0;
mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG;
(void) nxge_mii_write(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->shadow), mode.value);
(void) nxge_mii_read(nxgep, xcvr_portn,
(uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value);
NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
"nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
xcvr_portn, mode.value));
}
#endif