/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#define TN1010_SPEED_10G 0
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 {
/*
* Ethernet broadcast address definition.
*/
{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
/*
* Ethernet zero address definition.
*/
{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
/*
* Supported chip types
*/
};
};
sizeof (uint32_t))
sizeof (uint32_t))
/*
* static functions
*/
static void nxge_bcm5464_link_led_off(p_nxge_t);
uint8_t *);
#ifdef NXGE_DEBUG
static void nxge_mii_dump(p_nxge_t);
#endif
/*
* xcvr tables for supported transceivers
*/
/*
* nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems.
* The Teranetics TN1010 based copper XAUI card can also be used
* on N2-NIU systems in 10G mode, but it uses its own table
* nxge_n2_10G_tn1010_table below.
*/
};
/*
* For the Teranetics TN1010 based copper XAUI card
*/
nxge_n2_serdes_init, /* Handle both 1G and 10G */
nxge_tn1010_xcvr_init, /* Handle both 1G and 10G */
nxge_check_tn1010_link, /* Will figure out speed */
};
};
nxge_1G_fiber_link_intr_stop, /* TN1010 is a Cu PHY, but it uses */
nxge_1G_fiber_link_intr_start, /* PCS for 1G, so call fiber func */
};
};
};
};
NULL,
};
/* This table is for Neptune portmode == PORT_1G_SERDES cases */
};
NULL,
NULL,
NULL,
NULL,
};
/*
* NXGE_PORT_TN1010 is defined as,
* NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT)
* = 0 | 5 << 16 = 0x50000
*
* So NEPTUNE_2_TN1010 =
* (NXGE_PORT_TN1010 |
* (NXGE_PORT_TN1010 << 4) |
* (NXGE_PORT_NONE << 8) |
* (NXGE_PORT_NONE << 12)),
* = 0x50000 | (0x50000 << 4)
* = 0x550000
*
* This function partitions nxgep->nxge_hw_p->niu_type (which may have
* value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010
* = 0x50000
*/
{
& NXGE_PHY_MASK) == NXGE_PORT_TN1010) {
return (B_TRUE);
} else {
return (B_FALSE);
}
}
/*
* Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties,
* serial EEPROM or VPD if possible. Note that not all systems could get
* the portmode information by calling this function. For example, the
* Maramba system figures out the portmode information by calling function
* nxge_setup_xcvr_table.
*/
{
char *phy_type;
char *prop_val;
/* For Opus NEM, skip xcvr checking if 10G Serdes link is up */
return (status);
}
/*
* First check for hot swappable phy property.
*/
"hot-swappable-phy") == 1) {
"hot-swappable-phy") == 1) {
}
/*
* MDIO polling support for Monza RTM card, Goa NEM card
*/
if (portn > 1) {
return (NXGE_ERROR);
}
goto found_phy;
/* Check Serdes link to detect Opus NEM */
XPCS_REG_STATUS, &val);
"HSP 10G Serdes FOUND!!"));
}
goto check_phy_done;
"found for hot swappable phy"));
return (status);
}
/* Get phy-type property (May have been set by nxge.conf) */
"found conf file: phy-type %s", prop_val));
"found: 10G Serdes"));
/*
* Before OBP supports new phy-type property
* value "xgc", the 10G copper XAUI may carry
* "xgf" instead of "xgc". If the OBP is
* upgraded to a newer version which supports
* "xgc", then the TN1010 related code in this
* "xgf" case will not be used anymore.
*/
if (nxge_is_tn1010_phy(nxgep)) {
!= NXGE_OK) {
return (status);
}
} else { /* For Fiber XAUI */
"10G Fiber Xcvr"));
}
return (status);
}
"phy-type", prop_val);
"Got phy type [0x%x] from conf file",
return (NXGE_OK);
}
/* Get phy-type property from OBP */
/*
* Before OBP supports new phy-type property
* value "xgc", the 10G copper XAUI may carry
* "xgf" instead of "xgc". If the OBP is
* upgraded to a newer version which supports
* "xgc", then the TN1010 related code in this
* "xgf" case will not be used anymore.
*/
if (nxge_is_tn1010_phy(nxgep)) {
if ((status =
!= NXGE_OK) {
return (status);
}
"TN1010 Xcvr"));
} else if (nxge_is_nlp2020_phy(nxgep)) {
if ((status =
!= NXGE_OK) {
return (status);
}
"NLP2020 Xcvr"));
} else { /* For Fiber XAUI */
= XPCS_XCVR;
"10G Fiber Xcvr"));
}
"1G Copper Xcvr"));
"1G Fiber Xcvr"));
return (status);
"OBP: 10G Serdes"));
"OBP: 1G Serdes"));
} else {
"Unknown phy-type: %s", prop_val));
return (NXGE_ERROR);
}
(void) ddi_prop_update_string(DDI_DEV_T_NONE,
"Got phy type [0x%x] from OBP",
return (status);
} else {
"Exiting...phy-type property not found"));
return (NXGE_ERROR);
}
}
return (NXGE_OK);
}
goto read_seeprom;
}
"Reading phy type from expansion ROM"));
/*
* Try to read the phy type from the vpd data read off the
* expansion ROM.
*/
"nxge_get_xcvr_type: Failed to set TN1010 param"));
goto read_seeprom;
}
} else {
"nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM",
goto read_seeprom;
}
return (status);
/*
* read the phy type from the SEEPROM - NCR registers
*/
"Failed to get phy type"));
}
return (status);
}
/* Set up the PHY specific values. */
{
portn));
case N2_NIU:
case PORT_1G_FIBER:
case PORT_1G_SERDES:
"Serdes"));
break;
case PORT_10G_FIBER:
case PORT_10G_COPPER:
case PORT_10G_SERDES:
}
"Copper" : "Serdes")));
break;
case PORT_1G_TN1010:
"TN1010 Copper Xcvr in 1G"));
break;
case PORT_10G_TN1010:
"TN1010 Copper Xcvr in 10G"));
break;
case PORT_HSP_MODE:
"Swappable Xcvr (not present)"));
break;
default:
"<== nxge_setup_xcvr_table: "
"Unable to determine NIU portmode"));
return (NXGE_ERROR);
}
break;
default:
/*
* Would be the case for platforms like Maramba
* in which the phy type could not be got from conf
* file, OBP, VPD or Serial PROM.
*/
if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
"<== nxge_setup_xcvr_table:"
" Invalid Neptune type [0x%x]",
return (NXGE_ERROR);
}
switch (port_type) {
case NXGE_PORT_1G_COPPER:
break;
case NXGE_PORT_10G_COPPER:
break;
case NXGE_PORT_1G_FIBRE:
break;
case NXGE_PORT_10G_FIBRE:
break;
case NXGE_PORT_1G_SERDES:
break;
case NXGE_PORT_10G_SERDES:
break;
/* Ports 2 and 3 of Alonso or ARTM */
case NXGE_PORT_1G_RGMII_FIBER:
break;
case NXGE_PORT_TN1010:
/*
* If this port uses the TN1010 copper
* PHY, then its speed is not known yet
* because nxge_scan_ports_phy could only
* figure out the vendor of the PHY but
* not its speed. nxge_set_tn1010_param
* will read the PHY speed and set
* portmode accordingly.
*/
!= NXGE_OK) {
"nxge_set_tn1010_param failed"));
return (status);
}
break;
default:
"<== nxge_setup_xcvr_table: "
"Unknown port-type: 0x%x", port_type));
return (NXGE_ERROR);
}
}
/*
* Above switch has figured out nxge->mac.portmode, now set
* nxgep->xcvr (the table) and nxgep->xcvr_addr according
* to portmode.
*/
case PORT_1G_COPPER:
case PORT_1G_RGMII_FIBER:
/*
* For Altas 4-1G copper, Xcvr port numbers are
* swapped with ethernet port number. This is
* designed for better signal integrity in
* routing. This is also the case for the
* on-board Neptune copper ports on the Maramba
* platform.
*/
switch (nxgep->platform_type) {
case P_NEPTUNE_ATLAS_4PORT:
case P_NEPTUNE_MARAMBA_P0:
case P_NEPTUNE_MARAMBA_P1:
switch (portn) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
default:
return (NXGE_ERROR);
}
break;
default:
break;
}
"Copper" : "RGMII Fiber"));
break;
case PORT_10G_COPPER:
break;
case PORT_1G_TN1010:
"1G TN1010 copper Xcvr"));
break;
case PORT_10G_TN1010:
"10G TN1010 copper Xcvr"));
break;
case PORT_1G_FIBER:
case PORT_1G_SERDES:
"Fiber" : "Serdes"));
break;
case PORT_10G_FIBER:
case PORT_10G_SERDES:
"nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] "
"nxgep->xcvr_addr = [%d]",
}
switch (nxgep->platform_type) {
case P_NEPTUNE_MARAMBA_P0:
case P_NEPTUNE_MARAMBA_P1:
/*
* Switch off LED for corresponding copper
* port
*/
break;
default:
break;
}
"Fiber" : "Serdes"));
break;
case PORT_HSP_MODE:
"Swappable Xcvr (not present)"));
break;
default:
"Unknown port-type: 0x%x", port_type));
return (NXGE_ERROR);
}
}
"nxge_setup_xcvr_table: "
"Chip ID MARVELL [0x%x] for 10G xcvr", chip_id));
} else if ((pma_pmd_id & NLP2020_DEV_ID_MASK) ==
"nxge_setup_xcvr_table: "
"Chip ID AEL2020 [0x%x] for 10G xcvr", chip_id));
switch (chip_id) {
case BCM8704_CHIP_ID:
"nxge_setup_xcvr_table: "
"Chip ID 8704 [0x%x] for 10G xcvr",
chip_id));
break;
case BCM8706_CHIP_ID:
"nxge_setup_xcvr_table: "
"Chip ID 8706 [0x%x] for 10G xcvr",
chip_id));
break;
default:
"nxge_setup_xcvr_table: "
"Unknown Chip ID [0x%x] for 10G xcvr",
chip_id));
break;
}
}
}
/*
* Get the actual device ID value returned by MDIO read.
*/
} else {
} else {
}
}
}
return (status);
}
/* Initialize the entire MAC and physical layer */
{
/* Initialize XIF to configure a network mode */
goto fail;
}
goto fail;
}
/* Initialize TX and RX MACs */
/*
* Always perform XIF init first, before TX and RX MAC init
*/
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
}
/* Initialize MAC control configuration */
goto fail;
}
/* The Neptune Serdes needs to be reinitialized again */
if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
"nxge_mac_init: reinit Neptune 1G Serdes "));
goto fail;
}
}
return (NXGE_OK);
fail:
"nxge_mac_init: failed to initialize MAC port<%d>", portn));
return (status);
}
/* Initialize the Ethernet Link */
{
#ifdef NXGE_DEBUG
#endif
/* For Opus NEM, Serdes always needs to be initialized */
/*
* Workaround to get link up in both NIU ports. Some portmodes require
* that the xcvr be initialized twice, the first time before calling
* nxge_serdes_init.
*/
(portmode != PORT_10G_TN1010) &&
(portmode != PORT_1G_TN1010) &&
(portmode != PORT_1G_SERDES)) {
goto fail;
}
}
NXGE_DELAY(200000);
/* Initialize internal serdes */
goto fail;
NXGE_DELAY(200000);
goto fail;
return (NXGE_OK);
fail:
"failed to initialize Ethernet link on port<%d>", portn));
return (status);
}
/* Initialize the XIF sub-block within the MAC */
{
if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) &&
"nxge_xcvr_init: set ATCA mode"));
}
if (portt == PORT_TYPE_XMAC) {
/* Setup XIF Configuration for XMAC */
if ((portmode == PORT_10G_FIBER) ||
(portmode == PORT_10G_COPPER) ||
(portmode == PORT_10G_TN1010) ||
(portmode == PORT_HSP_MODE) ||
(portmode == PORT_10G_SERDES))
/* Bypass PCS so that RGMII will be used */
if (portmode == PORT_1G_COPPER) {
}
/* Set MAC Internal Loopback if necessary */
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)) {
/* Assume LED same for 1G and 10G */
} else {
}
}
if (rs != NPI_SUCCESS)
goto fail;
/* Set Port Mode */
if ((portmode == PORT_10G_FIBER) ||
(portmode == PORT_10G_COPPER) ||
(portmode == PORT_10G_TN1010) ||
(portmode == PORT_HSP_MODE) ||
(portmode == PORT_10G_SERDES)) {
MAC_XGMII_MODE, rs);
if (rs != NPI_SUCCESS)
goto fail;
goto fail;
} else {
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_xif_init: Port[%d] Mode[%d] Speed[%d]",
MAC_GMII_MODE, rs);
} else {
MAC_MII_MODE, rs);
}
if (rs != NPI_SUCCESS)
goto fail;
} else {
"nxge_xif_init: Unknown port mode (%d)"
goto fail;
}
/* Enable ATCA mode */
} else if (portt == PORT_TYPE_BMAC) {
/* Setup XIF Configuration for BMAC */
if ((portmode == PORT_1G_COPPER) ||
(portmode == PORT_1G_RGMII_FIBER)) {
}
if (rs != NPI_SUCCESS)
goto fail;
}
return (NXGE_OK);
fail:
"nxge_xif_init: Failed to initialize XIF port<%d>", portn));
return (NXGE_ERROR | rs);
}
/*
* Initialize the PCS sub-block in the MAC. Note that PCS does not
* support loopback like XPCS.
*/
{
uint8_t i;
if (portmode == PORT_1G_FIBER ||
portmode == PORT_1G_TN1010 ||
portmode == PORT_1G_SERDES) {
if (portmode == PORT_1G_TN1010) {
/* Reset PCS multiple time in PORT_1G_TN1010 mode */
for (i = 0; i < 6; i ++) {
!= NPI_SUCCESS) {
goto fail;
}
}
} else {
!= NPI_SUCCESS)
goto fail;
}
/* Initialize port's PCS */
"==> nxge_pcs_init: (1G) port<%d> write config 0x%llx",
if (portmode == PORT_1G_TN1010) {
/*
* Must disable PCS auto-negotiation when the the driver
* is driving the TN1010 based XAUI card Otherwise the
* autonegotiation between the PCS and the TN1010 PCS
*/
}
} else if (portmode == PORT_10G_FIBER ||
portmode == PORT_10G_COPPER ||
portmode == PORT_10G_TN1010 ||
portmode == PORT_HSP_MODE ||
portmode == PORT_10G_SERDES) {
/* Use internal XPCS, bypass 1G PCS */
val &= ~XMAC_XIF_XPCS_BYPASS;
goto fail;
/* Set XPCS Internal Loopback if necessary */
goto fail;
val |= XPCS_CTRL1_LOOPBK;
else
val &= ~XPCS_CTRL1_LOOPBK;
goto fail;
/* Clear descw errors */
XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS)
goto fail;
/* Clear symbol errors */
goto fail;
goto fail;
} else if ((portmode == PORT_1G_COPPER) ||
(portmode == PORT_1G_RGMII_FIBER)) {
"==> nxge_pcs_init: (1G) copper port<%d>", portn));
if (portn < 4) {
}
goto fail;
} else {
goto fail;
}
pass:
return (NXGE_OK);
fail:
"nxge_pcs_init: Failed to initialize PCS port<%d>", portn));
return (NXGE_ERROR | rs);
}
/*
* Initialize the MAC CTRL sub-block within the MAC
* Only the receive-pause-cap is supported.
*/
{
portn));
if (portt == PORT_TYPE_XMAC) {
/* Reading the current XMAC Config Register for XMAC */
/*
* Setup XMAC Configuration for XMAC
* XMAC only supports receive-pause
*/
/*
* If adv_cap_asmpause is 1 and adv_cap_pause
* is 0, enable receive pause.
*/
} else {
/*
* If adv_cap_asmpause is 1 and adv_cap_pause
* is 1, disable receive pause. Send pause is
* not supported.
*/
}
} else {
"==> nxge_mac_ctrl_init: port<%d>: pause",
portn));
"==> nxge_mac_ctrl_init: port<%d>: "
"enable pause", portn));
/*
* If adv_cap_asmpause is 0 and adv_cap_pause
* is 1, enable receive pause.
*/
} else {
/*
* If adv_cap_asmpause is 0 and adv_cap_pause
* is 0, disable receive pause. Send pause is
* not supported
*/
"==> nxge_mac_ctrl_init: port<%d>: "
"disable pause", portn));
}
}
} else if (portt == PORT_TYPE_BMAC) {
/* Reading the current MAC CTRL Config Register for BMAC */
/* Setup MAC CTRL Configuration for BMAC */
/*
* If adv_cap_asmpause is 1 and adv_cap_pause
* is 1, disable receive pause. Send pause
* is not supported
*/
} else {
/*
* If adv_cap_asmpause is 1 and adv_cap_pause
* is 0, enable receive pause and disable
* send pause.
*/
}
} else {
/*
* If adv_cap_asmpause is 0 and adv_cap_pause
* is 1, enable receive pause. Send pause is
* not supported.
*/
} else {
/*
* If adv_cap_asmpause is 0 and adv_cap_pause
* is 0, pause capability is not available in
* either direction.
*/
val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN &
}
}
}
portn));
return (NXGE_OK);
}
/* Initialize the Internal Serdes */
{
#ifdef NXGE_DEBUG
#endif
#ifdef NXGE_DEBUG
"==> nxge_serdes_init port<%d>", portn));
#endif
goto fail;
}
portn));
return (NXGE_OK);
fail:
"nxge_serdes_init: Failed to initialize serdes for port<%d>",
portn));
return (status);
}
/* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */
static nxge_status_t
{
int chan;
#ifdef NXGE_DEBUG
#endif
portn));
"==> nxge_n2_serdes_init port<%d>: KT-NIU", portn));
return (nxge_n2_kt_serdes_init(nxgep));
}
/*
* If the nxge driver has been plumbed without a link, then it will
* detect a link up when a cable connecting to an anto-negotiation
* partner is plugged into the port. Because the TN1010 PHY supports
* both 1G and 10G speeds, the driver must re-configure the
* is called at the post-link-up reconfiguration time. Here it calls
* nxge_set_tn1010_param to set portmode before re-initializing
* the serdes.
*/
goto fail;
}
}
/* 0x0E01 */
/* 0x9101 */
/* 0x0008 */
/* Set loopback mode if necessary */
goto fail;
}
/* Initialize PLL for 10G */
goto fail;
goto fail;
#ifdef NXGE_DEBUG
"==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
"==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
#endif
/* 0x0E21 */
/* 0x9121 */
if (portn == 0) {
/* 0x8 */
}
/* Initialize PLL for 1G */
goto fail;
goto fail;
#ifdef NXGE_DEBUG
"==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
"==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)",
#endif
/* Set loopback mode if necessary */
"==> nxge_n2_serdes_init port<%d>: loopback 0x%x",
goto fail;
}
}
} else {
goto fail;
}
/* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */
NXGE_DELAY(20);
/* init TX channels */
goto fail;
goto fail;
"==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x",
"==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x",
}
/* init RX channels */
goto fail;
goto fail;
"==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x",
"==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x",
}
portn));
return (NXGE_OK);
fail:
"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
portn));
return (status);
}
/* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */
static nxge_status_t
{
int chan, i;
#ifdef NXGE_DEBUG
#endif
"==> nxge_n2_kt_serdes_init port<%d>", portn));
/*
* The following setting assumes the reference clock frquency
* is 156.25 MHz.
*/
/*
* If the nxge driver has been plumbed without a link, then it will
* detect a link up when a cable connecting to an anto-negotiation
* partner is plugged into the port. Because the TN1010 PHY supports
* both 1G and 10G speeds, the driver must re-configure the
* is called at the post-link-up reconfiguration time. Here it calls
* nxge_set_tn1010_param to set portmode before re-initializing
* the serdes.
*/
goto fail;
}
}
/* Take tunables from OBP if present, otherwise use defaults */
} else {
/* 0x1e21 */
}
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
} else {
/* channel 0: enable syn. master */
/* 0x40 */
}
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
} else {
/* 0x4821 */
}
"==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
} else {
/* 0x0008 */
}
"==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x",
} else {
/* 0xa1: Initialize PLL for 10G */
}
"==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
goto fail;
"==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
/* Set loopback mode if necessary */
"==> nxge_n2_kt_serdes_init port<%d>: "
}
#ifdef NXGE_DEBUG
"==> nxge_n2_kt_serdes_init port<%d>: "
"PLL cfg.l 0x%x (0x%x)",
"==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
#endif
/* 0x1e41 */
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x",
/* channel 0: enable syn. master */
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
/* 0x4841 */
"==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x",
/* 0x0008 */
"==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x",
/* 0xa1: Initialize PLL for 1G */
"==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x",
!= NXGE_OK)
goto fail;
#ifdef NXGE_DEBUG
"==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)",
"==> nxge_n2_kt_serdes_init port<%d>: (0x%x)",
#endif
/* Set loopback mode if necessary */
"==> nxge_n2_kt_serdes_init port<%d>: "
goto fail;
}
}
} else {
"nxge_n2_kt_serdes_init:port<%d> - "
"unsupported port mode %d",
goto fail;
}
NXGE_DELAY(20);
/* Clear the test register (offset 0x8004) */
goto fail;
}
NXGE_DELAY(20);
/* init TX channels */
if (mode_1g)
goto fail;
goto fail;
"==> nxge_n2_kt_serdes_init port<%d>: "
"==> nxge_n2_kt_serdes_init port<%d>: "
}
/* init RX channels */
/* 1G mode only write to the first channel */
!= NXGE_OK)
goto fail;
!= NXGE_OK)
goto fail;
"==> nxge_n2_kt_serdes_init port<%d>: "
"==> nxge_n2_kt_serdes_init port<%d>: "
}
if (portn == 0) {
/* Wait for serdes to be ready */
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
if ((val & ESR_SIG_P0_BITS_MASK) !=
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
/*
* RDY signal stays low may due to the absent of the
* external PHY, it is not an error condition.
* But still print the message for the debugging
* purpose when link stays down
*/
"nxge_n2_kt_serdes_init: "
goto done;
}
} else if (portn == 1) {
/* Wait for serdes to be ready */
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
if ((val & ESR_SIG_P1_BITS_MASK) !=
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
/*
* RDY signal stays low may due to the absent of the
* external PHY, it is not an error condition.
* But still print the message for the debugging
* purpose when link stays down
*/
"nxge_n2_kt_serdes_init: "
goto done;
}
}
done:
"<== nxge_n2_kt_serdes_init port<%d>", portn));
return (NXGE_OK);
fail:
"nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>",
portn));
return (status);
}
/* Initialize the Neptune Internal Serdes for 10G (Neptune only) */
static nxge_status_t
{
int chan, i;
return (NXGE_OK);
"==> nxge_neptune_10G_serdes_init port<%d>", portn));
switch (portn) {
case 0:
/* Reset Serdes */
NXGE_DELAY(20);
NXGE_DELAY(2000);
/* Configure Serdes to 10G mode */
(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));
/* Set Serdes0 Internal Loopback if necessary */
} else {
}
break;
case 1:
/* Reset Serdes */
NXGE_DELAY(20);
NXGE_DELAY(2000);
/* Configure Serdes to 10G mode */
(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));
/* Set Serdes1 Internal Loopback if necessary */
} else {
}
break;
default:
/* Nothing to do here */
goto done;
}
/* init TX RX channels */
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
goto fail;
}
/* Apply Tx core reset */
goto fail;
goto fail;
NXGE_DELAY(200);
/* Apply Rx core reset */
goto fail;
NXGE_DELAY(200);
goto fail;
NXGE_DELAY(200);
goto fail;
goto fail;
"Failed to reset port<%d> XAUI Serdes "
"(val16l 0x%x val16h 0x%x)",
}
if (portn == 0) {
/* Wait for serdes to be ready */
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
if ((val & ESR_SIG_P0_BITS_MASK) !=
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
/*
* RDY signal stays low may due to the absent of the
* external PHY, it is not an error condition. But still
* print the message for the debugging purpose when link
* stays down
*/
"nxge_neptune_10G_serdes_init: "
goto done;
}
} else if (portn == 1) {
/* Wait for serdes to be ready */
for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) {
if ((val & ESR_SIG_P1_BITS_MASK) !=
else
break;
}
if (i == MAX_SERDES_RDY_RETRIES) {
/*
* RDY signal stays low may due to the absent of the
* external PHY, it is not an error condition. But still
* print the message for the debugging purpose when link
* stays down
*/
"nxge_neptune_10G_serdes_init: "
goto done;
}
}
done:
"<== nxge_neptune_10G_serdes_init port<%d>", portn));
return (NXGE_OK);
fail:
"nxge_neptune_10G_serdes_init: "
"Failed to initialize Neptune serdes for port<%d>", portn));
return (status);
}
/* Initialize Neptune Internal Serdes for 1G (Neptune only) */
static nxge_status_t
{
int chan;
"==> nxge_1G_serdes_init port<%d>", portn));
switch (portn) {
case 0:
/* Assert the reset register */
val |= ESR_RESET_0;
/* Set the PLL register to 0x79 */
/* Set the control register to 0x249249f */
/* Set Serdes0 Internal Loopback if necessary */
/* Set pad loopback modes 0xaa */
} else {
}
/* Deassert the reset register */
val &= ~ESR_RESET_0;
break;
case 1:
/* Assert the reset register */
val |= ESR_RESET_1;
/* Set PLL register to 0x79 */
/* Set the control register to 0x249249f */
/* Set Serdes1 Internal Loopback if necessary */
/* Set pad loopback mode 0xaa */
} else {
}
/* Deassert the reset register */
val &= ~ESR_RESET_1;
break;
default:
/* Nothing to do here */
goto done;
}
/* init TX RX channels */
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
}
goto fail;
}
goto fail;
}
goto fail;
}
goto fail;
}
/* Apply Tx core reset */
goto fail;
}
NXGE_OK) {
goto fail;
}
NXGE_DELAY(200);
/* Apply Rx core reset */
NXGE_OK) {
goto fail;
}
NXGE_DELAY(200);
goto fail;
}
NXGE_DELAY(200);
goto fail;
}
goto fail;
}
"Failed to reset port<%d> XAUI Serdes "
status = NXGE_ERROR;
goto fail;
}
NXGE_DELAY(200);
"nxge_neptune_serdes_init: read internal signal reg port<%d> "
if (portn == 0) {
if ((val & ESR_SIG_P0_BITS_MASK_1G) !=
/*
* RDY signal stays low may due to the absent of the
* external PHY, it is not an error condition. But still
* print the message for the debugging purpose when link
* stays down
*/
"nxge_neptune_1G_serdes_init: "
goto done;
}
} else if (portn == 1) {
if ((val & ESR_SIG_P1_BITS_MASK_1G) !=
/*
* RDY signal stays low may due to the absent of the
* external PHY, it is not an error condition. But still
* print the message for the debugging purpose when link
* stays down
*/
"nxge_neptune_1G_serdes_init: "
goto done;
}
}
done:
"<== nxge_1G_serdes_init port<%d>", portn));
return (NXGE_OK);
fail:
"nxge_1G_serdes_init: "
"Failed to initialize Neptune serdes for port<%d>",
portn));
return (status);
}
{ \
int i; \
\
break; \
} \
"From OBP, write<dev.reg.val> = " \
"<0x%x.0x%x.0x%x>", \
} \
} \
}
/* Initialize the BCM 8704 xcvr */
static nxge_status_t
{
#ifdef NXGE_DEBUG
#endif
#ifdef NXGE_DEBUG
#endif
portn));
/* Reset the transceiver */
goto fail;
goto fail;
do {
drv_usecwait(500);
goto fail;
delay++;
if (delay == 100) {
"failed to reset Transceiver on port<%d>", portn));
status = NXGE_ERROR;
goto fail;
}
/* Set to 0x7FBF */
!= NXGE_OK)
goto fail;
/* Set to 0x164 */
goto fail;
/*
* According to Broadcom's instruction, SW needs to read
* back these registers twice after written.
*/
!= NXGE_OK)
goto fail;
!= NXGE_OK)
goto fail;
!= NXGE_OK)
goto fail;
!= NXGE_OK)
goto fail;
/* Enable Tx and Rx LEDs to be driven by traffic */
goto fail;
if (NXGE_IS_XAUI_PLATFORM(nxgep)) {
} else {
}
goto fail;
NXGE_DELAY(1000000);
/*
* Set XAUI link tunables from OBP if present.
*/
"nxge_BCM8704_xcvr_init: Failed setting PHY tunables"));
goto fail;
}
/* Set BCM8704 Internal Loopback mode if necessary */
!= NXGE_OK)
goto fail;
else
!= NXGE_OK)
goto fail;
goto fail;
goto fail;
goto fail;
#ifdef NXGE_DEBUG
/* Diagnose link issue if link is not up */
&val);
goto fail;
goto fail;
goto fail;
goto fail;
if (val != 0x3FC) {
"Cable not connected to peer or bad"
" cable on port<%d>\n", portn));
} else if (val == 0x639C) {
"Optical module (XFP) is bad or absent"
" on port<%d>\n", portn));
}
}
#endif
portn));
return (NXGE_OK);
fail:
"nxge_BCM8704_xcvr_init: failed to initialize transceiver for "
return (NXGE_ERROR);
}
/* Initialize the BCM 8706 Transceiver */
static nxge_status_t
{
#ifdef NXGE_DEBUG
#endif
portn));
/* Reset the transceiver */
goto fail;
goto fail;
do {
drv_usecwait(500);
goto fail;
delay++;
if (delay == 100) {
"failed to reset Transceiver on port<%d>", portn));
status = NXGE_ERROR;
goto fail;
}
NXGE_DELAY(1000000);
/*
* Set XAUI link tunables from OBP if present.
*/
"nxge_BCM8706_xcvr_init: Failed setting PHY tunables"));
goto fail;
}
/* Set BCM8706 Internal Loopback mode if necessary */
!= NXGE_OK)
goto fail;
else
!= NXGE_OK)
goto fail;
/* Enable Tx and Rx LEDs to be driven by traffic */
goto fail;
goto fail;
portn));
return (NXGE_OK);
fail:
"nxge_BCM8706_xcvr_init: failed to initialize transceiver for "
return (status);
}
static int
{
/*
* NLP2020_I2C_SNOOP_ADDR_REG [15:9][1] - Address
* NLP2020_I2C_SNOOP_ADDR_REG[7:0] - register in the xcvr's i2c
*/
goto fail;
&stat);
}
if (count) {
&phy_data);
return (0);
}
fail:
"nxge_nlp2020_i2c_read: FAILED"));
return (1);
}
/* Initialize the Netlogic AEL2020 Transceiver */
#define NLP_INI_STOP 0
{0x1C003, 0x3101},
{0x1CC01, 0x488a},
{0x1CB1B, 0x0200},
{0x1CB1C, 0x00f0},
{0x1CC06, 0x00e0},
{NLP_INI_STOP, 0},
};
{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
{
/* Reset the transceiver */
!= NXGE_OK)
goto fail;
drv_usecwait(1000);
}
if (count == 0) {
"PMA_PMD reset failed"));
goto fail;
}
/* Set loopback mode if required */
/* Set PMA PMD system loopback */
!= NXGE_OK)
goto fail;
pmd_ctl |= 0x0001;
else
pmd_ctl &= 0xfffe;
!= NXGE_OK)
goto fail;
"setting LB, wrote NLP2020_PMA_PMD_CTL_REG[0x%x]", pmd_ctl));
/* Check connector details using I2c */
goto fail;
}
switch (connector) {
case SFPP_FIBER:
"nxge_nlp2020_xcvr_init: SFPP_FIBER detected"));
break;
case QSFP_FIBER:
"nxge_nlp2020_xcvr_init: QSFP_FIBER detected"));
break;
case QSFP_COPPER_TWINAX:
"nxge_nlp2020_xcvr_init: QSFP_COPPER_TWINAX/"
"SFPP_COPPER_TWINAX detected"));
break;
default:
"nxge_nlp2020_xcvr_init: Unknown type [0x%x] detected",
"...setting to QSFP_FIBER",
connector));
break;
}
/* Run appropriate init sequence */
if (reg == NLP_INI_WAIT) {
} else {
goto fail;
}
}
/* rx_los inversion */
goto fail;
rx_los &= ~(NLP2020_RXLOS_ACT_H);
goto fail;
goto fail;
}
goto fail;
}
if (connector == QSFP_COPPER_TWINAX) {
if (len >= 7) {
/* enable pre-emphasis */
/* write emphasis value */
/* stop microcontroller */
/* reset program counter */
/* start microcontroller */
}
}
if (lpm & QSFP_MSA_LPM_HIGH) {
/* enable high power mode */
} else {
/* revert to low power mode */
}
/*
* Set XAUI link tunables from OBP if present.
*/
"nxge_nlp2020_xcvr_init: Failed setting PHY tunables"));
goto fail;
}
/* It takes ~2s for EDC to settle */
drv_usecwait(2000000);
return (NXGE_OK);
fail:
"nxge_nlp2020_xcvr_init: failed to initialize transceiver for "
return (status);
}
{
return (B_TRUE);
} else {
return (B_FALSE);
}
}
{
return (connector);
}
{
switch (connector) {
case SFPP_FIBER:
"nxge_set_nlp2020_param: SFPP_FIBER detected"));
break;
case QSFP_FIBER:
"nxge_set_nlp2020_param: QSFP_FIBER detected"));
break;
case QSFP_COPPER_TWINAX:
"nxge_set_nlp2020_param: QSFP_COPPER_TWINAX/"
"SFPP_COPPER_TWINAX detected"));
break;
default:
"nxge_set_nlp2020_param: Unknown type [0x%x] detected"
"...setting to QSFP_FIBER",
connector));
break;
}
return (NXGE_OK);
}
static void
{
value);
}
}
static nxge_status_t
{
else
fail:
return (status);
}
static void
{
"nxge_mrvl88x2011_led: nxge_mdio_write failed!!"));
}
}
static nxge_status_t
{
"==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>",
/* Set LED functions */
/* PCS activity */
/* Set internal loopback mode if necessary */
/* Enable PMD */
fail:
return (status);
}
/* Initialize the 10G Transceiver */
static nxge_status_t
{
#ifdef NXGE_DEBUG
#endif
portn));
/* Disable Link LEDs, with or without PHY */
goto done;
/* Skip MDIO, if PHY absent */
goto done;
}
/* Set Clause 45 */
case BCM8704_CHIP_ID:
break;
case BCM8706_CHIP_ID:
break;
case MRVL88X201X_CHIP_ID:
break;
case NLP2020_CHIP_ID:
break;
default:
"Unknown chip ID 0x%x for 10G xcvr addr[%d]",
goto fail;
}
goto fail;
}
done:
portn));
return (NXGE_OK);
fail:
"nxge_10G_xcvr_init: failed to initialize transceiver for "
return (NXGE_ERROR);
}
/* Initialize the 1G copper (BCM 5464) Transceiver */
static nxge_status_t
{
goto done;
}
/* Set Clause 22 */
/* Set capability flags */
}
done:
return (status);
}
/*
* Although the Teranetics copper transceiver (TN1010) does not need
* to be initialized by the driver for passing packets, this funtion
* initializes the members of nxgep->statsp->mac_stats struct for
* kstat based on the value of nxgep->statsp->ports_stats.lb_mode.
* It also configures the TN1010 for PHY loopback to support SunVTS.
*
* TN1010 only has the option to disable advertisement for the 10G
* mode. So we can set it to either Dual Mode or 1G Only mode but
* can't set it to 10G Only mode.
*
*
* ----------------------------------------------------------------
* ----------------------------------------------------------------
* adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg
* adv_10gfdx_cap
* adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx
* adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx
* adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx
* adv_pause_cap kstat nxge:1 | grep adv_cap_pause
* ----------------------------------------------------------------
*/
static nxge_status_t
{
/*
* Initialize the xcvr statistics which are NOT controlled by ndd
*/
/*
* Read the TN1010 link speed and initialize capabilities kstat. Note
* that function nxge_check_tn1010_link repeatedly invoked by the
* timer will update link_speed real time.
*/
goto fail;
}
if (speed == TN1010_SPEED_1G) {
} else {
}
/* Whether we are in 1G or 10G mode, we always have the 1G capability */
/* TN1010 is not able to operate in the following states */
/* param_anar_pause can be modified by ndd -set */
/*
* The following 4 lines actually overwrites what ever the ndd command
* has set. For example, by command
* we could set param_arr[param_autoneg].value to n. However, because
* here we assign constants to these parameters, whatever we set with
* the "ndd -set" command will be replaced. So command
* kstat nxge:X | grep param
* will always show those constant values. In other words, the
* "ndd -set" command can NOT change the values of these 4 parameters
* even though the command appears to be successful.
*
* Note: TN1010 auto negotiation is always enabled.
*/
/*
* The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as
* defined in nxge_param_arr[], therefore they are not seen by the
* "ndd -get" command and can not be changed by ndd. We just set
* them (both ndd param and kstat values) to constant 0 because TN1010
* does not support those speeds.
*/
/*
* adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified
* by ndd
*/
/*
* nxge_param_arr[] defines the adv_cap_asmpause with type
* NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the
* "ndd -get" command and can not be changed by ndd. Here we do not
* assign a constant to it so the default value defined in
* nxge_param_arr[] will be used to set the parameter and
* will be shown by the kstat.
*/
/*
* Initialize the link statistics.
*/
if (speed == TN1010_SPEED_1G) {
} else {
}
/*
* Because TN1010 does not have a link partner register, to
* figure out the link partner's capabilities is tricky. Here we
* just set the kstat based on our knowledge about the partner
* (The partner must support auto-neg because auto-negotiation
* has completed, it must support 1G or 10G because that is the
* negotiated speed we are using.)
*
* Note: Current kstat does not show lp_cap_10gfdx and
* lp_cap_10ghdx.
*/
if (speed == TN1010_SPEED_1G) {
} else {
}
/* Handle PHY loopback for SunVTS loopback test */
goto fail;
}
} else {
}
goto fail;
}
"<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
return (status);
fail:
"<== nxge_1G_tn1010_xcvr_init status 0x%x", status));
return (status);
}
/* Initialize transceiver */
{
#ifdef NXGE_DEBUG
#endif
#ifdef NXGE_DEBUG
#endif
/*
* Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will
* modify mac_stats.
*/
/*
* Initialize the link statistics.
*/
goto fail;
}
portn));
return (NXGE_OK);
fail:
"nxge_xcvr_init: failed to initialize transceiver for port<%d>",
portn));
return (status);
}
/* Look for transceiver type */
{
return (NXGE_ERROR);
return (NXGE_ERROR);
return (NXGE_OK);
}
/* Initialize the TxMAC sub-block */
{
portn));
/* Set Max and Min Frame Size */
/*
* Use maxframesize to configure the hardware maxframe size
* and minframesize to configure the hardware minframe size.
*/
"==> nxge_tx_mac_init: port<%d> "
"min framesize %d max framesize %d ",
portn));
rs);
if (rs != NPI_SUCCESS)
goto fail;
if (portt == PORT_TYPE_XMAC) {
0)) != NPI_SUCCESS)
goto fail;
if ((portmode == PORT_10G_FIBER) ||
(portmode == PORT_10G_COPPER) ||
(portmode == PORT_10G_TN1010) ||
(portmode == PORT_HSP_MODE) ||
(portmode == PORT_10G_SERDES)) {
if (rs != NPI_SUCCESS)
goto fail;
} else {
if (rs != NPI_SUCCESS)
goto fail;
}
goto fail;
!= NPI_SUCCESS)
goto fail;
} else {
0)) != NPI_SUCCESS)
goto fail;
rs);
if (rs != NPI_SUCCESS)
goto fail;
if (rs != NPI_SUCCESS)
goto fail;
goto fail;
}
portn));
return (NXGE_OK);
fail:
"nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn));
return (NXGE_ERROR | rs);
}
static npi_status_t
{
uint32_t i;
/*
* Load the multicast hash filter bits.
*/
for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
if (hash_filter != NULL) {
(NMCFILTER_REGS - 1) - i];
} else {
hashtab_e = 0;
}
return (rs);
}
return (NPI_SUCCESS);
}
/*
* Initialize the RxMAC sub-block
*/
{
portn));
if (rs != NPI_SUCCESS)
goto fail;
if (rs != NPI_SUCCESS)
goto fail;
if (rs != NPI_SUCCESS)
goto fail;
if (rs != NPI_SUCCESS)
goto fail;
if (portt == PORT_TYPE_XMAC) {
0)) != NPI_SUCCESS)
goto fail;
(void) nxge_fflp_init_hostinfo(nxgep);
goto fail;
/*
* Comparison of mac unique address is always
* enabled on XMAC
*/
!= NPI_SUCCESS)
goto fail;
} else {
0) != NPI_SUCCESS)
goto fail;
(void) nxge_fflp_init_hostinfo(nxgep);
goto fail;
/*
* Always enable comparison of mac unique address
*/
portn, 0)) != NPI_SUCCESS)
goto fail;
}
portn));
return (NXGE_OK);
fail:
"nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn));
return (NXGE_ERROR | rs);
}
/* Enable TXMAC */
{
goto fail;
/* based on speed */
CFG_XMAC_TX)) != NPI_SUCCESS)
goto fail;
} else {
CFG_BMAC_TX)) != NPI_SUCCESS)
goto fail;
}
return (NXGE_OK);
fail:
"nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC",
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (status);
}
/* Disable TXMAC */
{
if (isLDOMguest(nxgep))
return (NXGE_OK);
goto fail;
} else {
goto fail;
}
return (NXGE_OK);
fail:
"nxge_tx_mac_disable: Failed to disable port<%d> TxMAC",
return (NXGE_ERROR | rs);
}
/* Enable RXMAC */
{
/* This is a service-domain-only activity. */
if (isLDOMguest(nxgep))
return (status);
portn));
goto fail;
CFG_XMAC_RX)) != NPI_SUCCESS)
goto fail;
} else {
CFG_BMAC_RX)) != NPI_SUCCESS)
goto fail;
}
"<== nxge_rx_mac_enable: port<%d>", portn));
return (NXGE_OK);
fail:
"nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn));
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (status);
}
/* Disable RXMAC */
{
/* If we are a guest domain driver, don't bother. */
if (isLDOMguest(nxgep))
return (NXGE_OK);
portn));
CFG_XMAC_RX)) != NPI_SUCCESS)
goto fail;
} else {
CFG_BMAC_RX)) != NPI_SUCCESS)
goto fail;
}
portn));
return (NXGE_OK);
fail:
"nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn));
return (NXGE_ERROR | rs);
}
/* Reset TXMAC */
{
portn));
!= NPI_SUCCESS)
goto fail;
} else {
!= NPI_SUCCESS)
goto fail;
}
portn));
return (NXGE_OK);
fail:
"nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn));
return (NXGE_ERROR | rs);
}
/* Reset RXMAC */
{
portn));
!= NPI_SUCCESS)
goto fail;
} else {
!= NPI_SUCCESS)
goto fail;
}
portn));
return (NXGE_OK);
fail:
"nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn));
return (NXGE_ERROR | rs);
}
/* 10G fiber link interrupt start routine */
static nxge_status_t
{
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
/* 10G fiber link interrupt stop routine */
static nxge_status_t
{
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
/* 1G fiber link interrupt start routine */
static nxge_status_t
{
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
/* 1G fiber link interrupt stop routine */
static nxge_status_t
{
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
/* 1G copper link interrupt start routine */
static nxge_status_t
{
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
/* 1G copper link interrupt stop routine */
static nxge_status_t
{
if (rs != NPI_SUCCESS)
return (NXGE_ERROR | rs);
else
return (NXGE_OK);
}
{
return (NXGE_OK);
if (enable == LINK_INTR_START)
else if (enable == LINK_INTR_STOP)
goto fail;
return (NXGE_OK);
fail:
"nxge_link_intr: Failed to set port<%d> mif intr mode", portn));
return (status);
}
/* Initialize 1G Fiber / Copper transceiver using Clause 22 */
{
/*
* The mif phy mode may be connected to either a copper link
* or fiber link. Read the mode control register to get the fiber
* configuration if it is hard-wired to fiber link.
*/
(void) nxge_mii_get_link_mode(nxgep);
return (nxge_mii_xcvr_fiber_init(nxgep));
}
/*
* Reset the transceiver.
*/
delay = 0;
#if defined(__i386)
#else
#endif
goto fail;
do {
drv_usecwait(500);
#if defined(__i386)
#else
#endif
goto fail;
delay++;
if (delay == 1000) {
goto fail;
}
#if defined(__i386)
#else
#endif
goto fail;
/*
* Initialize the xcvr statistics.
*/
/*
* Initialize the xcvr advertised capability statistics.
*/
/*
* Check for extended status just in case we're
* running a Gigibit phy.
*/
#if defined(__i386)
#else
#endif
goto fail;
} else {
}
/*
* Initialize 1G Statistics once the capability is established.
*/
/*
* Initialize the link statistics.
*/
/*
* Switch off Auto-negotiation, 100M and full duplex.
*/
#if defined(__i386)
#else
#endif
goto fail;
} else {
}
bcm5464r_aux.value = 0;
goto fail;
}
/* If auto-negotiation is desired */
"Restarting Auto-negotiation."));
/*
* Setup our Auto-negotiation advertisement register.
*/
}
/* Write to the auto-negotiation advertisement register */
#if defined(__i386)
#else
#endif
goto fail;
#if defined(__i386)
#else
#endif
goto fail;
}
} else {
/* Force to 1G */
#if defined(__i386)
#else
#endif
goto fail;
} else
/* Force to 100M */
} else
/* Force to 10M */
} else {
} else
}
}
/* BCM5464R 1000mbps external loopback mode */
#if defined(__i386)
#else
#endif
goto fail;
== nxge_lb_ext100) {
/* BCM5464R 100mbps external loopback mode */
== nxge_lb_ext10) {
/* BCM5464R 10mbps external loopback mode */
}
}
}
#if defined(__i386)
#else
#endif
goto fail;
#if defined(__i386)
#else
#endif
goto fail;
/*
* Initialize the xcvr status kept in the context structure.
*/
#if defined(__i386)
#else
#endif
goto fail;
fail:
"<== nxge_mii_xcvr_init status 0x%x", status));
return (status);
}
{
"nxge_mii_xcvr_fiber_init: "
/*
* Reset the transceiver.
*/
delay = 0;
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
do {
drv_usecwait(500);
#if defined(__i386)
!= NXGE_OK)
goto fail;
#else
!= NXGE_OK)
goto fail;
#endif
delay++;
if (delay == 1000) {
goto fail;
}
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
/*
* Initialize the xcvr statistics.
*/
/*
* Initialize the xcvr advertised capability statistics.
*/
/*
* Check for extended status just in case we're
* running a Gigibit phy.
*/
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
} else {
}
/*
* Initialize 1G Statistics once the capability is established.
*/
/*
* Initialize the link statistics.
*/
/*
* Switch off Auto-negotiation, 100M and full duplex.
*/
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
} else {
}
bcm5464r_aux.value = 0;
goto fail;
}
/* BCM5464R 1000mbps external loopback mode */
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
}
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
"nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x",
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
/*
* Initialize the xcvr status kept in the context structure.
*/
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
"<== nxge_mii_xcvr_fiber_init status 0x%x", status));
return (status);
fail:
"<== nxge_mii_xcvr_fiber_init status 0x%x", status));
return (status);
}
/* Read from a MII compliant register */
{
goto fail;
goto fail;
} else
goto fail;
return (NXGE_OK);
fail:
"nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
/* Write to a MII compliant Register */
{
goto fail;
goto fail;
} else
goto fail;
return (NXGE_OK);
fail:
"nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
/*
* Perform write to Clause45 serdes / transceiver device
* Arguments:
* xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port
* number if nxge_mdio_write is used for accessing the
* internal LSIL serdes. Otherwise PHYAD is different
* for different platforms.
* device: With each PHYAD, the driver can use MDIO to control
* multiple devices inside the PHY, here "device" is an
* MMD (MDIO managable device).
* xcvr_reg: Each device has multiple registers. xcvr_reg specifies
* the register which the driver will write value to.
* value: The register value will be filled in.
*/
{
xcvr_portn));
goto fail;
xcvr_portn));
return (NXGE_OK);
fail:
"nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
/* Perform write to Clause45 serdes / transceiver device */
{
xcvr_portn));
goto fail;
xcvr_portn));
return (NXGE_OK);
fail:
"nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn));
return (NXGE_ERROR | rs);
}
/* Check MII to see if there is any link status change */
{
"==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x",
"==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x",
"==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int "
} else {
/* Only status change will update *link_up */
*link_up = LINK_IS_DOWN;
/* Will notify, turn off further msg */
}
"Link down cable problem"));
}
}
else
}
}
} else
*link_up = LINK_IS_UP;
}
"==> nxge_mii_check "
"(auto negotiation complete or link up) "
"soft bmsr 0x%x bmsr_int 0x%x",
#if defined(__i386)
#else
#endif
goto fail;
#if defined(__i386)
#else
#endif
goto fail;
#if defined(__i386)
#else
#endif
goto fail;
#if defined(__i386)
#else
#endif
goto fail;
} else if (
}
}
} else {
goto fail;
}
}
int link_pause;
link_pause = 0;
} else {
link_pause = 1;
}
} else {
}
}
}
}
/* Initial link_notify, delay link down msg */
}
return (NXGE_OK);
fail:
"nxge_mii_check: Unable to check MII"));
return (status);
}
/*
* Check PCS to see if there is any link status change.
* This function is called by PORT_1G_SERDES only.
*/
void
{
if (linkup) {
if ((nxgep->link_notify &&
*link_up = LINK_IS_UP;
}
} else {
*link_up = LINK_IS_DOWN;
}
}
}
/* Add a multicast address entry into the HW hash table */
{
uint_t j;
"Allocating hash filter storage."));
KM_SLEEP);
}
j = mchash / HASH_REG_WIDTH;
}
if (rs != NPI_SUCCESS)
goto fail;
return (NXGE_OK);
fail:
"Unable to add multicast address"));
return (status);
}
/* Remove a multicast address entry from the HW hash table */
{
uint_t j;
"Hash filter already de_allocated."));
return (NXGE_OK);
}
j = mchash / HASH_REG_WIDTH;
}
if (hash_filter->hash_ref_cnt == 0) {
"De-allocating hash filter storage."));
}
if (rs != NPI_SUCCESS)
goto fail;
return (NXGE_OK);
fail:
"Unable to remove multicast address"));
return (status);
}
/* Set MAC address into MAC address HW registers */
{
/*
* Exit if the address is same as ouraddr or multicast or broadcast
*/
goto nxge_set_mac_addr_exit;
}
/*
* Set new interface local address and re-init device.
* This is destructive to any other streams attached
* to this device.
*/
goto fail;
goto fail;
goto nxge_set_mac_addr_end;
return (NXGE_OK);
fail:
"Unable to set mac address"));
return (status);
}
static
{
/* If the poll has been cancelled, return STOP. */
nxge->nxge_link_poll_timerid = 0;
"nxge_check_%s_link(port<%d>) stopped.",
return (CHECK_LINK_STOP);
}
return (CHECK_LINK_RESCHEDULE);
}
/*
* Check status of MII (MIF or PCS) link.
* This function is called once per second, that is because this function
* calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to
* call this function recursively.
*/
static nxge_status_t
{
return (NXGE_ERROR);
return (NXGE_OK);
portn));
goto nxge_check_mii_link_exit;
default:
#if defined(__i386)
#else
#endif
goto fail;
}
"==> nxge_check_mii_link port<0x%x> "
"RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ",
#if defined(__i386)
#else
#endif
goto fail;
#if defined(__i386)
#else
#endif
goto fail;
}
}
}
/* Workaround for link down issue */
goto nxge_check_mii_link_exit;
}
"==> nxge_check_mii_link port<0x%x> :"
"BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x",
"==> nxge_check_mii_link port<0x%x> CALLING "
"bmsr_data 0x%x bmsr_ints.value 0x%x",
goto fail;
}
break;
case PORT_1G_SERDES:
/*
* Above default is for all cases except PORT_1G_SERDES.
* The default case gets information from the PHY, but a
* nxge whose portmode equals PORT_1G_SERDES does not
* have a PHY.
*/
"==> nxge_check_mii_link port<%d> (SERDES)", portn));
break;
}
if (link_up == LINK_IS_UP) {
} else if (link_up == LINK_IS_DOWN) {
}
portn));
return (NXGE_OK);
fail:
"nxge_check_mii_link: Failed to check link port<%d>", portn));
return (status);
}
/*ARGSUSED*/
static nxge_status_t
{
return (NXGE_ERROR);
return (NXGE_OK);
val = 0;
rs = NPI_SUCCESS;
portn));
default:
/*
* Check if the phy is present in case of hot swappable phy
*/
if (nxgep->hot_swappable_phy) {
/* Check back-to-back XAUI connect to detect Opus NEM */
if (rs != 0)
goto fail;
if (val & XPCS_STATUS_LANE_ALIGN) {
}
if (nxgep->phy_absent) {
if (phy_present_now) {
/*
* Detect, Initialize phy and do link up
* set xcvr vals, link_init, nxge_init
*/
"Hot swappable phy DETECTED!!"));
(void) nxge_xcvr_find(nxgep);
(void) nxge_link_init(nxgep);
"Hot swappable "
"phy present, but"
" driver init"
" failed..."));
goto fail;
}
}
} else if (link_up) { /* XAUI linkup, no PHY */
/*
* This is the back-to-back XAUI
* connect case for Opus NEM.
*/
"HSP 10G Serdes DETECTED!!"));
break;
}
if (nxgep->link_notify &&
0;
}
goto start_link_check;
} else if (!phy_present_now) {
/*
* Phy gone, bring link down reset xcvr vals
*/
"Hot swappable phy REMOVED!!"));
(void) nxge_xcvr_find(nxgep);
goto start_link_check;
}
}
case MRVL88X201X_CHIP_ID:
break;
case NLP2020_CHIP_ID:
break;
default:
break;
}
goto fail;
break;
case PORT_10G_SERDES:
XPCS_REG_STATUS, &val);
if (rs != 0)
goto fail;
if (val & XPCS_STATUS_LANE_ALIGN) {
}
"==> nxge_check_10g_link port<%d> "
"XPCS_REG_STATUS2 0x%x link_up %d",
break;
}
if (link_up) {
if ((nxgep->link_notify &&
goto fail;
}
} else {
goto fail;
"Link down cable problem"));
/*
* NEM was unplugged, set up xcvr table
* to find another xcvr in the future.
*/
(void) nxge_xcvr_find(nxgep);
}
}
}
portn));
return (NXGE_OK);
fail:
(void) nxge_check_link_stop(nxgep);
"nxge_check_10g_link: Failed to check link port<%d>",
portn));
return (status);
}
/* Declare link down */
void
{
if (nxge_no_msg == B_FALSE) {
}
}
/* Declare link up */
void
{
else
/* Clean up symbol errors incurred during link transition */
}
/*
* If the driver was plumbed without a link (therefore auto-negotiation
* could not complete), the driver will detect a link up when a cable
* conneting to a link partner is plugged into the port. By the time
* link-up is detected, auto-negotiation should have completed (The
* TN1010 tries to contact a link partner every 8~24ms). Here we re-
* This is necessary only for the TN1010 basad device because only the
* TN1010 supports dual speeds.
*/
(void) nxge_set_tn1010_param(nxgep);
/*
* nxge_xcvr_find calls nxge_get_xcvr_type (which sets
* nxgep->portmode) and nxge_setup_xcvr_table (which sets
* the nxgep->xcvr to the proper nxge_xcvr_table_t struct).
*/
"nxge_link_is_up: nxge_xcvr_find failed"));
}
/* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */
"nxge_link_is_up: nxge_link_init failed"));
}
/*
* nxge_mac_init calls many subroutines including
* nxge_xif_init which sets XGMII or GMII mode
*/
"nxge_link_is_up: nxge_mac_init failed"));
}
} else {
(void) nxge_xif_init(nxgep);
}
if (nxge_no_msg == B_FALSE) {
}
}
#ifdef NXGE_DEBUG
/* Dump all TN1010 Status registers */
static void
{
}
#endif
/*
* Calculate the bit in the multicast address filter
* that selects the given * address.
* Note: For GEM, the last 8-bits are used.
*/
{
uint32_t c;
int byte;
int bit;
else
c >>= 1;
}
}
}
/* Reset serdes */
{
drv_usecwait(500);
return (NXGE_OK);
}
/*
* This function monitors link status using interrupt or polling.
* It calls nxgep->xcvr.check_link, a member function of
* nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this
* function back, that is why the check_link routine is
* executed periodically.
*/
{
/* If we are a guest domain driver, don't bother. */
if (isLDOMguest(nxgep))
return (status);
/*
* Return immediately if this is an imaginary XMAC port.
* (At least, we don't have 4-port XMAC cards yet.)
*/
return (NXGE_OK);
/* stats has not been allocated. */
return (NXGE_OK);
}
/* Don't check link if we're in internal loopback mode */
return (NXGE_OK);
"==> nxge_link_monitor port<%d> enable=%d",
if (enable == LINK_MONITOR_START) {
!= NXGE_OK)
goto fail;
} else {
/*
* check_link_stop means "Stop the link check", so
* we return without starting the timer.
*/
return (NXGE_OK);
/*
* Otherwise fire the timer for the nxge to check
* the link using the check_link function
* of the nxge_xcvr_table and pass "nxgep" as the
* argument to the check_link function.
*/
nxgep->link_check_count ++;
} else {
return (NXGE_ERROR);
}
}
} else {
!= NXGE_OK)
goto fail;
} else {
/* If <timerid> == 0, the link monitor has */
/* never been started, or just now stopped. */
if (nxgep->nxge_link_poll_timerid == 0) {
return (NXGE_OK);
}
if (rv == -1) {
"==> stopping port %d: "
"cv_timedwait(%d) timed out",
nxgep->nxge_link_poll_timerid = 0;
}
}
}
"<== nxge_link_monitor port<%d> enable=%d",
return (NXGE_OK);
fail:
return (status);
}
{
/* magic is 0 if driver is not attached */
return (NXGE_ERROR);
}
/* Link has been stopped, no need to continue */
return (NXGE_OK);
}
goto fail;
if (link_up == LINK_IS_UP)
else if (link_up == LINK_IS_DOWN)
/*
* nxge_link_monitor will call (nxgep->xcvr.check_link)
* which could be THIS function.
*/
return (NXGE_OK);
fail:
"nxge_check_tn1010_link: Failed to check link"));
return (status);
}
/*
* Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN.
*/
static nxge_status_t
{
/* Check if link is up */
!= NXGE_OK) {
goto fail;
}
/*
* nxge_link_is_up has called nxge_set_tn1010_param and set
* portmode and link_speed
*/
if (val & TN1010_AN_LINK_STAT_BIT) {
if ((nxgep->link_notify &&
*link_up = LINK_IS_UP;
}
} else {
*link_up = LINK_IS_DOWN;
}
}
return (NXGE_OK);
fail:
"nxge_tn1010_check: Unable to check TN1010"));
return (status);
}
/* Set promiscous mode */
{
goto fail;
}
goto fail;
}
if (on)
else
return (NXGE_OK);
fail:
"Unable to set promisc (%d)", on));
return (status);
}
/*ARGSUSED*/
{
#ifdef NXGE_DEBUG
#endif
#if NXGE_MIF
#endif
#ifdef NXGE_MIF
}
#endif
return (DDI_INTR_CLAIMED);
return (DDI_INTR_UNCLAIMED);
}
/*ARGSUSED*/
{
}
/*
* This interrupt handler is for a specific
* mac port.
*/
"==> nxge_mac_intr: reading mac stats: port<%d>", 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) {
}
if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) {
/*
* Do not send FMA ereport because this
* error does not indicate HW failure.
*/
}
if (status & ICFG_XMAC_TX_OVERFLOW) {
}
if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) {
}
if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) {
}
if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) {
}
}
(xmac_rx_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_XMAC_RX_ALL) {
if (status & ICFG_XMAC_RX_OVERFLOW)
if (status & ICFG_XMAC_RX_UNDERFLOW) {
}
/*
* Do not send FMA ereport for the following 3 errors
* because they do not indicate HW failures.
*/
if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_OCT_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_HST_CNT1_EXP) {
}
if (status & ICFG_XMAC_RX_HST_CNT2_EXP) {
}
if (status & ICFG_XMAC_RX_HST_CNT3_EXP) {
}
if (status & ICFG_XMAC_RX_HST_CNT4_EXP) {
}
if (status & ICFG_XMAC_RX_HST_CNT5_EXP) {
}
if (status & ICFG_XMAC_RX_HST_CNT6_EXP) {
}
if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) {
}
/*
* Do not send FMA ereport for the following 3 errors
* because they do not indicate HW failures.
*/
if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) {
}
if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) {
}
if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) {
}
}
(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)
if (status & ICFG_XMAC_CTRL_PAUSE_STATE)
}
(bmac_tx_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_BMAC_TX_ALL) {
if (status & ICFG_BMAC_TX_UNDERFLOW) {
}
if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) {
}
if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) {
}
if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) {
}
}
(bmac_rx_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_BMAC_RX_ALL) {
if (status & ICFG_BMAC_RX_OVERFLOW) {
}
if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) {
}
if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) {
}
if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) {
}
}
if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) {
}
if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) {
}
(bmac_ctl_iconfig_t *)&status);
if (rs != NPI_SUCCESS)
goto npi_fail;
if (status & ICFG_BMAC_CTL_ALL) {
if (status & ICFG_BMAC_CTL_RCVPAUSE)
if (status & ICFG_BMAC_CTL_INPAUSE_ST)
}
}
}
return (DDI_INTR_CLAIMED);
return (DDI_INTR_UNCLAIMED);
}
{
#ifdef NXGE_DEBUG_SYMBOL_ERR
#endif
#ifdef NXGE_DEBUG_SYMBOL_ERR
/* Check Device 3 Register Device 3 0xC809 */
if ((val_debug & ~0x200) != 0) {
&val_debug);
}
if (val != 0)
if (val != 0)
if (val != 0)
#endif
/* Check from BCM8704 if 10G link is up or down */
/* Check Device 1 Register 0xA bit0 */
goto fail;
/* Check Device 3 Register 0x20 bit0 */
goto fail;
/* Check Device 4 Register 0x18 bit12 */
goto fail;
case BCM8704_CHIP_ID:
break;
case BCM8706_CHIP_ID:
break;
default:
goto fail;
}
#ifdef NXGE_DEBUG_ALIGN_ERR
/* Temp workaround for link down issue */
if (pcs_blk_lock == B_FALSE) {
if (val2 != 0x4) {
}
}
if (link_align == B_FALSE) {
if (val3 != 0x140f) {
link_align = B_TRUE;
}
}
"!LINK DEBUG: port %d Dev3 or Dev4 read zero\n",
}
}
#endif
return (NXGE_OK);
fail:
return (status);
}
static nxge_status_t
{
/* Check from Marvell 88X2011 if 10G link is up or down */
"nxge_check_mrvl88x2011_link: pmd=0x%x", val));
/* Check PMC Register : 3.0001.2 == 1: read twice */
"nxge_check_mrvl88x2011_link: pcs=0x%x", val));
/* Check XGXS Register : 4.0018.[0-3,12] */
"nxge_check_mrvl88x2011_link: xgxs=0x%x", val));
fail:
/* PCS OFF */
} else {
/* PCS Activity */
}
" <== nxge_check_mrvl88x2011_link: up=%d", *link_up));
return (status);
}
static nxge_status_t
{
/* Check from Netlogic AEL2020 if 10G link is up or down */
goto fail;
goto fail;
goto fail;
if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) &&
/*
* If previously link was down, check the connector type as
* it might have been changed.
*/
switch (connector) {
case SFPP_FIBER:
"nxge_check_nlp2020_link: SFPP_FIBER"));
(void) nxge_nlp2020_xcvr_init(nxgep);
}
break;
case QSFP_FIBER:
"nxge_check_nlp2020_link: QSFP_FIBER"));
(void) nxge_nlp2020_xcvr_init(nxgep);
}
break;
case QSFP_COPPER_TWINAX:
"nxge_check_nlp2020_link: "
"QSFP_COPPER_TWINAX/"
"SFPP_COPPER_TWINAX"));
(void) nxge_nlp2020_xcvr_init(nxgep);
} else {
&len);
if (((len < 7) &&
((len >= 7) &&
(void) nxge_nlp2020_xcvr_init(nxgep);
}
}
break;
default:
"nxge_check_nlp2020_link: Unknown type [0x%x] "
"detected...setting to QSFP_FIBER",
connector));
(void) nxge_nlp2020_xcvr_init(nxgep);
}
break;
}
}
fail:
/* Turn link LED OFF */
/* Turn link LED ON */
}
" <== nxge_check_nlp2020_link: up=%d", *link_up));
return (status);
}
{
!= NPI_SUCCESS)
return (NXGE_ERROR);
else
return (NXGE_OK);
}
{
!= NPI_SUCCESS)
return (NXGE_ERROR);
else
return (NXGE_OK);
}
static boolean_t
{
/*
* check for BCM PHY (GOA NEM)
*/
/*
* If this is the 2nd NIU port, then check 2 addresses
* to take care of the Goa NEM card. Port 1 can have addr 17
* (in the eval board) or 20 (in the P0 board).
*/
if (portn == 1) {
goto found_phy;
}
}
goto found_phy;
}
/*
* check for NLP2020 PHY on C4 NEM
*/
switch (portn) {
case 0:
goto found_phy;
goto found_phy;
goto found_phy;
goto found_phy;
}
break;
case 1:
goto found_phy;
goto found_phy;
goto found_phy;
goto found_phy;
}
break;
default:
break;
}
return (B_FALSE);
return (B_TRUE);
}
static boolean_t
{
"nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id));
goto found_phy;
"nxge_is_phy_present: pcs_id[0x%x]", pcs_id));
goto found_phy;
"nxge_is_phy_present: phy_id[0x%x]", phy_id));
goto found_phy;
return (B_FALSE);
return (B_TRUE);
}
/* Check if the given id read using the given MDIO Clause is supported */
static boolean_t
{
int i;
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)) ||
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)) {
break;
}
}
break;
default:
break;
}
return (found);
}
static uint32_t
{
/* Concatenate the Device ID stored in two registers. */
pma_pmd_dev_id |= val2;
return (pma_pmd_dev_id);
}
static uint32_t
{
pcs_dev_id = val1;
pcs_dev_id |= val2;
return (pcs_dev_id);
}
static uint32_t
{
&val1);
if (npi_status != NPI_SUCCESS) {
"clause 22 read to reg 2 failed!!!"));
goto exit;
}
&val2);
if (npi_status != 0) {
"clause 22 read to reg 3 failed!!!"));
goto exit;
}
exit:
return (phy_id);
}
/*
* Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO
* read. Then use the values obtained to determine the phy type of each port
* and the Neptune type.
*
* This function sets hw_p->xcvr_addr[i] for future MDIO access and set
* hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode
* in case the portmode information is not available via OBP, nxge.conf,
* VPD or SEEPROM.
*/
{
int i, j, l;
"==> nxge_scan_ports_phy: nxge niu_type[0x%x]",
if (isLDOMguest(nxgep)) {
return (NXGE_OK);
}
j = l = 0;
total_port_fd = total_phy_fd = 0;
/*
* for on chip serdes usages. "i" in the following for loop starts at 6.
*/
for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) {
pma_pmd_dev_fd[i] = 1;
"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) {
} else if ((pma_pmd_dev_id &
port_pma_pmd_dev_id[j] =
} else {
port_pma_pmd_dev_id[j] =
}
port_fd_arr[j] = (uint8_t)i;
j++;
}
} else {
pma_pmd_dev_fd[i] = 0;
}
pcs_dev_fd[i] = 1;
"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] =
} else if ((pcs_dev_id & NLP2020_DEV_ID_MASK)
== NLP2020_DEV_ID) {
port_pcs_dev_id[j - 1] =
} else {
port_pcs_dev_id[j - 1] =
}
} else {
if (j < NXGE_PORTS_NEPTUNE) {
if ((pcs_dev_id & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) {
port_pcs_dev_id[j] =
} else if ((pcs_dev_id &
== NLP2020_DEV_ID) {
port_pcs_dev_id[j] =
} else {
port_pcs_dev_id[j] =
}
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 ++;
}
total_phy_fd ++;
"%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:
/* 2 10G, 2 1G RGMII Fiber / copper */
if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
switch (hw_p->platform_type) {
case P_NEPTUNE_ROCK:
/*
* ROCK platform has assigned a lower
* addr to port 1. (port 0 = 0x9 and
* port 1 = 0x8).
*/
"Rock with 2 10G, 2 1GC"));
break;
case P_NEPTUNE_NONE:
default:
"ARTM card with 2 10G, 2 1GF"));
break;
}
} else {
"Unsupported neptune type 1"));
goto error_exit;
}
break;
case 1:
/* TODO - 2 10G, 1 1G */
"Unsupported neptune type 2 10G, 1 1G"));
goto error_exit;
case 0:
/*
* 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI
* cards, etc.
*/
if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) &&
((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) &&
((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) &&
((port_pma_pmd_dev_id[0] ==
(port_pma_pmd_dev_id[1] ==
/*
* Check the first phy port address against
* the known phy start addresses to determine
* the platform type.
*/
switch (port_fd_arr[0]) {
/*
* The Marvell case also falls into
* this case as
* MRVL88X2011_NEPTUNE_PORT_ADDR_BASE
* == NEPTUNE_CLAUSE45_PORT_ADDR_BASE.
* This is OK for the 2 10G case.
*/
break;
if (hw_p->platform_type !=
}
break;
default:
"Unsupported neptune type 2 - 1"));
goto error_exit;
}
for (i = 0; i < 2; i++) {
}
/* 2 10G optical Netlogic AEL2020 ports */
} else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) &&
((port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) &&
}
"Found 2 NL PHYs at addrs 0x%x and 0x%x",
/* Both XAUI slots have copper XAUI cards */
} else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
== TN1010_DEV_ID)) ||
(((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
== TN1010_DEV_ID))) {
/* Slot0 has fiber XAUI, slot1 has copper XAUI */
} else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
== TN1010_DEV_ID) ||
(port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY &&
TN1010_DEV_ID)) {
/* Slot0 has copper XAUI, slot1 has fiber XAUI */
== TN1010_DEV_ID) ||
== TN1010_DEV_ID)) {
} else {
"Unsupported neptune type 2"));
goto error_exit;
}
break;
case 4:
if (nxge_get_num_of_xaui(
goto error_exit;
}
if (num_xaui != 2)
goto error_exit;
/*
* Maramba with 2 XAUIs (either fiber or copper)
*
* Check the first phy port address against
* the known phy start addresses to determine
* the platform type.
*/
switch (phy_fd_arr[0]) {
break;
break;
default:
"Unknown port %d...Cannot "
"determine platform type", i));
goto error_exit;
}
/* slot0 has fiber XAUI, slot1 has Cu XAUI */
if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
== TN1010_DEV_ID) {
/* slot0 has Cu XAUI, slot1 has fiber XAUI */
} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
/* Both slots have fiber XAUI */
} else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY &&
/* Both slots have copper XAUI */
} else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID) &&
== TN1010_DEV_ID) {
} else {
"Unsupported neptune type 3"));
goto error_exit;
}
break;
default:
"Unsupported neptune type 5"));
goto error_exit;
}
break;
case 1: /* Only one clause45 port */
switch (total_phy_fd) { /* Number of clause22 ports */
case 3:
/*
* TODO 3 1G, 1 10G mode.
* Differentiate between 1_1G_1_10G_2_1G and
* 1_10G_3_1G
*/
"Unsupported neptune type 7"));
goto error_exit;
case 2:
/*
* TODO 2 1G, 1 10G mode.
* Differentiate between 1_1G_1_10G_1_1G and
* 1_10G_2_1G
*/
"Unsupported neptune type 8"));
goto error_exit;
case 1:
/*
* TODO 1 1G, 1 10G mode.
* Differentiate between 1_1G_1_10G and
* 1_10G_1_1G
*/
"Unsupported neptune type 9"));
goto error_exit;
case 0: /* N2 with 1 XAUI (fiber or copper) */
/* Fiber XAUI */
if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY ||
port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) {
/*
* Check the first phy port address against
* the known phy start addresses to determine
* the platform type.
*/
switch (port_fd_arr[0]) {
case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
/*
* If hw_p->platform_type ==
* P_NEPTUNE_NIU, then portmode
* is already known, so there is
* no need to figure out hw_p->
* platform_type because
* platform_type is only for
* figuring out portmode.
*/
if (hw_p->platform_type !=
}
break;
default:
"Unsupported neptune type 10"));
goto error_exit;
}
/*
* For GOA, which is a hot swappable PHY, the
* phy address to function number mapping
* should be preserved, i.e., addr 16 is
* assigned to function 0 and 20 to function 1
* But for Huron XAUI, the assignment should
* be by function number, i.e., whichever
* function number attaches should be
* assigned the available PHY (this is required
* primarily to support pre-production Huron
* boards where function 0 is mapped to addr 17
*/
if (port_fd_arr[0] ==
} else {
port_fd_arr[0];
}
} else if (port_pcs_dev_id[0] == NLP2020_DEV_ID ||
port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) {
/* A 10G NLP2020 PHY in slot0 or slot1 */
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, then portmode
* is already known, so there is
* no need to figure out hw_p->
* platform_type because
* platform_type is only for
* figuring out portmode.
*/
if (hw_p->platform_type !=
}
break;
default:
"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:
break;
case NLP2020_CL45_PORT1_ADDR0:
case NLP2020_CL45_PORT1_ADDR1:
case NLP2020_CL45_PORT1_ADDR2:
case NLP2020_CL45_PORT1_ADDR3:
break;
default:
"Unsupported neptune type 10-11"));
goto error_exit;
}
"Found 1 NL PHYs at addr 0x%x",
port_fd_arr[0]));
/* A 10G copper XAUI in either slot0 or slot1 */
} else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK)
== TN1010_DEV_ID ||
== TN1010_DEV_ID) {
switch (port_fd_arr[0]) {
/* The XAUI is in slot0 */
break;
/* The XAUI is in slot1 */
case (N2_CLAUSE45_PORT_ADDR_BASE + 1):
break;
default:
"Unsupported XAUI port address"));
goto error_exit;
}
= port_fd_arr[0];
} else {
"Unsupported PHY type"));
goto error_exit;
}
break;
case 4: /* Maramba always have 4 clause 45 ports */
/* Maramba with 1 XAUI */
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) &&
!= TN1010_DEV_ID)) {
"Unsupported neptune type 12"));
goto error_exit;
}
/*
* Check the first phy port address against
* the known phy start addresses to determine
* the platform type.
*/
switch (phy_fd_arr[0]) {
break;
break;
default:
"Unknown port %d...Cannot "
"determine platform type 10 - 2",
i));
goto error_exit;
}
/*
* Check the clause45 address to determine
* if XAUI is in port 0 or port 1.
*/
switch (port_fd_arr[0]) {
if (port_pcs_dev_id[0]
== PHY_BCM8704_FAMILY ||
== PHY_BCM8704_FAMILY) {
} else {
}
for (i = 1; i < NXGE_MAX_PORTS; i++) {
phy_fd_arr[i];
}
break;
case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1):
if (port_pcs_dev_id[0]
== PHY_BCM8704_FAMILY ||
== PHY_BCM8704_FAMILY) {
} else {
}
break;
default:
"Unsupported neptune type 11"));
goto error_exit;
}
"Maramba with 1 XAUI (fiber or copper)"));
break;
default:
"Unsupported neptune type 13"));
goto error_exit;
}
break;
case 0: /* 4 ports Neptune based NIC */
switch (total_phy_fd) {
case 4:
if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) &&
/*
* Check the first phy port address against
* the known phy start addresses to determine
* the platform type.
*/
switch (phy_fd_arr[0]) {
break;
break;
default:
"Unknown port %d...Cannot "
"determine platform type", i));
goto error_exit;
}
for (i = 0; i < NXGE_MAX_PORTS; i++) {
}
} else {
"Unsupported neptune type 14"));
goto error_exit;
}
break;
case 3:
/* TODO 3 1G mode */
"Unsupported neptune type 15"));
goto error_exit;
case 2:
/* TODO 2 1G mode */
if ((port_phy_id[0] == PHY_BCM5482_FAMILY) &&
} else {
"Unsupported neptune type 16"));
goto error_exit;
}
"2 RGMII Fiber ports - RTM"));
break;
case 1:
/* TODO 1 1G mode */
"Unsupported neptune type 17"));
goto error_exit;
default:
"Unsupported neptune type 18, total phy fd %d",
total_phy_fd));
goto error_exit;
}
break;
default:
"Unsupported neptune type 19"));
goto error_exit;
}
return (status);
return (NXGE_ERROR);
}
{
return (B_FALSE);
else
return (B_TRUE);
}
static void
}
/*
* For Altas 4-1G copper, Xcvr port numbers are
* swapped with ethernet port number. This is
* designed for better signal integrity in routing.
*/
switch (portn) {
case 0:
xcvr_portn += 3;
break;
case 1:
xcvr_portn += 2;
break;
case 2:
xcvr_portn += 1;
break;
case 3:
default:
break;
}
if (rs != NPI_SUCCESS) {
"<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
"returned error 0x[%x]", rs));
return;
}
if (rs != NPI_SUCCESS) {
"<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write "
"returned error 0x[%x]", rs));
}
}
static nxge_status_t
{
#if defined(__i386)
goto fail;
#else
goto fail;
#endif
}
#if defined(__i386)
goto fail;
}
#else
goto fail;
}
#endif
"nxge_mii_get_link_mode: fiber mode"));
}
"nxge_mii_get_link_mode: "
"(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x",
"<== nxge_mii_get_link_mode"));
return (status);
fail:
"<== nxge_mii_get_link_mode (failed)"));
return (NXGE_ERROR);
}
{
"==> nxge_mac_sec_framesize: port<%d> "
"min framesize %d max framesize %d ",
rs);
if (rs != NPI_SUCCESS) {
"<== nxge_mac_set_framesize: failed to configure "
return (NXGE_ERROR | rs);
}
"<== nxge_mac_set_framesize: port<%d>", portn));
return (NXGE_OK);
}
static nxge_status_t
{
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) ++;
}
== TN1010_DEV_ID) &&
== TN1010_DEV_ID))) {
(*num_xaui) ++;
}
return (NXGE_OK);
}
/*
* Instruction from Teranetics: Once you detect link is up, go
* read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You
* may want to qualify it by first checking Register 30.1.7:6 and
* making sure it reads "01" (Auto-Neg Complete).
*
* If this function is called when the link is down or before auto-
* negotiation has completed, then the speed of the PHY is not certain.
* In such cases, this function returns 1G as the default speed with
* NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the
* driver based on a default speed because this function will be called
* again when the link comes up. Returning NXGE_ERROR, which may
* cause brutal chain reaction in caller functions, is not necessary.
*/
static nxge_status_t
{
/* Set default speed to 10G */
/* Set Clause 45 */
/* Check Device 1 Register 0xA bit0 for link up status */
goto fail;
"nxge_get_tn1010_speed: link is down"));
}
goto fail;
}
/*
* Return NXGE_OK even when we can not get a settled speed. In
* such case, the speed reported should not be trusted but that
* is OK, we will call this function periodically and will get
* the correct speed after the link is up.
*/
switch (autoneg_stat) {
case TN1010_AN_IN_PROG:
"nxge_get_tn1010_speed: Auto-negotiation in progress"));
break;
case TN1010_AN_COMPLETE:
goto fail;
}
break;
case TN1010_AN_RSVD:
"nxge_get_tn1010_speed: Autoneg status undefined"));
break;
case TN1010_AN_FAILED:
"nxge_get_tn1010_speed: Auto-negotiation failed"));
break;
default:
break;
}
return (NXGE_OK);
fail:
return (status);
}
/*
* Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function
* figures out the speed of the PHY determined by the autonegotiation
* process and sets the following 3 parameters,
* nxgep->mac.portmode
* nxgep->statsp->mac_stats.link_speed
* nxgep->statsp->mac_stats.xcvr_inuse
*/
static nxge_status_t
{
"nxge_set_tn1010_param: "
"Failed to get TN1010 speed"));
return (NXGE_ERROR);
}
if (speed == TN1010_SPEED_1G) {
} else {
}
return (NXGE_OK);
}
#ifdef NXGE_DEBUG
static void
{
#if defined(__i386)
#else
#endif
"nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x",
#if defined(__i386)
(void) nxge_mii_read(nxgep,
#else
(void) nxge_mii_read(nxgep,
#endif
"nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x",
#if defined(__i386)
(void) nxge_mii_read(nxgep,
#else
(void) nxge_mii_read(nxgep,
#endif
#if defined(__i386)
(void) nxge_mii_read(nxgep,
#else
(void) nxge_mii_read(nxgep,
#endif
"nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x",
"nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x",
#if defined(__i386)
#else
#endif
"nxge_mii_dump: mode control xcvr 0x%x value 0x%x",
}
#endif